Skip to content

Commit 3c36c4f

Browse files
committed
Added universal skills.
1 parent aaf6cf6 commit 3c36c4f

File tree

5 files changed

+384
-0
lines changed

5 files changed

+384
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
name: systems-manager-code-analysis
3+
description: Code Analysis using Tree-Sitter and Abstract Syntax Trees (AST).
4+
---
5+
# Code Analysis Skill
6+
7+
This skill provides capabilities for deep structural analysis of codebases using Tree-Sitter and ASTs. It enables agents to understand code structure, find definitions, and analyze dependencies beyond simple text search.
8+
9+
## Overview
10+
Tree-sitter is a parser generator tool and an incremental parsing library. It builds a concrete syntax tree for a source file and efficiently updates the tree as the source file is edited.
11+
12+
## Capabilities
13+
14+
### 1. Structural Search (Tree-Sitter Query)
15+
- **Goal**: Find code elements based on their syntactic structure (e.g., "all function definitions", "calls to function X", "assignments to variable Y").
16+
- **Usage**: Use `python` to load `tree-sitter` and run queries.
17+
- **Example**:
18+
```python
19+
from tree_sitter import Language, Parser
20+
# Load language (requires building the language library first, or using python bindings)
21+
# For this environment, we recommend using pre-installed python bindings if available
22+
# or falling back to simple AST parsing for Python.
23+
```
24+
25+
### 2. AST Traversal
26+
- **Goal**: Walk the syntax tree to understand the hierarchy of code elements.
27+
- **Usage**: Traverse nodes to find classes, methods, and their relationships.
28+
29+
### 3. Symbol Extraction
30+
- **Goal**: Extract definitions of functions, classes, and variables with their locations.
31+
- **Usage**: Useful for building a map of the codebase.
32+
33+
## Best Practices
34+
- **Combine with Grep**: Use `ripgrep` to narrow down files, then use AST analysis for precision.
35+
- **Handle Errors**: Tree-sitter is robust to syntax errors, but always check for missing nodes.
36+
- **Language Support**: Ensure the appropriate language grammar is available.
37+
38+
## Tool Usage
39+
Since `tree-sitter` CLI might not be installed, use Python scripts to leverage the library.
40+
41+
```python
42+
import tree_sitter
43+
# Implementation details specific to the environment
44+
```
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
name: systems-manager-codebase-search
3+
description: Fast and precise codebase search using ripgrep (rg) and glob patterns.
4+
---
5+
# Codebase Search Skill
6+
7+
This skill provides powerful capabilities for searching codebases using `ripgrep` (rg) and glob patterns. These tools are the foundation for efficient agentic exploration.
8+
9+
## Tools
10+
11+
### 1. ripgrep (rg)
12+
- **Description**: A line-oriented search tool that recursively searches directories for a regex pattern.
13+
- **Why use it**: It's faster than standard grep, respects `.gitignore`, and provides cleaner output for LLMs.
14+
- **Common Flags**:
15+
- `-n`: Show line numbers (essential for context).
16+
- `-i`: Case insensitive search.
17+
- `-C 2`: Show 2 lines of context around matches.
18+
- `-t <type>`: Filter by file type (e.g., `-t py`, `-t js`).
19+
- `-g <glob>`: Include/exclude files based on glob patterns.
20+
- **Example Usage**:
21+
```bash
22+
rg "class User" -t py -n
23+
rg "TODO" -g "!tests/" -C 2
24+
```
25+
26+
### 2. Glob
27+
- **Description**: Pattern matching for file paths.
28+
- **Usage**: Use with `rg`, `find`, or directly via shell.
29+
- **Patterns**:
30+
- `*`: Matches any characters in a filename.
31+
- `**`: Matches directories recursively.
32+
- `?`: Matches a single character.
33+
- `[...]`: Matches a range of characters.
34+
- **Example**:
35+
```bash
36+
ls **/*.py
37+
rg --files -g "**/*.{js,ts}"
38+
```
39+
40+
## Agentic Workflow
41+
1. **Global Discovery**: Start with `ls -R` or `fd` to map the structure.
42+
2. **Narrow Search**: Use `glob` patterns to filter relevant files.
43+
3. **Precise Search**: Use `rg` to find specific symbols or text within the narrowed set.
44+
4. **Read**: Finally, read the content of the identified files.
45+
46+
## Best Practices
47+
- **Prefer `rg` over `grep`**: Always use `ripgrep` for code searches due to its speed and ignore-handling.
48+
- **Use Context**: When searching for code, always request context lines (`-C`) to understand usage.
49+
- **Filter**: Use file type filters (`-t`) to reduce noise.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
name: systems-manager-file-navigation
3+
description: Efficient file navigation and structure mapping.
4+
---
5+
# File Navigation Skill
6+
7+
This skill encompasses tools and strategies for navigating directory structures, understanding project layouts, and locating files.
8+
9+
## Tools
10+
11+
### 1. `tree`
12+
- **Description**: Displays directories and files as a recursive tree.
13+
- **Usage**: Good for a quick overview of project structure.
14+
- **Flags**:
15+
- `-L <level>`: Limit recursion depth.
16+
- `-I <pattern>`: Ignore files matching pattern.
17+
- `-d`: List directories only.
18+
19+
### 2. `fd` a.k.a `fd-find`
20+
- **Description**: A faster alternative to `find`.
21+
- **Usage**: Quickly locate files by name.
22+
- **Flags**:
23+
- `-H`: Include hidden files.
24+
- `-I`: Ignore `.gitignore`.
25+
- `-e <ext>`: Filter by file extension.
26+
27+
### 3. `ls` (standard)
28+
- **Description**: List directory contents.
29+
- **Usage**: Basic navigation.
30+
- **Flags**:
31+
- `-R`: Recursive list.
32+
- `-a`: Show hidden files.
33+
- `-l`: Long format (permissions, size, etc.).
34+
35+
## Agentic Workflow
36+
1. **Assess Structure**: Use `tree -L 2` to understand the high-level layout.
37+
2. **Explore Details**: Use `ls -l` to inspect specific directories.
38+
3. **Locate**: Use `fd` (or `find`) to locate specific files or patterns (e.g., config files).
39+
4. **Map**: Build a mental map of where components (src, tests, docs) reside.
40+
41+
## Best Practices
42+
- **Limit Depth**: Always use depth limits (`-L` or `-maxdepth`) when exploring large repos to avoid overwhelming output.
43+
- **Ignore Noise**: Use `-I` or `.gitignore` to skip `node_modules`, `venv`, etc.
44+
- **Combine**: Use `fd` to find files, then `xargs` to process them (e.g., `fd -e py | xargs wc -l`).
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
name: a2a-client
3+
description: Communicate with other agents using the Agent-to-Agent (A2A) protocol.
4+
---
5+
6+
### Overview
7+
This skill allows the agent to act as a client and communicate with other A2A-compatible agents. It handles agent discovery (via `agent-card.json`), message sending (via JSON-RPC), and result polling.
8+
9+
### Capabilities
10+
- **Agent Discovery**: Validates the target agent by fetching its `.well-known/agent-card.json`.
11+
- **Send Message**: Sends a prompt/query to the target agent to initiate a task.
12+
- **Poll Results**: Monitors the task status and retrieves the final response when complete.
13+
14+
### Scripts
15+
- `scripts/a2a_client.py`: The core python script that implements the A2A client logic.
16+
17+
### Usage
18+
Run the script `scripts/a2a_client.py` with the target agent's URL and your query.
19+
20+
**Arguments:**
21+
- `--url`: The base URL of the A2A endpoint (e.g., `http://target-agent.arpa/a2a/`).
22+
- `--query`: The text message or query you want to send to the agent.
23+
24+
### Example
25+
To ask a search agent about the latest news about the United States:
26+
```bash
27+
python3 genius_agent/skills/a2a_client/scripts/a2a_client.py \
28+
--url http://searxng-agent.arpa/a2a/ \
29+
--query "Can you search the latest news about the United States?"
30+
```
31+
32+
### Protocol Flow
33+
1. **Validation**: `GET {url}/.well-known/agent-card.json`
34+
2. **Send Message**: `POST {url}` with JSON-RPC method `message/send`
35+
3. **Poll Status**: `POST {url}` with JSON-RPC method `tasks/get` until state is `completed` (or failed).
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
#!/usr/bin/env python3
2+
import asyncio
3+
import httpx
4+
import json
5+
import uuid
6+
import argparse
7+
import sys
8+
9+
10+
async def validate_agent_card(client, agent_url):
11+
"""
12+
Validates the agent by fetching its well-known agent card.
13+
"""
14+
card_url = f"{agent_url.rstrip('/')}/.well-known/agent-card.json"
15+
print(f"Fetching agent card from: {card_url}")
16+
try:
17+
resp = await client.get(card_url)
18+
if resp.status_code == 200:
19+
try:
20+
card_data = resp.json()
21+
print(f"Agent Card Found: {json.dumps(card_data, indent=2)}")
22+
return True
23+
except json.JSONDecodeError:
24+
print(f"Failed to decode agent card JSON from {card_url}")
25+
return False
26+
else:
27+
print(f"Failed to fetch agent card. Status Code: {resp.status_code}")
28+
return False
29+
except httpx.RequestError as e:
30+
print(f"Connection failed to {card_url}: {e}")
31+
return False
32+
33+
34+
async def send_message(client, agent_url, message_text):
35+
"""
36+
Sends a message to the agent via JSON-RPC.
37+
"""
38+
print(f"\nSending Message: '{message_text}' to {agent_url}")
39+
40+
payload = {
41+
"jsonrpc": "2.0",
42+
"method": "message/send",
43+
"params": {
44+
"message": {
45+
"kind": "message",
46+
"role": "user",
47+
"parts": [{"kind": "text", "text": message_text}],
48+
"messageId": str(uuid.uuid4()),
49+
}
50+
},
51+
"id": 1,
52+
}
53+
54+
try:
55+
resp = await client.post(
56+
agent_url, json=payload, headers={"Content-Type": "application/json"}
57+
)
58+
59+
if resp.status_code != 200:
60+
print(f"Error sending message. Status Code: {resp.status_code}")
61+
print(resp.text)
62+
return None
63+
64+
data = resp.json()
65+
if "error" in data:
66+
print(f"JSON-RPC Error: {data['error']}")
67+
return None
68+
69+
if "result" in data and "id" in data["result"]:
70+
task_id = data["result"]["id"]
71+
print(f"Task Submitted with ID: {task_id}")
72+
return task_id
73+
else:
74+
print(f"Unexpected response format: {data}")
75+
return None
76+
77+
except httpx.RequestError as e:
78+
print(f"Connection failed during message send: {e}")
79+
return None
80+
except json.JSONDecodeError:
81+
print(f"Failed to decode response JSON: {resp.text}")
82+
return None
83+
84+
85+
async def poll_task(client, agent_url, task_id):
86+
"""
87+
Polls the task status until completion.
88+
"""
89+
print(f"Polling for result for Task ID: {task_id}...")
90+
91+
while True:
92+
await asyncio.sleep(2)
93+
poll_payload = {
94+
"jsonrpc": "2.0",
95+
"method": "tasks/get",
96+
"params": {"id": task_id},
97+
"id": 2,
98+
}
99+
100+
try:
101+
poll_resp = await client.post(
102+
agent_url,
103+
json=poll_payload,
104+
headers={"Content-Type": "application/json"},
105+
)
106+
107+
if poll_resp.status_code != 200:
108+
print(f"Polling Failed: {poll_resp.status_code}")
109+
print(f"Details: {poll_resp.text}")
110+
break
111+
112+
poll_data = poll_resp.json()
113+
114+
if "error" in poll_data:
115+
print(f"Polling Error: {poll_data['error']}")
116+
break
117+
118+
if "result" in poll_data:
119+
status = poll_data["result"].get("status", {})
120+
state = status.get("state")
121+
print(f"Task State: {state}")
122+
123+
if state not in ["submitted", "running", "working"]:
124+
print(f"\nTask Finished with state: {state}")
125+
return poll_data["result"]
126+
else:
127+
print(f"Unexpected polling response: {poll_data}")
128+
break
129+
130+
except httpx.RequestError as e:
131+
print(f"Connection failed during polling: {e}")
132+
break
133+
except json.JSONDecodeError:
134+
print(f"Failed to decode polling response: {poll_resp.text}")
135+
break
136+
137+
138+
def print_result(result):
139+
"""
140+
Prints the final result from the agent.
141+
"""
142+
if not result:
143+
return
144+
145+
history = result.get("history", [])
146+
if history:
147+
last_msg = None
148+
# Find the last message that is NOT from the user (i.e., the agent's response)
149+
for msg in reversed(history):
150+
if msg.get("role") != "user":
151+
last_msg = msg
152+
break
153+
154+
if last_msg:
155+
print("\n--- Agent Response ---")
156+
if "parts" in last_msg:
157+
for part in last_msg["parts"]:
158+
if "text" in part:
159+
print(part["text"])
160+
elif "content" in part:
161+
print(part["content"])
162+
else:
163+
print(f"Final Message (No parts): {last_msg}")
164+
else:
165+
print("\n--- No Agent Response Found in History ---")
166+
167+
# print(f"\nFull Result Debug:\n{json.dumps(result, indent=2)}")
168+
169+
170+
async def main():
171+
parser = argparse.ArgumentParser(
172+
description="A2A Client for communicating with other agents."
173+
)
174+
parser.add_argument(
175+
"--url",
176+
required=True,
177+
help="The base URL of the A2A Agent (e.g., http://agent.arpa/a2a/)",
178+
)
179+
parser.add_argument(
180+
"--query", required=True, help="The message/query to send to the agent"
181+
)
182+
183+
args = parser.parse_args()
184+
185+
agent_url = args.url
186+
query = args.query
187+
188+
print("Initializing A2A Client...")
189+
print(f"Target Agent: {agent_url}")
190+
print(f"Query: {query}")
191+
192+
async with httpx.AsyncClient(timeout=60.0) as client:
193+
# 1. Validate Agent
194+
if not await validate_agent_card(client, agent_url):
195+
print("Agent validation failed. Aborting.")
196+
sys.exit(1)
197+
198+
# 2. Send Message
199+
task_id = await send_message(client, agent_url, query)
200+
if not task_id:
201+
print("Failed to submit task. Aborting.")
202+
sys.exit(1)
203+
204+
# 3. Poll for Result
205+
result = await poll_task(client, agent_url, task_id)
206+
207+
# 4. Print Result
208+
print_result(result)
209+
210+
211+
if __name__ == "__main__":
212+
asyncio.run(main())

0 commit comments

Comments
 (0)