@algosuite/vo-mcp 0.2.0-beta.30 → 0.2.0-beta.33
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/agent-auth-probe-cli.mjs +187 -6
- package/dist/cli.js +65 -6
- package/dist/cli.js.map +2 -2
- package/dist/index.js +65 -6
- package/dist/index.js.map +2 -2
- package/dist/runner-cli.js +926 -164
- package/dist/runner-cli.js.map +4 -4
- package/package.json +2 -2
|
@@ -1118,8 +1118,180 @@ var CursorRunner = class {
|
|
|
1118
1118
|
};
|
|
1119
1119
|
var cursorRunner = new CursorRunner();
|
|
1120
1120
|
|
|
1121
|
+
// ../../scripts/virtual-office/code-runner/ollama-agent-tools.mjs
|
|
1122
|
+
var MAX_READ_BYTES = 64 * 1024;
|
|
1123
|
+
var MAX_WRITE_BYTES = 512 * 1024;
|
|
1124
|
+
var TOOL_DEFS = [
|
|
1125
|
+
{
|
|
1126
|
+
type: "function",
|
|
1127
|
+
function: {
|
|
1128
|
+
name: "read_file",
|
|
1129
|
+
description: "Read a UTF-8 text file inside the working directory. Returns up to 64 KiB.",
|
|
1130
|
+
parameters: {
|
|
1131
|
+
type: "object",
|
|
1132
|
+
properties: {
|
|
1133
|
+
path: { type: "string", description: "File path relative to the working directory." }
|
|
1134
|
+
},
|
|
1135
|
+
required: ["path"]
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
},
|
|
1139
|
+
{
|
|
1140
|
+
type: "function",
|
|
1141
|
+
function: {
|
|
1142
|
+
name: "list_files",
|
|
1143
|
+
description: "List entries in a directory inside the working directory (files and subdirs).",
|
|
1144
|
+
parameters: {
|
|
1145
|
+
type: "object",
|
|
1146
|
+
properties: {
|
|
1147
|
+
path: { type: "string", description: 'Directory path relative to the working directory. Default ".".' }
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
},
|
|
1152
|
+
{
|
|
1153
|
+
type: "function",
|
|
1154
|
+
function: {
|
|
1155
|
+
name: "write_file",
|
|
1156
|
+
description: "Create or overwrite a UTF-8 text file inside the working directory. Parent dirs are created.",
|
|
1157
|
+
parameters: {
|
|
1158
|
+
type: "object",
|
|
1159
|
+
properties: {
|
|
1160
|
+
path: { type: "string", description: "File path relative to the working directory." },
|
|
1161
|
+
content: { type: "string", description: "Full new file contents." }
|
|
1162
|
+
},
|
|
1163
|
+
required: ["path", "content"]
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
];
|
|
1168
|
+
var TOOL_NAMES = TOOL_DEFS.map((t) => t.function.name);
|
|
1169
|
+
var READ_ONLY_TOOL_NAMES = Object.freeze(["read_file", "list_files"]);
|
|
1170
|
+
var READ_ONLY_TOOL_DEFS = Object.freeze(
|
|
1171
|
+
TOOL_DEFS.filter((tool) => READ_ONLY_TOOL_NAMES.includes(tool.function.name))
|
|
1172
|
+
);
|
|
1173
|
+
|
|
1174
|
+
// ../../scripts/virtual-office/code-runner/ollama-agent-core.mjs
|
|
1175
|
+
var MAX_TURNS_DEFAULT = 20;
|
|
1176
|
+
var NUM_CTX_DEFAULT = 16384;
|
|
1177
|
+
function parseOllamaAgentEvent(line) {
|
|
1178
|
+
const trimmed = String(line || "").trim();
|
|
1179
|
+
if (!trimmed) return null;
|
|
1180
|
+
let evt;
|
|
1181
|
+
try {
|
|
1182
|
+
evt = JSON.parse(trimmed);
|
|
1183
|
+
} catch {
|
|
1184
|
+
return null;
|
|
1185
|
+
}
|
|
1186
|
+
if (!evt || typeof evt !== "object") return null;
|
|
1187
|
+
if (evt.type === "progress") {
|
|
1188
|
+
const text = String(evt.text || "").trim();
|
|
1189
|
+
return text ? { kind: "progress", text } : null;
|
|
1190
|
+
}
|
|
1191
|
+
if (evt.type === "tool") {
|
|
1192
|
+
const via = evt.recovered ? " (recovered from text)" : "";
|
|
1193
|
+
const label = `${evt.ok === false ? "tool failed" : "tool"}: ${evt.name}${evt.path ? ` ${evt.path}` : ""}${via}`;
|
|
1194
|
+
return { kind: "progress", text: label };
|
|
1195
|
+
}
|
|
1196
|
+
if (evt.type === "result") {
|
|
1197
|
+
const usage = evt.usage || null;
|
|
1198
|
+
const tokenUsage = usage ? { inputTokens: usage.inputTokens ?? null, outputTokens: usage.outputTokens ?? null, totalTokens: usage.totalTokens ?? null } : void 0;
|
|
1199
|
+
return {
|
|
1200
|
+
kind: "result",
|
|
1201
|
+
isError: Boolean(evt.isError),
|
|
1202
|
+
costUsd: 0,
|
|
1203
|
+
// sovereign local inference is free — no meter.
|
|
1204
|
+
summary: String(evt.summary || (evt.isError ? "local run failed" : "completed")),
|
|
1205
|
+
numTurns: Number.isInteger(evt.numTurns) ? evt.numTurns : null,
|
|
1206
|
+
...tokenUsage ? { tokenUsage } : {},
|
|
1207
|
+
// Pass the sovereign receipt through to the daemon. Omitted entirely when
|
|
1208
|
+
// absent so the event shape is unchanged for every other transport.
|
|
1209
|
+
...evt.receipt ? { receipt: evt.receipt } : {}
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1212
|
+
return null;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
// ../../scripts/virtual-office/code-runner/ollama-native-transport.mjs
|
|
1216
|
+
import { fileURLToPath } from "node:url";
|
|
1217
|
+
import { dirname, join } from "node:path";
|
|
1218
|
+
var DEFAULT_LOCAL_TRANSPORT = "codex";
|
|
1219
|
+
var LOCAL_NATIVE_PROFILES = Object.freeze(["coding", "verification"]);
|
|
1220
|
+
var DEFAULT_LOCAL_NATIVE_PROFILE = "coding";
|
|
1221
|
+
function resolveLocalNativeProfile(env = process.env) {
|
|
1222
|
+
const profile = String(env.VO_CODE_RUNNER_LOCAL_PROFILE || "").trim().toLowerCase() || DEFAULT_LOCAL_NATIVE_PROFILE;
|
|
1223
|
+
if (!LOCAL_NATIVE_PROFILES.includes(profile)) {
|
|
1224
|
+
throw new Error(`local-model runner (native): unknown profile "${profile}" (coding|verification).`);
|
|
1225
|
+
}
|
|
1226
|
+
return profile;
|
|
1227
|
+
}
|
|
1228
|
+
function resolveLocalTransport(env = process.env) {
|
|
1229
|
+
return String(env.VO_CODE_RUNNER_LOCAL_TRANSPORT || "").trim().toLowerCase() === "native" ? "native" : DEFAULT_LOCAL_TRANSPORT;
|
|
1230
|
+
}
|
|
1231
|
+
function ollamaAgentScriptPath() {
|
|
1232
|
+
return join(dirname(fileURLToPath(import.meta.url)), "ollama-agent.mjs");
|
|
1233
|
+
}
|
|
1234
|
+
function posIntOr(raw, fallback) {
|
|
1235
|
+
const n = Number(String(raw ?? "").trim());
|
|
1236
|
+
return Number.isInteger(n) && n > 0 ? n : fallback;
|
|
1237
|
+
}
|
|
1238
|
+
function buildOllamaAgentArgs({ model, numCtx, maxTurns, profile = DEFAULT_LOCAL_NATIVE_PROFILE } = {}) {
|
|
1239
|
+
return [
|
|
1240
|
+
ollamaAgentScriptPath(),
|
|
1241
|
+
"--model",
|
|
1242
|
+
String(model),
|
|
1243
|
+
"--profile",
|
|
1244
|
+
String(profile),
|
|
1245
|
+
"--num-ctx",
|
|
1246
|
+
String(posIntOr(numCtx, NUM_CTX_DEFAULT)),
|
|
1247
|
+
"--max-turns",
|
|
1248
|
+
String(posIntOr(maxTurns, MAX_TURNS_DEFAULT))
|
|
1249
|
+
];
|
|
1250
|
+
}
|
|
1251
|
+
function buildLocalNativeArgs(opts = {}, env = process.env) {
|
|
1252
|
+
const provider = resolveLocalProvider(env);
|
|
1253
|
+
if (provider !== "ollama") {
|
|
1254
|
+
throw new Error(
|
|
1255
|
+
`local-model runner (native): the native tool-loop executor speaks Ollama's /api/chat; provider "${provider}" is not supported on native transport. Set VO_CODE_RUNNER_LOCAL_PROVIDER=ollama, or use VO_CODE_RUNNER_LOCAL_TRANSPORT=codex for LM Studio.`
|
|
1256
|
+
);
|
|
1257
|
+
}
|
|
1258
|
+
const model = resolveLocalModel(env);
|
|
1259
|
+
if (!model) {
|
|
1260
|
+
throw new Error(
|
|
1261
|
+
"local-model runner (native): set VO_CODE_RUNNER_LOCAL_MODEL to a coding model your Ollama server already has (e.g. qwen2.5-coder:7b). Refusing to run with no explicit model (fail-closed)."
|
|
1262
|
+
);
|
|
1263
|
+
}
|
|
1264
|
+
if (!isValidLocalModel(model)) {
|
|
1265
|
+
throw new Error(`local-model runner (native): "${model}" is not a valid local model id.`);
|
|
1266
|
+
}
|
|
1267
|
+
const baseUrl = resolveLocalBaseUrl(env);
|
|
1268
|
+
if (baseUrl && !isLoopbackBaseUrl(baseUrl)) {
|
|
1269
|
+
throw new Error(
|
|
1270
|
+
"local-model runner (native): VO_CODE_RUNNER_LOCAL_BASE_URL must be a loopback http(s) URL (localhost / 127.0.0.1 / [::1]). Remote endpoints are refused \u2014 use the Model Firewall lanes."
|
|
1271
|
+
);
|
|
1272
|
+
}
|
|
1273
|
+
return buildOllamaAgentArgs({
|
|
1274
|
+
model,
|
|
1275
|
+
profile: resolveLocalNativeProfile(env),
|
|
1276
|
+
numCtx: env.VO_CODE_RUNNER_LOCAL_NUM_CTX,
|
|
1277
|
+
maxTurns: env.VO_CODE_RUNNER_LOCAL_MAX_TURNS
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1121
1281
|
// ../../scripts/virtual-office/code-runner/local-model-runner.mjs
|
|
1122
1282
|
var LOCAL_API_KEY_ENV = "VO_CODE_RUNNER_LOCAL_API_KEY";
|
|
1283
|
+
var FORBIDDEN_LOCAL_CHILD_CREDENTIALS = /* @__PURE__ */ new Set([
|
|
1284
|
+
"ANTHROPIC_API_KEY",
|
|
1285
|
+
"AWS_ACCESS_KEY_ID",
|
|
1286
|
+
"AWS_SECRET_ACCESS_KEY",
|
|
1287
|
+
"AWS_SESSION_TOKEN",
|
|
1288
|
+
"FIREBASE_TOKEN",
|
|
1289
|
+
"GH_TOKEN",
|
|
1290
|
+
"GITHUB_TOKEN",
|
|
1291
|
+
"GOOGLE_API_KEY",
|
|
1292
|
+
"GOOGLE_APPLICATION_CREDENTIALS",
|
|
1293
|
+
"OPENAI_API_KEY"
|
|
1294
|
+
]);
|
|
1123
1295
|
var LOCAL_PROVIDERS = ["ollama", "lmstudio"];
|
|
1124
1296
|
var DEFAULT_LOCAL_PROVIDER = "ollama";
|
|
1125
1297
|
var LOCAL_PROBE_URLS = {
|
|
@@ -1196,6 +1368,9 @@ function buildLocalArgs(opts = {}, env = process.env) {
|
|
|
1196
1368
|
}
|
|
1197
1369
|
function applyLocalAuthEnv(baseEnv = process.env, configEnv = process.env) {
|
|
1198
1370
|
const out = withAgentKey("local", baseEnv);
|
|
1371
|
+
for (const key of Object.keys(out)) {
|
|
1372
|
+
if (FORBIDDEN_LOCAL_CHILD_CREDENTIALS.has(key.toUpperCase())) delete out[key];
|
|
1373
|
+
}
|
|
1199
1374
|
const baseUrl = resolveLocalBaseUrl(configEnv);
|
|
1200
1375
|
if (baseUrl && isLoopbackBaseUrl(baseUrl) && resolveLocalProvider(configEnv) === "ollama" && !String(out.OLLAMA_HOST || "").trim()) {
|
|
1201
1376
|
out.OLLAMA_HOST = baseUrl.replace(/\/+$/, "");
|
|
@@ -1214,19 +1389,25 @@ var LocalModelRunner = class {
|
|
|
1214
1389
|
this.env = env;
|
|
1215
1390
|
this.fetchImpl = fetchImpl;
|
|
1216
1391
|
}
|
|
1217
|
-
/**
|
|
1392
|
+
/**
|
|
1393
|
+
* Transport binary. codex transport → the codex CLI. native transport →
|
|
1394
|
+
* this daemon's own node (process.execPath), which runs ollama-agent.mjs; no
|
|
1395
|
+
* external CLI is involved on the native path.
|
|
1396
|
+
*/
|
|
1218
1397
|
get binary() {
|
|
1219
|
-
return this.resolveBinary();
|
|
1398
|
+
return resolveLocalTransport(this.env) === "native" ? process.execPath : this.resolveBinary();
|
|
1220
1399
|
}
|
|
1221
1400
|
buildArgs(opts = {}) {
|
|
1222
|
-
return buildLocalArgs(opts, this.env);
|
|
1401
|
+
return resolveLocalTransport(this.env) === "native" ? buildLocalNativeArgs(opts, this.env) : buildLocalArgs(opts, this.env);
|
|
1223
1402
|
}
|
|
1224
1403
|
/**
|
|
1225
|
-
*
|
|
1226
|
-
*
|
|
1227
|
-
*
|
|
1404
|
+
* native transport → parse the executor's own JSONL contract. codex transport
|
|
1405
|
+
* → codex JSONL maps identically, except a sovereign local model has no vendor
|
|
1406
|
+
* bill: codex omits total_cost_usd for OSS runs, so turn that known fact into a
|
|
1407
|
+
* measured zero at the producer. (The native parser already stamps costUsd:0.)
|
|
1228
1408
|
*/
|
|
1229
1409
|
parseEvent(line) {
|
|
1410
|
+
if (resolveLocalTransport(this.env) === "native") return parseOllamaAgentEvent(line);
|
|
1230
1411
|
const event = parseCodexEvent(line);
|
|
1231
1412
|
return event?.kind === "result" ? { ...event, costUsd: 0 } : event;
|
|
1232
1413
|
}
|
package/dist/cli.js
CHANGED
|
@@ -1079,6 +1079,42 @@ function toEventPerModelVerdicts(src) {
|
|
|
1079
1079
|
};
|
|
1080
1080
|
});
|
|
1081
1081
|
}
|
|
1082
|
+
function aggregateEventTokenUsage(src, engineUsage) {
|
|
1083
|
+
if (engineUsage !== void 0) {
|
|
1084
|
+
const hasIn = Object.keys(engineUsage.per_model_tokens_in).length > 0;
|
|
1085
|
+
const hasOut = Object.keys(engineUsage.per_model_tokens_out).length > 0;
|
|
1086
|
+
return {
|
|
1087
|
+
per_model_tokens_in: hasIn ? engineUsage.per_model_tokens_in : null,
|
|
1088
|
+
per_model_tokens_out: hasOut ? engineUsage.per_model_tokens_out : null,
|
|
1089
|
+
total_cost_usd: engineUsage.cost_micro_usd === null ? null : engineUsage.cost_micro_usd / 1e6
|
|
1090
|
+
};
|
|
1091
|
+
}
|
|
1092
|
+
const tokensIn = {};
|
|
1093
|
+
const tokensOut = {};
|
|
1094
|
+
let anyTokensIn = false;
|
|
1095
|
+
let anyTokensOut = false;
|
|
1096
|
+
let costMicroUsd = 0;
|
|
1097
|
+
let anyCost = false;
|
|
1098
|
+
for (const v of src) {
|
|
1099
|
+
if (typeof v.input_tokens === "number") {
|
|
1100
|
+
tokensIn[v.model] = (tokensIn[v.model] ?? 0) + v.input_tokens;
|
|
1101
|
+
anyTokensIn = true;
|
|
1102
|
+
}
|
|
1103
|
+
if (typeof v.output_tokens === "number") {
|
|
1104
|
+
tokensOut[v.model] = (tokensOut[v.model] ?? 0) + v.output_tokens;
|
|
1105
|
+
anyTokensOut = true;
|
|
1106
|
+
}
|
|
1107
|
+
if (typeof v.cost_micro_usd === "number") {
|
|
1108
|
+
costMicroUsd += v.cost_micro_usd;
|
|
1109
|
+
anyCost = true;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
return {
|
|
1113
|
+
per_model_tokens_in: anyTokensIn ? tokensIn : null,
|
|
1114
|
+
per_model_tokens_out: anyTokensOut ? tokensOut : null,
|
|
1115
|
+
total_cost_usd: anyCost ? costMicroUsd / 1e6 : null
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1082
1118
|
function toEventSynthesizedVerdict(src) {
|
|
1083
1119
|
return {
|
|
1084
1120
|
verdict: src.verdict,
|
|
@@ -2778,7 +2814,8 @@ async function handleCheckHollowTest(deps, rawInput, signal) {
|
|
|
2778
2814
|
synthesized_verdict: synthForEvent,
|
|
2779
2815
|
consensus_confidence: engineResult.synthesized_verdict.confidence,
|
|
2780
2816
|
duration_ms: engineResult.duration_ms,
|
|
2781
|
-
consensus_engine_version: engineResult.engine_version
|
|
2817
|
+
consensus_engine_version: engineResult.engine_version,
|
|
2818
|
+
...aggregateEventTokenUsage(engineResult.per_model_verdicts, engineResult.token_usage)
|
|
2782
2819
|
};
|
|
2783
2820
|
const payload = {
|
|
2784
2821
|
verdict: engineResult.synthesized_verdict.verdict,
|
|
@@ -2961,7 +2998,8 @@ async function handleVerifyAnswer(deps, rawInput, signal) {
|
|
|
2961
2998
|
synthesized_verdict: synthForEvent,
|
|
2962
2999
|
consensus_confidence: engineResult.synthesized_verdict.confidence,
|
|
2963
3000
|
duration_ms: engineResult.duration_ms,
|
|
2964
|
-
consensus_engine_version: engineResult.engine_version
|
|
3001
|
+
consensus_engine_version: engineResult.engine_version,
|
|
3002
|
+
...aggregateEventTokenUsage(engineResult.per_model_verdicts, engineResult.token_usage)
|
|
2965
3003
|
};
|
|
2966
3004
|
const payload = {
|
|
2967
3005
|
verdict: engineResult.synthesized_verdict.verdict,
|
|
@@ -2970,6 +3008,7 @@ async function handleVerifyAnswer(deps, rawInput, signal) {
|
|
|
2970
3008
|
synthesized_verdict: synthForEvent,
|
|
2971
3009
|
engine_version: engineResult.engine_version,
|
|
2972
3010
|
degraded: engineResult.degraded,
|
|
3011
|
+
...engineResult.quorum_failed === true ? { quorum_failed: true } : {},
|
|
2973
3012
|
gate_type: gateType,
|
|
2974
3013
|
...kbResult.error !== null ? { kb_unavailable: true } : {},
|
|
2975
3014
|
...kbTruncated > 0 ? { kb_rules_truncated: kbTruncated } : {}
|
|
@@ -3226,7 +3265,8 @@ async function handleConsensusJudgment(deps, rawInput, signal) {
|
|
|
3226
3265
|
duration_ms: engineResult.duration_ms,
|
|
3227
3266
|
consensus_engine_version: engineResult.engine_version,
|
|
3228
3267
|
per_model_verdicts: perModelForEvent,
|
|
3229
|
-
synthesized_verdict: synthForEvent
|
|
3268
|
+
synthesized_verdict: synthForEvent,
|
|
3269
|
+
...aggregateEventTokenUsage(engineResult.per_model_verdicts, engineResult.token_usage)
|
|
3230
3270
|
};
|
|
3231
3271
|
const payload = {
|
|
3232
3272
|
verdict: engineResult.synthesized_verdict.verdict,
|
|
@@ -3235,6 +3275,7 @@ async function handleConsensusJudgment(deps, rawInput, signal) {
|
|
|
3235
3275
|
synthesized_verdict: synthForEvent,
|
|
3236
3276
|
engine_version: engineResult.engine_version,
|
|
3237
3277
|
degraded: engineResult.degraded,
|
|
3278
|
+
...engineResult.quorum_failed === true ? { quorum_failed: true } : {},
|
|
3238
3279
|
gate_type: gateType,
|
|
3239
3280
|
// ─── Consensus-engine feature outputs (additive; 2026-06-13) ─────────────
|
|
3240
3281
|
// Feature 2 (calibrated-confidence) — ON by default; the engine attaches
|
|
@@ -3435,7 +3476,8 @@ async function handleArchitectureReview(deps, rawInput, signal) {
|
|
|
3435
3476
|
synthesized_verdict: synthForEvent,
|
|
3436
3477
|
consensus_confidence: engineResult.synthesized_verdict.confidence,
|
|
3437
3478
|
duration_ms: engineResult.duration_ms,
|
|
3438
|
-
consensus_engine_version: engineResult.engine_version
|
|
3479
|
+
consensus_engine_version: engineResult.engine_version,
|
|
3480
|
+
...aggregateEventTokenUsage(engineResult.per_model_verdicts, engineResult.token_usage)
|
|
3439
3481
|
};
|
|
3440
3482
|
const escalationRequired = engineResult.escalation_required === true || engineResult.escalation_required === void 0 && engineResult.synthesized_verdict.dissent_summary !== null;
|
|
3441
3483
|
const escalationReason = engineResult.escalation_reason ?? engineResult.synthesized_verdict.dissent_summary ?? "";
|
|
@@ -4922,7 +4964,8 @@ Produce the JSON dispatch plan now.`;
|
|
|
4922
4964
|
duration_ms: engineResult.duration_ms,
|
|
4923
4965
|
consensus_engine_version: engineResult.engine_version,
|
|
4924
4966
|
per_model_verdicts: toEventPerModelVerdicts(engineResult.per_model_verdicts),
|
|
4925
|
-
synthesized_verdict: toEventSynthesizedVerdict(engineResult.synthesized_verdict)
|
|
4967
|
+
synthesized_verdict: toEventSynthesizedVerdict(engineResult.synthesized_verdict),
|
|
4968
|
+
...aggregateEventTokenUsage(engineResult.per_model_verdicts, engineResult.token_usage)
|
|
4926
4969
|
};
|
|
4927
4970
|
deps.events.append(enrichedEvent);
|
|
4928
4971
|
return jsonContent(envelope);
|
|
@@ -5796,7 +5839,8 @@ async function handleReviewMerge(deps, rawInput, signal) {
|
|
|
5796
5839
|
duration_ms: result.duration_ms,
|
|
5797
5840
|
consensus_engine_version: result.engine_version,
|
|
5798
5841
|
per_model_verdicts: perModel,
|
|
5799
|
-
synthesized_verdict: synth
|
|
5842
|
+
synthesized_verdict: synth,
|
|
5843
|
+
...aggregateEventTokenUsage(result.per_model_verdicts, result.token_usage)
|
|
5800
5844
|
});
|
|
5801
5845
|
}
|
|
5802
5846
|
|
|
@@ -7801,6 +7845,14 @@ function shadowEnabled(env) {
|
|
|
7801
7845
|
const norm = raw.trim().toLowerCase();
|
|
7802
7846
|
return !(norm === "0" || norm === "false" || norm === "no" || norm === "off" || norm === "");
|
|
7803
7847
|
}
|
|
7848
|
+
var MIN_RESPONDERS_ENV_VAR = "VO_CONSENSUS_MIN_RESPONDERS";
|
|
7849
|
+
function resolveMinResponders(env) {
|
|
7850
|
+
const raw = (env ?? {})[MIN_RESPONDERS_ENV_VAR];
|
|
7851
|
+
if (raw === void 0 || raw.trim() === "") return 2;
|
|
7852
|
+
const parsed = Number.parseInt(raw.trim(), 10);
|
|
7853
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return void 0;
|
|
7854
|
+
return parsed;
|
|
7855
|
+
}
|
|
7804
7856
|
function mapShadowSynthesis(s) {
|
|
7805
7857
|
if (s === void 0) return void 0;
|
|
7806
7858
|
return {
|
|
@@ -7950,9 +8002,11 @@ function createEngineConsensusClient(options) {
|
|
|
7950
8002
|
...options.agreement_gate_enabled !== void 0 ? { configEnabled: options.agreement_gate_enabled } : {},
|
|
7951
8003
|
...options.env !== void 0 ? { env: options.env } : {}
|
|
7952
8004
|
});
|
|
8005
|
+
const minResponders = resolveMinResponders(options.env);
|
|
7953
8006
|
const engineOptions = {
|
|
7954
8007
|
panel,
|
|
7955
8008
|
...options.per_model_timeout_ms !== void 0 ? { per_model_timeout_ms: options.per_model_timeout_ms } : {},
|
|
8009
|
+
...minResponders !== void 0 ? { min_responders: minResponders } : {},
|
|
7956
8010
|
...agreementGate !== void 0 ? { agreement_gate: agreementGate } : {},
|
|
7957
8011
|
// Stage A7-shadow: run the adaptive verdict alongside the live one for grading.
|
|
7958
8012
|
// Cheap (pure log-odds over already-fetched verdicts; no extra model calls),
|
|
@@ -8005,8 +8059,13 @@ function createEngineConsensusClient(options) {
|
|
|
8005
8059
|
synthesized_verdict: response.synthesized_verdict,
|
|
8006
8060
|
per_model_verdicts: response.per_model_verdicts,
|
|
8007
8061
|
degraded: response.degraded,
|
|
8062
|
+
...response.quorum_failed === true ? { quorum_failed: true } : {},
|
|
8008
8063
|
duration_ms: response.duration_ms,
|
|
8009
8064
|
engine_version: response.engine_version,
|
|
8065
|
+
// Cumulative cross-round inference usage (B44-3). Absent when no panel
|
|
8066
|
+
// member reported usage; forwarded verbatim — the aggregator prefers it
|
|
8067
|
+
// over summing final-round verdicts (which under-reports deliberation).
|
|
8068
|
+
...response.token_usage !== void 0 ? { token_usage: response.token_usage } : {},
|
|
8010
8069
|
// Phase 2 Lane D-1 — forward escalation signal when present. The
|
|
8011
8070
|
// source-grounded layer's own escalation (from the citation grade)
|
|
8012
8071
|
// takes precedence when set, else the synthesizer's.
|