supyagent 0.2.1__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of supyagent might be problematic. Click here for more details.
- {supyagent-0.2.1 → supyagent-0.2.2}/.gitignore +1 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/PKG-INFO +1 -1
- supyagent-0.2.2/agents/tester.yaml +23 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/pyproject.toml +1 -1
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/cli/main.py +12 -15
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/core/llm.py +4 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/core/tools.py +43 -25
- supyagent-0.2.2/supypowers/__init__.py +1 -0
- supyagent-0.2.1/supypowers/__init__.py +0 -6
- {supyagent-0.2.1 → supyagent-0.2.2}/LICENSE +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/README.md +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/agents/assistant.yaml +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/agents/coder.yaml +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/agents/planner.yaml +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/agents/researcher.yaml +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/agents/summarizer.yaml +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/agents/writer.yaml +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/plans/initial_plan.md +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/scripts/release.sh +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/sprints/README.md +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/sprints/sprint_1_foundation.md +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/sprints/sprint_2_sessions.md +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/sprints/sprint_3_repl.md +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/sprints/sprint_4_execution.md +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/sprints/sprint_5_multiagent.md +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/sprints/sprint_6_polish.md +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/__init__.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/__main__.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/cli/__init__.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/core/__init__.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/core/agent.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/core/config.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/core/context.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/core/credentials.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/core/delegation.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/core/executor.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/core/registry.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/core/session_manager.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/default_tools/__init__.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/default_tools/files.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/default_tools/shell.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/models/__init__.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/models/agent_config.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/models/session.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/utils/__init__.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supyagent/utils/paths.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supypowers/files.py +0 -0
- {supyagent-0.2.1 → supyagent-0.2.2}/supypowers/shell.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: supyagent
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: LLM agents powered by supypowers - build AI agents with tool use, multi-agent orchestration, and secure credential management
|
|
5
5
|
Project-URL: Homepage, https://github.com/ergodic-ai/supyagent
|
|
6
6
|
Project-URL: Documentation, https://github.com/ergodic-ai/supyagent#readme
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: tester
|
|
2
|
+
description: A test agent to verify supyagent works
|
|
3
|
+
version: "1.0"
|
|
4
|
+
type: interactive
|
|
5
|
+
|
|
6
|
+
model:
|
|
7
|
+
provider: openrouter/moonshotai/kimi-k2.5
|
|
8
|
+
temperature: 0.7
|
|
9
|
+
max_tokens: 4096
|
|
10
|
+
|
|
11
|
+
system_prompt: |
|
|
12
|
+
You are a helpful AI assistant for testing supyagent.
|
|
13
|
+
You have access to shell commands and file operations.
|
|
14
|
+
|
|
15
|
+
When asked to do something, use the available tools.
|
|
16
|
+
Be concise in your responses.
|
|
17
|
+
|
|
18
|
+
tools:
|
|
19
|
+
allow:
|
|
20
|
+
- "*"
|
|
21
|
+
|
|
22
|
+
limits:
|
|
23
|
+
max_tool_calls_per_turn: 10
|
|
@@ -25,10 +25,11 @@ from supyagent.default_tools import install_default_tools, list_default_tools
|
|
|
25
25
|
from supyagent.models.agent_config import AgentNotFoundError, load_agent_config
|
|
26
26
|
|
|
27
27
|
console = Console()
|
|
28
|
+
console_err = Console(stderr=True)
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
@click.group()
|
|
31
|
-
@click.version_option(version="0.2.
|
|
32
|
+
@click.version_option(version="0.2.2", prog_name="supyagent")
|
|
32
33
|
def cli():
|
|
33
34
|
"""
|
|
34
35
|
Supyagent - LLM agents powered by supypowers.
|
|
@@ -707,15 +708,14 @@ def run(
|
|
|
707
708
|
try:
|
|
708
709
|
config = load_agent_config(agent_name)
|
|
709
710
|
except AgentNotFoundError as e:
|
|
710
|
-
|
|
711
|
+
console_err.print(f"[red]Error:[/red] {e}")
|
|
711
712
|
sys.exit(1)
|
|
712
713
|
|
|
713
714
|
# Warn if using interactive agent in execution mode
|
|
714
715
|
if config.type != "execution" and not quiet:
|
|
715
|
-
|
|
716
|
+
console_err.print(
|
|
716
717
|
f"[yellow]Note:[/yellow] '{agent_name}' is an interactive agent. "
|
|
717
|
-
"Consider using 'chat' for interactive use."
|
|
718
|
-
err=True,
|
|
718
|
+
"Consider using 'chat' for interactive use."
|
|
719
719
|
)
|
|
720
720
|
|
|
721
721
|
# Parse secrets
|
|
@@ -730,9 +730,7 @@ def run(
|
|
|
730
730
|
else:
|
|
731
731
|
input_path = Path(input_file)
|
|
732
732
|
if not input_path.exists():
|
|
733
|
-
|
|
734
|
-
f"[red]Error:[/red] File not found: {input_file}", err=True
|
|
735
|
-
)
|
|
733
|
+
console_err.print(f"[red]Error:[/red] File not found: {input_file}")
|
|
736
734
|
sys.exit(1)
|
|
737
735
|
task_content = input_path.read_text().strip()
|
|
738
736
|
elif task:
|
|
@@ -746,22 +744,21 @@ def run(
|
|
|
746
744
|
if not sys.stdin.isatty():
|
|
747
745
|
task_content = sys.stdin.read().strip()
|
|
748
746
|
else:
|
|
749
|
-
|
|
747
|
+
console_err.print(
|
|
750
748
|
"[red]Error:[/red] No task provided. "
|
|
751
|
-
"Use positional argument, --input, or pipe to stdin."
|
|
752
|
-
err=True,
|
|
749
|
+
"Use positional argument, --input, or pipe to stdin."
|
|
753
750
|
)
|
|
754
751
|
sys.exit(1)
|
|
755
752
|
|
|
756
753
|
if not task_content:
|
|
757
|
-
|
|
754
|
+
console_err.print("[red]Error:[/red] Empty task")
|
|
758
755
|
sys.exit(1)
|
|
759
756
|
|
|
760
757
|
# Run the agent
|
|
761
758
|
runner = ExecutionRunner(config)
|
|
762
759
|
|
|
763
760
|
if not quiet:
|
|
764
|
-
|
|
761
|
+
console_err.print(f"[dim]Running {agent_name}...[/dim]")
|
|
765
762
|
|
|
766
763
|
result = runner.run(task_content, secrets=secrets_dict, output_format=output_format)
|
|
767
764
|
|
|
@@ -771,7 +768,7 @@ def run(
|
|
|
771
768
|
elif result["ok"]:
|
|
772
769
|
click.echo(result["data"])
|
|
773
770
|
else:
|
|
774
|
-
|
|
771
|
+
console_err.print(f"[red]Error:[/red] {result['error']}")
|
|
775
772
|
sys.exit(1)
|
|
776
773
|
|
|
777
774
|
|
|
@@ -827,7 +824,7 @@ def batch(
|
|
|
827
824
|
try:
|
|
828
825
|
config = load_agent_config(agent_name)
|
|
829
826
|
except AgentNotFoundError as e:
|
|
830
|
-
|
|
827
|
+
console_err.print(f"[red]Error:[/red] {e}")
|
|
831
828
|
sys.exit(1)
|
|
832
829
|
|
|
833
830
|
# Parse secrets
|
|
@@ -4,9 +4,13 @@ LiteLLM wrapper for unified LLM access.
|
|
|
4
4
|
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
+
import litellm
|
|
7
8
|
from litellm import completion
|
|
8
9
|
from litellm.types.utils import ModelResponse
|
|
9
10
|
|
|
11
|
+
# Suppress LiteLLM debug messages (e.g., "Provider List: ...")
|
|
12
|
+
litellm.suppress_debug_info = True
|
|
13
|
+
|
|
10
14
|
|
|
11
15
|
class LLMClient:
|
|
12
16
|
"""
|
|
@@ -193,43 +193,61 @@ def supypowers_to_openai_tools(sp_tools: list[dict[str, Any]]) -> list[dict[str,
|
|
|
193
193
|
Convert supypowers tool definitions to OpenAI function calling format.
|
|
194
194
|
|
|
195
195
|
Supypowers docs output format:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
196
|
+
[
|
|
197
|
+
{
|
|
198
|
+
"script": "/path/to/script.py",
|
|
199
|
+
"functions": [
|
|
200
|
+
{
|
|
201
|
+
"name": "function_name",
|
|
202
|
+
"description": "...",
|
|
203
|
+
"input_schema": {...}
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
]
|
|
202
208
|
|
|
203
209
|
OpenAI format:
|
|
204
210
|
{
|
|
205
211
|
"type": "function",
|
|
206
212
|
"function": {
|
|
207
|
-
"name": "
|
|
213
|
+
"name": "script__function_name",
|
|
208
214
|
"description": "...",
|
|
209
215
|
"parameters": {...}
|
|
210
216
|
}
|
|
211
217
|
}
|
|
212
218
|
"""
|
|
219
|
+
import os
|
|
220
|
+
|
|
213
221
|
openai_tools = []
|
|
214
222
|
|
|
215
|
-
for
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
223
|
+
for script_entry in sp_tools:
|
|
224
|
+
script_path = script_entry.get("script", "")
|
|
225
|
+
functions = script_entry.get("functions", [])
|
|
226
|
+
|
|
227
|
+
# Extract script name from path (e.g., "files" from "/path/to/files.py")
|
|
228
|
+
script_name = os.path.splitext(os.path.basename(script_path))[0]
|
|
229
|
+
|
|
230
|
+
# Skip __init__ files with no functions
|
|
231
|
+
if script_name == "__init__" and not functions:
|
|
232
|
+
continue
|
|
233
|
+
|
|
234
|
+
for func_def in functions:
|
|
235
|
+
func_name = func_def.get("name", "")
|
|
236
|
+
description = func_def.get("description", "No description")
|
|
237
|
+
input_schema = func_def.get("input_schema", {"type": "object", "properties": {}})
|
|
238
|
+
|
|
239
|
+
# Use double underscore to join script:function (since : isn't allowed in function names)
|
|
240
|
+
name = f"{script_name}__{func_name}"
|
|
241
|
+
|
|
242
|
+
openai_tool = {
|
|
243
|
+
"type": "function",
|
|
244
|
+
"function": {
|
|
245
|
+
"name": name,
|
|
246
|
+
"description": description,
|
|
247
|
+
"parameters": input_schema,
|
|
248
|
+
},
|
|
249
|
+
}
|
|
232
250
|
|
|
233
|
-
|
|
251
|
+
openai_tools.append(openai_tool)
|
|
234
252
|
|
|
235
253
|
return openai_tools
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Supypowers tools for this project."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|