@haven_ai/connect 0.1.28-alpha.0 → 0.1.30-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.d.cts CHANGED
@@ -12,6 +12,11 @@ interface ConnectApiClient {
12
12
  * never any secret material.
13
13
  */
14
14
  getConnectorStatus(setupId: string, apiKey: string): Promise<ConnectorStatusResponse>;
15
+ /**
16
+ * #1700: the agent behind an API key. Used by the re-key flow on both sides
17
+ * of the dashboard hand-off — see {@link AgentIdentity}.
18
+ */
19
+ getAgentIdentity(apiKey: string): Promise<AgentIdentity>;
15
20
  }
16
21
  interface ConnectorStatusResponse {
17
22
  status: string;
@@ -33,6 +38,18 @@ interface RegisterSetupInput extends ResolveSetupInput {
33
38
  proofSignature: string;
34
39
  apiKeyHash: string;
35
40
  apiKeyPrefix: string;
41
+ /**
42
+ * #1878: the RESOLVED hosted MCP server name this agent is being wired as —
43
+ * `haven` for the bare pair, `haven-<slug>` for a named one. Sent so the
44
+ * dashboard can tell two agents in one harness apart; it is a display aid
45
+ * and Haven keys nothing off it.
46
+ *
47
+ * Always sent by a connector that supports it, bare pair included. Omitting
48
+ * it for the bare pair would make "absent" ambiguous between *this is the
49
+ * unnamed pair* and *an older connector said nothing*, and only the second
50
+ * of those may render as unknown.
51
+ */
52
+ mcpServerName?: string;
36
53
  connectorContext?: ConnectorContext;
37
54
  installCapabilities?: {
38
55
  canWriteRuntimeConfig?: boolean;
@@ -105,6 +122,25 @@ interface RegisterSetupResponse {
105
122
  hosted_mcp_url: string;
106
123
  next_action: string;
107
124
  }
125
+ /**
126
+ * The agent identity behind an API key (#1700).
127
+ *
128
+ * Read from `GET /machine-payments/agent`, the same agent-authenticated
129
+ * endpoint the SDK's `getAgent()` uses. Re-key needs it twice and for two
130
+ * different questions: BEFORE, to refuse a legacy-rail account the way the
131
+ * backend would rather than let the owner discover it five signed steps later;
132
+ * and AFTER, to prove the API key the owner pasted really belongs to this
133
+ * agent and really names the key this machine just generated.
134
+ */
135
+ interface AgentIdentity {
136
+ id: string;
137
+ name: string;
138
+ status: string;
139
+ safe_address: string | null;
140
+ delegate_address: string | null;
141
+ chain_id: number | null;
142
+ execution_rail: 'legacy' | 'delegation' | string;
143
+ }
108
144
  declare function createConnectApiClient(baseUrl: string, fetchImpl?: typeof fetch): ConnectApiClient;
109
145
 
110
146
  interface LocalDelegateKey {
@@ -125,6 +161,12 @@ interface StoredCredentialPaths {
125
161
  interface WriteCredentialInput {
126
162
  baseDir?: string;
127
163
  agentId: string;
164
+ /**
165
+ * #1696: wiring slug. Named agents live at ~/.haven/agents/<slug>/ (stable
166
+ * across a re-key by construction — the slug never rotates); unnamed keep
167
+ * the historical ~/.haven/agents/<agent-uuid>/. Both schemes coexist.
168
+ */
169
+ serverName?: string;
128
170
  apiKey: string;
129
171
  delegateKey: string;
130
172
  delegateAddress: string;
@@ -161,6 +203,69 @@ interface RuntimeProfile {
161
203
  }
162
204
  declare function runtimeProfile(runtime: string | undefined, env?: NodeJS.ProcessEnv): RuntimeProfile;
163
205
  declare function normalizeRuntime(runtime: string | undefined, env?: NodeJS.ProcessEnv): RuntimeId;
206
+ /** The flag values a refusal message should offer. Mirrors RuntimeId. */
207
+ declare const RUNTIME_FLAG_VALUES: "claude-code, codex-cli, codex-desktop, cursor, vscode, vscode-insiders, claude-desktop, hermes, other";
208
+ interface RuntimeSelection {
209
+ runtime: RuntimeId | null;
210
+ source: 'force' | 'detected' | 'explicit' | 'prompted' | 'none';
211
+ /** Set when a confident environment detection overrode a contradicting explicit hint (#1672). */
212
+ overrodeHint?: RuntimeId;
213
+ /** Set when a supplied hint was not a runtime name at all and detection carried the run (#1719). */
214
+ discardedHint?: string;
215
+ }
216
+ interface RuntimeResolutionOptions {
217
+ env?: NodeJS.ProcessEnv;
218
+ /**
219
+ * Rung 3b (#1719): the harness an AGENT executing this command reported for
220
+ * ITSELF, when detection found nothing to go on.
221
+ *
222
+ * It deliberately enters at the same precedence as `--runtime`, which is
223
+ * what makes it safe: a hint can only ever fill a vacuum, and loses to a
224
+ * confident detection exactly as #1672 made it. In practice the agent
225
+ * supplies it BY re-running with `--runtime <name>`; this field exists so a
226
+ * programmatic caller can pass a self-report without pretending to be a
227
+ * command-line flag, and so the ladder names the rung it has.
228
+ */
229
+ selfReported?: string;
230
+ /**
231
+ * Rung 4 (#1719): ask a human at an interactive terminal which of the
232
+ * clients installed on this machine to configure. Injected as a thunk so
233
+ * the ladder stays a policy function — the scan, the readline prompt, and
234
+ * the "nothing writable is installed" refusal all live in
235
+ * `installed-clients.ts`. Omitted (`--json`, no TTY, library callers) means
236
+ * the rung is skipped entirely, not answered with a guess.
237
+ */
238
+ promptForRuntime?: () => Promise<RuntimeId>;
239
+ }
240
+ /**
241
+ * Runtime resolution, detection-first (#1672) and self-resolving (#1719).
242
+ *
243
+ * The setup command carries no `--runtime`; the connector works out the
244
+ * runtime it is executing inside. Precedence:
245
+ *
246
+ * 1. `--runtime-force <name>` — always wins (unknown name refuses).
247
+ * 2. Environment detection over a CONTRADICTING hint. Detection only fires
248
+ * inside a real agent shell, where writing a different client's config is
249
+ * almost surely wrong — the claude-desktop-hint-in-Claude-Code dead end
250
+ * this exists to close.
251
+ * 3. An explicit `--runtime`, or an agent's self-report, with no contradicting
252
+ * detection (the legit plain-terminal "configure Claude Desktop by hand"
253
+ * case — unchanged).
254
+ * 4. Detection alone.
255
+ * 5. An interactive pick among the clients actually installed here, when a
256
+ * human is at a TTY. The scan populates the choices; it never selects.
257
+ * 6. Nothing known → `runtime: null`; the caller refuses BEFORE side effects
258
+ * rather than guessing a config location.
259
+ *
260
+ * A hint that is not a runtime name at all is not a hint — it is a mistake, and
261
+ * the one thing it must never do is fall through to a config location nobody
262
+ * asked for. With no detection to fall back on it refuses (`runtime_unrecognized`).
263
+ * With a detection it loses to it, loudly, exactly like a contradicting hint:
264
+ * the detected client is the right write either way, and refusing there would
265
+ * turn every rollout window in which the dashboard learns an id before the
266
+ * published connector does into a hard failure.
267
+ */
268
+ declare function resolveRuntimeSelection(explicit: string | undefined, force: string | undefined, options?: RuntimeResolutionOptions): Promise<RuntimeSelection>;
164
269
 
165
270
  type RuntimeMcpMode = 'local_stdio' | 'hosted_plus_signer' | 'manual';
166
271
 
@@ -184,6 +289,8 @@ interface PrepareLocalMcpRuntimeInput {
184
289
  signerPath: string;
185
290
  homeDir?: string;
186
291
  nodeVersion?: string;
292
+ /** #1696: wiring slug, recorded in the sidecar for per-agent inventory (#1697). */
293
+ serverName?: string;
187
294
  }
188
295
  interface PreparedLocalMcpRuntime {
189
296
  command: string;
@@ -199,6 +306,8 @@ interface PrepareSignerRuntimeInput {
199
306
  credentialDirectory: string;
200
307
  signerPath: string;
201
308
  homeDir?: string;
309
+ /** #1696: wiring slug, recorded in the sidecar for per-agent inventory (#1697). */
310
+ serverName?: string;
202
311
  }
203
312
  interface PreparedSignerRuntime {
204
313
  /** Absolute command to register as the signer MCP `command`. */
@@ -249,6 +358,11 @@ interface RuntimeInstallInput {
249
358
  * used when this is true and the runtime supports it.
250
359
  */
251
360
  localMcp?: boolean;
361
+ /**
362
+ * #1695: wiring slug for a NAMED MCP pair (haven-<slug> /
363
+ * haven-signer-<slug>). Absent = the bare pair, unchanged from today.
364
+ */
365
+ serverName?: string;
252
366
  }
253
367
  interface RuntimeInstallResult {
254
368
  runtime: RuntimeId;
@@ -333,13 +447,30 @@ declare function runtimeInstallCapabilities(runtime: string | undefined, env?: N
333
447
  restartRequired: boolean;
334
448
  };
335
449
 
336
- declare const CONNECTOR_VERSION = "0.1.28-alpha.0";
450
+ declare const CONNECTOR_VERSION = "0.1.30-alpha.0";
337
451
  interface ConnectOptions {
338
452
  setupToken: string;
339
453
  apiBaseUrl: string;
340
454
  runtime?: string;
455
+ /** #1672 escape hatch: use exactly this runtime, ignoring environment detection. */
456
+ runtimeForce?: string;
457
+ /**
458
+ * #1719: the harness an AGENT running this command reported for itself. Enters
459
+ * at the same precedence as `runtime`, so it can only fill a vacuum — never
460
+ * override a detected environment.
461
+ */
462
+ runtimeSelfReport?: string;
463
+ /**
464
+ * #1719: this run may ask a human which installed client to configure. The
465
+ * CLI sets it for a non-`--json` run; a library caller must opt in. Combined
466
+ * with `deps.isTty`, it is what makes the prompt rung SKIPPED rather than
467
+ * answered in CI, in `--json` automation, and in library embeddings.
468
+ */
469
+ interactive?: boolean;
341
470
  credentialsDir?: string;
342
471
  environmentLabel?: string;
472
+ /** #1696: wiring slug for a named MCP pair + slug-keyed credential dir. */
473
+ serverName?: string;
343
474
  connectorVersion?: string;
344
475
  ackSigner?: boolean;
345
476
  ackLocalTools?: boolean;
@@ -401,6 +532,12 @@ interface ConnectDeps {
401
532
  redactPaths?: boolean;
402
533
  /** Overridable so the Node-floor refusal is testable without spawning a Node. */
403
534
  nodeVersion?: string;
535
+ /** Overridable so runtime detection (#1672) is testable without faking process.env. */
536
+ env?: NodeJS.ProcessEnv;
537
+ /** Overridable so the #1719 TTY gate is testable without faking process.stdin. */
538
+ isTty?: boolean;
539
+ /** Overridable so the #1719 installed-client prompt is testable without readline. */
540
+ promptRuntime?: () => Promise<RuntimeId>;
404
541
  }
405
542
  interface ConnectResult {
406
543
  setupId: string;
@@ -420,6 +557,11 @@ declare function completionOutcome(input: {
420
557
  /**
421
558
  * A deliberately terse failure record: error messages can contain server or
422
559
  * filesystem detail, while this public contract must remain safe to serialize.
560
+ *
561
+ * #1719: a `ConnectError` carries its own code and next action, so it is read
562
+ * rather than guessed. The regex ladder below survives only for the refusals
563
+ * that are still plain `Error`s — every new failure mode joins the vocabulary
564
+ * instead of joining that ladder.
423
565
  */
424
566
  declare function failedConnectOutcome(runtimeHint: string | undefined, error: unknown): ConnectOutcome;
425
567
  /**
@@ -452,6 +594,22 @@ interface ParsedCli {
452
594
  /** #1589: diagnosis mode — no setup token required. */
453
595
  doctor: boolean;
454
596
  repair: boolean;
597
+ /** #1681: retire an agent credential directory in place — no token required. */
598
+ tombstone?: {
599
+ directory: string;
600
+ reason?: string;
601
+ replacedBy?: string;
602
+ };
603
+ /**
604
+ * #1700: replace an agent's signing key on this machine. Two phases, because
605
+ * the dashboard sits between them — `start` generates the key and prints its
606
+ * address, `finish` writes the key the owner brings back. No setup token: the
607
+ * re-key API is owner-authenticated and this connector never calls it.
608
+ */
609
+ rekey?: {
610
+ phase: 'start' | 'finish';
611
+ newApiKey?: string;
612
+ };
455
613
  }
456
614
  declare function parseArgs(argv: string[], env?: NodeJS.ProcessEnv): ParsedCli;
457
615
  declare function helpText(): string;
@@ -459,13 +617,91 @@ declare function helpText(): string;
459
617
  declare function redactSecrets(value: string): string;
460
618
  declare function shortAddress(address: string): string;
461
619
 
620
+ /**
621
+ * The connector's machine-readable failure vocabulary (#1719).
622
+ *
623
+ * Before this, a refusal was a bare `throw new Error(...)` and the automation
624
+ * contract recovered a code by regex-matching the message in
625
+ * `failedConnectOutcome`. That works only for as long as nobody rewords a
626
+ * sentence, and it gives the caller nothing to branch on that the wording did
627
+ * not accidentally provide. Every refusal this module fronts carries:
628
+ *
629
+ * - `code` — stable, snake_case, safe to switch on;
630
+ * - `nextAction` — the one thing to do next, in the same snake_case shape the
631
+ * install-status contract already uses for `next_action`;
632
+ * - `message` — human/agent prose, still the thing printed to a terminal.
633
+ *
634
+ * Codes are additive and never renamed: a consumer pinned to an older
635
+ * connector must keep recognising the ones it already knows.
636
+ */
637
+ declare class ConnectError extends Error {
638
+ readonly code: string;
639
+ readonly nextAction: string;
640
+ constructor(code: string, message: string, nextAction: string);
641
+ }
642
+ declare function isConnectError(err: unknown): err is ConnectError;
643
+
644
+ /**
645
+ * Installed-client scan + interactive pick (#1719).
646
+ *
647
+ * The rung that answers "which runtime am I configuring?" for a HUMAN in a
648
+ * plain terminal, where there is no agent shell to detect. Two properties hold
649
+ * it up, and both are load-bearing:
650
+ *
651
+ * 1. **Only clients the connector can actually write.** A row that cannot be
652
+ * configured is not a choice, it is a dead end wearing a choice's clothes.
653
+ * 2. **The scan populates the choices; it never selects.** Finding exactly one
654
+ * installed app tells you what EXISTS, not where the user wants their agent
655
+ * to run — and the cost of being wrong is an API key and a delegate key
656
+ * written into an app the user does not use. `scanInstalledClients` returns
657
+ * candidates and nothing else; only an answer typed at the prompt resolves
658
+ * a runtime.
659
+ */
660
+ interface InstalledClientCandidate {
661
+ runtime: RuntimeId;
662
+ label: string;
663
+ /** What made this a candidate — shown at the prompt so the pick is informed. */
664
+ detail: string;
665
+ /**
666
+ * The config file Haven would write for this client, when it owns one.
667
+ * `null` for Claude Code, which is configured through its own CLI. Set
668
+ * regardless of which evidence found the client — `evidence` is what says
669
+ * whether that file exists today.
670
+ */
671
+ configPath: string | null;
672
+ evidence: 'config-file' | 'client-directory';
673
+ }
674
+ interface ScanInstalledClientsOptions {
675
+ homeDir?: string;
676
+ /** Workspace root, for the project-local `.vscode/` marker. */
677
+ cwd?: string;
678
+ env?: NodeJS.ProcessEnv;
679
+ /** Injectable so the scan is testable without a populated home directory. */
680
+ exists?: (path: string) => Promise<boolean>;
681
+ }
682
+ declare function scanInstalledClients(options?: ScanInstalledClientsOptions): Promise<InstalledClientCandidate[]>;
683
+ interface PromptIo {
684
+ write: (text: string) => void;
685
+ /** Resolves the typed line, or `null` on EOF / Ctrl-C. */
686
+ question: (query: string) => Promise<string | null>;
687
+ }
688
+ declare function promptForInstalledClient(candidates: readonly InstalledClientCandidate[], io?: PromptIo): Promise<RuntimeId>;
689
+ /**
690
+ * The whole rung as one thunk: scan, refuse if nothing writable is installed,
691
+ * otherwise prompt. This is what `resolveRuntimeSelection` calls, which is why
692
+ * the registry needs no knowledge of the filesystem or of readline.
693
+ */
694
+ declare function resolveRuntimeByInstalledClientPrompt(options?: ScanInstalledClientsOptions & {
695
+ io?: PromptIo;
696
+ }): Promise<RuntimeId>;
697
+
462
698
  declare const MCP_RUNTIME_MANIFEST: {
463
699
  readonly mcpPackage: "@haven_ai/mcp";
464
- readonly mcpVersion: "0.1.28-alpha.0";
700
+ readonly mcpVersion: "0.1.30-alpha.0";
465
701
  readonly sdkPackage: "@haven_ai/sdk";
466
- readonly sdkVersion: "0.1.28-alpha.0";
702
+ readonly sdkVersion: "0.1.30-alpha.0";
467
703
  readonly signerPackage: "@haven_ai/signer";
468
- readonly signerVersion: "0.1.28-alpha.0";
704
+ readonly signerVersion: "0.1.30-alpha.0";
469
705
  readonly minimumNodeVersion: "22.0.0";
470
706
  readonly supportedClients: readonly ["codex-cli", "codex-desktop", "claude-code"];
471
707
  readonly requiredTools: readonly string[];
@@ -481,4 +717,4 @@ declare function mcpPackageSpec(): string;
481
717
  declare function sdkPackageSpec(): string;
482
718
  declare function signerPackageSpec(): string;
483
719
 
484
- export { CONNECTOR_VERSION, CONNECT_OUTCOME_SCHEMA_VERSION, type ConnectApiClient, type ConnectDeps, type ConnectOptions, type ConnectOutcome, type ConnectOutcomeStatus, type ConnectResult, type LocalDelegateKey, MCP_RUNTIME_MANIFEST, type ParsedCli, type PrepareSignerRuntimeInput, type PreparedSignerRuntime, type RegisterSetupInput, type RegisterSetupResponse, type ResolveSetupInput, type ResolvedSetup, type RuntimeId, type RuntimeInstallInput, type RuntimeInstallResult, type RuntimeProfile, type StoredCredentialPaths, type UpdateInstallStatusInput, type WriteCredentialInput, completionOutcome, createConnectApiClient, defaultAgentDirectory, delegateKeyFromPrivateKey, failedConnectOutcome, generateDelegateKey, helpText, installRuntime, mcpPackageSpec, normalizeRuntime, parseArgs, prepareSignerRuntime, redactSecrets, runConnect, runtimeInstallCapabilities, runtimeProfile, sdkPackageSpec, shortAddress, signerPackageSpec, writeCredentialFiles };
720
+ export { CONNECTOR_VERSION, CONNECT_OUTCOME_SCHEMA_VERSION, type ConnectApiClient, type ConnectDeps, ConnectError, type ConnectOptions, type ConnectOutcome, type ConnectOutcomeStatus, type ConnectResult, type InstalledClientCandidate, type LocalDelegateKey, MCP_RUNTIME_MANIFEST, type ParsedCli, type PrepareSignerRuntimeInput, type PreparedSignerRuntime, type PromptIo, RUNTIME_FLAG_VALUES, type RegisterSetupInput, type RegisterSetupResponse, type ResolveSetupInput, type ResolvedSetup, type RuntimeId, type RuntimeInstallInput, type RuntimeInstallResult, type RuntimeProfile, type RuntimeResolutionOptions, type RuntimeSelection, type ScanInstalledClientsOptions, type StoredCredentialPaths, type UpdateInstallStatusInput, type WriteCredentialInput, completionOutcome, createConnectApiClient, defaultAgentDirectory, delegateKeyFromPrivateKey, failedConnectOutcome, generateDelegateKey, helpText, installRuntime, isConnectError, mcpPackageSpec, normalizeRuntime, parseArgs, prepareSignerRuntime, promptForInstalledClient, redactSecrets, resolveRuntimeByInstalledClientPrompt, resolveRuntimeSelection, runConnect, runtimeInstallCapabilities, runtimeProfile, scanInstalledClients, sdkPackageSpec, shortAddress, signerPackageSpec, writeCredentialFiles };