|
1 | 1 | // @vitest-environment node |
2 | | -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; |
| 2 | +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; |
3 | 3 | import { ACTIVITY_ENTRY_LIMIT, ACTIVITY_OUTPUT_PREVIEW_LIMIT } from "./activity-model.ts"; |
4 | 4 | import { |
5 | 5 | handleAgentEvent, |
@@ -833,12 +833,25 @@ describe("app-tool-stream fallback lifecycle handling", () => { |
833 | 833 | }); |
834 | 834 |
|
835 | 835 | describe("stream:item toolprogress events", () => { |
| 836 | + let weSetWindow = false; |
836 | 837 | beforeAll(() => { |
837 | 838 | const globalWithWindow = globalThis as typeof globalThis & { |
838 | 839 | window?: Window & typeof globalThis; |
839 | 840 | }; |
840 | 841 | if (!globalWithWindow.window) { |
841 | 842 | globalWithWindow.window = globalThis as unknown as Window & typeof globalThis; |
| 843 | + weSetWindow = true; |
| 844 | + } |
| 845 | + }); |
| 846 | + afterAll(() => { |
| 847 | + // Only clean up the window we installed; leave any pre-existing one |
| 848 | + // intact so we don't disturb sibling describe blocks that may rely on it. |
| 849 | + if (weSetWindow) { |
| 850 | + const globalWithWindow = globalThis as typeof globalThis & { |
| 851 | + window?: Window & typeof globalThis; |
| 852 | + }; |
| 853 | + delete globalWithWindow.window; |
| 854 | + weSetWindow = false; |
842 | 855 | } |
843 | 856 | }); |
844 | 857 |
|
@@ -910,6 +923,58 @@ describe("stream:item toolprogress events", () => { |
910 | 923 | expect(host.toolStreamOrder).toHaveLength(0); |
911 | 924 | }); |
912 | 925 |
|
| 926 | + it("ignores stream:item events whose kind is not 'tool'", () => { |
| 927 | + const host = createHost(); |
| 928 | + handleAgentEvent( |
| 929 | + host, |
| 930 | + agentEvent("run-1", 1, "tool", { |
| 931 | + phase: "start", |
| 932 | + toolCallId: "id-1", |
| 933 | + name: "trading_quick", |
| 934 | + }), |
| 935 | + ); |
| 936 | + handleAgentEvent( |
| 937 | + host, |
| 938 | + agentEvent("run-1", 2, "item", { |
| 939 | + kind: "text", |
| 940 | + phase: "update", |
| 941 | + toolCallId: "id-1", |
| 942 | + progressText: "should be ignored", |
| 943 | + }), |
| 944 | + ); |
| 945 | + const entry = host.toolStreamById.get("id-1"); |
| 946 | + expect(entry?.progressText).toBeUndefined(); |
| 947 | + expect(entry?.message.content).not.toContainEqual( |
| 948 | + expect.objectContaining({ type: "toolprogress" }), |
| 949 | + ); |
| 950 | + }); |
| 951 | + |
| 952 | + it("ignores stream:item tool events whose phase is not 'update'", () => { |
| 953 | + const host = createHost(); |
| 954 | + handleAgentEvent( |
| 955 | + host, |
| 956 | + agentEvent("run-1", 1, "tool", { |
| 957 | + phase: "start", |
| 958 | + toolCallId: "id-1", |
| 959 | + name: "trading_quick", |
| 960 | + }), |
| 961 | + ); |
| 962 | + handleAgentEvent( |
| 963 | + host, |
| 964 | + agentEvent("run-1", 2, "item", { |
| 965 | + kind: "tool", |
| 966 | + phase: "start", |
| 967 | + toolCallId: "id-1", |
| 968 | + progressText: "should be ignored", |
| 969 | + }), |
| 970 | + ); |
| 971 | + const entry = host.toolStreamById.get("id-1"); |
| 972 | + expect(entry?.progressText).toBeUndefined(); |
| 973 | + expect(entry?.message.content).not.toContainEqual( |
| 974 | + expect.objectContaining({ type: "toolprogress" }), |
| 975 | + ); |
| 976 | + }); |
| 977 | + |
913 | 978 | it("clears progressText when the final result arrives", () => { |
914 | 979 | const host = createHost(); |
915 | 980 | handleAgentEvent( |
|
0 commit comments