@haven_ai/connect 0.0.0-dev.202609200127.a29d546 → 0.0.0-dev.202609230656.9b1d80a

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
@@ -640,6 +640,7 @@ across the rest is yours.
640
640
  ## Diagnosing a stuck setup: `--doctor` / `--repair` (#1589)
641
641
 
642
642
  ```bash
643
+ npx @haven_ai/connect@<channel> --doctor
643
644
  npx @haven_ai/connect@<channel> --doctor --runtime codex-desktop
644
645
  npx @haven_ai/connect@<channel> --doctor --repair --runtime codex-desktop
645
646
  ```
@@ -649,6 +650,16 @@ not indifferent: `signer_runtime` compares the sidecar against the manifest of
649
650
  the connector **that runs the check**, so a doctor from another channel reports
650
651
  a skew that is not there. Use the channel your dashboard hands out.
651
652
 
653
+ `--runtime` is optional for `--doctor` and required for `--repair` (#3210).
654
+ Without the flag the doctor checks the runtime the setup recorded in the
655
+ agent directory's `last-connect-outcome.json` (#3120), and the `runtime_config`
656
+ verdict says which runtime it resolved and from which file; when no
657
+ record names one, the `runtime_config` check FAILS with "Runtime is unknown —
658
+ the runtime config was NOT checked" and the exit code is 1 — never a pass on a
659
+ config it did not open. `--repair` rewrites that config, so the runtime it
660
+ rewrites is named on the command line rather than inherited from a record on
661
+ disk: a flagless `--repair` is refused before anything runs.
662
+
652
663
  `--doctor` is read-only and needs NO setup token: it checks the runtime config,
653
664
  the agent credential files, the pinned signer runtime install (and, since
654
665
  #2424, whether that install was made under a local runtime-spec override —
package/dist/cli.cjs CHANGED
@@ -619,9 +619,9 @@ var init_runtime_manifest = __esm({
619
619
  mcpPackage: "@haven_ai/mcp",
620
620
  mcpVersion: mcp.MCP_VERSION,
621
621
  sdkPackage: "@haven_ai/sdk",
622
- sdkVersion: "0.0.0-dev.202609200127.a29d546",
622
+ sdkVersion: "0.0.0-dev.202609230656.9b1d80a",
623
623
  signerPackage: "@haven_ai/signer",
624
- signerVersion: "0.0.0-dev.202609200127.a29d546",
624
+ signerVersion: "0.0.0-dev.202609230656.9b1d80a",
625
625
  // Sourced from the SDK, never a literal (#1161). This field read '20.0.0'
626
626
  // while every package's `engines` said `>=24` and the docs said `>=24.0.0`,
627
627
  // so the guard that was supposed to enforce the floor waved Node v23 through
@@ -3808,6 +3808,10 @@ function rollUpLevel(checks) {
3808
3808
  function runtimeFlagFor(runtime) {
3809
3809
  return normalizeRuntimeName(runtime) ? ` --runtime ${runtime}` : "";
3810
3810
  }
3811
+ function repairCommandFor(runtime, suffix = "") {
3812
+ if (normalizeRuntimeName(runtime)) return `Run: ${RERUN} --doctor --repair --runtime ${runtime}${suffix}`;
3813
+ return `Run: ${RERUN} --doctor --repair --runtime <runtime>${suffix.replace(/\.$/, "")} \u2014 --repair needs the runtime named; one of: ${RUNTIME_FLAG_VALUE_LIST.join(", ")}.`;
3814
+ }
3811
3815
  async function resolveDoctorRuntime(input, directory) {
3812
3816
  const explicit = input.runtime.trim();
3813
3817
  if (explicit) return { runtime: explicit, origin: "flag" };
@@ -4010,7 +4014,7 @@ async function verdictsForAgent(entry, input, deps) {
4010
4014
  label: "Signer runtime (preinstalled wrapper)",
4011
4015
  level: "failed",
4012
4016
  detail: "No signer-runtime.json sidecar \u2014 the pinned signer runtime was never prepared (or a pre-#1586 npx config).",
4013
- repair: `Run: ${RERUN} --doctor --repair${runtimeFlagFor(input.runtime)}`
4017
+ repair: repairCommandFor(input.runtime)
4014
4018
  });
4015
4019
  } else if (sidecar.runtime_spec_override) {
4016
4020
  const matches = await installedRuntimeMatchesVersions(sidecar.runtime_directory, sidecar.cli_path, {
@@ -4022,7 +4026,7 @@ async function verdictsForAgent(entry, input, deps) {
4022
4026
  label: "Signer runtime (preinstalled wrapper)",
4023
4027
  level: matches ? "ok" : "failed",
4024
4028
  detail: matches ? `Installed ${sidecar.signer_package}@${sidecar.signer_version} at ${sidecar.runtime_directory} (override install \u2014 see runtime_spec_override)` : `Override runtime directory is stale or empty (${sidecar.runtime_directory}) \u2014 the CLI or package versions are missing.`,
4025
- ...matches ? {} : { repair: `Run: ${RERUN} --doctor --repair${runtimeFlagFor(input.runtime)} with the same HAVEN_*_SPEC variables set.` }
4029
+ ...matches ? {} : { repair: repairCommandFor(input.runtime, " with the same HAVEN_*_SPEC variables set.") }
4026
4030
  });
4027
4031
  } else {
4028
4032
  const intact = await installedRuntimeMatchesVersions(sidecar.runtime_directory, sidecar.cli_path, {
@@ -4036,7 +4040,7 @@ async function verdictsForAgent(entry, input, deps) {
4036
4040
  label: "Signer runtime (preinstalled wrapper)",
4037
4041
  level: ok ? "ok" : intact ? "advisory" : "failed",
4038
4042
  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.`,
4039
- ...ok ? {} : { repair: `Run: ${RERUN} --doctor --repair${runtimeFlagFor(input.runtime)}` }
4043
+ ...ok ? {} : { repair: repairCommandFor(input.runtime) }
4040
4044
  });
4041
4045
  }
4042
4046
  const overrideCheck = await runtimeSpecOverrideCheck(directory, sidecar, deps.env ?? process.env);
@@ -4129,7 +4133,7 @@ async function verdictsForAgent(entry, input, deps) {
4129
4133
  label: "Signer stdio handshake",
4130
4134
  level: probe.status === "ok" ? "ok" : "failed",
4131
4135
  detail: probe.status === "ok" ? `Signer started, listed ${probe.toolNames?.length ?? 0} tools${probe.serverInfo?.version ? ` (v${probe.serverInfo.version})` : ""}.${compatDetail}` : `Handshake failed: ${probe.status}.`,
4132
- ...probe.status === "ok" ? {} : { repair: `Run: ${RERUN} --doctor --repair${runtimeFlagFor(input.runtime)}` }
4136
+ ...probe.status === "ok" ? {} : { repair: repairCommandFor(input.runtime) }
4133
4137
  });
4134
4138
  }
4135
4139
  } else {
@@ -4138,7 +4142,7 @@ async function verdictsForAgent(entry, input, deps) {
4138
4142
  label: "Signer stdio handshake",
4139
4143
  level: "failed",
4140
4144
  detail: "Skipped \u2014 no prepared signer runtime to probe.",
4141
- repair: `Run: ${RERUN} --doctor --repair${runtimeFlagFor(input.runtime)}`
4145
+ repair: repairCommandFor(input.runtime)
4142
4146
  });
4143
4147
  }
4144
4148
  return { checks, ...signerCapabilities ? { signerCapabilities } : {} };
@@ -4274,7 +4278,7 @@ async function runDoctor(input, deps = {}) {
4274
4278
  label: "Runtime MCP config",
4275
4279
  level: "failed",
4276
4280
  detail: `No runtime config at ${configPath}.`,
4277
- repair: `Run: ${RERUN} --doctor --repair${runtimeFlagFor(input2.runtime)}`
4281
+ repair: repairCommandFor(input2.runtime)
4278
4282
  });
4279
4283
  } else {
4280
4284
  const primaryIdentity = await readIdentity(primaryDirectory ?? "");
@@ -4288,7 +4292,7 @@ async function runDoctor(input, deps = {}) {
4288
4292
  label: "Runtime MCP config",
4289
4293
  level: ok ? "ok" : "failed",
4290
4294
  detail: ok ? `Config at ${configPath} references the hosted server and the prepared signer wrapper.` : signerViaNpx ? `Config at ${configPath} still launches the signer via npx \u2014 the pre-#1586 shape that cannot start under a 120s startup timeout.` : `Config at ${configPath} is missing the Haven entries${primarySidecar && !wrapperReferenced ? " (or references a different signer wrapper)" : ""}.`,
4291
- ...ok ? {} : { repair: `Run: ${RERUN} --doctor --repair${runtimeFlagFor(input2.runtime)}` }
4295
+ ...ok ? {} : { repair: repairCommandFor(input2.runtime) }
4292
4296
  });
4293
4297
  }
4294
4298
  for (const id of ["hosted_mcp", "identity_match", "rekey_pending"]) {
@@ -4400,7 +4404,13 @@ async function runDoctor(input, deps = {}) {
4400
4404
  repair: `Run: ${RERUN} --prune-signer-runtimes (add --dry-run to list only).`
4401
4405
  });
4402
4406
  }
4403
- const restart = restartRequiredForRuntime(input2.runtime, deps.env);
4407
+ if (resolution.origin === "record") {
4408
+ const rc = checks.find((check) => check.id === "runtime_config");
4409
+ if (rc) {
4410
+ rc.detail += ` (Resolved '${resolution.runtime}' from ${path.join(directory ?? "", CONNECT_OUTCOME_FILENAME)}; pass --runtime to check a different one.)`;
4411
+ }
4412
+ }
4413
+ const restart = normalizedRuntime === null ? false : restartRequiredForRuntime(input2.runtime, deps.env);
4404
4414
  checks.push({
4405
4415
  id: "restart",
4406
4416
  label: "Runtime restart",
@@ -4820,7 +4830,7 @@ async function pathExists2(path) {
4820
4830
  init_unwire();
4821
4831
  init_local_mcp_runtime();
4822
4832
  init_runtime_manifest();
4823
- var CONNECTOR_VERSION = "0.0.0-dev.202609200127.a29d546";
4833
+ var CONNECTOR_VERSION = "0.0.0-dev.202609230656.9b1d80a";
4824
4834
  var CONNECT_OUTCOME_SCHEMA_VERSION = 1;
4825
4835
  var failureOutcomesByError = /* @__PURE__ */ new WeakMap();
4826
4836
  function failureOutcomeFor(runtimeHint, error) {
@@ -5761,8 +5771,10 @@ function parseArgs(argv, env = process.env) {
5761
5771
  return { options, help, json, doctor, repair, tombstone, rekey, unwire, unwireDir };
5762
5772
  }
5763
5773
  if (doctor || repair) {
5764
- if (!options.runtime) {
5765
- throw new Error("--doctor/--repair need --runtime <runtime> (which config to examine).");
5774
+ if (repair && !options.runtime?.trim()) {
5775
+ throw new Error(
5776
+ "--repair needs --runtime <runtime>: it rewrites that runtime's config, so the runtime is named explicitly rather than inherited from the setup record. --doctor alone resolves it from the record."
5777
+ );
5766
5778
  }
5767
5779
  return { options, help, json, doctor, repair, tombstone, rekey };
5768
5780
  }
@@ -5813,9 +5825,12 @@ function helpText() {
5813
5825
  " --json Emit one versioned, secret-free result object on stdout; progress stays on stderr.",
5814
5826
  " --doctor Diagnose an existing setup (read-only, no token): config, credentials,",
5815
5827
  " signer runtime, hosted MCP, and a live signer handshake. Exits non-zero only on a failed check; an advisory (!) exits 0.",
5828
+ " --runtime is optional: without it the doctor checks the runtime the setup recorded,",
5829
+ " and reports a failure (not a pass) when no record names one.",
5816
5830
  " --repair Repair, then re-diagnose (implies --doctor): reinstall the pinned signer",
5817
5831
  " runtime, rewrite the wrapper and runtime config from stored credentials.",
5818
5832
  " Hosted topology only (refuses to touch a --local config). No keys, no token.",
5833
+ " Requires --runtime <runtime>: it rewrites that config, so the runtime is never inherited.",
5819
5834
  " --rekey Replace this agent's signing key (no token). Generates a fresh keypair HERE and",
5820
5835
  " prints its public address to paste into the Haven agent page. Nothing changes",
5821
5836
  " until you finish; the agent keeps working on its old key throughout.",