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