fix: persist verbose off and gate tool stream
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
import type { AssistantMessage } from "@mariozechner/pi-ai";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { emitAgentEvent } from "../infra/agent-events.js";
|
||||
import { subscribeEmbeddedPiSession } from "./pi-embedded-subscribe.js";
|
||||
|
||||
vi.mock("../infra/agent-events.js", () => ({
|
||||
emitAgentEvent: vi.fn(),
|
||||
}));
|
||||
|
||||
type StubSession = {
|
||||
subscribe: (fn: (evt: unknown) => void) => () => void;
|
||||
};
|
||||
@@ -10,6 +15,8 @@ type StubSession = {
|
||||
type SessionEventHandler = (evt: unknown) => void;
|
||||
|
||||
describe("subscribeEmbeddedPiSession", () => {
|
||||
const emitAgentEventMock = vi.mocked(emitAgentEvent);
|
||||
|
||||
it("filters to <final> and falls back when tags are malformed", () => {
|
||||
let handler: ((evt: unknown) => void) | undefined;
|
||||
const session: StubSession = {
|
||||
@@ -1467,6 +1474,48 @@ describe("subscribeEmbeddedPiSession", () => {
|
||||
expect(onToolResult).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("skips tool stream events when tool verbose is off", () => {
|
||||
let handler: ((evt: unknown) => void) | undefined;
|
||||
const session: StubSession = {
|
||||
subscribe: (fn) => {
|
||||
handler = fn;
|
||||
return () => {};
|
||||
},
|
||||
};
|
||||
|
||||
emitAgentEventMock.mockReset();
|
||||
|
||||
subscribeEmbeddedPiSession({
|
||||
session: session as unknown as Parameters<
|
||||
typeof subscribeEmbeddedPiSession
|
||||
>[0]["session"],
|
||||
runId: "run-tool-events-off",
|
||||
shouldEmitToolResult: () => false,
|
||||
});
|
||||
|
||||
handler?.({
|
||||
type: "tool_execution_start",
|
||||
toolName: "read",
|
||||
toolCallId: "tool-evt-1",
|
||||
args: { path: "/tmp/off.txt" },
|
||||
});
|
||||
handler?.({
|
||||
type: "tool_execution_update",
|
||||
toolName: "read",
|
||||
toolCallId: "tool-evt-1",
|
||||
partialResult: "partial",
|
||||
});
|
||||
handler?.({
|
||||
type: "tool_execution_end",
|
||||
toolName: "read",
|
||||
toolCallId: "tool-evt-1",
|
||||
isError: false,
|
||||
result: "ok",
|
||||
});
|
||||
|
||||
expect(emitAgentEventMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("emits tool summaries when shouldEmitToolResult overrides verbose", () => {
|
||||
let handler: ((evt: unknown) => void) | undefined;
|
||||
const session: StubSession = {
|
||||
|
||||
@@ -368,6 +368,7 @@ export function subscribeEmbeddedPiSession(params: {
|
||||
const toolMetas: Array<{ toolName?: string; meta?: string }> = [];
|
||||
const toolMetaById = new Map<string, string | undefined>();
|
||||
const toolSummaryById = new Set<string>();
|
||||
const toolEventById = new Set<string>();
|
||||
const blockReplyBreak = params.blockReplyBreak ?? "text_end";
|
||||
const reasoningMode = params.reasoningMode ?? "off";
|
||||
const includeReasoning = reasoningMode === "on";
|
||||
@@ -589,6 +590,7 @@ export function subscribeEmbeddedPiSession(params: {
|
||||
toolMetas.length = 0;
|
||||
toolMetaById.clear();
|
||||
toolSummaryById.clear();
|
||||
toolEventById.clear();
|
||||
messagingToolSentTexts.length = 0;
|
||||
messagingToolSentTargets.length = 0;
|
||||
pendingMessagingTexts.clear();
|
||||
@@ -639,16 +641,20 @@ export function subscribeEmbeddedPiSession(params: {
|
||||
`embedded run tool start: runId=${params.runId} tool=${toolName} toolCallId=${toolCallId}`,
|
||||
);
|
||||
|
||||
emitAgentEvent({
|
||||
runId: params.runId,
|
||||
stream: "tool",
|
||||
data: {
|
||||
phase: "start",
|
||||
name: toolName,
|
||||
toolCallId,
|
||||
args: args as Record<string, unknown>,
|
||||
},
|
||||
});
|
||||
const shouldEmitToolEvents = shouldEmitToolResult();
|
||||
if (shouldEmitToolEvents) {
|
||||
toolEventById.add(toolCallId);
|
||||
emitAgentEvent({
|
||||
runId: params.runId,
|
||||
stream: "tool",
|
||||
data: {
|
||||
phase: "start",
|
||||
name: toolName,
|
||||
toolCallId,
|
||||
args: args as Record<string, unknown>,
|
||||
},
|
||||
});
|
||||
}
|
||||
params.onAgentEvent?.({
|
||||
stream: "tool",
|
||||
data: { phase: "start", name: toolName, toolCallId },
|
||||
@@ -656,7 +662,7 @@ export function subscribeEmbeddedPiSession(params: {
|
||||
|
||||
if (
|
||||
params.onToolResult &&
|
||||
shouldEmitToolResult() &&
|
||||
shouldEmitToolEvents &&
|
||||
!toolSummaryById.has(toolCallId)
|
||||
) {
|
||||
toolSummaryById.add(toolCallId);
|
||||
@@ -704,16 +710,18 @@ export function subscribeEmbeddedPiSession(params: {
|
||||
const partial = (evt as AgentEvent & { partialResult?: unknown })
|
||||
.partialResult;
|
||||
const sanitized = sanitizeToolResult(partial);
|
||||
emitAgentEvent({
|
||||
runId: params.runId,
|
||||
stream: "tool",
|
||||
data: {
|
||||
phase: "update",
|
||||
name: toolName,
|
||||
toolCallId,
|
||||
partialResult: sanitized,
|
||||
},
|
||||
});
|
||||
if (toolEventById.has(toolCallId)) {
|
||||
emitAgentEvent({
|
||||
runId: params.runId,
|
||||
stream: "tool",
|
||||
data: {
|
||||
phase: "update",
|
||||
name: toolName,
|
||||
toolCallId,
|
||||
partialResult: sanitized,
|
||||
},
|
||||
});
|
||||
}
|
||||
params.onAgentEvent?.({
|
||||
stream: "tool",
|
||||
data: {
|
||||
@@ -760,18 +768,22 @@ export function subscribeEmbeddedPiSession(params: {
|
||||
}
|
||||
}
|
||||
|
||||
emitAgentEvent({
|
||||
runId: params.runId,
|
||||
stream: "tool",
|
||||
data: {
|
||||
phase: "result",
|
||||
name: toolName,
|
||||
toolCallId,
|
||||
meta,
|
||||
isError,
|
||||
result: sanitizedResult,
|
||||
},
|
||||
});
|
||||
const shouldEmitToolEvents = toolEventById.has(toolCallId);
|
||||
if (shouldEmitToolEvents) {
|
||||
emitAgentEvent({
|
||||
runId: params.runId,
|
||||
stream: "tool",
|
||||
data: {
|
||||
phase: "result",
|
||||
name: toolName,
|
||||
toolCallId,
|
||||
meta,
|
||||
isError,
|
||||
result: sanitizedResult,
|
||||
},
|
||||
});
|
||||
}
|
||||
toolEventById.delete(toolCallId);
|
||||
params.onAgentEvent?.({
|
||||
stream: "tool",
|
||||
data: {
|
||||
|
||||
Reference in New Issue
Block a user