agent.libx.js 0.94.17 → 0.94.19

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/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { a as AgentOptions, H as Hooks, h as RunResult, A as Agent } from './Agent-COa80xYy.js';
2
- export { C as ChatFragment, D as DEFAULT_MUTATING, b as Decision, P as PermissionOptions, c as PermissionPolicy, d as PermissionRule, e as PreToolUseDecision, R as ReasoningEffort, f as RecordingHooks, g as RecordingLifecycle, T as ToolUse, i as ToolUseMeta, j as composeHooks, p as planMode, r as reasoningToChatFragment } from './Agent-COa80xYy.js';
1
+ import { a as AgentOptions, H as Hooks, h as RunResult, A as Agent } from './Agent-DmsB5hzp.js';
2
+ export { C as ChatFragment, D as DEFAULT_MUTATING, b as Decision, P as PermissionOptions, c as PermissionPolicy, d as PermissionRule, e as PreToolUseDecision, R as ReasoningEffort, f as RecordingHooks, g as RecordingLifecycle, T as ToolUse, i as ToolUseMeta, j as composeHooks, p as planMode, r as reasoningToChatFragment } from './Agent-DmsB5hzp.js';
3
3
  import { IFilesystem, FileMetadata } from '@livx.cc/wcli/core';
4
4
  export { CommandExecutor, FileMetadata, IFilesystem, IndexedDbFilesystem, MemFilesystem, registerHeadlessCommands } from '@livx.cc/wcli/core';
5
5
  import { BodDB } from '@bod.ee/db';
6
- import { A as AgentTool, C as ChatLike, a as ChatOptions, b as ChatResponse, h as ToolCall, H as HostBridge, U as UserQuestion, e as MessageContent } from './tools-GPWp7oXq.js';
7
- export { c as ContentPart, d as HostEvent, M as Message, R as Role, S as SandboxJobRegistry, f as StreamChunk, T as TodoItem, g as Tool, i as ToolContext, j as bashTool, k as contentText, l as defaultTools, m as editTool, n as exitSessionTool, o as imagePart, p as makeContext, q as makeJobTools, r as readTool, t as toWireTools, s as todoWriteTool, u as toolRegistry, v as toolsByName } from './tools-GPWp7oXq.js';
8
- export { M as McpCall, a as McpImage, b as McpRoute, c as McpRouteResolver, d as McpToolResult, e as McpToolSearchOptions, f as McpToolSpec, g as MountedMcpLike, h as buildMcpCatalog, m as makeLazyMcpToolSearch, i as makeMcpToolSearch, j as makeMcpToolSearchFromMounted, k as mcpToolToAgentTool, l as mcpToolsToAgentTools } from './mcp-C5GuDinb.js';
6
+ import { A as AgentTool, C as ChatLike, a as ChatOptions, b as ChatResponse, h as ToolCall, H as HostBridge, U as UserQuestion, e as MessageContent } from './tools-9AUK6SG2.js';
7
+ export { c as ContentPart, d as HostEvent, M as Message, R as Role, S as SandboxJobRegistry, f as StreamChunk, T as TodoItem, g as Tool, i as ToolContext, j as bashTool, k as contentText, l as defaultTools, m as editTool, n as exitSessionTool, o as imagePart, p as makeContext, q as makeJobTools, r as readTool, t as toWireTools, s as todoWriteTool, u as toolRegistry, v as toolsByName } from './tools-9AUK6SG2.js';
8
+ export { M as McpCall, a as McpImage, b as McpRoute, c as McpRouteResolver, d as McpToolResult, e as McpToolSearchOptions, f as McpToolSpec, g as MountedMcpLike, h as buildMcpCatalog, m as makeLazyMcpToolSearch, i as makeMcpToolSearch, j as makeMcpToolSearchFromMounted, k as mcpToolToAgentTool, l as mcpToolsToAgentTools } from './mcp-D00OuccC.js';
9
9
  import * as libx_js_src_modules_log from 'libx.js/src/modules/log';
10
10
  export { log } from 'libx.js/src/modules/log';
11
11
 
package/dist/index.js CHANGED
@@ -2586,9 +2586,10 @@ function planMode(opts) {
2586
2586
  parameters: { type: "object", required: ["plan"], properties: { plan: { type: "string", description: "the concrete steps you will take" } } },
2587
2587
  async run({ plan }, _ctx) {
2588
2588
  if (opts?.host?.confirm) {
2589
- const ok = await opts.host.confirm(`Approve this plan?
2589
+ const confirm = opts.host.confirm(`Approve this plan?
2590
2590
 
2591
2591
  ${String(plan ?? "")}`);
2592
+ const ok = await (_ctx?.parkHuman ? _ctx.parkHuman(confirm) : confirm);
2592
2593
  if (!ok) return "Plan not approved. Revise it and call ExitPlanMode again.";
2593
2594
  }
2594
2595
  approved = true;
@@ -2744,7 +2745,8 @@ var AgentOptions = class {
2744
2745
  tools = defaultTools();
2745
2746
  maxSteps = 25;
2746
2747
  // --- automatic kill-switches (always on; protect the API budget against runaway loops/abuse) ---
2747
- /** Hard ceiling on accumulated tokens (prompt+completion) across the run. 0 = unbounded. */
2748
+ /** Hard ceiling on accumulated tokens (prompt+completion) across the run; cache READS count at 0.
2749
+ * (their real price) so a fat cached context doesn't trip the guard on healthy turns. 0 = unbounded. */
2748
2750
  maxTokens = 2e5;
2749
2751
  /** Wall-clock ceiling in ms for the whole run. 0 = unbounded. */
2750
2752
  timeoutMs = 12e4;
@@ -2846,6 +2848,18 @@ var Agent = class _Agent {
2846
2848
  // the assembled system prompt from the last prepare()
2847
2849
  started = false;
2848
2850
  // session-start lifecycle hook fires once per conversation
2851
+ parkedMs = 0;
2852
+ // cumulative time blocked on the HUMAN (permission/plan prompts) — excluded from the timeout
2853
+ /** Time a human-blocking await (a permission/plan prompt) and bank it in `parkedMs` so idle prompt
2854
+ * time never trips the wall-clock kill-switch. The agent did no work while parked on the user. */
2855
+ async park(p) {
2856
+ const t = Date.now();
2857
+ try {
2858
+ return await p;
2859
+ } finally {
2860
+ this.parkedMs += Date.now() - t;
2861
+ }
2862
+ }
2849
2863
  /** Force the next `send()`/`run()` to rebuild the system prompt, tools, plan-mode and permission hooks
2850
2864
  * from `options` — apply mid-conversation changes to `planMode`/`permissions`/`model` etc. (prepare()
2851
2865
  * is otherwise memoized per conversation). */
@@ -2874,6 +2888,7 @@ var Agent = class _Agent {
2874
2888
  if (this.options.lintOnWrite) this.ctx.lint = checkSyntax;
2875
2889
  this.ctx.ai = this.options.ai;
2876
2890
  this.ctx.model = this.options.model;
2891
+ this.ctx.parkHuman = (p) => this.park(p);
2877
2892
  if (this.options.backgroundJobs) this.ctx.jobs = new SandboxJobRegistry();
2878
2893
  }
2879
2894
  /**
@@ -3019,19 +3034,21 @@ var Agent = class _Agent {
3019
3034
  const usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 };
3020
3035
  let usageEstimated = false;
3021
3036
  const start = Date.now();
3037
+ this.parkedMs = 0;
3022
3038
  let toolCallsTotal = 0;
3023
3039
  let lastFp = "";
3024
3040
  let repeats = 0;
3025
3041
  const kill = (finishReason) => {
3026
- log3.warn(`kill-switch: ${finishReason} (steps=${steps}, tokens=${usage.totalTokens}, ms=${Date.now() - start})`);
3042
+ log3.warn(`kill-switch: ${finishReason} (steps=${steps}, tokens=${usage.totalTokens}, budgetTokens=${Math.round(usage.totalTokens - 0.9 * usage.cacheReadTokens)}, ms=${Date.now() - start - this.parkedMs}${this.parkedMs ? ` +${this.parkedMs} parked` : ""})`);
3027
3043
  this.ctx.jobs?.killAll();
3028
3044
  return { text: lastAssistantText(this.transcript), steps, finishReason, messages: this.transcript, usage, usageEstimated };
3029
3045
  };
3030
3046
  while (true) {
3031
3047
  if (o.signal?.aborted) return kill("aborted");
3032
3048
  if (steps >= o.maxSteps) return kill("max_steps");
3033
- if (o.timeoutMs && Date.now() - start >= o.timeoutMs) return kill("timeout");
3034
- if (o.maxTokens && usage.totalTokens >= o.maxTokens) return kill("budget");
3049
+ if (o.timeoutMs && Date.now() - start - this.parkedMs >= o.timeoutMs) return kill("timeout");
3050
+ const budgetTokens = usage.totalTokens - 0.9 * usage.cacheReadTokens;
3051
+ if (o.maxTokens && budgetTokens >= o.maxTokens) return kill("budget");
3035
3052
  steps++;
3036
3053
  this.options.host?.notify?.({ kind: "turn_start", message: `step ${steps}` });
3037
3054
  let res;
@@ -3166,7 +3183,7 @@ var Agent = class _Agent {
3166
3183
  const hooks = this.activeHooks;
3167
3184
  const call = { name: tc.function.name, args };
3168
3185
  const meta = { id: tc.id };
3169
- const decision = await hooks?.preToolUse?.(call, meta);
3186
+ const decision = await this.park(Promise.resolve(hooks?.preToolUse?.(call, meta)));
3170
3187
  if (decision?.block) {
3171
3188
  const blocked = `Blocked by hook: ${decision.reason ?? "no reason given"}`;
3172
3189
  log3.debug(`${tc.function.name} -> ${blocked}`);
@@ -3208,6 +3225,7 @@ var Agent = class _Agent {
3208
3225
  this.ctx.emit = void 0;
3209
3226
  }
3210
3227
  if (!threw) result = await this.maybeAutoTest(tc.function.name, result);
3228
+ if (images?.length && !result) result = `[${images.length} image${images.length > 1 ? "s" : ""} attached]`;
3211
3229
  const cap = this.options.maxToolResultBytes ?? 0;
3212
3230
  if (!threw && cap > 0 && result.length > cap) {
3213
3231
  const info = { tool: tc.function.name, args };