pi-harness-runtime 1.1.136 → 1.1.139

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 (131) hide show
  1. package/harness/langchain/daemon.ts +128 -25
  2. package/harness/langchain/run.ts +1 -1
  3. package/index.ts +54 -2
  4. package/package.json +1 -1
  5. package/packages/a2a-adapter/package.json +1 -1
  6. package/packages/architecture-generator/package.json +1 -1
  7. package/packages/auth/package.json +1 -1
  8. package/packages/autonomous-refactor/package.json +1 -1
  9. package/packages/autonomous-runtime/package.json +1 -1
  10. package/packages/cache-strategy/package.json +1 -1
  11. package/packages/capability-registry/package.json +1 -1
  12. package/packages/checkpoint/package.json +1 -1
  13. package/packages/cli-plugin-sdk/package.json +1 -1
  14. package/packages/clipboard/package.json +1 -1
  15. package/packages/clipboard-plugin/package.json +1 -1
  16. package/packages/code-generation/package.json +1 -1
  17. package/packages/code-review/package.json +1 -1
  18. package/packages/codex-adapter/package.json +1 -1
  19. package/packages/codex-watcher/dist/src/index.d.ts +42 -0
  20. package/packages/codex-watcher/dist/src/index.d.ts.map +1 -0
  21. package/packages/codex-watcher/dist/src/index.js +198 -0
  22. package/packages/codex-watcher/dist/src/index.js.map +1 -0
  23. package/packages/codex-watcher/dist/src/parser.d.ts +36 -0
  24. package/packages/codex-watcher/dist/src/parser.d.ts.map +1 -0
  25. package/packages/codex-watcher/dist/src/parser.js +151 -0
  26. package/packages/codex-watcher/dist/src/parser.js.map +1 -0
  27. package/packages/codex-watcher/dist/src/session.d.ts +9 -0
  28. package/packages/codex-watcher/dist/src/session.d.ts.map +1 -0
  29. package/packages/codex-watcher/dist/src/session.js +131 -0
  30. package/packages/codex-watcher/dist/src/session.js.map +1 -0
  31. package/packages/codex-watcher/dist/src/types.d.ts +63 -0
  32. package/packages/codex-watcher/dist/src/types.d.ts.map +1 -0
  33. package/packages/codex-watcher/dist/src/types.js +17 -0
  34. package/packages/codex-watcher/dist/src/types.js.map +1 -0
  35. package/packages/codex-watcher/package.json +26 -0
  36. package/packages/codex-watcher/src/index.ts +244 -0
  37. package/packages/codex-watcher/src/parser.ts +210 -0
  38. package/packages/codex-watcher/src/session.ts +151 -0
  39. package/packages/codex-watcher/src/types.ts +67 -0
  40. package/packages/codex-watcher/test/watch.test.ts +150 -0
  41. package/packages/config-capture/package.json +1 -1
  42. package/packages/config-capture/src/index.ts +5 -16
  43. package/packages/context-compiler/package.json +1 -1
  44. package/packages/context-discovery/package.json +1 -1
  45. package/packages/context-manager/package.json +1 -1
  46. package/packages/cookie-sanitizer/package.json +1 -1
  47. package/packages/cost-optimizer/package.json +1 -1
  48. package/packages/dependency-analyzer/package.json +1 -1
  49. package/packages/django-plugin/package.json +1 -1
  50. package/packages/doc-generator/package.json +1 -1
  51. package/packages/evaluation-engine/package.json +1 -1
  52. package/packages/evaluation-runner/package.json +1 -1
  53. package/packages/event-bus/package.json +1 -1
  54. package/packages/event-store/package.json +1 -1
  55. package/packages/experience-replay/package.json +1 -1
  56. package/packages/feedback-collector/package.json +1 -1
  57. package/packages/file-copy-helper/package.json +1 -1
  58. package/packages/framework-detector/package.json +1 -1
  59. package/packages/framework-plugin-sdk/package.json +1 -1
  60. package/packages/frappe-plugin/package.json +1 -1
  61. package/packages/generic-web-plugin/package.json +1 -1
  62. package/packages/health-monitor/package.json +1 -1
  63. package/packages/intent-analyzer/package.json +1 -1
  64. package/packages/jev-judge/package.json +1 -1
  65. package/packages/knowledge-graph/package.json +1 -1
  66. package/packages/knowledge-retrieval/package.json +1 -1
  67. package/packages/laravel-plugin/package.json +1 -1
  68. package/packages/learning-engine/package.json +1 -1
  69. package/packages/mcp-adapter/package.json +1 -1
  70. package/packages/memory-engine/package.json +1 -1
  71. package/packages/milestone-manager/package.json +1 -1
  72. package/packages/model-registry/package.json +1 -1
  73. package/packages/nextjs-plugin/package.json +1 -1
  74. package/packages/notification/package.json +1 -1
  75. package/packages/observability/package.json +1 -1
  76. package/packages/okf-indexer/package.json +1 -1
  77. package/packages/performance-optimizer/package.json +1 -1
  78. package/packages/privilege-broker/package.json +1 -1
  79. package/packages/project-analyzer/package.json +1 -1
  80. package/packages/project-bootstrap/package.json +1 -1
  81. package/packages/projection-engine/package.json +1 -1
  82. package/packages/prompt-compiler/package.json +1 -1
  83. package/packages/prompt-versioning/package.json +1 -1
  84. package/packages/provider-adapter-sdk/package.json +1 -1
  85. package/packages/provider-router/package.json +1 -1
  86. package/packages/provider-selector/package.json +1 -1
  87. package/packages/providers/package.json +1 -1
  88. package/packages/qdrant-skills/package.json +1 -1
  89. package/packages/quota-manager/package.json +1 -1
  90. package/packages/rate-limiter/package.json +1 -1
  91. package/packages/react-vite-plugin/package.json +1 -1
  92. package/packages/release-manager/package.json +1 -1
  93. package/packages/requirement-compiler/package.json +1 -1
  94. package/packages/runtime/package.json +1 -1
  95. package/packages/scheduler/package.json +1 -1
  96. package/packages/scheduler-adapter/package.json +1 -1
  97. package/packages/session/package.json +1 -1
  98. package/packages/session-api/package.json +1 -1
  99. package/packages/session-export/package.json +1 -1
  100. package/packages/shared-context/package.json +1 -1
  101. package/packages/skill-mcp-client/package.json +1 -1
  102. package/packages/skill-registry/package.json +1 -1
  103. package/packages/skills/package.json +1 -1
  104. package/packages/sprint-planner/package.json +1 -1
  105. package/packages/subscription-engine/package.json +1 -1
  106. package/packages/task-compiler/package.json +1 -1
  107. package/packages/tencentdb-memory/package.json +1 -1
  108. package/packages/tencentdb-sync/package.json +1 -1
  109. package/packages/test-data-generator/package.json +1 -1
  110. package/packages/test-generator/package.json +1 -1
  111. package/packages/todo-bd-sync/package.json +1 -1
  112. package/packages/token-estimation/package.json +1 -1
  113. package/packages/token-optimizer/package.json +1 -1
  114. package/packages/trajectory/package.json +1 -1
  115. package/packages/tui/dist/harness-header.d.ts +18 -14
  116. package/packages/tui/dist/harness-header.d.ts.map +1 -1
  117. package/packages/tui/dist/harness-header.js +110 -64
  118. package/packages/tui/dist/harness-header.js.map +1 -1
  119. package/packages/tui/dist/index.d.ts +1 -2
  120. package/packages/tui/dist/index.d.ts.map +1 -1
  121. package/packages/tui/dist/index.js +1 -2
  122. package/packages/tui/dist/index.js.map +1 -1
  123. package/packages/tui/package.json +1 -1
  124. package/packages/tui/src/harness-header.ts +156 -77
  125. package/packages/tui/src/index.ts +6 -2
  126. package/packages/tui/test/harness-header.test.ts +380 -100
  127. package/packages/types/package.json +1 -1
  128. package/packages/workflow-events/package.json +1 -1
  129. package/packages/workspace-scanner/package.json +1 -1
  130. package/packages/worktree/package.json +1 -1
  131. package/packages/write-review/package.json +1 -1
@@ -26,6 +26,7 @@
26
26
  * Wiki: wiki/auto-trigger-multi-agent.md
27
27
  */
28
28
 
29
+ import { execSync } from "node:child_process";
29
30
  import { randomUUID } from "node:crypto";
30
31
  import {
31
32
  existsSync,
@@ -34,42 +35,34 @@ import {
34
35
  readFileSync,
35
36
  writeFileSync,
36
37
  } from "node:fs";
37
- import { execSync } from "node:child_process";
38
- import { join } from "node:path";
39
38
  import { homedir } from "node:os";
39
+ import { join } from "node:path";
40
40
 
41
41
  import { LeaseManager } from "../../packages/autonomous-runtime/src/lease.js";
42
42
  import type { ApprovalClass } from "../../packages/autonomous-runtime/src/types.js";
43
43
  import {
44
+ type CodexSession,
45
+ startWatcher,
46
+ type WatcherHandle,
47
+ } from "../../packages/codex-watcher/dist/src/index.js";
48
+ import { classifyMessage } from "../../packages/codex-watcher/dist/src/parser.js";
49
+ import {
50
+ createHerdrBus,
44
51
  ensureHerdrWorkspace,
45
52
  getHerdrWorkspace,
46
53
  type HerdrEventBus,
47
54
  type LoopVerdict,
48
- } from "../../packages/event-bus/src/herdr-bus.js";
49
- import {
50
- createHerdrBus,
51
55
  publishCodeWritten,
52
56
  publishLoopFinished,
53
57
  publishLoopStarted,
54
58
  publishReviewCompleted,
55
59
  } from "../../packages/event-bus/src/herdr-bus.js";
56
60
  import { NotificationCenter } from "../../packages/notification/dist/notification-center.js";
57
-
58
- import {
59
- invokeWithSurgeRetry,
60
- invokeWithGLMRetry,
61
- SurgeScheduler,
62
- type SurgePolicy,
63
- } from "./surge.js";
64
- import type { LoopWidget } from "./widget.js";
65
- import { StatusLineManager, isPiLensAvailable } from "./status-line.js";
66
- import { createLoopCheckpointer } from "./checkpointer.js";
67
-
68
61
  import {
69
- getTrajectoryStore,
70
62
  getApprovedPatternStore,
63
+ getTrajectoryStore,
71
64
  } from "../../packages/trajectory/src/index.js";
72
-
65
+ import { createLoopCheckpointer } from "./checkpointer.js";
73
66
  import {
74
67
  buildDryRunDeps,
75
68
  buildRealLoopDeps,
@@ -78,10 +71,19 @@ import {
78
71
  type LoopState,
79
72
  type WriteReviewLoop,
80
73
  } from "./graph.js";
74
+ import { submitPingPongIntent } from "./ping-pong-middleware.js";
75
+ import { isPiLensAvailable, StatusLineManager } from "./status-line.js";
76
+ import {
77
+ invokeWithGLMRetry,
78
+ invokeWithSurgeRetry,
79
+ type SurgePolicy,
80
+ SurgeScheduler,
81
+ } from "./surge.js";
82
+ import type { LoopWidget } from "./widget.js";
81
83
 
82
84
  // ─── Config ─────────────────────────────────────────────────────────────────
83
85
 
84
- export type TriggerSource = "bd-tasks" | "inbox" | "bus" | "cron";
86
+ export type TriggerSource = "bd-tasks" | "inbox" | "bus" | "cron" | "codex";
85
87
 
86
88
  export type ApprovalPolicy =
87
89
  | "never" // fully autonomous; notify only on finish/blocked (default)
@@ -556,6 +558,73 @@ class BdTasksWatcher {
556
558
  * Drop a JSON file into the right bucket to schedule a task.
557
559
  * Set "enabled": false to pause without deleting.
558
560
  */
561
+
562
+ // ─── Codex watcher ──────────────────────────────────────────────────────────
563
+
564
+ /** Polls ~/.codex/sessions/ for active Codex CLI sessions.
565
+ * When Codex emits a plan-type message, emits a TriggeredTask so the daemon
566
+ * can qualify it via submitPingPongIntent and run the ping-pong loop.
567
+ */
568
+ class CodexWatcher {
569
+ private readonly pollMs: number;
570
+ private handle: WatcherHandle | null = null;
571
+ private running = false;
572
+ private seenMsgs = new Set<string>();
573
+ private seenSessions = new Set<string>();
574
+
575
+ constructor(pollMs: number) {
576
+ this.pollMs = pollMs;
577
+ }
578
+
579
+ start(onTask: (task: TriggeredTask) => void): void {
580
+ if (this.running) return;
581
+ this.running = true;
582
+
583
+ this.handle = startWatcher({
584
+ pollIntervalMs: this.pollMs,
585
+ onMessages: (msgs) => {
586
+ // Get current session from handle for deduplication key
587
+ const session = this.handle?.latestSession();
588
+ const sessionId = session?.id ?? "unknown";
589
+
590
+ for (const msg of msgs) {
591
+ // Deduplicate by ordinal — Codex rewrites the last line on each turn
592
+ const msgKey = `${sessionId}:${msg.ordinal}`;
593
+ if (this.seenMsgs.has(msgKey)) continue;
594
+ this.seenMsgs.add(msgKey);
595
+
596
+ // Only emit plan-type messages
597
+ const classification = classifyMessage(msg.text);
598
+ if (classification !== "plan") continue;
599
+ if (!msg.text.trim()) continue;
600
+
601
+ const taskId = `codex-${sessionId}-${msg.ordinal}`;
602
+ onTask({
603
+ taskId,
604
+ request: msg.text.trim(),
605
+ source: "codex",
606
+ triggeredAt: msg.timestamp,
607
+ });
608
+ }
609
+ },
610
+ onSessionChange: (session: CodexSession | null) => {
611
+ if (!session) return;
612
+ if (this.seenSessions.has(session.id)) return;
613
+ this.seenSessions.add(session.id);
614
+ console.log(
615
+ `[codex-watcher] Session started: ${session.id} — "${session.threadName}"`,
616
+ );
617
+ },
618
+ });
619
+ }
620
+
621
+ stop(): void {
622
+ this.running = false;
623
+ this.handle?.stop();
624
+ this.handle = null;
625
+ }
626
+ }
627
+
559
628
  class CronWatcher {
560
629
  private readonly workspace: string;
561
630
  private readonly scheduleMs: Record<string, number>;
@@ -814,6 +883,7 @@ export class LoopDaemon {
814
883
  private readonly inboxWatcher: InboxWatcher;
815
884
  private readonly busWatcher: BusWatcher;
816
885
  private readonly bdWatcher: BdTasksWatcher;
886
+ private readonly codexWatcher: CodexWatcher | null;
817
887
  private readonly cronWatcher: CronWatcher | null;
818
888
  private readonly tunnelMonitor: TunnelMonitor | null;
819
889
  private readonly statusLine: StatusLineManager | null;
@@ -858,9 +928,11 @@ export class LoopDaemon {
858
928
 
859
929
  if (this.config.notificationConfig) {
860
930
  this.notificationCenter = new NotificationCenter({
861
- channels: this._buildChannels(this.config.notificationConfig) as Parameters<
862
- typeof NotificationCenter.prototype.notify
863
- >[0] extends { channels: infer C }
931
+ channels: this._buildChannels(
932
+ this.config.notificationConfig,
933
+ ) as Parameters<typeof NotificationCenter.prototype.notify>[0] extends {
934
+ channels: infer C;
935
+ }
864
936
  ? C
865
937
  : never,
866
938
  enabled: true,
@@ -873,6 +945,9 @@ export class LoopDaemon {
873
945
  this.widget = this.config.widget ?? null;
874
946
  this.busWatcher = new BusWatcher(this.bus, this.config.pollMs);
875
947
  this.bdWatcher = new BdTasksWatcher(this.config.pollMs);
948
+ this.codexWatcher = this.config.sources.includes("codex")
949
+ ? new CodexWatcher(this.config.pollMs)
950
+ : null;
876
951
  this.cronWatcher = this.config.sources.includes("cron")
877
952
  ? new CronWatcher(this.bus.getWorkspace())
878
953
  : null;
@@ -920,6 +995,11 @@ export class LoopDaemon {
920
995
  this.bdWatcher.start((t) => this._onTriggered(t));
921
996
  }
922
997
 
998
+ if (this.config.sources.includes("codex")) {
999
+ console.log(`[daemon] Starting Codex CLI session watcher`);
1000
+ this.codexWatcher?.start((t) => this._onTriggered(t));
1001
+ }
1002
+
923
1003
  this.tunnelMonitor?.start();
924
1004
  this.statusLine?.start();
925
1005
 
@@ -934,6 +1014,7 @@ export class LoopDaemon {
934
1014
  this.inboxWatcher.stop();
935
1015
  this.busWatcher.stop();
936
1016
  this.bdWatcher.stop();
1017
+ this.codexWatcher?.stop();
937
1018
  this.cronWatcher?.stop();
938
1019
  this.statusLine?.stop();
939
1020
  this.tunnelMonitor?.stop();
@@ -961,6 +1042,23 @@ export class LoopDaemon {
961
1042
  private _onTriggered(task: TriggeredTask): void {
962
1043
  if (this.stopped) return;
963
1044
 
1045
+ // ── Codex source: qualify via ping-pong middleware ──────────────────
1046
+ if (task.source === "codex") {
1047
+ const result = submitPingPongIntent(task.request, {
1048
+ actorId: this.agentId,
1049
+ });
1050
+ console.log(
1051
+ `[daemon] Ping-pong decision for [codex] ${task.taskId}: ${result.decision.decision} ` +
1052
+ `(score=${result.decision.score.toFixed(1)}, ` +
1053
+ `reasons=${result.decision.reasons.slice(0, 2).join("; ")}...)`,
1054
+ );
1055
+ console.log(`[daemon] blackboard: ${result.blackboardFile}`);
1056
+ console.log(`[daemon] audit: ${result.auditFile}`);
1057
+ if (result.enqueued) {
1058
+ console.log(`[daemon] enqueued: ${result.taskFile}`);
1059
+ }
1060
+ }
1061
+
964
1062
  // Skip if already running this task
965
1063
  if (this.running.has(task.taskId)) {
966
1064
  console.log(
@@ -1014,7 +1112,9 @@ export class LoopDaemon {
1014
1112
  // ── Gate check (I7) ──────────────────────────────────────────────
1015
1113
  const policy = effectivePolicy(task, this.config);
1016
1114
  if (policy === "always" || policy === "on_blocked") {
1017
- log(`Gate policy=${policy} — waiting for human approval before starting`);
1115
+ log(
1116
+ `Gate policy=${policy} — waiting for human approval before starting`,
1117
+ );
1018
1118
  const approved = await waitForAck(
1019
1119
  task,
1020
1120
  this.config,
@@ -1079,7 +1179,9 @@ export class LoopDaemon {
1079
1179
  }
1080
1180
  return undefined; // default MemorySaver
1081
1181
  })();
1082
- const loop: WriteReviewLoop = buildWriteReviewLoop(deps, { checkpointer });
1182
+ const loop: WriteReviewLoop = buildWriteReviewLoop(deps, {
1183
+ checkpointer,
1184
+ });
1083
1185
 
1084
1186
  // Persistent scheduler: attempt counter survives across multiple loop.invoke()
1085
1187
  // calls within the same task. This enables true exponential escalation
@@ -1211,7 +1313,8 @@ export class LoopDaemon {
1211
1313
  ? "reviewer blocked the task"
1212
1314
  : iterations >= this.config.maxIterations
1213
1315
  ? `max iterations (${iterations}) reached with changes still requested`
1214
- : comments.length > 0 && comments.every((c) => c.severity === "minor")
1316
+ : comments.length > 0 &&
1317
+ comments.every((c) => c.severity === "minor")
1215
1318
  ? `converged: only minor comments (${comments.length})`
1216
1319
  : `stuck: changes still requested after ${iterations} iteration(s)`;
1217
1320
 
@@ -180,7 +180,7 @@ async function runDaemon(args: CliArgs): Promise<void> {
180
180
  const daemon = new LoopDaemon({
181
181
  maxIterations: args.maxIterations,
182
182
  dryRun: args.dryRun,
183
- sources: ["inbox", "bus"],
183
+ sources: ["inbox", "bus", "codex"],
184
184
  });
185
185
 
186
186
  // Graceful shutdown on SIGTERM / SIGINT
package/index.ts CHANGED
@@ -244,7 +244,6 @@ async function initQdrant(): Promise<void> {
244
244
 
245
245
  // --- telegram-notifications: Telegram bot for harness event notifications ------------
246
246
  // Sends Telegram messages when jobs complete, tasks finish, or human input is needed.
247
- let _notificationCenter: unknown = null;
248
247
  async function initTelegram(): Promise<void> {
249
248
  try {
250
249
  const { NotificationCenter } = await import("./packages/notification/dist/index.js");
@@ -290,7 +289,7 @@ async function initTelegram(): Promise<void> {
290
289
  return;
291
290
  }
292
291
 
293
- _notificationCenter = center;
292
+ // NotificationCenter ready
294
293
  logStartup(`[pi-harness] Telegram notifications ready`);
295
294
  } catch (err) {
296
295
  logStartup("[pi-harness] Telegram: init failed:", err instanceof Error ? err.message : String(err));
@@ -2354,6 +2353,59 @@ Run \`bd ready\` to see current bd issues.
2354
2353
 
2355
2354
  // --- Footer status (persistent badge) --------------------------------
2356
2355
  pi.on("session_start", async (_event, ctx) => {
2356
+ // ── Auto-start LangChain loop daemon ───────────────────────────────────
2357
+ // Spawns `bun harness/langchain/run.ts --daemon` as a detached background
2358
+ // process if no daemon is currently running. The daemon watches:
2359
+ // inbox/ → manual task files dropped by the user
2360
+ // bus/ → task.proposed events (herdr event bus)
2361
+ // codex/ → Codex CLI session plans (PING-PONG Planner)
2362
+ // Detached pattern: spawn with detached:true + stdio:ignore + unref() so
2363
+ // the extension process can exit without killing the daemon.
2364
+ // PID file at ~/.pi-harness-runtime/daemon.pid prevents double-start.
2365
+ //
2366
+ // SAFETY: fire-and-forget IIFE with try/catch. Throwing from this handler
2367
+ // crashes pi.dev and kicks the user out. NEVER let exceptions escape.
2368
+ void (async () => {
2369
+ try {
2370
+ const { readFileSync: dfs, writeFileSync: wfs, unlinkSync: ufs } = await import("node:fs");
2371
+ const { spawn: spwn } = await import("node:child_process");
2372
+ const { dirname } = await import("node:path");
2373
+ const { fileURLToPath } = await import("node:url");
2374
+ const { freemem } = await import("node:os");
2375
+ const runtimeRoot = dirname(fileURLToPath(import.meta.url));
2376
+ const DAEMON_PID_FILE = `${process.env.HOME}/.pi-harness-runtime/daemon.pid`;
2377
+ const DAEMON_SCRIPT = `${runtimeRoot}/harness/langchain/run.ts`;
2378
+
2379
+ // Memory guard: skip if system has < 1 GB free (daemon can spike to 500 MB+)
2380
+ const FREE_RAM_MB = freemem() / (1024 * 1024);
2381
+ const MIN_FREE_MB = 1024;
2382
+ if (FREE_RAM_MB < MIN_FREE_MB) {
2383
+ console.error(`[pi-harness] Daemon skipped: only ${FREE_RAM_MB.toFixed(0)} MB RAM free (need ${MIN_FREE_MB} MB). Run /langchain manually.`);
2384
+ return;
2385
+ }
2386
+
2387
+ let daemonPid = 0;
2388
+ try { daemonPid = parseInt(dfs(DAEMON_PID_FILE, "utf8").trim(), 10); } catch { /* no PID file */ }
2389
+ if (daemonPid > 0) {
2390
+ try { process.kill(daemonPid, 0); /* alive? */ } catch {
2391
+ try { ufs(DAEMON_PID_FILE); } catch { /* ignore */ }
2392
+ daemonPid = 0;
2393
+ }
2394
+ }
2395
+ if (daemonPid > 0) {
2396
+ console.error(`[pi-harness] LangChain daemon already running (pid=${daemonPid})`);
2397
+ return;
2398
+ }
2399
+ const daemonProc = spwn("bun", ["run", DAEMON_SCRIPT, "--daemon"], { detached: true, stdio: "ignore" });
2400
+ daemonProc.unref();
2401
+ try { wfs(DAEMON_PID_FILE, String(daemonProc.pid), "utf8"); } catch { /* ignore */ }
2402
+ console.error(`[pi-harness] LangChain daemon started (pid=${daemonProc.pid})`);
2403
+ } catch (err) {
2404
+ // MUST NOT throw — throwing here crashes pi.dev and kicks the user out
2405
+ console.error("[pi-harness] Daemon spawn failed (non-fatal):", err instanceof Error ? err.message : String(err));
2406
+ }
2407
+ })();
2408
+
2357
2409
  // Capture only the setStatus function, not the ctx
2358
2410
  footerSetStatus = ctx.ui.setStatus.bind(ctx.ui);
2359
2411
  refreshFooterStatus(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-harness-runtime",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "description": "[BETA] Codex-style /usage status + autonomous coding harness for pi. Not production ready — expect breaking changes.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/a2a-adapter",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "type": "module",
5
5
  "description": "Google Agent-to-Agent (A2A) protocol adapter for pi-harness",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/architecture-generator",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "description": "Generate ADR and Mermaid diagrams from project analysis",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/auth",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "description": "pi-harness-runtime — auth",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/autonomous-refactor",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "type": "module",
5
5
  "description": "Autonomous refactoring engine",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/autonomous-runtime",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "description": "Autonomous Operations Runtime — task inbox, lease management, and worker lifecycle (RFC-0101)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/cache-strategy",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "type": "module",
5
5
  "description": "Smart caching with TTL and invalidation strategies (RFC-0022)",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/capability-registry",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "description": "Capability Registry for pi-harness-runtime — tracks model capabilities and enables capability-based routing",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/checkpoint",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "description": "Enhanced checkpoint system with incremental snapshots, diff-based storage, and recovery strategies",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/cli-plugin-sdk",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "type": "module",
5
5
  "description": "CLI Plugin SDK for pi-harness — install, list, remove, update, invoke plugins",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/clipboard",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/clipboard-plugin",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/code-generation",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "description": "Code generation pipeline for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/code-review",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "description": "Automated code review engine for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/codex-adapter",
3
- "version": "1.1.136",
3
+ "version": "1.1.139",
4
4
  "type": "module",
5
5
  "description": "OpenAI Codex provider adapter for pi-harness",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Codex Session Watcher — Main API
3
+ *
4
+ * Watches the active Codex CLI session and emits visible messages (user + assistant)
5
+ * so the harness PING-PONG middleware can feed them to pi.dev.
6
+ *
7
+ * Usage:
8
+ * import { startWatcher, getLatestSession, getVisibleMessages } from "@pi-harness/codex-watcher";
9
+ *
10
+ * // One-shot: get latest messages from the current session
11
+ * const session = getLatestSession();
12
+ * const messages = await getVisibleMessages(session.rolloutPath, { fromOrdinal: 0 });
13
+ *
14
+ * // Continuous: poll the active session and emit messages
15
+ * const handle = startWatcher({
16
+ * onMessages: (msgs) => console.log(msgs),
17
+ * });
18
+ * // later: handle.stop();
19
+ */
20
+ import { classifyMessage } from "./parser.js";
21
+ import { getAllSessions, getLatestSession } from "./session.js";
22
+ import type { CodexMessage, CodexSession, WatcherHandle, WatcherOptions } from "./types.js";
23
+ export type { CodexMessage, CodexSession, WatcherHandle, WatcherOptions };
24
+ export { classifyMessage, getAllSessions, getLatestSession };
25
+ /** Read all visible messages from a rollout file, starting from a given ordinal. */
26
+ export declare function getVisibleMessages(rolloutPath: string, options?: {
27
+ fromOrdinal?: number;
28
+ limit?: number;
29
+ }): Promise<CodexMessage[]>;
30
+ /**
31
+ * Start watching the active Codex session and call `onMessages` whenever
32
+ * new visible messages appear in the rollout file.
33
+ *
34
+ * @returns WatcherHandle — call handle.stop() to stop watching
35
+ *
36
+ * The watcher:
37
+ * 1. Polls session_index.jsonl to detect active session changes
38
+ * 2. Tracks file position so it only reads new lines (no re-read of full file)
39
+ * 3. Calls onMessages with incremental messages each poll cycle
40
+ */
41
+ export declare function startWatcher(options?: WatcherOptions): WatcherHandle;
42
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,EAAE,eAAe,EAAoB,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EACX,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,EACd,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAC;AAM7D,oFAAoF;AACpF,wBAAsB,kBAAkB,CACvC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,OAAO,CAAC,YAAY,EAAE,CAAC,CAkBzB;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,cAAmB,GAAG,aAAa,CA6JxE"}