zwarm 2.0.1__py3-none-any.whl → 2.3__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/cli/main.py CHANGED
@@ -1375,7 +1375,7 @@ def interactive(
1375
1375
 
1376
1376
  def do_spawn(args: list[str]):
1377
1377
  """Spawn a new coding agent session using CodexSessionManager (same as orchestrator)."""
1378
- from zwarm.sessions import CodexSessionManager
1378
+ from zwarm.sessions import CodexSessionManager, SessionStatus as SessStatus
1379
1379
  import time
1380
1380
 
1381
1381
  parsed = parse_spawn_args(args)
@@ -1431,15 +1431,18 @@ def interactive(
1431
1431
  break
1432
1432
  time.sleep(1.0)
1433
1433
 
1434
- # Get the response
1434
+ # Get all assistant responses
1435
1435
  messages = manager.get_messages(session.id)
1436
- for msg in messages:
1437
- if msg.role == "assistant":
1438
- response_preview = msg.content[:300]
1436
+ assistant_msgs = [m for m in messages if m.role == "assistant"]
1437
+ if assistant_msgs:
1438
+ console.print(f"\n[bold]Response ({len(assistant_msgs)} message{'s' if len(assistant_msgs) > 1 else ''}):[/]")
1439
+ for msg in assistant_msgs:
1440
+ preview = msg.content[:300]
1439
1441
  if len(msg.content) > 300:
1440
- response_preview += "..."
1441
- console.print(f"\n[bold]Response:[/]\n{response_preview}")
1442
- break
1442
+ preview += "..."
1443
+ console.print(preview)
1444
+ if len(assistant_msgs) > 1:
1445
+ console.print() # Blank line between multiple messages
1443
1446
 
1444
1447
  console.print(f"\n[dim]Use 'show {session.short_id}' to see full details[/]")
1445
1448
  console.print(f"[dim]Use 'c {session.short_id} \"message\"' to continue[/]")
@@ -1580,6 +1583,10 @@ def interactive(
1580
1583
  console.print(f"[dim]Source:[/] {session.source_display} [dim]│[/] [dim]Runtime:[/] {session.runtime}")
1581
1584
  if session.pid:
1582
1585
  console.print(f"[dim]PID:[/] {session.pid}")
1586
+
1587
+ # Show log file path
1588
+ log_path = default_dir / ".zwarm" / "sessions" / session.id / "turns" / f"turn_{session.turn}.jsonl"
1589
+ console.print(f"[dim]Log:[/] {log_path}")
1583
1590
  console.print()
1584
1591
 
1585
1592
  # Get messages from manager
zwarm/sessions/manager.py CHANGED
@@ -301,9 +301,18 @@ class CodexSessionManager:
301
301
  session.messages = messages
302
302
  session.token_usage = usage
303
303
 
304
- if error:
304
+ # Check if we got actual assistant responses
305
+ has_response = any(m.role == "assistant" for m in messages)
306
+
307
+ if error and not has_response:
308
+ # Only mark as failed if we have an error AND no response
305
309
  session.status = SessionStatus.FAILED
306
310
  session.error = error
311
+ elif error and has_response:
312
+ # Got response but also an error (e.g., network disconnect at end)
313
+ # Treat as completed but note the error
314
+ session.status = SessionStatus.COMPLETED
315
+ session.error = f"Completed with error: {error}"
307
316
  else:
308
317
  session.status = SessionStatus.COMPLETED
309
318
  else:
@@ -634,6 +643,9 @@ Continue from where you left off, addressing the user's new message."""
634
643
  turn_usage = event.get("usage", {})
635
644
  for key, value in turn_usage.items():
636
645
  usage[key] = usage.get(key, 0) + value
646
+ # Compute total_tokens if not present
647
+ if "total_tokens" not in usage:
648
+ usage["total_tokens"] = usage.get("input_tokens", 0) + usage.get("output_tokens", 0)
637
649
 
638
650
  elif event_type == "error":
639
651
  error = event.get("message", str(event))
zwarm/tools/delegation.py CHANGED
@@ -83,6 +83,14 @@ def _format_session_header(session) -> str:
83
83
  return f"[{session.short_id}] codex ({session.status.value})"
84
84
 
85
85
 
86
+ def _get_total_tokens(session) -> int:
87
+ """Get total tokens, computing from input+output if not present."""
88
+ usage = session.token_usage
89
+ if "total_tokens" in usage:
90
+ return usage["total_tokens"]
91
+ return usage.get("input_tokens", 0) + usage.get("output_tokens", 0)
92
+
93
+
86
94
  def _validate_working_dir(
87
95
  requested_dir: Path | str | None,
88
96
  default_dir: Path,
@@ -238,6 +246,25 @@ def delegate(
238
246
  response_text = msg.content
239
247
  break # Take first assistant message
240
248
 
249
+ # Build log path for debugging
250
+ log_path = str(manager._output_path(session.id, session.turn))
251
+
252
+ # Check if session failed
253
+ from zwarm.sessions import SessionStatus
254
+ if session.status == SessionStatus.FAILED:
255
+ return {
256
+ "success": False,
257
+ "session": _format_session_header(session),
258
+ "session_id": session.id,
259
+ "status": "failed",
260
+ "task": _truncate(task, 100),
261
+ "error": session.error or "Unknown error",
262
+ "response": response_text or "(no response captured)",
263
+ "tokens": _get_total_tokens(session),
264
+ "log_file": log_path,
265
+ "hint": "Check log_file for raw codex output. Use bash('cat <log_file>') to inspect.",
266
+ }
267
+
241
268
  return {
242
269
  "success": True,
243
270
  "session": _format_session_header(session),
@@ -245,7 +272,8 @@ def delegate(
245
272
  "status": session.status.value,
246
273
  "task": _truncate(task, 100),
247
274
  "response": response_text or "(no response captured)",
248
- "tokens": session.token_usage.get("total_tokens", 0),
275
+ "tokens": _get_total_tokens(session),
276
+ "log_file": log_path,
249
277
  "hint": "Use converse(session_id, message) to send follow-up messages",
250
278
  }
251
279
  else:
@@ -382,7 +410,7 @@ def converse(
382
410
  "turn": session.turn,
383
411
  "you_said": _truncate(message, 100),
384
412
  "response": response_text or "(no response captured)",
385
- "tokens": session.token_usage.get("total_tokens", 0),
413
+ "tokens": _get_total_tokens(session),
386
414
  }
387
415
 
388
416
 
@@ -423,7 +451,10 @@ def check_session(
423
451
  response_text = msg.content
424
452
  break
425
453
 
426
- return {
454
+ # Build log path
455
+ log_path = str(manager._output_path(session.id, session.turn))
456
+
457
+ result = {
427
458
  "success": True,
428
459
  "session": _format_session_header(session),
429
460
  "session_id": session_id,
@@ -433,10 +464,19 @@ def check_session(
433
464
  "message_count": len(messages),
434
465
  "task": _truncate(session.task, 80),
435
466
  "response": _truncate(response_text, 500) if response_text else "(no response yet)",
436
- "tokens": session.token_usage.get("total_tokens", 0),
467
+ "tokens": _get_total_tokens(session),
437
468
  "runtime": session.runtime,
469
+ "log_file": log_path,
438
470
  }
439
471
 
472
+ # Add error info if failed
473
+ from zwarm.sessions import SessionStatus
474
+ if session.status == SessionStatus.FAILED:
475
+ result["success"] = False
476
+ result["error"] = session.error or "Unknown error"
477
+
478
+ return result
479
+
440
480
 
441
481
  @weaveTool
442
482
  def peek_session(
@@ -539,7 +579,7 @@ def end_session(
539
579
  "status": session.status.value,
540
580
  "reason": reason or "ended by orchestrator",
541
581
  "turn": session.turn,
542
- "tokens": session.token_usage.get("total_tokens", 0),
582
+ "tokens": _get_total_tokens(session),
543
583
  }
544
584
 
545
585
 
@@ -646,7 +686,7 @@ def list_sessions(
646
686
  "updated_secs": int(updated_secs),
647
687
  "last_message": _truncate(last_message, 100) if last_message else "(no response yet)",
648
688
  "needs_attention": needs_attention,
649
- "tokens": s.token_usage.get("total_tokens", 0),
689
+ "tokens": _get_total_tokens(s),
650
690
  })
651
691
 
652
692
  # Summary counts
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zwarm
3
- Version: 2.0.1
3
+ Version: 2.3
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
@@ -9,7 +9,7 @@ zwarm/adapters/registry.py,sha256=EdyHECaNA5Kv1od64pYFBJyA_r_6I1r_eJTNP1XYLr4,17
9
9
  zwarm/adapters/test_codex_mcp.py,sha256=0qhVzxn_KF-XUS30gXSJKwMdR3kWGsDY9iPk1Ihqn3w,10698
10
10
  zwarm/adapters/test_registry.py,sha256=otxcVDONwFCMisyANToF3iy7Y8dSbCL8bTmZNhxNuF4,2383
11
11
  zwarm/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- zwarm/cli/main.py,sha256=FmJIYt6qocsZkk3WjsrszY5IDNIM5WrBM1AeHPgc68E,88179
12
+ zwarm/cli/main.py,sha256=fQT9oP03zsru1_80WfVBdX48kdpLIVfEgS8eJQxRxUM,88668
13
13
  zwarm/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  zwarm/core/compact.py,sha256=Y8C7Gs-5-WOU43WRvQ863Qzd5xtuEqR6Aw3r2p8_-i8,10907
15
15
  zwarm/core/config.py,sha256=331i4io9uEnloFwUMjTPJ5_lQFKJR1nhTpA4SPfSpiI,11748
@@ -22,16 +22,16 @@ zwarm/core/test_models.py,sha256=sWTIhMZvuLP5AooGR6y8OR2EyWydqVfhmGrE7NPBBnk,845
22
22
  zwarm/prompts/__init__.py,sha256=FiaIOniLrIyfD3_osxT6I7FfyKjtctbf8jNs5QTPs_s,213
23
23
  zwarm/prompts/orchestrator.py,sha256=-VZ3B5t-2ALOTpdZyNZGSjjzaHiTufAuLzrTLgwg70M,15442
24
24
  zwarm/sessions/__init__.py,sha256=jRibY8IfmNcnkgNmrgK2T81oa1w71wP_KQp9A1hPL7Q,568
25
- zwarm/sessions/manager.py,sha256=slCDE0n9-pw6iZ08YZMjxZRwH0aoEi6MAAChLlAsuPw,22212
25
+ zwarm/sessions/manager.py,sha256=XDwXXZKJwxgBXOl4Mf61_BCdYoKU7lpJHxE_7Lyzuy4,22946
26
26
  zwarm/tools/__init__.py,sha256=FpqxwXJA6-fQ7C-oLj30jjK_0qqcE7MbI0dQuaB56kU,290
27
- zwarm/tools/delegation.py,sha256=2NI9J2VArVUbqOTZJY8Vgz5Rd5nI7BdZ8GNaYVIR_JU,20886
27
+ zwarm/tools/delegation.py,sha256=FFfZvDnppbbqsTeoYUned6gjqwE9m1gkJ09jSkiiWps,22307
28
28
  zwarm/watchers/__init__.py,sha256=yYGTbhuImQLESUdtfrYbHYBJNvCNX3B-Ei-vY5BizX8,760
29
29
  zwarm/watchers/base.py,sha256=r1GoPlj06nOT2xp4fghfSjxbRyFFFQUB6HpZbEyO2OY,3834
30
30
  zwarm/watchers/builtin.py,sha256=IL5QwwKOIqWEfJ_uQWb321Px4i5OLtI_vnWQMudqKoA,19064
31
31
  zwarm/watchers/manager.py,sha256=XZjBVeHjgCUlkTUeHqdvBvHoBC862U1ik0fG6nlRGog,5587
32
32
  zwarm/watchers/registry.py,sha256=A9iBIVIFNtO7KPX0kLpUaP8dAK7ozqWLA44ocJGnOw4,1219
33
33
  zwarm/watchers/test_watchers.py,sha256=zOsxumBqKfR5ZVGxrNlxz6KcWjkcdp0QhW9WB0_20zM,7855
34
- zwarm-2.0.1.dist-info/METADATA,sha256=DdMCZK1-t2KcZkKvAvrZmSSZD_N1YB1RbiO9ZqvVsR0,7680
35
- zwarm-2.0.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
36
- zwarm-2.0.1.dist-info/entry_points.txt,sha256=u0OXq4q8d3yJ3EkUXwZfkS-Y8Lcy0F8cWrcQfoRxM6Q,46
37
- zwarm-2.0.1.dist-info/RECORD,,
34
+ zwarm-2.3.dist-info/METADATA,sha256=fBqubqwFUeool8DcYfqk66WQsG42plPI27JLbrTpg3Q,7678
35
+ zwarm-2.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
36
+ zwarm-2.3.dist-info/entry_points.txt,sha256=u0OXq4q8d3yJ3EkUXwZfkS-Y8Lcy0F8cWrcQfoRxM6Q,46
37
+ zwarm-2.3.dist-info/RECORD,,
File without changes