@agentdeck/bridge 1.1.0 → 1.2.1

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 (199) hide show
  1. package/README.md +14 -6
  2. package/assets/fonts/NOTICE-PocketSansWorld.md +10 -0
  3. package/assets/fonts/OFL-PocketSansWorld.txt +93 -0
  4. package/assets/fonts/PocketSansWorld_12.cpfont +0 -0
  5. package/assets/fonts/pocket-sans-world.manifest.json +49 -0
  6. package/assets/learning/LICENSE-CC-BY-SA-4.0.txt +10 -0
  7. package/assets/learning/NOTICE.md +33 -0
  8. package/assets/learning/jp-n3-ko.manifest.json +27 -0
  9. package/assets/learning/jp-n3-ko.pdl +0 -0
  10. package/dist/agent-cli-diagnostics.d.ts +20 -0
  11. package/dist/agent-cli-diagnostics.d.ts.map +1 -0
  12. package/dist/agent-cli-diagnostics.js +100 -0
  13. package/dist/agent-cli-diagnostics.js.map +1 -0
  14. package/dist/apme/classifier.d.ts.map +1 -1
  15. package/dist/apme/classifier.js +18 -10
  16. package/dist/apme/classifier.js.map +1 -1
  17. package/dist/apme/claude-transcript-reader.d.ts +36 -0
  18. package/dist/apme/claude-transcript-reader.d.ts.map +1 -1
  19. package/dist/apme/claude-transcript-reader.js +78 -2
  20. package/dist/apme/claude-transcript-reader.js.map +1 -1
  21. package/dist/apme/collector.d.ts +126 -3
  22. package/dist/apme/collector.d.ts.map +1 -1
  23. package/dist/apme/collector.js +450 -41
  24. package/dist/apme/collector.js.map +1 -1
  25. package/dist/apme/dashboard-html.d.ts.map +1 -1
  26. package/dist/apme/dashboard-html.js +278 -36
  27. package/dist/apme/dashboard-html.js.map +1 -1
  28. package/dist/apme/graph.d.ts +1 -1
  29. package/dist/apme/graph.d.ts.map +1 -1
  30. package/dist/apme/graph.js +51 -1
  31. package/dist/apme/graph.js.map +1 -1
  32. package/dist/apme/http.d.ts.map +1 -1
  33. package/dist/apme/http.js +37 -5
  34. package/dist/apme/http.js.map +1 -1
  35. package/dist/apme/index.d.ts +4 -0
  36. package/dist/apme/index.d.ts.map +1 -1
  37. package/dist/apme/index.js +19 -3
  38. package/dist/apme/index.js.map +1 -1
  39. package/dist/apme/runner.d.ts +90 -0
  40. package/dist/apme/runner.d.ts.map +1 -1
  41. package/dist/apme/runner.js +524 -48
  42. package/dist/apme/runner.js.map +1 -1
  43. package/dist/apme/sample-to-timeline.d.ts.map +1 -1
  44. package/dist/apme/sample-to-timeline.js +5 -0
  45. package/dist/apme/sample-to-timeline.js.map +1 -1
  46. package/dist/apme/settings.d.ts +8 -0
  47. package/dist/apme/settings.d.ts.map +1 -1
  48. package/dist/apme/settings.js +4 -0
  49. package/dist/apme/settings.js.map +1 -1
  50. package/dist/apme/store.d.ts +118 -9
  51. package/dist/apme/store.d.ts.map +1 -1
  52. package/dist/apme/store.js +342 -44
  53. package/dist/apme/store.js.map +1 -1
  54. package/dist/apme/task-gradeability.d.ts +82 -0
  55. package/dist/apme/task-gradeability.d.ts.map +1 -0
  56. package/dist/apme/task-gradeability.js +126 -0
  57. package/dist/apme/task-gradeability.js.map +1 -0
  58. package/dist/awaiting-overlay.d.ts +13 -26
  59. package/dist/awaiting-overlay.d.ts.map +1 -1
  60. package/dist/awaiting-overlay.js +7 -40
  61. package/dist/awaiting-overlay.js.map +1 -1
  62. package/dist/bridge-core.d.ts +15 -0
  63. package/dist/bridge-core.d.ts.map +1 -1
  64. package/dist/bridge-core.js +30 -4
  65. package/dist/bridge-core.js.map +1 -1
  66. package/dist/claude-permission-rules.d.ts +20 -32
  67. package/dist/claude-permission-rules.d.ts.map +1 -1
  68. package/dist/claude-permission-rules.js +19 -102
  69. package/dist/claude-permission-rules.js.map +1 -1
  70. package/dist/claude-usage-recovery.d.ts +54 -0
  71. package/dist/claude-usage-recovery.d.ts.map +1 -0
  72. package/dist/claude-usage-recovery.js +200 -0
  73. package/dist/claude-usage-recovery.js.map +1 -0
  74. package/dist/cli.d.ts +11 -0
  75. package/dist/cli.d.ts.map +1 -1
  76. package/dist/cli.js +81 -14
  77. package/dist/cli.js.map +1 -1
  78. package/dist/codex-rate-limits-live.d.ts +180 -10
  79. package/dist/codex-rate-limits-live.d.ts.map +1 -1
  80. package/dist/codex-rate-limits-live.js +475 -22
  81. package/dist/codex-rate-limits-live.js.map +1 -1
  82. package/dist/codex-rollout-response.d.ts +43 -0
  83. package/dist/codex-rollout-response.d.ts.map +1 -1
  84. package/dist/codex-rollout-response.js +67 -0
  85. package/dist/codex-rollout-response.js.map +1 -1
  86. package/dist/coordination-evidence.d.ts +150 -0
  87. package/dist/coordination-evidence.d.ts.map +1 -0
  88. package/dist/coordination-evidence.js +455 -0
  89. package/dist/coordination-evidence.js.map +1 -0
  90. package/dist/daemon-server.d.ts.map +1 -1
  91. package/dist/daemon-server.js +592 -35
  92. package/dist/daemon-server.js.map +1 -1
  93. package/dist/daemon-ws-client.d.ts +1 -0
  94. package/dist/daemon-ws-client.d.ts.map +1 -1
  95. package/dist/daemon-ws-client.js +25 -16
  96. package/dist/daemon-ws-client.js.map +1 -1
  97. package/dist/daemon.js +1 -1
  98. package/dist/deferred-reply-read.d.ts +24 -0
  99. package/dist/deferred-reply-read.d.ts.map +1 -0
  100. package/dist/deferred-reply-read.js +42 -0
  101. package/dist/deferred-reply-read.js.map +1 -0
  102. package/dist/esp32-serial.d.ts +15 -0
  103. package/dist/esp32-serial.d.ts.map +1 -1
  104. package/dist/esp32-serial.js +61 -2
  105. package/dist/esp32-serial.js.map +1 -1
  106. package/dist/font-pack.d.ts +15 -0
  107. package/dist/font-pack.d.ts.map +1 -0
  108. package/dist/font-pack.js +75 -0
  109. package/dist/font-pack.js.map +1 -0
  110. package/dist/glance-frame.d.ts.map +1 -1
  111. package/dist/glance-frame.js +2 -0
  112. package/dist/glance-frame.js.map +1 -1
  113. package/dist/hook-codex-sessions.d.ts +9 -0
  114. package/dist/hook-codex-sessions.d.ts.map +1 -1
  115. package/dist/hook-codex-sessions.js +35 -2
  116. package/dist/hook-codex-sessions.js.map +1 -1
  117. package/dist/hook-opencode-sessions.d.ts +62 -0
  118. package/dist/hook-opencode-sessions.d.ts.map +1 -0
  119. package/dist/hook-opencode-sessions.js +180 -0
  120. package/dist/hook-opencode-sessions.js.map +1 -0
  121. package/dist/hook-response-source.d.ts +40 -0
  122. package/dist/hook-response-source.d.ts.map +1 -0
  123. package/dist/hook-response-source.js +31 -0
  124. package/dist/hook-response-source.js.map +1 -0
  125. package/dist/http-auth-gate.d.ts.map +1 -1
  126. package/dist/http-auth-gate.js +9 -1
  127. package/dist/http-auth-gate.js.map +1 -1
  128. package/dist/index.d.ts.map +1 -1
  129. package/dist/index.js +6 -3
  130. package/dist/index.js.map +1 -1
  131. package/dist/learning-pack.d.ts +24 -0
  132. package/dist/learning-pack.d.ts.map +1 -0
  133. package/dist/learning-pack.js +125 -0
  134. package/dist/learning-pack.js.map +1 -0
  135. package/dist/mdns.js +1 -1
  136. package/dist/mdns.js.map +1 -1
  137. package/dist/native-dependency-diagnostics.d.ts +29 -0
  138. package/dist/native-dependency-diagnostics.d.ts.map +1 -0
  139. package/dist/native-dependency-diagnostics.js +95 -0
  140. package/dist/native-dependency-diagnostics.js.map +1 -0
  141. package/dist/observed-steering.d.ts +4 -4
  142. package/dist/observed-steering.d.ts.map +1 -1
  143. package/dist/observed-steering.js +28 -32
  144. package/dist/observed-steering.js.map +1 -1
  145. package/dist/openclaw-gateway-stability.d.ts +94 -0
  146. package/dist/openclaw-gateway-stability.d.ts.map +1 -0
  147. package/dist/openclaw-gateway-stability.js +176 -0
  148. package/dist/openclaw-gateway-stability.js.map +1 -0
  149. package/dist/pairing-knocks.d.ts +80 -0
  150. package/dist/pairing-knocks.d.ts.map +1 -0
  151. package/dist/pairing-knocks.js +312 -0
  152. package/dist/pairing-knocks.js.map +1 -0
  153. package/dist/passive-observer.d.ts +5 -0
  154. package/dist/passive-observer.d.ts.map +1 -1
  155. package/dist/passive-observer.js +6 -0
  156. package/dist/passive-observer.js.map +1 -1
  157. package/dist/pixoo/micro-glyphs.d.ts +4 -0
  158. package/dist/pixoo/micro-glyphs.d.ts.map +1 -1
  159. package/dist/pixoo/micro-glyphs.js +29 -0
  160. package/dist/pixoo/micro-glyphs.js.map +1 -1
  161. package/dist/pixoo/pixoo-font.d.ts.map +1 -1
  162. package/dist/pixoo/pixoo-font.js +3 -1
  163. package/dist/pixoo/pixoo-font.js.map +1 -1
  164. package/dist/pixoo/pixoo-renderer.d.ts +1 -1
  165. package/dist/pixoo/pixoo-renderer.d.ts.map +1 -1
  166. package/dist/pixoo/pixoo-renderer.js +17 -2
  167. package/dist/pixoo/pixoo-renderer.js.map +1 -1
  168. package/dist/pty-manager.d.ts +9 -0
  169. package/dist/pty-manager.d.ts.map +1 -1
  170. package/dist/pty-manager.js +63 -4
  171. package/dist/pty-manager.js.map +1 -1
  172. package/dist/relayed-usage.d.ts +30 -0
  173. package/dist/relayed-usage.d.ts.map +1 -1
  174. package/dist/relayed-usage.js +25 -2
  175. package/dist/relayed-usage.js.map +1 -1
  176. package/dist/review-runner.js +1 -1
  177. package/dist/subagent-timeline.d.ts +27 -0
  178. package/dist/subagent-timeline.d.ts.map +1 -1
  179. package/dist/subagent-timeline.js +52 -5
  180. package/dist/subagent-timeline.js.map +1 -1
  181. package/dist/surface-protocol.d.ts.map +1 -1
  182. package/dist/surface-protocol.js +2 -0
  183. package/dist/surface-protocol.js.map +1 -1
  184. package/dist/tui/dashboard.d.ts.map +1 -1
  185. package/dist/tui/dashboard.js +8 -1
  186. package/dist/tui/dashboard.js.map +1 -1
  187. package/dist/usage-api.d.ts +3 -0
  188. package/dist/usage-api.d.ts.map +1 -1
  189. package/dist/usage-api.js +101 -36
  190. package/dist/usage-api.js.map +1 -1
  191. package/dist/usage-event.d.ts.map +1 -1
  192. package/dist/usage-event.js +2 -1
  193. package/dist/usage-event.js.map +1 -1
  194. package/dist/ws-server.d.ts +18 -0
  195. package/dist/ws-server.d.ts.map +1 -1
  196. package/dist/ws-server.js +40 -2
  197. package/dist/ws-server.js.map +1 -1
  198. package/package.json +6 -5
  199. package/src/timebox/sync_ble.py +35 -16
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Hook-derived OpenCode session rows for the Node daemon.
3
+ *
4
+ * The passive process scan lists a standalone `opencode` TUI as
5
+ * `observed:opencode:<pid>` — alive, always `idle`, project from the process
6
+ * cwd — because it can see nothing else. The AgentDeck observer plugin
7
+ * (hooks/src/opencode-install.ts) POSTs `opencode_*` lifecycle hooks keyed by
8
+ * OpenCode's own session id, and those carry everything the scan cannot: the
9
+ * turn (prompt/stop), the running tool, and — the reason this module exists —
10
+ * `permission.asked`, which OpenCode emits only when it is GENUINELY waiting
11
+ * for the user. Until 2026-09-05 the Node daemon classified those hooks for
12
+ * the timeline/APME and dropped them for session state, so an OpenCode
13
+ * session blocked on a permission read `idle` on every surface while the
14
+ * Swift daemon (which builds `opencode:<id>` rows from the same hooks)
15
+ * showed PERM with an answerable requestId.
16
+ *
17
+ * Mirror of the Swift daemon's `opencode_*` cases in `DaemonServer.swift`,
18
+ * shaped like `HookCodexSessions`: rows come and go with the hooks, and the
19
+ * PID row for the same working directory yields to the hook row so one TUI is
20
+ * never two creatures.
21
+ */
22
+ import type { ObservedSession } from './passive-observer.js';
23
+ export type HookOpenCodeState = 'idle' | 'processing' | 'awaiting_permission';
24
+ export interface HookOpenCodeSession {
25
+ sessionId: string;
26
+ projectName: string;
27
+ cwd?: string;
28
+ state: HookOpenCodeState;
29
+ currentTool?: string;
30
+ /** Permission prompt text while `awaiting_permission`. */
31
+ question?: string;
32
+ /** `ocperm:<sid>:<permissionId>` — the daemon's `permission_decision`
33
+ * route recognises this prefix and answers through the plugin queue. */
34
+ requestId?: string;
35
+ startedAt: number;
36
+ lastHookAt: number;
37
+ }
38
+ export interface HookOpenCodePayload {
39
+ sessionId?: string;
40
+ cwd?: string;
41
+ projectName?: string;
42
+ toolName?: string;
43
+ permissionId?: string;
44
+ title?: string;
45
+ }
46
+ export declare function openCodePermissionRequestId(sessionId: string, permissionId: string): string;
47
+ export declare class HookOpenCodeSessions {
48
+ private readonly sessions;
49
+ /** Fired when a hook changed something worth broadcasting. */
50
+ onChanged: (() => void) | undefined;
51
+ note(event: string, payload: HookOpenCodePayload, now?: number): boolean;
52
+ snapshot(): HookOpenCodeSession[];
53
+ private clearPermission;
54
+ private reap;
55
+ /**
56
+ * Merge hook rows into the observed list. A hook row wins over a PID row
57
+ * for the same working directory: the scan cannot tell which TUI is which,
58
+ * while the hook row knows its session, its turn and its prompt.
59
+ */
60
+ applyTo(observed: ObservedSession[], now?: number): ObservedSession[];
61
+ }
62
+ //# sourceMappingURL=hook-opencode-sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-opencode-sessions.d.ts","sourceRoot":"","sources":["../src/hook-opencode-sessions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAO7D,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,YAAY,GAAG,qBAAqB,CAAC;AAE9E,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,iBAAiB,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;6EACyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAE3F;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;IAEnE,8DAA8D;IAC9D,SAAS,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IAEpC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,SAAa,GAAG,OAAO;IA+E5E,QAAQ,IAAI,mBAAmB,EAAE;IAIjC,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,IAAI;IAMZ;;;;OAIG;IACH,OAAO,CAAC,QAAQ,EAAE,eAAe,EAAE,EAAE,GAAG,SAAa,GAAG,eAAe,EAAE;CA6C1E"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Hook-derived OpenCode session rows for the Node daemon.
3
+ *
4
+ * The passive process scan lists a standalone `opencode` TUI as
5
+ * `observed:opencode:<pid>` — alive, always `idle`, project from the process
6
+ * cwd — because it can see nothing else. The AgentDeck observer plugin
7
+ * (hooks/src/opencode-install.ts) POSTs `opencode_*` lifecycle hooks keyed by
8
+ * OpenCode's own session id, and those carry everything the scan cannot: the
9
+ * turn (prompt/stop), the running tool, and — the reason this module exists —
10
+ * `permission.asked`, which OpenCode emits only when it is GENUINELY waiting
11
+ * for the user. Until 2026-09-05 the Node daemon classified those hooks for
12
+ * the timeline/APME and dropped them for session state, so an OpenCode
13
+ * session blocked on a permission read `idle` on every surface while the
14
+ * Swift daemon (which builds `opencode:<id>` rows from the same hooks)
15
+ * showed PERM with an answerable requestId.
16
+ *
17
+ * Mirror of the Swift daemon's `opencode_*` cases in `DaemonServer.swift`,
18
+ * shaped like `HookCodexSessions`: rows come and go with the hooks, and the
19
+ * PID row for the same working directory yields to the hook row so one TUI is
20
+ * never two creatures.
21
+ */
22
+ import { resolveProjectNameFromCwdCached } from './utils/project-name.js';
23
+ /** A row with no hook at all for this long is gone (the plugin posts on every
24
+ * turn edge and tool, so an attended session refreshes constantly). */
25
+ const SILENT_TTL_MS = 30 * 60_000;
26
+ const OPENING_EVENTS = new Set([
27
+ 'opencode_session_start', 'opencode_user_prompt_submit', 'opencode_tool_start',
28
+ 'opencode_permission_asked',
29
+ ]);
30
+ export function openCodePermissionRequestId(sessionId, permissionId) {
31
+ return `ocperm:${sessionId}:${permissionId}`;
32
+ }
33
+ export class HookOpenCodeSessions {
34
+ sessions = new Map();
35
+ /** Fired when a hook changed something worth broadcasting. */
36
+ onChanged;
37
+ note(event, payload, now = Date.now()) {
38
+ const sessionId = payload.sessionId?.trim();
39
+ if (!sessionId || !event.startsWith('opencode_'))
40
+ return false;
41
+ if (event === 'opencode_session_end') {
42
+ const removed = this.sessions.delete(sessionId);
43
+ if (removed)
44
+ this.onChanged?.();
45
+ return removed;
46
+ }
47
+ const existing = this.sessions.get(sessionId);
48
+ if (!existing && !OPENING_EVENTS.has(event))
49
+ return false;
50
+ const session = existing ?? {
51
+ sessionId,
52
+ projectName: '',
53
+ state: 'idle',
54
+ startedAt: now,
55
+ lastHookAt: now,
56
+ };
57
+ const before = JSON.stringify(session);
58
+ session.lastHookAt = now;
59
+ if (!session.cwd && payload.cwd) {
60
+ session.cwd = payload.cwd;
61
+ session.projectName = resolveProjectNameFromCwdCached(payload.cwd);
62
+ }
63
+ if (!session.projectName && payload.projectName)
64
+ session.projectName = payload.projectName;
65
+ switch (event) {
66
+ case 'opencode_user_prompt_submit':
67
+ session.state = 'processing';
68
+ session.currentTool = undefined;
69
+ this.clearPermission(session);
70
+ break;
71
+ case 'opencode_tool_start':
72
+ session.state = 'processing';
73
+ session.currentTool = payload.toolName || undefined;
74
+ this.clearPermission(session);
75
+ break;
76
+ case 'opencode_tool_end':
77
+ session.state = 'processing';
78
+ session.currentTool = undefined;
79
+ this.clearPermission(session);
80
+ break;
81
+ case 'opencode_stop':
82
+ session.state = 'idle';
83
+ session.currentTool = undefined;
84
+ this.clearPermission(session);
85
+ break;
86
+ case 'opencode_permission_asked': {
87
+ // OpenCode fires this only when it is genuinely asking — a
88
+ // zero-false-positive gate signal, no prediction needed.
89
+ const permissionId = payload.permissionId?.trim();
90
+ if (permissionId) {
91
+ const title = (payload.title ?? '').replace(/\s+/g, ' ').trim();
92
+ session.state = 'awaiting_permission';
93
+ session.question = (title || 'Permission requested').slice(0, 120);
94
+ session.requestId = openCodePermissionRequestId(sessionId, permissionId);
95
+ }
96
+ break;
97
+ }
98
+ case 'opencode_permission_replied':
99
+ // Answered in the TUI or from a device — the tool now runs (or the
100
+ // turn ends); either way the wait is over.
101
+ if (session.state === 'awaiting_permission')
102
+ session.state = 'processing';
103
+ this.clearPermission(session);
104
+ break;
105
+ default:
106
+ break;
107
+ }
108
+ this.sessions.set(sessionId, session);
109
+ this.reap(now);
110
+ const changed = JSON.stringify(session) !== before || !existing;
111
+ if (changed)
112
+ this.onChanged?.();
113
+ return changed;
114
+ }
115
+ snapshot() {
116
+ return [...this.sessions.values()];
117
+ }
118
+ clearPermission(session) {
119
+ session.question = undefined;
120
+ session.requestId = undefined;
121
+ }
122
+ reap(now) {
123
+ for (const [sessionId, session] of this.sessions) {
124
+ if (now - session.lastHookAt > SILENT_TTL_MS)
125
+ this.sessions.delete(sessionId);
126
+ }
127
+ }
128
+ /**
129
+ * Merge hook rows into the observed list. A hook row wins over a PID row
130
+ * for the same working directory: the scan cannot tell which TUI is which,
131
+ * while the hook row knows its session, its turn and its prompt.
132
+ */
133
+ applyTo(observed, now = Date.now()) {
134
+ this.reap(now);
135
+ if (this.sessions.size === 0)
136
+ return observed;
137
+ const hookRows = [...this.sessions.values()];
138
+ const hookCwds = new Set(hookRows.map((s) => s.cwd).filter((c) => Boolean(c)));
139
+ const seen = new Set();
140
+ const kept = [];
141
+ for (const session of observed) {
142
+ const match = /^observed:opencode:(.+)$/.exec(session.id);
143
+ if (!match?.[1]) {
144
+ kept.push(session);
145
+ continue;
146
+ }
147
+ if (this.sessions.has(match[1])) {
148
+ seen.add(match[1]);
149
+ kept.push(session);
150
+ continue;
151
+ }
152
+ // A PID-keyed scan row in a directory a hook row already covers.
153
+ const isPidRow = /^\d+$/.test(match[1]);
154
+ if (isPidRow && session.cwd && hookCwds.has(session.cwd))
155
+ continue;
156
+ kept.push(session);
157
+ }
158
+ for (const session of hookRows) {
159
+ if (seen.has(session.sessionId))
160
+ continue;
161
+ kept.push({
162
+ id: `observed:opencode:${session.sessionId}`,
163
+ port: 0,
164
+ pid: 0,
165
+ projectName: session.projectName || (session.cwd ? resolveProjectNameFromCwdCached(session.cwd) : 'OpenCode'),
166
+ agentType: 'opencode',
167
+ alive: true,
168
+ state: session.state,
169
+ controlMode: 'observed',
170
+ cwd: session.cwd,
171
+ startedAt: new Date(session.startedAt).toISOString(),
172
+ currentTask: session.currentTool,
173
+ ...(session.question ? { question: session.question } : {}),
174
+ ...(session.requestId ? { requestId: session.requestId } : {}),
175
+ });
176
+ }
177
+ return kept;
178
+ }
179
+ }
180
+ //# sourceMappingURL=hook-opencode-sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-opencode-sessions.js","sourceRoot":"","sources":["../src/hook-opencode-sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Where a Stop hook's reply text comes from, decided per agent.
3
+ *
4
+ * Inline text wins wherever it exists — it is the hook's own statement of
5
+ * what the agent said. Otherwise each agent's OWN on-disk record is read by
6
+ * ITS reader: Claude's transcript JSONL by the Claude reader, Codex's rollout
7
+ * by the Codex reader. The old rule was "transcript_path ⇒ Claude reader",
8
+ * and a Codex hook carries a transcript_path too — its rollout — so every
9
+ * Codex turn read '' while `last_assistant_message` sat in the same payload.
10
+ * Measured 2026-09-03 over one week: 3 of 128 codex stop-turns held a
11
+ * response; the task judge scored the other tasks against silence.
12
+ *
13
+ * Pure so the decision table is testable without a daemon: the readers are
14
+ * injected, and only the one the agent owns is ever called.
15
+ */
16
+ import type { CodexTurnOutcome } from './codex-rollout-response.js';
17
+ export interface StopResponseReaders {
18
+ /** Claude transcript JSONL → last assistant text ('' when none). */
19
+ readClaudeTranscript: (transcriptPath: string) => string;
20
+ /** Codex rollout at a known path. */
21
+ readCodexRolloutPath: (rolloutPath: string) => CodexTurnOutcome;
22
+ /** Codex rollout located by session id (when the hook carried no path). */
23
+ readCodexRolloutById: (sessionId: string) => CodexTurnOutcome;
24
+ }
25
+ export interface StopResponseInput {
26
+ agentType: string;
27
+ sessionId: string;
28
+ /** Payload fields, in preference order, already reduced to the first
29
+ * non-empty string (`last_assistant_message` / `response` / …). */
30
+ inlineResponse: string;
31
+ transcriptPath: string;
32
+ }
33
+ export interface StopResponse {
34
+ /** Raw reply text before display sanitising; '' when nothing was found. */
35
+ text: string;
36
+ /** Codex's recorded failure for the turn, when its rollout was read. */
37
+ rollout: CodexTurnOutcome;
38
+ }
39
+ export declare function resolveStopResponse(input: StopResponseInput, readers: StopResponseReaders): StopResponse;
40
+ //# sourceMappingURL=hook-response-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-response-source.d.ts","sourceRoot":"","sources":["../src/hook-response-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAEpE,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,oBAAoB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,MAAM,CAAC;IACzD,qCAAqC;IACrC,oBAAoB,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,gBAAgB,CAAC;IAChE,2EAA2E;IAC3E,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,gBAAgB,CAAC;CAC/D;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB;wEACoE;IACpE,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAID,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAYxG"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Where a Stop hook's reply text comes from, decided per agent.
3
+ *
4
+ * Inline text wins wherever it exists — it is the hook's own statement of
5
+ * what the agent said. Otherwise each agent's OWN on-disk record is read by
6
+ * ITS reader: Claude's transcript JSONL by the Claude reader, Codex's rollout
7
+ * by the Codex reader. The old rule was "transcript_path ⇒ Claude reader",
8
+ * and a Codex hook carries a transcript_path too — its rollout — so every
9
+ * Codex turn read '' while `last_assistant_message` sat in the same payload.
10
+ * Measured 2026-09-03 over one week: 3 of 128 codex stop-turns held a
11
+ * response; the task judge scored the other tasks against silence.
12
+ *
13
+ * Pure so the decision table is testable without a daemon: the readers are
14
+ * injected, and only the one the agent owns is ever called.
15
+ */
16
+ const NO_OUTCOME = { text: '' };
17
+ export function resolveStopResponse(input, readers) {
18
+ if (input.inlineResponse)
19
+ return { text: input.inlineResponse, rollout: NO_OUTCOME };
20
+ if (input.agentType === 'codex-cli') {
21
+ const rollout = input.transcriptPath
22
+ ? readers.readCodexRolloutPath(input.transcriptPath)
23
+ : readers.readCodexRolloutById(input.sessionId);
24
+ return { text: rollout.text, rollout };
25
+ }
26
+ if (input.agentType === 'claude-code' && input.transcriptPath) {
27
+ return { text: readers.readClaudeTranscript(input.transcriptPath), rollout: NO_OUTCOME };
28
+ }
29
+ return { text: '', rollout: NO_OUTCOME };
30
+ }
31
+ //# sourceMappingURL=hook-response-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-response-source.js","sourceRoot":"","sources":["../src/hook-response-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA6BH,MAAM,UAAU,GAAqB,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AAElD,MAAM,UAAU,mBAAmB,CAAC,KAAwB,EAAE,OAA4B;IACxF,IAAI,KAAK,CAAC,cAAc;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,cAAc,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IACrF,IAAI,KAAK,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,KAAK,CAAC,cAAc;YAClC,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,KAAK,CAAC,cAAc,CAAC;YACpD,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAClD,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;IACzC,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,KAAK,aAAa,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QAC9D,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,oBAAoB,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IAC3F,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;AAC3C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"http-auth-gate.d.ts","sourceRoot":"","sources":["../src/http-auth-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAG5C,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,eAAe,GAAG,aAAa,GAAG,MAAM,CAAC;AAElF,8EAA8E;AAC9E,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,KAAK,GAAG,SAAS,CAAC,GAAG;IAAE,MAAM,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACrF,OAAO,CAiBT;AAED,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,OAAO,EACnB,iBAAiB,UAAQ,GACxB,gBAAgB,CAKlB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQvE"}
1
+ {"version":3,"file":"http-auth-gate.d.ts","sourceRoot":"","sources":["../src/http-auth-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAK5C,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,eAAe,GAAG,aAAa,GAAG,MAAM,CAAC;AAElF,8EAA8E;AAC9E,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,KAAK,GAAG,SAAS,CAAC,GAAG;IAAE,MAAM,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACrF,OAAO,CAwBT;AAED,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,OAAO,EACnB,iBAAiB,UAAQ,GACxB,gBAAgB,CAKlB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQvE"}
@@ -1,4 +1,6 @@
1
+ import { DEVICE_ID_HEADER } from '@agentdeck/shared';
1
2
  import { isLocalConnection, validateToken } from './auth.js';
3
+ import { deviceIdFromHeaders, isApprovedPeer } from './pairing-knocks.js';
2
4
  /** True when the request is same-machine or carries a valid pairing token. */
3
5
  export function isAuthorizedHttpRequest(req) {
4
6
  const ip = req.socket.remoteAddress ?? '';
@@ -17,7 +19,13 @@ export function isAuthorizedHttpRequest(req) {
17
19
  if (typeof auth === 'string' && auth.startsWith('Bearer ') && validateToken(auth.slice(7))) {
18
20
  return true;
19
21
  }
20
- return false;
22
+ // An operator-approved peer is authenticated; it simply carries its
23
+ // credential as a device id (or, for a client too old to send one, as its
24
+ // address) rather than as a token. Folded in here rather than passed to
25
+ // `gateHttpRequest` as a third parameter so that function stays the pure
26
+ // truth table its test drives — "authorized" is one input, however the peer
27
+ // earned it. Mirrors DaemonServer.httpAccessResponse on the Swift side.
28
+ return isApprovedPeer(ip, deviceIdFromHeaders(req.headers, DEVICE_ID_HEADER));
21
29
  }
22
30
  /** The redemption route. Only a route while an operator window is open. */
23
31
  export const PAIR_REDEEM_PATH = '/pair';
@@ -1 +1 @@
1
- {"version":3,"file":"http-auth-gate.js","sourceRoot":"","sources":["../src/http-auth-gate.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAI7D,8EAA8E;AAC9E,MAAM,UAAU,uBAAuB,CACrC,GAAsF;IAEtF,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC;IAC1C,IAAI,iBAAiB,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,kBAAkB,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,UAAU,IAAI,aAAa,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,kDAAkD;IACpD,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;IACvC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3F,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,2EAA2E;AAC3E,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAExC;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAc,EACd,QAAgB,EAChB,UAAmB,EACnB,iBAAiB,GAAG,KAAK;IAEzB,IAAI,UAAU;QAAE,OAAO,OAAO,CAAC;IAC/B,IAAI,MAAM,KAAK,KAAK,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,eAAe,CAAC;IACvE,IAAI,MAAM,KAAK,MAAM,IAAI,QAAQ,KAAK,gBAAgB,IAAI,iBAAiB;QAAE,OAAO,aAAa,CAAC;IAClG,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,QAAQ;QACd,IAAI;QACJ,iBAAiB,EAAE,IAAI;QACvB,YAAY,EAAE,IAAI;KACnB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"http-auth-gate.js","sourceRoot":"","sources":["../src/http-auth-gate.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1E,8EAA8E;AAC9E,MAAM,UAAU,uBAAuB,CACrC,GAAsF;IAEtF,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC;IAC1C,IAAI,iBAAiB,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,kBAAkB,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,UAAU,IAAI,aAAa,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,kDAAkD;IACpD,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;IACvC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3F,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oEAAoE;IACpE,0EAA0E;IAC1E,wEAAwE;IACxE,yEAAyE;IACzE,4EAA4E;IAC5E,wEAAwE;IACxE,OAAO,cAAc,CAAC,EAAE,EAAE,mBAAmB,CAAC,GAAG,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAChF,CAAC;AAED,2EAA2E;AAC3E,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAExC;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAc,EACd,QAAgB,EAChB,UAAmB,EACnB,iBAAiB,GAAG,KAAK;IAEzB,IAAI,UAAU;QAAE,OAAO,OAAO,CAAC;IAC/B,IAAI,MAAM,KAAK,KAAK,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,eAAe,CAAC;IACvE,IAAI,MAAM,KAAK,MAAM,IAAI,QAAQ,KAAK,gBAAgB,IAAI,iBAAiB;QAAE,OAAO,aAAa,CAAC;IAClG,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,QAAQ;QACd,IAAI;QACJ,iBAAiB,EAAE,IAAI;QACvB,YAAY,EAAE,IAAI;KACnB,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA4DH,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAUvE,OAAO,EAOL,KAAK,SAAS,EAQf,MAAM,YAAY,CAAC;AAwDpB,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,wEAAwE;IACxE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;kFAC8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;0EACsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;gEAC4D;IAC5D,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAID,wBAAsB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA6rCtE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA4DH,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAUvE,OAAO,EAOL,KAAK,SAAS,EAQf,MAAM,YAAY,CAAC;AAwDpB,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,wEAAwE;IACxE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;kFAC8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;0EACsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;gEAC4D;IAC5D,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAID,wBAAsB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAgsCtE"}
package/dist/index.js CHANGED
@@ -452,13 +452,16 @@ export async function startSession(opts) {
452
452
  adapter.on('event', (evt) => {
453
453
  if (evt.source !== 'hook')
454
454
  return;
455
- subagentTimeline.handle({
455
+ const result = subagentTimeline.handle({
456
456
  eventName: evt.event,
457
457
  payload: evt.data ?? {},
458
458
  sessionId: core.sessionId,
459
459
  agentType,
460
460
  projectName: core.projectName,
461
461
  });
462
+ if (result.sampleEvent) {
463
+ apme?.collector.noteSubagentLifecycle(core.sessionId, result.sampleEvent);
464
+ }
462
465
  });
463
466
  // Claude Code hook events → timeline entries
464
467
  if (agentType === 'claude-code') {
@@ -498,12 +501,12 @@ export async function startSession(opts) {
498
501
  const hookSilence = new CodexHookSilenceWarning({
499
502
  onSilent: () => {
500
503
  log('WARNING: no Codex lifecycle event has reached this bridge — state/timeline/eval are blind for this session.');
501
- log('Repair: rerun `agentdeck codex` (reinstalls hooks) or `agentdeck daemon install`, and check [hooks]/notify in ~/.codex/config.toml.');
504
+ log('Repair: run `agentdeck daemon install`, then check [hooks]/notify in ~/.codex/config.toml.');
502
505
  core.bridgeTimeline.addEntry({
503
506
  ts: Date.now(),
504
507
  type: 'error',
505
508
  raw: 'Codex lifecycle hooks silent — session is lifecycle-blind',
506
- detail: 'The terminal is active but no codex_* hook or notify event arrived. Hooks and the notify fallback share one curl/port path in ~/.codex/config.toml, so a stale port or config-layer conflict kills both. Rerun `agentdeck codex` or `agentdeck daemon install` to repair.',
509
+ detail: 'The terminal is active but no codex_* hook or notify event arrived. Hooks and the notify fallback share one curl/port path in ~/.codex/config.toml, so a stale port or config-layer conflict kills both. Run `agentdeck daemon install` to repair.',
507
510
  agentType: 'codex-cli',
508
511
  });
509
512
  },