@haven_ai/connect 0.1.16-alpha.0 → 0.1.18-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.18-alpha.0",
239
239
  signerPackage: "@haven_ai/signer",
240
- signerVersion: "0.1.16-alpha.0",
240
+ signerVersion: "0.1.18-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;
@@ -1398,7 +1405,12 @@ async function installRuntime(input, deps = {}) {
1398
1405
  localMcpAcknowledged: false,
1399
1406
  messages: [
1400
1407
  ...consentMessages,
1401
- "Runtime was not recognized. Keep the local credentials and add Haven MCP entries manually after wallet approval."
1408
+ "Custom runtime: Haven did not auto-configure it. Your credentials are on disk (chmod 600) \u2014 read them at runtime; never paste a key into the agent prompt, memory, or logs.",
1409
+ ` identity (hosted MCP Bearer): ${input.identityPath}`,
1410
+ ` signer (local signing key): ${input.signerPath}`,
1411
+ "After wallet approval, wire the runtime to Haven by reference:",
1412
+ ` Hosted MCP + local signer: point your MCP client at ${input.hostedMcpUrl} with the api_key from identity.json, then run npx -y ${signerPackageSpec()} --credentials ${input.signerPath}`,
1413
+ ` Fully local MCP (no hosted dependency): npx -y ${mcpPackageSpec()} --identity ${input.identityPath} --signer ${input.signerPath}`
1402
1414
  ]
1403
1415
  };
1404
1416
  }
@@ -1435,6 +1447,7 @@ async function installRuntime(input, deps = {}) {
1435
1447
  }
1436
1448
  let signerCommand;
1437
1449
  if (!localRuntime) {
1450
+ progress("Getting the signer ready\u2026");
1438
1451
  try {
1439
1452
  const signerRuntime = await prepareSignerForRuntime(input, deps);
1440
1453
  signerCommand = { command: signerRuntime.command, args: signerRuntime.args };
@@ -1446,6 +1459,7 @@ async function installRuntime(input, deps = {}) {
1446
1459
  }
1447
1460
  }
1448
1461
  const signerRuntimePrepared = localRuntime ? void 0 : signerCommand !== void 0;
1462
+ progress("Setting up your Haven tools\u2026");
1449
1463
  const configResult = runtime === "claude-code" ? localRuntime ? await configureClaudeCode(deps, localRuntimeInstall?.command ?? "") : await configureClaudeCodeHosted(deps, input, signerCommand) : await writeRuntimeConfig({
1450
1464
  runtime,
1451
1465
  hostedMcpUrl: input.hostedMcpUrl,
@@ -1458,6 +1472,7 @@ async function installRuntime(input, deps = {}) {
1458
1472
  homeDir: deps.homeDir,
1459
1473
  mode: localRuntime ? "local" : "hosted"
1460
1474
  });
1475
+ progress("Almost there \u2014 just confirming everything connects\u2026");
1461
1476
  const localProbePromise = configResult.runtimeMcpMode === "local_stdio" && localRuntimeInstall ? runLocalMcpProbe(localRuntimeInstall, deps) : Promise.resolve(void 0);
1462
1477
  const [hostedProbe, signerCredentialReady, localMcpProbe] = await Promise.all([
1463
1478
  configResult.hostedConfigured ? probeHostedMcpTools(input.apiKey, input.hostedMcpUrl, deps.fetch) : Promise.resolve({ status: "bad_response" }),
@@ -1522,8 +1537,7 @@ async function configureClaudeCode(deps, localMcpCommand) {
1522
1537
  restartRequired: true,
1523
1538
  messages: [
1524
1539
  "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."
1540
+ ...verified ? ["Verified Claude Code MCP entry."] : []
1527
1541
  ]
1528
1542
  };
1529
1543
  } catch (err) {
@@ -1572,8 +1586,7 @@ async function configureClaudeCodeHosted(deps, input, signerCommand) {
1572
1586
  restartRequired: true,
1573
1587
  messages: [
1574
1588
  "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."
1589
+ ...verified ? ["Verified Claude Code MCP entry."] : []
1577
1590
  ]
1578
1591
  };
1579
1592
  } catch (err) {
@@ -1701,7 +1714,7 @@ function localRuntimePrepareErrorCode(err) {
1701
1714
  }
1702
1715
 
1703
1716
  // src/runtime.ts
1704
- var CONNECTOR_VERSION = "0.1.16-alpha.0";
1717
+ var CONNECTOR_VERSION = "0.1.18-alpha.0";
1705
1718
  async function runConnect(options, deps = {}) {
1706
1719
  const connectorVersion = options.connectorVersion ?? CONNECTOR_VERSION;
1707
1720
  const api = deps.api ?? createConnectApiClient(options.apiBaseUrl);
@@ -1721,6 +1734,7 @@ async function runConnect(options, deps = {}) {
1721
1734
  );
1722
1735
  }
1723
1736
  }
1737
+ log("Warming up your connection to Haven\u2026");
1724
1738
  const setup = await api.resolveSetup({
1725
1739
  setupToken: options.setupToken,
1726
1740
  connectorVersion,
@@ -1728,12 +1742,12 @@ async function runConnect(options, deps = {}) {
1728
1742
  });
1729
1743
  printSetupSummary(setup, log);
1730
1744
  await preflightStorage({ baseDir: options.credentialsDir, warn: log });
1731
- log("Checked local credential storage.");
1745
+ log("Checked local credential storage \u2014 all clear.");
1732
1746
  const localKey = generateKey();
1733
1747
  const localApiKey = generateLocalApiKey();
1734
- log("Generated local signing key.");
1735
- log("Generated local Haven API key.");
1748
+ log("Minting a fresh signing key and API key \u2014 both stay on this machine.");
1736
1749
  const proofSignature = await localKey.signChallenge(setup.challenge.message);
1750
+ log("Introducing your agent to Haven\u2026");
1737
1751
  const registration = await api.registerSetup({
1738
1752
  setupToken: options.setupToken,
1739
1753
  connectorVersion,
@@ -1750,6 +1764,7 @@ async function runConnect(options, deps = {}) {
1750
1764
  installCapabilities
1751
1765
  });
1752
1766
  log(`Registered signing address with Haven: ${shortAddress(registration.delegate_address)}.`);
1767
+ log("Tucking your credentials away safely on disk\u2026");
1753
1768
  const credentialPaths = await writeCredentials({
1754
1769
  baseDir: options.credentialsDir,
1755
1770
  agentId: registration.agent_id,
@@ -1790,8 +1805,14 @@ async function runConnect(options, deps = {}) {
1790
1805
  ackSigner: options.ackSigner,
1791
1806
  ackLocalTools: options.ackLocalTools,
1792
1807
  localMcp: options.localMcp
1793
- });
1808
+ }, { onProgress: log });
1794
1809
  printRuntimeInstall(runtimeInstall, log);
1810
+ if (runtimeInstall.errorCode) {
1811
+ log("Haven setup needs a couple more steps on this machine \u2014 see the notes above.");
1812
+ } else {
1813
+ log("Haven setup on this machine is complete.");
1814
+ }
1815
+ printNextSteps(runtimeInstall, log);
1795
1816
  try {
1796
1817
  await api.updateInstallStatus(registration.setup_id, localApiKey, {
1797
1818
  runtime: runtimeInstall.runtime,
@@ -1814,14 +1835,6 @@ async function runConnect(options, deps = {}) {
1814
1835
  } catch (err) {
1815
1836
  log(`Could not report install status to Haven: ${err instanceof Error ? err.message : String(err)}`);
1816
1837
  }
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
1838
  return {
1826
1839
  setupId: registration.setup_id,
1827
1840
  agentId: registration.agent_id,
@@ -1859,6 +1872,18 @@ function printRuntimeInstall(result, log) {
1859
1872
  log("Local Haven signer still needs runtime setup.");
1860
1873
  }
1861
1874
  }
1875
+ function printNextSteps(result, log) {
1876
+ log("Next: approve the agent rules in Haven. No Haven tools appear until you approve \u2014 restart or not.");
1877
+ if (result.restartRequired) {
1878
+ if (runtimeRequiresHardRestart(result.runtime)) {
1879
+ log("After you approve, restart this agent so it can load Haven tools.");
1880
+ } else {
1881
+ log("After you approve, restart this agent \u2014 your current session won't load the Haven tools until you do.");
1882
+ }
1883
+ } else {
1884
+ log("After you approve, the Haven tools should appear in this runtime shortly.");
1885
+ }
1886
+ }
1862
1887
 
1863
1888
  // src/args.ts
1864
1889
  function parseArgs(argv, env = process.env) {