supyagent 0.1.0__py3-none-any.whl → 0.2.1__py3-none-any.whl
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.
- supyagent/cli/main.py +251 -1
- supyagent/core/__init__.py +3 -0
- supyagent/core/config.py +352 -0
- supyagent/default_tools/__init__.py +74 -0
- supyagent/default_tools/files.py +439 -0
- supyagent/default_tools/shell.py +217 -0
- {supyagent-0.1.0.dist-info → supyagent-0.2.1.dist-info}/METADATA +95 -32
- {supyagent-0.1.0.dist-info → supyagent-0.2.1.dist-info}/RECORD +11 -7
- {supyagent-0.1.0.dist-info → supyagent-0.2.1.dist-info}/WHEEL +0 -0
- {supyagent-0.1.0.dist-info → supyagent-0.2.1.dist-info}/entry_points.txt +0 -0
- {supyagent-0.1.0.dist-info → supyagent-0.2.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# /// script
|
|
2
|
+
# dependencies = ["pydantic"]
|
|
3
|
+
# ///
|
|
4
|
+
"""
|
|
5
|
+
Shell command execution tools.
|
|
6
|
+
|
|
7
|
+
Allows agents to run bash/shell commands on the system.
|
|
8
|
+
Use with caution - consider restricting via agent tool permissions.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import subprocess
|
|
13
|
+
import shutil
|
|
14
|
+
from typing import Optional
|
|
15
|
+
|
|
16
|
+
from pydantic import BaseModel, Field
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class RunCommandInput(BaseModel):
|
|
20
|
+
"""Input for run_command function."""
|
|
21
|
+
|
|
22
|
+
command: str = Field(description="The shell command to execute")
|
|
23
|
+
working_dir: Optional[str] = Field(
|
|
24
|
+
default=None, description="Working directory for the command"
|
|
25
|
+
)
|
|
26
|
+
timeout: int = Field(
|
|
27
|
+
default=60, description="Maximum seconds to wait for command"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class RunCommandOutput(BaseModel):
|
|
32
|
+
"""Output for run_command function."""
|
|
33
|
+
|
|
34
|
+
ok: bool
|
|
35
|
+
stdout: str
|
|
36
|
+
stderr: str
|
|
37
|
+
exit_code: int
|
|
38
|
+
command: str
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def run_command(input: RunCommandInput) -> RunCommandOutput:
|
|
42
|
+
"""
|
|
43
|
+
Execute a shell command and return the result.
|
|
44
|
+
|
|
45
|
+
Examples:
|
|
46
|
+
>>> run_command({"command": "ls -la"})
|
|
47
|
+
>>> run_command({"command": "echo 'hello' | grep hello"})
|
|
48
|
+
>>> run_command({"command": "pwd", "working_dir": "/tmp"})
|
|
49
|
+
"""
|
|
50
|
+
try:
|
|
51
|
+
working_dir = input.working_dir
|
|
52
|
+
if working_dir:
|
|
53
|
+
working_dir = os.path.expanduser(working_dir)
|
|
54
|
+
working_dir = os.path.expandvars(working_dir)
|
|
55
|
+
|
|
56
|
+
result = subprocess.run(
|
|
57
|
+
input.command,
|
|
58
|
+
shell=True,
|
|
59
|
+
capture_output=True,
|
|
60
|
+
text=True,
|
|
61
|
+
timeout=input.timeout,
|
|
62
|
+
cwd=working_dir,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
return RunCommandOutput(
|
|
66
|
+
ok=result.returncode == 0,
|
|
67
|
+
stdout=result.stdout,
|
|
68
|
+
stderr=result.stderr,
|
|
69
|
+
exit_code=result.returncode,
|
|
70
|
+
command=input.command,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
except subprocess.TimeoutExpired:
|
|
74
|
+
return RunCommandOutput(
|
|
75
|
+
ok=False,
|
|
76
|
+
stdout="",
|
|
77
|
+
stderr=f"Command timed out after {input.timeout} seconds",
|
|
78
|
+
exit_code=-1,
|
|
79
|
+
command=input.command,
|
|
80
|
+
)
|
|
81
|
+
except Exception as e:
|
|
82
|
+
return RunCommandOutput(
|
|
83
|
+
ok=False,
|
|
84
|
+
stdout="",
|
|
85
|
+
stderr=str(e),
|
|
86
|
+
exit_code=-1,
|
|
87
|
+
command=input.command,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class RunScriptInput(BaseModel):
|
|
92
|
+
"""Input for run_script function."""
|
|
93
|
+
|
|
94
|
+
script: str = Field(description="Multi-line script content")
|
|
95
|
+
interpreter: str = Field(
|
|
96
|
+
default="/bin/bash", description="Script interpreter"
|
|
97
|
+
)
|
|
98
|
+
working_dir: Optional[str] = Field(
|
|
99
|
+
default=None, description="Working directory"
|
|
100
|
+
)
|
|
101
|
+
timeout: int = Field(default=120, description="Max seconds to wait")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class RunScriptOutput(BaseModel):
|
|
105
|
+
"""Output for run_script function."""
|
|
106
|
+
|
|
107
|
+
ok: bool
|
|
108
|
+
stdout: str
|
|
109
|
+
stderr: str
|
|
110
|
+
exit_code: int
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def run_script(input: RunScriptInput) -> RunScriptOutput:
|
|
114
|
+
"""
|
|
115
|
+
Execute a multi-line shell script.
|
|
116
|
+
|
|
117
|
+
Examples:
|
|
118
|
+
>>> run_script({"script": "cd /tmp\\necho $(pwd)\\nls"})
|
|
119
|
+
"""
|
|
120
|
+
try:
|
|
121
|
+
working_dir = input.working_dir
|
|
122
|
+
if working_dir:
|
|
123
|
+
working_dir = os.path.expanduser(working_dir)
|
|
124
|
+
|
|
125
|
+
result = subprocess.run(
|
|
126
|
+
[input.interpreter],
|
|
127
|
+
input=input.script,
|
|
128
|
+
capture_output=True,
|
|
129
|
+
text=True,
|
|
130
|
+
timeout=input.timeout,
|
|
131
|
+
cwd=working_dir,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
return RunScriptOutput(
|
|
135
|
+
ok=result.returncode == 0,
|
|
136
|
+
stdout=result.stdout,
|
|
137
|
+
stderr=result.stderr,
|
|
138
|
+
exit_code=result.returncode,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
except subprocess.TimeoutExpired:
|
|
142
|
+
return RunScriptOutput(
|
|
143
|
+
ok=False,
|
|
144
|
+
stdout="",
|
|
145
|
+
stderr=f"Script timed out after {input.timeout} seconds",
|
|
146
|
+
exit_code=-1,
|
|
147
|
+
)
|
|
148
|
+
except Exception as e:
|
|
149
|
+
return RunScriptOutput(
|
|
150
|
+
ok=False,
|
|
151
|
+
stdout="",
|
|
152
|
+
stderr=str(e),
|
|
153
|
+
exit_code=-1,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class WhichInput(BaseModel):
|
|
158
|
+
"""Input for which function."""
|
|
159
|
+
|
|
160
|
+
command: str = Field(description="Command name to look up")
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class WhichOutput(BaseModel):
|
|
164
|
+
"""Output for which function."""
|
|
165
|
+
|
|
166
|
+
ok: bool
|
|
167
|
+
path: Optional[str] = None
|
|
168
|
+
error: Optional[str] = None
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def which(input: WhichInput) -> WhichOutput:
|
|
172
|
+
"""
|
|
173
|
+
Find the path to an executable.
|
|
174
|
+
|
|
175
|
+
Examples:
|
|
176
|
+
>>> which({"command": "python"})
|
|
177
|
+
>>> which({"command": "git"})
|
|
178
|
+
"""
|
|
179
|
+
path = shutil.which(input.command)
|
|
180
|
+
if path:
|
|
181
|
+
return WhichOutput(ok=True, path=path)
|
|
182
|
+
else:
|
|
183
|
+
return WhichOutput(ok=False, error=f"Command not found: {input.command}")
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class GetEnvInput(BaseModel):
|
|
187
|
+
"""Input for get_env function."""
|
|
188
|
+
|
|
189
|
+
name: str = Field(description="Environment variable name")
|
|
190
|
+
default: Optional[str] = Field(
|
|
191
|
+
default=None, description="Default if not set"
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class GetEnvOutput(BaseModel):
|
|
196
|
+
"""Output for get_env function."""
|
|
197
|
+
|
|
198
|
+
ok: bool
|
|
199
|
+
value: Optional[str] = None
|
|
200
|
+
error: Optional[str] = None
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def get_env(input: GetEnvInput) -> GetEnvOutput:
|
|
204
|
+
"""
|
|
205
|
+
Get an environment variable value.
|
|
206
|
+
|
|
207
|
+
Examples:
|
|
208
|
+
>>> get_env({"name": "HOME"})
|
|
209
|
+
>>> get_env({"name": "MY_VAR", "default": "fallback"})
|
|
210
|
+
"""
|
|
211
|
+
value = os.environ.get(input.name, input.default)
|
|
212
|
+
if value is not None:
|
|
213
|
+
return GetEnvOutput(ok=True, value=value)
|
|
214
|
+
else:
|
|
215
|
+
return GetEnvOutput(
|
|
216
|
+
ok=False, error=f"Environment variable not set: {input.name}"
|
|
217
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: supyagent
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
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
|
|
@@ -68,6 +68,12 @@ uv pip install supyagent
|
|
|
68
68
|
## Quick Start
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
|
+
# Initialize supyagent (sets up default tools)
|
|
72
|
+
supyagent init
|
|
73
|
+
|
|
74
|
+
# Set up your API key (stored securely)
|
|
75
|
+
supyagent config set ANTHROPIC_API_KEY
|
|
76
|
+
|
|
71
77
|
# Create your first agent
|
|
72
78
|
supyagent new myagent
|
|
73
79
|
|
|
@@ -133,39 +139,40 @@ supyagent plan "Build a Python library for data validation"
|
|
|
133
139
|
# The planner will delegate to specialist agents (coder, writer, researcher)
|
|
134
140
|
```
|
|
135
141
|
|
|
136
|
-
##
|
|
142
|
+
## Configuration
|
|
137
143
|
|
|
138
|
-
|
|
144
|
+
### Setting Up API Keys
|
|
139
145
|
|
|
140
|
-
|
|
141
|
-
name: researcher
|
|
142
|
-
description: An AI research assistant
|
|
143
|
-
type: interactive # or "execution"
|
|
146
|
+
Supyagent securely stores your LLM API keys so you don't need to export them every time:
|
|
144
147
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
```bash
|
|
149
|
+
# Interactive setup (recommended)
|
|
150
|
+
supyagent config set
|
|
151
|
+
# Shows a menu of common providers to choose from
|
|
149
152
|
|
|
150
|
-
|
|
151
|
-
|
|
153
|
+
# Set a specific key
|
|
154
|
+
supyagent config set ANTHROPIC_API_KEY
|
|
155
|
+
supyagent config set OPENAI_API_KEY
|
|
152
156
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
- "*" # Allow all tools
|
|
156
|
-
# or be specific:
|
|
157
|
-
# - "web:*" # All functions in web.py
|
|
158
|
-
# - "math:calc" # Specific function
|
|
159
|
-
deny:
|
|
160
|
-
- "dangerous:*" # Block specific tools
|
|
157
|
+
# Import from a .env file
|
|
158
|
+
supyagent config import .env
|
|
161
159
|
|
|
162
|
-
#
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
160
|
+
# Import only specific keys
|
|
161
|
+
supyagent config import .env --filter OPENAI
|
|
162
|
+
|
|
163
|
+
# List configured keys
|
|
164
|
+
supyagent config list
|
|
165
|
+
|
|
166
|
+
# Export keys to backup
|
|
167
|
+
supyagent config export backup.env
|
|
168
|
+
|
|
169
|
+
# Delete a key
|
|
170
|
+
supyagent config delete OPENAI_API_KEY
|
|
166
171
|
```
|
|
167
172
|
|
|
168
|
-
|
|
173
|
+
Keys are encrypted and stored in `~/.supyagent/config/`. They're automatically loaded when running any agent command.
|
|
174
|
+
|
|
175
|
+
### Supported Providers
|
|
169
176
|
|
|
170
177
|
Supyagent uses LiteLLM, supporting 100+ providers:
|
|
171
178
|
|
|
@@ -187,11 +194,36 @@ model:
|
|
|
187
194
|
provider: gemini/gemini-pro
|
|
188
195
|
```
|
|
189
196
|
|
|
190
|
-
|
|
197
|
+
## Agent Configuration
|
|
191
198
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
199
|
+
Agents are defined in YAML files in the `agents/` directory:
|
|
200
|
+
|
|
201
|
+
```yaml
|
|
202
|
+
name: researcher
|
|
203
|
+
description: An AI research assistant
|
|
204
|
+
type: interactive # or "execution"
|
|
205
|
+
|
|
206
|
+
model:
|
|
207
|
+
provider: anthropic/claude-3-5-sonnet-20241022
|
|
208
|
+
temperature: 0.7
|
|
209
|
+
max_tokens: 4096
|
|
210
|
+
|
|
211
|
+
system_prompt: |
|
|
212
|
+
You are a helpful research assistant...
|
|
213
|
+
|
|
214
|
+
tools:
|
|
215
|
+
allow:
|
|
216
|
+
- "*" # Allow all tools
|
|
217
|
+
# or be specific:
|
|
218
|
+
# - "web:*" # All functions in web.py
|
|
219
|
+
# - "math:calc" # Specific function
|
|
220
|
+
deny:
|
|
221
|
+
- "dangerous:*" # Block specific tools
|
|
222
|
+
|
|
223
|
+
# For multi-agent support
|
|
224
|
+
delegates:
|
|
225
|
+
- coder
|
|
226
|
+
- writer
|
|
195
227
|
```
|
|
196
228
|
|
|
197
229
|
## CLI Reference
|
|
@@ -200,6 +232,7 @@ export ANTHROPIC_API_KEY=sk-ant-...
|
|
|
200
232
|
|
|
201
233
|
| Command | Description |
|
|
202
234
|
|---------|-------------|
|
|
235
|
+
| `supyagent init` | Initialize project with default tools |
|
|
203
236
|
| `supyagent new <name>` | Create a new agent |
|
|
204
237
|
| `supyagent list` | List all agents |
|
|
205
238
|
| `supyagent show <name>` | Show agent details |
|
|
@@ -223,6 +256,16 @@ export ANTHROPIC_API_KEY=sk-ant-...
|
|
|
223
256
|
| `supyagent agents` | List active agent instances |
|
|
224
257
|
| `supyagent cleanup` | Remove completed instances |
|
|
225
258
|
|
|
259
|
+
### Config Commands
|
|
260
|
+
|
|
261
|
+
| Command | Description |
|
|
262
|
+
|---------|-------------|
|
|
263
|
+
| `supyagent config set [KEY]` | Set an API key (interactive menu if no key specified) |
|
|
264
|
+
| `supyagent config list` | List all configured keys |
|
|
265
|
+
| `supyagent config import <file>` | Import keys from .env file |
|
|
266
|
+
| `supyagent config export <file>` | Export keys to .env file |
|
|
267
|
+
| `supyagent config delete <key>` | Delete a stored key |
|
|
268
|
+
|
|
226
269
|
### In-Chat Commands
|
|
227
270
|
|
|
228
271
|
While chatting, use these commands:
|
|
@@ -242,6 +285,25 @@ While chatting, use these commands:
|
|
|
242
285
|
| `/clear` | Clear conversation history |
|
|
243
286
|
| `/quit` | Exit the chat |
|
|
244
287
|
|
|
288
|
+
## Bundled Tools
|
|
289
|
+
|
|
290
|
+
Running `supyagent init` installs these default tools:
|
|
291
|
+
|
|
292
|
+
### Shell (`shell.py`)
|
|
293
|
+
- `run_command` - Execute shell commands
|
|
294
|
+
- `run_script` - Run multi-line bash scripts
|
|
295
|
+
- `which` - Find executable paths
|
|
296
|
+
- `get_env` - Get environment variables
|
|
297
|
+
|
|
298
|
+
### Files (`files.py`)
|
|
299
|
+
- `read_file` / `write_file` - File I/O
|
|
300
|
+
- `list_directory` - List files with glob patterns
|
|
301
|
+
- `copy_file` / `move_file` / `delete_file` - File operations
|
|
302
|
+
- `create_directory` - Create directories
|
|
303
|
+
- `file_info` - Get file metadata
|
|
304
|
+
|
|
305
|
+
You can add your own tools by creating Python files in `supypowers/`.
|
|
306
|
+
|
|
245
307
|
## Project Structure
|
|
246
308
|
|
|
247
309
|
```
|
|
@@ -251,8 +313,9 @@ your-project/
|
|
|
251
313
|
│ ├── planner.yaml
|
|
252
314
|
│ └── researcher.yaml
|
|
253
315
|
├── supypowers/ # Tool definitions (Python)
|
|
254
|
-
│ ├──
|
|
255
|
-
│
|
|
316
|
+
│ ├── shell.py # Shell commands (bundled)
|
|
317
|
+
│ ├── files.py # File operations (bundled)
|
|
318
|
+
│ └── my_tools.py # Your custom tools
|
|
256
319
|
└── .supyagent/ # Runtime data (gitignore this)
|
|
257
320
|
├── sessions/ # Conversation history
|
|
258
321
|
├── credentials/ # Encrypted secrets
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
supyagent/__init__.py,sha256=JrrQbk1bmDhUb2qOqxqDGBq1V-oArwVS4f5f9Qu-VcM,77
|
|
2
2
|
supyagent/__main__.py,sha256=szUvsccEIA428c2_5J_X1qzq4L44qLvDvHfuRPYoy7c,121
|
|
3
3
|
supyagent/cli/__init__.py,sha256=7jb5kxHtzce4rNKd9zrAiATp3Zxj7UQvtpQsyA97BTc,32
|
|
4
|
-
supyagent/cli/main.py,sha256=
|
|
5
|
-
supyagent/core/__init__.py,sha256=
|
|
4
|
+
supyagent/cli/main.py,sha256=6jXcEZjLRgE_9PnPvyg-6BWGg5_yB71xZOD8_cejSno,38515
|
|
5
|
+
supyagent/core/__init__.py,sha256=7MI6K2-OR_Fg0wcMziC4u3gNa0YxWmzJXO0RtOCevUg,727
|
|
6
6
|
supyagent/core/agent.py,sha256=mkiV6CnK6Vk0Wg-DiAMm29wAViMa52-1Yb33Y5-FvQY,12655
|
|
7
|
+
supyagent/core/config.py,sha256=kuTpuxy-qr-fhou7rJ-JLF82cdzdHQTu46kCZccSw1Y,10041
|
|
7
8
|
supyagent/core/context.py,sha256=ywen6IjWxcudxtipeqA_PHpZKdjK52eqOb9xy7QKnTM,4565
|
|
8
9
|
supyagent/core/credentials.py,sha256=35JBrzMOEDzHnn3XuyGmRjXVdSICL3tups3BLO_NCXQ,7600
|
|
9
10
|
supyagent/core/delegation.py,sha256=B6OYlLjkZaRTPMQsK9nIGeXVO9JeC7RDpxXsOk652xs,9391
|
|
@@ -12,13 +13,16 @@ supyagent/core/llm.py,sha256=z16cjqjPfwRGtEpUhZe1XlzOXJdlgKHjckNdeJnEWYw,1898
|
|
|
12
13
|
supyagent/core/registry.py,sha256=1CGCPsOcrIc_63_oJaFmHY8WwMgJEvbwsv8mnsOBWtY,7326
|
|
13
14
|
supyagent/core/session_manager.py,sha256=ngqrbofR8V0wZSuOfGHTtSYE0C9U6noDrzfDsO8wi24,7389
|
|
14
15
|
supyagent/core/tools.py,sha256=exIynhwulsMJTzzW5NmDqBeXepULAt4FlVhGbtrvdXE,6627
|
|
16
|
+
supyagent/default_tools/__init__.py,sha256=VwVjwNSPxjflmzJ-Mv_7L79Yjn9LdxyeXNUkWzu3wFo,1890
|
|
17
|
+
supyagent/default_tools/files.py,sha256=tUpjkP7TKbcK75lQ6jzEDpVDBSeupzTSqx_g2-rkON0,12059
|
|
18
|
+
supyagent/default_tools/shell.py,sha256=fYXdy693Nb0hsNLMzTFgj3zaHq0wFSQ3SxpqHbVayjM,5478
|
|
15
19
|
supyagent/models/__init__.py,sha256=y7fIdzh-yD0LKAK0zfY_MZdtjJhxofwRWBqrHDU93h0,259
|
|
16
20
|
supyagent/models/agent_config.py,sha256=sQ7S7zExoFs0g-IMgACsGH2SMiDRjJTnCVZwhN6DnkY,2570
|
|
17
21
|
supyagent/models/session.py,sha256=_Dwuija_Uvt_KzcNp82ja8qP5ltNHHz43Llug1vq1ic,1136
|
|
18
22
|
supyagent/utils/__init__.py,sha256=l4HdE3n8axphMInBex1J1dB_O1MjzbZz6ot1l8Syf0g,39
|
|
19
23
|
supyagent/utils/paths.py,sha256=Xum9kX_UjRvmshifSq423QsAKynpnyAVfpWuFjlsdDQ,692
|
|
20
|
-
supyagent-0.1.
|
|
21
|
-
supyagent-0.1.
|
|
22
|
-
supyagent-0.1.
|
|
23
|
-
supyagent-0.1.
|
|
24
|
-
supyagent-0.1.
|
|
24
|
+
supyagent-0.2.1.dist-info/METADATA,sha256=5sn1RwCPZ0Ja2ZGLatdfHlgg7KZnCr3v0u7zywAgpSs,10387
|
|
25
|
+
supyagent-0.2.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
26
|
+
supyagent-0.2.1.dist-info/entry_points.txt,sha256=7dFXWtRewhLfA5XUckV7Yu1E5_c6c9lq8Gz-7BFs6TM,53
|
|
27
|
+
supyagent-0.2.1.dist-info/licenses/LICENSE,sha256=35fw1cvTM-IhiR3xaUohbiFBc2OBNRjI5z1b1cF7vZI,1067
|
|
28
|
+
supyagent-0.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|