@livx.cc/agentx 0.99.30 → 0.99.31

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.
@@ -1,5 +1,5 @@
1
1
  import { IFilesystem } from '@livx.cc/wcli/core';
2
- import { M as Message, H as HostBridge, A as AgentTool, C as ChatLike, g as MessageContent, U as UserQuestion } from './tools-BZVppx-6.js';
2
+ import { M as Message, H as HostBridge, A as AgentTool, C as ChatLike, g as MessageContent, U as UserQuestion } from './tools-Byyh_bae.js';
3
3
 
4
4
  /**
5
5
  * Hooks — deterministic interception points around tool execution, run by the
@@ -325,8 +325,9 @@ declare class AgentOptions {
325
325
  traceDir?: string;
326
326
  /** Stream tokens from the model. Takes effect only with a `host.notify`; off => current (non-stream) behavior. */
327
327
  stream: boolean;
328
- /** Closure reflex for delegated runtimes (cursor/claude-code): when such a turn ends on a tool call with
329
- * no assistant text after it (the runtime went silent post-work), nudge ONE more step to ANSWER the user
328
+ /** Closure reflex for delegated runtimes (cursor/claude-code): when such a turn runs tools but never
329
+ * closes — no assistant text after the last tool, or text that trails off on an action it announced
330
+ * and never took ("Also checking for X.") — nudge ONE more step to ANSWER the user
330
331
  * from the tool results already in the transcript — so the turn delivers a reply instead of trailing off
331
332
  * mid-narration. Deliberately not a "summarize what you did" nudge: that produced process reports and
332
333
  * permission-asking instead of answers (see the nudge text in runLoop).
package/dist/cli.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
- import { H as Hooks, i as RunResult, R as ReasoningEffort, A as Agent } from './Agent-DC7FEEjF.js';
2
+ import { H as Hooks, i as RunResult, R as ReasoningEffort, A as Agent } from './Agent-USp7SIao.js';
3
3
  import { IFilesystem } from '@livx.cc/wcli/core';
4
- import { M as Message, U as UserQuestion, H as HostBridge, c as ContentPart, g as MessageContent } from './tools-BZVppx-6.js';
4
+ import { M as Message, U as UserQuestion, H as HostBridge, c as ContentPart, g as MessageContent } from './tools-Byyh_bae.js';
5
5
 
6
6
  /**
7
7
  * On-disk session store for the CLI: each conversation is one JSON file at
package/dist/cli.js CHANGED
@@ -258,7 +258,13 @@ function stripContent(content, stub) {
258
258
  });
259
259
  return changed ? out : content;
260
260
  }
261
- var log2, p_sep, IMAGE_ELIDE_STUB, IMAGE_REF_SCHEME, REF_REGISTRY_MAX, refRegistry, isImageRefUrl, bearsImage;
261
+ function endsOnAnnouncedAction(text) {
262
+ const sentences = text.split(/(?<=[.!?])\s+|\n+/).map((s) => s.trim()).filter(Boolean);
263
+ const last = sentences[sentences.length - 1];
264
+ if (!last || NEXT_STEP.test(last)) return false;
265
+ return ANNOUNCED_ACTION.test(last);
266
+ }
267
+ var log2, p_sep, IMAGE_ELIDE_STUB, IMAGE_REF_SCHEME, REF_REGISTRY_MAX, refRegistry, isImageRefUrl, bearsImage, ANNOUNCED_ACTION, NEXT_STEP;
262
268
  var init_llm = __esm({
263
269
  "src/llm.ts"() {
264
270
  "use strict";
@@ -271,6 +277,8 @@ var init_llm = __esm({
271
277
  refRegistry = /* @__PURE__ */ new Map();
272
278
  isImageRefUrl = (url) => !!url && url.startsWith(IMAGE_REF_SCHEME);
273
279
  bearsImage = (m) => messageHasImage(m.content) || toolImageRef(m.content) != null;
280
+ 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;
281
+ NEXT_STEP = /^next (?:step|run|up)\b/i;
274
282
  }
275
283
  });
276
284
 
@@ -3614,8 +3622,9 @@ var AgentOptions = class {
3614
3622
  traceDir;
3615
3623
  /** Stream tokens from the model. Takes effect only with a `host.notify`; off => current (non-stream) behavior. */
3616
3624
  stream = false;
3617
- /** Closure reflex for delegated runtimes (cursor/claude-code): when such a turn ends on a tool call with
3618
- * no assistant text after it (the runtime went silent post-work), nudge ONE more step to ANSWER the user
3625
+ /** Closure reflex for delegated runtimes (cursor/claude-code): when such a turn runs tools but never
3626
+ * closes — no assistant text after the last tool, or text that trails off on an action it announced
3627
+ * and never took ("Also checking for X.") — nudge ONE more step to ANSWER the user
3619
3628
  * from the tool results already in the transcript — so the turn delivers a reply instead of trailing off
3620
3629
  * mid-narration. Deliberately not a "summarize what you did" nudge: that produced process reports and
3621
3630
  * permission-asking instead of answers (see the nudge text in runLoop).
@@ -4118,7 +4127,7 @@ var Agent = class _Agent {
4118
4127
  }
4119
4128
  if (toolCalls.length === 0) {
4120
4129
  if (this.drainInjections()) continue;
4121
- if (o.closeDelegatedTurns && res.endedOnToolNoText && !closureNudged && steps < o.maxSteps) {
4130
+ if (o.closeDelegatedTurns && res.endedWithoutClosing && !closureNudged && steps < o.maxSteps) {
4122
4131
  closureNudged = true;
4123
4132
  log6.verbose("delegated turn went silent after a tool \u2014 nudging a closing answer");
4124
4133
  this.transcript.push({
@@ -4225,7 +4234,8 @@ var Agent = class _Agent {
4225
4234
  let usage;
4226
4235
  const delegated = /* @__PURE__ */ new Map();
4227
4236
  const delegatedOrder = [];
4228
- let endedOnToolNoText = false;
4237
+ let sawTool = false;
4238
+ let trailing = "";
4229
4239
  for await (const chunk of stream) {
4230
4240
  poke?.();
4231
4241
  if (this.options.signal?.aborted) break;
@@ -4245,11 +4255,12 @@ var Agent = class _Agent {
4245
4255
  if (a.output !== void 0) prev.output = a.output;
4246
4256
  prev.status = a.status;
4247
4257
  }
4248
- endedOnToolNoText = true;
4258
+ sawTool = true;
4259
+ trailing = "";
4249
4260
  }
4250
4261
  if (chunk.content) {
4251
4262
  content += chunk.content;
4252
- if (chunk.content.trim()) endedOnToolNoText = false;
4263
+ trailing += chunk.content;
4253
4264
  this.options.host.notify({ kind: "text_delta", message: chunk.content });
4254
4265
  }
4255
4266
  if (chunk.finishReason) finishReason = chunk.finishReason;
@@ -4257,7 +4268,8 @@ var Agent = class _Agent {
4257
4268
  if (chunk.usage) usage = chunk.usage;
4258
4269
  }
4259
4270
  const delegatedTools = delegatedOrder.map((k) => delegated.get(k));
4260
- return { content, ...finishReason ? { finishReason } : {}, ...toolCalls ? { toolCalls } : {}, ...usage ? { usage } : {}, ...delegatedTools.length ? { delegatedTools } : {}, ...endedOnToolNoText ? { endedOnToolNoText: true } : {} };
4271
+ const endedWithoutClosing = sawTool && (!trailing.trim() || endsOnAnnouncedAction(trailing));
4272
+ return { content, ...finishReason ? { finishReason } : {}, ...toolCalls ? { toolCalls } : {}, ...usage ? { usage } : {}, ...delegatedTools.length ? { delegatedTools } : {}, ...endedWithoutClosing ? { endedWithoutClosing: true } : {} };
4261
4273
  }
4262
4274
  async dispatch(tc) {
4263
4275
  const tool = this.activeTools.find((t) => t.name === tc.function.name);
@@ -9038,7 +9050,8 @@ The filesystem root '/' is the real machine root \u2014 you have full filesystem
9038
9050
  const list = [...names];
9039
9051
  return `You are agentx (an agent runtime) \u2014 NOT Claude Code or Claude Desktop, which are separate agents with their own config. Your MCP servers are configured in .agent/settings.json or .agent/config.* (this project's .agent/ or ~/.agent/), and their tools are already in your tool list as \`mcp__<server>__<tool>\`.${list.length ? ` Configured MCP servers: ${list.join(", ")}.` : " No MCP servers are currently configured."} When asked which MCPs/tools you have, answer from your own tool list \u2014 never read Claude Code/Desktop config (e.g. ~/.claude.json, claude_desktop_config.json) to answer; those belong to a different agent.`;
9040
9052
  })();
9041
- const extra = [o.appendSystemPrompt, envNote, cwdNote, shellNote, toneNote, mountNote, mcpNote].filter(Boolean).join("\n\n");
9053
+ const closureNote = isDelegated ? "Never end your turn on an action you only announced. If you say you are about to search, read, check or run something, DO it in the same turn before you stop. Your last message must be the ANSWER \u2014 the result and what it means \u2014 or an explicit statement that you are blocked and why. Narration of what you are about to do is not an ending." : "";
9054
+ const extra = [o.appendSystemPrompt, envNote, cwdNote, shellNote, toneNote, mountNote, mcpNote, closureNote].filter(Boolean).join("\n\n");
9042
9055
  const basePrompt = (() => {
9043
9056
  let p = new AgentOptions().systemPrompt;
9044
9057
  if (!virtual) p = p.replace("operating on a virtual filesystem", "operating on the host filesystem");