@algosuite/vo-mcp 0.2.0-beta.17 → 0.2.0-beta.18
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/cli.js +146 -7
- package/dist/cli.js.map +4 -4
- package/dist/index.js +141 -3
- package/dist/index.js.map +4 -4
- package/dist/runner-cli.js +335 -38
- package/dist/runner-cli.js.map +4 -4
- package/dist/runner-supervisor.js +20 -2
- package/dist/runner-supervisor.js.map +2 -2
- package/package.json +1 -1
package/dist/runner-cli.js
CHANGED
|
@@ -3187,6 +3187,65 @@ var init_orphan_agent_reaper = __esm({
|
|
|
3187
3187
|
}
|
|
3188
3188
|
});
|
|
3189
3189
|
|
|
3190
|
+
// ../../scripts/virtual-office/code-runner/cli-version-floor.mjs
|
|
3191
|
+
function parseCliVersion(output) {
|
|
3192
|
+
const match = /\b(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?\b/.exec(String(output ?? ""));
|
|
3193
|
+
return match ? `${match[1]}.${match[2]}.${match[3]}` : null;
|
|
3194
|
+
}
|
|
3195
|
+
function compareSemver(a, b) {
|
|
3196
|
+
const pa = a.split(".").map(Number);
|
|
3197
|
+
const pb = b.split(".").map(Number);
|
|
3198
|
+
for (let i = 0; i < 3; i += 1) {
|
|
3199
|
+
if (pa[i] !== pb[i]) return pa[i] < pb[i] ? -1 : 1;
|
|
3200
|
+
}
|
|
3201
|
+
return 0;
|
|
3202
|
+
}
|
|
3203
|
+
function checkCliVersionFloor(versionOutput, { floor = MIN_CLAUDE_CLI_VERSION } = {}) {
|
|
3204
|
+
const version = parseCliVersion(versionOutput);
|
|
3205
|
+
if (!version) {
|
|
3206
|
+
const seen = String(versionOutput ?? "").trim().slice(0, 120) || "<empty>";
|
|
3207
|
+
return {
|
|
3208
|
+
ok: false,
|
|
3209
|
+
version: null,
|
|
3210
|
+
floor,
|
|
3211
|
+
message: `could not parse a semver from \`claude --version\` output ("${seen}") \u2014 cannot prove the CLI meets the ${floor} security floor. ${SECURITY_RATIONALE}`
|
|
3212
|
+
};
|
|
3213
|
+
}
|
|
3214
|
+
if (compareSemver(version, floor) < 0) {
|
|
3215
|
+
return {
|
|
3216
|
+
ok: false,
|
|
3217
|
+
version,
|
|
3218
|
+
floor,
|
|
3219
|
+
message: `claude CLI ${version} is BELOW the minimum security floor ${floor}. ` + SECURITY_RATIONALE
|
|
3220
|
+
};
|
|
3221
|
+
}
|
|
3222
|
+
return {
|
|
3223
|
+
ok: true,
|
|
3224
|
+
version,
|
|
3225
|
+
floor,
|
|
3226
|
+
message: `claude CLI ${version} meets the minimum security floor ${floor}`
|
|
3227
|
+
};
|
|
3228
|
+
}
|
|
3229
|
+
function applyCliVersionFloor({ versionOutput, env: env2 = process.env, log: log3 = console.error } = {}) {
|
|
3230
|
+
const check = checkCliVersionFloor(versionOutput);
|
|
3231
|
+
if (check.ok) return { refused: false, check, message: check.message };
|
|
3232
|
+
const enforce = String(env2?.VO_CLI_FLOOR_ENFORCE ?? "") === "1";
|
|
3233
|
+
const message = `[cli-version-floor] ${enforce ? "REFUSING (VO_CLI_FLOOR_ENFORCE=1)" : "WARNING (warn-only)"}: ` + check.message;
|
|
3234
|
+
try {
|
|
3235
|
+
log3(message);
|
|
3236
|
+
} catch {
|
|
3237
|
+
}
|
|
3238
|
+
return { refused: enforce, check, message };
|
|
3239
|
+
}
|
|
3240
|
+
var MIN_CLAUDE_CLI_VERSION, SECURITY_RATIONALE;
|
|
3241
|
+
var init_cli_version_floor = __esm({
|
|
3242
|
+
"../../scripts/virtual-office/code-runner/cli-version-floor.mjs"() {
|
|
3243
|
+
"use strict";
|
|
3244
|
+
MIN_CLAUDE_CLI_VERSION = "2.1.216";
|
|
3245
|
+
SECURITY_RATIONALE = "Claude Code 2.1.211/2.1.213 fixed a PreToolUse-hook bypass on unsandboxed Bash (our destructive-fs/git/cloud tripwires DO NOT FIRE on older CLIs) and worktree-subagents mutating the main checkout. Update: npm install -g @anthropic-ai/claude-code (or the native installer).";
|
|
3246
|
+
}
|
|
3247
|
+
});
|
|
3248
|
+
|
|
3190
3249
|
// ../../scripts/virtual-office/code-runner/claude-runner.mjs
|
|
3191
3250
|
import { spawn as spawn2 } from "node:child_process";
|
|
3192
3251
|
function extractText(content) {
|
|
@@ -3409,6 +3468,7 @@ var init_claude_runner = __esm({
|
|
|
3409
3468
|
init_windows_claude_launch();
|
|
3410
3469
|
init_terminal_process_cleanup();
|
|
3411
3470
|
init_orphan_agent_reaper();
|
|
3471
|
+
init_cli_version_floor();
|
|
3412
3472
|
ClaudeRunner = class {
|
|
3413
3473
|
get binary() {
|
|
3414
3474
|
return "claude";
|
|
@@ -3445,7 +3505,7 @@ var init_claude_runner = __esm({
|
|
|
3445
3505
|
*/
|
|
3446
3506
|
async checkAuth() {
|
|
3447
3507
|
try {
|
|
3448
|
-
const probe = spawnClaudeSync(["--version"], { timeout: 3e3,
|
|
3508
|
+
const probe = spawnClaudeSync(["--version"], { timeout: 3e3, encoding: "utf8" });
|
|
3449
3509
|
if (probe.error) {
|
|
3450
3510
|
return {
|
|
3451
3511
|
installed: false,
|
|
@@ -3456,6 +3516,8 @@ var init_claude_runner = __esm({
|
|
|
3456
3516
|
if (probe.status !== 0) {
|
|
3457
3517
|
return { installed: true, authenticated: false, message: "claude binary exists but --version failed (auth unclear)" };
|
|
3458
3518
|
}
|
|
3519
|
+
const floorGate = applyCliVersionFloor({ versionOutput: probe.stdout, env: process.env });
|
|
3520
|
+
if (floorGate.refused) return { installed: true, authenticated: false, message: floorGate.message };
|
|
3459
3521
|
const loggedIn = probeClaudeLoginState();
|
|
3460
3522
|
if (loggedIn === false) {
|
|
3461
3523
|
return {
|
|
@@ -4932,6 +4994,84 @@ var init_resume_branch = __esm({
|
|
|
4932
4994
|
}
|
|
4933
4995
|
});
|
|
4934
4996
|
|
|
4997
|
+
// ../../scripts/virtual-office/code-runner/skill-catalog.mjs
|
|
4998
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync3, statSync } from "node:fs";
|
|
4999
|
+
import { dirname as dirname3, join as join3 } from "node:path";
|
|
5000
|
+
import { fileURLToPath } from "node:url";
|
|
5001
|
+
function parseFrontmatterNameDescription(raw) {
|
|
5002
|
+
const text = String(raw).replace(/\r\n/g, "\n");
|
|
5003
|
+
if (!text.startsWith("---\n")) return null;
|
|
5004
|
+
const end = text.indexOf("\n---\n", 4);
|
|
5005
|
+
if (end === -1) return null;
|
|
5006
|
+
let name = "";
|
|
5007
|
+
let description = "";
|
|
5008
|
+
for (const line of text.slice(4, end).split("\n")) {
|
|
5009
|
+
const idx = line.indexOf(":");
|
|
5010
|
+
if (idx === -1) continue;
|
|
5011
|
+
const key = line.slice(0, idx).trim();
|
|
5012
|
+
const value = line.slice(idx + 1).trim();
|
|
5013
|
+
if (key === "name") name = value;
|
|
5014
|
+
else if (key === "description") description = value;
|
|
5015
|
+
}
|
|
5016
|
+
return name && description ? { name, description } : null;
|
|
5017
|
+
}
|
|
5018
|
+
function resolveDefaultRepoRoot() {
|
|
5019
|
+
const starts = [dirname3(fileURLToPath(import.meta.url)), process.cwd()];
|
|
5020
|
+
for (const start of starts) {
|
|
5021
|
+
let dir = start;
|
|
5022
|
+
for (let i = 0; i < 8; i += 1) {
|
|
5023
|
+
try {
|
|
5024
|
+
if (statSync(join3(dir, ".claude", "skills")).isDirectory()) return dir;
|
|
5025
|
+
} catch {
|
|
5026
|
+
}
|
|
5027
|
+
const parent = dirname3(dir);
|
|
5028
|
+
if (parent === dir) break;
|
|
5029
|
+
dir = parent;
|
|
5030
|
+
}
|
|
5031
|
+
}
|
|
5032
|
+
return process.cwd();
|
|
5033
|
+
}
|
|
5034
|
+
function loadSkillCatalog({ repoRoot: repoRoot2 = resolveDefaultRepoRoot() } = {}) {
|
|
5035
|
+
try {
|
|
5036
|
+
const skillsDir = join3(repoRoot2, ".claude", "skills");
|
|
5037
|
+
const catalog = [];
|
|
5038
|
+
for (const entry of readdirSync2(skillsDir)) {
|
|
5039
|
+
const dir = join3(skillsDir, entry);
|
|
5040
|
+
try {
|
|
5041
|
+
if (!statSync(dir).isDirectory()) continue;
|
|
5042
|
+
const parsed = parseFrontmatterNameDescription(
|
|
5043
|
+
readFileSync3(join3(dir, "SKILL.md"), "utf8")
|
|
5044
|
+
);
|
|
5045
|
+
if (parsed) catalog.push(parsed);
|
|
5046
|
+
} catch {
|
|
5047
|
+
}
|
|
5048
|
+
}
|
|
5049
|
+
return catalog.sort((a, b) => a.name.localeCompare(b.name)).slice(0, CATALOG_CAP);
|
|
5050
|
+
} catch {
|
|
5051
|
+
return [];
|
|
5052
|
+
}
|
|
5053
|
+
}
|
|
5054
|
+
function buildSkillCatalogBlock(catalog) {
|
|
5055
|
+
if (!Array.isArray(catalog) || catalog.length === 0) return "";
|
|
5056
|
+
const lines = catalog.map((s) => ` - ${s.name}: ${s.description}`);
|
|
5057
|
+
return [
|
|
5058
|
+
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 ALGOSUITE SKILL CATALOG \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",
|
|
5059
|
+
"The repo ships a skill corpus (same one Claude Code loads natively). When a",
|
|
5060
|
+
"task matches a skill below, LOAD ITS FULL INSTRUCTIONS FIRST and follow them:",
|
|
5061
|
+
" - via MCP: call vo_skill_get with the skill name (any vendor with AlgoHQ MCP tools), or",
|
|
5062
|
+
" - via file: read .claude/skills/<name>/SKILL.md in this worktree.",
|
|
5063
|
+
lines.join("\n"),
|
|
5064
|
+
""
|
|
5065
|
+
].join("\n");
|
|
5066
|
+
}
|
|
5067
|
+
var CATALOG_CAP;
|
|
5068
|
+
var init_skill_catalog = __esm({
|
|
5069
|
+
"../../scripts/virtual-office/code-runner/skill-catalog.mjs"() {
|
|
5070
|
+
"use strict";
|
|
5071
|
+
CATALOG_CAP = 60;
|
|
5072
|
+
}
|
|
5073
|
+
});
|
|
5074
|
+
|
|
4935
5075
|
// ../../scripts/virtual-office/code-runner/dispatch-onboarding.mjs
|
|
4936
5076
|
function buildDispatchOnboarding({ repo = "Algosuite-ai/Nexus" } = {}) {
|
|
4937
5077
|
const reads = MANDATORY_READS.map((r, i) => ` ${i + 1}. ${r}`).join("\n");
|
|
@@ -4976,9 +5116,13 @@ function buildKnowledgeContextBlock(contextMarkdown) {
|
|
|
4976
5116
|
}
|
|
4977
5117
|
function composeDispatchPrompt(taskPrompt, opts = {}) {
|
|
4978
5118
|
const knowledge = buildKnowledgeContextBlock(opts.knowledgeContextMarkdown);
|
|
5119
|
+
const catalog = opts.includeSkillCatalog === false ? "" : buildSkillCatalogBlock(
|
|
5120
|
+
opts.skillCatalog ?? loadSkillCatalog({ repoRoot: opts.repoRoot })
|
|
5121
|
+
);
|
|
4979
5122
|
const task = String(taskPrompt ?? "").trim();
|
|
4980
5123
|
return [
|
|
4981
5124
|
buildDispatchOnboarding(opts),
|
|
5125
|
+
catalog,
|
|
4982
5126
|
knowledge,
|
|
4983
5127
|
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 YOUR TASK \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",
|
|
4984
5128
|
task,
|
|
@@ -4989,6 +5133,7 @@ var MANDATORY_READS, NON_NEGOTIABLES;
|
|
|
4989
5133
|
var init_dispatch_onboarding = __esm({
|
|
4990
5134
|
"../../scripts/virtual-office/code-runner/dispatch-onboarding.mjs"() {
|
|
4991
5135
|
"use strict";
|
|
5136
|
+
init_skill_catalog();
|
|
4992
5137
|
MANDATORY_READS = [
|
|
4993
5138
|
"CLAUDE.md (repo root \u2014 Claude-specific rules; auto-loaded, but READ it)",
|
|
4994
5139
|
'AGENTS.md (repo root \u2014 cross-vendor rules + "Onboarding for a lane"; NOT auto-loaded)',
|
|
@@ -5252,7 +5397,7 @@ var init_task_attachments = __esm({
|
|
|
5252
5397
|
|
|
5253
5398
|
// ../../scripts/virtual-office/code-runner/session-spool-forwarder.mjs
|
|
5254
5399
|
import { homedir as homedir3 } from "node:os";
|
|
5255
|
-
import { join as
|
|
5400
|
+
import { join as join4 } from "node:path";
|
|
5256
5401
|
import { readdir as readdir2, readFile as readFile2, unlink, writeFile as writeFile2 } from "node:fs/promises";
|
|
5257
5402
|
import { createHash as createHash4 } from "node:crypto";
|
|
5258
5403
|
function deriveUuid(seed) {
|
|
@@ -5284,9 +5429,9 @@ async function readSpool(spoolDir = SPOOL_DIR) {
|
|
|
5284
5429
|
for (const f of files) {
|
|
5285
5430
|
if (!f.endsWith(".json")) continue;
|
|
5286
5431
|
try {
|
|
5287
|
-
const record = JSON.parse(await readFile2(
|
|
5432
|
+
const record = JSON.parse(await readFile2(join4(spoolDir, f), "utf8"));
|
|
5288
5433
|
if (record && typeof record.session_key === "string") {
|
|
5289
|
-
out.push({ full:
|
|
5434
|
+
out.push({ full: join4(spoolDir, f), record });
|
|
5290
5435
|
}
|
|
5291
5436
|
} catch {
|
|
5292
5437
|
}
|
|
@@ -5368,8 +5513,8 @@ var SPOOL_DIR, CLOUD_MAP_FILE, STALE_MS, ACTIVE_SILENCE_MS;
|
|
|
5368
5513
|
var init_session_spool_forwarder = __esm({
|
|
5369
5514
|
"../../scripts/virtual-office/code-runner/session-spool-forwarder.mjs"() {
|
|
5370
5515
|
"use strict";
|
|
5371
|
-
SPOOL_DIR =
|
|
5372
|
-
CLOUD_MAP_FILE =
|
|
5516
|
+
SPOOL_DIR = join4(homedir3(), ".vo", "session-spool");
|
|
5517
|
+
CLOUD_MAP_FILE = join4(homedir3(), ".vo", "session-cloud-map.json");
|
|
5373
5518
|
STALE_MS = 60 * 60 * 1e3;
|
|
5374
5519
|
ACTIVE_SILENCE_MS = 10 * 60 * 1e3;
|
|
5375
5520
|
}
|
|
@@ -5438,14 +5583,14 @@ var init_rate_limit_resume_scheduler_core = __esm({
|
|
|
5438
5583
|
});
|
|
5439
5584
|
|
|
5440
5585
|
// ../../scripts/virtual-office/code-runner/rate-limit-resume-scheduler.mjs
|
|
5441
|
-
import { readFileSync as
|
|
5442
|
-
import { dirname as
|
|
5586
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync as mkdirSync4 } from "node:fs";
|
|
5587
|
+
import { dirname as dirname4, join as join5, resolve } from "node:path";
|
|
5443
5588
|
function log(msg) {
|
|
5444
5589
|
console.log(`[rate-limit-scheduler ${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}`);
|
|
5445
5590
|
}
|
|
5446
5591
|
function readQueue(queuePath) {
|
|
5447
5592
|
if (!existsSync5(queuePath)) return [];
|
|
5448
|
-
const content =
|
|
5593
|
+
const content = readFileSync4(queuePath, "utf-8");
|
|
5449
5594
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
5450
5595
|
const entries = [];
|
|
5451
5596
|
for (const line of lines) {
|
|
@@ -5458,18 +5603,18 @@ function readQueue(queuePath) {
|
|
|
5458
5603
|
return entries;
|
|
5459
5604
|
}
|
|
5460
5605
|
function writeQueue(queuePath, entries) {
|
|
5461
|
-
mkdirSync4(
|
|
5606
|
+
mkdirSync4(dirname4(queuePath), { recursive: true });
|
|
5462
5607
|
const lines = entries.map((e) => JSON.stringify(e)).join("\n");
|
|
5463
5608
|
writeFileSync3(queuePath, lines + (entries.length > 0 ? "\n" : ""), "utf-8");
|
|
5464
5609
|
}
|
|
5465
5610
|
function attemptsStorePath() {
|
|
5466
|
-
return
|
|
5611
|
+
return join5(dirname4(resumeQueuePath()), "resume-attempts.json");
|
|
5467
5612
|
}
|
|
5468
5613
|
function readAttemptsStore() {
|
|
5469
5614
|
const p = attemptsStorePath();
|
|
5470
5615
|
if (!existsSync5(p)) return {};
|
|
5471
5616
|
try {
|
|
5472
|
-
const parsed = JSON.parse(
|
|
5617
|
+
const parsed = JSON.parse(readFileSync4(p, "utf-8"));
|
|
5473
5618
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
5474
5619
|
} catch {
|
|
5475
5620
|
return {};
|
|
@@ -5477,7 +5622,7 @@ function readAttemptsStore() {
|
|
|
5477
5622
|
}
|
|
5478
5623
|
function writeAttemptsStore(store) {
|
|
5479
5624
|
const p = attemptsStorePath();
|
|
5480
|
-
mkdirSync4(
|
|
5625
|
+
mkdirSync4(dirname4(p), { recursive: true });
|
|
5481
5626
|
writeFileSync3(p, JSON.stringify(store, null, 2), "utf-8");
|
|
5482
5627
|
}
|
|
5483
5628
|
function countsFromStore(store) {
|
|
@@ -6203,7 +6348,7 @@ var init_superseded_pr_source = __esm({
|
|
|
6203
6348
|
|
|
6204
6349
|
// ../../scripts/virtual-office/code-runner/pr-watcher.mjs
|
|
6205
6350
|
import { homedir as homedir4 } from "node:os";
|
|
6206
|
-
import { join as
|
|
6351
|
+
import { join as join6 } from "node:path";
|
|
6207
6352
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir2 } from "node:fs/promises";
|
|
6208
6353
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
6209
6354
|
function ghViewPr(prNumber, repo) {
|
|
@@ -6298,7 +6443,7 @@ async function readState(stateFile) {
|
|
|
6298
6443
|
}
|
|
6299
6444
|
async function writeState(stateFile, state) {
|
|
6300
6445
|
try {
|
|
6301
|
-
await mkdir2(
|
|
6446
|
+
await mkdir2(join6(stateFile, ".."), { recursive: true });
|
|
6302
6447
|
await writeFile3(stateFile, JSON.stringify(state, null, 2), "utf8");
|
|
6303
6448
|
} catch {
|
|
6304
6449
|
}
|
|
@@ -6503,7 +6648,7 @@ var init_pr_watcher = __esm({
|
|
|
6503
6648
|
init_pr_watcher_failure_confirmation();
|
|
6504
6649
|
init_superseded_pr_source();
|
|
6505
6650
|
init_superseded_pr_source();
|
|
6506
|
-
DEFAULT_STATE_FILE =
|
|
6651
|
+
DEFAULT_STATE_FILE = join6(homedir4(), ".vo", "dispatched-prs.json");
|
|
6507
6652
|
FAIL_CONCLUSIONS = /* @__PURE__ */ new Set([
|
|
6508
6653
|
"FAILURE",
|
|
6509
6654
|
"TIMED_OUT",
|
|
@@ -6743,44 +6888,45 @@ ${effortConfig.multiAgentInstruction}
|
|
|
6743
6888
|
parts.push(String(basePrompt || "").trim());
|
|
6744
6889
|
return parts.join("\n");
|
|
6745
6890
|
}
|
|
6746
|
-
var EFFORT_MODE_CONFIG, DEFAULT_MODE;
|
|
6891
|
+
var RED_TEAM_DIRECTIVE, EFFORT_MODE_CONFIG, DEFAULT_MODE;
|
|
6747
6892
|
var init_effort_mode_config = __esm({
|
|
6748
6893
|
"../../scripts/virtual-office/code-runner/effort-mode-config.mjs"() {
|
|
6749
6894
|
"use strict";
|
|
6895
|
+
RED_TEAM_DIRECTIVE = "Before declaring done, red-team your own work: name the top ways it could be wrong \u2014 especially code that is correct but silently not wired into production callers \u2014 give the failure scenario for each, and state the evidence that rules it out.";
|
|
6750
6896
|
EFFORT_MODE_CONFIG = {
|
|
6751
6897
|
fast: {
|
|
6752
6898
|
tier: "cheap",
|
|
6753
6899
|
permissionMode: "acceptEdits",
|
|
6754
6900
|
maxTurns: 80,
|
|
6755
|
-
thinkingDirective:
|
|
6901
|
+
thinkingDirective: RED_TEAM_DIRECTIVE,
|
|
6756
6902
|
multiAgentInstruction: ""
|
|
6757
6903
|
},
|
|
6758
6904
|
standard: {
|
|
6759
6905
|
tier: "mid",
|
|
6760
6906
|
permissionMode: "acceptEdits",
|
|
6761
6907
|
maxTurns: 200,
|
|
6762
|
-
thinkingDirective:
|
|
6908
|
+
thinkingDirective: RED_TEAM_DIRECTIVE,
|
|
6763
6909
|
multiAgentInstruction: ""
|
|
6764
6910
|
},
|
|
6765
6911
|
deep: {
|
|
6766
6912
|
tier: "best",
|
|
6767
6913
|
permissionMode: "acceptEdits",
|
|
6768
6914
|
maxTurns: 300,
|
|
6769
|
-
thinkingDirective:
|
|
6915
|
+
thinkingDirective: `Think step-by-step. Verify assumptions against source code. Check edge cases. ${RED_TEAM_DIRECTIVE}`,
|
|
6770
6916
|
multiAgentInstruction: ""
|
|
6771
6917
|
},
|
|
6772
6918
|
ultra: {
|
|
6773
6919
|
tier: "best",
|
|
6774
6920
|
permissionMode: "acceptEdits",
|
|
6775
6921
|
maxTurns: 500,
|
|
6776
|
-
thinkingDirective:
|
|
6922
|
+
thinkingDirective: `Think step-by-step. Exhaustively verify every assumption against source code and documentation. ${RED_TEAM_DIRECTIVE}`,
|
|
6777
6923
|
multiAgentInstruction: "If this task needs multiple phases (research, build, verify), propose a plan first."
|
|
6778
6924
|
},
|
|
6779
6925
|
ultracode: {
|
|
6780
6926
|
tier: "best",
|
|
6781
6927
|
permissionMode: "acceptEdits",
|
|
6782
6928
|
maxTurns: 800,
|
|
6783
|
-
thinkingDirective:
|
|
6929
|
+
thinkingDirective: `Think step-by-step. Exhaustively verify every assumption against source code and documentation. Build worked examples to validate correctness. ${RED_TEAM_DIRECTIVE}`,
|
|
6784
6930
|
multiAgentInstruction: "Decompose this work into parallel research, build, and verification streams; use workflow orchestration where it helps."
|
|
6785
6931
|
}
|
|
6786
6932
|
};
|
|
@@ -6791,7 +6937,7 @@ var init_effort_mode_config = __esm({
|
|
|
6791
6937
|
// ../../scripts/virtual-office/model-registry.mjs
|
|
6792
6938
|
import fs7 from "node:fs";
|
|
6793
6939
|
import path15 from "node:path";
|
|
6794
|
-
import { fileURLToPath } from "node:url";
|
|
6940
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
6795
6941
|
function uniqueModels(models = []) {
|
|
6796
6942
|
return [...new Set(models.map((model) => String(model || "").trim()).filter(Boolean))];
|
|
6797
6943
|
}
|
|
@@ -6971,7 +7117,7 @@ var __dirname, ROOT, DEFAULT_CACHE_DIR, DEFAULT_CACHE_FILE, DEFAULT_TTL_MS3, ANT
|
|
|
6971
7117
|
var init_model_registry = __esm({
|
|
6972
7118
|
"../../scripts/virtual-office/model-registry.mjs"() {
|
|
6973
7119
|
"use strict";
|
|
6974
|
-
__dirname = path15.dirname(
|
|
7120
|
+
__dirname = path15.dirname(fileURLToPath2(import.meta.url));
|
|
6975
7121
|
ROOT = path15.resolve(__dirname, "..", "..");
|
|
6976
7122
|
DEFAULT_CACHE_DIR = path15.join(ROOT, ".virtual-office-cache", "model-registry");
|
|
6977
7123
|
DEFAULT_CACHE_FILE = path15.join(DEFAULT_CACHE_DIR, "catalog.json");
|
|
@@ -7551,9 +7697,9 @@ var init_classify_task = __esm({
|
|
|
7551
7697
|
});
|
|
7552
7698
|
|
|
7553
7699
|
// ../../scripts/virtual-office/code-runner/auto-router/effort-policy.mjs
|
|
7554
|
-
import { readFileSync as
|
|
7700
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
7555
7701
|
import { homedir as homedir5 } from "node:os";
|
|
7556
|
-
import { join as
|
|
7702
|
+
import { join as join7 } from "node:path";
|
|
7557
7703
|
function difficultyToRung(difficulty, thresholds) {
|
|
7558
7704
|
const b = thresholds.rungBounds;
|
|
7559
7705
|
if (difficulty >= b.R5) return "R5";
|
|
@@ -7578,7 +7724,7 @@ function operatorTierToRung(tier, difficulty, thresholds) {
|
|
|
7578
7724
|
if (tier === "best" && difficulty >= thresholds.rungBounds.R5) return "R5";
|
|
7579
7725
|
return base;
|
|
7580
7726
|
}
|
|
7581
|
-
function readCodexModelsCache({ path: path18 = DEFAULT_CODEX_MODELS_CACHE, read =
|
|
7727
|
+
function readCodexModelsCache({ path: path18 = DEFAULT_CODEX_MODELS_CACHE, read = readFileSync5 } = {}) {
|
|
7582
7728
|
try {
|
|
7583
7729
|
const parsed = JSON.parse(read(path18, "utf8"));
|
|
7584
7730
|
return Array.isArray(parsed?.models) ? parsed : null;
|
|
@@ -7630,23 +7776,148 @@ var init_effort_policy = __esm({
|
|
|
7630
7776
|
init_meta_model_catalog();
|
|
7631
7777
|
RUNG_ORDER = ["R1", "R2", "R3", "R4", "R5"];
|
|
7632
7778
|
rungIndex = (rung) => RUNG_ORDER.indexOf(rung);
|
|
7633
|
-
DEFAULT_CODEX_MODELS_CACHE =
|
|
7779
|
+
DEFAULT_CODEX_MODELS_CACHE = join7(homedir5(), ".codex", "models_cache.json");
|
|
7780
|
+
}
|
|
7781
|
+
});
|
|
7782
|
+
|
|
7783
|
+
// ../../scripts/virtual-office/code-runner/auto-router/role-cost-shadow.mjs
|
|
7784
|
+
function attributeRoleCosts({ plannerTokens, workerTokens, plannerModelRate, workerModelRate } = {}) {
|
|
7785
|
+
const inputs = { plannerTokens, workerTokens, plannerModelRate, workerModelRate };
|
|
7786
|
+
for (const [name, value] of Object.entries(inputs)) {
|
|
7787
|
+
if (!isNonNegativeFinite(value)) {
|
|
7788
|
+
return {
|
|
7789
|
+
valid: false,
|
|
7790
|
+
reason: `invalid ${name} (${String(value)}) \u2014 fail-open, no attribution`,
|
|
7791
|
+
...EMPTY_ATTRIBUTION
|
|
7792
|
+
};
|
|
7793
|
+
}
|
|
7794
|
+
}
|
|
7795
|
+
const plannerCostUsd = plannerTokens * plannerModelRate;
|
|
7796
|
+
const workerCostUsd = workerTokens * workerModelRate;
|
|
7797
|
+
const totalCostUsd = plannerCostUsd + workerCostUsd;
|
|
7798
|
+
const totalTokens = plannerTokens + workerTokens;
|
|
7799
|
+
const plannerCostShare = totalCostUsd > 0 ? plannerCostUsd / totalCostUsd : null;
|
|
7800
|
+
const workerCostShare = totalCostUsd > 0 ? workerCostUsd / totalCostUsd : null;
|
|
7801
|
+
const plannerTokenShare = totalTokens > 0 ? plannerTokens / totalTokens : null;
|
|
7802
|
+
const workerTokenShare = totalTokens > 0 ? workerTokens / totalTokens : null;
|
|
7803
|
+
const plannerCostShareRatio = plannerCostShare !== null && plannerTokenShare !== null && plannerTokenShare > 0 ? plannerCostShare / plannerTokenShare : null;
|
|
7804
|
+
return {
|
|
7805
|
+
valid: true,
|
|
7806
|
+
plannerCostUsd,
|
|
7807
|
+
workerCostUsd,
|
|
7808
|
+
totalCostUsd,
|
|
7809
|
+
plannerCostShare,
|
|
7810
|
+
workerCostShare,
|
|
7811
|
+
plannerTokenShare,
|
|
7812
|
+
workerTokenShare,
|
|
7813
|
+
plannerCostShareRatio
|
|
7814
|
+
};
|
|
7815
|
+
}
|
|
7816
|
+
function shadowFanOutGate({ taskClass, disagreementSignal, confidence, panelSize } = {}, { thresholds } = {}) {
|
|
7817
|
+
const cfg = { ...DEFAULT_SHADOW_FAN_OUT, ...thresholds?.shadowFanOut ?? {} };
|
|
7818
|
+
const defaultsUsed = !thresholds?.shadowFanOut;
|
|
7819
|
+
const no = (reason) => ({ wouldFanOut: false, reason, criterion: SHADOW_CRITERION, defaultsUsed });
|
|
7820
|
+
if (!isUnitInterval(disagreementSignal)) {
|
|
7821
|
+
return no(`invalid disagreementSignal (${String(disagreementSignal)}) \u2014 fail-open, single-model`);
|
|
7822
|
+
}
|
|
7823
|
+
if (!isUnitInterval(confidence)) {
|
|
7824
|
+
return no(`invalid confidence (${String(confidence)}) \u2014 fail-open, single-model`);
|
|
7825
|
+
}
|
|
7826
|
+
const size = panelSize === void 0 || panelSize === null ? cfg.defaultPanelSize : panelSize;
|
|
7827
|
+
if (!Number.isInteger(size) || size < 1) {
|
|
7828
|
+
return no(`invalid panelSize (${String(panelSize)}) \u2014 fail-open, single-model`);
|
|
7829
|
+
}
|
|
7830
|
+
const never = Array.isArray(cfg.neverFanOutClasses) ? cfg.neverFanOutClasses : [];
|
|
7831
|
+
if (typeof taskClass === "string" && never.includes(taskClass)) {
|
|
7832
|
+
return no(`class=${taskClass} in neverFanOutClasses \u2014 fan-out never pays on low-stakes classes`);
|
|
7833
|
+
}
|
|
7834
|
+
if (size < cfg.minPanelSize) {
|
|
7835
|
+
return no(`panelSize ${size} < ${cfg.minPanelSize} \u2014 too small to contribute independent signal`);
|
|
7836
|
+
}
|
|
7837
|
+
if (disagreementSignal < cfg.minDisagreementSignal) {
|
|
7838
|
+
return no(`disagreement ${disagreementSignal} < ${cfg.minDisagreementSignal} \u2014 extra models would confirm, not inform`);
|
|
7839
|
+
}
|
|
7840
|
+
if (confidence > cfg.maxSingleModelConfidence) {
|
|
7841
|
+
return no(`confidence ${confidence} > ${cfg.maxSingleModelConfidence} \u2014 single model already confident; fan-out adds cost, not signal`);
|
|
7842
|
+
}
|
|
7843
|
+
return {
|
|
7844
|
+
wouldFanOut: true,
|
|
7845
|
+
reason: `disagreement ${disagreementSignal} \u2265 ${cfg.minDisagreementSignal} AND confidence ${confidence} \u2264 ${cfg.maxSingleModelConfidence} (panel ${size})`,
|
|
7846
|
+
criterion: SHADOW_CRITERION,
|
|
7847
|
+
defaultsUsed
|
|
7848
|
+
};
|
|
7849
|
+
}
|
|
7850
|
+
function buildShadowRecords({ decision, task = {}, thresholds, roleCostInputs = null } = {}) {
|
|
7851
|
+
if (!decision || typeof decision !== "object") return [];
|
|
7852
|
+
const base = {
|
|
7853
|
+
shadow: true,
|
|
7854
|
+
routerVersion: decision.routerVersion ?? null,
|
|
7855
|
+
ts: decision.ts ?? null,
|
|
7856
|
+
taskId: task?.id ?? null
|
|
7857
|
+
};
|
|
7858
|
+
const roleCost = roleCostInputs ? attributeRoleCosts(roleCostInputs) : { valid: false, reason: "planner/worker token telemetry unavailable at routing time", ...EMPTY_ATTRIBUTION };
|
|
7859
|
+
const hasTaskSignal = typeof task?.disagreement_signal === "number";
|
|
7860
|
+
const disagreementSignal = hasTaskSignal ? task.disagreement_signal : typeof decision.difficulty === "number" ? decision.difficulty / 100 : void 0;
|
|
7861
|
+
const gate = shadowFanOutGate(
|
|
7862
|
+
{
|
|
7863
|
+
taskClass: decision.taskClass,
|
|
7864
|
+
disagreementSignal,
|
|
7865
|
+
confidence: decision.confidence,
|
|
7866
|
+
panelSize: task?.panel_size
|
|
7867
|
+
},
|
|
7868
|
+
{ thresholds }
|
|
7869
|
+
);
|
|
7870
|
+
return [
|
|
7871
|
+
{ kind: "shadow_role_cost", ...base, roleCost },
|
|
7872
|
+
{
|
|
7873
|
+
kind: "shadow_fan_out",
|
|
7874
|
+
...base,
|
|
7875
|
+
disagreementSignal: disagreementSignal ?? null,
|
|
7876
|
+
disagreementSource: hasTaskSignal ? "task.disagreement_signal" : "difficulty-proxy-v0",
|
|
7877
|
+
...gate
|
|
7878
|
+
}
|
|
7879
|
+
];
|
|
7880
|
+
}
|
|
7881
|
+
var SHADOW_CRITERION, DEFAULT_SHADOW_FAN_OUT, isNonNegativeFinite, isUnitInterval, EMPTY_ATTRIBUTION;
|
|
7882
|
+
var init_role_cost_shadow = __esm({
|
|
7883
|
+
"../../scripts/virtual-office/code-runner/auto-router/role-cost-shadow.mjs"() {
|
|
7884
|
+
"use strict";
|
|
7885
|
+
SHADOW_CRITERION = "info-bottleneck-v0";
|
|
7886
|
+
DEFAULT_SHADOW_FAN_OUT = Object.freeze({
|
|
7887
|
+
minDisagreementSignal: 0.4,
|
|
7888
|
+
maxSingleModelConfidence: 0.6,
|
|
7889
|
+
minPanelSize: 2,
|
|
7890
|
+
defaultPanelSize: 3,
|
|
7891
|
+
neverFanOutClasses: Object.freeze(["chore", "docs"])
|
|
7892
|
+
});
|
|
7893
|
+
isNonNegativeFinite = (n) => typeof n === "number" && Number.isFinite(n) && n >= 0;
|
|
7894
|
+
isUnitInterval = (n) => isNonNegativeFinite(n) && n <= 1;
|
|
7895
|
+
EMPTY_ATTRIBUTION = Object.freeze({
|
|
7896
|
+
plannerCostUsd: null,
|
|
7897
|
+
workerCostUsd: null,
|
|
7898
|
+
totalCostUsd: null,
|
|
7899
|
+
plannerCostShare: null,
|
|
7900
|
+
workerCostShare: null,
|
|
7901
|
+
plannerTokenShare: null,
|
|
7902
|
+
workerTokenShare: null,
|
|
7903
|
+
plannerCostShareRatio: null
|
|
7904
|
+
});
|
|
7634
7905
|
}
|
|
7635
7906
|
});
|
|
7636
7907
|
|
|
7637
7908
|
// ../../scripts/virtual-office/code-runner/auto-router/auto-router.mjs
|
|
7638
|
-
import { readFileSync as
|
|
7909
|
+
import { readFileSync as readFileSync6, appendFileSync as appendFileSync2, mkdirSync as mkdirSync5 } from "node:fs";
|
|
7639
7910
|
import { homedir as homedir6 } from "node:os";
|
|
7640
|
-
import { join as
|
|
7641
|
-
import { fileURLToPath as
|
|
7911
|
+
import { join as join8, dirname as dirname5 } from "node:path";
|
|
7912
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
7642
7913
|
function getAutoRouterMode(env2 = process.env) {
|
|
7643
7914
|
const raw = String(env2.VO_CODE_RUNNER_AUTO_ROUTER || "").trim().toLowerCase();
|
|
7644
7915
|
return MODES.has(raw) ? raw : "off";
|
|
7645
7916
|
}
|
|
7646
7917
|
function loadThresholds() {
|
|
7647
7918
|
if (!cachedThresholds) {
|
|
7648
|
-
const here =
|
|
7649
|
-
cachedThresholds = JSON.parse(
|
|
7919
|
+
const here = dirname5(fileURLToPath3(import.meta.url));
|
|
7920
|
+
cachedThresholds = JSON.parse(readFileSync6(join8(here, "thresholds.json"), "utf8"));
|
|
7650
7921
|
}
|
|
7651
7922
|
return cachedThresholds;
|
|
7652
7923
|
}
|
|
@@ -7712,16 +7983,36 @@ function formatDecisionReason(decision, maxLen = 480) {
|
|
|
7712
7983
|
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("; ")}`;
|
|
7713
7984
|
return s.length > maxLen ? `${s.slice(0, maxLen - 1)}\u2026` : s;
|
|
7714
7985
|
}
|
|
7715
|
-
|
|
7986
|
+
function appendDecisionFallback(decision, { path: path18 = DECISION_FALLBACK_PATH, append = appendFileSync2, mkdir: mkdir3 = mkdirSync5, task, thresholds, roleCostInputs } = {}) {
|
|
7987
|
+
try {
|
|
7988
|
+
mkdir3(dirname5(path18), { recursive: true });
|
|
7989
|
+
append(path18, `${JSON.stringify(decision)}
|
|
7990
|
+
`, "utf8");
|
|
7991
|
+
if (isRouterDecision(decision)) {
|
|
7992
|
+
try {
|
|
7993
|
+
const records = buildShadowRecords({ decision, task, thresholds: thresholds || loadThresholds(), roleCostInputs });
|
|
7994
|
+
for (const record of records) append(path18, `${JSON.stringify(record)}
|
|
7995
|
+
`, "utf8");
|
|
7996
|
+
} catch {
|
|
7997
|
+
}
|
|
7998
|
+
}
|
|
7999
|
+
return true;
|
|
8000
|
+
} catch {
|
|
8001
|
+
return false;
|
|
8002
|
+
}
|
|
8003
|
+
}
|
|
8004
|
+
var ROUTER_VERSION, DECISION_FALLBACK_PATH, MODES, cachedThresholds, isRouterDecision;
|
|
7716
8005
|
var init_auto_router = __esm({
|
|
7717
8006
|
"../../scripts/virtual-office/code-runner/auto-router/auto-router.mjs"() {
|
|
7718
8007
|
"use strict";
|
|
7719
8008
|
init_classify_task();
|
|
7720
8009
|
init_effort_policy();
|
|
8010
|
+
init_role_cost_shadow();
|
|
7721
8011
|
ROUTER_VERSION = "0.1.0";
|
|
7722
|
-
DECISION_FALLBACK_PATH =
|
|
8012
|
+
DECISION_FALLBACK_PATH = join8(homedir6(), ".claude", "vo-auto-router-decisions.jsonl");
|
|
7723
8013
|
MODES = /* @__PURE__ */ new Set(["off", "shadow", "on"]);
|
|
7724
8014
|
cachedThresholds = null;
|
|
8015
|
+
isRouterDecision = (d) => Boolean(d && typeof d === "object" && typeof d.taskClass === "string" && typeof d.confidence === "number");
|
|
7725
8016
|
}
|
|
7726
8017
|
});
|
|
7727
8018
|
|
|
@@ -7753,7 +8044,7 @@ function resolveAgentEffort({ agent, tier, env: env2, applying, decision }) {
|
|
|
7753
8044
|
}
|
|
7754
8045
|
return applying ? decision.effort ?? null : null;
|
|
7755
8046
|
}
|
|
7756
|
-
async function resolveEffortDispatch({ client, task, agent = "claude", env: env2, basePrompt, resolveModel = resolveTaskModel, route = routeTask }) {
|
|
8047
|
+
async function resolveEffortDispatch({ client, task, agent = "claude", env: env2, basePrompt, resolveModel = resolveTaskModel, route = routeTask, appendDecision = appendDecisionFallback }) {
|
|
7757
8048
|
const dispatchMode = task.dispatch_mode ?? await client.getDispatchMode().catch(() => "standard");
|
|
7758
8049
|
const effortConfig = resolveEffortMode(dispatchMode);
|
|
7759
8050
|
const routerMode = getAutoRouterMode(env2);
|
|
@@ -7772,6 +8063,12 @@ async function resolveEffortDispatch({ client, task, agent = "claude", env: env2
|
|
|
7772
8063
|
{ agent }
|
|
7773
8064
|
);
|
|
7774
8065
|
const effort = resolveAgentEffort({ agent, tier, env: env2, applying, decision });
|
|
8066
|
+
if (decision) {
|
|
8067
|
+
try {
|
|
8068
|
+
appendDecision(decision, { task });
|
|
8069
|
+
} catch {
|
|
8070
|
+
}
|
|
8071
|
+
}
|
|
7775
8072
|
return {
|
|
7776
8073
|
dispatchMode,
|
|
7777
8074
|
routerMode,
|
|
@@ -8360,7 +8657,7 @@ __export(code_runner_daemon_exports, {
|
|
|
8360
8657
|
});
|
|
8361
8658
|
import os4 from "node:os";
|
|
8362
8659
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
8363
|
-
import { fileURLToPath as
|
|
8660
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
8364
8661
|
function log2(msg) {
|
|
8365
8662
|
console.log(`[code-runner ${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}`);
|
|
8366
8663
|
}
|
|
@@ -8718,7 +9015,7 @@ var init_code_runner_daemon = __esm({
|
|
|
8718
9015
|
sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
8719
9016
|
numOrUndef = (x) => typeof x === "number" ? x : void 0;
|
|
8720
9017
|
safeProgress = makeSafeProgress(log2);
|
|
8721
|
-
invokedDirectly = process.argv[1] &&
|
|
9018
|
+
invokedDirectly = process.argv[1] && fileURLToPath4(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).
|
|
8722
9019
|
import.meta.url.endsWith("code-runner-daemon.mjs");
|
|
8723
9020
|
if (invokedDirectly) {
|
|
8724
9021
|
const once2 = process.argv.includes("--once");
|