@haven_ai/connect 0.1.11-alpha.0 → 0.1.13-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 +180 -93
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +178 -91
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +181 -93
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -5
- package/dist/index.d.ts +52 -5
- package/dist/index.js +179 -92
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.cts
CHANGED
|
@@ -64,6 +64,7 @@ interface ResolvedSetup {
|
|
|
64
64
|
reset_period_min: number;
|
|
65
65
|
}>;
|
|
66
66
|
hosted_mcp_url: string;
|
|
67
|
+
x402_binding_signer?: string | null;
|
|
67
68
|
challenge: {
|
|
68
69
|
id: string;
|
|
69
70
|
message: string;
|
|
@@ -112,6 +113,7 @@ interface WriteCredentialInput {
|
|
|
112
113
|
}>;
|
|
113
114
|
apiUrl: string;
|
|
114
115
|
hostedMcpUrl: string;
|
|
116
|
+
x402BindingSigner?: string;
|
|
115
117
|
warn?: (message: string) => void;
|
|
116
118
|
}
|
|
117
119
|
interface PreflightCredentialStorageInput {
|
|
@@ -158,6 +160,42 @@ interface PreparedLocalMcpRuntime {
|
|
|
158
160
|
messages: string[];
|
|
159
161
|
}
|
|
160
162
|
|
|
163
|
+
interface PrepareSignerRuntimeInput {
|
|
164
|
+
credentialDirectory: string;
|
|
165
|
+
signerPath: string;
|
|
166
|
+
homeDir?: string;
|
|
167
|
+
}
|
|
168
|
+
interface PreparedSignerRuntime {
|
|
169
|
+
/** Absolute command to register as the signer MCP `command`. */
|
|
170
|
+
command: string;
|
|
171
|
+
/** Args to register alongside `command` (credentials are baked into the wrapper). */
|
|
172
|
+
args: string[];
|
|
173
|
+
wrapperPath: string;
|
|
174
|
+
runtimeDirectory: string;
|
|
175
|
+
npmCacheDirectory: string;
|
|
176
|
+
cliPath: string;
|
|
177
|
+
messages: string[];
|
|
178
|
+
}
|
|
179
|
+
interface SignerRuntimeDeps {
|
|
180
|
+
runCommand?: (command: string, args: string[]) => Promise<void>;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Pre-install the edge signer into a version-pinned, connector-managed
|
|
184
|
+
* directory and write a stable wrapper that launches it with an absolute Node
|
|
185
|
+
* path. The signer MCP is then registered as `command: <wrapper>` instead of a
|
|
186
|
+
* runtime `npx -y @haven_ai/signer@…` invocation.
|
|
187
|
+
*
|
|
188
|
+
* Why: launching the signer via bare `npx` at every MCP spawn made it depend on
|
|
189
|
+
* the PATH/environment the agent runtime hands the stdio subprocess, which is
|
|
190
|
+
* not the user's interactive shell — the failure mode that left `haven-signer`
|
|
191
|
+
* stuck at "Failed to connect" while the hosted HTTP server connected fine. The
|
|
192
|
+
* local MCP topology already avoids this with the same pre-install + wrapper
|
|
193
|
+
* pattern (see prepareLocalMcpRuntime); this brings the default hosted+signer
|
|
194
|
+
* topology to parity. Version stays pinned (no unpinned `npm i -g`), and the
|
|
195
|
+
* wrapper lives under ~/.haven so the reset flow already cleans it up.
|
|
196
|
+
*/
|
|
197
|
+
declare function prepareSignerRuntime(input: PrepareSignerRuntimeInput, deps?: SignerRuntimeDeps): Promise<PreparedSignerRuntime>;
|
|
198
|
+
|
|
161
199
|
interface RuntimeInstallInput {
|
|
162
200
|
runtime?: string;
|
|
163
201
|
hostedMcpUrl: string;
|
|
@@ -191,6 +229,14 @@ interface RuntimeInstallResult {
|
|
|
191
229
|
localMcpAcknowledged?: boolean;
|
|
192
230
|
activationCommand?: string;
|
|
193
231
|
skillInstalled?: boolean;
|
|
232
|
+
/**
|
|
233
|
+
* Hosted topology only: true when the signer was pre-installed and registered
|
|
234
|
+
* via its absolute wrapper, false when prep failed and it fell back to the
|
|
235
|
+
* fragile runtime-`npx` launch. Undefined for local/manual topologies that
|
|
236
|
+
* do not run the signer as a separate MCP. Lets callers/tests detect the
|
|
237
|
+
* silent npx fallback instead of treating every write as fully healthy.
|
|
238
|
+
*/
|
|
239
|
+
signerRuntimePrepared?: boolean;
|
|
194
240
|
messages: string[];
|
|
195
241
|
}
|
|
196
242
|
interface RuntimeInstallDeps {
|
|
@@ -199,6 +245,7 @@ interface RuntimeInstallDeps {
|
|
|
199
245
|
fetch?: typeof fetch;
|
|
200
246
|
runCommand?: (command: string, args: string[]) => Promise<void>;
|
|
201
247
|
prepareLocalMcpRuntime?: (input: PrepareLocalMcpRuntimeInput) => Promise<PreparedLocalMcpRuntime>;
|
|
248
|
+
prepareSignerRuntime?: (input: PrepareSignerRuntimeInput) => Promise<PreparedSignerRuntime>;
|
|
202
249
|
probeLocalMcpTools?: (command: string, args: string[], requiredTools: readonly string[]) => Promise<LocalMcpProbeResult>;
|
|
203
250
|
}
|
|
204
251
|
declare function installRuntime(input: RuntimeInstallInput, deps?: RuntimeInstallDeps): Promise<RuntimeInstallResult>;
|
|
@@ -207,7 +254,7 @@ declare function runtimeInstallCapabilities(runtime: string | undefined, env?: N
|
|
|
207
254
|
restartRequired: boolean;
|
|
208
255
|
};
|
|
209
256
|
|
|
210
|
-
declare const CONNECTOR_VERSION = "0.1.
|
|
257
|
+
declare const CONNECTOR_VERSION = "0.1.13-alpha.0";
|
|
211
258
|
interface ConnectOptions {
|
|
212
259
|
setupToken: string;
|
|
213
260
|
apiBaseUrl: string;
|
|
@@ -248,11 +295,11 @@ declare function shortAddress(address: string): string;
|
|
|
248
295
|
|
|
249
296
|
declare const MCP_RUNTIME_MANIFEST: {
|
|
250
297
|
readonly mcpPackage: "@haven_ai/mcp";
|
|
251
|
-
readonly mcpVersion: "0.1.
|
|
298
|
+
readonly mcpVersion: "0.1.13-alpha.0";
|
|
252
299
|
readonly sdkPackage: "@haven_ai/sdk";
|
|
253
|
-
readonly sdkVersion: "0.1.
|
|
300
|
+
readonly sdkVersion: "0.1.13-alpha.0";
|
|
254
301
|
readonly signerPackage: "@haven_ai/signer";
|
|
255
|
-
readonly signerVersion: "0.1.
|
|
302
|
+
readonly signerVersion: "0.1.13-alpha.0";
|
|
256
303
|
readonly minimumNodeVersion: "20.0.0";
|
|
257
304
|
readonly supportedClients: readonly ["codex-cli", "codex-desktop", "claude-code"];
|
|
258
305
|
readonly requiredTools: readonly string[];
|
|
@@ -261,4 +308,4 @@ declare function mcpPackageSpec(): string;
|
|
|
261
308
|
declare function sdkPackageSpec(): string;
|
|
262
309
|
declare function signerPackageSpec(): string;
|
|
263
310
|
|
|
264
|
-
export { CONNECTOR_VERSION, type ConnectApiClient, type ConnectDeps, type ConnectOptions, type ConnectResult, type LocalDelegateKey, MCP_RUNTIME_MANIFEST, type RegisterSetupInput, type RegisterSetupResponse, type ResolveSetupInput, type ResolvedSetup, type RuntimeId, type RuntimeInstallInput, type RuntimeInstallResult, type RuntimeProfile, type StoredCredentialPaths, type UpdateInstallStatusInput, type WriteCredentialInput, createConnectApiClient, defaultAgentDirectory, delegateKeyFromPrivateKey, generateDelegateKey, helpText, installRuntime, mcpPackageSpec, normalizeRuntime, parseArgs, redactSecrets, runConnect, runtimeInstallCapabilities, runtimeProfile, sdkPackageSpec, shortAddress, signerPackageSpec, writeCredentialFiles };
|
|
311
|
+
export { CONNECTOR_VERSION, type ConnectApiClient, type ConnectDeps, type ConnectOptions, type ConnectResult, type LocalDelegateKey, MCP_RUNTIME_MANIFEST, 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, createConnectApiClient, defaultAgentDirectory, delegateKeyFromPrivateKey, generateDelegateKey, helpText, installRuntime, mcpPackageSpec, normalizeRuntime, parseArgs, prepareSignerRuntime, redactSecrets, runConnect, runtimeInstallCapabilities, runtimeProfile, sdkPackageSpec, shortAddress, signerPackageSpec, writeCredentialFiles };
|
package/dist/index.d.ts
CHANGED
|
@@ -64,6 +64,7 @@ interface ResolvedSetup {
|
|
|
64
64
|
reset_period_min: number;
|
|
65
65
|
}>;
|
|
66
66
|
hosted_mcp_url: string;
|
|
67
|
+
x402_binding_signer?: string | null;
|
|
67
68
|
challenge: {
|
|
68
69
|
id: string;
|
|
69
70
|
message: string;
|
|
@@ -112,6 +113,7 @@ interface WriteCredentialInput {
|
|
|
112
113
|
}>;
|
|
113
114
|
apiUrl: string;
|
|
114
115
|
hostedMcpUrl: string;
|
|
116
|
+
x402BindingSigner?: string;
|
|
115
117
|
warn?: (message: string) => void;
|
|
116
118
|
}
|
|
117
119
|
interface PreflightCredentialStorageInput {
|
|
@@ -158,6 +160,42 @@ interface PreparedLocalMcpRuntime {
|
|
|
158
160
|
messages: string[];
|
|
159
161
|
}
|
|
160
162
|
|
|
163
|
+
interface PrepareSignerRuntimeInput {
|
|
164
|
+
credentialDirectory: string;
|
|
165
|
+
signerPath: string;
|
|
166
|
+
homeDir?: string;
|
|
167
|
+
}
|
|
168
|
+
interface PreparedSignerRuntime {
|
|
169
|
+
/** Absolute command to register as the signer MCP `command`. */
|
|
170
|
+
command: string;
|
|
171
|
+
/** Args to register alongside `command` (credentials are baked into the wrapper). */
|
|
172
|
+
args: string[];
|
|
173
|
+
wrapperPath: string;
|
|
174
|
+
runtimeDirectory: string;
|
|
175
|
+
npmCacheDirectory: string;
|
|
176
|
+
cliPath: string;
|
|
177
|
+
messages: string[];
|
|
178
|
+
}
|
|
179
|
+
interface SignerRuntimeDeps {
|
|
180
|
+
runCommand?: (command: string, args: string[]) => Promise<void>;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Pre-install the edge signer into a version-pinned, connector-managed
|
|
184
|
+
* directory and write a stable wrapper that launches it with an absolute Node
|
|
185
|
+
* path. The signer MCP is then registered as `command: <wrapper>` instead of a
|
|
186
|
+
* runtime `npx -y @haven_ai/signer@…` invocation.
|
|
187
|
+
*
|
|
188
|
+
* Why: launching the signer via bare `npx` at every MCP spawn made it depend on
|
|
189
|
+
* the PATH/environment the agent runtime hands the stdio subprocess, which is
|
|
190
|
+
* not the user's interactive shell — the failure mode that left `haven-signer`
|
|
191
|
+
* stuck at "Failed to connect" while the hosted HTTP server connected fine. The
|
|
192
|
+
* local MCP topology already avoids this with the same pre-install + wrapper
|
|
193
|
+
* pattern (see prepareLocalMcpRuntime); this brings the default hosted+signer
|
|
194
|
+
* topology to parity. Version stays pinned (no unpinned `npm i -g`), and the
|
|
195
|
+
* wrapper lives under ~/.haven so the reset flow already cleans it up.
|
|
196
|
+
*/
|
|
197
|
+
declare function prepareSignerRuntime(input: PrepareSignerRuntimeInput, deps?: SignerRuntimeDeps): Promise<PreparedSignerRuntime>;
|
|
198
|
+
|
|
161
199
|
interface RuntimeInstallInput {
|
|
162
200
|
runtime?: string;
|
|
163
201
|
hostedMcpUrl: string;
|
|
@@ -191,6 +229,14 @@ interface RuntimeInstallResult {
|
|
|
191
229
|
localMcpAcknowledged?: boolean;
|
|
192
230
|
activationCommand?: string;
|
|
193
231
|
skillInstalled?: boolean;
|
|
232
|
+
/**
|
|
233
|
+
* Hosted topology only: true when the signer was pre-installed and registered
|
|
234
|
+
* via its absolute wrapper, false when prep failed and it fell back to the
|
|
235
|
+
* fragile runtime-`npx` launch. Undefined for local/manual topologies that
|
|
236
|
+
* do not run the signer as a separate MCP. Lets callers/tests detect the
|
|
237
|
+
* silent npx fallback instead of treating every write as fully healthy.
|
|
238
|
+
*/
|
|
239
|
+
signerRuntimePrepared?: boolean;
|
|
194
240
|
messages: string[];
|
|
195
241
|
}
|
|
196
242
|
interface RuntimeInstallDeps {
|
|
@@ -199,6 +245,7 @@ interface RuntimeInstallDeps {
|
|
|
199
245
|
fetch?: typeof fetch;
|
|
200
246
|
runCommand?: (command: string, args: string[]) => Promise<void>;
|
|
201
247
|
prepareLocalMcpRuntime?: (input: PrepareLocalMcpRuntimeInput) => Promise<PreparedLocalMcpRuntime>;
|
|
248
|
+
prepareSignerRuntime?: (input: PrepareSignerRuntimeInput) => Promise<PreparedSignerRuntime>;
|
|
202
249
|
probeLocalMcpTools?: (command: string, args: string[], requiredTools: readonly string[]) => Promise<LocalMcpProbeResult>;
|
|
203
250
|
}
|
|
204
251
|
declare function installRuntime(input: RuntimeInstallInput, deps?: RuntimeInstallDeps): Promise<RuntimeInstallResult>;
|
|
@@ -207,7 +254,7 @@ declare function runtimeInstallCapabilities(runtime: string | undefined, env?: N
|
|
|
207
254
|
restartRequired: boolean;
|
|
208
255
|
};
|
|
209
256
|
|
|
210
|
-
declare const CONNECTOR_VERSION = "0.1.
|
|
257
|
+
declare const CONNECTOR_VERSION = "0.1.13-alpha.0";
|
|
211
258
|
interface ConnectOptions {
|
|
212
259
|
setupToken: string;
|
|
213
260
|
apiBaseUrl: string;
|
|
@@ -248,11 +295,11 @@ declare function shortAddress(address: string): string;
|
|
|
248
295
|
|
|
249
296
|
declare const MCP_RUNTIME_MANIFEST: {
|
|
250
297
|
readonly mcpPackage: "@haven_ai/mcp";
|
|
251
|
-
readonly mcpVersion: "0.1.
|
|
298
|
+
readonly mcpVersion: "0.1.13-alpha.0";
|
|
252
299
|
readonly sdkPackage: "@haven_ai/sdk";
|
|
253
|
-
readonly sdkVersion: "0.1.
|
|
300
|
+
readonly sdkVersion: "0.1.13-alpha.0";
|
|
254
301
|
readonly signerPackage: "@haven_ai/signer";
|
|
255
|
-
readonly signerVersion: "0.1.
|
|
302
|
+
readonly signerVersion: "0.1.13-alpha.0";
|
|
256
303
|
readonly minimumNodeVersion: "20.0.0";
|
|
257
304
|
readonly supportedClients: readonly ["codex-cli", "codex-desktop", "claude-code"];
|
|
258
305
|
readonly requiredTools: readonly string[];
|
|
@@ -261,4 +308,4 @@ declare function mcpPackageSpec(): string;
|
|
|
261
308
|
declare function sdkPackageSpec(): string;
|
|
262
309
|
declare function signerPackageSpec(): string;
|
|
263
310
|
|
|
264
|
-
export { CONNECTOR_VERSION, type ConnectApiClient, type ConnectDeps, type ConnectOptions, type ConnectResult, type LocalDelegateKey, MCP_RUNTIME_MANIFEST, type RegisterSetupInput, type RegisterSetupResponse, type ResolveSetupInput, type ResolvedSetup, type RuntimeId, type RuntimeInstallInput, type RuntimeInstallResult, type RuntimeProfile, type StoredCredentialPaths, type UpdateInstallStatusInput, type WriteCredentialInput, createConnectApiClient, defaultAgentDirectory, delegateKeyFromPrivateKey, generateDelegateKey, helpText, installRuntime, mcpPackageSpec, normalizeRuntime, parseArgs, redactSecrets, runConnect, runtimeInstallCapabilities, runtimeProfile, sdkPackageSpec, shortAddress, signerPackageSpec, writeCredentialFiles };
|
|
311
|
+
export { CONNECTOR_VERSION, type ConnectApiClient, type ConnectDeps, type ConnectOptions, type ConnectResult, type LocalDelegateKey, MCP_RUNTIME_MANIFEST, 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, createConnectApiClient, defaultAgentDirectory, delegateKeyFromPrivateKey, generateDelegateKey, helpText, installRuntime, mcpPackageSpec, normalizeRuntime, parseArgs, prepareSignerRuntime, redactSecrets, runConnect, runtimeInstallCapabilities, runtimeProfile, sdkPackageSpec, shortAddress, signerPackageSpec, writeCredentialFiles };
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { join, resolve, dirname } from 'path';
|
|
|
6
6
|
import { execFile, spawn } from 'child_process';
|
|
7
7
|
import { promisify } from 'util';
|
|
8
8
|
import { registeredToolNames, MCP_VERSION, ensureConsent, computeConsentHash, loadCredentials, consentInputFromClient } from '@haven_ai/mcp';
|
|
9
|
+
import { SKILL_FOLDER_NAME, HAVEN_SKILL_MD } from '@haven_ai/sdk';
|
|
9
10
|
import { ensureSignerConsent, computeSignerConsentHash, loadSignerCredentials, createEdgeSigner, toolSchemas } from '@haven_ai/signer';
|
|
10
11
|
|
|
11
12
|
// src/api.ts
|
|
@@ -140,6 +141,7 @@ async function writeCredentialFiles(input) {
|
|
|
140
141
|
safe_address: input.safeAddress,
|
|
141
142
|
chain_id: input.chainId,
|
|
142
143
|
network: input.network,
|
|
144
|
+
x402_binding_signer: input.x402BindingSigner,
|
|
143
145
|
note: "Local signer credential. Haven backend never receives this private key."
|
|
144
146
|
},
|
|
145
147
|
input.warn
|
|
@@ -206,9 +208,9 @@ var MCP_RUNTIME_MANIFEST = {
|
|
|
206
208
|
mcpPackage: "@haven_ai/mcp",
|
|
207
209
|
mcpVersion: MCP_VERSION,
|
|
208
210
|
sdkPackage: "@haven_ai/sdk",
|
|
209
|
-
sdkVersion: "0.1.
|
|
211
|
+
sdkVersion: "0.1.13-alpha.0",
|
|
210
212
|
signerPackage: "@haven_ai/signer",
|
|
211
|
-
signerVersion: "0.1.
|
|
213
|
+
signerVersion: "0.1.13-alpha.0",
|
|
212
214
|
minimumNodeVersion: "20.0.0",
|
|
213
215
|
supportedClients: ["codex-cli", "codex-desktop", "claude-code"],
|
|
214
216
|
requiredTools: registeredToolNames()
|
|
@@ -381,10 +383,16 @@ function buildHostedServer(hostedMcpUrl, apiKey, runtime) {
|
|
|
381
383
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
382
384
|
};
|
|
383
385
|
}
|
|
384
|
-
function
|
|
385
|
-
|
|
386
|
+
function resolveSignerLaunchSpec(input) {
|
|
387
|
+
return input.signerCommand ?? {
|
|
386
388
|
command: "npx",
|
|
387
|
-
args: ["-y",
|
|
389
|
+
args: ["-y", signerPackageSpec(), "--credentials", input.signerPath]
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
function buildSignerServer(spec, runtime) {
|
|
393
|
+
const server = {
|
|
394
|
+
command: spec.command,
|
|
395
|
+
args: spec.args
|
|
388
396
|
};
|
|
389
397
|
if (runtime === "vscode" || runtime === "vscode-insiders") return { type: "stdio", ...server };
|
|
390
398
|
return server;
|
|
@@ -417,7 +425,7 @@ function mergeCodexToml(existingToml, localMcpCommand) {
|
|
|
417
425
|
`;
|
|
418
426
|
return merged;
|
|
419
427
|
}
|
|
420
|
-
function mergeCodexTomlHosted(existingToml, hostedMcpUrl, apiKey,
|
|
428
|
+
function mergeCodexTomlHosted(existingToml, hostedMcpUrl, apiKey, signerSpec) {
|
|
421
429
|
let next = removeTomlTableTree(removeTomlTableTree(existingToml, "mcp_servers.haven"), "mcp_servers.haven_signer");
|
|
422
430
|
next = next.trimEnd();
|
|
423
431
|
const block = [
|
|
@@ -426,8 +434,8 @@ function mergeCodexTomlHosted(existingToml, hostedMcpUrl, apiKey, signerPath) {
|
|
|
426
434
|
`http_headers = { "Authorization" = ${tomlString(`Bearer ${apiKey}`)} }`,
|
|
427
435
|
"",
|
|
428
436
|
"[mcp_servers.haven_signer]",
|
|
429
|
-
|
|
430
|
-
`args = [
|
|
437
|
+
`command = ${tomlString(signerSpec.command)}`,
|
|
438
|
+
`args = [${signerSpec.args.map((arg) => tomlString(arg)).join(", ")}]`,
|
|
431
439
|
"startup_timeout_sec = 120"
|
|
432
440
|
].join("\n");
|
|
433
441
|
validateCodexToml(block, "Generated Codex Haven config");
|
|
@@ -444,7 +452,7 @@ async function writeJsonRuntimeConfig(input, target, serverRoot) {
|
|
|
444
452
|
existing,
|
|
445
453
|
serverRoot,
|
|
446
454
|
buildHostedServer(input.hostedMcpUrl, input.apiKey, input.runtime),
|
|
447
|
-
buildSignerServer(input
|
|
455
|
+
buildSignerServer(resolveSignerLaunchSpec(input), input.runtime)
|
|
448
456
|
);
|
|
449
457
|
await writeOwnerOnlyText(target, merged);
|
|
450
458
|
return {
|
|
@@ -500,7 +508,7 @@ async function writeCodexConfig(input) {
|
|
|
500
508
|
]
|
|
501
509
|
};
|
|
502
510
|
}
|
|
503
|
-
const merged = mergeCodexTomlHosted(existing ?? "", input.hostedMcpUrl, input.apiKey, input
|
|
511
|
+
const merged = mergeCodexTomlHosted(existing ?? "", input.hostedMcpUrl, input.apiKey, resolveSignerLaunchSpec(input));
|
|
504
512
|
await writeOwnerOnlyText(target, merged);
|
|
505
513
|
return {
|
|
506
514
|
hostedConfigured: true,
|
|
@@ -785,9 +793,6 @@ function configTargetLabel(runtime) {
|
|
|
785
793
|
return "runtime MCP config";
|
|
786
794
|
}
|
|
787
795
|
}
|
|
788
|
-
function signerPackageName() {
|
|
789
|
-
return signerPackageSpec();
|
|
790
|
-
}
|
|
791
796
|
async function acknowledgeLocalMcpConsent(identityPath, signerPath, log) {
|
|
792
797
|
try {
|
|
793
798
|
const input = await buildLocalMcpConsentInput(identityPath, signerPath);
|
|
@@ -901,7 +906,7 @@ async function probeLocalSignerCredential(signerPath) {
|
|
|
901
906
|
}
|
|
902
907
|
}
|
|
903
908
|
async function probeLocalMcpTools(command, args, requiredTools, timeoutMs = 1e4) {
|
|
904
|
-
return new Promise((
|
|
909
|
+
return new Promise((resolve8) => {
|
|
905
910
|
const child = spawn(command, args, { stdio: ["pipe", "pipe", "ignore"] });
|
|
906
911
|
let stdout = "";
|
|
907
912
|
let settled = false;
|
|
@@ -911,7 +916,7 @@ async function probeLocalMcpTools(command, args, requiredTools, timeoutMs = 1e4)
|
|
|
911
916
|
settled = true;
|
|
912
917
|
clearTimeout(timeout);
|
|
913
918
|
child.kill();
|
|
914
|
-
|
|
919
|
+
resolve8(result);
|
|
915
920
|
};
|
|
916
921
|
const timeout = setTimeout(() => finish({ status: "timeout" }), timeoutMs);
|
|
917
922
|
child.on("error", () => finish({ status: "process_error" }));
|
|
@@ -1149,75 +1154,126 @@ async function assertFileExists(path, label) {
|
|
|
1149
1154
|
throw new Error(`Missing ${label}: ${path}`);
|
|
1150
1155
|
}
|
|
1151
1156
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1157
|
+
var execFileAsync2 = promisify(execFile);
|
|
1158
|
+
async function prepareSignerRuntime(input, deps = {}) {
|
|
1159
|
+
const homeDir = input.homeDir ?? homedir();
|
|
1160
|
+
const runtimeDirectory = resolve(homeDir, ".haven", "signer-runtime", MCP_RUNTIME_MANIFEST.signerVersion);
|
|
1161
|
+
const npmCacheDirectory = resolve(homeDir, ".haven", "npm-cache");
|
|
1162
|
+
const cliPath = join(runtimeDirectory, "node_modules", "@haven_ai", "signer", "dist", "cli.js");
|
|
1163
|
+
const messages = [];
|
|
1164
|
+
await mkdir(runtimeDirectory, { recursive: true, mode: 448 });
|
|
1165
|
+
await chmod(runtimeDirectory, 448).catch(() => void 0);
|
|
1166
|
+
await mkdir(npmCacheDirectory, { recursive: true, mode: 448 });
|
|
1167
|
+
await chmod(npmCacheDirectory, 448).catch(() => void 0);
|
|
1168
|
+
if (await installedRuntimeMatches2(runtimeDirectory, cliPath)) {
|
|
1169
|
+
messages.push(`Using existing local Haven signer runtime ${signerPackageSpec()}.`);
|
|
1170
|
+
} else {
|
|
1171
|
+
await installRuntimePackages2(runtimeDirectory, npmCacheDirectory, deps.runCommand);
|
|
1172
|
+
messages.push(`Installed local Haven signer runtime ${signerPackageSpec()}.`);
|
|
1173
|
+
}
|
|
1174
|
+
await assertFileExists2(cliPath, "local Haven signer CLI");
|
|
1175
|
+
const wrapperPath = join(input.credentialDirectory, "bin", "haven-signer.mjs");
|
|
1176
|
+
await writeWrapper2({ wrapperPath, cliPath, signerPath: input.signerPath });
|
|
1177
|
+
await writeRuntimeSidecar2({
|
|
1178
|
+
path: join(input.credentialDirectory, "signer-runtime.json"),
|
|
1179
|
+
wrapperPath,
|
|
1180
|
+
runtimeDirectory,
|
|
1181
|
+
npmCacheDirectory,
|
|
1182
|
+
cliPath
|
|
1183
|
+
});
|
|
1184
|
+
messages.push(`Prepared stable local Haven signer wrapper: ${wrapperPath}`);
|
|
1185
|
+
return {
|
|
1186
|
+
command: wrapperPath,
|
|
1187
|
+
args: [],
|
|
1188
|
+
wrapperPath,
|
|
1189
|
+
runtimeDirectory,
|
|
1190
|
+
npmCacheDirectory,
|
|
1191
|
+
cliPath,
|
|
1192
|
+
messages
|
|
1193
|
+
};
|
|
1194
|
+
}
|
|
1195
|
+
async function installRuntimePackages2(runtimeDirectory, npmCacheDirectory, runCommand) {
|
|
1196
|
+
const args = [
|
|
1197
|
+
"install",
|
|
1198
|
+
"--prefix",
|
|
1199
|
+
runtimeDirectory,
|
|
1200
|
+
"--cache",
|
|
1201
|
+
npmCacheDirectory,
|
|
1202
|
+
"--no-audit",
|
|
1203
|
+
"--no-fund",
|
|
1204
|
+
"--omit=dev",
|
|
1205
|
+
signerPackageSpec(),
|
|
1206
|
+
sdkPackageSpec()
|
|
1207
|
+
];
|
|
1208
|
+
try {
|
|
1209
|
+
if (runCommand) await runCommand("npm", args);
|
|
1210
|
+
else await execFileAsync2("npm", args, { timeout: 12e4, maxBuffer: 1024 * 1024 });
|
|
1211
|
+
} catch (err) {
|
|
1212
|
+
throw new Error(
|
|
1213
|
+
`Could not install local Haven signer runtime ${signerPackageSpec()}: ${err instanceof Error ? err.message : String(err)}`
|
|
1214
|
+
);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
async function installedRuntimeMatches2(runtimeDirectory, cliPath) {
|
|
1218
|
+
try {
|
|
1219
|
+
await assertFileExists2(cliPath, "local Haven signer CLI");
|
|
1220
|
+
const [signerPackage, sdkPackage] = await Promise.all([
|
|
1221
|
+
readPackageJson2(join(runtimeDirectory, "node_modules", "@haven_ai", "signer", "package.json")),
|
|
1222
|
+
readPackageJson2(join(runtimeDirectory, "node_modules", "@haven_ai", "sdk", "package.json"))
|
|
1223
|
+
]);
|
|
1224
|
+
return signerPackage.version === MCP_RUNTIME_MANIFEST.signerVersion && sdkPackage.version === MCP_RUNTIME_MANIFEST.sdkVersion;
|
|
1225
|
+
} catch {
|
|
1226
|
+
return false;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
async function readPackageJson2(path) {
|
|
1230
|
+
return JSON.parse(await readFile(path, "utf8"));
|
|
1231
|
+
}
|
|
1232
|
+
async function writeWrapper2(input) {
|
|
1233
|
+
await mkdir(dirname(input.wrapperPath), { recursive: true, mode: 448 });
|
|
1234
|
+
await chmod(dirname(input.wrapperPath), 448).catch(() => void 0);
|
|
1235
|
+
const source = [
|
|
1236
|
+
"#!/usr/bin/env node",
|
|
1237
|
+
"import { spawn } from 'node:child_process'",
|
|
1238
|
+
"",
|
|
1239
|
+
`const cliPath = ${JSON.stringify(input.cliPath)}`,
|
|
1240
|
+
`const signerPath = ${JSON.stringify(input.signerPath)}`,
|
|
1241
|
+
"",
|
|
1242
|
+
"const child = spawn(process.execPath, [cliPath, '--credentials', signerPath, ...process.argv.slice(2)], {",
|
|
1243
|
+
" stdio: 'inherit',",
|
|
1244
|
+
"})",
|
|
1245
|
+
"",
|
|
1246
|
+
"child.on('exit', (code, signal) => {",
|
|
1247
|
+
" if (signal) process.kill(process.pid, signal)",
|
|
1248
|
+
" else process.exit(code ?? 1)",
|
|
1249
|
+
"})",
|
|
1250
|
+
""
|
|
1251
|
+
].join("\n");
|
|
1252
|
+
await writeFile(input.wrapperPath, source, { mode: 448 });
|
|
1253
|
+
await chmod(input.wrapperPath, 448).catch(() => void 0);
|
|
1254
|
+
}
|
|
1255
|
+
async function writeRuntimeSidecar2(input) {
|
|
1256
|
+
const value = {
|
|
1257
|
+
signer_package: MCP_RUNTIME_MANIFEST.signerPackage,
|
|
1258
|
+
signer_version: MCP_RUNTIME_MANIFEST.signerVersion,
|
|
1259
|
+
sdk_package: MCP_RUNTIME_MANIFEST.sdkPackage,
|
|
1260
|
+
sdk_version: MCP_RUNTIME_MANIFEST.sdkVersion,
|
|
1261
|
+
wrapper_path: input.wrapperPath,
|
|
1262
|
+
runtime_directory: input.runtimeDirectory,
|
|
1263
|
+
npm_cache_directory: input.npmCacheDirectory,
|
|
1264
|
+
cli_path: input.cliPath
|
|
1265
|
+
};
|
|
1266
|
+
await writeFile(input.path, `${JSON.stringify(value, null, 2)}
|
|
1267
|
+
`, { mode: 384 });
|
|
1268
|
+
await chmod(input.path, 384).catch(() => void 0);
|
|
1269
|
+
}
|
|
1270
|
+
async function assertFileExists2(path, label) {
|
|
1271
|
+
try {
|
|
1272
|
+
await access(path);
|
|
1273
|
+
} catch {
|
|
1274
|
+
throw new Error(`Missing ${label}: ${path}`);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1221
1277
|
async function acknowledgeLocalSignerConsent(signerPath, log) {
|
|
1222
1278
|
try {
|
|
1223
1279
|
const input = await buildSignerConsentInput(signerPath);
|
|
@@ -1289,7 +1345,7 @@ function writeLogChunk2(log, chunk) {
|
|
|
1289
1345
|
}
|
|
1290
1346
|
|
|
1291
1347
|
// src/runtime-install.ts
|
|
1292
|
-
var
|
|
1348
|
+
var execFileAsync3 = promisify(execFile);
|
|
1293
1349
|
async function installRuntime(input, deps = {}) {
|
|
1294
1350
|
const runtime = normalizeRuntime(input.runtime, deps.env);
|
|
1295
1351
|
const profile = runtimeProfile(runtime, deps.env);
|
|
@@ -1350,7 +1406,20 @@ async function installRuntime(input, deps = {}) {
|
|
|
1350
1406
|
]
|
|
1351
1407
|
};
|
|
1352
1408
|
}
|
|
1353
|
-
|
|
1409
|
+
let signerCommand;
|
|
1410
|
+
if (!localRuntime) {
|
|
1411
|
+
try {
|
|
1412
|
+
const signerRuntime = await prepareSignerForRuntime(input, deps);
|
|
1413
|
+
signerCommand = { command: signerRuntime.command, args: signerRuntime.args };
|
|
1414
|
+
consentMessages.push(...signerRuntime.messages);
|
|
1415
|
+
} catch (err) {
|
|
1416
|
+
consentMessages.push(
|
|
1417
|
+
`Could not pre-install the local Haven signer; falling back to npx launch: ${err instanceof Error ? err.message : String(err)}`
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
const signerRuntimePrepared = localRuntime ? void 0 : signerCommand !== void 0;
|
|
1422
|
+
const configResult = runtime === "claude-code" ? localRuntime ? await configureClaudeCode(deps, localRuntimeInstall?.command ?? "") : await configureClaudeCodeHosted(deps, input, signerCommand) : await writeRuntimeConfig({
|
|
1354
1423
|
runtime,
|
|
1355
1424
|
hostedMcpUrl: input.hostedMcpUrl,
|
|
1356
1425
|
apiKey: input.apiKey,
|
|
@@ -1358,6 +1427,7 @@ async function installRuntime(input, deps = {}) {
|
|
|
1358
1427
|
signerPath: input.signerPath,
|
|
1359
1428
|
credentialDirectory: input.credentialDirectory,
|
|
1360
1429
|
localMcpCommand: localRuntimeInstall?.command,
|
|
1430
|
+
signerCommand,
|
|
1361
1431
|
homeDir: deps.homeDir,
|
|
1362
1432
|
mode: localRuntime ? "local" : "hosted"
|
|
1363
1433
|
});
|
|
@@ -1389,6 +1459,7 @@ async function installRuntime(input, deps = {}) {
|
|
|
1389
1459
|
localMcpAcknowledged: localMcpConsent?.acknowledged,
|
|
1390
1460
|
activationCommand: configResult.activationCommand,
|
|
1391
1461
|
skillInstalled: skillInstall?.installed,
|
|
1462
|
+
signerRuntimePrepared,
|
|
1392
1463
|
messages: [...consentMessages, ...localRuntimeInstall?.messages ?? [], ...configResult.messages, ...localProbeMessages, ...skillInstall?.messages ?? []]
|
|
1393
1464
|
};
|
|
1394
1465
|
}
|
|
@@ -1445,7 +1516,7 @@ async function configureClaudeCode(deps, localMcpCommand) {
|
|
|
1445
1516
|
};
|
|
1446
1517
|
}
|
|
1447
1518
|
}
|
|
1448
|
-
async function configureClaudeCodeHosted(deps, input) {
|
|
1519
|
+
async function configureClaudeCodeHosted(deps, input, signerCommand) {
|
|
1449
1520
|
const runCommand = deps.runCommand ?? defaultRunCommand;
|
|
1450
1521
|
const hostedJson = JSON.stringify({
|
|
1451
1522
|
type: "http",
|
|
@@ -1454,8 +1525,8 @@ async function configureClaudeCodeHosted(deps, input) {
|
|
|
1454
1525
|
});
|
|
1455
1526
|
const signerJson = JSON.stringify({
|
|
1456
1527
|
type: "stdio",
|
|
1457
|
-
command: "npx",
|
|
1458
|
-
args: ["-y", signerPackageSpec(), "--credentials", input.signerPath],
|
|
1528
|
+
command: signerCommand?.command ?? "npx",
|
|
1529
|
+
args: signerCommand?.args ?? ["-y", signerPackageSpec(), "--credentials", input.signerPath],
|
|
1459
1530
|
env: {}
|
|
1460
1531
|
});
|
|
1461
1532
|
try {
|
|
@@ -1496,7 +1567,7 @@ async function configureClaudeCodeHosted(deps, input) {
|
|
|
1496
1567
|
}
|
|
1497
1568
|
}
|
|
1498
1569
|
async function defaultRunCommand(command, args) {
|
|
1499
|
-
await
|
|
1570
|
+
await execFileAsync3(command, args, { timeout: 1e4 });
|
|
1500
1571
|
}
|
|
1501
1572
|
async function installClaudeSkill(homeDir) {
|
|
1502
1573
|
try {
|
|
@@ -1579,6 +1650,14 @@ async function prepareRuntimeForLocalMcp(input, deps) {
|
|
|
1579
1650
|
homeDir: deps.homeDir
|
|
1580
1651
|
});
|
|
1581
1652
|
}
|
|
1653
|
+
async function prepareSignerForRuntime(input, deps) {
|
|
1654
|
+
const prepare = deps.prepareSignerRuntime ?? ((runtimeInput) => prepareSignerRuntime(runtimeInput, { runCommand: deps.runCommand }));
|
|
1655
|
+
return prepare({
|
|
1656
|
+
credentialDirectory: input.credentialDirectory,
|
|
1657
|
+
signerPath: input.signerPath,
|
|
1658
|
+
homeDir: deps.homeDir
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1582
1661
|
async function runLocalMcpProbe(runtimeInstall, deps) {
|
|
1583
1662
|
const probe = deps.probeLocalMcpTools ?? probeLocalMcpTools;
|
|
1584
1663
|
try {
|
|
@@ -1595,7 +1674,7 @@ function localRuntimePrepareErrorCode(err) {
|
|
|
1595
1674
|
}
|
|
1596
1675
|
|
|
1597
1676
|
// src/runtime.ts
|
|
1598
|
-
var CONNECTOR_VERSION = "0.1.
|
|
1677
|
+
var CONNECTOR_VERSION = "0.1.13-alpha.0";
|
|
1599
1678
|
async function runConnect(options, deps = {}) {
|
|
1600
1679
|
const connectorVersion = options.connectorVersion ?? CONNECTOR_VERSION;
|
|
1601
1680
|
const api = deps.api ?? createConnectApiClient(options.apiBaseUrl);
|
|
@@ -1660,10 +1739,18 @@ async function runConnect(options, deps = {}) {
|
|
|
1660
1739
|
})),
|
|
1661
1740
|
apiUrl: options.apiBaseUrl,
|
|
1662
1741
|
hostedMcpUrl: registration.hosted_mcp_url,
|
|
1742
|
+
x402BindingSigner: setup.x402_binding_signer ?? void 0,
|
|
1663
1743
|
warn: log
|
|
1664
1744
|
});
|
|
1665
1745
|
log(`Stored Haven identity credential locally: ${credentialPaths.identityPath}`);
|
|
1666
1746
|
log(`Stored local signer credential locally: ${credentialPaths.signerPath}`);
|
|
1747
|
+
if (setup.x402_binding_signer) {
|
|
1748
|
+
log("Configured x402 binding signer for the local signer.");
|
|
1749
|
+
} else {
|
|
1750
|
+
log(
|
|
1751
|
+
"Warning: Haven did not provide an x402 binding signer, so x402 payments will not sign until HAVEN_X402_BINDING_SIGNER is set for the signer. Non-x402 payments are unaffected."
|
|
1752
|
+
);
|
|
1753
|
+
}
|
|
1667
1754
|
const runtimeInstall = await runRuntimeInstall({
|
|
1668
1755
|
runtime: options.runtime,
|
|
1669
1756
|
hostedMcpUrl: registration.hosted_mcp_url,
|
|
@@ -1826,6 +1913,6 @@ function requireValue(argv, index, option) {
|
|
|
1826
1913
|
return value;
|
|
1827
1914
|
}
|
|
1828
1915
|
|
|
1829
|
-
export { CONNECTOR_VERSION, MCP_RUNTIME_MANIFEST, createConnectApiClient, defaultAgentDirectory, delegateKeyFromPrivateKey, generateDelegateKey, helpText, installRuntime, mcpPackageSpec, normalizeRuntime, parseArgs, redactSecrets, runConnect, runtimeInstallCapabilities, runtimeProfile, sdkPackageSpec, shortAddress, signerPackageSpec, writeCredentialFiles };
|
|
1916
|
+
export { CONNECTOR_VERSION, MCP_RUNTIME_MANIFEST, createConnectApiClient, defaultAgentDirectory, delegateKeyFromPrivateKey, generateDelegateKey, helpText, installRuntime, mcpPackageSpec, normalizeRuntime, parseArgs, prepareSignerRuntime, redactSecrets, runConnect, runtimeInstallCapabilities, runtimeProfile, sdkPackageSpec, shortAddress, signerPackageSpec, writeCredentialFiles };
|
|
1830
1917
|
//# sourceMappingURL=index.js.map
|
|
1831
1918
|
//# sourceMappingURL=index.js.map
|