@loompad/cli 0.1.0
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/ARCHITECTURE.md +211 -0
- package/CHANGELOG.md +470 -0
- package/LICENSE +21 -0
- package/README.md +630 -0
- package/dist/adapters/base.d.ts +71 -0
- package/dist/adapters/base.js +187 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/bridges/antigravity.d.ts +53 -0
- package/dist/adapters/bridges/antigravity.js +106 -0
- package/dist/adapters/bridges/antigravity.js.map +1 -0
- package/dist/adapters/bridges/cdp.d.ts +82 -0
- package/dist/adapters/bridges/cdp.js +222 -0
- package/dist/adapters/bridges/cdp.js.map +1 -0
- package/dist/adapters/bridges/gui-chat.d.ts +113 -0
- package/dist/adapters/bridges/gui-chat.js +498 -0
- package/dist/adapters/bridges/gui-chat.js.map +1 -0
- package/dist/adapters/bridges/kiro.d.ts +19 -0
- package/dist/adapters/bridges/kiro.js +22 -0
- package/dist/adapters/bridges/kiro.js.map +1 -0
- package/dist/adapters/bridges/profiles.d.ts +82 -0
- package/dist/adapters/bridges/profiles.js +125 -0
- package/dist/adapters/bridges/profiles.js.map +1 -0
- package/dist/adapters/claude-code.d.ts +26 -0
- package/dist/adapters/claude-code.js +209 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/codex.d.ts +51 -0
- package/dist/adapters/codex.js +291 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/echo.d.ts +20 -0
- package/dist/adapters/echo.js +79 -0
- package/dist/adapters/echo.js.map +1 -0
- package/dist/adapters/grok.d.ts +61 -0
- package/dist/adapters/grok.js +217 -0
- package/dist/adapters/grok.js.map +1 -0
- package/dist/adapters/index.d.ts +9 -0
- package/dist/adapters/index.js +33 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/opencode.d.ts +64 -0
- package/dist/adapters/opencode.js +426 -0
- package/dist/adapters/opencode.js.map +1 -0
- package/dist/cli/common.d.ts +11 -0
- package/dist/cli/common.js +40 -0
- package/dist/cli/common.js.map +1 -0
- package/dist/cli/doctor.d.ts +12 -0
- package/dist/cli/doctor.js +181 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.js +641 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/tui-model.d.ts +73 -0
- package/dist/cli/tui-model.js +312 -0
- package/dist/cli/tui-model.js.map +1 -0
- package/dist/cli/tui.d.ts +15 -0
- package/dist/cli/tui.js +451 -0
- package/dist/cli/tui.js.map +1 -0
- package/dist/cli/ui.d.ts +10 -0
- package/dist/cli/ui.js +135 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/core/ades.d.ts +79 -0
- package/dist/core/ades.js +130 -0
- package/dist/core/ades.js.map +1 -0
- package/dist/core/baton.d.ts +37 -0
- package/dist/core/baton.js +92 -0
- package/dist/core/baton.js.map +1 -0
- package/dist/core/brain-extract.d.ts +111 -0
- package/dist/core/brain-extract.js +248 -0
- package/dist/core/brain-extract.js.map +1 -0
- package/dist/core/brain-index.d.ts +128 -0
- package/dist/core/brain-index.js +338 -0
- package/dist/core/brain-index.js.map +1 -0
- package/dist/core/brain.d.ts +214 -0
- package/dist/core/brain.js +425 -0
- package/dist/core/brain.js.map +1 -0
- package/dist/core/claude-cli.d.ts +12 -0
- package/dist/core/claude-cli.js +47 -0
- package/dist/core/claude-cli.js.map +1 -0
- package/dist/core/distill.d.ts +19 -0
- package/dist/core/distill.js +88 -0
- package/dist/core/distill.js.map +1 -0
- package/dist/core/eventlog.d.ts +43 -0
- package/dist/core/eventlog.js +211 -0
- package/dist/core/eventlog.js.map +1 -0
- package/dist/core/git.d.ts +203 -0
- package/dist/core/git.js +460 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/logbook.d.ts +59 -0
- package/dist/core/logbook.js +118 -0
- package/dist/core/logbook.js.map +1 -0
- package/dist/core/memory.d.ts +34 -0
- package/dist/core/memory.js +124 -0
- package/dist/core/memory.js.map +1 -0
- package/dist/core/notify.d.ts +11 -0
- package/dist/core/notify.js +30 -0
- package/dist/core/notify.js.map +1 -0
- package/dist/core/projection.d.ts +20 -0
- package/dist/core/projection.js +96 -0
- package/dist/core/projection.js.map +1 -0
- package/dist/core/registry.d.ts +76 -0
- package/dist/core/registry.js +147 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core/router.d.ts +42 -0
- package/dist/core/router.js +99 -0
- package/dist/core/router.js.map +1 -0
- package/dist/core/routes.d.ts +93 -0
- package/dist/core/routes.js +399 -0
- package/dist/core/routes.js.map +1 -0
- package/dist/core/search.d.ts +63 -0
- package/dist/core/search.js +0 -0
- package/dist/core/search.js.map +1 -0
- package/dist/core/setup.d.ts +70 -0
- package/dist/core/setup.js +250 -0
- package/dist/core/setup.js.map +1 -0
- package/dist/core/suggestions.d.ts +15 -0
- package/dist/core/suggestions.js +38 -0
- package/dist/core/suggestions.js.map +1 -0
- package/dist/core/worktree.d.ts +32 -0
- package/dist/core/worktree.js +83 -0
- package/dist/core/worktree.js.map +1 -0
- package/dist/daemon/app-page.d.ts +32 -0
- package/dist/daemon/app-page.js +6363 -0
- package/dist/daemon/app-page.js.map +1 -0
- package/dist/daemon/auth.d.ts +51 -0
- package/dist/daemon/auth.js +135 -0
- package/dist/daemon/auth.js.map +1 -0
- package/dist/daemon/board.d.ts +117 -0
- package/dist/daemon/board.js +202 -0
- package/dist/daemon/board.js.map +1 -0
- package/dist/daemon/brand-icons.d.ts +29 -0
- package/dist/daemon/brand-icons.js +44 -0
- package/dist/daemon/brand-icons.js.map +1 -0
- package/dist/daemon/client.d.ts +127 -0
- package/dist/daemon/client.js +237 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/geist-font.d.ts +10 -0
- package/dist/daemon/geist-font.js +783 -0
- package/dist/daemon/geist-font.js.map +1 -0
- package/dist/daemon/guards.d.ts +18 -0
- package/dist/daemon/guards.js +40 -0
- package/dist/daemon/guards.js.map +1 -0
- package/dist/daemon/linear.d.ts +59 -0
- package/dist/daemon/linear.js +117 -0
- package/dist/daemon/linear.js.map +1 -0
- package/dist/daemon/push.d.ts +22 -0
- package/dist/daemon/push.js +58 -0
- package/dist/daemon/push.js.map +1 -0
- package/dist/daemon/runtime.d.ts +299 -0
- package/dist/daemon/runtime.js +1016 -0
- package/dist/daemon/runtime.js.map +1 -0
- package/dist/daemon/server.d.ts +125 -0
- package/dist/daemon/server.js +1728 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/tasks.d.ts +153 -0
- package/dist/daemon/tasks.js +264 -0
- package/dist/daemon/tasks.js.map +1 -0
- package/dist/daemon/terminals.d.ts +82 -0
- package/dist/daemon/terminals.js +372 -0
- package/dist/daemon/terminals.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/sdk.d.ts +17 -0
- package/dist/sdk.js +17 -0
- package/dist/sdk.js.map +1 -0
- package/dist/types.d.ts +236 -0
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -0
- package/docs/SETUP.md +265 -0
- package/docs/adapters.md +132 -0
- package/docs/design-system.md +245 -0
- package/docs/img/board-linear.png +0 -0
- package/docs/img/board-projects.png +0 -0
- package/docs/img/brain.png +0 -0
- package/docs/img/settings.png +0 -0
- package/docs/img/workspace.png +0 -0
- package/docs/integration-notes.md +76 -0
- package/docs/proposals/brain.md +262 -0
- package/package.json +84 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What each GUI agent's chat is made of.
|
|
3
|
+
*
|
|
4
|
+
* Read off the running apps, with two projects' work behind them:
|
|
5
|
+
* krishnakanthb13/antigravity_phone_chat for the shape of Antigravity's chat,
|
|
6
|
+
* and yazanbaker94/AntiGravity-AutoAccept for how to attach to it at all. Both
|
|
7
|
+
* MIT, both doing this daily against real installs.
|
|
8
|
+
*
|
|
9
|
+
* Everything here was then checked against Antigravity IDE 1.107.0 on this
|
|
10
|
+
* machine, and the checking mattered — two of the borrowed selectors are gone
|
|
11
|
+
* in this build, and the app that matters isn't the one with the obvious name.
|
|
12
|
+
*
|
|
13
|
+
* The scoping is the important idea, and it's from the phone-chat project. The
|
|
14
|
+
* composer is looked for *inside* `#conversation` — never in the document at
|
|
15
|
+
* large. These are VS Code-family apps and Monaco, the editor holding your
|
|
16
|
+
* source file, is a `contenteditable`. Hunt the document and you will
|
|
17
|
+
* eventually find it and type a prompt into someone's code. Search inside the
|
|
18
|
+
* chat panel and you cannot.
|
|
19
|
+
*
|
|
20
|
+
* Selectors rot; two already did. When they stop matching, the bridge says so
|
|
21
|
+
* rather than improvising, and `options.selectors` overrides any of it without
|
|
22
|
+
* waiting for a release.
|
|
23
|
+
*/
|
|
24
|
+
/** Anything under one of these is never a composer, whatever else it looks like. */
|
|
25
|
+
export const FORBIDDEN_ANCESTORS = [".monaco-editor", ".editor-instance", '[role="code"]'];
|
|
26
|
+
export const PROFILES = {
|
|
27
|
+
/**
|
|
28
|
+
* Antigravity IDE — a Lexical composer inside a `#conversation` panel.
|
|
29
|
+
*
|
|
30
|
+
* Read off the real thing: Antigravity IDE 1.107.0, signed in, workbench
|
|
31
|
+
* open. The composer is `<div data-lexical-editor="true" aria-label="Message
|
|
32
|
+
* input">` and the submit is:
|
|
33
|
+
*
|
|
34
|
+
* <button aria-label="Send message" data-testid="send-button"
|
|
35
|
+
* data-tooltip-id="input-send-button-send-tooltip">
|
|
36
|
+
*
|
|
37
|
+
* `data-testid` leads because a testid is a promise to a test suite, and
|
|
38
|
+
* things people test against get renamed less often than classes do. The
|
|
39
|
+
* tooltip id is the same control by another name, and it's what
|
|
40
|
+
* antigravity_phone_chat matches on. `svg.lucide-arrow-right` is that
|
|
41
|
+
* project's selector and finds nothing in this build — kept last so older
|
|
42
|
+
* installs still work.
|
|
43
|
+
*
|
|
44
|
+
* Note WHICH app this is. `Antigravity.app` and `Antigravity IDE.app` are two
|
|
45
|
+
* different programs: the first is the Manager (a plain https:// page behind
|
|
46
|
+
* a Google sign-in, no chat DOM at all), the second is the VS Code fork with
|
|
47
|
+
* the agent in it. Probing the Manager for a composer finds nothing and
|
|
48
|
+
* tells you Antigravity has no chat, which is wrong and wasted an afternoon.
|
|
49
|
+
*/
|
|
50
|
+
antigravity: {
|
|
51
|
+
name: "Antigravity IDE",
|
|
52
|
+
defaultPort: 9333,
|
|
53
|
+
launch: {
|
|
54
|
+
darwin: 'open -a "Antigravity IDE" --args --remote-debugging-port=9333',
|
|
55
|
+
win32: "right-click the Antigravity IDE shortcut → Properties → append --remote-debugging-port=9333 to Target",
|
|
56
|
+
linux: "antigravity --remote-debugging-port=9333 (or add it to the Exec line of its .desktop file)",
|
|
57
|
+
},
|
|
58
|
+
chatRoots: ["#conversation", "#chat", ".cascade"],
|
|
59
|
+
composer: '[data-lexical-editor="true"], [contenteditable="true"]',
|
|
60
|
+
send: [
|
|
61
|
+
'[data-testid="send-button"]',
|
|
62
|
+
'[data-tooltip-id="input-send-button-send-tooltip"]',
|
|
63
|
+
"svg.lucide-arrow-right",
|
|
64
|
+
],
|
|
65
|
+
busy: '[data-tooltip-id="input-send-button-cancel-tooltip"]',
|
|
66
|
+
transcript: ["#conversation", "#chat", ".cascade", "[data-scroll-area]"],
|
|
67
|
+
// Observed verbatim in 1.107.0: "There was an error with your
|
|
68
|
+
// authentication. To log in, click here".
|
|
69
|
+
signedOut: /error with your authentication|to log in, click here|^log in$/i,
|
|
70
|
+
},
|
|
71
|
+
/**
|
|
72
|
+
* Kiro — a VS Code fork whose chat lives in a workbench panel.
|
|
73
|
+
*
|
|
74
|
+
* Nobody has published working selectors for it and this machine can't
|
|
75
|
+
* produce them either: Kiro opens on a Getting Started tab with no chat panel,
|
|
76
|
+
* so there was nothing to read. These are the VS Code conventions its panel
|
|
77
|
+
* most likely follows, and if they miss, the bridge reports that rather than
|
|
78
|
+
* falling back to the document — which is where Monaco lives.
|
|
79
|
+
*
|
|
80
|
+
* Unverified. Set options.selectors.composer and it stops mattering.
|
|
81
|
+
*/
|
|
82
|
+
kiro: {
|
|
83
|
+
name: "Kiro",
|
|
84
|
+
defaultPort: 9334,
|
|
85
|
+
launch: {
|
|
86
|
+
darwin: 'open -a "Kiro" --args --remote-debugging-port=9334',
|
|
87
|
+
win32: "right-click the Kiro shortcut → Properties → append --remote-debugging-port=9334 to Target",
|
|
88
|
+
linux: "kiro --remote-debugging-port=9334",
|
|
89
|
+
},
|
|
90
|
+
chatRoots: [
|
|
91
|
+
"#workbench\\.parts\\.sidebar",
|
|
92
|
+
"#workbench\\.parts\\.auxiliarybar",
|
|
93
|
+
"#workbench\\.parts\\.panel",
|
|
94
|
+
".chat-container",
|
|
95
|
+
"[id*='chat']",
|
|
96
|
+
],
|
|
97
|
+
composer: '.chat-input-container [contenteditable="true"], textarea, [contenteditable="true"]',
|
|
98
|
+
send: [".codicon-send", "[aria-label*='Send' i]"],
|
|
99
|
+
transcript: [".chat-container", ".interactive-list", "[id*='chat']"],
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* When we don't know the app: no chat root to scope to, so the composer has to
|
|
104
|
+
* earn it by being labelled like one, and Monaco is excluded explicitly rather
|
|
105
|
+
* than structurally. Strictly worse than a profile — that's why profiles exist.
|
|
106
|
+
*/
|
|
107
|
+
export const GENERIC = {
|
|
108
|
+
name: "the app",
|
|
109
|
+
defaultPort: 9222,
|
|
110
|
+
launch: {
|
|
111
|
+
darwin: "launch it with --remote-debugging-port=9222",
|
|
112
|
+
win32: "launch it with --remote-debugging-port=9222",
|
|
113
|
+
linux: "launch it with --remote-debugging-port=9222",
|
|
114
|
+
},
|
|
115
|
+
chatRoots: ["body"],
|
|
116
|
+
composer: 'textarea, [contenteditable="true"]',
|
|
117
|
+
send: ["[aria-label='Send' i]", "button"],
|
|
118
|
+
transcript: ["body"],
|
|
119
|
+
};
|
|
120
|
+
/** What a chat box calls itself, for the generic path only. */
|
|
121
|
+
export const CHATTY = /ask|message|chat|prompt|plan|type .*here|what.*build|reply/i;
|
|
122
|
+
export function profileFor(kind) {
|
|
123
|
+
return PROFILES[kind] ?? GENERIC;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=profiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../../src/adapters/bridges/profiles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AA8CH,oFAAoF;AACpF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,eAAe,CAAC,CAAC;AAE3F,MAAM,CAAC,MAAM,QAAQ,GAA+B;IAClD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,WAAW,EAAE;QACX,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE;YACN,MAAM,EAAE,+DAA+D;YACvE,KAAK,EAAE,uGAAuG;YAC9G,KAAK,EAAE,6FAA6F;SACrG;QACD,SAAS,EAAE,CAAC,eAAe,EAAE,OAAO,EAAE,UAAU,CAAC;QACjD,QAAQ,EAAE,wDAAwD;QAClE,IAAI,EAAE;YACJ,6BAA6B;YAC7B,oDAAoD;YACpD,wBAAwB;SACzB;QACD,IAAI,EAAE,sDAAsD;QAC5D,UAAU,EAAE,CAAC,eAAe,EAAE,OAAO,EAAE,UAAU,EAAE,oBAAoB,CAAC;QACxE,8DAA8D;QAC9D,0CAA0C;QAC1C,SAAS,EAAE,gEAAgE;KAC5E;IAED;;;;;;;;;;OAUG;IACH,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE;YACN,MAAM,EAAE,oDAAoD;YAC5D,KAAK,EAAE,4FAA4F;YACnG,KAAK,EAAE,mCAAmC;SAC3C;QACD,SAAS,EAAE;YACT,8BAA8B;YAC9B,mCAAmC;YACnC,4BAA4B;YAC5B,iBAAiB;YACjB,cAAc;SACf;QACD,QAAQ,EAAE,oFAAoF;QAC9F,IAAI,EAAE,CAAC,eAAe,EAAE,wBAAwB,CAAC;QACjD,UAAU,EAAE,CAAC,iBAAiB,EAAE,mBAAmB,EAAE,cAAc,CAAC;KACrE;CACF,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAe;IACjC,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,IAAI;IACjB,MAAM,EAAE;QACN,MAAM,EAAE,6CAA6C;QACrD,KAAK,EAAE,6CAA6C;QACpD,KAAK,EAAE,6CAA6C;KACrD;IACD,SAAS,EAAE,CAAC,MAAM,CAAC;IACnB,QAAQ,EAAE,oCAAoC;IAC9C,IAAI,EAAE,CAAC,uBAAuB,EAAE,QAAQ,CAAC;IACzC,UAAU,EAAE,CAAC,MAAM,CAAC;CACrB,CAAC;AAEF,+DAA+D;AAC/D,MAAM,CAAC,MAAM,MAAM,GAAG,6DAA6D,CAAC;AAEpF,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code adapter — drives the `claude` CLI headless, one process per
|
|
3
|
+
* turn, resuming the same session id across turns.
|
|
4
|
+
*
|
|
5
|
+
* claude -p "<text>" --output-format stream-json --verbose
|
|
6
|
+
* [--resume <sessionId>] [--append-system-prompt <briefing>]
|
|
7
|
+
* --permission-mode <mode>
|
|
8
|
+
*
|
|
9
|
+
* Surface verified against claude 2.1.83 — see docs/integration-notes.md.
|
|
10
|
+
*/
|
|
11
|
+
import type { SendInput } from "../types.js";
|
|
12
|
+
import { AdapterBase } from "./base.js";
|
|
13
|
+
export declare class ClaudeCodeAdapter extends AdapterBase {
|
|
14
|
+
private child;
|
|
15
|
+
private options;
|
|
16
|
+
constructor(id: string, projectDir: string, options?: Record<string, unknown>);
|
|
17
|
+
private get sessionId();
|
|
18
|
+
private set sessionId(value);
|
|
19
|
+
private get bin();
|
|
20
|
+
available(): Promise<boolean>;
|
|
21
|
+
start(): Promise<void>;
|
|
22
|
+
stop(): Promise<void>;
|
|
23
|
+
send(input: SendInput): Promise<void>;
|
|
24
|
+
private handleStreamEvent;
|
|
25
|
+
interrupt(): Promise<void>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code adapter — drives the `claude` CLI headless, one process per
|
|
3
|
+
* turn, resuming the same session id across turns.
|
|
4
|
+
*
|
|
5
|
+
* claude -p "<text>" --output-format stream-json --verbose
|
|
6
|
+
* [--resume <sessionId>] [--append-system-prompt <briefing>]
|
|
7
|
+
* --permission-mode <mode>
|
|
8
|
+
*
|
|
9
|
+
* Surface verified against claude 2.1.83 — see docs/integration-notes.md.
|
|
10
|
+
*/
|
|
11
|
+
import { spawn } from "node:child_process";
|
|
12
|
+
import readline from "node:readline";
|
|
13
|
+
import { readProjectState, writeProjectState } from "../core/registry.js";
|
|
14
|
+
import { AdapterBase, agentEnv, cliAvailable } from "./base.js";
|
|
15
|
+
export class ClaudeCodeAdapter extends AdapterBase {
|
|
16
|
+
child = null;
|
|
17
|
+
options;
|
|
18
|
+
constructor(id, projectDir, options = {}) {
|
|
19
|
+
super(id, "claude-code", projectDir);
|
|
20
|
+
this.options = options;
|
|
21
|
+
}
|
|
22
|
+
get sessionId() {
|
|
23
|
+
const state = readProjectState(this.projectDir);
|
|
24
|
+
return state.agents[this.id]?.sessionId;
|
|
25
|
+
}
|
|
26
|
+
set sessionId(value) {
|
|
27
|
+
const state = readProjectState(this.projectDir);
|
|
28
|
+
state.agents[this.id] = { ...state.agents[this.id], sessionId: value };
|
|
29
|
+
writeProjectState(this.projectDir, state);
|
|
30
|
+
}
|
|
31
|
+
get bin() {
|
|
32
|
+
return this.options.bin ?? "claude";
|
|
33
|
+
}
|
|
34
|
+
async available() {
|
|
35
|
+
return cliAvailable(this.bin);
|
|
36
|
+
}
|
|
37
|
+
async start() {
|
|
38
|
+
this.emit({ kind: "status", payload: { state: "ready", session: this.sessionId ?? null } });
|
|
39
|
+
}
|
|
40
|
+
async stop() {
|
|
41
|
+
await this.interrupt();
|
|
42
|
+
}
|
|
43
|
+
async send(input) {
|
|
44
|
+
if (this._busy)
|
|
45
|
+
throw new Error(`claude-code agent "${this.id}" is busy`);
|
|
46
|
+
this._busy = true;
|
|
47
|
+
const started = Date.now();
|
|
48
|
+
const args = [
|
|
49
|
+
"-p",
|
|
50
|
+
input.text,
|
|
51
|
+
"--output-format",
|
|
52
|
+
"stream-json",
|
|
53
|
+
"--verbose",
|
|
54
|
+
"--permission-mode",
|
|
55
|
+
this.options.permissionMode ?? "acceptEdits",
|
|
56
|
+
];
|
|
57
|
+
if (this.sessionId)
|
|
58
|
+
args.push("--resume", this.sessionId);
|
|
59
|
+
if (input.briefing)
|
|
60
|
+
args.push("--append-system-prompt", input.briefing);
|
|
61
|
+
if (this.options.model)
|
|
62
|
+
args.push("--model", this.options.model);
|
|
63
|
+
if (this.options.extraArgs)
|
|
64
|
+
args.push(...this.options.extraArgs);
|
|
65
|
+
try {
|
|
66
|
+
await new Promise((resolve, reject) => {
|
|
67
|
+
const child = spawn(this.bin, args, {
|
|
68
|
+
cwd: this.projectDir,
|
|
69
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
70
|
+
env: agentEnv(),
|
|
71
|
+
});
|
|
72
|
+
this.child = child;
|
|
73
|
+
let lastAssistantText = "";
|
|
74
|
+
let sawResult = false;
|
|
75
|
+
let stderrTail = "";
|
|
76
|
+
const rl = readline.createInterface({ input: child.stdout });
|
|
77
|
+
rl.on("line", (line) => {
|
|
78
|
+
const trimmed = line.trim();
|
|
79
|
+
if (!trimmed.startsWith("{"))
|
|
80
|
+
return;
|
|
81
|
+
let evt;
|
|
82
|
+
try {
|
|
83
|
+
evt = JSON.parse(trimmed);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.handleStreamEvent(evt, (t) => (lastAssistantText = t));
|
|
89
|
+
if (evt.type === "result")
|
|
90
|
+
sawResult = true;
|
|
91
|
+
});
|
|
92
|
+
child.stderr.on("data", (d) => {
|
|
93
|
+
stderrTail = (stderrTail + d.toString()).slice(-2000);
|
|
94
|
+
});
|
|
95
|
+
child.on("error", (err) => reject(err));
|
|
96
|
+
child.on("close", (code, signal) => {
|
|
97
|
+
this.child = null;
|
|
98
|
+
if (signal) {
|
|
99
|
+
this.emit({ kind: "status", payload: { state: "interrupted", signal } });
|
|
100
|
+
resolve();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (code !== 0 && !sawResult) {
|
|
104
|
+
this.emit({
|
|
105
|
+
kind: "error",
|
|
106
|
+
payload: { message: `${this.bin} exited ${code}`, stderr: stderrTail },
|
|
107
|
+
});
|
|
108
|
+
reject(new Error(`${this.bin} exited ${code}: ${stderrTail.slice(0, 200)}`));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// Blocked-on-human heuristic: the turn ended on a question.
|
|
112
|
+
if (/\?\s*$/.test(lastAssistantText.trim())) {
|
|
113
|
+
this.emit({
|
|
114
|
+
kind: "needs_input",
|
|
115
|
+
payload: { question: lastAssistantText.slice(-500) },
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
this.emit({
|
|
119
|
+
kind: "run_complete",
|
|
120
|
+
payload: { durationMs: Date.now() - started },
|
|
121
|
+
});
|
|
122
|
+
resolve();
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
finally {
|
|
127
|
+
this._busy = false;
|
|
128
|
+
this.child = null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
handleStreamEvent(evt, setLastText) {
|
|
132
|
+
const type = evt.type;
|
|
133
|
+
if (type === "system" && evt.subtype === "init") {
|
|
134
|
+
const sid = evt.session_id;
|
|
135
|
+
if (sid)
|
|
136
|
+
this.sessionId = sid;
|
|
137
|
+
this.emit({ kind: "status", payload: { state: "turn_started", session: sid ?? null } });
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (type === "assistant") {
|
|
141
|
+
const message = evt.message;
|
|
142
|
+
for (const block of message?.content ?? []) {
|
|
143
|
+
if (block.type === "text" && typeof block.text === "string" && block.text.trim()) {
|
|
144
|
+
setLastText(block.text);
|
|
145
|
+
this.emit({ kind: "message", payload: { text: block.text } });
|
|
146
|
+
}
|
|
147
|
+
else if (block.type === "thinking" && typeof block.thinking === "string" && block.thinking.trim()) {
|
|
148
|
+
// Extended thinking. Emitted as a reasoning-tagged message so the UI
|
|
149
|
+
// can fold it into its "thinking" block, the same shape codex and
|
|
150
|
+
// grok use. It never becomes lastAssistantText (that's the reply).
|
|
151
|
+
this.emit({ kind: "message", payload: { text: block.thinking, reasoning: true } });
|
|
152
|
+
}
|
|
153
|
+
else if (block.type === "tool_use") {
|
|
154
|
+
const name = String(block.name ?? "tool");
|
|
155
|
+
const input = (block.input ?? {});
|
|
156
|
+
this.emit({
|
|
157
|
+
kind: "tool_call",
|
|
158
|
+
payload: { tool: name, summary: summarizeToolInput(name, input) },
|
|
159
|
+
});
|
|
160
|
+
const path = input.file_path ?? input.notebook_path;
|
|
161
|
+
if (["Edit", "Write", "NotebookEdit", "MultiEdit"].includes(name) && path) {
|
|
162
|
+
this.emit({ kind: "file_edit", payload: { path: String(path), tool: name } });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (type === "result") {
|
|
169
|
+
const cost = evt.total_cost_usd;
|
|
170
|
+
const isError = Boolean(evt.is_error);
|
|
171
|
+
if (isError) {
|
|
172
|
+
this.emit({
|
|
173
|
+
kind: "error",
|
|
174
|
+
payload: { message: String(evt.result ?? evt.subtype ?? "unknown error") },
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
if (cost !== undefined) {
|
|
178
|
+
this.emit({ kind: "status", payload: { state: "turn_cost", costUsd: cost } });
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async interrupt() {
|
|
183
|
+
const child = this.child;
|
|
184
|
+
if (!child)
|
|
185
|
+
return;
|
|
186
|
+
child.kill("SIGINT");
|
|
187
|
+
await new Promise((resolve) => {
|
|
188
|
+
const t = setTimeout(() => {
|
|
189
|
+
try {
|
|
190
|
+
child.kill("SIGKILL");
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// already gone
|
|
194
|
+
}
|
|
195
|
+
resolve();
|
|
196
|
+
}, 3000);
|
|
197
|
+
child.on("close", () => {
|
|
198
|
+
clearTimeout(t);
|
|
199
|
+
resolve();
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function summarizeToolInput(name, input) {
|
|
205
|
+
const interesting = input.file_path ?? input.command ?? input.pattern ?? input.url ?? input.prompt ?? "";
|
|
206
|
+
const text = String(interesting).replace(/\s+/g, " ");
|
|
207
|
+
return `${name}: ${text.slice(0, 160)}`;
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=claude-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/adapters/claude-code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex adapter — drives the `codex` CLI headless, one process per turn,
|
|
3
|
+
* resuming the same thread across turns.
|
|
4
|
+
*
|
|
5
|
+
* codex exec --json --skip-git-repo-check -C <dir> -s <sandbox> "<text>"
|
|
6
|
+
* codex exec resume <threadId> --json … "<text>"
|
|
7
|
+
*
|
|
8
|
+
* The CLI ships inside the desktop app as well as on PATH, so `available()`
|
|
9
|
+
* looks in both places — a Mac with Codex.app installed and nothing on PATH is
|
|
10
|
+
* the common case, and refusing to find it there would be wrong.
|
|
11
|
+
*
|
|
12
|
+
* Event surface verified against codex-cli 0.142.4 by running it and reading
|
|
13
|
+
* what came out, not by guessing:
|
|
14
|
+
*
|
|
15
|
+
* {"type":"thread.started","thread_id":"019f…"}
|
|
16
|
+
* {"type":"turn.started"}
|
|
17
|
+
* {"type":"item.started","item":{"id":"item_1","type":"command_execution",…}}
|
|
18
|
+
* {"type":"item.completed","item":{"id":"item_1","type":"command_execution",
|
|
19
|
+
* "command":"/bin/zsh -lc 'echo hi'","aggregated_output":"hi\n","exit_code":0}}
|
|
20
|
+
* {"type":"item.completed","item":{"id":"item_2","type":"agent_message","text":"…"}}
|
|
21
|
+
* {"type":"item.completed","item":{"id":"item_3","type":"file_change",
|
|
22
|
+
* "changes":[{"path":"/abs/note.txt","kind":"add"}]}}
|
|
23
|
+
* {"type":"turn.completed","usage":{"input_tokens":52831,"output_tokens":120,…}}
|
|
24
|
+
*
|
|
25
|
+
* Note what is NOT in there: money. Codex reports tokens, never a dollar
|
|
26
|
+
* figure, so this adapter reports tokens and no cost. Inventing a USD number
|
|
27
|
+
* from a price table we'd have to keep current is how you end up with a fake
|
|
28
|
+
* $0.001 in the UI presented as fact.
|
|
29
|
+
*/
|
|
30
|
+
import type { SendInput } from "../types.js";
|
|
31
|
+
import { AdapterBase } from "./base.js";
|
|
32
|
+
/**
|
|
33
|
+
* Where the codex CLI is on this machine: an explicit override, then PATH,
|
|
34
|
+
* then inside the app bundle.
|
|
35
|
+
*/
|
|
36
|
+
export declare function codexBin(override?: string): string | null;
|
|
37
|
+
export declare class CodexAdapter extends AdapterBase {
|
|
38
|
+
private child;
|
|
39
|
+
private options;
|
|
40
|
+
constructor(id: string, projectDir: string, options?: Record<string, unknown>);
|
|
41
|
+
/** Codex calls it a thread; loom stores it in the same slot as any session. */
|
|
42
|
+
private get threadId();
|
|
43
|
+
private set threadId(value);
|
|
44
|
+
available(): Promise<boolean>;
|
|
45
|
+
start(): Promise<void>;
|
|
46
|
+
stop(): Promise<void>;
|
|
47
|
+
send(input: SendInput): Promise<void>;
|
|
48
|
+
private handleEvent;
|
|
49
|
+
private handleItem;
|
|
50
|
+
interrupt(): Promise<void>;
|
|
51
|
+
}
|