@livx.cc/agentx 0.99.30 → 0.99.32

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,14 +1,14 @@
1
- import { a as AgentOptions, H as Hooks, i as RunResult, A as Agent } from './Agent-DC7FEEjF.js';
2
- export { C as ChatFragment, b as CompactResult, D as DEFAULT_MUTATING, c as Decision, P as PermissionOptions, d as PermissionPolicy, e as PermissionRule, f as PreToolUseDecision, R as ReasoningEffort, g as RecordingHooks, h as RecordingLifecycle, T as ToolUse, j as ToolUseMeta, k as composeHooks, l as estimateTokens, p as planMode, r as reasoningToChatFragment } from './Agent-DC7FEEjF.js';
1
+ import { a as AgentOptions, H as Hooks, i as RunResult, A as Agent } from './Agent-USp7SIao.js';
2
+ export { C as ChatFragment, b as CompactResult, D as DEFAULT_MUTATING, c as Decision, P as PermissionOptions, d as PermissionPolicy, e as PermissionRule, f as PreToolUseDecision, R as ReasoningEffort, g as RecordingHooks, h as RecordingLifecycle, T as ToolUse, j as ToolUseMeta, k as composeHooks, l as estimateTokens, p as planMode, r as reasoningToChatFragment } from './Agent-USp7SIao.js';
3
3
  export { MODEL_ALIASES, ModelSwitch, ResolveModelSwitchOpts, modelShortLabel, resolveModelAlias, resolveModelSwitch } from './models.js';
4
4
  import { IFilesystem, FileMetadata } from '@livx.cc/wcli/core';
5
5
  export { CommandExecutor, FileMetadata, IFilesystem, IndexedDbFilesystem, MemFilesystem, registerHeadlessCommands } from '@livx.cc/wcli/core';
6
6
  import { BodDB } from '@bod.ee/db';
7
- import { A as AgentTool, C as ChatLike, a as ChatOptions, b as ChatResponse, j as ToolCall, H as HostBridge, U as UserQuestion, g as MessageContent } from './tools-BZVppx-6.js';
8
- export { c as ContentPart, d as HostEvent, I as IMAGE_ELIDE_STUB, e as IMAGE_REF_SCHEME, f as ImageRef, M as Message, R as Role, S as SandboxJobRegistry, h as StreamChunk, T as TodoItem, i as Tool, k as ToolContext, l as bashTool, m as clearImageRefs, n as contentBytes, o as contentText, p as defaultTools, q as editTool, r as elideImages, s as elideInlineImages, t as elideStaleImages, u as exitSessionTool, v as expandImagesForSend, w as imagePart, x as imageRefPart, y as imageRefResult, z as makeContext, B as makeJobTools, D as messageHasImage, E as messageHasImageRef, F as messageHasInlineImage, G as mintImageRef, J as parseImageRef, K as readTool, L as remintImageRefs, N as sendBytes, O as sendBytesPer, P as toWireTools, Q as todoWriteTool, V as toolImageRef, W as toolRegistry, X as toolsByName } from './tools-BZVppx-6.js';
7
+ import { A as AgentTool, C as ChatLike, a as ChatOptions, b as ChatResponse, j as ToolCall, H as HostBridge, U as UserQuestion, g as MessageContent } from './tools-Byyh_bae.js';
8
+ export { c as ContentPart, d as HostEvent, I as IMAGE_ELIDE_STUB, e as IMAGE_REF_SCHEME, f as ImageRef, M as Message, R as Role, S as SandboxJobRegistry, h as StreamChunk, T as TodoItem, i as Tool, k as ToolContext, l as bashTool, m as clearImageRefs, n as contentBytes, o as contentText, p as defaultTools, q as editTool, r as elideImages, s as elideInlineImages, t as elideStaleImages, u as exitSessionTool, v as expandImagesForSend, w as imagePart, x as imageRefPart, y as imageRefResult, z as makeContext, B as makeJobTools, D as messageHasImage, E as messageHasImageRef, F as messageHasInlineImage, G as mintImageRef, J as parseImageRef, K as readTool, L as remintImageRefs, N as sendBytes, O as sendBytesPer, P as toWireTools, Q as todoWriteTool, V as toolImageRef, W as toolRegistry, X as toolsByName } from './tools-Byyh_bae.js';
9
9
  import { SpokenSplitter } from '@bod.ee/voice';
10
10
  export { AudioSink, AudioSource, AuthProvider, CartesiaTTS, CartesiaTTSOptions, STT_SAMPLE_RATE, SonioxSTT, SonioxSTTOptions, SttLike, TTS_SAMPLE_RATE, TtsLike, VoiceEngine, VoiceEngineOptions, VoiceState, resolveAuth } from '@bod.ee/voice';
11
- 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-Cnq0pS95.js';
11
+ 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-Bd19NiCL.js';
12
12
  import * as libx_js_src_modules_log from 'libx.js/src/modules/log';
13
13
  export { log } from 'libx.js/src/modules/log';
14
14
 
package/dist/index.js CHANGED
@@ -260,7 +260,13 @@ function stripContent(content, stub) {
260
260
  });
261
261
  return changed ? out : content;
262
262
  }
263
- var log2, p_sep, IMAGE_ELIDE_STUB, IMAGE_REF_SCHEME, REF_REGISTRY_MAX, refRegistry, isImageRefUrl, bearsImage;
263
+ function endsOnAnnouncedAction(text) {
264
+ const sentences = text.split(/(?<=[.!?])\s+|\n+/).map((s) => s.trim()).filter(Boolean);
265
+ const last = sentences[sentences.length - 1];
266
+ if (!last || NEXT_STEP.test(last)) return false;
267
+ return ANNOUNCED_ACTION.test(last);
268
+ }
269
+ var log2, p_sep, IMAGE_ELIDE_STUB, IMAGE_REF_SCHEME, REF_REGISTRY_MAX, refRegistry, isImageRefUrl, bearsImage, ANNOUNCED_ACTION, NEXT_STEP;
264
270
  var init_llm = __esm({
265
271
  "src/llm.ts"() {
266
272
  "use strict";
@@ -273,6 +279,8 @@ var init_llm = __esm({
273
279
  refRegistry = /* @__PURE__ */ new Map();
274
280
  isImageRefUrl = (url) => !!url && url.startsWith(IMAGE_REF_SCHEME);
275
281
  bearsImage = (m) => messageHasImage(m.content) || toolImageRef(m.content) != null;
282
+ ANNOUNCED_ACTION = /^(?:also\s+|now\s+|then\s+)*(?:let me\b|i'?ll\b|i will\b|i'?m going to\b|(?:re-?)?(?:check|search|scan|read|verify|run|inspect|expand|look|examin|continu|proceed|try|fetch|load|open|test|build|grep|find|review|trac|dig|explor)\w*ing\b)/i;
283
+ NEXT_STEP = /^next (?:step|run|up)\b/i;
276
284
  }
277
285
  });
278
286
 
@@ -1869,20 +1877,23 @@ async function nodeSpawn() {
1869
1877
  return _spawn;
1870
1878
  }
1871
1879
  function makeRealShellTool(options) {
1872
- const timeoutMs = options.timeoutMs ?? 12e4;
1880
+ const defaultTimeoutMs = options.timeoutMs ?? 12e4;
1881
+ const maxTimeoutMs = Math.max(options.maxTimeoutMs ?? 6e5, defaultTimeoutMs);
1873
1882
  return {
1874
1883
  name: "Shell",
1875
- description: "Run a shell command via /bin/sh in the working directory. Executes any installed binary \u2014 ls, cat, grep, git, bun, node, curl, scripts, etc. Returns combined stdout+stderr; non-zero exits are prefixed `[exit N]`. Runs non-interactively with no terminal (stdin is /dev/null): commands that prompt for input fail fast rather than hang \u2014 for privileged actions use a non-interactive flag (e.g. `sudo -n`), or ask the user to run the command themselves. Set `background:true` for long-running processes (servers, watchers) \u2014 returns a job id immediately; poll with ShellOutput, stop with ShellKill.",
1884
+ description: `Run a shell command via /bin/sh in the working directory. Executes any installed binary \u2014 ls, cat, grep, git, bun, node, curl, scripts, etc. Returns combined stdout+stderr; non-zero exits are prefixed \`[exit N]\`. Runs non-interactively with no terminal (stdin is /dev/null): commands that prompt for input fail fast rather than hang \u2014 for privileged actions use a non-interactive flag (e.g. \`sudo -n\`), or ask the user to run the command themselves. Each command is killed after ${defaultTimeoutMs}ms (result \`[exit 124]\` with whatever output it produced) \u2014 pass \`timeoutMs\` (max ${maxTimeoutMs}) for a legitimately slower command, and always bound network commands yourself (e.g. \`curl -m 10\`). Set \`background:true\` for long-running processes (servers, watchers) \u2014 returns a job id immediately; poll with ShellOutput, stop with ShellKill.`,
1876
1885
  parameters: {
1877
1886
  type: "object",
1878
1887
  required: ["command"],
1879
1888
  properties: {
1880
1889
  command: { type: "string", description: "the shell command line to execute" },
1881
- background: { type: "boolean", description: "run detached and return a job id immediately (for servers/watchers/long builds)" }
1890
+ background: { type: "boolean", description: "run detached and return a job id immediately (for servers/watchers/long builds)" },
1891
+ timeoutMs: { type: "number", description: "wall-clock cap for THIS command, overriding the default (clamped to the tool max)" }
1882
1892
  }
1883
1893
  },
1884
- async run({ command, background }, ctx) {
1894
+ async run({ command, background, timeoutMs: askedTimeoutMs }, ctx) {
1885
1895
  const cmd = String(command ?? "");
1896
+ const timeoutMs = Number.isFinite(askedTimeoutMs) && Number(askedTimeoutMs) > 0 ? Math.min(Number(askedTimeoutMs), maxTimeoutMs) : defaultTimeoutMs;
1886
1897
  if (!cmd.trim()) return "[exit 1] empty command";
1887
1898
  if (background) {
1888
1899
  if (!options.registry) return "Error: background execution is not enabled in this host (no job registry).";
@@ -3579,8 +3590,9 @@ var AgentOptions = class {
3579
3590
  traceDir;
3580
3591
  /** Stream tokens from the model. Takes effect only with a `host.notify`; off => current (non-stream) behavior. */
3581
3592
  stream = false;
3582
- /** Closure reflex for delegated runtimes (cursor/claude-code): when such a turn ends on a tool call with
3583
- * no assistant text after it (the runtime went silent post-work), nudge ONE more step to ANSWER the user
3593
+ /** Closure reflex for delegated runtimes (cursor/claude-code): when such a turn runs tools but never
3594
+ * closes — no assistant text after the last tool, or text that trails off on an action it announced
3595
+ * and never took ("Also checking for X.") — nudge ONE more step to ANSWER the user
3584
3596
  * from the tool results already in the transcript — so the turn delivers a reply instead of trailing off
3585
3597
  * mid-narration. Deliberately not a "summarize what you did" nudge: that produced process reports and
3586
3598
  * permission-asking instead of answers (see the nudge text in runLoop).
@@ -4083,7 +4095,7 @@ var Agent = class _Agent {
4083
4095
  }
4084
4096
  if (toolCalls.length === 0) {
4085
4097
  if (this.drainInjections()) continue;
4086
- if (o.closeDelegatedTurns && res.endedOnToolNoText && !closureNudged && steps < o.maxSteps) {
4098
+ if (o.closeDelegatedTurns && res.endedWithoutClosing && !closureNudged && steps < o.maxSteps) {
4087
4099
  closureNudged = true;
4088
4100
  log6.verbose("delegated turn went silent after a tool \u2014 nudging a closing answer");
4089
4101
  this.transcript.push({
@@ -4190,7 +4202,8 @@ var Agent = class _Agent {
4190
4202
  let usage;
4191
4203
  const delegated = /* @__PURE__ */ new Map();
4192
4204
  const delegatedOrder = [];
4193
- let endedOnToolNoText = false;
4205
+ let sawTool = false;
4206
+ let trailing = "";
4194
4207
  for await (const chunk of stream) {
4195
4208
  poke?.();
4196
4209
  if (this.options.signal?.aborted) break;
@@ -4210,11 +4223,12 @@ var Agent = class _Agent {
4210
4223
  if (a.output !== void 0) prev.output = a.output;
4211
4224
  prev.status = a.status;
4212
4225
  }
4213
- endedOnToolNoText = true;
4226
+ sawTool = true;
4227
+ trailing = "";
4214
4228
  }
4215
4229
  if (chunk.content) {
4216
4230
  content += chunk.content;
4217
- if (chunk.content.trim()) endedOnToolNoText = false;
4231
+ trailing += chunk.content;
4218
4232
  this.options.host.notify({ kind: "text_delta", message: chunk.content });
4219
4233
  }
4220
4234
  if (chunk.finishReason) finishReason = chunk.finishReason;
@@ -4222,7 +4236,8 @@ var Agent = class _Agent {
4222
4236
  if (chunk.usage) usage = chunk.usage;
4223
4237
  }
4224
4238
  const delegatedTools = delegatedOrder.map((k) => delegated.get(k));
4225
- return { content, ...finishReason ? { finishReason } : {}, ...toolCalls ? { toolCalls } : {}, ...usage ? { usage } : {}, ...delegatedTools.length ? { delegatedTools } : {}, ...endedOnToolNoText ? { endedOnToolNoText: true } : {} };
4239
+ const endedWithoutClosing = sawTool && (!trailing.trim() || endsOnAnnouncedAction(trailing));
4240
+ return { content, ...finishReason ? { finishReason } : {}, ...toolCalls ? { toolCalls } : {}, ...usage ? { usage } : {}, ...delegatedTools.length ? { delegatedTools } : {}, ...endedWithoutClosing ? { endedWithoutClosing: true } : {} };
4226
4241
  }
4227
4242
  async dispatch(tc) {
4228
4243
  const tool = this.activeTools.find((t) => t.name === tc.function.name);