@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,291 @@
|
|
|
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 { spawn } from "node:child_process";
|
|
31
|
+
import fs from "node:fs";
|
|
32
|
+
import readline from "node:readline";
|
|
33
|
+
import { readProjectState, writeProjectState } from "../core/registry.js";
|
|
34
|
+
import { AdapterBase, agentEnv, cliAvailable, frameBriefing } from "./base.js";
|
|
35
|
+
/** The CLI bundled inside the desktop app, per platform. */
|
|
36
|
+
const BUNDLED = [
|
|
37
|
+
"/Applications/Codex.app/Contents/Resources/codex",
|
|
38
|
+
`${process.env.HOME ?? ""}/Applications/Codex.app/Contents/Resources/codex`,
|
|
39
|
+
];
|
|
40
|
+
/**
|
|
41
|
+
* Where the codex CLI is on this machine: an explicit override, then PATH,
|
|
42
|
+
* then inside the app bundle.
|
|
43
|
+
*/
|
|
44
|
+
export function codexBin(override) {
|
|
45
|
+
if (override)
|
|
46
|
+
return fs.existsSync(override) ? override : null;
|
|
47
|
+
for (const p of BUNDLED) {
|
|
48
|
+
if (fs.existsSync(p))
|
|
49
|
+
return p;
|
|
50
|
+
}
|
|
51
|
+
return "codex"; // let PATH resolution (and cliAvailable) decide
|
|
52
|
+
}
|
|
53
|
+
export class CodexAdapter extends AdapterBase {
|
|
54
|
+
child = null;
|
|
55
|
+
options;
|
|
56
|
+
constructor(id, projectDir, options = {}) {
|
|
57
|
+
super(id, "codex", projectDir);
|
|
58
|
+
this.options = options;
|
|
59
|
+
}
|
|
60
|
+
/** Codex calls it a thread; loom stores it in the same slot as any session. */
|
|
61
|
+
get threadId() {
|
|
62
|
+
const state = readProjectState(this.projectDir);
|
|
63
|
+
return state.agents[this.id]?.sessionId;
|
|
64
|
+
}
|
|
65
|
+
set threadId(value) {
|
|
66
|
+
const state = readProjectState(this.projectDir);
|
|
67
|
+
state.agents[this.id] = { ...state.agents[this.id], sessionId: value };
|
|
68
|
+
writeProjectState(this.projectDir, state);
|
|
69
|
+
}
|
|
70
|
+
async available() {
|
|
71
|
+
const bin = codexBin(this.options.bin);
|
|
72
|
+
if (!bin)
|
|
73
|
+
return false;
|
|
74
|
+
return cliAvailable(bin);
|
|
75
|
+
}
|
|
76
|
+
async start() {
|
|
77
|
+
this.emit({ kind: "status", payload: { state: "ready", session: this.threadId ?? null } });
|
|
78
|
+
}
|
|
79
|
+
async stop() {
|
|
80
|
+
await this.interrupt();
|
|
81
|
+
}
|
|
82
|
+
async send(input) {
|
|
83
|
+
if (this._busy)
|
|
84
|
+
throw new Error(`codex agent "${this.id}" is busy`);
|
|
85
|
+
const bin = codexBin(this.options.bin);
|
|
86
|
+
if (!bin)
|
|
87
|
+
throw new Error("codex CLI not found — install it or open Codex.app once");
|
|
88
|
+
this._busy = true;
|
|
89
|
+
const started = Date.now();
|
|
90
|
+
// Codex exec has no --append-system-prompt, so the briefing rides in front
|
|
91
|
+
// of the text — but framed as an unmissable authoritative block (see
|
|
92
|
+
// frameBriefing), not a loose preamble the model skims past.
|
|
93
|
+
const text = input.briefing ? `${frameBriefing(input.briefing)}\n\n${input.text}` : input.text;
|
|
94
|
+
const args = this.threadId
|
|
95
|
+
? ["exec", "resume", this.threadId]
|
|
96
|
+
: ["exec"];
|
|
97
|
+
args.push("--json", "--skip-git-repo-check", "-C", this.projectDir, "-s", this.options.sandbox ?? "workspace-write");
|
|
98
|
+
if (this.options.model)
|
|
99
|
+
args.push("-m", this.options.model);
|
|
100
|
+
if (this.options.extraArgs)
|
|
101
|
+
args.push(...this.options.extraArgs);
|
|
102
|
+
args.push(text);
|
|
103
|
+
try {
|
|
104
|
+
await new Promise((resolve, reject) => {
|
|
105
|
+
const child = spawn(bin, args, {
|
|
106
|
+
cwd: this.projectDir,
|
|
107
|
+
// stdin closed: with a pipe open, `codex exec` waits on stdin for
|
|
108
|
+
// additional input and the turn never starts.
|
|
109
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
110
|
+
env: agentEnv(),
|
|
111
|
+
});
|
|
112
|
+
this.child = child;
|
|
113
|
+
let lastMessage = "";
|
|
114
|
+
let sawTurn = false;
|
|
115
|
+
let stderrTail = "";
|
|
116
|
+
const rl = readline.createInterface({ input: child.stdout });
|
|
117
|
+
rl.on("line", (line) => {
|
|
118
|
+
const trimmed = line.trim();
|
|
119
|
+
if (!trimmed.startsWith("{"))
|
|
120
|
+
return;
|
|
121
|
+
let evt;
|
|
122
|
+
try {
|
|
123
|
+
evt = JSON.parse(trimmed);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
this.handleEvent(evt, (t) => (lastMessage = t));
|
|
129
|
+
if (evt.type === "turn.completed")
|
|
130
|
+
sawTurn = true;
|
|
131
|
+
});
|
|
132
|
+
child.stderr.on("data", (d) => {
|
|
133
|
+
stderrTail = (stderrTail + d.toString()).slice(-2000);
|
|
134
|
+
});
|
|
135
|
+
child.on("error", (err) => reject(err));
|
|
136
|
+
child.on("close", (code, signal) => {
|
|
137
|
+
this.child = null;
|
|
138
|
+
if (signal) {
|
|
139
|
+
this.emit({ kind: "status", payload: { state: "interrupted", signal } });
|
|
140
|
+
resolve();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (code !== 0 && !sawTurn) {
|
|
144
|
+
this.emit({
|
|
145
|
+
kind: "error",
|
|
146
|
+
payload: { message: `codex exited ${code}`, stderr: stderrTail },
|
|
147
|
+
});
|
|
148
|
+
reject(new Error(`codex exited ${code}: ${stderrTail.slice(0, 200)}`));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// Same blocked-on-human heuristic the other adapters use: the turn
|
|
152
|
+
// ended on a question, so the baton is really with you.
|
|
153
|
+
if (/\?\s*$/.test(lastMessage.trim())) {
|
|
154
|
+
this.emit({ kind: "needs_input", payload: { question: lastMessage.slice(-500) } });
|
|
155
|
+
}
|
|
156
|
+
this.emit({ kind: "run_complete", payload: { durationMs: Date.now() - started } });
|
|
157
|
+
resolve();
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
this._busy = false;
|
|
163
|
+
this.child = null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
handleEvent(evt, setLast) {
|
|
167
|
+
const type = evt.type;
|
|
168
|
+
if (type === "thread.started") {
|
|
169
|
+
const id = evt.thread_id;
|
|
170
|
+
if (id)
|
|
171
|
+
this.threadId = id;
|
|
172
|
+
this.emit({ kind: "status", payload: { state: "turn_started", session: id ?? null } });
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (type === "item.completed" || type === "item.started") {
|
|
176
|
+
const item = (evt.item ?? {});
|
|
177
|
+
// Only completed items are reported: an in_progress command has no exit
|
|
178
|
+
// code yet, and a half-written file_change has nothing useful to say.
|
|
179
|
+
if (type !== "item.completed")
|
|
180
|
+
return;
|
|
181
|
+
this.handleItem(item, setLast);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (type === "turn.completed") {
|
|
185
|
+
const usage = (evt.usage ?? {});
|
|
186
|
+
this.emit({
|
|
187
|
+
kind: "status",
|
|
188
|
+
payload: {
|
|
189
|
+
state: "turn_tokens",
|
|
190
|
+
inputTokens: usage.input_tokens ?? 0,
|
|
191
|
+
cachedInputTokens: usage.cached_input_tokens ?? 0,
|
|
192
|
+
outputTokens: usage.output_tokens ?? 0,
|
|
193
|
+
reasoningTokens: usage.reasoning_output_tokens ?? 0,
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (type === "turn.failed" || type === "error") {
|
|
199
|
+
const err = (evt.error ?? evt);
|
|
200
|
+
this.emit({ kind: "error", payload: { message: String(err.message ?? "codex failed") } });
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
handleItem(item, setLast) {
|
|
204
|
+
switch (item.type) {
|
|
205
|
+
case "agent_message": {
|
|
206
|
+
const text = String(item.text ?? "");
|
|
207
|
+
if (!text.trim())
|
|
208
|
+
return;
|
|
209
|
+
setLast(text);
|
|
210
|
+
this.emit({ kind: "message", payload: { text } });
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
case "reasoning": {
|
|
214
|
+
const text = String(item.text ?? "").trim();
|
|
215
|
+
if (text)
|
|
216
|
+
this.emit({ kind: "message", payload: { text, reasoning: true } });
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
case "command_execution": {
|
|
220
|
+
const command = String(item.command ?? "");
|
|
221
|
+
const exit = item.exit_code;
|
|
222
|
+
this.emit({
|
|
223
|
+
kind: "tool_call",
|
|
224
|
+
payload: {
|
|
225
|
+
tool: "shell",
|
|
226
|
+
summary: `shell: ${command.replace(/\s+/g, " ").slice(0, 160)}`,
|
|
227
|
+
exitCode: typeof exit === "number" ? exit : null,
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
case "file_change": {
|
|
233
|
+
const changes = (item.changes ?? []);
|
|
234
|
+
for (const c of changes) {
|
|
235
|
+
if (!c.path)
|
|
236
|
+
continue;
|
|
237
|
+
this.emit({
|
|
238
|
+
kind: "file_edit",
|
|
239
|
+
payload: { path: String(c.path), tool: `file_change:${c.kind ?? "edit"}` },
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
case "mcp_tool_call": {
|
|
245
|
+
this.emit({
|
|
246
|
+
kind: "tool_call",
|
|
247
|
+
payload: { tool: String(item.tool ?? "mcp"), summary: `mcp: ${String(item.tool ?? "")}` },
|
|
248
|
+
});
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
case "web_search": {
|
|
252
|
+
this.emit({
|
|
253
|
+
kind: "tool_call",
|
|
254
|
+
payload: { tool: "web_search", summary: `search: ${String(item.query ?? "")}`.slice(0, 160) },
|
|
255
|
+
});
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
case "error": {
|
|
259
|
+
this.emit({ kind: "error", payload: { message: String(item.message ?? "codex error") } });
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
default:
|
|
263
|
+
// todo_list and whatever Codex adds next: not every item is worth an
|
|
264
|
+
// event, and inventing a rendering for one we don't understand is worse
|
|
265
|
+
// than staying quiet.
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
async interrupt() {
|
|
270
|
+
const child = this.child;
|
|
271
|
+
if (!child)
|
|
272
|
+
return;
|
|
273
|
+
child.kill("SIGINT");
|
|
274
|
+
await new Promise((resolve) => {
|
|
275
|
+
const t = setTimeout(() => {
|
|
276
|
+
try {
|
|
277
|
+
child.kill("SIGKILL");
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
// already gone
|
|
281
|
+
}
|
|
282
|
+
resolve();
|
|
283
|
+
}, 3000);
|
|
284
|
+
child.on("close", () => {
|
|
285
|
+
clearTimeout(t);
|
|
286
|
+
resolve();
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/adapters/codex.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Echo adapter — a deterministic in-process agent used by tests and demos.
|
|
3
|
+
* It behaves like a full-duplex adapter: streams a message, then completes.
|
|
4
|
+
*
|
|
5
|
+
* Prompt tricks (for exercising the machinery without a real model):
|
|
6
|
+
* - text containing "make a plan" → replies in planner voice ("plan is complete")
|
|
7
|
+
* - text containing "sleep:<ms>" → stays busy that long (interrupt testing)
|
|
8
|
+
* - text containing "ask: <q>" → asks the human (needs_input; route pausing)
|
|
9
|
+
* - text containing "write:<path>" → writes a small file (turn_diff testing)
|
|
10
|
+
*/
|
|
11
|
+
import type { SendInput } from "../types.js";
|
|
12
|
+
import { AdapterBase } from "./base.js";
|
|
13
|
+
export declare class EchoAdapter extends AdapterBase {
|
|
14
|
+
private aborted;
|
|
15
|
+
available(): Promise<boolean>;
|
|
16
|
+
start(): Promise<void>;
|
|
17
|
+
stop(): Promise<void>;
|
|
18
|
+
send(input: SendInput): Promise<void>;
|
|
19
|
+
interrupt(): Promise<void>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Echo adapter — a deterministic in-process agent used by tests and demos.
|
|
3
|
+
* It behaves like a full-duplex adapter: streams a message, then completes.
|
|
4
|
+
*
|
|
5
|
+
* Prompt tricks (for exercising the machinery without a real model):
|
|
6
|
+
* - text containing "make a plan" → replies in planner voice ("plan is complete")
|
|
7
|
+
* - text containing "sleep:<ms>" → stays busy that long (interrupt testing)
|
|
8
|
+
* - text containing "ask: <q>" → asks the human (needs_input; route pausing)
|
|
9
|
+
* - text containing "write:<path>" → writes a small file (turn_diff testing)
|
|
10
|
+
*/
|
|
11
|
+
import fs from "node:fs";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
import { AdapterBase } from "./base.js";
|
|
14
|
+
export class EchoAdapter extends AdapterBase {
|
|
15
|
+
aborted = false;
|
|
16
|
+
async available() {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
async start() {
|
|
20
|
+
this.emit({ kind: "status", payload: { state: "started" } });
|
|
21
|
+
}
|
|
22
|
+
async stop() {
|
|
23
|
+
this.emit({ kind: "status", payload: { state: "stopped" } });
|
|
24
|
+
}
|
|
25
|
+
async send(input) {
|
|
26
|
+
if (this._busy)
|
|
27
|
+
throw new Error(`echo agent "${this.id}" is busy`);
|
|
28
|
+
this._busy = true;
|
|
29
|
+
this.aborted = false;
|
|
30
|
+
const started = Date.now();
|
|
31
|
+
try {
|
|
32
|
+
const sleepMatch = input.text.match(/sleep:(\d+)/);
|
|
33
|
+
if (sleepMatch) {
|
|
34
|
+
const ms = Math.min(Number(sleepMatch[1]), 60_000);
|
|
35
|
+
const deadline = Date.now() + ms;
|
|
36
|
+
while (Date.now() < deadline && !this.aborted) {
|
|
37
|
+
await new Promise((r) => setTimeout(r, 20));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
await new Promise((r) => setTimeout(r, 25));
|
|
42
|
+
}
|
|
43
|
+
if (this.aborted) {
|
|
44
|
+
this.emit({ kind: "status", payload: { state: "interrupted" } });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const writeMatch = input.text.match(/write:([\w./-]+)/);
|
|
48
|
+
if (writeMatch && !writeMatch[1].includes("..")) {
|
|
49
|
+
const target = path.join(this.projectDir, writeMatch[1]);
|
|
50
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
51
|
+
fs.writeFileSync(target, `echo(${this.id}) wrote this\n`);
|
|
52
|
+
this.emit({ kind: "file_edit", payload: { path: writeMatch[1] } });
|
|
53
|
+
}
|
|
54
|
+
const briefingNote = input.briefing ? ` (briefed: ${input.briefing.length} chars)` : "";
|
|
55
|
+
const text = /make a plan/i.test(input.text)
|
|
56
|
+
? `Here is the approach. 1) analyze 2) implement 3) verify. The plan is complete and ready to execute.${briefingNote}`
|
|
57
|
+
: `echo(${this.id}): ${input.text}${briefingNote}`;
|
|
58
|
+
this.emit({ kind: "message", payload: { text } });
|
|
59
|
+
// Lookbehind so "Task:" (…t-ask:) doesn't read as a question.
|
|
60
|
+
const askMatch = input.text.match(/(?<![a-z])ask:\s*([^\n]+)/i);
|
|
61
|
+
if (askMatch) {
|
|
62
|
+
this.emit({ kind: "needs_input", payload: { question: askMatch[1].trim() } });
|
|
63
|
+
}
|
|
64
|
+
// Deterministic fake cost so telemetry is exercisable without a model.
|
|
65
|
+
this.emit({ kind: "status", payload: { state: "turn_cost", costUsd: 0.001 } });
|
|
66
|
+
this.emit({
|
|
67
|
+
kind: "run_complete",
|
|
68
|
+
payload: { durationMs: Date.now() - started, costUsd: 0.001 },
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
this._busy = false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async interrupt() {
|
|
76
|
+
this.aborted = true;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=echo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"echo.js","sourceRoot":"","sources":["../../src/adapters/echo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grok Code adapter — drives the `grok` CLI single-turn, resuming the same
|
|
3
|
+
* session across turns.
|
|
4
|
+
*
|
|
5
|
+
* grok -p "<text>" --output-format json --cwd <dir>
|
|
6
|
+
* --permission-mode acceptEdits [-r <sessionId>]
|
|
7
|
+
*
|
|
8
|
+
* Surface verified against grok 0.2.54 by running it:
|
|
9
|
+
*
|
|
10
|
+
* {"text":"ok","stopReason":"EndTurn","sessionId":"019f…",
|
|
11
|
+
* "requestId":"02a6…","thought":"The user wants me to…"}
|
|
12
|
+
*
|
|
13
|
+
* ## What this adapter cannot show you
|
|
14
|
+
*
|
|
15
|
+
* Grok's turn is a black box with an answer at the end. `--output-format
|
|
16
|
+
* streaming-json` sounds like it would help and doesn't: it emits `thought` and
|
|
17
|
+
* `text` token deltas and a final `end`, and nothing else — no tool calls, no
|
|
18
|
+
* file edits, not even when the turn demonstrably ran `echo` and wrote a file.
|
|
19
|
+
* The steps simply aren't reported by the CLI.
|
|
20
|
+
*
|
|
21
|
+
* So Loom shows grok's answer and its reasoning, and no tool_call or file_edit
|
|
22
|
+
* events, because there are none to be had. The alternative — inferring edits by
|
|
23
|
+
* diffing the tree and attributing them to grok — would put guesses in the event
|
|
24
|
+
* log wearing the same clothes as facts. The thread stays honest instead: with
|
|
25
|
+
* grok you see what it said, and `git status` tells you what changed.
|
|
26
|
+
*
|
|
27
|
+
* Streaming deltas are deliberately not used. Every Loom message is an event on
|
|
28
|
+
* a persisted log; one event per token would turn a paragraph into 200 rows.
|
|
29
|
+
*/
|
|
30
|
+
import type { SendInput } from "../types.js";
|
|
31
|
+
import { AdapterBase } from "./base.js";
|
|
32
|
+
export declare function grokBin(override?: string): string | null;
|
|
33
|
+
interface GrokResult {
|
|
34
|
+
text?: string;
|
|
35
|
+
thought?: string;
|
|
36
|
+
stopReason?: string;
|
|
37
|
+
sessionId?: string;
|
|
38
|
+
error?: string;
|
|
39
|
+
message?: string;
|
|
40
|
+
}
|
|
41
|
+
export declare class GrokAdapter extends AdapterBase {
|
|
42
|
+
private child;
|
|
43
|
+
private options;
|
|
44
|
+
constructor(id: string, projectDir: string, options?: Record<string, unknown>);
|
|
45
|
+
private get sessionId();
|
|
46
|
+
private set sessionId(value);
|
|
47
|
+
available(): Promise<boolean>;
|
|
48
|
+
start(): Promise<void>;
|
|
49
|
+
stop(): Promise<void>;
|
|
50
|
+
send(input: SendInput): Promise<void>;
|
|
51
|
+
interrupt(): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Pull grok's result object out of stdout.
|
|
55
|
+
*
|
|
56
|
+
* It pretty-prints one JSON object, but anything the CLI decides to log first
|
|
57
|
+
* lands on the same stream, so the object is found rather than assumed: last
|
|
58
|
+
* balanced `{…}` wins.
|
|
59
|
+
*/
|
|
60
|
+
export declare function parseGrokJson(stdout: string): GrokResult | null;
|
|
61
|
+
export {};
|