@oh-my-pi/pi-agent-core 17.0.7 → 17.0.8
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/CHANGELOG.md +6 -0
- package/dist/types/agent-loop.d.ts +9 -0
- package/package.json +7 -7
- package/src/agent-loop.ts +31 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [17.0.8] - 2026-07-22
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Improved resilience against transient stream JSON parse failures by recovering completed tool calls while safely preventing incomplete, unknown, refused, or sensitive calls from executing.
|
|
10
|
+
|
|
5
11
|
## [17.0.5] - 2026-07-18
|
|
6
12
|
|
|
7
13
|
### Added
|
|
@@ -111,6 +111,15 @@ export interface SyntheticToolResultDetails {
|
|
|
111
111
|
executed: false;
|
|
112
112
|
upstreamError?: string;
|
|
113
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Narrow an {@link AgentMessage} to a synthetic {@link ToolResultMessage} —
|
|
116
|
+
* a tool_result emitted for a tool call the assistant never invoked (see
|
|
117
|
+
* {@link SyntheticToolResultDetails}). Consumers use this to look past the
|
|
118
|
+
* placeholder pairing back to the assistant turn that produced it, e.g.
|
|
119
|
+
* `AgentSession.retry()` walking back over the synthetic results a
|
|
120
|
+
* stalled/aborted mid-tool-call turn leaves behind.
|
|
121
|
+
*/
|
|
122
|
+
export declare function isSyntheticToolResultMessage(message: AgentMessage | undefined): message is ToolResultMessage<SyntheticToolResultDetails>;
|
|
114
123
|
/**
|
|
115
124
|
* Create the persisted synthetic result for a tool call that was emitted by
|
|
116
125
|
* the assistant but never invoked locally.
|
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": "17.0.
|
|
4
|
+
"version": "17.0.8",
|
|
5
5
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
"fmt": "biome format --write ."
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@oh-my-pi/pi-ai": "17.0.
|
|
39
|
-
"@oh-my-pi/pi-catalog": "17.0.
|
|
40
|
-
"@oh-my-pi/pi-natives": "17.0.
|
|
41
|
-
"@oh-my-pi/pi-utils": "17.0.
|
|
42
|
-
"@oh-my-pi/pi-wire": "17.0.
|
|
43
|
-
"@oh-my-pi/snapcompact": "17.0.
|
|
38
|
+
"@oh-my-pi/pi-ai": "17.0.8",
|
|
39
|
+
"@oh-my-pi/pi-catalog": "17.0.8",
|
|
40
|
+
"@oh-my-pi/pi-natives": "17.0.8",
|
|
41
|
+
"@oh-my-pi/pi-utils": "17.0.8",
|
|
42
|
+
"@oh-my-pi/pi-wire": "17.0.8",
|
|
43
|
+
"@oh-my-pi/snapcompact": "17.0.8",
|
|
44
44
|
"@opentelemetry/api": "^1.9.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
package/src/agent-loop.ts
CHANGED
|
@@ -1629,13 +1629,26 @@ function recoverTransientErrorToolTurn(
|
|
|
1629
1629
|
if (message.stopReason !== "error") return message;
|
|
1630
1630
|
const toolCalls = message.content.filter(block => block.type === "toolCall");
|
|
1631
1631
|
if (toolCalls.length === 0) return message;
|
|
1632
|
+
const stopDetailType = message.stopDetails?.type;
|
|
1633
|
+
const stopDetailCategory = message.stopDetails?.category;
|
|
1634
|
+
if (
|
|
1635
|
+
stopDetailType === "refusal" ||
|
|
1636
|
+
stopDetailType === "sensitive" ||
|
|
1637
|
+
stopDetailCategory === "refusal" ||
|
|
1638
|
+
stopDetailCategory === "sensitive"
|
|
1639
|
+
)
|
|
1640
|
+
return message;
|
|
1632
1641
|
const availableToolNames = new Set<string>();
|
|
1633
1642
|
for (const tool of availableTools) {
|
|
1634
1643
|
availableToolNames.add(tool.name);
|
|
1635
1644
|
if (tool.customWireName !== undefined) availableToolNames.add(tool.customWireName);
|
|
1636
1645
|
}
|
|
1637
1646
|
if (!toolCalls.every(toolCall => availableToolNames.has(toolCall.name))) return message;
|
|
1638
|
-
if (
|
|
1647
|
+
if (
|
|
1648
|
+
!AIError.isStreamReadErrorText(`${message.errorMessage ?? ""}\n${message.stopDetails?.explanation ?? ""}`) &&
|
|
1649
|
+
!AIError.isTransientStreamParseError(message.errorMessage) &&
|
|
1650
|
+
!AIError.isTransientStreamParseError(message.stopDetails?.explanation)
|
|
1651
|
+
)
|
|
1639
1652
|
return message;
|
|
1640
1653
|
return {
|
|
1641
1654
|
...message,
|
|
@@ -2285,6 +2298,23 @@ export interface SyntheticToolResultDetails {
|
|
|
2285
2298
|
upstreamError?: string;
|
|
2286
2299
|
}
|
|
2287
2300
|
|
|
2301
|
+
/**
|
|
2302
|
+
* Narrow an {@link AgentMessage} to a synthetic {@link ToolResultMessage} —
|
|
2303
|
+
* a tool_result emitted for a tool call the assistant never invoked (see
|
|
2304
|
+
* {@link SyntheticToolResultDetails}). Consumers use this to look past the
|
|
2305
|
+
* placeholder pairing back to the assistant turn that produced it, e.g.
|
|
2306
|
+
* `AgentSession.retry()` walking back over the synthetic results a
|
|
2307
|
+
* stalled/aborted mid-tool-call turn leaves behind.
|
|
2308
|
+
*/
|
|
2309
|
+
export function isSyntheticToolResultMessage(
|
|
2310
|
+
message: AgentMessage | undefined,
|
|
2311
|
+
): message is ToolResultMessage<SyntheticToolResultDetails> {
|
|
2312
|
+
return (
|
|
2313
|
+
message?.role === "toolResult" &&
|
|
2314
|
+
(message.details as SyntheticToolResultDetails | undefined)?.__synthetic === true
|
|
2315
|
+
);
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2288
2318
|
function syntheticDetailsFor(
|
|
2289
2319
|
reason: "aborted" | "error" | "skipped" | "length",
|
|
2290
2320
|
errorMessage: string | undefined,
|