| @@ -921,9 +921,273 @@ describe("MessagesTimeline", () => { · 920 unmodified lines |
| 921 | expect(markup).toContain('aria-label="Open Package audit"'); | 921 | expect(markup).toContain('aria-label="Open Package audit"'); |
| 922 | expect(markup).toContain("Reading src/index.ts"); | 922 | expect(markup).toContain("Reading src/index.ts"); |
| 923 | expect(markup).not.toContain("Inspect the package"); | 923 | expect(markup).not.toContain("Inspect the package"); |
| | 924 | expect(markup).not.toContain('data-v2-subagent-result-disclosure="true"'); |
| 924 | expect(markup).not.toContain("Work Log"); | 925 | expect(markup).not.toContain("Work Log"); |
| 925 | }); | 926 | }); |
| 926 | | 927 | |
| | 928 | it("discloses the full Codex subagent result without projecting child events", async () => { |
| | 929 | const { MessagesTimeline } = await import("./MessagesTimeline"); |
| | 930 | const markup = renderToStaticMarkup( |
| | 931 | <MessagesTimeline |
| | 932 | {...buildProps()} |
| | 933 | timelineEntries={[ |
| | 934 | { |
| | 935 | id: "codex-subagent-result", |
| | 936 | kind: "event", |
| | 937 | createdAt: MESSAGE_CREATED_AT, |
| | 938 | projectedItem: { |
| | 939 | position: 0, |
| | 940 | visibility: "local", |
| | 941 | sourceThreadId: "thread-1", |
| | 942 | sourceItemId: "codex-subagent-result", |
| | 943 | item: { |
| | 944 | id: "codex-subagent-result", |
| | 945 | threadId: "thread-1", |
| | 946 | runId: "run-1", |
| | 947 | nodeId: "node-subagent-1", |
| | 948 | providerThreadId: "provider-thread-1", |
| | 949 | providerTurnId: "provider-turn-1", |
| | 950 | nativeItemRef: null, |
| | 951 | parentItemId: null, |
| | 952 | ordinal: 1, |
| | 953 | status: "completed", |
| | 954 | title: "Isolation report", |
| | 955 | startedAt: null, |
| | 956 | completedAt: null, |
| | 957 | updatedAt: {}, |
| | 958 | type: "subagent", |
| | 959 | subagentId: "node-subagent-1", |
| | 960 | origin: "provider_native", |
| | 961 | driver: "codex", |
| | 962 | providerInstanceId: "codex", |
| | 963 | childThreadId: "thread-subagent-1", |
| | 964 | prompt: "Explain test isolation", |
| | 965 | result: "Tests should be isolated.\n\nResult: no shared state.", |
| | 966 | }, |
| | 967 | } as never, |
| | 968 | }, |
| | 969 | ]} |
| | 970 | />, |
| | 971 | ); |
| | 972 | |
| | 973 | expect(markup).toContain('data-v2-item-type="subagent"'); |
| | 974 | expect(markup).toContain('data-v2-subagent-result-disclosure="true"'); |
| | 975 | expect(markup).toContain('data-v2-subagent-result="true"'); |
| | 976 | expect(markup).toContain('aria-label="Show full result for Isolation report"'); |
| | 977 | expect(markup).toContain('aria-label="Open Isolation report"'); |
| | 978 | expect(markup).toContain("Tests should be isolated."); |
| | 979 | expect(markup).toContain("Result: no shared state."); |
| | 980 | expect(markup).not.toContain("Explain test isolation"); |
| | 981 | }); |
| | 982 | |
| | 983 | it("keeps live progress when a running subagent streams a partial result", async () => { |
| | 984 | const { MessagesTimeline } = await import("./MessagesTimeline"); |
| | 985 | const markup = renderToStaticMarkup( |
| | 986 | <MessagesTimeline |
| | 987 | {...buildProps()} |
| | 988 | timelineEntries={[ |
| | 989 | { |
| | 990 | id: "subagent-partial-result", |
| | 991 | kind: "event", |
| | 992 | createdAt: MESSAGE_CREATED_AT, |
| | 993 | projectedItem: { |
| | 994 | position: 0, |
| | 995 | visibility: "local", |
| | 996 | sourceThreadId: "thread-1", |
| | 997 | sourceItemId: "subagent-partial-result", |
| | 998 | item: { |
| | 999 | id: "subagent-partial-result", |
| | 1000 | threadId: "thread-1", |
| | 1001 | runId: "run-1", |
| | 1002 | nodeId: "node-subagent-1", |
| | 1003 | providerThreadId: "provider-thread-1", |
| | 1004 | providerTurnId: "provider-turn-1", |
| | 1005 | nativeItemRef: null, |
| | 1006 | parentItemId: null, |
| | 1007 | ordinal: 1, |
| | 1008 | status: "running", |
| | 1009 | title: "Package audit", |
| | 1010 | startedAt: null, |
| | 1011 | completedAt: null, |
| | 1012 | updatedAt: {}, |
| | 1013 | type: "subagent", |
| | 1014 | subagentId: "node-subagent-1", |
| | 1015 | origin: "provider_native", |
| | 1016 | driver: "codex", |
| | 1017 | providerInstanceId: "codex", |
| | 1018 | childThreadId: "thread-subagent-1", |
| | 1019 | prompt: "Inspect the package", |
| | 1020 | progress: "Reading src/index.ts", |
| | 1021 | result: "Partial streamed answer so far", |
| | 1022 | }, |
| | 1023 | } as never, |
| | 1024 | }, |
| | 1025 | ]} |
| | 1026 | />, |
| | 1027 | ); |
| | 1028 | |
| | 1029 | expect(markup).toContain('data-v2-item-type="subagent"'); |
| | 1030 | expect(markup).toContain('aria-label="Open Package audit"'); |
| | 1031 | expect(markup).toContain("Reading src/index.ts"); |
| | 1032 | expect(markup).not.toContain("Partial streamed answer so far"); |
| | 1033 | expect(markup).not.toContain('data-v2-subagent-result-disclosure="true"'); |
| | 1034 | }); |
| | 1035 | |
| | 1036 | it("shows the streamed result while a subagent runs without progress", async () => { |
| | 1037 | const { MessagesTimeline } = await import("./MessagesTimeline"); |
| | 1038 | const markup = renderToStaticMarkup( |
| | 1039 | <MessagesTimeline |
| | 1040 | {...buildProps()} |
| | 1041 | timelineEntries={[ |
| | 1042 | { |
| | 1043 | id: "subagent-streamed-result", |
| | 1044 | kind: "event", |
| | 1045 | createdAt: MESSAGE_CREATED_AT, |
| | 1046 | projectedItem: { |
| | 1047 | position: 0, |
| | 1048 | visibility: "local", |
| | 1049 | sourceThreadId: "thread-1", |
| | 1050 | sourceItemId: "subagent-streamed-result", |
| | 1051 | item: { |
| | 1052 | id: "subagent-streamed-result", |
| | 1053 | threadId: "thread-1", |
| | 1054 | runId: "run-1", |
| | 1055 | nodeId: "node-subagent-1", |
| | 1056 | providerThreadId: "provider-thread-1", |
| | 1057 | providerTurnId: "provider-turn-1", |
| | 1058 | nativeItemRef: null, |
| | 1059 | parentItemId: null, |
| | 1060 | ordinal: 1, |
| | 1061 | status: "running", |
| | 1062 | title: "Package audit", |
| | 1063 | startedAt: null, |
| | 1064 | completedAt: null, |
| | 1065 | updatedAt: {}, |
| | 1066 | type: "subagent", |
| | 1067 | subagentId: "node-subagent-1", |
| | 1068 | origin: "provider_native", |
| | 1069 | driver: "codex", |
| | 1070 | providerInstanceId: "codex", |
| | 1071 | childThreadId: "thread-subagent-1", |
| | 1072 | prompt: "Inspect the package", |
| | 1073 | progress: null, |
| | 1074 | result: "Streaming answer so far", |
| | 1075 | }, |
| | 1076 | } as never, |
| | 1077 | }, |
| | 1078 | ]} |
| | 1079 | />, |
| | 1080 | ); |
| | 1081 | |
| | 1082 | expect(markup).toContain('data-v2-item-type="subagent"'); |
| | 1083 | expect(markup).toContain("Streaming answer so far"); |
| | 1084 | expect(markup).not.toContain("Inspect the package"); |
| | 1085 | expect(markup).not.toContain('data-v2-subagent-result-disclosure="true"'); |
| | 1086 | }); |
| | 1087 | |
| | 1088 | it("treats a cancelled subagent result as partial output", async () => { |
| | 1089 | const { MessagesTimeline } = await import("./MessagesTimeline"); |
| | 1090 | const markup = renderToStaticMarkup( |
| | 1091 | <MessagesTimeline |
| | 1092 | {...buildProps()} |
| | 1093 | timelineEntries={[ |
| | 1094 | { |
| | 1095 | id: "subagent-cancelled-result", |
| | 1096 | kind: "event", |
| | 1097 | createdAt: MESSAGE_CREATED_AT, |
| | 1098 | projectedItem: { |
| | 1099 | position: 0, |
| | 1100 | visibility: "local", |
| | 1101 | sourceThreadId: "thread-1", |
| | 1102 | sourceItemId: "subagent-cancelled-result", |
| | 1103 | item: { |
| | 1104 | id: "subagent-cancelled-result", |
| | 1105 | threadId: "thread-1", |
| | 1106 | runId: "run-1", |
| | 1107 | nodeId: "node-subagent-1", |
| | 1108 | providerThreadId: "provider-thread-1", |
| | 1109 | providerTurnId: "provider-turn-1", |
| | 1110 | nativeItemRef: null, |
| | 1111 | parentItemId: null, |
| | 1112 | ordinal: 1, |
| | 1113 | status: "cancelled", |
| | 1114 | title: "Package audit", |
| | 1115 | startedAt: null, |
| | 1116 | completedAt: null, |
| | 1117 | updatedAt: {}, |
| | 1118 | type: "subagent", |
| | 1119 | subagentId: "node-subagent-1", |
| | 1120 | origin: "provider_native", |
| | 1121 | driver: "codex", |
| | 1122 | providerInstanceId: "codex", |
| | 1123 | childThreadId: "thread-subagent-1", |
| | 1124 | prompt: "Inspect the package", |
| | 1125 | progress: "Reading src/index.ts", |
| | 1126 | result: "Partial output before cancel", |
| | 1127 | }, |
| | 1128 | } as never, |
| | 1129 | }, |
| | 1130 | ]} |
| | 1131 | />, |
| | 1132 | ); |
| | 1133 | |
| | 1134 | expect(markup).toContain('data-v2-item-type="subagent"'); |
| | 1135 | expect(markup).toContain("Partial output before cancel"); |
| | 1136 | expect(markup).not.toContain("Reading src/index.ts"); |
| | 1137 | expect(markup).not.toContain('data-v2-subagent-result-disclosure="true"'); |
| | 1138 | }); |
| | 1139 | |
| | 1140 | it("falls back to progress when a completed subagent result is whitespace-only", async () => { |
| | 1141 | const { MessagesTimeline } = await import("./MessagesTimeline"); |
| | 1142 | const markup = renderToStaticMarkup( |
| | 1143 | <MessagesTimeline |
| | 1144 | {...buildProps()} |
| | 1145 | timelineEntries={[ |
| | 1146 | { |
| | 1147 | id: "subagent-blank-result", |
| | 1148 | kind: "event", |
| | 1149 | createdAt: MESSAGE_CREATED_AT, |
| | 1150 | projectedItem: { |
| | 1151 | position: 0, |
| | 1152 | visibility: "local", |
| | 1153 | sourceThreadId: "thread-1", |
| | 1154 | sourceItemId: "subagent-blank-result", |
| | 1155 | item: { |
| | 1156 | id: "subagent-blank-result", |
| | 1157 | threadId: "thread-1", |
| | 1158 | runId: "run-1", |
| | 1159 | nodeId: "node-subagent-1", |
| | 1160 | providerThreadId: "provider-thread-1", |
| | 1161 | providerTurnId: "provider-turn-1", |
| | 1162 | nativeItemRef: null, |
| | 1163 | parentItemId: null, |
| | 1164 | ordinal: 1, |
| | 1165 | status: "completed", |
| | 1166 | title: "Package audit", |
| | 1167 | startedAt: null, |
| | 1168 | completedAt: null, |
| | 1169 | updatedAt: {}, |
| | 1170 | type: "subagent", |
| | 1171 | subagentId: "node-subagent-1", |
| | 1172 | origin: "provider_native", |
| | 1173 | driver: "codex", |
| | 1174 | providerInstanceId: "codex", |
| | 1175 | childThreadId: "thread-subagent-1", |
| | 1176 | prompt: "Inspect the package", |
| | 1177 | progress: "Audited 12 packages", |
| | 1178 | result: " \n\t ", |
| | 1179 | }, |
| | 1180 | } as never, |
| | 1181 | }, |
| | 1182 | ]} |
| | 1183 | />, |
| | 1184 | ); |
| | 1185 | |
| | 1186 | expect(markup).toContain('data-v2-item-type="subagent"'); |
| | 1187 | expect(markup).toContain("Audited 12 packages"); |
| | 1188 | expect(markup).not.toContain('data-v2-subagent-result-disclosure="true"'); |
| | 1189 | }); |
| | 1190 | |
| 927 | it("renders V2 provider failures as standalone error rows", async () => { | 1191 | it("renders V2 provider failures as standalone error rows", async () => { |
| 928 | const { MessagesTimeline } = await import("./MessagesTimeline"); | 1192 | const { MessagesTimeline } = await import("./MessagesTimeline"); |
| 929 | const markup = renderToStaticMarkup( | 1193 | const markup = renderToStaticMarkup( |