






















@@ -112,6 +112,42 @@ describe("subscribeEmbeddedPiSession", () => {
112112});
113113}
114114115+function findBlockReplyPayload(
116+onBlockReply: { mock: { calls: unknown[][] } },
117+text: string,
118+): { mediaUrls?: unknown } | undefined {
119+return onBlockReply.mock.calls
120+.map((call) => call[0] as { text?: unknown; mediaUrls?: unknown })
121+.find((payload) => payload.text === text);
122+}
123+124+function expectBlockReplyPayload(
125+onBlockReply: { mock: { calls: unknown[][] } },
126+expected: { text: string; mediaUrls?: string[] },
127+): void {
128+const payload = findBlockReplyPayload(onBlockReply, expected.text);
129+expect(payload).toBeDefined();
130+if (!payload) {
131+throw new Error(`Expected block reply text: ${expected.text}`);
132+}
133+if (expected.mediaUrls !== undefined) {
134+expect(payload.mediaUrls).toStrictEqual(expected.mediaUrls);
135+}
136+}
137+138+function expectLifecyclePayload(
139+payloads: Array<Record<string, unknown>>,
140+expected: { phase: string; livenessState: string; replayInvalid: boolean },
141+): void {
142+const payload = payloads.find(
143+(item) =>
144+item.phase === expected.phase &&
145+item.livenessState === expected.livenessState &&
146+item.replayInvalid === expected.replayInvalid,
147+);
148+expect(payload).toBeDefined();
149+}
150+115151it("captures usage from completions timings on done events", () => {
116152const { emit, subscription } = createSubscribedSessionHarness({ runId: "run" });
117153@@ -362,12 +398,10 @@ describe("subscribeEmbeddedPiSession", () => {
362398});
363399await flushBlockReplyCallbacks();
364400365-expect(onBlockReply).toHaveBeenCalledWith(
366-expect.objectContaining({
367-text: "Here is the image.",
368-mediaUrls: ["/tmp/generated.png"],
369-}),
370-);
401+expectBlockReplyPayload(onBlockReply, {
402+text: "Here is the image.",
403+mediaUrls: ["/tmp/generated.png"],
404+});
371405});
372406373407it("does not duplicate generated image media when the assistant reply has MEDIA lines", async () => {
@@ -417,12 +451,10 @@ describe("subscribeEmbeddedPiSession", () => {
417451});
418452await flushBlockReplyCallbacks();
419453420-expect(onBlockReply).toHaveBeenCalledWith(
421-expect.objectContaining({
422-text: "Here is the selected image.",
423-mediaUrls: ["./selected.png"],
424-}),
425-);
454+expectBlockReplyPayload(onBlockReply, {
455+text: "Here is the selected image.",
456+mediaUrls: ["./selected.png"],
457+});
426458});
427459428460it("does not attach generated image media to an early streamed chunk before explicit MEDIA", async () => {
@@ -465,11 +497,9 @@ describe("subscribeEmbeddedPiSession", () => {
465497emit({ type: "message_start", message: { role: "assistant" } });
466498emitAssistantTextDelta(emit, "Generated 1 image.\n");
467499468-expect(onBlockReply).toHaveBeenCalledWith(
469-expect.objectContaining({
470-text: "Generated 1 image.",
471-}),
472-);
500+expectBlockReplyPayload(onBlockReply, {
501+text: "Generated 1 image.",
502+});
473503const earlyMediaPayloads = onBlockReply.mock.calls
474504.map(([payload]) => payload)
475505.filter((payload) => payload.mediaUrls?.length);
@@ -542,12 +572,10 @@ describe("subscribeEmbeddedPiSession", () => {
542572emit({ type: "agent_end" });
543573await flushBlockReplyCallbacks();
544574545-expect(onBlockReply).toHaveBeenCalledWith(
546-expect.objectContaining({
547-text: "Here it is.",
548-mediaUrls: ["/tmp/lobster-boss.mp3"],
549-}),
550-);
575+expectBlockReplyPayload(onBlockReply, {
576+text: "Here it is.",
577+mediaUrls: ["/tmp/lobster-boss.mp3"],
578+});
551579});
552580553581it.each([
@@ -610,11 +638,9 @@ describe("subscribeEmbeddedPiSession", () => {
610638emit({ type: "message_start", message: { role: "assistant" } });
611639emitAssistantTextDelta(emit, firstChunk);
612640613-expect(onBlockReply).toHaveBeenCalledWith(
614-expect.objectContaining({
615-text: firstChunk.trim(),
616-}),
617-);
641+expectBlockReplyPayload(onBlockReply, {
642+text: firstChunk.trim(),
643+});
618644const earlyMediaPayloads = onBlockReply.mock.calls
619645.map(([payload]) => payload)
620646.filter((payload) => payload.mediaUrls?.length);
@@ -1031,9 +1057,10 @@ describe("subscribeEmbeddedPiSession", () => {
10311057// Look for lifecycle:error event
10321058const lifecycleError = findLifecycleErrorAgentEvent(onAgentEvent.mock.calls);
103310591034-expect(lifecycleError).toMatchObject({
1035-data: { error: expect.stringContaining("API rate limit reached") },
1036-});
1060+expect(lifecycleError).toBeDefined();
1061+const error = (lifecycleError?.data as { error?: unknown } | undefined)?.error;
1062+expect(typeof error).toBe("string");
1063+expect(error).toContain("API rate limit reached");
10371064});
1038106510391066it("preserves replay-invalid lifecycle truth across compaction retries after mutating tools", () => {
@@ -1067,13 +1094,11 @@ describe("subscribeEmbeddedPiSession", () => {
10671094hadPotentialSideEffects: true,
10681095});
10691096const payloads = extractAgentEventPayloads(onAgentEvent.mock.calls);
1070-expect(payloads).toContainEqual(
1071-expect.objectContaining({
1072-phase: "end",
1073-livenessState: "abandoned",
1074-replayInvalid: true,
1075-}),
1076-);
1097+expectLifecyclePayload(payloads, {
1098+phase: "end",
1099+livenessState: "abandoned",
1100+replayInvalid: true,
1101+});
10771102});
1078110310791104it("preserves deterministic side-effect liveness across compaction retries", () => {
@@ -1099,12 +1124,10 @@ describe("subscribeEmbeddedPiSession", () => {
10991124emit({ type: "agent_end" });
1100112511011126const payloads = extractAgentEventPayloads(onAgentEvent.mock.calls);
1102-expect(payloads).toContainEqual(
1103-expect.objectContaining({
1104-phase: "end",
1105-livenessState: "working",
1106-replayInvalid: true,
1107-}),
1108-);
1127+expectLifecyclePayload(payloads, {
1128+phase: "end",
1129+livenessState: "working",
1130+replayInvalid: true,
1131+});
11091132});
11101133});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。