@warlock.js/ai-cli 0.0.0-stage → 5.31.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 (139) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/LICENSE +21 -0
  3. package/README.md +69 -2
  4. package/cjs/index.cjs +4576 -0
  5. package/cjs/index.cjs.map +1 -0
  6. package/esm/adapters/aider.d.mts +41 -0
  7. package/esm/adapters/aider.d.mts.map +1 -0
  8. package/esm/adapters/aider.mjs +294 -0
  9. package/esm/adapters/aider.mjs.map +1 -0
  10. package/esm/adapters/amp.d.mts +33 -0
  11. package/esm/adapters/amp.d.mts.map +1 -0
  12. package/esm/adapters/amp.mjs +119 -0
  13. package/esm/adapters/amp.mjs.map +1 -0
  14. package/esm/adapters/antigravity.d.mts +37 -0
  15. package/esm/adapters/antigravity.d.mts.map +1 -0
  16. package/esm/adapters/antigravity.mjs +235 -0
  17. package/esm/adapters/antigravity.mjs.map +1 -0
  18. package/esm/adapters/claude-code.d.mts +30 -0
  19. package/esm/adapters/claude-code.d.mts.map +1 -0
  20. package/esm/adapters/claude-code.mjs +121 -0
  21. package/esm/adapters/claude-code.mjs.map +1 -0
  22. package/esm/adapters/claude-stream.d.mts +32 -0
  23. package/esm/adapters/claude-stream.d.mts.map +1 -0
  24. package/esm/adapters/claude-stream.mjs +140 -0
  25. package/esm/adapters/claude-stream.mjs.map +1 -0
  26. package/esm/adapters/codex.d.mts +37 -0
  27. package/esm/adapters/codex.d.mts.map +1 -0
  28. package/esm/adapters/codex.mjs +320 -0
  29. package/esm/adapters/codex.mjs.map +1 -0
  30. package/esm/adapters/copilot.d.mts +35 -0
  31. package/esm/adapters/copilot.d.mts.map +1 -0
  32. package/esm/adapters/copilot.mjs +244 -0
  33. package/esm/adapters/copilot.mjs.map +1 -0
  34. package/esm/adapters/cursor.d.mts +35 -0
  35. package/esm/adapters/cursor.d.mts.map +1 -0
  36. package/esm/adapters/cursor.mjs +203 -0
  37. package/esm/adapters/cursor.mjs.map +1 -0
  38. package/esm/adapters/droid.d.mts +32 -0
  39. package/esm/adapters/droid.d.mts.map +1 -0
  40. package/esm/adapters/droid.mjs +183 -0
  41. package/esm/adapters/droid.mjs.map +1 -0
  42. package/esm/adapters/grok.d.mts +32 -0
  43. package/esm/adapters/grok.d.mts.map +1 -0
  44. package/esm/adapters/grok.mjs +199 -0
  45. package/esm/adapters/grok.mjs.map +1 -0
  46. package/esm/adapters/index.d.mts +16 -0
  47. package/esm/adapters/index.mjs +18 -0
  48. package/esm/adapters/kimi.d.mts +34 -0
  49. package/esm/adapters/kimi.d.mts.map +1 -0
  50. package/esm/adapters/kimi.mjs +162 -0
  51. package/esm/adapters/kimi.mjs.map +1 -0
  52. package/esm/adapters/mistral-vibe.d.mts +32 -0
  53. package/esm/adapters/mistral-vibe.d.mts.map +1 -0
  54. package/esm/adapters/mistral-vibe.mjs +252 -0
  55. package/esm/adapters/mistral-vibe.mjs.map +1 -0
  56. package/esm/adapters/opencode.d.mts +36 -0
  57. package/esm/adapters/opencode.d.mts.map +1 -0
  58. package/esm/adapters/opencode.mjs +219 -0
  59. package/esm/adapters/opencode.mjs.map +1 -0
  60. package/esm/adapters/qwen-code.d.mts +30 -0
  61. package/esm/adapters/qwen-code.d.mts.map +1 -0
  62. package/esm/adapters/qwen-code.mjs +94 -0
  63. package/esm/adapters/qwen-code.mjs.map +1 -0
  64. package/esm/adapters/reasonix.d.mts +31 -0
  65. package/esm/adapters/reasonix.d.mts.map +1 -0
  66. package/esm/adapters/reasonix.mjs +250 -0
  67. package/esm/adapters/reasonix.mjs.map +1 -0
  68. package/esm/adapters/shared.d.mts +78 -0
  69. package/esm/adapters/shared.d.mts.map +1 -0
  70. package/esm/adapters/shared.mjs +161 -0
  71. package/esm/adapters/shared.mjs.map +1 -0
  72. package/esm/cli-agent.d.mts +40 -0
  73. package/esm/cli-agent.d.mts.map +1 -0
  74. package/esm/cli-agent.mjs +207 -0
  75. package/esm/cli-agent.mjs.map +1 -0
  76. package/esm/cli.d.mts +53 -0
  77. package/esm/cli.d.mts.map +1 -0
  78. package/esm/cli.mjs +61 -0
  79. package/esm/cli.mjs.map +1 -0
  80. package/esm/contracts/adapter.contract.d.mts +154 -0
  81. package/esm/contracts/adapter.contract.d.mts.map +1 -0
  82. package/esm/contracts/events.type.d.mts +111 -0
  83. package/esm/contracts/events.type.d.mts.map +1 -0
  84. package/esm/contracts/index.d.mts +4 -0
  85. package/esm/contracts/mcp.type.d.mts +29 -0
  86. package/esm/contracts/mcp.type.d.mts.map +1 -0
  87. package/esm/contracts/options.type.d.mts +87 -0
  88. package/esm/contracts/options.type.d.mts.map +1 -0
  89. package/esm/errors.d.mts +46 -0
  90. package/esm/errors.d.mts.map +1 -0
  91. package/esm/errors.mjs +32 -0
  92. package/esm/errors.mjs.map +1 -0
  93. package/esm/index.d.mts +31 -0
  94. package/esm/index.mjs +28 -0
  95. package/esm/model/cli-model.d.mts +48 -0
  96. package/esm/model/cli-model.d.mts.map +1 -0
  97. package/esm/model/cli-model.mjs +133 -0
  98. package/esm/model/cli-model.mjs.map +1 -0
  99. package/esm/probe/probe.d.mts +18 -0
  100. package/esm/probe/probe.d.mts.map +1 -0
  101. package/esm/probe/probe.mjs +148 -0
  102. package/esm/probe/probe.mjs.map +1 -0
  103. package/esm/session/aggregate.mjs +86 -0
  104. package/esm/session/aggregate.mjs.map +1 -0
  105. package/esm/session/environment.mjs +71 -0
  106. package/esm/session/environment.mjs.map +1 -0
  107. package/esm/session/run-directory.mjs +74 -0
  108. package/esm/session/run-directory.mjs.map +1 -0
  109. package/esm/session/session.mjs +188 -0
  110. package/esm/session/session.mjs.map +1 -0
  111. package/esm/spawn/invocation.d.mts +35 -0
  112. package/esm/spawn/invocation.d.mts.map +1 -0
  113. package/esm/spawn/invocation.mjs +76 -0
  114. package/esm/spawn/invocation.mjs.map +1 -0
  115. package/esm/spawn/process-tree.mjs +57 -0
  116. package/esm/spawn/process-tree.mjs.map +1 -0
  117. package/esm/spawn/resolve-command.d.mts +73 -0
  118. package/esm/spawn/resolve-command.d.mts.map +1 -0
  119. package/esm/spawn/resolve-command.mjs +109 -0
  120. package/esm/spawn/resolve-command.mjs.map +1 -0
  121. package/esm/stream/event-log.mjs +52 -0
  122. package/esm/stream/event-log.mjs.map +1 -0
  123. package/esm/stream/json-lines.d.mts +33 -0
  124. package/esm/stream/json-lines.d.mts.map +1 -0
  125. package/esm/stream/json-lines.mjs +65 -0
  126. package/esm/stream/json-lines.mjs.map +1 -0
  127. package/esm/stream/line-splitter.mjs +53 -0
  128. package/esm/stream/line-splitter.mjs.map +1 -0
  129. package/esm/utils/toml.d.mts +22 -0
  130. package/esm/utils/toml.d.mts.map +1 -0
  131. package/esm/utils/toml.mjs +53 -0
  132. package/esm/utils/toml.mjs.map +1 -0
  133. package/llms-full.txt +373 -0
  134. package/llms.txt +10 -0
  135. package/package.json +39 -4
  136. package/skills/README.md +13 -0
  137. package/skills/index.md +22 -0
  138. package/skills/run-cli-agents/SKILL.md +186 -0
  139. package/skills/write-a-cli-adapter/SKILL.md +173 -0
@@ -0,0 +1,235 @@
1
+ import { jsonLinesParser, numberField, recordField, stringField } from "../stream/json-lines.mjs";
2
+ import { argvPrompt, jsonFile, mapEffort, requirePrivateHome, usageOf } from "./shared.mjs";
3
+ import path from "node:path";
4
+
5
+ //#region ../../packages/ai-cli/src/adapters/antigravity.ts
6
+ /**
7
+ * Google Antigravity CLI (`agy`), installed by the
8
+ * `antigravity.google/cli/install.sh` script (no npm package). Not Gemini
9
+ * CLI, which it succeeds.
10
+ *
11
+ * Verified against the official docs only (the binary is distributed by a
12
+ * curl installer, which was not run): `antigravity.google/docs/cli/headless`,
13
+ * `/docs/cli/reference`, `/docs/mcp`, `/docs/permissions`, `/docs/settings`,
14
+ * `/docs/install`, and the 1.4.0 release notes, 2026-10-17. The capability
15
+ * probe checks every flag against the installed binary's `--help`.
16
+ *
17
+ * - Headless: `agy -p <prompt> --output-format stream-json`. For long
18
+ * prompts the adapter uses the documented stdin protocol instead:
19
+ * `--input-format stream-json` with one `{"event":"user","message":
20
+ * {"content":…}}` line, then stdin is closed.
21
+ * - Stream: `{"event":X, X:{…}}` lines — `init` (with `conversation_id`),
22
+ * `step_update` (`agent_response` steps carry `text_delta` fragments;
23
+ * `tool` steps carry `tool_info{name,parameters,output,error}` with call
24
+ * and result together, correlated by `step_index`) and a final `result`
25
+ * (`status`, `response`, `error`, cumulative `usage`). No cost field.
26
+ * - Permissions: headless soft-denies tools that need approval (the run
27
+ * continues and exits 0); bypass is `--dangerously-skip-permissions`.
28
+ * - Home: no variable relocates `~/.gemini`, so a private/owned home sets
29
+ * `HOME` (and `USERPROFILE`). MCP goes to
30
+ * `$HOME/.gemini/config/mcp_config.json` (remote servers use `serverUrl`).
31
+ * - Auth: `GEMINI_API_KEY` only works with `"modelProvider": "gemini"` in
32
+ * `$HOME/.gemini/antigravity-cli/settings.json`; the adapter writes that
33
+ * file when `apiKey` is set on a private home.
34
+ */
35
+ const antigravityAdapter = {
36
+ name: "antigravity",
37
+ title: "Antigravity CLI",
38
+ command: "agy",
39
+ apiKeyEnv: ["GEMINI_API_KEY"],
40
+ homeEnv: ["HOME", "USERPROFILE"],
41
+ transports: ["argv", "stdin"],
42
+ effort: true,
43
+ mcp: true,
44
+ probe: {
45
+ help: [["--help"]],
46
+ version: ["--version"]
47
+ },
48
+ verification: {
49
+ version: "1.4.0",
50
+ verifiedBy: "docs",
51
+ sources: [
52
+ "https://antigravity.google/docs/cli/headless",
53
+ "https://antigravity.google/docs/cli/reference",
54
+ "https://antigravity.google/docs/mcp",
55
+ "https://antigravity.google/docs/permissions",
56
+ "https://github.com/google-antigravity/antigravity-cli"
57
+ ],
58
+ checkedAt: "2026-10-17"
59
+ },
60
+ plan(context) {
61
+ const args = ["--output-format", "stream-json"];
62
+ const requires = ["--output-format", "stream-json"];
63
+ const files = [];
64
+ if (context.model !== void 0) {
65
+ args.push("--model", context.model);
66
+ requires.push("--model");
67
+ }
68
+ if (context.effort !== void 0) {
69
+ args.push("--effort", mapEffort(context.effort, {
70
+ low: "low",
71
+ medium: "medium",
72
+ high: "high"
73
+ }));
74
+ requires.push("--effort");
75
+ }
76
+ if (context.resume !== void 0) {
77
+ args.push("--conversation", context.resume);
78
+ requires.push("--conversation");
79
+ }
80
+ if (context.permission === "bypass") {
81
+ args.push("--dangerously-skip-permissions");
82
+ requires.push("--dangerously-skip-permissions");
83
+ }
84
+ if (context.mcp !== void 0) {
85
+ const home = requirePrivateHome(context, antigravityAdapter, "MCP servers");
86
+ files.push({
87
+ path: path.join(home, ".gemini", "config", "mcp_config.json"),
88
+ content: jsonFile({ mcpServers: antigravityMcp(context.mcp) })
89
+ });
90
+ }
91
+ if (context.apiKey !== void 0 && context.homeIsPrivate && context.home !== void 0) files.push({
92
+ path: path.join(context.home, ".gemini", "antigravity-cli", "settings.json"),
93
+ content: jsonFile({ modelProvider: "gemini" })
94
+ });
95
+ const env = context.home !== void 0 ? {
96
+ HOME: context.home,
97
+ USERPROFILE: context.home
98
+ } : {};
99
+ if (context.transport === "stdin") {
100
+ args.push("--input-format", "stream-json");
101
+ requires.push("--input-format");
102
+ return {
103
+ args,
104
+ stdin: `${JSON.stringify({
105
+ event: "user",
106
+ message: { content: context.prompt }
107
+ })}\n`,
108
+ env,
109
+ files,
110
+ requires
111
+ };
112
+ }
113
+ requires.push("-p");
114
+ return {
115
+ args,
116
+ tail: ["-p", argvPrompt(context.prompt)],
117
+ env,
118
+ files,
119
+ requires
120
+ };
121
+ },
122
+ parser: createAntigravityParser
123
+ };
124
+ function antigravityMcp(servers) {
125
+ const rendered = {};
126
+ for (const [name, server] of Object.entries(servers)) rendered[name] = server.type === "stdio" ? {
127
+ command: server.command,
128
+ args: server.args ?? [],
129
+ ...server.env ? { env: server.env } : {}
130
+ } : {
131
+ serverUrl: server.url,
132
+ ...server.headers ? { headers: server.headers } : {}
133
+ };
134
+ return rendered;
135
+ }
136
+ function stepUsage(usage) {
137
+ if (usage === void 0) return;
138
+ const cached = numberField(usage, "cache_read_tokens");
139
+ return usageOf({
140
+ input: numberField(usage, "input_tokens"),
141
+ output: numberField(usage, "output_tokens"),
142
+ total: numberField(usage, "total_tokens"),
143
+ cachedTokens: cached !== void 0 && cached > 0 ? cached : void 0,
144
+ reasoningTokens: numberField(usage, "thinking_tokens") || void 0
145
+ });
146
+ }
147
+ /** Parser for `agy -p … --output-format stream-json`. */
148
+ function createAntigravityParser() {
149
+ return jsonLinesParser((record) => {
150
+ const event = stringField(record, "event");
151
+ if (event === "init") {
152
+ const init = recordField(record, "init");
153
+ return [{
154
+ type: "session.started",
155
+ sessionRef: stringField(record, "conversation_id"),
156
+ model: stringField(init, "model"),
157
+ raw: record
158
+ }];
159
+ }
160
+ if (event === "step_update") {
161
+ const step = recordField(record, "step_update");
162
+ const stepType = stringField(step, "step_type");
163
+ const events = [];
164
+ if (stepType === "agent_response") {
165
+ const text = stringField(step, "text_delta") ?? "";
166
+ if (text.length > 0) events.push({
167
+ type: "message",
168
+ text,
169
+ delta: true,
170
+ raw: record
171
+ });
172
+ }
173
+ if (stepType === "tool" && stringField(step, "state") === "DONE") {
174
+ const info = recordField(step, "tool_info");
175
+ const error = recordField(info, "error");
176
+ const id = `step-${numberField(step, "step_index") ?? 0}`;
177
+ events.push({
178
+ type: "tool.call",
179
+ id,
180
+ name: stringField(info, "name") ?? stringField(step, "tool_name") ?? "",
181
+ input: info?.parameters,
182
+ raw: record
183
+ }, {
184
+ type: "tool.result",
185
+ id,
186
+ output: error !== void 0 ? stringField(error, "message") ?? stringField(error, "type") ?? "tool failed" : stringField(info, "output") ?? "",
187
+ isError: error !== void 0,
188
+ raw: record
189
+ });
190
+ }
191
+ const usage = stepUsage(recordField(step, "usage"));
192
+ if (usage !== void 0) events.push({
193
+ type: "usage",
194
+ usage,
195
+ cumulative: false,
196
+ raw: record
197
+ });
198
+ return events;
199
+ }
200
+ if (event === "result") {
201
+ const result = recordField(record, "result");
202
+ const events = [];
203
+ const usage = stepUsage(recordField(result, "usage"));
204
+ if (usage !== void 0) events.push({
205
+ type: "usage",
206
+ usage,
207
+ cumulative: true,
208
+ raw: record
209
+ });
210
+ const status = stringField(result, "status");
211
+ if (status !== void 0 && status !== "SUCCESS") events.push({
212
+ type: "error",
213
+ message: stringField(result, "error") || `Antigravity run ended ${status}`,
214
+ fatal: true,
215
+ raw: record
216
+ });
217
+ else {
218
+ const response = stringField(result, "response") ?? "";
219
+ if (response.length > 0) events.push({
220
+ type: "message",
221
+ text: response,
222
+ delta: false,
223
+ final: true,
224
+ raw: record
225
+ });
226
+ }
227
+ return events;
228
+ }
229
+ return [];
230
+ });
231
+ }
232
+
233
+ //#endregion
234
+ export { antigravityAdapter, createAntigravityParser };
235
+ //# sourceMappingURL=antigravity.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"antigravity.mjs","names":[],"sources":["../../../../../../../../packages/ai-cli/src/adapters/antigravity.ts"],"sourcesContent":["import path from \"node:path\";\nimport type {\n CliAdapter,\n CliLaunchFile,\n CliMcpServers,\n CliParsedEvent,\n CliStreamParser,\n} from \"../contracts\";\nimport {\n jsonLinesParser,\n numberField,\n recordField,\n stringField,\n type JsonRecord,\n} from \"../stream/json-lines\";\nimport { argvPrompt, jsonFile, mapEffort, requirePrivateHome, usageOf } from \"./shared\";\n\n/**\n * Google Antigravity CLI (`agy`), installed by the\n * `antigravity.google/cli/install.sh` script (no npm package). Not Gemini\n * CLI, which it succeeds.\n *\n * Verified against the official docs only (the binary is distributed by a\n * curl installer, which was not run): `antigravity.google/docs/cli/headless`,\n * `/docs/cli/reference`, `/docs/mcp`, `/docs/permissions`, `/docs/settings`,\n * `/docs/install`, and the 1.4.0 release notes, 2026-10-17. The capability\n * probe checks every flag against the installed binary's `--help`.\n *\n * - Headless: `agy -p <prompt> --output-format stream-json`. For long\n * prompts the adapter uses the documented stdin protocol instead:\n * `--input-format stream-json` with one `{\"event\":\"user\",\"message\":\n * {\"content\":…}}` line, then stdin is closed.\n * - Stream: `{\"event\":X, X:{…}}` lines — `init` (with `conversation_id`),\n * `step_update` (`agent_response` steps carry `text_delta` fragments;\n * `tool` steps carry `tool_info{name,parameters,output,error}` with call\n * and result together, correlated by `step_index`) and a final `result`\n * (`status`, `response`, `error`, cumulative `usage`). No cost field.\n * - Permissions: headless soft-denies tools that need approval (the run\n * continues and exits 0); bypass is `--dangerously-skip-permissions`.\n * - Home: no variable relocates `~/.gemini`, so a private/owned home sets\n * `HOME` (and `USERPROFILE`). MCP goes to\n * `$HOME/.gemini/config/mcp_config.json` (remote servers use `serverUrl`).\n * - Auth: `GEMINI_API_KEY` only works with `\"modelProvider\": \"gemini\"` in\n * `$HOME/.gemini/antigravity-cli/settings.json`; the adapter writes that\n * file when `apiKey` is set on a private home.\n */\nexport const antigravityAdapter: CliAdapter = {\n name: \"antigravity\",\n title: \"Antigravity CLI\",\n command: \"agy\",\n apiKeyEnv: [\"GEMINI_API_KEY\"],\n homeEnv: [\"HOME\", \"USERPROFILE\"],\n transports: [\"argv\", \"stdin\"],\n effort: true,\n mcp: true,\n probe: { help: [[\"--help\"]], version: [\"--version\"] },\n verification: {\n version: \"1.4.0\",\n verifiedBy: \"docs\",\n sources: [\n \"https://antigravity.google/docs/cli/headless\",\n \"https://antigravity.google/docs/cli/reference\",\n \"https://antigravity.google/docs/mcp\",\n \"https://antigravity.google/docs/permissions\",\n \"https://github.com/google-antigravity/antigravity-cli\",\n ],\n checkedAt: \"2026-10-17\",\n },\n plan(context) {\n const args = [\"--output-format\", \"stream-json\"];\n const requires = [\"--output-format\", \"stream-json\"];\n const files: CliLaunchFile[] = [];\n\n if (context.model !== undefined) {\n args.push(\"--model\", context.model);\n requires.push(\"--model\");\n }\n\n if (context.effort !== undefined) {\n // Documented levels: low | medium | high.\n args.push(\n \"--effort\",\n mapEffort(context.effort, { low: \"low\", medium: \"medium\", high: \"high\" }),\n );\n requires.push(\"--effort\");\n }\n\n if (context.resume !== undefined) {\n args.push(\"--conversation\", context.resume);\n requires.push(\"--conversation\");\n }\n\n if (context.permission === \"bypass\") {\n args.push(\"--dangerously-skip-permissions\");\n requires.push(\"--dangerously-skip-permissions\");\n }\n\n if (context.mcp !== undefined) {\n const home = requirePrivateHome(context, antigravityAdapter, \"MCP servers\");\n\n files.push({\n path: path.join(home, \".gemini\", \"config\", \"mcp_config.json\"),\n content: jsonFile({ mcpServers: antigravityMcp(context.mcp) }),\n });\n }\n\n if (context.apiKey !== undefined && context.homeIsPrivate && context.home !== undefined) {\n files.push({\n path: path.join(context.home, \".gemini\", \"antigravity-cli\", \"settings.json\"),\n content: jsonFile({ modelProvider: \"gemini\" }),\n });\n }\n\n const env: Record<string, string> =\n context.home !== undefined ? { HOME: context.home, USERPROFILE: context.home } : {};\n\n if (context.transport === \"stdin\") {\n // Documented form: `agy --input-format stream-json --output-format stream-json`, no `-p`.\n args.push(\"--input-format\", \"stream-json\");\n requires.push(\"--input-format\");\n\n return {\n args,\n stdin: `${JSON.stringify({ event: \"user\", message: { content: context.prompt } })}\\n`,\n env,\n files,\n requires,\n };\n }\n\n requires.push(\"-p\");\n\n return { args, tail: [\"-p\", argvPrompt(context.prompt)], env, files, requires };\n },\n parser: createAntigravityParser,\n};\n\nfunction antigravityMcp(servers: CliMcpServers): Record<string, unknown> {\n const rendered: Record<string, unknown> = {};\n\n for (const [name, server] of Object.entries(servers)) {\n rendered[name] =\n server.type === \"stdio\"\n ? {\n command: server.command,\n args: server.args ?? [],\n ...(server.env ? { env: server.env } : {}),\n }\n : { serverUrl: server.url, ...(server.headers ? { headers: server.headers } : {}) };\n }\n\n return rendered;\n}\n\nfunction stepUsage(usage: JsonRecord | undefined) {\n if (usage === undefined) {\n return undefined;\n }\n\n const cached = numberField(usage, \"cache_read_tokens\");\n\n return usageOf({\n input: numberField(usage, \"input_tokens\"),\n output: numberField(usage, \"output_tokens\"),\n total: numberField(usage, \"total_tokens\"),\n cachedTokens: cached !== undefined && cached > 0 ? cached : undefined,\n reasoningTokens: numberField(usage, \"thinking_tokens\") || undefined,\n });\n}\n\n/** Parser for `agy -p … --output-format stream-json`. */\nexport function createAntigravityParser(): CliStreamParser {\n return jsonLinesParser((record): CliParsedEvent[] => {\n const event = stringField(record, \"event\");\n\n if (event === \"init\") {\n const init = recordField(record, \"init\");\n\n return [\n {\n type: \"session.started\",\n sessionRef: stringField(record, \"conversation_id\"),\n model: stringField(init, \"model\"),\n raw: record,\n },\n ];\n }\n\n if (event === \"step_update\") {\n const step = recordField(record, \"step_update\");\n const stepType = stringField(step, \"step_type\");\n const events: CliParsedEvent[] = [];\n\n if (stepType === \"agent_response\") {\n const text = stringField(step, \"text_delta\") ?? \"\";\n\n if (text.length > 0) {\n events.push({ type: \"message\", text, delta: true, raw: record });\n }\n }\n\n if (stepType === \"tool\" && stringField(step, \"state\") === \"DONE\") {\n const info = recordField(step, \"tool_info\");\n const error = recordField(info, \"error\");\n const id = `step-${numberField(step, \"step_index\") ?? 0}`;\n\n events.push(\n {\n type: \"tool.call\",\n id,\n name: stringField(info, \"name\") ?? stringField(step, \"tool_name\") ?? \"\",\n input: info?.parameters,\n raw: record,\n },\n {\n type: \"tool.result\",\n id,\n output:\n error !== undefined\n ? (stringField(error, \"message\") ?? stringField(error, \"type\") ?? \"tool failed\")\n : (stringField(info, \"output\") ?? \"\"),\n isError: error !== undefined,\n raw: record,\n },\n );\n }\n\n const usage = stepUsage(recordField(step, \"usage\"));\n\n if (usage !== undefined) {\n events.push({ type: \"usage\", usage, cumulative: false, raw: record });\n }\n\n return events;\n }\n\n if (event === \"result\") {\n const result = recordField(record, \"result\");\n const events: CliParsedEvent[] = [];\n const usage = stepUsage(recordField(result, \"usage\"));\n\n if (usage !== undefined) {\n events.push({ type: \"usage\", usage, cumulative: true, raw: record });\n }\n\n const status = stringField(result, \"status\");\n\n if (status !== undefined && status !== \"SUCCESS\") {\n events.push({\n type: \"error\",\n message: stringField(result, \"error\") || `Antigravity run ended ${status}`,\n fatal: true,\n raw: record,\n });\n } else {\n const response = stringField(result, \"response\") ?? \"\";\n\n if (response.length > 0) {\n events.push({ type: \"message\", text: response, delta: false, final: true, raw: record });\n }\n }\n\n return events;\n }\n\n return [];\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { CliAdapter } from "../contracts/adapter.contract.mjs";
2
+ //#region ../../packages/ai-cli/src/adapters/claude-code.d.ts
3
+ /**
4
+ * Claude Code (`claude`, npm `@anthropic-ai/claude-code`).
5
+ *
6
+ * Verified against the real `claude --help` of 2.1.302, the event types of
7
+ * `@anthropic-ai/claude-agent-sdk` 0.3.302 and the docs
8
+ * (`code.claude.com/docs/en/{headless,cli-reference,mcp,env-vars,
9
+ * permission-modes}`), 2026-10-17.
10
+ *
11
+ * - Headless: `claude -p --output-format stream-json --verbose
12
+ * --include-partial-messages <prompt>` (`--verbose` is required with
13
+ * stream-json in print mode); piped stdin is the prompt when no positional
14
+ * prompt is given.
15
+ * - Stream: `system/init` (`session_id`), `stream_event` text deltas,
16
+ * `assistant` messages (text / `tool_use`), `user` messages with
17
+ * `tool_result`, and a final `result` (`result`, `usage`,
18
+ * `total_cost_usd`, `is_error`, `errors[]`).
19
+ * - Permissions: print mode auto-denies anything that would prompt; bypass
20
+ * is `--dangerously-skip-permissions` (Claude Code refuses it as root
21
+ * outside a recognised sandbox).
22
+ * - MCP: `--mcp-config <file>` with `{"mcpServers":…}`, written to the run
23
+ * directory.
24
+ * - Home: `CLAUDE_CONFIG_DIR`; auth `ANTHROPIC_API_KEY` (or a home you
25
+ * logged in to); auto-update off with `DISABLE_AUTOUPDATER=1`.
26
+ */
27
+ declare const claudeCodeAdapter: CliAdapter;
28
+ //#endregion
29
+ export { claudeCodeAdapter };
30
+ //# sourceMappingURL=claude-code.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.d.mts","names":[],"sources":["../../../../../../../../packages/ai-cli/src/adapters/claude-code.ts"],"mappings":";;;;;AA6BA;;;;AA2FC;;;;;;;;;;;;;;;;;cA3FY,iBAAA,EAAmB,UA2F/B"}
@@ -0,0 +1,121 @@
1
+ import { argvPrompt, jsonFile, mapEffort, mcpServersJson } from "./shared.mjs";
2
+ import { createClaudeStreamParser } from "./claude-stream.mjs";
3
+ import path from "node:path";
4
+
5
+ //#region ../../packages/ai-cli/src/adapters/claude-code.ts
6
+ /**
7
+ * Claude Code (`claude`, npm `@anthropic-ai/claude-code`).
8
+ *
9
+ * Verified against the real `claude --help` of 2.1.302, the event types of
10
+ * `@anthropic-ai/claude-agent-sdk` 0.3.302 and the docs
11
+ * (`code.claude.com/docs/en/{headless,cli-reference,mcp,env-vars,
12
+ * permission-modes}`), 2026-10-17.
13
+ *
14
+ * - Headless: `claude -p --output-format stream-json --verbose
15
+ * --include-partial-messages <prompt>` (`--verbose` is required with
16
+ * stream-json in print mode); piped stdin is the prompt when no positional
17
+ * prompt is given.
18
+ * - Stream: `system/init` (`session_id`), `stream_event` text deltas,
19
+ * `assistant` messages (text / `tool_use`), `user` messages with
20
+ * `tool_result`, and a final `result` (`result`, `usage`,
21
+ * `total_cost_usd`, `is_error`, `errors[]`).
22
+ * - Permissions: print mode auto-denies anything that would prompt; bypass
23
+ * is `--dangerously-skip-permissions` (Claude Code refuses it as root
24
+ * outside a recognised sandbox).
25
+ * - MCP: `--mcp-config <file>` with `{"mcpServers":…}`, written to the run
26
+ * directory.
27
+ * - Home: `CLAUDE_CONFIG_DIR`; auth `ANTHROPIC_API_KEY` (or a home you
28
+ * logged in to); auto-update off with `DISABLE_AUTOUPDATER=1`.
29
+ */
30
+ const claudeCodeAdapter = {
31
+ name: "claude-code",
32
+ title: "Claude Code",
33
+ command: "claude",
34
+ apiKeyEnv: ["ANTHROPIC_API_KEY"],
35
+ homeEnv: ["CLAUDE_CONFIG_DIR"],
36
+ transports: ["argv", "stdin"],
37
+ effort: true,
38
+ mcp: true,
39
+ probe: {
40
+ help: [["--help"]],
41
+ version: ["--version"]
42
+ },
43
+ verification: {
44
+ version: "2.1.302",
45
+ verifiedBy: "help",
46
+ sources: [
47
+ "https://code.claude.com/docs/en/headless",
48
+ "https://code.claude.com/docs/en/cli-reference",
49
+ "https://code.claude.com/docs/en/mcp",
50
+ "https://code.claude.com/docs/en/env-vars"
51
+ ],
52
+ checkedAt: "2026-10-17"
53
+ },
54
+ plan(context) {
55
+ const args = [
56
+ "--print",
57
+ "--output-format",
58
+ "stream-json",
59
+ "--verbose",
60
+ "--include-partial-messages"
61
+ ];
62
+ const requires = [
63
+ "--print",
64
+ "--output-format",
65
+ "stream-json",
66
+ "--verbose",
67
+ "--include-partial-messages"
68
+ ];
69
+ const files = [];
70
+ if (context.model !== void 0) {
71
+ args.push("--model", context.model);
72
+ requires.push("--model");
73
+ }
74
+ if (context.effort !== void 0) {
75
+ args.push("--effort", mapEffort(context.effort, {
76
+ low: "low",
77
+ medium: "medium",
78
+ high: "high",
79
+ xhigh: "xhigh",
80
+ max: "max"
81
+ }));
82
+ requires.push("--effort");
83
+ }
84
+ if (context.resume !== void 0) {
85
+ args.push("--resume", context.resume);
86
+ requires.push("--resume");
87
+ }
88
+ if (context.permission === "bypass") {
89
+ args.push("--dangerously-skip-permissions");
90
+ requires.push("--dangerously-skip-permissions");
91
+ }
92
+ if (context.mcp !== void 0) {
93
+ const file = path.join(context.runDir, "mcp.json");
94
+ files.push({
95
+ path: file,
96
+ content: jsonFile({ mcpServers: mcpServersJson(context.mcp, { typeField: true }) })
97
+ });
98
+ args.push("--mcp-config", file);
99
+ requires.push("--mcp-config");
100
+ }
101
+ return {
102
+ args,
103
+ tail: context.transport === "argv" ? [argvPrompt(context.prompt)] : [],
104
+ stdin: context.transport === "stdin" ? context.prompt : void 0,
105
+ env: {
106
+ ...context.home !== void 0 ? { CLAUDE_CONFIG_DIR: context.home } : {},
107
+ DISABLE_AUTOUPDATER: "1"
108
+ },
109
+ files,
110
+ requires
111
+ };
112
+ },
113
+ parser: () => createClaudeStreamParser({
114
+ usage: "anthropic",
115
+ vendor: "Claude Code"
116
+ })
117
+ };
118
+
119
+ //#endregion
120
+ export { claudeCodeAdapter };
121
+ //# sourceMappingURL=claude-code.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.mjs","names":[],"sources":["../../../../../../../../packages/ai-cli/src/adapters/claude-code.ts"],"sourcesContent":["import path from \"node:path\";\nimport type { CliAdapter, CliLaunchFile } from \"../contracts\";\nimport { createClaudeStreamParser } from \"./claude-stream\";\nimport { jsonFile, mapEffort, mcpServersJson, argvPrompt } from \"./shared\";\n\n/**\n * Claude Code (`claude`, npm `@anthropic-ai/claude-code`).\n *\n * Verified against the real `claude --help` of 2.1.302, the event types of\n * `@anthropic-ai/claude-agent-sdk` 0.3.302 and the docs\n * (`code.claude.com/docs/en/{headless,cli-reference,mcp,env-vars,\n * permission-modes}`), 2026-10-17.\n *\n * - Headless: `claude -p --output-format stream-json --verbose\n * --include-partial-messages <prompt>` (`--verbose` is required with\n * stream-json in print mode); piped stdin is the prompt when no positional\n * prompt is given.\n * - Stream: `system/init` (`session_id`), `stream_event` text deltas,\n * `assistant` messages (text / `tool_use`), `user` messages with\n * `tool_result`, and a final `result` (`result`, `usage`,\n * `total_cost_usd`, `is_error`, `errors[]`).\n * - Permissions: print mode auto-denies anything that would prompt; bypass\n * is `--dangerously-skip-permissions` (Claude Code refuses it as root\n * outside a recognised sandbox).\n * - MCP: `--mcp-config <file>` with `{\"mcpServers\":…}`, written to the run\n * directory.\n * - Home: `CLAUDE_CONFIG_DIR`; auth `ANTHROPIC_API_KEY` (or a home you\n * logged in to); auto-update off with `DISABLE_AUTOUPDATER=1`.\n */\nexport const claudeCodeAdapter: CliAdapter = {\n name: \"claude-code\",\n title: \"Claude Code\",\n command: \"claude\",\n apiKeyEnv: [\"ANTHROPIC_API_KEY\"],\n homeEnv: [\"CLAUDE_CONFIG_DIR\"],\n transports: [\"argv\", \"stdin\"],\n effort: true,\n mcp: true,\n probe: { help: [[\"--help\"]], version: [\"--version\"] },\n verification: {\n version: \"2.1.302\",\n verifiedBy: \"help\",\n sources: [\n \"https://code.claude.com/docs/en/headless\",\n \"https://code.claude.com/docs/en/cli-reference\",\n \"https://code.claude.com/docs/en/mcp\",\n \"https://code.claude.com/docs/en/env-vars\",\n ],\n checkedAt: \"2026-10-17\",\n },\n plan(context) {\n const args = [\n \"--print\",\n \"--output-format\",\n \"stream-json\",\n \"--verbose\",\n \"--include-partial-messages\",\n ];\n const requires = [\n \"--print\",\n \"--output-format\",\n \"stream-json\",\n \"--verbose\",\n \"--include-partial-messages\",\n ];\n const files: CliLaunchFile[] = [];\n\n if (context.model !== undefined) {\n args.push(\"--model\", context.model);\n requires.push(\"--model\");\n }\n\n if (context.effort !== undefined) {\n args.push(\n \"--effort\",\n mapEffort(context.effort, {\n low: \"low\",\n medium: \"medium\",\n high: \"high\",\n xhigh: \"xhigh\",\n max: \"max\",\n }),\n );\n requires.push(\"--effort\");\n }\n\n if (context.resume !== undefined) {\n args.push(\"--resume\", context.resume);\n requires.push(\"--resume\");\n }\n\n if (context.permission === \"bypass\") {\n args.push(\"--dangerously-skip-permissions\");\n requires.push(\"--dangerously-skip-permissions\");\n }\n\n if (context.mcp !== undefined) {\n const file = path.join(context.runDir, \"mcp.json\");\n\n files.push({\n path: file,\n content: jsonFile({ mcpServers: mcpServersJson(context.mcp, { typeField: true }) }),\n });\n args.push(\"--mcp-config\", file);\n requires.push(\"--mcp-config\");\n }\n\n return {\n args,\n tail: context.transport === \"argv\" ? [argvPrompt(context.prompt)] : [],\n stdin: context.transport === \"stdin\" ? context.prompt : undefined,\n env: {\n ...(context.home !== undefined ? { CLAUDE_CONFIG_DIR: context.home } : {}),\n DISABLE_AUTOUPDATER: \"1\",\n },\n files,\n requires,\n };\n },\n parser: () => createClaudeStreamParser({ usage: \"anthropic\", vendor: \"Claude Code\" }),\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAa,oBAAgC;CAC3C,MAAM;CACN,OAAO;CACP,SAAS;CACT,WAAW,CAAC,mBAAmB;CAC/B,SAAS,CAAC,mBAAmB;CAC7B,YAAY,CAAC,QAAQ,OAAO;CAC5B,QAAQ;CACR,KAAK;CACL,OAAO;EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC;EAAG,SAAS,CAAC,WAAW;CAAE;CACpD,cAAc;EACZ,SAAS;EACT,YAAY;EACZ,SAAS;GACP;GACA;GACA;GACA;EACF;EACA,WAAW;CACb;CACA,KAAK,SAAS;EACZ,MAAM,OAAO;GACX;GACA;GACA;GACA;GACA;EACF;EACA,MAAM,WAAW;GACf;GACA;GACA;GACA;GACA;EACF;EACA,MAAM,QAAyB,CAAC;EAEhC,IAAI,QAAQ,UAAU,QAAW;GAC/B,KAAK,KAAK,WAAW,QAAQ,KAAK;GAClC,SAAS,KAAK,SAAS;EACzB;EAEA,IAAI,QAAQ,WAAW,QAAW;GAChC,KAAK,KACH,YACA,UAAU,QAAQ,QAAQ;IACxB,KAAK;IACL,QAAQ;IACR,MAAM;IACN,OAAO;IACP,KAAK;GACP,CAAC,CACH;GACA,SAAS,KAAK,UAAU;EAC1B;EAEA,IAAI,QAAQ,WAAW,QAAW;GAChC,KAAK,KAAK,YAAY,QAAQ,MAAM;GACpC,SAAS,KAAK,UAAU;EAC1B;EAEA,IAAI,QAAQ,eAAe,UAAU;GACnC,KAAK,KAAK,gCAAgC;GAC1C,SAAS,KAAK,gCAAgC;EAChD;EAEA,IAAI,QAAQ,QAAQ,QAAW;GAC7B,MAAM,OAAO,KAAK,KAAK,QAAQ,QAAQ,UAAU;GAEjD,MAAM,KAAK;IACT,MAAM;IACN,SAAS,SAAS,EAAE,YAAY,eAAe,QAAQ,KAAK,EAAE,WAAW,KAAK,CAAC,EAAE,CAAC;GACpF,CAAC;GACD,KAAK,KAAK,gBAAgB,IAAI;GAC9B,SAAS,KAAK,cAAc;EAC9B;EAEA,OAAO;GACL;GACA,MAAM,QAAQ,cAAc,SAAS,CAAC,WAAW,QAAQ,MAAM,CAAC,IAAI,CAAC;GACrE,OAAO,QAAQ,cAAc,UAAU,QAAQ,SAAS;GACxD,KAAK;IACH,GAAI,QAAQ,SAAS,SAAY,EAAE,mBAAmB,QAAQ,KAAK,IAAI,CAAC;IACxE,qBAAqB;GACvB;GACA;GACA;EACF;CACF;CACA,cAAc,yBAAyB;EAAE,OAAO;EAAa,QAAQ;CAAc,CAAC;AACtF"}
@@ -0,0 +1,32 @@
1
+ import { CliStreamParser } from "../contracts/adapter.contract.mjs";
2
+ //#region ../../packages/ai-cli/src/adapters/claude-stream.d.ts
3
+ /**
4
+ * How a Claude-style stream reports input tokens.
5
+ *
6
+ * - `anthropic` — `input_tokens` excludes cache reads/writes (Claude Code).
7
+ * - `inclusive` — `input_tokens` already includes cached tokens (Qwen Code).
8
+ */
9
+ type ClaudeStreamUsage = "anthropic" | "inclusive";
10
+ /**
11
+ * Parser for the Claude Code `stream-json` format, which several CLIs
12
+ * reproduce (Qwen Code, Grok Build's `streaming-messages-json`):
13
+ *
14
+ * - `{"type":"system","subtype":"init","session_id","model",…}`
15
+ * - `{"type":"assistant","message":{"content":[text | tool_use | thinking]}}`
16
+ * - `{"type":"user","message":{"content":[{"type":"tool_result","tool_use_id","content","is_error"}]}}`
17
+ * - `{"type":"stream_event","event":{"type":"content_block_delta","delta":{"type":"text_delta","text"}}}`
18
+ * (only with partial messages enabled)
19
+ * - `{"type":"result","subtype","is_error","result","session_id","usage","total_cost_usd"}`
20
+ *
21
+ * Per-message `usage` is ignored (Claude Code repeats it on every content
22
+ * block of a message); the `result` totals are reported as cumulative usage.
23
+ * Sub-agent traffic (`parent_tool_use_id` set) is reported like the main
24
+ * thread's, so its tool calls stay visible.
25
+ */
26
+ declare function createClaudeStreamParser(options?: {
27
+ usage?: ClaudeStreamUsage;
28
+ vendor?: string;
29
+ }): CliStreamParser;
30
+ //#endregion
31
+ export { ClaudeStreamUsage, createClaudeStreamParser };
32
+ //# sourceMappingURL=claude-stream.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-stream.d.mts","names":[],"sources":["../../../../../../../../packages/ai-cli/src/adapters/claude-stream.ts"],"mappings":";;;;;AAmBA;;;KAAY,iBAAA;AAAiB;AAoC7B;;;;;;;;;;AAEkB;;;;;AAtCW,iBAoCb,wBAAA,CACd,OAAA;EAAW,KAAA,GAAQ,iBAAA;EAAmB,MAAA;AAAA,IACrC,eAAe"}
@@ -0,0 +1,140 @@
1
+ import { asArray, asRecord, jsonLinesParser, numberField, outputText, recordField, stringField } from "../stream/json-lines.mjs";
2
+ import { anthropicUsage, usageOf } from "./shared.mjs";
3
+
4
+ //#region ../../packages/ai-cli/src/adapters/claude-stream.ts
5
+ function inclusiveUsage(usage, costUSD) {
6
+ if (usage === void 0) return;
7
+ const cached = numberField(usage, "cache_read_input_tokens");
8
+ const written = numberField(usage, "cache_creation_input_tokens");
9
+ return usageOf({
10
+ input: numberField(usage, "input_tokens"),
11
+ output: numberField(usage, "output_tokens"),
12
+ total: numberField(usage, "total_tokens"),
13
+ cachedTokens: cached !== void 0 && cached > 0 ? cached : void 0,
14
+ cacheWriteTokens: written !== void 0 && written > 0 ? written : void 0,
15
+ costUSD
16
+ });
17
+ }
18
+ /**
19
+ * Parser for the Claude Code `stream-json` format, which several CLIs
20
+ * reproduce (Qwen Code, Grok Build's `streaming-messages-json`):
21
+ *
22
+ * - `{"type":"system","subtype":"init","session_id","model",…}`
23
+ * - `{"type":"assistant","message":{"content":[text | tool_use | thinking]}}`
24
+ * - `{"type":"user","message":{"content":[{"type":"tool_result","tool_use_id","content","is_error"}]}}`
25
+ * - `{"type":"stream_event","event":{"type":"content_block_delta","delta":{"type":"text_delta","text"}}}`
26
+ * (only with partial messages enabled)
27
+ * - `{"type":"result","subtype","is_error","result","session_id","usage","total_cost_usd"}`
28
+ *
29
+ * Per-message `usage` is ignored (Claude Code repeats it on every content
30
+ * block of a message); the `result` totals are reported as cumulative usage.
31
+ * Sub-agent traffic (`parent_tool_use_id` set) is reported like the main
32
+ * thread's, so its tool calls stay visible.
33
+ */
34
+ function createClaudeStreamParser(options = {}) {
35
+ const style = options.usage ?? "anthropic";
36
+ const vendor = options.vendor ?? "The CLI";
37
+ return jsonLinesParser((record) => {
38
+ switch (stringField(record, "type")) {
39
+ case "system": {
40
+ const subtype = stringField(record, "subtype");
41
+ if (subtype?.startsWith("error") && stringField(record, "error") !== void 0) return [{
42
+ type: "error",
43
+ message: stringField(record, "error") ?? subtype,
44
+ raw: record
45
+ }];
46
+ return subtype === "init" || subtype === "session_start" ? [{
47
+ type: "session.started",
48
+ sessionRef: stringField(record, "session_id"),
49
+ model: stringField(record, "model"),
50
+ raw: record
51
+ }] : [];
52
+ }
53
+ case "assistant": {
54
+ const events = [];
55
+ for (const item of asArray(recordField(record, "message")?.content)) {
56
+ const block = asRecord(item);
57
+ const blockType = stringField(block, "type");
58
+ if (blockType === "text") {
59
+ const text = stringField(block, "text") ?? "";
60
+ if (text.length > 0) events.push({
61
+ type: "message",
62
+ text,
63
+ delta: false,
64
+ raw: record
65
+ });
66
+ } else if (blockType === "tool_use" || blockType === "server_tool_use") events.push({
67
+ type: "tool.call",
68
+ id: stringField(block, "id") ?? "",
69
+ name: stringField(block, "name") ?? "",
70
+ input: block?.input,
71
+ raw: record
72
+ });
73
+ }
74
+ return events;
75
+ }
76
+ case "user": {
77
+ const events = [];
78
+ for (const item of asArray(recordField(record, "message")?.content)) {
79
+ const block = asRecord(item);
80
+ if (stringField(block, "type") === "tool_result") events.push({
81
+ type: "tool.result",
82
+ id: stringField(block, "tool_use_id") ?? "",
83
+ output: outputText(block?.content),
84
+ isError: block?.is_error === true,
85
+ raw: record
86
+ });
87
+ }
88
+ return events;
89
+ }
90
+ case "stream_event": {
91
+ const event = recordField(record, "event");
92
+ const delta = recordField(event, "delta");
93
+ if (stringField(event, "type") === "content_block_delta" && stringField(delta, "type") === "text_delta") {
94
+ const text = stringField(delta, "text") ?? "";
95
+ return text.length > 0 ? [{
96
+ type: "message",
97
+ text,
98
+ delta: true,
99
+ raw: record
100
+ }] : [];
101
+ }
102
+ return [];
103
+ }
104
+ case "result": {
105
+ const events = [];
106
+ const cost = numberField(record, "total_cost_usd");
107
+ const usage = style === "anthropic" ? anthropicUsage(recordField(record, "usage"), cost) : inclusiveUsage(recordField(record, "usage"), cost);
108
+ if (usage !== void 0) events.push({
109
+ type: "usage",
110
+ usage,
111
+ cumulative: true,
112
+ raw: record
113
+ });
114
+ const result = stringField(record, "result");
115
+ if (record.is_error === true) {
116
+ const errors = asArray(record.errors).map((item) => typeof item === "string" ? item : stringField(asRecord(item), "message") ?? "").filter((item) => item.length > 0).join("; ");
117
+ const message = stringField(recordField(record, "error"), "message") || stringField(record, "error") || errors || result || `${vendor} run ended with ${stringField(record, "subtype") ?? "an error"}`;
118
+ events.push({
119
+ type: "error",
120
+ message,
121
+ fatal: true,
122
+ raw: record
123
+ });
124
+ } else if (result !== void 0 && result.length > 0) events.push({
125
+ type: "message",
126
+ text: result,
127
+ delta: false,
128
+ final: true,
129
+ raw: record
130
+ });
131
+ return events;
132
+ }
133
+ default: return [];
134
+ }
135
+ });
136
+ }
137
+
138
+ //#endregion
139
+ export { createClaudeStreamParser };
140
+ //# sourceMappingURL=claude-stream.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-stream.mjs","names":[],"sources":["../../../../../../../../packages/ai-cli/src/adapters/claude-stream.ts"],"sourcesContent":["import type { CliParsedEvent, CliStreamParser, CliUsage } from \"../contracts\";\nimport {\n asArray,\n asRecord,\n jsonLinesParser,\n numberField,\n outputText,\n recordField,\n stringField,\n type JsonRecord,\n} from \"../stream/json-lines\";\nimport { anthropicUsage, usageOf } from \"./shared\";\n\n/**\n * How a Claude-style stream reports input tokens.\n *\n * - `anthropic` — `input_tokens` excludes cache reads/writes (Claude Code).\n * - `inclusive` — `input_tokens` already includes cached tokens (Qwen Code).\n */\nexport type ClaudeStreamUsage = \"anthropic\" | \"inclusive\";\n\nfunction inclusiveUsage(usage: JsonRecord | undefined, costUSD?: number): CliUsage | undefined {\n if (usage === undefined) {\n return undefined;\n }\n\n const cached = numberField(usage, \"cache_read_input_tokens\");\n const written = numberField(usage, \"cache_creation_input_tokens\");\n\n return usageOf({\n input: numberField(usage, \"input_tokens\"),\n output: numberField(usage, \"output_tokens\"),\n total: numberField(usage, \"total_tokens\"),\n cachedTokens: cached !== undefined && cached > 0 ? cached : undefined,\n cacheWriteTokens: written !== undefined && written > 0 ? written : undefined,\n costUSD,\n });\n}\n\n/**\n * Parser for the Claude Code `stream-json` format, which several CLIs\n * reproduce (Qwen Code, Grok Build's `streaming-messages-json`):\n *\n * - `{\"type\":\"system\",\"subtype\":\"init\",\"session_id\",\"model\",…}`\n * - `{\"type\":\"assistant\",\"message\":{\"content\":[text | tool_use | thinking]}}`\n * - `{\"type\":\"user\",\"message\":{\"content\":[{\"type\":\"tool_result\",\"tool_use_id\",\"content\",\"is_error\"}]}}`\n * - `{\"type\":\"stream_event\",\"event\":{\"type\":\"content_block_delta\",\"delta\":{\"type\":\"text_delta\",\"text\"}}}`\n * (only with partial messages enabled)\n * - `{\"type\":\"result\",\"subtype\",\"is_error\",\"result\",\"session_id\",\"usage\",\"total_cost_usd\"}`\n *\n * Per-message `usage` is ignored (Claude Code repeats it on every content\n * block of a message); the `result` totals are reported as cumulative usage.\n * Sub-agent traffic (`parent_tool_use_id` set) is reported like the main\n * thread's, so its tool calls stay visible.\n */\nexport function createClaudeStreamParser(\n options: { usage?: ClaudeStreamUsage; vendor?: string } = {},\n): CliStreamParser {\n const style = options.usage ?? \"anthropic\";\n const vendor = options.vendor ?? \"The CLI\";\n\n return jsonLinesParser((record): CliParsedEvent[] => {\n switch (stringField(record, \"type\")) {\n case \"system\": {\n const subtype = stringField(record, \"subtype\");\n\n if (subtype?.startsWith(\"error\") && stringField(record, \"error\") !== undefined) {\n return [{ type: \"error\", message: stringField(record, \"error\") ?? subtype, raw: record }];\n }\n\n return subtype === \"init\" || subtype === \"session_start\"\n ? [\n {\n type: \"session.started\",\n sessionRef: stringField(record, \"session_id\"),\n model: stringField(record, \"model\"),\n raw: record,\n },\n ]\n : [];\n }\n case \"assistant\": {\n const events: CliParsedEvent[] = [];\n\n for (const item of asArray(recordField(record, \"message\")?.content)) {\n const block = asRecord(item);\n const blockType = stringField(block, \"type\");\n\n if (blockType === \"text\") {\n const text = stringField(block, \"text\") ?? \"\";\n\n if (text.length > 0) {\n events.push({ type: \"message\", text, delta: false, raw: record });\n }\n } else if (blockType === \"tool_use\" || blockType === \"server_tool_use\") {\n events.push({\n type: \"tool.call\",\n id: stringField(block, \"id\") ?? \"\",\n name: stringField(block, \"name\") ?? \"\",\n input: block?.input,\n raw: record,\n });\n }\n }\n\n return events;\n }\n case \"user\": {\n const events: CliParsedEvent[] = [];\n\n for (const item of asArray(recordField(record, \"message\")?.content)) {\n const block = asRecord(item);\n\n if (stringField(block, \"type\") === \"tool_result\") {\n events.push({\n type: \"tool.result\",\n id: stringField(block, \"tool_use_id\") ?? \"\",\n output: outputText(block?.content),\n isError: block?.is_error === true,\n raw: record,\n });\n }\n }\n\n return events;\n }\n case \"stream_event\": {\n const event = recordField(record, \"event\");\n const delta = recordField(event, \"delta\");\n\n if (\n stringField(event, \"type\") === \"content_block_delta\" &&\n stringField(delta, \"type\") === \"text_delta\"\n ) {\n const text = stringField(delta, \"text\") ?? \"\";\n\n return text.length > 0 ? [{ type: \"message\", text, delta: true, raw: record }] : [];\n }\n\n return [];\n }\n case \"result\": {\n const events: CliParsedEvent[] = [];\n const cost = numberField(record, \"total_cost_usd\");\n const usage =\n style === \"anthropic\"\n ? anthropicUsage(recordField(record, \"usage\"), cost)\n : inclusiveUsage(recordField(record, \"usage\"), cost);\n\n if (usage !== undefined) {\n events.push({ type: \"usage\", usage, cumulative: true, raw: record });\n }\n\n const result = stringField(record, \"result\");\n\n if (record.is_error === true) {\n const errors = asArray(record.errors)\n .map((item) =>\n typeof item === \"string\" ? item : (stringField(asRecord(item), \"message\") ?? \"\"),\n )\n .filter((item) => item.length > 0)\n .join(\"; \");\n const message =\n stringField(recordField(record, \"error\"), \"message\") ||\n stringField(record, \"error\") ||\n errors ||\n result ||\n `${vendor} run ended with ${stringField(record, \"subtype\") ?? \"an error\"}`;\n\n events.push({ type: \"error\", message, fatal: true, raw: record });\n } else if (result !== undefined && result.length > 0) {\n events.push({ type: \"message\", text: result, delta: false, final: true, raw: record });\n }\n\n return events;\n }\n default:\n return [];\n }\n });\n}\n"],"mappings":"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"}