@haven_ai/connect 0.1.30-alpha.0 → 0.1.31-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/cli.cjs +70 -20
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +70 -20
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +70 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -9
- package/dist/index.d.ts +36 -9
- package/dist/index.js +70 -20
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/cli.cjs
CHANGED
|
@@ -154,6 +154,9 @@ var init_key = __esm({
|
|
|
154
154
|
function redactSecrets(value) {
|
|
155
155
|
return value.replace(API_KEY_RE, "sk_agent_[redacted]").replace(PRIVATE_KEY_RE, "0x[redacted-private-key]");
|
|
156
156
|
}
|
|
157
|
+
function redactForAutomation(value) {
|
|
158
|
+
return redactSecrets(value).replace(/(?:~|\/)[^\s`"']*\/(?:identity|signer|agent)\.json\b/g, "[credential-file-redacted]").replace(/(?:~|\/)[^\s`"']*\/\.env\b/g, "[credential-env-redacted]");
|
|
159
|
+
}
|
|
157
160
|
function shortAddress(address) {
|
|
158
161
|
if (!/^0x[0-9a-fA-F]{40}$/.test(address)) return address;
|
|
159
162
|
return `${address.slice(0, 6)}...${address.slice(-4)}`;
|
|
@@ -524,9 +527,9 @@ var init_runtime_manifest = __esm({
|
|
|
524
527
|
mcpPackage: "@haven_ai/mcp",
|
|
525
528
|
mcpVersion: mcp.MCP_VERSION,
|
|
526
529
|
sdkPackage: "@haven_ai/sdk",
|
|
527
|
-
sdkVersion: "0.1.
|
|
530
|
+
sdkVersion: "0.1.31-alpha.0",
|
|
528
531
|
signerPackage: "@haven_ai/signer",
|
|
529
|
-
signerVersion: "0.1.
|
|
532
|
+
signerVersion: "0.1.31-alpha.0",
|
|
530
533
|
// Sourced from the SDK, never a literal (#1161). This field read '20.0.0'
|
|
531
534
|
// while every package's `engines` said `>=24` and the docs said `>=24.0.0`,
|
|
532
535
|
// so the guard that was supposed to enforce the floor waved Node v23 through
|
|
@@ -1946,11 +1949,13 @@ var init_connect_error = __esm({
|
|
|
1946
1949
|
ConnectError = class extends Error {
|
|
1947
1950
|
code;
|
|
1948
1951
|
nextAction;
|
|
1949
|
-
|
|
1952
|
+
details;
|
|
1953
|
+
constructor(code, message, nextAction2, details = {}) {
|
|
1950
1954
|
super(message);
|
|
1951
1955
|
this.name = "ConnectError";
|
|
1952
1956
|
this.code = code;
|
|
1953
1957
|
this.nextAction = nextAction2;
|
|
1958
|
+
this.details = details;
|
|
1954
1959
|
}
|
|
1955
1960
|
};
|
|
1956
1961
|
}
|
|
@@ -1973,7 +1978,8 @@ async function resolveRuntimeSelection(explicit, force, options = {}) {
|
|
|
1973
1978
|
throw new ConnectError(
|
|
1974
1979
|
"runtime_force_unrecognized",
|
|
1975
1980
|
`Unknown --runtime-force value "${force}". Valid values: ${RUNTIME_FLAG_VALUES}.`,
|
|
1976
|
-
"rerun_connect_with_a_valid_runtime_name"
|
|
1981
|
+
"rerun_connect_with_a_valid_runtime_name",
|
|
1982
|
+
{ allowedRuntimes: RUNTIME_FLAG_VALUE_LIST }
|
|
1977
1983
|
);
|
|
1978
1984
|
}
|
|
1979
1985
|
return { runtime: forced, source: "force" };
|
|
@@ -1986,7 +1992,8 @@ async function resolveRuntimeSelection(explicit, force, options = {}) {
|
|
|
1986
1992
|
throw new ConnectError(
|
|
1987
1993
|
"runtime_unrecognized",
|
|
1988
1994
|
`"${supplied}" is not an agent runtime Haven knows. Valid values: ${RUNTIME_FLAG_VALUES} (the aliases cowork, codex and openclaw are accepted too). Re-run with one of those, or --runtime other to store credentials and finish the MCP setup by hand. Nothing was written and the Haven setup token is still unused.`,
|
|
1989
|
-
"rerun_connect_with_a_valid_runtime_name"
|
|
1995
|
+
"rerun_connect_with_a_valid_runtime_name",
|
|
1996
|
+
{ allowedRuntimes: RUNTIME_FLAG_VALUE_LIST }
|
|
1990
1997
|
);
|
|
1991
1998
|
}
|
|
1992
1999
|
return { runtime: detected, source: "detected", discardedHint: supplied };
|
|
@@ -2021,7 +2028,7 @@ function detectRuntime(env) {
|
|
|
2021
2028
|
if (env.HERMES_HOME || env.HERMES_AGENT) return "hermes";
|
|
2022
2029
|
return null;
|
|
2023
2030
|
}
|
|
2024
|
-
var RUNTIME_PROFILES, RUNTIME_ALIASES, RUNTIME_FLAG_VALUES;
|
|
2031
|
+
var RUNTIME_PROFILES, RUNTIME_ALIASES, RUNTIME_FLAG_VALUE_LIST, RUNTIME_FLAG_VALUES;
|
|
2025
2032
|
var init_runtime_registry = __esm({
|
|
2026
2033
|
"src/runtime-registry.ts"() {
|
|
2027
2034
|
init_connect_error();
|
|
@@ -2140,7 +2147,18 @@ var init_runtime_registry = __esm({
|
|
|
2140
2147
|
other: "other",
|
|
2141
2148
|
manual: "other"
|
|
2142
2149
|
};
|
|
2143
|
-
|
|
2150
|
+
RUNTIME_FLAG_VALUE_LIST = [
|
|
2151
|
+
"claude-code",
|
|
2152
|
+
"codex-cli",
|
|
2153
|
+
"codex-desktop",
|
|
2154
|
+
"cursor",
|
|
2155
|
+
"vscode",
|
|
2156
|
+
"vscode-insiders",
|
|
2157
|
+
"claude-desktop",
|
|
2158
|
+
"hermes",
|
|
2159
|
+
"other"
|
|
2160
|
+
];
|
|
2161
|
+
RUNTIME_FLAG_VALUES = RUNTIME_FLAG_VALUE_LIST.join(", ");
|
|
2144
2162
|
}
|
|
2145
2163
|
});
|
|
2146
2164
|
async function acknowledgeLocalSignerConsent(signerPath, log) {
|
|
@@ -3703,7 +3721,7 @@ function defaultPromptIo() {
|
|
|
3703
3721
|
// src/runtime.ts
|
|
3704
3722
|
init_local_mcp_runtime();
|
|
3705
3723
|
init_runtime_manifest();
|
|
3706
|
-
var CONNECTOR_VERSION = "0.1.
|
|
3724
|
+
var CONNECTOR_VERSION = "0.1.31-alpha.0";
|
|
3707
3725
|
var CONNECT_OUTCOME_SCHEMA_VERSION = 1;
|
|
3708
3726
|
async function runConnect(options, deps = {}) {
|
|
3709
3727
|
assertSupportedNodeVersion(deps.nodeVersion, MCP_RUNTIME_MANIFEST.minimumNodeVersion);
|
|
@@ -3728,7 +3746,14 @@ async function runConnect(options, deps = {}) {
|
|
|
3728
3746
|
throw new ConnectError(
|
|
3729
3747
|
"runtime_undetermined",
|
|
3730
3748
|
`Could not determine the agent runtime: nothing was detected in this environment and no --runtime was given. If you are an AI agent running this command: re-run it once, unchanged except for adding --runtime <name>, naming the harness you are running in \u2014 one of: ${RUNTIME_FLAG_VALUES} (the aliases cowork, codex and openclaw are accepted too). Do not guess: if your harness is not one of those, use --runtime other, which stores the credentials and prints the manual MCP steps. Nothing was written and the Haven setup token is still unused.`,
|
|
3731
|
-
"rerun_connect_with_explicit_runtime"
|
|
3749
|
+
"rerun_connect_with_explicit_runtime",
|
|
3750
|
+
// #2091: the values must ride structurally too. The backend's setup
|
|
3751
|
+
// prompt permits a retry only with "one of the values that refusal
|
|
3752
|
+
// lists" — and --json discards prose, so a prose-only list deadlocked
|
|
3753
|
+
// every automation run in an undetected runtime (Codex in the field:
|
|
3754
|
+
// npx needs network, Codex runs network commands unsandboxed, and the
|
|
3755
|
+
// unsandboxed path carries none of the CODEX_* detection vars).
|
|
3756
|
+
{ allowedRuntimes: RUNTIME_FLAG_VALUE_LIST }
|
|
3732
3757
|
);
|
|
3733
3758
|
}
|
|
3734
3759
|
const runtime = selection.runtime;
|
|
@@ -3750,11 +3775,16 @@ async function runConnect(options, deps = {}) {
|
|
|
3750
3775
|
log(`runtime: ${runtime} (chosen at the prompt \u2014 nothing was detected in this environment)`);
|
|
3751
3776
|
}
|
|
3752
3777
|
log("Warming up your connection to Haven\u2026");
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3778
|
+
let setup;
|
|
3779
|
+
try {
|
|
3780
|
+
setup = await api.resolveSetup({
|
|
3781
|
+
setupToken: options.setupToken,
|
|
3782
|
+
connectorVersion,
|
|
3783
|
+
runtime
|
|
3784
|
+
});
|
|
3785
|
+
} catch (err) {
|
|
3786
|
+
throw deadSetupTokenError(err) ?? err;
|
|
3787
|
+
}
|
|
3758
3788
|
assertSetupChallengeIsUsable(setup.challenge.expires_at);
|
|
3759
3789
|
printSetupSummary(setup, log);
|
|
3760
3790
|
await preflightStorage({ baseDir: options.credentialsDir, warn: log });
|
|
@@ -3791,6 +3821,8 @@ async function runConnect(options, deps = {}) {
|
|
|
3791
3821
|
installCapabilities
|
|
3792
3822
|
});
|
|
3793
3823
|
} catch (err) {
|
|
3824
|
+
const dead = deadSetupTokenError(err);
|
|
3825
|
+
if (dead) throw dead;
|
|
3794
3826
|
if (isExpiredSetupChallenge(err)) {
|
|
3795
3827
|
throw new Error(
|
|
3796
3828
|
"The Haven setup challenge expired while connecting. Return to Haven, start a fresh connection, and run its new Connect command. Do not reuse or paste credentials."
|
|
@@ -3988,7 +4020,17 @@ function failedConnectOutcome(runtimeHint, error) {
|
|
|
3988
4020
|
tools: ["haven_get_agent", "haven_get_allowances"],
|
|
3989
4021
|
instruction: "After a successful setup and activation, verify only with haven_get_agent and haven_get_allowances."
|
|
3990
4022
|
},
|
|
3991
|
-
error: {
|
|
4023
|
+
error: {
|
|
4024
|
+
code,
|
|
4025
|
+
next_action: nextAction2,
|
|
4026
|
+
// Only a ConnectError's message enters the JSON record: the vocabulary's
|
|
4027
|
+
// prose is connector-authored and safe to serialize, while a plain
|
|
4028
|
+
// Error can carry arbitrary server or filesystem detail (that stance is
|
|
4029
|
+
// pinned by test). Redaction stays on as belt-and-braces; plain-Error
|
|
4030
|
+
// runs still get their redacted message on stderr via the CLI mirror.
|
|
4031
|
+
...error instanceof ConnectError && message ? { message: redactForAutomation(message) } : {},
|
|
4032
|
+
...error instanceof ConnectError && error.details.allowedRuntimes ? { allowed_runtimes: error.details.allowedRuntimes } : {}
|
|
4033
|
+
}
|
|
3992
4034
|
};
|
|
3993
4035
|
}
|
|
3994
4036
|
function printSetupSummary(setup, log) {
|
|
@@ -4010,16 +4052,20 @@ function assertSetupChallengeIsUsable(expiresAt) {
|
|
|
4010
4052
|
"This Haven setup challenge is expired or invalid. Return to Haven, start a fresh connection, and rerun Connect. No local credentials were written."
|
|
4011
4053
|
);
|
|
4012
4054
|
}
|
|
4055
|
+
function deadSetupTokenError(err) {
|
|
4056
|
+
if (!(err instanceof ConnectRequestError) || err.status !== 410 && err.status !== 401) return null;
|
|
4057
|
+
return new ConnectError(
|
|
4058
|
+
"setup_challenge_expired_or_invalid",
|
|
4059
|
+
"This Haven setup token is expired or invalid \u2014 tokens are single-use and expire 30 minutes after the dashboard issues them, and a mistyped token reads the same way. Return to Haven, start a fresh connection, and run its new Connect command. No local credentials were written.",
|
|
4060
|
+
"return_to_haven_for_fresh_setup"
|
|
4061
|
+
);
|
|
4062
|
+
}
|
|
4013
4063
|
function isExpiredSetupChallenge(err) {
|
|
4014
4064
|
return err instanceof Error && /(?:setup )?challenge.*expir|expir.*(?:setup )?challenge/i.test(err.message);
|
|
4015
4065
|
}
|
|
4016
4066
|
function secureLogger(log, redactPaths = false) {
|
|
4017
4067
|
return (message) => {
|
|
4018
|
-
|
|
4019
|
-
if (redactPaths) {
|
|
4020
|
-
safe = safe.replace(/(?:~|\/)[^\s`"']*\/(?:identity|signer|agent)\.json\b/g, "[credential-file-redacted]").replace(/(?:~|\/)[^\s`"']*\/\.env\b/g, "[credential-env-redacted]");
|
|
4021
|
-
}
|
|
4022
|
-
log(safe);
|
|
4068
|
+
log(redactPaths ? redactForAutomation(message) : redactSecrets(message));
|
|
4023
4069
|
};
|
|
4024
4070
|
}
|
|
4025
4071
|
function printRuntimeInstall(result, log) {
|
|
@@ -4360,6 +4406,8 @@ async function runCli(argv, io = {
|
|
|
4360
4406
|
parsed = parseArgs(argv);
|
|
4361
4407
|
} catch (err) {
|
|
4362
4408
|
if (wantsJson) {
|
|
4409
|
+
io.stderr(`${redactForAutomation(err instanceof Error ? err.message : String(err))}
|
|
4410
|
+
`);
|
|
4363
4411
|
io.stdout(`${JSON.stringify(failedConnectOutcome(void 0, err))}
|
|
4364
4412
|
`);
|
|
4365
4413
|
} else {
|
|
@@ -4540,6 +4588,8 @@ async function runCli(argv, io = {
|
|
|
4540
4588
|
return 0;
|
|
4541
4589
|
} catch (err) {
|
|
4542
4590
|
if (parsed.json) {
|
|
4591
|
+
io.stderr(`${redactForAutomation(err instanceof Error ? err.message : String(err))}
|
|
4592
|
+
`);
|
|
4543
4593
|
io.stdout(`${JSON.stringify(failedConnectOutcome(parsed.options.runtime, err))}
|
|
4544
4594
|
`);
|
|
4545
4595
|
} else {
|