@haven_ai/connect 0.1.6-alpha → 0.1.11-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/README.md +1 -1
- package/dist/cli.cjs +215 -23
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +215 -23
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +219 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -2
- package/dist/index.d.ts +26 -2
- package/dist/index.js +216 -24
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.cts
CHANGED
|
@@ -31,6 +31,7 @@ interface UpdateInstallStatusInput {
|
|
|
31
31
|
signerAcknowledged?: boolean;
|
|
32
32
|
localMcpAcknowledged?: boolean;
|
|
33
33
|
activationCommandAvailable?: boolean;
|
|
34
|
+
skillInstalled?: boolean;
|
|
34
35
|
probeResult: string;
|
|
35
36
|
restartRequired: boolean;
|
|
36
37
|
nextUserAction: string;
|
|
@@ -167,6 +168,12 @@ interface RuntimeInstallInput {
|
|
|
167
168
|
environmentLabel?: string;
|
|
168
169
|
ackSigner?: boolean;
|
|
169
170
|
ackLocalTools?: boolean;
|
|
171
|
+
/**
|
|
172
|
+
* Explicit opt-in to the local-stdio MCP topology (zero hosted dependency).
|
|
173
|
+
* Default is hosted MCP + local signer for every runtime; local MCP is only
|
|
174
|
+
* used when this is true and the runtime supports it.
|
|
175
|
+
*/
|
|
176
|
+
localMcp?: boolean;
|
|
170
177
|
}
|
|
171
178
|
interface RuntimeInstallResult {
|
|
172
179
|
runtime: RuntimeId;
|
|
@@ -183,6 +190,7 @@ interface RuntimeInstallResult {
|
|
|
183
190
|
signerAcknowledged?: boolean;
|
|
184
191
|
localMcpAcknowledged?: boolean;
|
|
185
192
|
activationCommand?: string;
|
|
193
|
+
skillInstalled?: boolean;
|
|
186
194
|
messages: string[];
|
|
187
195
|
}
|
|
188
196
|
interface RuntimeInstallDeps {
|
|
@@ -199,7 +207,7 @@ declare function runtimeInstallCapabilities(runtime: string | undefined, env?: N
|
|
|
199
207
|
restartRequired: boolean;
|
|
200
208
|
};
|
|
201
209
|
|
|
202
|
-
declare const CONNECTOR_VERSION = "0.1.
|
|
210
|
+
declare const CONNECTOR_VERSION = "0.1.11-alpha.0";
|
|
203
211
|
interface ConnectOptions {
|
|
204
212
|
setupToken: string;
|
|
205
213
|
apiBaseUrl: string;
|
|
@@ -209,6 +217,7 @@ interface ConnectOptions {
|
|
|
209
217
|
connectorVersion?: string;
|
|
210
218
|
ackSigner?: boolean;
|
|
211
219
|
ackLocalTools?: boolean;
|
|
220
|
+
localMcp?: boolean;
|
|
212
221
|
}
|
|
213
222
|
interface ConnectDeps {
|
|
214
223
|
api?: ConnectApiClient;
|
|
@@ -237,4 +246,19 @@ declare function helpText(): string;
|
|
|
237
246
|
declare function redactSecrets(value: string): string;
|
|
238
247
|
declare function shortAddress(address: string): string;
|
|
239
248
|
|
|
240
|
-
|
|
249
|
+
declare const MCP_RUNTIME_MANIFEST: {
|
|
250
|
+
readonly mcpPackage: "@haven_ai/mcp";
|
|
251
|
+
readonly mcpVersion: "0.1.11-alpha.0";
|
|
252
|
+
readonly sdkPackage: "@haven_ai/sdk";
|
|
253
|
+
readonly sdkVersion: "0.1.11-alpha.0";
|
|
254
|
+
readonly signerPackage: "@haven_ai/signer";
|
|
255
|
+
readonly signerVersion: "0.1.11-alpha.0";
|
|
256
|
+
readonly minimumNodeVersion: "20.0.0";
|
|
257
|
+
readonly supportedClients: readonly ["codex-cli", "codex-desktop", "claude-code"];
|
|
258
|
+
readonly requiredTools: readonly string[];
|
|
259
|
+
};
|
|
260
|
+
declare function mcpPackageSpec(): string;
|
|
261
|
+
declare function sdkPackageSpec(): string;
|
|
262
|
+
declare function signerPackageSpec(): string;
|
|
263
|
+
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ interface UpdateInstallStatusInput {
|
|
|
31
31
|
signerAcknowledged?: boolean;
|
|
32
32
|
localMcpAcknowledged?: boolean;
|
|
33
33
|
activationCommandAvailable?: boolean;
|
|
34
|
+
skillInstalled?: boolean;
|
|
34
35
|
probeResult: string;
|
|
35
36
|
restartRequired: boolean;
|
|
36
37
|
nextUserAction: string;
|
|
@@ -167,6 +168,12 @@ interface RuntimeInstallInput {
|
|
|
167
168
|
environmentLabel?: string;
|
|
168
169
|
ackSigner?: boolean;
|
|
169
170
|
ackLocalTools?: boolean;
|
|
171
|
+
/**
|
|
172
|
+
* Explicit opt-in to the local-stdio MCP topology (zero hosted dependency).
|
|
173
|
+
* Default is hosted MCP + local signer for every runtime; local MCP is only
|
|
174
|
+
* used when this is true and the runtime supports it.
|
|
175
|
+
*/
|
|
176
|
+
localMcp?: boolean;
|
|
170
177
|
}
|
|
171
178
|
interface RuntimeInstallResult {
|
|
172
179
|
runtime: RuntimeId;
|
|
@@ -183,6 +190,7 @@ interface RuntimeInstallResult {
|
|
|
183
190
|
signerAcknowledged?: boolean;
|
|
184
191
|
localMcpAcknowledged?: boolean;
|
|
185
192
|
activationCommand?: string;
|
|
193
|
+
skillInstalled?: boolean;
|
|
186
194
|
messages: string[];
|
|
187
195
|
}
|
|
188
196
|
interface RuntimeInstallDeps {
|
|
@@ -199,7 +207,7 @@ declare function runtimeInstallCapabilities(runtime: string | undefined, env?: N
|
|
|
199
207
|
restartRequired: boolean;
|
|
200
208
|
};
|
|
201
209
|
|
|
202
|
-
declare const CONNECTOR_VERSION = "0.1.
|
|
210
|
+
declare const CONNECTOR_VERSION = "0.1.11-alpha.0";
|
|
203
211
|
interface ConnectOptions {
|
|
204
212
|
setupToken: string;
|
|
205
213
|
apiBaseUrl: string;
|
|
@@ -209,6 +217,7 @@ interface ConnectOptions {
|
|
|
209
217
|
connectorVersion?: string;
|
|
210
218
|
ackSigner?: boolean;
|
|
211
219
|
ackLocalTools?: boolean;
|
|
220
|
+
localMcp?: boolean;
|
|
212
221
|
}
|
|
213
222
|
interface ConnectDeps {
|
|
214
223
|
api?: ConnectApiClient;
|
|
@@ -237,4 +246,19 @@ declare function helpText(): string;
|
|
|
237
246
|
declare function redactSecrets(value: string): string;
|
|
238
247
|
declare function shortAddress(address: string): string;
|
|
239
248
|
|
|
240
|
-
|
|
249
|
+
declare const MCP_RUNTIME_MANIFEST: {
|
|
250
|
+
readonly mcpPackage: "@haven_ai/mcp";
|
|
251
|
+
readonly mcpVersion: "0.1.11-alpha.0";
|
|
252
|
+
readonly sdkPackage: "@haven_ai/sdk";
|
|
253
|
+
readonly sdkVersion: "0.1.11-alpha.0";
|
|
254
|
+
readonly signerPackage: "@haven_ai/signer";
|
|
255
|
+
readonly signerVersion: "0.1.11-alpha.0";
|
|
256
|
+
readonly minimumNodeVersion: "20.0.0";
|
|
257
|
+
readonly supportedClients: readonly ["codex-cli", "codex-desktop", "claude-code"];
|
|
258
|
+
readonly requiredTools: readonly string[];
|
|
259
|
+
};
|
|
260
|
+
declare function mcpPackageSpec(): string;
|
|
261
|
+
declare function sdkPackageSpec(): string;
|
|
262
|
+
declare function signerPackageSpec(): string;
|
|
263
|
+
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -53,6 +53,7 @@ function createConnectApiClient(baseUrl, fetchImpl = fetch) {
|
|
|
53
53
|
signer_acknowledged: input.signerAcknowledged,
|
|
54
54
|
local_mcp_acknowledged: input.localMcpAcknowledged,
|
|
55
55
|
activation_command_available: input.activationCommandAvailable,
|
|
56
|
+
skill_installed: input.skillInstalled,
|
|
56
57
|
probe_result: input.probeResult,
|
|
57
58
|
restart_required: input.restartRequired,
|
|
58
59
|
next_user_action: input.nextUserAction,
|
|
@@ -205,9 +206,9 @@ var MCP_RUNTIME_MANIFEST = {
|
|
|
205
206
|
mcpPackage: "@haven_ai/mcp",
|
|
206
207
|
mcpVersion: MCP_VERSION,
|
|
207
208
|
sdkPackage: "@haven_ai/sdk",
|
|
208
|
-
sdkVersion: "0.1.
|
|
209
|
+
sdkVersion: "0.1.11-alpha.0",
|
|
209
210
|
signerPackage: "@haven_ai/signer",
|
|
210
|
-
signerVersion: "0.1.
|
|
211
|
+
signerVersion: "0.1.11-alpha.0",
|
|
211
212
|
minimumNodeVersion: "20.0.0",
|
|
212
213
|
supportedClients: ["codex-cli", "codex-desktop", "claude-code"],
|
|
213
214
|
requiredTools: registeredToolNames()
|
|
@@ -412,6 +413,26 @@ function mergeCodexToml(existingToml, localMcpCommand) {
|
|
|
412
413
|
validateCodexToml(block, "Generated Codex Haven config");
|
|
413
414
|
const merged = `${next ? `${next}
|
|
414
415
|
|
|
416
|
+
` : ""}${block}
|
|
417
|
+
`;
|
|
418
|
+
return merged;
|
|
419
|
+
}
|
|
420
|
+
function mergeCodexTomlHosted(existingToml, hostedMcpUrl, apiKey, signerPath) {
|
|
421
|
+
let next = removeTomlTableTree(removeTomlTableTree(existingToml, "mcp_servers.haven"), "mcp_servers.haven_signer");
|
|
422
|
+
next = next.trimEnd();
|
|
423
|
+
const block = [
|
|
424
|
+
"[mcp_servers.haven]",
|
|
425
|
+
`url = ${tomlString(hostedMcpUrl)}`,
|
|
426
|
+
`http_headers = { "Authorization" = ${tomlString(`Bearer ${apiKey}`)} }`,
|
|
427
|
+
"",
|
|
428
|
+
"[mcp_servers.haven_signer]",
|
|
429
|
+
'command = "npx"',
|
|
430
|
+
`args = ["-y", ${tomlString(signerPackageSpec())}, "--credentials", ${tomlString(signerPath)}]`,
|
|
431
|
+
"startup_timeout_sec = 120"
|
|
432
|
+
].join("\n");
|
|
433
|
+
validateCodexToml(block, "Generated Codex Haven config");
|
|
434
|
+
const merged = `${next ? `${next}
|
|
435
|
+
|
|
415
436
|
` : ""}${block}
|
|
416
437
|
`;
|
|
417
438
|
return merged;
|
|
@@ -452,27 +473,46 @@ async function writeJsonRuntimeConfig(input, target, serverRoot) {
|
|
|
452
473
|
}
|
|
453
474
|
async function writeCodexConfig(input) {
|
|
454
475
|
const target = codexConfigPath(input.homeDir);
|
|
476
|
+
const local = input.mode === "local";
|
|
477
|
+
const restartMessage = runtimeRequiresHardRestart(input.runtime) ? "After Haven approval, restart Codex Desktop so it can load Haven tools." : "After Haven approval, Haven tools should appear in your next Codex message. If they don't, restart Codex to load them.";
|
|
455
478
|
try {
|
|
456
479
|
const existing = await readOptional(target);
|
|
457
|
-
if (
|
|
458
|
-
|
|
480
|
+
if (local) {
|
|
481
|
+
if (!input.localMcpCommand) {
|
|
482
|
+
throw new Error("local MCP wrapper command is required");
|
|
483
|
+
}
|
|
484
|
+
const merged2 = mergeCodexToml(existing ?? "", input.localMcpCommand);
|
|
485
|
+
await writeOwnerOnlyText(target, merged2);
|
|
486
|
+
return {
|
|
487
|
+
hostedConfigured: false,
|
|
488
|
+
signerConfigured: true,
|
|
489
|
+
localMcpConfigured: true,
|
|
490
|
+
runtimeMcpMode: "local_stdio",
|
|
491
|
+
target: configTargetLabel(input.runtime),
|
|
492
|
+
changed: existing !== merged2,
|
|
493
|
+
restartRequired: true,
|
|
494
|
+
messages: [
|
|
495
|
+
`Updated local Haven MCP entry in ${configTargetLabel(input.runtime)}.`,
|
|
496
|
+
// Codex Desktop loads MCP servers at app launch; Codex CLI typically
|
|
497
|
+
// picks them up in the next session. Branch the copy so desktop users
|
|
498
|
+
// get the unambiguous instruction.
|
|
499
|
+
restartMessage
|
|
500
|
+
]
|
|
501
|
+
};
|
|
459
502
|
}
|
|
460
|
-
const merged =
|
|
503
|
+
const merged = mergeCodexTomlHosted(existing ?? "", input.hostedMcpUrl, input.apiKey, input.signerPath);
|
|
461
504
|
await writeOwnerOnlyText(target, merged);
|
|
462
505
|
return {
|
|
463
|
-
hostedConfigured:
|
|
506
|
+
hostedConfigured: true,
|
|
464
507
|
signerConfigured: true,
|
|
465
|
-
localMcpConfigured:
|
|
466
|
-
runtimeMcpMode: "
|
|
508
|
+
localMcpConfigured: false,
|
|
509
|
+
runtimeMcpMode: "hosted_plus_signer",
|
|
467
510
|
target: configTargetLabel(input.runtime),
|
|
468
511
|
changed: existing !== merged,
|
|
469
512
|
restartRequired: true,
|
|
470
513
|
messages: [
|
|
471
|
-
`Updated
|
|
472
|
-
|
|
473
|
-
// picks them up in the next session. Branch the copy so desktop users
|
|
474
|
-
// get the unambiguous instruction.
|
|
475
|
-
runtimeRequiresHardRestart(input.runtime) ? "After Haven approval, restart Codex Desktop so it can load Haven tools." : "After Haven approval, Haven tools should appear in your next Codex message. If they don't, restart Codex to load them."
|
|
514
|
+
`Updated Haven MCP entries in ${configTargetLabel(input.runtime)}.`,
|
|
515
|
+
restartMessage
|
|
476
516
|
]
|
|
477
517
|
};
|
|
478
518
|
} catch (err) {
|
|
@@ -481,7 +521,7 @@ async function writeCodexConfig(input) {
|
|
|
481
521
|
hostedConfigured: false,
|
|
482
522
|
signerConfigured: false,
|
|
483
523
|
localMcpConfigured: false,
|
|
484
|
-
runtimeMcpMode: "local_stdio",
|
|
524
|
+
runtimeMcpMode: local ? "local_stdio" : "hosted_plus_signer",
|
|
485
525
|
target: configTargetLabel(input.runtime),
|
|
486
526
|
changed: false,
|
|
487
527
|
restartRequired: true,
|
|
@@ -861,7 +901,7 @@ async function probeLocalSignerCredential(signerPath) {
|
|
|
861
901
|
}
|
|
862
902
|
}
|
|
863
903
|
async function probeLocalMcpTools(command, args, requiredTools, timeoutMs = 1e4) {
|
|
864
|
-
return new Promise((
|
|
904
|
+
return new Promise((resolve7) => {
|
|
865
905
|
const child = spawn(command, args, { stdio: ["pipe", "pipe", "ignore"] });
|
|
866
906
|
let stdout = "";
|
|
867
907
|
let settled = false;
|
|
@@ -871,7 +911,7 @@ async function probeLocalMcpTools(command, args, requiredTools, timeoutMs = 1e4)
|
|
|
871
911
|
settled = true;
|
|
872
912
|
clearTimeout(timeout);
|
|
873
913
|
child.kill();
|
|
874
|
-
|
|
914
|
+
resolve7(result);
|
|
875
915
|
};
|
|
876
916
|
const timeout = setTimeout(() => finish({ status: "timeout" }), timeoutMs);
|
|
877
917
|
child.on("error", () => finish({ status: "process_error" }));
|
|
@@ -1109,6 +1149,75 @@ async function assertFileExists(path, label) {
|
|
|
1109
1149
|
throw new Error(`Missing ${label}: ${path}`);
|
|
1110
1150
|
}
|
|
1111
1151
|
}
|
|
1152
|
+
|
|
1153
|
+
// src/skill-content.ts
|
|
1154
|
+
var HAVEN_SKILL_MD = `---
|
|
1155
|
+
name: haven-pay
|
|
1156
|
+
description: Pay for things from the user's Haven wallet within their agent rules. Use when the user asks to send, pay, tip, or transfer crypto \u2014 or when a request hits an HTTP 402 (x402) paywall.
|
|
1157
|
+
---
|
|
1158
|
+
|
|
1159
|
+
# Haven: pay from a Haven wallet
|
|
1160
|
+
|
|
1161
|
+
This skill lets the agent make payments from the user's Haven wallet through
|
|
1162
|
+
the Haven MCP tools. Every payment is checked against the agent's on-chain
|
|
1163
|
+
budget before money moves; payments above the remaining budget wait for the
|
|
1164
|
+
user's approval in Haven.
|
|
1165
|
+
|
|
1166
|
+
## When to use this skill
|
|
1167
|
+
|
|
1168
|
+
- The user asks to send money, pay someone, tip, donate, or transfer tokens.
|
|
1169
|
+
- A request returns HTTP 402 (x402): use the Haven pay tools to settle it,
|
|
1170
|
+
then retry the original request.
|
|
1171
|
+
|
|
1172
|
+
## Identity and budget come from the tools \u2014 never assume them
|
|
1173
|
+
|
|
1174
|
+
Do not guess the wallet address, network, or budget. Read them live:
|
|
1175
|
+
|
|
1176
|
+
- \`haven_get_agent\` \u2014 agent identity, Haven wallet address, network.
|
|
1177
|
+
- \`haven_get_allowances\` \u2014 current per-token budgets and what remains.
|
|
1178
|
+
|
|
1179
|
+
Budgets reset on a period the user chose. If a payment exceeds the remaining
|
|
1180
|
+
budget it is queued for the user to approve in the Haven dashboard \u2014 this is
|
|
1181
|
+
normal, not an error.
|
|
1182
|
+
|
|
1183
|
+
## Paying
|
|
1184
|
+
|
|
1185
|
+
- **Direct transfer:** \`haven_pay\` with recipient, amount, and token.
|
|
1186
|
+
- **x402 paywall:** \`haven_quote_x402\` to get a quote, then
|
|
1187
|
+
\`haven_pay_x402_quote\`. In the hosted setup the signing step happens in
|
|
1188
|
+
the local Haven signer; follow the tool results \u2014 they tell you the next
|
|
1189
|
+
action at every step. Retry the original request only when the result says
|
|
1190
|
+
\`retry_original_x402_request\`.
|
|
1191
|
+
- **Status:** \`haven_get_payment_status\` with a \`payment_id\` to check on
|
|
1192
|
+
queued or in-flight payments. Do not poll in a tight loop.
|
|
1193
|
+
|
|
1194
|
+
## Approval semantics
|
|
1195
|
+
|
|
1196
|
+
- A result with \`pending_approval\` means the payment exceeded the remaining
|
|
1197
|
+
budget and is waiting for the user in Haven. Tell the user, then check
|
|
1198
|
+
status later.
|
|
1199
|
+
- Never ask the user for private keys and never try to sign anything
|
|
1200
|
+
yourself \u2014 Haven signs. If a tool reports a missing or invalid credential,
|
|
1201
|
+
tell the user to re-run the Haven setup command.
|
|
1202
|
+
|
|
1203
|
+
## Failure handling
|
|
1204
|
+
|
|
1205
|
+
Haven errors are shaped \`{ error, status, details? }\` and written for
|
|
1206
|
+
humans \u2014 surface the message verbatim. Common cases:
|
|
1207
|
+
|
|
1208
|
+
- \`pending_approval\`: queued for the user's approval (see above).
|
|
1209
|
+
- \`insufficient_funds\`: the Haven wallet doesn't hold enough of that token.
|
|
1210
|
+
Suggest the user add funds in the Haven dashboard.
|
|
1211
|
+
- Budget exceeded: tell the user how much remains (from
|
|
1212
|
+
\`haven_get_allowances\`) and that they can raise the budget in Haven.
|
|
1213
|
+
|
|
1214
|
+
## Revoke
|
|
1215
|
+
|
|
1216
|
+
If this agent's credential may have leaked, tell the user to pause or revoke
|
|
1217
|
+
the agent in the Haven dashboard under Agents. New requests stop immediately
|
|
1218
|
+
for that credential.
|
|
1219
|
+
`;
|
|
1220
|
+
var SKILL_FOLDER_NAME = "haven-pay";
|
|
1112
1221
|
async function acknowledgeLocalSignerConsent(signerPath, log) {
|
|
1113
1222
|
try {
|
|
1114
1223
|
const input = await buildSignerConsentInput(signerPath);
|
|
@@ -1184,7 +1293,7 @@ var execFileAsync2 = promisify(execFile);
|
|
|
1184
1293
|
async function installRuntime(input, deps = {}) {
|
|
1185
1294
|
const runtime = normalizeRuntime(input.runtime, deps.env);
|
|
1186
1295
|
const profile = runtimeProfile(runtime, deps.env);
|
|
1187
|
-
const localRuntime =
|
|
1296
|
+
const localRuntime = input.localMcp === true && supportsLocalMcp(runtime);
|
|
1188
1297
|
const consentMessages = [];
|
|
1189
1298
|
const localMcpConsent = localRuntime ? await resolveLocalMcpConsent(input, consentMessages) : void 0;
|
|
1190
1299
|
const signerConsent = localRuntime ? void 0 : await resolveSignerConsent(input, consentMessages);
|
|
@@ -1241,7 +1350,7 @@ async function installRuntime(input, deps = {}) {
|
|
|
1241
1350
|
]
|
|
1242
1351
|
};
|
|
1243
1352
|
}
|
|
1244
|
-
const configResult = runtime === "claude-code" ? await configureClaudeCode(deps, localRuntimeInstall?.command ?? "") : await writeRuntimeConfig({
|
|
1353
|
+
const configResult = runtime === "claude-code" ? localRuntime ? await configureClaudeCode(deps, localRuntimeInstall?.command ?? "") : await configureClaudeCodeHosted(deps, input) : await writeRuntimeConfig({
|
|
1245
1354
|
runtime,
|
|
1246
1355
|
hostedMcpUrl: input.hostedMcpUrl,
|
|
1247
1356
|
apiKey: input.apiKey,
|
|
@@ -1249,7 +1358,8 @@ async function installRuntime(input, deps = {}) {
|
|
|
1249
1358
|
signerPath: input.signerPath,
|
|
1250
1359
|
credentialDirectory: input.credentialDirectory,
|
|
1251
1360
|
localMcpCommand: localRuntimeInstall?.command,
|
|
1252
|
-
homeDir: deps.homeDir
|
|
1361
|
+
homeDir: deps.homeDir,
|
|
1362
|
+
mode: localRuntime ? "local" : "hosted"
|
|
1253
1363
|
});
|
|
1254
1364
|
const localProbePromise = configResult.runtimeMcpMode === "local_stdio" && localRuntimeInstall ? runLocalMcpProbe(localRuntimeInstall, deps) : Promise.resolve(void 0);
|
|
1255
1365
|
const [hostedProbe, signerCredentialReady, localMcpProbe] = await Promise.all([
|
|
@@ -1263,6 +1373,7 @@ async function installRuntime(input, deps = {}) {
|
|
|
1263
1373
|
const restartRequired = configResult.restartRequired || restartRequiredForRuntime(runtime, deps.env);
|
|
1264
1374
|
const errorCode = configResult.errorCode ?? (configResult.runtimeMcpMode === "local_stdio" ? localMcpErrorCode(signerCredentialReady, localMcpConsent, localMcpProbe?.status) : signerConsentErrorCode(signerCredentialReady, signerConsent));
|
|
1265
1375
|
const localProbeMessages = localMcpProbe && localMcpProbe.status !== "ok" ? [`Local Haven MCP handshake failed: ${localMcpProbe.status}.`] : localMcpProbe?.status === "ok" ? ["Verified local Haven MCP tools with a stdio handshake."] : [];
|
|
1376
|
+
const skillInstall = runtime === "claude-code" && !configResult.errorCode ? await installClaudeSkill(deps.homeDir) : void 0;
|
|
1266
1377
|
return {
|
|
1267
1378
|
runtime,
|
|
1268
1379
|
runtimeMcpMode: configResult.runtimeMcpMode,
|
|
@@ -1277,7 +1388,8 @@ async function installRuntime(input, deps = {}) {
|
|
|
1277
1388
|
signerAcknowledged: signerConsent?.acknowledged,
|
|
1278
1389
|
localMcpAcknowledged: localMcpConsent?.acknowledged,
|
|
1279
1390
|
activationCommand: configResult.activationCommand,
|
|
1280
|
-
|
|
1391
|
+
skillInstalled: skillInstall?.installed,
|
|
1392
|
+
messages: [...consentMessages, ...localRuntimeInstall?.messages ?? [], ...configResult.messages, ...localProbeMessages, ...skillInstall?.messages ?? []]
|
|
1281
1393
|
};
|
|
1282
1394
|
}
|
|
1283
1395
|
function runtimeInstallCapabilities(runtime, env = process.env) {
|
|
@@ -1333,9 +1445,75 @@ async function configureClaudeCode(deps, localMcpCommand) {
|
|
|
1333
1445
|
};
|
|
1334
1446
|
}
|
|
1335
1447
|
}
|
|
1448
|
+
async function configureClaudeCodeHosted(deps, input) {
|
|
1449
|
+
const runCommand = deps.runCommand ?? defaultRunCommand;
|
|
1450
|
+
const hostedJson = JSON.stringify({
|
|
1451
|
+
type: "http",
|
|
1452
|
+
url: input.hostedMcpUrl,
|
|
1453
|
+
headers: { Authorization: `Bearer ${input.apiKey}` }
|
|
1454
|
+
});
|
|
1455
|
+
const signerJson = JSON.stringify({
|
|
1456
|
+
type: "stdio",
|
|
1457
|
+
command: "npx",
|
|
1458
|
+
args: ["-y", signerPackageSpec(), "--credentials", input.signerPath],
|
|
1459
|
+
env: {}
|
|
1460
|
+
});
|
|
1461
|
+
try {
|
|
1462
|
+
await runCommand("claude", ["mcp", "remove", "haven"]).catch(() => void 0);
|
|
1463
|
+
await runCommand("claude", ["mcp", "remove", "haven-signer"]).catch(() => void 0);
|
|
1464
|
+
await runCommand("claude", ["mcp", "add-json", "haven", hostedJson, "--scope", "user"]);
|
|
1465
|
+
await runCommand("claude", ["mcp", "add-json", "haven-signer", signerJson, "--scope", "user"]);
|
|
1466
|
+
const verified = await runCommand("claude", ["mcp", "get", "haven"]).then(() => true).catch(() => false);
|
|
1467
|
+
return {
|
|
1468
|
+
hostedConfigured: true,
|
|
1469
|
+
signerConfigured: true,
|
|
1470
|
+
localMcpConfigured: false,
|
|
1471
|
+
runtimeMcpMode: "hosted_plus_signer",
|
|
1472
|
+
target: "Claude Code MCP config",
|
|
1473
|
+
changed: true,
|
|
1474
|
+
restartRequired: true,
|
|
1475
|
+
messages: [
|
|
1476
|
+
"Updated hosted Haven MCP and local signer entries with Claude Code.",
|
|
1477
|
+
...verified ? ["Verified Claude Code MCP entry."] : [],
|
|
1478
|
+
"After Haven approval, Haven tools should appear in your next Claude Code message. If they don't, restart the session to load them."
|
|
1479
|
+
]
|
|
1480
|
+
};
|
|
1481
|
+
} catch (err) {
|
|
1482
|
+
return {
|
|
1483
|
+
hostedConfigured: false,
|
|
1484
|
+
signerConfigured: false,
|
|
1485
|
+
localMcpConfigured: false,
|
|
1486
|
+
runtimeMcpMode: "hosted_plus_signer",
|
|
1487
|
+
target: "Claude Code MCP config",
|
|
1488
|
+
changed: false,
|
|
1489
|
+
restartRequired: true,
|
|
1490
|
+
messages: [
|
|
1491
|
+
`Could not update Claude Code MCP config: ${err instanceof Error ? err.message : String(err)}`,
|
|
1492
|
+
"Install Claude Code or rerun the Haven setup command inside a Claude Code terminal."
|
|
1493
|
+
],
|
|
1494
|
+
errorCode: "claude_code_config_failed"
|
|
1495
|
+
};
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1336
1498
|
async function defaultRunCommand(command, args) {
|
|
1337
1499
|
await execFileAsync2(command, args, { timeout: 1e4 });
|
|
1338
1500
|
}
|
|
1501
|
+
async function installClaudeSkill(homeDir) {
|
|
1502
|
+
try {
|
|
1503
|
+
const skillDir = resolve(homeDir ?? homedir(), ".claude", "skills", SKILL_FOLDER_NAME);
|
|
1504
|
+
await mkdir(skillDir, { recursive: true });
|
|
1505
|
+
await writeFile(join(skillDir, "SKILL.md"), HAVEN_SKILL_MD, "utf8");
|
|
1506
|
+
return {
|
|
1507
|
+
installed: true,
|
|
1508
|
+
messages: ["Installed the generic Haven payment skill (~/.claude/skills/haven-pay). It contains no secrets."]
|
|
1509
|
+
};
|
|
1510
|
+
} catch (err) {
|
|
1511
|
+
return {
|
|
1512
|
+
installed: false,
|
|
1513
|
+
messages: [`Could not install the Haven payment skill: ${err instanceof Error ? err.message : String(err)}. Download it from the Haven dashboard instead.`]
|
|
1514
|
+
};
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1339
1517
|
function buildProbeResult(mode, hostedConfigured, hostedStatus, signerReady, localMcpReady, localMcpProbeStatus) {
|
|
1340
1518
|
if (mode === "local_stdio") {
|
|
1341
1519
|
if (localMcpReady) return "local_stdio_mcp_ready";
|
|
@@ -1389,7 +1567,7 @@ function nextAction(runtime, restartMode, errorCode) {
|
|
|
1389
1567
|
if (restartMode === "restart-session") return "return_to_haven_for_wallet_approval_then_restart_agent_session";
|
|
1390
1568
|
return "return_to_haven_for_wallet_approval_then_configure_runtime";
|
|
1391
1569
|
}
|
|
1392
|
-
function
|
|
1570
|
+
function supportsLocalMcp(runtime) {
|
|
1393
1571
|
return runtime === "codex-cli" || runtime === "codex-desktop" || runtime === "claude-code";
|
|
1394
1572
|
}
|
|
1395
1573
|
async function prepareRuntimeForLocalMcp(input, deps) {
|
|
@@ -1417,7 +1595,7 @@ function localRuntimePrepareErrorCode(err) {
|
|
|
1417
1595
|
}
|
|
1418
1596
|
|
|
1419
1597
|
// src/runtime.ts
|
|
1420
|
-
var CONNECTOR_VERSION = "0.1.
|
|
1598
|
+
var CONNECTOR_VERSION = "0.1.11-alpha.0";
|
|
1421
1599
|
async function runConnect(options, deps = {}) {
|
|
1422
1600
|
const connectorVersion = options.connectorVersion ?? CONNECTOR_VERSION;
|
|
1423
1601
|
const api = deps.api ?? createConnectApiClient(options.apiBaseUrl);
|
|
@@ -1429,6 +1607,14 @@ async function runConnect(options, deps = {}) {
|
|
|
1429
1607
|
const generateKey = deps.generateKey ?? generateDelegateKey;
|
|
1430
1608
|
const generateLocalApiKey = deps.generateApiKey ?? generateAgentApiKey;
|
|
1431
1609
|
const installCapabilities = runtimeInstallCapabilities(options.runtime);
|
|
1610
|
+
if (options.localMcp) {
|
|
1611
|
+
const resolvedRuntime = normalizeRuntime(options.runtime);
|
|
1612
|
+
if (!supportsLocalMcp(resolvedRuntime)) {
|
|
1613
|
+
throw new Error(
|
|
1614
|
+
`--local (fully-local Haven MCP) is only available for Claude Code and Codex. The detected runtime is ${runtimeProfile(resolvedRuntime).label}. Re-run without --local to use the default hosted MCP + local signer setup.`
|
|
1615
|
+
);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1432
1618
|
const setup = await api.resolveSetup({
|
|
1433
1619
|
setupToken: options.setupToken,
|
|
1434
1620
|
connectorVersion,
|
|
@@ -1487,7 +1673,8 @@ async function runConnect(options, deps = {}) {
|
|
|
1487
1673
|
credentialDirectory: credentialPaths.directory,
|
|
1488
1674
|
environmentLabel: options.environmentLabel ?? "Local workspace",
|
|
1489
1675
|
ackSigner: options.ackSigner,
|
|
1490
|
-
ackLocalTools: options.ackLocalTools
|
|
1676
|
+
ackLocalTools: options.ackLocalTools,
|
|
1677
|
+
localMcp: options.localMcp
|
|
1491
1678
|
});
|
|
1492
1679
|
printRuntimeInstall(runtimeInstall, log);
|
|
1493
1680
|
try {
|
|
@@ -1502,6 +1689,7 @@ async function runConnect(options, deps = {}) {
|
|
|
1502
1689
|
signerAcknowledged: runtimeInstall.signerAcknowledged,
|
|
1503
1690
|
localMcpAcknowledged: runtimeInstall.localMcpAcknowledged,
|
|
1504
1691
|
activationCommandAvailable: Boolean(runtimeInstall.activationCommand),
|
|
1692
|
+
skillInstalled: runtimeInstall.skillInstalled,
|
|
1505
1693
|
probeResult: runtimeInstall.probeResult,
|
|
1506
1694
|
restartRequired: runtimeInstall.restartRequired,
|
|
1507
1695
|
nextUserAction: runtimeInstall.nextUserAction,
|
|
@@ -1583,6 +1771,8 @@ function parseArgs(argv, env = process.env) {
|
|
|
1583
1771
|
} else if (arg === "--ack-signer") {
|
|
1584
1772
|
options.ackSigner = true;
|
|
1585
1773
|
options.ackLocalTools = true;
|
|
1774
|
+
} else if (arg === "--local" || arg === "--local-mcp") {
|
|
1775
|
+
options.localMcp = true;
|
|
1586
1776
|
} else if (arg === "--version") {
|
|
1587
1777
|
process.stdout.write(`${CONNECTOR_VERSION}
|
|
1588
1778
|
`);
|
|
@@ -1621,6 +1811,8 @@ function helpText() {
|
|
|
1621
1811
|
" --environment-label <text> Non-sensitive label shown in Haven setup review.",
|
|
1622
1812
|
" --ack-local-tools Write the one-time local Haven tools acknowledgement during setup.",
|
|
1623
1813
|
" --ack-signer Backward-compatible alias for --ack-local-tools.",
|
|
1814
|
+
" --local Advanced: install the fully-local Haven MCP (no hosted dependency).",
|
|
1815
|
+
" Only available for Claude Code and Codex. Default is hosted MCP + local signer.",
|
|
1624
1816
|
" --help Show this help.",
|
|
1625
1817
|
"",
|
|
1626
1818
|
"The connector never prints the private key and never sends it to Haven."
|
|
@@ -1634,6 +1826,6 @@ function requireValue(argv, index, option) {
|
|
|
1634
1826
|
return value;
|
|
1635
1827
|
}
|
|
1636
1828
|
|
|
1637
|
-
export { CONNECTOR_VERSION, createConnectApiClient, defaultAgentDirectory, delegateKeyFromPrivateKey, generateDelegateKey, helpText, installRuntime, normalizeRuntime, parseArgs, redactSecrets, runConnect, runtimeInstallCapabilities, runtimeProfile, shortAddress, writeCredentialFiles };
|
|
1829
|
+
export { CONNECTOR_VERSION, MCP_RUNTIME_MANIFEST, createConnectApiClient, defaultAgentDirectory, delegateKeyFromPrivateKey, generateDelegateKey, helpText, installRuntime, mcpPackageSpec, normalizeRuntime, parseArgs, redactSecrets, runConnect, runtimeInstallCapabilities, runtimeProfile, sdkPackageSpec, shortAddress, signerPackageSpec, writeCredentialFiles };
|
|
1638
1830
|
//# sourceMappingURL=index.js.map
|
|
1639
1831
|
//# sourceMappingURL=index.js.map
|