llmist 3.1.0 → 5.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/{chunk-JCFPJMRQ.js → chunk-3SZIQI45.js} +148 -36
- package/dist/chunk-3SZIQI45.js.map +1 -0
- package/dist/{chunk-LFI4WQVV.js → chunk-UBPZUVIN.js} +2 -2
- package/dist/chunk-UBPZUVIN.js.map +1 -0
- package/dist/cli.cjs +545 -280
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +371 -218
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +147 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +2 -2
- package/dist/{mock-stream-CTLm00_q.d.cts → mock-stream-CAY53Q6u.d.cts} +106 -25
- package/dist/{mock-stream-CTLm00_q.d.ts → mock-stream-CAY53Q6u.d.ts} +106 -25
- package/dist/testing/index.cjs +147 -35
- 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-JCFPJMRQ.js.map +0 -1
- package/dist/chunk-LFI4WQVV.js.map +0 -1
package/dist/cli.cjs
CHANGED
|
@@ -3496,7 +3496,7 @@ var init_executor = __esm({
|
|
|
3496
3496
|
init_exceptions();
|
|
3497
3497
|
init_parser();
|
|
3498
3498
|
GadgetExecutor = class {
|
|
3499
|
-
constructor(registry, requestHumanInput, logger, defaultGadgetTimeoutMs, errorFormatterOptions, client, mediaStore, agentConfig, subagentConfig,
|
|
3499
|
+
constructor(registry, requestHumanInput, logger, defaultGadgetTimeoutMs, errorFormatterOptions, client, mediaStore, agentConfig, subagentConfig, onSubagentEvent) {
|
|
3500
3500
|
this.registry = registry;
|
|
3501
3501
|
this.requestHumanInput = requestHumanInput;
|
|
3502
3502
|
this.defaultGadgetTimeoutMs = defaultGadgetTimeoutMs;
|
|
@@ -3504,7 +3504,7 @@ var init_executor = __esm({
|
|
|
3504
3504
|
this.mediaStore = mediaStore;
|
|
3505
3505
|
this.agentConfig = agentConfig;
|
|
3506
3506
|
this.subagentConfig = subagentConfig;
|
|
3507
|
-
this.
|
|
3507
|
+
this.onSubagentEvent = onSubagentEvent;
|
|
3508
3508
|
this.logger = logger ?? createLogger({ name: "llmist:executor" });
|
|
3509
3509
|
this.errorFormatter = new GadgetExecutionErrorFormatter(errorFormatterOptions);
|
|
3510
3510
|
this.argPrefix = errorFormatterOptions?.argPrefix ?? GADGET_ARG_PREFIX;
|
|
@@ -3652,7 +3652,7 @@ var init_executor = __esm({
|
|
|
3652
3652
|
agentConfig: this.agentConfig,
|
|
3653
3653
|
subagentConfig: this.subagentConfig,
|
|
3654
3654
|
invocationId: call.invocationId,
|
|
3655
|
-
|
|
3655
|
+
onSubagentEvent: this.onSubagentEvent
|
|
3656
3656
|
};
|
|
3657
3657
|
let rawResult;
|
|
3658
3658
|
if (timeoutMs && timeoutMs > 0) {
|
|
@@ -3892,7 +3892,7 @@ var init_stream_processor = __esm({
|
|
|
3892
3892
|
options.mediaStore,
|
|
3893
3893
|
options.agentConfig,
|
|
3894
3894
|
options.subagentConfig,
|
|
3895
|
-
options.
|
|
3895
|
+
options.onSubagentEvent
|
|
3896
3896
|
);
|
|
3897
3897
|
}
|
|
3898
3898
|
/**
|
|
@@ -4851,8 +4851,12 @@ var init_agent = __esm({
|
|
|
4851
4851
|
// Subagent configuration
|
|
4852
4852
|
agentContextConfig;
|
|
4853
4853
|
subagentConfig;
|
|
4854
|
-
//
|
|
4855
|
-
|
|
4854
|
+
// Subagent event callback for subagent gadgets
|
|
4855
|
+
userSubagentEventCallback;
|
|
4856
|
+
// Internal queue for yielding subagent events in run()
|
|
4857
|
+
pendingSubagentEvents = [];
|
|
4858
|
+
// Combined callback that queues events AND calls user callback
|
|
4859
|
+
onSubagentEvent;
|
|
4856
4860
|
/**
|
|
4857
4861
|
* Creates a new Agent instance.
|
|
4858
4862
|
* @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.
|
|
@@ -4930,7 +4934,72 @@ var init_agent = __esm({
|
|
|
4930
4934
|
temperature: this.temperature
|
|
4931
4935
|
};
|
|
4932
4936
|
this.subagentConfig = options.subagentConfig;
|
|
4933
|
-
this.
|
|
4937
|
+
this.userSubagentEventCallback = options.onSubagentEvent;
|
|
4938
|
+
this.onSubagentEvent = (event) => {
|
|
4939
|
+
this.pendingSubagentEvents.push(event);
|
|
4940
|
+
this.userSubagentEventCallback?.(event);
|
|
4941
|
+
const subagentContext = {
|
|
4942
|
+
parentGadgetInvocationId: event.gadgetInvocationId,
|
|
4943
|
+
depth: event.depth
|
|
4944
|
+
};
|
|
4945
|
+
if (event.type === "llm_call_start") {
|
|
4946
|
+
const info = event.event;
|
|
4947
|
+
void this.hooks?.observers?.onLLMCallStart?.({
|
|
4948
|
+
iteration: info.iteration,
|
|
4949
|
+
options: { model: info.model, messages: [] },
|
|
4950
|
+
logger: this.logger,
|
|
4951
|
+
subagentContext
|
|
4952
|
+
});
|
|
4953
|
+
} else if (event.type === "llm_call_end") {
|
|
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);
|
|
4960
|
+
void this.hooks?.observers?.onLLMCallComplete?.({
|
|
4961
|
+
iteration: info.iteration,
|
|
4962
|
+
options: { model: info.model, messages: [] },
|
|
4963
|
+
finishReason: info.finishReason ?? null,
|
|
4964
|
+
usage,
|
|
4965
|
+
rawResponse: "",
|
|
4966
|
+
finalMessage: "",
|
|
4967
|
+
logger: this.logger,
|
|
4968
|
+
subagentContext
|
|
4969
|
+
});
|
|
4970
|
+
} else if (event.type === "gadget_call") {
|
|
4971
|
+
const gadgetEvent = event.event;
|
|
4972
|
+
void this.hooks?.observers?.onGadgetExecutionStart?.({
|
|
4973
|
+
iteration: 0,
|
|
4974
|
+
gadgetName: gadgetEvent.call.gadgetName,
|
|
4975
|
+
invocationId: gadgetEvent.call.invocationId,
|
|
4976
|
+
parameters: gadgetEvent.call.parameters ?? {},
|
|
4977
|
+
logger: this.logger,
|
|
4978
|
+
subagentContext
|
|
4979
|
+
});
|
|
4980
|
+
} else if (event.type === "gadget_result") {
|
|
4981
|
+
const resultEvent = event.event;
|
|
4982
|
+
void this.hooks?.observers?.onGadgetExecutionComplete?.({
|
|
4983
|
+
iteration: 0,
|
|
4984
|
+
gadgetName: resultEvent.result.gadgetName ?? "unknown",
|
|
4985
|
+
invocationId: resultEvent.result.invocationId,
|
|
4986
|
+
parameters: {},
|
|
4987
|
+
executionTimeMs: resultEvent.result.executionTimeMs ?? 0,
|
|
4988
|
+
logger: this.logger,
|
|
4989
|
+
subagentContext
|
|
4990
|
+
});
|
|
4991
|
+
}
|
|
4992
|
+
};
|
|
4993
|
+
}
|
|
4994
|
+
/**
|
|
4995
|
+
* Flush pending subagent events as StreamEvents.
|
|
4996
|
+
* Called from run() to yield queued subagent events from subagent gadgets.
|
|
4997
|
+
*/
|
|
4998
|
+
*flushPendingSubagentEvents() {
|
|
4999
|
+
while (this.pendingSubagentEvents.length > 0) {
|
|
5000
|
+
const event = this.pendingSubagentEvents.shift();
|
|
5001
|
+
yield { type: "subagent_event", subagentEvent: event };
|
|
5002
|
+
}
|
|
4934
5003
|
}
|
|
4935
5004
|
/**
|
|
4936
5005
|
* Get the gadget registry for this agent.
|
|
@@ -5162,7 +5231,7 @@ var init_agent = __esm({
|
|
|
5162
5231
|
mediaStore: this.mediaStore,
|
|
5163
5232
|
agentConfig: this.agentContextConfig,
|
|
5164
5233
|
subagentConfig: this.subagentConfig,
|
|
5165
|
-
|
|
5234
|
+
onSubagentEvent: this.onSubagentEvent
|
|
5166
5235
|
});
|
|
5167
5236
|
let streamMetadata = null;
|
|
5168
5237
|
let gadgetCallCount = 0;
|
|
@@ -5180,6 +5249,7 @@ var init_agent = __esm({
|
|
|
5180
5249
|
gadgetResults.push(event);
|
|
5181
5250
|
}
|
|
5182
5251
|
yield event;
|
|
5252
|
+
yield* this.flushPendingSubagentEvents();
|
|
5183
5253
|
}
|
|
5184
5254
|
if (!streamMetadata) {
|
|
5185
5255
|
throw new Error("Stream processing completed without metadata event");
|
|
@@ -6934,6 +7004,9 @@ var init_gemini = __esm({
|
|
|
6934
7004
|
async countTokens(messages, descriptor, _spec) {
|
|
6935
7005
|
const client = this.client;
|
|
6936
7006
|
const contents = this.convertMessagesToContents(messages);
|
|
7007
|
+
if (!contents || contents.length === 0) {
|
|
7008
|
+
return 0;
|
|
7009
|
+
}
|
|
6937
7010
|
try {
|
|
6938
7011
|
const response = await client.models.countTokens({
|
|
6939
7012
|
model: descriptor.name,
|
|
@@ -8756,7 +8829,7 @@ var init_builder = __esm({
|
|
|
8756
8829
|
signal;
|
|
8757
8830
|
trailingMessage;
|
|
8758
8831
|
subagentConfig;
|
|
8759
|
-
|
|
8832
|
+
subagentEventCallback;
|
|
8760
8833
|
parentContext;
|
|
8761
8834
|
constructor(client) {
|
|
8762
8835
|
this.client = client;
|
|
@@ -9255,38 +9328,38 @@ var init_builder = __esm({
|
|
|
9255
9328
|
return this;
|
|
9256
9329
|
}
|
|
9257
9330
|
/**
|
|
9258
|
-
* Set the callback for
|
|
9331
|
+
* Set the callback for subagent events.
|
|
9259
9332
|
*
|
|
9260
|
-
* Subagent gadgets (like BrowseWeb) can use ExecutionContext.
|
|
9333
|
+
* Subagent gadgets (like BrowseWeb) can use ExecutionContext.onSubagentEvent
|
|
9261
9334
|
* to report their internal LLM calls and gadget executions in real-time.
|
|
9262
9335
|
* This callback receives those events, enabling hierarchical progress display.
|
|
9263
9336
|
*
|
|
9264
|
-
* @param callback - Function to handle
|
|
9337
|
+
* @param callback - Function to handle subagent events
|
|
9265
9338
|
* @returns This builder for chaining
|
|
9266
9339
|
*
|
|
9267
9340
|
* @example
|
|
9268
9341
|
* ```typescript
|
|
9269
|
-
* .
|
|
9342
|
+
* .withSubagentEventCallback((event) => {
|
|
9270
9343
|
* if (event.type === "llm_call_start") {
|
|
9271
|
-
* console.log(`
|
|
9344
|
+
* console.log(` Subagent LLM #${event.event.iteration} starting...`);
|
|
9272
9345
|
* } else if (event.type === "gadget_call") {
|
|
9273
9346
|
* console.log(` ⏵ ${event.event.call.gadgetName}...`);
|
|
9274
9347
|
* }
|
|
9275
9348
|
* })
|
|
9276
9349
|
* ```
|
|
9277
9350
|
*/
|
|
9278
|
-
|
|
9279
|
-
this.
|
|
9351
|
+
withSubagentEventCallback(callback) {
|
|
9352
|
+
this.subagentEventCallback = callback;
|
|
9280
9353
|
return this;
|
|
9281
9354
|
}
|
|
9282
9355
|
/**
|
|
9283
|
-
* Enable automatic
|
|
9356
|
+
* Enable automatic subagent event forwarding to parent agent.
|
|
9284
9357
|
*
|
|
9285
9358
|
* When building a subagent inside a gadget, call this method to automatically
|
|
9286
9359
|
* forward all LLM calls and gadget events to the parent agent. This enables
|
|
9287
9360
|
* hierarchical progress display without any manual event handling.
|
|
9288
9361
|
*
|
|
9289
|
-
* The method extracts `invocationId` and `
|
|
9362
|
+
* The method extracts `invocationId` and `onSubagentEvent` from the execution
|
|
9290
9363
|
* context and sets up automatic forwarding via hooks and event wrapping.
|
|
9291
9364
|
*
|
|
9292
9365
|
* @param ctx - ExecutionContext passed to the gadget's execute() method
|
|
@@ -9313,10 +9386,10 @@ var init_builder = __esm({
|
|
|
9313
9386
|
* ```
|
|
9314
9387
|
*/
|
|
9315
9388
|
withParentContext(ctx, depth = 1) {
|
|
9316
|
-
if (ctx.
|
|
9389
|
+
if (ctx.onSubagentEvent && ctx.invocationId) {
|
|
9317
9390
|
this.parentContext = {
|
|
9318
9391
|
invocationId: ctx.invocationId,
|
|
9319
|
-
|
|
9392
|
+
onSubagentEvent: ctx.onSubagentEvent,
|
|
9320
9393
|
depth
|
|
9321
9394
|
};
|
|
9322
9395
|
}
|
|
@@ -9391,20 +9464,22 @@ ${endPrefix}`
|
|
|
9391
9464
|
/**
|
|
9392
9465
|
* Compose the final hooks, including:
|
|
9393
9466
|
* - Trailing message injection (if configured)
|
|
9394
|
-
* -
|
|
9467
|
+
* - Subagent event forwarding for LLM calls (if parentContext is set)
|
|
9395
9468
|
*/
|
|
9396
9469
|
composeHooks() {
|
|
9397
9470
|
let hooks = this.hooks;
|
|
9398
9471
|
if (this.parentContext) {
|
|
9399
|
-
const { invocationId,
|
|
9472
|
+
const { invocationId, onSubagentEvent, depth } = this.parentContext;
|
|
9400
9473
|
const existingOnLLMCallStart = hooks?.observers?.onLLMCallStart;
|
|
9401
9474
|
const existingOnLLMCallComplete = hooks?.observers?.onLLMCallComplete;
|
|
9475
|
+
const existingOnGadgetExecutionStart = hooks?.observers?.onGadgetExecutionStart;
|
|
9476
|
+
const existingOnGadgetExecutionComplete = hooks?.observers?.onGadgetExecutionComplete;
|
|
9402
9477
|
hooks = {
|
|
9403
9478
|
...hooks,
|
|
9404
9479
|
observers: {
|
|
9405
9480
|
...hooks?.observers,
|
|
9406
9481
|
onLLMCallStart: async (context) => {
|
|
9407
|
-
|
|
9482
|
+
onSubagentEvent({
|
|
9408
9483
|
type: "llm_call_start",
|
|
9409
9484
|
gadgetInvocationId: invocationId,
|
|
9410
9485
|
depth,
|
|
@@ -9418,20 +9493,57 @@ ${endPrefix}`
|
|
|
9418
9493
|
}
|
|
9419
9494
|
},
|
|
9420
9495
|
onLLMCallComplete: async (context) => {
|
|
9421
|
-
|
|
9496
|
+
onSubagentEvent({
|
|
9422
9497
|
type: "llm_call_end",
|
|
9423
9498
|
gadgetInvocationId: invocationId,
|
|
9424
9499
|
depth,
|
|
9425
9500
|
event: {
|
|
9426
9501
|
iteration: context.iteration,
|
|
9427
9502
|
model: context.options.model,
|
|
9503
|
+
// Backward compat fields
|
|
9504
|
+
inputTokens: context.usage?.inputTokens,
|
|
9428
9505
|
outputTokens: context.usage?.outputTokens,
|
|
9429
|
-
finishReason: context.finishReason
|
|
9506
|
+
finishReason: context.finishReason ?? void 0,
|
|
9507
|
+
// Full usage object with cache details (for first-class display)
|
|
9508
|
+
usage: context.usage
|
|
9509
|
+
// Cost will be calculated by parent if it has model registry
|
|
9430
9510
|
}
|
|
9431
9511
|
});
|
|
9432
9512
|
if (existingOnLLMCallComplete) {
|
|
9433
9513
|
await existingOnLLMCallComplete(context);
|
|
9434
9514
|
}
|
|
9515
|
+
},
|
|
9516
|
+
onGadgetExecutionStart: async (context) => {
|
|
9517
|
+
onSubagentEvent({
|
|
9518
|
+
type: "gadget_call",
|
|
9519
|
+
gadgetInvocationId: invocationId,
|
|
9520
|
+
depth,
|
|
9521
|
+
event: {
|
|
9522
|
+
call: {
|
|
9523
|
+
invocationId: context.invocationId,
|
|
9524
|
+
gadgetName: context.gadgetName,
|
|
9525
|
+
parameters: context.parameters
|
|
9526
|
+
}
|
|
9527
|
+
}
|
|
9528
|
+
});
|
|
9529
|
+
if (existingOnGadgetExecutionStart) {
|
|
9530
|
+
await existingOnGadgetExecutionStart(context);
|
|
9531
|
+
}
|
|
9532
|
+
},
|
|
9533
|
+
onGadgetExecutionComplete: async (context) => {
|
|
9534
|
+
onSubagentEvent({
|
|
9535
|
+
type: "gadget_result",
|
|
9536
|
+
gadgetInvocationId: invocationId,
|
|
9537
|
+
depth,
|
|
9538
|
+
event: {
|
|
9539
|
+
result: {
|
|
9540
|
+
invocationId: context.invocationId
|
|
9541
|
+
}
|
|
9542
|
+
}
|
|
9543
|
+
});
|
|
9544
|
+
if (existingOnGadgetExecutionComplete) {
|
|
9545
|
+
await existingOnGadgetExecutionComplete(context);
|
|
9546
|
+
}
|
|
9435
9547
|
}
|
|
9436
9548
|
}
|
|
9437
9549
|
};
|
|
@@ -9518,11 +9630,11 @@ ${endPrefix}`
|
|
|
9518
9630
|
this.client = new LLMistClass();
|
|
9519
9631
|
}
|
|
9520
9632
|
const registry = GadgetRegistry.from(this.gadgets);
|
|
9521
|
-
let
|
|
9633
|
+
let onSubagentEvent = this.subagentEventCallback;
|
|
9522
9634
|
if (this.parentContext) {
|
|
9523
|
-
const { invocationId,
|
|
9524
|
-
const existingCallback = this.
|
|
9525
|
-
|
|
9635
|
+
const { invocationId, onSubagentEvent: parentCallback, depth } = this.parentContext;
|
|
9636
|
+
const existingCallback = this.subagentEventCallback;
|
|
9637
|
+
onSubagentEvent = (event) => {
|
|
9526
9638
|
parentCallback({
|
|
9527
9639
|
...event,
|
|
9528
9640
|
gadgetInvocationId: invocationId,
|
|
@@ -9557,7 +9669,7 @@ ${endPrefix}`
|
|
|
9557
9669
|
compactionConfig: this.compactionConfig,
|
|
9558
9670
|
signal: this.signal,
|
|
9559
9671
|
subagentConfig: this.subagentConfig,
|
|
9560
|
-
|
|
9672
|
+
onSubagentEvent
|
|
9561
9673
|
};
|
|
9562
9674
|
}
|
|
9563
9675
|
ask(userPrompt) {
|
|
@@ -9714,11 +9826,11 @@ ${endPrefix}`
|
|
|
9714
9826
|
this.client = new LLMistClass();
|
|
9715
9827
|
}
|
|
9716
9828
|
const registry = GadgetRegistry.from(this.gadgets);
|
|
9717
|
-
let
|
|
9829
|
+
let onSubagentEvent = this.subagentEventCallback;
|
|
9718
9830
|
if (this.parentContext) {
|
|
9719
|
-
const { invocationId,
|
|
9720
|
-
const existingCallback = this.
|
|
9721
|
-
|
|
9831
|
+
const { invocationId, onSubagentEvent: parentCallback, depth } = this.parentContext;
|
|
9832
|
+
const existingCallback = this.subagentEventCallback;
|
|
9833
|
+
onSubagentEvent = (event) => {
|
|
9722
9834
|
parentCallback({
|
|
9723
9835
|
...event,
|
|
9724
9836
|
gadgetInvocationId: invocationId,
|
|
@@ -9753,7 +9865,7 @@ ${endPrefix}`
|
|
|
9753
9865
|
compactionConfig: this.compactionConfig,
|
|
9754
9866
|
signal: this.signal,
|
|
9755
9867
|
subagentConfig: this.subagentConfig,
|
|
9756
|
-
|
|
9868
|
+
onSubagentEvent
|
|
9757
9869
|
};
|
|
9758
9870
|
return new Agent(AGENT_INTERNAL_KEY, options);
|
|
9759
9871
|
}
|
|
@@ -9793,7 +9905,6 @@ var OPTION_FLAGS = {
|
|
|
9793
9905
|
docker: "--docker",
|
|
9794
9906
|
dockerRo: "--docker-ro",
|
|
9795
9907
|
noDocker: "--no-docker",
|
|
9796
|
-
dockerDev: "--docker-dev",
|
|
9797
9908
|
// Multimodal input options
|
|
9798
9909
|
inputImage: "--image <path>",
|
|
9799
9910
|
inputAudio: "--audio <path>",
|
|
@@ -9828,7 +9939,6 @@ var OPTION_DESCRIPTIONS = {
|
|
|
9828
9939
|
docker: "Run agent in a Docker sandbox container for security isolation.",
|
|
9829
9940
|
dockerRo: "Run in Docker with current directory mounted read-only.",
|
|
9830
9941
|
noDocker: "Disable Docker sandboxing (override config).",
|
|
9831
|
-
dockerDev: "Run in Docker dev mode (mount local source instead of npm install).",
|
|
9832
9942
|
// Image generation descriptions
|
|
9833
9943
|
imageSize: "Image size/aspect ratio, e.g. '1024x1024', '1:1', '16:9'.",
|
|
9834
9944
|
imageQuality: "Image quality: 'standard', 'hd', 'low', 'medium', 'high'.",
|
|
@@ -9848,7 +9958,7 @@ var import_commander2 = require("commander");
|
|
|
9848
9958
|
// package.json
|
|
9849
9959
|
var package_default = {
|
|
9850
9960
|
name: "llmist",
|
|
9851
|
-
version: "
|
|
9961
|
+
version: "5.0.0",
|
|
9852
9962
|
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.",
|
|
9853
9963
|
type: "module",
|
|
9854
9964
|
main: "dist/index.cjs",
|
|
@@ -9891,7 +10001,8 @@ var package_default = {
|
|
|
9891
10001
|
"test:all": "bun run test && bun run test:e2e",
|
|
9892
10002
|
clean: "rimraf dist",
|
|
9893
10003
|
prepare: "node scripts/install-hooks.js || true",
|
|
9894
|
-
"release:dry": "bunx semantic-release --dry-run"
|
|
10004
|
+
"release:dry": "bunx semantic-release --dry-run",
|
|
10005
|
+
"release:publish": 'test "$(git branch --show-current)" = "main" && git pull origin main && bun run build && npm publish'
|
|
9895
10006
|
},
|
|
9896
10007
|
bin: {
|
|
9897
10008
|
llmist: "dist/cli.js"
|
|
@@ -11250,20 +11361,17 @@ var DOCKER_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
11250
11361
|
"mounts",
|
|
11251
11362
|
"env-vars",
|
|
11252
11363
|
"image-name",
|
|
11253
|
-
"dev-mode",
|
|
11254
|
-
"dev-source",
|
|
11255
11364
|
"docker-args"
|
|
11256
11365
|
]);
|
|
11257
11366
|
var DEFAULT_IMAGE_NAME = "llmist-sandbox";
|
|
11258
11367
|
var DEFAULT_CWD_PERMISSION = "rw";
|
|
11259
11368
|
var DEFAULT_CONFIG_PERMISSION = "ro";
|
|
11369
|
+
var GADGET_CACHE_VOLUME = "llmist-gadget-cache";
|
|
11260
11370
|
var FORWARDED_API_KEYS = [
|
|
11261
11371
|
"ANTHROPIC_API_KEY",
|
|
11262
11372
|
"OPENAI_API_KEY",
|
|
11263
11373
|
"GEMINI_API_KEY"
|
|
11264
11374
|
];
|
|
11265
|
-
var DEV_IMAGE_NAME = "llmist-dev-sandbox";
|
|
11266
|
-
var DEV_SOURCE_MOUNT_TARGET = "/llmist-src";
|
|
11267
11375
|
|
|
11268
11376
|
// src/cli/docker/docker-config.ts
|
|
11269
11377
|
var MOUNT_CONFIG_KEYS = /* @__PURE__ */ new Set(["source", "target", "permission"]);
|
|
@@ -11375,12 +11483,6 @@ function validateDockerConfig(raw, section) {
|
|
|
11375
11483
|
if ("image-name" in rawObj) {
|
|
11376
11484
|
result["image-name"] = validateString2(rawObj["image-name"], "image-name", section);
|
|
11377
11485
|
}
|
|
11378
|
-
if ("dev-mode" in rawObj) {
|
|
11379
|
-
result["dev-mode"] = validateBoolean2(rawObj["dev-mode"], "dev-mode", section);
|
|
11380
|
-
}
|
|
11381
|
-
if ("dev-source" in rawObj) {
|
|
11382
|
-
result["dev-source"] = validateString2(rawObj["dev-source"], "dev-source", section);
|
|
11383
|
-
}
|
|
11384
11486
|
if ("docker-args" in rawObj) {
|
|
11385
11487
|
result["docker-args"] = validateStringArray2(rawObj["docker-args"], "docker-args", section);
|
|
11386
11488
|
}
|
|
@@ -11390,7 +11492,6 @@ function validateDockerConfig(raw, section) {
|
|
|
11390
11492
|
// src/cli/docker/docker-wrapper.ts
|
|
11391
11493
|
var import_node_fs5 = require("fs");
|
|
11392
11494
|
var import_node_os4 = require("os");
|
|
11393
|
-
var import_node_path6 = require("path");
|
|
11394
11495
|
|
|
11395
11496
|
// src/cli/docker/dockerfile.ts
|
|
11396
11497
|
var DEFAULT_DOCKERFILE = `# llmist sandbox image
|
|
@@ -11410,6 +11511,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \\
|
|
|
11410
11511
|
curl \\
|
|
11411
11512
|
# ca-certificates for HTTPS
|
|
11412
11513
|
ca-certificates \\
|
|
11514
|
+
# python3 for native module compilation (node-gyp)
|
|
11515
|
+
python3 \\
|
|
11516
|
+
# build-essential for compiling native modules
|
|
11517
|
+
build-essential \\
|
|
11413
11518
|
&& rm -rf /var/lib/apt/lists/*
|
|
11414
11519
|
|
|
11415
11520
|
# Install ast-grep for code search/refactoring
|
|
@@ -11427,37 +11532,8 @@ WORKDIR /workspace
|
|
|
11427
11532
|
# Entry point - llmist with all arguments forwarded
|
|
11428
11533
|
ENTRYPOINT ["llmist"]
|
|
11429
11534
|
`;
|
|
11430
|
-
|
|
11431
|
-
|
|
11432
|
-
|
|
11433
|
-
FROM oven/bun:1-debian
|
|
11434
|
-
|
|
11435
|
-
# Install essential tools (same as production)
|
|
11436
|
-
RUN apt-get update && apt-get install -y --no-install-recommends \\
|
|
11437
|
-
ed \\
|
|
11438
|
-
ripgrep \\
|
|
11439
|
-
git \\
|
|
11440
|
-
curl \\
|
|
11441
|
-
ca-certificates \\
|
|
11442
|
-
&& rm -rf /var/lib/apt/lists/*
|
|
11443
|
-
|
|
11444
|
-
# Install ast-grep for code search/refactoring
|
|
11445
|
-
RUN curl -fsSL https://raw.githubusercontent.com/ast-grep/ast-grep/main/install.sh | bash \\
|
|
11446
|
-
&& mv /root/.local/bin/ast-grep /usr/local/bin/ 2>/dev/null || true \\
|
|
11447
|
-
&& mv /root/.local/bin/sg /usr/local/bin/ 2>/dev/null || true
|
|
11448
|
-
|
|
11449
|
-
# Working directory (host CWD will be mounted here)
|
|
11450
|
-
WORKDIR /workspace
|
|
11451
|
-
|
|
11452
|
-
# Entry point - run llmist from mounted source
|
|
11453
|
-
# Source is mounted at ${DEV_SOURCE_MOUNT_TARGET}
|
|
11454
|
-
ENTRYPOINT ["bun", "run", "${DEV_SOURCE_MOUNT_TARGET}/src/cli.ts"]
|
|
11455
|
-
`;
|
|
11456
|
-
function resolveDockerfile(config, devMode = false) {
|
|
11457
|
-
if (config.dockerfile) {
|
|
11458
|
-
return config.dockerfile;
|
|
11459
|
-
}
|
|
11460
|
-
return devMode ? DEV_DOCKERFILE : DEFAULT_DOCKERFILE;
|
|
11535
|
+
function resolveDockerfile(config) {
|
|
11536
|
+
return config.dockerfile ?? DEFAULT_DOCKERFILE;
|
|
11461
11537
|
}
|
|
11462
11538
|
function computeDockerfileHash(dockerfile) {
|
|
11463
11539
|
const encoder = new TextEncoder();
|
|
@@ -11519,10 +11595,13 @@ async function buildImage(imageName, dockerfile) {
|
|
|
11519
11595
|
ensureCacheDir();
|
|
11520
11596
|
const dockerfilePath = (0, import_node_path5.join)(CACHE_DIR, "Dockerfile");
|
|
11521
11597
|
(0, import_node_fs4.writeFileSync)(dockerfilePath, dockerfile);
|
|
11522
|
-
const proc = Bun.spawn(
|
|
11523
|
-
|
|
11524
|
-
|
|
11525
|
-
|
|
11598
|
+
const proc = Bun.spawn(
|
|
11599
|
+
["docker", "build", "--no-cache", "-t", imageName, "-f", dockerfilePath, CACHE_DIR],
|
|
11600
|
+
{
|
|
11601
|
+
stdout: "pipe",
|
|
11602
|
+
stderr: "pipe"
|
|
11603
|
+
}
|
|
11604
|
+
);
|
|
11526
11605
|
const exitCode = await proc.exited;
|
|
11527
11606
|
const stdout = await new Response(proc.stdout).text();
|
|
11528
11607
|
const stderr = await new Response(proc.stderr).text();
|
|
@@ -11584,46 +11663,13 @@ function isInsideContainer() {
|
|
|
11584
11663
|
}
|
|
11585
11664
|
return false;
|
|
11586
11665
|
}
|
|
11587
|
-
function autoDetectDevSource() {
|
|
11588
|
-
const scriptPath = process.argv[1];
|
|
11589
|
-
if (!scriptPath || !scriptPath.endsWith("src/cli.ts")) {
|
|
11590
|
-
return void 0;
|
|
11591
|
-
}
|
|
11592
|
-
const srcDir = (0, import_node_path6.dirname)(scriptPath);
|
|
11593
|
-
const projectDir = (0, import_node_path6.dirname)(srcDir);
|
|
11594
|
-
const packageJsonPath = (0, import_node_path6.join)(projectDir, "package.json");
|
|
11595
|
-
if (!(0, import_node_fs5.existsSync)(packageJsonPath)) {
|
|
11596
|
-
return void 0;
|
|
11597
|
-
}
|
|
11598
|
-
try {
|
|
11599
|
-
const pkg = JSON.parse((0, import_node_fs5.readFileSync)(packageJsonPath, "utf-8"));
|
|
11600
|
-
if (pkg.name === "llmist") {
|
|
11601
|
-
return projectDir;
|
|
11602
|
-
}
|
|
11603
|
-
} catch {
|
|
11604
|
-
}
|
|
11605
|
-
return void 0;
|
|
11606
|
-
}
|
|
11607
|
-
function resolveDevMode(config, cliDevMode) {
|
|
11608
|
-
const enabled = cliDevMode || config?.["dev-mode"] || process.env.LLMIST_DEV_MODE === "1";
|
|
11609
|
-
if (!enabled) {
|
|
11610
|
-
return { enabled: false, sourcePath: void 0 };
|
|
11611
|
-
}
|
|
11612
|
-
const sourcePath = config?.["dev-source"] || process.env.LLMIST_DEV_SOURCE || autoDetectDevSource();
|
|
11613
|
-
if (!sourcePath) {
|
|
11614
|
-
throw new Error(
|
|
11615
|
-
"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)."
|
|
11616
|
-
);
|
|
11617
|
-
}
|
|
11618
|
-
return { enabled: true, sourcePath };
|
|
11619
|
-
}
|
|
11620
11666
|
function expandHome(path6) {
|
|
11621
11667
|
if (path6.startsWith("~")) {
|
|
11622
11668
|
return path6.replace(/^~/, (0, import_node_os4.homedir)());
|
|
11623
11669
|
}
|
|
11624
11670
|
return path6;
|
|
11625
11671
|
}
|
|
11626
|
-
function buildDockerRunArgs(ctx, imageName
|
|
11672
|
+
function buildDockerRunArgs(ctx, imageName) {
|
|
11627
11673
|
const args = ["run", "--rm"];
|
|
11628
11674
|
const timestamp = Date.now();
|
|
11629
11675
|
const random = Math.random().toString(36).slice(2, 8);
|
|
@@ -11637,11 +11683,15 @@ function buildDockerRunArgs(ctx, imageName, devMode) {
|
|
|
11637
11683
|
args.push("-w", "/workspace");
|
|
11638
11684
|
const configPermission = ctx.config["config-permission"] ?? DEFAULT_CONFIG_PERMISSION;
|
|
11639
11685
|
const llmistDir = expandHome("~/.llmist");
|
|
11640
|
-
|
|
11641
|
-
if (
|
|
11642
|
-
|
|
11643
|
-
args.push("-v", `${expandedSource}:${DEV_SOURCE_MOUNT_TARGET}:ro`);
|
|
11686
|
+
const cliTomlPath = `${llmistDir}/cli.toml`;
|
|
11687
|
+
if ((0, import_node_fs5.existsSync)(cliTomlPath)) {
|
|
11688
|
+
args.push("-v", `${cliTomlPath}:/root/.llmist/cli.toml:${configPermission}`);
|
|
11644
11689
|
}
|
|
11690
|
+
const gadgetsDir = `${llmistDir}/gadgets`;
|
|
11691
|
+
if ((0, import_node_fs5.existsSync)(gadgetsDir)) {
|
|
11692
|
+
args.push("-v", `${gadgetsDir}:/root/.llmist/gadgets:${configPermission}`);
|
|
11693
|
+
}
|
|
11694
|
+
args.push("-v", `${GADGET_CACHE_VOLUME}:/root/.llmist/gadget-cache`);
|
|
11645
11695
|
if (ctx.config.mounts) {
|
|
11646
11696
|
for (const mount of ctx.config.mounts) {
|
|
11647
11697
|
const source = expandHome(mount.source);
|
|
@@ -11668,7 +11718,7 @@ function buildDockerRunArgs(ctx, imageName, devMode) {
|
|
|
11668
11718
|
return args;
|
|
11669
11719
|
}
|
|
11670
11720
|
function filterDockerArgs(argv) {
|
|
11671
|
-
const dockerFlags = /* @__PURE__ */ new Set(["--docker", "--docker-ro", "--no-docker"
|
|
11721
|
+
const dockerFlags = /* @__PURE__ */ new Set(["--docker", "--docker-ro", "--no-docker"]);
|
|
11672
11722
|
return argv.filter((arg) => !dockerFlags.has(arg));
|
|
11673
11723
|
}
|
|
11674
11724
|
function resolveDockerEnabled(config, options, profileDocker) {
|
|
@@ -11683,22 +11733,16 @@ function resolveDockerEnabled(config, options, profileDocker) {
|
|
|
11683
11733
|
}
|
|
11684
11734
|
return config?.enabled ?? false;
|
|
11685
11735
|
}
|
|
11686
|
-
async function executeInDocker(ctx
|
|
11736
|
+
async function executeInDocker(ctx) {
|
|
11687
11737
|
if (isInsideContainer()) {
|
|
11688
|
-
console.error(
|
|
11689
|
-
"Warning: Docker mode requested but already inside a container. Proceeding without re-containerization."
|
|
11690
|
-
);
|
|
11691
11738
|
throw new DockerSkipError();
|
|
11692
11739
|
}
|
|
11693
11740
|
const available = await checkDockerAvailable();
|
|
11694
11741
|
if (!available) {
|
|
11695
11742
|
throw new DockerUnavailableError();
|
|
11696
11743
|
}
|
|
11697
|
-
const dockerfile = resolveDockerfile(ctx.config
|
|
11698
|
-
const imageName =
|
|
11699
|
-
if (devMode.enabled) {
|
|
11700
|
-
console.error(`[dev mode] Mounting source from ${devMode.sourcePath}`);
|
|
11701
|
-
}
|
|
11744
|
+
const dockerfile = resolveDockerfile(ctx.config);
|
|
11745
|
+
const imageName = ctx.config["image-name"] ?? DEFAULT_IMAGE_NAME;
|
|
11702
11746
|
try {
|
|
11703
11747
|
await ensureImage(imageName, dockerfile);
|
|
11704
11748
|
} catch (error) {
|
|
@@ -11709,7 +11753,7 @@ async function executeInDocker(ctx, devMode) {
|
|
|
11709
11753
|
}
|
|
11710
11754
|
throw error;
|
|
11711
11755
|
}
|
|
11712
|
-
const dockerArgs = buildDockerRunArgs(ctx, imageName
|
|
11756
|
+
const dockerArgs = buildDockerRunArgs(ctx, imageName);
|
|
11713
11757
|
const proc = Bun.spawn(["docker", ...dockerArgs], {
|
|
11714
11758
|
stdin: "inherit",
|
|
11715
11759
|
stdout: "inherit",
|
|
@@ -11730,7 +11774,7 @@ function createDockerContext(config, options, argv, cwd, profileCwdPermission) {
|
|
|
11730
11774
|
|
|
11731
11775
|
// src/cli/file-utils.ts
|
|
11732
11776
|
var import_promises3 = require("fs/promises");
|
|
11733
|
-
var
|
|
11777
|
+
var import_node_path6 = require("path");
|
|
11734
11778
|
init_input_content();
|
|
11735
11779
|
var DEFAULT_MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
11736
11780
|
function formatFileSize(bytes) {
|
|
@@ -11748,7 +11792,7 @@ async function checkFileSize(absolutePath, filePath, maxSize) {
|
|
|
11748
11792
|
}
|
|
11749
11793
|
}
|
|
11750
11794
|
async function readImageFile(filePath, options = {}) {
|
|
11751
|
-
const absolutePath = (0,
|
|
11795
|
+
const absolutePath = (0, import_node_path6.resolve)(filePath);
|
|
11752
11796
|
const maxFileSize = options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
|
|
11753
11797
|
let buffer;
|
|
11754
11798
|
try {
|
|
@@ -11767,7 +11811,7 @@ async function readImageFile(filePath, options = {}) {
|
|
|
11767
11811
|
return imageFromBuffer(buffer, mimeType);
|
|
11768
11812
|
}
|
|
11769
11813
|
async function readAudioFile(filePath, options = {}) {
|
|
11770
|
-
const absolutePath = (0,
|
|
11814
|
+
const absolutePath = (0, import_node_path6.resolve)(filePath);
|
|
11771
11815
|
const maxFileSize = options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
|
|
11772
11816
|
let buffer;
|
|
11773
11817
|
try {
|
|
@@ -11786,7 +11830,7 @@ async function readAudioFile(filePath, options = {}) {
|
|
|
11786
11830
|
return audioFromBuffer(buffer, mimeType);
|
|
11787
11831
|
}
|
|
11788
11832
|
async function readFileBuffer(filePath, options = {}) {
|
|
11789
|
-
const absolutePath = (0,
|
|
11833
|
+
const absolutePath = (0, import_node_path6.resolve)(filePath);
|
|
11790
11834
|
const maxFileSize = options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
|
|
11791
11835
|
try {
|
|
11792
11836
|
await checkFileSize(absolutePath, filePath, maxFileSize);
|
|
@@ -11799,7 +11843,7 @@ async function readFileBuffer(filePath, options = {}) {
|
|
|
11799
11843
|
|
|
11800
11844
|
// src/cli/gadgets.ts
|
|
11801
11845
|
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
11802
|
-
var
|
|
11846
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
11803
11847
|
var import_node_url2 = require("url");
|
|
11804
11848
|
init_gadget();
|
|
11805
11849
|
|
|
@@ -11879,7 +11923,7 @@ init_gadget();
|
|
|
11879
11923
|
|
|
11880
11924
|
// src/cli/builtins/filesystem/utils.ts
|
|
11881
11925
|
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
11882
|
-
var
|
|
11926
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
11883
11927
|
var PathSandboxException = class extends Error {
|
|
11884
11928
|
constructor(inputPath, reason) {
|
|
11885
11929
|
super(`Path access denied: ${inputPath}. ${reason}`);
|
|
@@ -11888,7 +11932,7 @@ var PathSandboxException = class extends Error {
|
|
|
11888
11932
|
};
|
|
11889
11933
|
function validatePathIsWithinCwd(inputPath) {
|
|
11890
11934
|
const cwd = process.cwd();
|
|
11891
|
-
const resolvedPath =
|
|
11935
|
+
const resolvedPath = import_node_path7.default.resolve(cwd, inputPath);
|
|
11892
11936
|
let finalPath;
|
|
11893
11937
|
try {
|
|
11894
11938
|
finalPath = import_node_fs6.default.realpathSync(resolvedPath);
|
|
@@ -11900,7 +11944,7 @@ function validatePathIsWithinCwd(inputPath) {
|
|
|
11900
11944
|
throw error;
|
|
11901
11945
|
}
|
|
11902
11946
|
}
|
|
11903
|
-
const cwdWithSep = cwd +
|
|
11947
|
+
const cwdWithSep = cwd + import_node_path7.default.sep;
|
|
11904
11948
|
if (!finalPath.startsWith(cwdWithSep) && finalPath !== cwd) {
|
|
11905
11949
|
throw new PathSandboxException(inputPath, "Path is outside the current working directory");
|
|
11906
11950
|
}
|
|
@@ -12003,15 +12047,15 @@ error: ${message}`;
|
|
|
12003
12047
|
|
|
12004
12048
|
// src/cli/builtins/filesystem/list-directory.ts
|
|
12005
12049
|
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
12006
|
-
var
|
|
12050
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
12007
12051
|
var import_zod5 = require("zod");
|
|
12008
12052
|
function listFiles(dirPath, basePath = dirPath, maxDepth = 1, currentDepth = 1) {
|
|
12009
12053
|
const entries = [];
|
|
12010
12054
|
try {
|
|
12011
12055
|
const items = import_node_fs7.default.readdirSync(dirPath);
|
|
12012
12056
|
for (const item of items) {
|
|
12013
|
-
const fullPath =
|
|
12014
|
-
const relativePath =
|
|
12057
|
+
const fullPath = import_node_path8.default.join(dirPath, item);
|
|
12058
|
+
const relativePath = import_node_path8.default.relative(basePath, fullPath);
|
|
12015
12059
|
try {
|
|
12016
12060
|
const stats = import_node_fs7.default.lstatSync(fullPath);
|
|
12017
12061
|
let type;
|
|
@@ -12155,7 +12199,7 @@ ${content}`;
|
|
|
12155
12199
|
|
|
12156
12200
|
// src/cli/builtins/filesystem/write-file.ts
|
|
12157
12201
|
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
12158
|
-
var
|
|
12202
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
12159
12203
|
var import_zod7 = require("zod");
|
|
12160
12204
|
var writeFile2 = createGadget({
|
|
12161
12205
|
name: "WriteFile",
|
|
@@ -12190,7 +12234,7 @@ console.log(\`Server running on http://localhost:\${port}\`);`
|
|
|
12190
12234
|
],
|
|
12191
12235
|
execute: ({ filePath, content }) => {
|
|
12192
12236
|
const validatedPath = validatePathIsWithinCwd(filePath);
|
|
12193
|
-
const parentDir =
|
|
12237
|
+
const parentDir = import_node_path9.default.dirname(validatedPath);
|
|
12194
12238
|
let createdDir = false;
|
|
12195
12239
|
if (!import_node_fs9.default.existsSync(parentDir)) {
|
|
12196
12240
|
validatePathIsWithinCwd(parentDir);
|
|
@@ -12199,7 +12243,7 @@ console.log(\`Server running on http://localhost:\${port}\`);`
|
|
|
12199
12243
|
}
|
|
12200
12244
|
import_node_fs9.default.writeFileSync(validatedPath, content, "utf-8");
|
|
12201
12245
|
const bytesWritten = Buffer.byteLength(content, "utf-8");
|
|
12202
|
-
const dirNote = createdDir ? ` (created directory: ${
|
|
12246
|
+
const dirNote = createdDir ? ` (created directory: ${import_node_path9.default.dirname(filePath)})` : "";
|
|
12203
12247
|
return `path=${filePath}
|
|
12204
12248
|
|
|
12205
12249
|
Wrote ${bytesWritten} bytes${dirNote}`;
|
|
@@ -12328,10 +12372,10 @@ function isBuiltinGadgetName(name) {
|
|
|
12328
12372
|
// src/cli/external-gadgets.ts
|
|
12329
12373
|
var import_node_child_process = require("child_process");
|
|
12330
12374
|
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
12331
|
-
var
|
|
12375
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
12332
12376
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
12333
12377
|
var import_node_url = require("url");
|
|
12334
|
-
var CACHE_DIR2 =
|
|
12378
|
+
var CACHE_DIR2 = import_node_path10.default.join(import_node_os5.default.homedir(), ".llmist", "gadget-cache");
|
|
12335
12379
|
function isExternalPackageSpecifier(specifier) {
|
|
12336
12380
|
if (/^@?[a-z0-9][\w.-]*(?:@[\w.-]+)?(?::[a-z]+)?(?:\/\w+)?$/i.test(specifier)) {
|
|
12337
12381
|
return true;
|
|
@@ -12369,13 +12413,13 @@ function parseGadgetSpecifier(specifier) {
|
|
|
12369
12413
|
function getCacheDir(spec) {
|
|
12370
12414
|
const versionSuffix = spec.version ? `@${spec.version}` : "@latest";
|
|
12371
12415
|
if (spec.type === "npm") {
|
|
12372
|
-
return
|
|
12416
|
+
return import_node_path10.default.join(CACHE_DIR2, "npm", `${spec.package}${versionSuffix}`);
|
|
12373
12417
|
}
|
|
12374
12418
|
const sanitizedUrl = spec.package.replace(/[/:]/g, "-").replace(/^-+|-+$/g, "");
|
|
12375
|
-
return
|
|
12419
|
+
return import_node_path10.default.join(CACHE_DIR2, "git", `${sanitizedUrl}${versionSuffix}`);
|
|
12376
12420
|
}
|
|
12377
12421
|
function isCached(cacheDir) {
|
|
12378
|
-
const packageJsonPath =
|
|
12422
|
+
const packageJsonPath = import_node_path10.default.join(cacheDir, "package.json");
|
|
12379
12423
|
return import_node_fs10.default.existsSync(packageJsonPath);
|
|
12380
12424
|
}
|
|
12381
12425
|
async function installNpmPackage(spec, cacheDir) {
|
|
@@ -12385,10 +12429,10 @@ async function installNpmPackage(spec, cacheDir) {
|
|
|
12385
12429
|
private: true,
|
|
12386
12430
|
type: "module"
|
|
12387
12431
|
};
|
|
12388
|
-
import_node_fs10.default.writeFileSync(
|
|
12432
|
+
import_node_fs10.default.writeFileSync(import_node_path10.default.join(cacheDir, "package.json"), JSON.stringify(packageJson, null, 2));
|
|
12389
12433
|
const packageSpec = spec.version ? `${spec.package}@${spec.version}` : spec.package;
|
|
12390
12434
|
try {
|
|
12391
|
-
(0, import_node_child_process.execSync)(`
|
|
12435
|
+
(0, import_node_child_process.execSync)(`bun add "${packageSpec}"`, {
|
|
12392
12436
|
stdio: "pipe",
|
|
12393
12437
|
cwd: cacheDir
|
|
12394
12438
|
});
|
|
@@ -12398,7 +12442,7 @@ async function installNpmPackage(spec, cacheDir) {
|
|
|
12398
12442
|
}
|
|
12399
12443
|
}
|
|
12400
12444
|
async function installGitPackage(spec, cacheDir) {
|
|
12401
|
-
import_node_fs10.default.mkdirSync(
|
|
12445
|
+
import_node_fs10.default.mkdirSync(import_node_path10.default.dirname(cacheDir), { recursive: true });
|
|
12402
12446
|
if (import_node_fs10.default.existsSync(cacheDir)) {
|
|
12403
12447
|
try {
|
|
12404
12448
|
(0, import_node_child_process.execSync)("git fetch", { cwd: cacheDir, stdio: "pipe" });
|
|
@@ -12417,17 +12461,17 @@ async function installGitPackage(spec, cacheDir) {
|
|
|
12417
12461
|
const message = error instanceof Error ? error.message : String(error);
|
|
12418
12462
|
throw new Error(`Failed to clone git repository '${spec.package}': ${message}`);
|
|
12419
12463
|
}
|
|
12420
|
-
if (import_node_fs10.default.existsSync(
|
|
12464
|
+
if (import_node_fs10.default.existsSync(import_node_path10.default.join(cacheDir, "package.json"))) {
|
|
12421
12465
|
try {
|
|
12422
|
-
(0, import_node_child_process.execSync)("
|
|
12466
|
+
(0, import_node_child_process.execSync)("bun install", { cwd: cacheDir, stdio: "inherit" });
|
|
12423
12467
|
} catch (error) {
|
|
12424
12468
|
const message = error instanceof Error ? error.message : String(error);
|
|
12425
12469
|
throw new Error(`Failed to install dependencies for '${spec.package}': ${message}`);
|
|
12426
12470
|
}
|
|
12427
12471
|
try {
|
|
12428
|
-
const packageJson = JSON.parse(import_node_fs10.default.readFileSync(
|
|
12472
|
+
const packageJson = JSON.parse(import_node_fs10.default.readFileSync(import_node_path10.default.join(cacheDir, "package.json"), "utf-8"));
|
|
12429
12473
|
if (packageJson.scripts?.build) {
|
|
12430
|
-
(0, import_node_child_process.execSync)("
|
|
12474
|
+
(0, import_node_child_process.execSync)("bun run build", { cwd: cacheDir, stdio: "inherit" });
|
|
12431
12475
|
}
|
|
12432
12476
|
} catch (error) {
|
|
12433
12477
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -12437,7 +12481,7 @@ async function installGitPackage(spec, cacheDir) {
|
|
|
12437
12481
|
}
|
|
12438
12482
|
}
|
|
12439
12483
|
function readManifest(packageDir) {
|
|
12440
|
-
const packageJsonPath =
|
|
12484
|
+
const packageJsonPath = import_node_path10.default.join(packageDir, "package.json");
|
|
12441
12485
|
if (!import_node_fs10.default.existsSync(packageJsonPath)) {
|
|
12442
12486
|
return null;
|
|
12443
12487
|
}
|
|
@@ -12449,7 +12493,7 @@ function readManifest(packageDir) {
|
|
|
12449
12493
|
}
|
|
12450
12494
|
}
|
|
12451
12495
|
function getPackagePath(cacheDir, packageName) {
|
|
12452
|
-
const nodeModulesPath =
|
|
12496
|
+
const nodeModulesPath = import_node_path10.default.join(cacheDir, "node_modules", packageName);
|
|
12453
12497
|
if (import_node_fs10.default.existsSync(nodeModulesPath)) {
|
|
12454
12498
|
return nodeModulesPath;
|
|
12455
12499
|
}
|
|
@@ -12493,7 +12537,7 @@ async function loadExternalGadgets(specifier, forceInstall = false) {
|
|
|
12493
12537
|
} else {
|
|
12494
12538
|
entryPoint = manifest?.gadgets || "./dist/index.js";
|
|
12495
12539
|
}
|
|
12496
|
-
const resolvedEntryPoint =
|
|
12540
|
+
const resolvedEntryPoint = import_node_path10.default.resolve(packagePath, entryPoint);
|
|
12497
12541
|
if (!import_node_fs10.default.existsSync(resolvedEntryPoint)) {
|
|
12498
12542
|
throw new Error(
|
|
12499
12543
|
`Entry point not found: ${resolvedEntryPoint}. Make sure the package is built (run 'npm run build' in the package directory).`
|
|
@@ -12562,10 +12606,10 @@ function expandHomePath(input) {
|
|
|
12562
12606
|
if (!home) {
|
|
12563
12607
|
return input;
|
|
12564
12608
|
}
|
|
12565
|
-
return
|
|
12609
|
+
return import_node_path11.default.join(home, input.slice(1));
|
|
12566
12610
|
}
|
|
12567
12611
|
function isFileLikeSpecifier(specifier) {
|
|
12568
|
-
return PATH_PREFIXES.some((prefix) => specifier.startsWith(prefix)) || specifier.includes(
|
|
12612
|
+
return PATH_PREFIXES.some((prefix) => specifier.startsWith(prefix)) || specifier.includes(import_node_path11.default.sep);
|
|
12569
12613
|
}
|
|
12570
12614
|
function tryResolveBuiltin(specifier) {
|
|
12571
12615
|
if (specifier.startsWith(BUILTIN_PREFIX)) {
|
|
@@ -12588,7 +12632,7 @@ function resolveGadgetSpecifier(specifier, cwd) {
|
|
|
12588
12632
|
return specifier;
|
|
12589
12633
|
}
|
|
12590
12634
|
const expanded = expandHomePath(specifier);
|
|
12591
|
-
const resolvedPath =
|
|
12635
|
+
const resolvedPath = import_node_path11.default.resolve(cwd, expanded);
|
|
12592
12636
|
if (!import_node_fs11.default.existsSync(resolvedPath)) {
|
|
12593
12637
|
throw new Error(`Gadget module not found at ${resolvedPath}`);
|
|
12594
12638
|
}
|
|
@@ -12673,12 +12717,12 @@ async function loadGadgets(specifiers, cwd, importer = (specifier) => import(spe
|
|
|
12673
12717
|
// src/cli/llm-logging.ts
|
|
12674
12718
|
var import_promises4 = require("fs/promises");
|
|
12675
12719
|
var import_node_os6 = require("os");
|
|
12676
|
-
var
|
|
12720
|
+
var import_node_path12 = require("path");
|
|
12677
12721
|
init_messages();
|
|
12678
|
-
var DEFAULT_LLM_LOG_DIR = (0,
|
|
12722
|
+
var DEFAULT_LLM_LOG_DIR = (0, import_node_path12.join)((0, import_node_os6.homedir)(), ".llmist", "logs");
|
|
12679
12723
|
function resolveLogDir(option, subdir) {
|
|
12680
12724
|
if (option === true) {
|
|
12681
|
-
return (0,
|
|
12725
|
+
return (0, import_node_path12.join)(DEFAULT_LLM_LOG_DIR, subdir);
|
|
12682
12726
|
}
|
|
12683
12727
|
if (typeof option === "string") {
|
|
12684
12728
|
return option;
|
|
@@ -12696,7 +12740,7 @@ function formatLlmRequest(messages) {
|
|
|
12696
12740
|
}
|
|
12697
12741
|
async function writeLogFile(dir, filename, content) {
|
|
12698
12742
|
await (0, import_promises4.mkdir)(dir, { recursive: true });
|
|
12699
|
-
await (0, import_promises4.writeFile)((0,
|
|
12743
|
+
await (0, import_promises4.writeFile)((0, import_node_path12.join)(dir, filename), content, "utf-8");
|
|
12700
12744
|
}
|
|
12701
12745
|
function formatSessionTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
12702
12746
|
const pad = (n) => n.toString().padStart(2, "0");
|
|
@@ -12710,7 +12754,7 @@ function formatSessionTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
|
12710
12754
|
}
|
|
12711
12755
|
async function createSessionDir(baseDir) {
|
|
12712
12756
|
const timestamp = formatSessionTimestamp();
|
|
12713
|
-
const sessionDir = (0,
|
|
12757
|
+
const sessionDir = (0, import_node_path12.join)(baseDir, timestamp);
|
|
12714
12758
|
try {
|
|
12715
12759
|
await (0, import_promises4.mkdir)(sessionDir, { recursive: true });
|
|
12716
12760
|
return sessionDir;
|
|
@@ -12803,6 +12847,45 @@ function formatCost(cost) {
|
|
|
12803
12847
|
}
|
|
12804
12848
|
return cost.toFixed(2);
|
|
12805
12849
|
}
|
|
12850
|
+
function formatLLMCallLine(info) {
|
|
12851
|
+
const parts = [];
|
|
12852
|
+
parts.push(`${import_chalk3.default.cyan(`#${info.iteration}`)} ${import_chalk3.default.magenta(info.model)}`);
|
|
12853
|
+
if (info.contextPercent !== void 0 && info.contextPercent !== null) {
|
|
12854
|
+
const formatted = `${Math.round(info.contextPercent)}%`;
|
|
12855
|
+
if (info.contextPercent >= 80) {
|
|
12856
|
+
parts.push(import_chalk3.default.red(formatted));
|
|
12857
|
+
} else if (info.contextPercent >= 50) {
|
|
12858
|
+
parts.push(import_chalk3.default.yellow(formatted));
|
|
12859
|
+
} else {
|
|
12860
|
+
parts.push(import_chalk3.default.green(formatted));
|
|
12861
|
+
}
|
|
12862
|
+
}
|
|
12863
|
+
if (info.inputTokens && info.inputTokens > 0) {
|
|
12864
|
+
const prefix = info.estimated?.input ? "~" : "";
|
|
12865
|
+
parts.push(import_chalk3.default.dim("\u2191") + import_chalk3.default.yellow(` ${prefix}${formatTokens(info.inputTokens)}`));
|
|
12866
|
+
}
|
|
12867
|
+
if (info.cachedInputTokens && info.cachedInputTokens > 0) {
|
|
12868
|
+
parts.push(import_chalk3.default.dim("\u27F3") + import_chalk3.default.blue(` ${formatTokens(info.cachedInputTokens)}`));
|
|
12869
|
+
}
|
|
12870
|
+
if (info.outputTokens !== void 0 && info.outputTokens > 0 || info.isStreaming) {
|
|
12871
|
+
const prefix = info.estimated?.output ? "~" : "";
|
|
12872
|
+
parts.push(import_chalk3.default.dim("\u2193") + import_chalk3.default.green(` ${prefix}${formatTokens(info.outputTokens ?? 0)}`));
|
|
12873
|
+
}
|
|
12874
|
+
parts.push(import_chalk3.default.dim(`${info.elapsedSeconds.toFixed(1)}s`));
|
|
12875
|
+
if (info.cost !== void 0 && info.cost > 0) {
|
|
12876
|
+
parts.push(import_chalk3.default.cyan(`$${formatCost(info.cost)}`));
|
|
12877
|
+
}
|
|
12878
|
+
if (info.isStreaming && info.spinner) {
|
|
12879
|
+
parts.push(import_chalk3.default.cyan(info.spinner));
|
|
12880
|
+
} else if (info.finishReason !== void 0) {
|
|
12881
|
+
if (!info.finishReason || info.finishReason === "stop" || info.finishReason === "end_turn") {
|
|
12882
|
+
parts.push(import_chalk3.default.green("\u2713"));
|
|
12883
|
+
} else {
|
|
12884
|
+
parts.push(import_chalk3.default.yellow(info.finishReason));
|
|
12885
|
+
}
|
|
12886
|
+
}
|
|
12887
|
+
return parts.join(import_chalk3.default.dim(" | "));
|
|
12888
|
+
}
|
|
12806
12889
|
function renderSummary(metadata) {
|
|
12807
12890
|
const parts = [];
|
|
12808
12891
|
if (metadata.iterations !== void 0) {
|
|
@@ -12859,23 +12942,84 @@ function renderOverallSummary(metadata) {
|
|
|
12859
12942
|
}
|
|
12860
12943
|
return parts.join(import_chalk3.default.dim(" | "));
|
|
12861
12944
|
}
|
|
12862
|
-
function
|
|
12945
|
+
function getRawValue(value) {
|
|
12946
|
+
if (typeof value === "string") {
|
|
12947
|
+
return value;
|
|
12948
|
+
}
|
|
12949
|
+
if (typeof value === "boolean" || typeof value === "number") {
|
|
12950
|
+
return String(value);
|
|
12951
|
+
}
|
|
12952
|
+
return JSON.stringify(value);
|
|
12953
|
+
}
|
|
12954
|
+
function truncateValue(str, maxLen) {
|
|
12955
|
+
if (maxLen <= 0) return "";
|
|
12956
|
+
if (str.length <= maxLen) return str;
|
|
12957
|
+
return `${str.slice(0, maxLen)}\u2026`;
|
|
12958
|
+
}
|
|
12959
|
+
function formatParametersInline(params, maxWidth) {
|
|
12863
12960
|
if (!params || Object.keys(params).length === 0) {
|
|
12864
12961
|
return "";
|
|
12865
12962
|
}
|
|
12866
|
-
|
|
12867
|
-
|
|
12868
|
-
|
|
12869
|
-
|
|
12870
|
-
|
|
12871
|
-
|
|
12963
|
+
const entries = Object.entries(params);
|
|
12964
|
+
const defaultLimit = 30;
|
|
12965
|
+
const rawValues = entries.map(([, value]) => getRawValue(value));
|
|
12966
|
+
const overhead = entries.reduce((sum, [key], i) => {
|
|
12967
|
+
return sum + key.length + 1 + (i > 0 ? 2 : 0);
|
|
12968
|
+
}, 0);
|
|
12969
|
+
let limits;
|
|
12970
|
+
if (maxWidth && maxWidth > overhead) {
|
|
12971
|
+
const availableForValues = maxWidth - overhead;
|
|
12972
|
+
const totalRawLength = rawValues.reduce((sum, v) => sum + v.length, 0);
|
|
12973
|
+
if (totalRawLength <= availableForValues) {
|
|
12974
|
+
limits = rawValues.map(() => Infinity);
|
|
12872
12975
|
} else {
|
|
12873
|
-
const
|
|
12874
|
-
|
|
12976
|
+
const minPerValue = 10;
|
|
12977
|
+
const minTotal = entries.length * minPerValue;
|
|
12978
|
+
if (availableForValues <= minTotal) {
|
|
12979
|
+
limits = rawValues.map(() => Math.max(1, Math.floor(availableForValues / entries.length)));
|
|
12980
|
+
} else {
|
|
12981
|
+
limits = rawValues.map((v) => {
|
|
12982
|
+
const proportion = v.length / totalRawLength;
|
|
12983
|
+
return Math.max(minPerValue, Math.floor(proportion * availableForValues));
|
|
12984
|
+
});
|
|
12985
|
+
}
|
|
12875
12986
|
}
|
|
12987
|
+
} else {
|
|
12988
|
+
limits = rawValues.map(() => defaultLimit);
|
|
12989
|
+
}
|
|
12990
|
+
return entries.map(([key, _], i) => {
|
|
12991
|
+
const formatted = truncateValue(rawValues[i], limits[i]);
|
|
12876
12992
|
return `${import_chalk3.default.dim(key)}${import_chalk3.default.dim("=")}${import_chalk3.default.cyan(formatted)}`;
|
|
12877
12993
|
}).join(import_chalk3.default.dim(", "));
|
|
12878
12994
|
}
|
|
12995
|
+
function formatGadgetLine(info, maxWidth) {
|
|
12996
|
+
const terminalWidth = maxWidth ?? process.stdout.columns ?? 80;
|
|
12997
|
+
const gadgetLabel = import_chalk3.default.magenta.bold(info.name);
|
|
12998
|
+
const timeStr = `${info.elapsedSeconds.toFixed(1)}s`;
|
|
12999
|
+
const timeLabel = import_chalk3.default.dim(timeStr);
|
|
13000
|
+
const fixedLength = 2 + info.name.length + 2 + 1 + timeStr.length;
|
|
13001
|
+
const availableForParams = Math.max(40, terminalWidth - fixedLength - 2);
|
|
13002
|
+
const paramsStr = formatParametersInline(info.parameters, availableForParams);
|
|
13003
|
+
const paramsLabel = paramsStr ? `${import_chalk3.default.dim("(")}${paramsStr}${import_chalk3.default.dim(")")}` : "";
|
|
13004
|
+
if (info.error) {
|
|
13005
|
+
const errorMsg = info.error.length > 50 ? `${info.error.slice(0, 50)}\u2026` : info.error;
|
|
13006
|
+
return `${import_chalk3.default.red("\u2717")} ${gadgetLabel}${paramsLabel} ${import_chalk3.default.red("error:")} ${errorMsg} ${timeLabel}`;
|
|
13007
|
+
}
|
|
13008
|
+
if (!info.isComplete) {
|
|
13009
|
+
return `${import_chalk3.default.blue("\u23F5")} ${gadgetLabel}${paramsLabel} ${timeLabel}`;
|
|
13010
|
+
}
|
|
13011
|
+
let outputStr;
|
|
13012
|
+
if (info.tokenCount !== void 0 && info.tokenCount > 0) {
|
|
13013
|
+
outputStr = `${formatTokens(info.tokenCount)} tokens`;
|
|
13014
|
+
} else if (info.outputBytes !== void 0 && info.outputBytes > 0) {
|
|
13015
|
+
outputStr = formatBytes(info.outputBytes);
|
|
13016
|
+
} else {
|
|
13017
|
+
outputStr = "";
|
|
13018
|
+
}
|
|
13019
|
+
const icon = info.breaksLoop ? import_chalk3.default.yellow("\u23F9") : import_chalk3.default.green("\u2713");
|
|
13020
|
+
const outputLabel = outputStr ? ` ${import_chalk3.default.dim("\u2192")} ${import_chalk3.default.green(outputStr)}` : "";
|
|
13021
|
+
return `${icon} ${gadgetLabel}${paramsLabel}${outputLabel} ${timeLabel}`;
|
|
13022
|
+
}
|
|
12879
13023
|
function formatBytes(bytes) {
|
|
12880
13024
|
if (bytes < 1024) {
|
|
12881
13025
|
return `${bytes} bytes`;
|
|
@@ -12908,25 +13052,28 @@ function formatMediaLine(media) {
|
|
|
12908
13052
|
return `${import_chalk3.default.dim("[")}${icon} ${id} ${mimeType} ${size}${import_chalk3.default.dim("]")} ${import_chalk3.default.dim("\u2192")} ${path6}`;
|
|
12909
13053
|
}
|
|
12910
13054
|
function formatGadgetSummary2(result) {
|
|
13055
|
+
const terminalWidth = process.stdout.columns || 80;
|
|
12911
13056
|
const gadgetLabel = import_chalk3.default.magenta.bold(result.gadgetName);
|
|
12912
|
-
const
|
|
12913
|
-
|
|
12914
|
-
|
|
12915
|
-
const paramsStr = formatParametersInline(result.parameters);
|
|
12916
|
-
const paramsLabel = paramsStr ? `${import_chalk3.default.dim("(")}${paramsStr}${import_chalk3.default.dim(")")}` : "";
|
|
12917
|
-
if (result.error) {
|
|
12918
|
-
const errorMsg = result.error.length > 50 ? `${result.error.slice(0, 50)}\u2026` : result.error;
|
|
12919
|
-
return `${import_chalk3.default.red("\u2717")} ${gadgetLabel}${paramsLabel} ${import_chalk3.default.red("error:")} ${errorMsg} ${timeLabel}`;
|
|
12920
|
-
}
|
|
12921
|
-
let outputLabel;
|
|
13057
|
+
const timeStr = result.executionTimeMs >= 1e3 ? `${(result.executionTimeMs / 1e3).toFixed(1)}s` : `${Math.round(result.executionTimeMs)}ms`;
|
|
13058
|
+
const timeLabel = import_chalk3.default.dim(timeStr);
|
|
13059
|
+
let outputStr;
|
|
12922
13060
|
if (result.tokenCount !== void 0 && result.tokenCount > 0) {
|
|
12923
|
-
|
|
13061
|
+
outputStr = `${formatTokens(result.tokenCount)} tokens`;
|
|
12924
13062
|
} else if (result.result) {
|
|
12925
13063
|
const outputBytes = Buffer.byteLength(result.result, "utf-8");
|
|
12926
|
-
|
|
13064
|
+
outputStr = outputBytes > 0 ? formatBytes(outputBytes) : "no output";
|
|
12927
13065
|
} else {
|
|
12928
|
-
|
|
13066
|
+
outputStr = "no output";
|
|
13067
|
+
}
|
|
13068
|
+
const fixedLength = 2 + result.gadgetName.length + 2 + 3 + outputStr.length + 1 + timeStr.length;
|
|
13069
|
+
const availableForParams = Math.max(40, terminalWidth - fixedLength - 2);
|
|
13070
|
+
const paramsStr = formatParametersInline(result.parameters, availableForParams);
|
|
13071
|
+
const paramsLabel = paramsStr ? `${import_chalk3.default.dim("(")}${paramsStr}${import_chalk3.default.dim(")")}` : "";
|
|
13072
|
+
if (result.error) {
|
|
13073
|
+
const errorMsg = result.error.length > 50 ? `${result.error.slice(0, 50)}\u2026` : result.error;
|
|
13074
|
+
return `${import_chalk3.default.red("\u2717")} ${gadgetLabel}${paramsLabel} ${import_chalk3.default.red("error:")} ${errorMsg} ${timeLabel}`;
|
|
12929
13075
|
}
|
|
13076
|
+
const outputLabel = outputStr === "no output" ? import_chalk3.default.dim(outputStr) : import_chalk3.default.green(outputStr);
|
|
12930
13077
|
const icon = result.breaksLoop ? import_chalk3.default.yellow("\u23F9") : import_chalk3.default.green("\u2713");
|
|
12931
13078
|
let summaryLine = `${icon} ${gadgetLabel}${paramsLabel} ${import_chalk3.default.dim("\u2192")} ${outputLabel} ${timeLabel}`;
|
|
12932
13079
|
if (result.media && result.media.length > 0) {
|
|
@@ -13151,11 +13298,35 @@ var StreamProgress = class {
|
|
|
13151
13298
|
}
|
|
13152
13299
|
/**
|
|
13153
13300
|
* Update a nested agent with completion info (called when nested llm_call_end event received).
|
|
13301
|
+
* Records completion time to freeze the elapsed timer.
|
|
13302
|
+
* @param info - Full LLM call info including tokens, cache details, and cost
|
|
13154
13303
|
*/
|
|
13155
|
-
updateNestedAgent(id,
|
|
13304
|
+
updateNestedAgent(id, info) {
|
|
13156
13305
|
const agent = this.nestedAgents.get(id);
|
|
13157
13306
|
if (agent) {
|
|
13158
|
-
agent.
|
|
13307
|
+
agent.inputTokens = info.inputTokens;
|
|
13308
|
+
agent.outputTokens = info.outputTokens;
|
|
13309
|
+
agent.cachedInputTokens = info.cachedInputTokens;
|
|
13310
|
+
agent.cacheCreationInputTokens = info.cacheCreationInputTokens;
|
|
13311
|
+
agent.finishReason = info.finishReason;
|
|
13312
|
+
if (info.cost !== void 0) {
|
|
13313
|
+
agent.cost = info.cost;
|
|
13314
|
+
} else if (this.modelRegistry && agent.model && info.outputTokens) {
|
|
13315
|
+
try {
|
|
13316
|
+
const modelName = agent.model.includes(":") ? agent.model.split(":")[1] : agent.model;
|
|
13317
|
+
const costResult = this.modelRegistry.estimateCost(
|
|
13318
|
+
modelName,
|
|
13319
|
+
info.inputTokens ?? 0,
|
|
13320
|
+
info.outputTokens,
|
|
13321
|
+
info.cachedInputTokens,
|
|
13322
|
+
info.cacheCreationInputTokens
|
|
13323
|
+
);
|
|
13324
|
+
agent.cost = costResult?.totalCost;
|
|
13325
|
+
} catch {
|
|
13326
|
+
}
|
|
13327
|
+
}
|
|
13328
|
+
agent.completed = true;
|
|
13329
|
+
agent.completedTime = Date.now();
|
|
13159
13330
|
if (this.isRunning && this.isTTY) {
|
|
13160
13331
|
this.render();
|
|
13161
13332
|
}
|
|
@@ -13173,11 +13344,12 @@ var StreamProgress = class {
|
|
|
13173
13344
|
/**
|
|
13174
13345
|
* Add a nested gadget call (called when nested gadget_call event received).
|
|
13175
13346
|
*/
|
|
13176
|
-
addNestedGadget(id, depth, parentInvocationId, name) {
|
|
13347
|
+
addNestedGadget(id, depth, parentInvocationId, name, parameters) {
|
|
13177
13348
|
this.nestedGadgets.set(id, {
|
|
13178
13349
|
depth,
|
|
13179
13350
|
parentInvocationId,
|
|
13180
13351
|
name,
|
|
13352
|
+
parameters,
|
|
13181
13353
|
startTime: Date.now()
|
|
13182
13354
|
});
|
|
13183
13355
|
if (this.isRunning && this.isTTY) {
|
|
@@ -13193,6 +13365,20 @@ var StreamProgress = class {
|
|
|
13193
13365
|
this.render();
|
|
13194
13366
|
}
|
|
13195
13367
|
}
|
|
13368
|
+
/**
|
|
13369
|
+
* Mark a nested gadget as completed (keeps it visible with ✓ indicator).
|
|
13370
|
+
* Records completion time to freeze the elapsed timer.
|
|
13371
|
+
*/
|
|
13372
|
+
completeNestedGadget(id) {
|
|
13373
|
+
const gadget = this.nestedGadgets.get(id);
|
|
13374
|
+
if (gadget) {
|
|
13375
|
+
gadget.completed = true;
|
|
13376
|
+
gadget.completedTime = Date.now();
|
|
13377
|
+
if (this.isRunning && this.isTTY) {
|
|
13378
|
+
this.render();
|
|
13379
|
+
}
|
|
13380
|
+
}
|
|
13381
|
+
}
|
|
13196
13382
|
/**
|
|
13197
13383
|
* Starts a new LLM call. Switches to streaming mode.
|
|
13198
13384
|
* @param model - Model name being used
|
|
@@ -13329,24 +13515,73 @@ var StreamProgress = class {
|
|
|
13329
13515
|
}
|
|
13330
13516
|
if (this.isTTY) {
|
|
13331
13517
|
for (const [gadgetId, gadget] of this.inFlightGadgets) {
|
|
13332
|
-
const
|
|
13333
|
-
const gadgetLine = ` ${
|
|
13518
|
+
const elapsedSeconds = (Date.now() - gadget.startTime) / 1e3;
|
|
13519
|
+
const gadgetLine = ` ${formatGadgetLine({
|
|
13520
|
+
name: gadget.name,
|
|
13521
|
+
parameters: gadget.params,
|
|
13522
|
+
elapsedSeconds,
|
|
13523
|
+
isComplete: false
|
|
13524
|
+
})}`;
|
|
13334
13525
|
lines.push(gadgetLine);
|
|
13526
|
+
const nestedOps = [];
|
|
13335
13527
|
for (const [_agentId, nested] of this.nestedAgents) {
|
|
13336
|
-
if (nested.parentInvocationId
|
|
13337
|
-
|
|
13338
|
-
|
|
13339
|
-
|
|
13340
|
-
|
|
13341
|
-
|
|
13342
|
-
|
|
13528
|
+
if (nested.parentInvocationId === gadgetId) {
|
|
13529
|
+
nestedOps.push({
|
|
13530
|
+
type: "agent",
|
|
13531
|
+
startTime: nested.startTime,
|
|
13532
|
+
depth: nested.depth,
|
|
13533
|
+
iteration: nested.iteration,
|
|
13534
|
+
model: nested.model,
|
|
13535
|
+
inputTokens: nested.inputTokens,
|
|
13536
|
+
cachedInputTokens: nested.cachedInputTokens,
|
|
13537
|
+
outputTokens: nested.outputTokens,
|
|
13538
|
+
cost: nested.cost,
|
|
13539
|
+
finishReason: nested.finishReason,
|
|
13540
|
+
completed: nested.completed,
|
|
13541
|
+
completedTime: nested.completedTime
|
|
13542
|
+
});
|
|
13543
|
+
}
|
|
13343
13544
|
}
|
|
13344
13545
|
for (const [_nestedId, nestedGadget] of this.nestedGadgets) {
|
|
13345
13546
|
if (nestedGadget.parentInvocationId === gadgetId) {
|
|
13346
|
-
|
|
13347
|
-
|
|
13348
|
-
|
|
13349
|
-
|
|
13547
|
+
nestedOps.push({
|
|
13548
|
+
type: "gadget",
|
|
13549
|
+
startTime: nestedGadget.startTime,
|
|
13550
|
+
depth: nestedGadget.depth,
|
|
13551
|
+
name: nestedGadget.name,
|
|
13552
|
+
parameters: nestedGadget.parameters,
|
|
13553
|
+
completed: nestedGadget.completed,
|
|
13554
|
+
completedTime: nestedGadget.completedTime
|
|
13555
|
+
});
|
|
13556
|
+
}
|
|
13557
|
+
}
|
|
13558
|
+
nestedOps.sort((a, b) => a.startTime - b.startTime);
|
|
13559
|
+
for (const op of nestedOps) {
|
|
13560
|
+
const indent = " ".repeat(op.depth + 1);
|
|
13561
|
+
const endTime = op.completedTime ?? Date.now();
|
|
13562
|
+
const elapsedSeconds2 = (endTime - op.startTime) / 1e3;
|
|
13563
|
+
if (op.type === "agent") {
|
|
13564
|
+
const line = formatLLMCallLine({
|
|
13565
|
+
iteration: op.iteration ?? 0,
|
|
13566
|
+
model: op.model ?? "",
|
|
13567
|
+
inputTokens: op.inputTokens,
|
|
13568
|
+
cachedInputTokens: op.cachedInputTokens,
|
|
13569
|
+
outputTokens: op.outputTokens,
|
|
13570
|
+
elapsedSeconds: elapsedSeconds2,
|
|
13571
|
+
cost: op.cost,
|
|
13572
|
+
finishReason: op.completed ? op.finishReason ?? "stop" : void 0,
|
|
13573
|
+
isStreaming: !op.completed,
|
|
13574
|
+
spinner
|
|
13575
|
+
});
|
|
13576
|
+
lines.push(`${indent}${line}`);
|
|
13577
|
+
} else {
|
|
13578
|
+
const line = formatGadgetLine({
|
|
13579
|
+
name: op.name ?? "",
|
|
13580
|
+
parameters: op.parameters,
|
|
13581
|
+
elapsedSeconds: elapsedSeconds2,
|
|
13582
|
+
isComplete: op.completed ?? false
|
|
13583
|
+
});
|
|
13584
|
+
lines.push(`${indent}${line}`);
|
|
13350
13585
|
}
|
|
13351
13586
|
}
|
|
13352
13587
|
}
|
|
@@ -13368,42 +13603,27 @@ var StreamProgress = class {
|
|
|
13368
13603
|
}
|
|
13369
13604
|
/**
|
|
13370
13605
|
* Format the streaming mode progress line (returns string, doesn't write).
|
|
13606
|
+
* Uses the shared formatLLMCallLine() function for consistent formatting
|
|
13607
|
+
* between main agent and nested subagent displays.
|
|
13371
13608
|
*/
|
|
13372
13609
|
formatStreamingLine(spinner) {
|
|
13373
|
-
const elapsed = ((Date.now() - this.callStartTime) / 1e3).toFixed(1);
|
|
13374
13610
|
const outTokens = this.callOutputTokensEstimated ? Math.round(this.callOutputChars / FALLBACK_CHARS_PER_TOKEN) : this.callOutputTokens;
|
|
13375
|
-
|
|
13376
|
-
|
|
13377
|
-
|
|
13378
|
-
|
|
13379
|
-
|
|
13380
|
-
|
|
13381
|
-
|
|
13382
|
-
|
|
13383
|
-
|
|
13384
|
-
|
|
13385
|
-
|
|
13386
|
-
|
|
13387
|
-
|
|
13388
|
-
|
|
13389
|
-
} else {
|
|
13390
|
-
parts.push(import_chalk4.default.green(formatted));
|
|
13611
|
+
return formatLLMCallLine({
|
|
13612
|
+
iteration: this.currentIteration,
|
|
13613
|
+
model: this.model ?? "",
|
|
13614
|
+
inputTokens: this.callInputTokens,
|
|
13615
|
+
cachedInputTokens: this.callCachedInputTokens,
|
|
13616
|
+
outputTokens: outTokens,
|
|
13617
|
+
elapsedSeconds: (Date.now() - this.callStartTime) / 1e3,
|
|
13618
|
+
cost: this.calculateCurrentCallCost(outTokens),
|
|
13619
|
+
isStreaming: true,
|
|
13620
|
+
spinner,
|
|
13621
|
+
contextPercent: this.getContextUsagePercent(),
|
|
13622
|
+
estimated: {
|
|
13623
|
+
input: this.callInputTokensEstimated,
|
|
13624
|
+
output: this.callOutputTokensEstimated
|
|
13391
13625
|
}
|
|
13392
|
-
}
|
|
13393
|
-
if (this.callInputTokens > 0) {
|
|
13394
|
-
const prefix = this.callInputTokensEstimated ? "~" : "";
|
|
13395
|
-
parts.push(import_chalk4.default.dim("\u2191") + import_chalk4.default.yellow(` ${prefix}${formatTokens(this.callInputTokens)}`));
|
|
13396
|
-
}
|
|
13397
|
-
if (this.isStreaming || outTokens > 0) {
|
|
13398
|
-
const prefix = this.callOutputTokensEstimated ? "~" : "";
|
|
13399
|
-
parts.push(import_chalk4.default.dim("\u2193") + import_chalk4.default.green(` ${prefix}${formatTokens(outTokens)}`));
|
|
13400
|
-
}
|
|
13401
|
-
parts.push(import_chalk4.default.dim(`${elapsed}s`));
|
|
13402
|
-
const callCost = this.calculateCurrentCallCost(outTokens);
|
|
13403
|
-
if (callCost > 0) {
|
|
13404
|
-
parts.push(import_chalk4.default.cyan(`$${formatCost(callCost)}`));
|
|
13405
|
-
}
|
|
13406
|
-
return `${parts.join(import_chalk4.default.dim(" | "))} ${import_chalk4.default.cyan(spinner)}`;
|
|
13626
|
+
});
|
|
13407
13627
|
}
|
|
13408
13628
|
/**
|
|
13409
13629
|
* Calculates live cost estimate for the current streaming call.
|
|
@@ -13631,7 +13851,7 @@ function addAgentOptions(cmd, defaults) {
|
|
|
13631
13851
|
OPTION_FLAGS.logLlmRequests,
|
|
13632
13852
|
OPTION_DESCRIPTIONS.logLlmRequests,
|
|
13633
13853
|
defaults?.["log-llm-requests"]
|
|
13634
|
-
).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)
|
|
13854
|
+
).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);
|
|
13635
13855
|
}
|
|
13636
13856
|
function configToCompleteOptions(config) {
|
|
13637
13857
|
const result = {};
|
|
@@ -13708,8 +13928,7 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13708
13928
|
const dockerOptions = {
|
|
13709
13929
|
docker: options.docker ?? false,
|
|
13710
13930
|
dockerRo: options.dockerRo ?? false,
|
|
13711
|
-
noDocker: options.noDocker ?? false
|
|
13712
|
-
dockerDev: options.dockerDev ?? false
|
|
13931
|
+
noDocker: options.noDocker ?? false
|
|
13713
13932
|
};
|
|
13714
13933
|
const dockerEnabled = resolveDockerEnabled(
|
|
13715
13934
|
env.dockerConfig,
|
|
@@ -13718,7 +13937,6 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13718
13937
|
// Profile-level docker: true/false
|
|
13719
13938
|
);
|
|
13720
13939
|
if (dockerEnabled) {
|
|
13721
|
-
const devMode = resolveDevMode(env.dockerConfig, dockerOptions.dockerDev);
|
|
13722
13940
|
const ctx = createDockerContext(
|
|
13723
13941
|
env.dockerConfig,
|
|
13724
13942
|
dockerOptions,
|
|
@@ -13729,7 +13947,7 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13729
13947
|
// Profile-level CWD permission override
|
|
13730
13948
|
);
|
|
13731
13949
|
try {
|
|
13732
|
-
await executeInDocker(ctx
|
|
13950
|
+
await executeInDocker(ctx);
|
|
13733
13951
|
} catch (error) {
|
|
13734
13952
|
if (error instanceof DockerSkipError) {
|
|
13735
13953
|
} else {
|
|
@@ -13756,9 +13974,18 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13756
13974
|
registry.registerByClass(gadget);
|
|
13757
13975
|
}
|
|
13758
13976
|
}
|
|
13977
|
+
if (!options.quiet) {
|
|
13978
|
+
const allNames = registry.getAll().map((g) => g.name).join(", ");
|
|
13979
|
+
env.stderr.write(import_chalk5.default.dim(`Gadgets: ${allNames}
|
|
13980
|
+
`));
|
|
13981
|
+
}
|
|
13759
13982
|
const printer = new StreamPrinter(env.stdout);
|
|
13760
13983
|
const stderrTTY = env.stderr.isTTY === true;
|
|
13761
|
-
const progress = new StreamProgress(
|
|
13984
|
+
const progress = new StreamProgress(
|
|
13985
|
+
env.stderr,
|
|
13986
|
+
stderrTTY,
|
|
13987
|
+
client.modelRegistry
|
|
13988
|
+
);
|
|
13762
13989
|
const abortController = new AbortController();
|
|
13763
13990
|
let wasCancelled = false;
|
|
13764
13991
|
let isStreaming = false;
|
|
@@ -13768,9 +13995,11 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13768
13995
|
wasCancelled = true;
|
|
13769
13996
|
abortController.abort();
|
|
13770
13997
|
progress.pause();
|
|
13771
|
-
env.stderr.write(
|
|
13998
|
+
env.stderr.write(
|
|
13999
|
+
import_chalk5.default.yellow(`
|
|
13772
14000
|
[Cancelled] ${progress.formatStats()}
|
|
13773
|
-
`)
|
|
14001
|
+
`)
|
|
14002
|
+
);
|
|
13774
14003
|
} else {
|
|
13775
14004
|
handleQuit();
|
|
13776
14005
|
}
|
|
@@ -13780,7 +14009,11 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13780
14009
|
cleanupSigint: null,
|
|
13781
14010
|
restore: () => {
|
|
13782
14011
|
if (stdinIsInteractive && stdinStream.isTTY && !wasCancelled) {
|
|
13783
|
-
keyboard.cleanupEsc = createEscKeyListener(
|
|
14012
|
+
keyboard.cleanupEsc = createEscKeyListener(
|
|
14013
|
+
stdinStream,
|
|
14014
|
+
handleCancel,
|
|
14015
|
+
handleCancel
|
|
14016
|
+
);
|
|
13784
14017
|
}
|
|
13785
14018
|
}
|
|
13786
14019
|
};
|
|
@@ -13805,7 +14038,11 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13805
14038
|
process.exit(130);
|
|
13806
14039
|
};
|
|
13807
14040
|
if (stdinIsInteractive && stdinStream.isTTY) {
|
|
13808
|
-
keyboard.cleanupEsc = createEscKeyListener(
|
|
14041
|
+
keyboard.cleanupEsc = createEscKeyListener(
|
|
14042
|
+
stdinStream,
|
|
14043
|
+
handleCancel,
|
|
14044
|
+
handleCancel
|
|
14045
|
+
);
|
|
13809
14046
|
}
|
|
13810
14047
|
keyboard.cleanupSigint = createSigintListener(
|
|
13811
14048
|
handleCancel,
|
|
@@ -13831,7 +14068,12 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13831
14068
|
gadgetApprovals,
|
|
13832
14069
|
defaultMode: "allowed"
|
|
13833
14070
|
};
|
|
13834
|
-
const approvalManager = new ApprovalManager(
|
|
14071
|
+
const approvalManager = new ApprovalManager(
|
|
14072
|
+
approvalConfig,
|
|
14073
|
+
env,
|
|
14074
|
+
progress,
|
|
14075
|
+
keyboard
|
|
14076
|
+
);
|
|
13835
14077
|
let usage;
|
|
13836
14078
|
let iterations = 0;
|
|
13837
14079
|
const llmLogsBaseDir = resolveLogDir(options.logLlmRequests, "requests");
|
|
@@ -13841,7 +14083,10 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13841
14083
|
try {
|
|
13842
14084
|
return await client.countTokens(model, messages);
|
|
13843
14085
|
} catch {
|
|
13844
|
-
const totalChars = messages.reduce(
|
|
14086
|
+
const totalChars = messages.reduce(
|
|
14087
|
+
(sum, m) => sum + (m.content?.length ?? 0),
|
|
14088
|
+
0
|
|
14089
|
+
);
|
|
13845
14090
|
return Math.round(totalChars / FALLBACK_CHARS_PER_TOKEN);
|
|
13846
14091
|
}
|
|
13847
14092
|
};
|
|
@@ -13863,7 +14108,9 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13863
14108
|
observers: {
|
|
13864
14109
|
// onLLMCallStart: Start progress indicator for each LLM call
|
|
13865
14110
|
// This showcases how to react to agent lifecycle events
|
|
14111
|
+
// Skip for subagent events (tracked separately via nested display)
|
|
13866
14112
|
onLLMCallStart: async (context) => {
|
|
14113
|
+
if (context.subagentContext) return;
|
|
13867
14114
|
isStreaming = true;
|
|
13868
14115
|
llmCallCounter++;
|
|
13869
14116
|
const inputTokens = await countMessagesTokens(
|
|
@@ -13889,7 +14136,9 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13889
14136
|
},
|
|
13890
14137
|
// onStreamChunk: Real-time updates as LLM generates tokens
|
|
13891
14138
|
// This enables responsive UIs that show progress during generation
|
|
14139
|
+
// Skip for subagent events (tracked separately via nested display)
|
|
13892
14140
|
onStreamChunk: async (context) => {
|
|
14141
|
+
if (context.subagentContext) return;
|
|
13893
14142
|
progress.update(context.accumulatedText.length);
|
|
13894
14143
|
if (context.usage) {
|
|
13895
14144
|
if (context.usage.inputTokens) {
|
|
@@ -13906,7 +14155,9 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13906
14155
|
},
|
|
13907
14156
|
// onLLMCallComplete: Finalize metrics after each LLM call
|
|
13908
14157
|
// This is where you'd typically log metrics or update dashboards
|
|
14158
|
+
// Skip progress updates for subagent events (tracked separately via nested display)
|
|
13909
14159
|
onLLMCallComplete: async (context) => {
|
|
14160
|
+
if (context.subagentContext) return;
|
|
13910
14161
|
isStreaming = false;
|
|
13911
14162
|
usage = context.usage;
|
|
13912
14163
|
iterations = Math.max(iterations, context.iteration + 1);
|
|
@@ -13935,7 +14186,7 @@ async function executeAgent(promptArg, options, env) {
|
|
|
13935
14186
|
}
|
|
13936
14187
|
const callElapsed = progress.getCallElapsedSeconds();
|
|
13937
14188
|
progress.endCall(context.usage);
|
|
13938
|
-
if (!options.quiet) {
|
|
14189
|
+
if (!options.quiet && !context.subagentContext) {
|
|
13939
14190
|
const summary = renderSummary({
|
|
13940
14191
|
iterations: context.iteration + 1,
|
|
13941
14192
|
model: options.model,
|
|
@@ -13993,7 +14244,10 @@ ${ctx.gadgetName} is denied by configuration.`
|
|
|
13993
14244
|
}
|
|
13994
14245
|
return { action: "proceed" };
|
|
13995
14246
|
}
|
|
13996
|
-
const result = await approvalManager.requestApproval(
|
|
14247
|
+
const result = await approvalManager.requestApproval(
|
|
14248
|
+
ctx.gadgetName,
|
|
14249
|
+
ctx.parameters
|
|
14250
|
+
);
|
|
13997
14251
|
if (!result.approved) {
|
|
13998
14252
|
return {
|
|
13999
14253
|
action: "skip",
|
|
@@ -14036,11 +14290,11 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
14036
14290
|
builder.withSyntheticGadgetCall(
|
|
14037
14291
|
"TellUser",
|
|
14038
14292
|
{
|
|
14039
|
-
message: "\u{1F44B} Hello! I'm ready to help.\n\
|
|
14293
|
+
message: "\u{1F44B} Hello! I'm ready to help.\n\nWhat would you like me to work on?",
|
|
14040
14294
|
done: false,
|
|
14041
14295
|
type: "info"
|
|
14042
14296
|
},
|
|
14043
|
-
"\u2139\uFE0F \u{1F44B} Hello! I'm ready to help.\n\
|
|
14297
|
+
"\u2139\uFE0F \u{1F44B} Hello! I'm ready to help.\n\nWhat would you like me to work on?"
|
|
14044
14298
|
);
|
|
14045
14299
|
builder.withTextOnlyHandler("acknowledge");
|
|
14046
14300
|
builder.withTextWithGadgetsHandler({
|
|
@@ -14056,34 +14310,41 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
14056
14310
|
].join(" ")
|
|
14057
14311
|
);
|
|
14058
14312
|
if (!options.quiet) {
|
|
14059
|
-
builder.
|
|
14060
|
-
if (
|
|
14061
|
-
const info =
|
|
14062
|
-
const
|
|
14313
|
+
builder.withSubagentEventCallback((subagentEvent) => {
|
|
14314
|
+
if (subagentEvent.type === "llm_call_start") {
|
|
14315
|
+
const info = subagentEvent.event;
|
|
14316
|
+
const subagentId = `${subagentEvent.gadgetInvocationId}:${info.iteration}`;
|
|
14063
14317
|
progress.addNestedAgent(
|
|
14064
|
-
|
|
14065
|
-
|
|
14066
|
-
|
|
14318
|
+
subagentId,
|
|
14319
|
+
subagentEvent.gadgetInvocationId,
|
|
14320
|
+
subagentEvent.depth,
|
|
14067
14321
|
info.model,
|
|
14068
14322
|
info.iteration,
|
|
14069
14323
|
info.inputTokens
|
|
14070
14324
|
);
|
|
14071
|
-
} else if (
|
|
14072
|
-
const info =
|
|
14073
|
-
const
|
|
14074
|
-
progress.updateNestedAgent(
|
|
14075
|
-
|
|
14076
|
-
|
|
14077
|
-
|
|
14325
|
+
} else if (subagentEvent.type === "llm_call_end") {
|
|
14326
|
+
const info = subagentEvent.event;
|
|
14327
|
+
const subagentId = `${subagentEvent.gadgetInvocationId}:${info.iteration}`;
|
|
14328
|
+
progress.updateNestedAgent(subagentId, {
|
|
14329
|
+
inputTokens: info.usage?.inputTokens ?? info.inputTokens,
|
|
14330
|
+
outputTokens: info.usage?.outputTokens ?? info.outputTokens,
|
|
14331
|
+
cachedInputTokens: info.usage?.cachedInputTokens,
|
|
14332
|
+
cacheCreationInputTokens: info.usage?.cacheCreationInputTokens,
|
|
14333
|
+
finishReason: info.finishReason,
|
|
14334
|
+
cost: info.cost
|
|
14335
|
+
});
|
|
14336
|
+
} else if (subagentEvent.type === "gadget_call") {
|
|
14337
|
+
const gadgetEvent = subagentEvent.event;
|
|
14078
14338
|
progress.addNestedGadget(
|
|
14079
14339
|
gadgetEvent.call.invocationId,
|
|
14080
|
-
|
|
14081
|
-
|
|
14082
|
-
gadgetEvent.call.gadgetName
|
|
14340
|
+
subagentEvent.depth,
|
|
14341
|
+
subagentEvent.gadgetInvocationId,
|
|
14342
|
+
gadgetEvent.call.gadgetName,
|
|
14343
|
+
gadgetEvent.call.parameters
|
|
14083
14344
|
);
|
|
14084
|
-
} else if (
|
|
14085
|
-
const resultEvent =
|
|
14086
|
-
progress.
|
|
14345
|
+
} else if (subagentEvent.type === "gadget_result") {
|
|
14346
|
+
const resultEvent = subagentEvent.event;
|
|
14347
|
+
progress.completeNestedGadget(resultEvent.result.invocationId);
|
|
14087
14348
|
}
|
|
14088
14349
|
});
|
|
14089
14350
|
}
|
|
@@ -14144,6 +14405,7 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
14144
14405
|
if (progress.hasInFlightGadgets()) {
|
|
14145
14406
|
progress.start();
|
|
14146
14407
|
}
|
|
14408
|
+
} else if (event.type === "subagent_event") {
|
|
14147
14409
|
}
|
|
14148
14410
|
}
|
|
14149
14411
|
} catch (error) {
|
|
@@ -14177,7 +14439,10 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
14177
14439
|
}
|
|
14178
14440
|
}
|
|
14179
14441
|
function registerAgentCommand(program, env, config, globalSubagents) {
|
|
14180
|
-
const cmd = program.command(COMMANDS.agent).description("Run the llmist agent loop with optional gadgets.").argument(
|
|
14442
|
+
const cmd = program.command(COMMANDS.agent).description("Run the llmist agent loop with optional gadgets.").argument(
|
|
14443
|
+
"[prompt]",
|
|
14444
|
+
"Prompt for the agent loop. Falls back to stdin when available."
|
|
14445
|
+
);
|
|
14181
14446
|
addAgentOptions(cmd, config);
|
|
14182
14447
|
cmd.action(
|
|
14183
14448
|
(prompt, options) => executeAction(() => {
|
|
@@ -14287,7 +14552,7 @@ function registerCompleteCommand(program, env, config) {
|
|
|
14287
14552
|
|
|
14288
14553
|
// src/cli/init-command.ts
|
|
14289
14554
|
var import_node_fs12 = require("fs");
|
|
14290
|
-
var
|
|
14555
|
+
var import_node_path13 = require("path");
|
|
14291
14556
|
var STARTER_CONFIG = `# ~/.llmist/cli.toml
|
|
14292
14557
|
# llmist CLI configuration file
|
|
14293
14558
|
#
|
|
@@ -14343,7 +14608,7 @@ var STARTER_CONFIG = `# ~/.llmist/cli.toml
|
|
|
14343
14608
|
`;
|
|
14344
14609
|
async function executeInit(_options, env) {
|
|
14345
14610
|
const configPath = getConfigPath();
|
|
14346
|
-
const configDir = (0,
|
|
14611
|
+
const configDir = (0, import_node_path13.dirname)(configPath);
|
|
14347
14612
|
if ((0, import_node_fs12.existsSync)(configPath)) {
|
|
14348
14613
|
env.stderr.write(`Configuration already exists at ${configPath}
|
|
14349
14614
|
`);
|