@algosuite/vo-mcp 0.2.0-beta.33 → 0.2.0-beta.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/runner-cli.js +111 -240
- package/dist/runner-cli.js.map +4 -4
- package/dist/runner-supervisor.js +99 -2
- package/dist/runner-supervisor.js.map +4 -4
- package/package.json +1 -1
package/dist/runner-cli.js
CHANGED
|
@@ -2582,11 +2582,6 @@ var init_control_plane_auth_stub = __esm({
|
|
|
2582
2582
|
});
|
|
2583
2583
|
|
|
2584
2584
|
// ../../scripts/virtual-office/code-runner/control-plane-client.mjs
|
|
2585
|
-
var control_plane_client_exports = {};
|
|
2586
|
-
__export(control_plane_client_exports, {
|
|
2587
|
-
ClaimAuthorityChangedError: () => ClaimAuthorityChangedError,
|
|
2588
|
-
createControlPlaneClient: () => createControlPlaneClient
|
|
2589
|
-
});
|
|
2590
2585
|
async function resolveBearer(env2) {
|
|
2591
2586
|
const adminToken = env2.VO_CONTROL_PLANE_ADMIN_TOKEN;
|
|
2592
2587
|
if (adminToken) return adminToken;
|
|
@@ -2619,11 +2614,11 @@ function createControlPlaneClient({
|
|
|
2619
2614
|
const resolvedBaseUrl = baseUrl ?? env2.VO_CONTROL_PLANE_URL ?? "";
|
|
2620
2615
|
if (!resolvedBaseUrl) throw new Error("VO_CONTROL_PLANE_URL is required for the code-runner daemon");
|
|
2621
2616
|
const root = resolvedBaseUrl.replace(/\/+$/, "");
|
|
2622
|
-
async function req(method,
|
|
2617
|
+
async function req(method, path22, body, { timeoutMs } = {}) {
|
|
2623
2618
|
const bearer = await resolveBearer(env2);
|
|
2624
2619
|
const controller = timeoutMs ? new AbortController() : null;
|
|
2625
2620
|
let timeoutId;
|
|
2626
|
-
const request = Promise.resolve(fetchImpl(`${root}${
|
|
2621
|
+
const request = Promise.resolve(fetchImpl(`${root}${path22}`, {
|
|
2627
2622
|
method,
|
|
2628
2623
|
headers: {
|
|
2629
2624
|
"content-type": "application/json",
|
|
@@ -2636,7 +2631,7 @@ function createControlPlaneClient({
|
|
|
2636
2631
|
const timeout = new Promise((_, reject) => {
|
|
2637
2632
|
timeoutId = setTimeout(() => {
|
|
2638
2633
|
controller.abort();
|
|
2639
|
-
reject(new Error(`control-plane ${
|
|
2634
|
+
reject(new Error(`control-plane ${path22} timed out after ${timeoutMs}ms`));
|
|
2640
2635
|
}, timeoutMs);
|
|
2641
2636
|
});
|
|
2642
2637
|
try {
|
|
@@ -2645,7 +2640,7 @@ function createControlPlaneClient({
|
|
|
2645
2640
|
clearTimeout(timeoutId);
|
|
2646
2641
|
}
|
|
2647
2642
|
}
|
|
2648
|
-
const taskReq = (method,
|
|
2643
|
+
const taskReq = (method, path22, body, options = {}) => req(method, path22, body, { timeoutMs: taskRequestTimeoutMs, ...options });
|
|
2649
2644
|
return {
|
|
2650
2645
|
...makeAutonomousDispatchAdmissionClient(
|
|
2651
2646
|
req,
|
|
@@ -2768,8 +2763,8 @@ function createControlPlaneClient({
|
|
|
2768
2763
|
return listAllPrOpenedTasks(taskReq);
|
|
2769
2764
|
},
|
|
2770
2765
|
async downloadTaskAttachment(taskId, attachmentId) {
|
|
2771
|
-
const
|
|
2772
|
-
const res = await taskReq("GET",
|
|
2766
|
+
const path22 = `/api/v1/code-task/${encodeURIComponent(taskId)}/attachment/${encodeURIComponent(attachmentId)}`;
|
|
2767
|
+
const res = await taskReq("GET", path22);
|
|
2773
2768
|
if (res.status === 401) cachedFirebaseToken = null;
|
|
2774
2769
|
if (!res.ok) throw new Error(`attachment download failed: HTTP ${res.status}`);
|
|
2775
2770
|
return Buffer.from(await res.arrayBuffer());
|
|
@@ -5981,14 +5976,14 @@ function parsePorcelainZ(out) {
|
|
|
5981
5976
|
for (let i = 0; i < tokens.length; i += 1) {
|
|
5982
5977
|
const token2 = tokens[i];
|
|
5983
5978
|
if (!token2) continue;
|
|
5984
|
-
const
|
|
5985
|
-
if (
|
|
5979
|
+
const path22 = token2.slice(3);
|
|
5980
|
+
if (path22) files.push(path22);
|
|
5986
5981
|
if (token2[0] === "R" || token2[0] === "C") i += 1;
|
|
5987
5982
|
}
|
|
5988
5983
|
return files;
|
|
5989
5984
|
}
|
|
5990
|
-
function isAgentScratch(
|
|
5991
|
-
const normalized = String(
|
|
5985
|
+
function isAgentScratch(path22) {
|
|
5986
|
+
const normalized = String(path22 || "");
|
|
5992
5987
|
return SCRATCH_PATTERNS.some((pattern) => pattern.test(normalized));
|
|
5993
5988
|
}
|
|
5994
5989
|
var SCRATCH_PATTERNS;
|
|
@@ -6055,6 +6050,15 @@ var init_publish = __esm({
|
|
|
6055
6050
|
}
|
|
6056
6051
|
});
|
|
6057
6052
|
|
|
6053
|
+
// ../../scripts/virtual-office/test-gen/marker.mjs
|
|
6054
|
+
var TEST_GEN_MARKER;
|
|
6055
|
+
var init_marker = __esm({
|
|
6056
|
+
"../../scripts/virtual-office/test-gen/marker.mjs"() {
|
|
6057
|
+
"use strict";
|
|
6058
|
+
TEST_GEN_MARKER = "[VO-TEST-GEN]";
|
|
6059
|
+
}
|
|
6060
|
+
});
|
|
6061
|
+
|
|
6058
6062
|
// ../../scripts/virtual-office/test-gen/auto-tier.mjs
|
|
6059
6063
|
function lower(s) {
|
|
6060
6064
|
return typeof s === "string" ? s.toLowerCase() : "";
|
|
@@ -6128,146 +6132,6 @@ var init_auto_tier = __esm({
|
|
|
6128
6132
|
}
|
|
6129
6133
|
});
|
|
6130
6134
|
|
|
6131
|
-
// ../../scripts/virtual-office/test-gen/dispatch.mjs
|
|
6132
|
-
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
6133
|
-
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
6134
|
-
import path14 from "node:path";
|
|
6135
|
-
function buildGenerationPrompt({ contract = {}, tier }) {
|
|
6136
|
-
const label = tierLabel(tier);
|
|
6137
|
-
const target = contract.callable ? `the \`${contract.callable}\` callable` : contract.route ? `the \`${contract.route}\` route` : contract.feature_name || "the feature";
|
|
6138
|
-
return [
|
|
6139
|
-
`Write a ${label} test for ${target} in product "${contract.product || "unknown"}".`,
|
|
6140
|
-
contract.source_file ? `Source: ${contract.source_file}.` : "",
|
|
6141
|
-
contract.expected_behavior ? `Expected behavior: ${contract.expected_behavior}.` : "",
|
|
6142
|
-
"",
|
|
6143
|
-
`TIER REQUIREMENT \u2014 ${TIER_GUIDANCE[tier] || TIER_GUIDANCE[2]}`,
|
|
6144
|
-
"",
|
|
6145
|
-
"Follow the AlgoSuite test-honesty standard: NO fake-green (no bare toBeTruthy, no broad",
|
|
6146
|
-
"try/catch that swallows failures, no treating INVALID_ARGUMENT / empty / null / SKIP as a",
|
|
6147
|
-
"pass). Use a real fixture (smoke@algosuite.ai) and real data shapes.",
|
|
6148
|
-
"",
|
|
6149
|
-
"After writing the test, it will be GATED server-side: deterministic ratchets, then",
|
|
6150
|
-
"multi-model consensus that it proves the behavior with VERIFIED-CORRECT expected values.",
|
|
6151
|
-
"A test that does not pass BOTH gates will NOT ship \u2014 so make the assertions real and the",
|
|
6152
|
-
"expected values known-correct. Leave the test file UNCOMMITTED; the runner opens the PR."
|
|
6153
|
-
].filter((l) => l !== "").join("\n");
|
|
6154
|
-
}
|
|
6155
|
-
function planTestGenDispatch({ contract = {} }) {
|
|
6156
|
-
const { tier, rationale } = classifyTier(contract);
|
|
6157
|
-
return {
|
|
6158
|
-
contract,
|
|
6159
|
-
tier,
|
|
6160
|
-
tier_label: tierLabel(tier),
|
|
6161
|
-
tier_rationale: rationale,
|
|
6162
|
-
generation_prompt: buildGenerationPrompt({ contract, tier })
|
|
6163
|
-
};
|
|
6164
|
-
}
|
|
6165
|
-
function buildTestGenTaskPrompt(dispatch = {}) {
|
|
6166
|
-
const contractJson = JSON.stringify(dispatch.contract ?? {});
|
|
6167
|
-
return `${TEST_GEN_MARKER} ${contractJson}
|
|
6168
|
-
|
|
6169
|
-
${dispatch.generation_prompt ?? ""}`;
|
|
6170
|
-
}
|
|
6171
|
-
function pickNextTarget({ gaps = [] }) {
|
|
6172
|
-
if (!Array.isArray(gaps) || gaps.length === 0) return null;
|
|
6173
|
-
const ranked = [...gaps].sort((a, b) => {
|
|
6174
|
-
const al = LEGAL.has(String(a.product)) ? 0 : 1;
|
|
6175
|
-
const bl = LEGAL.has(String(b.product)) ? 0 : 1;
|
|
6176
|
-
return al - bl;
|
|
6177
|
-
});
|
|
6178
|
-
return ranked[0];
|
|
6179
|
-
}
|
|
6180
|
-
function resolveRepo(argv, env2) {
|
|
6181
|
-
const repoArg = argv.indexOf("--repo");
|
|
6182
|
-
if (repoArg >= 0 && argv[repoArg + 1]) return argv[repoArg + 1];
|
|
6183
|
-
if (env2.VO_TEST_GEN_REPO) return env2.VO_TEST_GEN_REPO;
|
|
6184
|
-
const remote = spawnSync10("git", ["remote", "get-url", "origin"], { encoding: "utf8" });
|
|
6185
|
-
if (remote.status === 0) {
|
|
6186
|
-
const m = String(remote.stdout).trim().match(/[:/]([^/]+\/[^/]+?)(?:\.git)?$/);
|
|
6187
|
-
if (m) return m[1];
|
|
6188
|
-
}
|
|
6189
|
-
return null;
|
|
6190
|
-
}
|
|
6191
|
-
async function main(argv = process.argv.slice(2)) {
|
|
6192
|
-
const countArg = argv.indexOf("--count");
|
|
6193
|
-
const count3 = countArg >= 0 ? Math.max(1, Number(argv[countArg + 1]) || 1) : 1;
|
|
6194
|
-
const enqueue = argv.includes("--enqueue");
|
|
6195
|
-
const here = path14.dirname(fileURLToPath3(import.meta.url));
|
|
6196
|
-
const scan = spawnSync10("node", [path14.join(here, "coverage-scan.mjs"), "--limit", String(count3 * 8)], {
|
|
6197
|
-
encoding: "utf8",
|
|
6198
|
-
maxBuffer: 64 * 1024 * 1024
|
|
6199
|
-
});
|
|
6200
|
-
if (scan.status !== 0) {
|
|
6201
|
-
console.error(`[dispatch] coverage-scan failed: ${scan.stderr || scan.stdout}`);
|
|
6202
|
-
process.exit(1);
|
|
6203
|
-
}
|
|
6204
|
-
let gaps = [];
|
|
6205
|
-
try {
|
|
6206
|
-
gaps = JSON.parse(scan.stdout).gaps || [];
|
|
6207
|
-
} catch (err) {
|
|
6208
|
-
console.error(`[dispatch] could not parse scan output: ${err.message}`);
|
|
6209
|
-
process.exit(1);
|
|
6210
|
-
}
|
|
6211
|
-
const dispatches = [];
|
|
6212
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6213
|
-
let pool = gaps;
|
|
6214
|
-
while (dispatches.length < count3 && pool.length > 0) {
|
|
6215
|
-
const target = pickNextTarget({ gaps: pool });
|
|
6216
|
-
if (!target) break;
|
|
6217
|
-
const key = `${target.product}:${target.callable}`;
|
|
6218
|
-
if (!seen.has(key)) {
|
|
6219
|
-
seen.add(key);
|
|
6220
|
-
dispatches.push(planTestGenDispatch({ contract: target }));
|
|
6221
|
-
}
|
|
6222
|
-
pool = pool.filter((g) => `${g.product}:${g.callable}` !== key);
|
|
6223
|
-
}
|
|
6224
|
-
if (!enqueue) {
|
|
6225
|
-
console.log(JSON.stringify({ requested: count3, emitted: dispatches.length, dispatches }, null, 2));
|
|
6226
|
-
return;
|
|
6227
|
-
}
|
|
6228
|
-
const repo = resolveRepo(argv, process.env);
|
|
6229
|
-
if (!repo) {
|
|
6230
|
-
console.error("[dispatch] --enqueue needs a repo: pass --repo owner/name or set VO_TEST_GEN_REPO (could not derive from git origin)");
|
|
6231
|
-
process.exit(1);
|
|
6232
|
-
}
|
|
6233
|
-
const { createControlPlaneClient: createControlPlaneClient2 } = await Promise.resolve().then(() => (init_control_plane_client(), control_plane_client_exports));
|
|
6234
|
-
const client = createControlPlaneClient2({ env: process.env });
|
|
6235
|
-
const enqueued = [];
|
|
6236
|
-
for (const d of dispatches) {
|
|
6237
|
-
const task = await client.enqueueCodeTask({
|
|
6238
|
-
repo,
|
|
6239
|
-
prompt: buildTestGenTaskPrompt(d),
|
|
6240
|
-
max_turns: 40
|
|
6241
|
-
});
|
|
6242
|
-
const taskId = task && task.code_task_id ? task.code_task_id : "(unknown)";
|
|
6243
|
-
enqueued.push({ task_id: taskId, product: d.contract.product, callable: d.contract.callable, tier: d.tier_label });
|
|
6244
|
-
console.error(`[dispatch] enqueued ${d.tier_label} test-gen for ${d.contract.product}:${d.contract.callable} \u2192 task ${taskId}`);
|
|
6245
|
-
}
|
|
6246
|
-
console.log(JSON.stringify({ requested: count3, enqueued: enqueued.length, repo, tasks: enqueued }, null, 2));
|
|
6247
|
-
}
|
|
6248
|
-
var TEST_GEN_MARKER, TIER_GUIDANCE, LEGAL, invokedDirectly;
|
|
6249
|
-
var init_dispatch = __esm({
|
|
6250
|
-
"../../scripts/virtual-office/test-gen/dispatch.mjs"() {
|
|
6251
|
-
"use strict";
|
|
6252
|
-
init_auto_tier();
|
|
6253
|
-
TEST_GEN_MARKER = "[VO-TEST-GEN]";
|
|
6254
|
-
TIER_GUIDANCE = {
|
|
6255
|
-
1: "Surface/navigation smoke: assert the surface renders and the key controls are present. No backend effect needed.",
|
|
6256
|
-
2: "E2E with VERIFIED RESULTS: drive the real user/callable workflow, then READ BACK the produced artifact and assert KNOWN-CORRECT expected values (not just a 200 / truthiness).",
|
|
6257
|
-
3: "Real-time monitor / sentinel: drive the workflow AND verify the state transitions + safety rails (no money moved / graded / admin action without the guard). Assert the post-conditions, not just the response.",
|
|
6258
|
-
4: "Source-grounded governed-fact: assert expected values that are GROUNDED in the cited authoritative source (the contract's authoritative_source_url). The fixture and the expected number/string must trace to that source."
|
|
6259
|
-
};
|
|
6260
|
-
LEGAL = /* @__PURE__ */ new Set(["algotax", "algolaw", "algoteach", "algolegal"]);
|
|
6261
|
-
invokedDirectly = process.argv[1] && fileURLToPath3(import.meta.url) === path14.resolve(process.argv[1]);
|
|
6262
|
-
if (invokedDirectly) {
|
|
6263
|
-
main().catch((err) => {
|
|
6264
|
-
console.error(`[dispatch] ${err.message}`);
|
|
6265
|
-
process.exit(1);
|
|
6266
|
-
});
|
|
6267
|
-
}
|
|
6268
|
-
}
|
|
6269
|
-
});
|
|
6270
|
-
|
|
6271
6135
|
// ../../scripts/virtual-office/test-gen/executor.mjs
|
|
6272
6136
|
function consensusQuestion(tier) {
|
|
6273
6137
|
const tierAsk = tier >= 4 ? " For this governed-fact (Tier 4) test, the expected values MUST be grounded in the cited authoritative source." : tier >= 3 ? " For this safety-critical (Tier 3) test, it must verify state transitions and the safety rails, not just a 200." : "";
|
|
@@ -6374,7 +6238,7 @@ var init_executor = __esm({
|
|
|
6374
6238
|
|
|
6375
6239
|
// ../../scripts/virtual-office/code-runner/test-gen-gate.mjs
|
|
6376
6240
|
import fs7 from "node:fs";
|
|
6377
|
-
import
|
|
6241
|
+
import path14 from "node:path";
|
|
6378
6242
|
async function postFailed(client, id, message, result) {
|
|
6379
6243
|
try {
|
|
6380
6244
|
await client.postProgress(id, {
|
|
@@ -6410,7 +6274,7 @@ async function gateTestGenTaskOrFail({ client, id, task, files, worktreeDir, env
|
|
|
6410
6274
|
}
|
|
6411
6275
|
let testSource = "";
|
|
6412
6276
|
try {
|
|
6413
|
-
testSource = fs7.readFileSync(
|
|
6277
|
+
testSource = fs7.readFileSync(path14.join(worktreeDir, testFile), "utf8");
|
|
6414
6278
|
} catch (err) {
|
|
6415
6279
|
await postFailed(client, id, `could not read generated test ${testFile}: ${err.message}`, "gate_test_unreadable");
|
|
6416
6280
|
return true;
|
|
@@ -6451,7 +6315,7 @@ var TEST_FILE_RE;
|
|
|
6451
6315
|
var init_test_gen_gate = __esm({
|
|
6452
6316
|
"../../scripts/virtual-office/code-runner/test-gen-gate.mjs"() {
|
|
6453
6317
|
"use strict";
|
|
6454
|
-
|
|
6318
|
+
init_marker();
|
|
6455
6319
|
init_executor();
|
|
6456
6320
|
TEST_FILE_RE = /\.(test|spec)\.(ts|tsx|mjs|js)$/;
|
|
6457
6321
|
}
|
|
@@ -6460,7 +6324,7 @@ var init_test_gen_gate = __esm({
|
|
|
6460
6324
|
// ../../scripts/virtual-office/code-runner/completion-gate.mjs
|
|
6461
6325
|
import { execFile } from "node:child_process";
|
|
6462
6326
|
import fs8 from "node:fs";
|
|
6463
|
-
import
|
|
6327
|
+
import path15 from "node:path";
|
|
6464
6328
|
function resolveCompletionGate(task) {
|
|
6465
6329
|
const raw = task?.completion_gate;
|
|
6466
6330
|
if (raw === void 0 || raw === null) return null;
|
|
@@ -6498,14 +6362,14 @@ function workspaceFingerprint(worktreeDir, execFileImpl = execFile) {
|
|
|
6498
6362
|
}
|
|
6499
6363
|
function readState(worktreeDir) {
|
|
6500
6364
|
try {
|
|
6501
|
-
return JSON.parse(fs8.readFileSync(
|
|
6365
|
+
return JSON.parse(fs8.readFileSync(path15.join(worktreeDir, COMPLETION_GATE_STATE_FILE), "utf8"));
|
|
6502
6366
|
} catch {
|
|
6503
6367
|
return null;
|
|
6504
6368
|
}
|
|
6505
6369
|
}
|
|
6506
6370
|
function writeState(worktreeDir, state) {
|
|
6507
6371
|
try {
|
|
6508
|
-
fs8.writeFileSync(
|
|
6372
|
+
fs8.writeFileSync(path15.join(worktreeDir, COMPLETION_GATE_STATE_FILE), `${JSON.stringify(state)}
|
|
6509
6373
|
`, "utf8");
|
|
6510
6374
|
} catch {
|
|
6511
6375
|
}
|
|
@@ -7083,7 +6947,7 @@ var init_publish_async = __esm({
|
|
|
7083
6947
|
// ../../scripts/virtual-office/code-runner/skill-catalog.mjs
|
|
7084
6948
|
import { readdirSync as readdirSync2, readFileSync as readFileSync3, statSync } from "node:fs";
|
|
7085
6949
|
import { dirname as dirname3, join as join4 } from "node:path";
|
|
7086
|
-
import { fileURLToPath as
|
|
6950
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
7087
6951
|
function parseFrontmatterNameDescription(raw) {
|
|
7088
6952
|
const text = String(raw).replace(/\r\n/g, "\n");
|
|
7089
6953
|
if (!text.startsWith("---\n")) return null;
|
|
@@ -7102,7 +6966,7 @@ function parseFrontmatterNameDescription(raw) {
|
|
|
7102
6966
|
return name && description ? { name, description } : null;
|
|
7103
6967
|
}
|
|
7104
6968
|
function resolveDefaultRepoRoot() {
|
|
7105
|
-
const starts = [dirname3(
|
|
6969
|
+
const starts = [dirname3(fileURLToPath3(import.meta.url)), process.cwd()];
|
|
7106
6970
|
for (const start of starts) {
|
|
7107
6971
|
let dir = start;
|
|
7108
6972
|
for (let i = 0; i < 8; i += 1) {
|
|
@@ -7358,7 +7222,7 @@ var init_task_prompt = __esm({
|
|
|
7358
7222
|
import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
|
|
7359
7223
|
import { chmod, mkdir, mkdtemp, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
7360
7224
|
import os2 from "node:os";
|
|
7361
|
-
import
|
|
7225
|
+
import path16 from "node:path";
|
|
7362
7226
|
function safeTaskToken(taskId) {
|
|
7363
7227
|
return String(taskId || "task").replace(/[^0-9A-Za-z_-]/gu, "_").slice(0, 48) || "task";
|
|
7364
7228
|
}
|
|
@@ -7368,25 +7232,25 @@ function sanitizeTaskAttachmentName(name, index = 0) {
|
|
|
7368
7232
|
return `${String(index + 1).padStart(2, "0")}-${normalized}`;
|
|
7369
7233
|
}
|
|
7370
7234
|
function assertGeneratedDirectory(directory, tempRoot) {
|
|
7371
|
-
const resolvedDirectory =
|
|
7372
|
-
const resolvedRoot =
|
|
7373
|
-
if (
|
|
7235
|
+
const resolvedDirectory = path16.resolve(directory);
|
|
7236
|
+
const resolvedRoot = path16.resolve(tempRoot);
|
|
7237
|
+
if (path16.dirname(resolvedDirectory) !== resolvedRoot || !path16.basename(resolvedDirectory).startsWith(DIRECTORY_PREFIX)) {
|
|
7374
7238
|
throw new Error("refusing to clean an unverified task-attachment directory");
|
|
7375
7239
|
}
|
|
7376
7240
|
return resolvedDirectory;
|
|
7377
7241
|
}
|
|
7378
7242
|
async function createAttachmentDirectory(taskId, tempRoot) {
|
|
7379
|
-
const root =
|
|
7243
|
+
const root = path16.resolve(tempRoot);
|
|
7380
7244
|
await mkdir(root, { recursive: true });
|
|
7381
|
-
const directory = await mkdtemp(
|
|
7382
|
-
const marker = JSON.stringify({ owner: MARKER_OWNER, token: randomUUID2(), directory:
|
|
7383
|
-
await writeFile(
|
|
7245
|
+
const directory = await mkdtemp(path16.join(root, `${DIRECTORY_PREFIX}${safeTaskToken(taskId)}-`));
|
|
7246
|
+
const marker = JSON.stringify({ owner: MARKER_OWNER, token: randomUUID2(), directory: path16.basename(directory), created_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
7247
|
+
await writeFile(path16.join(directory, MARKER_FILE), marker, { encoding: "utf8", mode: 384 });
|
|
7384
7248
|
return { directory, marker, tempRoot: root };
|
|
7385
7249
|
}
|
|
7386
7250
|
async function cleanupGeneratedDirectory(state) {
|
|
7387
7251
|
if (!state || state.cleaned) return;
|
|
7388
7252
|
const directory = assertGeneratedDirectory(state.directory, state.tempRoot);
|
|
7389
|
-
const marker = await readFile(
|
|
7253
|
+
const marker = await readFile(path16.join(directory, MARKER_FILE), "utf8").catch(() => "");
|
|
7390
7254
|
if (marker !== state.marker) throw new Error("refusing to clean a task-attachment directory without its exact marker");
|
|
7391
7255
|
await rm(directory, { recursive: true, force: true });
|
|
7392
7256
|
state.cleaned = true;
|
|
@@ -7405,7 +7269,7 @@ async function sweepStaleTaskAttachmentDirectories({
|
|
|
7405
7269
|
now = Date.now(),
|
|
7406
7270
|
maxAgeMs = DEFAULT_STALE_AGE_MS
|
|
7407
7271
|
} = {}) {
|
|
7408
|
-
const root =
|
|
7272
|
+
const root = path16.resolve(tempRoot);
|
|
7409
7273
|
if (!Number.isFinite(maxAgeMs) || maxAgeMs <= 0) throw new Error("stale attachment age must be positive");
|
|
7410
7274
|
const entries = await readdir(root, { withFileTypes: true }).catch((error) => {
|
|
7411
7275
|
if (error?.code === "ENOENT") return [];
|
|
@@ -7414,8 +7278,8 @@ async function sweepStaleTaskAttachmentDirectories({
|
|
|
7414
7278
|
let removed = 0;
|
|
7415
7279
|
for (const entry of entries) {
|
|
7416
7280
|
if (!entry.isDirectory() || !entry.name.startsWith(DIRECTORY_PREFIX)) continue;
|
|
7417
|
-
const directory = assertGeneratedDirectory(
|
|
7418
|
-
const markerRaw = await readFile(
|
|
7281
|
+
const directory = assertGeneratedDirectory(path16.join(root, entry.name), root);
|
|
7282
|
+
const markerRaw = await readFile(path16.join(directory, MARKER_FILE), "utf8").catch(() => "");
|
|
7419
7283
|
const marker = parseOwnedMarker(markerRaw, entry.name);
|
|
7420
7284
|
if (!marker) continue;
|
|
7421
7285
|
const directoryStat = await stat(directory);
|
|
@@ -7458,10 +7322,10 @@ async function materializeTaskAttachments(client, task, { tempRoot = os2.tmpdir(
|
|
|
7458
7322
|
const sha256 = createHash3("sha256").update(content).digest("hex");
|
|
7459
7323
|
if (sha256 !== ref.sha256) throw new Error(`attachment ${ref.attachment_id} sha256 mismatch`);
|
|
7460
7324
|
const name = sanitizeTaskAttachmentName(ref.name, index);
|
|
7461
|
-
const filePath =
|
|
7325
|
+
const filePath = path16.join(state.directory, name);
|
|
7462
7326
|
await writeFile(filePath, content, { flag: "wx", mode: 384 });
|
|
7463
7327
|
await chmod(filePath, 384);
|
|
7464
|
-
files.push({ attachmentId: ref.attachment_id, name, mime: ref.mime, sizeBytes: ref.size_bytes, sha256, path:
|
|
7328
|
+
files.push({ attachmentId: ref.attachment_id, name, mime: ref.mime, sizeBytes: ref.size_bytes, sha256, path: path16.resolve(filePath) });
|
|
7465
7329
|
}
|
|
7466
7330
|
return { directory: state.directory, files, manifestMarkdown: buildManifest(files), cleanup: () => cleanupGeneratedDirectory(state) };
|
|
7467
7331
|
} catch (error) {
|
|
@@ -7525,9 +7389,9 @@ async function readSpool(spoolDir = SPOOL_DIR) {
|
|
|
7525
7389
|
}
|
|
7526
7390
|
return out;
|
|
7527
7391
|
}
|
|
7528
|
-
async function readCloudMap(
|
|
7392
|
+
async function readCloudMap(path22) {
|
|
7529
7393
|
try {
|
|
7530
|
-
return JSON.parse(await readFile2(
|
|
7394
|
+
return JSON.parse(await readFile2(path22, "utf8"));
|
|
7531
7395
|
} catch {
|
|
7532
7396
|
return {};
|
|
7533
7397
|
}
|
|
@@ -7817,6 +7681,10 @@ function makeLoopTicks({
|
|
|
7817
7681
|
applyRemoteConfig: () => false,
|
|
7818
7682
|
heartbeatFields: () => ({})
|
|
7819
7683
|
},
|
|
7684
|
+
// Host version awareness: reads `update_status` off the heartbeat ACK and logs
|
|
7685
|
+
// ONE line per drift change (daemon-update-status.mjs). No-op default keeps
|
|
7686
|
+
// old callers working; absent update_status reads as unknown, never current.
|
|
7687
|
+
updateStatusTracker = { applyHeartbeatResponse: () => false },
|
|
7820
7688
|
// Cached agent-availability provider (agent-availability.mjs); returns null
|
|
7821
7689
|
// until the first probe completes — the heartbeat simply omits the field.
|
|
7822
7690
|
getAgentAvailability = () => null,
|
|
@@ -7857,6 +7725,7 @@ function makeLoopTicks({
|
|
|
7857
7725
|
request.then((response) => {
|
|
7858
7726
|
capacityController.applyCapacity(response?.capacity, nextPayload.operatorId);
|
|
7859
7727
|
localModelController.applyRemoteConfig(response?.local_model, nextPayload.operatorId);
|
|
7728
|
+
updateStatusTracker.applyHeartbeatResponse(response);
|
|
7860
7729
|
}).catch((e) => log2(`heartbeat failed: ${e.message}`)).finally(() => {
|
|
7861
7730
|
for (const done of waiters) done();
|
|
7862
7731
|
if (state.pending) {
|
|
@@ -8046,7 +7915,7 @@ var init_runner_capacity = __esm({
|
|
|
8046
7915
|
});
|
|
8047
7916
|
|
|
8048
7917
|
// ../../scripts/virtual-office/code-runner/agent-auth-probe-process.mjs
|
|
8049
|
-
import { fileURLToPath as
|
|
7918
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
8050
7919
|
async function probeAgentInChild(agent, timeoutMs) {
|
|
8051
7920
|
const stdout = await runProcess2(process.execPath, [probeCli, agent], {
|
|
8052
7921
|
timeout: timeoutMs,
|
|
@@ -8059,7 +7928,7 @@ var init_agent_auth_probe_process = __esm({
|
|
|
8059
7928
|
"../../scripts/virtual-office/code-runner/agent-auth-probe-process.mjs"() {
|
|
8060
7929
|
"use strict";
|
|
8061
7930
|
init_process_runner2();
|
|
8062
|
-
probeCli =
|
|
7931
|
+
probeCli = fileURLToPath4(new URL("./agent-auth-probe-cli.mjs", import.meta.url));
|
|
8063
7932
|
}
|
|
8064
7933
|
});
|
|
8065
7934
|
|
|
@@ -8360,7 +8229,7 @@ var init_shared = __esm({
|
|
|
8360
8229
|
// ../../scripts/virtual-office/code-runner/account-usage/claude.mjs
|
|
8361
8230
|
import fs10 from "node:fs";
|
|
8362
8231
|
import os3 from "node:os";
|
|
8363
|
-
import
|
|
8232
|
+
import path17 from "node:path";
|
|
8364
8233
|
function fileCaptureTime(filePath, explicit, statFn) {
|
|
8365
8234
|
if (typeof explicit === "string" && explicit) return explicit;
|
|
8366
8235
|
try {
|
|
@@ -8374,7 +8243,7 @@ function usageBaseUrl(env2 = process.env) {
|
|
|
8374
8243
|
return String(raw).replace(/\/+$/, "");
|
|
8375
8244
|
}
|
|
8376
8245
|
function readOAuthToken({ homeDir = os3.homedir(), read = readJson, now = Date.now() } = {}) {
|
|
8377
|
-
const creds = read(
|
|
8246
|
+
const creds = read(path17.join(homeDir, ".claude", ".credentials.json"));
|
|
8378
8247
|
const oauth = creds && typeof creds === "object" ? creds.claudeAiOauth : null;
|
|
8379
8248
|
if (!oauth || typeof oauth !== "object") return null;
|
|
8380
8249
|
const token2 = typeof oauth.accessToken === "string" ? oauth.accessToken.trim() : "";
|
|
@@ -8384,7 +8253,7 @@ function readOAuthToken({ homeDir = os3.homedir(), read = readJson, now = Date.n
|
|
|
8384
8253
|
return token2;
|
|
8385
8254
|
}
|
|
8386
8255
|
function readAccountId({ homeDir = os3.homedir(), read = readJson } = {}) {
|
|
8387
|
-
const cfg = read(
|
|
8256
|
+
const cfg = read(path17.join(homeDir, ".claude.json"));
|
|
8388
8257
|
const account = cfg && typeof cfg === "object" ? cfg.oauthAccount : null;
|
|
8389
8258
|
return account && typeof account.accountUuid === "string" ? account.accountUuid : null;
|
|
8390
8259
|
}
|
|
@@ -8494,7 +8363,7 @@ function readClaudeFileUsage({
|
|
|
8494
8363
|
if (age === null || age > MAX_FILE_AGE_MS) return null;
|
|
8495
8364
|
return row;
|
|
8496
8365
|
};
|
|
8497
|
-
const statusPath =
|
|
8366
|
+
const statusPath = path17.join(homeDir, ".claude", "claude-usage.json");
|
|
8498
8367
|
const status = read(statusPath);
|
|
8499
8368
|
if (status && (status.seven_day || status.five_hour)) {
|
|
8500
8369
|
const row = fresh(makeUsageRow({
|
|
@@ -8509,7 +8378,7 @@ function readClaudeFileUsage({
|
|
|
8509
8378
|
}));
|
|
8510
8379
|
if (row) return row;
|
|
8511
8380
|
}
|
|
8512
|
-
const weeklyPath =
|
|
8381
|
+
const weeklyPath = path17.join(homeDir, ".claude", "claude-weekly-usage.json");
|
|
8513
8382
|
const weekly = read(weeklyPath);
|
|
8514
8383
|
if (weekly) {
|
|
8515
8384
|
const row = fresh(makeUsageRow({
|
|
@@ -9785,9 +9654,9 @@ function buildControlHandler({ getStatus, requestStop, allowedOrigin }) {
|
|
|
9785
9654
|
res.end();
|
|
9786
9655
|
return;
|
|
9787
9656
|
}
|
|
9788
|
-
const
|
|
9657
|
+
const path22 = String(req.url || "").split("?")[0];
|
|
9789
9658
|
res.setHeader("content-type", "application/json");
|
|
9790
|
-
if (req.method === "GET" &&
|
|
9659
|
+
if (req.method === "GET" && path22 === "/status") {
|
|
9791
9660
|
let status;
|
|
9792
9661
|
try {
|
|
9793
9662
|
status = getStatus();
|
|
@@ -9798,7 +9667,7 @@ function buildControlHandler({ getStatus, requestStop, allowedOrigin }) {
|
|
|
9798
9667
|
res.end(JSON.stringify({ ok: true, ...status }));
|
|
9799
9668
|
return;
|
|
9800
9669
|
}
|
|
9801
|
-
if (req.method === "POST" &&
|
|
9670
|
+
if (req.method === "POST" && path22 === "/stop") {
|
|
9802
9671
|
if (!isControlOriginAllowed(req.headers.origin, allowedOrigin) || !req.headers["x-vo-control"]) {
|
|
9803
9672
|
res.statusCode = 403;
|
|
9804
9673
|
res.end(JSON.stringify({ ok: false, error: "forbidden" }));
|
|
@@ -9859,7 +9728,7 @@ function startControlServer({ port, getStatus, requestStop, allowedOrigin, log:
|
|
|
9859
9728
|
return server;
|
|
9860
9729
|
}
|
|
9861
9730
|
function startDaemonControl({ cfg, runnerInstanceId, requestStop, getActiveCount, isRunning, startedAt, log: log2 = () => {
|
|
9862
|
-
}, onDuplicate = null }) {
|
|
9731
|
+
}, onDuplicate = null, getUpdateStatus = () => null }) {
|
|
9863
9732
|
if (!cfg.controlEnabled) return null;
|
|
9864
9733
|
return startControlServer({
|
|
9865
9734
|
port: cfg.controlPort,
|
|
@@ -9876,7 +9745,9 @@ function startDaemonControl({ cfg, runnerInstanceId, requestStop, getActiveCount
|
|
|
9876
9745
|
watchEnabled: cfg.watchEnabled,
|
|
9877
9746
|
activeTasks: getActiveCount(),
|
|
9878
9747
|
startedAt: new Date(startedAt).toISOString(),
|
|
9879
|
-
uptimeSec: Math.round((Date.now() - startedAt) / 1e3)
|
|
9748
|
+
uptimeSec: Math.round((Date.now() - startedAt) / 1e3),
|
|
9749
|
+
// Host version awareness — the app + `runner --status` read drift from here.
|
|
9750
|
+
updateStatus: getUpdateStatus()
|
|
9880
9751
|
}),
|
|
9881
9752
|
log: log2
|
|
9882
9753
|
});
|
|
@@ -9964,22 +9835,22 @@ var init_effort_mode_config = __esm({
|
|
|
9964
9835
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
9965
9836
|
import fs11 from "node:fs";
|
|
9966
9837
|
import os4 from "node:os";
|
|
9967
|
-
import
|
|
9968
|
-
import { fileURLToPath as
|
|
9838
|
+
import path18 from "node:path";
|
|
9839
|
+
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
9969
9840
|
function userCacheRoot() {
|
|
9970
9841
|
try {
|
|
9971
9842
|
const home = os4.homedir();
|
|
9972
|
-
if (home) return
|
|
9843
|
+
if (home) return path18.join(home, ".claude");
|
|
9973
9844
|
} catch {
|
|
9974
9845
|
}
|
|
9975
|
-
return
|
|
9846
|
+
return path18.join(os4.tmpdir(), `vo-model-registry-${randomUUID5()}`);
|
|
9976
9847
|
}
|
|
9977
9848
|
function resolveCacheBaseDir(env2 = process.env, moduleDir = __dirname) {
|
|
9978
9849
|
if (env2.VO_MODEL_REGISTRY_CACHE_DIR) return env2.VO_MODEL_REGISTRY_CACHE_DIR;
|
|
9979
9850
|
if (env2.VO_RUNNER_RUNTIME_ROOT) return env2.VO_RUNNER_RUNTIME_ROOT;
|
|
9980
|
-
const segments = moduleDir.split(
|
|
9851
|
+
const segments = moduleDir.split(path18.sep);
|
|
9981
9852
|
const isRepoCheckout = segments.at(-1) === "virtual-office" && segments.at(-2) === "scripts";
|
|
9982
|
-
return isRepoCheckout ?
|
|
9853
|
+
return isRepoCheckout ? path18.resolve(moduleDir, "..", "..") : userCacheRoot();
|
|
9983
9854
|
}
|
|
9984
9855
|
function uniqueModels(models = []) {
|
|
9985
9856
|
return [...new Set(models.map((model) => String(model || "").trim()).filter(Boolean))];
|
|
@@ -10102,7 +9973,7 @@ function readCache(cacheFile = DEFAULT_CACHE_FILE, nowMs = Date.now(), ttlMs = D
|
|
|
10102
9973
|
}
|
|
10103
9974
|
}
|
|
10104
9975
|
function writeCache(cacheFile = DEFAULT_CACHE_FILE, payload) {
|
|
10105
|
-
fs11.mkdirSync(
|
|
9976
|
+
fs11.mkdirSync(path18.dirname(cacheFile), { recursive: true });
|
|
10106
9977
|
fs11.writeFileSync(cacheFile, JSON.stringify(payload, null, 2));
|
|
10107
9978
|
}
|
|
10108
9979
|
async function fetchRegistryCatalog({
|
|
@@ -10160,13 +10031,13 @@ var __dirname, DEFAULT_CACHE_DIR, DEFAULT_CACHE_FILE, DEFAULT_TTL_MS3, ANTHROPIC
|
|
|
10160
10031
|
var init_model_registry = __esm({
|
|
10161
10032
|
"../../scripts/virtual-office/model-registry.mjs"() {
|
|
10162
10033
|
"use strict";
|
|
10163
|
-
__dirname =
|
|
10164
|
-
DEFAULT_CACHE_DIR =
|
|
10034
|
+
__dirname = path18.dirname(fileURLToPath5(import.meta.url));
|
|
10035
|
+
DEFAULT_CACHE_DIR = path18.join(
|
|
10165
10036
|
resolveCacheBaseDir(),
|
|
10166
10037
|
".virtual-office-cache",
|
|
10167
10038
|
"model-registry"
|
|
10168
10039
|
);
|
|
10169
|
-
DEFAULT_CACHE_FILE =
|
|
10040
|
+
DEFAULT_CACHE_FILE = path18.join(DEFAULT_CACHE_DIR, "catalog.json");
|
|
10170
10041
|
DEFAULT_TTL_MS3 = 60 * 60 * 1e3;
|
|
10171
10042
|
ANTHROPIC_API_VERSION = "2023-06-01";
|
|
10172
10043
|
FAMILY_DEFINITIONS = {
|
|
@@ -10800,9 +10671,9 @@ function operatorTierToRung(tier, difficulty, thresholds) {
|
|
|
10800
10671
|
if (tier === "best" && difficulty >= thresholds.rungBounds.R5) return "R5";
|
|
10801
10672
|
return base;
|
|
10802
10673
|
}
|
|
10803
|
-
function readCodexModelsCache({ path:
|
|
10674
|
+
function readCodexModelsCache({ path: path22 = DEFAULT_CODEX_MODELS_CACHE, read = readFileSync4 } = {}) {
|
|
10804
10675
|
try {
|
|
10805
|
-
const parsed = JSON.parse(read(
|
|
10676
|
+
const parsed = JSON.parse(read(path22, "utf8"));
|
|
10806
10677
|
return Array.isArray(parsed?.models) ? parsed : null;
|
|
10807
10678
|
} catch {
|
|
10808
10679
|
return null;
|
|
@@ -10985,14 +10856,14 @@ var init_role_cost_shadow = __esm({
|
|
|
10985
10856
|
import { readFileSync as readFileSync5, appendFileSync, mkdirSync as mkdirSync4 } from "node:fs";
|
|
10986
10857
|
import { homedir as homedir7 } from "node:os";
|
|
10987
10858
|
import { join as join9, dirname as dirname6 } from "node:path";
|
|
10988
|
-
import { fileURLToPath as
|
|
10859
|
+
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
10989
10860
|
function getAutoRouterMode(env2 = process.env) {
|
|
10990
10861
|
const raw = String(env2.VO_CODE_RUNNER_AUTO_ROUTER || "").trim().toLowerCase();
|
|
10991
10862
|
return MODES.has(raw) ? raw : "off";
|
|
10992
10863
|
}
|
|
10993
10864
|
function loadThresholds() {
|
|
10994
10865
|
if (!cachedThresholds) {
|
|
10995
|
-
const here = dirname6(
|
|
10866
|
+
const here = dirname6(fileURLToPath6(import.meta.url));
|
|
10996
10867
|
cachedThresholds = JSON.parse(readFileSync5(join9(here, "thresholds.json"), "utf8"));
|
|
10997
10868
|
}
|
|
10998
10869
|
return cachedThresholds;
|
|
@@ -11059,15 +10930,15 @@ function formatDecisionReason(decision, maxLen = 480) {
|
|
|
11059
10930
|
const s = `[${decision.routerVersion}] ${decision.taskClass} d=${decision.difficulty} c=${decision.confidence} \u2192 ${decision.rung}/${decision.tier}${decision.effort ? ` effort=${decision.effort}` : ""} turns=${decision.maxTurns} $${decision.maxBudgetUsd}${decision.flags.length ? ` [${decision.flags.join(",")}]` : ""} :: ${decision.reasons.join("; ")}`;
|
|
11060
10931
|
return s.length > maxLen ? `${s.slice(0, maxLen - 1)}\u2026` : s;
|
|
11061
10932
|
}
|
|
11062
|
-
function appendDecisionFallback(decision, { path:
|
|
10933
|
+
function appendDecisionFallback(decision, { path: path22 = DECISION_FALLBACK_PATH, append = appendFileSync, mkdir: mkdir4 = mkdirSync4, task, thresholds, roleCostInputs } = {}) {
|
|
11063
10934
|
try {
|
|
11064
|
-
mkdir4(dirname6(
|
|
11065
|
-
append(
|
|
10935
|
+
mkdir4(dirname6(path22), { recursive: true });
|
|
10936
|
+
append(path22, `${JSON.stringify(decision)}
|
|
11066
10937
|
`, "utf8");
|
|
11067
10938
|
if (isRouterDecision(decision)) {
|
|
11068
10939
|
try {
|
|
11069
10940
|
const records = buildShadowRecords({ decision, task, thresholds: thresholds || loadThresholds(), roleCostInputs });
|
|
11070
|
-
for (const record of records) append(
|
|
10941
|
+
for (const record of records) append(path22, `${JSON.stringify(record)}
|
|
11071
10942
|
`, "utf8");
|
|
11072
10943
|
} catch {
|
|
11073
10944
|
}
|
|
@@ -12060,7 +11931,7 @@ var init_inference_task_runner = __esm({
|
|
|
12060
11931
|
// ../../scripts/virtual-office/code-runner/isolation-audit.mjs
|
|
12061
11932
|
import fs12 from "node:fs";
|
|
12062
11933
|
import fsp11 from "node:fs/promises";
|
|
12063
|
-
import
|
|
11934
|
+
import path19 from "node:path";
|
|
12064
11935
|
async function defaultRun(command, args, cwd, options = {}) {
|
|
12065
11936
|
return runProcess2(command, args, { cwd, timeout: 6e4, ...options });
|
|
12066
11937
|
}
|
|
@@ -12073,7 +11944,7 @@ async function canonicalRootForWorktree(worktreeDir, run) {
|
|
|
12073
11944
|
"--path-format=absolute",
|
|
12074
11945
|
"--git-common-dir"
|
|
12075
11946
|
])).trim();
|
|
12076
|
-
const root =
|
|
11947
|
+
const root = path19.dirname(commonDir);
|
|
12077
11948
|
return samePath2(root, worktreeDir) ? null : root;
|
|
12078
11949
|
}
|
|
12079
11950
|
async function snapshot(root, run) {
|
|
@@ -12115,21 +11986,21 @@ async function changedPaths(root, run) {
|
|
|
12115
11986
|
}
|
|
12116
11987
|
async function quarantineCanonicalWrites({ baseline, worktreeDir, taskId, run, now }) {
|
|
12117
11988
|
const paths = await changedPaths(baseline.root, run);
|
|
12118
|
-
const quarantineDir =
|
|
12119
|
-
|
|
11989
|
+
const quarantineDir = path19.join(
|
|
11990
|
+
path19.dirname(worktreeDir),
|
|
12120
11991
|
".canonical-recovery",
|
|
12121
11992
|
`${String(taskId || "unknown").replace(/[^a-z0-9-]/gi, "-")}-${now().toISOString().replace(/[:.]/g, "-")}`
|
|
12122
11993
|
);
|
|
12123
11994
|
await fsp11.mkdir(quarantineDir, { recursive: true });
|
|
12124
11995
|
const patch = await git2(run, baseline.root, ["diff", "--binary", "HEAD"], { raw: true });
|
|
12125
|
-
await fsp11.writeFile(
|
|
11996
|
+
await fsp11.writeFile(path19.join(quarantineDir, "tracked.patch"), patch, "utf8");
|
|
12126
11997
|
for (const relative of paths.untracked) {
|
|
12127
|
-
const source =
|
|
12128
|
-
const target =
|
|
12129
|
-
await fsp11.mkdir(
|
|
11998
|
+
const source = path19.join(baseline.root, relative);
|
|
11999
|
+
const target = path19.join(quarantineDir, "untracked", relative);
|
|
12000
|
+
await fsp11.mkdir(path19.dirname(target), { recursive: true });
|
|
12130
12001
|
await fsp11.copyFile(source, target);
|
|
12131
12002
|
}
|
|
12132
|
-
await fsp11.writeFile(
|
|
12003
|
+
await fsp11.writeFile(path19.join(quarantineDir, "manifest.json"), `${JSON.stringify({
|
|
12133
12004
|
taskId,
|
|
12134
12005
|
canonicalRoot: baseline.root,
|
|
12135
12006
|
canonicalHead: baseline.head,
|
|
@@ -12151,8 +12022,8 @@ async function restoreExactCanonicalPaths(baseline, evidence, run) {
|
|
|
12151
12022
|
]);
|
|
12152
12023
|
}
|
|
12153
12024
|
for (const relative of evidence.untracked) {
|
|
12154
|
-
const target =
|
|
12155
|
-
const prefix = `${
|
|
12025
|
+
const target = path19.resolve(baseline.root, relative);
|
|
12026
|
+
const prefix = `${path19.resolve(baseline.root)}${path19.sep}`;
|
|
12156
12027
|
if (!target.startsWith(prefix) || !fs12.existsSync(target)) continue;
|
|
12157
12028
|
await fsp11.rm(target, { force: true });
|
|
12158
12029
|
}
|
|
@@ -12189,7 +12060,7 @@ var init_isolation_audit = __esm({
|
|
|
12189
12060
|
init_process_runner2();
|
|
12190
12061
|
splitZ2 = (value) => String(value || "").split("\0").map((item) => item.trim()).filter(Boolean);
|
|
12191
12062
|
samePath2 = (left, right) => {
|
|
12192
|
-
const [a, b] = [left, right].map((value) =>
|
|
12063
|
+
const [a, b] = [left, right].map((value) => path19.resolve(value));
|
|
12193
12064
|
return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
12194
12065
|
};
|
|
12195
12066
|
}
|
|
@@ -12549,7 +12420,7 @@ var init_publication_outcome = __esm({
|
|
|
12549
12420
|
|
|
12550
12421
|
// ../../scripts/virtual-office/code-runner/committed-scratch-cleanup.mjs
|
|
12551
12422
|
import fsp12 from "node:fs/promises";
|
|
12552
|
-
import
|
|
12423
|
+
import path20 from "node:path";
|
|
12553
12424
|
function defaultRun2(command, args, cwd, options = {}) {
|
|
12554
12425
|
return runProcess2(command, args, { cwd, ...options });
|
|
12555
12426
|
}
|
|
@@ -12557,13 +12428,13 @@ async function resolveSafeScratchTarget(worktreeDir, file) {
|
|
|
12557
12428
|
if (!isAgentScratch(file)) {
|
|
12558
12429
|
throw new Error(`refusing to remove non-scratch publication path: ${file}`);
|
|
12559
12430
|
}
|
|
12560
|
-
const root =
|
|
12561
|
-
const target =
|
|
12562
|
-
const relative =
|
|
12563
|
-
if (!relative || relative.startsWith(`..${
|
|
12431
|
+
const root = path20.resolve(worktreeDir);
|
|
12432
|
+
const target = path20.resolve(root, file);
|
|
12433
|
+
const relative = path20.relative(root, target);
|
|
12434
|
+
if (!relative || relative.startsWith(`..${path20.sep}`) || path20.isAbsolute(relative)) {
|
|
12564
12435
|
throw new Error(`refusing to remove publication scratch outside worktree: ${file}`);
|
|
12565
12436
|
}
|
|
12566
|
-
for (let cursor = target; cursor !== root; cursor =
|
|
12437
|
+
for (let cursor = target; cursor !== root; cursor = path20.dirname(cursor)) {
|
|
12567
12438
|
try {
|
|
12568
12439
|
if ((await fsp12.lstat(cursor)).isSymbolicLink()) {
|
|
12569
12440
|
throw new Error(`refusing to follow symlink while removing publication scratch: ${file}`);
|
|
@@ -12685,7 +12556,7 @@ var init_publication_scope = __esm({
|
|
|
12685
12556
|
// ../../scripts/virtual-office/code-runner/recovery-ledger.mjs
|
|
12686
12557
|
import fs13 from "node:fs";
|
|
12687
12558
|
import fsp13 from "node:fs/promises";
|
|
12688
|
-
import
|
|
12559
|
+
import path21 from "node:path";
|
|
12689
12560
|
function recoveryTaskId(prompt) {
|
|
12690
12561
|
const match = String(prompt || "").match(/VO_RECOVERY_FROM_CODE_TASK:\s*([0-9a-f-]{36})/i);
|
|
12691
12562
|
return match ? match[1].toLowerCase() : null;
|
|
@@ -12699,10 +12570,10 @@ function cloneLeaf(repo) {
|
|
|
12699
12570
|
function recoveryLedgerCandidates(repo, clonesRoot2) {
|
|
12700
12571
|
const leaf = cloneLeaf(repo);
|
|
12701
12572
|
if (!leaf || !clonesRoot2) return [];
|
|
12702
|
-
const canonical =
|
|
12573
|
+
const canonical = path21.join(clonesRoot2, leaf);
|
|
12703
12574
|
return [
|
|
12704
|
-
|
|
12705
|
-
|
|
12575
|
+
path21.join(clonesRoot2, ".agent-worktrees", leaf, "recovery-ledger.jsonl"),
|
|
12576
|
+
path21.join(canonical, ".agent-worktrees", "recovery-ledger.jsonl")
|
|
12706
12577
|
];
|
|
12707
12578
|
}
|
|
12708
12579
|
async function readLedger(file, readFile5) {
|
|
@@ -13438,10 +13309,10 @@ var init_task_worktree_preparation = __esm({
|
|
|
13438
13309
|
// ../../scripts/virtual-office/code-runner-daemon.mjs
|
|
13439
13310
|
var code_runner_daemon_exports = {};
|
|
13440
13311
|
__export(code_runner_daemon_exports, {
|
|
13441
|
-
main: () =>
|
|
13312
|
+
main: () => main
|
|
13442
13313
|
});
|
|
13443
13314
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
13444
|
-
import { fileURLToPath as
|
|
13315
|
+
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
13445
13316
|
function log(msg) {
|
|
13446
13317
|
console.log(`[code-runner ${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}`);
|
|
13447
13318
|
}
|
|
@@ -13663,7 +13534,7 @@ Closes #${publicationTarget.supersedesPrNumber}` : "";
|
|
|
13663
13534
|
}
|
|
13664
13535
|
}
|
|
13665
13536
|
}
|
|
13666
|
-
async function
|
|
13537
|
+
async function main({ env: env2 = process.env, once: once2 = false } = {}) {
|
|
13667
13538
|
const cfg = loadCodeRunnerConfig(env2, { log });
|
|
13668
13539
|
await sweepStaleTaskAttachmentDirectories().catch((error) => log(`stale attachment cleanup failed: ${error.message}`));
|
|
13669
13540
|
const runnerInstanceId = randomUUID7();
|
|
@@ -13809,7 +13680,7 @@ async function main2({ env: env2 = process.env, once: once2 = false } = {}) {
|
|
|
13809
13680
|
if (controlServer) controlServer.close();
|
|
13810
13681
|
log("stopped");
|
|
13811
13682
|
}
|
|
13812
|
-
var RATE_LIMIT_RESUME_ENABLED, sleep2, safeProgress,
|
|
13683
|
+
var RATE_LIMIT_RESUME_ENABLED, sleep2, safeProgress, invokedDirectly;
|
|
13813
13684
|
var init_code_runner_daemon = __esm({
|
|
13814
13685
|
"../../scripts/virtual-office/code-runner-daemon.mjs"() {
|
|
13815
13686
|
"use strict";
|
|
@@ -13859,11 +13730,11 @@ var init_code_runner_daemon = __esm({
|
|
|
13859
13730
|
RATE_LIMIT_RESUME_ENABLED = process.env.VO_RATE_LIMIT_RESUME !== "0";
|
|
13860
13731
|
sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
13861
13732
|
safeProgress = makeSafeProgress(log);
|
|
13862
|
-
|
|
13733
|
+
invokedDirectly = process.argv[1] && fileURLToPath7(import.meta.url) === process.argv[1] && // Bundle-safe: self-start only when THIS file is the real entry (not inlined into vo-mcp's runner-cli.js ⇒ double-claim).
|
|
13863
13734
|
import.meta.url.endsWith("code-runner-daemon.mjs");
|
|
13864
|
-
if (
|
|
13735
|
+
if (invokedDirectly) {
|
|
13865
13736
|
const once2 = process.argv.includes("--once");
|
|
13866
|
-
|
|
13737
|
+
main({ once: once2 }).catch((err) => {
|
|
13867
13738
|
console.error("[code-runner] fatal:", err);
|
|
13868
13739
|
process.exit(1);
|
|
13869
13740
|
});
|
|
@@ -14230,8 +14101,8 @@ var env = {
|
|
|
14230
14101
|
...pairedOperatorId ? { VO_CODE_RUNNER_OPERATOR_IDS: pairedOperatorId } : {}
|
|
14231
14102
|
};
|
|
14232
14103
|
var once = process.argv.includes("--once");
|
|
14233
|
-
var { main:
|
|
14234
|
-
|
|
14104
|
+
var { main: main2 } = await Promise.resolve().then(() => (init_code_runner_daemon(), code_runner_daemon_exports));
|
|
14105
|
+
main2({ env, once }).catch((err) => {
|
|
14235
14106
|
console.error("[vo-mcp runner] fatal:", err);
|
|
14236
14107
|
process.exit(1);
|
|
14237
14108
|
});
|