codex-autorunner 1.2.0__py3-none-any.whl → 1.3.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.
Files changed (67) hide show
  1. codex_autorunner/bootstrap.py +26 -5
  2. codex_autorunner/core/about_car.py +12 -12
  3. codex_autorunner/core/config.py +178 -61
  4. codex_autorunner/core/context_awareness.py +1 -0
  5. codex_autorunner/core/filesystem.py +24 -0
  6. codex_autorunner/core/flows/controller.py +50 -12
  7. codex_autorunner/core/flows/runtime.py +8 -3
  8. codex_autorunner/core/hub.py +293 -16
  9. codex_autorunner/core/lifecycle_events.py +44 -5
  10. codex_autorunner/core/pma_context.py +188 -1
  11. codex_autorunner/core/pma_delivery.py +81 -0
  12. codex_autorunner/core/pma_dispatches.py +224 -0
  13. codex_autorunner/core/pma_lane_worker.py +122 -0
  14. codex_autorunner/core/pma_queue.py +167 -18
  15. codex_autorunner/core/pma_reactive.py +91 -0
  16. codex_autorunner/core/pma_safety.py +58 -0
  17. codex_autorunner/core/pma_sink.py +104 -0
  18. codex_autorunner/core/pma_transcripts.py +183 -0
  19. codex_autorunner/core/safe_paths.py +117 -0
  20. codex_autorunner/housekeeping.py +77 -23
  21. codex_autorunner/integrations/agents/codex_backend.py +18 -12
  22. codex_autorunner/integrations/agents/wiring.py +2 -0
  23. codex_autorunner/integrations/app_server/client.py +31 -0
  24. codex_autorunner/integrations/app_server/supervisor.py +3 -0
  25. codex_autorunner/integrations/telegram/adapter.py +1 -1
  26. codex_autorunner/integrations/telegram/config.py +1 -1
  27. codex_autorunner/integrations/telegram/constants.py +1 -1
  28. codex_autorunner/integrations/telegram/handlers/commands/execution.py +16 -15
  29. codex_autorunner/integrations/telegram/handlers/commands/files.py +5 -8
  30. codex_autorunner/integrations/telegram/handlers/commands/github.py +10 -6
  31. codex_autorunner/integrations/telegram/handlers/commands/shared.py +9 -8
  32. codex_autorunner/integrations/telegram/handlers/commands/workspace.py +85 -2
  33. codex_autorunner/integrations/telegram/handlers/commands_runtime.py +29 -8
  34. codex_autorunner/integrations/telegram/handlers/messages.py +8 -2
  35. codex_autorunner/integrations/telegram/helpers.py +30 -2
  36. codex_autorunner/integrations/telegram/ticket_flow_bridge.py +54 -3
  37. codex_autorunner/static/archive.js +274 -81
  38. codex_autorunner/static/archiveApi.js +21 -0
  39. codex_autorunner/static/constants.js +1 -1
  40. codex_autorunner/static/docChatCore.js +2 -0
  41. codex_autorunner/static/hub.js +59 -0
  42. codex_autorunner/static/index.html +70 -54
  43. codex_autorunner/static/notificationBell.js +173 -0
  44. codex_autorunner/static/notifications.js +187 -36
  45. codex_autorunner/static/pma.js +96 -35
  46. codex_autorunner/static/styles.css +431 -4
  47. codex_autorunner/static/terminalManager.js +22 -3
  48. codex_autorunner/static/utils.js +5 -1
  49. codex_autorunner/surfaces/cli/cli.py +206 -129
  50. codex_autorunner/surfaces/cli/template_repos.py +157 -0
  51. codex_autorunner/surfaces/web/app.py +193 -5
  52. codex_autorunner/surfaces/web/routes/archive.py +197 -0
  53. codex_autorunner/surfaces/web/routes/file_chat.py +115 -87
  54. codex_autorunner/surfaces/web/routes/flows.py +125 -67
  55. codex_autorunner/surfaces/web/routes/pma.py +638 -57
  56. codex_autorunner/surfaces/web/schemas.py +11 -0
  57. codex_autorunner/tickets/agent_pool.py +6 -1
  58. codex_autorunner/tickets/outbox.py +27 -14
  59. codex_autorunner/tickets/replies.py +4 -10
  60. codex_autorunner/tickets/runner.py +1 -0
  61. codex_autorunner/workspace/paths.py +8 -3
  62. {codex_autorunner-1.2.0.dist-info → codex_autorunner-1.3.0.dist-info}/METADATA +1 -1
  63. {codex_autorunner-1.2.0.dist-info → codex_autorunner-1.3.0.dist-info}/RECORD +67 -57
  64. {codex_autorunner-1.2.0.dist-info → codex_autorunner-1.3.0.dist-info}/WHEEL +0 -0
  65. {codex_autorunner-1.2.0.dist-info → codex_autorunner-1.3.0.dist-info}/entry_points.txt +0 -0
  66. {codex_autorunner-1.2.0.dist-info → codex_autorunner-1.3.0.dist-info}/licenses/LICENSE +0 -0
  67. {codex_autorunner-1.2.0.dist-info → codex_autorunner-1.3.0.dist-info}/top_level.txt +0 -0
@@ -18,6 +18,7 @@ from ...manifest import load_manifest
18
18
  from ...tickets import AgentPool
19
19
  from .adapter import chunk_message
20
20
  from .constants import TELEGRAM_MAX_MESSAGE_LENGTH
21
+ from .helpers import format_public_error
21
22
  from .state import parse_topic_key
22
23
 
23
24
 
@@ -163,7 +164,7 @@ class TelegramTicketFlowBridge:
163
164
  key, self._set_ticket_dispatch_marker(marker)
164
165
  )
165
166
 
166
- primary_key, _primary_record = primary
167
+ primary_key, primary_record = primary
167
168
  try:
168
169
  chat_id, thread_id, _scope = parse_topic_key(primary_key)
169
170
  except Exception as exc:
@@ -182,6 +183,8 @@ class TelegramTicketFlowBridge:
182
183
  seq=seq,
183
184
  content=content,
184
185
  archived_dir=archived_dir,
186
+ workspace_root=workspace_root,
187
+ repo_id=getattr(primary_record, "repo_id", None),
185
188
  )
186
189
  self._pause_targets[str(workspace_root)] = run_id
187
190
  except Exception as exc:
@@ -296,9 +299,14 @@ class TelegramTicketFlowBridge:
296
299
  def _format_ticket_flow_pause_reason(record: FlowRunRecord) -> str:
297
300
  state = record.state or {}
298
301
  engine = state.get("ticket_engine") or {}
299
- reason = (
302
+ reason_raw = (
300
303
  engine.get("reason") or record.error_message or "Paused without details."
301
304
  )
305
+ reason = (
306
+ format_public_error(str(reason_raw))
307
+ if reason_raw
308
+ else "Paused without details."
309
+ )
302
310
  return f"Reason: {reason}"
303
311
 
304
312
  def get_paused_ticket_flow(
@@ -373,6 +381,7 @@ class TelegramTicketFlowBridge:
373
381
  seq=seq,
374
382
  content=content,
375
383
  archived_dir=archived_dir,
384
+ workspace_root=workspace_root,
376
385
  )
377
386
  self._last_default_notification[workspace_root] = marker
378
387
  self._pause_targets[str(workspace_root)] = run_id
@@ -396,6 +405,8 @@ class TelegramTicketFlowBridge:
396
405
  seq: str,
397
406
  content: str,
398
407
  archived_dir: Optional[Path],
408
+ workspace_root: Optional[Path],
409
+ repo_id: Optional[str] = None,
399
410
  ) -> None:
400
411
  await self._send_dispatch_text(
401
412
  chat_id,
@@ -403,6 +414,8 @@ class TelegramTicketFlowBridge:
403
414
  run_id=run_id,
404
415
  seq=seq,
405
416
  content=content,
417
+ workspace_root=workspace_root,
418
+ repo_id=repo_id,
406
419
  )
407
420
  if self._pause_config.send_attachments and archived_dir:
408
421
  await self._send_dispatch_attachments(
@@ -421,9 +434,15 @@ class TelegramTicketFlowBridge:
421
434
  run_id: str,
422
435
  seq: str,
423
436
  content: str,
437
+ workspace_root: Optional[Path],
438
+ repo_id: Optional[str] = None,
424
439
  ) -> None:
425
440
  body = content.strip() or "(no dispatch message)"
426
- header = f"Ticket flow paused (run {run_id}). Latest dispatch #{seq}:\n\n"
441
+ source = self._format_dispatch_source(workspace_root, repo_id)
442
+ header = (
443
+ f"Ticket flow paused (run {run_id}). Latest dispatch #{seq}:\n"
444
+ f"Source: {source}\n\n"
445
+ )
427
446
  footer = "\n\nUse /flow resume to continue."
428
447
  full_text = f"{header}{body}{footer}"
429
448
 
@@ -446,6 +465,38 @@ class TelegramTicketFlowBridge:
446
465
  if idx == 0:
447
466
  await asyncio.sleep(0)
448
467
 
468
+ def _format_dispatch_source(
469
+ self, workspace_root: Optional[Path], repo_id: Optional[str]
470
+ ) -> str:
471
+ workspace_label = None
472
+ if isinstance(workspace_root, Path):
473
+ workspace_label = str(workspace_root)
474
+ repo_label = repo_id.strip() if isinstance(repo_id, str) else ""
475
+ if self._hub_root and self._manifest_path and self._manifest_path.exists():
476
+ try:
477
+ manifest = load_manifest(self._manifest_path, self._hub_root)
478
+ if workspace_root:
479
+ entry = manifest.get_by_path(self._hub_root, workspace_root)
480
+ else:
481
+ entry = None
482
+ if entry:
483
+ repo_label = entry.id or repo_label
484
+ if entry.display_name and entry.display_name != repo_label:
485
+ repo_label = f"{repo_label} ({entry.display_name})"
486
+ if entry.kind == "worktree" and entry.worktree_of:
487
+ repo_label = f"{repo_label} [worktree of {entry.worktree_of}]"
488
+ except Exception as exc:
489
+ self._logger.debug(
490
+ "telegram.ticket_flow.manifest_label_failed", exc_info=exc
491
+ )
492
+ if repo_label and workspace_label:
493
+ return f"{repo_label} @ {workspace_label}"
494
+ if repo_label:
495
+ return repo_label
496
+ if workspace_label:
497
+ return workspace_label
498
+ return "unknown workspace"
499
+
449
500
  async def _send_dispatch_attachments(
450
501
  self,
451
502
  chat_id: int,