@oh-my-pi/pi-agent-core 13.14.2 → 13.15.2
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/package.json +3 -3
- package/src/agent-loop.ts +29 -35
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-agent-core",
|
|
4
|
-
"version": "13.
|
|
4
|
+
"version": "13.15.2",
|
|
5
5
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
6
6
|
"homepage": "https://github.com/can1357/oh-my-pi",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"test": "bun test"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@oh-my-pi/pi-ai": "13.
|
|
35
|
-
"@oh-my-pi/pi-utils": "13.
|
|
34
|
+
"@oh-my-pi/pi-ai": "13.15.2",
|
|
35
|
+
"@oh-my-pi/pi-utils": "13.15.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@sinclair/typebox": "^0.34",
|
package/src/agent-loop.ts
CHANGED
|
@@ -196,7 +196,6 @@ async function runLoop(
|
|
|
196
196
|
// Outer loop: continues when queued follow-up messages arrive after agent would stop
|
|
197
197
|
while (true) {
|
|
198
198
|
let hasMoreToolCalls = true;
|
|
199
|
-
let steeringAfterTools: AgentMessage[] | null = null;
|
|
200
199
|
|
|
201
200
|
// Inner loop: process tool calls and steering messages
|
|
202
201
|
while (hasMoreToolCalls || pendingMessages.length > 0) {
|
|
@@ -225,6 +224,7 @@ async function runLoop(
|
|
|
225
224
|
// Stream assistant response
|
|
226
225
|
const message = await streamAssistantResponse(currentContext, config, signal, stream, streamFn);
|
|
227
226
|
newMessages.push(message);
|
|
227
|
+
let steeringMessagesFromExecution: AgentMessage[] | undefined;
|
|
228
228
|
|
|
229
229
|
if (message.stopReason === "error" || message.stopReason === "aborted") {
|
|
230
230
|
// Create placeholder tool results for any tool calls in the aborted message
|
|
@@ -250,19 +250,20 @@ async function runLoop(
|
|
|
250
250
|
|
|
251
251
|
const toolResults: ToolResultMessage[] = [];
|
|
252
252
|
if (hasMoreToolCalls) {
|
|
253
|
-
const
|
|
253
|
+
const executionResult = await executeToolCalls(
|
|
254
254
|
currentContext.tools,
|
|
255
255
|
message,
|
|
256
256
|
signal,
|
|
257
257
|
stream,
|
|
258
258
|
config.getSteeringMessages,
|
|
259
|
-
config.getToolContext,
|
|
260
259
|
config.interruptMode,
|
|
260
|
+
config.getToolContext,
|
|
261
261
|
config.transformToolCallArguments,
|
|
262
262
|
config.intentTracing,
|
|
263
263
|
);
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
|
|
265
|
+
toolResults.push(...executionResult.toolResults);
|
|
266
|
+
steeringMessagesFromExecution = executionResult.steeringMessages;
|
|
266
267
|
|
|
267
268
|
for (const result of toolResults) {
|
|
268
269
|
currentContext.messages.push(result);
|
|
@@ -272,13 +273,7 @@ async function runLoop(
|
|
|
272
273
|
|
|
273
274
|
stream.push({ type: "turn_end", message, toolResults });
|
|
274
275
|
|
|
275
|
-
|
|
276
|
-
if (steeringAfterTools && steeringAfterTools.length > 0) {
|
|
277
|
-
pendingMessages = steeringAfterTools;
|
|
278
|
-
steeringAfterTools = null;
|
|
279
|
-
} else {
|
|
280
|
-
pendingMessages = (await config.getSteeringMessages?.()) || [];
|
|
281
|
-
}
|
|
276
|
+
pendingMessages = steeringMessagesFromExecution ?? ((await config.getSteeringMessages?.()) || []);
|
|
282
277
|
}
|
|
283
278
|
|
|
284
279
|
// Agent would stop here. Check for follow-up messages.
|
|
@@ -433,25 +428,37 @@ async function executeToolCalls(
|
|
|
433
428
|
signal: AbortSignal | undefined,
|
|
434
429
|
stream: EventStream<AgentEvent, AgentMessage[]>,
|
|
435
430
|
getSteeringMessages?: AgentLoopConfig["getSteeringMessages"],
|
|
436
|
-
getToolContext?: AgentLoopConfig["getToolContext"],
|
|
437
431
|
interruptMode: AgentLoopConfig["interruptMode"] = "immediate",
|
|
432
|
+
getToolContext?: AgentLoopConfig["getToolContext"],
|
|
438
433
|
transformToolCallArguments?: AgentLoopConfig["transformToolCallArguments"],
|
|
439
434
|
intentTracing?: AgentLoopConfig["intentTracing"],
|
|
440
435
|
): Promise<{ toolResults: ToolResultMessage[]; steeringMessages?: AgentMessage[] }> {
|
|
441
436
|
type ToolCallContent = Extract<AssistantMessage["content"][number], { type: "toolCall" }>;
|
|
442
437
|
const toolCalls = assistantMessage.content.filter((c): c is ToolCallContent => c.type === "toolCall");
|
|
443
438
|
const emittedToolResults: ToolResultMessage[] = [];
|
|
444
|
-
let steeringMessages: AgentMessage[] | undefined;
|
|
445
|
-
const shouldInterruptImmediately = interruptMode !== "wait";
|
|
446
439
|
const toolCallInfos = toolCalls.map(call => ({ id: call.id, name: call.name }));
|
|
447
440
|
const batchId = `${assistantMessage.timestamp ?? Date.now()}_${toolCalls[0]?.id ?? "batch"}`;
|
|
441
|
+
const shouldInterruptImmediately = interruptMode !== "wait";
|
|
448
442
|
const steeringAbortController = new AbortController();
|
|
449
443
|
const toolSignal = signal
|
|
450
444
|
? AbortSignal.any([signal, steeringAbortController.signal])
|
|
451
445
|
: steeringAbortController.signal;
|
|
452
446
|
const interruptState = { triggered: false };
|
|
447
|
+
let steeringMessages: AgentMessage[] | undefined;
|
|
453
448
|
let steeringCheck: Promise<void> | null = null;
|
|
454
449
|
|
|
450
|
+
const records = toolCalls.map(toolCall => ({
|
|
451
|
+
toolCall,
|
|
452
|
+
tool: tools?.find(t => t.name === toolCall.name),
|
|
453
|
+
args: toolCall.arguments as Record<string, unknown>,
|
|
454
|
+
started: false,
|
|
455
|
+
result: undefined as AgentToolResult<any> | undefined,
|
|
456
|
+
isError: false,
|
|
457
|
+
skipped: false,
|
|
458
|
+
toolResultMessage: undefined as ToolResultMessage | undefined,
|
|
459
|
+
resultEmitted: false,
|
|
460
|
+
}));
|
|
461
|
+
|
|
455
462
|
const checkSteering = async (): Promise<void> => {
|
|
456
463
|
if (!shouldInterruptImmediately || !getSteeringMessages || interruptState.triggered) {
|
|
457
464
|
return;
|
|
@@ -473,18 +480,6 @@ async function executeToolCalls(
|
|
|
473
480
|
await steeringCheck;
|
|
474
481
|
};
|
|
475
482
|
|
|
476
|
-
const records = toolCalls.map(toolCall => ({
|
|
477
|
-
toolCall,
|
|
478
|
-
tool: tools?.find(t => t.name === toolCall.name),
|
|
479
|
-
args: toolCall.arguments as Record<string, unknown>,
|
|
480
|
-
started: false,
|
|
481
|
-
result: undefined as AgentToolResult<any> | undefined,
|
|
482
|
-
isError: false,
|
|
483
|
-
skipped: false,
|
|
484
|
-
toolResultMessage: undefined as ToolResultMessage | undefined,
|
|
485
|
-
resultEmitted: false,
|
|
486
|
-
}));
|
|
487
|
-
|
|
488
483
|
const emitToolResult = (record: (typeof records)[number], result: AgentToolResult<any>, isError: boolean): void => {
|
|
489
484
|
if (record.resultEmitted) return;
|
|
490
485
|
const { toolCall } = record;
|
|
@@ -578,7 +573,6 @@ async function executeToolCalls(
|
|
|
578
573
|
transformToolCallArguments ? transformToolCallArguments(effectiveArgs, toolCall.name) : effectiveArgs,
|
|
579
574
|
tool.nonAbortable ? undefined : toolSignal,
|
|
580
575
|
partialResult => {
|
|
581
|
-
if (interruptState.triggered) return;
|
|
582
576
|
stream.push({
|
|
583
577
|
type: "tool_execution_update",
|
|
584
578
|
toolCallId: toolCall.id,
|
|
@@ -637,13 +631,6 @@ async function executeToolCalls(
|
|
|
637
631
|
return { toolResults: emittedToolResults, steeringMessages };
|
|
638
632
|
}
|
|
639
633
|
|
|
640
|
-
function createSkippedToolResult(): AgentToolResult<any> {
|
|
641
|
-
return {
|
|
642
|
-
content: [{ type: "text", text: "Skipped due to queued user message." }],
|
|
643
|
-
details: {},
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
|
-
|
|
647
634
|
/**
|
|
648
635
|
* Create a tool result for a tool call that was aborted or errored before execution.
|
|
649
636
|
* Maintains the tool_use/tool_result pairing required by the API.
|
|
@@ -690,3 +677,10 @@ function createAbortedToolResult(
|
|
|
690
677
|
|
|
691
678
|
return toolResultMessage;
|
|
692
679
|
}
|
|
680
|
+
|
|
681
|
+
function createSkippedToolResult(): AgentToolResult<any> {
|
|
682
|
+
return {
|
|
683
|
+
content: [{ type: "text", text: "Skipped due to queued user message." }],
|
|
684
|
+
details: {},
|
|
685
|
+
};
|
|
686
|
+
}
|