flaio-cli 0.3.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 (271) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +461 -0
  3. package/dist/agents/agent-detector.d.ts +21 -0
  4. package/dist/agents/agent-detector.d.ts.map +1 -0
  5. package/dist/agents/agent-detector.js +109 -0
  6. package/dist/agents/agent-detector.js.map +1 -0
  7. package/dist/agents/agent-registry.d.ts +6 -0
  8. package/dist/agents/agent-registry.d.ts.map +1 -0
  9. package/dist/agents/agent-registry.js +25 -0
  10. package/dist/agents/agent-registry.js.map +1 -0
  11. package/dist/agents/agent-session.d.ts +60 -0
  12. package/dist/agents/agent-session.d.ts.map +1 -0
  13. package/dist/agents/agent-session.js +251 -0
  14. package/dist/agents/agent-session.js.map +1 -0
  15. package/dist/agents/drivers/base-driver.d.ts +37 -0
  16. package/dist/agents/drivers/base-driver.d.ts.map +1 -0
  17. package/dist/agents/drivers/base-driver.js +18 -0
  18. package/dist/agents/drivers/base-driver.js.map +1 -0
  19. package/dist/agents/drivers/claude-driver.d.ts +23 -0
  20. package/dist/agents/drivers/claude-driver.d.ts.map +1 -0
  21. package/dist/agents/drivers/claude-driver.js +61 -0
  22. package/dist/agents/drivers/claude-driver.js.map +1 -0
  23. package/dist/agents/drivers/gemini-driver.d.ts +23 -0
  24. package/dist/agents/drivers/gemini-driver.d.ts.map +1 -0
  25. package/dist/agents/drivers/gemini-driver.js +60 -0
  26. package/dist/agents/drivers/gemini-driver.js.map +1 -0
  27. package/dist/agents/session-metadata.d.ts +33 -0
  28. package/dist/agents/session-metadata.d.ts.map +1 -0
  29. package/dist/agents/session-metadata.js +34 -0
  30. package/dist/agents/session-metadata.js.map +1 -0
  31. package/dist/agents/sideband/hook-scripts.d.ts +29 -0
  32. package/dist/agents/sideband/hook-scripts.d.ts.map +1 -0
  33. package/dist/agents/sideband/hook-scripts.js +259 -0
  34. package/dist/agents/sideband/hook-scripts.js.map +1 -0
  35. package/dist/agents/sideband/sideband-receiver.d.ts +37 -0
  36. package/dist/agents/sideband/sideband-receiver.d.ts.map +1 -0
  37. package/dist/agents/sideband/sideband-receiver.js +203 -0
  38. package/dist/agents/sideband/sideband-receiver.js.map +1 -0
  39. package/dist/agents/sideband/status-resolver.d.ts +55 -0
  40. package/dist/agents/sideband/status-resolver.d.ts.map +1 -0
  41. package/dist/agents/sideband/status-resolver.js +194 -0
  42. package/dist/agents/sideband/status-resolver.js.map +1 -0
  43. package/dist/app.d.ts +3 -0
  44. package/dist/app.d.ts.map +1 -0
  45. package/dist/app.js +94 -0
  46. package/dist/app.js.map +1 -0
  47. package/dist/cli.d.ts +3 -0
  48. package/dist/cli.d.ts.map +1 -0
  49. package/dist/cli.js +188 -0
  50. package/dist/cli.js.map +1 -0
  51. package/dist/config/config.d.ts +341 -0
  52. package/dist/config/config.d.ts.map +1 -0
  53. package/dist/config/config.js +94 -0
  54. package/dist/config/config.js.map +1 -0
  55. package/dist/config/defaults.d.ts +33 -0
  56. package/dist/config/defaults.d.ts.map +1 -0
  57. package/dist/config/defaults.js +33 -0
  58. package/dist/config/defaults.js.map +1 -0
  59. package/dist/connectors/adapters/discord-adapter.d.ts +25 -0
  60. package/dist/connectors/adapters/discord-adapter.d.ts.map +1 -0
  61. package/dist/connectors/adapters/discord-adapter.js +154 -0
  62. package/dist/connectors/adapters/discord-adapter.js.map +1 -0
  63. package/dist/connectors/adapters/slack-adapter.d.ts +38 -0
  64. package/dist/connectors/adapters/slack-adapter.d.ts.map +1 -0
  65. package/dist/connectors/adapters/slack-adapter.js +502 -0
  66. package/dist/connectors/adapters/slack-adapter.js.map +1 -0
  67. package/dist/connectors/adapters/telegram-adapter.d.ts +25 -0
  68. package/dist/connectors/adapters/telegram-adapter.d.ts.map +1 -0
  69. package/dist/connectors/adapters/telegram-adapter.js +164 -0
  70. package/dist/connectors/adapters/telegram-adapter.js.map +1 -0
  71. package/dist/connectors/connector-interface.d.ts +41 -0
  72. package/dist/connectors/connector-interface.d.ts.map +1 -0
  73. package/dist/connectors/connector-interface.js +2 -0
  74. package/dist/connectors/connector-interface.js.map +1 -0
  75. package/dist/connectors/connector-manager.d.ts +24 -0
  76. package/dist/connectors/connector-manager.d.ts.map +1 -0
  77. package/dist/connectors/connector-manager.js +82 -0
  78. package/dist/connectors/connector-manager.js.map +1 -0
  79. package/dist/connectors/debug.d.ts +3 -0
  80. package/dist/connectors/debug.d.ts.map +1 -0
  81. package/dist/connectors/debug.js +16 -0
  82. package/dist/connectors/debug.js.map +1 -0
  83. package/dist/hooks/hook-server.d.ts +27 -0
  84. package/dist/hooks/hook-server.d.ts.map +1 -0
  85. package/dist/hooks/hook-server.js +149 -0
  86. package/dist/hooks/hook-server.js.map +1 -0
  87. package/dist/hooks/hook.d.ts +10 -0
  88. package/dist/hooks/hook.d.ts.map +1 -0
  89. package/dist/hooks/hook.js +58 -0
  90. package/dist/hooks/hook.js.map +1 -0
  91. package/dist/hooks/install.d.ts +8 -0
  92. package/dist/hooks/install.d.ts.map +1 -0
  93. package/dist/hooks/install.js +160 -0
  94. package/dist/hooks/install.js.map +1 -0
  95. package/dist/hooks/notification-hook.d.ts +9 -0
  96. package/dist/hooks/notification-hook.d.ts.map +1 -0
  97. package/dist/hooks/notification-hook.js +38 -0
  98. package/dist/hooks/notification-hook.js.map +1 -0
  99. package/dist/hooks/post-tool-hook.d.ts +9 -0
  100. package/dist/hooks/post-tool-hook.d.ts.map +1 -0
  101. package/dist/hooks/post-tool-hook.js +39 -0
  102. package/dist/hooks/post-tool-hook.js.map +1 -0
  103. package/dist/hooks/stop-hook.d.ts +9 -0
  104. package/dist/hooks/stop-hook.d.ts.map +1 -0
  105. package/dist/hooks/stop-hook.js +37 -0
  106. package/dist/hooks/stop-hook.js.map +1 -0
  107. package/dist/portal/ansi-renderer.d.ts +15 -0
  108. package/dist/portal/ansi-renderer.d.ts.map +1 -0
  109. package/dist/portal/ansi-renderer.js +75 -0
  110. package/dist/portal/ansi-renderer.js.map +1 -0
  111. package/dist/portal/portal-client.d.ts +18 -0
  112. package/dist/portal/portal-client.d.ts.map +1 -0
  113. package/dist/portal/portal-client.js +335 -0
  114. package/dist/portal/portal-client.js.map +1 -0
  115. package/dist/portal/portal-picker.d.ts +8 -0
  116. package/dist/portal/portal-picker.d.ts.map +1 -0
  117. package/dist/portal/portal-picker.js +145 -0
  118. package/dist/portal/portal-picker.js.map +1 -0
  119. package/dist/portal/portal-server.d.ts +24 -0
  120. package/dist/portal/portal-server.d.ts.map +1 -0
  121. package/dist/portal/portal-server.js +330 -0
  122. package/dist/portal/portal-server.js.map +1 -0
  123. package/dist/portal/shared.d.ts +79 -0
  124. package/dist/portal/shared.d.ts.map +1 -0
  125. package/dist/portal/shared.js +5 -0
  126. package/dist/portal/shared.js.map +1 -0
  127. package/dist/relay/rate-limiter.d.ts +16 -0
  128. package/dist/relay/rate-limiter.d.ts.map +1 -0
  129. package/dist/relay/rate-limiter.js +37 -0
  130. package/dist/relay/rate-limiter.js.map +1 -0
  131. package/dist/relay/relay-auth.d.ts +29 -0
  132. package/dist/relay/relay-auth.d.ts.map +1 -0
  133. package/dist/relay/relay-auth.js +129 -0
  134. package/dist/relay/relay-auth.js.map +1 -0
  135. package/dist/relay/relay-client.d.ts +52 -0
  136. package/dist/relay/relay-client.d.ts.map +1 -0
  137. package/dist/relay/relay-client.js +1102 -0
  138. package/dist/relay/relay-client.js.map +1 -0
  139. package/dist/relay/relay-crypto.d.ts +29 -0
  140. package/dist/relay/relay-crypto.d.ts.map +1 -0
  141. package/dist/relay/relay-crypto.js +100 -0
  142. package/dist/relay/relay-crypto.js.map +1 -0
  143. package/dist/relay/relay-message-schemas.d.ts +276 -0
  144. package/dist/relay/relay-message-schemas.d.ts.map +1 -0
  145. package/dist/relay/relay-message-schemas.js +137 -0
  146. package/dist/relay/relay-message-schemas.js.map +1 -0
  147. package/dist/relay/relay-protocol.d.ts +444 -0
  148. package/dist/relay/relay-protocol.d.ts.map +1 -0
  149. package/dist/relay/relay-protocol.js +15 -0
  150. package/dist/relay/relay-protocol.js.map +1 -0
  151. package/dist/relay/relay-store.d.ts +23 -0
  152. package/dist/relay/relay-store.d.ts.map +1 -0
  153. package/dist/relay/relay-store.js +54 -0
  154. package/dist/relay/relay-store.js.map +1 -0
  155. package/dist/relay/ticket-tracker.d.ts +18 -0
  156. package/dist/relay/ticket-tracker.d.ts.map +1 -0
  157. package/dist/relay/ticket-tracker.js +58 -0
  158. package/dist/relay/ticket-tracker.js.map +1 -0
  159. package/dist/store/app-store.d.ts +66 -0
  160. package/dist/store/app-store.d.ts.map +1 -0
  161. package/dist/store/app-store.js +227 -0
  162. package/dist/store/app-store.js.map +1 -0
  163. package/dist/store/connector-store.d.ts +21 -0
  164. package/dist/store/connector-store.d.ts.map +1 -0
  165. package/dist/store/connector-store.js +591 -0
  166. package/dist/store/connector-store.js.map +1 -0
  167. package/dist/store/portal-store.d.ts +5 -0
  168. package/dist/store/portal-store.d.ts.map +1 -0
  169. package/dist/store/portal-store.js +5 -0
  170. package/dist/store/portal-store.js.map +1 -0
  171. package/dist/store/settings-store.d.ts +13 -0
  172. package/dist/store/settings-store.d.ts.map +1 -0
  173. package/dist/store/settings-store.js +59 -0
  174. package/dist/store/settings-store.js.map +1 -0
  175. package/dist/terminal/pty-manager.d.ts +19 -0
  176. package/dist/terminal/pty-manager.d.ts.map +1 -0
  177. package/dist/terminal/pty-manager.js +58 -0
  178. package/dist/terminal/pty-manager.js.map +1 -0
  179. package/dist/terminal/screen-buffer.d.ts +36 -0
  180. package/dist/terminal/screen-buffer.d.ts.map +1 -0
  181. package/dist/terminal/screen-buffer.js +109 -0
  182. package/dist/terminal/screen-buffer.js.map +1 -0
  183. package/dist/terminal/xterm-bridge.d.ts +32 -0
  184. package/dist/terminal/xterm-bridge.d.ts.map +1 -0
  185. package/dist/terminal/xterm-bridge.js +168 -0
  186. package/dist/terminal/xterm-bridge.js.map +1 -0
  187. package/dist/ui/components/adopt-agent-dialog.d.ts +10 -0
  188. package/dist/ui/components/adopt-agent-dialog.d.ts.map +1 -0
  189. package/dist/ui/components/adopt-agent-dialog.js +31 -0
  190. package/dist/ui/components/adopt-agent-dialog.js.map +1 -0
  191. package/dist/ui/components/agent-tab.d.ts +17 -0
  192. package/dist/ui/components/agent-tab.d.ts.map +1 -0
  193. package/dist/ui/components/agent-tab.js +33 -0
  194. package/dist/ui/components/agent-tab.js.map +1 -0
  195. package/dist/ui/components/agents-settings-content.d.ts +7 -0
  196. package/dist/ui/components/agents-settings-content.d.ts.map +1 -0
  197. package/dist/ui/components/agents-settings-content.js +238 -0
  198. package/dist/ui/components/agents-settings-content.js.map +1 -0
  199. package/dist/ui/components/help-modal.d.ts +7 -0
  200. package/dist/ui/components/help-modal.d.ts.map +1 -0
  201. package/dist/ui/components/help-modal.js +29 -0
  202. package/dist/ui/components/help-modal.js.map +1 -0
  203. package/dist/ui/components/new-session-dialog.d.ts +8 -0
  204. package/dist/ui/components/new-session-dialog.d.ts.map +1 -0
  205. package/dist/ui/components/new-session-dialog.js +84 -0
  206. package/dist/ui/components/new-session-dialog.js.map +1 -0
  207. package/dist/ui/components/path-input.d.ts +8 -0
  208. package/dist/ui/components/path-input.d.ts.map +1 -0
  209. package/dist/ui/components/path-input.js +151 -0
  210. package/dist/ui/components/path-input.js.map +1 -0
  211. package/dist/ui/components/settings-panel.d.ts +7 -0
  212. package/dist/ui/components/settings-panel.d.ts.map +1 -0
  213. package/dist/ui/components/settings-panel.js +134 -0
  214. package/dist/ui/components/settings-panel.js.map +1 -0
  215. package/dist/ui/components/standalone-agents.d.ts +9 -0
  216. package/dist/ui/components/standalone-agents.d.ts.map +1 -0
  217. package/dist/ui/components/standalone-agents.js +28 -0
  218. package/dist/ui/components/standalone-agents.js.map +1 -0
  219. package/dist/ui/components/terminal-view.d.ts +12 -0
  220. package/dist/ui/components/terminal-view.d.ts.map +1 -0
  221. package/dist/ui/components/terminal-view.js +53 -0
  222. package/dist/ui/components/terminal-view.js.map +1 -0
  223. package/dist/ui/components/viewer-approval-dialog.d.ts +9 -0
  224. package/dist/ui/components/viewer-approval-dialog.d.ts.map +1 -0
  225. package/dist/ui/components/viewer-approval-dialog.js +38 -0
  226. package/dist/ui/components/viewer-approval-dialog.js.map +1 -0
  227. package/dist/ui/hooks/use-git-info.d.ts +8 -0
  228. package/dist/ui/hooks/use-git-info.d.ts.map +1 -0
  229. package/dist/ui/hooks/use-git-info.js +72 -0
  230. package/dist/ui/hooks/use-git-info.js.map +1 -0
  231. package/dist/ui/hooks/use-keybindings.d.ts +10 -0
  232. package/dist/ui/hooks/use-keybindings.d.ts.map +1 -0
  233. package/dist/ui/hooks/use-keybindings.js +91 -0
  234. package/dist/ui/hooks/use-keybindings.js.map +1 -0
  235. package/dist/ui/hooks/use-portal-connected.d.ts +2 -0
  236. package/dist/ui/hooks/use-portal-connected.d.ts.map +1 -0
  237. package/dist/ui/hooks/use-portal-connected.js +10 -0
  238. package/dist/ui/hooks/use-portal-connected.js.map +1 -0
  239. package/dist/ui/hooks/use-raw-input.d.ts +8 -0
  240. package/dist/ui/hooks/use-raw-input.d.ts.map +1 -0
  241. package/dist/ui/hooks/use-raw-input.js +106 -0
  242. package/dist/ui/hooks/use-raw-input.js.map +1 -0
  243. package/dist/ui/hooks/use-spinner.d.ts +2 -0
  244. package/dist/ui/hooks/use-spinner.d.ts.map +1 -0
  245. package/dist/ui/hooks/use-spinner.js +13 -0
  246. package/dist/ui/hooks/use-spinner.js.map +1 -0
  247. package/dist/ui/hooks/use-terminal-size.d.ts +5 -0
  248. package/dist/ui/hooks/use-terminal-size.d.ts.map +1 -0
  249. package/dist/ui/hooks/use-terminal-size.js +22 -0
  250. package/dist/ui/hooks/use-terminal-size.js.map +1 -0
  251. package/dist/ui/hooks/use-update-check.d.ts +6 -0
  252. package/dist/ui/hooks/use-update-check.d.ts.map +1 -0
  253. package/dist/ui/hooks/use-update-check.js +62 -0
  254. package/dist/ui/hooks/use-update-check.js.map +1 -0
  255. package/dist/ui/layout/main-pane.d.ts +13 -0
  256. package/dist/ui/layout/main-pane.d.ts.map +1 -0
  257. package/dist/ui/layout/main-pane.js +36 -0
  258. package/dist/ui/layout/main-pane.js.map +1 -0
  259. package/dist/ui/layout/shell.d.ts +17 -0
  260. package/dist/ui/layout/shell.d.ts.map +1 -0
  261. package/dist/ui/layout/shell.js +24 -0
  262. package/dist/ui/layout/shell.js.map +1 -0
  263. package/dist/ui/layout/sidebar.d.ts +12 -0
  264. package/dist/ui/layout/sidebar.d.ts.map +1 -0
  265. package/dist/ui/layout/sidebar.js +9 -0
  266. package/dist/ui/layout/sidebar.js.map +1 -0
  267. package/dist/ui/layout/status-bar.d.ts +9 -0
  268. package/dist/ui/layout/status-bar.d.ts.map +1 -0
  269. package/dist/ui/layout/status-bar.js +138 -0
  270. package/dist/ui/layout/status-bar.js.map +1 -0
  271. package/package.json +70 -0
@@ -0,0 +1,34 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Per-session metadata store (cost, tokens, model, context window)
3
+ // ---------------------------------------------------------------------------
4
+ import { EventEmitter } from "node:events";
5
+ /**
6
+ * Singleton metadata store — keyed by flaio session ID.
7
+ * Emits `"update"` with (sessionId, metadata) on every change.
8
+ */
9
+ class SessionMetadataStore extends EventEmitter {
10
+ data = new Map();
11
+ get(sessionId) {
12
+ return this.data.get(sessionId);
13
+ }
14
+ update(sessionId, partial) {
15
+ const existing = this.data.get(sessionId) ?? {};
16
+ const merged = {
17
+ ...existing,
18
+ ...partial,
19
+ contextWindow: partial.contextWindow
20
+ ? { ...existing.contextWindow, ...partial.contextWindow }
21
+ : existing.contextWindow,
22
+ };
23
+ this.data.set(sessionId, merged);
24
+ this.emit("update", sessionId, merged);
25
+ }
26
+ remove(sessionId) {
27
+ this.data.delete(sessionId);
28
+ }
29
+ clear() {
30
+ this.data.clear();
31
+ }
32
+ }
33
+ export const sessionMetadataStore = new SessionMetadataStore();
34
+ //# sourceMappingURL=session-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-metadata.js","sourceRoot":"","sources":["../../src/agents/session-metadata.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,mEAAmE;AACnE,8EAA8E;AAE9E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAqB3C;;;GAGG;AACH,MAAM,oBAAqB,SAAQ,YAAY;IACrC,IAAI,GAAG,IAAI,GAAG,EAA2B,CAAC;IAElD,GAAG,CAAC,SAAiB;QACnB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,CAAC,SAAiB,EAAE,OAAiC;QACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAChD,MAAM,MAAM,GAAoB;YAC9B,GAAG,QAAQ;YACX,GAAG,OAAO;YACV,aAAa,EAAE,OAAO,CAAC,aAAa;gBAClC,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC,aAAa,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE;gBACzD,CAAC,CAAC,QAAQ,CAAC,aAAa;SAC3B,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,CAAC,SAAiB;QACtB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,oBAAoB,EAAE,CAAC"}
@@ -0,0 +1,29 @@
1
+ export declare function installHookScripts(): Promise<{
2
+ hookPath: string;
3
+ statusLinePath: string;
4
+ }>;
5
+ /**
6
+ * Returns the hooks configuration object to merge into ~/.claude/settings.json.
7
+ * Claude Code hook format:
8
+ * { "PreToolUse": [{ "matcher": "", "hooks": [{ "type": "command", "command": "..." }] }] }
9
+ * matcher is a regex string — "" or omitted matches all occurrences.
10
+ * Some events (Stop) don't support matchers — omit matcher for those.
11
+ */
12
+ export declare function getClaudeHooksConfig(hookPath: string): Record<string, unknown>;
13
+ /**
14
+ * Returns the status line configuration for ~/.claude/settings.json.
15
+ * See: https://code.claude.com/docs/en/statusline
16
+ */
17
+ export declare function getClaudeStatusLineConfig(statusLinePath: string): Record<string, unknown>;
18
+ /**
19
+ * Returns hooks config to merge into ~/.gemini/settings.json.
20
+ */
21
+ export declare function getGeminiHooksConfig(hookPath: string): Record<string, unknown>;
22
+ /**
23
+ * Reads a JSON settings file, deep-merges the patch, and writes it back.
24
+ * For hook arrays, appends our hook if not already present (preserves user hooks).
25
+ */
26
+ export declare function mergeSettingsFile(filePath: string, patch: Record<string, unknown>): Promise<void>;
27
+ export declare function areClaudeHooksConfigured(): Promise<boolean>;
28
+ export declare function areGeminiHooksConfigured(): Promise<boolean>;
29
+ //# sourceMappingURL=hook-scripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-scripts.d.ts","sourceRoot":"","sources":["../../../src/agents/sideband/hook-scripts.ts"],"names":[],"mappings":"AA0CA,wBAAsB,kBAAkB,IAAI,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC,CAUhG;AAuBD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoB9E;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOzF;AAeD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAW9E;AAMD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC,CAcf;AAuED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,OAAO,CAAC,CA4BjE;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,OAAO,CAAC,CAkBjE"}
@@ -0,0 +1,259 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Hook script installer + settings merger for Claude Code and Gemini CLI
3
+ // ---------------------------------------------------------------------------
4
+ import fs from "node:fs/promises";
5
+ import path from "node:path";
6
+ import os from "node:os";
7
+ const HOOK_DIR = path.join(os.homedir(), ".config", "flaio", "hooks");
8
+ // ---------------------------------------------------------------------------
9
+ // Hook script content
10
+ // ---------------------------------------------------------------------------
11
+ /**
12
+ * Shell script that appends hook JSON from stdin to the sideband events file.
13
+ * No-op when FLAIO_SIDEBAND_DIR is not set (safe for normal CLI usage).
14
+ */
15
+ const RELAY_HOOK_SH = `#!/bin/sh
16
+ # Support both new and legacy env var names
17
+ dir="\${FLAIO_SIDEBAND_DIR:-$CODE_RELAY_SIDEBAND_DIR}"
18
+ [ -z "$dir" ] && exit 0
19
+ cat >> "$dir/events.jsonl"
20
+ printf '\\n' >> "$dir/events.jsonl"
21
+ `;
22
+ /**
23
+ * Shell script for Claude Code status line. Reads JSON from stdin,
24
+ * writes to metadata.json, then outputs a formatted display string.
25
+ */
26
+ const RELAY_STATUSLINE_SH = `#!/bin/sh
27
+ # Support both new and legacy env var names
28
+ dir="\${FLAIO_SIDEBAND_DIR:-$CODE_RELAY_SIDEBAND_DIR}"
29
+ [ -z "$dir" ] && exit 0
30
+ input=$(cat)
31
+ printf '%s' "$input" > "$dir/metadata.json"
32
+ `;
33
+ // ---------------------------------------------------------------------------
34
+ // Install scripts to disk
35
+ // ---------------------------------------------------------------------------
36
+ export async function installHookScripts() {
37
+ await fs.mkdir(HOOK_DIR, { recursive: true });
38
+ const hookPath = path.join(HOOK_DIR, "relay-hook.sh");
39
+ const statusLinePath = path.join(HOOK_DIR, "relay-statusline.sh");
40
+ await fs.writeFile(hookPath, RELAY_HOOK_SH, { mode: 0o755 });
41
+ await fs.writeFile(statusLinePath, RELAY_STATUSLINE_SH, { mode: 0o755 });
42
+ return { hookPath, statusLinePath };
43
+ }
44
+ // ---------------------------------------------------------------------------
45
+ // Claude Code settings hooks config
46
+ // ---------------------------------------------------------------------------
47
+ /** All Claude Code hook event names we want to intercept. */
48
+ const CLAUDE_HOOK_EVENTS = [
49
+ "SessionStart",
50
+ "UserPromptSubmit",
51
+ "PreToolUse",
52
+ "PermissionRequest",
53
+ "PostToolUse",
54
+ "PostToolUseFailure",
55
+ "Notification",
56
+ "SubagentStart",
57
+ "SubagentStop",
58
+ "Stop",
59
+ "TaskCompleted",
60
+ "PreCompact",
61
+ "SessionEnd",
62
+ ];
63
+ /**
64
+ * Returns the hooks configuration object to merge into ~/.claude/settings.json.
65
+ * Claude Code hook format:
66
+ * { "PreToolUse": [{ "matcher": "", "hooks": [{ "type": "command", "command": "..." }] }] }
67
+ * matcher is a regex string — "" or omitted matches all occurrences.
68
+ * Some events (Stop) don't support matchers — omit matcher for those.
69
+ */
70
+ export function getClaudeHooksConfig(hookPath) {
71
+ // Events that don't support matchers — always fire on every occurrence
72
+ const NO_MATCHER_EVENTS = new Set(["UserPromptSubmit", "Stop", "TaskCompleted"]);
73
+ const hooks = {};
74
+ for (const event of CLAUDE_HOOK_EVENTS) {
75
+ const entry = {
76
+ hooks: [
77
+ {
78
+ type: "command",
79
+ command: hookPath,
80
+ },
81
+ ],
82
+ };
83
+ if (!NO_MATCHER_EVENTS.has(event)) {
84
+ entry.matcher = "";
85
+ }
86
+ hooks[event] = [entry];
87
+ }
88
+ return { hooks };
89
+ }
90
+ /**
91
+ * Returns the status line configuration for ~/.claude/settings.json.
92
+ * See: https://code.claude.com/docs/en/statusline
93
+ */
94
+ export function getClaudeStatusLineConfig(statusLinePath) {
95
+ return {
96
+ statusLine: {
97
+ type: "command",
98
+ command: statusLinePath,
99
+ },
100
+ };
101
+ }
102
+ // ---------------------------------------------------------------------------
103
+ // Gemini CLI settings hooks config
104
+ // ---------------------------------------------------------------------------
105
+ const GEMINI_HOOK_EVENTS = [
106
+ "BeforeTool",
107
+ "AfterTool",
108
+ "BeforeAgent",
109
+ "AfterAgent",
110
+ "SessionStart",
111
+ "SessionEnd",
112
+ ];
113
+ /**
114
+ * Returns hooks config to merge into ~/.gemini/settings.json.
115
+ */
116
+ export function getGeminiHooksConfig(hookPath) {
117
+ const hooks = {};
118
+ for (const event of GEMINI_HOOK_EVENTS) {
119
+ hooks[event] = [
120
+ {
121
+ type: "command",
122
+ command: hookPath,
123
+ },
124
+ ];
125
+ }
126
+ return { hooks };
127
+ }
128
+ // ---------------------------------------------------------------------------
129
+ // Settings file merger
130
+ // ---------------------------------------------------------------------------
131
+ /**
132
+ * Reads a JSON settings file, deep-merges the patch, and writes it back.
133
+ * For hook arrays, appends our hook if not already present (preserves user hooks).
134
+ */
135
+ export async function mergeSettingsFile(filePath, patch) {
136
+ let existing = {};
137
+ try {
138
+ const text = await fs.readFile(filePath, "utf-8");
139
+ existing = JSON.parse(text);
140
+ }
141
+ catch {
142
+ // File doesn't exist or invalid JSON — start fresh
143
+ }
144
+ const merged = deepMergeHooks(existing, patch);
145
+ // Ensure parent directory exists
146
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
147
+ await fs.writeFile(filePath, JSON.stringify(merged, null, 2) + "\n");
148
+ }
149
+ /**
150
+ * Deep merge that handles hooks specially: for hook arrays, removes any
151
+ * old-format entries with the same command, then adds/replaces with new-format
152
+ * entries. Preserves the user's OTHER hooks.
153
+ */
154
+ function deepMergeHooks(target, source) {
155
+ const result = { ...target };
156
+ for (const [key, sourceVal] of Object.entries(source)) {
157
+ const targetVal = result[key];
158
+ if (key === "hooks" && isObj(targetVal) && isObj(sourceVal)) {
159
+ // Merge hook events individually
160
+ const mergedHooks = { ...targetVal };
161
+ for (const [event, hooks] of Object.entries(sourceVal)) {
162
+ if (!Array.isArray(hooks))
163
+ continue;
164
+ let existing = Array.isArray(mergedHooks[event]) ? [...mergedHooks[event]] : [];
165
+ for (const hook of hooks) {
166
+ const cmd = extractCommand(hook);
167
+ if (cmd) {
168
+ // Remove any existing entries (old or new format) with the same command
169
+ existing = existing.filter((e) => {
170
+ if (!isObj(e))
171
+ return true;
172
+ return extractCommand(e) !== cmd;
173
+ });
174
+ }
175
+ existing.push(hook);
176
+ }
177
+ mergedHooks[event] = existing;
178
+ }
179
+ result[key] = mergedHooks;
180
+ }
181
+ else if (isObj(targetVal) && isObj(sourceVal)) {
182
+ result[key] = deepMergeHooks(targetVal, sourceVal);
183
+ }
184
+ else {
185
+ result[key] = sourceVal;
186
+ }
187
+ }
188
+ return result;
189
+ }
190
+ function isObj(val) {
191
+ return val !== null && typeof val === "object" && !Array.isArray(val);
192
+ }
193
+ /** Extract the command string from a hook entry (supports both old and new format). */
194
+ function extractCommand(entry) {
195
+ // New format: { matcher: {}, hooks: [{ type, command }] }
196
+ const entryHooks = entry.hooks;
197
+ if (Array.isArray(entryHooks) && entryHooks.length > 0) {
198
+ const first = entryHooks[0];
199
+ if (isObj(first) && typeof first.command === "string") {
200
+ return first.command;
201
+ }
202
+ }
203
+ // Old format: { type, command }
204
+ if (typeof entry.command === "string") {
205
+ return entry.command;
206
+ }
207
+ return null;
208
+ }
209
+ // ---------------------------------------------------------------------------
210
+ // Check if hooks are already configured
211
+ // ---------------------------------------------------------------------------
212
+ export async function areClaudeHooksConfigured() {
213
+ try {
214
+ const settingsPath = path.join(os.homedir(), ".claude", "settings.json");
215
+ const text = await fs.readFile(settingsPath, "utf-8");
216
+ const settings = JSON.parse(text);
217
+ const hooks = settings?.hooks;
218
+ if (!hooks || typeof hooks !== "object")
219
+ return false;
220
+ // Check if at least SessionStart hook exists with our script
221
+ const sessionStartHooks = hooks.SessionStart;
222
+ if (!Array.isArray(sessionStartHooks))
223
+ return false;
224
+ const hookPath = path.join(HOOK_DIR, "relay-hook.sh");
225
+ return sessionStartHooks.some((entry) => {
226
+ if (!isObj(entry))
227
+ return false;
228
+ // New format: { matcher: {}, hooks: [{ type, command }] }
229
+ const entryHooks = entry.hooks;
230
+ if (Array.isArray(entryHooks)) {
231
+ return entryHooks.some((h) => isObj(h) && h.command === hookPath);
232
+ }
233
+ // Legacy format: { type, command }
234
+ return entry.command === hookPath;
235
+ });
236
+ }
237
+ catch {
238
+ return false;
239
+ }
240
+ }
241
+ export async function areGeminiHooksConfigured() {
242
+ try {
243
+ const settingsPath = path.join(os.homedir(), ".gemini", "settings.json");
244
+ const text = await fs.readFile(settingsPath, "utf-8");
245
+ const settings = JSON.parse(text);
246
+ const hooks = settings?.hooks;
247
+ if (!hooks || typeof hooks !== "object")
248
+ return false;
249
+ const sessionStartHooks = hooks.SessionStart;
250
+ if (!Array.isArray(sessionStartHooks))
251
+ return false;
252
+ const hookPath = path.join(HOOK_DIR, "relay-hook.sh");
253
+ return sessionStartHooks.some((h) => isObj(h) && h.command === hookPath);
254
+ }
255
+ catch {
256
+ return false;
257
+ }
258
+ }
259
+ //# sourceMappingURL=hook-scripts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-scripts.js","sourceRoot":"","sources":["../../../src/agents/sideband/hook-scripts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { EventEmitter } from "node:events";
2
+ /**
3
+ * SidebandReceiver manages a per-session temp directory where hook scripts
4
+ * and status line scripts write data. It watches two files:
5
+ *
6
+ * events.jsonl — hook events (one JSON object per line, append-only)
7
+ * metadata.json — status line metadata (overwritten each update)
8
+ *
9
+ * Emits:
10
+ * "hook" (event: HookEvent)
11
+ * "metadata" (data: SessionMetadata)
12
+ */
13
+ export declare class SidebandReceiver extends EventEmitter {
14
+ private readonly sessionId;
15
+ private dir;
16
+ private eventsWatcher;
17
+ private metadataWatcher;
18
+ private eventsOffset;
19
+ private stopped;
20
+ constructor(sessionId: string);
21
+ /** The sideband temp directory path (available after start). */
22
+ get sidebandDir(): string | null;
23
+ /**
24
+ * Env vars to inject into the PTY spawn environment.
25
+ * Must be called after start().
26
+ */
27
+ getSpawnEnv(): Record<string, string>;
28
+ /** Create the temp dir and start watching. */
29
+ start(): Promise<void>;
30
+ /** Stop watching and clean up the temp directory. */
31
+ stop(): Promise<void>;
32
+ private watchEvents;
33
+ private readNewEvents;
34
+ private watchMetadata;
35
+ private readMetadata;
36
+ }
37
+ //# sourceMappingURL=sideband-receiver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sideband-receiver.d.ts","sourceRoot":"","sources":["../../../src/agents/sideband/sideband-receiver.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQ3C;;;;;;;;;;GAUG;AACH,qBAAa,gBAAiB,SAAQ,YAAY;IAOpC,OAAO,CAAC,QAAQ,CAAC,SAAS;IANtC,OAAO,CAAC,GAAG,CAAuB;IAClC,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,OAAO,CAAS;gBAEK,SAAS,EAAE,MAAM;IAI9C,gEAAgE;IAChE,IAAI,WAAW,IAAI,MAAM,GAAG,IAAI,CAE/B;IAED;;;OAGG;IACH,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAWrC,8CAA8C;IACxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B,qDAAqD;IAC/C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA0B3B,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,aAAa;IAuCrB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,YAAY;CAWrB"}
@@ -0,0 +1,203 @@
1
+ // ---------------------------------------------------------------------------
2
+ // SidebandReceiver — watches temp dir for hook events + status line metadata
3
+ // ---------------------------------------------------------------------------
4
+ import { EventEmitter } from "node:events";
5
+ import fs from "node:fs";
6
+ import fsp from "node:fs/promises";
7
+ import path from "node:path";
8
+ import os from "node:os";
9
+ /**
10
+ * SidebandReceiver manages a per-session temp directory where hook scripts
11
+ * and status line scripts write data. It watches two files:
12
+ *
13
+ * events.jsonl — hook events (one JSON object per line, append-only)
14
+ * metadata.json — status line metadata (overwritten each update)
15
+ *
16
+ * Emits:
17
+ * "hook" (event: HookEvent)
18
+ * "metadata" (data: SessionMetadata)
19
+ */
20
+ export class SidebandReceiver extends EventEmitter {
21
+ sessionId;
22
+ dir = null;
23
+ eventsWatcher = null;
24
+ metadataWatcher = null;
25
+ eventsOffset = 0;
26
+ stopped = false;
27
+ constructor(sessionId) {
28
+ super();
29
+ this.sessionId = sessionId;
30
+ }
31
+ /** The sideband temp directory path (available after start). */
32
+ get sidebandDir() {
33
+ return this.dir;
34
+ }
35
+ /**
36
+ * Env vars to inject into the PTY spawn environment.
37
+ * Must be called after start().
38
+ */
39
+ getSpawnEnv() {
40
+ if (!this.dir)
41
+ return {};
42
+ return {
43
+ FLAIO_SESSION_ID: this.sessionId,
44
+ FLAIO_SIDEBAND_DIR: this.dir,
45
+ // Backward compat — remove in next major
46
+ CODE_RELAY_SESSION_ID: this.sessionId,
47
+ CODE_RELAY_SIDEBAND_DIR: this.dir,
48
+ };
49
+ }
50
+ /** Create the temp dir and start watching. */
51
+ async start() {
52
+ this.dir = await fsp.mkdtemp(path.join(os.tmpdir(), `flaio-${this.sessionId}-`));
53
+ // Pre-create the files so fs.watch has something to watch
54
+ const eventsPath = path.join(this.dir, "events.jsonl");
55
+ const metadataPath = path.join(this.dir, "metadata.json");
56
+ await fsp.writeFile(eventsPath, "");
57
+ await fsp.writeFile(metadataPath, "");
58
+ this.watchEvents(eventsPath);
59
+ this.watchMetadata(metadataPath);
60
+ }
61
+ /** Stop watching and clean up the temp directory. */
62
+ async stop() {
63
+ this.stopped = true;
64
+ if (this.eventsWatcher) {
65
+ this.eventsWatcher.close();
66
+ this.eventsWatcher = null;
67
+ }
68
+ if (this.metadataWatcher) {
69
+ this.metadataWatcher.close();
70
+ this.metadataWatcher = null;
71
+ }
72
+ if (this.dir) {
73
+ try {
74
+ await fsp.rm(this.dir, { recursive: true, force: true });
75
+ }
76
+ catch {
77
+ // Best effort cleanup
78
+ }
79
+ this.dir = null;
80
+ }
81
+ }
82
+ // -------------------------------------------------------------------------
83
+ // events.jsonl watcher — read new lines on change
84
+ // -------------------------------------------------------------------------
85
+ watchEvents(filePath) {
86
+ this.eventsWatcher = fs.watch(filePath, () => {
87
+ if (this.stopped)
88
+ return;
89
+ this.readNewEvents(filePath);
90
+ });
91
+ }
92
+ readNewEvents(filePath) {
93
+ let fd = null;
94
+ try {
95
+ fd = fs.openSync(filePath, "r");
96
+ const stat = fs.fstatSync(fd);
97
+ const bytesToRead = stat.size - this.eventsOffset;
98
+ if (bytesToRead <= 0) {
99
+ fs.closeSync(fd);
100
+ return;
101
+ }
102
+ const buf = Buffer.alloc(bytesToRead);
103
+ fs.readSync(fd, buf, 0, bytesToRead, this.eventsOffset);
104
+ this.eventsOffset = stat.size;
105
+ fs.closeSync(fd);
106
+ fd = null;
107
+ const text = buf.toString("utf-8");
108
+ const lines = text.split("\n").filter(Boolean);
109
+ for (const line of lines) {
110
+ try {
111
+ const parsed = JSON.parse(line);
112
+ this.emit("hook", parsed);
113
+ }
114
+ catch {
115
+ // Skip malformed lines
116
+ }
117
+ }
118
+ }
119
+ catch {
120
+ if (fd !== null) {
121
+ try {
122
+ fs.closeSync(fd);
123
+ }
124
+ catch { /* ignore */ }
125
+ }
126
+ }
127
+ }
128
+ // -------------------------------------------------------------------------
129
+ // metadata.json watcher — read and parse on change
130
+ // -------------------------------------------------------------------------
131
+ watchMetadata(filePath) {
132
+ // Debounce: status line may update rapidly
133
+ let debounceTimer = null;
134
+ this.metadataWatcher = fs.watch(filePath, () => {
135
+ if (this.stopped)
136
+ return;
137
+ if (debounceTimer)
138
+ clearTimeout(debounceTimer);
139
+ debounceTimer = setTimeout(() => {
140
+ this.readMetadata(filePath);
141
+ }, 200);
142
+ });
143
+ }
144
+ readMetadata(filePath) {
145
+ try {
146
+ const text = fs.readFileSync(filePath, "utf-8").trim();
147
+ if (!text)
148
+ return;
149
+ const raw = JSON.parse(text);
150
+ const metadata = normalizeMetadata(raw);
151
+ this.emit("metadata", metadata);
152
+ }
153
+ catch {
154
+ // File may be mid-write — will retry on next change
155
+ }
156
+ }
157
+ }
158
+ // ---------------------------------------------------------------------------
159
+ // Normalize snake_case keys from status line JSON → camelCase SessionMetadata
160
+ // ---------------------------------------------------------------------------
161
+ function normalizeMetadata(raw) {
162
+ const model = raw.model;
163
+ const cost = raw.cost;
164
+ const ctx = raw.context_window;
165
+ const metadata = {};
166
+ if (model) {
167
+ if (typeof model.id === "string")
168
+ metadata.modelId = model.id;
169
+ if (typeof model.display_name === "string")
170
+ metadata.modelDisplayName = model.display_name;
171
+ }
172
+ if (cost) {
173
+ if (typeof cost.total_cost_usd === "number")
174
+ metadata.totalCostUsd = cost.total_cost_usd;
175
+ if (typeof cost.total_duration_ms === "number")
176
+ metadata.totalDurationMs = cost.total_duration_ms;
177
+ if (typeof cost.total_lines_added === "number")
178
+ metadata.totalLinesAdded = cost.total_lines_added;
179
+ if (typeof cost.total_lines_removed === "number")
180
+ metadata.totalLinesRemoved = cost.total_lines_removed;
181
+ }
182
+ if (ctx) {
183
+ metadata.contextWindow = {};
184
+ if (typeof ctx.total_tokens === "number")
185
+ metadata.contextWindow.totalTokens = ctx.total_tokens;
186
+ if (typeof ctx.used_tokens === "number")
187
+ metadata.contextWindow.usedTokens = ctx.used_tokens;
188
+ if (typeof ctx.used_percentage === "number")
189
+ metadata.contextWindow.usedPercentage = ctx.used_percentage;
190
+ if (typeof ctx.cache_creation_tokens === "number")
191
+ metadata.contextWindow.cacheCreationTokens = ctx.cache_creation_tokens;
192
+ if (typeof ctx.cache_read_tokens === "number")
193
+ metadata.contextWindow.cacheReadTokens = ctx.cache_read_tokens;
194
+ }
195
+ if (typeof raw.session_id === "string")
196
+ metadata.sessionId = raw.session_id;
197
+ if (typeof raw.transcript_path === "string")
198
+ metadata.transcriptPath = raw.transcript_path;
199
+ if (typeof raw.version === "string")
200
+ metadata.version = raw.version;
201
+ return metadata;
202
+ }
203
+ //# sourceMappingURL=sideband-receiver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sideband-receiver.js","sourceRoot":"","sources":["../../../src/agents/sideband/sideband-receiver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import type { AgentStatus } from "../drivers/base-driver.js";
2
+ export type DetailedStatus = {
3
+ state: "running";
4
+ detail: "thinking" | "tool_use" | "writing" | "subagent" | "compacting" | "general";
5
+ } | {
6
+ state: "waiting_input";
7
+ detail: "prompt" | "idle_timeout" | "ask_question" | "task_completed";
8
+ } | {
9
+ state: "waiting_permission";
10
+ detail: "tool_approval";
11
+ } | {
12
+ state: "starting";
13
+ } | {
14
+ state: "idle";
15
+ } | {
16
+ state: "exited";
17
+ };
18
+ export interface ResolvedStatus {
19
+ agentStatus: AgentStatus;
20
+ detailed: DetailedStatus;
21
+ toolName?: string;
22
+ }
23
+ /** Raw hook event as written to the JSONL sideband file. */
24
+ export interface HookEvent {
25
+ /** Hook name, e.g. "PreToolUse", "Stop", "Notification" */
26
+ hook: string;
27
+ /** Session ID from the CLI (Claude's internal session ID) */
28
+ sessionId?: string;
29
+ /** Tool name (PreToolUse / PostToolUse / PostToolUseFailure) */
30
+ toolName?: string;
31
+ /** Error message (PostToolUseFailure) */
32
+ error?: string;
33
+ /** Notification type: "permission_prompt", "idle_prompt", "elicitation_dialog" */
34
+ notificationType?: string;
35
+ /** Model info from SessionStart */
36
+ model?: string;
37
+ /** Raw JSON payload passed via stdin (kept for forward-compatibility) */
38
+ raw?: Record<string, unknown>;
39
+ }
40
+ export declare function resolveFromClaudeHook(event: HookEvent): ResolvedStatus;
41
+ /**
42
+ * Parse Gemini's OSC title string to determine status.
43
+ * Gemini CLI with `--show-status` sets terminal title via OSC:
44
+ * - "◇ Ready" → waiting_input
45
+ * - "✦ Working" → running
46
+ * - "✋ Action Required" → waiting_permission
47
+ */
48
+ export declare function resolveFromGeminiOscTitle(title: string): ResolvedStatus | null;
49
+ export declare function resolveFromGeminiHook(event: HookEvent): ResolvedStatus;
50
+ /**
51
+ * Extract OSC title from raw PTY data.
52
+ * OSC format: ESC ] 0 ; <title> BEL or ESC ] 0 ; <title> ESC \
53
+ */
54
+ export declare function extractOscTitle(data: string): string | null;
55
+ //# sourceMappingURL=status-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-resolver.d.ts","sourceRoot":"","sources":["../../../src/agents/sideband/status-resolver.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAM7D,MAAM,MAAM,cAAc,GACtB;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAA;CAAE,GACzG;IAAE,KAAK,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,QAAQ,GAAG,cAAc,GAAG,cAAc,GAAG,gBAAgB,CAAA;CAAE,GACjG;IAAE,KAAK,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,GACxD;IAAE,KAAK,EAAE,UAAU,CAAA;CAAE,GACrB;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACjB;IAAE,KAAK,EAAE,QAAQ,CAAA;CAAE,CAAC;AAExB,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,4DAA4D;AAC5D,MAAM,WAAW,SAAS;IACxB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAQD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,GAAG,cAAc,CA2GtE;AAMD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAyB9E;AAMD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,GAAG,cAAc,CAgDtE;AAMD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3D"}