@oh-my-pi/pi-agent-core 16.0.0 → 16.0.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/CHANGELOG.md +7 -0
- package/dist/types/agent-loop.d.ts +2 -0
- package/dist/types/telemetry.d.ts +1 -1
- package/package.json +6 -6
- package/src/agent-loop.ts +18 -3
- package/src/telemetry.ts +10 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [16.0.1] - 2026-06-15
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Fixed transient provider errors after streamed tool-call arguments so incomplete tool calls are marked as interrupted output instead of eligible for automatic retry ([#2683](https://github.com/can1357/oh-my-pi/issues/2683)).
|
|
10
|
+
- Fixed `@oh-my-pi/pi-agent-core` telemetry content capture crashing every chat turn with `TypeError: systemPrompt.map is not a function` when `captureMessageContent` is enabled (`OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true`). `ChatRequestSnapshot.systemPrompt` now accepts `string | readonly string[]` and the telemetry serializers normalize a bare string to a single-element array — previously the full-system serializer called `.map` on a string (the `.length` guard passed, so it threw) and the request-message serializer iterated the string into one `system` message per character.
|
|
11
|
+
|
|
5
12
|
## [16.0.0] - 2026-06-15
|
|
6
13
|
|
|
7
14
|
### Breaking Changes
|
|
@@ -6,6 +6,8 @@ import { type Context, EventStream } from "@oh-my-pi/pi-ai";
|
|
|
6
6
|
import { type Dialect } from "@oh-my-pi/pi-ai/dialect";
|
|
7
7
|
import { type AgentRunCoverage, type AgentRunSummary } from "./run-collector";
|
|
8
8
|
import type { AgentContext, AgentEvent, AgentLoopConfig, AgentMessage, StreamFn } from "./types";
|
|
9
|
+
/** Stop-details marker for a provider error after assistant content/tool args already streamed. */
|
|
10
|
+
export declare const STREAM_INTERRUPTED_AFTER_CONTENT_STOP_DETAIL = "stream_interrupted_after_content";
|
|
9
11
|
/**
|
|
10
12
|
* Start an agent loop with a new prompt message.
|
|
11
13
|
* The prompt is added to the context and events are emitted for it.
|
|
@@ -369,7 +369,7 @@ export interface ChatRequestSnapshot {
|
|
|
369
369
|
readonly tools?: readonly {
|
|
370
370
|
readonly name: string;
|
|
371
371
|
}[];
|
|
372
|
-
readonly systemPrompt?: readonly string[];
|
|
372
|
+
readonly systemPrompt?: string | readonly string[];
|
|
373
373
|
readonly messages?: readonly Message[];
|
|
374
374
|
}
|
|
375
375
|
/**
|
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": "16.0.
|
|
4
|
+
"version": "16.0.2",
|
|
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,11 +35,11 @@
|
|
|
35
35
|
"fmt": "biome format --write ."
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@oh-my-pi/pi-ai": "16.0.
|
|
39
|
-
"@oh-my-pi/pi-catalog": "16.0.
|
|
40
|
-
"@oh-my-pi/pi-natives": "16.0.
|
|
41
|
-
"@oh-my-pi/pi-utils": "16.0.
|
|
42
|
-
"@oh-my-pi/snapcompact": "16.0.
|
|
38
|
+
"@oh-my-pi/pi-ai": "16.0.2",
|
|
39
|
+
"@oh-my-pi/pi-catalog": "16.0.2",
|
|
40
|
+
"@oh-my-pi/pi-natives": "16.0.2",
|
|
41
|
+
"@oh-my-pi/pi-utils": "16.0.2",
|
|
42
|
+
"@oh-my-pi/snapcompact": "16.0.2",
|
|
43
43
|
"@opentelemetry/api": "^1.9.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
package/src/agent-loop.ts
CHANGED
|
@@ -63,6 +63,9 @@ import type {
|
|
|
63
63
|
} from "./types";
|
|
64
64
|
import { yieldIfDue } from "./utils/yield";
|
|
65
65
|
|
|
66
|
+
/** Stop-details marker for a provider error after assistant content/tool args already streamed. */
|
|
67
|
+
export const STREAM_INTERRUPTED_AFTER_CONTENT_STOP_DETAIL = "stream_interrupted_after_content";
|
|
68
|
+
|
|
66
69
|
/** Sentinel returned by the abort race in `streamAssistantResponse`. */
|
|
67
70
|
const ABORTED: unique symbol = Symbol("agent-loop-aborted");
|
|
68
71
|
|
|
@@ -1355,14 +1358,26 @@ function retainCompletedToolCalls(
|
|
|
1355
1358
|
completedToolCallIds: ReadonlySet<string>,
|
|
1356
1359
|
): AssistantMessage {
|
|
1357
1360
|
if (message.stopReason !== "error" && message.stopReason !== "aborted") return message;
|
|
1358
|
-
let
|
|
1361
|
+
let droppedIncompleteToolCall = false;
|
|
1359
1362
|
const content = message.content.filter(block => {
|
|
1360
1363
|
if (block.type !== "toolCall") return true;
|
|
1361
1364
|
const keep = completedToolCallIds.has(block.id);
|
|
1362
|
-
if (!keep)
|
|
1365
|
+
if (!keep) droppedIncompleteToolCall = true;
|
|
1363
1366
|
return keep;
|
|
1364
1367
|
});
|
|
1365
|
-
|
|
1368
|
+
if (!droppedIncompleteToolCall) return message;
|
|
1369
|
+
return {
|
|
1370
|
+
...message,
|
|
1371
|
+
content,
|
|
1372
|
+
stopDetails:
|
|
1373
|
+
message.stopDetails?.type === STREAM_INTERRUPTED_AFTER_CONTENT_STOP_DETAIL
|
|
1374
|
+
? message.stopDetails
|
|
1375
|
+
: {
|
|
1376
|
+
type: STREAM_INTERRUPTED_AFTER_CONTENT_STOP_DETAIL,
|
|
1377
|
+
category: message.stopDetails?.type ?? null,
|
|
1378
|
+
explanation: message.stopDetails?.explanation ?? null,
|
|
1379
|
+
},
|
|
1380
|
+
};
|
|
1366
1381
|
}
|
|
1367
1382
|
|
|
1368
1383
|
function emitDiscardedHarmonyPartial(
|
package/src/telemetry.ts
CHANGED
|
@@ -731,7 +731,7 @@ export interface ChatRequestSnapshot {
|
|
|
731
731
|
readonly reasoningEffort?: string;
|
|
732
732
|
readonly toolChoice?: ToolChoice;
|
|
733
733
|
readonly tools?: readonly { readonly name: string }[];
|
|
734
|
-
readonly systemPrompt?: readonly string[];
|
|
734
|
+
readonly systemPrompt?: string | readonly string[];
|
|
735
735
|
readonly messages?: readonly Message[];
|
|
736
736
|
}
|
|
737
737
|
|
|
@@ -796,6 +796,11 @@ function applyContentCaptureForResponse(telemetry: AgentTelemetry, span: Span, m
|
|
|
796
796
|
}
|
|
797
797
|
}
|
|
798
798
|
|
|
799
|
+
function normalizeSystemPromptParts(systemPrompt: string | readonly string[] | undefined): readonly string[] {
|
|
800
|
+
if (!systemPrompt) return [];
|
|
801
|
+
return typeof systemPrompt === "string" ? [systemPrompt] : systemPrompt;
|
|
802
|
+
}
|
|
803
|
+
|
|
799
804
|
function serializeRequestMessagesForTelemetry(
|
|
800
805
|
telemetry: AgentTelemetry,
|
|
801
806
|
request: ChatRequestSnapshot,
|
|
@@ -803,10 +808,8 @@ function serializeRequestMessagesForTelemetry(
|
|
|
803
808
|
const serializer = telemetry.config.contentSerializer?.requestMessages;
|
|
804
809
|
if (serializer) return callContentSerializer(telemetry, "requestMessages", () => serializer(request));
|
|
805
810
|
const messages: TelemetryMessageSummary[] = [];
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
messages.push({ role: "system", content: summarizeTelemetryValue(text) });
|
|
809
|
-
}
|
|
811
|
+
for (const text of normalizeSystemPromptParts(request.systemPrompt))
|
|
812
|
+
messages.push({ role: "system", content: summarizeTelemetryValue(text) });
|
|
810
813
|
if (request.messages) {
|
|
811
814
|
for (const message of request.messages) {
|
|
812
815
|
messages.push({ role: message.role, content: summarizeTelemetryValue(message.content) });
|
|
@@ -874,8 +877,8 @@ interface OtelOutputMessage extends OtelInputMessage {
|
|
|
874
877
|
}
|
|
875
878
|
|
|
876
879
|
function serializeFullSystemInstructionsForTelemetry(request: ChatRequestSnapshot): string | undefined {
|
|
877
|
-
const systemPrompt = request.systemPrompt;
|
|
878
|
-
if (
|
|
880
|
+
const systemPrompt = normalizeSystemPromptParts(request.systemPrompt);
|
|
881
|
+
if (systemPrompt.length === 0) return undefined;
|
|
879
882
|
return stringifyJsonAttribute(systemPrompt.map(text => ({ type: "text", content: text }) satisfies OtelMessagePart));
|
|
880
883
|
}
|
|
881
884
|
|