@smithers-orchestrator/agents 0.24.0 → 0.25.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/package.json +15 -5
- package/src/AgentLike.ts +5 -0
- package/src/AmpAgent.js +15 -5
- package/src/AmpAgentOptions.ts +6 -0
- package/src/BaseCliAgent/BaseCliAgent.js +205 -11
- package/src/BaseCliAgent/createAgentStdoutTextEmitter.js +21 -3
- package/src/BaseCliAgent/index.d.ts +467 -0
- package/src/ClaudeCodeAgent.js +6 -2
- package/src/CodexAgent.js +17 -2
- package/src/CodexAgentOptions.ts +11 -0
- package/src/GeminiAgent.js +34 -224
- package/src/GeminiAgentOptions.ts +4 -9
- package/src/OpenCodeAgent.js +2 -12
- package/src/OpenCodeAgentOptions.ts +19 -0
- package/src/PiAgent.js +63 -5
- package/src/cli-capabilities/CliAgentCapabilityAdapterId.ts +0 -1
- package/src/cli-capabilities/getCliAgentCapabilityDoctorReport.js +3 -2
- package/src/cli-capabilities/getCliAgentCapabilityReport.js +0 -6
- package/src/cli-surface/cliAgentSurfaceManifest.js +1 -40
- package/src/createElevenLabsTextToSpeechTool.js +128 -0
- package/src/createElevenLabsTextToSpeechTool.ts +33 -0
- package/src/diagnostics/getDiagnosticStrategy.js +94 -23
- package/src/diagnostics/launchDiagnostics.js +7 -4
- package/src/document-parsing/DocumentParsingProvider.ts +13 -0
- package/src/document-parsing/DocumentParsingResult.ts +13 -0
- package/src/document-parsing/DocumentParsingToolset.ts +4 -0
- package/src/document-parsing/DocumentParsingToolsetOptions.ts +9 -0
- package/src/document-parsing/createDocumentParsingToolset.d.ts +9 -0
- package/src/document-parsing/createDocumentParsingToolset.js +416 -0
- package/src/http/CreateHttpToolOptions.ts +4 -0
- package/src/http/HttpToolAuth.ts +15 -0
- package/src/http/HttpToolInput.ts +11 -0
- package/src/http/HttpToolOutput.ts +7 -0
- package/src/http/createHttpTool.js +136 -0
- package/src/image-generation/ImageGenerationProvider.ts +7 -0
- package/src/image-generation/ImageGenerationRequest.ts +8 -0
- package/src/image-generation/ImageGenerationResult.ts +10 -0
- package/src/image-generation/ImageGenerationToolOptions.ts +10 -0
- package/src/image-generation/createImageGenerationTool.d.ts +18 -0
- package/src/image-generation/createImageGenerationTool.js +92 -0
- package/src/index.d.ts +490 -147
- package/src/index.js +23 -5
- package/src/streamResultToGenerateResult.js +55 -26
- package/src/transcription/createTranscriptionTool.js +182 -0
- package/src/transcription/createTranscriptionTool.ts +29 -0
- package/src/transcription/index.js +1 -0
- package/src/transcription/index.ts +6 -0
- package/src/web-search/GroundedWebSearchProvider.ts +21 -0
- package/src/web-search/GroundedWebSearchToolset.ts +6 -0
- package/src/web-search/createBraveSearchProvider.js +53 -0
- package/src/web-search/createExaSearchProvider.js +72 -0
- package/src/web-search/createGroundedWebSearchToolset.js +110 -0
- package/src/web-search/createSerperSearchProvider.js +63 -0
- package/src/web-search/createTavilySearchProvider.js +59 -0
- package/src/web-search/index.js +5 -0
- package/src/zodToOpenAISchema.js +4 -0
- package/src/OpenCodeAgent.ts +0 -43
package/src/GeminiAgent.js
CHANGED
|
@@ -1,18 +1,27 @@
|
|
|
1
|
-
import { BaseCliAgent
|
|
2
|
-
import { normalizeCapabilityStringList
|
|
3
|
-
|
|
1
|
+
import { BaseCliAgent } from "./BaseCliAgent/index.js";
|
|
2
|
+
import { normalizeCapabilityStringList } from "./capability-registry/index.js";
|
|
3
|
+
|
|
4
4
|
/** @typedef {import("./capability-registry/AgentCapabilityRegistry.ts").AgentCapabilityRegistry} AgentCapabilityRegistry */
|
|
5
5
|
/** @typedef {import("./BaseCliAgent/CliOutputInterpreter.ts").CliOutputInterpreter} CliOutputInterpreter */
|
|
6
6
|
/** @typedef {import("./GeminiAgentOptions.ts").GeminiAgentOptions} GeminiAgentOptions */
|
|
7
7
|
|
|
8
|
+
export const GEMINI_SUNSET_MESSAGE = [
|
|
9
|
+
"Gemini CLI support has been sunset in Smithers.",
|
|
10
|
+
"Use AntigravityAgent with Google's `agy` CLI instead.",
|
|
11
|
+
"Example:",
|
|
12
|
+
' import { AntigravityAgent } from "smithers-orchestrator";',
|
|
13
|
+
' const agent = new AntigravityAgent({ model: "gemini-3.1-pro-preview", cwd: process.cwd() });',
|
|
14
|
+
].join("\n");
|
|
15
|
+
|
|
8
16
|
/**
|
|
9
17
|
* @param {GeminiAgentOptions} opts
|
|
10
18
|
*/
|
|
11
19
|
function resolveGeminiBuiltIns(opts) {
|
|
12
20
|
return opts.allowedTools?.length
|
|
13
21
|
? normalizeCapabilityStringList(opts.allowedTools)
|
|
14
|
-
: ["
|
|
22
|
+
: ["sunset"];
|
|
15
23
|
}
|
|
24
|
+
|
|
16
25
|
/**
|
|
17
26
|
* @param {GeminiAgentOptions} [opts]
|
|
18
27
|
* @returns {AgentCapabilityRegistry}
|
|
@@ -23,9 +32,9 @@ export function createGeminiCapabilityRegistry(opts = {}) {
|
|
|
23
32
|
engine: "gemini",
|
|
24
33
|
runtimeTools: {},
|
|
25
34
|
mcp: {
|
|
26
|
-
bootstrap: "
|
|
35
|
+
bootstrap: "unsupported",
|
|
27
36
|
supportsProjectScope: false,
|
|
28
|
-
supportsUserScope:
|
|
37
|
+
supportsUserScope: false,
|
|
29
38
|
},
|
|
30
39
|
skills: {
|
|
31
40
|
supportsSkills: false,
|
|
@@ -38,14 +47,16 @@ export function createGeminiCapabilityRegistry(opts = {}) {
|
|
|
38
47
|
builtIns: resolveGeminiBuiltIns(opts),
|
|
39
48
|
};
|
|
40
49
|
}
|
|
50
|
+
|
|
41
51
|
/**
|
|
42
|
-
* @deprecated
|
|
43
|
-
*
|
|
52
|
+
* @deprecated Gemini CLI support has been sunset. Use AntigravityAgent with
|
|
53
|
+
* Google's `agy` CLI instead.
|
|
44
54
|
*/
|
|
45
55
|
export class GeminiAgent extends BaseCliAgent {
|
|
46
56
|
opts;
|
|
47
57
|
capabilities;
|
|
48
58
|
cliEngine = "gemini";
|
|
59
|
+
|
|
49
60
|
/**
|
|
50
61
|
* @param {GeminiAgentOptions} [opts]
|
|
51
62
|
*/
|
|
@@ -54,228 +65,27 @@ export class GeminiAgent extends BaseCliAgent {
|
|
|
54
65
|
this.opts = opts;
|
|
55
66
|
this.capabilities = createGeminiCapabilityRegistry(opts);
|
|
56
67
|
}
|
|
68
|
+
|
|
57
69
|
/**
|
|
58
70
|
* @returns {CliOutputInterpreter}
|
|
59
71
|
*/
|
|
60
72
|
createOutputInterpreter() {
|
|
61
|
-
let sessionId;
|
|
62
|
-
let finalAnswer = "";
|
|
63
|
-
let didEmitCompleted = false;
|
|
64
|
-
const nextSyntheticId = createSyntheticIdGenerator();
|
|
65
|
-
/**
|
|
66
|
-
* @param {string} line
|
|
67
|
-
* @returns {AgentCliEvent[]}
|
|
68
|
-
*/
|
|
69
|
-
const parseLine = (line) => {
|
|
70
|
-
const trimmed = line.trim();
|
|
71
|
-
if (!trimmed)
|
|
72
|
-
return [];
|
|
73
|
-
let payload;
|
|
74
|
-
try {
|
|
75
|
-
payload = JSON.parse(trimmed);
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
return [];
|
|
79
|
-
}
|
|
80
|
-
if (!isRecord(payload))
|
|
81
|
-
return [];
|
|
82
|
-
const type = asString(payload.type);
|
|
83
|
-
if (!type)
|
|
84
|
-
return [];
|
|
85
|
-
if (type === "init") {
|
|
86
|
-
const resume = asString(payload.session_id);
|
|
87
|
-
if (resume) {
|
|
88
|
-
sessionId = resume;
|
|
89
|
-
}
|
|
90
|
-
return [{
|
|
91
|
-
type: "started",
|
|
92
|
-
engine: this.cliEngine,
|
|
93
|
-
title: "Gemini CLI",
|
|
94
|
-
resume: sessionId,
|
|
95
|
-
detail: {
|
|
96
|
-
model: asString(payload.model),
|
|
97
|
-
},
|
|
98
|
-
}];
|
|
99
|
-
}
|
|
100
|
-
if (type === "MESSAGE") {
|
|
101
|
-
const role = asString(payload.role);
|
|
102
|
-
const content = asString(payload.content);
|
|
103
|
-
if (role === "assistant" && content) {
|
|
104
|
-
if (payload.delta === true) {
|
|
105
|
-
finalAnswer += content;
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
finalAnswer = content;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return [];
|
|
112
|
-
}
|
|
113
|
-
if (type === "TOOL_USE") {
|
|
114
|
-
const toolName = asString(payload.tool_name) ?? "tool";
|
|
115
|
-
const toolId = asString(payload.tool_id) ?? nextSyntheticId("gemini-tool");
|
|
116
|
-
return [{
|
|
117
|
-
type: "action",
|
|
118
|
-
engine: this.cliEngine,
|
|
119
|
-
phase: "started",
|
|
120
|
-
entryType: "thought",
|
|
121
|
-
action: {
|
|
122
|
-
id: toolId,
|
|
123
|
-
kind: toolKindFromName(toolName),
|
|
124
|
-
title: toolName,
|
|
125
|
-
detail: {
|
|
126
|
-
parameters: payload.parameters,
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
message: `Running ${toolName}`,
|
|
130
|
-
level: "info",
|
|
131
|
-
}];
|
|
132
|
-
}
|
|
133
|
-
if (type === "TOOL_RESULT") {
|
|
134
|
-
const toolId = asString(payload.tool_id) ?? nextSyntheticId("gemini-tool");
|
|
135
|
-
const ok = asString(payload.status) !== "error";
|
|
136
|
-
const error = isRecord(payload.error) ? asString(payload.error.message) : undefined;
|
|
137
|
-
const output = asString(payload.output);
|
|
138
|
-
return [{
|
|
139
|
-
type: "action",
|
|
140
|
-
engine: this.cliEngine,
|
|
141
|
-
phase: "completed",
|
|
142
|
-
entryType: "thought",
|
|
143
|
-
action: {
|
|
144
|
-
id: toolId,
|
|
145
|
-
kind: "tool",
|
|
146
|
-
title: "tool result",
|
|
147
|
-
detail: {
|
|
148
|
-
status: asString(payload.status),
|
|
149
|
-
output: output ? truncate(output, 400) : undefined,
|
|
150
|
-
},
|
|
151
|
-
},
|
|
152
|
-
message: error ?? output,
|
|
153
|
-
ok,
|
|
154
|
-
level: ok ? "info" : "warning",
|
|
155
|
-
}];
|
|
156
|
-
}
|
|
157
|
-
if (type === "ERROR") {
|
|
158
|
-
return [{
|
|
159
|
-
type: "action",
|
|
160
|
-
engine: this.cliEngine,
|
|
161
|
-
phase: "completed",
|
|
162
|
-
entryType: "thought",
|
|
163
|
-
action: {
|
|
164
|
-
id: nextSyntheticId("gemini-warning"),
|
|
165
|
-
kind: "warning",
|
|
166
|
-
title: "warning",
|
|
167
|
-
detail: {
|
|
168
|
-
severity: asString(payload.severity),
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
message: asString(payload.message),
|
|
172
|
-
ok: asString(payload.severity) !== "error",
|
|
173
|
-
level: asString(payload.severity) === "error" ? "error" : "warning",
|
|
174
|
-
}];
|
|
175
|
-
}
|
|
176
|
-
if (type === "RESULT") {
|
|
177
|
-
if (didEmitCompleted)
|
|
178
|
-
return [];
|
|
179
|
-
didEmitCompleted = true;
|
|
180
|
-
return [{
|
|
181
|
-
type: "completed",
|
|
182
|
-
engine: this.cliEngine,
|
|
183
|
-
ok: asString(payload.status) !== "error",
|
|
184
|
-
answer: finalAnswer || asString(payload.response),
|
|
185
|
-
resume: sessionId,
|
|
186
|
-
usage: isRecord(payload.stats) ? payload.stats : undefined,
|
|
187
|
-
}];
|
|
188
|
-
}
|
|
189
|
-
return [];
|
|
190
|
-
};
|
|
191
73
|
return {
|
|
192
|
-
onStdoutLine:
|
|
193
|
-
onExit: (
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return [{
|
|
200
|
-
type: "completed",
|
|
201
|
-
engine: this.cliEngine,
|
|
202
|
-
ok: false,
|
|
203
|
-
answer: finalAnswer || undefined,
|
|
204
|
-
error: result.stderr.trim() || `Gemini exited with code ${result.exitCode}`,
|
|
205
|
-
resume: sessionId,
|
|
206
|
-
}];
|
|
207
|
-
},
|
|
74
|
+
onStdoutLine: () => [],
|
|
75
|
+
onExit: () => [{
|
|
76
|
+
type: "completed",
|
|
77
|
+
engine: this.cliEngine,
|
|
78
|
+
ok: false,
|
|
79
|
+
error: GEMINI_SUNSET_MESSAGE,
|
|
80
|
+
}],
|
|
208
81
|
};
|
|
209
82
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
// output text. With "text" format, tool call results (file contents etc.)
|
|
218
|
-
// are concatenated into the response, making JSON extraction unreliable.
|
|
219
|
-
const outputFormat = this.opts.outputFormat ??
|
|
220
|
-
(params.options?.onEvent ? "stream-json" : "json");
|
|
221
|
-
const resumeSession = typeof params.options?.resumeSession === "string"
|
|
222
|
-
? params.options.resumeSession
|
|
223
|
-
: this.opts.resume;
|
|
224
|
-
if (this.opts.debug)
|
|
225
|
-
args.push("--debug");
|
|
226
|
-
pushFlag(args, "--model", this.opts.model ?? this.model);
|
|
227
|
-
if (this.opts.sandbox)
|
|
228
|
-
args.push("--sandbox");
|
|
229
|
-
if (this.opts.approvalMode) {
|
|
230
|
-
pushFlag(args, "--approval-mode", this.opts.approvalMode);
|
|
231
|
-
}
|
|
232
|
-
else if (yoloEnabled) {
|
|
233
|
-
args.push("--yolo");
|
|
234
|
-
}
|
|
235
|
-
if (this.opts.experimentalAcp)
|
|
236
|
-
args.push("--experimental-acp");
|
|
237
|
-
pushList(args, "--allowed-mcp-server-names", this.opts.allowedMcpServerNames);
|
|
238
|
-
if (this.opts.allowedTools !== undefined) {
|
|
239
|
-
if (this.opts.allowedTools.length === 0) {
|
|
240
|
-
pushFlag(args, "--allowed-tools", "");
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
pushList(args, "--allowed-tools", this.opts.allowedTools);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
pushList(args, "--extensions", this.opts.extensions);
|
|
247
|
-
if (this.opts.listExtensions)
|
|
248
|
-
args.push("--list-extensions");
|
|
249
|
-
pushFlag(args, "--resume", resumeSession);
|
|
250
|
-
if (this.opts.listSessions)
|
|
251
|
-
args.push("--list-sessions");
|
|
252
|
-
pushFlag(args, "--delete-session", this.opts.deleteSession);
|
|
253
|
-
pushList(args, "--include-directories", this.opts.includeDirectories);
|
|
254
|
-
if (this.opts.screenReader)
|
|
255
|
-
args.push("--screen-reader");
|
|
256
|
-
pushFlag(args, "--output-format", outputFormat);
|
|
257
|
-
if (this.extraArgs?.length)
|
|
258
|
-
args.push(...this.extraArgs);
|
|
259
|
-
const systemPrefix = params.systemPrompt
|
|
260
|
-
? `${params.systemPrompt}\n\n`
|
|
261
|
-
: "";
|
|
262
|
-
// Reinforce raw JSON output requirement in the prompt for Gemini models
|
|
263
|
-
// which tend to forget structured output instructions on long responses.
|
|
264
|
-
const jsonReminder = params.prompt?.includes("REQUIRED OUTPUT")
|
|
265
|
-
? "\n\nREMINDER: Your response MUST be ONLY the required raw JSON object. Do not include prose, markdown, or code fences. The first character must be `{` and the last character must be `}`.\n"
|
|
266
|
-
: "";
|
|
267
|
-
const fullPrompt = `${systemPrefix}${params.prompt ?? ""}${jsonReminder}`;
|
|
268
|
-
args.push("--prompt", fullPrompt);
|
|
269
|
-
const accountEnv = {};
|
|
270
|
-
if (this.opts.configDir)
|
|
271
|
-
accountEnv.GEMINI_DIR = this.opts.configDir;
|
|
272
|
-
if (this.opts.apiKey)
|
|
273
|
-
accountEnv.GEMINI_API_KEY = this.opts.apiKey;
|
|
274
|
-
return {
|
|
275
|
-
command: "gemini",
|
|
276
|
-
args,
|
|
277
|
-
outputFormat,
|
|
278
|
-
env: Object.keys(accountEnv).length > 0 ? accountEnv : undefined,
|
|
279
|
-
};
|
|
83
|
+
|
|
84
|
+
async generate() {
|
|
85
|
+
throw new Error(GEMINI_SUNSET_MESSAGE);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async buildCommand() {
|
|
89
|
+
throw new Error(GEMINI_SUNSET_MESSAGE);
|
|
280
90
|
}
|
|
281
91
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { BaseCliAgentOptions } from "./BaseCliAgent/BaseCliAgentOptions";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @deprecated
|
|
5
|
-
*
|
|
6
|
-
* enterprise Gemini CLI setups.
|
|
4
|
+
* @deprecated Gemini CLI support has been sunset. Use AntigravityAgentOptions
|
|
5
|
+
* with the Antigravity CLI (`agy`) for Google CLI integrations.
|
|
7
6
|
*/
|
|
8
7
|
export type GeminiAgentOptions = BaseCliAgentOptions & {
|
|
9
8
|
debug?: boolean;
|
|
@@ -23,15 +22,11 @@ export type GeminiAgentOptions = BaseCliAgentOptions & {
|
|
|
23
22
|
screenReader?: boolean;
|
|
24
23
|
outputFormat?: "text" | "json" | "stream-json";
|
|
25
24
|
/**
|
|
26
|
-
*
|
|
27
|
-
* spawned process so this invocation uses the credentials stored at
|
|
28
|
-
* `<configDir>/oauth_creds.json` (instead of the user's default
|
|
29
|
-
* `~/.gemini/`). Use this to run multiple Gemini accounts side-by-side.
|
|
25
|
+
* Legacy option retained only so old constructor calls type-check.
|
|
30
26
|
*/
|
|
31
27
|
configDir?: string;
|
|
32
28
|
/**
|
|
33
|
-
*
|
|
34
|
-
* API-billed invocations.
|
|
29
|
+
* Legacy option retained only so old constructor calls type-check.
|
|
35
30
|
*/
|
|
36
31
|
apiKey?: string;
|
|
37
32
|
};
|
package/src/OpenCodeAgent.js
CHANGED
|
@@ -12,17 +12,7 @@ import { normalizeCapabilityStringList } from "./capability-registry/index.js";
|
|
|
12
12
|
|
|
13
13
|
/** @typedef {import("./BaseCliAgent/index.ts").BaseCliAgentOptions} BaseCliAgentOptions */
|
|
14
14
|
/** @typedef {import("./capability-registry/index.ts").AgentCapabilityRegistry} AgentCapabilityRegistry */
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @typedef {BaseCliAgentOptions & {
|
|
18
|
-
* model?: string;
|
|
19
|
-
* agentName?: string;
|
|
20
|
-
* attachFiles?: string[];
|
|
21
|
-
* continueSession?: boolean;
|
|
22
|
-
* sessionId?: string;
|
|
23
|
-
* variant?: "high" | "medium" | "low";
|
|
24
|
-
* }} OpenCodeAgentOptions
|
|
25
|
-
*/
|
|
15
|
+
/** @typedef {import("./OpenCodeAgentOptions.ts").OpenCodeAgentOptions} OpenCodeAgentOptions */
|
|
26
16
|
|
|
27
17
|
/** @typedef {import("./BaseCliAgent/index.ts").CliOutputInterpreter} CliOutputInterpreter */
|
|
28
18
|
|
|
@@ -80,7 +70,7 @@ export function createOpenCodeCapabilityRegistry(opts = {}) {
|
|
|
80
70
|
*
|
|
81
71
|
* Usage:
|
|
82
72
|
* const agent = new OpenCodeAgent({
|
|
83
|
-
* model: "anthropic/claude-opus-4-
|
|
73
|
+
* model: "anthropic/claude-opus-4-8",
|
|
84
74
|
* yolo: true,
|
|
85
75
|
* });
|
|
86
76
|
* const result = await agent.generate({
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BaseCliAgentOptions } from "./BaseCliAgent";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the OpenCodeAgent.
|
|
5
|
+
*/
|
|
6
|
+
export type OpenCodeAgentOptions = BaseCliAgentOptions & {
|
|
7
|
+
/** Model identifier (e.g., "anthropic/claude-opus-4-8", "openai/gpt-5.4") */
|
|
8
|
+
model?: string;
|
|
9
|
+
/** OpenCode agent name (maps to --agent flag, selects predefined agent config) */
|
|
10
|
+
agentName?: string;
|
|
11
|
+
/** Files to attach to the prompt via -f flags */
|
|
12
|
+
attachFiles?: string[];
|
|
13
|
+
/** Continue a previous session */
|
|
14
|
+
continueSession?: boolean;
|
|
15
|
+
/** Resume a specific session by ID */
|
|
16
|
+
sessionId?: string;
|
|
17
|
+
/** Provider-specific model variant/reasoning effort level */
|
|
18
|
+
variant?: string;
|
|
19
|
+
};
|
package/src/PiAgent.js
CHANGED
|
@@ -104,11 +104,14 @@ export class PiAgent extends BaseCliAgent {
|
|
|
104
104
|
: undefined;
|
|
105
105
|
const effectiveSession = resumeSession ?? this.opts.session;
|
|
106
106
|
this.issuedSessionRef = effectiveSession;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
// pi's --print (non-interactive: process prompt and exit) and --mode
|
|
108
|
+
// are independent. Apply --print to every non-RPC mode so json task
|
|
109
|
+
// executions also process one prompt and exit instead of lingering as
|
|
110
|
+
// an interactive session (#284).
|
|
111
|
+
if (params.mode !== "rpc" && this.opts.print !== false) {
|
|
112
|
+
args.push("--print");
|
|
110
113
|
}
|
|
111
|
-
|
|
114
|
+
if (params.mode !== "text") {
|
|
112
115
|
args.push("--mode", params.mode);
|
|
113
116
|
}
|
|
114
117
|
pushFlag(args, "--provider", this.opts.provider);
|
|
@@ -197,7 +200,9 @@ export class PiAgent extends BaseCliAgent {
|
|
|
197
200
|
createOutputInterpreter() {
|
|
198
201
|
let sessionId = this.issuedSessionRef;
|
|
199
202
|
let emittedStarted = false;
|
|
203
|
+
let emittedCompleted = false;
|
|
200
204
|
let finalAnswer = "";
|
|
205
|
+
let finalUsage;
|
|
201
206
|
/**
|
|
202
207
|
* @param {unknown} value
|
|
203
208
|
*/
|
|
@@ -231,6 +236,17 @@ export class PiAgent extends BaseCliAgent {
|
|
|
231
236
|
}];
|
|
232
237
|
};
|
|
233
238
|
/**
|
|
239
|
+
* @param {Record<string, unknown>} payload
|
|
240
|
+
*/
|
|
241
|
+
const captureUsage = (payload) => {
|
|
242
|
+
const candidate = (payload && typeof payload.usage === "object" && payload.usage) ||
|
|
243
|
+
(payload && typeof payload.message === "object" && payload.message && typeof payload.message.usage === "object" && payload.message.usage) ||
|
|
244
|
+
undefined;
|
|
245
|
+
if (candidate && typeof candidate === "object" && !Array.isArray(candidate)) {
|
|
246
|
+
finalUsage = candidate;
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
234
250
|
* @param {string} line
|
|
235
251
|
* @returns {AgentCliEvent[]}
|
|
236
252
|
*/
|
|
@@ -267,6 +283,7 @@ export class PiAgent extends BaseCliAgent {
|
|
|
267
283
|
return startedEvents();
|
|
268
284
|
}
|
|
269
285
|
if (type === "message_end" || type === "turn_end") {
|
|
286
|
+
captureUsage(payload);
|
|
270
287
|
const message = payload.message;
|
|
271
288
|
if (message?.role === "assistant") {
|
|
272
289
|
const extracted = extractTextFromJsonValue(message);
|
|
@@ -276,6 +293,33 @@ export class PiAgent extends BaseCliAgent {
|
|
|
276
293
|
}
|
|
277
294
|
return startedEvents();
|
|
278
295
|
}
|
|
296
|
+
if (type === "agent_end") {
|
|
297
|
+
captureUsage(payload);
|
|
298
|
+
if (Array.isArray(payload.messages)) {
|
|
299
|
+
for (let i = payload.messages.length - 1; i >= 0; i--) {
|
|
300
|
+
const message = payload.messages[i];
|
|
301
|
+
if (message?.role === "assistant") {
|
|
302
|
+
const extracted = extractTextFromJsonValue(message);
|
|
303
|
+
if (extracted) {
|
|
304
|
+
finalAnswer = extracted;
|
|
305
|
+
}
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
emittedCompleted = true;
|
|
311
|
+
return [
|
|
312
|
+
...startedEvents(),
|
|
313
|
+
{
|
|
314
|
+
type: "completed",
|
|
315
|
+
engine: this.cliEngine,
|
|
316
|
+
ok: true,
|
|
317
|
+
answer: finalAnswer || undefined,
|
|
318
|
+
usage: finalUsage,
|
|
319
|
+
resume: sessionId,
|
|
320
|
+
},
|
|
321
|
+
];
|
|
322
|
+
}
|
|
279
323
|
if (type === "tool_execution_start") {
|
|
280
324
|
const toolName = asString(payload.toolName) ?? "tool";
|
|
281
325
|
const toolId = asString(payload.toolCallId) ?? toolName;
|
|
@@ -355,6 +399,9 @@ export class PiAgent extends BaseCliAgent {
|
|
|
355
399
|
const started = !emittedStarted && sessionId
|
|
356
400
|
? startedEvents()
|
|
357
401
|
: [];
|
|
402
|
+
if (emittedCompleted) {
|
|
403
|
+
return started;
|
|
404
|
+
}
|
|
358
405
|
return [
|
|
359
406
|
...started,
|
|
360
407
|
{
|
|
@@ -362,6 +409,7 @@ export class PiAgent extends BaseCliAgent {
|
|
|
362
409
|
engine: this.cliEngine,
|
|
363
410
|
ok: !result.exitCode || result.exitCode === 0,
|
|
364
411
|
answer: finalAnswer || undefined,
|
|
412
|
+
usage: finalUsage,
|
|
365
413
|
error: result.exitCode && result.exitCode !== 0
|
|
366
414
|
? result.stderr.trim() || `PI exited with code ${result.exitCode}`
|
|
367
415
|
: undefined,
|
|
@@ -394,7 +442,7 @@ export class PiAgent extends BaseCliAgent {
|
|
|
394
442
|
const cwd = this.cwd ?? options?.rootDir ?? process.cwd();
|
|
395
443
|
const env = { ...process.env, ...this.env };
|
|
396
444
|
const args = this.buildArgs({ prompt, cwd, options, mode });
|
|
397
|
-
const diagnosticsPromise = launchDiagnostics("pi", env, cwd);
|
|
445
|
+
const diagnosticsPromise = launchDiagnostics("pi", env, cwd, this.diagnosticHints());
|
|
398
446
|
const interpreter = this.createOutputInterpreter();
|
|
399
447
|
/**
|
|
400
448
|
* @param {AgentCliEvent[] | AgentCliEvent | null | undefined} payload
|
|
@@ -465,4 +513,14 @@ export class PiAgent extends BaseCliAgent {
|
|
|
465
513
|
outputFormat: mode,
|
|
466
514
|
};
|
|
467
515
|
}
|
|
516
|
+
/**
|
|
517
|
+
* @returns {{ provider?: string; model?: string; apiKey?: string }}
|
|
518
|
+
*/
|
|
519
|
+
diagnosticHints() {
|
|
520
|
+
return {
|
|
521
|
+
provider: this.opts.provider,
|
|
522
|
+
model: this.opts.model ?? this.model,
|
|
523
|
+
apiKey: this.opts.apiKey,
|
|
524
|
+
};
|
|
525
|
+
}
|
|
468
526
|
}
|
|
@@ -116,10 +116,11 @@ function diagnoseSurfaceContract(entry) {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
|
+
* @param {CliAgentCapabilityReportEntry[]} [entries]
|
|
119
120
|
* @returns {CliAgentCapabilityDoctorReport}
|
|
120
121
|
*/
|
|
121
|
-
export function getCliAgentCapabilityDoctorReport() {
|
|
122
|
-
const agents =
|
|
122
|
+
export function getCliAgentCapabilityDoctorReport(entries = getCliAgentCapabilityReport()) {
|
|
123
|
+
const agents = entries.map((entry) => {
|
|
123
124
|
const issues = [
|
|
124
125
|
...diagnoseCapabilityRegistry(entry.capabilities),
|
|
125
126
|
...diagnoseSurfaceContract(entry),
|
|
@@ -4,7 +4,6 @@ import { createAntigravityCapabilityRegistry } from "../AntigravityAgent.js";
|
|
|
4
4
|
import { createClaudeCodeCapabilityRegistry } from "../ClaudeCodeAgent.js";
|
|
5
5
|
import { createCodexCapabilityRegistry } from "../CodexAgent.js";
|
|
6
6
|
import { createForgeCapabilityRegistry } from "../ForgeAgent.js";
|
|
7
|
-
import { createGeminiCapabilityRegistry } from "../GeminiAgent.js";
|
|
8
7
|
import { createKimiCapabilityRegistry } from "../KimiAgent.js";
|
|
9
8
|
import { createOpenCodeCapabilityRegistry } from "../OpenCodeAgent.js";
|
|
10
9
|
import { createPiCapabilityRegistry } from "../PiAgent.js";
|
|
@@ -33,11 +32,6 @@ const CLI_AGENT_CAPABILITY_ADAPTERS = [
|
|
|
33
32
|
binary: "agy",
|
|
34
33
|
buildRegistry: () => createAntigravityCapabilityRegistry(),
|
|
35
34
|
},
|
|
36
|
-
{
|
|
37
|
-
id: "gemini",
|
|
38
|
-
binary: "gemini",
|
|
39
|
-
buildRegistry: () => createGeminiCapabilityRegistry(),
|
|
40
|
-
},
|
|
41
35
|
{
|
|
42
36
|
id: "forge",
|
|
43
37
|
binary: "forge",
|
|
@@ -97,6 +97,7 @@ export const CLI_AGENT_SURFACE_MANIFEST = [
|
|
|
97
97
|
"--color",
|
|
98
98
|
"--json",
|
|
99
99
|
"--output-last-message",
|
|
100
|
+
"-",
|
|
100
101
|
],
|
|
101
102
|
supportedFlags: [],
|
|
102
103
|
unsupportedFlags: [],
|
|
@@ -213,45 +214,6 @@ export const CLI_AGENT_SURFACE_MANIFEST = [
|
|
|
213
214
|
notes: "Smithers maps native session ids to `agy --conversation <id>`.",
|
|
214
215
|
},
|
|
215
216
|
},
|
|
216
|
-
{
|
|
217
|
-
id: "gemini",
|
|
218
|
-
displayName: "Gemini",
|
|
219
|
-
binary: "gemini",
|
|
220
|
-
packageExport: "GeminiAgent",
|
|
221
|
-
defaultOutputFormat: "json",
|
|
222
|
-
docsUrls: ["https://github.com/google-gemini/gemini-cli"],
|
|
223
|
-
emittedFlags: [
|
|
224
|
-
"--debug",
|
|
225
|
-
"--model",
|
|
226
|
-
"--sandbox",
|
|
227
|
-
"--approval-mode",
|
|
228
|
-
"--yolo",
|
|
229
|
-
"--experimental-acp",
|
|
230
|
-
"--allowed-mcp-server-names",
|
|
231
|
-
"--allowed-tools",
|
|
232
|
-
"--extensions",
|
|
233
|
-
"--list-extensions",
|
|
234
|
-
"--resume",
|
|
235
|
-
"--list-sessions",
|
|
236
|
-
"--delete-session",
|
|
237
|
-
"--include-directories",
|
|
238
|
-
"--screen-reader",
|
|
239
|
-
"--output-format",
|
|
240
|
-
"--prompt",
|
|
241
|
-
],
|
|
242
|
-
supportedFlags: [],
|
|
243
|
-
unsupportedFlags: [],
|
|
244
|
-
optionMappings: [
|
|
245
|
-
{ option: "configDir", env: "GEMINI_DIR" },
|
|
246
|
-
{ option: "apiKey", env: "GEMINI_API_KEY" },
|
|
247
|
-
{ option: "resume", flag: "--resume" },
|
|
248
|
-
],
|
|
249
|
-
resume: {
|
|
250
|
-
kind: "flag",
|
|
251
|
-
emitted: ["--resume"],
|
|
252
|
-
notes: "Legacy Gemini CLI session id.",
|
|
253
|
-
},
|
|
254
|
-
},
|
|
255
217
|
{
|
|
256
218
|
id: "pi",
|
|
257
219
|
displayName: "Pi",
|
|
@@ -287,7 +249,6 @@ export const CLI_AGENT_SURFACE_MANIFEST = [
|
|
|
287
249
|
"--no-themes",
|
|
288
250
|
"--thinking",
|
|
289
251
|
"--verbose",
|
|
290
|
-
"--files",
|
|
291
252
|
],
|
|
292
253
|
supportedFlags: [],
|
|
293
254
|
unsupportedFlags: [],
|