@strayl/agent 0.1.11 → 0.1.12

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.
Files changed (2) hide show
  1. package/dist/agent.js +30 -18
  2. package/package.json +1 -1
package/dist/agent.js CHANGED
@@ -7201,16 +7201,11 @@ var LLMClient = class {
7201
7201
  }
7202
7202
  }
7203
7203
  }
7204
- if (choice.finish_reason) {
7205
- console.error(`[LLM] finish_reason: ${choice.finish_reason}, partialToolCalls: ${partialToolCalls.size}`);
7206
- }
7207
- if (choice.finish_reason === "tool_calls" || choice.finish_reason === "stop") {
7208
- if (!emittedToolCalls) {
7209
- emittedToolCalls = true;
7210
- for (const [, partial] of partialToolCalls) {
7211
- if (partial.id && partial.name) {
7212
- yield { type: "tool_call_complete", id: partial.id, name: partial.name, arguments: partial.arguments };
7213
- }
7204
+ if (choice.finish_reason && !emittedToolCalls) {
7205
+ emittedToolCalls = true;
7206
+ for (const [, partial] of partialToolCalls) {
7207
+ if (partial.id && partial.name) {
7208
+ yield { type: "tool_call_complete", id: partial.id, name: partial.name, arguments: partial.arguments };
7214
7209
  }
7215
7210
  }
7216
7211
  }
@@ -7223,11 +7218,10 @@ var LLMClient = class {
7223
7218
  };
7224
7219
  }
7225
7220
  }
7226
- if (!emittedToolCalls && partialToolCalls.size > 0) {
7227
- console.error(`[LLM] Fallback tool call emit: ${partialToolCalls.size} partial calls`);
7221
+ if (!emittedToolCalls) {
7228
7222
  for (const [, partial] of partialToolCalls) {
7229
7223
  if (partial.id && partial.name) {
7230
- yield { type: "tool_call_complete", id: partial.id, name: partial.name, arguments: partial.arguments || "{}" };
7224
+ yield { type: "tool_call_complete", id: partial.id, name: partial.name, arguments: partial.arguments };
7231
7225
  }
7232
7226
  }
7233
7227
  }
@@ -7660,7 +7654,11 @@ var HITLManager = class {
7660
7654
  this.idMap.set(id, safe);
7661
7655
  return safe;
7662
7656
  }
7663
- async waitForResponse(id) {
7657
+ /**
7658
+ * Wait for HITL response, polling both file system and optional stdin drain callback.
7659
+ * @param onPoll - Called each poll iteration so the caller can drain stdin and write pending responses.
7660
+ */
7661
+ async waitForResponse(id, onPoll) {
7664
7662
  const safe = this.safeId(id);
7665
7663
  const filePath = path2.join(this.dir, `${safe}.json`);
7666
7664
  const maxWait = 30 * 60 * 1e3;
@@ -7669,6 +7667,7 @@ var HITLManager = class {
7669
7667
  if (await this.isCancelled()) {
7670
7668
  return { decision: "reject" };
7671
7669
  }
7670
+ if (onPoll) await onPoll();
7672
7671
  try {
7673
7672
  const content = await fs.readFile(filePath, "utf-8");
7674
7673
  const response = JSON.parse(content);
@@ -13550,6 +13549,8 @@ async function runAgent(config) {
13550
13549
  const maxIterations = config.maxIterations ?? 200;
13551
13550
  let consecutiveLLMErrors = 0;
13552
13551
  const MAX_CONSECUTIVE_LLM_ERRORS = 5;
13552
+ let consecutiveNoToolCalls = 0;
13553
+ const MAX_NO_TOOL_RETRIES = 3;
13553
13554
  if (config.restoreCheckpoint) {
13554
13555
  const cp = config.restoreCheckpoint;
13555
13556
  context.restoreMessages(cp.messages);
@@ -13723,10 +13724,14 @@ ${IMPLEMENTATION_MODE_PROMPT2}`);
13723
13724
  });
13724
13725
  }
13725
13726
  if (completedToolCalls.length === 0) {
13726
- console.error(`[Agent] Iteration ${iteration}: No tool calls. assistantText: ${assistantText.length} chars. Breaking.`);
13727
- break;
13727
+ consecutiveNoToolCalls++;
13728
+ if (consecutiveNoToolCalls >= MAX_NO_TOOL_RETRIES) break;
13729
+ context.addUser(
13730
+ "[System] You output text without calling any tools. Do not think out loud \u2014 use your tools to take action. If you need to communicate with the user, call the askUser tool. If you need to create a plan, call the writePlan tool. Continue working on the task."
13731
+ );
13732
+ continue;
13728
13733
  }
13729
- console.error(`[Agent] Iteration ${iteration}: ${completedToolCalls.length} tool call(s): ${completedToolCalls.map((tc) => tc.function.name).join(", ")}`);
13734
+ consecutiveNoToolCalls = 0;
13730
13735
  for (const tc of completedToolCalls) {
13731
13736
  if (stdin.isCancelled()) {
13732
13737
  context.addToolResult(tc.id, tc.function.name, JSON.stringify({ error: "Cancelled by user." }));
@@ -13747,7 +13752,14 @@ ${IMPLEMENTATION_MODE_PROMPT2}`);
13747
13752
  const toolDef = registry.get(tc.function.name);
13748
13753
  if (toolDef?.hitl) {
13749
13754
  emitter.emit({ type: "hitl-request", id: tc.id, safe_id: hitl.safeId(tc.id), tool: tc.function.name, args: parsedArgs });
13750
- const response = await hitl.waitForResponse(tc.id);
13755
+ const response = await hitl.waitForResponse(tc.id, async () => {
13756
+ for (const cmd of stdin.drain()) {
13757
+ if (cmd.type === "hitl-response") {
13758
+ await hitl.writeResponse(cmd.id, { decision: cmd.decision, data: cmd.data });
13759
+ } else if (cmd.type === "cancel") {
13760
+ }
13761
+ }
13762
+ });
13751
13763
  if (response.decision === "reject") {
13752
13764
  const rejectResult = JSON.stringify({ error: "User rejected this action." });
13753
13765
  emitter.emit({ type: "tool-result", id: tc.id, name: tc.function.name, output: rejectResult });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strayl/agent",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"