@algosuite/vo-mcp 0.2.0-beta.18 → 0.2.0-beta.19

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
@@ -5402,11 +5402,86 @@ async function handleHqWhiteboardRead(_deps, rawInput, signal) {
5402
5402
  }
5403
5403
 
5404
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";
5405
+ import { existsSync as existsSync6, statSync as statSync5 } from "node:fs";
5406
+ import { dirname as dirname5, isAbsolute, join as join9, resolve as resolve2 } from "node:path";
5407
+
5408
+ // ../skill-registry/src/loader.ts
5409
+ import { readdirSync as readdirSync5, readFileSync as readFileSync8, statSync as statSync4 } from "node:fs";
5410
+ import { join as join8 } from "node:path";
5411
+ var InvalidSkillFrontmatterError = class extends Error {
5412
+ constructor(skillFile, reason) {
5413
+ super(`Invalid frontmatter in ${skillFile}: ${reason}`);
5414
+ this.skillFile = skillFile;
5415
+ this.reason = reason;
5416
+ }
5417
+ skillFile;
5418
+ reason;
5419
+ name = "InvalidSkillFrontmatterError";
5420
+ };
5421
+ var FRONTMATTER_DELIMITER = "---";
5422
+ function parseFrontmatter(rawInput, sourcePath) {
5423
+ const raw = rawInput.replace(/\r\n/g, "\n");
5424
+ if (!raw.startsWith(`${FRONTMATTER_DELIMITER}
5425
+ `)) {
5426
+ throw new InvalidSkillFrontmatterError(sourcePath, 'file does not start with frontmatter delimiter "---"');
5427
+ }
5428
+ const afterFirst = raw.slice(FRONTMATTER_DELIMITER.length + 1);
5429
+ const closingIdx = afterFirst.indexOf(`
5430
+ ${FRONTMATTER_DELIMITER}
5431
+ `);
5432
+ if (closingIdx === -1) {
5433
+ throw new InvalidSkillFrontmatterError(sourcePath, 'missing closing frontmatter delimiter "---"');
5434
+ }
5435
+ const frontmatterText = afterFirst.slice(0, closingIdx);
5436
+ const body = afterFirst.slice(closingIdx + `
5437
+ ${FRONTMATTER_DELIMITER}
5438
+ `.length);
5439
+ let name = "";
5440
+ let description23 = "";
5441
+ for (const line of frontmatterText.split("\n")) {
5442
+ const trimmed = line.trim();
5443
+ if (trimmed.length === 0) continue;
5444
+ const colonIdx = trimmed.indexOf(":");
5445
+ if (colonIdx === -1) continue;
5446
+ const key = trimmed.slice(0, colonIdx).trim();
5447
+ const value = trimmed.slice(colonIdx + 1).trim();
5448
+ if (key === "name") name = value;
5449
+ else if (key === "description") description23 = value;
5450
+ }
5451
+ if (name.length === 0) {
5452
+ throw new InvalidSkillFrontmatterError(sourcePath, 'missing required field "name"');
5453
+ }
5454
+ if (description23.length === 0) {
5455
+ throw new InvalidSkillFrontmatterError(sourcePath, 'missing required field "description"');
5456
+ }
5457
+ return { name, description: description23, body };
5458
+ }
5459
+ function loadSkillsFromDir(skillsDir) {
5460
+ const entries = readdirSync5(skillsDir);
5461
+ const skills = [];
5462
+ for (const entry of entries) {
5463
+ const entryPath = join8(skillsDir, entry);
5464
+ let stat;
5465
+ try {
5466
+ stat = statSync4(entryPath);
5467
+ } catch {
5468
+ continue;
5469
+ }
5470
+ if (!stat.isDirectory()) continue;
5471
+ const skillFile = join8(entryPath, "SKILL.md");
5472
+ let raw;
5473
+ try {
5474
+ raw = readFileSync8(skillFile, "utf8");
5475
+ } catch {
5476
+ continue;
5477
+ }
5478
+ const { name, description: description23, body } = parseFrontmatter(raw, skillFile);
5479
+ skills.push({ name, description: description23, body, sourcePath: skillFile });
5480
+ }
5481
+ return [...skills].sort((a, b) => a.name.localeCompare(b.name));
5482
+ }
5483
+
5484
+ // src/tools/skills/skill-corpus.ts
5410
5485
  var LIST_TOOL_NAME = "vo_skill_list";
5411
5486
  var GET_TOOL_NAME = "vo_skill_get";
5412
5487
  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.";
@@ -5437,12 +5512,12 @@ function resolveSkillsDir(env = process.env, startDir = process.cwd()) {
5437
5512
  const override = env.VO_SKILLS_DIR;
5438
5513
  if (typeof override === "string" && override.length > 0) {
5439
5514
  const abs = isAbsolute(override) ? override : resolve2(startDir, override);
5440
- return existsSync6(abs) && statSync4(abs).isDirectory() ? abs : null;
5515
+ return existsSync6(abs) && statSync5(abs).isDirectory() ? abs : null;
5441
5516
  }
5442
5517
  let dir = resolve2(startDir);
5443
5518
  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;
5519
+ const candidate = join9(dir, ".claude", "skills");
5520
+ if (existsSync6(candidate) && statSync5(candidate).isDirectory()) return candidate;
5446
5521
  const parent = dirname5(dir);
5447
5522
  if (parent === dir) break;
5448
5523
  dir = parent;
@@ -6044,6 +6119,30 @@ function createMetaModelCaller(options = {}) {
6044
6119
  }
6045
6120
  var callMetaWithMetrics = createMetaModelCaller();
6046
6121
 
6122
+ // src/consensus/consensus-panel.ts
6123
+ var VO_MCP_CONSENSUS_PANEL = {
6124
+ anthropic: "claude-opus-4-7",
6125
+ openai: "gpt-5",
6126
+ // gemini-2.5-FLASH (not -pro): flash accepts the default thinkingBudget=0 from
6127
+ // callGeminiWithMetrics; 2.5-pro REJECTS budget 0 ("only works in thinking mode").
6128
+ // Flash is also ~10x cheaper. 2026-06-02.
6129
+ google: "gemini-2.5-flash",
6130
+ deepseek: "deepseek-chat",
6131
+ // Muse Spark identity is owned by meta-model-caller.ts (single source of
6132
+ // truth for the meta slot); re-exported here so the panel stays complete.
6133
+ meta: META_CONSENSUS_MODEL
6134
+ };
6135
+ function getVoMcpConsensusPanel(panel = VO_MCP_CONSENSUS_PANEL) {
6136
+ for (const [provider, modelId] of Object.entries(panel)) {
6137
+ if (typeof modelId !== "string" || modelId.trim().length === 0) {
6138
+ throw new Error(
6139
+ `getVoMcpConsensusPanel: panel slot "${provider}" has a missing or blank model ID`
6140
+ );
6141
+ }
6142
+ }
6143
+ return panel;
6144
+ }
6145
+
6047
6146
  // src/consensus/engine-options.ts
6048
6147
  var AGREEMENT_GATE_ENV_VAR = "VO_CONSENSUS_AGREEMENT_GATE";
6049
6148
  function isTruthyFlag(raw) {
@@ -6331,20 +6430,7 @@ function createEngineConsensusClient(options) {
6331
6430
  }
6332
6431
  };
6333
6432
  }
6334
- var DEFAULT_MODELS = {
6335
- // These ids match the strategic-roadmap §4 `newsStandard` / `newsDeep` panel
6336
- // intent — current production model ids. Per handoff §C-3 these MUST come
6337
- // from `CONSENSUS_PANELS` in `functions-shared/shared-model-resolvers.ts`
6338
- // for V1; placeholder defaults here keep Phase 2 Lane A non-blocking.
6339
- anthropic: "claude-opus-4-7",
6340
- openai: "gpt-5",
6341
- // gemini-2.5-FLASH (not -pro): flash accepts the default thinkingBudget=0 from
6342
- // callGeminiWithMetrics; 2.5-pro REJECTS budget 0 ("only works in thinking mode").
6343
- // Flash is also ~10x cheaper. 2026-06-02.
6344
- google: "gemini-2.5-flash",
6345
- deepseek: "deepseek-chat",
6346
- meta: META_CONSENSUS_MODEL
6347
- };
6433
+ var DEFAULT_MODELS = getVoMcpConsensusPanel();
6348
6434
  function probeProviders(env = process.env) {
6349
6435
  const out = [];
6350
6436
  if ((env["ANTHROPIC_API_KEY"] ?? "").trim().length > 0) out.push("anthropic");