@llmist/cli 15.19.0 → 16.0.1
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/dist/cli.js +275 -65
- package/dist/cli.js.map +1 -1
- package/package.json +5 -4
package/dist/cli.js
CHANGED
|
@@ -110,7 +110,7 @@ import { Command, InvalidArgumentError as InvalidArgumentError2 } from "commande
|
|
|
110
110
|
// package.json
|
|
111
111
|
var package_default = {
|
|
112
112
|
name: "@llmist/cli",
|
|
113
|
-
version: "
|
|
113
|
+
version: "16.0.1",
|
|
114
114
|
description: "CLI for llmist - run LLM agents from the command line",
|
|
115
115
|
type: "module",
|
|
116
116
|
main: "dist/cli.js",
|
|
@@ -136,7 +136,8 @@ var package_default = {
|
|
|
136
136
|
build: "tsup",
|
|
137
137
|
typecheck: "tsc --noEmit",
|
|
138
138
|
clean: "rimraf dist",
|
|
139
|
-
postinstall: "node scripts/postinstall.js"
|
|
139
|
+
postinstall: "node scripts/postinstall.js",
|
|
140
|
+
dev: "npx --silent tsx src/cli.ts"
|
|
140
141
|
},
|
|
141
142
|
homepage: "https://llmist.dev",
|
|
142
143
|
repository: {
|
|
@@ -166,7 +167,7 @@ var package_default = {
|
|
|
166
167
|
node: ">=22.0.0"
|
|
167
168
|
},
|
|
168
169
|
dependencies: {
|
|
169
|
-
llmist: "^
|
|
170
|
+
llmist: "^16.0.1",
|
|
170
171
|
"@unblessed/node": "^1.0.0-alpha.23",
|
|
171
172
|
chalk: "^5.6.2",
|
|
172
173
|
commander: "^12.1.0",
|
|
@@ -180,7 +181,7 @@ var package_default = {
|
|
|
180
181
|
zod: "^4.1.12"
|
|
181
182
|
},
|
|
182
183
|
devDependencies: {
|
|
183
|
-
"@llmist/testing": "^
|
|
184
|
+
"@llmist/testing": "^16.0.1",
|
|
184
185
|
"@types/diff": "^8.0.0",
|
|
185
186
|
"@types/js-yaml": "^4.0.9",
|
|
186
187
|
"@types/marked-terminal": "^6.1.1",
|
|
@@ -195,13 +196,194 @@ var package_default = {
|
|
|
195
196
|
import { AgentBuilder, GadgetRegistry, HookPresets, isAbortError, text } from "llmist";
|
|
196
197
|
|
|
197
198
|
// src/builtin-gadgets.ts
|
|
198
|
-
import { createGadget, HumanInputRequiredException, TaskCompletionSignal } from "llmist";
|
|
199
|
+
import { createGadget as createGadget2, HumanInputRequiredException, TaskCompletionSignal } from "llmist";
|
|
200
|
+
import { z as z2 } from "zod";
|
|
201
|
+
|
|
202
|
+
// src/builtins/text-to-speech.ts
|
|
203
|
+
import { createGadget, getErrorMessage, resultWithAudio } from "llmist";
|
|
199
204
|
import { z } from "zod";
|
|
200
|
-
|
|
205
|
+
|
|
206
|
+
// src/ffmpeg.ts
|
|
207
|
+
import { spawn } from "child_process";
|
|
208
|
+
var CONVERSION_TIMEOUT_MS = 3e4;
|
|
209
|
+
var ffmpegCheckPromise = null;
|
|
210
|
+
async function isFFmpegAvailable() {
|
|
211
|
+
if (ffmpegCheckPromise !== null) return ffmpegCheckPromise;
|
|
212
|
+
ffmpegCheckPromise = new Promise((resolve3) => {
|
|
213
|
+
const proc = spawn("ffmpeg", ["-version"], { stdio: "ignore" });
|
|
214
|
+
proc.on("error", () => resolve3(false));
|
|
215
|
+
proc.on("close", (code) => resolve3(code === 0));
|
|
216
|
+
});
|
|
217
|
+
return ffmpegCheckPromise;
|
|
218
|
+
}
|
|
219
|
+
async function convertToMp3(input, inputFormat, timeout = CONVERSION_TIMEOUT_MS) {
|
|
220
|
+
return new Promise((resolve3) => {
|
|
221
|
+
let timeoutId;
|
|
222
|
+
const inputArgs = inputFormat === "pcm16" ? ["-f", "s16le", "-ar", "24000", "-ac", "1"] : ["-f", inputFormat];
|
|
223
|
+
const proc = spawn(
|
|
224
|
+
"ffmpeg",
|
|
225
|
+
[
|
|
226
|
+
...inputArgs,
|
|
227
|
+
"-i",
|
|
228
|
+
"pipe:0",
|
|
229
|
+
// Read from stdin
|
|
230
|
+
"-f",
|
|
231
|
+
"mp3",
|
|
232
|
+
// Output format
|
|
233
|
+
"-ab",
|
|
234
|
+
"128k",
|
|
235
|
+
// Bitrate
|
|
236
|
+
"pipe:1"
|
|
237
|
+
// Write to stdout
|
|
238
|
+
],
|
|
239
|
+
{ stdio: ["pipe", "pipe", "ignore"] }
|
|
240
|
+
);
|
|
241
|
+
const chunks = [];
|
|
242
|
+
proc.stdout.on("data", (chunk) => chunks.push(chunk));
|
|
243
|
+
proc.on("error", () => {
|
|
244
|
+
clearTimeout(timeoutId);
|
|
245
|
+
resolve3(null);
|
|
246
|
+
});
|
|
247
|
+
proc.on("close", (code) => {
|
|
248
|
+
clearTimeout(timeoutId);
|
|
249
|
+
resolve3(code === 0 ? Buffer.concat(chunks) : null);
|
|
250
|
+
});
|
|
251
|
+
timeoutId = setTimeout(() => {
|
|
252
|
+
proc.kill();
|
|
253
|
+
resolve3(null);
|
|
254
|
+
}, timeout);
|
|
255
|
+
proc.stdin.on("error", () => {
|
|
256
|
+
});
|
|
257
|
+
proc.stdin.write(input);
|
|
258
|
+
proc.stdin.end();
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// src/builtins/text-to-speech.ts
|
|
263
|
+
var TTS_VOICES = ["alloy", "echo", "fable", "onyx", "nova", "shimmer"];
|
|
264
|
+
var TTS_FORMATS = ["mp3", "opus", "aac", "flac", "wav", "pcm16"];
|
|
265
|
+
function createTextToSpeech(config) {
|
|
266
|
+
if (config?.voice && !TTS_VOICES.includes(config.voice)) {
|
|
267
|
+
throw new Error(`Invalid TTS voice "${config.voice}". Valid voices: ${TTS_VOICES.join(", ")}`);
|
|
268
|
+
}
|
|
269
|
+
if (config?.format && !TTS_FORMATS.includes(config.format)) {
|
|
270
|
+
throw new Error(
|
|
271
|
+
`Invalid TTS format "${config.format}". Valid formats: ${TTS_FORMATS.join(", ")}`
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
if (config?.speed !== void 0 && (config.speed < 0.25 || config.speed > 4)) {
|
|
275
|
+
throw new Error(`Invalid TTS speed "${config.speed}". Must be between 0.25 and 4.0`);
|
|
276
|
+
}
|
|
277
|
+
const defaultModel = config?.model ?? "tts-1";
|
|
278
|
+
const defaultVoice = config?.voice ?? "nova";
|
|
279
|
+
const defaultFormat = config?.format ?? "mp3";
|
|
280
|
+
const defaultSpeed = config?.speed ?? 1;
|
|
281
|
+
return createGadget({
|
|
282
|
+
name: "TextToSpeech",
|
|
283
|
+
description: `Convert text to speech audio. Uses configured TTS model. Defaults: ${defaultVoice} voice, ${defaultFormat} format.`,
|
|
284
|
+
schema: z.object({
|
|
285
|
+
text: z.string().min(1).describe("Text to convert to speech"),
|
|
286
|
+
voice: z.enum(TTS_VOICES).optional().describe(`Voice to use (default: ${defaultVoice})`),
|
|
287
|
+
format: z.enum(TTS_FORMATS).optional().describe(`Output format (default: ${defaultFormat})`),
|
|
288
|
+
speed: z.number().min(0.25).max(4).optional().describe(`Speech speed 0.25-4.0 (default: ${defaultSpeed})`)
|
|
289
|
+
}),
|
|
290
|
+
examples: [
|
|
291
|
+
{
|
|
292
|
+
comment: "Generate speech with default settings",
|
|
293
|
+
params: { text: "Hello, welcome to our application!" },
|
|
294
|
+
output: "Generated audio (mp3, 35 chars, $0.000525)"
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
comment: "Use a specific voice",
|
|
298
|
+
params: {
|
|
299
|
+
text: "This is an important announcement.",
|
|
300
|
+
voice: "onyx"
|
|
301
|
+
},
|
|
302
|
+
output: "Generated audio (mp3, 35 chars, $0.001050)"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
comment: "Generate slower speech in WAV format",
|
|
306
|
+
params: {
|
|
307
|
+
text: "Please listen carefully to these instructions.",
|
|
308
|
+
format: "wav",
|
|
309
|
+
speed: 0.8
|
|
310
|
+
},
|
|
311
|
+
output: "Generated audio (wav, 46 chars, $0.000690)"
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
comment: "Result when cost is unavailable (some providers)",
|
|
315
|
+
params: { text: "Hello there!" },
|
|
316
|
+
output: "Generated audio (mp3, 12 chars, $N/A)"
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
comment: "Auto-converted to MP3 (when ffmpeg is available and format isn't MP3)",
|
|
320
|
+
params: { text: "Converted audio.", format: "pcm16" },
|
|
321
|
+
output: "Generated audio (mp3, 16 chars, $0.000240) [converted from pcm16]"
|
|
322
|
+
}
|
|
323
|
+
],
|
|
324
|
+
execute: async ({ text: text3, voice, format, speed }, ctx) => {
|
|
325
|
+
if (!ctx?.llmist?.speech?.generate) {
|
|
326
|
+
return "status=1\n\nerror: Speech generation requires LLMist client with speech capability.";
|
|
327
|
+
}
|
|
328
|
+
const selectedModel = defaultModel;
|
|
329
|
+
const selectedVoice = voice ?? defaultVoice;
|
|
330
|
+
const selectedFormat = format ?? defaultFormat;
|
|
331
|
+
const selectedSpeed = speed ?? (defaultSpeed !== 1 ? defaultSpeed : void 0);
|
|
332
|
+
const maxRetries = 2;
|
|
333
|
+
let lastError;
|
|
334
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
335
|
+
try {
|
|
336
|
+
const result = await ctx.llmist.speech.generate({
|
|
337
|
+
model: selectedModel,
|
|
338
|
+
input: text3,
|
|
339
|
+
voice: selectedVoice,
|
|
340
|
+
// Cast is safe: Zod validates LLM input, config values validated at factory time
|
|
341
|
+
responseFormat: selectedFormat,
|
|
342
|
+
...selectedSpeed !== void 0 ? { speed: selectedSpeed } : {}
|
|
343
|
+
});
|
|
344
|
+
let audioBuffer = Buffer.from(result.audio);
|
|
345
|
+
let finalFormat = result.format;
|
|
346
|
+
if (finalFormat !== "mp3" && await isFFmpegAvailable()) {
|
|
347
|
+
const mp3Buffer = await convertToMp3(audioBuffer, finalFormat);
|
|
348
|
+
if (mp3Buffer) {
|
|
349
|
+
audioBuffer = mp3Buffer;
|
|
350
|
+
finalFormat = "mp3";
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
const conversionNote = finalFormat !== result.format ? ` [converted from ${result.format}]` : "";
|
|
354
|
+
return resultWithAudio(
|
|
355
|
+
`Generated audio (${finalFormat}, ${result.usage.characterCount} chars, $${result.cost?.toFixed(6) ?? "N/A"})${conversionNote}`,
|
|
356
|
+
audioBuffer,
|
|
357
|
+
{
|
|
358
|
+
mimeType: `audio/${finalFormat}`,
|
|
359
|
+
cost: result.cost,
|
|
360
|
+
description: `TTS: "${text3.slice(0, 50)}${text3.length > 50 ? "..." : ""}"`
|
|
361
|
+
}
|
|
362
|
+
);
|
|
363
|
+
} catch (error) {
|
|
364
|
+
lastError = error;
|
|
365
|
+
const errorMsg = getErrorMessage(error);
|
|
366
|
+
const isRetryable = errorMsg.includes("HTTP 4") || errorMsg.includes("HTTP 5");
|
|
367
|
+
if (!isRetryable || attempt === maxRetries) {
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
await new Promise((r) => setTimeout(r, 500 * (attempt + 1)));
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return `status=1
|
|
374
|
+
|
|
375
|
+
error: ${getErrorMessage(lastError)}`;
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
var textToSpeech = createTextToSpeech();
|
|
380
|
+
|
|
381
|
+
// src/builtin-gadgets.ts
|
|
382
|
+
var askUser = createGadget2({
|
|
201
383
|
name: "AskUser",
|
|
202
384
|
description: "Ask the user a question when you need more information or clarification. The user's response will be provided back to you.",
|
|
203
|
-
schema:
|
|
204
|
-
question:
|
|
385
|
+
schema: z2.object({
|
|
386
|
+
question: z2.string().describe("The question to ask the user in plain-text or Markdown")
|
|
205
387
|
}),
|
|
206
388
|
examples: [
|
|
207
389
|
{
|
|
@@ -219,12 +401,12 @@ var askUser = createGadget({
|
|
|
219
401
|
throw new HumanInputRequiredException(question);
|
|
220
402
|
}
|
|
221
403
|
});
|
|
222
|
-
var tellUser =
|
|
404
|
+
var tellUser = createGadget2({
|
|
223
405
|
name: "TellUser",
|
|
224
406
|
description: "Tell the user something important.",
|
|
225
|
-
schema:
|
|
226
|
-
message:
|
|
227
|
-
type:
|
|
407
|
+
schema: z2.object({
|
|
408
|
+
message: z2.string().optional().describe("The message to display to the user in Markdown"),
|
|
409
|
+
type: z2.enum(["info", "success", "warning", "error"]).default("info").describe("Message type: info, success, warning, or error")
|
|
228
410
|
}),
|
|
229
411
|
examples: [
|
|
230
412
|
{
|
|
@@ -255,10 +437,10 @@ var tellUser = createGadget({
|
|
|
255
437
|
return prefixes[type] + message;
|
|
256
438
|
}
|
|
257
439
|
});
|
|
258
|
-
var finish =
|
|
440
|
+
var finish = createGadget2({
|
|
259
441
|
name: "Finish",
|
|
260
442
|
description: "Signal that you have completed your task. Call this when your work is done.",
|
|
261
|
-
schema:
|
|
443
|
+
schema: z2.object({}),
|
|
262
444
|
examples: [
|
|
263
445
|
{
|
|
264
446
|
comment: "Signal task completion",
|
|
@@ -269,7 +451,10 @@ var finish = createGadget({
|
|
|
269
451
|
throw new TaskCompletionSignal("Task completed");
|
|
270
452
|
}
|
|
271
453
|
});
|
|
272
|
-
var builtinGadgets = [askUser, tellUser, finish];
|
|
454
|
+
var builtinGadgets = [askUser, tellUser, finish, createTextToSpeech()];
|
|
455
|
+
function getBuiltinGadgets(speechConfig) {
|
|
456
|
+
return [askUser, tellUser, finish, createTextToSpeech(speechConfig)];
|
|
457
|
+
}
|
|
273
458
|
|
|
274
459
|
// src/config.ts
|
|
275
460
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
@@ -1530,8 +1715,8 @@ import { AbstractGadget } from "llmist";
|
|
|
1530
1715
|
|
|
1531
1716
|
// src/builtins/filesystem/edit-file.ts
|
|
1532
1717
|
import { readFileSync as readFileSync3, writeFileSync } from "fs";
|
|
1533
|
-
import { createGadget as
|
|
1534
|
-
import { z as
|
|
1718
|
+
import { createGadget as createGadget3 } from "llmist";
|
|
1719
|
+
import { z as z3 } from "zod";
|
|
1535
1720
|
|
|
1536
1721
|
// src/builtins/filesystem/editfile/matcher.ts
|
|
1537
1722
|
var DEFAULT_OPTIONS = {
|
|
@@ -1844,7 +2029,7 @@ function formatFailure(filePath, search, failure, fileContent) {
|
|
|
1844
2029
|
lines.push("", "CURRENT FILE CONTENT:", "```", fileContent, "```");
|
|
1845
2030
|
return lines.join("\n");
|
|
1846
2031
|
}
|
|
1847
|
-
var editFile =
|
|
2032
|
+
var editFile = createGadget3({
|
|
1848
2033
|
name: "EditFile",
|
|
1849
2034
|
description: `Edit a file by searching for content and replacing it.
|
|
1850
2035
|
|
|
@@ -1858,10 +2043,10 @@ For multiple edits to the same file, call this gadget multiple times.
|
|
|
1858
2043
|
Each call provides immediate feedback, allowing you to adjust subsequent edits.`,
|
|
1859
2044
|
maxConcurrent: 1,
|
|
1860
2045
|
// Sequential execution to prevent race conditions
|
|
1861
|
-
schema:
|
|
1862
|
-
filePath:
|
|
1863
|
-
search:
|
|
1864
|
-
replace:
|
|
2046
|
+
schema: z3.object({
|
|
2047
|
+
filePath: z3.string().describe("Path to the file to edit (relative or absolute)"),
|
|
2048
|
+
search: z3.string().describe("The content to search for in the file"),
|
|
2049
|
+
replace: z3.string().describe("The content to replace it with (empty string to delete)")
|
|
1865
2050
|
}),
|
|
1866
2051
|
examples: [
|
|
1867
2052
|
{
|
|
@@ -1955,8 +2140,8 @@ ${newContent}
|
|
|
1955
2140
|
// src/builtins/filesystem/list-directory.ts
|
|
1956
2141
|
import fs2 from "fs";
|
|
1957
2142
|
import path2 from "path";
|
|
1958
|
-
import { createGadget as
|
|
1959
|
-
import { z as
|
|
2143
|
+
import { createGadget as createGadget4 } from "llmist";
|
|
2144
|
+
import { z as z4 } from "zod";
|
|
1960
2145
|
function listFiles(dirPath, basePath = dirPath, maxDepth = 1, currentDepth = 1) {
|
|
1961
2146
|
const entries = [];
|
|
1962
2147
|
try {
|
|
@@ -2040,12 +2225,12 @@ function formatEntriesAsString(entries) {
|
|
|
2040
2225
|
);
|
|
2041
2226
|
return [header, ...rows].join("\n");
|
|
2042
2227
|
}
|
|
2043
|
-
var listDirectory =
|
|
2228
|
+
var listDirectory = createGadget4({
|
|
2044
2229
|
name: "ListDirectory",
|
|
2045
2230
|
description: "List files and directories in a directory with full details (names, types, sizes, modification dates). Use maxDepth to explore subdirectories recursively. The directory path must be within the current working directory or its subdirectories.",
|
|
2046
|
-
schema:
|
|
2047
|
-
directoryPath:
|
|
2048
|
-
maxDepth:
|
|
2231
|
+
schema: z4.object({
|
|
2232
|
+
directoryPath: z4.string().default(".").describe("Path to the directory to list"),
|
|
2233
|
+
maxDepth: z4.number().int().min(1).max(10).default(3).describe(
|
|
2049
2234
|
"Maximum depth to recurse (1 = immediate children only, 2 = include grandchildren, etc.)"
|
|
2050
2235
|
)
|
|
2051
2236
|
}),
|
|
@@ -2077,13 +2262,13 @@ ${formattedList}`;
|
|
|
2077
2262
|
|
|
2078
2263
|
// src/builtins/filesystem/read-file.ts
|
|
2079
2264
|
import fs3 from "fs";
|
|
2080
|
-
import { createGadget as
|
|
2081
|
-
import { z as
|
|
2082
|
-
var readFile2 =
|
|
2265
|
+
import { createGadget as createGadget5 } from "llmist";
|
|
2266
|
+
import { z as z5 } from "zod";
|
|
2267
|
+
var readFile2 = createGadget5({
|
|
2083
2268
|
name: "ReadFile",
|
|
2084
2269
|
description: "Read the entire content of a file and return it as text. The file path must be within the current working directory or its subdirectories.",
|
|
2085
|
-
schema:
|
|
2086
|
-
filePath:
|
|
2270
|
+
schema: z5.object({
|
|
2271
|
+
filePath: z5.string().describe("Path to the file to read (relative or absolute)")
|
|
2087
2272
|
}),
|
|
2088
2273
|
examples: [
|
|
2089
2274
|
{
|
|
@@ -2109,16 +2294,16 @@ ${content}`;
|
|
|
2109
2294
|
// src/builtins/filesystem/write-file.ts
|
|
2110
2295
|
import fs4 from "fs";
|
|
2111
2296
|
import path3 from "path";
|
|
2112
|
-
import { createGadget as
|
|
2113
|
-
import { z as
|
|
2114
|
-
var writeFile =
|
|
2297
|
+
import { createGadget as createGadget6 } from "llmist";
|
|
2298
|
+
import { z as z6 } from "zod";
|
|
2299
|
+
var writeFile = createGadget6({
|
|
2115
2300
|
name: "WriteFile",
|
|
2116
2301
|
description: "Write content to a file. Creates parent directories if needed. Overwrites existing files. The file path must be within the current working directory or its subdirectories.",
|
|
2117
2302
|
maxConcurrent: 1,
|
|
2118
2303
|
// Sequential execution to prevent race conditions
|
|
2119
|
-
schema:
|
|
2120
|
-
filePath:
|
|
2121
|
-
content:
|
|
2304
|
+
schema: z6.object({
|
|
2305
|
+
filePath: z6.string().describe("Path to the file to write (relative or absolute)"),
|
|
2306
|
+
content: z6.string().describe("Content to write to the file")
|
|
2122
2307
|
}),
|
|
2123
2308
|
examples: [
|
|
2124
2309
|
{
|
|
@@ -2163,8 +2348,8 @@ Wrote ${bytesWritten} bytes${dirNote}`;
|
|
|
2163
2348
|
});
|
|
2164
2349
|
|
|
2165
2350
|
// src/builtins/run-command.ts
|
|
2166
|
-
import { createGadget as
|
|
2167
|
-
import { z as
|
|
2351
|
+
import { createGadget as createGadget7 } from "llmist";
|
|
2352
|
+
import { z as z7 } from "zod";
|
|
2168
2353
|
|
|
2169
2354
|
// src/spawn.ts
|
|
2170
2355
|
import { spawn as nodeSpawn } from "child_process";
|
|
@@ -2187,7 +2372,7 @@ function nodeStreamToReadableStream(nodeStream) {
|
|
|
2187
2372
|
}
|
|
2188
2373
|
});
|
|
2189
2374
|
}
|
|
2190
|
-
function
|
|
2375
|
+
function spawn2(argv, options = {}) {
|
|
2191
2376
|
const [command, ...args] = argv;
|
|
2192
2377
|
const proc = nodeSpawn(command, args, {
|
|
2193
2378
|
cwd: options.cwd,
|
|
@@ -2225,13 +2410,13 @@ function spawn(argv, options = {}) {
|
|
|
2225
2410
|
}
|
|
2226
2411
|
|
|
2227
2412
|
// src/builtins/run-command.ts
|
|
2228
|
-
var runCommand =
|
|
2413
|
+
var runCommand = createGadget7({
|
|
2229
2414
|
name: "RunCommand",
|
|
2230
2415
|
description: "Execute a command with arguments and return its output. Uses argv array to bypass shell - arguments are passed directly without interpretation. Returns stdout/stderr combined with exit status.",
|
|
2231
|
-
schema:
|
|
2232
|
-
argv:
|
|
2233
|
-
cwd:
|
|
2234
|
-
timeout:
|
|
2416
|
+
schema: z7.object({
|
|
2417
|
+
argv: z7.array(z7.string()).describe("Command and arguments as array (e.g., ['git', 'commit', '-m', 'message'])"),
|
|
2418
|
+
cwd: z7.string().optional().describe("Working directory for the command (default: current directory)"),
|
|
2419
|
+
timeout: z7.number().default(3e4).describe("Timeout in milliseconds (default: 30000)")
|
|
2235
2420
|
}),
|
|
2236
2421
|
examples: [
|
|
2237
2422
|
{
|
|
@@ -2294,7 +2479,7 @@ var runCommand = createGadget6({
|
|
|
2294
2479
|
}
|
|
2295
2480
|
let timeoutId;
|
|
2296
2481
|
try {
|
|
2297
|
-
const proc =
|
|
2482
|
+
const proc = spawn2(argv, {
|
|
2298
2483
|
cwd: workingDir,
|
|
2299
2484
|
stdout: "pipe",
|
|
2300
2485
|
stderr: "pipe"
|
|
@@ -2338,7 +2523,8 @@ var builtinGadgetRegistry = {
|
|
|
2338
2523
|
ReadFile: readFile2,
|
|
2339
2524
|
WriteFile: writeFile,
|
|
2340
2525
|
EditFile: editFile,
|
|
2341
|
-
RunCommand: runCommand
|
|
2526
|
+
RunCommand: runCommand,
|
|
2527
|
+
TextToSpeech: textToSpeech
|
|
2342
2528
|
};
|
|
2343
2529
|
function getBuiltinGadget(name) {
|
|
2344
2530
|
return builtinGadgetRegistry[name];
|
|
@@ -4679,6 +4865,17 @@ function formatGadgetExpanded(node) {
|
|
|
4679
4865
|
}
|
|
4680
4866
|
lines.push(`${indent}${chalk3.dim(BOX.bottomLeft + BOX.horizontal.repeat(width - 1))}`);
|
|
4681
4867
|
}
|
|
4868
|
+
if (node.mediaOutputs && node.mediaOutputs.length > 0) {
|
|
4869
|
+
const headerLine = `${BOX.topLeft}${BOX.horizontal} Media ${BOX.horizontal.repeat(width - 9)}`;
|
|
4870
|
+
lines.push(`${indent}${chalk3.dim(headerLine)}`);
|
|
4871
|
+
for (const media of node.mediaOutputs) {
|
|
4872
|
+
const kindEmoji = media.kind === "audio" ? "\u{1F50A}" : media.kind === "image" ? "\u{1F5BC}\uFE0F" : media.kind === "video" ? "\u{1F3AC}" : "\u{1F4C4}";
|
|
4873
|
+
const maxPathLen = width - 8;
|
|
4874
|
+
const displayPath = media.path.length > maxPathLen ? "..." + media.path.slice(-(maxPathLen - 3)) : media.path;
|
|
4875
|
+
lines.push(`${indent}${chalk3.dim(BOX.vertical)} ${kindEmoji} ${chalk3.cyan(displayPath)}`);
|
|
4876
|
+
}
|
|
4877
|
+
lines.push(`${indent}${chalk3.dim(BOX.bottomLeft + BOX.horizontal.repeat(width - 1))}`);
|
|
4878
|
+
}
|
|
4682
4879
|
if (node.children.length > 0) {
|
|
4683
4880
|
const headerLine = `${BOX.topLeft}${BOX.horizontal} Subagent Activity ${BOX.horizontal.repeat(width - 21)}`;
|
|
4684
4881
|
lines.push(`${indent}${chalk3.dim(headerLine)}`);
|
|
@@ -4906,14 +5103,16 @@ var BlockRenderer = class _BlockRenderer {
|
|
|
4906
5103
|
/**
|
|
4907
5104
|
* Complete a gadget with result.
|
|
4908
5105
|
*/
|
|
4909
|
-
completeGadget(invocationId,
|
|
5106
|
+
completeGadget(invocationId, options = {}) {
|
|
4910
5107
|
const node = this.findGadgetByInvocationId(invocationId);
|
|
4911
5108
|
if (!node) return;
|
|
5109
|
+
const { result, error, executionTimeMs, cost, mediaOutputs } = options;
|
|
4912
5110
|
node.isComplete = true;
|
|
4913
5111
|
node.result = result;
|
|
4914
5112
|
node.error = error;
|
|
4915
5113
|
node.executionTimeMs = executionTimeMs;
|
|
4916
5114
|
node.cost = cost;
|
|
5115
|
+
node.mediaOutputs = mediaOutputs;
|
|
4917
5116
|
if (result) {
|
|
4918
5117
|
node.resultTokens = Math.ceil(result.length / 4);
|
|
4919
5118
|
}
|
|
@@ -5939,17 +6138,25 @@ ${indicator}`;
|
|
|
5939
6138
|
break;
|
|
5940
6139
|
}
|
|
5941
6140
|
case "gadget_complete": {
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
6141
|
+
const mediaOutputs = event.storedMedia?.map((m) => ({
|
|
6142
|
+
kind: m.kind,
|
|
6143
|
+
path: m.path,
|
|
6144
|
+
mimeType: m.mimeType,
|
|
6145
|
+
description: m.description
|
|
6146
|
+
}));
|
|
6147
|
+
this.completeGadget(event.invocationId, {
|
|
6148
|
+
result: event.result,
|
|
6149
|
+
executionTimeMs: event.executionTimeMs,
|
|
6150
|
+
cost: event.cost,
|
|
6151
|
+
mediaOutputs
|
|
6152
|
+
});
|
|
5949
6153
|
break;
|
|
5950
6154
|
}
|
|
5951
6155
|
case "gadget_error": {
|
|
5952
|
-
this.completeGadget(event.invocationId,
|
|
6156
|
+
this.completeGadget(event.invocationId, {
|
|
6157
|
+
error: event.error,
|
|
6158
|
+
executionTimeMs: event.executionTimeMs
|
|
6159
|
+
});
|
|
5953
6160
|
break;
|
|
5954
6161
|
}
|
|
5955
6162
|
case "gadget_skipped": {
|
|
@@ -6776,11 +6983,8 @@ var InputHandler = class {
|
|
|
6776
6983
|
handlePaste(content) {
|
|
6777
6984
|
if (!content) return;
|
|
6778
6985
|
if (content.includes("\n")) {
|
|
6779
|
-
|
|
6780
|
-
this.openEditorForInput(currentValue + content);
|
|
6986
|
+
this.openEditorForInput(this.inputBar.getValue());
|
|
6781
6987
|
} else {
|
|
6782
|
-
const currentValue = this.inputBar.getValue();
|
|
6783
|
-
this.inputBar.setValue(currentValue + content);
|
|
6784
6988
|
this.inputBar.readInput();
|
|
6785
6989
|
}
|
|
6786
6990
|
}
|
|
@@ -8683,8 +8887,15 @@ async function executeAgent(promptArg, options, env, commandName) {
|
|
|
8683
8887
|
prompt = await resolvePrompt(promptArg, env);
|
|
8684
8888
|
}
|
|
8685
8889
|
const registry = new GadgetRegistry();
|
|
8890
|
+
let speechConfig;
|
|
8891
|
+
try {
|
|
8892
|
+
const fullConfig = loadConfig();
|
|
8893
|
+
speechConfig = fullConfig.speech;
|
|
8894
|
+
} catch {
|
|
8895
|
+
}
|
|
8686
8896
|
if (options.builtins !== false) {
|
|
8687
|
-
|
|
8897
|
+
const builtins = getBuiltinGadgets(speechConfig);
|
|
8898
|
+
for (const gadget of builtins) {
|
|
8688
8899
|
if (gadget.name === "AskUser" && (options.builtinInteraction === false || !stdinIsInteractive || !stdoutTTY)) {
|
|
8689
8900
|
continue;
|
|
8690
8901
|
}
|
|
@@ -9005,6 +9216,7 @@ ${ctx.gadgetName} requires interactive approval. Run in a terminal to approve.`
|
|
|
9005
9216
|
if (tui) {
|
|
9006
9217
|
tui.resetAbort();
|
|
9007
9218
|
tui.startNewSession();
|
|
9219
|
+
tui.showUserMessage(userPrompt);
|
|
9008
9220
|
builder.withSignal(tui.getAbortSignal());
|
|
9009
9221
|
}
|
|
9010
9222
|
if (currentAgent) {
|
|
@@ -9070,7 +9282,6 @@ ${ctx.gadgetName} requires interactive approval. Run in a terminal to approve.`
|
|
|
9070
9282
|
if (!currentPrompt) {
|
|
9071
9283
|
tui.setFocusMode("input");
|
|
9072
9284
|
currentPrompt = await tui.waitForPrompt();
|
|
9073
|
-
tui.showUserMessage(currentPrompt);
|
|
9074
9285
|
}
|
|
9075
9286
|
while (true) {
|
|
9076
9287
|
try {
|
|
@@ -9081,7 +9292,6 @@ ${ctx.gadgetName} requires interactive approval. Run in a terminal to approve.`
|
|
|
9081
9292
|
}
|
|
9082
9293
|
}
|
|
9083
9294
|
currentPrompt = await tui.waitForPrompt();
|
|
9084
|
-
tui.showUserMessage(currentPrompt);
|
|
9085
9295
|
}
|
|
9086
9296
|
} else {
|
|
9087
9297
|
try {
|