llmist 1.0.0 → 1.1.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/dist/cli.js CHANGED
@@ -21,8 +21,12 @@ import {
21
21
  init_messages,
22
22
  init_model_shortcuts,
23
23
  init_registry,
24
- resolveModel
25
- } from "./chunk-T24KLXY4.js";
24
+ init_schema_to_json,
25
+ init_schema_validator,
26
+ resolveModel,
27
+ schemaToJSONSchema,
28
+ validateGadgetSchema
29
+ } from "./chunk-VXPZQZF5.js";
26
30
 
27
31
  // src/cli/constants.ts
28
32
  var CLI_NAME = "llmist";
@@ -30,7 +34,8 @@ var CLI_DESCRIPTION = "Command line utilities for llmist agents and direct LLM a
30
34
  var COMMANDS = {
31
35
  complete: "complete",
32
36
  agent: "agent",
33
- models: "models"
37
+ models: "models",
38
+ gadget: "gadget"
34
39
  };
35
40
  var LOG_LEVELS = ["silly", "trace", "debug", "info", "warn", "error", "fatal"];
36
41
  var DEFAULT_MODEL = "openai:gpt-5-nano";
@@ -74,7 +79,7 @@ import { Command, InvalidArgumentError as InvalidArgumentError2 } from "commande
74
79
  // package.json
75
80
  var package_default = {
76
81
  name: "llmist",
77
- version: "0.8.0",
82
+ version: "1.0.0",
78
83
  description: "Universal TypeScript LLM client with streaming-first agent framework. Works with any model - no structured outputs or native tool calling required. Implements its own flexible grammar for function calling.",
79
84
  type: "module",
80
85
  main: "dist/index.cjs",
@@ -2061,8 +2066,439 @@ function resolveInheritance(config, configPath) {
2061
2066
  return resolved;
2062
2067
  }
2063
2068
 
2064
- // src/cli/models-command.ts
2069
+ // src/cli/gadget-command.ts
2070
+ init_schema_to_json();
2071
+ init_schema_validator();
2072
+ import chalk5 from "chalk";
2073
+
2074
+ // src/cli/gadget-prompts.ts
2075
+ init_schema_to_json();
2076
+ import { createInterface as createInterface2 } from "node:readline/promises";
2065
2077
  import chalk4 from "chalk";
2078
+ async function promptForParameters(schema, ctx) {
2079
+ if (!schema) {
2080
+ return {};
2081
+ }
2082
+ const jsonSchema = schemaToJSONSchema(schema, { target: "draft-7" });
2083
+ if (!jsonSchema.properties || Object.keys(jsonSchema.properties).length === 0) {
2084
+ return {};
2085
+ }
2086
+ const rl = createInterface2({ input: ctx.stdin, output: ctx.stdout });
2087
+ const params = {};
2088
+ try {
2089
+ for (const [key, prop] of Object.entries(jsonSchema.properties)) {
2090
+ const value = await promptForField(rl, key, prop, jsonSchema.required ?? []);
2091
+ if (value !== void 0) {
2092
+ params[key] = value;
2093
+ }
2094
+ }
2095
+ } finally {
2096
+ rl.close();
2097
+ }
2098
+ const result = schema.safeParse(params);
2099
+ if (!result.success) {
2100
+ const issues = result.error.issues.map((i) => ` ${i.path.join(".")}: ${i.message}`).join("\n");
2101
+ throw new Error(`Invalid parameters:
2102
+ ${issues}`);
2103
+ }
2104
+ return result.data;
2105
+ }
2106
+ async function promptForField(rl, key, prop, required) {
2107
+ const isRequired = required.includes(key);
2108
+ const typeHint = formatTypeHint(prop);
2109
+ const defaultHint = prop.default !== void 0 ? chalk4.dim(` [default: ${JSON.stringify(prop.default)}]`) : "";
2110
+ const requiredMarker = isRequired ? chalk4.red("*") : "";
2111
+ let prompt = `
2112
+ ${chalk4.cyan.bold(key)}${requiredMarker}`;
2113
+ if (prop.description) {
2114
+ prompt += chalk4.dim(` - ${prop.description}`);
2115
+ }
2116
+ prompt += `
2117
+ ${typeHint}${defaultHint}
2118
+ ${chalk4.green(">")} `;
2119
+ const answer = await rl.question(prompt);
2120
+ const trimmed = answer.trim();
2121
+ if (!trimmed) {
2122
+ if (prop.default !== void 0) {
2123
+ return void 0;
2124
+ }
2125
+ if (!isRequired) {
2126
+ return void 0;
2127
+ }
2128
+ throw new Error(`Parameter '${key}' is required.`);
2129
+ }
2130
+ return parseValue(trimmed, prop, key);
2131
+ }
2132
+ function formatTypeHint(prop) {
2133
+ if (prop.enum) {
2134
+ return chalk4.yellow(`(${prop.enum.join(" | ")})`);
2135
+ }
2136
+ if (prop.type === "array") {
2137
+ const items = prop.items;
2138
+ if (items?.enum) {
2139
+ return chalk4.yellow(`(${items.enum.join(" | ")})[] comma-separated`);
2140
+ }
2141
+ const itemType = items?.type ?? "any";
2142
+ return chalk4.yellow(`(${itemType}[]) comma-separated`);
2143
+ }
2144
+ if (prop.type === "object" && prop.properties) {
2145
+ return chalk4.yellow("(object) enter as JSON");
2146
+ }
2147
+ return chalk4.yellow(`(${prop.type ?? "any"})`);
2148
+ }
2149
+ function parseValue(input, prop, key) {
2150
+ const type = prop.type;
2151
+ if (type === "number" || type === "integer") {
2152
+ const num = Number(input);
2153
+ if (Number.isNaN(num)) {
2154
+ throw new Error(`Invalid number for '${key}': ${input}`);
2155
+ }
2156
+ if (type === "integer" && !Number.isInteger(num)) {
2157
+ throw new Error(`Expected integer for '${key}', got: ${input}`);
2158
+ }
2159
+ return num;
2160
+ }
2161
+ if (type === "boolean") {
2162
+ const lower = input.toLowerCase();
2163
+ if (["true", "yes", "1", "y"].includes(lower)) return true;
2164
+ if (["false", "no", "0", "n"].includes(lower)) return false;
2165
+ throw new Error(`Invalid boolean for '${key}': ${input} (use true/false, yes/no, 1/0)`);
2166
+ }
2167
+ if (type === "array") {
2168
+ const items = input.split(",").map((s) => s.trim()).filter(Boolean);
2169
+ const itemType = prop.items?.type;
2170
+ if (itemType === "number" || itemType === "integer") {
2171
+ return items.map((item) => {
2172
+ const num = Number(item);
2173
+ if (Number.isNaN(num)) throw new Error(`Invalid number in '${key}' array: ${item}`);
2174
+ return num;
2175
+ });
2176
+ }
2177
+ if (itemType === "boolean") {
2178
+ return items.map((item) => {
2179
+ const lower = item.toLowerCase();
2180
+ if (["true", "yes", "1", "y"].includes(lower)) return true;
2181
+ if (["false", "no", "0", "n"].includes(lower)) return false;
2182
+ throw new Error(`Invalid boolean in '${key}' array: ${item}`);
2183
+ });
2184
+ }
2185
+ return items;
2186
+ }
2187
+ if (type === "object") {
2188
+ try {
2189
+ return JSON.parse(input);
2190
+ } catch {
2191
+ throw new Error(`Invalid JSON for '${key}': ${input}`);
2192
+ }
2193
+ }
2194
+ return input;
2195
+ }
2196
+ async function readStdinJson(stdin) {
2197
+ const chunks = [];
2198
+ for await (const chunk of stdin) {
2199
+ if (typeof chunk === "string") {
2200
+ chunks.push(chunk);
2201
+ } else {
2202
+ chunks.push(chunk.toString("utf8"));
2203
+ }
2204
+ }
2205
+ const content = chunks.join("").trim();
2206
+ if (!content) {
2207
+ return {};
2208
+ }
2209
+ try {
2210
+ const parsed = JSON.parse(content);
2211
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
2212
+ throw new Error("Stdin must contain a JSON object, not an array or primitive.");
2213
+ }
2214
+ return parsed;
2215
+ } catch (error) {
2216
+ if (error instanceof SyntaxError) {
2217
+ throw new Error(`Invalid JSON from stdin: ${error.message}`);
2218
+ }
2219
+ throw error;
2220
+ }
2221
+ }
2222
+
2223
+ // src/cli/gadget-command.ts
2224
+ async function selectGadget(file, nameOption, cwd) {
2225
+ const gadgets = await loadGadgets([file], cwd);
2226
+ if (gadgets.length === 0) {
2227
+ throw new Error(
2228
+ `No gadgets found in '${file}'.
2229
+ Ensure the file exports a Gadget class or instance.`
2230
+ );
2231
+ }
2232
+ if (gadgets.length === 1) {
2233
+ const gadget = gadgets[0];
2234
+ const name = gadget.name ?? gadget.constructor.name;
2235
+ return { gadget, name };
2236
+ }
2237
+ const names = gadgets.map((g) => g.name ?? g.constructor.name);
2238
+ if (!nameOption) {
2239
+ throw new Error(
2240
+ `File '${file}' exports ${gadgets.length} gadgets.
2241
+ Use --name to select one:
2242
+ ` + names.map((n) => ` - ${n}`).join("\n")
2243
+ );
2244
+ }
2245
+ const found = gadgets.find((g) => (g.name ?? g.constructor.name) === nameOption);
2246
+ if (!found) {
2247
+ throw new Error(
2248
+ `Gadget '${nameOption}' not found in '${file}'.
2249
+ Available gadgets:
2250
+ ` + names.map((n) => ` - ${n}`).join("\n")
2251
+ );
2252
+ }
2253
+ return { gadget: found, name: nameOption };
2254
+ }
2255
+ async function executeGadgetRun(file, options, env) {
2256
+ const cwd = process.cwd();
2257
+ const { gadget, name } = await selectGadget(file, options.name, cwd);
2258
+ env.stderr.write(chalk5.cyan.bold(`
2259
+ \u{1F527} Running gadget: ${name}
2260
+ `));
2261
+ let params;
2262
+ if (env.isTTY) {
2263
+ params = await promptForParameters(gadget.parameterSchema, {
2264
+ stdin: env.stdin,
2265
+ stdout: env.stderr
2266
+ // Prompts go to stderr to keep stdout clean
2267
+ });
2268
+ } else {
2269
+ env.stderr.write(chalk5.dim("Reading parameters from stdin...\n"));
2270
+ const stdinParams = await readStdinJson(env.stdin);
2271
+ if (gadget.parameterSchema) {
2272
+ const result2 = gadget.parameterSchema.safeParse(stdinParams);
2273
+ if (!result2.success) {
2274
+ const issues = result2.error.issues.map((i) => ` ${i.path.join(".")}: ${i.message}`).join("\n");
2275
+ throw new Error(`Invalid parameters:
2276
+ ${issues}`);
2277
+ }
2278
+ params = result2.data;
2279
+ } else {
2280
+ params = stdinParams;
2281
+ }
2282
+ }
2283
+ env.stderr.write(chalk5.dim("\nExecuting...\n"));
2284
+ const startTime = Date.now();
2285
+ let result;
2286
+ try {
2287
+ if (gadget.timeoutMs && gadget.timeoutMs > 0) {
2288
+ result = await Promise.race([
2289
+ Promise.resolve(gadget.execute(params)),
2290
+ new Promise(
2291
+ (_, reject) => setTimeout(
2292
+ () => reject(new Error(`Gadget timed out after ${gadget.timeoutMs}ms`)),
2293
+ gadget.timeoutMs
2294
+ )
2295
+ )
2296
+ ]);
2297
+ } else {
2298
+ result = await Promise.resolve(gadget.execute(params));
2299
+ }
2300
+ } catch (error) {
2301
+ const message = error instanceof Error ? error.message : String(error);
2302
+ throw new Error(`Execution failed: ${message}`);
2303
+ }
2304
+ const elapsed = Date.now() - startTime;
2305
+ env.stderr.write(chalk5.green(`
2306
+ \u2713 Completed in ${elapsed}ms
2307
+
2308
+ `));
2309
+ formatOutput(result, options, env.stdout);
2310
+ }
2311
+ function formatOutput(result, options, stdout) {
2312
+ if (options.raw) {
2313
+ stdout.write(result);
2314
+ if (!result.endsWith("\n")) stdout.write("\n");
2315
+ return;
2316
+ }
2317
+ if (options.json || looksLikeJson(result)) {
2318
+ try {
2319
+ const parsed = JSON.parse(result);
2320
+ stdout.write(JSON.stringify(parsed, null, 2) + "\n");
2321
+ return;
2322
+ } catch {
2323
+ }
2324
+ }
2325
+ stdout.write(result);
2326
+ if (!result.endsWith("\n")) stdout.write("\n");
2327
+ }
2328
+ function looksLikeJson(str) {
2329
+ const trimmed = str.trim();
2330
+ return trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]");
2331
+ }
2332
+ async function executeGadgetInfo(file, options, env) {
2333
+ const cwd = process.cwd();
2334
+ const { gadget, name } = await selectGadget(file, options.name, cwd);
2335
+ if (options.json) {
2336
+ const info = buildGadgetInfo(gadget, name);
2337
+ env.stdout.write(JSON.stringify(info, null, 2) + "\n");
2338
+ return;
2339
+ }
2340
+ env.stdout.write("\n");
2341
+ env.stdout.write(chalk5.cyan.bold(`${name}
2342
+ `));
2343
+ env.stdout.write(chalk5.cyan("\u2550".repeat(name.length)) + "\n\n");
2344
+ env.stdout.write(chalk5.bold("Description:\n"));
2345
+ env.stdout.write(` ${gadget.description}
2346
+
2347
+ `);
2348
+ if (gadget.parameterSchema) {
2349
+ env.stdout.write(chalk5.bold("Parameters:\n"));
2350
+ const jsonSchema = schemaToJSONSchema(gadget.parameterSchema, { target: "draft-7" });
2351
+ env.stdout.write(formatSchemaAsText(jsonSchema, " ") + "\n\n");
2352
+ } else {
2353
+ env.stdout.write(chalk5.dim("No parameters required.\n\n"));
2354
+ }
2355
+ if (gadget.timeoutMs) {
2356
+ env.stdout.write(chalk5.bold("Timeout:\n"));
2357
+ env.stdout.write(` ${gadget.timeoutMs}ms
2358
+
2359
+ `);
2360
+ }
2361
+ if (gadget.examples && gadget.examples.length > 0) {
2362
+ env.stdout.write(chalk5.bold("Examples:\n"));
2363
+ for (const example of gadget.examples) {
2364
+ if (example.comment) {
2365
+ env.stdout.write(chalk5.dim(` # ${example.comment}
2366
+ `));
2367
+ }
2368
+ env.stdout.write(` Input: ${chalk5.cyan(JSON.stringify(example.params))}
2369
+ `);
2370
+ if (example.output !== void 0) {
2371
+ env.stdout.write(` Output: ${chalk5.green(example.output)}
2372
+ `);
2373
+ }
2374
+ env.stdout.write("\n");
2375
+ }
2376
+ }
2377
+ }
2378
+ function buildGadgetInfo(gadget, name) {
2379
+ const info = {
2380
+ name,
2381
+ description: gadget.description
2382
+ };
2383
+ if (gadget.parameterSchema) {
2384
+ info.schema = schemaToJSONSchema(gadget.parameterSchema, { target: "draft-7" });
2385
+ }
2386
+ if (gadget.timeoutMs) {
2387
+ info.timeoutMs = gadget.timeoutMs;
2388
+ }
2389
+ if (gadget.examples && gadget.examples.length > 0) {
2390
+ info.examples = gadget.examples;
2391
+ }
2392
+ return info;
2393
+ }
2394
+ function formatSchemaAsText(schema, indent = "") {
2395
+ const lines = [];
2396
+ const properties = schema.properties || {};
2397
+ const required = schema.required || [];
2398
+ for (const [key, prop] of Object.entries(properties)) {
2399
+ const type = prop.type;
2400
+ const description = prop.description;
2401
+ const isRequired = required.includes(key);
2402
+ const enumValues = prop.enum;
2403
+ const defaultValue = prop.default;
2404
+ let line = `${indent}${chalk5.cyan(key)}`;
2405
+ if (isRequired) {
2406
+ line += chalk5.red("*");
2407
+ }
2408
+ if (type === "array") {
2409
+ const items = prop.items;
2410
+ const itemType = items?.type || "any";
2411
+ line += chalk5.dim(` (${itemType}[])`);
2412
+ } else if (type === "object" && prop.properties) {
2413
+ line += chalk5.dim(" (object)");
2414
+ } else {
2415
+ line += chalk5.dim(` (${type})`);
2416
+ }
2417
+ if (defaultValue !== void 0) {
2418
+ line += chalk5.dim(` [default: ${JSON.stringify(defaultValue)}]`);
2419
+ }
2420
+ if (description) {
2421
+ line += `: ${description}`;
2422
+ }
2423
+ if (enumValues) {
2424
+ line += chalk5.yellow(` - one of: ${enumValues.join(", ")}`);
2425
+ }
2426
+ lines.push(line);
2427
+ if (type === "object" && prop.properties) {
2428
+ lines.push(formatSchemaAsText(prop, indent + " "));
2429
+ }
2430
+ }
2431
+ return lines.join("\n");
2432
+ }
2433
+ async function executeGadgetValidate(file, env) {
2434
+ const cwd = process.cwd();
2435
+ try {
2436
+ const gadgets = await loadGadgets([file], cwd);
2437
+ if (gadgets.length === 0) {
2438
+ throw new Error(
2439
+ "No gadgets exported from file.\nA valid gadget must have:\n - execute() method\n - description property\n - parameterSchema (optional)"
2440
+ );
2441
+ }
2442
+ const issues = [];
2443
+ for (const gadget of gadgets) {
2444
+ const name = gadget.name ?? gadget.constructor.name;
2445
+ if (!gadget.description) {
2446
+ issues.push(`${name}: Missing 'description' property.`);
2447
+ }
2448
+ if (gadget.parameterSchema) {
2449
+ try {
2450
+ validateGadgetSchema(gadget.parameterSchema, name);
2451
+ } catch (schemaError) {
2452
+ const message = schemaError instanceof Error ? schemaError.message : String(schemaError);
2453
+ issues.push(`${name}: ${message}`);
2454
+ }
2455
+ }
2456
+ if (typeof gadget.execute !== "function") {
2457
+ issues.push(`${name}: Missing 'execute()' method.`);
2458
+ }
2459
+ }
2460
+ if (issues.length > 0) {
2461
+ throw new Error(`Validation issues:
2462
+ ${issues.map((i) => ` - ${i}`).join("\n")}`);
2463
+ }
2464
+ env.stdout.write(chalk5.green.bold("\n\u2713 Valid\n\n"));
2465
+ env.stdout.write(chalk5.bold("Gadgets found:\n"));
2466
+ for (const gadget of gadgets) {
2467
+ const name = gadget.name ?? gadget.constructor.name;
2468
+ const schemaInfo = gadget.parameterSchema ? chalk5.cyan("(with schema)") : chalk5.dim("(no schema)");
2469
+ env.stdout.write(` ${chalk5.bold(name)} ${schemaInfo}
2470
+ `);
2471
+ env.stdout.write(chalk5.dim(` ${gadget.description}
2472
+ `));
2473
+ }
2474
+ env.stdout.write("\n");
2475
+ } catch (error) {
2476
+ const message = error instanceof Error ? error.message : String(error);
2477
+ env.stdout.write(chalk5.red.bold(`
2478
+ \u2717 Invalid
2479
+
2480
+ `));
2481
+ env.stdout.write(`${message}
2482
+
2483
+ `);
2484
+ env.setExitCode(1);
2485
+ }
2486
+ }
2487
+ function registerGadgetCommand(program, env) {
2488
+ const gadgetCmd = program.command("gadget").description("Test and inspect gadgets outside the agent loop.");
2489
+ gadgetCmd.command("run <file>").description("Execute a gadget with interactive prompts or stdin JSON.").option("--name <gadget>", "Select gadget by name (required if file exports multiple)").option("--json", "Format output as pretty-printed JSON").option("--raw", "Output result as raw string without formatting").action(
2490
+ (file, options) => executeAction(() => executeGadgetRun(file, options, env), env)
2491
+ );
2492
+ gadgetCmd.command("info <file>").description("Display gadget description, schema, and examples.").option("--name <gadget>", "Select gadget by name (required if file exports multiple)").option("--json", "Output as JSON instead of formatted text").action(
2493
+ (file, options) => executeAction(() => executeGadgetInfo(file, options, env), env)
2494
+ );
2495
+ gadgetCmd.command("validate <file>").description("Check if file exports valid gadget(s).").action(
2496
+ (file) => executeAction(() => executeGadgetValidate(file, env), env)
2497
+ );
2498
+ }
2499
+
2500
+ // src/cli/models-command.ts
2501
+ import chalk6 from "chalk";
2066
2502
  init_model_shortcuts();
2067
2503
  async function handleModelsCommand(options, env) {
2068
2504
  const client = env.createClient();
@@ -2082,13 +2518,13 @@ function renderTable(models, verbose, stream) {
2082
2518
  }
2083
2519
  grouped.get(provider).push(model);
2084
2520
  }
2085
- stream.write(chalk4.bold.cyan("\nAvailable Models\n"));
2086
- stream.write(chalk4.cyan("=".repeat(80)) + "\n\n");
2521
+ stream.write(chalk6.bold.cyan("\nAvailable Models\n"));
2522
+ stream.write(chalk6.cyan("=".repeat(80)) + "\n\n");
2087
2523
  const providers = Array.from(grouped.keys()).sort();
2088
2524
  for (const provider of providers) {
2089
2525
  const providerModels = grouped.get(provider);
2090
2526
  const providerName = provider.charAt(0).toUpperCase() + provider.slice(1);
2091
- stream.write(chalk4.bold.yellow(`${providerName} Models
2527
+ stream.write(chalk6.bold.yellow(`${providerName} Models
2092
2528
  `));
2093
2529
  if (verbose) {
2094
2530
  renderVerboseTable(providerModels, stream);
@@ -2097,11 +2533,11 @@ function renderTable(models, verbose, stream) {
2097
2533
  }
2098
2534
  stream.write("\n");
2099
2535
  }
2100
- stream.write(chalk4.bold.magenta("Model Shortcuts\n"));
2101
- stream.write(chalk4.dim("\u2500".repeat(80)) + "\n");
2536
+ stream.write(chalk6.bold.magenta("Model Shortcuts\n"));
2537
+ stream.write(chalk6.dim("\u2500".repeat(80)) + "\n");
2102
2538
  const shortcuts = Object.entries(MODEL_ALIASES).sort((a, b) => a[0].localeCompare(b[0]));
2103
2539
  for (const [shortcut, fullName] of shortcuts) {
2104
- stream.write(chalk4.cyan(` ${shortcut.padEnd(15)}`) + chalk4.dim(" \u2192 ") + chalk4.white(fullName) + "\n");
2540
+ stream.write(chalk6.cyan(` ${shortcut.padEnd(15)}`) + chalk6.dim(" \u2192 ") + chalk6.white(fullName) + "\n");
2105
2541
  }
2106
2542
  stream.write("\n");
2107
2543
  }
@@ -2111,45 +2547,45 @@ function renderCompactTable(models, stream) {
2111
2547
  const contextWidth = 13;
2112
2548
  const inputWidth = 10;
2113
2549
  const outputWidth = 10;
2114
- stream.write(chalk4.dim("\u2500".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + "\n");
2550
+ stream.write(chalk6.dim("\u2500".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + "\n");
2115
2551
  stream.write(
2116
- chalk4.bold(
2552
+ chalk6.bold(
2117
2553
  "Model ID".padEnd(idWidth) + " " + "Display Name".padEnd(nameWidth) + " " + "Context".padEnd(contextWidth) + " " + "Input".padEnd(inputWidth) + " " + "Output".padEnd(outputWidth)
2118
2554
  ) + "\n"
2119
2555
  );
2120
- stream.write(chalk4.dim("\u2500".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + "\n");
2556
+ stream.write(chalk6.dim("\u2500".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + "\n");
2121
2557
  for (const model of models) {
2122
2558
  const contextFormatted = formatTokens2(model.contextWindow);
2123
2559
  const inputPrice = `$${model.pricing.input.toFixed(2)}`;
2124
2560
  const outputPrice = `$${model.pricing.output.toFixed(2)}`;
2125
2561
  stream.write(
2126
- chalk4.green(model.modelId.padEnd(idWidth)) + " " + chalk4.white(model.displayName.padEnd(nameWidth)) + " " + chalk4.yellow(contextFormatted.padEnd(contextWidth)) + " " + chalk4.cyan(inputPrice.padEnd(inputWidth)) + " " + chalk4.cyan(outputPrice.padEnd(outputWidth)) + "\n"
2562
+ chalk6.green(model.modelId.padEnd(idWidth)) + " " + chalk6.white(model.displayName.padEnd(nameWidth)) + " " + chalk6.yellow(contextFormatted.padEnd(contextWidth)) + " " + chalk6.cyan(inputPrice.padEnd(inputWidth)) + " " + chalk6.cyan(outputPrice.padEnd(outputWidth)) + "\n"
2127
2563
  );
2128
2564
  }
2129
- stream.write(chalk4.dim("\u2500".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + "\n");
2130
- stream.write(chalk4.dim(` * Prices are per 1M tokens
2565
+ stream.write(chalk6.dim("\u2500".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + "\n");
2566
+ stream.write(chalk6.dim(` * Prices are per 1M tokens
2131
2567
  `));
2132
2568
  }
2133
2569
  function renderVerboseTable(models, stream) {
2134
2570
  for (const model of models) {
2135
- stream.write(chalk4.bold.green(`
2571
+ stream.write(chalk6.bold.green(`
2136
2572
  ${model.modelId}
2137
2573
  `));
2138
- stream.write(chalk4.dim(" " + "\u2500".repeat(60)) + "\n");
2139
- stream.write(` ${chalk4.dim("Name:")} ${chalk4.white(model.displayName)}
2574
+ stream.write(chalk6.dim(" " + "\u2500".repeat(60)) + "\n");
2575
+ stream.write(` ${chalk6.dim("Name:")} ${chalk6.white(model.displayName)}
2140
2576
  `);
2141
- stream.write(` ${chalk4.dim("Context:")} ${chalk4.yellow(formatTokens2(model.contextWindow))}
2577
+ stream.write(` ${chalk6.dim("Context:")} ${chalk6.yellow(formatTokens2(model.contextWindow))}
2142
2578
  `);
2143
- stream.write(` ${chalk4.dim("Max Output:")} ${chalk4.yellow(formatTokens2(model.maxOutputTokens))}
2579
+ stream.write(` ${chalk6.dim("Max Output:")} ${chalk6.yellow(formatTokens2(model.maxOutputTokens))}
2144
2580
  `);
2145
- stream.write(` ${chalk4.dim("Pricing:")} ${chalk4.cyan(`$${model.pricing.input.toFixed(2)} input`)} ${chalk4.dim("/")} ${chalk4.cyan(`$${model.pricing.output.toFixed(2)} output`)} ${chalk4.dim("(per 1M tokens)")}
2581
+ stream.write(` ${chalk6.dim("Pricing:")} ${chalk6.cyan(`$${model.pricing.input.toFixed(2)} input`)} ${chalk6.dim("/")} ${chalk6.cyan(`$${model.pricing.output.toFixed(2)} output`)} ${chalk6.dim("(per 1M tokens)")}
2146
2582
  `);
2147
2583
  if (model.pricing.cachedInput !== void 0) {
2148
- stream.write(` ${chalk4.dim("Cached Input:")} ${chalk4.cyan(`$${model.pricing.cachedInput.toFixed(2)} per 1M tokens`)}
2584
+ stream.write(` ${chalk6.dim("Cached Input:")} ${chalk6.cyan(`$${model.pricing.cachedInput.toFixed(2)} per 1M tokens`)}
2149
2585
  `);
2150
2586
  }
2151
2587
  if (model.knowledgeCutoff) {
2152
- stream.write(` ${chalk4.dim("Knowledge:")} ${model.knowledgeCutoff}
2588
+ stream.write(` ${chalk6.dim("Knowledge:")} ${model.knowledgeCutoff}
2153
2589
  `);
2154
2590
  }
2155
2591
  const features = [];
@@ -2160,20 +2596,20 @@ function renderVerboseTable(models, stream) {
2160
2596
  if (model.features.structuredOutputs) features.push("structured-outputs");
2161
2597
  if (model.features.fineTuning) features.push("fine-tuning");
2162
2598
  if (features.length > 0) {
2163
- stream.write(` ${chalk4.dim("Features:")} ${chalk4.blue(features.join(", "))}
2599
+ stream.write(` ${chalk6.dim("Features:")} ${chalk6.blue(features.join(", "))}
2164
2600
  `);
2165
2601
  }
2166
2602
  if (model.metadata) {
2167
2603
  if (model.metadata.family) {
2168
- stream.write(` ${chalk4.dim("Family:")} ${model.metadata.family}
2604
+ stream.write(` ${chalk6.dim("Family:")} ${model.metadata.family}
2169
2605
  `);
2170
2606
  }
2171
2607
  if (model.metadata.releaseDate) {
2172
- stream.write(` ${chalk4.dim("Released:")} ${model.metadata.releaseDate}
2608
+ stream.write(` ${chalk6.dim("Released:")} ${model.metadata.releaseDate}
2173
2609
  `);
2174
2610
  }
2175
2611
  if (model.metadata.notes) {
2176
- stream.write(` ${chalk4.dim("Notes:")} ${chalk4.italic(model.metadata.notes)}
2612
+ stream.write(` ${chalk6.dim("Notes:")} ${chalk6.italic(model.metadata.notes)}
2177
2613
  `);
2178
2614
  }
2179
2615
  }
@@ -2225,7 +2661,7 @@ function registerModelsCommand(program, env) {
2225
2661
  init_client();
2226
2662
  init_logger();
2227
2663
  import readline from "node:readline";
2228
- import chalk5 from "chalk";
2664
+ import chalk7 from "chalk";
2229
2665
  var LOG_LEVEL_MAP = {
2230
2666
  silly: 0,
2231
2667
  trace: 1,
@@ -2272,14 +2708,14 @@ function createPromptFunction(stdin, stdout) {
2272
2708
  output: stdout
2273
2709
  });
2274
2710
  stdout.write("\n");
2275
- stdout.write(`${chalk5.cyan("\u2500".repeat(60))}
2711
+ stdout.write(`${chalk7.cyan("\u2500".repeat(60))}
2276
2712
  `);
2277
- stdout.write(chalk5.cyan.bold("\u{1F916} Agent asks:\n"));
2713
+ stdout.write(chalk7.cyan.bold("\u{1F916} Agent asks:\n"));
2278
2714
  stdout.write(`${question}
2279
2715
  `);
2280
- stdout.write(`${chalk5.cyan("\u2500".repeat(60))}
2716
+ stdout.write(`${chalk7.cyan("\u2500".repeat(60))}
2281
2717
  `);
2282
- rl.question(chalk5.green.bold("You: "), (answer) => {
2718
+ rl.question(chalk7.green.bold("You: "), (answer) => {
2283
2719
  rl.close();
2284
2720
  resolve(answer);
2285
2721
  });
@@ -2369,6 +2805,7 @@ function createProgram(env, config) {
2369
2805
  registerCompleteCommand(program, env, config?.complete);
2370
2806
  registerAgentCommand(program, env, config?.agent);
2371
2807
  registerModelsCommand(program, env);
2808
+ registerGadgetCommand(program, env);
2372
2809
  if (config) {
2373
2810
  const customNames = getCustomCommandNames(config);
2374
2811
  for (const name of customNames) {