@haven_ai/connect 0.1.12-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 +168 -22
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +168 -22
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +169 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -5
- package/dist/index.d.ts +50 -5
- package/dist/index.js +169 -23
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/cli.cjs
CHANGED
|
@@ -215,9 +215,9 @@ var MCP_RUNTIME_MANIFEST = {
|
|
|
215
215
|
mcpPackage: "@haven_ai/mcp",
|
|
216
216
|
mcpVersion: mcp.MCP_VERSION,
|
|
217
217
|
sdkPackage: "@haven_ai/sdk",
|
|
218
|
-
sdkVersion: "0.1.
|
|
218
|
+
sdkVersion: "0.1.13-alpha.0",
|
|
219
219
|
signerPackage: "@haven_ai/signer",
|
|
220
|
-
signerVersion: "0.1.
|
|
220
|
+
signerVersion: "0.1.13-alpha.0",
|
|
221
221
|
minimumNodeVersion: "20.0.0",
|
|
222
222
|
supportedClients: ["codex-cli", "codex-desktop", "claude-code"],
|
|
223
223
|
requiredTools: mcp.registeredToolNames()
|
|
@@ -390,10 +390,16 @@ function buildHostedServer(hostedMcpUrl, apiKey, runtime) {
|
|
|
390
390
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
391
391
|
};
|
|
392
392
|
}
|
|
393
|
-
function
|
|
394
|
-
|
|
393
|
+
function resolveSignerLaunchSpec(input) {
|
|
394
|
+
return input.signerCommand ?? {
|
|
395
395
|
command: "npx",
|
|
396
|
-
args: ["-y",
|
|
396
|
+
args: ["-y", signerPackageSpec(), "--credentials", input.signerPath]
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
function buildSignerServer(spec, runtime) {
|
|
400
|
+
const server = {
|
|
401
|
+
command: spec.command,
|
|
402
|
+
args: spec.args
|
|
397
403
|
};
|
|
398
404
|
if (runtime === "vscode" || runtime === "vscode-insiders") return { type: "stdio", ...server };
|
|
399
405
|
return server;
|
|
@@ -426,7 +432,7 @@ function mergeCodexToml(existingToml, localMcpCommand) {
|
|
|
426
432
|
`;
|
|
427
433
|
return merged;
|
|
428
434
|
}
|
|
429
|
-
function mergeCodexTomlHosted(existingToml, hostedMcpUrl, apiKey,
|
|
435
|
+
function mergeCodexTomlHosted(existingToml, hostedMcpUrl, apiKey, signerSpec) {
|
|
430
436
|
let next = removeTomlTableTree(removeTomlTableTree(existingToml, "mcp_servers.haven"), "mcp_servers.haven_signer");
|
|
431
437
|
next = next.trimEnd();
|
|
432
438
|
const block = [
|
|
@@ -435,8 +441,8 @@ function mergeCodexTomlHosted(existingToml, hostedMcpUrl, apiKey, signerPath) {
|
|
|
435
441
|
`http_headers = { "Authorization" = ${tomlString(`Bearer ${apiKey}`)} }`,
|
|
436
442
|
"",
|
|
437
443
|
"[mcp_servers.haven_signer]",
|
|
438
|
-
|
|
439
|
-
`args = [
|
|
444
|
+
`command = ${tomlString(signerSpec.command)}`,
|
|
445
|
+
`args = [${signerSpec.args.map((arg) => tomlString(arg)).join(", ")}]`,
|
|
440
446
|
"startup_timeout_sec = 120"
|
|
441
447
|
].join("\n");
|
|
442
448
|
validateCodexToml(block, "Generated Codex Haven config");
|
|
@@ -453,7 +459,7 @@ async function writeJsonRuntimeConfig(input, target, serverRoot) {
|
|
|
453
459
|
existing,
|
|
454
460
|
serverRoot,
|
|
455
461
|
buildHostedServer(input.hostedMcpUrl, input.apiKey, input.runtime),
|
|
456
|
-
buildSignerServer(input
|
|
462
|
+
buildSignerServer(resolveSignerLaunchSpec(input), input.runtime)
|
|
457
463
|
);
|
|
458
464
|
await writeOwnerOnlyText(target, merged);
|
|
459
465
|
return {
|
|
@@ -509,7 +515,7 @@ async function writeCodexConfig(input) {
|
|
|
509
515
|
]
|
|
510
516
|
};
|
|
511
517
|
}
|
|
512
|
-
const merged = mergeCodexTomlHosted(existing ?? "", input.hostedMcpUrl, input.apiKey, input
|
|
518
|
+
const merged = mergeCodexTomlHosted(existing ?? "", input.hostedMcpUrl, input.apiKey, resolveSignerLaunchSpec(input));
|
|
513
519
|
await writeOwnerOnlyText(target, merged);
|
|
514
520
|
return {
|
|
515
521
|
hostedConfigured: true,
|
|
@@ -794,9 +800,6 @@ function configTargetLabel(runtime) {
|
|
|
794
800
|
return "runtime MCP config";
|
|
795
801
|
}
|
|
796
802
|
}
|
|
797
|
-
function signerPackageName() {
|
|
798
|
-
return signerPackageSpec();
|
|
799
|
-
}
|
|
800
803
|
async function acknowledgeLocalMcpConsent(identityPath, signerPath, log) {
|
|
801
804
|
try {
|
|
802
805
|
const input = await buildLocalMcpConsentInput(identityPath, signerPath);
|
|
@@ -910,7 +913,7 @@ async function probeLocalSignerCredential(signerPath) {
|
|
|
910
913
|
}
|
|
911
914
|
}
|
|
912
915
|
async function probeLocalMcpTools(command, args, requiredTools, timeoutMs = 1e4) {
|
|
913
|
-
return new Promise((
|
|
916
|
+
return new Promise((resolve8) => {
|
|
914
917
|
const child = child_process.spawn(command, args, { stdio: ["pipe", "pipe", "ignore"] });
|
|
915
918
|
let stdout = "";
|
|
916
919
|
let settled = false;
|
|
@@ -920,7 +923,7 @@ async function probeLocalMcpTools(command, args, requiredTools, timeoutMs = 1e4)
|
|
|
920
923
|
settled = true;
|
|
921
924
|
clearTimeout(timeout);
|
|
922
925
|
child.kill();
|
|
923
|
-
|
|
926
|
+
resolve8(result);
|
|
924
927
|
};
|
|
925
928
|
const timeout = setTimeout(() => finish({ status: "timeout" }), timeoutMs);
|
|
926
929
|
child.on("error", () => finish({ status: "process_error" }));
|
|
@@ -1158,6 +1161,126 @@ async function assertFileExists(path, label) {
|
|
|
1158
1161
|
throw new Error(`Missing ${label}: ${path}`);
|
|
1159
1162
|
}
|
|
1160
1163
|
}
|
|
1164
|
+
var execFileAsync2 = util.promisify(child_process.execFile);
|
|
1165
|
+
async function prepareSignerRuntime(input, deps = {}) {
|
|
1166
|
+
const homeDir = input.homeDir ?? os.homedir();
|
|
1167
|
+
const runtimeDirectory = path.resolve(homeDir, ".haven", "signer-runtime", MCP_RUNTIME_MANIFEST.signerVersion);
|
|
1168
|
+
const npmCacheDirectory = path.resolve(homeDir, ".haven", "npm-cache");
|
|
1169
|
+
const cliPath = path.join(runtimeDirectory, "node_modules", "@haven_ai", "signer", "dist", "cli.js");
|
|
1170
|
+
const messages = [];
|
|
1171
|
+
await promises.mkdir(runtimeDirectory, { recursive: true, mode: 448 });
|
|
1172
|
+
await promises.chmod(runtimeDirectory, 448).catch(() => void 0);
|
|
1173
|
+
await promises.mkdir(npmCacheDirectory, { recursive: true, mode: 448 });
|
|
1174
|
+
await promises.chmod(npmCacheDirectory, 448).catch(() => void 0);
|
|
1175
|
+
if (await installedRuntimeMatches2(runtimeDirectory, cliPath)) {
|
|
1176
|
+
messages.push(`Using existing local Haven signer runtime ${signerPackageSpec()}.`);
|
|
1177
|
+
} else {
|
|
1178
|
+
await installRuntimePackages2(runtimeDirectory, npmCacheDirectory, deps.runCommand);
|
|
1179
|
+
messages.push(`Installed local Haven signer runtime ${signerPackageSpec()}.`);
|
|
1180
|
+
}
|
|
1181
|
+
await assertFileExists2(cliPath, "local Haven signer CLI");
|
|
1182
|
+
const wrapperPath = path.join(input.credentialDirectory, "bin", "haven-signer.mjs");
|
|
1183
|
+
await writeWrapper2({ wrapperPath, cliPath, signerPath: input.signerPath });
|
|
1184
|
+
await writeRuntimeSidecar2({
|
|
1185
|
+
path: path.join(input.credentialDirectory, "signer-runtime.json"),
|
|
1186
|
+
wrapperPath,
|
|
1187
|
+
runtimeDirectory,
|
|
1188
|
+
npmCacheDirectory,
|
|
1189
|
+
cliPath
|
|
1190
|
+
});
|
|
1191
|
+
messages.push(`Prepared stable local Haven signer wrapper: ${wrapperPath}`);
|
|
1192
|
+
return {
|
|
1193
|
+
command: wrapperPath,
|
|
1194
|
+
args: [],
|
|
1195
|
+
wrapperPath,
|
|
1196
|
+
runtimeDirectory,
|
|
1197
|
+
npmCacheDirectory,
|
|
1198
|
+
cliPath,
|
|
1199
|
+
messages
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
1202
|
+
async function installRuntimePackages2(runtimeDirectory, npmCacheDirectory, runCommand) {
|
|
1203
|
+
const args = [
|
|
1204
|
+
"install",
|
|
1205
|
+
"--prefix",
|
|
1206
|
+
runtimeDirectory,
|
|
1207
|
+
"--cache",
|
|
1208
|
+
npmCacheDirectory,
|
|
1209
|
+
"--no-audit",
|
|
1210
|
+
"--no-fund",
|
|
1211
|
+
"--omit=dev",
|
|
1212
|
+
signerPackageSpec(),
|
|
1213
|
+
sdkPackageSpec()
|
|
1214
|
+
];
|
|
1215
|
+
try {
|
|
1216
|
+
if (runCommand) await runCommand("npm", args);
|
|
1217
|
+
else await execFileAsync2("npm", args, { timeout: 12e4, maxBuffer: 1024 * 1024 });
|
|
1218
|
+
} catch (err) {
|
|
1219
|
+
throw new Error(
|
|
1220
|
+
`Could not install local Haven signer runtime ${signerPackageSpec()}: ${err instanceof Error ? err.message : String(err)}`
|
|
1221
|
+
);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
async function installedRuntimeMatches2(runtimeDirectory, cliPath) {
|
|
1225
|
+
try {
|
|
1226
|
+
await assertFileExists2(cliPath, "local Haven signer CLI");
|
|
1227
|
+
const [signerPackage, sdkPackage] = await Promise.all([
|
|
1228
|
+
readPackageJson2(path.join(runtimeDirectory, "node_modules", "@haven_ai", "signer", "package.json")),
|
|
1229
|
+
readPackageJson2(path.join(runtimeDirectory, "node_modules", "@haven_ai", "sdk", "package.json"))
|
|
1230
|
+
]);
|
|
1231
|
+
return signerPackage.version === MCP_RUNTIME_MANIFEST.signerVersion && sdkPackage.version === MCP_RUNTIME_MANIFEST.sdkVersion;
|
|
1232
|
+
} catch {
|
|
1233
|
+
return false;
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
async function readPackageJson2(path) {
|
|
1237
|
+
return JSON.parse(await promises.readFile(path, "utf8"));
|
|
1238
|
+
}
|
|
1239
|
+
async function writeWrapper2(input) {
|
|
1240
|
+
await promises.mkdir(path.dirname(input.wrapperPath), { recursive: true, mode: 448 });
|
|
1241
|
+
await promises.chmod(path.dirname(input.wrapperPath), 448).catch(() => void 0);
|
|
1242
|
+
const source = [
|
|
1243
|
+
"#!/usr/bin/env node",
|
|
1244
|
+
"import { spawn } from 'node:child_process'",
|
|
1245
|
+
"",
|
|
1246
|
+
`const cliPath = ${JSON.stringify(input.cliPath)}`,
|
|
1247
|
+
`const signerPath = ${JSON.stringify(input.signerPath)}`,
|
|
1248
|
+
"",
|
|
1249
|
+
"const child = spawn(process.execPath, [cliPath, '--credentials', signerPath, ...process.argv.slice(2)], {",
|
|
1250
|
+
" stdio: 'inherit',",
|
|
1251
|
+
"})",
|
|
1252
|
+
"",
|
|
1253
|
+
"child.on('exit', (code, signal) => {",
|
|
1254
|
+
" if (signal) process.kill(process.pid, signal)",
|
|
1255
|
+
" else process.exit(code ?? 1)",
|
|
1256
|
+
"})",
|
|
1257
|
+
""
|
|
1258
|
+
].join("\n");
|
|
1259
|
+
await promises.writeFile(input.wrapperPath, source, { mode: 448 });
|
|
1260
|
+
await promises.chmod(input.wrapperPath, 448).catch(() => void 0);
|
|
1261
|
+
}
|
|
1262
|
+
async function writeRuntimeSidecar2(input) {
|
|
1263
|
+
const value = {
|
|
1264
|
+
signer_package: MCP_RUNTIME_MANIFEST.signerPackage,
|
|
1265
|
+
signer_version: MCP_RUNTIME_MANIFEST.signerVersion,
|
|
1266
|
+
sdk_package: MCP_RUNTIME_MANIFEST.sdkPackage,
|
|
1267
|
+
sdk_version: MCP_RUNTIME_MANIFEST.sdkVersion,
|
|
1268
|
+
wrapper_path: input.wrapperPath,
|
|
1269
|
+
runtime_directory: input.runtimeDirectory,
|
|
1270
|
+
npm_cache_directory: input.npmCacheDirectory,
|
|
1271
|
+
cli_path: input.cliPath
|
|
1272
|
+
};
|
|
1273
|
+
await promises.writeFile(input.path, `${JSON.stringify(value, null, 2)}
|
|
1274
|
+
`, { mode: 384 });
|
|
1275
|
+
await promises.chmod(input.path, 384).catch(() => void 0);
|
|
1276
|
+
}
|
|
1277
|
+
async function assertFileExists2(path, label) {
|
|
1278
|
+
try {
|
|
1279
|
+
await promises.access(path);
|
|
1280
|
+
} catch {
|
|
1281
|
+
throw new Error(`Missing ${label}: ${path}`);
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1161
1284
|
async function acknowledgeLocalSignerConsent(signerPath, log) {
|
|
1162
1285
|
try {
|
|
1163
1286
|
const input = await buildSignerConsentInput(signerPath);
|
|
@@ -1229,7 +1352,7 @@ function writeLogChunk2(log, chunk) {
|
|
|
1229
1352
|
}
|
|
1230
1353
|
|
|
1231
1354
|
// src/runtime-install.ts
|
|
1232
|
-
var
|
|
1355
|
+
var execFileAsync3 = util.promisify(child_process.execFile);
|
|
1233
1356
|
async function installRuntime(input, deps = {}) {
|
|
1234
1357
|
const runtime = normalizeRuntime(input.runtime, deps.env);
|
|
1235
1358
|
const profile = runtimeProfile(runtime, deps.env);
|
|
@@ -1290,7 +1413,20 @@ async function installRuntime(input, deps = {}) {
|
|
|
1290
1413
|
]
|
|
1291
1414
|
};
|
|
1292
1415
|
}
|
|
1293
|
-
|
|
1416
|
+
let signerCommand;
|
|
1417
|
+
if (!localRuntime) {
|
|
1418
|
+
try {
|
|
1419
|
+
const signerRuntime = await prepareSignerForRuntime(input, deps);
|
|
1420
|
+
signerCommand = { command: signerRuntime.command, args: signerRuntime.args };
|
|
1421
|
+
consentMessages.push(...signerRuntime.messages);
|
|
1422
|
+
} catch (err) {
|
|
1423
|
+
consentMessages.push(
|
|
1424
|
+
`Could not pre-install the local Haven signer; falling back to npx launch: ${err instanceof Error ? err.message : String(err)}`
|
|
1425
|
+
);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
const signerRuntimePrepared = localRuntime ? void 0 : signerCommand !== void 0;
|
|
1429
|
+
const configResult = runtime === "claude-code" ? localRuntime ? await configureClaudeCode(deps, localRuntimeInstall?.command ?? "") : await configureClaudeCodeHosted(deps, input, signerCommand) : await writeRuntimeConfig({
|
|
1294
1430
|
runtime,
|
|
1295
1431
|
hostedMcpUrl: input.hostedMcpUrl,
|
|
1296
1432
|
apiKey: input.apiKey,
|
|
@@ -1298,6 +1434,7 @@ async function installRuntime(input, deps = {}) {
|
|
|
1298
1434
|
signerPath: input.signerPath,
|
|
1299
1435
|
credentialDirectory: input.credentialDirectory,
|
|
1300
1436
|
localMcpCommand: localRuntimeInstall?.command,
|
|
1437
|
+
signerCommand,
|
|
1301
1438
|
homeDir: deps.homeDir,
|
|
1302
1439
|
mode: localRuntime ? "local" : "hosted"
|
|
1303
1440
|
});
|
|
@@ -1329,6 +1466,7 @@ async function installRuntime(input, deps = {}) {
|
|
|
1329
1466
|
localMcpAcknowledged: localMcpConsent?.acknowledged,
|
|
1330
1467
|
activationCommand: configResult.activationCommand,
|
|
1331
1468
|
skillInstalled: skillInstall?.installed,
|
|
1469
|
+
signerRuntimePrepared,
|
|
1332
1470
|
messages: [...consentMessages, ...localRuntimeInstall?.messages ?? [], ...configResult.messages, ...localProbeMessages, ...skillInstall?.messages ?? []]
|
|
1333
1471
|
};
|
|
1334
1472
|
}
|
|
@@ -1385,7 +1523,7 @@ async function configureClaudeCode(deps, localMcpCommand) {
|
|
|
1385
1523
|
};
|
|
1386
1524
|
}
|
|
1387
1525
|
}
|
|
1388
|
-
async function configureClaudeCodeHosted(deps, input) {
|
|
1526
|
+
async function configureClaudeCodeHosted(deps, input, signerCommand) {
|
|
1389
1527
|
const runCommand = deps.runCommand ?? defaultRunCommand;
|
|
1390
1528
|
const hostedJson = JSON.stringify({
|
|
1391
1529
|
type: "http",
|
|
@@ -1394,8 +1532,8 @@ async function configureClaudeCodeHosted(deps, input) {
|
|
|
1394
1532
|
});
|
|
1395
1533
|
const signerJson = JSON.stringify({
|
|
1396
1534
|
type: "stdio",
|
|
1397
|
-
command: "npx",
|
|
1398
|
-
args: ["-y", signerPackageSpec(), "--credentials", input.signerPath],
|
|
1535
|
+
command: signerCommand?.command ?? "npx",
|
|
1536
|
+
args: signerCommand?.args ?? ["-y", signerPackageSpec(), "--credentials", input.signerPath],
|
|
1399
1537
|
env: {}
|
|
1400
1538
|
});
|
|
1401
1539
|
try {
|
|
@@ -1436,7 +1574,7 @@ async function configureClaudeCodeHosted(deps, input) {
|
|
|
1436
1574
|
}
|
|
1437
1575
|
}
|
|
1438
1576
|
async function defaultRunCommand(command, args) {
|
|
1439
|
-
await
|
|
1577
|
+
await execFileAsync3(command, args, { timeout: 1e4 });
|
|
1440
1578
|
}
|
|
1441
1579
|
async function installClaudeSkill(homeDir) {
|
|
1442
1580
|
try {
|
|
@@ -1519,6 +1657,14 @@ async function prepareRuntimeForLocalMcp(input, deps) {
|
|
|
1519
1657
|
homeDir: deps.homeDir
|
|
1520
1658
|
});
|
|
1521
1659
|
}
|
|
1660
|
+
async function prepareSignerForRuntime(input, deps) {
|
|
1661
|
+
const prepare = deps.prepareSignerRuntime ?? ((runtimeInput) => prepareSignerRuntime(runtimeInput, { runCommand: deps.runCommand }));
|
|
1662
|
+
return prepare({
|
|
1663
|
+
credentialDirectory: input.credentialDirectory,
|
|
1664
|
+
signerPath: input.signerPath,
|
|
1665
|
+
homeDir: deps.homeDir
|
|
1666
|
+
});
|
|
1667
|
+
}
|
|
1522
1668
|
async function runLocalMcpProbe(runtimeInstall, deps) {
|
|
1523
1669
|
const probe = deps.probeLocalMcpTools ?? probeLocalMcpTools;
|
|
1524
1670
|
try {
|
|
@@ -1535,7 +1681,7 @@ function localRuntimePrepareErrorCode(err) {
|
|
|
1535
1681
|
}
|
|
1536
1682
|
|
|
1537
1683
|
// src/runtime.ts
|
|
1538
|
-
var CONNECTOR_VERSION = "0.1.
|
|
1684
|
+
var CONNECTOR_VERSION = "0.1.13-alpha.0";
|
|
1539
1685
|
async function runConnect(options, deps = {}) {
|
|
1540
1686
|
const connectorVersion = options.connectorVersion ?? CONNECTOR_VERSION;
|
|
1541
1687
|
const api = deps.api ?? createConnectApiClient(options.apiBaseUrl);
|