


























@@ -32,10 +32,12 @@ const DEFAULT_CODEX_MODEL = "openai/gpt-5.5";
3232type TrajectoryExportApprovalEntry = {
3333id?: string;
3434command?: string;
35+commandArgv?: string[];
3536commandText?: string;
3637commandPreview?: string;
3738request?: {
3839command?: string;
40+commandArgv?: string[];
3941commandText?: string;
4042commandPreview?: string;
4143};
@@ -46,6 +48,11 @@ type TrajectoryExportApprovalSummary = {
4648hasTrajectoryExportCommand: boolean;
4749};
485051+type TrajectoryExportSignal = {
52+approvalId?: string;
53+instructionText: string;
54+};
55+4956function logLiveStep(step: string, details?: Record<string, unknown>): void {
5057if (!CODEX_HARNESS_DEBUG) {
5158return;
@@ -212,9 +219,11 @@ function extractAssistantTexts(messages: unknown[]): string[] {
212219function getTrajectoryExportApprovalCommands(entry: TrajectoryExportApprovalEntry): string[] {
213220return [
214221entry.request?.command,
222+entry.request?.commandArgv?.join(" "),
215223entry.request?.commandText,
216224entry.request?.commandPreview,
217225entry.command,
226+entry.commandArgv?.join(" "),
218227entry.commandText,
219228entry.commandPreview,
220229].filter((value): value is string => typeof value === "string" && value.trim().length > 0);
@@ -238,18 +247,19 @@ function summarizeTrajectoryExportApproval(
238247return summary;
239248}
240249241-async function waitForTrajectoryExportInstructionText(params: {
250+async function waitForTrajectoryExportSignal(params: {
242251client: GatewayClient;
243252events: EventFrame[];
244253eventStartIndex: number;
245254expectedText: string;
246255runId: string;
247256sessionKey: string;
248257timeoutMs: number;
249-}): Promise<string> {
258+}): Promise<TrajectoryExportSignal> {
250259const deadline = Date.now() + params.timeoutMs;
251-let finalTexts: string[] = [];
252-let assistantTexts: string[] = [];
260+let finalTexts: string[] | undefined;
261+let assistantTexts: string[] | undefined;
262+let approvalId: string | undefined;
253263let nextHistoryPollAt = 0;
254264while (Date.now() < deadline) {
255265const newEvents = params.events.slice(params.eventStartIndex);
@@ -258,7 +268,7 @@ async function waitForTrajectoryExportInstructionText(params: {
258268.filter((text): text is string => typeof text === "string" && text.trim().length > 0);
259269const matchedText = finalTexts.find((text) => text.includes(params.expectedText));
260270if (matchedText) {
261-return matchedText;
271+return { ...(approvalId ? { approvalId } : {}), instructionText: matchedText };
262272}
263273if (Date.now() >= nextHistoryPollAt) {
264274try {
@@ -275,11 +285,22 @@ async function waitForTrajectoryExportInstructionText(params: {
275285text.includes(params.expectedText),
276286);
277287if (matchedHistoryText) {
278-return matchedHistoryText;
288+return { ...(approvalId ? { approvalId } : {}), instructionText: matchedHistoryText };
279289}
280290} catch {
281291assistantTexts = [];
282292}
293+try {
294+const approvals = (await params.client.request(
295+"exec.approval.list",
296+{},
297+{ timeoutMs: 10_000 },
298+)) as TrajectoryExportApprovalEntry[];
299+const approval = approvals.find(isTrajectoryExportApproval);
300+if (approval && !approvalId) {
301+approvalId = await approveTrajectoryExport(params.client, approval);
302+}
303+} catch {}
283304nextHistoryPollAt = Date.now() + 2_000;
284305}
285306await new Promise((resolve) => {
@@ -299,7 +320,7 @@ async function waitForTrajectoryExportInstructionText(params: {
299320}
300321throw new Error(
301322`timed out waiting for trajectory export instruction text for ${params.runId}; ` +
302-`events=${params.events.length}; finalTexts=${formatTextPreview(finalTexts)}; assistantTexts=${formatTextPreview(assistantTexts)}; approvals=${JSON.stringify(approvalSummaries)}`,
323+`events=${params.events.length}; approved=${approvalId ?? "<none>"}; finalTexts=${formatTextPreview(finalTexts ?? [])}; assistantTexts=${formatTextPreview(assistantTexts ?? [])}; approvals=${JSON.stringify(approvalSummaries)}`,
303324);
304325}
305326@@ -353,11 +374,14 @@ function extractVisibleMessageText(message: unknown): string | undefined {
353374return text || undefined;
354375}
355376356-async function approveTrajectoryExport(client: GatewayClient): Promise<string> {
377+async function approveTrajectoryExport(
378+client: GatewayClient,
379+existingApproval?: TrajectoryExportApprovalEntry,
380+): Promise<string> {
357381const startedAt = Date.now();
358-let approval: TrajectoryExportApprovalEntry | undefined;
382+let approval: TrajectoryExportApprovalEntry | undefined = existingApproval;
359383let lastApprovalSummaries: TrajectoryExportApprovalSummary[] = [];
360-while (Date.now() - startedAt < 60_000) {
384+while (!approval && Date.now() - startedAt < 60_000) {
361385const approvals = (await client.request(
362386"exec.approval.list",
363387{},
@@ -504,10 +528,10 @@ describeLive("gateway live trajectory export", () => {
504528exportResponse?.status === "ok" ||
505529exportResponse?.status === "started",
506530).toBe(true);
507-const finalText =
531+const exportSignal: TrajectoryExportSignal =
508532typeof exportResponse?.message === "object"
509- ? extractVisibleMessageText(exportResponse.message)
510- : await waitForTrajectoryExportInstructionText({
533+ ? { instructionText: extractVisibleMessageText(exportResponse.message) ?? "" }
534+ : await waitForTrajectoryExportSignal({
511535 client,
512536events: gatewayEvents,
513537eventStartIndex: exportEventStartIndex,
@@ -516,13 +540,13 @@ describeLive("gateway live trajectory export", () => {
516540 sessionKey,
517541timeoutMs: TRAJECTORY_EXPORT_INSTRUCTION_TIMEOUT_MS,
518542});
519-expect(finalText).toContain("Trajectory exports can include");
520-expect(finalText).toContain("through exec approval");
521-expect(finalText).toContain("Approve once");
522-const approvalId = await approveTrajectoryExport(client);
543+expect(exportSignal.instructionText).toContain("Trajectory exports can include");
544+expect(exportSignal.instructionText).toContain("through exec approval");
545+expect(exportSignal.instructionText).toContain("Approve once");
546+const approvalId = exportSignal.approvalId ?? (await approveTrajectoryExport(client));
523547logLiveStep("export:approved", { approvalId });
524548await waitForPath(path.join(bundleDir, "events.jsonl"), 60_000);
525-logLiveStep("export:done", { approvalId, finalText });
549+logLiveStep("export:done", { approvalId, finalText: exportSignal.instructionText });
526550const bundleNames = await listDirectoryNames(bundleDir);
527551for (const expectedName of [
528552"artifacts.json",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。