@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.js
CHANGED
|
@@ -147,6 +147,9 @@ var init_key = __esm({
|
|
|
147
147
|
function redactSecrets(value) {
|
|
148
148
|
return value.replace(API_KEY_RE, "sk_agent_[redacted]").replace(PRIVATE_KEY_RE, "0x[redacted-private-key]");
|
|
149
149
|
}
|
|
150
|
+
function redactForAutomation(value) {
|
|
151
|
+
return redactSecrets(value).replace(/(?:~|\/)[^\s`"']*\/(?:identity|signer|agent)\.json\b/g, "[credential-file-redacted]").replace(/(?:~|\/)[^\s`"']*\/\.env\b/g, "[credential-env-redacted]");
|
|
152
|
+
}
|
|
150
153
|
function shortAddress(address) {
|
|
151
154
|
if (!/^0x[0-9a-fA-F]{40}$/.test(address)) return address;
|
|
152
155
|
return `${address.slice(0, 6)}...${address.slice(-4)}`;
|
|
@@ -517,9 +520,9 @@ var init_runtime_manifest = __esm({
|
|
|
517
520
|
mcpPackage: "@haven_ai/mcp",
|
|
518
521
|
mcpVersion: MCP_VERSION,
|
|
519
522
|
sdkPackage: "@haven_ai/sdk",
|
|
520
|
-
sdkVersion: "0.1.
|
|
523
|
+
sdkVersion: "0.1.31-alpha.0",
|
|
521
524
|
signerPackage: "@haven_ai/signer",
|
|
522
|
-
signerVersion: "0.1.
|
|
525
|
+
signerVersion: "0.1.31-alpha.0",
|
|
523
526
|
// Sourced from the SDK, never a literal (#1161). This field read '20.0.0'
|
|
524
527
|
// while every package's `engines` said `>=24` and the docs said `>=24.0.0`,
|
|
525
528
|
// so the guard that was supposed to enforce the floor waved Node v23 through
|
|
@@ -1939,11 +1942,13 @@ var init_connect_error = __esm({
|
|
|
1939
1942
|
ConnectError = class extends Error {
|
|
1940
1943
|
code;
|
|
1941
1944
|
nextAction;
|
|
1942
|
-
|
|
1945
|
+
details;
|
|
1946
|
+
constructor(code, message, nextAction2, details = {}) {
|
|
1943
1947
|
super(message);
|
|
1944
1948
|
this.name = "ConnectError";
|
|
1945
1949
|
this.code = code;
|
|
1946
1950
|
this.nextAction = nextAction2;
|
|
1951
|
+
this.details = details;
|
|
1947
1952
|
}
|
|
1948
1953
|
};
|
|
1949
1954
|
}
|
|
@@ -1966,7 +1971,8 @@ async function resolveRuntimeSelection(explicit, force, options = {}) {
|
|
|
1966
1971
|
throw new ConnectError(
|
|
1967
1972
|
"runtime_force_unrecognized",
|
|
1968
1973
|
`Unknown --runtime-force value "${force}". Valid values: ${RUNTIME_FLAG_VALUES}.`,
|
|
1969
|
-
"rerun_connect_with_a_valid_runtime_name"
|
|
1974
|
+
"rerun_connect_with_a_valid_runtime_name",
|
|
1975
|
+
{ allowedRuntimes: RUNTIME_FLAG_VALUE_LIST }
|
|
1970
1976
|
);
|
|
1971
1977
|
}
|
|
1972
1978
|
return { runtime: forced, source: "force" };
|
|
@@ -1979,7 +1985,8 @@ async function resolveRuntimeSelection(explicit, force, options = {}) {
|
|
|
1979
1985
|
throw new ConnectError(
|
|
1980
1986
|
"runtime_unrecognized",
|
|
1981
1987
|
`"${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.`,
|
|
1982
|
-
"rerun_connect_with_a_valid_runtime_name"
|
|
1988
|
+
"rerun_connect_with_a_valid_runtime_name",
|
|
1989
|
+
{ allowedRuntimes: RUNTIME_FLAG_VALUE_LIST }
|
|
1983
1990
|
);
|
|
1984
1991
|
}
|
|
1985
1992
|
return { runtime: detected, source: "detected", discardedHint: supplied };
|
|
@@ -2014,7 +2021,7 @@ function detectRuntime(env) {
|
|
|
2014
2021
|
if (env.HERMES_HOME || env.HERMES_AGENT) return "hermes";
|
|
2015
2022
|
return null;
|
|
2016
2023
|
}
|
|
2017
|
-
var RUNTIME_PROFILES, RUNTIME_ALIASES, RUNTIME_FLAG_VALUES;
|
|
2024
|
+
var RUNTIME_PROFILES, RUNTIME_ALIASES, RUNTIME_FLAG_VALUE_LIST, RUNTIME_FLAG_VALUES;
|
|
2018
2025
|
var init_runtime_registry = __esm({
|
|
2019
2026
|
"src/runtime-registry.ts"() {
|
|
2020
2027
|
init_connect_error();
|
|
@@ -2133,7 +2140,18 @@ var init_runtime_registry = __esm({
|
|
|
2133
2140
|
other: "other",
|
|
2134
2141
|
manual: "other"
|
|
2135
2142
|
};
|
|
2136
|
-
|
|
2143
|
+
RUNTIME_FLAG_VALUE_LIST = [
|
|
2144
|
+
"claude-code",
|
|
2145
|
+
"codex-cli",
|
|
2146
|
+
"codex-desktop",
|
|
2147
|
+
"cursor",
|
|
2148
|
+
"vscode",
|
|
2149
|
+
"vscode-insiders",
|
|
2150
|
+
"claude-desktop",
|
|
2151
|
+
"hermes",
|
|
2152
|
+
"other"
|
|
2153
|
+
];
|
|
2154
|
+
RUNTIME_FLAG_VALUES = RUNTIME_FLAG_VALUE_LIST.join(", ");
|
|
2137
2155
|
}
|
|
2138
2156
|
});
|
|
2139
2157
|
async function acknowledgeLocalSignerConsent(signerPath, log) {
|
|
@@ -3696,7 +3714,7 @@ function defaultPromptIo() {
|
|
|
3696
3714
|
// src/runtime.ts
|
|
3697
3715
|
init_local_mcp_runtime();
|
|
3698
3716
|
init_runtime_manifest();
|
|
3699
|
-
var CONNECTOR_VERSION = "0.1.
|
|
3717
|
+
var CONNECTOR_VERSION = "0.1.31-alpha.0";
|
|
3700
3718
|
var CONNECT_OUTCOME_SCHEMA_VERSION = 1;
|
|
3701
3719
|
async function runConnect(options, deps = {}) {
|
|
3702
3720
|
assertSupportedNodeVersion(deps.nodeVersion, MCP_RUNTIME_MANIFEST.minimumNodeVersion);
|
|
@@ -3721,7 +3739,14 @@ async function runConnect(options, deps = {}) {
|
|
|
3721
3739
|
throw new ConnectError(
|
|
3722
3740
|
"runtime_undetermined",
|
|
3723
3741
|
`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.`,
|
|
3724
|
-
"rerun_connect_with_explicit_runtime"
|
|
3742
|
+
"rerun_connect_with_explicit_runtime",
|
|
3743
|
+
// #2091: the values must ride structurally too. The backend's setup
|
|
3744
|
+
// prompt permits a retry only with "one of the values that refusal
|
|
3745
|
+
// lists" — and --json discards prose, so a prose-only list deadlocked
|
|
3746
|
+
// every automation run in an undetected runtime (Codex in the field:
|
|
3747
|
+
// npx needs network, Codex runs network commands unsandboxed, and the
|
|
3748
|
+
// unsandboxed path carries none of the CODEX_* detection vars).
|
|
3749
|
+
{ allowedRuntimes: RUNTIME_FLAG_VALUE_LIST }
|
|
3725
3750
|
);
|
|
3726
3751
|
}
|
|
3727
3752
|
const runtime = selection.runtime;
|
|
@@ -3743,11 +3768,16 @@ async function runConnect(options, deps = {}) {
|
|
|
3743
3768
|
log(`runtime: ${runtime} (chosen at the prompt \u2014 nothing was detected in this environment)`);
|
|
3744
3769
|
}
|
|
3745
3770
|
log("Warming up your connection to Haven\u2026");
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3771
|
+
let setup;
|
|
3772
|
+
try {
|
|
3773
|
+
setup = await api.resolveSetup({
|
|
3774
|
+
setupToken: options.setupToken,
|
|
3775
|
+
connectorVersion,
|
|
3776
|
+
runtime
|
|
3777
|
+
});
|
|
3778
|
+
} catch (err) {
|
|
3779
|
+
throw deadSetupTokenError(err) ?? err;
|
|
3780
|
+
}
|
|
3751
3781
|
assertSetupChallengeIsUsable(setup.challenge.expires_at);
|
|
3752
3782
|
printSetupSummary(setup, log);
|
|
3753
3783
|
await preflightStorage({ baseDir: options.credentialsDir, warn: log });
|
|
@@ -3784,6 +3814,8 @@ async function runConnect(options, deps = {}) {
|
|
|
3784
3814
|
installCapabilities
|
|
3785
3815
|
});
|
|
3786
3816
|
} catch (err) {
|
|
3817
|
+
const dead = deadSetupTokenError(err);
|
|
3818
|
+
if (dead) throw dead;
|
|
3787
3819
|
if (isExpiredSetupChallenge(err)) {
|
|
3788
3820
|
throw new Error(
|
|
3789
3821
|
"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."
|
|
@@ -3981,7 +4013,17 @@ function failedConnectOutcome(runtimeHint, error) {
|
|
|
3981
4013
|
tools: ["haven_get_agent", "haven_get_allowances"],
|
|
3982
4014
|
instruction: "After a successful setup and activation, verify only with haven_get_agent and haven_get_allowances."
|
|
3983
4015
|
},
|
|
3984
|
-
error: {
|
|
4016
|
+
error: {
|
|
4017
|
+
code,
|
|
4018
|
+
next_action: nextAction2,
|
|
4019
|
+
// Only a ConnectError's message enters the JSON record: the vocabulary's
|
|
4020
|
+
// prose is connector-authored and safe to serialize, while a plain
|
|
4021
|
+
// Error can carry arbitrary server or filesystem detail (that stance is
|
|
4022
|
+
// pinned by test). Redaction stays on as belt-and-braces; plain-Error
|
|
4023
|
+
// runs still get their redacted message on stderr via the CLI mirror.
|
|
4024
|
+
...error instanceof ConnectError && message ? { message: redactForAutomation(message) } : {},
|
|
4025
|
+
...error instanceof ConnectError && error.details.allowedRuntimes ? { allowed_runtimes: error.details.allowedRuntimes } : {}
|
|
4026
|
+
}
|
|
3985
4027
|
};
|
|
3986
4028
|
}
|
|
3987
4029
|
function printSetupSummary(setup, log) {
|
|
@@ -4003,16 +4045,20 @@ function assertSetupChallengeIsUsable(expiresAt) {
|
|
|
4003
4045
|
"This Haven setup challenge is expired or invalid. Return to Haven, start a fresh connection, and rerun Connect. No local credentials were written."
|
|
4004
4046
|
);
|
|
4005
4047
|
}
|
|
4048
|
+
function deadSetupTokenError(err) {
|
|
4049
|
+
if (!(err instanceof ConnectRequestError) || err.status !== 410 && err.status !== 401) return null;
|
|
4050
|
+
return new ConnectError(
|
|
4051
|
+
"setup_challenge_expired_or_invalid",
|
|
4052
|
+
"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.",
|
|
4053
|
+
"return_to_haven_for_fresh_setup"
|
|
4054
|
+
);
|
|
4055
|
+
}
|
|
4006
4056
|
function isExpiredSetupChallenge(err) {
|
|
4007
4057
|
return err instanceof Error && /(?:setup )?challenge.*expir|expir.*(?:setup )?challenge/i.test(err.message);
|
|
4008
4058
|
}
|
|
4009
4059
|
function secureLogger(log, redactPaths = false) {
|
|
4010
4060
|
return (message) => {
|
|
4011
|
-
|
|
4012
|
-
if (redactPaths) {
|
|
4013
|
-
safe = safe.replace(/(?:~|\/)[^\s`"']*\/(?:identity|signer|agent)\.json\b/g, "[credential-file-redacted]").replace(/(?:~|\/)[^\s`"']*\/\.env\b/g, "[credential-env-redacted]");
|
|
4014
|
-
}
|
|
4015
|
-
log(safe);
|
|
4061
|
+
log(redactPaths ? redactForAutomation(message) : redactSecrets(message));
|
|
4016
4062
|
};
|
|
4017
4063
|
}
|
|
4018
4064
|
function printRuntimeInstall(result, log) {
|
|
@@ -4353,6 +4399,8 @@ async function runCli(argv, io = {
|
|
|
4353
4399
|
parsed = parseArgs(argv);
|
|
4354
4400
|
} catch (err) {
|
|
4355
4401
|
if (wantsJson) {
|
|
4402
|
+
io.stderr(`${redactForAutomation(err instanceof Error ? err.message : String(err))}
|
|
4403
|
+
`);
|
|
4356
4404
|
io.stdout(`${JSON.stringify(failedConnectOutcome(void 0, err))}
|
|
4357
4405
|
`);
|
|
4358
4406
|
} else {
|
|
@@ -4533,6 +4581,8 @@ async function runCli(argv, io = {
|
|
|
4533
4581
|
return 0;
|
|
4534
4582
|
} catch (err) {
|
|
4535
4583
|
if (parsed.json) {
|
|
4584
|
+
io.stderr(`${redactForAutomation(err instanceof Error ? err.message : String(err))}
|
|
4585
|
+
`);
|
|
4536
4586
|
io.stdout(`${JSON.stringify(failedConnectOutcome(parsed.options.runtime, err))}
|
|
4537
4587
|
`);
|
|
4538
4588
|
} else {
|