@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/index.cjs
CHANGED
|
@@ -153,6 +153,9 @@ var init_key = __esm({
|
|
|
153
153
|
function redactSecrets(value) {
|
|
154
154
|
return value.replace(API_KEY_RE, "sk_agent_[redacted]").replace(PRIVATE_KEY_RE, "0x[redacted-private-key]");
|
|
155
155
|
}
|
|
156
|
+
function redactForAutomation(value) {
|
|
157
|
+
return redactSecrets(value).replace(/(?:~|\/)[^\s`"']*\/(?:identity|signer|agent)\.json\b/g, "[credential-file-redacted]").replace(/(?:~|\/)[^\s`"']*\/\.env\b/g, "[credential-env-redacted]");
|
|
158
|
+
}
|
|
156
159
|
function shortAddress(address) {
|
|
157
160
|
if (!/^0x[0-9a-fA-F]{40}$/.test(address)) return address;
|
|
158
161
|
return `${address.slice(0, 6)}...${address.slice(-4)}`;
|
|
@@ -523,9 +526,9 @@ var init_runtime_manifest = __esm({
|
|
|
523
526
|
mcpPackage: "@haven_ai/mcp",
|
|
524
527
|
mcpVersion: mcp.MCP_VERSION,
|
|
525
528
|
sdkPackage: "@haven_ai/sdk",
|
|
526
|
-
sdkVersion: "0.1.
|
|
529
|
+
sdkVersion: "0.1.31-alpha.0",
|
|
527
530
|
signerPackage: "@haven_ai/signer",
|
|
528
|
-
signerVersion: "0.1.
|
|
531
|
+
signerVersion: "0.1.31-alpha.0",
|
|
529
532
|
// Sourced from the SDK, never a literal (#1161). This field read '20.0.0'
|
|
530
533
|
// while every package's `engines` said `>=24` and the docs said `>=24.0.0`,
|
|
531
534
|
// so the guard that was supposed to enforce the floor waved Node v23 through
|
|
@@ -1948,11 +1951,13 @@ var init_connect_error = __esm({
|
|
|
1948
1951
|
exports.ConnectError = class extends Error {
|
|
1949
1952
|
code;
|
|
1950
1953
|
nextAction;
|
|
1951
|
-
|
|
1954
|
+
details;
|
|
1955
|
+
constructor(code, message, nextAction2, details = {}) {
|
|
1952
1956
|
super(message);
|
|
1953
1957
|
this.name = "ConnectError";
|
|
1954
1958
|
this.code = code;
|
|
1955
1959
|
this.nextAction = nextAction2;
|
|
1960
|
+
this.details = details;
|
|
1956
1961
|
}
|
|
1957
1962
|
};
|
|
1958
1963
|
}
|
|
@@ -1975,7 +1980,8 @@ async function resolveRuntimeSelection(explicit, force, options = {}) {
|
|
|
1975
1980
|
throw new exports.ConnectError(
|
|
1976
1981
|
"runtime_force_unrecognized",
|
|
1977
1982
|
`Unknown --runtime-force value "${force}". Valid values: ${exports.RUNTIME_FLAG_VALUES}.`,
|
|
1978
|
-
"rerun_connect_with_a_valid_runtime_name"
|
|
1983
|
+
"rerun_connect_with_a_valid_runtime_name",
|
|
1984
|
+
{ allowedRuntimes: RUNTIME_FLAG_VALUE_LIST }
|
|
1979
1985
|
);
|
|
1980
1986
|
}
|
|
1981
1987
|
return { runtime: forced, source: "force" };
|
|
@@ -1988,7 +1994,8 @@ async function resolveRuntimeSelection(explicit, force, options = {}) {
|
|
|
1988
1994
|
throw new exports.ConnectError(
|
|
1989
1995
|
"runtime_unrecognized",
|
|
1990
1996
|
`"${supplied}" is not an agent runtime Haven knows. Valid values: ${exports.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.`,
|
|
1991
|
-
"rerun_connect_with_a_valid_runtime_name"
|
|
1997
|
+
"rerun_connect_with_a_valid_runtime_name",
|
|
1998
|
+
{ allowedRuntimes: RUNTIME_FLAG_VALUE_LIST }
|
|
1992
1999
|
);
|
|
1993
2000
|
}
|
|
1994
2001
|
return { runtime: detected, source: "detected", discardedHint: supplied };
|
|
@@ -2023,7 +2030,7 @@ function detectRuntime(env) {
|
|
|
2023
2030
|
if (env.HERMES_HOME || env.HERMES_AGENT) return "hermes";
|
|
2024
2031
|
return null;
|
|
2025
2032
|
}
|
|
2026
|
-
var RUNTIME_PROFILES, RUNTIME_ALIASES; exports.RUNTIME_FLAG_VALUES = void 0;
|
|
2033
|
+
var RUNTIME_PROFILES, RUNTIME_ALIASES, RUNTIME_FLAG_VALUE_LIST; exports.RUNTIME_FLAG_VALUES = void 0;
|
|
2027
2034
|
var init_runtime_registry = __esm({
|
|
2028
2035
|
"src/runtime-registry.ts"() {
|
|
2029
2036
|
init_connect_error();
|
|
@@ -2142,7 +2149,18 @@ var init_runtime_registry = __esm({
|
|
|
2142
2149
|
other: "other",
|
|
2143
2150
|
manual: "other"
|
|
2144
2151
|
};
|
|
2145
|
-
|
|
2152
|
+
RUNTIME_FLAG_VALUE_LIST = [
|
|
2153
|
+
"claude-code",
|
|
2154
|
+
"codex-cli",
|
|
2155
|
+
"codex-desktop",
|
|
2156
|
+
"cursor",
|
|
2157
|
+
"vscode",
|
|
2158
|
+
"vscode-insiders",
|
|
2159
|
+
"claude-desktop",
|
|
2160
|
+
"hermes",
|
|
2161
|
+
"other"
|
|
2162
|
+
];
|
|
2163
|
+
exports.RUNTIME_FLAG_VALUES = RUNTIME_FLAG_VALUE_LIST.join(", ");
|
|
2146
2164
|
}
|
|
2147
2165
|
});
|
|
2148
2166
|
async function acknowledgeLocalSignerConsent(signerPath, log) {
|
|
@@ -3705,7 +3723,7 @@ function defaultPromptIo() {
|
|
|
3705
3723
|
// src/runtime.ts
|
|
3706
3724
|
init_local_mcp_runtime();
|
|
3707
3725
|
init_runtime_manifest();
|
|
3708
|
-
var CONNECTOR_VERSION = "0.1.
|
|
3726
|
+
var CONNECTOR_VERSION = "0.1.31-alpha.0";
|
|
3709
3727
|
var CONNECT_OUTCOME_SCHEMA_VERSION = 1;
|
|
3710
3728
|
async function runConnect(options, deps = {}) {
|
|
3711
3729
|
assertSupportedNodeVersion(deps.nodeVersion, exports.MCP_RUNTIME_MANIFEST.minimumNodeVersion);
|
|
@@ -3730,7 +3748,14 @@ async function runConnect(options, deps = {}) {
|
|
|
3730
3748
|
throw new exports.ConnectError(
|
|
3731
3749
|
"runtime_undetermined",
|
|
3732
3750
|
`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: ${exports.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.`,
|
|
3733
|
-
"rerun_connect_with_explicit_runtime"
|
|
3751
|
+
"rerun_connect_with_explicit_runtime",
|
|
3752
|
+
// #2091: the values must ride structurally too. The backend's setup
|
|
3753
|
+
// prompt permits a retry only with "one of the values that refusal
|
|
3754
|
+
// lists" — and --json discards prose, so a prose-only list deadlocked
|
|
3755
|
+
// every automation run in an undetected runtime (Codex in the field:
|
|
3756
|
+
// npx needs network, Codex runs network commands unsandboxed, and the
|
|
3757
|
+
// unsandboxed path carries none of the CODEX_* detection vars).
|
|
3758
|
+
{ allowedRuntimes: RUNTIME_FLAG_VALUE_LIST }
|
|
3734
3759
|
);
|
|
3735
3760
|
}
|
|
3736
3761
|
const runtime = selection.runtime;
|
|
@@ -3752,11 +3777,16 @@ async function runConnect(options, deps = {}) {
|
|
|
3752
3777
|
log(`runtime: ${runtime} (chosen at the prompt \u2014 nothing was detected in this environment)`);
|
|
3753
3778
|
}
|
|
3754
3779
|
log("Warming up your connection to Haven\u2026");
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3780
|
+
let setup;
|
|
3781
|
+
try {
|
|
3782
|
+
setup = await api.resolveSetup({
|
|
3783
|
+
setupToken: options.setupToken,
|
|
3784
|
+
connectorVersion,
|
|
3785
|
+
runtime
|
|
3786
|
+
});
|
|
3787
|
+
} catch (err) {
|
|
3788
|
+
throw deadSetupTokenError(err) ?? err;
|
|
3789
|
+
}
|
|
3760
3790
|
assertSetupChallengeIsUsable(setup.challenge.expires_at);
|
|
3761
3791
|
printSetupSummary(setup, log);
|
|
3762
3792
|
await preflightStorage({ baseDir: options.credentialsDir, warn: log });
|
|
@@ -3793,6 +3823,8 @@ async function runConnect(options, deps = {}) {
|
|
|
3793
3823
|
installCapabilities
|
|
3794
3824
|
});
|
|
3795
3825
|
} catch (err) {
|
|
3826
|
+
const dead = deadSetupTokenError(err);
|
|
3827
|
+
if (dead) throw dead;
|
|
3796
3828
|
if (isExpiredSetupChallenge(err)) {
|
|
3797
3829
|
throw new Error(
|
|
3798
3830
|
"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."
|
|
@@ -3990,7 +4022,17 @@ function failedConnectOutcome(runtimeHint, error) {
|
|
|
3990
4022
|
tools: ["haven_get_agent", "haven_get_allowances"],
|
|
3991
4023
|
instruction: "After a successful setup and activation, verify only with haven_get_agent and haven_get_allowances."
|
|
3992
4024
|
},
|
|
3993
|
-
error: {
|
|
4025
|
+
error: {
|
|
4026
|
+
code,
|
|
4027
|
+
next_action: nextAction2,
|
|
4028
|
+
// Only a ConnectError's message enters the JSON record: the vocabulary's
|
|
4029
|
+
// prose is connector-authored and safe to serialize, while a plain
|
|
4030
|
+
// Error can carry arbitrary server or filesystem detail (that stance is
|
|
4031
|
+
// pinned by test). Redaction stays on as belt-and-braces; plain-Error
|
|
4032
|
+
// runs still get their redacted message on stderr via the CLI mirror.
|
|
4033
|
+
...error instanceof exports.ConnectError && message ? { message: redactForAutomation(message) } : {},
|
|
4034
|
+
...error instanceof exports.ConnectError && error.details.allowedRuntimes ? { allowed_runtimes: error.details.allowedRuntimes } : {}
|
|
4035
|
+
}
|
|
3994
4036
|
};
|
|
3995
4037
|
}
|
|
3996
4038
|
function printSetupSummary(setup, log) {
|
|
@@ -4012,16 +4054,20 @@ function assertSetupChallengeIsUsable(expiresAt) {
|
|
|
4012
4054
|
"This Haven setup challenge is expired or invalid. Return to Haven, start a fresh connection, and rerun Connect. No local credentials were written."
|
|
4013
4055
|
);
|
|
4014
4056
|
}
|
|
4057
|
+
function deadSetupTokenError(err) {
|
|
4058
|
+
if (!(err instanceof ConnectRequestError) || err.status !== 410 && err.status !== 401) return null;
|
|
4059
|
+
return new exports.ConnectError(
|
|
4060
|
+
"setup_challenge_expired_or_invalid",
|
|
4061
|
+
"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.",
|
|
4062
|
+
"return_to_haven_for_fresh_setup"
|
|
4063
|
+
);
|
|
4064
|
+
}
|
|
4015
4065
|
function isExpiredSetupChallenge(err) {
|
|
4016
4066
|
return err instanceof Error && /(?:setup )?challenge.*expir|expir.*(?:setup )?challenge/i.test(err.message);
|
|
4017
4067
|
}
|
|
4018
4068
|
function secureLogger(log, redactPaths = false) {
|
|
4019
4069
|
return (message) => {
|
|
4020
|
-
|
|
4021
|
-
if (redactPaths) {
|
|
4022
|
-
safe = safe.replace(/(?:~|\/)[^\s`"']*\/(?:identity|signer|agent)\.json\b/g, "[credential-file-redacted]").replace(/(?:~|\/)[^\s`"']*\/\.env\b/g, "[credential-env-redacted]");
|
|
4023
|
-
}
|
|
4024
|
-
log(safe);
|
|
4070
|
+
log(redactPaths ? redactForAutomation(message) : redactSecrets(message));
|
|
4025
4071
|
};
|
|
4026
4072
|
}
|
|
4027
4073
|
function printRuntimeInstall(result, log) {
|
|
@@ -4365,6 +4411,8 @@ async function runCli(argv, io = {
|
|
|
4365
4411
|
parsed = parseArgs(argv);
|
|
4366
4412
|
} catch (err) {
|
|
4367
4413
|
if (wantsJson) {
|
|
4414
|
+
io.stderr(`${redactForAutomation(err instanceof Error ? err.message : String(err))}
|
|
4415
|
+
`);
|
|
4368
4416
|
io.stdout(`${JSON.stringify(failedConnectOutcome(void 0, err))}
|
|
4369
4417
|
`);
|
|
4370
4418
|
} else {
|
|
@@ -4545,6 +4593,8 @@ async function runCli(argv, io = {
|
|
|
4545
4593
|
return 0;
|
|
4546
4594
|
} catch (err) {
|
|
4547
4595
|
if (parsed.json) {
|
|
4596
|
+
io.stderr(`${redactForAutomation(err instanceof Error ? err.message : String(err))}
|
|
4597
|
+
`);
|
|
4548
4598
|
io.stdout(`${JSON.stringify(failedConnectOutcome(parsed.options.runtime, err))}
|
|
4549
4599
|
`);
|
|
4550
4600
|
} else {
|