@llmist/cli 9.6.0 → 10.0.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 +435 -149
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,8 @@ var COMMANDS = {
|
|
|
11
11
|
image: "image",
|
|
12
12
|
speech: "speech",
|
|
13
13
|
vision: "vision",
|
|
14
|
-
init: "init"
|
|
14
|
+
init: "init",
|
|
15
|
+
config: "config"
|
|
15
16
|
};
|
|
16
17
|
var LOG_LEVELS = ["silly", "trace", "debug", "info", "warn", "error", "fatal"];
|
|
17
18
|
var DEFAULT_MODEL = "openai:gpt-5-nano";
|
|
@@ -23,9 +24,7 @@ var OPTION_FLAGS = {
|
|
|
23
24
|
maxIterations: "-i, --max-iterations <count>",
|
|
24
25
|
gadgetModule: "-g, --gadget <module>",
|
|
25
26
|
logLevel: "--log-level <level>",
|
|
26
|
-
|
|
27
|
-
logReset: "--log-reset",
|
|
28
|
-
logLlmRequests: "--log-llm-requests [dir]",
|
|
27
|
+
logLlmRequests: "--log-llm-requests",
|
|
29
28
|
noBuiltins: "--no-builtins",
|
|
30
29
|
noBuiltinInteraction: "--no-builtin-interaction",
|
|
31
30
|
quiet: "-q, --quiet",
|
|
@@ -51,9 +50,7 @@ var OPTION_DESCRIPTIONS = {
|
|
|
51
50
|
maxIterations: "Maximum number of agent loop iterations before exiting.",
|
|
52
51
|
gadgetModule: "Path or module specifier for a gadget export. Repeat to register multiple gadgets.",
|
|
53
52
|
logLevel: "Log level: silly, trace, debug, info, warn, error, fatal.",
|
|
54
|
-
|
|
55
|
-
logReset: "Reset (truncate) the log file at session start instead of appending.",
|
|
56
|
-
logLlmRequests: "Save LLM requests/responses to session directories. Optional dir, defaults to ~/.llmist/logs/requests/",
|
|
53
|
+
logLlmRequests: "Save LLM requests/responses to the session log directory.",
|
|
57
54
|
noBuiltins: "Disable built-in gadgets (AskUser, TellUser).",
|
|
58
55
|
noBuiltinInteraction: "Disable interactive gadgets (AskUser) while keeping TellUser.",
|
|
59
56
|
quiet: "Suppress all output except content (text and TellUser messages).",
|
|
@@ -79,7 +76,7 @@ import { Command, InvalidArgumentError as InvalidArgumentError2 } from "commande
|
|
|
79
76
|
// package.json
|
|
80
77
|
var package_default = {
|
|
81
78
|
name: "@llmist/cli",
|
|
82
|
-
version: "
|
|
79
|
+
version: "10.0.0",
|
|
83
80
|
description: "CLI for llmist - run LLM agents from the command line",
|
|
84
81
|
type: "module",
|
|
85
82
|
main: "dist/cli.js",
|
|
@@ -412,9 +409,9 @@ function spawn(argv, options = {}) {
|
|
|
412
409
|
options.stderr === "pipe" ? "pipe" : options.stderr ?? "ignore"
|
|
413
410
|
]
|
|
414
411
|
});
|
|
415
|
-
const exited = new Promise((
|
|
412
|
+
const exited = new Promise((resolve3, reject) => {
|
|
416
413
|
proc.on("exit", (code) => {
|
|
417
|
-
|
|
414
|
+
resolve3(code ?? 1);
|
|
418
415
|
});
|
|
419
416
|
proc.on("error", (err) => {
|
|
420
417
|
reject(err);
|
|
@@ -1262,6 +1259,15 @@ async function loadExternalGadgets(specifier, forceInstall = false) {
|
|
|
1262
1259
|
return gadgets;
|
|
1263
1260
|
}
|
|
1264
1261
|
|
|
1262
|
+
// src/paths.ts
|
|
1263
|
+
import { homedir } from "os";
|
|
1264
|
+
function expandTildePath(path6) {
|
|
1265
|
+
if (!path6.startsWith("~")) {
|
|
1266
|
+
return path6;
|
|
1267
|
+
}
|
|
1268
|
+
return path6.replace(/^~/, homedir());
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1265
1271
|
// src/gadgets.ts
|
|
1266
1272
|
var PATH_PREFIXES = [".", "/", "~"];
|
|
1267
1273
|
var BUILTIN_PREFIX = "builtin:";
|
|
@@ -1289,16 +1295,6 @@ function isGadgetConstructor(value) {
|
|
|
1289
1295
|
}
|
|
1290
1296
|
return isGadgetLike(prototype);
|
|
1291
1297
|
}
|
|
1292
|
-
function expandHomePath(input) {
|
|
1293
|
-
if (!input.startsWith("~")) {
|
|
1294
|
-
return input;
|
|
1295
|
-
}
|
|
1296
|
-
const home = process.env.HOME;
|
|
1297
|
-
if (!home) {
|
|
1298
|
-
return input;
|
|
1299
|
-
}
|
|
1300
|
-
return path5.join(home, input.slice(1));
|
|
1301
|
-
}
|
|
1302
1298
|
function parseLocalSpecifier(specifier) {
|
|
1303
1299
|
const match = specifier.match(/^(.+):([A-Z][a-zA-Z0-9]*)$/);
|
|
1304
1300
|
if (match) {
|
|
@@ -1330,7 +1326,7 @@ function resolveGadgetSpecifier(specifier, cwd) {
|
|
|
1330
1326
|
if (!isFileLikeSpecifier(specifier)) {
|
|
1331
1327
|
return specifier;
|
|
1332
1328
|
}
|
|
1333
|
-
const expanded =
|
|
1329
|
+
const expanded = expandTildePath(specifier);
|
|
1334
1330
|
const resolvedPath = path5.resolve(cwd, expanded);
|
|
1335
1331
|
if (!fs6.existsSync(resolvedPath)) {
|
|
1336
1332
|
throw new Error(`Gadget module not found at ${resolvedPath}`);
|
|
@@ -1429,19 +1425,8 @@ async function loadGadgets(specifiers, cwd, importer = (specifier) => import(spe
|
|
|
1429
1425
|
|
|
1430
1426
|
// src/llm-logging.ts
|
|
1431
1427
|
import { mkdir, writeFile as writeFile2 } from "fs/promises";
|
|
1432
|
-
import { homedir } from "os";
|
|
1433
1428
|
import { join } from "path";
|
|
1434
1429
|
import { extractMessageText } from "llmist";
|
|
1435
|
-
var DEFAULT_LLM_LOG_DIR = join(homedir(), ".llmist", "logs");
|
|
1436
|
-
function resolveLogDir(option, subdir) {
|
|
1437
|
-
if (option === true) {
|
|
1438
|
-
return join(DEFAULT_LLM_LOG_DIR, subdir);
|
|
1439
|
-
}
|
|
1440
|
-
if (typeof option === "string") {
|
|
1441
|
-
return option;
|
|
1442
|
-
}
|
|
1443
|
-
return void 0;
|
|
1444
|
-
}
|
|
1445
1430
|
function formatLlmRequest(messages) {
|
|
1446
1431
|
const lines = [];
|
|
1447
1432
|
for (const msg of messages) {
|
|
@@ -1455,27 +1440,6 @@ async function writeLogFile(dir, filename, content) {
|
|
|
1455
1440
|
await mkdir(dir, { recursive: true });
|
|
1456
1441
|
await writeFile2(join(dir, filename), content, "utf-8");
|
|
1457
1442
|
}
|
|
1458
|
-
function formatSessionTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
1459
|
-
const pad = (n) => n.toString().padStart(2, "0");
|
|
1460
|
-
const year = date.getFullYear();
|
|
1461
|
-
const month = pad(date.getMonth() + 1);
|
|
1462
|
-
const day = pad(date.getDate());
|
|
1463
|
-
const hours = pad(date.getHours());
|
|
1464
|
-
const minutes = pad(date.getMinutes());
|
|
1465
|
-
const seconds = pad(date.getSeconds());
|
|
1466
|
-
return `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`;
|
|
1467
|
-
}
|
|
1468
|
-
async function createSessionDir(baseDir) {
|
|
1469
|
-
const timestamp = formatSessionTimestamp();
|
|
1470
|
-
const sessionDir = join(baseDir, timestamp);
|
|
1471
|
-
try {
|
|
1472
|
-
await mkdir(sessionDir, { recursive: true });
|
|
1473
|
-
return sessionDir;
|
|
1474
|
-
} catch (error) {
|
|
1475
|
-
console.warn(`[llmist] Failed to create log session directory: ${sessionDir}`, error);
|
|
1476
|
-
return void 0;
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
1443
|
function formatCallNumber(n) {
|
|
1480
1444
|
return n.toString().padStart(4, "0");
|
|
1481
1445
|
}
|
|
@@ -3274,11 +3238,11 @@ var InputHandler = class {
|
|
|
3274
3238
|
* @returns Promise that resolves with user's response
|
|
3275
3239
|
*/
|
|
3276
3240
|
async waitForInput(question, gadgetName) {
|
|
3277
|
-
return new Promise((
|
|
3241
|
+
return new Promise((resolve3, reject) => {
|
|
3278
3242
|
this.pendingInput = {
|
|
3279
3243
|
question,
|
|
3280
3244
|
gadgetName,
|
|
3281
|
-
resolve:
|
|
3245
|
+
resolve: resolve3,
|
|
3282
3246
|
reject
|
|
3283
3247
|
};
|
|
3284
3248
|
this.appendQuestionToBody(question);
|
|
@@ -3294,11 +3258,11 @@ var InputHandler = class {
|
|
|
3294
3258
|
* @returns Promise that resolves with user's prompt
|
|
3295
3259
|
*/
|
|
3296
3260
|
async waitForPrompt() {
|
|
3297
|
-
return new Promise((
|
|
3261
|
+
return new Promise((resolve3, reject) => {
|
|
3298
3262
|
this.pendingInput = {
|
|
3299
3263
|
question: "",
|
|
3300
3264
|
gadgetName: "prompt",
|
|
3301
|
-
resolve:
|
|
3265
|
+
resolve: resolve3,
|
|
3302
3266
|
reject
|
|
3303
3267
|
};
|
|
3304
3268
|
this.setPendingPrompt();
|
|
@@ -3370,10 +3334,10 @@ var InputHandler = class {
|
|
|
3370
3334
|
return;
|
|
3371
3335
|
}
|
|
3372
3336
|
if (this.pendingInput) {
|
|
3373
|
-
const { resolve:
|
|
3337
|
+
const { resolve: resolve3 } = this.pendingInput;
|
|
3374
3338
|
this.pendingInput = null;
|
|
3375
3339
|
this.setIdle();
|
|
3376
|
-
|
|
3340
|
+
resolve3(value);
|
|
3377
3341
|
} else if (this.midSessionHandler) {
|
|
3378
3342
|
this.midSessionHandler(value);
|
|
3379
3343
|
this.setIdle();
|
|
@@ -4569,7 +4533,7 @@ import { Box as Box3 } from "@unblessed/node";
|
|
|
4569
4533
|
var MAX_PREVIEW_LINES = 10;
|
|
4570
4534
|
var MAX_PARAM_VALUE_LENGTH = 60;
|
|
4571
4535
|
function showApprovalDialog(screen, context) {
|
|
4572
|
-
return new Promise((
|
|
4536
|
+
return new Promise((resolve3) => {
|
|
4573
4537
|
const content = buildDialogContent(context);
|
|
4574
4538
|
const dialog = new Box3({
|
|
4575
4539
|
parent: screen,
|
|
@@ -4624,7 +4588,7 @@ function showApprovalDialog(screen, context) {
|
|
|
4624
4588
|
if (response) {
|
|
4625
4589
|
dialog.destroy();
|
|
4626
4590
|
screen.render();
|
|
4627
|
-
|
|
4591
|
+
resolve3(response);
|
|
4628
4592
|
}
|
|
4629
4593
|
};
|
|
4630
4594
|
dialog.on("keypress", handleKey);
|
|
@@ -4694,7 +4658,7 @@ var WHITE = "\x1B[37m";
|
|
|
4694
4658
|
function showRawViewer(options) {
|
|
4695
4659
|
let closeCallback = () => {
|
|
4696
4660
|
};
|
|
4697
|
-
const closed = new Promise((
|
|
4661
|
+
const closed = new Promise((resolve3) => {
|
|
4698
4662
|
const {
|
|
4699
4663
|
screen,
|
|
4700
4664
|
mode,
|
|
@@ -4790,7 +4754,7 @@ ${error}`;
|
|
|
4790
4754
|
helpBar.destroy();
|
|
4791
4755
|
viewer.destroy();
|
|
4792
4756
|
screen.render();
|
|
4793
|
-
|
|
4757
|
+
resolve3();
|
|
4794
4758
|
};
|
|
4795
4759
|
closeCallback = close;
|
|
4796
4760
|
viewer.key(["escape", "q"], close);
|
|
@@ -5588,8 +5552,8 @@ async function executeAgent(promptArg, options, env) {
|
|
|
5588
5552
|
};
|
|
5589
5553
|
let usage;
|
|
5590
5554
|
let iterations = 0;
|
|
5591
|
-
const
|
|
5592
|
-
|
|
5555
|
+
const llmLogsEnabled = options.logLlmRequests === true;
|
|
5556
|
+
const llmLogDir = llmLogsEnabled ? env.session?.logDir : void 0;
|
|
5593
5557
|
let llmCallCounter = 0;
|
|
5594
5558
|
const countMessagesTokens = async (model, messages) => {
|
|
5595
5559
|
try {
|
|
@@ -5636,15 +5600,10 @@ async function executeAgent(promptArg, options, env) {
|
|
|
5636
5600
|
if (tui) {
|
|
5637
5601
|
tui.setLLMCallRequest(context.options.messages);
|
|
5638
5602
|
}
|
|
5639
|
-
if (
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
if (llmSessionDir) {
|
|
5644
|
-
const filename = `${formatCallNumber(llmCallCounter)}.request`;
|
|
5645
|
-
const content = formatLlmRequest(context.options.messages);
|
|
5646
|
-
await writeLogFile(llmSessionDir, filename, content);
|
|
5647
|
-
}
|
|
5603
|
+
if (llmLogDir) {
|
|
5604
|
+
const filename = `${formatCallNumber(llmCallCounter)}.request`;
|
|
5605
|
+
const content = formatLlmRequest(context.options.messages);
|
|
5606
|
+
await writeLogFile(llmLogDir, filename, content);
|
|
5648
5607
|
}
|
|
5649
5608
|
},
|
|
5650
5609
|
// onStreamChunk: Update status bar with real-time output token estimate
|
|
@@ -5687,9 +5646,9 @@ async function executeAgent(promptArg, options, env) {
|
|
|
5687
5646
|
rawResponse: context.rawResponse
|
|
5688
5647
|
});
|
|
5689
5648
|
}
|
|
5690
|
-
if (
|
|
5649
|
+
if (llmLogDir) {
|
|
5691
5650
|
const filename = `${formatCallNumber(llmCallCounter)}.response`;
|
|
5692
|
-
await writeLogFile(
|
|
5651
|
+
await writeLogFile(llmLogDir, filename, context.rawResponse);
|
|
5693
5652
|
}
|
|
5694
5653
|
}
|
|
5695
5654
|
},
|
|
@@ -5937,15 +5896,12 @@ async function executeComplete(promptArg, options, env) {
|
|
|
5937
5896
|
builder.addUser(prompt);
|
|
5938
5897
|
}
|
|
5939
5898
|
const messages = builder.build();
|
|
5940
|
-
const
|
|
5941
|
-
|
|
5942
|
-
if (
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
const content = formatLlmRequest(messages);
|
|
5947
|
-
await writeLogFile(llmSessionDir, filename, content);
|
|
5948
|
-
}
|
|
5899
|
+
const llmLogsEnabled = options.logLlmRequests === true;
|
|
5900
|
+
const llmLogDir = llmLogsEnabled ? env.session?.logDir : void 0;
|
|
5901
|
+
if (llmLogDir) {
|
|
5902
|
+
const filename = "0001.request";
|
|
5903
|
+
const content = formatLlmRequest(messages);
|
|
5904
|
+
await writeLogFile(llmLogDir, filename, content);
|
|
5949
5905
|
}
|
|
5950
5906
|
const stream = client.stream({
|
|
5951
5907
|
model,
|
|
@@ -5984,9 +5940,9 @@ async function executeComplete(promptArg, options, env) {
|
|
|
5984
5940
|
progress.endCall(usage);
|
|
5985
5941
|
progress.complete();
|
|
5986
5942
|
printer.ensureNewline();
|
|
5987
|
-
if (
|
|
5943
|
+
if (llmLogDir) {
|
|
5988
5944
|
const filename = "0001.response";
|
|
5989
|
-
await writeLogFile(
|
|
5945
|
+
await writeLogFile(llmLogDir, filename, accumulatedResponse);
|
|
5990
5946
|
}
|
|
5991
5947
|
if (stderrTTY && !options.quiet) {
|
|
5992
5948
|
const summary = renderSummary({ finishReason, usage, cost: progress.getTotalCost() });
|
|
@@ -6004,18 +5960,163 @@ function registerCompleteCommand(program, env, config) {
|
|
|
6004
5960
|
);
|
|
6005
5961
|
}
|
|
6006
5962
|
|
|
5963
|
+
// src/config-command.ts
|
|
5964
|
+
function registerConfigCommand(program, env, config) {
|
|
5965
|
+
program.command(`${COMMANDS.config} [profile]`).description("Display resolved configuration for a profile or list all profiles").action(
|
|
5966
|
+
(profileName) => executeAction(() => executeConfigCommand(profileName, config, env), env)
|
|
5967
|
+
);
|
|
5968
|
+
}
|
|
5969
|
+
async function executeConfigCommand(profileName, config, env) {
|
|
5970
|
+
if (!config || Object.keys(config).length === 0) {
|
|
5971
|
+
env.stdout.write("No configuration file found at ~/.llmist/cli.toml\n");
|
|
5972
|
+
env.stdout.write("Run 'llmist init' to create one.\n");
|
|
5973
|
+
return;
|
|
5974
|
+
}
|
|
5975
|
+
if (!profileName) {
|
|
5976
|
+
listProfiles(config, env);
|
|
5977
|
+
} else {
|
|
5978
|
+
showProfile(profileName, config, env);
|
|
5979
|
+
}
|
|
5980
|
+
}
|
|
5981
|
+
function listProfiles(config, env) {
|
|
5982
|
+
const reserved = /* @__PURE__ */ new Set(["global", "prompts", "subagents"]);
|
|
5983
|
+
const profiles = Object.keys(config).filter((k) => !reserved.has(k));
|
|
5984
|
+
if (profiles.length === 0) {
|
|
5985
|
+
env.stdout.write("No profiles defined in configuration.\n");
|
|
5986
|
+
return;
|
|
5987
|
+
}
|
|
5988
|
+
env.stdout.write("Available Profiles:\n\n");
|
|
5989
|
+
for (const name of profiles) {
|
|
5990
|
+
const section = config[name];
|
|
5991
|
+
const inherits = section?.inherits;
|
|
5992
|
+
const desc = section?.description;
|
|
5993
|
+
let line = ` ${name.padEnd(22)}`;
|
|
5994
|
+
if (desc) {
|
|
5995
|
+
line += desc;
|
|
5996
|
+
} else if (inherits) {
|
|
5997
|
+
line += `inherits: ${Array.isArray(inherits) ? inherits.join(", ") : inherits}`;
|
|
5998
|
+
}
|
|
5999
|
+
env.stdout.write(line + "\n");
|
|
6000
|
+
}
|
|
6001
|
+
}
|
|
6002
|
+
function showProfile(name, config, env) {
|
|
6003
|
+
const reserved = /* @__PURE__ */ new Set(["global", "prompts", "subagents"]);
|
|
6004
|
+
if (reserved.has(name)) {
|
|
6005
|
+
env.stderr.write(`"${name}" is a reserved section, not a profile.
|
|
6006
|
+
`);
|
|
6007
|
+
return;
|
|
6008
|
+
}
|
|
6009
|
+
const section = config[name];
|
|
6010
|
+
if (!section) {
|
|
6011
|
+
env.stderr.write(`Profile "${name}" not found.
|
|
6012
|
+
`);
|
|
6013
|
+
env.stderr.write("Run 'llmist config' to see available profiles.\n");
|
|
6014
|
+
return;
|
|
6015
|
+
}
|
|
6016
|
+
const separator = "\u2500".repeat(60);
|
|
6017
|
+
env.stdout.write(`
|
|
6018
|
+
Profile: ${name}
|
|
6019
|
+
`);
|
|
6020
|
+
if (section.inherits) {
|
|
6021
|
+
const chain = Array.isArray(section.inherits) ? section.inherits.join(" \u2192 ") : section.inherits;
|
|
6022
|
+
env.stdout.write(`Inherits: ${chain}
|
|
6023
|
+
`);
|
|
6024
|
+
}
|
|
6025
|
+
if (section.description) {
|
|
6026
|
+
env.stdout.write(`Description: ${section.description}
|
|
6027
|
+
`);
|
|
6028
|
+
}
|
|
6029
|
+
env.stdout.write(separator + "\n\n");
|
|
6030
|
+
env.stdout.write("Options:\n");
|
|
6031
|
+
env.stdout.write(` Model: ${section.model ?? "(default)"}
|
|
6032
|
+
`);
|
|
6033
|
+
env.stdout.write(` Max Iterations: ${section["max-iterations"] ?? "(default)"}
|
|
6034
|
+
`);
|
|
6035
|
+
env.stdout.write(
|
|
6036
|
+
` Temperature: ${section.temperature !== void 0 ? section.temperature : "(default)"}
|
|
6037
|
+
`
|
|
6038
|
+
);
|
|
6039
|
+
const gadgets = section.gadgets ?? section.gadget;
|
|
6040
|
+
if (gadgets && gadgets.length > 0) {
|
|
6041
|
+
env.stdout.write("\nGadgets:\n");
|
|
6042
|
+
for (const g of gadgets) {
|
|
6043
|
+
env.stdout.write(` \u2022 ${g}
|
|
6044
|
+
`);
|
|
6045
|
+
}
|
|
6046
|
+
}
|
|
6047
|
+
const approval = section["gadget-approval"];
|
|
6048
|
+
if (approval && Object.keys(approval).length > 0) {
|
|
6049
|
+
env.stdout.write("\nGadget Approval:\n");
|
|
6050
|
+
for (const [gadget, policy] of Object.entries(approval)) {
|
|
6051
|
+
env.stdout.write(` \u2022 ${gadget}: ${policy}
|
|
6052
|
+
`);
|
|
6053
|
+
}
|
|
6054
|
+
}
|
|
6055
|
+
if (section.subagents && Object.keys(section.subagents).length > 0) {
|
|
6056
|
+
env.stdout.write("\nSubagents:\n");
|
|
6057
|
+
for (const [subagent, subConfig] of Object.entries(section.subagents)) {
|
|
6058
|
+
env.stdout.write(` ${subagent}:
|
|
6059
|
+
`);
|
|
6060
|
+
if (subConfig.model) env.stdout.write(` model: ${subConfig.model}
|
|
6061
|
+
`);
|
|
6062
|
+
if (subConfig.maxIterations)
|
|
6063
|
+
env.stdout.write(` maxIterations: ${subConfig.maxIterations}
|
|
6064
|
+
`);
|
|
6065
|
+
if (subConfig.timeoutMs) env.stdout.write(` timeoutMs: ${subConfig.timeoutMs}
|
|
6066
|
+
`);
|
|
6067
|
+
}
|
|
6068
|
+
}
|
|
6069
|
+
if (section.system) {
|
|
6070
|
+
const chars = section.system.length;
|
|
6071
|
+
const lines = section.system.split("\n").length;
|
|
6072
|
+
env.stdout.write(`
|
|
6073
|
+
System Prompt (${chars.toLocaleString()} chars, ${lines} lines):
|
|
6074
|
+
`);
|
|
6075
|
+
env.stdout.write(separator + "\n");
|
|
6076
|
+
env.stdout.write(section.system);
|
|
6077
|
+
if (!section.system.endsWith("\n")) {
|
|
6078
|
+
env.stdout.write("\n");
|
|
6079
|
+
}
|
|
6080
|
+
env.stdout.write(separator + "\n");
|
|
6081
|
+
} else {
|
|
6082
|
+
env.stdout.write("\nSystem Prompt: (none)\n");
|
|
6083
|
+
}
|
|
6084
|
+
}
|
|
6085
|
+
|
|
6007
6086
|
// src/init-command.ts
|
|
6008
|
-
import { existsSync as
|
|
6009
|
-
import { dirname } from "path";
|
|
6087
|
+
import { existsSync as existsSync3, mkdirSync, writeFileSync } from "fs";
|
|
6088
|
+
import { dirname as dirname2 } from "path";
|
|
6010
6089
|
|
|
6011
6090
|
// src/config.ts
|
|
6012
|
-
import { existsSync, readFileSync } from "fs";
|
|
6091
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
6013
6092
|
import { homedir as homedir2 } from "os";
|
|
6014
6093
|
import { join as join2 } from "path";
|
|
6015
6094
|
import { load as parseToml } from "js-toml";
|
|
6016
6095
|
|
|
6017
6096
|
// src/templates.ts
|
|
6018
6097
|
import { Eta } from "eta";
|
|
6098
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
6099
|
+
import { dirname, resolve as resolve2 } from "path";
|
|
6100
|
+
var MAX_PROMPT_FILE_SIZE = 1024 * 1024;
|
|
6101
|
+
function resolvePromptFilePath(filePath, configDir) {
|
|
6102
|
+
const expanded = expandTildePath(filePath);
|
|
6103
|
+
if (expanded.startsWith("/")) {
|
|
6104
|
+
return expanded;
|
|
6105
|
+
}
|
|
6106
|
+
return resolve2(configDir ?? process.cwd(), expanded);
|
|
6107
|
+
}
|
|
6108
|
+
function loadFileContents(filePath, configDir) {
|
|
6109
|
+
const absolutePath = resolvePromptFilePath(filePath, configDir);
|
|
6110
|
+
if (!existsSync(absolutePath)) {
|
|
6111
|
+
throw new Error(`File not found: ${filePath}`);
|
|
6112
|
+
}
|
|
6113
|
+
const stats = statSync(absolutePath);
|
|
6114
|
+
if (stats.size > MAX_PROMPT_FILE_SIZE) {
|
|
6115
|
+
const sizeMB = (stats.size / (1024 * 1024)).toFixed(1);
|
|
6116
|
+
throw new Error(`File too large: ${filePath} (${sizeMB}MB, max 1MB)`);
|
|
6117
|
+
}
|
|
6118
|
+
return readFileSync(absolutePath, "utf-8");
|
|
6119
|
+
}
|
|
6019
6120
|
var TemplateError = class extends Error {
|
|
6020
6121
|
constructor(message, promptName, configPath) {
|
|
6021
6122
|
super(promptName ? `[prompts.${promptName}]: ${message}` : message);
|
|
@@ -6025,14 +6126,40 @@ var TemplateError = class extends Error {
|
|
|
6025
6126
|
}
|
|
6026
6127
|
};
|
|
6027
6128
|
function createTemplateEngine(prompts, configPath) {
|
|
6129
|
+
const configDir = configPath ? dirname(configPath) : void 0;
|
|
6028
6130
|
const eta = new Eta({
|
|
6029
6131
|
views: "/",
|
|
6030
6132
|
// Required but we use named templates
|
|
6031
6133
|
autoEscape: false,
|
|
6032
6134
|
// Don't escape - these are prompts, not HTML
|
|
6033
|
-
autoTrim: false
|
|
6135
|
+
autoTrim: false,
|
|
6034
6136
|
// Preserve whitespace in prompts
|
|
6137
|
+
// Inject includeFile function into compiled templates
|
|
6138
|
+
functionHeader: "const includeFile = (path) => it.__includeFile(path);"
|
|
6035
6139
|
});
|
|
6140
|
+
const includeStack = [];
|
|
6141
|
+
eta.__includeFileImpl = (path6) => {
|
|
6142
|
+
if (includeStack.includes(path6)) {
|
|
6143
|
+
throw new Error(
|
|
6144
|
+
`Circular include detected: ${[...includeStack, path6].join(" -> ")}`
|
|
6145
|
+
);
|
|
6146
|
+
}
|
|
6147
|
+
includeStack.push(path6);
|
|
6148
|
+
try {
|
|
6149
|
+
const content = loadFileContents(path6, configDir);
|
|
6150
|
+
if (hasTemplateSyntax(content)) {
|
|
6151
|
+
const context = {
|
|
6152
|
+
env: process.env,
|
|
6153
|
+
date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
|
|
6154
|
+
__includeFile: eta.__includeFileImpl
|
|
6155
|
+
};
|
|
6156
|
+
return eta.renderString(content, context);
|
|
6157
|
+
}
|
|
6158
|
+
return content;
|
|
6159
|
+
} finally {
|
|
6160
|
+
includeStack.pop();
|
|
6161
|
+
}
|
|
6162
|
+
};
|
|
6036
6163
|
for (const [name, template] of Object.entries(prompts)) {
|
|
6037
6164
|
try {
|
|
6038
6165
|
eta.loadTemplate(`@${name}`, template);
|
|
@@ -6051,8 +6178,9 @@ function resolveTemplate(eta, template, context = {}, configPath) {
|
|
|
6051
6178
|
const fullContext = {
|
|
6052
6179
|
...context,
|
|
6053
6180
|
env: process.env,
|
|
6054
|
-
date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
|
|
6181
|
+
date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
|
|
6055
6182
|
// "2025-12-01"
|
|
6183
|
+
__includeFile: eta.__includeFileImpl ?? (() => "")
|
|
6056
6184
|
};
|
|
6057
6185
|
return eta.renderString(template, fullContext);
|
|
6058
6186
|
} catch (error) {
|
|
@@ -6067,7 +6195,10 @@ function validatePrompts(prompts, configPath) {
|
|
|
6067
6195
|
const eta = createTemplateEngine(prompts, configPath);
|
|
6068
6196
|
for (const [name, template] of Object.entries(prompts)) {
|
|
6069
6197
|
try {
|
|
6070
|
-
eta.renderString(template, {
|
|
6198
|
+
eta.renderString(template, {
|
|
6199
|
+
env: {},
|
|
6200
|
+
__includeFile: eta.__includeFileImpl ?? (() => "")
|
|
6201
|
+
});
|
|
6071
6202
|
} catch (error) {
|
|
6072
6203
|
throw new TemplateError(
|
|
6073
6204
|
error instanceof Error ? error.message : String(error),
|
|
@@ -6097,7 +6228,7 @@ function hasTemplateSyntax(str) {
|
|
|
6097
6228
|
|
|
6098
6229
|
// src/config.ts
|
|
6099
6230
|
var VALID_PERMISSION_LEVELS = ["allowed", "denied", "approval-required"];
|
|
6100
|
-
var GLOBAL_CONFIG_KEYS = /* @__PURE__ */ new Set(["log-level"
|
|
6231
|
+
var GLOBAL_CONFIG_KEYS = /* @__PURE__ */ new Set(["log-level"]);
|
|
6101
6232
|
var VALID_LOG_LEVELS = ["silly", "trace", "debug", "info", "warn", "error", "fatal"];
|
|
6102
6233
|
var COMPLETE_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
6103
6234
|
"model",
|
|
@@ -6107,8 +6238,6 @@ var COMPLETE_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
6107
6238
|
"quiet",
|
|
6108
6239
|
"inherits",
|
|
6109
6240
|
"log-level",
|
|
6110
|
-
"log-file",
|
|
6111
|
-
"log-reset",
|
|
6112
6241
|
"log-llm-requests",
|
|
6113
6242
|
"type"
|
|
6114
6243
|
// Allowed for inheritance compatibility, ignored for built-in commands
|
|
@@ -6137,8 +6266,6 @@ var AGENT_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
6137
6266
|
"quiet",
|
|
6138
6267
|
"inherits",
|
|
6139
6268
|
"log-level",
|
|
6140
|
-
"log-file",
|
|
6141
|
-
"log-reset",
|
|
6142
6269
|
"log-llm-requests",
|
|
6143
6270
|
"type"
|
|
6144
6271
|
// Allowed for inheritance compatibility, ignored for built-in commands
|
|
@@ -6167,6 +6294,9 @@ function validateString(value, key, section) {
|
|
|
6167
6294
|
}
|
|
6168
6295
|
return value;
|
|
6169
6296
|
}
|
|
6297
|
+
function validatePathString(value, key, section) {
|
|
6298
|
+
return expandTildePath(validateString(value, key, section));
|
|
6299
|
+
}
|
|
6170
6300
|
function validateNumber(value, key, section, opts) {
|
|
6171
6301
|
if (typeof value !== "number") {
|
|
6172
6302
|
throw new ConfigError(`[${section}].${key} must be a number`);
|
|
@@ -6234,6 +6364,13 @@ function validateSingleSubagentConfig(value, subagentName, section) {
|
|
|
6234
6364
|
);
|
|
6235
6365
|
}
|
|
6236
6366
|
result.maxIterations = val;
|
|
6367
|
+
} else if (key === "timeoutMs") {
|
|
6368
|
+
if (typeof val !== "number" || !Number.isInteger(val) || val < 0) {
|
|
6369
|
+
throw new ConfigError(
|
|
6370
|
+
`[${section}].${subagentName}.timeoutMs must be a non-negative integer`
|
|
6371
|
+
);
|
|
6372
|
+
}
|
|
6373
|
+
result.timeoutMs = val;
|
|
6237
6374
|
} else {
|
|
6238
6375
|
result[key] = val;
|
|
6239
6376
|
}
|
|
@@ -6301,12 +6438,6 @@ function validateLoggingConfig(raw, section) {
|
|
|
6301
6438
|
}
|
|
6302
6439
|
result["log-level"] = level;
|
|
6303
6440
|
}
|
|
6304
|
-
if ("log-file" in raw) {
|
|
6305
|
-
result["log-file"] = validateString(raw["log-file"], "log-file", section);
|
|
6306
|
-
}
|
|
6307
|
-
if ("log-reset" in raw) {
|
|
6308
|
-
result["log-reset"] = validateBoolean(raw["log-reset"], "log-reset", section);
|
|
6309
|
-
}
|
|
6310
6441
|
return result;
|
|
6311
6442
|
}
|
|
6312
6443
|
function validateBaseConfig(raw, section) {
|
|
@@ -6364,11 +6495,7 @@ function validateCompleteConfig(raw, section) {
|
|
|
6364
6495
|
result.quiet = validateBoolean(rawObj.quiet, "quiet", section);
|
|
6365
6496
|
}
|
|
6366
6497
|
if ("log-llm-requests" in rawObj) {
|
|
6367
|
-
result["log-llm-requests"] =
|
|
6368
|
-
rawObj["log-llm-requests"],
|
|
6369
|
-
"log-llm-requests",
|
|
6370
|
-
section
|
|
6371
|
-
);
|
|
6498
|
+
result["log-llm-requests"] = validateBoolean(rawObj["log-llm-requests"], "log-llm-requests", section);
|
|
6372
6499
|
}
|
|
6373
6500
|
return result;
|
|
6374
6501
|
}
|
|
@@ -6449,11 +6576,7 @@ function validateAgentConfig(raw, section) {
|
|
|
6449
6576
|
result.quiet = validateBoolean(rawObj.quiet, "quiet", section);
|
|
6450
6577
|
}
|
|
6451
6578
|
if ("log-llm-requests" in rawObj) {
|
|
6452
|
-
result["log-llm-requests"] =
|
|
6453
|
-
rawObj["log-llm-requests"],
|
|
6454
|
-
"log-llm-requests",
|
|
6455
|
-
section
|
|
6456
|
-
);
|
|
6579
|
+
result["log-llm-requests"] = validateBoolean(rawObj["log-llm-requests"], "log-llm-requests", section);
|
|
6457
6580
|
}
|
|
6458
6581
|
return result;
|
|
6459
6582
|
}
|
|
@@ -6485,7 +6608,7 @@ function validateImageConfig(raw, section) {
|
|
|
6485
6608
|
});
|
|
6486
6609
|
}
|
|
6487
6610
|
if ("output" in rawObj) {
|
|
6488
|
-
result.output =
|
|
6611
|
+
result.output = validatePathString(rawObj.output, "output", section);
|
|
6489
6612
|
}
|
|
6490
6613
|
if ("quiet" in rawObj) {
|
|
6491
6614
|
result.quiet = validateBoolean(rawObj.quiet, "quiet", section);
|
|
@@ -6519,19 +6642,13 @@ function validateSpeechConfig(raw, section) {
|
|
|
6519
6642
|
});
|
|
6520
6643
|
}
|
|
6521
6644
|
if ("output" in rawObj) {
|
|
6522
|
-
result.output =
|
|
6645
|
+
result.output = validatePathString(rawObj.output, "output", section);
|
|
6523
6646
|
}
|
|
6524
6647
|
if ("quiet" in rawObj) {
|
|
6525
6648
|
result.quiet = validateBoolean(rawObj.quiet, "quiet", section);
|
|
6526
6649
|
}
|
|
6527
6650
|
return result;
|
|
6528
6651
|
}
|
|
6529
|
-
function validateStringOrBoolean(value, field, section) {
|
|
6530
|
-
if (typeof value === "string" || typeof value === "boolean") {
|
|
6531
|
-
return value;
|
|
6532
|
-
}
|
|
6533
|
-
throw new ConfigError(`[${section}].${field} must be a string or boolean`);
|
|
6534
|
-
}
|
|
6535
6652
|
function validateCustomConfig(raw, section) {
|
|
6536
6653
|
if (typeof raw !== "object" || raw === null) {
|
|
6537
6654
|
throw new ConfigError(`[${section}] must be a table`);
|
|
@@ -6625,6 +6742,9 @@ function validateCustomConfig(raw, section) {
|
|
|
6625
6742
|
if ("quiet" in rawObj) {
|
|
6626
6743
|
result.quiet = validateBoolean(rawObj.quiet, "quiet", section);
|
|
6627
6744
|
}
|
|
6745
|
+
if ("log-llm-requests" in rawObj) {
|
|
6746
|
+
result["log-llm-requests"] = validateBoolean(rawObj["log-llm-requests"], "log-llm-requests", section);
|
|
6747
|
+
}
|
|
6628
6748
|
Object.assign(result, validateLoggingConfig(rawObj, section));
|
|
6629
6749
|
return result;
|
|
6630
6750
|
}
|
|
@@ -6677,12 +6797,12 @@ function validateConfig(raw, configPath) {
|
|
|
6677
6797
|
}
|
|
6678
6798
|
function loadConfig() {
|
|
6679
6799
|
const configPath = getConfigPath();
|
|
6680
|
-
if (!
|
|
6800
|
+
if (!existsSync2(configPath)) {
|
|
6681
6801
|
return {};
|
|
6682
6802
|
}
|
|
6683
6803
|
let content;
|
|
6684
6804
|
try {
|
|
6685
|
-
content =
|
|
6805
|
+
content = readFileSync2(configPath, "utf-8");
|
|
6686
6806
|
} catch (error) {
|
|
6687
6807
|
throw new ConfigError(
|
|
6688
6808
|
`Failed to read config file: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
@@ -6924,8 +7044,8 @@ var STARTER_CONFIG = `# ~/.llmist/cli.toml
|
|
|
6924
7044
|
`;
|
|
6925
7045
|
async function executeInit(_options, env) {
|
|
6926
7046
|
const configPath = getConfigPath();
|
|
6927
|
-
const configDir =
|
|
6928
|
-
if (
|
|
7047
|
+
const configDir = dirname2(configPath);
|
|
7048
|
+
if (existsSync3(configPath)) {
|
|
6929
7049
|
env.stderr.write(`Configuration already exists at ${configPath}
|
|
6930
7050
|
`);
|
|
6931
7051
|
env.stderr.write("\n");
|
|
@@ -6935,7 +7055,7 @@ async function executeInit(_options, env) {
|
|
|
6935
7055
|
`);
|
|
6936
7056
|
return;
|
|
6937
7057
|
}
|
|
6938
|
-
if (!
|
|
7058
|
+
if (!existsSync3(configDir)) {
|
|
6939
7059
|
mkdirSync(configDir, { recursive: true });
|
|
6940
7060
|
}
|
|
6941
7061
|
writeFileSync(configPath, STARTER_CONFIG, "utf-8");
|
|
@@ -6965,6 +7085,7 @@ function registerInitCommand(program, env) {
|
|
|
6965
7085
|
}
|
|
6966
7086
|
|
|
6967
7087
|
// src/environment.ts
|
|
7088
|
+
import { join as join3 } from "path";
|
|
6968
7089
|
import readline from "readline";
|
|
6969
7090
|
import chalk4 from "chalk";
|
|
6970
7091
|
import { LLMist, createLogger } from "llmist";
|
|
@@ -6977,7 +7098,7 @@ var LOG_LEVEL_MAP = {
|
|
|
6977
7098
|
error: 5,
|
|
6978
7099
|
fatal: 6
|
|
6979
7100
|
};
|
|
6980
|
-
function createLoggerFactory(config) {
|
|
7101
|
+
function createLoggerFactory(config, sessionLogDir) {
|
|
6981
7102
|
return (name) => {
|
|
6982
7103
|
const options = { name };
|
|
6983
7104
|
if (config?.logLevel) {
|
|
@@ -6986,12 +7107,10 @@ function createLoggerFactory(config) {
|
|
|
6986
7107
|
options.minLevel = LOG_LEVEL_MAP[level];
|
|
6987
7108
|
}
|
|
6988
7109
|
}
|
|
6989
|
-
if (
|
|
6990
|
-
|
|
6991
|
-
}
|
|
6992
|
-
if (config?.logFile) {
|
|
7110
|
+
if (sessionLogDir) {
|
|
7111
|
+
const logFile = join3(sessionLogDir, "session.log.jsonl");
|
|
6993
7112
|
const originalLogFile = process.env.LLMIST_LOG_FILE;
|
|
6994
|
-
process.env.LLMIST_LOG_FILE =
|
|
7113
|
+
process.env.LLMIST_LOG_FILE = logFile;
|
|
6995
7114
|
const logger = createLogger(options);
|
|
6996
7115
|
if (originalLogFile === void 0) {
|
|
6997
7116
|
delete process.env.LLMIST_LOG_FILE;
|
|
@@ -7008,7 +7127,7 @@ function createLoggerFactory(config) {
|
|
|
7008
7127
|
}
|
|
7009
7128
|
function createPromptFunction(stdin, stdout) {
|
|
7010
7129
|
return (question) => {
|
|
7011
|
-
return new Promise((
|
|
7130
|
+
return new Promise((resolve3) => {
|
|
7012
7131
|
const rl = readline.createInterface({
|
|
7013
7132
|
input: stdin,
|
|
7014
7133
|
output: stdout
|
|
@@ -7023,12 +7142,12 @@ function createPromptFunction(stdin, stdout) {
|
|
|
7023
7142
|
`);
|
|
7024
7143
|
rl.question(chalk4.green.bold("You: "), (answer) => {
|
|
7025
7144
|
rl.close();
|
|
7026
|
-
|
|
7145
|
+
resolve3(answer);
|
|
7027
7146
|
});
|
|
7028
7147
|
});
|
|
7029
7148
|
};
|
|
7030
7149
|
}
|
|
7031
|
-
function createDefaultEnvironment(loggerConfig) {
|
|
7150
|
+
function createDefaultEnvironment(loggerConfig, sessionLogDir) {
|
|
7032
7151
|
const isTTY = Boolean(process.stdin.isTTY);
|
|
7033
7152
|
return {
|
|
7034
7153
|
argv: process.argv,
|
|
@@ -7040,7 +7159,7 @@ function createDefaultEnvironment(loggerConfig) {
|
|
|
7040
7159
|
process.exitCode = code;
|
|
7041
7160
|
},
|
|
7042
7161
|
loggerConfig,
|
|
7043
|
-
createLogger: createLoggerFactory(loggerConfig),
|
|
7162
|
+
createLogger: createLoggerFactory(loggerConfig, sessionLogDir),
|
|
7044
7163
|
isTTY,
|
|
7045
7164
|
prompt: isTTY ? createPromptFunction(process.stdin, process.stdout) : async () => {
|
|
7046
7165
|
throw new Error("Cannot prompt for input: stdin is not a TTY");
|
|
@@ -7050,19 +7169,17 @@ function createDefaultEnvironment(loggerConfig) {
|
|
|
7050
7169
|
|
|
7051
7170
|
// src/custom-command.ts
|
|
7052
7171
|
function createCommandEnvironment(baseEnv, config) {
|
|
7053
|
-
const hasLoggingConfig = config["log-level"] !== void 0
|
|
7172
|
+
const hasLoggingConfig = config["log-level"] !== void 0;
|
|
7054
7173
|
if (!hasLoggingConfig) {
|
|
7055
7174
|
return baseEnv;
|
|
7056
7175
|
}
|
|
7057
7176
|
const loggerConfig = {
|
|
7058
|
-
logLevel: config["log-level"] ?? baseEnv.loggerConfig?.logLevel
|
|
7059
|
-
logFile: config["log-file"] ?? baseEnv.loggerConfig?.logFile,
|
|
7060
|
-
logReset: config["log-reset"] ?? baseEnv.loggerConfig?.logReset
|
|
7177
|
+
logLevel: config["log-level"] ?? baseEnv.loggerConfig?.logLevel
|
|
7061
7178
|
};
|
|
7062
7179
|
return {
|
|
7063
7180
|
...baseEnv,
|
|
7064
7181
|
loggerConfig,
|
|
7065
|
-
createLogger: createLoggerFactory(loggerConfig)
|
|
7182
|
+
createLogger: createLoggerFactory(loggerConfig, baseEnv.session?.logDir)
|
|
7066
7183
|
};
|
|
7067
7184
|
}
|
|
7068
7185
|
function registerCustomCommand(program, name, config, env, globalSubagents) {
|
|
@@ -7998,6 +8115,174 @@ function registerModelsCommand(program, env) {
|
|
|
7998
8115
|
);
|
|
7999
8116
|
}
|
|
8000
8117
|
|
|
8118
|
+
// src/session.ts
|
|
8119
|
+
import { existsSync as existsSync4 } from "fs";
|
|
8120
|
+
import { mkdir as mkdir2 } from "fs/promises";
|
|
8121
|
+
import { homedir as homedir3 } from "os";
|
|
8122
|
+
import { join as join4 } from "path";
|
|
8123
|
+
|
|
8124
|
+
// src/session-names.ts
|
|
8125
|
+
var ADJECTIVES = [
|
|
8126
|
+
"bright",
|
|
8127
|
+
"calm",
|
|
8128
|
+
"clever",
|
|
8129
|
+
"cool",
|
|
8130
|
+
"crisp",
|
|
8131
|
+
"eager",
|
|
8132
|
+
"fair",
|
|
8133
|
+
"fancy",
|
|
8134
|
+
"fast",
|
|
8135
|
+
"fresh",
|
|
8136
|
+
"gentle",
|
|
8137
|
+
"glad",
|
|
8138
|
+
"golden",
|
|
8139
|
+
"green",
|
|
8140
|
+
"happy",
|
|
8141
|
+
"jolly",
|
|
8142
|
+
"keen",
|
|
8143
|
+
"kind",
|
|
8144
|
+
"lively",
|
|
8145
|
+
"lucky",
|
|
8146
|
+
"merry",
|
|
8147
|
+
"neat",
|
|
8148
|
+
"nice",
|
|
8149
|
+
"noble",
|
|
8150
|
+
"peppy",
|
|
8151
|
+
"perky",
|
|
8152
|
+
"pink",
|
|
8153
|
+
"proud",
|
|
8154
|
+
"quick",
|
|
8155
|
+
"quiet",
|
|
8156
|
+
"rapid",
|
|
8157
|
+
"ready",
|
|
8158
|
+
"red",
|
|
8159
|
+
"rich",
|
|
8160
|
+
"rosy",
|
|
8161
|
+
"royal",
|
|
8162
|
+
"sharp",
|
|
8163
|
+
"shiny",
|
|
8164
|
+
"silver",
|
|
8165
|
+
"sleek",
|
|
8166
|
+
"smart",
|
|
8167
|
+
"smooth",
|
|
8168
|
+
"snappy",
|
|
8169
|
+
"solar",
|
|
8170
|
+
"steady",
|
|
8171
|
+
"sunny",
|
|
8172
|
+
"super",
|
|
8173
|
+
"sweet",
|
|
8174
|
+
"swift",
|
|
8175
|
+
"tidy",
|
|
8176
|
+
"vivid",
|
|
8177
|
+
"warm",
|
|
8178
|
+
"wild",
|
|
8179
|
+
"wise",
|
|
8180
|
+
"witty",
|
|
8181
|
+
"young"
|
|
8182
|
+
];
|
|
8183
|
+
var NOUNS = [
|
|
8184
|
+
"arrow",
|
|
8185
|
+
"badge",
|
|
8186
|
+
"bear",
|
|
8187
|
+
"bird",
|
|
8188
|
+
"blade",
|
|
8189
|
+
"bolt",
|
|
8190
|
+
"brook",
|
|
8191
|
+
"cloud",
|
|
8192
|
+
"coral",
|
|
8193
|
+
"crane",
|
|
8194
|
+
"creek",
|
|
8195
|
+
"crown",
|
|
8196
|
+
"delta",
|
|
8197
|
+
"dove",
|
|
8198
|
+
"eagle",
|
|
8199
|
+
"ember",
|
|
8200
|
+
"falcon",
|
|
8201
|
+
"flame",
|
|
8202
|
+
"flash",
|
|
8203
|
+
"frost",
|
|
8204
|
+
"gem",
|
|
8205
|
+
"grove",
|
|
8206
|
+
"hawk",
|
|
8207
|
+
"heart",
|
|
8208
|
+
"heron",
|
|
8209
|
+
"hill",
|
|
8210
|
+
"jade",
|
|
8211
|
+
"lake",
|
|
8212
|
+
"leaf",
|
|
8213
|
+
"lion",
|
|
8214
|
+
"lotus",
|
|
8215
|
+
"maple",
|
|
8216
|
+
"moon",
|
|
8217
|
+
"oak",
|
|
8218
|
+
"ocean",
|
|
8219
|
+
"olive",
|
|
8220
|
+
"otter",
|
|
8221
|
+
"owl",
|
|
8222
|
+
"panda",
|
|
8223
|
+
"pearl",
|
|
8224
|
+
"pine",
|
|
8225
|
+
"plum",
|
|
8226
|
+
"raven",
|
|
8227
|
+
"reef",
|
|
8228
|
+
"ridge",
|
|
8229
|
+
"river",
|
|
8230
|
+
"robin",
|
|
8231
|
+
"rose",
|
|
8232
|
+
"sage",
|
|
8233
|
+
"shell",
|
|
8234
|
+
"snow",
|
|
8235
|
+
"spark",
|
|
8236
|
+
"star",
|
|
8237
|
+
"stone",
|
|
8238
|
+
"storm",
|
|
8239
|
+
"stream",
|
|
8240
|
+
"sun",
|
|
8241
|
+
"swan",
|
|
8242
|
+
"tiger",
|
|
8243
|
+
"tree",
|
|
8244
|
+
"wave",
|
|
8245
|
+
"willow",
|
|
8246
|
+
"wind",
|
|
8247
|
+
"wolf"
|
|
8248
|
+
];
|
|
8249
|
+
function generateSessionName() {
|
|
8250
|
+
const adjective = ADJECTIVES[Math.floor(Math.random() * ADJECTIVES.length)];
|
|
8251
|
+
const noun = NOUNS[Math.floor(Math.random() * NOUNS.length)];
|
|
8252
|
+
return `${adjective}-${noun}`;
|
|
8253
|
+
}
|
|
8254
|
+
|
|
8255
|
+
// src/session.ts
|
|
8256
|
+
var currentSession;
|
|
8257
|
+
var SESSION_LOGS_BASE = join4(homedir3(), ".llmist", "logs");
|
|
8258
|
+
function findUniqueName(baseName) {
|
|
8259
|
+
const baseDir = join4(SESSION_LOGS_BASE, baseName);
|
|
8260
|
+
if (!existsSync4(baseDir)) {
|
|
8261
|
+
return baseName;
|
|
8262
|
+
}
|
|
8263
|
+
let suffix = 2;
|
|
8264
|
+
while (suffix < 1e3) {
|
|
8265
|
+
const name = `${baseName}-${suffix}`;
|
|
8266
|
+
const dir = join4(SESSION_LOGS_BASE, name);
|
|
8267
|
+
if (!existsSync4(dir)) {
|
|
8268
|
+
return name;
|
|
8269
|
+
}
|
|
8270
|
+
suffix++;
|
|
8271
|
+
}
|
|
8272
|
+
return `${baseName}-${Date.now()}`;
|
|
8273
|
+
}
|
|
8274
|
+
async function initSession() {
|
|
8275
|
+
if (currentSession) {
|
|
8276
|
+
return currentSession;
|
|
8277
|
+
}
|
|
8278
|
+
const baseName = generateSessionName();
|
|
8279
|
+
const name = findUniqueName(baseName);
|
|
8280
|
+
const logDir = join4(SESSION_LOGS_BASE, name);
|
|
8281
|
+
await mkdir2(logDir, { recursive: true });
|
|
8282
|
+
currentSession = { name, logDir };
|
|
8283
|
+
return currentSession;
|
|
8284
|
+
}
|
|
8285
|
+
|
|
8001
8286
|
// src/speech-command.ts
|
|
8002
8287
|
import { writeFileSync as writeFileSync3 } from "fs";
|
|
8003
8288
|
var DEFAULT_SPEECH_MODEL = "tts-1";
|
|
@@ -8091,7 +8376,7 @@ function parseLogLevel(value) {
|
|
|
8091
8376
|
}
|
|
8092
8377
|
function createProgram(env, config) {
|
|
8093
8378
|
const program = new Command();
|
|
8094
|
-
program.name(CLI_NAME).description(CLI_DESCRIPTION).version(package_default.version).option(OPTION_FLAGS.logLevel, OPTION_DESCRIPTIONS.logLevel, parseLogLevel).
|
|
8379
|
+
program.name(CLI_NAME).description(CLI_DESCRIPTION).version(package_default.version).option(OPTION_FLAGS.logLevel, OPTION_DESCRIPTIONS.logLevel, parseLogLevel).configureOutput({
|
|
8095
8380
|
writeOut: (str) => env.stdout.write(str),
|
|
8096
8381
|
writeErr: (str) => env.stderr.write(str)
|
|
8097
8382
|
});
|
|
@@ -8103,6 +8388,7 @@ function createProgram(env, config) {
|
|
|
8103
8388
|
registerModelsCommand(program, env);
|
|
8104
8389
|
registerGadgetCommand(program, env);
|
|
8105
8390
|
registerInitCommand(program, env);
|
|
8391
|
+
registerConfigCommand(program, env, config);
|
|
8106
8392
|
if (config) {
|
|
8107
8393
|
const customNames = getCustomCommandNames(config);
|
|
8108
8394
|
for (const name of customNames) {
|
|
@@ -8116,19 +8402,19 @@ async function runCLI(overrides = {}) {
|
|
|
8116
8402
|
const opts = "env" in overrides || "config" in overrides ? overrides : { env: overrides };
|
|
8117
8403
|
const config = opts.config !== void 0 ? opts.config : loadConfig();
|
|
8118
8404
|
const envOverrides = opts.env ?? {};
|
|
8405
|
+
const session = await initSession();
|
|
8119
8406
|
const preParser = new Command();
|
|
8120
|
-
preParser.option(OPTION_FLAGS.logLevel, OPTION_DESCRIPTIONS.logLevel, parseLogLevel).
|
|
8407
|
+
preParser.option(OPTION_FLAGS.logLevel, OPTION_DESCRIPTIONS.logLevel, parseLogLevel).allowUnknownOption().allowExcessArguments().helpOption(false);
|
|
8121
8408
|
preParser.parse(process.argv);
|
|
8122
8409
|
const globalOpts = preParser.opts();
|
|
8123
8410
|
const loggerConfig = {
|
|
8124
|
-
logLevel: globalOpts.logLevel ?? config.global?.["log-level"]
|
|
8125
|
-
logFile: globalOpts.logFile ?? config.global?.["log-file"],
|
|
8126
|
-
logReset: globalOpts.logReset ?? config.global?.["log-reset"]
|
|
8411
|
+
logLevel: globalOpts.logLevel ?? config.global?.["log-level"]
|
|
8127
8412
|
};
|
|
8128
|
-
const defaultEnv = createDefaultEnvironment(loggerConfig);
|
|
8413
|
+
const defaultEnv = createDefaultEnvironment(loggerConfig, session.logDir);
|
|
8129
8414
|
const env = {
|
|
8130
8415
|
...defaultEnv,
|
|
8131
|
-
...envOverrides
|
|
8416
|
+
...envOverrides,
|
|
8417
|
+
session
|
|
8132
8418
|
};
|
|
8133
8419
|
const program = createProgram(env, config);
|
|
8134
8420
|
await program.parseAsync(env.argv);
|