llmist 4.0.0 → 5.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/{chunk-Q6NQRMYD.js → chunk-F5QK5YVI.js} +2 -2
- package/dist/{chunk-RHR2M6T6.js → chunk-YJKUWFIC.js} +28 -8
- package/dist/chunk-YJKUWFIC.js.map +1 -0
- package/dist/cli.cjs +533 -250
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +478 -215
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +27 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/{mock-stream-BvNYtrlG.d.cts → mock-stream-CAY53Q6u.d.cts} +23 -2
- package/dist/{mock-stream-BvNYtrlG.d.ts → mock-stream-CAY53Q6u.d.ts} +23 -2
- package/dist/testing/index.cjs +27 -7
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +2 -2
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +1 -1
- package/package.json +3 -2
- package/dist/chunk-RHR2M6T6.js.map +0 -1
- /package/dist/{chunk-Q6NQRMYD.js.map → chunk-F5QK5YVI.js.map} +0 -0
package/dist/cli.cjs
CHANGED
|
@@ -4952,15 +4952,16 @@ var init_agent = __esm({
|
|
|
4952
4952
|
});
|
|
4953
4953
|
} else if (event.type === "llm_call_end") {
|
|
4954
4954
|
const info = event.event;
|
|
4955
|
+
const usage = info.usage ?? (info.outputTokens ? {
|
|
4956
|
+
inputTokens: info.inputTokens ?? 0,
|
|
4957
|
+
outputTokens: info.outputTokens,
|
|
4958
|
+
totalTokens: (info.inputTokens ?? 0) + info.outputTokens
|
|
4959
|
+
} : void 0);
|
|
4955
4960
|
void this.hooks?.observers?.onLLMCallComplete?.({
|
|
4956
4961
|
iteration: info.iteration,
|
|
4957
4962
|
options: { model: info.model, messages: [] },
|
|
4958
4963
|
finishReason: info.finishReason ?? null,
|
|
4959
|
-
usage
|
|
4960
|
-
inputTokens: info.inputTokens ?? 0,
|
|
4961
|
-
outputTokens: info.outputTokens,
|
|
4962
|
-
totalTokens: (info.inputTokens ?? 0) + info.outputTokens
|
|
4963
|
-
} : void 0,
|
|
4964
|
+
usage,
|
|
4964
4965
|
rawResponse: "",
|
|
4965
4966
|
finalMessage: "",
|
|
4966
4967
|
logger: this.logger,
|
|
@@ -7003,6 +7004,9 @@ var init_gemini = __esm({
|
|
|
7003
7004
|
async countTokens(messages, descriptor, _spec) {
|
|
7004
7005
|
const client = this.client;
|
|
7005
7006
|
const contents = this.convertMessagesToContents(messages);
|
|
7007
|
+
if (!contents || contents.length === 0) {
|
|
7008
|
+
return 0;
|
|
7009
|
+
}
|
|
7006
7010
|
try {
|
|
7007
7011
|
const response = await client.models.countTokens({
|
|
7008
7012
|
model: descriptor.name,
|
|
@@ -9475,13 +9479,24 @@ ${endPrefix}`
|
|
|
9475
9479
|
observers: {
|
|
9476
9480
|
...hooks?.observers,
|
|
9477
9481
|
onLLMCallStart: async (context) => {
|
|
9482
|
+
let inputTokens;
|
|
9483
|
+
try {
|
|
9484
|
+
if (this.client) {
|
|
9485
|
+
inputTokens = await this.client.countTokens(
|
|
9486
|
+
context.options.model,
|
|
9487
|
+
context.options.messages
|
|
9488
|
+
);
|
|
9489
|
+
}
|
|
9490
|
+
} catch {
|
|
9491
|
+
}
|
|
9478
9492
|
onSubagentEvent({
|
|
9479
9493
|
type: "llm_call_start",
|
|
9480
9494
|
gadgetInvocationId: invocationId,
|
|
9481
9495
|
depth,
|
|
9482
9496
|
event: {
|
|
9483
9497
|
iteration: context.iteration,
|
|
9484
|
-
model: context.options.model
|
|
9498
|
+
model: context.options.model,
|
|
9499
|
+
inputTokens
|
|
9485
9500
|
}
|
|
9486
9501
|
});
|
|
9487
9502
|
if (existingOnLLMCallStart) {
|
|
@@ -9496,8 +9511,13 @@ ${endPrefix}`
|
|
|
9496
9511
|
event: {
|
|
9497
9512
|
iteration: context.iteration,
|
|
9498
9513
|
model: context.options.model,
|
|
9514
|
+
// Backward compat fields
|
|
9515
|
+
inputTokens: context.usage?.inputTokens,
|
|
9499
9516
|
outputTokens: context.usage?.outputTokens,
|
|
9500
|
-
finishReason: context.finishReason
|
|
9517
|
+
finishReason: context.finishReason ?? void 0,
|
|
9518
|
+
// Full usage object with cache details (for first-class display)
|
|
9519
|
+
usage: context.usage
|
|
9520
|
+
// Cost will be calculated by parent if it has model registry
|
|
9501
9521
|
}
|
|
9502
9522
|
});
|
|
9503
9523
|
if (existingOnLLMCallComplete) {
|
|
@@ -9896,7 +9916,6 @@ var OPTION_FLAGS = {
|
|
|
9896
9916
|
docker: "--docker",
|
|
9897
9917
|
dockerRo: "--docker-ro",
|
|
9898
9918
|
noDocker: "--no-docker",
|
|
9899
|
-
dockerDev: "--docker-dev",
|
|
9900
9919
|
// Multimodal input options
|
|
9901
9920
|
inputImage: "--image <path>",
|
|
9902
9921
|
inputAudio: "--audio <path>",
|
|
@@ -9931,7 +9950,6 @@ var OPTION_DESCRIPTIONS = {
|
|
|
9931
9950
|
docker: "Run agent in a Docker sandbox container for security isolation.",
|
|
9932
9951
|
dockerRo: "Run in Docker with current directory mounted read-only.",
|
|
9933
9952
|
noDocker: "Disable Docker sandboxing (override config).",
|
|
9934
|
-
dockerDev: "Run in Docker dev mode (mount local source instead of npm install).",
|
|
9935
9953
|
// Image generation descriptions
|
|
9936
9954
|
imageSize: "Image size/aspect ratio, e.g. '1024x1024', '1:1', '16:9'.",
|
|
9937
9955
|
imageQuality: "Image quality: 'standard', 'hd', 'low', 'medium', 'high'.",
|
|
@@ -9951,7 +9969,7 @@ var import_commander2 = require("commander");
|
|
|
9951
9969
|
// package.json
|
|
9952
9970
|
var package_default = {
|
|
9953
9971
|
name: "llmist",
|
|
9954
|
-
version: "
|
|
9972
|
+
version: "5.1.0",
|
|
9955
9973
|
description: "TypeScript LLM client with streaming tool execution. Tools fire mid-stream. Built-in function calling works with any model\u2014no structured outputs or native tool support required.",
|
|
9956
9974
|
type: "module",
|
|
9957
9975
|
main: "dist/index.cjs",
|
|
@@ -9994,7 +10012,8 @@ var package_default = {
|
|
|
9994
10012
|
"test:all": "bun run test && bun run test:e2e",
|
|
9995
10013
|
clean: "rimraf dist",
|
|
9996
10014
|
prepare: "node scripts/install-hooks.js || true",
|
|
9997
|
-
"release:dry": "bunx semantic-release --dry-run"
|
|
10015
|
+
"release:dry": "bunx semantic-release --dry-run",
|
|
10016
|
+
"release:publish": 'test "$(git branch --show-current)" = "main" && git pull origin main && bun run build && npm publish'
|
|
9998
10017
|
},
|
|
9999
10018
|
bin: {
|
|
10000
10019
|
llmist: "dist/cli.js"
|
|
@@ -11353,20 +11372,17 @@ var DOCKER_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
11353
11372
|
"mounts",
|
|
11354
11373
|
"env-vars",
|
|
11355
11374
|
"image-name",
|
|
11356
|
-
"dev-mode",
|
|
11357
|
-
"dev-source",
|
|
11358
11375
|
"docker-args"
|
|
11359
11376
|
]);
|
|
11360
11377
|
var DEFAULT_IMAGE_NAME = "llmist-sandbox";
|
|
11361
11378
|
var DEFAULT_CWD_PERMISSION = "rw";
|
|
11362
11379
|
var DEFAULT_CONFIG_PERMISSION = "ro";
|
|
11380
|
+
var GADGET_CACHE_VOLUME = "llmist-gadget-cache";
|
|
11363
11381
|
var FORWARDED_API_KEYS = [
|
|
11364
11382
|
"ANTHROPIC_API_KEY",
|
|
11365
11383
|
"OPENAI_API_KEY",
|
|
11366
11384
|
"GEMINI_API_KEY"
|
|
11367
11385
|
];
|
|
11368
|
-
var DEV_IMAGE_NAME = "llmist-dev-sandbox";
|
|
11369
|
-
var DEV_SOURCE_MOUNT_TARGET = "/llmist-src";
|
|
11370
11386
|
|
|
11371
11387
|
// src/cli/docker/docker-config.ts
|
|
11372
11388
|
var MOUNT_CONFIG_KEYS = /* @__PURE__ */ new Set(["source", "target", "permission"]);
|
|
@@ -11478,12 +11494,6 @@ function validateDockerConfig(raw, section) {
|
|
|
11478
11494
|
if ("image-name" in rawObj) {
|
|
11479
11495
|
result["image-name"] = validateString2(rawObj["image-name"], "image-name", section);
|
|
11480
11496
|
}
|
|
11481
|
-
if ("dev-mode" in rawObj) {
|
|
11482
|
-
result["dev-mode"] = validateBoolean2(rawObj["dev-mode"], "dev-mode", section);
|
|
11483
|
-
}
|
|
11484
|
-
if ("dev-source" in rawObj) {
|
|
11485
|
-
result["dev-source"] = validateString2(rawObj["dev-source"], "dev-source", section);
|
|
11486
|
-
}
|
|
11487
11497
|
if ("docker-args" in rawObj) {
|
|
11488
11498
|
result["docker-args"] = validateStringArray2(rawObj["docker-args"], "docker-args", section);
|
|
11489
11499
|
}
|
|
@@ -11493,7 +11503,6 @@ function validateDockerConfig(raw, section) {
|
|
|
11493
11503
|
// src/cli/docker/docker-wrapper.ts
|
|
11494
11504
|
var import_node_fs5 = require("fs");
|
|
11495
11505
|
var import_node_os4 = require("os");
|
|
11496
|
-
var import_node_path6 = require("path");
|
|
11497
11506
|
|
|
11498
11507
|
// src/cli/docker/dockerfile.ts
|
|
11499
11508
|
var DEFAULT_DOCKERFILE = `# llmist sandbox image
|
|
@@ -11513,6 +11522,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \\
|
|
|
11513
11522
|
curl \\
|
|
11514
11523
|
# ca-certificates for HTTPS
|
|
11515
11524
|
ca-certificates \\
|
|
11525
|
+
# python3 for native module compilation (node-gyp)
|
|
11526
|
+
python3 \\
|
|
11527
|
+
# build-essential for compiling native modules
|
|
11528
|
+
build-essential \\
|
|
11516
11529
|
&& rm -rf /var/lib/apt/lists/*
|
|
11517
11530
|
|
|
11518
11531
|
# Install ast-grep for code search/refactoring
|
|
@@ -11530,37 +11543,8 @@ WORKDIR /workspace
|
|
|
11530
11543
|
# Entry point - llmist with all arguments forwarded
|
|
11531
11544
|
ENTRYPOINT ["llmist"]
|
|
11532
11545
|
`;
|
|
11533
|
-
|
|
11534
|
-
|
|
11535
|
-
|
|
11536
|
-
FROM oven/bun:1-debian
|
|
11537
|
-
|
|
11538
|
-
# Install essential tools (same as production)
|
|
11539
|
-
RUN apt-get update && apt-get install -y --no-install-recommends \\
|
|
11540
|
-
ed \\
|
|
11541
|
-
ripgrep \\
|
|
11542
|
-
git \\
|
|
11543
|
-
curl \\
|
|
11544
|
-
ca-certificates \\
|
|
11545
|
-
&& rm -rf /var/lib/apt/lists/*
|
|
11546
|
-
|
|
11547
|
-
# Install ast-grep for code search/refactoring
|
|
11548
|
-
RUN curl -fsSL https://raw.githubusercontent.com/ast-grep/ast-grep/main/install.sh | bash \\
|
|
11549
|
-
&& mv /root/.local/bin/ast-grep /usr/local/bin/ 2>/dev/null || true \\
|
|
11550
|
-
&& mv /root/.local/bin/sg /usr/local/bin/ 2>/dev/null || true
|
|
11551
|
-
|
|
11552
|
-
# Working directory (host CWD will be mounted here)
|
|
11553
|
-
WORKDIR /workspace
|
|
11554
|
-
|
|
11555
|
-
# Entry point - run llmist from mounted source
|
|
11556
|
-
# Source is mounted at ${DEV_SOURCE_MOUNT_TARGET}
|
|
11557
|
-
ENTRYPOINT ["bun", "run", "${DEV_SOURCE_MOUNT_TARGET}/src/cli.ts"]
|
|
11558
|
-
`;
|
|
11559
|
-
function resolveDockerfile(config, devMode = false) {
|
|
11560
|
-
if (config.dockerfile) {
|
|
11561
|
-
return config.dockerfile;
|
|
11562
|
-
}
|
|
11563
|
-
return devMode ? DEV_DOCKERFILE : DEFAULT_DOCKERFILE;
|
|
11546
|
+
function resolveDockerfile(config) {
|
|
11547
|
+
return config.dockerfile ?? DEFAULT_DOCKERFILE;
|
|
11564
11548
|
}
|
|
11565
11549
|
function computeDockerfileHash(dockerfile) {
|
|
11566
11550
|
const encoder = new TextEncoder();
|
|
@@ -11622,10 +11606,13 @@ async function buildImage(imageName, dockerfile) {
|
|
|
11622
11606
|
ensureCacheDir();
|
|
11623
11607
|
const dockerfilePath = (0, import_node_path5.join)(CACHE_DIR, "Dockerfile");
|
|
11624
11608
|
(0, import_node_fs4.writeFileSync)(dockerfilePath, dockerfile);
|
|
11625
|
-
const proc = Bun.spawn(
|
|
11626
|
-
|
|
11627
|
-
|
|
11628
|
-
|
|
11609
|
+
const proc = Bun.spawn(
|
|
11610
|
+
["docker", "build", "--no-cache", "-t", imageName, "-f", dockerfilePath, CACHE_DIR],
|
|
11611
|
+
{
|
|
11612
|
+
stdout: "pipe",
|
|
11613
|
+
stderr: "pipe"
|
|
11614
|
+
}
|
|
11615
|
+
);
|
|
11629
11616
|
const exitCode = await proc.exited;
|
|
11630
11617
|
const stdout = await new Response(proc.stdout).text();
|
|
11631
11618
|
const stderr = await new Response(proc.stderr).text();
|
|
@@ -11687,46 +11674,13 @@ function isInsideContainer() {
|
|
|
11687
11674
|
}
|
|
11688
11675
|
return false;
|
|
11689
11676
|
}
|
|
11690
|
-
function autoDetectDevSource() {
|
|
11691
|
-
const scriptPath = process.argv[1];
|
|
11692
|
-
if (!scriptPath || !scriptPath.endsWith("src/cli.ts")) {
|
|
11693
|
-
return void 0;
|
|
11694
|
-
}
|
|
11695
|
-
const srcDir = (0, import_node_path6.dirname)(scriptPath);
|
|
11696
|
-
const projectDir = (0, import_node_path6.dirname)(srcDir);
|
|
11697
|
-
const packageJsonPath = (0, import_node_path6.join)(projectDir, "package.json");
|
|
11698
|
-
if (!(0, import_node_fs5.existsSync)(packageJsonPath)) {
|
|
11699
|
-
return void 0;
|
|
11700
|
-
}
|
|
11701
|
-
try {
|
|
11702
|
-
const pkg = JSON.parse((0, import_node_fs5.readFileSync)(packageJsonPath, "utf-8"));
|
|
11703
|
-
if (pkg.name === "llmist") {
|
|
11704
|
-
return projectDir;
|
|
11705
|
-
}
|
|
11706
|
-
} catch {
|
|
11707
|
-
}
|
|
11708
|
-
return void 0;
|
|
11709
|
-
}
|
|
11710
|
-
function resolveDevMode(config, cliDevMode) {
|
|
11711
|
-
const enabled = cliDevMode || config?.["dev-mode"] || process.env.LLMIST_DEV_MODE === "1";
|
|
11712
|
-
if (!enabled) {
|
|
11713
|
-
return { enabled: false, sourcePath: void 0 };
|
|
11714
|
-
}
|
|
11715
|
-
const sourcePath = config?.["dev-source"] || process.env.LLMIST_DEV_SOURCE || autoDetectDevSource();
|
|
11716
|
-
if (!sourcePath) {
|
|
11717
|
-
throw new Error(
|
|
11718
|
-
"Docker dev mode enabled but llmist source path not found. Set [docker].dev-source in config, LLMIST_DEV_SOURCE env var, or run from the llmist source directory (bun src/cli.ts)."
|
|
11719
|
-
);
|
|
11720
|
-
}
|
|
11721
|
-
return { enabled: true, sourcePath };
|
|
11722
|
-
}
|
|
11723
11677
|
function expandHome(path6) {
|
|
11724
11678
|
if (path6.startsWith("~")) {
|
|
11725
11679
|
return path6.replace(/^~/, (0, import_node_os4.homedir)());
|
|
11726
11680
|
}
|
|
11727
11681
|
return path6;
|
|
11728
11682
|
}
|
|
11729
|
-
function buildDockerRunArgs(ctx, imageName
|
|
11683
|
+
function buildDockerRunArgs(ctx, imageName) {
|
|
11730
11684
|
const args = ["run", "--rm"];
|
|
11731
11685
|
const timestamp = Date.now();
|
|
11732
11686
|
const random = Math.random().toString(36).slice(2, 8);
|
|
@@ -11740,11 +11694,15 @@ function buildDockerRunArgs(ctx, imageName, devMode) {
|
|
|
11740
11694
|
args.push("-w", "/workspace");
|
|
11741
11695
|
const configPermission = ctx.config["config-permission"] ?? DEFAULT_CONFIG_PERMISSION;
|
|
11742
11696
|
const llmistDir = expandHome("~/.llmist");
|
|
11743
|
-
|
|
11744
|
-
if (
|
|
11745
|
-
|
|
11746
|
-
|
|
11697
|
+
const cliTomlPath = `${llmistDir}/cli.toml`;
|
|
11698
|
+
if ((0, import_node_fs5.existsSync)(cliTomlPath)) {
|
|
11699
|
+
args.push("-v", `${cliTomlPath}:/root/.llmist/cli.toml:${configPermission}`);
|
|
11700
|
+
}
|
|
11701
|
+
const gadgetsDir = `${llmistDir}/gadgets`;
|
|
11702
|
+
if ((0, import_node_fs5.existsSync)(gadgetsDir)) {
|
|
11703
|
+
args.push("-v", `${gadgetsDir}:/root/.llmist/gadgets:${configPermission}`);
|
|
11747
11704
|
}
|
|
11705
|
+
args.push("-v", `${GADGET_CACHE_VOLUME}:/root/.llmist/gadget-cache`);
|
|
11748
11706
|
if (ctx.config.mounts) {
|
|
11749
11707
|
for (const mount of ctx.config.mounts) {
|
|
11750
11708
|
const source = expandHome(mount.source);
|
|
@@ -11771,7 +11729,7 @@ function buildDockerRunArgs(ctx, imageName, devMode) {
|
|
|
11771
11729
|
return args;
|
|
11772
11730
|
}
|
|
11773
11731
|
function filterDockerArgs(argv) {
|
|
11774
|
-
const dockerFlags = /* @__PURE__ */ new Set(["--docker", "--docker-ro", "--no-docker"
|
|
11732
|
+
const dockerFlags = /* @__PURE__ */ new Set(["--docker", "--docker-ro", "--no-docker"]);
|
|
11775
11733
|
return argv.filter((arg) => !dockerFlags.has(arg));
|
|
11776
11734
|
}
|
|
11777
11735
|
function resolveDockerEnabled(config, options, profileDocker) {
|
|
@@ -11786,22 +11744,16 @@ function resolveDockerEnabled(config, options, profileDocker) {
|
|
|
11786
11744
|
}
|
|
11787
11745
|
return config?.enabled ?? false;
|
|
11788
11746
|
}
|
|
11789
|
-
async function executeInDocker(ctx
|
|
11747
|
+
async function executeInDocker(ctx) {
|
|
11790
11748
|
if (isInsideContainer()) {
|
|
11791
|
-
console.error(
|
|
11792
|
-
"Warning: Docker mode requested but already inside a container. Proceeding without re-containerization."
|
|
11793
|
-
);
|
|
11794
11749
|
throw new DockerSkipError();
|
|
11795
11750
|
}
|
|
11796
11751
|
const available = await checkDockerAvailable();
|
|
11797
11752
|
if (!available) {
|
|
11798
11753
|
throw new DockerUnavailableError();
|
|
11799
11754
|
}
|
|
11800
|
-
const dockerfile = resolveDockerfile(ctx.config
|
|
11801
|
-
const imageName =
|
|
11802
|
-
if (devMode.enabled) {
|
|
11803
|
-
console.error(`[dev mode] Mounting source from ${devMode.sourcePath}`);
|
|
11804
|
-
}
|
|
11755
|
+
const dockerfile = resolveDockerfile(ctx.config);
|
|
11756
|
+
const imageName = ctx.config["image-name"] ?? DEFAULT_IMAGE_NAME;
|
|
11805
11757
|
try {
|
|
11806
11758
|
await ensureImage(imageName, dockerfile);
|
|
11807
11759
|
} catch (error) {
|
|
@@ -11812,7 +11764,7 @@ async function executeInDocker(ctx, devMode) {
|
|
|
11812
11764
|
}
|
|
11813
11765
|
throw error;
|
|
11814
11766
|
}
|
|
11815
|
-
const dockerArgs = buildDockerRunArgs(ctx, imageName
|
|
11767
|
+
const dockerArgs = buildDockerRunArgs(ctx, imageName);
|
|
11816
11768
|
const proc = Bun.spawn(["docker", ...dockerArgs], {
|
|
11817
11769
|
stdin: "inherit",
|
|
11818
11770
|
stdout: "inherit",
|
|
@@ -11833,7 +11785,7 @@ function createDockerContext(config, options, argv, cwd, profileCwdPermission) {
|
|
|
11833
11785
|
|
|
11834
11786
|
// src/cli/file-utils.ts
|
|
11835
11787
|
var import_promises3 = require("fs/promises");
|
|
11836
|
-
var
|
|
11788
|
+
var import_node_path6 = require("path");
|
|
11837
11789
|
init_input_content();
|
|
11838
11790
|
var DEFAULT_MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
11839
11791
|
function formatFileSize(bytes) {
|
|
@@ -11851,7 +11803,7 @@ async function checkFileSize(absolutePath, filePath, maxSize) {
|
|
|
11851
11803
|
}
|
|
11852
11804
|
}
|
|
11853
11805
|
async function readImageFile(filePath, options = {}) {
|
|
11854
|
-
const absolutePath = (0,
|
|
11806
|
+
const absolutePath = (0, import_node_path6.resolve)(filePath);
|
|
11855
11807
|
const maxFileSize = options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
|
|
11856
11808
|
let buffer;
|
|
11857
11809
|
try {
|
|
@@ -11870,7 +11822,7 @@ async function readImageFile(filePath, options = {}) {
|
|
|
11870
11822
|
return imageFromBuffer(buffer, mimeType);
|
|
11871
11823
|
}
|
|
11872
11824
|
async function readAudioFile(filePath, options = {}) {
|
|
11873
|
-
const absolutePath = (0,
|
|
11825
|
+
const absolutePath = (0, import_node_path6.resolve)(filePath);
|
|
11874
11826
|
const maxFileSize = options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
|
|
11875
11827
|
let buffer;
|
|
11876
11828
|
try {
|
|
@@ -11889,7 +11841,7 @@ async function readAudioFile(filePath, options = {}) {
|
|
|
11889
11841
|
return audioFromBuffer(buffer, mimeType);
|
|
11890
11842
|
}
|
|
11891
11843
|
async function readFileBuffer(filePath, options = {}) {
|
|
11892
|
-
const absolutePath = (0,
|
|
11844
|
+
const absolutePath = (0, import_node_path6.resolve)(filePath);
|
|
11893
11845
|
const maxFileSize = options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
|
|
11894
11846
|
try {
|
|
11895
11847
|
await checkFileSize(absolutePath, filePath, maxFileSize);
|
|
@@ -11902,7 +11854,7 @@ async function readFileBuffer(filePath, options = {}) {
|
|
|
11902
11854
|
|
|
11903
11855
|
// src/cli/gadgets.ts
|
|
11904
11856
|
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
11905
|
-
var
|
|
11857
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
11906
11858
|
var import_node_url2 = require("url");
|
|
11907
11859
|
init_gadget();
|
|
11908
11860
|
|
|
@@ -11982,7 +11934,7 @@ init_gadget();
|
|
|
11982
11934
|
|
|
11983
11935
|
// src/cli/builtins/filesystem/utils.ts
|
|
11984
11936
|
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
11985
|
-
var
|
|
11937
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
11986
11938
|
var PathSandboxException = class extends Error {
|
|
11987
11939
|
constructor(inputPath, reason) {
|
|
11988
11940
|
super(`Path access denied: ${inputPath}. ${reason}`);
|
|
@@ -11991,7 +11943,7 @@ var PathSandboxException = class extends Error {
|
|
|
11991
11943
|
};
|
|
11992
11944
|
function validatePathIsWithinCwd(inputPath) {
|
|
11993
11945
|
const cwd = process.cwd();
|
|
11994
|
-
const resolvedPath =
|
|
11946
|
+
const resolvedPath = import_node_path7.default.resolve(cwd, inputPath);
|
|
11995
11947
|
let finalPath;
|
|
11996
11948
|
try {
|
|
11997
11949
|
finalPath = import_node_fs6.default.realpathSync(resolvedPath);
|
|
@@ -12003,7 +11955,7 @@ function validatePathIsWithinCwd(inputPath) {
|
|
|
12003
11955
|
throw error;
|
|
12004
11956
|
}
|
|
12005
11957
|
}
|
|
12006
|
-
const cwdWithSep = cwd +
|
|
11958
|
+
const cwdWithSep = cwd + import_node_path7.default.sep;
|
|
12007
11959
|
if (!finalPath.startsWith(cwdWithSep) && finalPath !== cwd) {
|
|
12008
11960
|
throw new PathSandboxException(inputPath, "Path is outside the current working directory");
|
|
12009
11961
|
}
|
|
@@ -12106,15 +12058,15 @@ error: ${message}`;
|
|
|
12106
12058
|
|
|
12107
12059
|
// src/cli/builtins/filesystem/list-directory.ts
|
|
12108
12060
|
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
12109
|
-
var
|
|
12061
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
12110
12062
|
var import_zod5 = require("zod");
|
|
12111
12063
|
function listFiles(dirPath, basePath = dirPath, maxDepth = 1, currentDepth = 1) {
|
|
12112
12064
|
const entries = [];
|
|
12113
12065
|
try {
|
|
12114
12066
|
const items = import_node_fs7.default.readdirSync(dirPath);
|
|
12115
12067
|
for (const item of items) {
|
|
12116
|
-
const fullPath =
|
|
12117
|
-
const relativePath =
|
|
12068
|
+
const fullPath = import_node_path8.default.join(dirPath, item);
|
|
12069
|
+
const relativePath = import_node_path8.default.relative(basePath, fullPath);
|
|
12118
12070
|
try {
|
|
12119
12071
|
const stats = import_node_fs7.default.lstatSync(fullPath);
|
|
12120
12072
|
let type;
|
|
@@ -12258,7 +12210,7 @@ ${content}`;
|
|
|
12258
12210
|
|
|
12259
12211
|
// src/cli/builtins/filesystem/write-file.ts
|
|
12260
12212
|
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
12261
|
-
var
|
|
12213
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
12262
12214
|
var import_zod7 = require("zod");
|
|
12263
12215
|
var writeFile2 = createGadget({
|
|
12264
12216
|
name: "WriteFile",
|
|
@@ -12293,7 +12245,7 @@ console.log(\`Server running on http://localhost:\${port}\`);`
|
|
|
12293
12245
|
],
|
|
12294
12246
|
execute: ({ filePath, content }) => {
|
|
12295
12247
|
const validatedPath = validatePathIsWithinCwd(filePath);
|
|
12296
|
-
const parentDir =
|
|
12248
|
+
const parentDir = import_node_path9.default.dirname(validatedPath);
|
|
12297
12249
|
let createdDir = false;
|
|
12298
12250
|
if (!import_node_fs9.default.existsSync(parentDir)) {
|
|
12299
12251
|
validatePathIsWithinCwd(parentDir);
|
|
@@ -12302,7 +12254,7 @@ console.log(\`Server running on http://localhost:\${port}\`);`
|
|
|
12302
12254
|
}
|
|
12303
12255
|
import_node_fs9.default.writeFileSync(validatedPath, content, "utf-8");
|
|
12304
12256
|
const bytesWritten = Buffer.byteLength(content, "utf-8");
|
|
12305
|
-
const dirNote = createdDir ? ` (created directory: ${
|
|
12257
|
+
const dirNote = createdDir ? ` (created directory: ${import_node_path9.default.dirname(filePath)})` : "";
|
|
12306
12258
|
return `path=${filePath}
|
|
12307
12259
|
|
|
12308
12260
|
Wrote ${bytesWritten} bytes${dirNote}`;
|
|
@@ -12431,10 +12383,10 @@ function isBuiltinGadgetName(name) {
|
|
|
12431
12383
|
// src/cli/external-gadgets.ts
|
|
12432
12384
|
var import_node_child_process = require("child_process");
|
|
12433
12385
|
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
12434
|
-
var
|
|
12386
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
12435
12387
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
12436
12388
|
var import_node_url = require("url");
|
|
12437
|
-
var CACHE_DIR2 =
|
|
12389
|
+
var CACHE_DIR2 = import_node_path10.default.join(import_node_os5.default.homedir(), ".llmist", "gadget-cache");
|
|
12438
12390
|
function isExternalPackageSpecifier(specifier) {
|
|
12439
12391
|
if (/^@?[a-z0-9][\w.-]*(?:@[\w.-]+)?(?::[a-z]+)?(?:\/\w+)?$/i.test(specifier)) {
|
|
12440
12392
|
return true;
|
|
@@ -12472,13 +12424,13 @@ function parseGadgetSpecifier(specifier) {
|
|
|
12472
12424
|
function getCacheDir(spec) {
|
|
12473
12425
|
const versionSuffix = spec.version ? `@${spec.version}` : "@latest";
|
|
12474
12426
|
if (spec.type === "npm") {
|
|
12475
|
-
return
|
|
12427
|
+
return import_node_path10.default.join(CACHE_DIR2, "npm", `${spec.package}${versionSuffix}`);
|
|
12476
12428
|
}
|
|
12477
12429
|
const sanitizedUrl = spec.package.replace(/[/:]/g, "-").replace(/^-+|-+$/g, "");
|
|
12478
|
-
return
|
|
12430
|
+
return import_node_path10.default.join(CACHE_DIR2, "git", `${sanitizedUrl}${versionSuffix}`);
|
|
12479
12431
|
}
|
|
12480
12432
|
function isCached(cacheDir) {
|
|
12481
|
-
const packageJsonPath =
|
|
12433
|
+
const packageJsonPath = import_node_path10.default.join(cacheDir, "package.json");
|
|
12482
12434
|
return import_node_fs10.default.existsSync(packageJsonPath);
|
|
12483
12435
|
}
|
|
12484
12436
|
async function installNpmPackage(spec, cacheDir) {
|
|
@@ -12488,10 +12440,10 @@ async function installNpmPackage(spec, cacheDir) {
|
|
|
12488
12440
|
private: true,
|
|
12489
12441
|
type: "module"
|
|
12490
12442
|
};
|
|
12491
|
-
import_node_fs10.default.writeFileSync(
|
|
12443
|
+
import_node_fs10.default.writeFileSync(import_node_path10.default.join(cacheDir, "package.json"), JSON.stringify(packageJson, null, 2));
|
|
12492
12444
|
const packageSpec = spec.version ? `${spec.package}@${spec.version}` : spec.package;
|
|
12493
12445
|
try {
|
|
12494
|
-
(0, import_node_child_process.execSync)(`
|
|
12446
|
+
(0, import_node_child_process.execSync)(`bun add "${packageSpec}"`, {
|
|
12495
12447
|
stdio: "pipe",
|
|
12496
12448
|
cwd: cacheDir
|
|
12497
12449
|
});
|
|
@@ -12501,7 +12453,7 @@ async function installNpmPackage(spec, cacheDir) {
|
|
|
12501
12453
|
}
|
|
12502
12454
|
}
|
|
12503
12455
|
async function installGitPackage(spec, cacheDir) {
|
|
12504
|
-
import_node_fs10.default.mkdirSync(
|
|
12456
|
+
import_node_fs10.default.mkdirSync(import_node_path10.default.dirname(cacheDir), { recursive: true });
|
|
12505
12457
|
if (import_node_fs10.default.existsSync(cacheDir)) {
|
|
12506
12458
|
try {
|
|
12507
12459
|
(0, import_node_child_process.execSync)("git fetch", { cwd: cacheDir, stdio: "pipe" });
|
|
@@ -12520,17 +12472,17 @@ async function installGitPackage(spec, cacheDir) {
|
|
|
12520
12472
|
const message = error instanceof Error ? error.message : String(error);
|
|
12521
12473
|
throw new Error(`Failed to clone git repository '${spec.package}': ${message}`);
|
|
12522
12474
|
}
|
|
12523
|
-
if (import_node_fs10.default.existsSync(
|
|
12475
|
+
if (import_node_fs10.default.existsSync(import_node_path10.default.join(cacheDir, "package.json"))) {
|
|
12524
12476
|
try {
|
|
12525
|
-
(0, import_node_child_process.execSync)("
|
|
12477
|
+
(0, import_node_child_process.execSync)("bun install", { cwd: cacheDir, stdio: "inherit" });
|
|
12526
12478
|
} catch (error) {
|
|
12527
12479
|
const message = error instanceof Error ? error.message : String(error);
|
|
12528
12480
|
throw new Error(`Failed to install dependencies for '${spec.package}': ${message}`);
|
|
12529
12481
|
}
|
|
12530
12482
|
try {
|
|
12531
|
-
const packageJson = JSON.parse(import_node_fs10.default.readFileSync(
|
|
12483
|
+
const packageJson = JSON.parse(import_node_fs10.default.readFileSync(import_node_path10.default.join(cacheDir, "package.json"), "utf-8"));
|
|
12532
12484
|
if (packageJson.scripts?.build) {
|
|
12533
|
-
(0, import_node_child_process.execSync)("
|
|
12485
|
+
(0, import_node_child_process.execSync)("bun run build", { cwd: cacheDir, stdio: "inherit" });
|
|
12534
12486
|
}
|
|
12535
12487
|
} catch (error) {
|
|
12536
12488
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -12540,7 +12492,7 @@ async function installGitPackage(spec, cacheDir) {
|
|
|
12540
12492
|
}
|
|
12541
12493
|
}
|
|
12542
12494
|
function readManifest(packageDir) {
|
|
12543
|
-
const packageJsonPath =
|
|
12495
|
+
const packageJsonPath = import_node_path10.default.join(packageDir, "package.json");
|
|
12544
12496
|
if (!import_node_fs10.default.existsSync(packageJsonPath)) {
|
|
12545
12497
|
return null;
|
|
12546
12498
|
}
|
|
@@ -12552,7 +12504,7 @@ function readManifest(packageDir) {
|
|
|
12552
12504
|
}
|
|
12553
12505
|
}
|
|
12554
12506
|
function getPackagePath(cacheDir, packageName) {
|
|
12555
|
-
const nodeModulesPath =
|
|
12507
|
+
const nodeModulesPath = import_node_path10.default.join(cacheDir, "node_modules", packageName);
|
|
12556
12508
|
if (import_node_fs10.default.existsSync(nodeModulesPath)) {
|
|
12557
12509
|
return nodeModulesPath;
|
|
12558
12510
|
}
|
|
@@ -12596,7 +12548,7 @@ async function loadExternalGadgets(specifier, forceInstall = false) {
|
|
|
12596
12548
|
} else {
|
|
12597
12549
|
entryPoint = manifest?.gadgets || "./dist/index.js";
|
|
12598
12550
|
}
|
|
12599
|
-
const resolvedEntryPoint =
|
|
12551
|
+
const resolvedEntryPoint = import_node_path10.default.resolve(packagePath, entryPoint);
|
|
12600
12552
|
if (!import_node_fs10.default.existsSync(resolvedEntryPoint)) {
|
|
12601
12553
|
throw new Error(
|
|
12602
12554
|
`Entry point not found: ${resolvedEntryPoint}. Make sure the package is built (run 'npm run build' in the package directory).`
|
|
@@ -12665,10 +12617,10 @@ function expandHomePath(input) {
|
|
|
12665
12617
|
if (!home) {
|
|
12666
12618
|
return input;
|
|
12667
12619
|
}
|
|
12668
|
-
return
|
|
12620
|
+
return import_node_path11.default.join(home, input.slice(1));
|
|
12669
12621
|
}
|
|
12670
12622
|
function isFileLikeSpecifier(specifier) {
|
|
12671
|
-
return PATH_PREFIXES.some((prefix) => specifier.startsWith(prefix)) || specifier.includes(
|
|
12623
|
+
return PATH_PREFIXES.some((prefix) => specifier.startsWith(prefix)) || specifier.includes(import_node_path11.default.sep);
|
|
12672
12624
|
}
|
|
12673
12625
|
function tryResolveBuiltin(specifier) {
|
|
12674
12626
|
if (specifier.startsWith(BUILTIN_PREFIX)) {
|
|
@@ -12691,7 +12643,7 @@ function resolveGadgetSpecifier(specifier, cwd) {
|
|
|
12691
12643
|
return specifier;
|
|
12692
12644
|
}
|
|
12693
12645
|
const expanded = expandHomePath(specifier);
|
|
12694
|
-
const resolvedPath =
|
|
12646
|
+
const resolvedPath = import_node_path11.default.resolve(cwd, expanded);
|
|
12695
12647
|
if (!import_node_fs11.default.existsSync(resolvedPath)) {
|
|
12696
12648
|
throw new Error(`Gadget module not found at ${resolvedPath}`);
|
|
12697
12649
|
}
|
|
@@ -12776,12 +12728,12 @@ async function loadGadgets(specifiers, cwd, importer = (specifier) => import(spe
|
|
|
12776
12728
|
// src/cli/llm-logging.ts
|
|
12777
12729
|
var import_promises4 = require("fs/promises");
|
|
12778
12730
|
var import_node_os6 = require("os");
|
|
12779
|
-
var
|
|
12731
|
+
var import_node_path12 = require("path");
|
|
12780
12732
|
init_messages();
|
|
12781
|
-
var DEFAULT_LLM_LOG_DIR = (0,
|
|
12733
|
+
var DEFAULT_LLM_LOG_DIR = (0, import_node_path12.join)((0, import_node_os6.homedir)(), ".llmist", "logs");
|
|
12782
12734
|
function resolveLogDir(option, subdir) {
|
|
12783
12735
|
if (option === true) {
|
|
12784
|
-
return (0,
|
|
12736
|
+
return (0, import_node_path12.join)(DEFAULT_LLM_LOG_DIR, subdir);
|
|
12785
12737
|
}
|
|
12786
12738
|
if (typeof option === "string") {
|
|
12787
12739
|
return option;
|
|
@@ -12799,7 +12751,7 @@ function formatLlmRequest(messages) {
|
|
|
12799
12751
|
}
|
|
12800
12752
|
async function writeLogFile(dir, filename, content) {
|
|
12801
12753
|
await (0, import_promises4.mkdir)(dir, { recursive: true });
|
|
12802
|
-
await (0, import_promises4.writeFile)((0,
|
|
12754
|
+
await (0, import_promises4.writeFile)((0, import_node_path12.join)(dir, filename), content, "utf-8");
|
|
12803
12755
|
}
|
|
12804
12756
|
function formatSessionTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
12805
12757
|
const pad = (n) => n.toString().padStart(2, "0");
|
|
@@ -12813,7 +12765,7 @@ function formatSessionTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
|
12813
12765
|
}
|
|
12814
12766
|
async function createSessionDir(baseDir) {
|
|
12815
12767
|
const timestamp = formatSessionTimestamp();
|
|
12816
|
-
const sessionDir = (0,
|
|
12768
|
+
const sessionDir = (0, import_node_path12.join)(baseDir, timestamp);
|
|
12817
12769
|
try {
|
|
12818
12770
|
await (0, import_promises4.mkdir)(sessionDir, { recursive: true });
|
|
12819
12771
|
return sessionDir;
|
|
@@ -12906,6 +12858,45 @@ function formatCost(cost) {
|
|
|
12906
12858
|
}
|
|
12907
12859
|
return cost.toFixed(2);
|
|
12908
12860
|
}
|
|
12861
|
+
function formatLLMCallLine(info) {
|
|
12862
|
+
const parts = [];
|
|
12863
|
+
parts.push(`${import_chalk3.default.cyan(`#${info.iteration}`)} ${import_chalk3.default.magenta(info.model)}`);
|
|
12864
|
+
if (info.contextPercent !== void 0 && info.contextPercent !== null) {
|
|
12865
|
+
const formatted = `${Math.round(info.contextPercent)}%`;
|
|
12866
|
+
if (info.contextPercent >= 80) {
|
|
12867
|
+
parts.push(import_chalk3.default.red(formatted));
|
|
12868
|
+
} else if (info.contextPercent >= 50) {
|
|
12869
|
+
parts.push(import_chalk3.default.yellow(formatted));
|
|
12870
|
+
} else {
|
|
12871
|
+
parts.push(import_chalk3.default.green(formatted));
|
|
12872
|
+
}
|
|
12873
|
+
}
|
|
12874
|
+
if (info.inputTokens && info.inputTokens > 0) {
|
|
12875
|
+
const prefix = info.estimated?.input ? "~" : "";
|
|
12876
|
+
parts.push(import_chalk3.default.dim("\u2191") + import_chalk3.default.yellow(` ${prefix}${formatTokens(info.inputTokens)}`));
|
|
12877
|
+
}
|
|
12878
|
+
if (info.cachedInputTokens && info.cachedInputTokens > 0) {
|
|
12879
|
+
parts.push(import_chalk3.default.dim("\u27F3") + import_chalk3.default.blue(` ${formatTokens(info.cachedInputTokens)}`));
|
|
12880
|
+
}
|
|
12881
|
+
if (info.outputTokens !== void 0 && info.outputTokens > 0 || info.isStreaming) {
|
|
12882
|
+
const prefix = info.estimated?.output ? "~" : "";
|
|
12883
|
+
parts.push(import_chalk3.default.dim("\u2193") + import_chalk3.default.green(` ${prefix}${formatTokens(info.outputTokens ?? 0)}`));
|
|
12884
|
+
}
|
|
12885
|
+
parts.push(import_chalk3.default.dim(`${info.elapsedSeconds.toFixed(1)}s`));
|
|
12886
|
+
if (info.cost !== void 0 && info.cost > 0) {
|
|
12887
|
+
parts.push(import_chalk3.default.cyan(`$${formatCost(info.cost)}`));
|
|
12888
|
+
}
|
|
12889
|
+
if (info.isStreaming && info.spinner) {
|
|
12890
|
+
parts.push(import_chalk3.default.cyan(info.spinner));
|
|
12891
|
+
} else if (info.finishReason !== void 0) {
|
|
12892
|
+
if (!info.finishReason || info.finishReason === "stop" || info.finishReason === "end_turn") {
|
|
12893
|
+
parts.push(import_chalk3.default.green("\u2713"));
|
|
12894
|
+
} else {
|
|
12895
|
+
parts.push(import_chalk3.default.yellow(info.finishReason));
|
|
12896
|
+
}
|
|
12897
|
+
}
|
|
12898
|
+
return parts.join(import_chalk3.default.dim(" | "));
|
|
12899
|
+
}
|
|
12909
12900
|
function renderSummary(metadata) {
|
|
12910
12901
|
const parts = [];
|
|
12911
12902
|
if (metadata.iterations !== void 0) {
|
|
@@ -12974,7 +12965,7 @@ function getRawValue(value) {
|
|
|
12974
12965
|
function truncateValue(str, maxLen) {
|
|
12975
12966
|
if (maxLen <= 0) return "";
|
|
12976
12967
|
if (str.length <= maxLen) return str;
|
|
12977
|
-
return `${str.slice(0, maxLen)}\u2026`;
|
|
12968
|
+
return `${str.slice(0, maxLen - 1)}\u2026`;
|
|
12978
12969
|
}
|
|
12979
12970
|
function formatParametersInline(params, maxWidth) {
|
|
12980
12971
|
if (!params || Object.keys(params).length === 0) {
|
|
@@ -13002,6 +12993,11 @@ function formatParametersInline(params, maxWidth) {
|
|
|
13002
12993
|
const proportion = v.length / totalRawLength;
|
|
13003
12994
|
return Math.max(minPerValue, Math.floor(proportion * availableForValues));
|
|
13004
12995
|
});
|
|
12996
|
+
const totalLimits = limits.reduce((sum, l) => sum + l, 0);
|
|
12997
|
+
if (totalLimits > availableForValues) {
|
|
12998
|
+
const scale = availableForValues / totalLimits;
|
|
12999
|
+
limits = limits.map((l) => Math.max(1, Math.floor(l * scale)));
|
|
13000
|
+
}
|
|
13005
13001
|
}
|
|
13006
13002
|
}
|
|
13007
13003
|
} else {
|
|
@@ -13012,6 +13008,38 @@ function formatParametersInline(params, maxWidth) {
|
|
|
13012
13008
|
return `${import_chalk3.default.dim(key)}${import_chalk3.default.dim("=")}${import_chalk3.default.cyan(formatted)}`;
|
|
13013
13009
|
}).join(import_chalk3.default.dim(", "));
|
|
13014
13010
|
}
|
|
13011
|
+
function formatGadgetLine(info, maxWidth) {
|
|
13012
|
+
const terminalWidth = maxWidth ?? process.stdout.columns ?? 80;
|
|
13013
|
+
const gadgetLabel = import_chalk3.default.magenta.bold(info.name);
|
|
13014
|
+
const timeStr = `${info.elapsedSeconds.toFixed(1)}s`;
|
|
13015
|
+
const timeLabel = import_chalk3.default.dim(timeStr);
|
|
13016
|
+
const fixedLength = 3 + info.name.length + 2 + 1 + timeStr.length;
|
|
13017
|
+
const availableForParams = Math.max(40, terminalWidth - fixedLength - 3);
|
|
13018
|
+
const paramsStr = formatParametersInline(info.parameters, availableForParams);
|
|
13019
|
+
const paramsLabel = paramsStr ? `${import_chalk3.default.dim("(")}${paramsStr}${import_chalk3.default.dim(")")}` : "";
|
|
13020
|
+
if (info.error) {
|
|
13021
|
+
const errorMsg = info.error.length > 50 ? `${info.error.slice(0, 50)}\u2026` : info.error;
|
|
13022
|
+
return `${import_chalk3.default.red("\u2717")} ${gadgetLabel}${paramsLabel} ${import_chalk3.default.red("error:")} ${errorMsg} ${timeLabel}`;
|
|
13023
|
+
}
|
|
13024
|
+
if (!info.isComplete) {
|
|
13025
|
+
return `${import_chalk3.default.blue("\u23F5")} ${gadgetLabel}${paramsLabel} ${timeLabel}`;
|
|
13026
|
+
}
|
|
13027
|
+
let outputLabel;
|
|
13028
|
+
if (info.tokenCount !== void 0 && info.tokenCount > 0) {
|
|
13029
|
+
outputLabel = import_chalk3.default.dim("\u2193") + import_chalk3.default.green(` ${formatTokens(info.tokenCount)} `);
|
|
13030
|
+
} else if (info.outputBytes !== void 0 && info.outputBytes > 0) {
|
|
13031
|
+
outputLabel = import_chalk3.default.green(formatBytes(info.outputBytes)) + " ";
|
|
13032
|
+
} else {
|
|
13033
|
+
outputLabel = "";
|
|
13034
|
+
}
|
|
13035
|
+
const icon = info.breaksLoop ? import_chalk3.default.yellow("\u23F9") : import_chalk3.default.green("\u2713");
|
|
13036
|
+
const nameRef = import_chalk3.default.magenta(info.name);
|
|
13037
|
+
const line1 = `${icon} ${gadgetLabel}${paramsLabel}`;
|
|
13038
|
+
const line2Prefix = ` ${import_chalk3.default.dim("\u2192")} ${nameRef} ${outputLabel}`;
|
|
13039
|
+
const line2 = `${line2Prefix}${timeLabel}`;
|
|
13040
|
+
return `${line1}
|
|
13041
|
+
${line2}`;
|
|
13042
|
+
}
|
|
13015
13043
|
function formatBytes(bytes) {
|
|
13016
13044
|
if (bytes < 1024) {
|
|
13017
13045
|
return `${bytes} bytes`;
|
|
@@ -13021,6 +13049,11 @@ function formatBytes(bytes) {
|
|
|
13021
13049
|
}
|
|
13022
13050
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
13023
13051
|
}
|
|
13052
|
+
function truncateOutputPreview(output, maxWidth) {
|
|
13053
|
+
const normalized = output.replace(/\s+/g, " ").trim();
|
|
13054
|
+
if (normalized.length <= maxWidth) return normalized;
|
|
13055
|
+
return normalized.slice(0, maxWidth - 1) + "\u2026";
|
|
13056
|
+
}
|
|
13024
13057
|
function getMediaIcon(kind) {
|
|
13025
13058
|
switch (kind) {
|
|
13026
13059
|
case "image":
|
|
@@ -13048,37 +13081,99 @@ function formatGadgetSummary2(result) {
|
|
|
13048
13081
|
const gadgetLabel = import_chalk3.default.magenta.bold(result.gadgetName);
|
|
13049
13082
|
const timeStr = result.executionTimeMs >= 1e3 ? `${(result.executionTimeMs / 1e3).toFixed(1)}s` : `${Math.round(result.executionTimeMs)}ms`;
|
|
13050
13083
|
const timeLabel = import_chalk3.default.dim(timeStr);
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
|
|
13084
|
+
const fixedLength = 3 + result.gadgetName.length + 2;
|
|
13085
|
+
const availableForParams = Math.max(40, terminalWidth - fixedLength - 3);
|
|
13086
|
+
const paramsStr = formatParametersInline(result.parameters, availableForParams);
|
|
13087
|
+
const paramsLabel = paramsStr ? `${import_chalk3.default.dim("(")}${paramsStr}${import_chalk3.default.dim(")")}` : "";
|
|
13088
|
+
const icon = result.breaksLoop ? import_chalk3.default.yellow("\u23F9") : result.error ? import_chalk3.default.red("\u2717") : import_chalk3.default.green("\u2713");
|
|
13089
|
+
const line1 = `${icon} ${gadgetLabel}${paramsLabel}`;
|
|
13090
|
+
const nameRef = import_chalk3.default.magenta(result.gadgetName);
|
|
13091
|
+
const hasSubagentMetrics = result.subagentMetrics && result.subagentMetrics.callCount > 0;
|
|
13092
|
+
let outputLabel;
|
|
13093
|
+
let outputStrRaw;
|
|
13094
|
+
if (!hasSubagentMetrics && result.tokenCount !== void 0 && result.tokenCount > 0) {
|
|
13095
|
+
const tokenStr = formatTokens(result.tokenCount);
|
|
13096
|
+
outputLabel = import_chalk3.default.dim("\u2193") + import_chalk3.default.green(` ${tokenStr} `);
|
|
13097
|
+
outputStrRaw = `\u2193 ${tokenStr} `;
|
|
13098
|
+
} else if (!hasSubagentMetrics && result.result) {
|
|
13055
13099
|
const outputBytes = Buffer.byteLength(result.result, "utf-8");
|
|
13056
|
-
|
|
13100
|
+
if (outputBytes > 0) {
|
|
13101
|
+
const bytesStr = formatBytes(outputBytes);
|
|
13102
|
+
outputLabel = import_chalk3.default.green(bytesStr) + " ";
|
|
13103
|
+
outputStrRaw = bytesStr + " ";
|
|
13104
|
+
} else {
|
|
13105
|
+
outputLabel = "";
|
|
13106
|
+
outputStrRaw = "";
|
|
13107
|
+
}
|
|
13057
13108
|
} else {
|
|
13058
|
-
|
|
13109
|
+
outputLabel = "";
|
|
13110
|
+
outputStrRaw = "";
|
|
13059
13111
|
}
|
|
13060
|
-
const fixedLength = 2 + result.gadgetName.length + 2 + 3 + outputStr.length + 1 + timeStr.length;
|
|
13061
|
-
const availableForParams = Math.max(40, terminalWidth - fixedLength - 2);
|
|
13062
|
-
const paramsStr = formatParametersInline(result.parameters, availableForParams);
|
|
13063
|
-
const paramsLabel = paramsStr ? `${import_chalk3.default.dim("(")}${paramsStr}${import_chalk3.default.dim(")")}` : "";
|
|
13064
13112
|
if (result.error) {
|
|
13065
13113
|
const errorMsg = result.error.length > 50 ? `${result.error.slice(0, 50)}\u2026` : result.error;
|
|
13066
|
-
|
|
13114
|
+
const line22 = ` ${import_chalk3.default.dim("\u2192")} ${nameRef} ${import_chalk3.default.red("error:")} ${errorMsg} ${timeLabel}`;
|
|
13115
|
+
return `${line1}
|
|
13116
|
+
${line22}`;
|
|
13117
|
+
}
|
|
13118
|
+
const previewWidth = Math.floor(terminalWidth * 0.6);
|
|
13119
|
+
const prefixLength = 4 + result.gadgetName.length + 1 + outputStrRaw.length + 1 + timeStr.length + 2;
|
|
13120
|
+
const availablePreview = Math.max(20, previewWidth - prefixLength);
|
|
13121
|
+
let customPreview;
|
|
13122
|
+
if (result.gadgetName === "TodoUpsert" && result.parameters?.content) {
|
|
13123
|
+
const statusEmoji = result.parameters.status === "done" ? "\u2705" : result.parameters.status === "in_progress" ? "\u{1F504}" : "\u2B1C";
|
|
13124
|
+
const content = String(result.parameters.content);
|
|
13125
|
+
customPreview = `${statusEmoji} ${truncateOutputPreview(content, availablePreview - 3)}`;
|
|
13126
|
+
}
|
|
13127
|
+
if (result.gadgetName === "GoogleSearch" && result.parameters?.query) {
|
|
13128
|
+
const query = String(result.parameters.query);
|
|
13129
|
+
const countMatch = result.result?.match(/\((\d+)\s+of\s+[\d,]+\s+results?\)/i) || // "(10 of 36400000 results)"
|
|
13130
|
+
result.result?.match(/(\d+)\s+results?\s+found/i) || // "10 results found"
|
|
13131
|
+
result.result?.match(/found\s+(\d+)\s+results?/i);
|
|
13132
|
+
const count = countMatch?.[1] ?? (result.parameters.maxResults ? String(result.parameters.maxResults) : null);
|
|
13133
|
+
const countStr = count ? ` \u2192 ${count} results` : "";
|
|
13134
|
+
const queryPreview = truncateOutputPreview(query, availablePreview - 5 - countStr.length);
|
|
13135
|
+
customPreview = `\u{1F50D} "${queryPreview}"${countStr}`;
|
|
13136
|
+
}
|
|
13137
|
+
let subagentMetricsStr = "";
|
|
13138
|
+
if (result.subagentMetrics && result.subagentMetrics.callCount > 0) {
|
|
13139
|
+
const parts = [];
|
|
13140
|
+
const m = result.subagentMetrics;
|
|
13141
|
+
if (m.inputTokens > 0) {
|
|
13142
|
+
parts.push(import_chalk3.default.dim("\u2191") + import_chalk3.default.yellow(` ${formatTokens(m.inputTokens)}`));
|
|
13143
|
+
}
|
|
13144
|
+
if (m.cachedInputTokens > 0) {
|
|
13145
|
+
parts.push(import_chalk3.default.dim("\u27F3") + import_chalk3.default.blue(` ${formatTokens(m.cachedInputTokens)}`));
|
|
13146
|
+
}
|
|
13147
|
+
if (m.outputTokens > 0) {
|
|
13148
|
+
parts.push(import_chalk3.default.dim("\u2193") + import_chalk3.default.green(` ${formatTokens(m.outputTokens)}`));
|
|
13149
|
+
}
|
|
13150
|
+
if (m.cost > 0) {
|
|
13151
|
+
parts.push(import_chalk3.default.cyan(`$${formatCost(m.cost)}`));
|
|
13152
|
+
}
|
|
13153
|
+
if (parts.length > 0) {
|
|
13154
|
+
subagentMetricsStr = parts.join(import_chalk3.default.dim(" | ")) + import_chalk3.default.dim(" | ");
|
|
13155
|
+
}
|
|
13156
|
+
}
|
|
13157
|
+
let line2;
|
|
13158
|
+
const previewContent = customPreview ?? (result.result?.trim() ? truncateOutputPreview(result.result, availablePreview) : null);
|
|
13159
|
+
if (previewContent) {
|
|
13160
|
+
line2 = ` ${import_chalk3.default.dim("\u2192")} ${nameRef} ${outputLabel}${subagentMetricsStr}${timeLabel}${import_chalk3.default.dim(":")} ${import_chalk3.default.dim(previewContent)}`;
|
|
13161
|
+
} else {
|
|
13162
|
+
line2 = ` ${import_chalk3.default.dim("\u2192")} ${nameRef} ${outputLabel}${subagentMetricsStr}${timeLabel}`;
|
|
13067
13163
|
}
|
|
13068
|
-
|
|
13069
|
-
|
|
13070
|
-
let summaryLine = `${icon} ${gadgetLabel}${paramsLabel} ${import_chalk3.default.dim("\u2192")} ${outputLabel} ${timeLabel}`;
|
|
13164
|
+
let output = `${line1}
|
|
13165
|
+
${line2}`;
|
|
13071
13166
|
if (result.media && result.media.length > 0) {
|
|
13072
13167
|
const mediaLines = result.media.map(formatMediaLine);
|
|
13073
|
-
|
|
13168
|
+
output += "\n" + mediaLines.join("\n");
|
|
13074
13169
|
}
|
|
13075
13170
|
if (result.gadgetName === "TellUser" && result.parameters?.message) {
|
|
13076
13171
|
const message = String(result.parameters.message);
|
|
13077
13172
|
const rendered = renderMarkdownWithSeparators(message);
|
|
13078
|
-
return `${
|
|
13173
|
+
return `${output}
|
|
13079
13174
|
${rendered}`;
|
|
13080
13175
|
}
|
|
13081
|
-
return
|
|
13176
|
+
return output;
|
|
13082
13177
|
}
|
|
13083
13178
|
|
|
13084
13179
|
// src/cli/utils.ts
|
|
@@ -13275,14 +13370,15 @@ var StreamProgress = class {
|
|
|
13275
13370
|
* Add a nested agent LLM call (called when nested llm_call_start event received).
|
|
13276
13371
|
* Used to display hierarchical progress for subagent gadgets.
|
|
13277
13372
|
*/
|
|
13278
|
-
addNestedAgent(id, parentInvocationId, depth, model, iteration,
|
|
13373
|
+
addNestedAgent(id, parentInvocationId, depth, model, iteration, info) {
|
|
13279
13374
|
this.nestedAgents.set(id, {
|
|
13280
13375
|
parentInvocationId,
|
|
13281
13376
|
depth,
|
|
13282
13377
|
model,
|
|
13283
13378
|
iteration,
|
|
13284
13379
|
startTime: Date.now(),
|
|
13285
|
-
inputTokens
|
|
13380
|
+
inputTokens: info?.inputTokens,
|
|
13381
|
+
cachedInputTokens: info?.cachedInputTokens
|
|
13286
13382
|
});
|
|
13287
13383
|
if (this.isRunning && this.isTTY) {
|
|
13288
13384
|
this.render();
|
|
@@ -13290,11 +13386,36 @@ var StreamProgress = class {
|
|
|
13290
13386
|
}
|
|
13291
13387
|
/**
|
|
13292
13388
|
* Update a nested agent with completion info (called when nested llm_call_end event received).
|
|
13389
|
+
* Records completion time to freeze the elapsed timer.
|
|
13390
|
+
* @param info - Full LLM call info including tokens, cache details, and cost
|
|
13293
13391
|
*/
|
|
13294
|
-
updateNestedAgent(id,
|
|
13392
|
+
updateNestedAgent(id, info) {
|
|
13295
13393
|
const agent = this.nestedAgents.get(id);
|
|
13296
13394
|
if (agent) {
|
|
13297
|
-
agent.
|
|
13395
|
+
if (info.inputTokens !== void 0) agent.inputTokens = info.inputTokens;
|
|
13396
|
+
if (info.outputTokens !== void 0) agent.outputTokens = info.outputTokens;
|
|
13397
|
+
if (info.cachedInputTokens !== void 0) agent.cachedInputTokens = info.cachedInputTokens;
|
|
13398
|
+
if (info.cacheCreationInputTokens !== void 0)
|
|
13399
|
+
agent.cacheCreationInputTokens = info.cacheCreationInputTokens;
|
|
13400
|
+
if (info.finishReason !== void 0) agent.finishReason = info.finishReason;
|
|
13401
|
+
if (info.cost !== void 0) {
|
|
13402
|
+
agent.cost = info.cost;
|
|
13403
|
+
} else if (this.modelRegistry && agent.model && agent.outputTokens) {
|
|
13404
|
+
try {
|
|
13405
|
+
const modelName = agent.model.includes(":") ? agent.model.split(":")[1] : agent.model;
|
|
13406
|
+
const costResult = this.modelRegistry.estimateCost(
|
|
13407
|
+
modelName,
|
|
13408
|
+
agent.inputTokens ?? 0,
|
|
13409
|
+
agent.outputTokens,
|
|
13410
|
+
agent.cachedInputTokens,
|
|
13411
|
+
agent.cacheCreationInputTokens
|
|
13412
|
+
);
|
|
13413
|
+
agent.cost = costResult?.totalCost;
|
|
13414
|
+
} catch {
|
|
13415
|
+
}
|
|
13416
|
+
}
|
|
13417
|
+
agent.completed = true;
|
|
13418
|
+
agent.completedTime = Date.now();
|
|
13298
13419
|
if (this.isRunning && this.isTTY) {
|
|
13299
13420
|
this.render();
|
|
13300
13421
|
}
|
|
@@ -13309,14 +13430,36 @@ var StreamProgress = class {
|
|
|
13309
13430
|
this.render();
|
|
13310
13431
|
}
|
|
13311
13432
|
}
|
|
13433
|
+
/**
|
|
13434
|
+
* Get aggregated metrics from all nested agents for a parent gadget.
|
|
13435
|
+
* Used to show total token counts and cost for subagent gadgets like BrowseWeb.
|
|
13436
|
+
*/
|
|
13437
|
+
getAggregatedSubagentMetrics(parentInvocationId) {
|
|
13438
|
+
let inputTokens = 0;
|
|
13439
|
+
let outputTokens = 0;
|
|
13440
|
+
let cachedInputTokens = 0;
|
|
13441
|
+
let cost = 0;
|
|
13442
|
+
let callCount = 0;
|
|
13443
|
+
for (const [, nested] of this.nestedAgents) {
|
|
13444
|
+
if (nested.parentInvocationId === parentInvocationId) {
|
|
13445
|
+
inputTokens += nested.inputTokens ?? 0;
|
|
13446
|
+
outputTokens += nested.outputTokens ?? 0;
|
|
13447
|
+
cachedInputTokens += nested.cachedInputTokens ?? 0;
|
|
13448
|
+
cost += nested.cost ?? 0;
|
|
13449
|
+
callCount++;
|
|
13450
|
+
}
|
|
13451
|
+
}
|
|
13452
|
+
return { inputTokens, outputTokens, cachedInputTokens, cost, callCount };
|
|
13453
|
+
}
|
|
13312
13454
|
/**
|
|
13313
13455
|
* Add a nested gadget call (called when nested gadget_call event received).
|
|
13314
13456
|
*/
|
|
13315
|
-
addNestedGadget(id, depth, parentInvocationId, name) {
|
|
13457
|
+
addNestedGadget(id, depth, parentInvocationId, name, parameters) {
|
|
13316
13458
|
this.nestedGadgets.set(id, {
|
|
13317
13459
|
depth,
|
|
13318
13460
|
parentInvocationId,
|
|
13319
13461
|
name,
|
|
13462
|
+
parameters,
|
|
13320
13463
|
startTime: Date.now()
|
|
13321
13464
|
});
|
|
13322
13465
|
if (this.isRunning && this.isTTY) {
|
|
@@ -13334,11 +13477,13 @@ var StreamProgress = class {
|
|
|
13334
13477
|
}
|
|
13335
13478
|
/**
|
|
13336
13479
|
* Mark a nested gadget as completed (keeps it visible with ✓ indicator).
|
|
13480
|
+
* Records completion time to freeze the elapsed timer.
|
|
13337
13481
|
*/
|
|
13338
13482
|
completeNestedGadget(id) {
|
|
13339
13483
|
const gadget = this.nestedGadgets.get(id);
|
|
13340
13484
|
if (gadget) {
|
|
13341
13485
|
gadget.completed = true;
|
|
13486
|
+
gadget.completedTime = Date.now();
|
|
13342
13487
|
if (this.isRunning && this.isTTY) {
|
|
13343
13488
|
this.render();
|
|
13344
13489
|
}
|
|
@@ -13473,38 +13618,130 @@ var StreamProgress = class {
|
|
|
13473
13618
|
this.clearRenderedLines();
|
|
13474
13619
|
const spinner = SPINNER_FRAMES[this.frameIndex++ % SPINNER_FRAMES.length];
|
|
13475
13620
|
const lines = [];
|
|
13476
|
-
|
|
13477
|
-
lines.push(this.formatStreamingLine(spinner));
|
|
13478
|
-
} else {
|
|
13479
|
-
lines.push(this.formatCumulativeLine(spinner));
|
|
13480
|
-
}
|
|
13621
|
+
const activeNestedStreams = [];
|
|
13481
13622
|
if (this.isTTY) {
|
|
13482
13623
|
for (const [gadgetId, gadget] of this.inFlightGadgets) {
|
|
13483
|
-
const
|
|
13484
|
-
const
|
|
13624
|
+
const elapsedSeconds = (Date.now() - gadget.startTime) / 1e3;
|
|
13625
|
+
const termWidth = process.stdout.columns ?? 80;
|
|
13626
|
+
const gadgetIndent = " ";
|
|
13627
|
+
const line = formatGadgetLine(
|
|
13628
|
+
{
|
|
13629
|
+
name: gadget.name,
|
|
13630
|
+
parameters: gadget.params,
|
|
13631
|
+
elapsedSeconds,
|
|
13632
|
+
isComplete: false
|
|
13633
|
+
},
|
|
13634
|
+
termWidth - gadgetIndent.length
|
|
13635
|
+
);
|
|
13636
|
+
const gadgetLine = line.split("\n").map((l) => gadgetIndent + l).join("\n");
|
|
13485
13637
|
lines.push(gadgetLine);
|
|
13638
|
+
const nestedOps = [];
|
|
13486
13639
|
for (const [_agentId, nested] of this.nestedAgents) {
|
|
13487
|
-
if (nested.parentInvocationId
|
|
13488
|
-
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
|
|
13492
|
-
|
|
13493
|
-
|
|
13494
|
-
|
|
13495
|
-
|
|
13640
|
+
if (nested.parentInvocationId === gadgetId) {
|
|
13641
|
+
nestedOps.push({
|
|
13642
|
+
type: "agent",
|
|
13643
|
+
startTime: nested.startTime,
|
|
13644
|
+
depth: nested.depth,
|
|
13645
|
+
iteration: nested.iteration,
|
|
13646
|
+
model: nested.model,
|
|
13647
|
+
inputTokens: nested.inputTokens,
|
|
13648
|
+
cachedInputTokens: nested.cachedInputTokens,
|
|
13649
|
+
outputTokens: nested.outputTokens,
|
|
13650
|
+
cost: nested.cost,
|
|
13651
|
+
finishReason: nested.finishReason,
|
|
13652
|
+
completed: nested.completed,
|
|
13653
|
+
completedTime: nested.completedTime
|
|
13654
|
+
});
|
|
13655
|
+
if (!nested.completed) {
|
|
13656
|
+
activeNestedStreams.push({
|
|
13657
|
+
depth: nested.depth,
|
|
13658
|
+
iteration: nested.iteration,
|
|
13659
|
+
model: nested.model,
|
|
13660
|
+
inputTokens: nested.inputTokens,
|
|
13661
|
+
cachedInputTokens: nested.cachedInputTokens,
|
|
13662
|
+
outputTokens: nested.outputTokens,
|
|
13663
|
+
cost: nested.cost,
|
|
13664
|
+
startTime: nested.startTime
|
|
13665
|
+
});
|
|
13666
|
+
}
|
|
13667
|
+
}
|
|
13668
|
+
}
|
|
13669
|
+
for (const [_nestedId, nestedGadget] of this.nestedGadgets) {
|
|
13496
13670
|
if (nestedGadget.parentInvocationId === gadgetId) {
|
|
13497
|
-
|
|
13498
|
-
|
|
13499
|
-
|
|
13500
|
-
|
|
13501
|
-
|
|
13671
|
+
nestedOps.push({
|
|
13672
|
+
type: "gadget",
|
|
13673
|
+
startTime: nestedGadget.startTime,
|
|
13674
|
+
depth: nestedGadget.depth,
|
|
13675
|
+
name: nestedGadget.name,
|
|
13676
|
+
parameters: nestedGadget.parameters,
|
|
13677
|
+
completed: nestedGadget.completed,
|
|
13678
|
+
completedTime: nestedGadget.completedTime
|
|
13679
|
+
});
|
|
13680
|
+
}
|
|
13681
|
+
}
|
|
13682
|
+
nestedOps.sort((a, b) => a.startTime - b.startTime);
|
|
13683
|
+
for (const op of nestedOps) {
|
|
13684
|
+
if (op.type === "agent" && !op.completed) {
|
|
13685
|
+
continue;
|
|
13686
|
+
}
|
|
13687
|
+
const indent = " ".repeat(op.depth + 2);
|
|
13688
|
+
const endTime = op.completedTime ?? Date.now();
|
|
13689
|
+
const elapsedSeconds2 = (endTime - op.startTime) / 1e3;
|
|
13690
|
+
if (op.type === "agent") {
|
|
13691
|
+
const line2 = formatLLMCallLine({
|
|
13692
|
+
iteration: op.iteration ?? 0,
|
|
13693
|
+
model: op.model ?? "",
|
|
13694
|
+
inputTokens: op.inputTokens,
|
|
13695
|
+
cachedInputTokens: op.cachedInputTokens,
|
|
13696
|
+
outputTokens: op.outputTokens,
|
|
13697
|
+
elapsedSeconds: elapsedSeconds2,
|
|
13698
|
+
cost: op.cost,
|
|
13699
|
+
finishReason: op.completed ? op.finishReason ?? "stop" : void 0,
|
|
13700
|
+
isStreaming: !op.completed,
|
|
13701
|
+
spinner
|
|
13702
|
+
});
|
|
13703
|
+
lines.push(`${indent}${line2}`);
|
|
13704
|
+
} else {
|
|
13705
|
+
const termWidth2 = process.stdout.columns ?? 80;
|
|
13706
|
+
const line2 = formatGadgetLine(
|
|
13707
|
+
{
|
|
13708
|
+
name: op.name ?? "",
|
|
13709
|
+
parameters: op.parameters,
|
|
13710
|
+
elapsedSeconds: elapsedSeconds2,
|
|
13711
|
+
isComplete: op.completed ?? false
|
|
13712
|
+
},
|
|
13713
|
+
termWidth2 - indent.length
|
|
13714
|
+
);
|
|
13715
|
+
const indentedLine = line2.split("\n").map((l) => indent + l).join("\n");
|
|
13716
|
+
lines.push(indentedLine);
|
|
13502
13717
|
}
|
|
13503
13718
|
}
|
|
13504
13719
|
}
|
|
13505
13720
|
}
|
|
13506
|
-
|
|
13507
|
-
|
|
13721
|
+
for (const stream2 of activeNestedStreams) {
|
|
13722
|
+
const indent = " ".repeat(stream2.depth + 2);
|
|
13723
|
+
const elapsedSeconds = (Date.now() - stream2.startTime) / 1e3;
|
|
13724
|
+
const line = formatLLMCallLine({
|
|
13725
|
+
iteration: stream2.iteration,
|
|
13726
|
+
model: stream2.model,
|
|
13727
|
+
inputTokens: stream2.inputTokens,
|
|
13728
|
+
cachedInputTokens: stream2.cachedInputTokens,
|
|
13729
|
+
outputTokens: stream2.outputTokens,
|
|
13730
|
+
elapsedSeconds,
|
|
13731
|
+
cost: stream2.cost,
|
|
13732
|
+
isStreaming: true,
|
|
13733
|
+
spinner
|
|
13734
|
+
});
|
|
13735
|
+
lines.push(`${indent}${line}`);
|
|
13736
|
+
}
|
|
13737
|
+
if (this.mode === "streaming") {
|
|
13738
|
+
lines.push(this.formatStreamingLine(spinner));
|
|
13739
|
+
} else {
|
|
13740
|
+
lines.push(this.formatCumulativeLine(spinner));
|
|
13741
|
+
}
|
|
13742
|
+
const output = lines.join("\n");
|
|
13743
|
+
this.lastRenderLineCount = (output.match(/\n/g) || []).length + 1;
|
|
13744
|
+
this.target.write("\r" + output);
|
|
13508
13745
|
this.hasRendered = true;
|
|
13509
13746
|
}
|
|
13510
13747
|
/**
|
|
@@ -13520,42 +13757,27 @@ var StreamProgress = class {
|
|
|
13520
13757
|
}
|
|
13521
13758
|
/**
|
|
13522
13759
|
* Format the streaming mode progress line (returns string, doesn't write).
|
|
13760
|
+
* Uses the shared formatLLMCallLine() function for consistent formatting
|
|
13761
|
+
* between main agent and nested subagent displays.
|
|
13523
13762
|
*/
|
|
13524
13763
|
formatStreamingLine(spinner) {
|
|
13525
|
-
const elapsed = ((Date.now() - this.callStartTime) / 1e3).toFixed(1);
|
|
13526
13764
|
const outTokens = this.callOutputTokensEstimated ? Math.round(this.callOutputChars / FALLBACK_CHARS_PER_TOKEN) : this.callOutputTokens;
|
|
13527
|
-
|
|
13528
|
-
|
|
13529
|
-
|
|
13530
|
-
|
|
13531
|
-
|
|
13532
|
-
|
|
13533
|
-
|
|
13534
|
-
|
|
13535
|
-
|
|
13536
|
-
|
|
13537
|
-
|
|
13538
|
-
|
|
13539
|
-
|
|
13540
|
-
|
|
13541
|
-
} else {
|
|
13542
|
-
parts.push(import_chalk4.default.green(formatted));
|
|
13765
|
+
return formatLLMCallLine({
|
|
13766
|
+
iteration: this.currentIteration,
|
|
13767
|
+
model: this.model ?? "",
|
|
13768
|
+
inputTokens: this.callInputTokens,
|
|
13769
|
+
cachedInputTokens: this.callCachedInputTokens,
|
|
13770
|
+
outputTokens: outTokens,
|
|
13771
|
+
elapsedSeconds: (Date.now() - this.callStartTime) / 1e3,
|
|
13772
|
+
cost: this.calculateCurrentCallCost(outTokens),
|
|
13773
|
+
isStreaming: true,
|
|
13774
|
+
spinner,
|
|
13775
|
+
contextPercent: this.getContextUsagePercent(),
|
|
13776
|
+
estimated: {
|
|
13777
|
+
input: this.callInputTokensEstimated,
|
|
13778
|
+
output: this.callOutputTokensEstimated
|
|
13543
13779
|
}
|
|
13544
|
-
}
|
|
13545
|
-
if (this.callInputTokens > 0) {
|
|
13546
|
-
const prefix = this.callInputTokensEstimated ? "~" : "";
|
|
13547
|
-
parts.push(import_chalk4.default.dim("\u2191") + import_chalk4.default.yellow(` ${prefix}${formatTokens(this.callInputTokens)}`));
|
|
13548
|
-
}
|
|
13549
|
-
if (this.isStreaming || outTokens > 0) {
|
|
13550
|
-
const prefix = this.callOutputTokensEstimated ? "~" : "";
|
|
13551
|
-
parts.push(import_chalk4.default.dim("\u2193") + import_chalk4.default.green(` ${prefix}${formatTokens(outTokens)}`));
|
|
13552
|
-
}
|
|
13553
|
-
parts.push(import_chalk4.default.dim(`${elapsed}s`));
|
|
13554
|
-
const callCost = this.calculateCurrentCallCost(outTokens);
|
|
13555
|
-
if (callCost > 0) {
|
|
13556
|
-
parts.push(import_chalk4.default.cyan(`$${formatCost(callCost)}`));
|
|
13557
|
-
}
|
|
13558
|
-
return `${parts.join(import_chalk4.default.dim(" | "))} ${import_chalk4.default.cyan(spinner)}`;
|
|
13780
|
+
});
|
|
13559
13781
|
}
|
|
13560
13782
|
/**
|
|
13561
13783
|
* Calculates live cost estimate for the current streaming call.
|
|
@@ -13783,7 +14005,7 @@ function addAgentOptions(cmd, defaults) {
|
|
|
13783
14005
|
OPTION_FLAGS.logLlmRequests,
|
|
13784
14006
|
OPTION_DESCRIPTIONS.logLlmRequests,
|
|
13785
14007
|
defaults?.["log-llm-requests"]
|
|
13786
|
-
).option(OPTION_FLAGS.inputImage, OPTION_DESCRIPTIONS.inputImage).option(OPTION_FLAGS.inputAudio, OPTION_DESCRIPTIONS.inputAudio).option(OPTION_FLAGS.docker, OPTION_DESCRIPTIONS.docker).option(OPTION_FLAGS.dockerRo, OPTION_DESCRIPTIONS.dockerRo).option(OPTION_FLAGS.noDocker, OPTION_DESCRIPTIONS.noDocker)
|
|
14008
|
+
).option(OPTION_FLAGS.inputImage, OPTION_DESCRIPTIONS.inputImage).option(OPTION_FLAGS.inputAudio, OPTION_DESCRIPTIONS.inputAudio).option(OPTION_FLAGS.docker, OPTION_DESCRIPTIONS.docker).option(OPTION_FLAGS.dockerRo, OPTION_DESCRIPTIONS.dockerRo).option(OPTION_FLAGS.noDocker, OPTION_DESCRIPTIONS.noDocker);
|
|
13787
14009
|
}
|
|
13788
14010
|
function configToCompleteOptions(config) {
|
|
13789
14011
|
const result = {};
|
|
@@ -13860,8 +14082,7 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13860
14082
|
const dockerOptions = {
|
|
13861
14083
|
docker: options.docker ?? false,
|
|
13862
14084
|
dockerRo: options.dockerRo ?? false,
|
|
13863
|
-
noDocker: options.noDocker ?? false
|
|
13864
|
-
dockerDev: options.dockerDev ?? false
|
|
14085
|
+
noDocker: options.noDocker ?? false
|
|
13865
14086
|
};
|
|
13866
14087
|
const dockerEnabled = resolveDockerEnabled(
|
|
13867
14088
|
env.dockerConfig,
|
|
@@ -13870,7 +14091,6 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13870
14091
|
// Profile-level docker: true/false
|
|
13871
14092
|
);
|
|
13872
14093
|
if (dockerEnabled) {
|
|
13873
|
-
const devMode = resolveDevMode(env.dockerConfig, dockerOptions.dockerDev);
|
|
13874
14094
|
const ctx = createDockerContext(
|
|
13875
14095
|
env.dockerConfig,
|
|
13876
14096
|
dockerOptions,
|
|
@@ -13881,7 +14101,7 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13881
14101
|
// Profile-level CWD permission override
|
|
13882
14102
|
);
|
|
13883
14103
|
try {
|
|
13884
|
-
await executeInDocker(ctx
|
|
14104
|
+
await executeInDocker(ctx);
|
|
13885
14105
|
} catch (error) {
|
|
13886
14106
|
if (error instanceof DockerSkipError) {
|
|
13887
14107
|
} else {
|
|
@@ -13908,9 +14128,18 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13908
14128
|
registry.registerByClass(gadget);
|
|
13909
14129
|
}
|
|
13910
14130
|
}
|
|
14131
|
+
if (!options.quiet) {
|
|
14132
|
+
const allNames = registry.getAll().map((g) => g.name).join(", ");
|
|
14133
|
+
env.stderr.write(import_chalk5.default.dim(`Gadgets: ${allNames}
|
|
14134
|
+
`));
|
|
14135
|
+
}
|
|
13911
14136
|
const printer = new StreamPrinter(env.stdout);
|
|
13912
14137
|
const stderrTTY = env.stderr.isTTY === true;
|
|
13913
|
-
const progress = new StreamProgress(
|
|
14138
|
+
const progress = new StreamProgress(
|
|
14139
|
+
env.stderr,
|
|
14140
|
+
stderrTTY,
|
|
14141
|
+
client.modelRegistry
|
|
14142
|
+
);
|
|
13914
14143
|
const abortController = new AbortController();
|
|
13915
14144
|
let wasCancelled = false;
|
|
13916
14145
|
let isStreaming = false;
|
|
@@ -13920,9 +14149,11 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13920
14149
|
wasCancelled = true;
|
|
13921
14150
|
abortController.abort();
|
|
13922
14151
|
progress.pause();
|
|
13923
|
-
env.stderr.write(
|
|
14152
|
+
env.stderr.write(
|
|
14153
|
+
import_chalk5.default.yellow(`
|
|
13924
14154
|
[Cancelled] ${progress.formatStats()}
|
|
13925
|
-
`)
|
|
14155
|
+
`)
|
|
14156
|
+
);
|
|
13926
14157
|
} else {
|
|
13927
14158
|
handleQuit();
|
|
13928
14159
|
}
|
|
@@ -13932,7 +14163,11 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13932
14163
|
cleanupSigint: null,
|
|
13933
14164
|
restore: () => {
|
|
13934
14165
|
if (stdinIsInteractive && stdinStream.isTTY && !wasCancelled) {
|
|
13935
|
-
keyboard.cleanupEsc = createEscKeyListener(
|
|
14166
|
+
keyboard.cleanupEsc = createEscKeyListener(
|
|
14167
|
+
stdinStream,
|
|
14168
|
+
handleCancel,
|
|
14169
|
+
handleCancel
|
|
14170
|
+
);
|
|
13936
14171
|
}
|
|
13937
14172
|
}
|
|
13938
14173
|
};
|
|
@@ -13957,7 +14192,11 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13957
14192
|
process.exit(130);
|
|
13958
14193
|
};
|
|
13959
14194
|
if (stdinIsInteractive && stdinStream.isTTY) {
|
|
13960
|
-
keyboard.cleanupEsc = createEscKeyListener(
|
|
14195
|
+
keyboard.cleanupEsc = createEscKeyListener(
|
|
14196
|
+
stdinStream,
|
|
14197
|
+
handleCancel,
|
|
14198
|
+
handleCancel
|
|
14199
|
+
);
|
|
13961
14200
|
}
|
|
13962
14201
|
keyboard.cleanupSigint = createSigintListener(
|
|
13963
14202
|
handleCancel,
|
|
@@ -13983,7 +14222,12 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13983
14222
|
gadgetApprovals,
|
|
13984
14223
|
defaultMode: "allowed"
|
|
13985
14224
|
};
|
|
13986
|
-
const approvalManager = new ApprovalManager(
|
|
14225
|
+
const approvalManager = new ApprovalManager(
|
|
14226
|
+
approvalConfig,
|
|
14227
|
+
env,
|
|
14228
|
+
progress,
|
|
14229
|
+
keyboard
|
|
14230
|
+
);
|
|
13987
14231
|
let usage;
|
|
13988
14232
|
let iterations = 0;
|
|
13989
14233
|
const llmLogsBaseDir = resolveLogDir(options.logLlmRequests, "requests");
|
|
@@ -13993,7 +14237,10 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13993
14237
|
try {
|
|
13994
14238
|
return await client.countTokens(model, messages);
|
|
13995
14239
|
} catch {
|
|
13996
|
-
const totalChars = messages.reduce(
|
|
14240
|
+
const totalChars = messages.reduce(
|
|
14241
|
+
(sum, m) => sum + (m.content?.length ?? 0),
|
|
14242
|
+
0
|
|
14243
|
+
);
|
|
13997
14244
|
return Math.round(totalChars / FALLBACK_CHARS_PER_TOKEN);
|
|
13998
14245
|
}
|
|
13999
14246
|
};
|
|
@@ -14015,7 +14262,9 @@ async function executeAgent(promptArg, options, env) {
|
|
|
14015
14262
|
observers: {
|
|
14016
14263
|
// onLLMCallStart: Start progress indicator for each LLM call
|
|
14017
14264
|
// This showcases how to react to agent lifecycle events
|
|
14265
|
+
// Skip for subagent events (tracked separately via nested display)
|
|
14018
14266
|
onLLMCallStart: async (context) => {
|
|
14267
|
+
if (context.subagentContext) return;
|
|
14019
14268
|
isStreaming = true;
|
|
14020
14269
|
llmCallCounter++;
|
|
14021
14270
|
const inputTokens = await countMessagesTokens(
|
|
@@ -14041,7 +14290,9 @@ async function executeAgent(promptArg, options, env) {
|
|
|
14041
14290
|
},
|
|
14042
14291
|
// onStreamChunk: Real-time updates as LLM generates tokens
|
|
14043
14292
|
// This enables responsive UIs that show progress during generation
|
|
14293
|
+
// Skip for subagent events (tracked separately via nested display)
|
|
14044
14294
|
onStreamChunk: async (context) => {
|
|
14295
|
+
if (context.subagentContext) return;
|
|
14045
14296
|
progress.update(context.accumulatedText.length);
|
|
14046
14297
|
if (context.usage) {
|
|
14047
14298
|
if (context.usage.inputTokens) {
|
|
@@ -14058,7 +14309,9 @@ async function executeAgent(promptArg, options, env) {
|
|
|
14058
14309
|
},
|
|
14059
14310
|
// onLLMCallComplete: Finalize metrics after each LLM call
|
|
14060
14311
|
// This is where you'd typically log metrics or update dashboards
|
|
14312
|
+
// Skip progress updates for subagent events (tracked separately via nested display)
|
|
14061
14313
|
onLLMCallComplete: async (context) => {
|
|
14314
|
+
if (context.subagentContext) return;
|
|
14062
14315
|
isStreaming = false;
|
|
14063
14316
|
usage = context.usage;
|
|
14064
14317
|
iterations = Math.max(iterations, context.iteration + 1);
|
|
@@ -14087,7 +14340,7 @@ async function executeAgent(promptArg, options, env) {
|
|
|
14087
14340
|
}
|
|
14088
14341
|
const callElapsed = progress.getCallElapsedSeconds();
|
|
14089
14342
|
progress.endCall(context.usage);
|
|
14090
|
-
if (!options.quiet) {
|
|
14343
|
+
if (!options.quiet && !context.subagentContext) {
|
|
14091
14344
|
const summary = renderSummary({
|
|
14092
14345
|
iterations: context.iteration + 1,
|
|
14093
14346
|
model: options.model,
|
|
@@ -14100,6 +14353,7 @@ async function executeAgent(promptArg, options, env) {
|
|
|
14100
14353
|
env.stderr.write(`${summary}
|
|
14101
14354
|
`);
|
|
14102
14355
|
}
|
|
14356
|
+
env.stderr.write("\n");
|
|
14103
14357
|
}
|
|
14104
14358
|
if (llmSessionDir) {
|
|
14105
14359
|
const filename = `${formatCallNumber(llmCallCounter)}.response`;
|
|
@@ -14145,7 +14399,10 @@ ${ctx.gadgetName} is denied by configuration.`
|
|
|
14145
14399
|
}
|
|
14146
14400
|
return { action: "proceed" };
|
|
14147
14401
|
}
|
|
14148
|
-
const result = await approvalManager.requestApproval(
|
|
14402
|
+
const result = await approvalManager.requestApproval(
|
|
14403
|
+
ctx.gadgetName,
|
|
14404
|
+
ctx.parameters
|
|
14405
|
+
);
|
|
14149
14406
|
if (!result.approved) {
|
|
14150
14407
|
return {
|
|
14151
14408
|
action: "skip",
|
|
@@ -14188,11 +14445,11 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
14188
14445
|
builder.withSyntheticGadgetCall(
|
|
14189
14446
|
"TellUser",
|
|
14190
14447
|
{
|
|
14191
|
-
message: "\u{1F44B} Hello! I'm ready to help.\n\
|
|
14448
|
+
message: "\u{1F44B} Hello! I'm ready to help.\n\nWhat would you like me to work on?",
|
|
14192
14449
|
done: false,
|
|
14193
14450
|
type: "info"
|
|
14194
14451
|
},
|
|
14195
|
-
"\u2139\uFE0F \u{1F44B} Hello! I'm ready to help.\n\
|
|
14452
|
+
"\u2139\uFE0F \u{1F44B} Hello! I'm ready to help.\n\nWhat would you like me to work on?"
|
|
14196
14453
|
);
|
|
14197
14454
|
builder.withTextOnlyHandler("acknowledge");
|
|
14198
14455
|
builder.withTextWithGadgetsHandler({
|
|
@@ -14203,8 +14460,7 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
14203
14460
|
builder.withTrailingMessage(
|
|
14204
14461
|
(ctx) => [
|
|
14205
14462
|
`[Iteration ${ctx.iteration + 1}/${ctx.maxIterations}]`,
|
|
14206
|
-
"Think carefully: what gadget invocations can
|
|
14207
|
-
"Maximize efficiency by batching independent operations in a single response."
|
|
14463
|
+
"Think carefully in two steps: 1. what gadget invocations we should be making next? 2. how do they depend on one another so we can run all of them in the right order? Then respond with all the gadget invocations you are able to do now."
|
|
14208
14464
|
].join(" ")
|
|
14209
14465
|
);
|
|
14210
14466
|
if (!options.quiet) {
|
|
@@ -14217,21 +14473,32 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
14217
14473
|
subagentEvent.gadgetInvocationId,
|
|
14218
14474
|
subagentEvent.depth,
|
|
14219
14475
|
info.model,
|
|
14220
|
-
info.iteration,
|
|
14221
|
-
|
|
14476
|
+
info.iteration + 1,
|
|
14477
|
+
// Make 1-indexed like main agent
|
|
14478
|
+
{
|
|
14479
|
+
inputTokens: info.usage?.inputTokens ?? info.inputTokens,
|
|
14480
|
+
cachedInputTokens: info.usage?.cachedInputTokens
|
|
14481
|
+
}
|
|
14222
14482
|
);
|
|
14223
14483
|
} else if (subagentEvent.type === "llm_call_end") {
|
|
14224
14484
|
const info = subagentEvent.event;
|
|
14225
14485
|
const subagentId = `${subagentEvent.gadgetInvocationId}:${info.iteration}`;
|
|
14226
|
-
progress.updateNestedAgent(subagentId,
|
|
14227
|
-
|
|
14486
|
+
progress.updateNestedAgent(subagentId, {
|
|
14487
|
+
inputTokens: info.usage?.inputTokens ?? info.inputTokens,
|
|
14488
|
+
outputTokens: info.usage?.outputTokens ?? info.outputTokens,
|
|
14489
|
+
cachedInputTokens: info.usage?.cachedInputTokens,
|
|
14490
|
+
cacheCreationInputTokens: info.usage?.cacheCreationInputTokens,
|
|
14491
|
+
finishReason: info.finishReason,
|
|
14492
|
+
cost: info.cost
|
|
14493
|
+
});
|
|
14228
14494
|
} else if (subagentEvent.type === "gadget_call") {
|
|
14229
14495
|
const gadgetEvent = subagentEvent.event;
|
|
14230
14496
|
progress.addNestedGadget(
|
|
14231
14497
|
gadgetEvent.call.invocationId,
|
|
14232
14498
|
subagentEvent.depth,
|
|
14233
14499
|
subagentEvent.gadgetInvocationId,
|
|
14234
|
-
gadgetEvent.call.gadgetName
|
|
14500
|
+
gadgetEvent.call.gadgetName,
|
|
14501
|
+
gadgetEvent.call.parameters
|
|
14235
14502
|
);
|
|
14236
14503
|
} else if (subagentEvent.type === "gadget_result") {
|
|
14237
14504
|
const resultEvent = subagentEvent.event;
|
|
@@ -14288,10 +14555,23 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
14288
14555
|
}
|
|
14289
14556
|
} else {
|
|
14290
14557
|
const tokenCount = await countGadgetOutputTokens(event.result.result);
|
|
14291
|
-
|
|
14292
|
-
|
|
14293
|
-
`
|
|
14558
|
+
const subagentMetrics = progress.getAggregatedSubagentMetrics(
|
|
14559
|
+
event.result.invocationId
|
|
14294
14560
|
);
|
|
14561
|
+
const summary = formatGadgetSummary2({
|
|
14562
|
+
...event.result,
|
|
14563
|
+
tokenCount,
|
|
14564
|
+
media: event.result.storedMedia,
|
|
14565
|
+
subagentMetrics: subagentMetrics.callCount > 0 ? subagentMetrics : void 0
|
|
14566
|
+
});
|
|
14567
|
+
if (event.result.gadgetName === "TellUser") {
|
|
14568
|
+
env.stderr.write(`${summary}
|
|
14569
|
+
`);
|
|
14570
|
+
} else {
|
|
14571
|
+
const indentedSummary = summary.split("\n").map((line) => " " + line).join("\n");
|
|
14572
|
+
env.stderr.write(`${indentedSummary}
|
|
14573
|
+
`);
|
|
14574
|
+
}
|
|
14295
14575
|
}
|
|
14296
14576
|
if (progress.hasInFlightGadgets()) {
|
|
14297
14577
|
progress.start();
|
|
@@ -14330,7 +14610,10 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
14330
14610
|
}
|
|
14331
14611
|
}
|
|
14332
14612
|
function registerAgentCommand(program, env, config, globalSubagents) {
|
|
14333
|
-
const cmd = program.command(COMMANDS.agent).description("Run the llmist agent loop with optional gadgets.").argument(
|
|
14613
|
+
const cmd = program.command(COMMANDS.agent).description("Run the llmist agent loop with optional gadgets.").argument(
|
|
14614
|
+
"[prompt]",
|
|
14615
|
+
"Prompt for the agent loop. Falls back to stdin when available."
|
|
14616
|
+
);
|
|
14334
14617
|
addAgentOptions(cmd, config);
|
|
14335
14618
|
cmd.action(
|
|
14336
14619
|
(prompt, options) => executeAction(() => {
|
|
@@ -14440,7 +14723,7 @@ function registerCompleteCommand(program, env, config) {
|
|
|
14440
14723
|
|
|
14441
14724
|
// src/cli/init-command.ts
|
|
14442
14725
|
var import_node_fs12 = require("fs");
|
|
14443
|
-
var
|
|
14726
|
+
var import_node_path13 = require("path");
|
|
14444
14727
|
var STARTER_CONFIG = `# ~/.llmist/cli.toml
|
|
14445
14728
|
# llmist CLI configuration file
|
|
14446
14729
|
#
|
|
@@ -14496,7 +14779,7 @@ var STARTER_CONFIG = `# ~/.llmist/cli.toml
|
|
|
14496
14779
|
`;
|
|
14497
14780
|
async function executeInit(_options, env) {
|
|
14498
14781
|
const configPath = getConfigPath();
|
|
14499
|
-
const configDir = (0,
|
|
14782
|
+
const configDir = (0, import_node_path13.dirname)(configPath);
|
|
14500
14783
|
if ((0, import_node_fs12.existsSync)(configPath)) {
|
|
14501
14784
|
env.stderr.write(`Configuration already exists at ${configPath}
|
|
14502
14785
|
`);
|