@agentmeshhq/agent 0.4.16 → 0.4.20

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 (182) hide show
  1. package/LICENSE +21 -0
  2. package/dist/__tests__/attach.test.d.ts +1 -0
  3. package/dist/__tests__/attach.test.js +200 -0
  4. package/dist/__tests__/attach.test.js.map +1 -0
  5. package/dist/__tests__/auth-guard.integration.test.js +1 -1
  6. package/dist/__tests__/auth-guard.integration.test.js.map +1 -1
  7. package/dist/__tests__/auth-guard.test.js +3 -3
  8. package/dist/__tests__/auth-guard.test.js.map +1 -1
  9. package/dist/__tests__/bootstrap.test.js +23 -0
  10. package/dist/__tests__/bootstrap.test.js.map +1 -1
  11. package/dist/__tests__/daemon-hub-resilience.test.js +2 -2
  12. package/dist/__tests__/daemon-hub-resilience.test.js.map +1 -1
  13. package/dist/__tests__/evicted-cleanup.test.js.map +1 -1
  14. package/dist/__tests__/injection-verify.test.d.ts +1 -0
  15. package/dist/__tests__/injection-verify.test.js +93 -0
  16. package/dist/__tests__/injection-verify.test.js.map +1 -0
  17. package/dist/__tests__/injector.test.js +124 -4
  18. package/dist/__tests__/injector.test.js.map +1 -1
  19. package/dist/__tests__/list.test.d.ts +1 -0
  20. package/dist/__tests__/list.test.js +62 -0
  21. package/dist/__tests__/list.test.js.map +1 -0
  22. package/dist/__tests__/opencode-serve.test.d.ts +1 -0
  23. package/dist/__tests__/opencode-serve.test.js +54 -0
  24. package/dist/__tests__/opencode-serve.test.js.map +1 -0
  25. package/dist/__tests__/opencode-session-policy.test.d.ts +1 -0
  26. package/dist/__tests__/opencode-session-policy.test.js +61 -0
  27. package/dist/__tests__/opencode-session-policy.test.js.map +1 -0
  28. package/dist/__tests__/opencode-session.test.d.ts +1 -0
  29. package/dist/__tests__/opencode-session.test.js +178 -0
  30. package/dist/__tests__/opencode-session.test.js.map +1 -0
  31. package/dist/__tests__/registry.register.test.js +16 -0
  32. package/dist/__tests__/registry.register.test.js.map +1 -1
  33. package/dist/__tests__/relay.test.d.ts +1 -0
  34. package/dist/__tests__/relay.test.js +136 -0
  35. package/dist/__tests__/relay.test.js.map +1 -0
  36. package/dist/__tests__/runner.test.js +17 -0
  37. package/dist/__tests__/runner.test.js.map +1 -1
  38. package/dist/__tests__/session-recovery.test.js +214 -11
  39. package/dist/__tests__/session-recovery.test.js.map +1 -1
  40. package/dist/__tests__/shared-resource-guards.test.js +1 -4
  41. package/dist/__tests__/shared-resource-guards.test.js.map +1 -1
  42. package/dist/__tests__/start-team-id.test.js +22 -0
  43. package/dist/__tests__/start-team-id.test.js.map +1 -1
  44. package/dist/__tests__/startup-diagnostics.test.d.ts +1 -0
  45. package/dist/__tests__/startup-diagnostics.test.js +250 -0
  46. package/dist/__tests__/startup-diagnostics.test.js.map +1 -0
  47. package/dist/__tests__/tmux-runtime.test.js +13 -0
  48. package/dist/__tests__/tmux-runtime.test.js.map +1 -1
  49. package/dist/__tests__/token-rejection-recovery.test.js +52 -0
  50. package/dist/__tests__/token-rejection-recovery.test.js.map +1 -1
  51. package/dist/__tests__/watcher-queue.test.d.ts +1 -0
  52. package/dist/__tests__/watcher-queue.test.js +90 -0
  53. package/dist/__tests__/watcher-queue.test.js.map +1 -0
  54. package/dist/__tests__/watcher-state.test.d.ts +1 -0
  55. package/dist/__tests__/watcher-state.test.js +159 -0
  56. package/dist/__tests__/watcher-state.test.js.map +1 -0
  57. package/dist/cli/attach.d.ts +1 -1
  58. package/dist/cli/attach.js +125 -2
  59. package/dist/cli/attach.js.map +1 -1
  60. package/dist/cli/auth.js.map +1 -1
  61. package/dist/cli/commands.d.ts +32 -0
  62. package/dist/cli/commands.js +165 -0
  63. package/dist/cli/commands.js.map +1 -0
  64. package/dist/cli/index.js +97 -4
  65. package/dist/cli/index.js.map +1 -1
  66. package/dist/cli/list.js +26 -2
  67. package/dist/cli/list.js.map +1 -1
  68. package/dist/cli/relay.d.ts +4 -0
  69. package/dist/cli/relay.js +165 -3
  70. package/dist/cli/relay.js.map +1 -1
  71. package/dist/cli/start.d.ts +9 -1
  72. package/dist/cli/start.js +8 -0
  73. package/dist/cli/start.js.map +1 -1
  74. package/dist/cli/status.js +21 -8
  75. package/dist/cli/status.js.map +1 -1
  76. package/dist/cli/test.js +12 -1
  77. package/dist/cli/test.js.map +1 -1
  78. package/dist/config/schema.d.ts +17 -1
  79. package/dist/core/auth-guard.js +2 -2
  80. package/dist/core/auth-guard.js.map +1 -1
  81. package/dist/core/chat-output-parser.d.ts +24 -0
  82. package/dist/core/chat-output-parser.js +150 -0
  83. package/dist/core/chat-output-parser.js.map +1 -0
  84. package/dist/core/chat-output-parser.test.d.ts +7 -0
  85. package/dist/core/chat-output-parser.test.js +151 -0
  86. package/dist/core/chat-output-parser.test.js.map +1 -0
  87. package/dist/core/daemon/bootstrap.d.ts +8 -0
  88. package/dist/core/daemon/bootstrap.js +6 -1
  89. package/dist/core/daemon/bootstrap.js.map +1 -1
  90. package/dist/core/daemon/crash-log.js +5 -0
  91. package/dist/core/daemon/crash-log.js.map +1 -1
  92. package/dist/core/daemon/injection-verify.d.ts +25 -0
  93. package/dist/core/daemon/injection-verify.js +94 -0
  94. package/dist/core/daemon/injection-verify.js.map +1 -0
  95. package/dist/core/daemon/roles.d.ts +2 -2
  96. package/dist/core/daemon/roles.js +3 -0
  97. package/dist/core/daemon/roles.js.map +1 -1
  98. package/dist/core/daemon/session-recovery.d.ts +18 -1
  99. package/dist/core/daemon/session-recovery.js +89 -5
  100. package/dist/core/daemon/session-recovery.js.map +1 -1
  101. package/dist/core/daemon/startup-diagnostics.d.ts +76 -0
  102. package/dist/core/daemon/startup-diagnostics.js +277 -0
  103. package/dist/core/daemon/startup-diagnostics.js.map +1 -0
  104. package/dist/core/daemon/state.d.ts +8 -0
  105. package/dist/core/daemon/state.js +8 -0
  106. package/dist/core/daemon/state.js.map +1 -1
  107. package/dist/core/daemon/tmux-session.d.ts +4 -0
  108. package/dist/core/daemon/tmux-session.js +9 -1
  109. package/dist/core/daemon/tmux-session.js.map +1 -1
  110. package/dist/core/daemon/watcher-loop.d.ts +27 -0
  111. package/dist/core/daemon/watcher-loop.js +134 -0
  112. package/dist/core/daemon/watcher-loop.js.map +1 -0
  113. package/dist/core/daemon/watcher-queue.d.ts +33 -0
  114. package/dist/core/daemon/watcher-queue.js +71 -0
  115. package/dist/core/daemon/watcher-queue.js.map +1 -0
  116. package/dist/core/daemon/watcher-state.d.ts +66 -0
  117. package/dist/core/daemon/watcher-state.js +151 -0
  118. package/dist/core/daemon/watcher-state.js.map +1 -0
  119. package/dist/core/daemon/workspace.js +10 -2
  120. package/dist/core/daemon/workspace.js.map +1 -1
  121. package/dist/core/daemon.d.ts +22 -1
  122. package/dist/core/daemon.js +289 -20
  123. package/dist/core/daemon.js.map +1 -1
  124. package/dist/core/handoff-sla.js +1 -1
  125. package/dist/core/handoff-sla.js.map +1 -1
  126. package/dist/core/injector.d.ts +2 -0
  127. package/dist/core/injector.js +227 -32
  128. package/dist/core/injector.js.map +1 -1
  129. package/dist/core/opencode-serve.d.ts +26 -0
  130. package/dist/core/opencode-serve.js +97 -0
  131. package/dist/core/opencode-serve.js.map +1 -0
  132. package/dist/core/opencode-session-policy.d.ts +10 -0
  133. package/dist/core/opencode-session-policy.js +10 -0
  134. package/dist/core/opencode-session-policy.js.map +1 -0
  135. package/dist/core/opencode-session.d.ts +12 -0
  136. package/dist/core/opencode-session.js +165 -0
  137. package/dist/core/opencode-session.js.map +1 -0
  138. package/dist/core/registry.d.ts +2 -1
  139. package/dist/core/registry.js +3 -2
  140. package/dist/core/registry.js.map +1 -1
  141. package/dist/core/runner/build.js +7 -31
  142. package/dist/core/runner/build.js.map +1 -1
  143. package/dist/core/runner/detect.js +2 -8
  144. package/dist/core/runner/detect.js.map +1 -1
  145. package/dist/core/runner/index.d.ts +3 -1
  146. package/dist/core/runner/index.js +2 -0
  147. package/dist/core/runner/index.js.map +1 -1
  148. package/dist/core/runner/kimi-models.d.ts +4 -0
  149. package/dist/core/runner/kimi-models.js +24 -0
  150. package/dist/core/runner/kimi-models.js.map +1 -0
  151. package/dist/core/runner/registry.d.ts +3 -0
  152. package/dist/core/runner/registry.js +75 -0
  153. package/dist/core/runner/registry.js.map +1 -0
  154. package/dist/core/runner/types.d.ts +17 -1
  155. package/dist/core/tmux-runtime.d.ts +2 -1
  156. package/dist/core/tmux-runtime.js +17 -1
  157. package/dist/core/tmux-runtime.js.map +1 -1
  158. package/dist/core/tmux.d.ts +4 -0
  159. package/dist/core/tmux.js +54 -11
  160. package/dist/core/tmux.js.map +1 -1
  161. package/dist/runtime/adapters/opencode.d.ts +63 -0
  162. package/dist/runtime/adapters/opencode.js +358 -0
  163. package/dist/runtime/adapters/opencode.js.map +1 -0
  164. package/dist/runtime/adapters/tmux-fallback.d.ts +23 -0
  165. package/dist/runtime/adapters/tmux-fallback.js +148 -0
  166. package/dist/runtime/adapters/tmux-fallback.js.map +1 -0
  167. package/dist/runtime/adapters/tmux-fallback.test.d.ts +4 -0
  168. package/dist/runtime/adapters/tmux-fallback.test.js +91 -0
  169. package/dist/runtime/adapters/tmux-fallback.test.js.map +1 -0
  170. package/dist/runtime/index.d.ts +146 -0
  171. package/dist/runtime/index.js +191 -0
  172. package/dist/runtime/index.js.map +1 -0
  173. package/dist/runtime/registry.d.ts +53 -0
  174. package/dist/runtime/registry.js +112 -0
  175. package/dist/runtime/registry.js.map +1 -0
  176. package/dist/runtime/registry.test.d.ts +4 -0
  177. package/dist/runtime/registry.test.js +69 -0
  178. package/dist/runtime/registry.test.js.map +1 -0
  179. package/dist/runtime/types.d.ts +158 -0
  180. package/dist/runtime/types.js +8 -0
  181. package/dist/runtime/types.js.map +1 -0
  182. package/package.json +11 -12
@@ -1,7 +1,91 @@
1
- export function isRecoverableSessionFailure(reason) {
2
- return (reason === "session_not_found" ||
3
- reason === "pane_dead" ||
4
- reason === "no_pid" ||
5
- reason.startsWith("check_failed"));
1
+ import { readStartupDiagnostics } from "./startup-diagnostics.js";
2
+ /**
3
+ * Extended reasons that can indicate a recoverable session failure
4
+ */
5
+ const RECOVERABLE_REASONS = [
6
+ "session_not_found",
7
+ "pane_dead",
8
+ "no_pid",
9
+ "pane_died",
10
+ "process_replaced",
11
+ "session_terminated",
12
+ ];
13
+ /**
14
+ * Maximum age of an exit event to consider it relevant (60 seconds)
15
+ * Exit events older than this are considered stale and unrelated to current failures
16
+ */
17
+ const MAX_EXIT_EVENT_AGE_MS = 60000;
18
+ /**
19
+ * Startup window - if process exits within this time of startup, it's recoverable
20
+ */
21
+ const STARTUP_WINDOW_MS = 15000;
22
+ /**
23
+ * Check if a reason string matches recoverable patterns
24
+ */
25
+ function matchesRecoverablePattern(reason) {
26
+ return (RECOVERABLE_REASONS.includes(reason) ||
27
+ reason.startsWith("check_failed") ||
28
+ reason.startsWith("session_creation_failed") ||
29
+ reason.startsWith("pane_dead"));
30
+ }
31
+ /**
32
+ * Gets the most recent process exit event from diagnostics
33
+ */
34
+ export function getLastProcessExit(agentName) {
35
+ const entries = readStartupDiagnostics(agentName);
36
+ // Find the most recent exit entry
37
+ for (let i = entries.length - 1; i >= 0; i--) {
38
+ if (entries[i].type === "exit") {
39
+ return entries[i].data;
40
+ }
41
+ }
42
+ return null;
43
+ }
44
+ /**
45
+ * Determines if a session failure is recoverable based on the reason
46
+ * and startup diagnostics.
47
+ *
48
+ * A failure is considered recoverable if:
49
+ * 1. The reason matches known recoverable patterns
50
+ * 2. The process exited during startup (within 15s) AND the exit event is fresh
51
+ * (within 60s) - this suggests a transient issue that may resolve on retry
52
+ *
53
+ * The freshness guard prevents old exit events from misclassifying unrelated
54
+ * future failures as recoverable.
55
+ */
56
+ export function isRecoverableSessionFailure(reason, agentName) {
57
+ // First check pattern match
58
+ if (matchesRecoverablePattern(reason)) {
59
+ return true;
60
+ }
61
+ // If we have agent name, check startup diagnostics
62
+ if (agentName) {
63
+ const entries = readStartupDiagnostics(agentName);
64
+ let lastExit = null;
65
+ for (let i = entries.length - 1; i >= 0; i--) {
66
+ if (entries[i].type === "exit") {
67
+ lastExit = {
68
+ exit: entries[i].data,
69
+ timestamp: entries[i].timestamp,
70
+ };
71
+ break;
72
+ }
73
+ }
74
+ if (lastExit) {
75
+ // Check freshness: exit event must be recent enough to be relevant
76
+ const exitTimestamp = new Date(lastExit.timestamp).getTime();
77
+ const now = Date.now();
78
+ const exitAgeMs = now - exitTimestamp;
79
+ // Only consider fresh exit events (within last 60 seconds)
80
+ if (exitAgeMs <= MAX_EXIT_EVENT_AGE_MS) {
81
+ // If process exited within 15 seconds of startup, consider it recoverable
82
+ // This catches cases where the runner crashed immediately
83
+ if (lastExit.exit.elapsedMs < STARTUP_WINDOW_MS) {
84
+ return true;
85
+ }
86
+ }
87
+ }
88
+ }
89
+ return false;
6
90
  }
7
91
  //# sourceMappingURL=session-recovery.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-recovery.js","sourceRoot":"","sources":["../../../src/core/daemon/session-recovery.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,2BAA2B,CAAC,MAAc;IACxD,OAAO,CACL,MAAM,KAAK,mBAAmB;QAC9B,MAAM,KAAK,WAAW;QACtB,MAAM,KAAK,QAAQ;QACnB,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,CAClC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"session-recovery.js","sourceRoot":"","sources":["../../../src/core/daemon/session-recovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEzF;;GAEG;AACH,MAAM,mBAAmB,GAAG;IAC1B,mBAAmB;IACnB,WAAW;IACX,QAAQ;IACR,WAAW;IACX,kBAAkB;IAClB,oBAAoB;CACrB,CAAC;AAEF;;;GAGG;AACH,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAEpC;;GAEG;AACH,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEhC;;GAEG;AACH,SAAS,yBAAyB,CAAC,MAAc;IAC/C,OAAO,CACL,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC;QACpC,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC;QACjC,MAAM,CAAC,UAAU,CAAC,yBAAyB,CAAC;QAC5C,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAC/B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,MAAM,OAAO,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAClD,kCAAkC;IAClC,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC/B,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,IAAwB,CAAC;QAC7C,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAAc,EAAE,SAAkB;IAC5E,4BAA4B;IAC5B,IAAI,yBAAyB,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mDAAmD;IACnD,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;QAOlD,IAAI,QAAQ,GAAqB,IAAI,CAAC;QAEtC,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC/B,QAAQ,GAAG;oBACT,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAwB;oBACzC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;iBAChC,CAAC;gBACF,MAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,EAAE,CAAC;YACb,mEAAmE;YACnE,MAAM,aAAa,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;YAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,SAAS,GAAG,GAAG,GAAG,aAAa,CAAC;YAEtC,2DAA2D;YAC3D,IAAI,SAAS,IAAI,qBAAqB,EAAE,CAAC;gBACvC,0EAA0E;gBAC1E,0DAA0D;gBAC1D,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,iBAAiB,EAAE,CAAC;oBAChD,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Startup Diagnostics for Agent Tmux Sessions
3
+ *
4
+ * Provides structured logging for runner startup to diagnose
5
+ * session creation failures and early exits.
6
+ */
7
+ export interface StartupDiagnostics {
8
+ /** The final resolved command (with args) that was executed */
9
+ resolvedCommand: string;
10
+ /** Environment variables set (keys only, values redacted) */
11
+ envKeys: string[];
12
+ /** Session name used for tmux */
13
+ sessionName: string;
14
+ /** Working directory for the session */
15
+ workdir?: string;
16
+ /** Timestamp when session creation started */
17
+ startTime: string;
18
+ /** Runner type detected */
19
+ runnerKind: "opencode" | "claude" | "codex" | "other";
20
+ /** Whether autonomous mode was enabled */
21
+ autonomous?: boolean;
22
+ }
23
+ export interface ProcessExitEvent {
24
+ /** Exit code (null if killed by signal) */
25
+ code: number | null;
26
+ /** Signal that killed the process (null if exited normally) */
27
+ signal: string | null;
28
+ /** Time elapsed since session creation (ms) */
29
+ elapsedMs: number;
30
+ /** Reason classification */
31
+ reason: string;
32
+ }
33
+ interface DiagnosticsEntry {
34
+ type: "startup" | "exit";
35
+ timestamp: string;
36
+ agentName: string;
37
+ data: StartupDiagnostics | ProcessExitEvent;
38
+ }
39
+ /**
40
+ * Redacts sensitive environment variable values, keeping only keys
41
+ */
42
+ export declare function redactEnvKeys(env: Record<string, string | undefined>): string[];
43
+ /**
44
+ * Detects the runner type from the command
45
+ */
46
+ export declare function detectRunnerKind(command: string): "opencode" | "claude" | "codex" | "other";
47
+ /**
48
+ * Logs startup diagnostics for a new tmux session
49
+ */
50
+ export declare function logSessionStartup(agentName: string, diagnostics: StartupDiagnostics): void;
51
+ /**
52
+ * Logs a process exit event
53
+ */
54
+ export declare function logProcessExit(agentName: string, exitEvent: ProcessExitEvent): void;
55
+ /**
56
+ * Reads the recent diagnostics for an agent
57
+ */
58
+ export declare function readStartupDiagnostics(agentName: string): DiagnosticsEntry[];
59
+ /**
60
+ * Clears old diagnostics for an agent (keeps last 100 entries)
61
+ */
62
+ export declare function cleanupOldDiagnostics(agentName: string): void;
63
+ /**
64
+ * Captures the current pane PID for an agent's session
65
+ */
66
+ export declare function capturePanePid(sessionName: string): number | null;
67
+ /**
68
+ * Monitors a tmux session for early process exit
69
+ * Returns a cleanup function to stop monitoring
70
+ */
71
+ export declare function monitorSessionExit(agentName: string, sessionName: string, startTime: Date, onEarlyExit?: (event: ProcessExitEvent) => void): () => void;
72
+ /**
73
+ * Formats a diagnostic summary for display
74
+ */
75
+ export declare function formatDiagnosticSummary(agentName: string): string;
76
+ export {};
@@ -0,0 +1,277 @@
1
+ /**
2
+ * Startup Diagnostics for Agent Tmux Sessions
3
+ *
4
+ * Provides structured logging for runner startup to diagnose
5
+ * session creation failures and early exits.
6
+ */
7
+ import { execSync } from "node:child_process";
8
+ import fs from "node:fs";
9
+ import os from "node:os";
10
+ import path from "node:path";
11
+ const DIAGNOSTICS_DIR = path.join(os.homedir(), ".agentmesh", "diagnostics");
12
+ const STARTUP_WINDOW_MS = 15000; // 15 second window for startup monitoring
13
+ /**
14
+ * Ensures the diagnostics directory exists
15
+ */
16
+ function ensureDiagnosticsDir() {
17
+ if (!fs.existsSync(DIAGNOSTICS_DIR)) {
18
+ fs.mkdirSync(DIAGNOSTICS_DIR, { recursive: true });
19
+ }
20
+ }
21
+ /**
22
+ * Gets the path to the diagnostics log file for an agent
23
+ */
24
+ function getDiagnosticsPath(agentName) {
25
+ return path.join(DIAGNOSTICS_DIR, `${agentName}-startup.jsonl`);
26
+ }
27
+ /**
28
+ * Redacts sensitive environment variable values, keeping only keys
29
+ */
30
+ export function redactEnvKeys(env) {
31
+ const sensitiveKeys = new Set([
32
+ "token",
33
+ "key",
34
+ "secret",
35
+ "password",
36
+ "auth",
37
+ "credential",
38
+ "api_key",
39
+ "apikey",
40
+ ]);
41
+ return Object.entries(env)
42
+ .filter(([, value]) => value !== undefined && value !== "")
43
+ .map(([key]) => {
44
+ const lowerKey = key.toLowerCase();
45
+ // Mark sensitive keys with [REDACTED] suffix
46
+ const isSensitive = sensitiveKeys.has(lowerKey) || [...sensitiveKeys].some((sk) => lowerKey.includes(sk));
47
+ return isSensitive ? `${key}=[REDACTED]` : key;
48
+ });
49
+ }
50
+ /**
51
+ * Detects the runner type from the command
52
+ */
53
+ export function detectRunnerKind(command) {
54
+ const cmd = command.trim().toLowerCase();
55
+ if (cmd.startsWith("opencode"))
56
+ return "opencode";
57
+ if (cmd.startsWith("claude"))
58
+ return "claude";
59
+ if (cmd.startsWith("codex"))
60
+ return "codex";
61
+ return "other";
62
+ }
63
+ /**
64
+ * Logs startup diagnostics for a new tmux session
65
+ */
66
+ export function logSessionStartup(agentName, diagnostics) {
67
+ ensureDiagnosticsDir();
68
+ const entry = {
69
+ type: "startup",
70
+ timestamp: new Date().toISOString(),
71
+ agentName,
72
+ data: diagnostics,
73
+ };
74
+ const logPath = getDiagnosticsPath(agentName);
75
+ fs.appendFileSync(logPath, `${JSON.stringify(entry)}\n`);
76
+ // Also log to console for immediate visibility
77
+ console.log(`[STARTUP] ${agentName}: ${diagnostics.resolvedCommand}`);
78
+ console.log(`[STARTUP] Runner: ${diagnostics.runnerKind}, Autonomous: ${diagnostics.autonomous ?? false}`);
79
+ }
80
+ /**
81
+ * Logs a process exit event
82
+ */
83
+ export function logProcessExit(agentName, exitEvent) {
84
+ ensureDiagnosticsDir();
85
+ const entry = {
86
+ type: "exit",
87
+ timestamp: new Date().toISOString(),
88
+ agentName,
89
+ data: exitEvent,
90
+ };
91
+ const logPath = getDiagnosticsPath(agentName);
92
+ fs.appendFileSync(logPath, `${JSON.stringify(entry)}\n`);
93
+ // Log with appropriate severity
94
+ const severity = exitEvent.elapsedMs < STARTUP_WINDOW_MS ? "ERROR" : "WARN";
95
+ console.log(`[${severity}] ${agentName}: Process exited (code=${exitEvent.code}, signal=${exitEvent.signal}, elapsed=${exitEvent.elapsedMs}ms) - ${exitEvent.reason}`);
96
+ }
97
+ /**
98
+ * Reads the recent diagnostics for an agent
99
+ */
100
+ export function readStartupDiagnostics(agentName) {
101
+ try {
102
+ const logPath = getDiagnosticsPath(agentName);
103
+ if (!fs.existsSync(logPath)) {
104
+ return [];
105
+ }
106
+ const content = fs.readFileSync(logPath, "utf-8");
107
+ return content
108
+ .trim()
109
+ .split("\n")
110
+ .filter(Boolean)
111
+ .map((line) => JSON.parse(line));
112
+ }
113
+ catch {
114
+ return [];
115
+ }
116
+ }
117
+ /**
118
+ * Clears old diagnostics for an agent (keeps last 100 entries)
119
+ */
120
+ export function cleanupOldDiagnostics(agentName) {
121
+ try {
122
+ const entries = readStartupDiagnostics(agentName);
123
+ if (entries.length <= 100)
124
+ return;
125
+ const logPath = getDiagnosticsPath(agentName);
126
+ const recent = entries.slice(-100);
127
+ fs.writeFileSync(logPath, `${recent.map((e) => JSON.stringify(e)).join("\n")}\n`);
128
+ }
129
+ catch {
130
+ // Non-fatal: cleanup failure should not break anything
131
+ }
132
+ }
133
+ /**
134
+ * Captures the current pane PID for an agent's session
135
+ */
136
+ export function capturePanePid(sessionName) {
137
+ try {
138
+ const output = execSync(`tmux list-panes -t "${sessionName}" -F "#{pane_pid}"`, {
139
+ encoding: "utf-8",
140
+ timeout: 5000,
141
+ }).trim();
142
+ const pid = parseInt(output, 10);
143
+ return Number.isNaN(pid) ? null : pid;
144
+ }
145
+ catch {
146
+ return null;
147
+ }
148
+ }
149
+ /**
150
+ * Monitors a tmux session for early process exit
151
+ * Returns a cleanup function to stop monitoring
152
+ */
153
+ export function monitorSessionExit(agentName, sessionName, startTime, onEarlyExit) {
154
+ const initialPid = capturePanePid(sessionName);
155
+ let checkInterval = null;
156
+ let hasExited = false;
157
+ // Stop monitoring after startup window + grace period
158
+ const stopMonitoringAt = startTime.getTime() + STARTUP_WINDOW_MS + 5000;
159
+ checkInterval = setInterval(() => {
160
+ if (hasExited)
161
+ return;
162
+ const now = Date.now();
163
+ if (now > stopMonitoringAt) {
164
+ // Startup window passed, stop monitoring
165
+ if (checkInterval) {
166
+ clearInterval(checkInterval);
167
+ checkInterval = null;
168
+ }
169
+ return;
170
+ }
171
+ try {
172
+ // Check if session still exists
173
+ execSync(`tmux has-session -t "${sessionName}" 2>/dev/null`, { timeout: 1000 });
174
+ // Check if pane is dead
175
+ const paneInfo = execSync(`tmux list-panes -t "${sessionName}" -F "#{pane_pid}:#{pane_dead}" 2>/dev/null`, { encoding: "utf-8", timeout: 1000 }).trim();
176
+ const [currentPidStr, dead] = paneInfo.split(":");
177
+ const currentPid = parseInt(currentPidStr, 10);
178
+ if (dead === "1") {
179
+ hasExited = true;
180
+ const elapsedMs = now - startTime.getTime();
181
+ const event = {
182
+ code: null,
183
+ signal: null,
184
+ elapsedMs,
185
+ reason: "pane_died",
186
+ };
187
+ logProcessExit(agentName, event);
188
+ onEarlyExit?.(event);
189
+ if (checkInterval) {
190
+ clearInterval(checkInterval);
191
+ checkInterval = null;
192
+ }
193
+ return;
194
+ }
195
+ // Check if PID changed (process restarted/exited)
196
+ if (initialPid && !Number.isNaN(currentPid) && currentPid !== initialPid && initialPid > 0) {
197
+ hasExited = true;
198
+ const elapsedMs = now - startTime.getTime();
199
+ const event = {
200
+ code: null,
201
+ signal: null,
202
+ elapsedMs,
203
+ reason: "process_replaced",
204
+ };
205
+ logProcessExit(agentName, event);
206
+ onEarlyExit?.(event);
207
+ if (checkInterval) {
208
+ clearInterval(checkInterval);
209
+ checkInterval = null;
210
+ }
211
+ }
212
+ }
213
+ catch {
214
+ // Session no longer exists - process exited
215
+ if (!hasExited) {
216
+ hasExited = true;
217
+ const elapsedMs = now - startTime.getTime();
218
+ const event = {
219
+ code: null,
220
+ signal: null,
221
+ elapsedMs,
222
+ reason: "session_terminated",
223
+ };
224
+ logProcessExit(agentName, event);
225
+ onEarlyExit?.(event);
226
+ if (checkInterval) {
227
+ clearInterval(checkInterval);
228
+ checkInterval = null;
229
+ }
230
+ }
231
+ }
232
+ }, 1000); // Check every second
233
+ // Return cleanup function
234
+ return () => {
235
+ if (checkInterval) {
236
+ clearInterval(checkInterval);
237
+ checkInterval = null;
238
+ }
239
+ };
240
+ }
241
+ /**
242
+ * Formats a diagnostic summary for display
243
+ */
244
+ export function formatDiagnosticSummary(agentName) {
245
+ const entries = readStartupDiagnostics(agentName);
246
+ if (entries.length === 0) {
247
+ return `No startup diagnostics found for ${agentName}`;
248
+ }
249
+ const recent = entries.slice(-5); // Last 5 entries
250
+ const lines = [
251
+ `\n=== Startup Diagnostics for ${agentName} ===`,
252
+ `Total entries: ${entries.length}`,
253
+ "",
254
+ ];
255
+ for (const entry of recent) {
256
+ if (entry.type === "startup") {
257
+ const data = entry.data;
258
+ lines.push(`[${entry.timestamp}] STARTUP`);
259
+ lines.push(` Command: ${data.resolvedCommand}`);
260
+ lines.push(` Runner: ${data.runnerKind}`);
261
+ lines.push(` Session: ${data.sessionName}`);
262
+ lines.push(` Workdir: ${data.workdir ?? "(not set)"}`);
263
+ lines.push(` Autonomous: ${data.autonomous ?? false}`);
264
+ lines.push(` Env vars: ${data.envKeys.join(", ")}`);
265
+ }
266
+ else {
267
+ const data = entry.data;
268
+ lines.push(`[${entry.timestamp}] EXIT`);
269
+ lines.push(` Code: ${data.code ?? "N/A"}, Signal: ${data.signal ?? "N/A"}`);
270
+ lines.push(` Elapsed: ${data.elapsedMs}ms`);
271
+ lines.push(` Reason: ${data.reason}`);
272
+ }
273
+ lines.push("");
274
+ }
275
+ return lines.join("\n");
276
+ }
277
+ //# sourceMappingURL=startup-diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startup-diagnostics.js","sourceRoot":"","sources":["../../../src/core/daemon/startup-diagnostics.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,14 @@ export interface PersistRunningStateInput {
11
11
  sandboxContainer?: string;
12
12
  serveMode: boolean;
13
13
  servePort: number;
14
+ serveHostname?: string;
15
+ serveUrl?: string;
16
+ servePublicUrl?: string;
17
+ serveAuthType?: "none" | "basic";
18
+ serveUsername?: string;
19
+ servePasswordEnv?: string;
20
+ serveHealthy?: boolean;
21
+ serveVersion?: string;
14
22
  }
15
23
  /**
16
24
  * Get the PID of the foreground process running in a tmux pane.
@@ -73,6 +73,14 @@ export function persistRunningState(input) {
73
73
  runnerType: input.runnerType,
74
74
  sandboxContainer: input.sandboxContainer,
75
75
  servePort: input.serveMode ? input.servePort : undefined,
76
+ serveHostname: input.serveMode ? input.serveHostname : undefined,
77
+ serveUrl: input.serveMode ? input.serveUrl : undefined,
78
+ servePublicUrl: input.serveMode ? input.servePublicUrl : undefined,
79
+ serveAuthType: input.serveMode ? input.serveAuthType : undefined,
80
+ serveUsername: input.serveMode ? input.serveUsername : undefined,
81
+ servePasswordEnv: input.serveMode ? input.servePasswordEnv : undefined,
82
+ serveHealthy: input.serveMode ? input.serveHealthy : undefined,
83
+ serveVersion: input.serveMode ? input.serveVersion : undefined,
76
84
  });
77
85
  }
78
86
  //# sourceMappingURL=state.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/core/daemon/state.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/core/daemon/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAwB5C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,WAAmB;IAChD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,uBAAuB,WAAW,gCAAgC,EAAE;YAC1F,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACxC,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY,GAAG,cAAc,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QAC9E,MAAM,SAAS,GAAG,MAAM;aACrB,IAAI,EAAE;aACN,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;aAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAE5C,MAAM,cAAc,GAAa,CAAC,GAAG,SAAS,CAAC,CAAC;QAChD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,cAAc,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnD,CAAC;QAED,OAAO,cAAc,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,SAAiB;IACrD,MAAM,WAAW,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IAE5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACnD,cAAc;IACd,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAA+B;IACjE,MAAM,WAAW,GAAG,KAAK,CAAC,SAAS;QACjC,CAAC,CAAC,SAAS,KAAK,CAAC,SAAS,EAAE;QAC5B,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAEpC,eAAe,CAAC;QACd,IAAI,EAAE,KAAK,CAAC,SAAS;QACrB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,WAAW,EAAE,WAAW;QACxB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QACxD,aAAa,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;QAChE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;QACtD,cAAc,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS;QAClE,aAAa,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;QAChE,aAAa,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;QAChE,gBAAgB,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS;QACtE,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS;QAC9D,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS;KAC/D,CAAC,CAAC;AACL,CAAC"}
@@ -1,3 +1,4 @@
1
+ import type { RunnerType } from "../runner/types.js";
1
2
  import { type SessionEnv } from "../tmux.js";
2
3
  export interface StartTmuxSessionInput {
3
4
  agentName: string;
@@ -5,7 +6,10 @@ export interface StartTmuxSessionInput {
5
6
  command: string;
6
7
  workdir?: string;
7
8
  runnerEnv: SessionEnv;
9
+ runnerType: RunnerType;
8
10
  shouldRestoreContext: boolean;
11
+ serveMode: boolean;
12
+ sandboxMode: boolean;
9
13
  autonomous?: boolean;
10
14
  }
11
15
  export interface StartTmuxSessionResult {
@@ -1,4 +1,5 @@
1
1
  import { loadContext } from "../../context/index.js";
2
+ import { shouldRestoreOpenCodeSession } from "../opencode-session-policy.js";
2
3
  import { snapshotSessionId } from "../session-id.js";
3
4
  import { createSession, getSessionName, sessionExists, updateSessionEnvironment, } from "../tmux.js";
4
5
  /**
@@ -9,7 +10,14 @@ export function startTmuxRuntimeSession(input) {
9
10
  const alreadyExists = sessionExists(sessionName);
10
11
  if (!alreadyExists) {
11
12
  let savedSessionId;
12
- if (input.shouldRestoreContext && input.agentId) {
13
+ if (input.shouldRestoreContext &&
14
+ input.agentId &&
15
+ shouldRestoreOpenCodeSession({
16
+ runnerType: input.runnerType,
17
+ autonomous: input.autonomous ?? false,
18
+ serveMode: input.serveMode,
19
+ sandboxMode: input.sandboxMode,
20
+ })) {
13
21
  const savedContext = loadContext(input.agentId);
14
22
  savedSessionId = savedContext?.custom?.opencodeSessionId;
15
23
  if (savedSessionId) {
@@ -1 +1 @@
1
- {"version":3,"file":"tmux-session.js","sourceRoot":"","sources":["../../../src/core/daemon/tmux-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EACL,aAAa,EACb,cAAc,EAEd,aAAa,EACb,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAiBpB;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAA4B;IAClE,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,aAAa,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAEjD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,IAAI,cAAkC,CAAC;QAEvC,IAAI,KAAK,CAAC,oBAAoB,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAChD,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAChD,cAAc,GAAG,YAAY,EAAE,MAAM,EAAE,iBAAuC,CAAC;YAC/E,IAAI,cAAc,EAAE,CAAC;gBACnB,OAAO,CAAC,GAAG,CAAC,8CAA8C,cAAc,EAAE,CAAC,CAAC;YAC9E,CAAC;QACH,CAAC;QAED,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAE7D,OAAO,CAAC,GAAG,CAAC,0BAA0B,WAAW,EAAE,CAAC,CAAC;QAErD,MAAM,OAAO,GAAG,aAAa,CAC3B,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,SAAS,EACf,cAAc,EACd,KAAK,CAAC,UAAU,CACjB,CAAC;QAEF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QAED,OAAO;YACL,iBAAiB;YACjB,wBAAwB,EAAE,cAAc;SACzC,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,qCAAqC,WAAW,EAAE,CAAC,CAAC;IAChE,wBAAwB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC3D,OAAO,EAAE,CAAC;AACZ,CAAC"}
1
+ {"version":3,"file":"tmux-session.js","sourceRoot":"","sources":["../../../src/core/daemon/tmux-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAE7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EACL,aAAa,EACb,cAAc,EAEd,aAAa,EACb,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAoBpB;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAA4B;IAClE,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,aAAa,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAEjD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,IAAI,cAAkC,CAAC;QAEvC,IACE,KAAK,CAAC,oBAAoB;YAC1B,KAAK,CAAC,OAAO;YACb,4BAA4B,CAAC;gBAC3B,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,KAAK;gBACrC,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,WAAW,EAAE,KAAK,CAAC,WAAW;aAC/B,CAAC,EACF,CAAC;YACD,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAChD,cAAc,GAAG,YAAY,EAAE,MAAM,EAAE,iBAAuC,CAAC;YAC/E,IAAI,cAAc,EAAE,CAAC;gBACnB,OAAO,CAAC,GAAG,CAAC,8CAA8C,cAAc,EAAE,CAAC,CAAC;YAC9E,CAAC;QACH,CAAC;QAED,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAE7D,OAAO,CAAC,GAAG,CAAC,0BAA0B,WAAW,EAAE,CAAC,CAAC;QAErD,MAAM,OAAO,GAAG,aAAa,CAC3B,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,SAAS,EACf,cAAc,EACd,KAAK,CAAC,UAAU,CACjB,CAAC;QAEF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QAED,OAAO;YACL,iBAAiB;YACjB,wBAAwB,EAAE,cAAc;SACzC,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,qCAAqC,WAAW,EAAE,CAAC,CAAC;IAChE,wBAAwB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC3D,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * LLM-powered watcher loop.
3
+ *
4
+ * Two event sources feed the tick queue:
5
+ * 1. Scheduled ticker — every 2 min, full state fetch
6
+ * 2. WebSocket events — immediate reactive ticks (coalesced while LLM is busy)
7
+ *
8
+ * A consumer loop polls every 5s:
9
+ * - If LLM is processing → check tmux for completion
10
+ * - If idle and queue has items → dequeue, fetch state, inject into tmux
11
+ *
12
+ * Epic #883
13
+ */
14
+ import type { WatcherTickQueue } from "./watcher-queue.js";
15
+ import { type WatcherContext } from "./watcher-state.js";
16
+ export interface WatcherLoopHandle {
17
+ stop: () => void;
18
+ }
19
+ export declare function startWatcherLoop(ctx: WatcherContext, queue: WatcherTickQueue): WatcherLoopHandle;
20
+ /**
21
+ * Intercept WebSocket events relevant to the watcher and enqueue reactive ticks.
22
+ * Returns true if the event was consumed (watcher-relevant), false otherwise.
23
+ */
24
+ export declare function handleWatcherWebSocketEvent(event: {
25
+ type: string;
26
+ [key: string]: unknown;
27
+ }, queue: WatcherTickQueue): boolean;