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.
Files changed (94) hide show
  1. {agentnova-0.3.2 → agentnova-0.3.4}/PKG-INFO +55 -3
  2. {agentnova-0.3.2 → agentnova-0.3.4}/README.md +54 -2
  3. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/__init__.py +1 -1
  4. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/acp_plugin.py +149 -0
  5. agentnova-0.3.4/agentnova/agent.py +1028 -0
  6. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/backends/__init__.py +11 -3
  7. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/backends/ollama.py +417 -3
  8. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/cli.py +45 -6
  9. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/config.py +15 -4
  10. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/__init__.py +59 -7
  11. agentnova-0.3.4/agentnova/core/error_recovery.py +725 -0
  12. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/helpers.py +16 -1
  13. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/memory.py +30 -10
  14. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/models.py +12 -2
  15. agentnova-0.3.4/agentnova/core/openresponses.py +812 -0
  16. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/prompts.py +54 -166
  17. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/tool_parse.py +118 -212
  18. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/types.py +15 -1
  19. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/00_basic_agent.py +22 -6
  20. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/01_quick_diagnostic.py +16 -4
  21. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/02_tool_test.py +46 -19
  22. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/04_gsm8k_benchmark.py +1 -1
  23. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/__init__.py +16 -2
  24. agentnova-0.3.4/agentnova/skills/loader.py +1893 -0
  25. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/soul/__init__.py +99 -97
  26. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/soul/loader.py +514 -5
  27. agentnova-0.3.4/agentnova/souls/nova-helper/IDENTITY.md +14 -0
  28. agentnova-0.3.4/agentnova/souls/nova-helper/SOUL.md +127 -0
  29. agentnova-0.3.4/agentnova/souls/nova-helper/STYLE.md +83 -0
  30. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/souls/nova-helper/soul.json +30 -30
  31. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/tools/builtins.py +22 -5
  32. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova.egg-info/PKG-INFO +55 -3
  33. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova.egg-info/SOURCES.txt +2 -0
  34. {agentnova-0.3.2 → agentnova-0.3.4}/pyproject.toml +1 -1
  35. agentnova-0.3.2/agentnova/agent.py +0 -981
  36. agentnova-0.3.2/agentnova/skills/loader.py +0 -445
  37. agentnova-0.3.2/agentnova/souls/nova-helper/IDENTITY.md +0 -36
  38. agentnova-0.3.2/agentnova/souls/nova-helper/SOUL.md +0 -51
  39. agentnova-0.3.2/agentnova/souls/nova-helper/STYLE.md +0 -49
  40. {agentnova-0.3.2 → agentnova-0.3.4}/LICENSE +0 -0
  41. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/__main__.py +0 -0
  42. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/agent_mode.py +0 -0
  43. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/backends/base.py +0 -0
  44. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/backends/bitnet.py +0 -0
  45. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/args_normal.py +0 -0
  46. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/math_prompts.py +0 -0
  47. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/model_config.py +0 -0
  48. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/core/model_family_config.py +0 -0
  49. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/03_reasoning_test.py +0 -0
  50. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/05_common_sense.py +0 -0
  51. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/06_causal_reasoning.py +0 -0
  52. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/07_logical_deduction.py +0 -0
  53. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/08_reading_comprehension.py +0 -0
  54. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/09_general_knowledge.py +0 -0
  55. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/10_implicit_reasoning.py +0 -0
  56. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/11_analogical_reasoning.py +0 -0
  57. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/examples/__init__.py +0 -0
  58. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/model_discovery.py +0 -0
  59. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/orchestrator.py +0 -0
  60. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/orchestrator_enhanced.py +0 -0
  61. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/py.typed +0 -0
  62. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/shared_args.py +0 -0
  63. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/acp/SKILL.md +0 -0
  64. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/datetime/SKILL.md +0 -0
  65. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/SKILL.md +0 -0
  66. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/__init__.py +0 -0
  67. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/aggregate_benchmark.py +0 -0
  68. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/generate_report.py +0 -0
  69. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/improve_description.py +0 -0
  70. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/init_skill.py +0 -0
  71. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/package_skill.py +0 -0
  72. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/quick_validate.py +0 -0
  73. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/run_eval.py +0 -0
  74. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/run_loop.py +0 -0
  75. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/security_scan.py +0 -0
  76. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/test_package_skill.py +0 -0
  77. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/test_quick_validate.py +0 -0
  78. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/utils.py +0 -0
  79. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/skill-creator/scripts/validate.py +0 -0
  80. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/skills/web-search/SKILL.md +0 -0
  81. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/soul/types.py +0 -0
  82. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/tools/__init__.py +0 -0
  83. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/tools/registry.py +0 -0
  84. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova/tools/sandboxed_repl.py +0 -0
  85. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova.egg-info/dependency_links.txt +0 -0
  86. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova.egg-info/entry_points.txt +0 -0
  87. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova.egg-info/requires.txt +0 -0
  88. {agentnova-0.3.2 → agentnova-0.3.4}/agentnova.egg-info/top_level.txt +0 -0
  89. {agentnova-0.3.2 → agentnova-0.3.4}/localclaw/__init__.py +0 -0
  90. {agentnova-0.3.2 → agentnova-0.3.4}/localclaw-redirect/localclaw/__init__.py +0 -0
  91. {agentnova-0.3.2 → agentnova-0.3.4}/setup.cfg +0 -0
  92. {agentnova-0.3.2 → agentnova-0.3.4}/tests/test_acp_integration.py +0 -0
  93. {agentnova-0.3.2 → agentnova-0.3.4}/tests/test_acp_subagents.py +0 -0
  94. {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.2
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.2
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://img.shields.io/badge/License-MIT-blue)](#license) [![Go to Python website](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2FVTSTech%2FAgentNova%2Frefs%2Fheads%2Fmain%2Fpyproject.toml&query=project.requires-python&label=python&logo=python&logoColor=white)](https://python.org)
51
51
 
52
- <img width="1102" height="960" alt="image" src="https://github.com/user-attachments/assets/2a5fe9b4-93df-46a0-9383-9e01e0c0105d" />
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.2
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://img.shields.io/badge/License-MIT-blue)](#license) [![Go to Python website](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2FVTSTech%2FAgentNova%2Frefs%2Fheads%2Fmain%2Fpyproject.toml&query=project.requires-python&label=python&logo=python&logoColor=white)](https://python.org)
17
17
 
18
- <img width="1102" height="960" alt="image" src="https://github.com/user-attachments/assets/2a5fe9b4-93df-46a0-9383-9e01e0c0105d" />
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:
@@ -28,7 +28,7 @@ Example Usage:
28
28
  agent = Agent(model="qwen2.5:0.5b", soul="/path/to/soul/package")
29
29
  """
30
30
 
31
- __version__ = "0.3.1"
31
+ __version__ = "0.3.4"
32
32
  __author__ = "VTSTech"
33
33
  __status__ = "Alpha"
34
34
 
@@ -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