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