






























@@ -868,6 +868,7 @@ async function runMatrixToolProgressScenario(
868868expectedPreviewKind: MatrixQaObservedEvent["kind"];
869869finalText: string;
870870allowFinalOnly?: boolean;
871+allowTopLevelFinalWithProgress?: boolean;
871872label: string;
872873allowGenericProgressLine?: boolean;
873874mentionSafety?: boolean;
@@ -891,19 +892,42 @@ async function runMatrixToolProgressScenario(
891892event.relatesTo?.relType === "m.replace" && event.relatesTo.eventId
892893 ? event.relatesTo.eventId
893894 : event.eventId;
895+const isFinalReply = (event: MatrixQaObservedEvent) =>
896+event.roomId === context.roomId &&
897+event.sender === context.sutUserId &&
898+event.type === "m.room.message" &&
899+event.relatesTo === undefined &&
900+isMatrixQaMessageLikeKind(event.kind) &&
901+doesMatrixQaReplyBodyMatchToken(event, params.finalText);
902+const isExpectedProgressKind = (event: MatrixQaObservedEvent) =>
903+event.kind === params.expectedPreviewKind ||
904+(params.allowTopLevelFinalWithProgress === true &&
905+isMatrixQaMessageLikeKind(event.kind) &&
906+matchesExpectedProgress(event.body));
907+const isProgressEvent = (event: MatrixQaObservedEvent) =>
908+event.roomId === context.roomId &&
909+event.sender === context.sutUserId &&
910+isExpectedProgressKind(event) &&
911+(matchesExpectedProgress(event.body) || event.relatesTo === undefined);
912+const isProgressProofEvent = (event: MatrixQaObservedEvent) =>
913+event.roomId === context.roomId &&
914+event.sender === context.sutUserId &&
915+isExpectedProgressKind(event) &&
916+matchesExpectedProgress(event.body);
917+const isProgressReplacement = (event: MatrixQaObservedEvent, previewRootEventId: string) =>
918+event.roomId === context.roomId &&
919+event.sender === context.sutUserId &&
920+event.kind === params.expectedPreviewKind &&
921+event.relatesTo?.relType === "m.replace" &&
922+event.relatesTo.eventId === previewRootEventId &&
923+matchesExpectedProgress(event.body);
894924const preview = await client
895925.waitForRoomEvent({
896926observedEvents: context.observedEvents,
897927predicate: (event) =>
898-event.roomId === context.roomId &&
899-event.sender === context.sutUserId &&
900-((event.kind === params.expectedPreviewKind &&
901-(event.relatesTo === undefined ||
902-(event.relatesTo.relType === "m.replace" && matchesExpectedProgress(event.body)))) ||
903-(params.allowFinalOnly === true &&
904-event.relatesTo === undefined &&
905-isMatrixQaMessageLikeKind(event.kind) &&
906-doesMatrixQaReplyBodyMatchToken(event, params.finalText))),
928+isProgressEvent(event) ||
929+((params.allowFinalOnly === true || params.allowTopLevelFinalWithProgress === true) &&
930+isFinalReply(event)),
907931roomId: context.roomId,
908932since: startSince,
909933timeoutMs: context.timeoutMs,
@@ -921,59 +945,146 @@ async function runMatrixToolProgressScenario(
921945}),
922946);
923947});
924-if (
925-params.allowFinalOnly === true &&
926-doesMatrixQaReplyBodyMatchToken(preview.event, params.finalText)
927-) {
928-const unexpectedWorkingEvents = findMatrixQaUnexpectedWorkingEvents({
929-events: context.observedEvents,
930-finalEventId: preview.event.eventId,
931-startIndex: startObservedIndex,
932-sutUserId: context.sutUserId,
933-});
934-if (unexpectedWorkingEvents.length > 0) {
935-throw new Error(
936-`Matrix tool progress leaked outside preview event: ${unexpectedWorkingEvents.map((event) => `${event.eventId}:${event.body ?? ""}`).join("; ")}`,
937-);
948+if (isFinalReply(preview.event)) {
949+if (params.allowTopLevelFinalWithProgress === true && params.allowFinalOnly !== true) {
950+const progressAfterFinal = await client
951+.waitForRoomEvent({
952+observedEvents: context.observedEvents,
953+predicate: isProgressProofEvent,
954+roomId: context.roomId,
955+since: preview.since,
956+timeoutMs: context.timeoutMs,
957+})
958+.catch((err: unknown) => {
959+throw new Error(
960+buildMatrixQaToolProgressTimeoutMessage({
961+cause: err,
962+events: context.observedEvents,
963+expectedPreviewKind: params.expectedPreviewKind,
964+previewEventId: "<not observed>",
965+roomId: context.roomId,
966+startIndex: startObservedIndex,
967+sutUserId: context.sutUserId,
968+}),
969+);
970+});
971+const progressPreviewEventId = getPreviewRootEventId(progressAfterFinal.event);
972+const unexpectedWorkingEvents = findMatrixQaUnexpectedWorkingEvents({
973+events: context.observedEvents,
974+finalEventId: preview.event.eventId,
975+previewEventId: progressPreviewEventId,
976+startIndex: startObservedIndex,
977+sutUserId: context.sutUserId,
978+});
979+if (unexpectedWorkingEvents.length > 0) {
980+throw new Error(
981+`Matrix tool progress leaked outside preview event: ${unexpectedWorkingEvents.map((event) => `${event.eventId}:${event.body ?? ""}`).join("; ")}`,
982+);
983+}
984+advanceMatrixQaActorCursor({
985+actorId: "driver",
986+syncState: context.syncState,
987+nextSince: progressAfterFinal.since,
988+ startSince,
989+});
990+const finalReply = buildMatrixReplyArtifact(preview.event, params.finalText);
991+return {
992+artifacts: {
993+ driverEventId,
994+previewBodyPreview: progressAfterFinal.event.body?.slice(0, 200),
995+previewEventId: progressPreviewEventId,
996+previewFormattedBodyPreview: progressAfterFinal.event.formattedBody?.slice(0, 200),
997+previewMentions: progressAfterFinal.event.mentions,
998+reply: finalReply,
999+token: params.finalText,
1000+ triggerBody,
1001+},
1002+details: [
1003+`driver event: ${driverEventId}`,
1004+`scenario: ${params.label}`,
1005+`preview event: ${progressPreviewEventId}`,
1006+`preview kind: ${progressAfterFinal.event.kind}`,
1007+`preview body: ${progressAfterFinal.event.body ?? "<none>"}`,
1008+"final reply relation: <none>; final delivered before observable tool-progress failure",
1009+ ...buildMatrixReplyDetails("final reply", finalReply),
1010+].join("\n"),
1011+} satisfies MatrixQaScenarioExecution;
1012+}
1013+1014+if (params.allowFinalOnly === true) {
1015+const unexpectedWorkingEvents = findMatrixQaUnexpectedWorkingEvents({
1016+events: context.observedEvents,
1017+finalEventId: preview.event.eventId,
1018+startIndex: startObservedIndex,
1019+sutUserId: context.sutUserId,
1020+});
1021+if (unexpectedWorkingEvents.length > 0) {
1022+throw new Error(
1023+`Matrix tool progress leaked outside preview event: ${unexpectedWorkingEvents.map((event) => `${event.eventId}:${event.body ?? ""}`).join("; ")}`,
1024+);
1025+}
1026+advanceMatrixQaActorCursor({
1027+actorId: "driver",
1028+syncState: context.syncState,
1029+nextSince: preview.since,
1030+ startSince,
1031+});
1032+const finalReply = buildMatrixReplyArtifact(preview.event, params.finalText);
1033+return {
1034+artifacts: {
1035+ driverEventId,
1036+previewEventId: undefined,
1037+reply: finalReply,
1038+token: params.finalText,
1039+ triggerBody,
1040+},
1041+details: [
1042+`driver event: ${driverEventId}`,
1043+`scenario: ${params.label}`,
1044+"preview event: <none>; final delivered before observable tool-progress preview",
1045+ ...buildMatrixReplyDetails("final reply", finalReply),
1046+].join("\n"),
1047+} satisfies MatrixQaScenarioExecution;
9381048}
939-advanceMatrixQaActorCursor({
940-actorId: "driver",
941-syncState: context.syncState,
942-nextSince: preview.since,
943- startSince,
944-});
945-const finalReply = buildMatrixReplyArtifact(preview.event, params.finalText);
946-return {
947-artifacts: {
948- driverEventId,
949-previewEventId: undefined,
950-reply: finalReply,
951-token: params.finalText,
952- triggerBody,
953-},
954-details: [
955-`driver event: ${driverEventId}`,
956-`scenario: ${params.label}`,
957-"preview event: <none>; final delivered before observable tool-progress preview",
958- ...buildMatrixReplyDetails("final reply", finalReply),
959-].join("\n"),
960-} satisfies MatrixQaScenarioExecution;
9611049}
9621050const previewRootEventId = getPreviewRootEventId(preview.event);
963-const progress = matchesExpectedProgress(preview.event.body)
964- ? preview
965- : await client
1051+const isProgressProofForPreview = (event: MatrixQaObservedEvent) =>
1052+isProgressReplacement(event, previewRootEventId) ||
1053+(params.allowTopLevelFinalWithProgress === true && isProgressProofEvent(event));
1054+let topLevelFinalBeforeProgress: typeof preview | undefined;
1055+let progress = preview;
1056+if (!matchesExpectedProgress(preview.event.body)) {
1057+const progressOrFinal = await client
1058+.waitForRoomEvent({
1059+observedEvents: context.observedEvents,
1060+predicate: (event) =>
1061+isProgressProofForPreview(event) ||
1062+(params.allowTopLevelFinalWithProgress === true && isFinalReply(event)),
1063+roomId: context.roomId,
1064+since: preview.since,
1065+timeoutMs: context.timeoutMs,
1066+})
1067+.catch((err: unknown) => {
1068+throw new Error(
1069+buildMatrixQaToolProgressTimeoutMessage({
1070+cause: err,
1071+events: context.observedEvents,
1072+expectedPreviewKind: params.expectedPreviewKind,
1073+previewEventId: previewRootEventId,
1074+roomId: context.roomId,
1075+startIndex: startObservedIndex,
1076+sutUserId: context.sutUserId,
1077+}),
1078+);
1079+});
1080+if (isFinalReply(progressOrFinal.event)) {
1081+topLevelFinalBeforeProgress = progressOrFinal;
1082+progress = await client
9661083.waitForRoomEvent({
9671084observedEvents: context.observedEvents,
968-predicate: (event) =>
969-event.roomId === context.roomId &&
970-event.sender === context.sutUserId &&
971-event.kind === params.expectedPreviewKind &&
972-event.relatesTo?.relType === "m.replace" &&
973-event.relatesTo.eventId === previewRootEventId &&
974-matchesExpectedProgress(event.body),
1085+predicate: isProgressProofForPreview,
9751086roomId: context.roomId,
976-since: preview.since,
1087+since: progressOrFinal.since,
9771088timeoutMs: context.timeoutMs,
9781089})
9791090.catch((err: unknown) => {
@@ -989,38 +1100,45 @@ async function runMatrixToolProgressScenario(
9891100}),
9901101);
9911102});
1103+} else {
1104+progress = progressOrFinal;
1105+}
1106+}
99211079931108if (params.mentionSafety) {
9941109assertMatrixQaToolProgressMentionsInert(progress.event);
9951110}
9961111997-const finalized = await client
998-.waitForRoomEvent({
999-observedEvents: context.observedEvents,
1000-predicate: (event) =>
1001-event.roomId === context.roomId &&
1002-event.sender === context.sutUserId &&
1003-isMatrixQaMessageLikeKind(event.kind) &&
1004-event.relatesTo?.relType === "m.replace" &&
1005-event.relatesTo.eventId === previewRootEventId &&
1006-doesMatrixQaReplyBodyMatchToken(event, params.finalText),
1007-roomId: context.roomId,
1008-since: progress.since,
1009-timeoutMs: context.timeoutMs,
1010-})
1011-.catch((err: unknown) => {
1012-throw new Error(
1013-buildMatrixQaToolProgressFinalTimeoutMessage({
1014-cause: err,
1015-events: context.observedEvents,
1016-previewEventId: previewRootEventId,
1017-roomId: context.roomId,
1018-startIndex: startObservedIndex,
1019-sutUserId: context.sutUserId,
1020-token: params.finalText,
1021-}),
1022-);
1023-});
1112+const finalized =
1113+topLevelFinalBeforeProgress ??
1114+(await client
1115+.waitForRoomEvent({
1116+observedEvents: context.observedEvents,
1117+predicate: (event) =>
1118+event.roomId === context.roomId &&
1119+event.sender === context.sutUserId &&
1120+isMatrixQaMessageLikeKind(event.kind) &&
1121+doesMatrixQaReplyBodyMatchToken(event, params.finalText) &&
1122+((event.relatesTo?.relType === "m.replace" &&
1123+event.relatesTo.eventId === previewRootEventId) ||
1124+(params.allowTopLevelFinalWithProgress === true && event.relatesTo === undefined)),
1125+roomId: context.roomId,
1126+since: progress.since,
1127+timeoutMs: context.timeoutMs,
1128+})
1129+.catch((err: unknown) => {
1130+throw new Error(
1131+buildMatrixQaToolProgressFinalTimeoutMessage({
1132+cause: err,
1133+events: context.observedEvents,
1134+previewEventId: previewRootEventId,
1135+roomId: context.roomId,
1136+startIndex: startObservedIndex,
1137+sutUserId: context.sutUserId,
1138+token: params.finalText,
1139+}),
1140+);
1141+}));
10241142const unexpectedWorkingEvents = findMatrixQaUnexpectedWorkingEvents({
10251143events: context.observedEvents,
10261144finalEventId: finalized.event.eventId,
@@ -1036,7 +1154,7 @@ async function runMatrixToolProgressScenario(
10361154advanceMatrixQaActorCursor({
10371155actorId: "driver",
10381156syncState: context.syncState,
1039-nextSince: finalized.since,
1157+nextSince: topLevelFinalBeforeProgress ? progress.since : finalized.since,
10401158 startSince,
10411159});
10421160const finalReply = buildMatrixReplyArtifact(finalized.event, params.finalText);
@@ -1097,7 +1215,9 @@ export async function runToolProgressErrorScenario(context: MatrixQaScenarioCont
10971215finalText: buildMatrixQaToken("MATRIX_QA_TOOL_PROGRESS_ERROR"),
10981216label: "tool progress error",
10991217allowGenericProgressLine: true,
1100-progressPattern: /\bread\s*:?\s*from\s+\S*missing-matrix-tool-progress-target\.txt\b/i,
1218+allowTopLevelFinalWithProgress: true,
1219+progressPattern:
1220+/\b(?:read|show)\s*:?\s*(?:from\s+)?\S*missing-matrix-tool-progress-target\.txt\b/i,
11011221triggerBodyBuilder: buildMatrixToolProgressErrorPrompt,
11021222});
11031223}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。