| @@ -921,9 +921,273 @@ describe("MessagesTimeline", () => { · 920 unmodified lines |
| 921 | 921 | expect(markup).toContain('aria-label="Open Package audit"'); |
| 922 | 922 | expect(markup).toContain("Reading src/index.ts"); |
| 923 | 923 | expect(markup).not.toContain("Inspect the package"); |
| 924 | + expect(markup).not.toContain('data-v2-subagent-result-disclosure="true"'); |
| 924 | 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 | 1191 | it("renders V2 provider failures as standalone error rows", async () => { |
| 928 | 1192 | const { MessagesTimeline } = await import("./MessagesTimeline"); |
| 929 | 1193 | const markup = renderToStaticMarkup( |