






















@@ -53,7 +53,12 @@ type CodeModeWorkerResult =
5353| {
5454status: "failed";
5555error: string;
56-code: "invalid_input" | "runtime_unavailable" | "timeout" | "internal_error";
56+code:
57+| "invalid_input"
58+| "runtime_unavailable"
59+| "timeout"
60+| "snapshot_limit_exceeded"
61+| "internal_error";
5762output: unknown[];
5863};
5964@@ -71,6 +76,21 @@ class CodeModeWorkerFailure extends Error {
7176}
7277}
737879+class CodeModeWorkerFailureWithOutput extends CodeModeWorkerFailure {
80+readonly output: unknown[];
81+82+constructor(
83+code: Extract<CodeModeWorkerResult, { status: "failed" }>["code"],
84+message: string,
85+output: unknown[],
86+options?: ErrorOptions,
87+) {
88+super(code, message, options);
89+this.name = "CodeModeWorkerFailureWithOutput";
90+this.output = output;
91+}
92+}
93+7494class CodeModeGuestError extends Error {
7595constructor(message: string) {
7696super(message);
@@ -337,6 +357,49 @@ function takeOutput(vm: QuickJS): unknown[] {
337357}
338358}
339359360+function takeOutputSafely(vm: QuickJS): unknown[] {
361+try {
362+return takeOutput(vm);
363+} catch {
364+return [];
365+}
366+}
367+368+function throwWorkerFailureWithOutput(params: {
369+error: unknown;
370+didTimeout: () => boolean;
371+output: unknown[];
372+vm: QuickJS;
373+}): never {
374+const timedOut = params.didTimeout() || isQuickJsInterruptedError(params.error);
375+const failureOutput = params.output.length > 0 ? params.output : takeOutputSafely(params.vm);
376+if (timedOut) {
377+throw new CodeModeWorkerFailureWithOutput(
378+"timeout",
379+"code mode timeout exceeded",
380+failureOutput,
381+{ cause: params.error },
382+);
383+}
384+if (params.error instanceof CodeModeWorkerFailure) {
385+throw new CodeModeWorkerFailureWithOutput(
386+params.error.code,
387+params.error.message,
388+failureOutput,
389+{ cause: params.error },
390+);
391+}
392+if (failureOutput.length > 0) {
393+throw new CodeModeWorkerFailureWithOutput(
394+"internal_error",
395+errorMessage(params.error),
396+failureOutput,
397+{ cause: params.error },
398+);
399+}
400+throw params.error;
401+}
402+340403function drainPendingJobs(vm: QuickJS): void {
341404for (let index = 0; index < 1000; index += 1) {
342405if (vm.executePendingJobs() === 0) {
@@ -377,7 +440,7 @@ function waitingResult(params: {
377440}): CodeModeWorkerResult {
378441const snapshotBytes = QuickJS.serializeSnapshot(params.vm.snapshot());
379442if (snapshotBytes.byteLength > params.config.maxSnapshotBytes) {
380-throw new Error("code mode snapshot limit exceeded");
443+throw new CodeModeWorkerFailure("snapshot_limit_exceeded", "code mode snapshot limit exceeded");
381444}
382445return {
383446status: "waiting",
@@ -394,14 +457,15 @@ async function runExec(input: Extract<CodeModeWorkerInput, { kind: "exec" }>) {
394457config: input.config,
395458 pendingRequests,
396459});
460+let output: unknown[] = [];
397461try {
398462vm.evalCode(
399463buildUserSource(input.source),
400464"openclaw-code-mode:user.js",
401465EvalFlags.ASYNC,
402466).dispose();
403467drainPendingJobs(vm);
404-const output = takeOutput(vm);
468+output = takeOutput(vm);
405469const resultHandle = getResultHandle(vm);
406470try {
407471if (pendingRequests.length > 0) {
@@ -419,10 +483,7 @@ async function runExec(input: Extract<CodeModeWorkerInput, { kind: "exec" }>) {
419483resultHandle.dispose();
420484}
421485} catch (error) {
422-if (didTimeout() || isQuickJsInterruptedError(error)) {
423-throw new CodeModeWorkerFailure("timeout", "code mode timeout exceeded", { cause: error });
424-}
425-throw error;
486+return throwWorkerFailureWithOutput({ error, didTimeout, output, vm });
426487} finally {
427488vm.dispose();
428489}
@@ -435,6 +496,7 @@ async function runResume(input: Extract<CodeModeWorkerInput, { kind: "resume" }>
435496config: input.config,
436497 pendingRequests,
437498});
499+let output: unknown[] = [];
438500try {
439501const settle = vm.global.getProp("__openclawSettleBridge");
440502try {
@@ -458,7 +520,7 @@ async function runResume(input: Extract<CodeModeWorkerInput, { kind: "resume" }>
458520settle.dispose();
459521}
460522drainPendingJobs(vm);
461-const output = takeOutput(vm);
523+output = takeOutput(vm);
462524const resultHandle = getResultHandle(vm);
463525try {
464526if (pendingRequests.length > 0) {
@@ -476,10 +538,7 @@ async function runResume(input: Extract<CodeModeWorkerInput, { kind: "resume" }>
476538resultHandle.dispose();
477539}
478540} catch (error) {
479-if (didTimeout() || isQuickJsInterruptedError(error)) {
480-throw new CodeModeWorkerFailure("timeout", "code mode timeout exceeded", { cause: error });
481-}
482-throw error;
541+return throwWorkerFailureWithOutput({ error, didTimeout, output, vm });
483542} finally {
484543vm.dispose();
485544}
@@ -525,7 +584,7 @@ async function main(): Promise<CodeModeWorkerResult> {
525584status: "failed",
526585error: errorMessage(error),
527586code: error instanceof CodeModeWorkerFailure ? error.code : "internal_error",
528-output: [],
587+output: error instanceof CodeModeWorkerFailureWithOutput ? error.output : [],
529588};
530589}
531590}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。