@algosuite/vo-mcp 0.2.0-beta.2 → 0.2.0-beta.7

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/index.js CHANGED
@@ -1122,9 +1122,15 @@ function createMemoryEventsWriter() {
1122
1122
  function readVoMcpVersion() {
1123
1123
  try {
1124
1124
  const here = dirname3(fileURLToPath2(import.meta.url));
1125
- const pkgPath = join4(here, "..", "..", "package.json");
1126
- const pkg = JSON.parse(readFileSync4(pkgPath, "utf8"));
1127
- return typeof pkg.version === "string" ? pkg.version : "0.0.0-unknown";
1125
+ for (const rel of ["..", ["..", ".."], ["..", "..", ".."]]) {
1126
+ try {
1127
+ const segs = Array.isArray(rel) ? rel : [rel];
1128
+ const pkg = JSON.parse(readFileSync4(join4(here, ...segs, "package.json"), "utf8"));
1129
+ if (pkg.name === "@algosuite/vo-mcp" && typeof pkg.version === "string") return pkg.version;
1130
+ } catch {
1131
+ }
1132
+ }
1133
+ return "0.0.0-unknown";
1128
1134
  } catch {
1129
1135
  return "0.0.0-unknown";
1130
1136
  }
@@ -2044,6 +2050,8 @@ async function handleConsensusJudgment(deps, rawInput, signal) {
2044
2050
  ...engineResult.synthesized_verdict.confidence_badge !== void 0 ? { confidence_badge: engineResult.synthesized_verdict.confidence_badge } : {},
2045
2051
  // Feature 1 (agreement-gate) — fan-out diagnostics (present iff the gate ran).
2046
2052
  ...engineResult.fan_out_diagnostics !== void 0 ? { fan_out_diagnostics: engineResult.fan_out_diagnostics } : {},
2053
+ // Stage A7-shadow — adaptive-vs-incumbent comparison (PII-free; present iff shadow on).
2054
+ ...engineResult.shadow_synthesis !== void 0 ? { shadow_synthesis: engineResult.shadow_synthesis } : {},
2047
2055
  // Source-grounded Tier-4 outputs (present iff the call was source-grounded).
2048
2056
  ...engineResult.source_grounded === true ? { source_grounded: true } : {},
2049
2057
  ...engineResult.citation_grade !== void 0 ? { citation_grade: engineResult.citation_grade } : {},
@@ -4488,6 +4496,8 @@ function suggestedHandoffPath(session_id, isoTimestamp) {
4488
4496
  }
4489
4497
 
4490
4498
  // src/tools/session/report-session-state.ts
4499
+ init_auth_token_source();
4500
+ init_credential_store();
4491
4501
  var TOOL_NAME19 = "vo_report_session_state";
4492
4502
  var VALID_AGENT_TYPES = ["claude-code", "codex", "cursor", "continue"];
4493
4503
  var MAX_GOAL_CHARS = 500;
@@ -4538,7 +4548,7 @@ var inputSchema19 = {
4538
4548
  required: ["operator_id", "session_id", "agent_type", "context_used_pct"],
4539
4549
  additionalProperties: false
4540
4550
  };
4541
- var description19 = "Reports per-session context-window utilization to VO and returns a directive: 'continue' (under 70%), 'prepare_handoff' (70-84%), or 'execute_handoff_now' (\u226585%). Implements V1 launch gate #9 (fleet context lifecycle management) per the official VO roadmap. V1 backend is stub-local \u2014 computes the directive purely from `context_used_pct` against the documented thresholds without a network call. Phase 3 wires this to the deployed vo-control-plane HTTP API; the response shape stays stable across the cutover (`backend_mode` field in the payload tells the caller which mode produced the verdict).";
4551
+ var description19 = "Reports per-session context-window utilization to VO and returns a directive: 'continue' (under 70%), 'prepare_handoff' (70-84%), or 'execute_handoff_now' (\u226585%). Implements V1 launch gate #9 (fleet context lifecycle management) per the official VO roadmap. Cloud-control-plane mode when VO_CONTROL_PLANE_URL plus a user/scoped VO credential (or legacy admin token) is available; auto-allocates the session on first report so interactive agents (Claude Code, Cursor, Codex, Continue) appear on the live fleet whiteboard. Stub-local fallback when cloud config is absent or fails. The response shape stays stable across modes (`backend_mode` field in the payload tells the caller which mode produced the verdict).";
4542
4552
  function isStringArray2(v, maxItems) {
4543
4553
  if (!Array.isArray(v)) return false;
4544
4554
  if (v.length > maxItems) return false;
@@ -4563,33 +4573,93 @@ function isToolInput19(v) {
4563
4573
  }
4564
4574
  return true;
4565
4575
  }
4566
- function getCloudConfig() {
4567
- const url = process.env["VO_CONTROL_PLANE_URL"];
4568
- const token = process.env["VO_CONTROL_PLANE_ADMIN_TOKEN"];
4569
- if (!url || !token) return null;
4570
- return { url, token };
4576
+ async function fetchCloudIdentity(url, token, fetchFn) {
4577
+ try {
4578
+ const response = await fetchFn(`${url}/api/v1/auth/me`, {
4579
+ method: "GET",
4580
+ headers: {
4581
+ "Authorization": `Bearer ${token}`
4582
+ }
4583
+ });
4584
+ if (!response.ok) return null;
4585
+ const data = await response.json();
4586
+ if (!data.ok || !data.provisioned || !data.operator_id || !data.tenant_id) return null;
4587
+ return { operator_id: data.operator_id, tenant_id: data.tenant_id };
4588
+ } catch {
4589
+ return null;
4590
+ }
4571
4591
  }
4572
- async function tryCloudReportState(cloud, input) {
4592
+ async function getCloudConfig(fetchFn = fetch) {
4593
+ const url = process.env["VO_CONTROL_PLANE_URL"]?.trim();
4594
+ if (!url) return null;
4595
+ const tokenSource = createAuthTokenSourceFromEnv(
4596
+ process.env,
4597
+ fetchFn,
4598
+ () => readStoredCredential(process.env)
4599
+ );
4600
+ const token = await tokenSource?.getToken();
4601
+ if (!token) return null;
4602
+ const tenant_id = process.env["VO_TENANT_ID"]?.trim();
4603
+ if (tenant_id) return { url, token, tenant_id };
4604
+ const identity = await fetchCloudIdentity(url, token, fetchFn);
4605
+ if (!identity) return null;
4606
+ return { url, token, tenant_id: identity.tenant_id, operator_id: identity.operator_id };
4607
+ }
4608
+ async function tryCloudReportState(cloud, input, fetchFn = fetch) {
4573
4609
  try {
4574
- const body = {
4610
+ const reportBody = {
4575
4611
  context_used_pct: input.context_used_pct
4576
4612
  };
4577
- if (input.current_goal !== void 0) body["current_goal"] = input.current_goal;
4613
+ if (input.current_goal !== void 0) reportBody["current_goal"] = input.current_goal;
4578
4614
  if (input.recent_files_touched !== void 0) {
4579
- body["recent_files_touched"] = input.recent_files_touched;
4615
+ reportBody["recent_files_touched"] = input.recent_files_touched;
4580
4616
  }
4581
4617
  if (input.recent_tool_uses !== void 0) {
4582
- body["recent_tool_uses"] = input.recent_tool_uses;
4618
+ reportBody["recent_tool_uses"] = input.recent_tool_uses;
4583
4619
  }
4584
- const url = `${cloud.url}/api/v1/session/${input.session_id}/report-state`;
4585
- const response = await fetch(url, {
4620
+ const reportUrl = `${cloud.url}/api/v1/session/${input.session_id}/report-state`;
4621
+ let response = await fetchFn(reportUrl, {
4586
4622
  method: "POST",
4587
4623
  headers: {
4588
4624
  "Content-Type": "application/json",
4589
4625
  "Authorization": `Bearer ${cloud.token}`
4590
4626
  },
4591
- body: JSON.stringify(body)
4627
+ body: JSON.stringify(reportBody)
4592
4628
  });
4629
+ if (response.status === 404) {
4630
+ const allocateBody = {
4631
+ operator_id: cloud.operator_id ?? input.operator_id,
4632
+ tenant_id: cloud.tenant_id,
4633
+ agent_type: input.agent_type,
4634
+ current_goal: input.current_goal ?? "Interactive session"
4635
+ };
4636
+ if (input.context_used_pct > 0) {
4637
+ allocateBody["initial_context_used_pct"] = input.context_used_pct;
4638
+ }
4639
+ const allocateUrl = `${cloud.url}/api/v1/session`;
4640
+ const allocateResponse = await fetchFn(allocateUrl, {
4641
+ method: "POST",
4642
+ headers: {
4643
+ "Content-Type": "application/json",
4644
+ "Authorization": `Bearer ${cloud.token}`
4645
+ },
4646
+ body: JSON.stringify(allocateBody)
4647
+ });
4648
+ if (!allocateResponse.ok) {
4649
+ return null;
4650
+ }
4651
+ const allocateData = await allocateResponse.json();
4652
+ const retrySessionId = typeof allocateData.session?.session_id === "string" && allocateData.session.session_id.length > 0 ? allocateData.session.session_id : input.session_id;
4653
+ const retryReportUrl = `${cloud.url}/api/v1/session/${retrySessionId}/report-state`;
4654
+ response = await fetchFn(retryReportUrl, {
4655
+ method: "POST",
4656
+ headers: {
4657
+ "Content-Type": "application/json",
4658
+ "Authorization": `Bearer ${cloud.token}`
4659
+ },
4660
+ body: JSON.stringify(reportBody)
4661
+ });
4662
+ }
4593
4663
  if (!response.ok) {
4594
4664
  return null;
4595
4665
  }
@@ -4620,7 +4690,7 @@ async function handleReportSessionState(deps, rawInput, _signal) {
4620
4690
  `invalid input. Required fields: operator_id (non-empty string), session_id (non-empty string), agent_type (one of: ${VALID_AGENT_TYPES.join(" | ")}), context_used_pct (number 0-100). Optional: current_goal (string \u2264${MAX_GOAL_CHARS} chars), recent_files_touched (string[] \u2264${MAX_RECENT_FILES}), recent_tool_uses (string[] \u2264${MAX_RECENT_TOOLS}).`
4621
4691
  );
4622
4692
  }
4623
- const cloud = getCloudConfig();
4693
+ const cloud = await getCloudConfig();
4624
4694
  if (cloud !== null) {
4625
4695
  const cloudPayload = await tryCloudReportState(cloud, rawInput);
4626
4696
  if (cloudPayload !== null) {
@@ -4864,6 +4934,27 @@ async function handleConciergeDispatch(deps, rawInput, _signal) {
4864
4934
  import { homedir as homedir5 } from "node:os";
4865
4935
  import { join as join7 } from "node:path";
4866
4936
  import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync3, readdirSync as readdirSync4 } from "node:fs";
4937
+
4938
+ // src/tools/memory/safe-memory-file.ts
4939
+ import { resolve, sep } from "node:path";
4940
+ var SAFE_MEMORY_FILE_RE = /^[A-Za-z0-9][A-Za-z0-9._ -]*\.md$/i;
4941
+ function isSafeMemoryFileName(fileName) {
4942
+ return fileName.length <= 200 && fileName.trim() === fileName && !fileName.includes("/") && !fileName.includes("\\") && !fileName.includes(":") && SAFE_MEMORY_FILE_RE.test(fileName);
4943
+ }
4944
+ function resolveMemoryFilePath(memoryDir, fileName) {
4945
+ if (!isSafeMemoryFileName(fileName)) {
4946
+ throw new Error(`unsafe memory file_name: ${fileName.slice(0, 80)}`);
4947
+ }
4948
+ const root = resolve(memoryDir);
4949
+ const filePath = resolve(root, fileName);
4950
+ const rootPrefix = root.endsWith(sep) ? root : `${root}${sep}`;
4951
+ if (filePath !== root && !filePath.startsWith(rootPrefix)) {
4952
+ throw new Error(`memory file path escapes memory directory: ${fileName.slice(0, 80)}`);
4953
+ }
4954
+ return filePath;
4955
+ }
4956
+
4957
+ // src/tools/memory/sync-config.ts
4867
4958
  var TOOL_NAME22 = "vo_sync_config";
4868
4959
  var inputSchema22 = {
4869
4960
  type: "object",
@@ -4890,14 +4981,13 @@ function isToolInput22(v) {
4890
4981
  return true;
4891
4982
  }
4892
4983
  function deriveProjectSlug(cwd) {
4893
- const normalized = cwd.replace(/\\/g, "/");
4894
- return normalized.replace(/^([A-Z]):/i, (_, drive) => `${drive.toUpperCase()}-`).replace(/\/$/g, "").split("/").join("--").replace(/\s+/g, "-");
4984
+ return cwd.replace(/\\/g, "/").replace(/\/+$/g, "").replace(/^([a-zA-Z]):/, (_m, drive) => `${drive.toUpperCase()}:`).replace(/[^a-zA-Z0-9]/g, "-");
4895
4985
  }
4896
4986
  function getMemoryDir(cwd) {
4897
4987
  const slug = deriveProjectSlug(cwd);
4898
4988
  return join7(homedir5(), ".claude", "projects", slug, "memory");
4899
4989
  }
4900
- async function pullMemory(controlPlaneUrl, token, memoryDir, sessionId, fetchFn) {
4990
+ async function pullMemory(controlPlaneUrl, token, memoryDir, fetchFn) {
4901
4991
  const url = `${controlPlaneUrl}/api/v1/agent-config/memory/me`;
4902
4992
  const response = await fetchFn(url, {
4903
4993
  method: "GET",
@@ -4913,10 +5003,13 @@ async function pullMemory(controlPlaneUrl, token, memoryDir, sessionId, fetchFn)
4913
5003
  if (!data.ok || !Array.isArray(data.entries)) {
4914
5004
  throw new Error("GET /api/v1/agent-config/memory/me response missing ok=true or entries array");
4915
5005
  }
5006
+ const writes = data.entries.map((entry) => ({
5007
+ entry,
5008
+ filePath: resolveMemoryFilePath(memoryDir, entry.file_name)
5009
+ }));
4916
5010
  mkdirSync4(memoryDir, { recursive: true });
4917
5011
  const files = [];
4918
- for (const entry of data.entries) {
4919
- const filePath = join7(memoryDir, entry.file_name);
5012
+ for (const { entry, filePath } of writes) {
4920
5013
  writeFileSync3(filePath, entry.content, "utf8");
4921
5014
  files.push(entry.file_name);
4922
5015
  }
@@ -4928,7 +5021,7 @@ async function pushMemory(controlPlaneUrl, token, memoryDir, sessionId, fetchFn)
4928
5021
  }
4929
5022
  const localFiles = readdirSync4(memoryDir).filter((f) => f.endsWith(".md")).map((f) => ({
4930
5023
  file_name: f,
4931
- content: readFileSync7(join7(memoryDir, f), "utf8"),
5024
+ content: readFileSync7(resolveMemoryFilePath(memoryDir, f), "utf8"),
4932
5025
  entry_type: f === "MEMORY.md" ? "index" : "topic"
4933
5026
  }));
4934
5027
  if (localFiles.length === 0) {
@@ -5010,102 +5103,150 @@ async function pushMemory(controlPlaneUrl, token, memoryDir, sessionId, fetchFn)
5010
5103
  }
5011
5104
  return { pushed: localFiles.length, created, updated };
5012
5105
  }
5013
- async function handleSyncConfig(deps, rawInput, _signal, fetchFn = globalThis.fetch) {
5014
- if (!isToolInput22(rawInput)) {
5015
- throw invalidParams(
5016
- TOOL_NAME22,
5017
- 'invalid input. Required: { action: "pull" | "push" }. Optional: { cwd: "<path>" }.'
5018
- );
5019
- }
5106
+ async function runMemorySync(action, cwd, sessionId, fetchFn = globalThis.fetch) {
5020
5107
  const controlPlaneUrl = process.env["VO_CONTROL_PLANE_URL"];
5021
5108
  if (!controlPlaneUrl) {
5022
- return jsonContent({
5023
- tool: TOOL_NAME22,
5024
- schema_version: 1,
5025
- payload: {
5026
- synced: false,
5027
- reason: "VO_CONTROL_PLANE_URL not set \u2014 cloud mode disabled"
5028
- }
5029
- });
5109
+ return { synced: false, reason: "VO_CONTROL_PLANE_URL not set \u2014 cloud mode disabled" };
5030
5110
  }
5031
5111
  const { createAuthTokenSourceFromEnv: createAuthTokenSourceFromEnv2 } = await Promise.resolve().then(() => (init_auth_token_source(), auth_token_source_exports));
5032
5112
  const { readStoredCredential: readStoredCredential2 } = await Promise.resolve().then(() => (init_credential_store(), credential_store_exports));
5033
5113
  const tokenSource = createAuthTokenSourceFromEnv2(process.env, fetchFn, () => readStoredCredential2(process.env));
5034
5114
  if (!tokenSource) {
5035
- return jsonContent({
5036
- tool: TOOL_NAME22,
5037
- schema_version: 1,
5038
- payload: {
5039
- synced: false,
5040
- reason: "No auth configured. Run `vo-mcp login` to authenticate as an operator."
5041
- }
5042
- });
5115
+ return { synced: false, reason: "No auth configured. Run `vo-mcp login` to authenticate as an operator." };
5043
5116
  }
5044
5117
  const token = await tokenSource.getToken();
5045
5118
  if (!token) {
5046
- return jsonContent({
5047
- tool: TOOL_NAME22,
5048
- schema_version: 1,
5049
- payload: {
5050
- synced: false,
5051
- reason: "Failed to obtain auth token. Run `vo-mcp login` to re-authenticate."
5052
- }
5053
- });
5119
+ return { synced: false, reason: "Failed to obtain auth token. Run `vo-mcp login` to re-authenticate." };
5054
5120
  }
5055
- const cwd = rawInput.cwd?.trim() || process.cwd();
5056
5121
  const memoryDir = getMemoryDir(cwd);
5122
+ const baseUrl = controlPlaneUrl.replace(/\/+$/, "");
5057
5123
  try {
5058
- if (rawInput.action === "pull") {
5059
- const result = await pullMemory(
5060
- controlPlaneUrl.replace(/\/+$/, ""),
5061
- token,
5062
- memoryDir,
5063
- deps.sessionId,
5064
- fetchFn
5065
- );
5066
- return jsonContent({
5067
- tool: TOOL_NAME22,
5068
- schema_version: 1,
5069
- payload: {
5070
- synced: true,
5071
- action: "pull",
5072
- pulled: result.pulled,
5073
- files: result.files,
5074
- memory_dir: memoryDir
5075
- }
5076
- });
5077
- } else {
5078
- const result = await pushMemory(
5079
- controlPlaneUrl.replace(/\/+$/, ""),
5080
- token,
5081
- memoryDir,
5082
- deps.sessionId,
5083
- fetchFn
5084
- );
5085
- return jsonContent({
5086
- tool: TOOL_NAME22,
5087
- schema_version: 1,
5088
- payload: {
5089
- synced: true,
5090
- action: "push",
5091
- pushed: result.pushed,
5092
- created: result.created,
5093
- updated: result.updated,
5094
- memory_dir: memoryDir
5095
- }
5096
- });
5124
+ if (action === "pull") {
5125
+ const result2 = await pullMemory(baseUrl, token, memoryDir, fetchFn);
5126
+ return { synced: true, action: "pull", pulled: result2.pulled, files: result2.files, memory_dir: memoryDir };
5097
5127
  }
5128
+ const result = await pushMemory(baseUrl, token, memoryDir, sessionId, fetchFn);
5129
+ return {
5130
+ synced: true,
5131
+ action: "push",
5132
+ pushed: result.pushed,
5133
+ created: result.created,
5134
+ updated: result.updated,
5135
+ memory_dir: memoryDir
5136
+ };
5098
5137
  } catch (err) {
5099
5138
  const message = err instanceof Error ? err.message : String(err);
5100
- return jsonContent({
5101
- tool: TOOL_NAME22,
5102
- schema_version: 1,
5103
- payload: {
5104
- synced: false,
5105
- reason: `Sync failed: ${message}`
5106
- }
5107
- });
5139
+ return { synced: false, reason: `Sync failed: ${message}` };
5140
+ }
5141
+ }
5142
+ async function handleSyncConfig(deps, rawInput, _signal, fetchFn = globalThis.fetch) {
5143
+ if (!isToolInput22(rawInput)) {
5144
+ throw invalidParams(
5145
+ TOOL_NAME22,
5146
+ 'invalid input. Required: { action: "pull" | "push" }. Optional: { cwd: "<path>" }.'
5147
+ );
5148
+ }
5149
+ const cwd = rawInput.cwd?.trim() || process.cwd();
5150
+ const result = await runMemorySync(rawInput.action, cwd, deps.session.sessionId, fetchFn);
5151
+ return jsonContent({ tool: TOOL_NAME22, schema_version: 1, payload: result });
5152
+ }
5153
+
5154
+ // src/tools/memory/private-knowledge.ts
5155
+ var UPSERT_TOOL_NAME = "vo_private_knowledge_upsert";
5156
+ var CONTEXT_TOOL_NAME = "vo_private_knowledge_context";
5157
+ var KNOWLEDGE_CLASSES = ["memory", "skill", "doctrine", "hook", "command"];
5158
+ var PRECISION_CHAR_BUDGET = 12e3;
5159
+ var upsertInputSchema = {
5160
+ type: "object",
5161
+ properties: {
5162
+ knowledge_class: { type: "string", enum: KNOWLEDGE_CLASSES },
5163
+ source_path: { type: "string", description: "Stable private source identifier; not exposed to other users." },
5164
+ title: { type: "string", description: 'Descriptive, retrieval-friendly title (e.g. "AlgoTax OCR redaction architecture", not "notes") \u2014 retrieval matches on it.' },
5165
+ content: { type: "string", description: "Private knowledge text to store server-side. Keep each entry tight and focused (~1-3 pages, under ~12k chars); split larger corpora into separate entries." }
5166
+ },
5167
+ required: ["knowledge_class", "source_path", "title", "content"],
5168
+ additionalProperties: false
5169
+ };
5170
+ var contextInputSchema = {
5171
+ type: "object",
5172
+ properties: {
5173
+ query: { type: "string" },
5174
+ limit: { type: "number", minimum: 1, maximum: 50 },
5175
+ knowledge_class: { type: "string", enum: KNOWLEDGE_CLASSES }
5176
+ },
5177
+ required: ["query"],
5178
+ additionalProperties: false
5179
+ };
5180
+ var upsertDescription = "Uploads or refreshes the authenticated operator\u2019s private cloud knowledge. Works for Claude, Codex, Cursor, and cowork clients via the same vo-mcp login credential. Returns metadata only, not raw stored content. PRECISION DISCIPLINE: keep each entry tight and focused (~1-3 pages) with a descriptive retrieval-friendly title \u2014 retrieval surfaces whole entries, so small dense entries beat bulk dumps. Split large corpora into focused entries, then run a retrieval self-test via vo_private_knowledge_context before relying on the knowledge.";
5181
+ var contextDescription = "Retrieves prompt-ready private knowledge context for the authenticated operator. Returns snippets/context only; no raw corpus download. Also the retrieval self-test surface: after upserting critical knowledge, query for it here and confirm the entry surfaces before trusting it in downstream work.";
5182
+ function isKnowledgeClass(value) {
5183
+ return typeof value === "string" && KNOWLEDGE_CLASSES.includes(value);
5184
+ }
5185
+ function isUpsertInput(value) {
5186
+ if (typeof value !== "object" || value === null) return false;
5187
+ const input = value;
5188
+ return isKnowledgeClass(input["knowledge_class"]) && typeof input["source_path"] === "string" && typeof input["title"] === "string" && typeof input["content"] === "string";
5189
+ }
5190
+ function isContextInput(value) {
5191
+ if (typeof value !== "object" || value === null) return false;
5192
+ const input = value;
5193
+ if (typeof input["query"] !== "string") return false;
5194
+ if (input["limit"] !== void 0 && typeof input["limit"] !== "number") return false;
5195
+ if (input["knowledge_class"] !== void 0 && !isKnowledgeClass(input["knowledge_class"])) return false;
5196
+ return true;
5197
+ }
5198
+ async function getCloudAuth(fetchFn) {
5199
+ const controlPlaneUrl = process.env["VO_CONTROL_PLANE_URL"]?.replace(/\/+$/, "");
5200
+ if (!controlPlaneUrl) {
5201
+ return { ok: false, reason: "VO_CONTROL_PLANE_URL not set \u2014 cloud mode disabled" };
5202
+ }
5203
+ const { createAuthTokenSourceFromEnv: createAuthTokenSourceFromEnv2 } = await Promise.resolve().then(() => (init_auth_token_source(), auth_token_source_exports));
5204
+ const { readStoredCredential: readStoredCredential2 } = await Promise.resolve().then(() => (init_credential_store(), credential_store_exports));
5205
+ const tokenSource = createAuthTokenSourceFromEnv2(process.env, fetchFn, () => readStoredCredential2(process.env));
5206
+ if (!tokenSource) return { ok: false, reason: "No auth configured. Run `vo-mcp login`." };
5207
+ const token = await tokenSource.getToken();
5208
+ if (!token) return { ok: false, reason: "Failed to obtain auth token. Run `vo-mcp login` again." };
5209
+ return { ok: true, controlPlaneUrl, token };
5210
+ }
5211
+ async function callPrivateKnowledge(path3, body, fetchFn) {
5212
+ const auth = await getCloudAuth(fetchFn);
5213
+ if (!auth.ok) return { ok: false, reason: auth.reason };
5214
+ const response = await fetchFn(`${auth.controlPlaneUrl}${path3}`, {
5215
+ method: "POST",
5216
+ headers: {
5217
+ authorization: `Bearer ${auth.token}`,
5218
+ "content-type": "application/json"
5219
+ },
5220
+ body: JSON.stringify(body)
5221
+ });
5222
+ const text = await response.text();
5223
+ const parsed = text ? JSON.parse(text) : null;
5224
+ if (response.status < 200 || response.status >= 300) {
5225
+ return { ok: false, status: response.status, response: parsed ?? text };
5226
+ }
5227
+ return parsed;
5228
+ }
5229
+ async function handlePrivateKnowledgeUpsert(_deps, rawInput, _signal, fetchFn = globalThis.fetch) {
5230
+ if (!isUpsertInput(rawInput)) {
5231
+ throw invalidParams(UPSERT_TOOL_NAME, "expected { knowledge_class, source_path, title, content }.");
5232
+ }
5233
+ const payload = await callPrivateKnowledge("/api/v1/knowledge/private", rawInput, fetchFn);
5234
+ const envelope = {
5235
+ tool: UPSERT_TOOL_NAME,
5236
+ schema_version: 1,
5237
+ payload
5238
+ };
5239
+ if (rawInput.content.length > PRECISION_CHAR_BUDGET) {
5240
+ envelope.precision_note = `content is ${rawInput.content.length} chars (> ${PRECISION_CHAR_BUDGET}). Tight 1-3 page entries retrieve better \u2014 consider splitting into focused entries, then re-test retrieval via ${CONTEXT_TOOL_NAME}.`;
5241
+ }
5242
+ return jsonContent(envelope);
5243
+ }
5244
+ async function handlePrivateKnowledgeContext(_deps, rawInput, _signal, fetchFn = globalThis.fetch) {
5245
+ if (!isContextInput(rawInput)) {
5246
+ throw invalidParams(CONTEXT_TOOL_NAME, "expected { query, optional limit, optional knowledge_class }.");
5108
5247
  }
5248
+ const payload = await callPrivateKnowledge("/api/v1/knowledge/private/context", rawInput, fetchFn);
5249
+ return jsonContent({ tool: CONTEXT_TOOL_NAME, schema_version: 1, payload });
5109
5250
  }
5110
5251
 
5111
5252
  // src/server.ts
@@ -5286,6 +5427,22 @@ function buildToolRegistry() {
5286
5427
  inputSchema: inputSchema22
5287
5428
  },
5288
5429
  handler: handleSyncConfig
5430
+ },
5431
+ [UPSERT_TOOL_NAME]: {
5432
+ definition: {
5433
+ name: UPSERT_TOOL_NAME,
5434
+ description: upsertDescription,
5435
+ inputSchema: upsertInputSchema
5436
+ },
5437
+ handler: handlePrivateKnowledgeUpsert
5438
+ },
5439
+ [CONTEXT_TOOL_NAME]: {
5440
+ definition: {
5441
+ name: CONTEXT_TOOL_NAME,
5442
+ description: contextDescription,
5443
+ inputSchema: contextInputSchema
5444
+ },
5445
+ handler: handlePrivateKnowledgeContext
5289
5446
  }
5290
5447
  };
5291
5448
  }
@@ -5575,6 +5732,64 @@ function createNullConsensusEngineClient(reason = NULL_CLIENT_DEFAULT_REASON) {
5575
5732
  // src/consensus/engine-client.ts
5576
5733
  import { randomUUID as randomUUID3 } from "node:crypto";
5577
5734
 
5735
+ // src/consensus/meta-model-caller.ts
5736
+ var META_MODEL_API_BASE_URL = "https://api.meta.ai/v1";
5737
+ var META_CONSENSUS_MODEL = "muse-spark-1.1";
5738
+ var META_MODEL_API_KEY_ENV = "MODEL_API_KEY";
5739
+ var META_MODEL_API_KEY_ALIAS = "META_API";
5740
+ function resolveMetaKey(env) {
5741
+ return String(env[META_MODEL_API_KEY_ENV] || env[META_MODEL_API_KEY_ALIAS] || "").trim();
5742
+ }
5743
+ function positiveMaxTokens(value) {
5744
+ const parsed = Math.floor(Number(value));
5745
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 2048;
5746
+ }
5747
+ function createMetaModelCaller(options = {}) {
5748
+ const fetchImpl = options.fetchImpl ?? fetch;
5749
+ const envSource = options.envSource ?? process.env;
5750
+ const reasoningEffort = options.reasoningEffort ?? "high";
5751
+ return async function callMetaWithMetrics2(prompt, systemPrompt, model, maxTokens, _privacyOptions, signal) {
5752
+ const key = resolveMetaKey(envSource);
5753
+ if (!key) throw new Error(`Missing ${META_MODEL_API_KEY_ENV} for Meta Model API`);
5754
+ const messages = [
5755
+ ...systemPrompt ? [{ role: "system", content: systemPrompt }] : [],
5756
+ { role: "user", content: prompt }
5757
+ ];
5758
+ const response = await fetchImpl(`${META_MODEL_API_BASE_URL}/chat/completions`, {
5759
+ method: "POST",
5760
+ headers: {
5761
+ Authorization: `Bearer ${key}`,
5762
+ "Content-Type": "application/json"
5763
+ },
5764
+ body: JSON.stringify({
5765
+ model: model || META_CONSENSUS_MODEL,
5766
+ messages,
5767
+ max_tokens: positiveMaxTokens(maxTokens),
5768
+ reasoning_effort: reasoningEffort
5769
+ }),
5770
+ signal
5771
+ });
5772
+ const payload = await response.json();
5773
+ if (!response.ok) {
5774
+ const message = String(payload.error?.message || response.statusText || "request failed").slice(0, 500);
5775
+ throw Object.assign(new Error(`Meta Model API ${response.status}: ${message}`), { status: response.status });
5776
+ }
5777
+ const content = payload.choices?.[0]?.message?.content;
5778
+ if (typeof content !== "string" || !content.trim()) {
5779
+ throw new Error(`Meta Model API returned no text (finish=${payload.choices?.[0]?.finish_reason || "unknown"})`);
5780
+ }
5781
+ const inputTokens = Number(payload.usage?.prompt_tokens || 0);
5782
+ const outputTokens = Number(payload.usage?.completion_tokens || 0);
5783
+ return {
5784
+ content,
5785
+ inputTokens,
5786
+ outputTokens,
5787
+ totalTokens: Number(payload.usage?.total_tokens || inputTokens + outputTokens)
5788
+ };
5789
+ };
5790
+ }
5791
+ var callMetaWithMetrics = createMetaModelCaller();
5792
+
5578
5793
  // src/consensus/engine-options.ts
5579
5794
  var AGREEMENT_GATE_ENV_VAR = "VO_CONSENSUS_AGREEMENT_GATE";
5580
5795
  function isTruthyFlag(raw) {
@@ -5621,6 +5836,25 @@ function mapFanOutDiagnostics(fd) {
5621
5836
  refused: fd.refused
5622
5837
  };
5623
5838
  }
5839
+ var SHADOW_SYNTHESIS_ENV_VAR = "VO_CONSENSUS_SHADOW";
5840
+ function shadowEnabled(env) {
5841
+ const raw = (env ?? {})[SHADOW_SYNTHESIS_ENV_VAR];
5842
+ if (raw === void 0) return true;
5843
+ const norm = raw.trim().toLowerCase();
5844
+ return !(norm === "0" || norm === "false" || norm === "no" || norm === "off" || norm === "");
5845
+ }
5846
+ function mapShadowSynthesis(s) {
5847
+ if (s === void 0) return void 0;
5848
+ return {
5849
+ incumbent: { verdict: s.incumbent.verdict, confidence: s.incumbent.confidence, synthesizer: s.incumbent.synthesizer },
5850
+ adaptive: {
5851
+ verdict: s.adaptive.verdict,
5852
+ confidence: s.adaptive.confidence,
5853
+ ...s.adaptive.calibrated_confidence !== void 0 ? { calibrated_confidence: s.adaptive.calibrated_confidence } : {}
5854
+ },
5855
+ agree: s.agree
5856
+ };
5857
+ }
5624
5858
  function mapCitationGrade(cg) {
5625
5859
  if (cg === void 0) return void 0;
5626
5860
  return {
@@ -5761,7 +5995,12 @@ function createEngineConsensusClient(options) {
5761
5995
  const engineOptions = {
5762
5996
  panel,
5763
5997
  ...options.per_model_timeout_ms !== void 0 ? { per_model_timeout_ms: options.per_model_timeout_ms } : {},
5764
- ...agreementGate !== void 0 ? { agreement_gate: agreementGate } : {}
5998
+ ...agreementGate !== void 0 ? { agreement_gate: agreementGate } : {},
5999
+ // Stage A7-shadow: run the adaptive verdict alongside the live one for grading.
6000
+ // Cheap (pure log-odds over already-fetched verdicts; no extra model calls),
6001
+ // PII-free, and never alters the live verdict. ON by default; kill with
6002
+ // VO_CONSENSUS_SHADOW=0. Cold-start has no skill registry → neutral priors.
6003
+ shadow_synthesis: { enabled: shadowEnabled(options.env) }
5765
6004
  };
5766
6005
  const sources = request.source_urls;
5767
6006
  const useSourceGrounded = sources !== void 0 && sources.length > 0 && typeof engine.runSourceGroundedConsensus === "function";
@@ -5817,6 +6056,8 @@ function createEngineConsensusClient(options) {
5817
6056
  ...sourceExtras?.escalation_reason !== void 0 ? { escalation_reason: sourceExtras.escalation_reason } : response.escalation_reason !== void 0 ? { escalation_reason: response.escalation_reason } : {},
5818
6057
  // Feature 1 (agreement-gate) — fan-out diagnostics (additive telemetry).
5819
6058
  ...mapFanOutDiagnostics(response.fan_out_diagnostics) !== void 0 ? { fan_out_diagnostics: mapFanOutDiagnostics(response.fan_out_diagnostics) } : {},
6059
+ // Stage A7-shadow — adaptive-vs-incumbent comparison (PII-free; present iff shadow on).
6060
+ ...mapShadowSynthesis(response.shadow_synthesis) !== void 0 ? { shadow_synthesis: mapShadowSynthesis(response.shadow_synthesis) } : {},
5820
6061
  // Source-grounded additive outputs (Tier-4 features).
5821
6062
  ...useSourceGrounded ? { source_grounded: true } : {},
5822
6063
  ...sourceExtras?.citation_grade !== void 0 ? { citation_grade: sourceExtras.citation_grade } : {},
@@ -5843,7 +6084,8 @@ var DEFAULT_MODELS = {
5843
6084
  // callGeminiWithMetrics; 2.5-pro REJECTS budget 0 ("only works in thinking mode").
5844
6085
  // Flash is also ~10x cheaper. 2026-06-02.
5845
6086
  google: "gemini-2.5-flash",
5846
- deepseek: "deepseek-chat"
6087
+ deepseek: "deepseek-chat",
6088
+ meta: META_CONSENSUS_MODEL
5847
6089
  };
5848
6090
  function probeProviders(env = process.env) {
5849
6091
  const out = [];
@@ -5851,6 +6093,7 @@ function probeProviders(env = process.env) {
5851
6093
  if ((env["OPENAI_API_KEY"] ?? "").trim().length > 0) out.push("openai");
5852
6094
  if ((env["GOOGLE_API_KEY"] ?? "").trim().length > 0) out.push("google");
5853
6095
  if ((env["DEEPSEEK_API_KEY"] ?? "").trim().length > 0) out.push("deepseek");
6096
+ if ((env[META_MODEL_API_KEY_ENV] ?? "").trim().length > 0 || (env[META_MODEL_API_KEY_ALIAS] ?? "").trim().length > 0) out.push("meta");
5854
6097
  return out;
5855
6098
  }
5856
6099
  async function loadFactoryAndCallers(injectedEngine, injectedShared) {
@@ -5896,21 +6139,24 @@ async function tryCreateEngineConsensusClientFromEnvAsync(options = {}) {
5896
6139
  anthropic: loaded.shared.callAnthropicWithMetrics,
5897
6140
  openai: loaded.shared.callOpenAIWithMetrics,
5898
6141
  google: loaded.shared.callGeminiWithMetrics,
5899
- deepseek: loaded.shared.callDeepSeekWithMetrics
6142
+ deepseek: loaded.shared.callDeepSeekWithMetrics,
6143
+ meta: options.metaCaller ?? callMetaWithMetrics
5900
6144
  };
5901
6145
  const modelByProvider = {
5902
6146
  anthropic: options.models?.anthropic ?? DEFAULT_MODELS.anthropic,
5903
6147
  openai: options.models?.openai ?? DEFAULT_MODELS.openai,
5904
6148
  google: options.models?.google ?? DEFAULT_MODELS.google,
5905
- deepseek: options.models?.deepseek ?? DEFAULT_MODELS.deepseek
6149
+ deepseek: options.models?.deepseek ?? DEFAULT_MODELS.deepseek,
6150
+ meta: options.models?.meta ?? DEFAULT_MODELS.meta
5906
6151
  };
6152
+ const adapterEnv = !(env[META_MODEL_API_KEY_ENV] ?? "").trim() && (env[META_MODEL_API_KEY_ALIAS] ?? "").trim() ? { ...env, [META_MODEL_API_KEY_ENV]: env[META_MODEL_API_KEY_ALIAS] } : env;
5907
6153
  const panel = [];
5908
6154
  for (const p of providers) {
5909
6155
  try {
5910
6156
  const adapter = loaded.engine.createAdapter(p, {
5911
6157
  model: modelByProvider[p],
5912
6158
  caller: callerByProvider[p],
5913
- envSource: env
6159
+ envSource: adapterEnv
5914
6160
  });
5915
6161
  panel.push(adapter);
5916
6162
  } catch {