@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.
Files changed (177) hide show
  1. package/ARCHITECTURE.md +211 -0
  2. package/CHANGELOG.md +470 -0
  3. package/LICENSE +21 -0
  4. package/README.md +630 -0
  5. package/dist/adapters/base.d.ts +71 -0
  6. package/dist/adapters/base.js +187 -0
  7. package/dist/adapters/base.js.map +1 -0
  8. package/dist/adapters/bridges/antigravity.d.ts +53 -0
  9. package/dist/adapters/bridges/antigravity.js +106 -0
  10. package/dist/adapters/bridges/antigravity.js.map +1 -0
  11. package/dist/adapters/bridges/cdp.d.ts +82 -0
  12. package/dist/adapters/bridges/cdp.js +222 -0
  13. package/dist/adapters/bridges/cdp.js.map +1 -0
  14. package/dist/adapters/bridges/gui-chat.d.ts +113 -0
  15. package/dist/adapters/bridges/gui-chat.js +498 -0
  16. package/dist/adapters/bridges/gui-chat.js.map +1 -0
  17. package/dist/adapters/bridges/kiro.d.ts +19 -0
  18. package/dist/adapters/bridges/kiro.js +22 -0
  19. package/dist/adapters/bridges/kiro.js.map +1 -0
  20. package/dist/adapters/bridges/profiles.d.ts +82 -0
  21. package/dist/adapters/bridges/profiles.js +125 -0
  22. package/dist/adapters/bridges/profiles.js.map +1 -0
  23. package/dist/adapters/claude-code.d.ts +26 -0
  24. package/dist/adapters/claude-code.js +209 -0
  25. package/dist/adapters/claude-code.js.map +1 -0
  26. package/dist/adapters/codex.d.ts +51 -0
  27. package/dist/adapters/codex.js +291 -0
  28. package/dist/adapters/codex.js.map +1 -0
  29. package/dist/adapters/echo.d.ts +20 -0
  30. package/dist/adapters/echo.js +79 -0
  31. package/dist/adapters/echo.js.map +1 -0
  32. package/dist/adapters/grok.d.ts +61 -0
  33. package/dist/adapters/grok.js +217 -0
  34. package/dist/adapters/grok.js.map +1 -0
  35. package/dist/adapters/index.d.ts +9 -0
  36. package/dist/adapters/index.js +33 -0
  37. package/dist/adapters/index.js.map +1 -0
  38. package/dist/adapters/opencode.d.ts +64 -0
  39. package/dist/adapters/opencode.js +426 -0
  40. package/dist/adapters/opencode.js.map +1 -0
  41. package/dist/cli/common.d.ts +11 -0
  42. package/dist/cli/common.js +40 -0
  43. package/dist/cli/common.js.map +1 -0
  44. package/dist/cli/doctor.d.ts +12 -0
  45. package/dist/cli/doctor.js +181 -0
  46. package/dist/cli/doctor.js.map +1 -0
  47. package/dist/cli/index.d.ts +8 -0
  48. package/dist/cli/index.js +641 -0
  49. package/dist/cli/index.js.map +1 -0
  50. package/dist/cli/tui-model.d.ts +73 -0
  51. package/dist/cli/tui-model.js +312 -0
  52. package/dist/cli/tui-model.js.map +1 -0
  53. package/dist/cli/tui.d.ts +15 -0
  54. package/dist/cli/tui.js +451 -0
  55. package/dist/cli/tui.js.map +1 -0
  56. package/dist/cli/ui.d.ts +10 -0
  57. package/dist/cli/ui.js +135 -0
  58. package/dist/cli/ui.js.map +1 -0
  59. package/dist/core/ades.d.ts +79 -0
  60. package/dist/core/ades.js +130 -0
  61. package/dist/core/ades.js.map +1 -0
  62. package/dist/core/baton.d.ts +37 -0
  63. package/dist/core/baton.js +92 -0
  64. package/dist/core/baton.js.map +1 -0
  65. package/dist/core/brain-extract.d.ts +111 -0
  66. package/dist/core/brain-extract.js +248 -0
  67. package/dist/core/brain-extract.js.map +1 -0
  68. package/dist/core/brain-index.d.ts +128 -0
  69. package/dist/core/brain-index.js +338 -0
  70. package/dist/core/brain-index.js.map +1 -0
  71. package/dist/core/brain.d.ts +214 -0
  72. package/dist/core/brain.js +425 -0
  73. package/dist/core/brain.js.map +1 -0
  74. package/dist/core/claude-cli.d.ts +12 -0
  75. package/dist/core/claude-cli.js +47 -0
  76. package/dist/core/claude-cli.js.map +1 -0
  77. package/dist/core/distill.d.ts +19 -0
  78. package/dist/core/distill.js +88 -0
  79. package/dist/core/distill.js.map +1 -0
  80. package/dist/core/eventlog.d.ts +43 -0
  81. package/dist/core/eventlog.js +211 -0
  82. package/dist/core/eventlog.js.map +1 -0
  83. package/dist/core/git.d.ts +203 -0
  84. package/dist/core/git.js +460 -0
  85. package/dist/core/git.js.map +1 -0
  86. package/dist/core/logbook.d.ts +59 -0
  87. package/dist/core/logbook.js +118 -0
  88. package/dist/core/logbook.js.map +1 -0
  89. package/dist/core/memory.d.ts +34 -0
  90. package/dist/core/memory.js +124 -0
  91. package/dist/core/memory.js.map +1 -0
  92. package/dist/core/notify.d.ts +11 -0
  93. package/dist/core/notify.js +30 -0
  94. package/dist/core/notify.js.map +1 -0
  95. package/dist/core/projection.d.ts +20 -0
  96. package/dist/core/projection.js +96 -0
  97. package/dist/core/projection.js.map +1 -0
  98. package/dist/core/registry.d.ts +76 -0
  99. package/dist/core/registry.js +147 -0
  100. package/dist/core/registry.js.map +1 -0
  101. package/dist/core/router.d.ts +42 -0
  102. package/dist/core/router.js +99 -0
  103. package/dist/core/router.js.map +1 -0
  104. package/dist/core/routes.d.ts +93 -0
  105. package/dist/core/routes.js +399 -0
  106. package/dist/core/routes.js.map +1 -0
  107. package/dist/core/search.d.ts +63 -0
  108. package/dist/core/search.js +0 -0
  109. package/dist/core/search.js.map +1 -0
  110. package/dist/core/setup.d.ts +70 -0
  111. package/dist/core/setup.js +250 -0
  112. package/dist/core/setup.js.map +1 -0
  113. package/dist/core/suggestions.d.ts +15 -0
  114. package/dist/core/suggestions.js +38 -0
  115. package/dist/core/suggestions.js.map +1 -0
  116. package/dist/core/worktree.d.ts +32 -0
  117. package/dist/core/worktree.js +83 -0
  118. package/dist/core/worktree.js.map +1 -0
  119. package/dist/daemon/app-page.d.ts +32 -0
  120. package/dist/daemon/app-page.js +6363 -0
  121. package/dist/daemon/app-page.js.map +1 -0
  122. package/dist/daemon/auth.d.ts +51 -0
  123. package/dist/daemon/auth.js +135 -0
  124. package/dist/daemon/auth.js.map +1 -0
  125. package/dist/daemon/board.d.ts +117 -0
  126. package/dist/daemon/board.js +202 -0
  127. package/dist/daemon/board.js.map +1 -0
  128. package/dist/daemon/brand-icons.d.ts +29 -0
  129. package/dist/daemon/brand-icons.js +44 -0
  130. package/dist/daemon/brand-icons.js.map +1 -0
  131. package/dist/daemon/client.d.ts +127 -0
  132. package/dist/daemon/client.js +237 -0
  133. package/dist/daemon/client.js.map +1 -0
  134. package/dist/daemon/geist-font.d.ts +10 -0
  135. package/dist/daemon/geist-font.js +783 -0
  136. package/dist/daemon/geist-font.js.map +1 -0
  137. package/dist/daemon/guards.d.ts +18 -0
  138. package/dist/daemon/guards.js +40 -0
  139. package/dist/daemon/guards.js.map +1 -0
  140. package/dist/daemon/linear.d.ts +59 -0
  141. package/dist/daemon/linear.js +117 -0
  142. package/dist/daemon/linear.js.map +1 -0
  143. package/dist/daemon/push.d.ts +22 -0
  144. package/dist/daemon/push.js +58 -0
  145. package/dist/daemon/push.js.map +1 -0
  146. package/dist/daemon/runtime.d.ts +299 -0
  147. package/dist/daemon/runtime.js +1016 -0
  148. package/dist/daemon/runtime.js.map +1 -0
  149. package/dist/daemon/server.d.ts +125 -0
  150. package/dist/daemon/server.js +1728 -0
  151. package/dist/daemon/server.js.map +1 -0
  152. package/dist/daemon/tasks.d.ts +153 -0
  153. package/dist/daemon/tasks.js +264 -0
  154. package/dist/daemon/tasks.js.map +1 -0
  155. package/dist/daemon/terminals.d.ts +82 -0
  156. package/dist/daemon/terminals.js +372 -0
  157. package/dist/daemon/terminals.js.map +1 -0
  158. package/dist/index.d.ts +20 -0
  159. package/dist/index.js +20 -0
  160. package/dist/index.js.map +1 -0
  161. package/dist/sdk.d.ts +17 -0
  162. package/dist/sdk.js +17 -0
  163. package/dist/sdk.js.map +1 -0
  164. package/dist/types.d.ts +236 -0
  165. package/dist/types.js +18 -0
  166. package/dist/types.js.map +1 -0
  167. package/docs/SETUP.md +265 -0
  168. package/docs/adapters.md +132 -0
  169. package/docs/design-system.md +245 -0
  170. package/docs/img/board-linear.png +0 -0
  171. package/docs/img/board-projects.png +0 -0
  172. package/docs/img/brain.png +0 -0
  173. package/docs/img/settings.png +0 -0
  174. package/docs/img/workspace.png +0 -0
  175. package/docs/integration-notes.md +76 -0
  176. package/docs/proposals/brain.md +262 -0
  177. 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":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,QAAQ,MAAM,eAAe,CAAC;AAErC,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAa/E,4DAA4D;AAC5D,MAAM,OAAO,GAAG;IACd,kDAAkD;IAClD,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,kDAAkD;CAC5E,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,QAAiB;IACxC,IAAI,QAAQ;QAAE,OAAO,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,OAAO,CAAC,CAAC,gDAAgD;AAClE,CAAC;AAED,MAAM,OAAO,YAAa,SAAQ,WAAW;IACnC,KAAK,GAAwB,IAAI,CAAC;IAClC,OAAO,CAAe;IAE9B,YAAY,EAAU,EAAE,UAAkB,EAAE,UAAmC,EAAE;QAC/E,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QAC/B,IAAI,CAAC,OAAO,GAAG,OAAuB,CAAC;IACzC,CAAC;IAED,+EAA+E;IAC/E,IAAY,QAAQ;QAClB,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChD,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,SAA+B,CAAC;IAChE,CAAC;IAED,IAAY,QAAQ,CAAC,KAAyB;QAC5C,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChD,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACvE,iBAAiB,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,SAAS;QACb,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,CAAC,GAAG;YAAE,OAAO,KAAK,CAAC;QACvB,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAgB;QACzB,IAAI,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC;QACpE,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QACrF,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE3B,2EAA2E;QAC3E,qEAAqE;QACrE,6DAA6D;QAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;QAE/F,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ;YACxB,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC;YACnC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACb,IAAI,CAAC,IAAI,CACP,QAAQ,EACR,uBAAuB,EACvB,IAAI,EACJ,IAAI,CAAC,UAAU,EACf,IAAI,EACJ,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,iBAAiB,CAC1C,CAAC;QACF,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC5D,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEhB,IAAI,CAAC;YACH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE;oBAC7B,GAAG,EAAE,IAAI,CAAC,UAAU;oBACpB,kEAAkE;oBAClE,8CAA8C;oBAC9C,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;oBACjC,GAAG,EAAE,QAAQ,EAAE;iBAChB,CAAC,CAAC;gBACH,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;gBACnB,IAAI,WAAW,GAAG,EAAE,CAAC;gBACrB,IAAI,OAAO,GAAG,KAAK,CAAC;gBACpB,IAAI,UAAU,GAAG,EAAE,CAAC;gBAEpB,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,MAAO,EAAE,CAAC,CAAC;gBAC9D,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;oBACrB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;oBAC5B,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;wBAAE,OAAO;oBACrC,IAAI,GAA4B,CAAC;oBACjC,IAAI,CAAC;wBACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;oBACvD,CAAC;oBAAC,MAAM,CAAC;wBACP,OAAO;oBACT,CAAC;oBACD,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC;oBAChD,IAAI,GAAG,CAAC,IAAI,KAAK,gBAAgB;wBAAE,OAAO,GAAG,IAAI,CAAC;gBACpD,CAAC,CAAC,CAAC;gBAEH,KAAK,CAAC,MAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE;oBACrC,UAAU,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;gBACxD,CAAC,CAAC,CAAC;gBAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBACxC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;oBACjC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;oBAClB,IAAI,MAAM,EAAE,CAAC;wBACX,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;wBACzE,OAAO,EAAE,CAAC;wBACV,OAAO;oBACT,CAAC;oBACD,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;wBAC3B,IAAI,CAAC,IAAI,CAAC;4BACR,IAAI,EAAE,OAAO;4BACb,OAAO,EAAE,EAAE,OAAO,EAAE,gBAAgB,IAAI,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;yBACjE,CAAC,CAAC;wBACH,MAAM,CAAC,IAAI,KAAK,CAAC,gBAAgB,IAAI,KAAK,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;wBACvE,OAAO;oBACT,CAAC;oBACD,mEAAmE;oBACnE,wDAAwD;oBACxD,IAAI,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;wBACtC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;oBACrF,CAAC;oBACD,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,EAAE,CAAC,CAAC;oBACnF,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;YACnB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,GAA4B,EAAE,OAA4B;QAC5E,MAAM,IAAI,GAAG,GAAG,CAAC,IAAc,CAAC;QAEhC,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;YAC9B,MAAM,EAAE,GAAG,GAAG,CAAC,SAA+B,CAAC;YAC/C,IAAI,EAAE;gBAAE,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;YACvF,OAAO;QACT,CAAC;QAED,IAAI,IAAI,KAAK,gBAAgB,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;YACzD,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAA4B,CAAC;YACzD,wEAAwE;YACxE,sEAAsE;YACtE,IAAI,IAAI,KAAK,gBAAgB;gBAAE,OAAO;YACtC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;YAC9B,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAA2B,CAAC;YAC1D,IAAI,CAAC,IAAI,CAAC;gBACR,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE;oBACP,KAAK,EAAE,aAAa;oBACpB,WAAW,EAAE,KAAK,CAAC,YAAY,IAAI,CAAC;oBACpC,iBAAiB,EAAE,KAAK,CAAC,mBAAmB,IAAI,CAAC;oBACjD,YAAY,EAAE,KAAK,CAAC,aAAa,IAAI,CAAC;oBACtC,eAAe,EAAE,KAAK,CAAC,uBAAuB,IAAI,CAAC;iBACpD;aACF,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YAC/C,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAA4B,CAAC;YAC1D,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,IAAI,cAAc,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,IAA6B,EAAE,OAA4B;QAC5E,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;YAClB,KAAK,eAAe,CAAC,CAAC,CAAC;gBACrB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;gBACrC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;oBAAE,OAAO;gBACzB,OAAO,CAAC,IAAI,CAAC,CAAC;gBACd,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;gBAClD,OAAO;YACT,CAAC;YACD,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC5C,IAAI,IAAI;oBAAE,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC7E,OAAO;YACT,CAAC;YACD,KAAK,mBAAmB,CAAC,CAAC,CAAC;gBACzB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;gBAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;gBAC5B,IAAI,CAAC,IAAI,CAAC;oBACR,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE;wBACP,IAAI,EAAE,OAAO;wBACb,OAAO,EAAE,UAAU,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;wBAC/D,QAAQ,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;qBACjD;iBACF,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YACD,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAA4C,CAAC;gBAChF,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;oBACxB,IAAI,CAAC,CAAC,CAAC,IAAI;wBAAE,SAAS;oBACtB,IAAI,CAAC,IAAI,CAAC;wBACR,IAAI,EAAE,WAAW;wBACjB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE;qBAC3E,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO;YACT,CAAC;YACD,KAAK,eAAe,CAAC,CAAC,CAAC;gBACrB,IAAI,CAAC,IAAI,CAAC;oBACR,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,EAAE;iBAC1F,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YACD,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,IAAI,CAAC,IAAI,CAAC;oBACR,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;iBAC9F,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YACD,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,aAAa,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC1F,OAAO;YACT,CAAC;YACD;gBACE,qEAAqE;gBACrE,wEAAwE;gBACxE,sBAAsB;gBACtB,OAAO;QACX,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE;gBACxB,IAAI,CAAC;oBACH,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACxB,CAAC;gBAAC,MAAM,CAAC;oBACP,eAAe;gBACjB,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC,EAAE,IAAI,CAAC,CAAC;YACT,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACrB,YAAY,CAAC,CAAC,CAAC,CAAC;gBAChB,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -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 {};