@algosuite/vo-mcp 0.2.0-beta.7 → 0.2.0-beta.8

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/bin/vo-mcp CHANGED
@@ -8,7 +8,7 @@
8
8
  * vo-mcp update # update MCP + runner package
9
9
  * vo-mcp login # credential login (browser loopback)
10
10
  * vo-mcp pair # device-code pairing (enter a code in the web)
11
- * vo-mcp runner # agent runner daemon
11
+ * vo-mcp runner # supervised agent runner
12
12
  * vo-mcp runner --install-autostart # register runner to start at login
13
13
  * vo-mcp runner --uninstall-autostart # remove auto-start registration
14
14
  */
@@ -31,9 +31,11 @@ if (command === 'install') {
31
31
  import('../dist/autostart-cli.js').then((m) => m.installAutostartCli());
32
32
  } else if (subcommand === '--uninstall-autostart') {
33
33
  import('../dist/autostart-cli.js').then((m) => m.uninstallAutostartCli());
34
- } else {
35
- // Bring-your-own runner daemon (bundled by scripts/bundle.mjs into dist/).
34
+ } else if (process.argv.includes('--once') || process.argv.includes('--status') || process.argv.includes('--version') || process.argv.includes('-v')) {
35
+ // Direct diagnostic/one-shot mode; remote maintenance uses the supervisor.
36
36
  import('../dist/runner-cli.js');
37
+ } else {
38
+ import('../dist/runner-supervisor.js');
37
39
  }
38
40
  } else {
39
41
  // Default: MCP stdio server
package/dist/cli.js CHANGED
@@ -6280,6 +6280,9 @@ function createClaimClassifier(model, options = {}) {
6280
6280
  };
6281
6281
  }
6282
6282
 
6283
+ // src/constants/consensus-models.ts
6284
+ var XAI_CONSENSUS_MODEL = "grok-4.5";
6285
+
6283
6286
  // src/consensus/engine-client.ts
6284
6287
  function raceAbort(signal) {
6285
6288
  return new Promise((_, reject) => {
@@ -6430,6 +6433,7 @@ var DEFAULT_MODELS = {
6430
6433
  // Flash is also ~10x cheaper. 2026-06-02.
6431
6434
  google: "gemini-2.5-flash",
6432
6435
  deepseek: "deepseek-chat",
6436
+ xai: XAI_CONSENSUS_MODEL,
6433
6437
  meta: META_CONSENSUS_MODEL
6434
6438
  };
6435
6439
  function probeProviders(env = process.env) {
@@ -6438,6 +6442,7 @@ function probeProviders(env = process.env) {
6438
6442
  if ((env["OPENAI_API_KEY"] ?? "").trim().length > 0) out.push("openai");
6439
6443
  if ((env["GOOGLE_API_KEY"] ?? "").trim().length > 0) out.push("google");
6440
6444
  if ((env["DEEPSEEK_API_KEY"] ?? "").trim().length > 0) out.push("deepseek");
6445
+ if ((env["XAI_API_KEY"] ?? "").trim().length > 0) out.push("xai");
6441
6446
  if ((env[META_MODEL_API_KEY_ENV] ?? "").trim().length > 0 || (env[META_MODEL_API_KEY_ALIAS] ?? "").trim().length > 0) out.push("meta");
6442
6447
  return out;
6443
6448
  }
@@ -6461,7 +6466,7 @@ async function loadFactoryAndCallers(injectedEngine, injectedShared) {
6461
6466
  return { ok: false, reason: ENGINE_UNAVAILABLE_REASONS.FUNCTIONS_SHARED_NOT_INSTALLED };
6462
6467
  }
6463
6468
  }
6464
- if (sharedMod === null || typeof sharedMod !== "object" || typeof sharedMod.callAnthropicWithMetrics !== "function" || typeof sharedMod.callOpenAIWithMetrics !== "function" || typeof sharedMod.callGeminiWithMetrics !== "function") {
6469
+ if (sharedMod === null || typeof sharedMod !== "object" || typeof sharedMod.callAnthropicWithMetrics !== "function" || typeof sharedMod.callOpenAIWithMetrics !== "function" || typeof sharedMod.callGeminiWithMetrics !== "function" || typeof sharedMod.callXAIWithMetrics !== "function") {
6465
6470
  return { ok: false, reason: ENGINE_UNAVAILABLE_REASONS.FUNCTIONS_SHARED_NOT_INSTALLED };
6466
6471
  }
6467
6472
  return {
@@ -6485,6 +6490,7 @@ async function tryCreateEngineConsensusClientFromEnvAsync(options = {}) {
6485
6490
  openai: loaded.shared.callOpenAIWithMetrics,
6486
6491
  google: loaded.shared.callGeminiWithMetrics,
6487
6492
  deepseek: loaded.shared.callDeepSeekWithMetrics,
6493
+ xai: loaded.shared.callXAIWithMetrics,
6488
6494
  meta: options.metaCaller ?? callMetaWithMetrics
6489
6495
  };
6490
6496
  const modelByProvider = {
@@ -6492,6 +6498,7 @@ async function tryCreateEngineConsensusClientFromEnvAsync(options = {}) {
6492
6498
  openai: options.models?.openai ?? DEFAULT_MODELS.openai,
6493
6499
  google: options.models?.google ?? DEFAULT_MODELS.google,
6494
6500
  deepseek: options.models?.deepseek ?? DEFAULT_MODELS.deepseek,
6501
+ xai: options.models?.xai ?? DEFAULT_MODELS.xai,
6495
6502
  meta: options.models?.meta ?? DEFAULT_MODELS.meta
6496
6503
  };
6497
6504
  const adapterEnv = !(env[META_MODEL_API_KEY_ENV] ?? "").trim() && (env[META_MODEL_API_KEY_ALIAS] ?? "").trim() ? { ...env, [META_MODEL_API_KEY_ENV]: env[META_MODEL_API_KEY_ALIAS] } : env;
@@ -6658,6 +6665,69 @@ function tryCreateMoatConsensusClientFromEnv(env = process.env, fetchFn) {
6658
6665
  });
6659
6666
  }
6660
6667
 
6668
+ // src/consensus/fallback-client.ts
6669
+ var MIN_VALID_LOCAL_VERDICTS = 2;
6670
+ var INSUFFICIENT_LOCAL_VERDICTS_REASON = "local-panel-insufficient-valid-verdicts";
6671
+ function createConsensusFallbackClient(primary, fallback, options = {}) {
6672
+ return {
6673
+ async run(request) {
6674
+ const primaryResult = await primary.run(request);
6675
+ if (request.signal?.aborted || !primaryResult.ok && primaryResult.reason === CANCELLED_REASON) {
6676
+ return primaryResult;
6677
+ }
6678
+ if (primaryResult.ok) {
6679
+ const validVerdicts = primaryResult.per_model_verdicts.filter(
6680
+ (verdict) => verdict.verdict !== "error"
6681
+ );
6682
+ if (validVerdicts.length >= MIN_VALID_LOCAL_VERDICTS) return primaryResult;
6683
+ options.onFallback?.(INSUFFICIENT_LOCAL_VERDICTS_REASON);
6684
+ return fallback.run(request);
6685
+ }
6686
+ options.onFallback?.(primaryResult.reason);
6687
+ return fallback.run(request);
6688
+ }
6689
+ };
6690
+ }
6691
+
6692
+ // src/consensus/local-credential-env.ts
6693
+ import { createRequire as createRequire2 } from "node:module";
6694
+ var require2 = createRequire2(import.meta.url);
6695
+ var KEY_SERVICE = "algosuite-vo";
6696
+ var KEYCHAIN_TARGETS = [
6697
+ { account: "anthropic-api-key", envVar: "ANTHROPIC_API_KEY" },
6698
+ { account: "openai-api-key", envVar: "OPENAI_API_KEY" },
6699
+ { account: "xai-api-key", envVar: "XAI_API_KEY" },
6700
+ { account: "meta-api-key", envVar: "MODEL_API_KEY" }
6701
+ ];
6702
+ function loadEntryCtor() {
6703
+ try {
6704
+ return require2("@napi-rs/keyring").Entry ?? null;
6705
+ } catch {
6706
+ return null;
6707
+ }
6708
+ }
6709
+ function readKey(EntryCtor, account) {
6710
+ try {
6711
+ return new EntryCtor(KEY_SERVICE, account).getPassword()?.trim() || null;
6712
+ } catch {
6713
+ return null;
6714
+ }
6715
+ }
6716
+ function withLocalConsensusCredentials(baseEnv = process.env, options = {}) {
6717
+ const env = { ...baseEnv };
6718
+ if (!env.OPENAI_API_KEY?.trim() && env.CODEX_API_KEY?.trim()) {
6719
+ env.OPENAI_API_KEY = env.CODEX_API_KEY;
6720
+ }
6721
+ const EntryCtor = options.EntryCtor === void 0 ? loadEntryCtor() : options.EntryCtor;
6722
+ if (!EntryCtor) return env;
6723
+ for (const target of KEYCHAIN_TARGETS) {
6724
+ if (env[target.envVar]?.trim()) continue;
6725
+ const key = readKey(EntryCtor, target.account);
6726
+ if (key) env[target.envVar] = key;
6727
+ }
6728
+ return env;
6729
+ }
6730
+
6661
6731
  // src/cloud/login.ts
6662
6732
  init_credential_store();
6663
6733
  import { createServer as createServer2 } from "node:http";
@@ -6921,11 +6991,23 @@ async function main() {
6921
6991
  const ratchets = createStubRatchetClient();
6922
6992
  const testModule = process.env["VO_MCP_TEST_ENGINE_MODULE"];
6923
6993
  const testClient = testModule !== void 0 && testModule.length > 0 ? await loadTestEngineClient(testModule) : null;
6994
+ const localEnv = withLocalConsensusCredentials();
6995
+ const localProviders = probeProviders(localEnv);
6996
+ for (const key of ["ANTHROPIC_API_KEY", "OPENAI_API_KEY", "GOOGLE_API_KEY", "DEEPSEEK_API_KEY", "XAI_API_KEY", "MODEL_API_KEY"]) {
6997
+ if (!process.env[key] && localEnv[key]) process.env[key] = localEnv[key];
6998
+ }
6999
+ const localConsensus = tryCreateEngineConsensusClientFromEnv({ envSource: localEnv });
6924
7000
  const cloudConsensus = testClient ? null : tryCreateMoatConsensusClientFromEnv();
6925
- if (cloudConsensus) {
6926
- console.error("[vo-mcp] cloud consensus active \u2014 verdicts via vo-moat-plane (no local model keys)");
7001
+ let consensus = testClient ?? localConsensus;
7002
+ if (!testClient && cloudConsensus && localProviders.length >= 2) {
7003
+ console.error(`[vo-mcp] local-first consensus active (${localProviders.join(", ")}); cloud moat is fallback-only`);
7004
+ consensus = createConsensusFallbackClient(localConsensus, cloudConsensus, {
7005
+ onFallback: (reason) => console.error(`[vo-mcp] local consensus unavailable (${reason}); using cloud moat fallback`)
7006
+ });
7007
+ } else if (!testClient && cloudConsensus) {
7008
+ console.error("[vo-mcp] fewer than 2 linked local providers; cloud moat consensus active");
7009
+ consensus = cloudConsensus;
6927
7010
  }
6928
- const consensus = testClient ?? cloudConsensus ?? tryCreateEngineConsensusClientFromEnv();
6929
7011
  let adminCallables = null;
6930
7012
  try {
6931
7013
  adminCallables = buildAdminCallableClientFromEnv();