@algosuite/vo-mcp 0.2.0-beta.16 → 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/index.js CHANGED
@@ -2064,7 +2064,11 @@ async function handleConsensusJudgment(deps, rawInput, signal) {
2064
2064
  ...engineResult.low_confidence_sources !== void 0 ? { low_confidence_sources: engineResult.low_confidence_sources } : {},
2065
2065
  // Escalation (from citation grade or human-tiebreak synthesizer).
2066
2066
  ...engineResult.escalation_required !== void 0 ? { escalation_required: engineResult.escalation_required } : {},
2067
- ...engineResult.escalation_reason !== void 0 ? { escalation_reason: engineResult.escalation_reason } : {}
2067
+ ...engineResult.escalation_reason !== void 0 ? { escalation_reason: engineResult.escalation_reason } : {},
2068
+ // Critique-uptake (2026-07-20 red-team fix) — the engine computes this
2069
+ // on every call; this spread closes the gap where the visibility report
2070
+ // was itself silently dropped at the payload boundary.
2071
+ ...engineResult.critique_uptake !== void 0 ? { critique_uptake: engineResult.critique_uptake } : {}
2068
2072
  };
2069
2073
  const envelope = {
2070
2074
  tool: TOOL_NAME4,
@@ -5397,6 +5401,120 @@ async function handleHqWhiteboardRead(_deps, rawInput, signal) {
5397
5401
  return jsonContent(await callWhiteboard("GET", input, signal));
5398
5402
  }
5399
5403
 
5404
+ // src/tools/skills/skill-corpus.ts
5405
+ import { existsSync as existsSync6, statSync as statSync4 } from "node:fs";
5406
+ import { dirname as dirname5, isAbsolute, join as join8, resolve as resolve2 } from "node:path";
5407
+ import {
5408
+ loadSkillsFromDir
5409
+ } from "@algosuite/skill-registry";
5410
+ var LIST_TOOL_NAME = "vo_skill_list";
5411
+ var GET_TOOL_NAME = "vo_skill_get";
5412
+ var listDescription = "List the Algosuite skill corpus (name + trigger description for every skill). Call once near session start to learn which skills exist; then fetch the full instructions for a relevant skill with vo_skill_get. This is the same corpus Claude Code loads natively from .claude/skills \u2014 served over MCP so every vendor works from identical playbooks. Pass refresh:true to re-scan from disk.";
5413
+ var getDescription = "Fetch the full markdown instructions of one Algosuite skill by name. Follow the returned instructions for the current task the same way a native skill invocation would. Use vo_skill_list to discover skill names.";
5414
+ var listInputSchema = {
5415
+ type: "object",
5416
+ properties: {
5417
+ refresh: {
5418
+ type: "boolean",
5419
+ description: "Re-scan the skills directory instead of using the cached corpus."
5420
+ }
5421
+ },
5422
+ required: []
5423
+ };
5424
+ var getInputSchema = {
5425
+ type: "object",
5426
+ properties: {
5427
+ name: {
5428
+ type: "string",
5429
+ description: "Skill name exactly as returned by vo_skill_list."
5430
+ }
5431
+ },
5432
+ required: ["name"]
5433
+ };
5434
+ var MAX_WALK_UP_LEVELS = 8;
5435
+ var cachedCorpus = null;
5436
+ function resolveSkillsDir(env = process.env, startDir = process.cwd()) {
5437
+ const override = env.VO_SKILLS_DIR;
5438
+ if (typeof override === "string" && override.length > 0) {
5439
+ const abs = isAbsolute(override) ? override : resolve2(startDir, override);
5440
+ return existsSync6(abs) && statSync4(abs).isDirectory() ? abs : null;
5441
+ }
5442
+ let dir = resolve2(startDir);
5443
+ for (let i = 0; i < MAX_WALK_UP_LEVELS; i += 1) {
5444
+ const candidate = join8(dir, ".claude", "skills");
5445
+ if (existsSync6(candidate) && statSync4(candidate).isDirectory()) return candidate;
5446
+ const parent = dirname5(dir);
5447
+ if (parent === dir) break;
5448
+ dir = parent;
5449
+ }
5450
+ return null;
5451
+ }
5452
+ function loadCorpus() {
5453
+ const skillsDir = resolveSkillsDir();
5454
+ if (skillsDir === null) {
5455
+ return {
5456
+ skills: [],
5457
+ skillsDir: null,
5458
+ unavailableReason: "No skills directory found. Set VO_SKILLS_DIR or run inside a repo with .claude/skills."
5459
+ };
5460
+ }
5461
+ try {
5462
+ return { skills: loadSkillsFromDir(skillsDir), skillsDir, unavailableReason: null };
5463
+ } catch (err) {
5464
+ const message = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
5465
+ return { skills: [], skillsDir, unavailableReason: message };
5466
+ }
5467
+ }
5468
+ function getCorpus(refresh) {
5469
+ if (refresh || cachedCorpus === null) {
5470
+ cachedCorpus = loadCorpus();
5471
+ }
5472
+ return cachedCorpus;
5473
+ }
5474
+ async function handleSkillList(_deps, rawInput) {
5475
+ const input = rawInput ?? {};
5476
+ const refresh = input.refresh === true;
5477
+ const corpus = getCorpus(refresh);
5478
+ return jsonContent({
5479
+ corpus_available: corpus.unavailableReason === null,
5480
+ skills_dir: corpus.skillsDir,
5481
+ unavailable_reason: corpus.unavailableReason,
5482
+ skill_count: corpus.skills.length,
5483
+ skills: corpus.skills.map((s) => ({ name: s.name, description: s.description }))
5484
+ });
5485
+ }
5486
+ async function handleSkillGet(_deps, rawInput) {
5487
+ const input = rawInput ?? {};
5488
+ if (typeof input.name !== "string" || input.name.trim().length === 0) {
5489
+ throw invalidParams(GET_TOOL_NAME, 'input field "name" (non-empty string) is required');
5490
+ }
5491
+ const requested = input.name.trim();
5492
+ const corpus = getCorpus(false);
5493
+ if (corpus.unavailableReason !== null) {
5494
+ return jsonContent({
5495
+ corpus_available: false,
5496
+ unavailable_reason: corpus.unavailableReason,
5497
+ skill: null
5498
+ });
5499
+ }
5500
+ const skill = corpus.skills.find((s) => s.name === requested);
5501
+ if (skill === void 0) {
5502
+ throw invalidParams(
5503
+ GET_TOOL_NAME,
5504
+ `unknown skill "${requested}". Known skills: ${corpus.skills.map((s) => s.name).join(", ")}`
5505
+ );
5506
+ }
5507
+ return jsonContent({
5508
+ corpus_available: true,
5509
+ skill: {
5510
+ name: skill.name,
5511
+ description: skill.description,
5512
+ instructions: skill.body,
5513
+ source_path: skill.sourcePath
5514
+ }
5515
+ });
5516
+ }
5517
+
5400
5518
  // src/server.ts
5401
5519
  function buildToolRegistry() {
5402
5520
  return {
@@ -5607,6 +5725,22 @@ function buildToolRegistry() {
5607
5725
  inputSchema: readInputSchema
5608
5726
  },
5609
5727
  handler: handleHqWhiteboardRead
5728
+ },
5729
+ [LIST_TOOL_NAME]: {
5730
+ definition: {
5731
+ name: LIST_TOOL_NAME,
5732
+ description: listDescription,
5733
+ inputSchema: listInputSchema
5734
+ },
5735
+ handler: handleSkillList
5736
+ },
5737
+ [GET_TOOL_NAME]: {
5738
+ definition: {
5739
+ name: GET_TOOL_NAME,
5740
+ description: getDescription,
5741
+ inputSchema: getInputSchema
5742
+ },
5743
+ handler: handleSkillGet
5610
5744
  }
5611
5745
  };
5612
5746
  }
@@ -5665,7 +5799,7 @@ function listToolNames() {
5665
5799
  // src/cache/sqlite-cache.ts
5666
5800
  import { createHash as createHash3 } from "node:crypto";
5667
5801
  import { chmodSync as chmodSync3, mkdirSync as mkdirSync5 } from "node:fs";
5668
- import { dirname as dirname5 } from "node:path";
5802
+ import { dirname as dirname6 } from "node:path";
5669
5803
  import { DatabaseSync } from "node:sqlite";
5670
5804
 
5671
5805
  // src/cache/canonicalize.ts
@@ -5710,7 +5844,7 @@ function normalizeString(s) {
5710
5844
  function createSqliteCache(options) {
5711
5845
  const fileBacked = options.dbPath !== ":memory:";
5712
5846
  if (fileBacked) {
5713
- mkdirSync5(dirname5(options.dbPath), { recursive: true, mode: 448 });
5847
+ mkdirSync5(dirname6(options.dbPath), { recursive: true, mode: 448 });
5714
5848
  }
5715
5849
  const versionNamespace = options.cacheVersionNamespace ?? "";
5716
5850
  const db = new DatabaseSync(options.dbPath);
@@ -5897,59 +6031,15 @@ function createNullConsensusEngineClient(reason = NULL_CLIENT_DEFAULT_REASON) {
5897
6031
  import { randomUUID as randomUUID3 } from "node:crypto";
5898
6032
 
5899
6033
  // src/consensus/meta-model-caller.ts
5900
- var META_MODEL_API_BASE_URL = "https://api.meta.ai/v1";
5901
6034
  var META_CONSENSUS_MODEL = "muse-spark-1.1";
5902
6035
  var META_MODEL_API_KEY_ENV = "MODEL_API_KEY";
5903
6036
  var META_MODEL_API_KEY_ALIAS = "META_API";
5904
- function resolveMetaKey(env) {
5905
- return String(env[META_MODEL_API_KEY_ENV] || env[META_MODEL_API_KEY_ALIAS] || "").trim();
5906
- }
5907
- function positiveMaxTokens(value) {
5908
- const parsed = Math.floor(Number(value));
5909
- return Number.isFinite(parsed) && parsed > 0 ? parsed : 2048;
5910
- }
5911
6037
  function createMetaModelCaller(options = {}) {
5912
- const fetchImpl = options.fetchImpl ?? fetch;
5913
- const envSource = options.envSource ?? process.env;
5914
- const reasoningEffort = options.reasoningEffort ?? "high";
5915
- return async function callMetaWithMetrics2(prompt, systemPrompt, model, maxTokens, _privacyOptions, signal) {
5916
- const key = resolveMetaKey(envSource);
5917
- if (!key) throw new Error(`Missing ${META_MODEL_API_KEY_ENV} for Meta Model API`);
5918
- const messages = [
5919
- ...systemPrompt ? [{ role: "system", content: systemPrompt }] : [],
5920
- { role: "user", content: prompt }
5921
- ];
5922
- const response = await fetchImpl(`${META_MODEL_API_BASE_URL}/chat/completions`, {
5923
- method: "POST",
5924
- headers: {
5925
- Authorization: `Bearer ${key}`,
5926
- "Content-Type": "application/json"
5927
- },
5928
- body: JSON.stringify({
5929
- model: model || META_CONSENSUS_MODEL,
5930
- messages,
5931
- max_tokens: positiveMaxTokens(maxTokens),
5932
- reasoning_effort: reasoningEffort
5933
- }),
5934
- signal
5935
- });
5936
- const payload = await response.json();
5937
- if (!response.ok) {
5938
- const message = String(payload.error?.message || response.statusText || "request failed").slice(0, 500);
5939
- throw Object.assign(new Error(`Meta Model API ${response.status}: ${message}`), { status: response.status });
5940
- }
5941
- const content = payload.choices?.[0]?.message?.content;
5942
- if (typeof content !== "string" || !content.trim()) {
5943
- throw new Error(`Meta Model API returned no text (finish=${payload.choices?.[0]?.finish_reason || "unknown"})`);
5944
- }
5945
- const inputTokens = Number(payload.usage?.prompt_tokens || 0);
5946
- const outputTokens = Number(payload.usage?.completion_tokens || 0);
5947
- return {
5948
- content,
5949
- inputTokens,
5950
- outputTokens,
5951
- totalTokens: Number(payload.usage?.total_tokens || inputTokens + outputTokens)
5952
- };
6038
+ void options;
6039
+ return async function callMetaWithMetrics2() {
6040
+ throw new Error(
6041
+ "Muse Spark direct consensus is disabled. Use an explicit sanitized task capsule through the AlgoSuite Model Firewall."
6042
+ );
5953
6043
  };
5954
6044
  }
5955
6045
  var callMetaWithMetrics = createMetaModelCaller();
@@ -6222,6 +6312,10 @@ function createEngineConsensusClient(options) {
6222
6312
  ...mapFanOutDiagnostics(response.fan_out_diagnostics) !== void 0 ? { fan_out_diagnostics: mapFanOutDiagnostics(response.fan_out_diagnostics) } : {},
6223
6313
  // Stage A7-shadow — adaptive-vs-incumbent comparison (PII-free; present iff shadow on).
6224
6314
  ...mapShadowSynthesis(response.shadow_synthesis) !== void 0 ? { shadow_synthesis: mapShadowSynthesis(response.shadow_synthesis) } : {},
6315
+ // Critique-uptake (2026-07-20 red-team fix) — verifier-critique
6316
+ // visibility report; previously computed by the engine on every
6317
+ // call but dropped at this boundary.
6318
+ ...response.critique_uptake !== void 0 ? { critique_uptake: response.critique_uptake } : {},
6225
6319
  // Source-grounded additive outputs (Tier-4 features).
6226
6320
  ...useSourceGrounded ? { source_grounded: true } : {},
6227
6321
  ...sourceExtras?.citation_grade !== void 0 ? { citation_grade: sourceExtras.citation_grade } : {},
@@ -6256,8 +6350,6 @@ function probeProviders(env = process.env) {
6256
6350
  if ((env["ANTHROPIC_API_KEY"] ?? "").trim().length > 0) out.push("anthropic");
6257
6351
  if ((env["OPENAI_API_KEY"] ?? "").trim().length > 0) out.push("openai");
6258
6352
  if ((env["GOOGLE_API_KEY"] ?? "").trim().length > 0) out.push("google");
6259
- if ((env["DEEPSEEK_API_KEY"] ?? "").trim().length > 0) out.push("deepseek");
6260
- if ((env[META_MODEL_API_KEY_ENV] ?? "").trim().length > 0 || (env[META_MODEL_API_KEY_ALIAS] ?? "").trim().length > 0) out.push("meta");
6261
6353
  return out;
6262
6354
  }
6263
6355
  async function loadFactoryAndCallers(injectedEngine, injectedShared) {