@haven_ai/connect 0.1.16-alpha.0 → 0.1.17-alpha.0

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.cjs CHANGED
@@ -236,9 +236,9 @@ var MCP_RUNTIME_MANIFEST = {
236
236
  mcpPackage: "@haven_ai/mcp",
237
237
  mcpVersion: mcp.MCP_VERSION,
238
238
  sdkPackage: "@haven_ai/sdk",
239
- sdkVersion: "0.1.16-alpha.0",
239
+ sdkVersion: "0.1.17-alpha.0",
240
240
  signerPackage: "@haven_ai/signer",
241
- signerVersion: "0.1.16-alpha.0",
241
+ signerVersion: "0.1.17-alpha.0",
242
242
  minimumNodeVersion: "20.0.0",
243
243
  supportedClients: ["codex-cli", "codex-desktop", "claude-code"],
244
244
  requiredTools: mcp.registeredToolNames()
@@ -253,117 +253,6 @@ function signerPackageSpec() {
253
253
  return `${MCP_RUNTIME_MANIFEST.signerPackage}@${MCP_RUNTIME_MANIFEST.signerVersion}`;
254
254
  }
255
255
 
256
- // src/runtime-registry.ts
257
- var RUNTIME_PROFILES = {
258
- "claude-code": {
259
- id: "claude-code",
260
- label: "Claude Code",
261
- restartMode: "restart-session",
262
- canWriteRuntimeConfig: true
263
- },
264
- "codex-cli": {
265
- id: "codex-cli",
266
- label: "Codex CLI",
267
- restartMode: "restart-session",
268
- canWriteRuntimeConfig: true
269
- },
270
- "codex-desktop": {
271
- id: "codex-desktop",
272
- label: "Codex Desktop",
273
- restartMode: "restart-session",
274
- canWriteRuntimeConfig: true
275
- },
276
- cursor: {
277
- id: "cursor",
278
- label: "Cursor",
279
- restartMode: "hot-reload",
280
- canWriteRuntimeConfig: true
281
- },
282
- vscode: {
283
- id: "vscode",
284
- label: "VS Code",
285
- restartMode: "hot-reload",
286
- canWriteRuntimeConfig: true
287
- },
288
- "vscode-insiders": {
289
- id: "vscode-insiders",
290
- label: "VS Code Insiders",
291
- restartMode: "hot-reload",
292
- canWriteRuntimeConfig: true
293
- },
294
- "claude-desktop": {
295
- id: "claude-desktop",
296
- label: "Claude Desktop",
297
- restartMode: "restart-app",
298
- canWriteRuntimeConfig: true
299
- },
300
- other: {
301
- id: "other",
302
- label: "Other agent runtime",
303
- restartMode: "manual",
304
- canWriteRuntimeConfig: false
305
- }
306
- };
307
- var RUNTIME_ALIASES = {
308
- claude: "claude-code",
309
- "claude-code": "claude-code",
310
- claudecode: "claude-code",
311
- "claude_code": "claude-code",
312
- codex: "codex-cli",
313
- "codex-cli": "codex-cli",
314
- codexcli: "codex-cli",
315
- "codex_cli": "codex-cli",
316
- "codex-desktop": "codex-desktop",
317
- "codex_desktop": "codex-desktop",
318
- codexdesktop: "codex-desktop",
319
- "codex-app": "codex-desktop",
320
- "codex_app": "codex-desktop",
321
- codexapp: "codex-desktop",
322
- cursor: "cursor",
323
- vscode: "vscode",
324
- "vs-code": "vscode",
325
- "vs_code": "vscode",
326
- code: "vscode",
327
- "vscode-insiders": "vscode-insiders",
328
- "vscode_insiders": "vscode-insiders",
329
- vscodeinsiders: "vscode-insiders",
330
- "vs-code-insiders": "vscode-insiders",
331
- "code-insiders": "vscode-insiders",
332
- insiders: "vscode-insiders",
333
- "claude-desktop": "claude-desktop",
334
- "claude_desktop": "claude-desktop",
335
- claudesktop: "claude-desktop",
336
- desktop: "claude-desktop",
337
- other: "other",
338
- manual: "other"
339
- };
340
- function runtimeProfile(runtime, env = process.env) {
341
- return RUNTIME_PROFILES[normalizeRuntime(runtime, env)];
342
- }
343
- function normalizeRuntime(runtime, env = process.env) {
344
- const explicit = normalizeRuntimeName(runtime);
345
- if (explicit) return explicit;
346
- return detectRuntime(env) ?? "other";
347
- }
348
- function restartRequiredForRuntime(runtime, env = process.env) {
349
- const mode = runtimeProfile(runtime, env).restartMode;
350
- return mode === "restart-session" || mode === "restart-app";
351
- }
352
- function runtimeRequiresHardRestart(runtime) {
353
- return runtime === "claude-desktop" || runtime === "codex-desktop";
354
- }
355
- function normalizeRuntimeName(runtime) {
356
- const key = runtime?.trim().toLowerCase();
357
- if (!key) return null;
358
- return RUNTIME_ALIASES[key.replace(/\s+/g, "-")] ?? null;
359
- }
360
- function detectRuntime(env) {
361
- if (env.CLAUDECODE || env.CLAUDE_CODE || env.CLAUDECODE_CWD) return "claude-code";
362
- if (env.CODEX_SANDBOX || env.CODEX_HOME || env.CODEX_CWD) return "codex-cli";
363
- if (env.VSCODE_CWD || env.VSCODE_IPC_HOOK_CLI || env.TERM_PROGRAM === "vscode") return "vscode";
364
- return null;
365
- }
366
-
367
256
  // src/config-writers.ts
368
257
  var InvalidCodexTomlError = class extends Error {
369
258
  constructor(message) {
@@ -510,7 +399,6 @@ async function writeJsonRuntimeConfig(input, target, serverRoot) {
510
399
  async function writeCodexConfig(input) {
511
400
  const target = codexConfigPath(input.homeDir);
512
401
  const local = input.mode === "local";
513
- const restartMessage = runtimeRequiresHardRestart(input.runtime) ? "After Haven approval, restart Codex Desktop so it can load Haven tools." : "After Haven approval, Haven tools should appear in your next Codex message. If they don't, restart Codex to load them.";
514
402
  try {
515
403
  const existing = await readOptional(target);
516
404
  if (local) {
@@ -528,11 +416,7 @@ async function writeCodexConfig(input) {
528
416
  changed: existing !== merged2,
529
417
  restartRequired: true,
530
418
  messages: [
531
- `Updated local Haven MCP entry in ${configTargetLabel(input.runtime)}.`,
532
- // Codex Desktop loads MCP servers at app launch; Codex CLI typically
533
- // picks them up in the next session. Branch the copy so desktop users
534
- // get the unambiguous instruction.
535
- restartMessage
419
+ `Updated local Haven MCP entry in ${configTargetLabel(input.runtime)}.`
536
420
  ]
537
421
  };
538
422
  }
@@ -547,8 +431,7 @@ async function writeCodexConfig(input) {
547
431
  changed: existing !== merged,
548
432
  restartRequired: true,
549
433
  messages: [
550
- `Updated Haven MCP entries in ${configTargetLabel(input.runtime)}.`,
551
- restartMessage
434
+ `Updated Haven MCP entries in ${configTargetLabel(input.runtime)}.`
552
435
  ]
553
436
  };
554
437
  } catch (err) {
@@ -1101,23 +984,29 @@ function parseNodeVersion(value) {
1101
984
  ];
1102
985
  }
1103
986
  async function installRuntimePackages(runtimeDirectory, npmCacheDirectory, runCommand) {
1104
- const args = [
987
+ const baseArgs = [
1105
988
  "install",
1106
989
  "--prefix",
1107
990
  runtimeDirectory,
1108
- "--cache",
1109
- npmCacheDirectory,
1110
991
  "--no-audit",
1111
992
  "--no-fund",
1112
993
  "--omit=dev",
994
+ "--prefer-offline",
1113
995
  mcpPackageSpec(),
1114
996
  sdkPackageSpec()
1115
997
  ];
1116
- try {
998
+ const run = async (args) => {
1117
999
  if (runCommand) await runCommand("npm", args);
1118
1000
  else await execFileAsync("npm", args, { timeout: 12e4, maxBuffer: 1024 * 1024 });
1119
- } catch (err) {
1120
- throw new Error(`Could not install local Haven MCP runtime ${mcpPackageSpec()}: ${err instanceof Error ? err.message : String(err)}`);
1001
+ };
1002
+ try {
1003
+ await run(baseArgs);
1004
+ } catch {
1005
+ try {
1006
+ await run([...baseArgs, "--cache", npmCacheDirectory]);
1007
+ } catch (err) {
1008
+ throw new Error(`Could not install local Haven MCP runtime ${mcpPackageSpec()}: ${err instanceof Error ? err.message : String(err)}`);
1009
+ }
1121
1010
  }
1122
1011
  }
1123
1012
  async function installedRuntimeMatches(runtimeDirectory, cliPath) {
@@ -1221,25 +1110,31 @@ async function prepareSignerRuntime(input, deps = {}) {
1221
1110
  };
1222
1111
  }
1223
1112
  async function installRuntimePackages2(runtimeDirectory, npmCacheDirectory, runCommand) {
1224
- const args = [
1113
+ const baseArgs = [
1225
1114
  "install",
1226
1115
  "--prefix",
1227
1116
  runtimeDirectory,
1228
- "--cache",
1229
- npmCacheDirectory,
1230
1117
  "--no-audit",
1231
1118
  "--no-fund",
1232
1119
  "--omit=dev",
1120
+ "--prefer-offline",
1233
1121
  signerPackageSpec(),
1234
1122
  sdkPackageSpec()
1235
1123
  ];
1236
- try {
1124
+ const run = async (args) => {
1237
1125
  if (runCommand) await runCommand("npm", args);
1238
1126
  else await execFileAsync2("npm", args, { timeout: 12e4, maxBuffer: 1024 * 1024 });
1239
- } catch (err) {
1240
- throw new Error(
1241
- `Could not install local Haven signer runtime ${signerPackageSpec()}: ${err instanceof Error ? err.message : String(err)}`
1242
- );
1127
+ };
1128
+ try {
1129
+ await run(baseArgs);
1130
+ } catch {
1131
+ try {
1132
+ await run([...baseArgs, "--cache", npmCacheDirectory]);
1133
+ } catch (err) {
1134
+ throw new Error(
1135
+ `Could not install local Haven signer runtime ${signerPackageSpec()}: ${err instanceof Error ? err.message : String(err)}`
1136
+ );
1137
+ }
1243
1138
  }
1244
1139
  }
1245
1140
  async function installedRuntimeMatches2(runtimeDirectory, cliPath) {
@@ -1302,6 +1197,117 @@ async function assertFileExists2(path, label) {
1302
1197
  throw new Error(`Missing ${label}: ${path}`);
1303
1198
  }
1304
1199
  }
1200
+
1201
+ // src/runtime-registry.ts
1202
+ var RUNTIME_PROFILES = {
1203
+ "claude-code": {
1204
+ id: "claude-code",
1205
+ label: "Claude Code",
1206
+ restartMode: "restart-session",
1207
+ canWriteRuntimeConfig: true
1208
+ },
1209
+ "codex-cli": {
1210
+ id: "codex-cli",
1211
+ label: "Codex CLI",
1212
+ restartMode: "restart-session",
1213
+ canWriteRuntimeConfig: true
1214
+ },
1215
+ "codex-desktop": {
1216
+ id: "codex-desktop",
1217
+ label: "Codex Desktop",
1218
+ restartMode: "restart-session",
1219
+ canWriteRuntimeConfig: true
1220
+ },
1221
+ cursor: {
1222
+ id: "cursor",
1223
+ label: "Cursor",
1224
+ restartMode: "hot-reload",
1225
+ canWriteRuntimeConfig: true
1226
+ },
1227
+ vscode: {
1228
+ id: "vscode",
1229
+ label: "VS Code",
1230
+ restartMode: "hot-reload",
1231
+ canWriteRuntimeConfig: true
1232
+ },
1233
+ "vscode-insiders": {
1234
+ id: "vscode-insiders",
1235
+ label: "VS Code Insiders",
1236
+ restartMode: "hot-reload",
1237
+ canWriteRuntimeConfig: true
1238
+ },
1239
+ "claude-desktop": {
1240
+ id: "claude-desktop",
1241
+ label: "Claude Desktop",
1242
+ restartMode: "restart-app",
1243
+ canWriteRuntimeConfig: true
1244
+ },
1245
+ other: {
1246
+ id: "other",
1247
+ label: "Other agent runtime",
1248
+ restartMode: "manual",
1249
+ canWriteRuntimeConfig: false
1250
+ }
1251
+ };
1252
+ var RUNTIME_ALIASES = {
1253
+ claude: "claude-code",
1254
+ "claude-code": "claude-code",
1255
+ claudecode: "claude-code",
1256
+ "claude_code": "claude-code",
1257
+ codex: "codex-cli",
1258
+ "codex-cli": "codex-cli",
1259
+ codexcli: "codex-cli",
1260
+ "codex_cli": "codex-cli",
1261
+ "codex-desktop": "codex-desktop",
1262
+ "codex_desktop": "codex-desktop",
1263
+ codexdesktop: "codex-desktop",
1264
+ "codex-app": "codex-desktop",
1265
+ "codex_app": "codex-desktop",
1266
+ codexapp: "codex-desktop",
1267
+ cursor: "cursor",
1268
+ vscode: "vscode",
1269
+ "vs-code": "vscode",
1270
+ "vs_code": "vscode",
1271
+ code: "vscode",
1272
+ "vscode-insiders": "vscode-insiders",
1273
+ "vscode_insiders": "vscode-insiders",
1274
+ vscodeinsiders: "vscode-insiders",
1275
+ "vs-code-insiders": "vscode-insiders",
1276
+ "code-insiders": "vscode-insiders",
1277
+ insiders: "vscode-insiders",
1278
+ "claude-desktop": "claude-desktop",
1279
+ "claude_desktop": "claude-desktop",
1280
+ claudesktop: "claude-desktop",
1281
+ desktop: "claude-desktop",
1282
+ other: "other",
1283
+ manual: "other"
1284
+ };
1285
+ function runtimeProfile(runtime, env = process.env) {
1286
+ return RUNTIME_PROFILES[normalizeRuntime(runtime, env)];
1287
+ }
1288
+ function normalizeRuntime(runtime, env = process.env) {
1289
+ const explicit = normalizeRuntimeName(runtime);
1290
+ if (explicit) return explicit;
1291
+ return detectRuntime(env) ?? "other";
1292
+ }
1293
+ function restartRequiredForRuntime(runtime, env = process.env) {
1294
+ const mode = runtimeProfile(runtime, env).restartMode;
1295
+ return mode === "restart-session" || mode === "restart-app";
1296
+ }
1297
+ function runtimeRequiresHardRestart(runtime) {
1298
+ return runtime === "claude-desktop" || runtime === "codex-desktop";
1299
+ }
1300
+ function normalizeRuntimeName(runtime) {
1301
+ const key = runtime?.trim().toLowerCase();
1302
+ if (!key) return null;
1303
+ return RUNTIME_ALIASES[key.replace(/\s+/g, "-")] ?? null;
1304
+ }
1305
+ function detectRuntime(env) {
1306
+ if (env.CLAUDECODE || env.CLAUDE_CODE || env.CLAUDECODE_CWD) return "claude-code";
1307
+ if (env.CODEX_SANDBOX || env.CODEX_HOME || env.CODEX_CWD) return "codex-cli";
1308
+ if (env.VSCODE_CWD || env.VSCODE_IPC_HOOK_CLI || env.TERM_PROGRAM === "vscode") return "vscode";
1309
+ return null;
1310
+ }
1305
1311
  async function acknowledgeLocalSignerConsent(signerPath, log) {
1306
1312
  try {
1307
1313
  const input = await buildSignerConsentInput(signerPath);
@@ -1377,6 +1383,7 @@ var execFileAsync3 = util.promisify(child_process.execFile);
1377
1383
  async function installRuntime(input, deps = {}) {
1378
1384
  const runtime = normalizeRuntime(input.runtime, deps.env);
1379
1385
  const profile = runtimeProfile(runtime, deps.env);
1386
+ const progress = deps.onProgress ?? (() => void 0);
1380
1387
  const localRuntime = input.localMcp === true && supportsLocalMcp(runtime);
1381
1388
  const consentMessages = [];
1382
1389
  const localMcpConsent = localRuntime ? await resolveLocalMcpConsent(input, consentMessages) : void 0;
@@ -1436,6 +1443,7 @@ async function installRuntime(input, deps = {}) {
1436
1443
  }
1437
1444
  let signerCommand;
1438
1445
  if (!localRuntime) {
1446
+ progress("Getting the signer ready\u2026");
1439
1447
  try {
1440
1448
  const signerRuntime = await prepareSignerForRuntime(input, deps);
1441
1449
  signerCommand = { command: signerRuntime.command, args: signerRuntime.args };
@@ -1447,6 +1455,7 @@ async function installRuntime(input, deps = {}) {
1447
1455
  }
1448
1456
  }
1449
1457
  const signerRuntimePrepared = localRuntime ? void 0 : signerCommand !== void 0;
1458
+ progress("Setting up your Haven tools\u2026");
1450
1459
  const configResult = runtime === "claude-code" ? localRuntime ? await configureClaudeCode(deps, localRuntimeInstall?.command ?? "") : await configureClaudeCodeHosted(deps, input, signerCommand) : await writeRuntimeConfig({
1451
1460
  runtime,
1452
1461
  hostedMcpUrl: input.hostedMcpUrl,
@@ -1459,6 +1468,7 @@ async function installRuntime(input, deps = {}) {
1459
1468
  homeDir: deps.homeDir,
1460
1469
  mode: localRuntime ? "local" : "hosted"
1461
1470
  });
1471
+ progress("Almost there \u2014 just confirming everything connects\u2026");
1462
1472
  const localProbePromise = configResult.runtimeMcpMode === "local_stdio" && localRuntimeInstall ? runLocalMcpProbe(localRuntimeInstall, deps) : Promise.resolve(void 0);
1463
1473
  const [hostedProbe, signerCredentialReady, localMcpProbe] = await Promise.all([
1464
1474
  configResult.hostedConfigured ? probeHostedMcpTools(input.apiKey, input.hostedMcpUrl, deps.fetch) : Promise.resolve({ status: "bad_response" }),
@@ -1523,8 +1533,7 @@ async function configureClaudeCode(deps, localMcpCommand) {
1523
1533
  restartRequired: true,
1524
1534
  messages: [
1525
1535
  "Updated local Haven MCP entry with Claude Code.",
1526
- ...verified ? ["Verified Claude Code MCP entry."] : [],
1527
- "After Haven approval, Haven tools should appear in your next Claude Code message. If they don't, restart the session to load them."
1536
+ ...verified ? ["Verified Claude Code MCP entry."] : []
1528
1537
  ]
1529
1538
  };
1530
1539
  } catch (err) {
@@ -1573,8 +1582,7 @@ async function configureClaudeCodeHosted(deps, input, signerCommand) {
1573
1582
  restartRequired: true,
1574
1583
  messages: [
1575
1584
  "Updated hosted Haven MCP and local signer entries with Claude Code.",
1576
- ...verified ? ["Verified Claude Code MCP entry."] : [],
1577
- "After Haven approval, Haven tools should appear in your next Claude Code message. If they don't, restart the session to load them."
1585
+ ...verified ? ["Verified Claude Code MCP entry."] : []
1578
1586
  ]
1579
1587
  };
1580
1588
  } catch (err) {
@@ -1702,7 +1710,7 @@ function localRuntimePrepareErrorCode(err) {
1702
1710
  }
1703
1711
 
1704
1712
  // src/runtime.ts
1705
- var CONNECTOR_VERSION = "0.1.16-alpha.0";
1713
+ var CONNECTOR_VERSION = "0.1.17-alpha.0";
1706
1714
  async function runConnect(options, deps = {}) {
1707
1715
  const connectorVersion = options.connectorVersion ?? CONNECTOR_VERSION;
1708
1716
  const api = deps.api ?? createConnectApiClient(options.apiBaseUrl);
@@ -1722,6 +1730,7 @@ async function runConnect(options, deps = {}) {
1722
1730
  );
1723
1731
  }
1724
1732
  }
1733
+ log("Warming up your connection to Haven\u2026");
1725
1734
  const setup = await api.resolveSetup({
1726
1735
  setupToken: options.setupToken,
1727
1736
  connectorVersion,
@@ -1729,12 +1738,12 @@ async function runConnect(options, deps = {}) {
1729
1738
  });
1730
1739
  printSetupSummary(setup, log);
1731
1740
  await preflightStorage({ baseDir: options.credentialsDir, warn: log });
1732
- log("Checked local credential storage.");
1741
+ log("Checked local credential storage \u2014 all clear.");
1733
1742
  const localKey = generateKey();
1734
1743
  const localApiKey = generateLocalApiKey();
1735
- log("Generated local signing key.");
1736
- log("Generated local Haven API key.");
1744
+ log("Minting a fresh signing key and API key \u2014 both stay on this machine.");
1737
1745
  const proofSignature = await localKey.signChallenge(setup.challenge.message);
1746
+ log("Introducing your agent to Haven\u2026");
1738
1747
  const registration = await api.registerSetup({
1739
1748
  setupToken: options.setupToken,
1740
1749
  connectorVersion,
@@ -1751,6 +1760,7 @@ async function runConnect(options, deps = {}) {
1751
1760
  installCapabilities
1752
1761
  });
1753
1762
  log(`Registered signing address with Haven: ${shortAddress(registration.delegate_address)}.`);
1763
+ log("Tucking your credentials away safely on disk\u2026");
1754
1764
  const credentialPaths = await writeCredentials({
1755
1765
  baseDir: options.credentialsDir,
1756
1766
  agentId: registration.agent_id,
@@ -1791,8 +1801,14 @@ async function runConnect(options, deps = {}) {
1791
1801
  ackSigner: options.ackSigner,
1792
1802
  ackLocalTools: options.ackLocalTools,
1793
1803
  localMcp: options.localMcp
1794
- });
1804
+ }, { onProgress: log });
1795
1805
  printRuntimeInstall(runtimeInstall, log);
1806
+ if (runtimeInstall.errorCode) {
1807
+ log("Haven setup needs a couple more steps on this machine \u2014 see the notes above.");
1808
+ } else {
1809
+ log("Haven setup on this machine is complete.");
1810
+ }
1811
+ printNextSteps(runtimeInstall, log);
1796
1812
  try {
1797
1813
  await api.updateInstallStatus(registration.setup_id, localApiKey, {
1798
1814
  runtime: runtimeInstall.runtime,
@@ -1815,14 +1831,6 @@ async function runConnect(options, deps = {}) {
1815
1831
  } catch (err) {
1816
1832
  log(`Could not report install status to Haven: ${err instanceof Error ? err.message : String(err)}`);
1817
1833
  }
1818
- log("Return to Haven to approve the agent rules.");
1819
- if (runtimeInstall.restartRequired) {
1820
- if (runtimeRequiresHardRestart(runtimeInstall.runtime)) {
1821
- log("After approval, restart this agent so it can load Haven tools.");
1822
- } else {
1823
- log("After approval, Haven tools should appear in your next message. If they don't, restart this agent to load them.");
1824
- }
1825
- }
1826
1834
  return {
1827
1835
  setupId: registration.setup_id,
1828
1836
  agentId: registration.agent_id,
@@ -1860,6 +1868,18 @@ function printRuntimeInstall(result, log) {
1860
1868
  log("Local Haven signer still needs runtime setup.");
1861
1869
  }
1862
1870
  }
1871
+ function printNextSteps(result, log) {
1872
+ log("Next: approve the agent rules in Haven. No Haven tools appear until you approve \u2014 restart or not.");
1873
+ if (result.restartRequired) {
1874
+ if (runtimeRequiresHardRestart(result.runtime)) {
1875
+ log("After you approve, restart this agent so it can load Haven tools.");
1876
+ } else {
1877
+ log("After you approve, restart this agent \u2014 your current session won't load the Haven tools until you do.");
1878
+ }
1879
+ } else {
1880
+ log("After you approve, the Haven tools should appear in this runtime shortly.");
1881
+ }
1882
+ }
1863
1883
 
1864
1884
  // src/args.ts
1865
1885
  function parseArgs(argv, env = process.env) {