@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/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);
@@ -6178,6 +6312,10 @@ function createEngineConsensusClient(options) {
6178
6312
  ...mapFanOutDiagnostics(response.fan_out_diagnostics) !== void 0 ? { fan_out_diagnostics: mapFanOutDiagnostics(response.fan_out_diagnostics) } : {},
6179
6313
  // Stage A7-shadow — adaptive-vs-incumbent comparison (PII-free; present iff shadow on).
6180
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 } : {},
6181
6319
  // Source-grounded additive outputs (Tier-4 features).
6182
6320
  ...useSourceGrounded ? { source_grounded: true } : {},
6183
6321
  ...sourceExtras?.citation_grade !== void 0 ? { citation_grade: sourceExtras.citation_grade } : {},