Files
rea/experiments/atomic-codemode/executor.mjs
T
782132cb58 fix(experiment): publish shared execution resource policy
Use one policy for executor defaults, MCP admission and help. Make timeout default/maximum explicit, omit Code Mode limits from direct help, and describe the independent switch facet.

Validate 73 shared tests, both actual MCP catalogs, rejection recovery, and real zlib Evidence access after bounded guest failures. Model results remain pinned to earlier discovery contracts.

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-16 16:22:38 +00:00

246 lines
7.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { getQuickJS } from "quickjs-emscripten";
import { methods } from "./api.mjs";
import { MAX_BRIDGE_BYTES as MAX_BRIDGE, EXECUTION_LIMITS } from "./limits.mjs";
const MAX_OUTPUT = EXECUTION_LIMITS.output_utf8_bytes;
const failure = (code, message) => ({ ok: false, error: { code, message } });
const projectGuestError = (code, error) => {
const message =
typeof error?.message === "string" ? error.message : String(error);
// Check raw size first: JSON escaping expands each code unit at most sixfold,
// so the second check has a 6×32 KiB string bound plus a fixed envelope.
if (
Buffer.byteLength(message) > MAX_OUTPUT ||
Buffer.byteLength(JSON.stringify({ code, message })) > MAX_OUTPUT
)
return {
code: "output_budget",
message: `JavaScript error exceeds the ${MAX_OUTPUT / 1024} KiB output budget; its message is omitted. Native Evidence remains retained.`,
details: {
original_error_code: code,
original_message_code_units: message.length,
original_message_omitted: true,
},
};
return { code, message };
};
export const executeJavaScript = async (
session,
code,
{
signal = new AbortController().signal,
timeoutMs = EXECUTION_LIMITS.timeout_ms.default,
cpuBudgetMs = EXECUTION_LIMITS.execution_cpu_ms,
} = {},
) => {
if (Buffer.byteLength(code) > EXECUTION_LIMITS.code_utf8_bytes)
return failure(
"code_budget",
`JavaScript source exceeds ${EXECUTION_LIMITS.code_utf8_bytes / 1024} KiB`,
);
const started = performance.now();
const context = session.context;
const lease = context?.lease;
const stop = new AbortController();
const combined = AbortSignal.any([signal, stop.signal]);
const deadline = Date.now() + timeoutMs;
const timer = setTimeout(() => stop.abort(), timeoutMs);
const QuickJS = await getQuickJS();
const runtime = QuickJS.newRuntime();
runtime.setMemoryLimit(EXECUTION_LIMITS.execution_heap_mib * 1024 * 1024);
runtime.setMaxStackSize(EXECUTION_LIMITS.execution_stack_bytes);
const budget = { used: 0, deadline: 0, exhausted: false };
const runGuest = (work) => {
budget.deadline = Date.now() + Math.max(1, cpuBudgetMs - budget.used);
const before = performance.now();
try {
return work();
} finally {
budget.used += performance.now() - before;
}
};
runtime.setInterruptHandler(() => {
budget.exhausted ||= Date.now() >= budget.deadline;
return budget.exhausted || combined.aborted || Date.now() >= deadline;
});
const vm = runtime.newContext();
const pending = new Set();
const calls = [];
const state = { disposed: false, evidence: new Set() };
const pump = () => {
if (!state.disposed) {
const result = runGuest(() => runtime.executePendingJobs());
if (result.error) {
result.error.dispose();
stop.abort();
}
}
};
installBridge(vm, session, { combined, lease, calls, pending, pump, state });
let outcome;
try {
const text = await evaluateGuest(vm, code, { runGuest, pump, combined });
if (Buffer.byteLength(text) > MAX_OUTPUT)
outcome = {
ok: false,
error: {
code: "output_budget",
message: `Return a smaller projection (${MAX_OUTPUT / 1024} KiB UTF-8 output budget); native Evidence remains retained`,
},
};
else
outcome = {
ok: true,
value: text === "undefined" ? null : JSON.parse(text),
};
} catch (error) {
outcome = {
ok: false,
error: projectGuestError(
budget.exhausted
? "cpu_budget"
: combined.aborted
? "cancelled"
: "javascript_error",
budget.exhausted
? "Guest synchronous execution budget exceeded"
: error,
),
};
} finally {
clearTimeout(timer);
stop.abort();
await Promise.allSettled(pending);
state.disposed = true;
vm.dispose();
runtime.dispose();
}
return {
...outcome,
context,
evidence_ids: [...state.evidence],
calls,
elapsed_ms: performance.now() - started,
};
};
const retainEvidence = (response, evidence) => {
const observation =
response.data ?? response.error?.details?.partial_observation;
for (const row of [observation, ...(observation?.results ?? [])]) {
const id =
row?.source?.evidence_id ??
row?.evidence_id ??
row?.error?.details?.evidence_id;
if (id) evidence.add(id);
}
if (response.error?.details?.evidence_id)
evidence.add(response.error.details.evidence_id);
};
const installBridge = (
vm,
session,
{ combined, lease, calls, pending, pump, state },
) => {
const bridge = vm.newFunction("analysis", (methodHandle, inputHandle) => {
const name = vm.getString(methodHandle);
const inputText = vm.getString(inputHandle);
if (
calls.length >= EXECUTION_LIMITS.max_host_calls ||
Buffer.byteLength(inputText) > MAX_BRIDGE
)
throw new Error("Host call or argument budget exceeded");
const promise = vm.newPromise();
const index = calls.length;
calls.push({
method: name,
input: JSON.parse(inputText),
status: "pending",
});
const work = Promise.resolve()
.then(async () => {
const before = performance.now();
const response = await session.call(
name,
JSON.parse(inputText),
combined,
lease,
);
retainEvidence(response, state.evidence);
calls[index].status = response.ok ? "ok" : "error";
if (!response.ok) calls[index].error = response.error;
calls[index].elapsed_ms = performance.now() - before;
let serialized = JSON.stringify(response);
if (Buffer.byteLength(serialized) > MAX_BRIDGE)
serialized = JSON.stringify({
ok: false,
error: {
code: "bridge_budget",
message:
"Select fewer fields or a smaller page; full source remains available via evidence",
},
});
if (!state.disposed) {
const value = vm.newString(serialized);
promise.resolve(value);
value.dispose();
pump();
}
})
.catch((error) => {
if (!state.disposed) {
const value = vm.newString(
JSON.stringify({
ok: false,
error: { code: "bridge_failed", message: error.message },
}),
);
promise.resolve(value);
value.dispose();
pump();
}
})
.finally(() => pending.delete(work));
pending.add(work);
return promise.handle;
});
vm.setProp(vm.global, "__analysis", bridge);
bridge.dispose();
};
const evaluateGuest = async (vm, code, { runGuest, pump, combined }) => {
const bootstrap = `globalThis.rea=Object.freeze(Object.fromEntries(${JSON.stringify(Object.keys(methods))}.map(name=>[name,async(input={})=>JSON.parse(await __analysis(name,JSON.stringify(input)))])));`;
vm.unwrapResult(runGuest(() => vm.evalCode(bootstrap))).dispose();
const promiseHandle = vm.unwrapResult(
runGuest(() =>
vm.evalCode(
`(async()=>JSON.stringify(await(async()=>{\n${code}\n})()))()`,
),
),
);
try {
const resolved = vm.resolvePromise(promiseHandle);
pump();
// A never-settling guest Promise must not hang the MCP request forever.
const aborted = new Promise((_, reject) => {
if (combined.aborted) {
reject(new Error("Execution cancelled"));
return;
}
combined.addEventListener(
"abort",
() => reject(new Error("Execution cancelled or timed out")),
{ once: true },
);
});
const result = await Promise.race([resolved, aborted]);
const value = vm.unwrapResult(result);
const text = vm.getString(value);
value.dispose();
return text;
} finally {
promiseHandle.dispose();
}
};