acpx 0.7.0 → 0.9.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/README.md +14 -6
- package/dist/{cli-T-Z-9x6a.js → cli-Bf3yjqzE.js} +35 -10
- package/dist/cli-Bf3yjqzE.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +724 -241
- package/dist/cli.js.map +1 -1
- package/dist/{client-COPilhO_.d.ts → client-BssohYqM.d.ts} +35 -4
- package/dist/client-BssohYqM.d.ts.map +1 -0
- package/dist/flags-C-rwARqg.js +260 -0
- package/dist/flags-C-rwARqg.js.map +1 -0
- package/dist/{flows-CF8w1rPI.js → flows-WLs26_5Y.js} +405 -337
- package/dist/flows-WLs26_5Y.js.map +1 -0
- package/dist/flows.d.ts +23 -2
- package/dist/flows.d.ts.map +1 -1
- package/dist/flows.js +1 -1
- package/dist/{prompt-turn-CVPMWdj1.js → live-checkpoint-D5d-K9s1.js} +2487 -609
- package/dist/live-checkpoint-D5d-K9s1.js.map +1 -0
- package/dist/output-DPg20dvn.js +4146 -0
- package/dist/output-DPg20dvn.js.map +1 -0
- package/dist/runtime.d.ts +56 -4
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +676 -393
- package/dist/runtime.js.map +1 -1
- package/dist/{types-CVBeQyi3.d.ts → session-options-CFudjdkU.d.ts} +62 -3
- package/dist/session-options-CFudjdkU.d.ts.map +1 -0
- package/package.json +30 -25
- package/skills/acpx/SKILL.md +211 -13
- package/dist/cli-T-Z-9x6a.js.map +0 -1
- package/dist/client-COPilhO_.d.ts.map +0 -1
- package/dist/flags-Dj-IXgo9.js +0 -163
- package/dist/flags-Dj-IXgo9.js.map +0 -1
- package/dist/flows-CF8w1rPI.js.map +0 -1
- package/dist/ipc-ABXlXzGP.js +0 -1290
- package/dist/ipc-ABXlXzGP.js.map +0 -1
- package/dist/jsonrpc-DSxh2w5R.js +0 -68
- package/dist/jsonrpc-DSxh2w5R.js.map +0 -1
- package/dist/output-DmHvT8vm.js +0 -807
- package/dist/output-DmHvT8vm.js.map +0 -1
- package/dist/perf-metrics-C2pXfxvR.js +0 -598
- package/dist/perf-metrics-C2pXfxvR.js.map +0 -1
- package/dist/prompt-turn-CVPMWdj1.js.map +0 -1
- package/dist/render-N5YwotCy.js +0 -172
- package/dist/render-N5YwotCy.js.map +0 -1
- package/dist/rolldown-runtime-CiIaOW0V.js +0 -13
- package/dist/session-CDaQe6BH.js +0 -1538
- package/dist/session-CDaQe6BH.js.map +0 -1
- package/dist/session-options-pCbHn_n7.d.ts +0 -13
- package/dist/session-options-pCbHn_n7.d.ts.map +0 -1
- package/dist/types-CVBeQyi3.d.ts.map +0 -1
package/dist/output-DmHvT8vm.js
DELETED
|
@@ -1,807 +0,0 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-CiIaOW0V.js";
|
|
2
|
-
import { a as parsePromptStopReason, i as parseJsonRpcErrorMessage, t as extractSessionUpdateNotification } from "./jsonrpc-DSxh2w5R.js";
|
|
3
|
-
//#region src/acp/jsonrpc-error.ts
|
|
4
|
-
const OUTPUT_ERROR_JSONRPC_CODES = {
|
|
5
|
-
NO_SESSION: -32002,
|
|
6
|
-
TIMEOUT: -32070,
|
|
7
|
-
PERMISSION_DENIED: -32071,
|
|
8
|
-
PERMISSION_PROMPT_UNAVAILABLE: -32072,
|
|
9
|
-
RUNTIME: -32603,
|
|
10
|
-
USAGE: -32602
|
|
11
|
-
};
|
|
12
|
-
function hasValidAcpError(acp) {
|
|
13
|
-
return Boolean(acp && Number.isFinite(acp.code) && typeof acp.message === "string" && acp.message.trim().length > 0);
|
|
14
|
-
}
|
|
15
|
-
function buildFallbackData(params) {
|
|
16
|
-
const data = {
|
|
17
|
-
acpxCode: params.outputCode,
|
|
18
|
-
detailCode: params.detailCode,
|
|
19
|
-
origin: params.origin,
|
|
20
|
-
retryable: params.retryable,
|
|
21
|
-
timestamp: params.timestamp,
|
|
22
|
-
sessionId: params.sessionId
|
|
23
|
-
};
|
|
24
|
-
for (const [key, value] of Object.entries(data)) if (value === void 0) delete data[key];
|
|
25
|
-
return data;
|
|
26
|
-
}
|
|
27
|
-
function mergeAcpErrorData(acpData, fallbackData) {
|
|
28
|
-
if (Object.keys(fallbackData).length === 0) return acpData;
|
|
29
|
-
if (acpData === void 0) return fallbackData;
|
|
30
|
-
if (acpData && typeof acpData === "object" && !Array.isArray(acpData)) return {
|
|
31
|
-
...fallbackData,
|
|
32
|
-
...acpData
|
|
33
|
-
};
|
|
34
|
-
return acpData;
|
|
35
|
-
}
|
|
36
|
-
function buildErrorObject(params) {
|
|
37
|
-
const fallbackData = buildFallbackData(params);
|
|
38
|
-
if (hasValidAcpError(params.acp)) {
|
|
39
|
-
const data = mergeAcpErrorData(params.acp.data, fallbackData);
|
|
40
|
-
return {
|
|
41
|
-
code: params.acp.code,
|
|
42
|
-
message: params.acp.message,
|
|
43
|
-
...data !== void 0 ? { data } : {}
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
const data = fallbackData;
|
|
47
|
-
return {
|
|
48
|
-
code: OUTPUT_ERROR_JSONRPC_CODES[params.outputCode] ?? -32603,
|
|
49
|
-
message: params.message,
|
|
50
|
-
...Object.keys(data).length > 0 ? { data } : {}
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function buildJsonRpcErrorResponse(params) {
|
|
54
|
-
return {
|
|
55
|
-
jsonrpc: "2.0",
|
|
56
|
-
id: params.id ?? null,
|
|
57
|
-
error: buildErrorObject(params)
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
//#endregion
|
|
61
|
-
//#region src/cli/output/read-suppression.ts
|
|
62
|
-
const SUPPRESSED_READ_OUTPUT = "[read output suppressed]";
|
|
63
|
-
function inferToolKindFromTitle(title) {
|
|
64
|
-
const normalized = title?.trim().toLowerCase();
|
|
65
|
-
if (!normalized) return;
|
|
66
|
-
const head = normalized.split(":", 1)[0]?.trim();
|
|
67
|
-
if (!head) return;
|
|
68
|
-
if (head.includes("read") || head.includes("cat") || head.includes("open") || head.includes("view")) return "read";
|
|
69
|
-
}
|
|
70
|
-
function isReadLikeTool(tool) {
|
|
71
|
-
return tool.kind?.trim().toLowerCase() === "read" || inferToolKindFromTitle(tool.title) === "read";
|
|
72
|
-
}
|
|
73
|
-
//#endregion
|
|
74
|
-
//#region src/cli/output/json-formatter.ts
|
|
75
|
-
const DEFAULT_JSON_SESSION_ID = "unknown";
|
|
76
|
-
function asRecord$1(value) {
|
|
77
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
78
|
-
return value;
|
|
79
|
-
}
|
|
80
|
-
function jsonRpcIdKey(value) {
|
|
81
|
-
if (typeof value === "string") return `s:${value}`;
|
|
82
|
-
if (typeof value === "number" && Number.isFinite(value)) return `n:${value}`;
|
|
83
|
-
}
|
|
84
|
-
function sanitizeReadResult(result) {
|
|
85
|
-
const record = asRecord$1(result);
|
|
86
|
-
if (!record || typeof record.content !== "string") return result;
|
|
87
|
-
return {
|
|
88
|
-
...record,
|
|
89
|
-
content: SUPPRESSED_READ_OUTPUT
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
function sanitizeToolContent(content) {
|
|
93
|
-
if (!Array.isArray(content)) return content;
|
|
94
|
-
return [{
|
|
95
|
-
type: "content",
|
|
96
|
-
content: {
|
|
97
|
-
type: "text",
|
|
98
|
-
text: SUPPRESSED_READ_OUTPUT
|
|
99
|
-
}
|
|
100
|
-
}];
|
|
101
|
-
}
|
|
102
|
-
function sanitizeToolMessage(message) {
|
|
103
|
-
const root = asRecord$1(message);
|
|
104
|
-
const params = asRecord$1(root?.params);
|
|
105
|
-
const update = asRecord$1(params?.update);
|
|
106
|
-
if (!root || !params || !update) return message;
|
|
107
|
-
return {
|
|
108
|
-
...root,
|
|
109
|
-
params: {
|
|
110
|
-
...params,
|
|
111
|
-
update: {
|
|
112
|
-
...update,
|
|
113
|
-
rawOutput: Object.prototype.hasOwnProperty.call(update, "rawOutput") && update.rawOutput !== void 0 ? { content: SUPPRESSED_READ_OUTPUT } : update.rawOutput,
|
|
114
|
-
content: Object.prototype.hasOwnProperty.call(update, "content") && update.content !== void 0 ? sanitizeToolContent(update.content) : update.content
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
var JsonOutputFormatter = class {
|
|
120
|
-
stdout;
|
|
121
|
-
suppressReads;
|
|
122
|
-
sessionId;
|
|
123
|
-
requestMethodById = /* @__PURE__ */ new Map();
|
|
124
|
-
toolStateById = /* @__PURE__ */ new Map();
|
|
125
|
-
constructor(stdout, suppressReads, context) {
|
|
126
|
-
this.stdout = stdout;
|
|
127
|
-
this.suppressReads = suppressReads;
|
|
128
|
-
this.sessionId = context?.sessionId?.trim() || DEFAULT_JSON_SESSION_ID;
|
|
129
|
-
}
|
|
130
|
-
setContext(context) {
|
|
131
|
-
this.sessionId = context.sessionId?.trim() || this.sessionId || DEFAULT_JSON_SESSION_ID;
|
|
132
|
-
}
|
|
133
|
-
onAcpMessage(message) {
|
|
134
|
-
this.stdout.write(`${JSON.stringify(this.sanitizeMessage(message))}\n`);
|
|
135
|
-
}
|
|
136
|
-
sanitizeMessage(message) {
|
|
137
|
-
if (!this.suppressReads) return message;
|
|
138
|
-
const sanitizedResponse = this.sanitizeReadResponse(message);
|
|
139
|
-
if (sanitizedResponse !== message) return sanitizedResponse;
|
|
140
|
-
const sanitizedToolMessage = this.sanitizeReadToolMessage(message);
|
|
141
|
-
if (sanitizedToolMessage !== message) return sanitizedToolMessage;
|
|
142
|
-
this.trackRequestMethod(message);
|
|
143
|
-
return message;
|
|
144
|
-
}
|
|
145
|
-
trackRequestMethod(message) {
|
|
146
|
-
const candidate = message;
|
|
147
|
-
if (typeof candidate.method !== "string") return;
|
|
148
|
-
const idKey = jsonRpcIdKey(candidate.id);
|
|
149
|
-
if (!idKey) return;
|
|
150
|
-
this.requestMethodById.set(idKey, candidate.method);
|
|
151
|
-
}
|
|
152
|
-
sanitizeReadResponse(message) {
|
|
153
|
-
const candidate = message;
|
|
154
|
-
const idKey = jsonRpcIdKey(candidate.id);
|
|
155
|
-
if (!idKey || !Object.hasOwn(candidate, "result")) return message;
|
|
156
|
-
const method = this.requestMethodById.get(idKey);
|
|
157
|
-
this.requestMethodById.delete(idKey);
|
|
158
|
-
if (method !== "fs/read_text_file") return message;
|
|
159
|
-
const root = asRecord$1(message);
|
|
160
|
-
if (!root) return message;
|
|
161
|
-
return {
|
|
162
|
-
...root,
|
|
163
|
-
result: sanitizeReadResult(candidate.result)
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
sanitizeReadToolMessage(message) {
|
|
167
|
-
const root = asRecord$1(message);
|
|
168
|
-
if (root?.method !== "session/update") return message;
|
|
169
|
-
const params = asRecord$1(root.params);
|
|
170
|
-
const update = asRecord$1(params?.update);
|
|
171
|
-
if (!params || !update) return message;
|
|
172
|
-
const sessionUpdate = update.sessionUpdate;
|
|
173
|
-
if (sessionUpdate !== "tool_call" && sessionUpdate !== "tool_call_update") return message;
|
|
174
|
-
const toolCallId = typeof update.toolCallId === "string" ? update.toolCallId : void 0;
|
|
175
|
-
if (!toolCallId) return message;
|
|
176
|
-
const previous = this.toolStateById.get(toolCallId) ?? {};
|
|
177
|
-
const current = {
|
|
178
|
-
title: typeof update.title === "string" ? update.title : previous.title,
|
|
179
|
-
kind: typeof update.kind === "string" || update.kind === null ? update.kind : previous.kind
|
|
180
|
-
};
|
|
181
|
-
this.toolStateById.set(toolCallId, current);
|
|
182
|
-
if (!isReadLikeTool(current)) return message;
|
|
183
|
-
return sanitizeToolMessage(message);
|
|
184
|
-
}
|
|
185
|
-
onError(params) {
|
|
186
|
-
this.stdout.write(`${JSON.stringify(buildJsonRpcErrorResponse({
|
|
187
|
-
outputCode: params.code,
|
|
188
|
-
detailCode: params.detailCode,
|
|
189
|
-
origin: params.origin,
|
|
190
|
-
message: params.message,
|
|
191
|
-
retryable: params.retryable,
|
|
192
|
-
timestamp: params.timestamp,
|
|
193
|
-
sessionId: this.sessionId,
|
|
194
|
-
acp: params.acp
|
|
195
|
-
}))}\n`);
|
|
196
|
-
}
|
|
197
|
-
flush() {}
|
|
198
|
-
};
|
|
199
|
-
function createJsonOutputFormatter(stdout, suppressReads = false, context) {
|
|
200
|
-
return new JsonOutputFormatter(stdout, suppressReads, context);
|
|
201
|
-
}
|
|
202
|
-
//#endregion
|
|
203
|
-
//#region src/cli/output/output.ts
|
|
204
|
-
var output_exports = /* @__PURE__ */ __exportAll({
|
|
205
|
-
createOutputFormatter: () => createOutputFormatter,
|
|
206
|
-
getTextErrorRemediationHints: () => getTextErrorRemediationHints
|
|
207
|
-
});
|
|
208
|
-
const MAX_THOUGHT_CHARS = 900;
|
|
209
|
-
const MAX_INLINE_CHARS = 220;
|
|
210
|
-
const MAX_OUTPUT_CHARS = 2e3;
|
|
211
|
-
const MAX_OUTPUT_LINES = 28;
|
|
212
|
-
const MAX_LOCATION_ITEMS = 5;
|
|
213
|
-
const OUTPUT_PRIORITY_KEYS = [
|
|
214
|
-
"stdout",
|
|
215
|
-
"stderr",
|
|
216
|
-
"output",
|
|
217
|
-
"content",
|
|
218
|
-
"text",
|
|
219
|
-
"message",
|
|
220
|
-
"result",
|
|
221
|
-
"response",
|
|
222
|
-
"value"
|
|
223
|
-
];
|
|
224
|
-
function asStatus(status) {
|
|
225
|
-
return status ?? "unknown";
|
|
226
|
-
}
|
|
227
|
-
function isFinalStatus(status) {
|
|
228
|
-
return status === "completed" || status === "failed";
|
|
229
|
-
}
|
|
230
|
-
function toStatusLabel(status) {
|
|
231
|
-
switch (status) {
|
|
232
|
-
case "in_progress": return "running";
|
|
233
|
-
case "pending": return "pending";
|
|
234
|
-
case "completed": return "completed";
|
|
235
|
-
case "failed": return "failed";
|
|
236
|
-
default: return "running";
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
function asRecord(value) {
|
|
240
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
241
|
-
return value;
|
|
242
|
-
}
|
|
243
|
-
function extractJsonRpcMethod(message) {
|
|
244
|
-
return Object.hasOwn(message, "method") ? message.method?.toString() : void 0;
|
|
245
|
-
}
|
|
246
|
-
function collapseWhitespace(value) {
|
|
247
|
-
return value.replace(/\s+/g, " ").trim();
|
|
248
|
-
}
|
|
249
|
-
function normalizeLineEndings(value) {
|
|
250
|
-
return value.replace(/\r\n?/g, "\n");
|
|
251
|
-
}
|
|
252
|
-
function truncate(value, maxChars) {
|
|
253
|
-
if (value.length <= maxChars) return value;
|
|
254
|
-
if (maxChars <= 3) return value.slice(0, maxChars);
|
|
255
|
-
return `${value.slice(0, maxChars - 3)}...`;
|
|
256
|
-
}
|
|
257
|
-
function toInline(value, maxChars = MAX_INLINE_CHARS) {
|
|
258
|
-
return truncate(collapseWhitespace(value), maxChars);
|
|
259
|
-
}
|
|
260
|
-
function indentBlock(value, prefix) {
|
|
261
|
-
return value.split("\n").map((line) => `${prefix}${line}`).join("\n");
|
|
262
|
-
}
|
|
263
|
-
function dedupeStrings(values) {
|
|
264
|
-
const seen = /* @__PURE__ */ new Set();
|
|
265
|
-
const result = [];
|
|
266
|
-
for (const value of values) {
|
|
267
|
-
if (seen.has(value)) continue;
|
|
268
|
-
seen.add(value);
|
|
269
|
-
result.push(value);
|
|
270
|
-
}
|
|
271
|
-
return result;
|
|
272
|
-
}
|
|
273
|
-
function safeJson(value, spacing) {
|
|
274
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
275
|
-
try {
|
|
276
|
-
return JSON.stringify(value, (_key, entry) => {
|
|
277
|
-
if (typeof entry === "bigint") return `${entry}n`;
|
|
278
|
-
if (typeof entry === "function") return `[Function ${entry.name || "anonymous"}]`;
|
|
279
|
-
if (typeof entry === "symbol") return entry.toString();
|
|
280
|
-
if (entry && typeof entry === "object") {
|
|
281
|
-
if (seen.has(entry)) return "[Circular]";
|
|
282
|
-
seen.add(entry);
|
|
283
|
-
}
|
|
284
|
-
return entry;
|
|
285
|
-
}, spacing);
|
|
286
|
-
} catch {
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
function readFirstString(source, keys) {
|
|
291
|
-
for (const key of keys) {
|
|
292
|
-
const value = source[key];
|
|
293
|
-
if (typeof value === "string" && value.trim()) return value.trim();
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
function readFirstFiniteNumber(source, keys) {
|
|
297
|
-
for (const key of keys) {
|
|
298
|
-
const value = source[key];
|
|
299
|
-
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
function formatMetadataNumber(value) {
|
|
303
|
-
return Number.isInteger(value) ? String(value) : String(Number(value.toFixed(8)));
|
|
304
|
-
}
|
|
305
|
-
function readFirstStringArray(source, keys) {
|
|
306
|
-
for (const key of keys) {
|
|
307
|
-
const value = source[key];
|
|
308
|
-
if (!Array.isArray(value)) continue;
|
|
309
|
-
const entries = value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter((entry) => entry.length > 0);
|
|
310
|
-
if (entries.length > 0) return entries;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
function formatDisjunction(values) {
|
|
314
|
-
if (values.length <= 1) return values[0] ?? "";
|
|
315
|
-
if (values.length === 2) return `${values[0]} or ${values[1]}`;
|
|
316
|
-
return `${values.slice(0, -1).join(", ")}, or ${values.at(-1)}`;
|
|
317
|
-
}
|
|
318
|
-
function parseAuthMethodIdsFromMessage(message) {
|
|
319
|
-
const methods = [];
|
|
320
|
-
const methodListMatch = message.match(/auth methods \[([^\]]+)\]/iu);
|
|
321
|
-
if (methodListMatch) methods.push(...methodListMatch[1].split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0));
|
|
322
|
-
const singleMethodMatch = message.match(/auth method ([\w.-]+)/iu);
|
|
323
|
-
if (singleMethodMatch) methods.push(singleMethodMatch[1]);
|
|
324
|
-
return dedupeStrings(methods);
|
|
325
|
-
}
|
|
326
|
-
function parseAuthMethodIdsFromAcpData(data) {
|
|
327
|
-
const record = asRecord(data);
|
|
328
|
-
if (!record) return [];
|
|
329
|
-
const methodIds = [];
|
|
330
|
-
if (typeof record.methodId === "string" && record.methodId.trim().length > 0) methodIds.push(record.methodId.trim());
|
|
331
|
-
if (Array.isArray(record.methods)) for (const entry of record.methods) {
|
|
332
|
-
if (typeof entry === "string" && entry.trim().length > 0) {
|
|
333
|
-
methodIds.push(entry.trim());
|
|
334
|
-
continue;
|
|
335
|
-
}
|
|
336
|
-
const id = asRecord(entry)?.id;
|
|
337
|
-
if (typeof id === "string" && id.trim().length > 0) methodIds.push(id.trim());
|
|
338
|
-
}
|
|
339
|
-
return dedupeStrings(methodIds);
|
|
340
|
-
}
|
|
341
|
-
function renderAuthRequiredHint(params) {
|
|
342
|
-
const methodIds = dedupeStrings([...parseAuthMethodIdsFromAcpData(params.acp?.data), ...parseAuthMethodIdsFromMessage(params.message)]);
|
|
343
|
-
if (methodIds.length === 0) return "hint: run `acpx config show` to locate the active config, then add the required credential under `auth` and retry.";
|
|
344
|
-
return `hint: run \`acpx config show\` to locate the active config, then add ${formatDisjunction(methodIds.map((methodId) => `\`auth.${methodId}\``))} and retry.`;
|
|
345
|
-
}
|
|
346
|
-
function getTextErrorRemediationHints(params) {
|
|
347
|
-
const lowerMessage = params.message.toLowerCase();
|
|
348
|
-
if (params.detailCode === "AUTH_REQUIRED") return [renderAuthRequiredHint(params)];
|
|
349
|
-
if (params.code === "TIMEOUT") return ["hint: increase `--timeout <seconds>` for long-running prompts, or check whether the agent/provider is stalled."];
|
|
350
|
-
if (params.code === "NO_SESSION") {
|
|
351
|
-
if (lowerMessage.includes("create one:")) return [];
|
|
352
|
-
return ["hint: the saved ACP session is missing or stale; start a fresh session with `acpx <agent> sessions new`, then retry."];
|
|
353
|
-
}
|
|
354
|
-
if (lowerMessage.includes("does not support session/load")) return ["hint: this adapter cannot resume saved ACP sessions; create a fresh one with `acpx <agent> sessions new` instead of reusing `--resume-session`."];
|
|
355
|
-
if (lowerMessage.includes("failed to resume acp session") || lowerMessage.includes("session/load")) return ["hint: rerun with `--verbose` to capture the ACP load failure details.", "hint: if you do not need the old backend session, start a fresh one with `acpx <agent> sessions new` and retry."];
|
|
356
|
-
if (/\b429\b/u.test(params.message) || lowerMessage.includes("rate limit") || lowerMessage.includes("quota exceeded")) return ["hint: the provider appears rate-limited; retry later, switch model, or check provider quota/billing."];
|
|
357
|
-
if (lowerMessage.includes("model not found") || lowerMessage.includes("unknown model") || lowerMessage.includes("invalid model")) return ["hint: check the configured model name for this agent, then retry with `--model <model>` or `sessions set-model <model>`."];
|
|
358
|
-
if (lowerMessage.includes("session/set_mode") || lowerMessage.includes("session/set_model") || lowerMessage.includes("session/set_config_option")) return ["hint: rerun with `--verbose` to capture the ACP method/error details before retrying."];
|
|
359
|
-
if (params.origin === "acp" && params.code === "RUNTIME" && (params.acp?.code === -32602 || params.acp?.code === -32603 || lowerMessage.includes("internal error"))) return ["hint: rerun with `--verbose` to capture the underlying ACP error details."];
|
|
360
|
-
return [];
|
|
361
|
-
}
|
|
362
|
-
function summarizeToolInput(rawInput) {
|
|
363
|
-
if (rawInput == null) return;
|
|
364
|
-
if (typeof rawInput === "string" || typeof rawInput === "number" || typeof rawInput === "boolean") return toInline(String(rawInput));
|
|
365
|
-
const record = asRecord(rawInput);
|
|
366
|
-
if (record) {
|
|
367
|
-
const command = readFirstString(record, [
|
|
368
|
-
"command",
|
|
369
|
-
"cmd",
|
|
370
|
-
"program"
|
|
371
|
-
]);
|
|
372
|
-
const args = readFirstStringArray(record, ["args", "arguments"]);
|
|
373
|
-
if (command) return toInline([command, ...args ?? []].join(" "));
|
|
374
|
-
const location = readFirstString(record, [
|
|
375
|
-
"path",
|
|
376
|
-
"file",
|
|
377
|
-
"filePath",
|
|
378
|
-
"filepath",
|
|
379
|
-
"target",
|
|
380
|
-
"uri",
|
|
381
|
-
"url"
|
|
382
|
-
]);
|
|
383
|
-
if (location) return toInline(location);
|
|
384
|
-
const query = readFirstString(record, [
|
|
385
|
-
"query",
|
|
386
|
-
"pattern",
|
|
387
|
-
"text",
|
|
388
|
-
"search"
|
|
389
|
-
]);
|
|
390
|
-
if (query) return toInline(query);
|
|
391
|
-
}
|
|
392
|
-
const json = safeJson(rawInput, 0);
|
|
393
|
-
return json ? toInline(json) : void 0;
|
|
394
|
-
}
|
|
395
|
-
function formatLocations(locations) {
|
|
396
|
-
if (!locations || locations.length === 0) return;
|
|
397
|
-
const unique = /* @__PURE__ */ new Set();
|
|
398
|
-
for (const location of locations) {
|
|
399
|
-
const path = location.path?.trim();
|
|
400
|
-
if (!path) continue;
|
|
401
|
-
const line = typeof location.line === "number" && Number.isFinite(location.line) ? `:${Math.max(1, Math.trunc(location.line))}` : "";
|
|
402
|
-
unique.add(`${path}${line}`);
|
|
403
|
-
}
|
|
404
|
-
const items = [...unique];
|
|
405
|
-
if (items.length === 0) return;
|
|
406
|
-
const visible = items.slice(0, MAX_LOCATION_ITEMS);
|
|
407
|
-
const hidden = items.length - visible.length;
|
|
408
|
-
if (hidden <= 0) return visible.join(", ");
|
|
409
|
-
return `${visible.join(", ")}, +${hidden} more`;
|
|
410
|
-
}
|
|
411
|
-
function summarizeDiff(path, oldText, newText) {
|
|
412
|
-
const oldLines = oldText ? oldText.split("\n").length : 0;
|
|
413
|
-
const delta = newText.split("\n").length - oldLines;
|
|
414
|
-
if (delta === 0) return `diff ${path} (line count unchanged)`;
|
|
415
|
-
return `diff ${path} (${`${delta > 0 ? "+" : ""}${delta}`} lines)`;
|
|
416
|
-
}
|
|
417
|
-
function textFromContentBlock(content) {
|
|
418
|
-
switch (content.type) {
|
|
419
|
-
case "text": return content.text;
|
|
420
|
-
case "resource_link": return content.title ?? content.name ?? content.uri;
|
|
421
|
-
case "resource": {
|
|
422
|
-
if ("text" in content.resource && typeof content.resource.text === "string") return content.resource.text;
|
|
423
|
-
const uri = content.resource.uri;
|
|
424
|
-
const mimeType = content.resource.mimeType;
|
|
425
|
-
return `[resource] ${uri}${mimeType ? ` (${mimeType})` : ""}`;
|
|
426
|
-
}
|
|
427
|
-
case "image": return `[image] ${content.mimeType}`;
|
|
428
|
-
case "audio": return `[audio] ${content.mimeType}`;
|
|
429
|
-
default: return;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
function summarizeToolContent(content) {
|
|
433
|
-
if (!content || content.length === 0) return;
|
|
434
|
-
const fragments = [];
|
|
435
|
-
for (const entry of content) {
|
|
436
|
-
if (entry.type === "content") {
|
|
437
|
-
const text = textFromContentBlock(entry.content);
|
|
438
|
-
if (text && text.trim()) fragments.push(text.trimEnd());
|
|
439
|
-
continue;
|
|
440
|
-
}
|
|
441
|
-
if (entry.type === "diff") {
|
|
442
|
-
fragments.push(summarizeDiff(entry.path, entry.oldText, entry.newText));
|
|
443
|
-
continue;
|
|
444
|
-
}
|
|
445
|
-
if (entry.type === "terminal") fragments.push(`[terminal] ${entry.terminalId}`);
|
|
446
|
-
}
|
|
447
|
-
const unique = dedupeStrings(fragments.map((fragment) => fragment.trim()).filter((fragment) => fragment.length > 0));
|
|
448
|
-
if (unique.length === 0) return;
|
|
449
|
-
return unique.join("\n\n");
|
|
450
|
-
}
|
|
451
|
-
function extractOutputText(value, depth = 0, seen = /* @__PURE__ */ new Set()) {
|
|
452
|
-
if (value == null) return;
|
|
453
|
-
if (typeof value === "string") {
|
|
454
|
-
const trimmed = value.trimEnd();
|
|
455
|
-
return trimmed.length > 0 ? trimmed : void 0;
|
|
456
|
-
}
|
|
457
|
-
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
458
|
-
if (depth >= 4) return;
|
|
459
|
-
if (Array.isArray(value)) {
|
|
460
|
-
const parts = value.map((entry) => extractOutputText(entry, depth + 1, seen)).filter((entry) => Boolean(entry));
|
|
461
|
-
if (parts.length === 0) return;
|
|
462
|
-
return dedupeStrings(parts).join("\n");
|
|
463
|
-
}
|
|
464
|
-
const record = asRecord(value);
|
|
465
|
-
if (!record) return;
|
|
466
|
-
if (seen.has(record)) return;
|
|
467
|
-
seen.add(record);
|
|
468
|
-
const preferred = [];
|
|
469
|
-
for (const key of OUTPUT_PRIORITY_KEYS) {
|
|
470
|
-
if (!(key in record)) continue;
|
|
471
|
-
const extracted = extractOutputText(record[key], depth + 1, seen);
|
|
472
|
-
if (extracted) preferred.push(extracted);
|
|
473
|
-
}
|
|
474
|
-
const uniquePreferred = dedupeStrings(preferred);
|
|
475
|
-
if (uniquePreferred.length > 0) return uniquePreferred.join("\n");
|
|
476
|
-
const json = safeJson(record, 2);
|
|
477
|
-
if (!json || json === "{}") return;
|
|
478
|
-
return json;
|
|
479
|
-
}
|
|
480
|
-
function summarizeToolOutput(rawOutput, content) {
|
|
481
|
-
const fragments = dedupeStrings([extractOutputText(rawOutput), summarizeToolContent(content)].map((fragment) => fragment?.trim()).filter((fragment) => Boolean(fragment)));
|
|
482
|
-
if (fragments.length === 0) return;
|
|
483
|
-
return fragments.join("\n\n");
|
|
484
|
-
}
|
|
485
|
-
function renderToolOutput(state, suppressReads) {
|
|
486
|
-
if (suppressReads && isReadLikeTool(state)) return SUPPRESSED_READ_OUTPUT;
|
|
487
|
-
return summarizeToolOutput(state.rawOutput, state.content);
|
|
488
|
-
}
|
|
489
|
-
function limitOutputBlock(value) {
|
|
490
|
-
const normalized = value.replace(/\r\n/g, "\n").trim();
|
|
491
|
-
if (!normalized) return "";
|
|
492
|
-
const lines = normalized.split("\n");
|
|
493
|
-
const visible = lines.slice(0, MAX_OUTPUT_LINES);
|
|
494
|
-
let result = visible.join("\n");
|
|
495
|
-
if (lines.length > visible.length) {
|
|
496
|
-
const hidden = lines.length - visible.length;
|
|
497
|
-
result += `\n... (${hidden} more lines)`;
|
|
498
|
-
}
|
|
499
|
-
if (result.length > MAX_OUTPUT_CHARS) result = `${result.slice(0, MAX_OUTPUT_CHARS - 3)}...`;
|
|
500
|
-
return result;
|
|
501
|
-
}
|
|
502
|
-
var TextOutputFormatter = class {
|
|
503
|
-
stdout;
|
|
504
|
-
useColor;
|
|
505
|
-
suppressReads;
|
|
506
|
-
toolStates = /* @__PURE__ */ new Map();
|
|
507
|
-
thoughtBuffer = "";
|
|
508
|
-
wroteAny = false;
|
|
509
|
-
atLineStart = true;
|
|
510
|
-
section = null;
|
|
511
|
-
constructor(stdout, suppressReads) {
|
|
512
|
-
this.stdout = stdout;
|
|
513
|
-
this.useColor = Boolean(stdout.isTTY);
|
|
514
|
-
this.suppressReads = suppressReads;
|
|
515
|
-
}
|
|
516
|
-
setContext(_context) {}
|
|
517
|
-
onAcpMessage(message) {
|
|
518
|
-
const notification = extractSessionUpdateNotification(message);
|
|
519
|
-
if (notification) {
|
|
520
|
-
this.renderSessionUpdate(notification);
|
|
521
|
-
return;
|
|
522
|
-
}
|
|
523
|
-
const method = extractJsonRpcMethod(message);
|
|
524
|
-
if (method && method !== "session/prompt" && method !== "session/cancel") {
|
|
525
|
-
this.onClientOperation({
|
|
526
|
-
method,
|
|
527
|
-
status: "running",
|
|
528
|
-
summary: method,
|
|
529
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
530
|
-
});
|
|
531
|
-
return;
|
|
532
|
-
}
|
|
533
|
-
const stopReason = parsePromptStopReason(message);
|
|
534
|
-
if (stopReason) {
|
|
535
|
-
this.renderDone(stopReason);
|
|
536
|
-
return;
|
|
537
|
-
}
|
|
538
|
-
const errorMessage = parseJsonRpcErrorMessage(message);
|
|
539
|
-
if (errorMessage) this.onError({
|
|
540
|
-
code: "RUNTIME",
|
|
541
|
-
origin: "acp",
|
|
542
|
-
message: errorMessage
|
|
543
|
-
});
|
|
544
|
-
}
|
|
545
|
-
renderSessionUpdate(notification) {
|
|
546
|
-
const update = notification.update;
|
|
547
|
-
if (update.sessionUpdate !== "agent_thought_chunk") this.flushThoughtBuffer();
|
|
548
|
-
switch (update.sessionUpdate) {
|
|
549
|
-
case "agent_message_chunk":
|
|
550
|
-
if (update.content.type === "text") this.writeAssistantChunk(update.content.text);
|
|
551
|
-
return;
|
|
552
|
-
case "agent_thought_chunk":
|
|
553
|
-
if (update.content.type === "text") this.thoughtBuffer += update.content.text;
|
|
554
|
-
return;
|
|
555
|
-
case "tool_call":
|
|
556
|
-
this.renderToolUpdate(update);
|
|
557
|
-
return;
|
|
558
|
-
case "tool_call_update":
|
|
559
|
-
this.renderToolUpdate(update);
|
|
560
|
-
return;
|
|
561
|
-
case "plan":
|
|
562
|
-
this.beginSection("plan");
|
|
563
|
-
this.writeLine(this.bold("[plan]"));
|
|
564
|
-
for (const entry of update.entries) this.writeLine(` - [${entry.status}] ${entry.content}`);
|
|
565
|
-
return;
|
|
566
|
-
default: return;
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
renderDone(stopReason) {
|
|
570
|
-
this.flushThoughtBuffer();
|
|
571
|
-
this.beginSection("done");
|
|
572
|
-
this.writeLine(this.dim(`[done] ${stopReason}`));
|
|
573
|
-
}
|
|
574
|
-
onError(params) {
|
|
575
|
-
this.flushThoughtBuffer();
|
|
576
|
-
this.beginSection("done");
|
|
577
|
-
this.writeLine(this.formatAnsi(`[error] ${params.code}: ${params.message}`, "31"));
|
|
578
|
-
for (const hint of getTextErrorRemediationHints(params)) this.writeLine(this.dim(hint));
|
|
579
|
-
}
|
|
580
|
-
onClientOperation(operation) {
|
|
581
|
-
this.flushThoughtBuffer();
|
|
582
|
-
this.beginSection("client");
|
|
583
|
-
const normalizedStatus = operation.status === "completed" ? "completed" : operation.status === "failed" ? "failed" : "in_progress";
|
|
584
|
-
const statusText = this.colorStatus(operation.status, normalizedStatus);
|
|
585
|
-
this.writeLine(`${this.bold("[client]")} ${operation.summary} (${statusText})`);
|
|
586
|
-
if (operation.details && operation.details.trim().length > 0) {
|
|
587
|
-
this.writeLine(" details:");
|
|
588
|
-
this.writeLine(indentBlock(operation.details, " "));
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
flush() {
|
|
592
|
-
this.flushThoughtBuffer();
|
|
593
|
-
if (!this.atLineStart) this.write("\n");
|
|
594
|
-
}
|
|
595
|
-
write(chunk) {
|
|
596
|
-
if (!chunk) return;
|
|
597
|
-
this.stdout.write(chunk);
|
|
598
|
-
this.wroteAny = true;
|
|
599
|
-
this.atLineStart = chunk.endsWith("\n");
|
|
600
|
-
}
|
|
601
|
-
writeLine(line) {
|
|
602
|
-
this.write(`${line}\n`);
|
|
603
|
-
}
|
|
604
|
-
beginSection(next) {
|
|
605
|
-
if (!this.atLineStart) this.write("\n");
|
|
606
|
-
if (this.wroteAny) this.write("\n");
|
|
607
|
-
this.section = next;
|
|
608
|
-
}
|
|
609
|
-
writeAssistantChunk(text) {
|
|
610
|
-
if (!text) return;
|
|
611
|
-
this.section = "assistant";
|
|
612
|
-
this.write(text);
|
|
613
|
-
}
|
|
614
|
-
flushThoughtBuffer() {
|
|
615
|
-
const thought = truncate(normalizeLineEndings(this.thoughtBuffer).trim(), MAX_THOUGHT_CHARS);
|
|
616
|
-
this.thoughtBuffer = "";
|
|
617
|
-
if (!thought) return;
|
|
618
|
-
this.beginSection("thought");
|
|
619
|
-
const [firstLine, ...restLines] = thought.split("\n");
|
|
620
|
-
this.writeLine(this.dim(`[thinking] ${firstLine}`));
|
|
621
|
-
for (const line of restLines) this.writeLine(this.dim(` ${line}`));
|
|
622
|
-
}
|
|
623
|
-
renderToolUpdate(update) {
|
|
624
|
-
const state = this.getOrCreateToolState(update.toolCallId);
|
|
625
|
-
this.mergeToolState(state, update);
|
|
626
|
-
const status = asStatus(state.status);
|
|
627
|
-
if (isFinalStatus(status)) {
|
|
628
|
-
const signature = this.toolSignature(state);
|
|
629
|
-
if (signature !== state.finalSignature) {
|
|
630
|
-
state.finalSignature = signature;
|
|
631
|
-
this.renderFinalToolState(state, status);
|
|
632
|
-
}
|
|
633
|
-
return;
|
|
634
|
-
}
|
|
635
|
-
if (state.startedPrinted) return;
|
|
636
|
-
state.startedPrinted = true;
|
|
637
|
-
this.renderStartingToolState(state, status);
|
|
638
|
-
}
|
|
639
|
-
getOrCreateToolState(toolCallId) {
|
|
640
|
-
const existing = this.toolStates.get(toolCallId);
|
|
641
|
-
if (existing) return existing;
|
|
642
|
-
const created = {
|
|
643
|
-
id: toolCallId,
|
|
644
|
-
startedPrinted: false
|
|
645
|
-
};
|
|
646
|
-
this.toolStates.set(toolCallId, created);
|
|
647
|
-
return created;
|
|
648
|
-
}
|
|
649
|
-
mergeToolState(state, update) {
|
|
650
|
-
if (typeof update.title === "string" && update.title.trim().length > 0) state.title = update.title;
|
|
651
|
-
if (update.status !== void 0) state.status = update.status;
|
|
652
|
-
if (update.kind !== void 0) state.kind = update.kind;
|
|
653
|
-
if (update.locations !== void 0) state.locations = update.locations;
|
|
654
|
-
if (update.rawInput !== void 0) state.rawInput = update.rawInput;
|
|
655
|
-
if (update.rawOutput !== void 0) state.rawOutput = update.rawOutput;
|
|
656
|
-
if (update.content !== void 0) state.content = update.content;
|
|
657
|
-
}
|
|
658
|
-
toolSignature(state) {
|
|
659
|
-
const signaturePayload = {
|
|
660
|
-
title: state.title,
|
|
661
|
-
status: state.status,
|
|
662
|
-
kind: state.kind,
|
|
663
|
-
input: summarizeToolInput(state.rawInput),
|
|
664
|
-
files: formatLocations(state.locations),
|
|
665
|
-
output: renderToolOutput(state, this.suppressReads)
|
|
666
|
-
};
|
|
667
|
-
return safeJson(signaturePayload, 0) ?? JSON.stringify(signaturePayload);
|
|
668
|
-
}
|
|
669
|
-
renderStartingToolState(state, status) {
|
|
670
|
-
this.beginSection("tool");
|
|
671
|
-
const title = state.title ?? state.id;
|
|
672
|
-
const label = status === "pending" ? "pending" : "running";
|
|
673
|
-
const statusText = this.colorStatus(label, status);
|
|
674
|
-
this.writeLine(`${this.bold("[tool]")} ${title} (${statusText})`);
|
|
675
|
-
const input = summarizeToolInput(state.rawInput);
|
|
676
|
-
if (input) this.writeLine(` input: ${input}`);
|
|
677
|
-
const files = formatLocations(state.locations);
|
|
678
|
-
if (files) this.writeLine(` files: ${files}`);
|
|
679
|
-
}
|
|
680
|
-
renderFinalToolState(state, status) {
|
|
681
|
-
this.beginSection("tool");
|
|
682
|
-
const title = state.title ?? state.id;
|
|
683
|
-
const statusText = this.colorStatus(toStatusLabel(status), status);
|
|
684
|
-
this.writeLine(`${this.bold("[tool]")} ${title} (${statusText})`);
|
|
685
|
-
if (state.kind) this.writeLine(` kind: ${state.kind}`);
|
|
686
|
-
const input = summarizeToolInput(state.rawInput);
|
|
687
|
-
if (input) this.writeLine(` input: ${input}`);
|
|
688
|
-
const files = formatLocations(state.locations);
|
|
689
|
-
if (files) this.writeLine(` files: ${files}`);
|
|
690
|
-
const output = renderToolOutput(state, this.suppressReads);
|
|
691
|
-
if (output) {
|
|
692
|
-
this.writeLine(" output:");
|
|
693
|
-
this.writeLine(indentBlock(limitOutputBlock(output), " "));
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
formatAnsi(text, code) {
|
|
697
|
-
if (!this.useColor) return text;
|
|
698
|
-
return `\u001b[${code}m${text}\u001b[0m`;
|
|
699
|
-
}
|
|
700
|
-
bold(text) {
|
|
701
|
-
return this.formatAnsi(text, "1");
|
|
702
|
-
}
|
|
703
|
-
dim(text) {
|
|
704
|
-
return this.formatAnsi(text, "2");
|
|
705
|
-
}
|
|
706
|
-
colorStatus(text, status) {
|
|
707
|
-
if (!this.useColor) return text;
|
|
708
|
-
switch (status) {
|
|
709
|
-
case "completed": return this.formatAnsi(text, "32");
|
|
710
|
-
case "failed": return this.formatAnsi(text, "31");
|
|
711
|
-
default: return this.formatAnsi(text, "33");
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
};
|
|
715
|
-
var QuietOutputFormatter = class {
|
|
716
|
-
stdout;
|
|
717
|
-
stderr;
|
|
718
|
-
chunks = [];
|
|
719
|
-
flushed = false;
|
|
720
|
-
metadataFlushed = false;
|
|
721
|
-
constructor(stdout, stderr) {
|
|
722
|
-
this.stdout = stdout;
|
|
723
|
-
this.stderr = stderr;
|
|
724
|
-
}
|
|
725
|
-
setContext(_context) {}
|
|
726
|
-
onAcpMessage(message) {
|
|
727
|
-
const update = extractSessionUpdateNotification(message);
|
|
728
|
-
if (update?.update.sessionUpdate === "agent_message_chunk" && update.update.content.type === "text") {
|
|
729
|
-
this.chunks.push(update.update.content.text);
|
|
730
|
-
return;
|
|
731
|
-
}
|
|
732
|
-
if (parsePromptStopReason(message)) {
|
|
733
|
-
this.flushBufferedOutput();
|
|
734
|
-
this.flushMetadata(message);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
onError(_params) {}
|
|
738
|
-
flush() {}
|
|
739
|
-
flushBufferedOutput() {
|
|
740
|
-
if (this.flushed) return;
|
|
741
|
-
this.flushed = true;
|
|
742
|
-
const text = this.chunks.join("");
|
|
743
|
-
this.stdout.write(text.endsWith("\n") ? text : `${text}\n`);
|
|
744
|
-
}
|
|
745
|
-
flushMetadata(message) {
|
|
746
|
-
if (this.metadataFlushed) return;
|
|
747
|
-
this.metadataFlushed = true;
|
|
748
|
-
const result = asRecord(message.result);
|
|
749
|
-
if (!result) return;
|
|
750
|
-
const usageLine = this.formatUsageLine(asRecord(result.usage));
|
|
751
|
-
if (usageLine) this.stderr.write(`${usageLine}\n`);
|
|
752
|
-
const costLine = this.formatCostLine(result.cost);
|
|
753
|
-
if (costLine) this.stderr.write(`${costLine}\n`);
|
|
754
|
-
}
|
|
755
|
-
formatUsageLine(usage) {
|
|
756
|
-
if (!usage) return;
|
|
757
|
-
const parts = [];
|
|
758
|
-
for (const [label, keys] of [
|
|
759
|
-
["input", ["inputTokens", "input_tokens"]],
|
|
760
|
-
["output", ["outputTokens", "output_tokens"]],
|
|
761
|
-
["cache_read", [
|
|
762
|
-
"cachedReadTokens",
|
|
763
|
-
"cacheReadInputTokens",
|
|
764
|
-
"cache_read_input_tokens"
|
|
765
|
-
]],
|
|
766
|
-
["cache_write", [
|
|
767
|
-
"cachedWriteTokens",
|
|
768
|
-
"cacheCreationInputTokens",
|
|
769
|
-
"cache_creation_input_tokens"
|
|
770
|
-
]],
|
|
771
|
-
["total", ["totalTokens", "total_tokens"]]
|
|
772
|
-
]) {
|
|
773
|
-
const value = readFirstFiniteNumber(usage, keys);
|
|
774
|
-
if (value !== void 0) parts.push(`${label}=${formatMetadataNumber(value)}`);
|
|
775
|
-
}
|
|
776
|
-
return parts.length > 0 ? `[acpx] tokens: ${parts.join(" ")}` : void 0;
|
|
777
|
-
}
|
|
778
|
-
formatCostLine(cost) {
|
|
779
|
-
if (typeof cost === "number" && Number.isFinite(cost)) return `[acpx] cost: ${formatMetadataNumber(cost)}`;
|
|
780
|
-
if (typeof cost === "string" && cost.trim()) return `[acpx] cost: ${cost.trim()}`;
|
|
781
|
-
const record = asRecord(cost);
|
|
782
|
-
if (!record) return;
|
|
783
|
-
const amount = readFirstFiniteNumber(record, [
|
|
784
|
-
"amount",
|
|
785
|
-
"value",
|
|
786
|
-
"total"
|
|
787
|
-
]);
|
|
788
|
-
if (amount === void 0) return;
|
|
789
|
-
const currency = typeof record.currency === "string" && record.currency.trim() ? ` ${record.currency.trim()}` : "";
|
|
790
|
-
return `[acpx] cost: ${formatMetadataNumber(amount)}${currency}`;
|
|
791
|
-
}
|
|
792
|
-
};
|
|
793
|
-
function createOutputFormatter(format, options = {}) {
|
|
794
|
-
const stdout = options.stdout ?? process.stdout;
|
|
795
|
-
const stderr = options.stderr ?? process.stderr;
|
|
796
|
-
const suppressReads = options.suppressReads === true;
|
|
797
|
-
switch (format) {
|
|
798
|
-
case "text": return new TextOutputFormatter(stdout, suppressReads);
|
|
799
|
-
case "json": return createJsonOutputFormatter(stdout, suppressReads, options.jsonContext);
|
|
800
|
-
case "quiet": return new QuietOutputFormatter(stdout, stderr);
|
|
801
|
-
default: throw new Error("Unsupported output format");
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
//#endregion
|
|
805
|
-
export { getTextErrorRemediationHints as n, output_exports as r, createOutputFormatter as t };
|
|
806
|
-
|
|
807
|
-
//# sourceMappingURL=output-DmHvT8vm.js.map
|