test: normalize subagent wrapper stop reasons

This commit is contained in:
pi
2026-04-11 01:44:47 +01:00
parent 1d426e82f2
commit 589c1f9cc5
2 changed files with 54 additions and 4 deletions

View File

@@ -1,3 +1,30 @@
const STOP_REASON_MAP = new Map([
["stop", "stop"],
["end_turn", "stop"],
["endturn", "stop"],
["length", "length"],
["tooluse", "toolUse"],
["tool_use", "toolUse"],
["aborted", "aborted"],
["error", "error"],
]);
export function normalizeStopReason(value) {
if (typeof value !== "string") {
return { stopReason: undefined, rawStopReason: undefined };
}
const rawStopReason = value.trim();
if (!rawStopReason) {
return { stopReason: undefined, rawStopReason: undefined };
}
return {
stopReason: STOP_REASON_MAP.get(rawStopReason.toLowerCase()),
rawStopReason,
};
}
export function normalizePiEvent(event) { export function normalizePiEvent(event) {
if (event?.type === "tool_execution_start") { if (event?.type === "tool_execution_start") {
return { return {
@@ -14,11 +41,14 @@ export function normalizePiEvent(event) {
.join("\n") .join("\n")
.trim(); .trim();
const { stopReason, rawStopReason } = normalizeStopReason(event.message.stopReason);
return { return {
type: "assistant_text", type: "assistant_text",
text, text,
model: event.message.model, model: event.message.model,
stopReason: event.message.stopReason, stopReason,
rawStopReason,
usage: event.message.usage, usage: event.message.usage,
}; };
} }

View File

@@ -1,6 +1,6 @@
import test from "node:test"; import test from "node:test";
import assert from "node:assert/strict"; import assert from "node:assert/strict";
import { normalizePiEvent } from "./normalize.mjs"; import { normalizePiEvent, normalizeStopReason } from "./normalize.mjs";
test("normalizePiEvent converts tool start events into protocol tool-call records", () => { test("normalizePiEvent converts tool start events into protocol tool-call records", () => {
const normalized = normalizePiEvent({ const normalized = normalizePiEvent({
@@ -16,7 +16,26 @@ test("normalizePiEvent converts tool start events into protocol tool-call record
}); });
}); });
test("normalizePiEvent converts assistant message_end into a final-text record", () => { test("normalizeStopReason maps raw tool-use variants to canonical toolUse", () => {
assert.deepEqual(normalizeStopReason("toolUse"), {
stopReason: "toolUse",
rawStopReason: "toolUse",
});
assert.deepEqual(normalizeStopReason("tool_use"), {
stopReason: "toolUse",
rawStopReason: "tool_use",
});
});
test("normalizeStopReason preserves unknown stop reasons without marking them terminal", () => {
assert.deepEqual(normalizeStopReason("custom_reason"), {
stopReason: undefined,
rawStopReason: "custom_reason",
});
});
test("normalizePiEvent converts assistant message_end into canonical final-text record", () => {
const normalized = normalizePiEvent({ const normalized = normalizePiEvent({
type: "message_end", type: "message_end",
message: { message: {
@@ -32,7 +51,8 @@ test("normalizePiEvent converts assistant message_end into a final-text record",
type: "assistant_text", type: "assistant_text",
text: "Final answer", text: "Final answer",
model: "anthropic/claude-sonnet-4-5", model: "anthropic/claude-sonnet-4-5",
stopReason: "end_turn", stopReason: "stop",
rawStopReason: "end_turn",
usage: { input: 10, output: 5, totalTokens: 15, cost: { total: 0.001 } }, usage: { input: 10, output: 5, totalTokens: 15, cost: { total: 0.001 } },
}); });
}); });