@haven_ai/connect 0.1.37-alpha.0 → 0.2.1-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/README.md CHANGED
@@ -101,6 +101,13 @@ one agent and sign as another, and it fails hard. This is the half of that
101
101
  hazard a local tool can know — the doctor still cannot see inside an
102
102
  already-running host, which is why the restart guidance below matters.
103
103
 
104
+ The hosted MCP `tools/list` row is an endpoint-reachability handshake, not a
105
+ credential-authentication result. When doctor classifies a superseded
106
+ directory, it uses the same authenticated, read-only identity endpoint: a
107
+ 401/403 means the stored key is already revoked; a successful identity read
108
+ means it remains spend-capable; and network or malformed responses remain
109
+ unverifiable.
110
+
104
111
  ## Retiring an old agent directory
105
112
 
106
113
  Re-running setup without `--replace` creates a NEW agent and retires nothing
package/dist/cli.cjs CHANGED
@@ -274,7 +274,7 @@ function signerPayload(input) {
274
274
  delegate_key: input.delegateKey,
275
275
  delegate_address: input.delegateAddress,
276
276
  agent_id: input.agentId,
277
- safe_address: input.safeAddress,
277
+ account_address: input.accountAddress,
278
278
  chain_id: input.chainId,
279
279
  network: input.network,
280
280
  x402_binding_signer: input.x402BindingSigner,
@@ -285,7 +285,7 @@ function identityPayload(input) {
285
285
  return {
286
286
  api_key: input.apiKey,
287
287
  agent_id: input.agentId,
288
- safe_address: input.safeAddress,
288
+ account_address: input.accountAddress,
289
289
  chain_id: input.chainId,
290
290
  network: input.network,
291
291
  api_url: input.apiUrl,
@@ -298,7 +298,7 @@ function agentPayload(input) {
298
298
  return {
299
299
  agent_id: input.agentId,
300
300
  delegate_address: input.delegateAddress,
301
- safe_address: input.safeAddress,
301
+ account_address: input.accountAddress,
302
302
  chain_id: input.chainId,
303
303
  network: input.network,
304
304
  agent_budget: input.agentBudget,
@@ -332,13 +332,20 @@ async function readStoredCredentials(serverName, agentIdOrSlug, baseDir) {
332
332
  apiUrl,
333
333
  hostedMcpUrl,
334
334
  delegateAddress: asString(agent.delegate_address) ?? asString(signer.delegate_address),
335
- safeAddress: asString(identity.safe_address) ?? asString(agent.safe_address),
335
+ ...readStoredAccountAddress(identity, agent),
336
336
  chainId: typeof identity.chain_id === "number" ? identity.chain_id : void 0,
337
337
  network: asString(identity.network),
338
338
  x402BindingSigner: asString(signer.x402_binding_signer),
339
339
  agentBudget: Array.isArray(identity.agent_budget) ? identity.agent_budget : void 0
340
340
  };
341
341
  }
342
+ function readStoredAccountAddress(identity, agent) {
343
+ const fresh = asString(identity.account_address) ?? asString(agent.account_address);
344
+ if (fresh) return { accountAddress: fresh, accountAddressKey: "account_address" };
345
+ const legacy = asString(identity.safe_address) ?? asString(agent.safe_address);
346
+ if (legacy) return { accountAddress: legacy, accountAddressKey: "safe_address" };
347
+ return {};
348
+ }
342
349
  async function discoverSoleAgentDirectory(baseDir) {
343
350
  const root = defaultCredentialRoot(baseDir);
344
351
  let entries = [];
@@ -550,9 +557,9 @@ var init_runtime_manifest = __esm({
550
557
  mcpPackage: "@haven_ai/mcp",
551
558
  mcpVersion: mcp.MCP_VERSION,
552
559
  sdkPackage: "@haven_ai/sdk",
553
- sdkVersion: "0.1.37-alpha.0",
560
+ sdkVersion: "0.2.1-alpha.0",
554
561
  signerPackage: "@haven_ai/signer",
555
- signerVersion: "0.1.37-alpha.0",
562
+ signerVersion: "0.2.1-alpha.0",
556
563
  // Sourced from the SDK, never a literal (#1161). This field read '20.0.0'
557
564
  // while every package's `engines` said `>=24` and the docs said `>=24.0.0`,
558
565
  // so the guard that was supposed to enforce the floor waved Node v23 through
@@ -1440,7 +1447,7 @@ async function buildLocalMcpConsentInput(identityPath, signerPath) {
1440
1447
  apiKey: credentials.apiKey,
1441
1448
  apiUrl: credentials.apiUrl,
1442
1449
  agentId: credentials.agentId,
1443
- safeAddress: credentials.safeAddress,
1450
+ safeAddress: credentials.accountAddress ?? credentials.safeAddress,
1444
1451
  delegateAddress: credentials.delegateAddress,
1445
1452
  chainId: credentials.chainId,
1446
1453
  allowanceSummary: credentials.allowanceSummary
@@ -2482,7 +2489,7 @@ async function buildSignerConsentInput(signerPath) {
2482
2489
  });
2483
2490
  return {
2484
2491
  delegateAddress: signer$1.delegateAddress,
2485
- safeAddress: credentials.safeAddress,
2492
+ safeAddress: credentials.accountAddress ?? credentials.safeAddress,
2486
2493
  agentId: credentials.agentId,
2487
2494
  chainId: credentials.chainId,
2488
2495
  network: credentials.network,
@@ -2658,7 +2665,7 @@ async function installRuntime(input, deps = {}) {
2658
2665
  (signerProbe === void 0 || signerProbe.status === "ok");
2659
2666
  const restartRequired = configResult.restartRequired || restartRequiredForRuntime(runtime, deps.env);
2660
2667
  const errorCode = configResult.errorCode ?? (configResult.runtimeMcpMode === "local_stdio" ? localMcpErrorCode(signerCredentialReady, localMcpConsent, localMcpProbe?.status) : hostedMcpErrorCode(configResult.hostedConfigured, hostedProbe.status) ?? signerConsentErrorCode(signerCredentialReady, signerConsent) ?? signerProbeErrorCode(signerProbe));
2661
- const hostedProbeMessages = configResult.hostedConfigured && hostedProbe.status !== "ok" ? [`Hosted Haven MCP probe failed: ${hostedProbe.status}.`] : configResult.hostedConfigured ? ["Verified hosted Haven MCP tools with a read-only handshake."] : [];
2668
+ const hostedProbeMessages = configResult.hostedConfigured && hostedProbe.status !== "ok" ? [`Hosted Haven MCP probe failed: ${hostedProbe.status}.`] : configResult.hostedConfigured ? ["Verified that the hosted Haven MCP tools endpoint responds to a read-only handshake."] : [];
2662
2669
  const signerProbeMessages = signerProbe ? signerProbe.status === "ok" ? ["Verified local Haven signer with a stdio handshake."] : [
2663
2670
  `Local Haven signer handshake failed: ${signerProbe.status}.`,
2664
2671
  `Re-run \`${sdk.connectorRerunCommand()}\` to repair the signer setup.`
@@ -3320,7 +3327,9 @@ async function finishRekey(options, deps = {}) {
3320
3327
  apiKey: options.newApiKey,
3321
3328
  delegateKey: pending.new_delegate_key,
3322
3329
  delegateAddress: pending.new_delegate_address,
3323
- safeAddress: stored.safeAddress ?? identity.safe_address ?? void 0,
3330
+ // #2908: the stored value (already new-name-first) wins; the hosted
3331
+ // identity's `account_address` twin before its deprecated `safe_address`.
3332
+ accountAddress: stored.accountAddress ?? identity.account_address ?? identity.safe_address ?? void 0,
3324
3333
  chainId: stored.chainId ?? identity.chain_id ?? void 0,
3325
3334
  network: stored.network,
3326
3335
  agentBudget: stored.agentBudget,
@@ -3506,6 +3515,7 @@ var init_rekey_restart = __esm({
3506
3515
  // src/doctor.ts
3507
3516
  var doctor_exports = {};
3508
3517
  __export(doctor_exports, {
3518
+ describeAccountAddressKey: () => describeAccountAddressKey,
3509
3519
  runDoctor: () => runDoctor,
3510
3520
  runRepair: () => runRepair
3511
3521
  });
@@ -3656,6 +3666,15 @@ async function readIdentity(directory) {
3656
3666
  return void 0;
3657
3667
  }
3658
3668
  }
3669
+ function describeAccountAddressKey(identity, signerFile) {
3670
+ const files = [identity, signerFile];
3671
+ const has = (key) => files.some((f) => typeof f?.[key] === "string" && f[key].trim() !== "");
3672
+ if (has("account_address")) return "account address stored as account_address";
3673
+ if (has("safe_address")) {
3674
+ return "account address stored under the pre-#2908 name safe_address \u2014 still read; the next --rekey or setup rewrites it as account_address";
3675
+ }
3676
+ return "no account address stored";
3677
+ }
3659
3678
  async function checksForAgent(entry, input, deps) {
3660
3679
  const { directory, identity, sidecar } = entry;
3661
3680
  const checks = [];
@@ -3672,7 +3691,7 @@ async function checksForAgent(entry, input, deps) {
3672
3691
  id: "credentials",
3673
3692
  label: "Agent credentials",
3674
3693
  ok: credentialsOk,
3675
- detail: credentialsOk ? `identity.json and signer.json parse (agent ${identity?.agent_id ?? "unknown"})` : "identity.json or signer.json is missing or unparseable.",
3694
+ detail: credentialsOk ? `identity.json and signer.json parse (agent ${identity?.agent_id ?? "unknown"}; ${describeAccountAddressKey(identity, signerFile)})` : "identity.json or signer.json is missing or unparseable.",
3676
3695
  ...credentialsOk ? {} : { repair: `Re-run the full setup with a fresh token: ${RERUN} --setup <token>.` }
3677
3696
  });
3678
3697
  if (!sidecar) {
@@ -3696,14 +3715,17 @@ async function checksForAgent(entry, input, deps) {
3696
3715
  ...matches ? {} : { repair: `Run: ${RERUN} --doctor --repair --runtime ${input.runtime} with the same HAVEN_*_SPEC variables set.` }
3697
3716
  });
3698
3717
  } else {
3699
- const matches = await installedRuntimeMatches(sidecar.runtime_directory, sidecar.cli_path);
3718
+ const intact = await installedRuntimeMatchesVersions(sidecar.runtime_directory, sidecar.cli_path, {
3719
+ signerVersion: sidecar.signer_version,
3720
+ sdkVersion: sidecar.sdk_version
3721
+ });
3700
3722
  const versionOk = sidecar.signer_version === MCP_RUNTIME_MANIFEST.signerVersion;
3701
- const ok = matches && versionOk;
3723
+ const ok = intact && versionOk;
3702
3724
  checks.push({
3703
3725
  id: "signer_runtime",
3704
3726
  label: "Signer runtime (preinstalled wrapper)",
3705
3727
  ok,
3706
- detail: ok ? `Installed ${sidecar.signer_package}@${sidecar.signer_version} at ${sidecar.runtime_directory}` : matches ? `Installed version ${sidecar.signer_version} does not match the connector's pinned ${MCP_RUNTIME_MANIFEST.signerVersion}.` : `Runtime directory is stale or empty (${sidecar.runtime_directory}) \u2014 the CLI or package versions are missing.`,
3728
+ detail: ok ? `Installed ${sidecar.signer_package}@${sidecar.signer_version} at ${sidecar.runtime_directory}` : intact ? `Installed version ${sidecar.signer_version} does not match the connector's pinned ${MCP_RUNTIME_MANIFEST.signerVersion} \u2014 intact, but outdated.` : `Runtime directory is stale or empty (${sidecar.runtime_directory}) \u2014 the CLI or package versions are missing.`,
3707
3729
  ...ok ? {} : { repair: `Run: ${RERUN} --doctor --repair --runtime ${input.runtime}` }
3708
3730
  });
3709
3731
  }
@@ -3716,9 +3738,9 @@ async function checksForAgent(entry, input, deps) {
3716
3738
  id: "hosted_mcp",
3717
3739
  label: "Hosted Haven MCP",
3718
3740
  ok: probe.status === "ok",
3719
- detail: probe.status === "ok" ? `Reachable and authorized (${hostedUrl}).` : `Probe failed: ${probe.status} (${hostedUrl}).`,
3741
+ detail: probe.status === "ok" ? `MCP tools endpoint is reachable (${hostedUrl}).` : `MCP tools endpoint probe failed: ${probe.status} (${hostedUrl}).`,
3720
3742
  ...probe.status === "ok" ? {} : {
3721
- repair: probe.status === "unauthorized" ? `The stored API key was rejected \u2014 re-run the full setup with a fresh token: ${RERUN} --setup <token>.` : "Check network access to the hosted MCP URL, then re-run --doctor."
3743
+ repair: "Check network access and runtime configuration for the hosted MCP URL, then re-run --doctor."
3722
3744
  }
3723
3745
  });
3724
3746
  } else {
@@ -3952,14 +3974,17 @@ async function runDoctor(input, deps = {}) {
3952
3974
  const identity = await readIdentity(entry.directory);
3953
3975
  const tombstone = await readAgentTombstone(entry.directory);
3954
3976
  const otherAgent = entry.agentId ?? path.basename(entry.directory);
3955
- const otherUrl = identity?.hosted_mcp_url ?? (identity?.api_url ? `${identity.api_url}/mcp` : void 0);
3956
- if (!identity?.api_key || !otherUrl) {
3977
+ if (!identity?.api_key || !identity.api_url) {
3957
3978
  if (tombstone) retired.push(`${otherAgent} (retired ${tombstone.retired_at})`);
3958
- else unverifiable.push(`${otherAgent} (no stored key/URL to probe)`);
3979
+ else unverifiable.push(`${otherAgent} (no stored key/API URL to probe)`);
3959
3980
  continue;
3960
3981
  }
3961
3982
  const suffix = tombstone ? " [tombstoned \u2014 key material still present]" : "";
3962
- const probe = await (deps.probeHosted ?? probeHostedMcpTools)(identity.api_key, otherUrl, deps.fetch);
3983
+ const probe = await (deps.probeHostedIdentity ?? probeHostedAgentIdentity)(
3984
+ identity.api_key,
3985
+ identity.api_url,
3986
+ deps.fetch
3987
+ );
3963
3988
  if (probe.status === "ok") live.push({ label: `${otherAgent}${suffix}`, entry });
3964
3989
  else if (probe.status === "unauthorized") revoked.push(`${otherAgent}${suffix}`);
3965
3990
  else unverifiable.push(`${otherAgent} (${probe.status})${suffix}`);
@@ -4403,7 +4428,7 @@ async function pathExists2(path) {
4403
4428
  init_unwire();
4404
4429
  init_local_mcp_runtime();
4405
4430
  init_runtime_manifest();
4406
- var CONNECTOR_VERSION = "0.1.37-alpha.0";
4431
+ var CONNECTOR_VERSION = "0.2.1-alpha.0";
4407
4432
  var CONNECT_OUTCOME_SCHEMA_VERSION = 1;
4408
4433
  var failureOutcomesByError = /* @__PURE__ */ new WeakMap();
4409
4434
  function failureOutcomeFor(runtimeHint, error) {
@@ -4579,7 +4604,7 @@ async function executeConnect(options, deps, trace) {
4579
4604
  apiKey: localApiKey,
4580
4605
  delegateKey: localKey.privateKey,
4581
4606
  delegateAddress: localKey.address,
4582
- safeAddress: setup.haven_wallet.address,
4607
+ accountAddress: setup.haven_wallet.address,
4583
4608
  chainId: setup.haven_wallet.chain_id,
4584
4609
  network: setup.haven_wallet.network,
4585
4610
  agentBudget: setup.agent_budget.map((budget) => ({