zwarm 3.2.1__py3-none-any.whl → 3.6.0__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.
zwarm/tools/delegation.py CHANGED
@@ -2,13 +2,17 @@
2
2
  Delegation tools for the orchestrator.
3
3
 
4
4
  These are the core tools that orchestrators use to delegate work to executors.
5
- They use the SAME CodexSessionManager that `zwarm interactive` uses - no special
5
+ They use the same session managers that `zwarm interactive` uses - no special
6
6
  MCP integration, no separate code path.
7
7
 
8
8
  The orchestrator LLM has access to the exact same tools a human would use.
9
9
 
10
+ Supports multiple adapters:
11
+ - codex: OpenAI's Codex CLI (default)
12
+ - claude: Anthropic's Claude Code CLI
13
+
10
14
  Tools:
11
- - delegate: Start a new codex session
15
+ - delegate: Start a new session (with adapter selection)
12
16
  - converse: Continue a conversation (inject follow-up message)
13
17
  - check_session: Check status of a session
14
18
  - end_session: End/kill a session
@@ -26,24 +30,53 @@ from wbal.helper import weaveTool
26
30
  if TYPE_CHECKING:
27
31
  from zwarm.orchestrator import Orchestrator
28
32
 
33
+ # Available adapters
34
+ ADAPTERS = ["codex", "claude"]
35
+
29
36
 
30
37
  def _get_session_manager(orchestrator: "Orchestrator"):
31
38
  """
32
- Get the CodexSessionManager - the SINGLE source of truth for sessions.
39
+ Get the default session manager for list/get operations.
33
40
 
34
- Both `zwarm interactive` and `zwarm orchestrate` use the same session manager.
35
- The orchestrator is just another user that happens to be an LLM.
36
-
37
- The session manager is created eagerly in Orchestrator.model_post_init()
38
- and shared with the environment for observe() visibility.
41
+ Uses CodexSessionManager as the default since all adapters share
42
+ the same .zwarm/sessions/ directory structure.
39
43
  """
40
- # Should already exist from model_post_init, but create if not
41
44
  if not hasattr(orchestrator, "_session_manager") or orchestrator._session_manager is None:
42
45
  from zwarm.sessions import CodexSessionManager
43
46
  orchestrator._session_manager = CodexSessionManager(orchestrator.working_dir / ".zwarm")
44
47
  return orchestrator._session_manager
45
48
 
46
49
 
50
+ def _get_adapter_manager(orchestrator: "Orchestrator", adapter: str):
51
+ """
52
+ Get the session manager for a specific adapter.
53
+
54
+ Each adapter has its own manager for start_session/inject_message,
55
+ but they all share the same .zwarm/sessions/ directory.
56
+
57
+ Args:
58
+ orchestrator: The orchestrator instance
59
+ adapter: Adapter name ("codex" or "claude")
60
+
61
+ Returns:
62
+ Session manager for the specified adapter
63
+ """
64
+ # Initialize adapter managers dict if needed
65
+ if not hasattr(orchestrator, "_adapter_managers"):
66
+ orchestrator._adapter_managers = {}
67
+
68
+ # Return cached manager if exists
69
+ if adapter in orchestrator._adapter_managers:
70
+ return orchestrator._adapter_managers[adapter]
71
+
72
+ # Create new manager for this adapter
73
+ from zwarm.sessions import get_session_manager
74
+ manager = get_session_manager(adapter, str(orchestrator.working_dir / ".zwarm"))
75
+ orchestrator._adapter_managers[adapter] = manager
76
+
77
+ return manager
78
+
79
+
47
80
  def _truncate(text: str, max_len: int = 200) -> str:
48
81
  """Truncate text with ellipsis."""
49
82
  if len(text) <= max_len:
@@ -53,7 +86,8 @@ def _truncate(text: str, max_len: int = 200) -> str:
53
86
 
54
87
  def _format_session_header(session) -> str:
55
88
  """Format a nice session header."""
56
- return f"[{session.short_id}] codex ({session.status.value})"
89
+ adapter = getattr(session, "adapter", "codex")
90
+ return f"[{session.short_id}] {adapter} ({session.status.value})"
57
91
 
58
92
 
59
93
  def _get_total_tokens(session) -> int:
@@ -129,11 +163,15 @@ def delegate(
129
163
  task: str,
130
164
  model: str | None = None,
131
165
  working_dir: str | None = None,
166
+ adapter: str = "codex",
132
167
  ) -> dict[str, Any]:
133
168
  """
134
- Delegate work to a Codex agent.
169
+ Delegate work to an executor agent.
170
+
171
+ Supports multiple adapters:
172
+ - codex: OpenAI's Codex CLI (default, fast, good for code tasks)
173
+ - claude: Claude Code CLI (powerful, good for complex reasoning)
135
174
 
136
- This spawns a codex session - the exact same way `zwarm interactive` does.
137
175
  All sessions run async - you get a session_id immediately and poll for results.
138
176
 
139
177
  Workflow pattern:
@@ -145,17 +183,27 @@ def delegate(
145
183
 
146
184
  Args:
147
185
  task: Clear description of what to do. Be specific about requirements.
148
- model: Model override (default: gpt-5.1-codex-mini).
149
- working_dir: Directory for codex to work in (default: orchestrator's dir).
186
+ model: Model override (codex: gpt-5.1-codex-mini, claude: sonnet).
187
+ working_dir: Directory for executor to work in (default: orchestrator's dir).
188
+ adapter: Which executor to use - "codex" (default) or "claude".
150
189
 
151
190
  Returns:
152
- {session_id, status: "running", task, hint}
191
+ {session_id, status: "running", task, adapter, hint}
153
192
 
154
- Example:
193
+ Example with codex (default):
155
194
  delegate(task="Add a logout button to the navbar")
156
- sleep(30)
157
- peek_session(session_id) # Check progress
195
+
196
+ Example with claude for complex tasks:
197
+ delegate(task="Refactor the auth system to use OAuth2", adapter="claude")
158
198
  """
199
+ # Validate adapter
200
+ if adapter not in ADAPTERS:
201
+ return {
202
+ "success": False,
203
+ "error": f"Unknown adapter: {adapter}. Available: {ADAPTERS}",
204
+ "hint": f"Use one of: {ADAPTERS}",
205
+ }
206
+
159
207
  # Validate working directory
160
208
  effective_dir, dir_error = _validate_working_dir(
161
209
  working_dir,
@@ -170,24 +218,28 @@ def delegate(
170
218
  "hint": "Use the default working directory or ask user to update allowed_dirs config",
171
219
  }
172
220
 
173
- # Get the session manager (same one zwarm interactive uses)
174
- manager = _get_session_manager(self)
221
+ # Get the session manager for this adapter
222
+ manager = _get_adapter_manager(self, adapter)
175
223
 
176
- # Determine model
177
- effective_model = model or self.config.executor.model or "gpt-5.1-codex-mini"
224
+ # Determine model (defaults vary by adapter)
225
+ if model:
226
+ effective_model = model
227
+ elif self.config.executor.model:
228
+ effective_model = self.config.executor.model
229
+ else:
230
+ # Use adapter-specific defaults
231
+ effective_model = manager.default_model
178
232
 
179
233
  # Determine sandbox mode
180
234
  sandbox = self.config.executor.sandbox or "workspace-write"
181
235
 
182
- # Start the session using CodexSessionManager
183
- # This is the SAME method that `zwarm interactive` uses
236
+ # Start the session
184
237
  session = manager.start_session(
185
238
  task=task,
186
239
  working_dir=effective_dir,
187
240
  model=effective_model,
188
241
  sandbox=sandbox,
189
242
  source=f"orchestrator:{self.instance_id or 'default'}",
190
- adapter="codex",
191
243
  )
192
244
 
193
245
  # Return immediately - session runs in background
@@ -197,6 +249,8 @@ def delegate(
197
249
  "session_id": session.id,
198
250
  "status": "running",
199
251
  "task": _truncate(task, 100),
252
+ "adapter": adapter,
253
+ "model": effective_model,
200
254
  "hint": "Use sleep() then check_session(session_id) to monitor progress",
201
255
  }
202
256
 
@@ -208,15 +262,18 @@ def converse(
208
262
  message: str,
209
263
  ) -> dict[str, Any]:
210
264
  """
211
- Continue a conversation with a codex session.
265
+ Continue a conversation with a session.
212
266
 
213
267
  This injects a follow-up message into the session, providing the
214
268
  conversation history as context. Like chatting with a developer.
215
269
  Returns immediately - use sleep() + check_session() to poll for the response.
216
270
 
271
+ Works with any adapter (codex or claude) - automatically uses the
272
+ correct adapter based on the session's original adapter.
273
+
217
274
  Args:
218
275
  session_id: The session to continue (from delegate() result).
219
- message: Your next message to codex.
276
+ message: Your next message.
220
277
 
221
278
  Returns:
222
279
  {session_id, turn, status: "running"}
@@ -226,10 +283,10 @@ def converse(
226
283
  sleep(30)
227
284
  check_session(session_id) # Get response
228
285
  """
229
- manager = _get_session_manager(self)
286
+ # First get session to determine adapter
287
+ default_manager = _get_session_manager(self)
288
+ session = default_manager.get_session(session_id)
230
289
 
231
- # Get current session
232
- session = manager.get_session(session_id)
233
290
  if not session:
234
291
  return {
235
292
  "success": False,
@@ -253,8 +310,12 @@ def converse(
253
310
  "hint": "Start a new session with delegate()",
254
311
  }
255
312
 
313
+ # Get the correct adapter manager for this session
314
+ adapter = getattr(session, "adapter", "codex")
315
+ manager = _get_adapter_manager(self, adapter)
316
+
256
317
  # Inject the follow-up message
257
- # This uses CodexSessionManager.inject_message() which:
318
+ # This uses the adapter's inject_message() which:
258
319
  # 1. Builds context from previous messages
259
320
  # 2. Starts a new turn with the context + new message (background process)
260
321
  updated_session = manager.inject_message(session_id, message)
@@ -273,6 +334,7 @@ def converse(
273
334
  "session_id": session_id,
274
335
  "turn": updated_session.turn,
275
336
  "status": "running",
337
+ "adapter": adapter,
276
338
  "you_said": _truncate(message, 100),
277
339
  "hint": "Use sleep() then check_session(session_id) to see the response",
278
340
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zwarm
3
- Version: 3.2.1
3
+ Version: 3.6.0
4
4
  Summary: Multi-Agent CLI Orchestration Research Platform
5
5
  Requires-Python: <3.14,>=3.13
6
6
  Requires-Dist: prompt-toolkit>=3.0.52
@@ -13,26 +13,30 @@ Description-Content-Type: text/markdown
13
13
 
14
14
  # zwarm
15
15
 
16
- Multi-agent CLI for orchestrating coding agents. Spawn, manage, and converse with multiple Codex sessions in parallel.
16
+ Multi-agent CLI for orchestrating coding agents. Spawn, manage, and converse with multiple coding agent sessions in parallel.
17
+
18
+ **Supports both [Codex CLI](https://github.com/openai/codex) and [Claude Code CLI](https://claude.com/claude-code).**
17
19
 
18
20
  ## Installation
19
21
 
20
22
  ```bash
21
- # From the workspace
22
- cd /path/to/labs
23
- uv sync
23
+ # From PyPI
24
+ pip install zwarm
24
25
 
25
- # Or install directly
26
- uv pip install -e ./zwarm
26
+ # Or with uv
27
+ uv pip install zwarm
27
28
  ```
28
29
 
29
30
  **Requirements:**
30
31
  - Python 3.13+
31
- - `codex` CLI installed and authenticated
32
+ - At least one of:
33
+ - `codex` CLI installed and authenticated (OpenAI)
34
+ - `claude` CLI installed and authenticated (Anthropic)
32
35
 
33
36
  **Environment:**
34
37
  ```bash
35
38
  export OPENAI_API_KEY="sk-..." # Required for Codex
39
+ export ANTHROPIC_API_KEY="sk-..." # Required for Claude
36
40
  export WEAVE_PROJECT="entity/zwarm" # Optional: Weave tracing
37
41
  ```
38
42
 
@@ -78,6 +82,19 @@ zwarm interactive
78
82
 
79
83
  ---
80
84
 
85
+ ## Multi-Adapter Support
86
+
87
+ zwarm supports multiple executor backends:
88
+
89
+ | Adapter | CLI | Models | Config |
90
+ |---------|-----|--------|--------|
91
+ | **Codex** | `codex` | gpt-5.1-codex-mini, etc. | `.zwarm/codex.toml` |
92
+ | **Claude** | `claude` | sonnet, opus, haiku | `.zwarm/claude.toml` |
93
+
94
+ You can mix adapters in the same session - for example, use Claude Opus for complex reasoning tasks and Codex Mini for quick edits.
95
+
96
+ ---
97
+
81
98
  ## Pilot Mode
82
99
 
83
100
  **You chat with an LLM that delegates to coding agents.** Best of both worlds - LLM intelligence with human oversight.
@@ -85,12 +102,14 @@ zwarm interactive
85
102
  ```bash
86
103
  zwarm pilot
87
104
  zwarm pilot --task "Add user authentication"
105
+ zwarm pilot --resume # Resume previous session
88
106
  ```
89
107
 
90
108
  ### Features
91
109
 
92
110
  - **Conversational**: Chat naturally, the LLM handles delegation
93
111
  - **Checkpoints**: Every turn is saved, time-travel with `:goto`
112
+ - **Resume**: Continue where you left off with `--resume`
94
113
  - **Multiline input**: Use `"""` for pasting large prompts
95
114
  - **Status bar**: See token usage, cost estimates, context window
96
115
 
@@ -103,7 +122,8 @@ zwarm pilot --task "Add user authentication"
103
122
  | `:history` | Show turn checkpoints |
104
123
  | `:goto T3` | Jump back to turn 3 |
105
124
  | `:sessions` | List executor sessions |
106
- | `:quit` | Exit |
125
+ | `:save` | Save current state |
126
+ | `:quit` | Exit (auto-saves) |
107
127
 
108
128
  ### Example
109
129
 
@@ -161,8 +181,8 @@ zwarm interactive
161
181
 
162
182
  | Command | Description |
163
183
  |---------|-------------|
164
- | `spawn "task"` | Start a new session |
165
- | `ls` | Dashboard of all sessions (with costs) |
184
+ | `spawn "task" [--search]` | Start a new session (--search enables web) |
185
+ | `ls` | Dashboard of all sessions (with costs, models) |
166
186
  | `? ID` / `peek ID` | Quick status check |
167
187
  | `show ID` | Full session details |
168
188
  | `traj ID` | Show trajectory (steps taken) |
@@ -170,6 +190,7 @@ zwarm interactive
170
190
  | `c ID "msg"` | Continue conversation |
171
191
  | `kill ID \| all` | Stop session(s) |
172
192
  | `rm ID \| all` | Delete session(s) |
193
+ | `!command` | Run shell command (e.g., `!git status`) |
173
194
  | `help` | Show all commands |
174
195
  | `quit` | Exit |
175
196
 
@@ -188,9 +209,9 @@ $ zwarm interactive
188
209
  > ls
189
210
  ⟳ 2 running
190
211
 
191
- ID │ │ Task │ Tokens │ Cost
192
- abc123 │ ⟳ │ Add tests for the auth... │ 5,234 │ $0.052
193
- def456 │ ⟳ │ Fix type errors in utils... │ 2,100 │ $0.021
212
+ ID │ │ Task │ Model │ Tokens │ Cost
213
+ abc123 │ ⟳ │ Add tests for the auth... │ codex-mini │ 5,234 │ $0.052
214
+ def456 │ ⟳ │ Fix type errors in utils... │ codex-mini │ 2,100 │ $0.021
194
215
 
195
216
  > watch abc123
196
217
  Watching abc123... (Ctrl+C to stop)
@@ -201,6 +222,11 @@ Watching abc123... (Ctrl+C to stop)
201
222
  > c abc123 "Also add edge case tests"
202
223
  ✓ Injected message, session running
203
224
 
225
+ > !git status
226
+ On branch main
227
+ Changes not staged for commit:
228
+ ...
229
+
204
230
  > kill all
205
231
  ✓ Killed abc123
206
232
  ✓ Killed def456
@@ -225,7 +251,7 @@ The orchestrator LLM has access to:
225
251
 
226
252
  | Tool | Description |
227
253
  |------|-------------|
228
- | `delegate(task)` | Start a new coding session |
254
+ | `delegate(task, adapter="codex")` | Start a new coding session |
229
255
  | `converse(id, msg)` | Continue a session |
230
256
  | `check_session(id)` | Get full session details |
231
257
  | `peek_session(id)` | Quick status check |
@@ -235,6 +261,10 @@ The orchestrator LLM has access to:
235
261
 
236
262
  **Async-first**: All sessions run in the background. The orchestrator uses `sleep()` to wait, then checks on progress.
237
263
 
264
+ **Multi-adapter**: Pass `adapter="claude"` or `adapter="codex"` to `delegate()` to choose the backend.
265
+
266
+ **Web Search**: Enable `web_search=True` in config for tasks needing current info (API docs, latest releases, etc.).
267
+
238
268
  ### Watchers
239
269
 
240
270
  Watchers monitor the orchestrator and intervene when needed:
@@ -283,9 +313,9 @@ spawn → running → completed/failed/killed
283
313
 
284
314
  ```
285
315
  .zwarm/sessions/<uuid>/
286
- ├── meta.json # Status, task, model, tokens, cost
316
+ ├── meta.json # Status, task, model, adapter, tokens, cost
287
317
  └── turns/
288
- ├── turn_1.jsonl # Raw codex output for turn 1
318
+ ├── turn_1.jsonl # Raw executor output for turn 1
289
319
  ├── turn_2.jsonl # Output after continue
290
320
  └── ...
291
321
  ```
@@ -303,6 +333,7 @@ zwarm init
303
333
  This creates:
304
334
  - `.zwarm/config.toml` - Runtime settings (Weave, watchers)
305
335
  - `.zwarm/codex.toml` - Codex CLI settings (model, reasoning)
336
+ - `.zwarm/claude.toml` - Claude CLI settings (model, permissions)
306
337
  - `zwarm.yaml` - Project context (optional, with `--with-project`)
307
338
 
308
339
  ### Config Files
@@ -316,7 +347,10 @@ project = "your-entity/zwarm"
316
347
  max_steps = 50
317
348
 
318
349
  [executor]
319
- adapter = "codex_mcp"
350
+ web_search = false # Enable web search for all delegated sessions
351
+
352
+ [pilot]
353
+ max_steps_per_turn = 25
320
354
 
321
355
  [watchers]
322
356
  enabled = ["progress", "budget", "delegation", "delegation_reminder"]
@@ -326,6 +360,13 @@ enabled = ["progress", "budget", "delegation", "delegation_reminder"]
326
360
  ```toml
327
361
  model = "gpt-5.1-codex-mini"
328
362
  model_reasoning_effort = "high" # low | medium | high
363
+ full_auto = true
364
+ ```
365
+
366
+ **`.zwarm/claude.toml`** - Controls the Claude Code CLI:
367
+ ```toml
368
+ model = "sonnet" # sonnet | opus | haiku
369
+ full_danger = true # Skip permission prompts
329
370
  ```
330
371
 
331
372
  **`zwarm.yaml`** - Project-specific context:
@@ -352,6 +393,7 @@ zwarm init --yes # Quick setup with defaults
352
393
 
353
394
  # Interfaces
354
395
  zwarm pilot # Conversational LLM guidance (recommended)
396
+ zwarm pilot --resume # Resume previous session
355
397
  zwarm interactive # Direct session control REPL
356
398
  zwarm orchestrate # Fully autonomous LLM
357
399
 
@@ -374,13 +416,15 @@ zwarm reset # Reset .zwarm/ state
374
416
  zwarm/
375
417
  ├── src/zwarm/
376
418
  │ ├── sessions/ # Session substrate
377
- │ │ └── manager.py # CodexSessionManager (ground truth)
419
+ │ │ ├── base.py # BaseSessionManager (ABC)
420
+ │ │ ├── manager.py # CodexSessionManager
421
+ │ │ └── claude.py # ClaudeSessionManager
378
422
  │ ├── cli/
379
423
  │ │ ├── main.py # CLI commands
380
424
  │ │ ├── pilot.py # Pilot REPL
381
425
  │ │ └── interactive.py # Interactive REPL
382
426
  │ ├── tools/
383
- │ │ └── delegation.py # Orchestrator tools
427
+ │ │ └── delegation.py # Orchestrator tools (multi-adapter)
384
428
  │ ├── core/
385
429
  │ │ ├── config.py # Configuration
386
430
  │ │ ├── checkpoints.py # Time-travel primitives
@@ -389,5 +433,13 @@ zwarm/
389
433
  │ ├── watchers/ # Trajectory alignment
390
434
  │ ├── prompts/ # System prompts
391
435
  │ └── orchestrator.py # Orchestrator agent
392
- └── STATE.md # Current project state
436
+ └── docs/
437
+ ├── CONCEPTS.md # Architecture diagrams
438
+ └── INTERNALS.md # Developer documentation
393
439
  ```
440
+
441
+ ---
442
+
443
+ ## License
444
+
445
+ MIT
@@ -1,35 +1,31 @@
1
1
  zwarm/__init__.py,sha256=3i3LMjHwIzE-LFIS2aUrwv3EZmpkvVMe-xj1h97rcSM,837
2
- zwarm/orchestrator.py,sha256=JGRGuJP05Nf5QibuWytjQAC_NuGGaGUR3G-tLq4SVxY,23624
2
+ zwarm/orchestrator.py,sha256=1IitiuhlCRGd512p3ObwiwI8c2zDzq1yzLTs_y6Mv_o,22803
3
3
  zwarm/test_orchestrator_watchers.py,sha256=QpoaehPU7ekT4XshbTOWnJ2H0wRveV3QOZjxbgyJJLY,807
4
- zwarm/adapters/__init__.py,sha256=O0b-SfZpb6txeNqFkXZ2aaf34yLFYreznyrAV25jF_Q,656
5
- zwarm/adapters/base.py,sha256=fZlQviTgVvOcwnxduTla6WuM6FzQJ_yoHMW5SxwVgQg,2527
6
- zwarm/adapters/claude_code.py,sha256=vAjsjD-_JjARmC4_FBSILQZmQCBrk_oNHo18a9ubuqk,11481
7
- zwarm/adapters/codex_mcp.py,sha256=EhdkM3gj5hc01AcM1ERhtfZbydK390yN4Pg3dawKIGU,48791
8
- zwarm/adapters/registry.py,sha256=EdyHECaNA5Kv1od64pYFBJyA_r_6I1r_eJTNP1XYLr4,1781
9
- zwarm/adapters/test_codex_mcp.py,sha256=0qhVzxn_KF-XUS30gXSJKwMdR3kWGsDY9iPk1Ihqn3w,10698
10
- zwarm/adapters/test_registry.py,sha256=otxcVDONwFCMisyANToF3iy7Y8dSbCL8bTmZNhxNuF4,2383
11
4
  zwarm/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- zwarm/cli/interactive.py,sha256=0-KFo8tCHdlycgzprW2QCJaN5IKAo2CS3t3n6Mhfd4Q,25893
13
- zwarm/cli/main.py,sha256=bekPGLv6YbWOs8npbcurneC-i6H0GhMsKso2R5Uf3vU,70220
14
- zwarm/cli/pilot.py,sha256=ev6UfniLJKDR_GMSEA8JjWdTbtfRK0MLGk3VBCXpwTg,38011
5
+ zwarm/cli/interactive.py,sha256=zNxaU7U3PwHyx04-aiGqxyxwCsKhX-0jG0tzMlvrV24,39031
6
+ zwarm/cli/main.py,sha256=vQGgbAkg_8ei5UTF-IvTtRv3Vxb85NNApVECwT1ghlg,77443
7
+ zwarm/cli/pilot.py,sha256=my0j6-YpWRTFZ8tMrsh2wtJ2n9BP58JokvP7K8ssl7Q,42403
15
8
  zwarm/core/__init__.py,sha256=nEdpEHMFo0gEEKgX-eKHabyOdrOI6UXfWqLu3FfZDao,376
16
9
  zwarm/core/checkpoints.py,sha256=D6sXCMB7Sa1kchQ9_lQx_rabwc5-_7jbuynWgA1nkNY,6560
17
10
  zwarm/core/compact.py,sha256=Y8C7Gs-5-WOU43WRvQ863Qzd5xtuEqR6Aw3r2p8_-i8,10907
18
- zwarm/core/config.py,sha256=331i4io9uEnloFwUMjTPJ5_lQFKJR1nhTpA4SPfSpiI,11748
19
- zwarm/core/costs.py,sha256=pLyixKn9hbDvtzQofOqajeK3XxOpoHPpA8nw8QM7j3g,5403
11
+ zwarm/core/config.py,sha256=m3Vm6U_BNtEDu_cz2d6E3p_RNQfRHWaq-946mDru9-8,12656
12
+ zwarm/core/costs.py,sha256=Z-5o-ZQWRCfFv0mTHev4Ke1AzyXKhXWO6ss7S8eBX9U,1485
20
13
  zwarm/core/environment.py,sha256=zrgh0N3Ng4HI2F1gCYkcQVGzjQPKiIFWuRe1OPRuRn0,6558
21
14
  zwarm/core/models.py,sha256=PrC3okRBVJxISUa1Fax4KkagqLT6Xub-kTxC9drN0sY,10083
15
+ zwarm/core/registry.py,sha256=-3mwW4MZ8LKM9SuNBR-r5KWFcQx5F7gqnKfghikxzAI,9484
22
16
  zwarm/core/state.py,sha256=MzrvODKEiJovI7YI1jajW4uukineZ3ezmW5oQinMgjg,11563
23
17
  zwarm/core/test_compact.py,sha256=WSdjCB5t4YMcknsrkmJIUsVOPY28s4y9GnDmu3Z4BFw,11878
24
- zwarm/core/test_config.py,sha256=26ozyiFOdjFF2c9Q-HDfFM6GOLfgw_5FZ55nTDMNYA8,4888
18
+ zwarm/core/test_config.py,sha256=bXXd3OHhK-ndC7wAxePWIdpu73s4O1eScxi3xDzrZwA,4828
25
19
  zwarm/core/test_models.py,sha256=sWTIhMZvuLP5AooGR6y8OR2EyWydqVfhmGrE7NPBBnk,8450
26
20
  zwarm/prompts/__init__.py,sha256=DI307o712F8qQyDt5vwnFgpVBrxpKwjhr0MaBHLzr9E,334
27
21
  zwarm/prompts/orchestrator.py,sha256=AkVbEpT91QbYFjUYOzm0d37wXrpm0esLBD1MG_W-3FI,15367
28
22
  zwarm/prompts/pilot.py,sha256=BcaV04-43FZyrtmoqCbA7DqnTlQ330TcDp9wNGhRojo,5586
29
- zwarm/sessions/__init__.py,sha256=jRibY8IfmNcnkgNmrgK2T81oa1w71wP_KQp9A1hPL7Q,568
30
- zwarm/sessions/manager.py,sha256=Aq7Wh-WW7ZMP8LgGa3g70wfGg6E2GYjJOBucy6HUfGc,27700
23
+ zwarm/sessions/__init__.py,sha256=5fPkl6JRS_GwPn9hi5iv3dzIpGWu_yghPtvPZdujhnM,1728
24
+ zwarm/sessions/base.py,sha256=UA5E39xDx5q4qX2rUcvhSX7cfrCEqTS3F9Tj-ubmrJA,16538
25
+ zwarm/sessions/claude.py,sha256=hBP_TpNFJjR29IRGJFB3rlG7Z9uWEYSbBGV61tpIr00,16672
26
+ zwarm/sessions/manager.py,sha256=Vq5PePzKfy658EVG24SFsUMXQc1OGgOm8vdOX_WPMF8,18530
31
27
  zwarm/tools/__init__.py,sha256=FpqxwXJA6-fQ7C-oLj30jjK_0qqcE7MbI0dQuaB56kU,290
32
- zwarm/tools/delegation.py,sha256=lw4jJk1zVpgPhuvkUVfjUWFFMJotpJXXVY1YfqiP_Iw,21468
28
+ zwarm/tools/delegation.py,sha256=FM8CIqm3ic6mHjVmY1DkOpTdMIYi21TniMclhdtPRn4,23424
33
29
  zwarm/watchers/__init__.py,sha256=a96s7X6ruYkF2ItWWOZ3Q5QUOMOoeCW4Vz8XXcYLXPM,956
34
30
  zwarm/watchers/base.py,sha256=r1GoPlj06nOT2xp4fghfSjxbRyFFFQUB6HpZbEyO2OY,3834
35
31
  zwarm/watchers/builtin.py,sha256=IL5QwwKOIqWEfJ_uQWb321Px4i5OLtI_vnWQMudqKoA,19064
@@ -37,7 +33,7 @@ zwarm/watchers/llm_watcher.py,sha256=yJGpE3BGKNZX3qgPsiNtJ5d3UJpiTT1V-A-Rh4AiMYM
37
33
  zwarm/watchers/manager.py,sha256=XZjBVeHjgCUlkTUeHqdvBvHoBC862U1ik0fG6nlRGog,5587
38
34
  zwarm/watchers/registry.py,sha256=A9iBIVIFNtO7KPX0kLpUaP8dAK7ozqWLA44ocJGnOw4,1219
39
35
  zwarm/watchers/test_watchers.py,sha256=zOsxumBqKfR5ZVGxrNlxz6KcWjkcdp0QhW9WB0_20zM,7855
40
- zwarm-3.2.1.dist-info/METADATA,sha256=JkWHnaILTCMmy_n6Xam4uLXuRU5XFDPSiOOzleaYQvg,9429
41
- zwarm-3.2.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
42
- zwarm-3.2.1.dist-info/entry_points.txt,sha256=u0OXq4q8d3yJ3EkUXwZfkS-Y8Lcy0F8cWrcQfoRxM6Q,46
43
- zwarm-3.2.1.dist-info/RECORD,,
36
+ zwarm-3.6.0.dist-info/METADATA,sha256=5nkx2jC93DRcLohSvGdZk-W1XWeOc1DModIazvr0gwI,11311
37
+ zwarm-3.6.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
38
+ zwarm-3.6.0.dist-info/entry_points.txt,sha256=u0OXq4q8d3yJ3EkUXwZfkS-Y8Lcy0F8cWrcQfoRxM6Q,46
39
+ zwarm-3.6.0.dist-info/RECORD,,
@@ -1,21 +0,0 @@
1
- """
2
- Adapters: Executor wrappers for CLI coding agents.
3
-
4
- Adapters provide a unified interface to different coding CLIs (Codex, Claude Code).
5
- Use the registry to discover and instantiate adapters by name.
6
- """
7
-
8
- from zwarm.adapters.base import ExecutorAdapter
9
- from zwarm.adapters.registry import register_adapter, get_adapter, list_adapters, adapter_exists
10
-
11
- # Import built-in adapters to register them
12
- from zwarm.adapters import codex_mcp as _codex_mcp # noqa: F401
13
- from zwarm.adapters import claude_code as _claude_code # noqa: F401
14
-
15
- __all__ = [
16
- "ExecutorAdapter",
17
- "register_adapter",
18
- "get_adapter",
19
- "list_adapters",
20
- "adapter_exists",
21
- ]
zwarm/adapters/base.py DELETED
@@ -1,109 +0,0 @@
1
- """
2
- Base adapter protocol for executor agents.
3
-
4
- All CLI coding agent adapters (codex, claude-code, gemini) implement this protocol.
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- from abc import ABC, abstractmethod
10
- from pathlib import Path
11
- from typing import Literal
12
-
13
- from zwarm.core.models import ConversationSession, SessionMode
14
-
15
-
16
- class ExecutorAdapter(ABC):
17
- """
18
- Abstract base class for CLI coding agent adapters.
19
-
20
- Adapters handle the mechanics of:
21
- - Starting sessions (sync or async)
22
- - Sending messages in sync mode
23
- - Checking status in async mode
24
- - Stopping sessions
25
- """
26
-
27
- name: str = "base"
28
-
29
- @abstractmethod
30
- async def start_session(
31
- self,
32
- task: str,
33
- working_dir: Path,
34
- mode: Literal["sync", "async"] = "sync",
35
- model: str | None = None,
36
- **kwargs,
37
- ) -> ConversationSession:
38
- """
39
- Start a new session with the executor.
40
-
41
- Args:
42
- task: The task description/prompt
43
- working_dir: Directory to work in
44
- mode: "sync" for conversational, "async" for fire-and-forget
45
- model: Optional model override
46
- **kwargs: Adapter-specific options
47
-
48
- Returns:
49
- A ConversationSession with initial response (if sync)
50
- """
51
- ...
52
-
53
- @abstractmethod
54
- async def send_message(
55
- self,
56
- session: ConversationSession,
57
- message: str,
58
- ) -> str:
59
- """
60
- Send a message to a sync session and get response.
61
-
62
- Args:
63
- session: The active session
64
- message: Message to send
65
-
66
- Returns:
67
- The agent's response
68
-
69
- Raises:
70
- ValueError: If session is not in sync mode or not active
71
- """
72
- ...
73
-
74
- @abstractmethod
75
- async def check_status(
76
- self,
77
- session: ConversationSession,
78
- ) -> dict:
79
- """
80
- Check the status of an async session.
81
-
82
- Args:
83
- session: The session to check
84
-
85
- Returns:
86
- Status dict with at least {"status": "running"|"completed"|"failed"}
87
- """
88
- ...
89
-
90
- @abstractmethod
91
- async def stop(
92
- self,
93
- session: ConversationSession,
94
- ) -> None:
95
- """
96
- Stop/kill a session.
97
-
98
- Args:
99
- session: The session to stop
100
- """
101
- ...
102
-
103
- async def cleanup(self) -> None:
104
- """
105
- Clean up adapter resources (e.g., MCP server).
106
-
107
- Called when the orchestrator shuts down.
108
- """
109
- pass