@oh-my-pi/pi-agent-core 5.4.2 → 5.6.7

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/package.json +3 -3
  2. package/src/agent-loop.ts +57 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-agent-core",
3
- "version": "5.4.2",
3
+ "version": "5.6.7",
4
4
  "description": "General-purpose agent with transport abstraction, state management, and attachment support",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -13,8 +13,8 @@
13
13
  "test": "vitest --run"
14
14
  },
15
15
  "dependencies": {
16
- "@oh-my-pi/pi-ai": "5.4.2",
17
- "@oh-my-pi/pi-tui": "5.4.2"
16
+ "@oh-my-pi/pi-ai": "5.6.7",
17
+ "@oh-my-pi/pi-tui": "5.6.7"
18
18
  },
19
19
  "keywords": [
20
20
  "ai",
package/src/agent-loop.ts CHANGED
@@ -168,7 +168,18 @@ async function runLoop(
168
168
  newMessages.push(message);
169
169
 
170
170
  if (message.stopReason === "error" || message.stopReason === "aborted") {
171
- stream.push({ type: "turn_end", message, toolResults: [] });
171
+ // Create placeholder tool results for any tool calls in the aborted message
172
+ // This maintains the tool_use/tool_result pairing that the API requires
173
+ type ToolCallContent = Extract<AssistantMessage["content"][number], { type: "toolCall" }>;
174
+ const toolCalls = message.content.filter((c): c is ToolCallContent => c.type === "toolCall");
175
+ const toolResults: ToolResultMessage[] = [];
176
+ for (const toolCall of toolCalls) {
177
+ const result = createAbortedToolResult(toolCall, stream, message.stopReason);
178
+ currentContext.messages.push(result);
179
+ newMessages.push(result);
180
+ toolResults.push(result);
181
+ }
182
+ stream.push({ type: "turn_end", message, toolResults });
172
183
  stream.push({ type: "agent_end", messages: newMessages });
173
184
  stream.end(newMessages);
174
185
  return;
@@ -487,3 +498,48 @@ function skipToolCall(
487
498
 
488
499
  return toolResultMessage;
489
500
  }
501
+
502
+ /**
503
+ * Create a tool result for a tool call that was aborted or errored before execution.
504
+ * Maintains the tool_use/tool_result pairing required by the API.
505
+ */
506
+ function createAbortedToolResult(
507
+ toolCall: Extract<AssistantMessage["content"][number], { type: "toolCall" }>,
508
+ stream: EventStream<AgentEvent, AgentMessage[]>,
509
+ reason: "aborted" | "error",
510
+ ): ToolResultMessage {
511
+ const message = reason === "aborted" ? "Tool execution was aborted." : "Tool execution failed due to an error.";
512
+ const result: AgentToolResult<any> = {
513
+ content: [{ type: "text", text: message }],
514
+ details: {},
515
+ };
516
+
517
+ stream.push({
518
+ type: "tool_execution_start",
519
+ toolCallId: toolCall.id,
520
+ toolName: toolCall.name,
521
+ args: toolCall.arguments,
522
+ });
523
+ stream.push({
524
+ type: "tool_execution_end",
525
+ toolCallId: toolCall.id,
526
+ toolName: toolCall.name,
527
+ result,
528
+ isError: true,
529
+ });
530
+
531
+ const toolResultMessage: ToolResultMessage = {
532
+ role: "toolResult",
533
+ toolCallId: toolCall.id,
534
+ toolName: toolCall.name,
535
+ content: result.content,
536
+ details: {},
537
+ isError: true,
538
+ timestamp: Date.now(),
539
+ };
540
+
541
+ stream.push({ type: "message_start", message: toolResultMessage });
542
+ stream.push({ type: "message_end", message: toolResultMessage });
543
+
544
+ return toolResultMessage;
545
+ }