@algosuite/vo-mcp 0.2.0-beta.74 → 0.2.0-beta.76

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
@@ -1614,8 +1614,8 @@ async function acquireMemorySyncLock(options) {
1614
1614
  const waitMs = positiveOr(options.waitMs, DEFAULT_LOCK_WAIT_MS);
1615
1615
  const ttlMs = positiveOr(options.ttlMs, DEFAULT_LOCK_TTL_MS);
1616
1616
  const now = options.now ?? Date.now;
1617
- const sleep = options.sleep ?? ((ms) => new Promise((resolve3) => {
1618
- setTimeout(resolve3, ms);
1617
+ const sleep = options.sleep ?? ((ms) => new Promise((resolve4) => {
1618
+ setTimeout(resolve4, ms);
1619
1619
  }));
1620
1620
  const isProcessAlive = options.isProcessAlive ?? defaultIsProcessAlive;
1621
1621
  const thisHost = hostname();
@@ -2170,8 +2170,8 @@ import { existsSync as existsSync8, readdirSync as readdirSync5, readFileSync as
2170
2170
  function extractMemoryTitle(fileName, content) {
2171
2171
  const frontmatter = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
2172
2172
  if (frontmatter) {
2173
- const description24 = frontmatter[1].match(/^description:\s*(.+)$/m);
2174
- if (description24 && description24[1].trim()) return description24[1].trim().slice(0, 200);
2173
+ const description25 = frontmatter[1].match(/^description:\s*(.+)$/m);
2174
+ if (description25 && description25[1].trim()) return description25[1].trim().slice(0, 200);
2175
2175
  }
2176
2176
  const heading = content.match(/^#\s+(.+)$/m);
2177
2177
  if (heading && heading[1].trim()) return heading[1].trim().slice(0, 200);
@@ -2458,7 +2458,7 @@ var init_sync_config = __esm({
2458
2458
  // src/cli.ts
2459
2459
  import { homedir as homedir9, hostname as hostname2 } from "node:os";
2460
2460
  import { randomUUID as randomUUID6 } from "node:crypto";
2461
- import { join as join15 } from "node:path";
2461
+ import { join as join16 } from "node:path";
2462
2462
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2463
2463
 
2464
2464
  // src/server.ts
@@ -6780,9 +6780,9 @@ function resolveWindowsClaudeExecutable({
6780
6780
 
6781
6781
  // src/swarm/successor-windows-exe.ts
6782
6782
  var resolveWindowsClaudeExe = (bin, env) => resolveWindowsClaudeExecutable({ bin, env });
6783
- function resolveNativeWindowsExecutable(bin, env = process.env, resolve3 = resolveWindowsClaudeExe) {
6783
+ function resolveNativeWindowsExecutable(bin, env = process.env, resolve4 = resolveWindowsClaudeExe) {
6784
6784
  try {
6785
- return { ok: true, bin: resolve3(bin, env) };
6785
+ return { ok: true, bin: resolve4(bin, env) };
6786
6786
  } catch (error) {
6787
6787
  const message = error instanceof Error ? error.message : String(error);
6788
6788
  return {
@@ -6835,7 +6835,7 @@ function checkSuccessorLiveness(child, logPath, config, deps = {}) {
6835
6835
  const killChild = deps.killChild ?? defaultKillChild;
6836
6836
  const outputGateEnabled = Number.isFinite(config.noOutputMs) && config.noOutputMs > 0;
6837
6837
  const startedAt = now();
6838
- return new Promise((resolve3) => {
6838
+ return new Promise((resolve4) => {
6839
6839
  let settled = false;
6840
6840
  let pollTimer = null;
6841
6841
  const onExit = (code, signal) => {
@@ -6860,7 +6860,7 @@ function checkSuccessorLiveness(child, logPath, config, deps = {}) {
6860
6860
  } catch {
6861
6861
  }
6862
6862
  }
6863
- resolve3(result);
6863
+ resolve4(result);
6864
6864
  };
6865
6865
  if (typeof child.exitCode === "number" || typeof child.signalCode === "string" && child.signalCode.length > 0) {
6866
6866
  finish({
@@ -7654,7 +7654,7 @@ ${FRONTMATTER_DELIMITER}
7654
7654
  ${FRONTMATTER_DELIMITER}
7655
7655
  `.length);
7656
7656
  let name = "";
7657
- let description24 = "";
7657
+ let description25 = "";
7658
7658
  for (const line of frontmatterText.split("\n")) {
7659
7659
  const trimmed = line.trim();
7660
7660
  if (trimmed.length === 0) continue;
@@ -7663,15 +7663,15 @@ ${FRONTMATTER_DELIMITER}
7663
7663
  const key = trimmed.slice(0, colonIdx).trim();
7664
7664
  const value = trimmed.slice(colonIdx + 1).trim();
7665
7665
  if (key === "name") name = value;
7666
- else if (key === "description") description24 = value;
7666
+ else if (key === "description") description25 = value;
7667
7667
  }
7668
7668
  if (name.length === 0) {
7669
7669
  throw new InvalidSkillFrontmatterError(sourcePath, 'missing required field "name"');
7670
7670
  }
7671
- if (description24.length === 0) {
7671
+ if (description25.length === 0) {
7672
7672
  throw new InvalidSkillFrontmatterError(sourcePath, 'missing required field "description"');
7673
7673
  }
7674
- return { name, description: description24, body };
7674
+ return { name, description: description25, body };
7675
7675
  }
7676
7676
  function loadSkillsFromDir(skillsDir) {
7677
7677
  const entries = readdirSync6(skillsDir);
@@ -7692,8 +7692,8 @@ function loadSkillsFromDir(skillsDir) {
7692
7692
  } catch {
7693
7693
  continue;
7694
7694
  }
7695
- const { name, description: description24, body } = parseFrontmatter(raw, skillFile);
7696
- skills.push({ name, description: description24, body, sourcePath: skillFile });
7695
+ const { name, description: description25, body } = parseFrontmatter(raw, skillFile);
7696
+ skills.push({ name, description: description25, body, sourcePath: skillFile });
7697
7697
  }
7698
7698
  return [...skills].sort((a, b) => a.name.localeCompare(b.name));
7699
7699
  }
@@ -7808,6 +7808,104 @@ async function handleSkillGet(_deps, rawInput) {
7808
7808
  });
7809
7809
  }
7810
7810
 
7811
+ // src/tools/action-catalog.ts
7812
+ init_common();
7813
+ import { existsSync as existsSync11, statSync as statSync8 } from "node:fs";
7814
+ import { dirname as dirname6, isAbsolute as isAbsolute2, join as join14, resolve as resolve3 } from "node:path";
7815
+ import { pathToFileURL } from "node:url";
7816
+ var TOOL_NAME24 = "vo_action_catalog_lookup";
7817
+ var inputSchema24 = {
7818
+ type: "object",
7819
+ properties: {
7820
+ product: {
7821
+ type: "string",
7822
+ description: `Optional product key (e.g. "tax", "news"). Lists that product's actions. Ignored when actionId is set.`
7823
+ },
7824
+ actionId: {
7825
+ type: "string",
7826
+ description: 'Optional fully-qualified action id (e.g. "tax:ask-advisor"). Looks up exactly one action.'
7827
+ }
7828
+ },
7829
+ additionalProperties: false
7830
+ };
7831
+ var description24 = 'Read-only lookup over the HQ agent-executor ACTION_CATALOG (product -> callable action list). Call with no arguments to list every product and its action count, with `product` to list that product\'s actions, or with `actionId` to look up one action by id. An unknown actionId returns a named not-found result (reason "unknown_action_id" or "unknown_product"), never a throw or a silently empty result. Returns `catalog_available: false` when run outside a Nexus monorepo checkout.';
7832
+ function isToolInput23(v) {
7833
+ if (typeof v !== "object" || v === null) return false;
7834
+ const obj = v;
7835
+ if ("product" in obj && obj.product !== void 0 && typeof obj.product !== "string") return false;
7836
+ if ("actionId" in obj && obj.actionId !== void 0 && typeof obj.actionId !== "string") return false;
7837
+ return true;
7838
+ }
7839
+ var MAX_WALK_UP_LEVELS2 = 8;
7840
+ var RELATIVE_MODULE_PATH = ["scripts", "virtual-office", "action-catalog-data.mjs"];
7841
+ function resolveActionCatalogModulePath(env = process.env, startDir = process.cwd()) {
7842
+ const override = env.VO_ACTION_CATALOG_MODULE;
7843
+ if (typeof override === "string" && override.length > 0) {
7844
+ const abs = isAbsolute2(override) ? override : resolve3(startDir, override);
7845
+ return existsSync11(abs) && statSync8(abs).isFile() ? abs : null;
7846
+ }
7847
+ let dir = resolve3(startDir);
7848
+ for (let i = 0; i < MAX_WALK_UP_LEVELS2; i += 1) {
7849
+ const candidate = join14(dir, ...RELATIVE_MODULE_PATH);
7850
+ if (existsSync11(candidate) && statSync8(candidate).isFile()) return candidate;
7851
+ const parent = dirname6(dir);
7852
+ if (parent === dir) break;
7853
+ dir = parent;
7854
+ }
7855
+ return null;
7856
+ }
7857
+ var cachedCatalog = null;
7858
+ async function loadCatalogModule(refresh) {
7859
+ if (!refresh && cachedCatalog !== null) return cachedCatalog;
7860
+ const modulePath = resolveActionCatalogModulePath();
7861
+ if (modulePath === null) {
7862
+ cachedCatalog = { modulePath: null, mod: null };
7863
+ return cachedCatalog;
7864
+ }
7865
+ const mod = await import(pathToFileURL(modulePath).href);
7866
+ cachedCatalog = { modulePath, mod };
7867
+ return cachedCatalog;
7868
+ }
7869
+ async function handleActionCatalogLookup(_deps, rawInput, _signal) {
7870
+ if (!isToolInput23(rawInput)) {
7871
+ throw invalidParams(TOOL_NAME24, 'invalid input. Optional fields: "product" (string), "actionId" (string).');
7872
+ }
7873
+ const { modulePath, mod } = await loadCatalogModule(false);
7874
+ if (mod === null) {
7875
+ return jsonContent({
7876
+ catalog_available: false,
7877
+ unavailable_reason: "scripts/virtual-office/action-catalog-data.mjs was not found. Set VO_ACTION_CATALOG_MODULE or run inside a Nexus monorepo checkout.",
7878
+ module_path: modulePath
7879
+ });
7880
+ }
7881
+ if (rawInput.actionId) {
7882
+ const lookup = mod.findAction(rawInput.actionId);
7883
+ return jsonContent({ catalog_available: true, module_path: modulePath, lookup });
7884
+ }
7885
+ if (rawInput.product) {
7886
+ const actions = mod.ACTION_CATALOG[rawInput.product];
7887
+ if (!actions) {
7888
+ return jsonContent({
7889
+ catalog_available: true,
7890
+ module_path: modulePath,
7891
+ product: rawInput.product,
7892
+ found: false,
7893
+ reason: "unknown_product",
7894
+ known_products: Object.keys(mod.ACTION_CATALOG).sort()
7895
+ });
7896
+ }
7897
+ return jsonContent({
7898
+ catalog_available: true,
7899
+ module_path: modulePath,
7900
+ product: rawInput.product,
7901
+ found: true,
7902
+ actions
7903
+ });
7904
+ }
7905
+ const products = Object.entries(mod.ACTION_CATALOG).map(([key, actions]) => ({ product: key, action_count: actions.length })).sort((a, b) => a.product.localeCompare(b.product));
7906
+ return jsonContent({ catalog_available: true, module_path: modulePath, products });
7907
+ }
7908
+
7811
7909
  // src/server.ts
7812
7910
  function buildToolRegistry() {
7813
7911
  return {
@@ -8058,6 +8156,14 @@ function buildToolRegistry() {
8058
8156
  inputSchema: getInputSchema
8059
8157
  },
8060
8158
  handler: handleSkillGet
8159
+ },
8160
+ [TOOL_NAME24]: {
8161
+ definition: {
8162
+ name: TOOL_NAME24,
8163
+ description: description24,
8164
+ inputSchema: inputSchema24
8165
+ },
8166
+ handler: handleActionCatalogLookup
8061
8167
  }
8062
8168
  };
8063
8169
  }
@@ -8113,7 +8219,7 @@ function createServer(options) {
8113
8219
  // src/cache/sqlite-cache.ts
8114
8220
  import { createHash as createHash4 } from "node:crypto";
8115
8221
  import { chmodSync as chmodSync3, mkdirSync as mkdirSync7 } from "node:fs";
8116
- import { dirname as dirname6 } from "node:path";
8222
+ import { dirname as dirname7 } from "node:path";
8117
8223
  import { DatabaseSync } from "node:sqlite";
8118
8224
 
8119
8225
  // src/cache/canonicalize.ts
@@ -8158,7 +8264,7 @@ function normalizeString(s) {
8158
8264
  function createSqliteCache(options) {
8159
8265
  const fileBacked = options.dbPath !== ":memory:";
8160
8266
  if (fileBacked) {
8161
- mkdirSync7(dirname6(options.dbPath), { recursive: true, mode: 448 });
8267
+ mkdirSync7(dirname7(options.dbPath), { recursive: true, mode: 448 });
8162
8268
  }
8163
8269
  const versionNamespace = options.cacheVersionNamespace ?? "";
8164
8270
  const db = new DatabaseSync(options.dbPath);
@@ -8959,20 +9065,20 @@ function createConsensusFallbackClient(primary, fallback, options = {}) {
8959
9065
  }
8960
9066
 
8961
9067
  // src/consensus/shadow-client.ts
8962
- import { appendFileSync as appendFileSync2, chmodSync as chmodSync4, mkdirSync as mkdirSync8, renameSync, statSync as statSync8 } from "node:fs";
9068
+ import { appendFileSync as appendFileSync2, chmodSync as chmodSync4, mkdirSync as mkdirSync8, renameSync, statSync as statSync9 } from "node:fs";
8963
9069
  import { homedir as homedir8 } from "node:os";
8964
- import { dirname as dirname7, join as join14 } from "node:path";
9070
+ import { dirname as dirname8, join as join15 } from "node:path";
8965
9071
  var DEFAULT_SHADOW_TIMEOUT_MS = 2e4;
8966
9072
  var SHADOW_RECEIPT_MAX_BYTES = 20 * 1024 * 1024;
8967
9073
  function defaultShadowReceiptPath(env = process.env) {
8968
9074
  const p = (env["VO_MCP_MOAT_SHADOW_PATH"] ?? "").trim();
8969
- return p || join14(homedir8(), ".claude", "vo-mcp-moat-shadow.jsonl");
9075
+ return p || join15(homedir8(), ".claude", "vo-mcp-moat-shadow.jsonl");
8970
9076
  }
8971
9077
  function appendShadowReceipt(receipt, path4 = defaultShadowReceiptPath()) {
8972
9078
  try {
8973
- mkdirSync8(dirname7(path4), { recursive: true, mode: 448 });
9079
+ mkdirSync8(dirname8(path4), { recursive: true, mode: 448 });
8974
9080
  try {
8975
- if (statSync8(path4).size > SHADOW_RECEIPT_MAX_BYTES) renameSync(path4, `${path4}.1`);
9081
+ if (statSync9(path4).size > SHADOW_RECEIPT_MAX_BYTES) renameSync(path4, `${path4}.1`);
8976
9082
  } catch {
8977
9083
  }
8978
9084
  appendFileSync2(path4, `${JSON.stringify(receipt)}
@@ -9173,7 +9279,7 @@ async function runLogin(opts = {}) {
9173
9279
  const nowIso = opts.nowIso ?? (() => (/* @__PURE__ */ new Date()).toISOString());
9174
9280
  const openBrowser = opts.openBrowser ?? defaultOpenBrowser;
9175
9281
  const state = randomBytes(32).toString("base64url");
9176
- return new Promise((resolve3, reject) => {
9282
+ return new Promise((resolve4, reject) => {
9177
9283
  let settled = false;
9178
9284
  const finish = (err, result) => {
9179
9285
  if (settled) return;
@@ -9181,7 +9287,7 @@ async function runLogin(opts = {}) {
9181
9287
  clearTimeout(timer);
9182
9288
  server.close();
9183
9289
  if (err) reject(err);
9184
- else resolve3(result);
9290
+ else resolve4(result);
9185
9291
  };
9186
9292
  const server = createServer2((req, res) => {
9187
9293
  const url = new URL(req.url ?? "/", "http://127.0.0.1");
@@ -9296,7 +9402,7 @@ init_common();
9296
9402
  function defaultCacheDbPath() {
9297
9403
  const env = process.env["VO_MCP_DB_PATH"];
9298
9404
  if (env && env.length > 0) return env;
9299
- return join15(homedir9(), ".claude", "vo-mcp-cache.db");
9405
+ return join16(homedir9(), ".claude", "vo-mcp-cache.db");
9300
9406
  }
9301
9407
  async function probeEngineVersion() {
9302
9408
  try {
@@ -9463,11 +9569,11 @@ if (process.argv[2] === "login") {
9463
9569
  const appendSyncLog = async (line) => {
9464
9570
  try {
9465
9571
  const { appendFileSync: appendFileSync3, mkdirSync: mkdirSync9 } = await import("node:fs");
9466
- const { join: join16 } = await import("node:path");
9572
+ const { join: join17 } = await import("node:path");
9467
9573
  const { homedir: homedir10 } = await import("node:os");
9468
- const dir = join16(homedir10(), ".claude");
9574
+ const dir = join17(homedir10(), ".claude");
9469
9575
  mkdirSync9(dir, { recursive: true });
9470
- appendFileSync3(join16(dir, "vo-mcp-sync.log"), `${line}
9576
+ appendFileSync3(join17(dir, "vo-mcp-sync.log"), `${line}
9471
9577
  `, "utf8");
9472
9578
  } catch {
9473
9579
  }