zwarm 2.0.0__tar.gz → 2.0.1__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 (37) hide show
  1. {zwarm-2.0.0 → zwarm-2.0.1}/PKG-INFO +2 -2
  2. {zwarm-2.0.0 → zwarm-2.0.1}/pyproject.toml +2 -2
  3. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/cli/main.py +4 -2
  4. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/orchestrator.py +43 -27
  5. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/tools/delegation.py +5 -2
  6. {zwarm-2.0.0 → zwarm-2.0.1}/.gitignore +0 -0
  7. {zwarm-2.0.0 → zwarm-2.0.1}/README.md +0 -0
  8. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/__init__.py +0 -0
  9. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/adapters/__init__.py +0 -0
  10. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/adapters/base.py +0 -0
  11. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/adapters/claude_code.py +0 -0
  12. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/adapters/codex_mcp.py +0 -0
  13. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/adapters/registry.py +0 -0
  14. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/adapters/test_codex_mcp.py +0 -0
  15. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/adapters/test_registry.py +0 -0
  16. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/cli/__init__.py +0 -0
  17. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/core/__init__.py +0 -0
  18. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/core/compact.py +0 -0
  19. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/core/config.py +0 -0
  20. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/core/environment.py +0 -0
  21. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/core/models.py +0 -0
  22. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/core/state.py +0 -0
  23. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/core/test_compact.py +0 -0
  24. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/core/test_config.py +0 -0
  25. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/core/test_models.py +0 -0
  26. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/prompts/__init__.py +0 -0
  27. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/prompts/orchestrator.py +0 -0
  28. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/sessions/__init__.py +0 -0
  29. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/sessions/manager.py +0 -0
  30. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/test_orchestrator_watchers.py +0 -0
  31. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/tools/__init__.py +0 -0
  32. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/watchers/__init__.py +0 -0
  33. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/watchers/base.py +0 -0
  34. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/watchers/builtin.py +0 -0
  35. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/watchers/manager.py +0 -0
  36. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/watchers/registry.py +0 -0
  37. {zwarm-2.0.0 → zwarm-2.0.1}/src/zwarm/watchers/test_watchers.py +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zwarm
3
- Version: 2.0.0
3
+ Version: 2.0.1
4
4
  Summary: Multi-Agent CLI Orchestration Research Platform
5
5
  Requires-Python: <3.14,>=3.13
6
6
  Requires-Dist: python-dotenv>=1.0.0
7
7
  Requires-Dist: pyyaml>=6.0
8
8
  Requires-Dist: rich>=13.0.0
9
9
  Requires-Dist: typer>=0.9.0
10
- Requires-Dist: wbal>=0.4.0
10
+ Requires-Dist: wbal>=0.5.8
11
11
  Description-Content-Type: text/markdown
12
12
 
13
13
  # zwarm
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "zwarm"
3
- version = "2.0.0"
3
+ version = "2.0.1"
4
4
  description = "Multi-Agent CLI Orchestration Research Platform"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13,<3.14"
@@ -9,7 +9,7 @@ dependencies = [
9
9
  "rich>=13.0.0",
10
10
  "python-dotenv>=1.0.0",
11
11
  "pyyaml>=6.0",
12
- "wbal>=0.4.0",
12
+ "wbal>=0.5.8",
13
13
  ]
14
14
 
15
15
  [project.scripts]
@@ -1425,8 +1425,9 @@ def interactive(
1425
1425
  timeout = 300.0
1426
1426
  start = time.time()
1427
1427
  while time.time() - start < timeout:
1428
+ # get_session() auto-updates status based on output completion
1428
1429
  session = manager.get_session(session.id)
1429
- if not session.is_running:
1430
+ if session.status != SessStatus.RUNNING:
1430
1431
  break
1431
1432
  time.sleep(1.0)
1432
1433
 
@@ -1663,8 +1664,9 @@ def interactive(
1663
1664
  timeout = 300.0
1664
1665
  start = time.time()
1665
1666
  while time.time() - start < timeout:
1667
+ # get_session() auto-updates status based on output completion
1666
1668
  session = manager.get_session(session.id)
1667
- if not session.is_running:
1669
+ if session.status != SessStatus.RUNNING:
1668
1670
  break
1669
1671
  time.sleep(1.0)
1670
1672
 
@@ -20,6 +20,8 @@ import weave
20
20
  from pydantic import Field, PrivateAttr
21
21
  from wbal.agents.yaml_agent import YamlAgent
22
22
  from wbal.helper import TOOL_CALL_TYPE, format_openai_tool_response
23
+ from wbal.lm import LM as wbalLMGeneric
24
+ from wbal.lm import GPT5LargeVerbose
23
25
 
24
26
  from zwarm.adapters import ExecutorAdapter, get_adapter
25
27
  from zwarm.core.compact import compact_messages, should_compact
@@ -29,9 +31,9 @@ from zwarm.core.models import ConversationSession
29
31
  from zwarm.core.state import StateManager
30
32
  from zwarm.prompts import get_orchestrator_prompt
31
33
  from zwarm.watchers import (
32
- WatcherManager,
33
- WatcherContext,
34
34
  WatcherAction,
35
+ WatcherContext,
36
+ WatcherManager,
35
37
  build_watcher_manager,
36
38
  )
37
39
 
@@ -48,6 +50,9 @@ class Orchestrator(YamlAgent):
48
50
  - Weave integration
49
51
  """
50
52
 
53
+ # LM definition override:
54
+ lm: wbalLMGeneric = Field(default_factory=GPT5LargeVerbose)
55
+
51
56
  # Configuration
52
57
  config: ZwarmConfig = Field(default_factory=ZwarmConfig)
53
58
  working_dir: Path = Field(default_factory=Path.cwd)
@@ -71,11 +76,13 @@ class Orchestrator(YamlAgent):
71
76
  _watcher_manager: WatcherManager | None = PrivateAttr(default=None)
72
77
  _resumed: bool = PrivateAttr(default=False)
73
78
  _total_tokens: int = PrivateAttr(default=0) # Cumulative orchestrator tokens
74
- _executor_usage: dict[str, int] = PrivateAttr(default_factory=lambda: {
75
- "input_tokens": 0,
76
- "output_tokens": 0,
77
- "total_tokens": 0,
78
- })
79
+ _executor_usage: dict[str, int] = PrivateAttr(
80
+ default_factory=lambda: {
81
+ "input_tokens": 0,
82
+ "output_tokens": 0,
83
+ "total_tokens": 0,
84
+ }
85
+ )
79
86
 
80
87
  def model_post_init(self, __context: Any) -> None:
81
88
  """Initialize state and adapters after model creation."""
@@ -93,6 +100,7 @@ class Orchestrator(YamlAgent):
93
100
  # Register instance if using instance isolation
94
101
  if self.instance_id:
95
102
  from zwarm.core.state import register_instance
103
+
96
104
  register_instance(
97
105
  instance_id=self.instance_id,
98
106
  name=self.instance_name,
@@ -149,7 +157,9 @@ class Orchestrator(YamlAgent):
149
157
  if not config_path.exists():
150
158
  config_path = None # Fallback to adapter defaults
151
159
 
152
- self._adapters[name] = get_adapter(name, model=model, config_path=config_path)
160
+ self._adapters[name] = get_adapter(
161
+ name, model=model, config_path=config_path
162
+ )
153
163
  return self._adapters[name]
154
164
 
155
165
  def get_executor_usage(self) -> dict[str, int]:
@@ -253,15 +263,18 @@ class Orchestrator(YamlAgent):
253
263
 
254
264
  # Log compaction event
255
265
  from zwarm.core.models import Event
256
- self._state.log_event(Event(
257
- kind="context_compacted",
258
- payload={
259
- "step": self._step_count,
260
- "original_count": result.original_count,
261
- "new_count": len(result.messages),
262
- "removed_count": result.removed_count,
263
- },
264
- ))
266
+
267
+ self._state.log_event(
268
+ Event(
269
+ kind="context_compacted",
270
+ payload={
271
+ "step": self._step_count,
272
+ "original_count": result.original_count,
273
+ "new_count": len(result.messages),
274
+ "removed_count": result.removed_count,
275
+ },
276
+ )
277
+ )
265
278
 
266
279
  return True
267
280
 
@@ -377,17 +390,20 @@ Review what was accomplished in the previous session and delegate new tasks as n
377
390
 
378
391
  # Log watcher execution to events
379
392
  from zwarm.core.models import Event
393
+
380
394
  watcher_names = [w.name for w in self.config.watchers.watchers if w.enabled]
381
- self.state.log_event(Event(
382
- kind="watchers_run",
383
- payload={
384
- "step": self._step_count,
385
- "watchers": watcher_names,
386
- "action": result.action.value,
387
- "triggered_by": result.metadata.get("triggered_by"),
388
- "reason": result.metadata.get("reason"),
389
- },
390
- ))
395
+ self.state.log_event(
396
+ Event(
397
+ kind="watchers_run",
398
+ payload={
399
+ "step": self._step_count,
400
+ "watchers": watcher_names,
401
+ "action": result.action.value,
402
+ "triggered_by": result.metadata.get("triggered_by"),
403
+ "reason": result.metadata.get("reason"),
404
+ },
405
+ )
406
+ )
391
407
 
392
408
  # Handle watcher result
393
409
  if result.action == WatcherAction.NUDGE and result.guidance:
@@ -53,14 +53,17 @@ def _wait_for_completion(manager, session_id: str, timeout: float = 300.0, poll_
53
53
  Returns:
54
54
  True if completed, False if timed out
55
55
  """
56
+ from zwarm.sessions import SessionStatus
57
+
56
58
  start = time.time()
57
59
  while time.time() - start < timeout:
60
+ # get_session() auto-updates status based on output completion markers
58
61
  session = manager.get_session(session_id)
59
62
  if not session:
60
63
  return False
61
64
 
62
- # Check if process is still running
63
- if not session.is_running:
65
+ # Check status (not is_running - PID check is unreliable due to reuse)
66
+ if session.status in (SessionStatus.COMPLETED, SessionStatus.FAILED, SessionStatus.KILLED):
64
67
  return True
65
68
 
66
69
  time.sleep(poll_interval)
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