@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/cli.js CHANGED
@@ -1625,7 +1625,7 @@ var init_sync_config = __esm({
1625
1625
  // src/cli.ts
1626
1626
  import { homedir as homedir6, hostname } from "node:os";
1627
1627
  import { randomUUID as randomUUID5 } from "node:crypto";
1628
- import { join as join8 } from "node:path";
1628
+ import { join as join9 } from "node:path";
1629
1629
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
1630
1630
 
1631
1631
  // src/server.ts
@@ -2481,7 +2481,11 @@ async function handleConsensusJudgment(deps, rawInput, signal) {
2481
2481
  ...engineResult.low_confidence_sources !== void 0 ? { low_confidence_sources: engineResult.low_confidence_sources } : {},
2482
2482
  // Escalation (from citation grade or human-tiebreak synthesizer).
2483
2483
  ...engineResult.escalation_required !== void 0 ? { escalation_required: engineResult.escalation_required } : {},
2484
- ...engineResult.escalation_reason !== void 0 ? { escalation_reason: engineResult.escalation_reason } : {}
2484
+ ...engineResult.escalation_reason !== void 0 ? { escalation_reason: engineResult.escalation_reason } : {},
2485
+ // Critique-uptake (2026-07-20 red-team fix) — the engine computes this
2486
+ // on every call; this spread closes the gap where the visibility report
2487
+ // was itself silently dropped at the payload boundary.
2488
+ ...engineResult.critique_uptake !== void 0 ? { critique_uptake: engineResult.critique_uptake } : {}
2485
2489
  };
2486
2490
  const envelope = {
2487
2491
  tool: TOOL_NAME4,
@@ -5741,6 +5745,121 @@ async function handleHqWhiteboardRead(_deps, rawInput, signal) {
5741
5745
  return jsonContent(await callWhiteboard("GET", input, signal));
5742
5746
  }
5743
5747
 
5748
+ // src/tools/skills/skill-corpus.ts
5749
+ init_common();
5750
+ import { existsSync as existsSync6, statSync as statSync4 } from "node:fs";
5751
+ import { dirname as dirname5, isAbsolute, join as join8, resolve as resolve2 } from "node:path";
5752
+ import {
5753
+ loadSkillsFromDir
5754
+ } from "@algosuite/skill-registry";
5755
+ var LIST_TOOL_NAME = "vo_skill_list";
5756
+ var GET_TOOL_NAME = "vo_skill_get";
5757
+ 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.";
5758
+ 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.";
5759
+ var listInputSchema = {
5760
+ type: "object",
5761
+ properties: {
5762
+ refresh: {
5763
+ type: "boolean",
5764
+ description: "Re-scan the skills directory instead of using the cached corpus."
5765
+ }
5766
+ },
5767
+ required: []
5768
+ };
5769
+ var getInputSchema = {
5770
+ type: "object",
5771
+ properties: {
5772
+ name: {
5773
+ type: "string",
5774
+ description: "Skill name exactly as returned by vo_skill_list."
5775
+ }
5776
+ },
5777
+ required: ["name"]
5778
+ };
5779
+ var MAX_WALK_UP_LEVELS = 8;
5780
+ var cachedCorpus = null;
5781
+ function resolveSkillsDir(env = process.env, startDir = process.cwd()) {
5782
+ const override = env.VO_SKILLS_DIR;
5783
+ if (typeof override === "string" && override.length > 0) {
5784
+ const abs = isAbsolute(override) ? override : resolve2(startDir, override);
5785
+ return existsSync6(abs) && statSync4(abs).isDirectory() ? abs : null;
5786
+ }
5787
+ let dir = resolve2(startDir);
5788
+ for (let i = 0; i < MAX_WALK_UP_LEVELS; i += 1) {
5789
+ const candidate = join8(dir, ".claude", "skills");
5790
+ if (existsSync6(candidate) && statSync4(candidate).isDirectory()) return candidate;
5791
+ const parent = dirname5(dir);
5792
+ if (parent === dir) break;
5793
+ dir = parent;
5794
+ }
5795
+ return null;
5796
+ }
5797
+ function loadCorpus() {
5798
+ const skillsDir = resolveSkillsDir();
5799
+ if (skillsDir === null) {
5800
+ return {
5801
+ skills: [],
5802
+ skillsDir: null,
5803
+ unavailableReason: "No skills directory found. Set VO_SKILLS_DIR or run inside a repo with .claude/skills."
5804
+ };
5805
+ }
5806
+ try {
5807
+ return { skills: loadSkillsFromDir(skillsDir), skillsDir, unavailableReason: null };
5808
+ } catch (err) {
5809
+ const message = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
5810
+ return { skills: [], skillsDir, unavailableReason: message };
5811
+ }
5812
+ }
5813
+ function getCorpus(refresh) {
5814
+ if (refresh || cachedCorpus === null) {
5815
+ cachedCorpus = loadCorpus();
5816
+ }
5817
+ return cachedCorpus;
5818
+ }
5819
+ async function handleSkillList(_deps, rawInput) {
5820
+ const input = rawInput ?? {};
5821
+ const refresh = input.refresh === true;
5822
+ const corpus = getCorpus(refresh);
5823
+ return jsonContent({
5824
+ corpus_available: corpus.unavailableReason === null,
5825
+ skills_dir: corpus.skillsDir,
5826
+ unavailable_reason: corpus.unavailableReason,
5827
+ skill_count: corpus.skills.length,
5828
+ skills: corpus.skills.map((s) => ({ name: s.name, description: s.description }))
5829
+ });
5830
+ }
5831
+ async function handleSkillGet(_deps, rawInput) {
5832
+ const input = rawInput ?? {};
5833
+ if (typeof input.name !== "string" || input.name.trim().length === 0) {
5834
+ throw invalidParams(GET_TOOL_NAME, 'input field "name" (non-empty string) is required');
5835
+ }
5836
+ const requested = input.name.trim();
5837
+ const corpus = getCorpus(false);
5838
+ if (corpus.unavailableReason !== null) {
5839
+ return jsonContent({
5840
+ corpus_available: false,
5841
+ unavailable_reason: corpus.unavailableReason,
5842
+ skill: null
5843
+ });
5844
+ }
5845
+ const skill = corpus.skills.find((s) => s.name === requested);
5846
+ if (skill === void 0) {
5847
+ throw invalidParams(
5848
+ GET_TOOL_NAME,
5849
+ `unknown skill "${requested}". Known skills: ${corpus.skills.map((s) => s.name).join(", ")}`
5850
+ );
5851
+ }
5852
+ return jsonContent({
5853
+ corpus_available: true,
5854
+ skill: {
5855
+ name: skill.name,
5856
+ description: skill.description,
5857
+ instructions: skill.body,
5858
+ source_path: skill.sourcePath
5859
+ }
5860
+ });
5861
+ }
5862
+
5744
5863
  // src/server.ts
5745
5864
  function buildToolRegistry() {
5746
5865
  return {
@@ -5951,6 +6070,22 @@ function buildToolRegistry() {
5951
6070
  inputSchema: readInputSchema
5952
6071
  },
5953
6072
  handler: handleHqWhiteboardRead
6073
+ },
6074
+ [LIST_TOOL_NAME]: {
6075
+ definition: {
6076
+ name: LIST_TOOL_NAME,
6077
+ description: listDescription,
6078
+ inputSchema: listInputSchema
6079
+ },
6080
+ handler: handleSkillList
6081
+ },
6082
+ [GET_TOOL_NAME]: {
6083
+ definition: {
6084
+ name: GET_TOOL_NAME,
6085
+ description: getDescription,
6086
+ inputSchema: getInputSchema
6087
+ },
6088
+ handler: handleSkillGet
5954
6089
  }
5955
6090
  };
5956
6091
  }
@@ -6006,7 +6141,7 @@ function createServer(options) {
6006
6141
  // src/cache/sqlite-cache.ts
6007
6142
  import { createHash as createHash3 } from "node:crypto";
6008
6143
  import { chmodSync as chmodSync3, mkdirSync as mkdirSync5 } from "node:fs";
6009
- import { dirname as dirname5 } from "node:path";
6144
+ import { dirname as dirname6 } from "node:path";
6010
6145
  import { DatabaseSync } from "node:sqlite";
6011
6146
 
6012
6147
  // src/cache/canonicalize.ts
@@ -6051,7 +6186,7 @@ function normalizeString(s) {
6051
6186
  function createSqliteCache(options) {
6052
6187
  const fileBacked = options.dbPath !== ":memory:";
6053
6188
  if (fileBacked) {
6054
- mkdirSync5(dirname5(options.dbPath), { recursive: true, mode: 448 });
6189
+ mkdirSync5(dirname6(options.dbPath), { recursive: true, mode: 448 });
6055
6190
  }
6056
6191
  const versionNamespace = options.cacheVersionNamespace ?? "";
6057
6192
  const db = new DatabaseSync(options.dbPath);
@@ -6243,59 +6378,15 @@ function createNullConsensusEngineClient(reason = NULL_CLIENT_DEFAULT_REASON) {
6243
6378
  }
6244
6379
 
6245
6380
  // src/consensus/meta-model-caller.ts
6246
- var META_MODEL_API_BASE_URL = "https://api.meta.ai/v1";
6247
6381
  var META_CONSENSUS_MODEL = "muse-spark-1.1";
6248
6382
  var META_MODEL_API_KEY_ENV = "MODEL_API_KEY";
6249
6383
  var META_MODEL_API_KEY_ALIAS = "META_API";
6250
- function resolveMetaKey(env) {
6251
- return String(env[META_MODEL_API_KEY_ENV] || env[META_MODEL_API_KEY_ALIAS] || "").trim();
6252
- }
6253
- function positiveMaxTokens(value) {
6254
- const parsed = Math.floor(Number(value));
6255
- return Number.isFinite(parsed) && parsed > 0 ? parsed : 2048;
6256
- }
6257
6384
  function createMetaModelCaller(options = {}) {
6258
- const fetchImpl = options.fetchImpl ?? fetch;
6259
- const envSource = options.envSource ?? process.env;
6260
- const reasoningEffort = options.reasoningEffort ?? "high";
6261
- return async function callMetaWithMetrics2(prompt, systemPrompt, model, maxTokens, _privacyOptions, signal) {
6262
- const key = resolveMetaKey(envSource);
6263
- if (!key) throw new Error(`Missing ${META_MODEL_API_KEY_ENV} for Meta Model API`);
6264
- const messages = [
6265
- ...systemPrompt ? [{ role: "system", content: systemPrompt }] : [],
6266
- { role: "user", content: prompt }
6267
- ];
6268
- const response = await fetchImpl(`${META_MODEL_API_BASE_URL}/chat/completions`, {
6269
- method: "POST",
6270
- headers: {
6271
- Authorization: `Bearer ${key}`,
6272
- "Content-Type": "application/json"
6273
- },
6274
- body: JSON.stringify({
6275
- model: model || META_CONSENSUS_MODEL,
6276
- messages,
6277
- max_tokens: positiveMaxTokens(maxTokens),
6278
- reasoning_effort: reasoningEffort
6279
- }),
6280
- signal
6281
- });
6282
- const payload = await response.json();
6283
- if (!response.ok) {
6284
- const message = String(payload.error?.message || response.statusText || "request failed").slice(0, 500);
6285
- throw Object.assign(new Error(`Meta Model API ${response.status}: ${message}`), { status: response.status });
6286
- }
6287
- const content = payload.choices?.[0]?.message?.content;
6288
- if (typeof content !== "string" || !content.trim()) {
6289
- throw new Error(`Meta Model API returned no text (finish=${payload.choices?.[0]?.finish_reason || "unknown"})`);
6290
- }
6291
- const inputTokens = Number(payload.usage?.prompt_tokens || 0);
6292
- const outputTokens = Number(payload.usage?.completion_tokens || 0);
6293
- return {
6294
- content,
6295
- inputTokens,
6296
- outputTokens,
6297
- totalTokens: Number(payload.usage?.total_tokens || inputTokens + outputTokens)
6298
- };
6385
+ void options;
6386
+ return async function callMetaWithMetrics2() {
6387
+ throw new Error(
6388
+ "Muse Spark direct consensus is disabled. Use an explicit sanitized task capsule through the AlgoSuite Model Firewall."
6389
+ );
6299
6390
  };
6300
6391
  }
6301
6392
  var callMetaWithMetrics = createMetaModelCaller();
@@ -6568,6 +6659,10 @@ function createEngineConsensusClient(options) {
6568
6659
  ...mapFanOutDiagnostics(response.fan_out_diagnostics) !== void 0 ? { fan_out_diagnostics: mapFanOutDiagnostics(response.fan_out_diagnostics) } : {},
6569
6660
  // Stage A7-shadow — adaptive-vs-incumbent comparison (PII-free; present iff shadow on).
6570
6661
  ...mapShadowSynthesis(response.shadow_synthesis) !== void 0 ? { shadow_synthesis: mapShadowSynthesis(response.shadow_synthesis) } : {},
6662
+ // Critique-uptake (2026-07-20 red-team fix) — verifier-critique
6663
+ // visibility report; previously computed by the engine on every
6664
+ // call but dropped at this boundary.
6665
+ ...response.critique_uptake !== void 0 ? { critique_uptake: response.critique_uptake } : {},
6571
6666
  // Source-grounded additive outputs (Tier-4 features).
6572
6667
  ...useSourceGrounded ? { source_grounded: true } : {},
6573
6668
  ...sourceExtras?.citation_grade !== void 0 ? { citation_grade: sourceExtras.citation_grade } : {},
@@ -6602,8 +6697,6 @@ function probeProviders(env = process.env) {
6602
6697
  if ((env["ANTHROPIC_API_KEY"] ?? "").trim().length > 0) out.push("anthropic");
6603
6698
  if ((env["OPENAI_API_KEY"] ?? "").trim().length > 0) out.push("openai");
6604
6699
  if ((env["GOOGLE_API_KEY"] ?? "").trim().length > 0) out.push("google");
6605
- if ((env["DEEPSEEK_API_KEY"] ?? "").trim().length > 0) out.push("deepseek");
6606
- if ((env[META_MODEL_API_KEY_ENV] ?? "").trim().length > 0 || (env[META_MODEL_API_KEY_ALIAS] ?? "").trim().length > 0) out.push("meta");
6607
6700
  return out;
6608
6701
  }
6609
6702
  async function loadFactoryAndCallers(injectedEngine, injectedShared) {
@@ -6950,7 +7043,7 @@ async function runLogin(opts = {}) {
6950
7043
  const nowIso = opts.nowIso ?? (() => (/* @__PURE__ */ new Date()).toISOString());
6951
7044
  const openBrowser = opts.openBrowser ?? defaultOpenBrowser;
6952
7045
  const state = randomBytes(32).toString("base64url");
6953
- return new Promise((resolve2, reject) => {
7046
+ return new Promise((resolve3, reject) => {
6954
7047
  let settled = false;
6955
7048
  const finish = (err, result) => {
6956
7049
  if (settled) return;
@@ -6958,7 +7051,7 @@ async function runLogin(opts = {}) {
6958
7051
  clearTimeout(timer);
6959
7052
  server.close();
6960
7053
  if (err) reject(err);
6961
- else resolve2(result);
7054
+ else resolve3(result);
6962
7055
  };
6963
7056
  const server = createServer2((req, res) => {
6964
7057
  const url = new URL(req.url ?? "/", "http://127.0.0.1");
@@ -7073,7 +7166,7 @@ init_common();
7073
7166
  function defaultCacheDbPath() {
7074
7167
  const env = process.env["VO_MCP_DB_PATH"];
7075
7168
  if (env && env.length > 0) return env;
7076
- return join8(homedir6(), ".claude", "vo-mcp-cache.db");
7169
+ return join9(homedir6(), ".claude", "vo-mcp-cache.db");
7077
7170
  }
7078
7171
  async function probeEngineVersion() {
7079
7172
  try {