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.
- package/LICENSE +21 -0
- package/README.md +461 -0
- package/dist/agents/agent-detector.d.ts +21 -0
- package/dist/agents/agent-detector.d.ts.map +1 -0
- package/dist/agents/agent-detector.js +109 -0
- package/dist/agents/agent-detector.js.map +1 -0
- package/dist/agents/agent-registry.d.ts +6 -0
- package/dist/agents/agent-registry.d.ts.map +1 -0
- package/dist/agents/agent-registry.js +25 -0
- package/dist/agents/agent-registry.js.map +1 -0
- package/dist/agents/agent-session.d.ts +60 -0
- package/dist/agents/agent-session.d.ts.map +1 -0
- package/dist/agents/agent-session.js +251 -0
- package/dist/agents/agent-session.js.map +1 -0
- package/dist/agents/drivers/base-driver.d.ts +37 -0
- package/dist/agents/drivers/base-driver.d.ts.map +1 -0
- package/dist/agents/drivers/base-driver.js +18 -0
- package/dist/agents/drivers/base-driver.js.map +1 -0
- package/dist/agents/drivers/claude-driver.d.ts +23 -0
- package/dist/agents/drivers/claude-driver.d.ts.map +1 -0
- package/dist/agents/drivers/claude-driver.js +61 -0
- package/dist/agents/drivers/claude-driver.js.map +1 -0
- package/dist/agents/drivers/gemini-driver.d.ts +23 -0
- package/dist/agents/drivers/gemini-driver.d.ts.map +1 -0
- package/dist/agents/drivers/gemini-driver.js +60 -0
- package/dist/agents/drivers/gemini-driver.js.map +1 -0
- package/dist/agents/session-metadata.d.ts +33 -0
- package/dist/agents/session-metadata.d.ts.map +1 -0
- package/dist/agents/session-metadata.js +34 -0
- package/dist/agents/session-metadata.js.map +1 -0
- package/dist/agents/sideband/hook-scripts.d.ts +29 -0
- package/dist/agents/sideband/hook-scripts.d.ts.map +1 -0
- package/dist/agents/sideband/hook-scripts.js +259 -0
- package/dist/agents/sideband/hook-scripts.js.map +1 -0
- package/dist/agents/sideband/sideband-receiver.d.ts +37 -0
- package/dist/agents/sideband/sideband-receiver.d.ts.map +1 -0
- package/dist/agents/sideband/sideband-receiver.js +203 -0
- package/dist/agents/sideband/sideband-receiver.js.map +1 -0
- package/dist/agents/sideband/status-resolver.d.ts +55 -0
- package/dist/agents/sideband/status-resolver.d.ts.map +1 -0
- package/dist/agents/sideband/status-resolver.js +194 -0
- package/dist/agents/sideband/status-resolver.js.map +1 -0
- package/dist/app.d.ts +3 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +94 -0
- package/dist/app.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +188 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/config.d.ts +341 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +94 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/defaults.d.ts +33 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +33 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/connectors/adapters/discord-adapter.d.ts +25 -0
- package/dist/connectors/adapters/discord-adapter.d.ts.map +1 -0
- package/dist/connectors/adapters/discord-adapter.js +154 -0
- package/dist/connectors/adapters/discord-adapter.js.map +1 -0
- package/dist/connectors/adapters/slack-adapter.d.ts +38 -0
- package/dist/connectors/adapters/slack-adapter.d.ts.map +1 -0
- package/dist/connectors/adapters/slack-adapter.js +502 -0
- package/dist/connectors/adapters/slack-adapter.js.map +1 -0
- package/dist/connectors/adapters/telegram-adapter.d.ts +25 -0
- package/dist/connectors/adapters/telegram-adapter.d.ts.map +1 -0
- package/dist/connectors/adapters/telegram-adapter.js +164 -0
- package/dist/connectors/adapters/telegram-adapter.js.map +1 -0
- package/dist/connectors/connector-interface.d.ts +41 -0
- package/dist/connectors/connector-interface.d.ts.map +1 -0
- package/dist/connectors/connector-interface.js +2 -0
- package/dist/connectors/connector-interface.js.map +1 -0
- package/dist/connectors/connector-manager.d.ts +24 -0
- package/dist/connectors/connector-manager.d.ts.map +1 -0
- package/dist/connectors/connector-manager.js +82 -0
- package/dist/connectors/connector-manager.js.map +1 -0
- package/dist/connectors/debug.d.ts +3 -0
- package/dist/connectors/debug.d.ts.map +1 -0
- package/dist/connectors/debug.js +16 -0
- package/dist/connectors/debug.js.map +1 -0
- package/dist/hooks/hook-server.d.ts +27 -0
- package/dist/hooks/hook-server.d.ts.map +1 -0
- package/dist/hooks/hook-server.js +149 -0
- package/dist/hooks/hook-server.js.map +1 -0
- package/dist/hooks/hook.d.ts +10 -0
- package/dist/hooks/hook.d.ts.map +1 -0
- package/dist/hooks/hook.js +58 -0
- package/dist/hooks/hook.js.map +1 -0
- package/dist/hooks/install.d.ts +8 -0
- package/dist/hooks/install.d.ts.map +1 -0
- package/dist/hooks/install.js +160 -0
- package/dist/hooks/install.js.map +1 -0
- package/dist/hooks/notification-hook.d.ts +9 -0
- package/dist/hooks/notification-hook.d.ts.map +1 -0
- package/dist/hooks/notification-hook.js +38 -0
- package/dist/hooks/notification-hook.js.map +1 -0
- package/dist/hooks/post-tool-hook.d.ts +9 -0
- package/dist/hooks/post-tool-hook.d.ts.map +1 -0
- package/dist/hooks/post-tool-hook.js +39 -0
- package/dist/hooks/post-tool-hook.js.map +1 -0
- package/dist/hooks/stop-hook.d.ts +9 -0
- package/dist/hooks/stop-hook.d.ts.map +1 -0
- package/dist/hooks/stop-hook.js +37 -0
- package/dist/hooks/stop-hook.js.map +1 -0
- package/dist/portal/ansi-renderer.d.ts +15 -0
- package/dist/portal/ansi-renderer.d.ts.map +1 -0
- package/dist/portal/ansi-renderer.js +75 -0
- package/dist/portal/ansi-renderer.js.map +1 -0
- package/dist/portal/portal-client.d.ts +18 -0
- package/dist/portal/portal-client.d.ts.map +1 -0
- package/dist/portal/portal-client.js +335 -0
- package/dist/portal/portal-client.js.map +1 -0
- package/dist/portal/portal-picker.d.ts +8 -0
- package/dist/portal/portal-picker.d.ts.map +1 -0
- package/dist/portal/portal-picker.js +145 -0
- package/dist/portal/portal-picker.js.map +1 -0
- package/dist/portal/portal-server.d.ts +24 -0
- package/dist/portal/portal-server.d.ts.map +1 -0
- package/dist/portal/portal-server.js +330 -0
- package/dist/portal/portal-server.js.map +1 -0
- package/dist/portal/shared.d.ts +79 -0
- package/dist/portal/shared.d.ts.map +1 -0
- package/dist/portal/shared.js +5 -0
- package/dist/portal/shared.js.map +1 -0
- package/dist/relay/rate-limiter.d.ts +16 -0
- package/dist/relay/rate-limiter.d.ts.map +1 -0
- package/dist/relay/rate-limiter.js +37 -0
- package/dist/relay/rate-limiter.js.map +1 -0
- package/dist/relay/relay-auth.d.ts +29 -0
- package/dist/relay/relay-auth.d.ts.map +1 -0
- package/dist/relay/relay-auth.js +129 -0
- package/dist/relay/relay-auth.js.map +1 -0
- package/dist/relay/relay-client.d.ts +52 -0
- package/dist/relay/relay-client.d.ts.map +1 -0
- package/dist/relay/relay-client.js +1102 -0
- package/dist/relay/relay-client.js.map +1 -0
- package/dist/relay/relay-crypto.d.ts +29 -0
- package/dist/relay/relay-crypto.d.ts.map +1 -0
- package/dist/relay/relay-crypto.js +100 -0
- package/dist/relay/relay-crypto.js.map +1 -0
- package/dist/relay/relay-message-schemas.d.ts +276 -0
- package/dist/relay/relay-message-schemas.d.ts.map +1 -0
- package/dist/relay/relay-message-schemas.js +137 -0
- package/dist/relay/relay-message-schemas.js.map +1 -0
- package/dist/relay/relay-protocol.d.ts +444 -0
- package/dist/relay/relay-protocol.d.ts.map +1 -0
- package/dist/relay/relay-protocol.js +15 -0
- package/dist/relay/relay-protocol.js.map +1 -0
- package/dist/relay/relay-store.d.ts +23 -0
- package/dist/relay/relay-store.d.ts.map +1 -0
- package/dist/relay/relay-store.js +54 -0
- package/dist/relay/relay-store.js.map +1 -0
- package/dist/relay/ticket-tracker.d.ts +18 -0
- package/dist/relay/ticket-tracker.d.ts.map +1 -0
- package/dist/relay/ticket-tracker.js +58 -0
- package/dist/relay/ticket-tracker.js.map +1 -0
- package/dist/store/app-store.d.ts +66 -0
- package/dist/store/app-store.d.ts.map +1 -0
- package/dist/store/app-store.js +227 -0
- package/dist/store/app-store.js.map +1 -0
- package/dist/store/connector-store.d.ts +21 -0
- package/dist/store/connector-store.d.ts.map +1 -0
- package/dist/store/connector-store.js +591 -0
- package/dist/store/connector-store.js.map +1 -0
- package/dist/store/portal-store.d.ts +5 -0
- package/dist/store/portal-store.d.ts.map +1 -0
- package/dist/store/portal-store.js +5 -0
- package/dist/store/portal-store.js.map +1 -0
- package/dist/store/settings-store.d.ts +13 -0
- package/dist/store/settings-store.d.ts.map +1 -0
- package/dist/store/settings-store.js +59 -0
- package/dist/store/settings-store.js.map +1 -0
- package/dist/terminal/pty-manager.d.ts +19 -0
- package/dist/terminal/pty-manager.d.ts.map +1 -0
- package/dist/terminal/pty-manager.js +58 -0
- package/dist/terminal/pty-manager.js.map +1 -0
- package/dist/terminal/screen-buffer.d.ts +36 -0
- package/dist/terminal/screen-buffer.d.ts.map +1 -0
- package/dist/terminal/screen-buffer.js +109 -0
- package/dist/terminal/screen-buffer.js.map +1 -0
- package/dist/terminal/xterm-bridge.d.ts +32 -0
- package/dist/terminal/xterm-bridge.d.ts.map +1 -0
- package/dist/terminal/xterm-bridge.js +168 -0
- package/dist/terminal/xterm-bridge.js.map +1 -0
- package/dist/ui/components/adopt-agent-dialog.d.ts +10 -0
- package/dist/ui/components/adopt-agent-dialog.d.ts.map +1 -0
- package/dist/ui/components/adopt-agent-dialog.js +31 -0
- package/dist/ui/components/adopt-agent-dialog.js.map +1 -0
- package/dist/ui/components/agent-tab.d.ts +17 -0
- package/dist/ui/components/agent-tab.d.ts.map +1 -0
- package/dist/ui/components/agent-tab.js +33 -0
- package/dist/ui/components/agent-tab.js.map +1 -0
- package/dist/ui/components/agents-settings-content.d.ts +7 -0
- package/dist/ui/components/agents-settings-content.d.ts.map +1 -0
- package/dist/ui/components/agents-settings-content.js +238 -0
- package/dist/ui/components/agents-settings-content.js.map +1 -0
- package/dist/ui/components/help-modal.d.ts +7 -0
- package/dist/ui/components/help-modal.d.ts.map +1 -0
- package/dist/ui/components/help-modal.js +29 -0
- package/dist/ui/components/help-modal.js.map +1 -0
- package/dist/ui/components/new-session-dialog.d.ts +8 -0
- package/dist/ui/components/new-session-dialog.d.ts.map +1 -0
- package/dist/ui/components/new-session-dialog.js +84 -0
- package/dist/ui/components/new-session-dialog.js.map +1 -0
- package/dist/ui/components/path-input.d.ts +8 -0
- package/dist/ui/components/path-input.d.ts.map +1 -0
- package/dist/ui/components/path-input.js +151 -0
- package/dist/ui/components/path-input.js.map +1 -0
- package/dist/ui/components/settings-panel.d.ts +7 -0
- package/dist/ui/components/settings-panel.d.ts.map +1 -0
- package/dist/ui/components/settings-panel.js +134 -0
- package/dist/ui/components/settings-panel.js.map +1 -0
- package/dist/ui/components/standalone-agents.d.ts +9 -0
- package/dist/ui/components/standalone-agents.d.ts.map +1 -0
- package/dist/ui/components/standalone-agents.js +28 -0
- package/dist/ui/components/standalone-agents.js.map +1 -0
- package/dist/ui/components/terminal-view.d.ts +12 -0
- package/dist/ui/components/terminal-view.d.ts.map +1 -0
- package/dist/ui/components/terminal-view.js +53 -0
- package/dist/ui/components/terminal-view.js.map +1 -0
- package/dist/ui/components/viewer-approval-dialog.d.ts +9 -0
- package/dist/ui/components/viewer-approval-dialog.d.ts.map +1 -0
- package/dist/ui/components/viewer-approval-dialog.js +38 -0
- package/dist/ui/components/viewer-approval-dialog.js.map +1 -0
- package/dist/ui/hooks/use-git-info.d.ts +8 -0
- package/dist/ui/hooks/use-git-info.d.ts.map +1 -0
- package/dist/ui/hooks/use-git-info.js +72 -0
- package/dist/ui/hooks/use-git-info.js.map +1 -0
- package/dist/ui/hooks/use-keybindings.d.ts +10 -0
- package/dist/ui/hooks/use-keybindings.d.ts.map +1 -0
- package/dist/ui/hooks/use-keybindings.js +91 -0
- package/dist/ui/hooks/use-keybindings.js.map +1 -0
- package/dist/ui/hooks/use-portal-connected.d.ts +2 -0
- package/dist/ui/hooks/use-portal-connected.d.ts.map +1 -0
- package/dist/ui/hooks/use-portal-connected.js +10 -0
- package/dist/ui/hooks/use-portal-connected.js.map +1 -0
- package/dist/ui/hooks/use-raw-input.d.ts +8 -0
- package/dist/ui/hooks/use-raw-input.d.ts.map +1 -0
- package/dist/ui/hooks/use-raw-input.js +106 -0
- package/dist/ui/hooks/use-raw-input.js.map +1 -0
- package/dist/ui/hooks/use-spinner.d.ts +2 -0
- package/dist/ui/hooks/use-spinner.d.ts.map +1 -0
- package/dist/ui/hooks/use-spinner.js +13 -0
- package/dist/ui/hooks/use-spinner.js.map +1 -0
- package/dist/ui/hooks/use-terminal-size.d.ts +5 -0
- package/dist/ui/hooks/use-terminal-size.d.ts.map +1 -0
- package/dist/ui/hooks/use-terminal-size.js +22 -0
- package/dist/ui/hooks/use-terminal-size.js.map +1 -0
- package/dist/ui/hooks/use-update-check.d.ts +6 -0
- package/dist/ui/hooks/use-update-check.d.ts.map +1 -0
- package/dist/ui/hooks/use-update-check.js +62 -0
- package/dist/ui/hooks/use-update-check.js.map +1 -0
- package/dist/ui/layout/main-pane.d.ts +13 -0
- package/dist/ui/layout/main-pane.d.ts.map +1 -0
- package/dist/ui/layout/main-pane.js +36 -0
- package/dist/ui/layout/main-pane.js.map +1 -0
- package/dist/ui/layout/shell.d.ts +17 -0
- package/dist/ui/layout/shell.d.ts.map +1 -0
- package/dist/ui/layout/shell.js +24 -0
- package/dist/ui/layout/shell.js.map +1 -0
- package/dist/ui/layout/sidebar.d.ts +12 -0
- package/dist/ui/layout/sidebar.d.ts.map +1 -0
- package/dist/ui/layout/sidebar.js +9 -0
- package/dist/ui/layout/sidebar.js.map +1 -0
- package/dist/ui/layout/status-bar.d.ts +9 -0
- package/dist/ui/layout/status-bar.d.ts.map +1 -0
- package/dist/ui/layout/status-bar.js +138 -0
- package/dist/ui/layout/status-bar.js.map +1 -0
- 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"}
|