@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.
- package/CHANGELOG.md +31 -0
- package/LICENSE +21 -0
- package/README.md +69 -2
- package/cjs/index.cjs +4576 -0
- package/cjs/index.cjs.map +1 -0
- package/esm/adapters/aider.d.mts +41 -0
- package/esm/adapters/aider.d.mts.map +1 -0
- package/esm/adapters/aider.mjs +294 -0
- package/esm/adapters/aider.mjs.map +1 -0
- package/esm/adapters/amp.d.mts +33 -0
- package/esm/adapters/amp.d.mts.map +1 -0
- package/esm/adapters/amp.mjs +119 -0
- package/esm/adapters/amp.mjs.map +1 -0
- package/esm/adapters/antigravity.d.mts +37 -0
- package/esm/adapters/antigravity.d.mts.map +1 -0
- package/esm/adapters/antigravity.mjs +235 -0
- package/esm/adapters/antigravity.mjs.map +1 -0
- package/esm/adapters/claude-code.d.mts +30 -0
- package/esm/adapters/claude-code.d.mts.map +1 -0
- package/esm/adapters/claude-code.mjs +121 -0
- package/esm/adapters/claude-code.mjs.map +1 -0
- package/esm/adapters/claude-stream.d.mts +32 -0
- package/esm/adapters/claude-stream.d.mts.map +1 -0
- package/esm/adapters/claude-stream.mjs +140 -0
- package/esm/adapters/claude-stream.mjs.map +1 -0
- package/esm/adapters/codex.d.mts +37 -0
- package/esm/adapters/codex.d.mts.map +1 -0
- package/esm/adapters/codex.mjs +320 -0
- package/esm/adapters/codex.mjs.map +1 -0
- package/esm/adapters/copilot.d.mts +35 -0
- package/esm/adapters/copilot.d.mts.map +1 -0
- package/esm/adapters/copilot.mjs +244 -0
- package/esm/adapters/copilot.mjs.map +1 -0
- package/esm/adapters/cursor.d.mts +35 -0
- package/esm/adapters/cursor.d.mts.map +1 -0
- package/esm/adapters/cursor.mjs +203 -0
- package/esm/adapters/cursor.mjs.map +1 -0
- package/esm/adapters/droid.d.mts +32 -0
- package/esm/adapters/droid.d.mts.map +1 -0
- package/esm/adapters/droid.mjs +183 -0
- package/esm/adapters/droid.mjs.map +1 -0
- package/esm/adapters/grok.d.mts +32 -0
- package/esm/adapters/grok.d.mts.map +1 -0
- package/esm/adapters/grok.mjs +199 -0
- package/esm/adapters/grok.mjs.map +1 -0
- package/esm/adapters/index.d.mts +16 -0
- package/esm/adapters/index.mjs +18 -0
- package/esm/adapters/kimi.d.mts +34 -0
- package/esm/adapters/kimi.d.mts.map +1 -0
- package/esm/adapters/kimi.mjs +162 -0
- package/esm/adapters/kimi.mjs.map +1 -0
- package/esm/adapters/mistral-vibe.d.mts +32 -0
- package/esm/adapters/mistral-vibe.d.mts.map +1 -0
- package/esm/adapters/mistral-vibe.mjs +252 -0
- package/esm/adapters/mistral-vibe.mjs.map +1 -0
- package/esm/adapters/opencode.d.mts +36 -0
- package/esm/adapters/opencode.d.mts.map +1 -0
- package/esm/adapters/opencode.mjs +219 -0
- package/esm/adapters/opencode.mjs.map +1 -0
- package/esm/adapters/qwen-code.d.mts +30 -0
- package/esm/adapters/qwen-code.d.mts.map +1 -0
- package/esm/adapters/qwen-code.mjs +94 -0
- package/esm/adapters/qwen-code.mjs.map +1 -0
- package/esm/adapters/reasonix.d.mts +31 -0
- package/esm/adapters/reasonix.d.mts.map +1 -0
- package/esm/adapters/reasonix.mjs +250 -0
- package/esm/adapters/reasonix.mjs.map +1 -0
- package/esm/adapters/shared.d.mts +78 -0
- package/esm/adapters/shared.d.mts.map +1 -0
- package/esm/adapters/shared.mjs +161 -0
- package/esm/adapters/shared.mjs.map +1 -0
- package/esm/cli-agent.d.mts +40 -0
- package/esm/cli-agent.d.mts.map +1 -0
- package/esm/cli-agent.mjs +207 -0
- package/esm/cli-agent.mjs.map +1 -0
- package/esm/cli.d.mts +53 -0
- package/esm/cli.d.mts.map +1 -0
- package/esm/cli.mjs +61 -0
- package/esm/cli.mjs.map +1 -0
- package/esm/contracts/adapter.contract.d.mts +154 -0
- package/esm/contracts/adapter.contract.d.mts.map +1 -0
- package/esm/contracts/events.type.d.mts +111 -0
- package/esm/contracts/events.type.d.mts.map +1 -0
- package/esm/contracts/index.d.mts +4 -0
- package/esm/contracts/mcp.type.d.mts +29 -0
- package/esm/contracts/mcp.type.d.mts.map +1 -0
- package/esm/contracts/options.type.d.mts +87 -0
- package/esm/contracts/options.type.d.mts.map +1 -0
- package/esm/errors.d.mts +46 -0
- package/esm/errors.d.mts.map +1 -0
- package/esm/errors.mjs +32 -0
- package/esm/errors.mjs.map +1 -0
- package/esm/index.d.mts +31 -0
- package/esm/index.mjs +28 -0
- package/esm/model/cli-model.d.mts +48 -0
- package/esm/model/cli-model.d.mts.map +1 -0
- package/esm/model/cli-model.mjs +133 -0
- package/esm/model/cli-model.mjs.map +1 -0
- package/esm/probe/probe.d.mts +18 -0
- package/esm/probe/probe.d.mts.map +1 -0
- package/esm/probe/probe.mjs +148 -0
- package/esm/probe/probe.mjs.map +1 -0
- package/esm/session/aggregate.mjs +86 -0
- package/esm/session/aggregate.mjs.map +1 -0
- package/esm/session/environment.mjs +71 -0
- package/esm/session/environment.mjs.map +1 -0
- package/esm/session/run-directory.mjs +74 -0
- package/esm/session/run-directory.mjs.map +1 -0
- package/esm/session/session.mjs +188 -0
- package/esm/session/session.mjs.map +1 -0
- package/esm/spawn/invocation.d.mts +35 -0
- package/esm/spawn/invocation.d.mts.map +1 -0
- package/esm/spawn/invocation.mjs +76 -0
- package/esm/spawn/invocation.mjs.map +1 -0
- package/esm/spawn/process-tree.mjs +57 -0
- package/esm/spawn/process-tree.mjs.map +1 -0
- package/esm/spawn/resolve-command.d.mts +73 -0
- package/esm/spawn/resolve-command.d.mts.map +1 -0
- package/esm/spawn/resolve-command.mjs +109 -0
- package/esm/spawn/resolve-command.mjs.map +1 -0
- package/esm/stream/event-log.mjs +52 -0
- package/esm/stream/event-log.mjs.map +1 -0
- package/esm/stream/json-lines.d.mts +33 -0
- package/esm/stream/json-lines.d.mts.map +1 -0
- package/esm/stream/json-lines.mjs +65 -0
- package/esm/stream/json-lines.mjs.map +1 -0
- package/esm/stream/line-splitter.mjs +53 -0
- package/esm/stream/line-splitter.mjs.map +1 -0
- package/esm/utils/toml.d.mts +22 -0
- package/esm/utils/toml.d.mts.map +1 -0
- package/esm/utils/toml.mjs +53 -0
- package/esm/utils/toml.mjs.map +1 -0
- package/llms-full.txt +373 -0
- package/llms.txt +10 -0
- package/package.json +39 -4
- package/skills/README.md +13 -0
- package/skills/index.md +22 -0
- package/skills/run-cli-agents/SKILL.md +186 -0
- 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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"}
|