agentnova 0.3.2__tar.gz → 0.3.4__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.
- {agentnova-0.3.2 → agentnova-0.3.4}/PKG-INFO +55 -3
- {agentnova-0.3.2 → agentnova-0.3.4}/README.md +54 -2
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/__init__.py +1 -1
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/acp_plugin.py +149 -0
- agentnova-0.3.4/agentnova/agent.py +1028 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/backends/__init__.py +11 -3
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/backends/ollama.py +417 -3
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/cli.py +45 -6
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/config.py +15 -4
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/__init__.py +59 -7
- agentnova-0.3.4/agentnova/core/error_recovery.py +725 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/helpers.py +16 -1
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/memory.py +30 -10
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/models.py +12 -2
- agentnova-0.3.4/agentnova/core/openresponses.py +812 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/prompts.py +54 -166
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/tool_parse.py +118 -212
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/types.py +15 -1
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/00_basic_agent.py +22 -6
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/01_quick_diagnostic.py +16 -4
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/02_tool_test.py +46 -19
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/04_gsm8k_benchmark.py +1 -1
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/__init__.py +16 -2
- agentnova-0.3.4/agentnova/skills/loader.py +1893 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/soul/__init__.py +99 -97
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/soul/loader.py +514 -5
- agentnova-0.3.4/agentnova/souls/nova-helper/IDENTITY.md +14 -0
- agentnova-0.3.4/agentnova/souls/nova-helper/SOUL.md +127 -0
- agentnova-0.3.4/agentnova/souls/nova-helper/STYLE.md +83 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/souls/nova-helper/soul.json +30 -30
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/tools/builtins.py +22 -5
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova.egg-info/PKG-INFO +55 -3
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova.egg-info/SOURCES.txt +2 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/pyproject.toml +1 -1
- agentnova-0.3.2/agentnova/agent.py +0 -981
- agentnova-0.3.2/agentnova/skills/loader.py +0 -445
- agentnova-0.3.2/agentnova/souls/nova-helper/IDENTITY.md +0 -36
- agentnova-0.3.2/agentnova/souls/nova-helper/SOUL.md +0 -51
- agentnova-0.3.2/agentnova/souls/nova-helper/STYLE.md +0 -49
- {agentnova-0.3.2 → agentnova-0.3.4}/LICENSE +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/__main__.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/agent_mode.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/backends/base.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/backends/bitnet.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/args_normal.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/math_prompts.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/model_config.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/model_family_config.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/03_reasoning_test.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/05_common_sense.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/06_causal_reasoning.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/07_logical_deduction.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/08_reading_comprehension.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/09_general_knowledge.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/10_implicit_reasoning.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/11_analogical_reasoning.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/__init__.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/model_discovery.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/orchestrator.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/orchestrator_enhanced.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/py.typed +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/shared_args.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/acp/SKILL.md +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/datetime/SKILL.md +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/SKILL.md +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/__init__.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/aggregate_benchmark.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/generate_report.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/improve_description.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/init_skill.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/package_skill.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/quick_validate.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/run_eval.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/run_loop.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/security_scan.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/test_package_skill.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/test_quick_validate.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/utils.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/validate.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/web-search/SKILL.md +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/soul/types.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/tools/__init__.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/tools/registry.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/tools/sandboxed_repl.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova.egg-info/dependency_links.txt +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova.egg-info/entry_points.txt +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova.egg-info/requires.txt +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/agentnova.egg-info/top_level.txt +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/localclaw/__init__.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/localclaw-redirect/localclaw/__init__.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/setup.cfg +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/tests/test_acp_integration.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/tests/test_acp_subagents.py +0 -0
- {agentnova-0.3.2 → agentnova-0.3.4}/tests/test_agent.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentnova
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: ⚛️ AgentNova - A minimal, hackable agentic framework for local LLM inference
|
|
5
5
|
Author-email: VTSTech <veritas@vts-tech.org>
|
|
6
6
|
Maintainer-email: VTSTech <veritas@vts-tech.org>
|
|
@@ -32,7 +32,7 @@ Requires-Dist: black>=23.0; extra == "dev"
|
|
|
32
32
|
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
33
33
|
Dynamic: license-file
|
|
34
34
|
|
|
35
|
-
# ⚛️ AgentNova R03.
|
|
35
|
+
# ⚛️ AgentNova R03.3
|
|
36
36
|
|
|
37
37
|
**Status: Alpha**
|
|
38
38
|
|
|
@@ -49,7 +49,7 @@ Inspired by the architecture of OpenClaw, rebuilt from scratch for local-first o
|
|
|
49
49
|
|
|
50
50
|
[](#license) [](https://python.org)
|
|
51
51
|
|
|
52
|
-
<img width="
|
|
52
|
+
<img width="1400" height="1001" alt="image" src="https://github.com/user-attachments/assets/1bc8fb7a-415b-4750-9ce2-1e721bbf9149" />
|
|
53
53
|
|
|
54
54
|
## 📚 Documentation
|
|
55
55
|
|
|
@@ -63,10 +63,14 @@ Inspired by the architecture of OpenClaw, rebuilt from scratch for local-first o
|
|
|
63
63
|
|
|
64
64
|
- **Zero dependencies** — Uses Python stdlib only (urllib for HTTP)
|
|
65
65
|
- **Ollama + BitNet backends** — Switch with `--backend` flag
|
|
66
|
+
- **Dual API support** — OpenResponses (`--api resp`) and Chat-Completions (`--api comp`)
|
|
66
67
|
- **Three-tier tool support** — Native, ReAct, or none (auto-detected)
|
|
67
68
|
- **Small model optimized** — Fuzzy matching, argument normalization
|
|
68
69
|
- **Built-in security** — Path validation, command blocklist, SSRF protection
|
|
69
70
|
- **Multi-agent orchestration** — Router, pipeline, and parallel modes
|
|
71
|
+
- **Soul Spec v0.5** — Persona packages with progressive disclosure
|
|
72
|
+
- **ACP v1.0.5 integration** — Agent Control Panel for monitoring and control
|
|
73
|
+
- **AgentSkills spec** — Skill loading with SPDX license validation
|
|
70
74
|
|
|
71
75
|
## Installation
|
|
72
76
|
|
|
@@ -94,6 +98,9 @@ agentnova chat -m qwen2.5:0.5b --tools calculator,shell
|
|
|
94
98
|
# Autonomous agent mode
|
|
95
99
|
agentnova agent -m qwen2.5:7b --tools calculator,shell,write_file
|
|
96
100
|
|
|
101
|
+
# Use Chat-Completions API (OpenAI-compatible)
|
|
102
|
+
agentnova chat -m qwen2.5:0.5b --api comp
|
|
103
|
+
|
|
97
104
|
# List available models
|
|
98
105
|
agentnova models
|
|
99
106
|
|
|
@@ -123,6 +130,37 @@ print(result.final_answer)
|
|
|
123
130
|
print(f"Completed in {result.total_ms:.0f}ms")
|
|
124
131
|
```
|
|
125
132
|
|
|
133
|
+
### Chat-Completions Streaming
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from agentnova.backends import get_backend
|
|
137
|
+
from agentnova.core.types import ApiMode
|
|
138
|
+
|
|
139
|
+
# Use Chat-Completions mode with streaming
|
|
140
|
+
backend = get_backend("ollama", api_mode=ApiMode.COMPLETIONS)
|
|
141
|
+
|
|
142
|
+
for chunk in backend.generate_completions_stream(
|
|
143
|
+
model="qwen2.5:0.5b",
|
|
144
|
+
messages=[{"role": "user", "content": "Hello!"}],
|
|
145
|
+
response_format={"type": "json_object"}
|
|
146
|
+
):
|
|
147
|
+
print(chunk["delta"], end="", flush=True)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Skill License Validation
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
from agentnova.skills import validate_spdx_license, parse_compatibility
|
|
154
|
+
|
|
155
|
+
# Validate SPDX license identifier
|
|
156
|
+
valid, msg = validate_spdx_license("MIT") # (True, "Valid SPDX identifier: MIT")
|
|
157
|
+
valid, msg = validate_spdx_license("Custom") # (False, "Unknown license...")
|
|
158
|
+
|
|
159
|
+
# Parse compatibility requirements
|
|
160
|
+
compat = parse_compatibility("python>=3.8, ollama")
|
|
161
|
+
# Returns: {"python": ">=3.8", "runtimes": ["ollama"], "frameworks": []}
|
|
162
|
+
```
|
|
163
|
+
|
|
126
164
|
### Multi-Agent Orchestration
|
|
127
165
|
|
|
128
166
|
```python
|
|
@@ -218,6 +256,20 @@ agentnova config
|
|
|
218
256
|
agentnova config --urls # Show only URLs
|
|
219
257
|
```
|
|
220
258
|
|
|
259
|
+
### CLI Options (run, chat, agent)
|
|
260
|
+
|
|
261
|
+
| Option | Description |
|
|
262
|
+
|--------|-------------|
|
|
263
|
+
| `--api resp\|comp` | API mode: OpenResponses (default) or Chat-Completions |
|
|
264
|
+
| `--response-format text\|json` | Response format (Chat-Completions mode) |
|
|
265
|
+
| `--truncation auto\|disabled` | Truncation behavior for long responses |
|
|
266
|
+
| `--soul <path>` | Load Soul Spec persona package |
|
|
267
|
+
| `--soul-level 1-3` | Progressive disclosure level |
|
|
268
|
+
| `--num-ctx <tokens>` | Context window size (default: 4096) |
|
|
269
|
+
| `--timeout <seconds>` | Request timeout (default: 120) |
|
|
270
|
+
| `--acp` | Enable ACP (Agent Control Panel) logging |
|
|
271
|
+
| `--acp-url <url>` | ACP server URL |
|
|
272
|
+
|
|
221
273
|
## LocalClaw Redirect
|
|
222
274
|
|
|
223
275
|
The `localclaw` command is provided for backward compatibility:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# ⚛️ AgentNova R03.
|
|
1
|
+
# ⚛️ AgentNova R03.3
|
|
2
2
|
|
|
3
3
|
**Status: Alpha**
|
|
4
4
|
|
|
@@ -15,7 +15,7 @@ Inspired by the architecture of OpenClaw, rebuilt from scratch for local-first o
|
|
|
15
15
|
|
|
16
16
|
[](#license) [](https://python.org)
|
|
17
17
|
|
|
18
|
-
<img width="
|
|
18
|
+
<img width="1400" height="1001" alt="image" src="https://github.com/user-attachments/assets/1bc8fb7a-415b-4750-9ce2-1e721bbf9149" />
|
|
19
19
|
|
|
20
20
|
## 📚 Documentation
|
|
21
21
|
|
|
@@ -29,10 +29,14 @@ Inspired by the architecture of OpenClaw, rebuilt from scratch for local-first o
|
|
|
29
29
|
|
|
30
30
|
- **Zero dependencies** — Uses Python stdlib only (urllib for HTTP)
|
|
31
31
|
- **Ollama + BitNet backends** — Switch with `--backend` flag
|
|
32
|
+
- **Dual API support** — OpenResponses (`--api resp`) and Chat-Completions (`--api comp`)
|
|
32
33
|
- **Three-tier tool support** — Native, ReAct, or none (auto-detected)
|
|
33
34
|
- **Small model optimized** — Fuzzy matching, argument normalization
|
|
34
35
|
- **Built-in security** — Path validation, command blocklist, SSRF protection
|
|
35
36
|
- **Multi-agent orchestration** — Router, pipeline, and parallel modes
|
|
37
|
+
- **Soul Spec v0.5** — Persona packages with progressive disclosure
|
|
38
|
+
- **ACP v1.0.5 integration** — Agent Control Panel for monitoring and control
|
|
39
|
+
- **AgentSkills spec** — Skill loading with SPDX license validation
|
|
36
40
|
|
|
37
41
|
## Installation
|
|
38
42
|
|
|
@@ -60,6 +64,9 @@ agentnova chat -m qwen2.5:0.5b --tools calculator,shell
|
|
|
60
64
|
# Autonomous agent mode
|
|
61
65
|
agentnova agent -m qwen2.5:7b --tools calculator,shell,write_file
|
|
62
66
|
|
|
67
|
+
# Use Chat-Completions API (OpenAI-compatible)
|
|
68
|
+
agentnova chat -m qwen2.5:0.5b --api comp
|
|
69
|
+
|
|
63
70
|
# List available models
|
|
64
71
|
agentnova models
|
|
65
72
|
|
|
@@ -89,6 +96,37 @@ print(result.final_answer)
|
|
|
89
96
|
print(f"Completed in {result.total_ms:.0f}ms")
|
|
90
97
|
```
|
|
91
98
|
|
|
99
|
+
### Chat-Completions Streaming
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from agentnova.backends import get_backend
|
|
103
|
+
from agentnova.core.types import ApiMode
|
|
104
|
+
|
|
105
|
+
# Use Chat-Completions mode with streaming
|
|
106
|
+
backend = get_backend("ollama", api_mode=ApiMode.COMPLETIONS)
|
|
107
|
+
|
|
108
|
+
for chunk in backend.generate_completions_stream(
|
|
109
|
+
model="qwen2.5:0.5b",
|
|
110
|
+
messages=[{"role": "user", "content": "Hello!"}],
|
|
111
|
+
response_format={"type": "json_object"}
|
|
112
|
+
):
|
|
113
|
+
print(chunk["delta"], end="", flush=True)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Skill License Validation
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from agentnova.skills import validate_spdx_license, parse_compatibility
|
|
120
|
+
|
|
121
|
+
# Validate SPDX license identifier
|
|
122
|
+
valid, msg = validate_spdx_license("MIT") # (True, "Valid SPDX identifier: MIT")
|
|
123
|
+
valid, msg = validate_spdx_license("Custom") # (False, "Unknown license...")
|
|
124
|
+
|
|
125
|
+
# Parse compatibility requirements
|
|
126
|
+
compat = parse_compatibility("python>=3.8, ollama")
|
|
127
|
+
# Returns: {"python": ">=3.8", "runtimes": ["ollama"], "frameworks": []}
|
|
128
|
+
```
|
|
129
|
+
|
|
92
130
|
### Multi-Agent Orchestration
|
|
93
131
|
|
|
94
132
|
```python
|
|
@@ -184,6 +222,20 @@ agentnova config
|
|
|
184
222
|
agentnova config --urls # Show only URLs
|
|
185
223
|
```
|
|
186
224
|
|
|
225
|
+
### CLI Options (run, chat, agent)
|
|
226
|
+
|
|
227
|
+
| Option | Description |
|
|
228
|
+
|--------|-------------|
|
|
229
|
+
| `--api resp\|comp` | API mode: OpenResponses (default) or Chat-Completions |
|
|
230
|
+
| `--response-format text\|json` | Response format (Chat-Completions mode) |
|
|
231
|
+
| `--truncation auto\|disabled` | Truncation behavior for long responses |
|
|
232
|
+
| `--soul <path>` | Load Soul Spec persona package |
|
|
233
|
+
| `--soul-level 1-3` | Progressive disclosure level |
|
|
234
|
+
| `--num-ctx <tokens>` | Context window size (default: 4096) |
|
|
235
|
+
| `--timeout <seconds>` | Request timeout (default: 120) |
|
|
236
|
+
| `--acp` | Enable ACP (Agent Control Panel) logging |
|
|
237
|
+
| `--acp-url <url>` | ACP server URL |
|
|
238
|
+
|
|
187
239
|
## LocalClaw Redirect
|
|
188
240
|
|
|
189
241
|
The `localclaw` command is provided for backward compatibility:
|
|
@@ -2059,3 +2059,152 @@ class ACPPlugin:
|
|
|
2059
2059
|
|
|
2060
2060
|
self._log(f"A2A: Broadcast {action} to {len(results)} agent(s)")
|
|
2061
2061
|
return results
|
|
2062
|
+
|
|
2063
|
+
# ------------------------------------------------------------------ #
|
|
2064
|
+
# Batch Context Manager (v1.0.6) #
|
|
2065
|
+
# ------------------------------------------------------------------ #
|
|
2066
|
+
|
|
2067
|
+
def batch_context(
|
|
2068
|
+
self,
|
|
2069
|
+
description: str = "Batch operation",
|
|
2070
|
+
auto_complete: bool = True,
|
|
2071
|
+
):
|
|
2072
|
+
"""
|
|
2073
|
+
Context manager for batch operations.
|
|
2074
|
+
|
|
2075
|
+
This provides a convenient way to group multiple activities
|
|
2076
|
+
into a single batch with automatic completion.
|
|
2077
|
+
|
|
2078
|
+
Parameters
|
|
2079
|
+
----------
|
|
2080
|
+
description : str
|
|
2081
|
+
Description for the batch operation
|
|
2082
|
+
auto_complete : bool
|
|
2083
|
+
Whether to automatically complete all activities on exit (default: True)
|
|
2084
|
+
|
|
2085
|
+
Yields
|
|
2086
|
+
------
|
|
2087
|
+
BatchHelper
|
|
2088
|
+
A helper object for adding activities to the batch
|
|
2089
|
+
|
|
2090
|
+
Example
|
|
2091
|
+
-------
|
|
2092
|
+
>>> with acp.batch_context("Read multiple config files") as batch:
|
|
2093
|
+
... batch.add_read("/etc/config1.yaml")
|
|
2094
|
+
... batch.add_read("/etc/config2.yaml")
|
|
2095
|
+
... batch.add_read("/etc/config3.yaml")
|
|
2096
|
+
>>> # All activities are automatically started and completed
|
|
2097
|
+
"""
|
|
2098
|
+
return _BatchContext(self, description, auto_complete)
|
|
2099
|
+
|
|
2100
|
+
|
|
2101
|
+
class _BatchContext:
|
|
2102
|
+
"""
|
|
2103
|
+
Internal batch context manager for grouping activities.
|
|
2104
|
+
|
|
2105
|
+
Collects activities and submits them as a batch when the context exits.
|
|
2106
|
+
"""
|
|
2107
|
+
|
|
2108
|
+
def __init__(self, acp: "ACPPlugin", description: str, auto_complete: bool):
|
|
2109
|
+
self._acp = acp
|
|
2110
|
+
self._description = description
|
|
2111
|
+
self._auto_complete = auto_complete
|
|
2112
|
+
self._activities: list[dict] = []
|
|
2113
|
+
self._results: list[dict] = []
|
|
2114
|
+
self._activity_ids: list[str] = []
|
|
2115
|
+
|
|
2116
|
+
def add(self, action: str, target: str, details: str = "", **kwargs) -> None:
|
|
2117
|
+
"""
|
|
2118
|
+
Add an activity to the batch.
|
|
2119
|
+
|
|
2120
|
+
Parameters
|
|
2121
|
+
----------
|
|
2122
|
+
action : str
|
|
2123
|
+
Action type (READ, WRITE, EDIT, BASH, etc.)
|
|
2124
|
+
target : str
|
|
2125
|
+
Target for the action (file path, command, etc.)
|
|
2126
|
+
details : str
|
|
2127
|
+
Optional details about the activity
|
|
2128
|
+
**kwargs
|
|
2129
|
+
Additional fields (content_size, priority, etc.)
|
|
2130
|
+
"""
|
|
2131
|
+
self._activities.append({
|
|
2132
|
+
"action": action,
|
|
2133
|
+
"target": target,
|
|
2134
|
+
"details": details,
|
|
2135
|
+
**kwargs
|
|
2136
|
+
})
|
|
2137
|
+
|
|
2138
|
+
def add_read(self, path: str, content_size: int = 0) -> None:
|
|
2139
|
+
"""Add a READ activity for a file."""
|
|
2140
|
+
self.add("READ", path, f"Read file: {path}", content_size=content_size)
|
|
2141
|
+
|
|
2142
|
+
def add_write(self, path: str, content_size: int = 0) -> None:
|
|
2143
|
+
"""Add a WRITE activity for a file."""
|
|
2144
|
+
self.add("WRITE", path, f"Write file: {path}", content_size=content_size)
|
|
2145
|
+
|
|
2146
|
+
def add_edit(self, path: str, content_size: int = 0) -> None:
|
|
2147
|
+
"""Add an EDIT activity for a file."""
|
|
2148
|
+
self.add("EDIT", path, f"Edit file: {path}", content_size=content_size)
|
|
2149
|
+
|
|
2150
|
+
def add_bash(self, command: str) -> None:
|
|
2151
|
+
"""Add a BASH activity for a command."""
|
|
2152
|
+
self.add("BASH", command[:100], f"Execute: {command[:200]}")
|
|
2153
|
+
|
|
2154
|
+
def add_search(self, query: str) -> None:
|
|
2155
|
+
"""Add a SEARCH activity for a web search."""
|
|
2156
|
+
self.add("SEARCH", query[:100], f"Search: {query[:200]}")
|
|
2157
|
+
|
|
2158
|
+
def add_api(self, url: str, method: str = "GET") -> None:
|
|
2159
|
+
"""Add an API activity for an HTTP request."""
|
|
2160
|
+
self.add("API", url[:100], f"{method} {url[:200]}")
|
|
2161
|
+
|
|
2162
|
+
@property
|
|
2163
|
+
def activity_ids(self) -> list[str]:
|
|
2164
|
+
"""Get the list of activity IDs (available after entering context)."""
|
|
2165
|
+
return self._activity_ids
|
|
2166
|
+
|
|
2167
|
+
@property
|
|
2168
|
+
def results(self) -> list[dict]:
|
|
2169
|
+
"""Get the batch results (available after exiting context)."""
|
|
2170
|
+
return self._results
|
|
2171
|
+
|
|
2172
|
+
def __enter__(self):
|
|
2173
|
+
"""Start all activities in the batch."""
|
|
2174
|
+
if not self._acp.enabled or not self._activities:
|
|
2175
|
+
return self
|
|
2176
|
+
|
|
2177
|
+
# Start all activities in batch
|
|
2178
|
+
result = self._acp.batch_start(self._activities)
|
|
2179
|
+
self._results = result.get("results", [])
|
|
2180
|
+
self._activity_ids = [
|
|
2181
|
+
r.get("activity_id") for r in self._results if r.get("activity_id")
|
|
2182
|
+
]
|
|
2183
|
+
|
|
2184
|
+
# Track activities
|
|
2185
|
+
for aid in self._activity_ids:
|
|
2186
|
+
if aid:
|
|
2187
|
+
self._acp._activity_stack.append(aid)
|
|
2188
|
+
|
|
2189
|
+
self._acp._log(f"Batch started: {len(self._activity_ids)} activities for '{self._description}'")
|
|
2190
|
+
return self
|
|
2191
|
+
|
|
2192
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
2193
|
+
"""Complete all activities in the batch."""
|
|
2194
|
+
if not self._acp.enabled or not self._activity_ids:
|
|
2195
|
+
return False
|
|
2196
|
+
|
|
2197
|
+
if self._auto_complete:
|
|
2198
|
+
# Complete all activities
|
|
2199
|
+
completions = []
|
|
2200
|
+
for aid in self._activity_ids:
|
|
2201
|
+
result = "Completed" if exc_type is None else f"Error: {exc_val}"
|
|
2202
|
+
completions.append({
|
|
2203
|
+
"activity_id": aid,
|
|
2204
|
+
"result": result,
|
|
2205
|
+
})
|
|
2206
|
+
|
|
2207
|
+
self._acp.batch_complete(completions)
|
|
2208
|
+
self._acp._log(f"Batch completed: {len(self._activity_ids)} activities")
|
|
2209
|
+
|
|
2210
|
+
return False # Don't suppress exceptions
|