@buda-ai/connector 0.1.12 → 0.1.15
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.js +67 -40
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -517,7 +517,7 @@ import path2 from "path";
|
|
|
517
517
|
// package.json
|
|
518
518
|
var package_default = {
|
|
519
519
|
name: "@buda-ai/connector",
|
|
520
|
-
version: "0.1.
|
|
520
|
+
version: "0.1.15",
|
|
521
521
|
private: false,
|
|
522
522
|
type: "module",
|
|
523
523
|
publishConfig: {
|
|
@@ -2357,6 +2357,20 @@ async function registerConnector(config, launchConfig, bunnyDaemon, options) {
|
|
|
2357
2357
|
relayProtocol: result.relayProtocol
|
|
2358
2358
|
};
|
|
2359
2359
|
}
|
|
2360
|
+
async function registerConnectorForExplicitEnrollment(config, launchConfig, bunnyDaemon) {
|
|
2361
|
+
try {
|
|
2362
|
+
return await registerConnector(config, launchConfig, bunnyDaemon);
|
|
2363
|
+
} catch (error) {
|
|
2364
|
+
const hasSpaceToken = Boolean(config.token?.trim() || getConnectorToken(launchConfig));
|
|
2365
|
+
const hasOauthToken = Boolean(launchConfig?.oauthToken?.trim());
|
|
2366
|
+
if (!(error instanceof ConnectorDeletedError) || !hasSpaceToken || hasOauthToken) {
|
|
2367
|
+
throw error;
|
|
2368
|
+
}
|
|
2369
|
+
return registerConnector(config, launchConfig, bunnyDaemon, {
|
|
2370
|
+
recoverMissingProfile: true
|
|
2371
|
+
});
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2360
2374
|
async function heartbeatConnector(config, launchConfig, bunnyDaemon) {
|
|
2361
2375
|
const logs = takePendingLogs();
|
|
2362
2376
|
const result = await postJson(
|
|
@@ -2397,6 +2411,13 @@ import path6 from "path";
|
|
|
2397
2411
|
import { promisify } from "util";
|
|
2398
2412
|
var execFileAsync = promisify(execFile);
|
|
2399
2413
|
var RUNTIME_INSTALL_TIMEOUT_MS = 5 * 6e4;
|
|
2414
|
+
var resolveBundledNodePlacement = (sourceRoot, sourceNode, pathApi = path6) => {
|
|
2415
|
+
const relativeNode = pathApi.relative(sourceRoot, sourceNode);
|
|
2416
|
+
return {
|
|
2417
|
+
copyNode: relativeNode.startsWith("..") || pathApi.isAbsolute(relativeNode),
|
|
2418
|
+
relativeNode
|
|
2419
|
+
};
|
|
2420
|
+
};
|
|
2400
2421
|
var exists = async (filePath) => access(filePath).then(() => true).catch(() => false);
|
|
2401
2422
|
var runtimeRoot = () => process.env.BUDA_CONNECTOR_RUNTIME_ROOT || path6.join(homedir3(), ".buda", "runtime");
|
|
2402
2423
|
var runtimePlatformKey = `${process.platform}-${process.arch}-node${process.versions.modules}`;
|
|
@@ -2468,10 +2489,10 @@ var installFromBundledRuntime = async (directory, sourceRoot) => {
|
|
|
2468
2489
|
if (relativeEntrypoint.startsWith("..") || path6.isAbsolute(relativeEntrypoint)) {
|
|
2469
2490
|
throw new Error("Bundled Connector entrypoint must be inside its runtime root");
|
|
2470
2491
|
}
|
|
2471
|
-
const relativeNode =
|
|
2492
|
+
const { copyNode, relativeNode } = resolveBundledNodePlacement(sourceRoot, sourceNode);
|
|
2472
2493
|
const entrypoint = path6.join(directory, relativeEntrypoint);
|
|
2473
|
-
const nodeExecutable =
|
|
2474
|
-
if (
|
|
2494
|
+
const nodeExecutable = copyNode ? path6.join(directory, "node", path6.basename(sourceNode)) : path6.join(directory, relativeNode);
|
|
2495
|
+
if (copyNode) {
|
|
2475
2496
|
await mkdir5(path6.dirname(nodeExecutable), { recursive: true });
|
|
2476
2497
|
await cp(sourceNode, nodeExecutable, { force: true });
|
|
2477
2498
|
}
|
|
@@ -2545,13 +2566,14 @@ var isProcessAlive2 = (pid) => {
|
|
|
2545
2566
|
return !(typeof error === "object" && error !== null && "code" in error && error.code === "ESRCH");
|
|
2546
2567
|
}
|
|
2547
2568
|
};
|
|
2548
|
-
var getRuntimeCommandArgs = (runtime, mode) => [
|
|
2569
|
+
var getRuntimeCommandArgs = (runtime, mode, options = {}) => [
|
|
2549
2570
|
...runtime.nodeArgs ?? [],
|
|
2550
2571
|
runtime.entrypoint,
|
|
2551
2572
|
"daemon",
|
|
2552
2573
|
"--internal-daemon",
|
|
2553
2574
|
"--daemon-mode",
|
|
2554
2575
|
mode,
|
|
2576
|
+
...options.explicitEnrollment ? ["--explicit-enrollment"] : [],
|
|
2555
2577
|
"--plain"
|
|
2556
2578
|
];
|
|
2557
2579
|
var compareVersions = (left, right) => {
|
|
@@ -2578,9 +2600,9 @@ var waitForDaemon = async (launchConfig, deadline) => {
|
|
|
2578
2600
|
lastConfig ? "Connector daemon did not expose its control channel in time" : "Connector registration did not create a canonical local identity in time"
|
|
2579
2601
|
);
|
|
2580
2602
|
};
|
|
2581
|
-
var spawnInternalDaemon = async (launchConfig, mode, preparedRuntime) => {
|
|
2603
|
+
var spawnInternalDaemon = async (launchConfig, mode, preparedRuntime, options = {}) => {
|
|
2582
2604
|
const runtime = preparedRuntime ?? await ensureStableConnectorRuntime();
|
|
2583
|
-
const child = spawn(runtime.nodeExecutable, getRuntimeCommandArgs(runtime, mode), {
|
|
2605
|
+
const child = spawn(runtime.nodeExecutable, getRuntimeCommandArgs(runtime, mode, options), {
|
|
2584
2606
|
detached: true,
|
|
2585
2607
|
env: {
|
|
2586
2608
|
...process.env,
|
|
@@ -2603,7 +2625,7 @@ var stopOlderIdleDaemon = async (config, status) => {
|
|
|
2603
2625
|
}
|
|
2604
2626
|
throw new Error("Older Connector daemon did not stop cleanly; existing identity was preserved");
|
|
2605
2627
|
};
|
|
2606
|
-
async function ensureConnectorDaemon(launchConfig, mode) {
|
|
2628
|
+
async function ensureConnectorDaemon(launchConfig, mode, options = {}) {
|
|
2607
2629
|
const deviceId = await getOrCreateSystemDeviceId(getConfigRoot());
|
|
2608
2630
|
const scope = await resolveConnectorScope(deviceId, launchConfig);
|
|
2609
2631
|
launchConfig = { ...launchConfig, spaceId: scope.spaceId };
|
|
@@ -2623,7 +2645,7 @@ async function ensureConnectorDaemon(launchConfig, mode) {
|
|
|
2623
2645
|
const status = mode === "persistent" ? await requestDaemonControl(existingConfig, "persist", getConfigRoot()) : existingStatus;
|
|
2624
2646
|
return { config: existingConfig, status };
|
|
2625
2647
|
}
|
|
2626
|
-
await spawnInternalDaemon(launchConfig, mode, preparedRuntime);
|
|
2648
|
+
await spawnInternalDaemon(launchConfig, mode, preparedRuntime, options);
|
|
2627
2649
|
return await waitForDaemon(launchConfig, Date.now() + START_TIMEOUT_MS);
|
|
2628
2650
|
}
|
|
2629
2651
|
const persistedStatus = await readPersistedDaemonStatus(
|
|
@@ -2636,7 +2658,7 @@ async function ensureConnectorDaemon(launchConfig, mode) {
|
|
|
2636
2658
|
);
|
|
2637
2659
|
}
|
|
2638
2660
|
}
|
|
2639
|
-
await spawnInternalDaemon(launchConfig, mode);
|
|
2661
|
+
await spawnInternalDaemon(launchConfig, mode, void 0, options);
|
|
2640
2662
|
return await waitForDaemon(launchConfig, Date.now() + START_TIMEOUT_MS);
|
|
2641
2663
|
} finally {
|
|
2642
2664
|
await bootstrapLock.release();
|
|
@@ -2780,7 +2802,9 @@ async function runConnectorDashboard(launchConfig, options = {}) {
|
|
|
2780
2802
|
plain: options.plain
|
|
2781
2803
|
});
|
|
2782
2804
|
if (!dashboard) {
|
|
2783
|
-
const { config } = await ensureConnectorDaemon(launchConfig, "persistent"
|
|
2805
|
+
const { config } = await ensureConnectorDaemon(launchConfig, "persistent", {
|
|
2806
|
+
explicitEnrollment: true
|
|
2807
|
+
});
|
|
2784
2808
|
const stopLogs2 = streamDaemonLogs({
|
|
2785
2809
|
connectorId: config.connectorId,
|
|
2786
2810
|
dashboardActive: false,
|
|
@@ -2835,7 +2859,7 @@ async function runConnectorDashboard(launchConfig, options = {}) {
|
|
|
2835
2859
|
preferredConnectorId = config.connectorId;
|
|
2836
2860
|
}).catch(() => void 0).finally(() => refresh());
|
|
2837
2861
|
const timer = setInterval(() => void refresh(), 1e3);
|
|
2838
|
-
void ensureConnectorDaemon(launchConfig, "persistent").then(async ({ config }) => {
|
|
2862
|
+
void ensureConnectorDaemon(launchConfig, "persistent", { explicitEnrollment: true }).then(async ({ config }) => {
|
|
2839
2863
|
pendingConnector = void 0;
|
|
2840
2864
|
preferredConnectorId = config.connectorId;
|
|
2841
2865
|
await refresh();
|
|
@@ -3003,13 +3027,12 @@ var createTerminalSession = async (grant, nodePtyLoader) => {
|
|
|
3003
3027
|
try {
|
|
3004
3028
|
nodePty = await nodePtyLoader();
|
|
3005
3029
|
} catch (error) {
|
|
3030
|
+
const message = serializeErrorMessage(error);
|
|
3006
3031
|
void writeLog(
|
|
3007
3032
|
"error",
|
|
3008
3033
|
`local terminal could not load node-pty: ${serializeErrorMessage(error)}`
|
|
3009
3034
|
);
|
|
3010
|
-
throw new LocalTerminalUnavailableError(
|
|
3011
|
-
"Local terminal is unavailable because node-pty could not be loaded. The connector remains available for other capabilities."
|
|
3012
|
-
);
|
|
3035
|
+
throw new LocalTerminalUnavailableError(message);
|
|
3013
3036
|
}
|
|
3014
3037
|
const shell = process.platform === "win32" ? "powershell.exe" : process.env.SHELL || "/bin/bash";
|
|
3015
3038
|
const shellArgs = process.platform === "win32" ? [] : ["-l"];
|
|
@@ -3199,7 +3222,7 @@ var proxyConnectorTerminalTunnel = async (input) => {
|
|
|
3199
3222
|
let bridgeAccepted = false;
|
|
3200
3223
|
let activityStarted = false;
|
|
3201
3224
|
let activityEnded = false;
|
|
3202
|
-
let
|
|
3225
|
+
let localCloseAfterBridge = null;
|
|
3203
3226
|
let localCloseAfterOpen = null;
|
|
3204
3227
|
const endActivity = () => {
|
|
3205
3228
|
if (!activityStarted || activityEnded) return;
|
|
@@ -3224,7 +3247,9 @@ var proxyConnectorTerminalTunnel = async (input) => {
|
|
|
3224
3247
|
if (!bridgeAccepted) {
|
|
3225
3248
|
if (!isBinary && data.toString() === '{"type":"bridge-accepted"}') {
|
|
3226
3249
|
bridgeAccepted = true;
|
|
3227
|
-
local.
|
|
3250
|
+
if (local.readyState === WebSocket.OPEN) {
|
|
3251
|
+
local.send(JSON.stringify({ type: "bridge-start" }));
|
|
3252
|
+
}
|
|
3228
3253
|
for (const [frame, binary] of pendingCloudFrames) {
|
|
3229
3254
|
if (local.readyState === WebSocket.OPEN) local.send(frame, { binary });
|
|
3230
3255
|
}
|
|
@@ -3234,6 +3259,9 @@ var proxyConnectorTerminalTunnel = async (input) => {
|
|
|
3234
3259
|
pendingCloudFrames.length = 0;
|
|
3235
3260
|
pendingLocalFrames.length = 0;
|
|
3236
3261
|
pendingBytes = 0;
|
|
3262
|
+
if (localCloseAfterBridge && cloud.readyState === WebSocket.OPEN) {
|
|
3263
|
+
cloud.close(localCloseAfterBridge.code, localCloseAfterBridge.reason);
|
|
3264
|
+
}
|
|
3237
3265
|
return;
|
|
3238
3266
|
}
|
|
3239
3267
|
bufferFrame(pendingCloudFrames, data, isBinary);
|
|
@@ -3270,15 +3298,10 @@ var proxyConnectorTerminalTunnel = async (input) => {
|
|
|
3270
3298
|
code: normalizeTerminalCloseCode(code),
|
|
3271
3299
|
reason: truncateTerminalCloseReason(reason.toString())
|
|
3272
3300
|
};
|
|
3273
|
-
if (
|
|
3301
|
+
if (!bridgeAccepted) {
|
|
3302
|
+
localCloseAfterBridge = normalizedClose;
|
|
3303
|
+
} else if (cloud.readyState === WebSocket.OPEN) {
|
|
3274
3304
|
cloud.close(normalizedClose.code, normalizedClose.reason);
|
|
3275
|
-
} else if (cloud.readyState === WebSocket.CONNECTING) {
|
|
3276
|
-
cloudCloseAfterOpen = normalizedClose;
|
|
3277
|
-
}
|
|
3278
|
-
});
|
|
3279
|
-
cloud.once("open", () => {
|
|
3280
|
-
if (cloudCloseAfterOpen && cloud.readyState === WebSocket.OPEN) {
|
|
3281
|
-
cloud.close(cloudCloseAfterOpen.code, cloudCloseAfterOpen.reason);
|
|
3282
3305
|
}
|
|
3283
3306
|
});
|
|
3284
3307
|
local.once("open", () => {
|
|
@@ -3295,9 +3318,11 @@ var proxyConnectorTerminalTunnel = async (input) => {
|
|
|
3295
3318
|
local.terminate();
|
|
3296
3319
|
throw error;
|
|
3297
3320
|
}
|
|
3298
|
-
if (cloud.readyState !== WebSocket.OPEN
|
|
3299
|
-
|
|
3300
|
-
|
|
3321
|
+
if (cloud.readyState !== WebSocket.OPEN) return;
|
|
3322
|
+
if (local.readyState === WebSocket.OPEN) {
|
|
3323
|
+
activityStarted = true;
|
|
3324
|
+
input.onActivityStart?.();
|
|
3325
|
+
}
|
|
3301
3326
|
cloud.send(JSON.stringify({ type: "bridge-ready" }));
|
|
3302
3327
|
await writeLog(
|
|
3303
3328
|
"info",
|
|
@@ -5421,9 +5446,7 @@ async function runOnboard(launchConfig, options = {}) {
|
|
|
5421
5446
|
await migrateLegacyWorkspaceRoot(config2.workdirRoot);
|
|
5422
5447
|
await provisionWorkdirLayout(config2.workdirRoot);
|
|
5423
5448
|
try {
|
|
5424
|
-
const registration = await
|
|
5425
|
-
recoverMissingProfile: false
|
|
5426
|
-
});
|
|
5449
|
+
const registration = await registerConnectorForExplicitEnrollment(config2, launchConfig);
|
|
5427
5450
|
config2.connectorId = registration.connectorId;
|
|
5428
5451
|
config2.spaceId = registration.spaceId ?? config2.spaceId;
|
|
5429
5452
|
relayProtocol = registration.relayProtocol;
|
|
@@ -5455,7 +5478,16 @@ async function runOnboard(launchConfig, options = {}) {
|
|
|
5455
5478
|
if (!existing) {
|
|
5456
5479
|
} else {
|
|
5457
5480
|
try {
|
|
5458
|
-
|
|
5481
|
+
const registration = await registerConnectorForExplicitEnrollment(
|
|
5482
|
+
config,
|
|
5483
|
+
launchConfig,
|
|
5484
|
+
bunnyDaemon
|
|
5485
|
+
);
|
|
5486
|
+
config.connectorId = registration.connectorId;
|
|
5487
|
+
config.spaceId = registration.spaceId ?? config.spaceId;
|
|
5488
|
+
if (!config.spaceId) throw new Error("Registration did not resolve a Space");
|
|
5489
|
+
relayProtocol = registration.relayProtocol;
|
|
5490
|
+
await writeDeviceConfig(config);
|
|
5459
5491
|
} catch (error) {
|
|
5460
5492
|
await stopEmbeddedBunnyDaemon(bunnyDaemon);
|
|
5461
5493
|
s.stop("Failed to register");
|
|
@@ -5543,15 +5575,12 @@ async function stopRecoveredIdleDaemon(config, configRoot) {
|
|
|
5543
5575
|
throw new Error(`Recovered Connector ${config.connectorId} did not stop cleanly.`);
|
|
5544
5576
|
}
|
|
5545
5577
|
async function runNewConnector(launchConfig) {
|
|
5546
|
-
const existing = await readDeviceConfig(launchConfig);
|
|
5547
5578
|
const config = await ensureDeviceConfig(launchConfig);
|
|
5548
5579
|
const paths = getConnectorPaths(config.serverUrl);
|
|
5549
5580
|
await migrateLegacyWorkspaceRoot(config.workdirRoot);
|
|
5550
5581
|
await provisionWorkdirLayout(config.workdirRoot);
|
|
5551
5582
|
await LocalWorkspaceRegistry.open(config.workdirRoot);
|
|
5552
|
-
const registration = await
|
|
5553
|
-
recoverMissingProfile: shouldRecoverMissingProfile(Boolean(existing), launchConfig)
|
|
5554
|
-
});
|
|
5583
|
+
const registration = await registerConnectorForExplicitEnrollment(config, launchConfig);
|
|
5555
5584
|
config.connectorId = registration.connectorId;
|
|
5556
5585
|
config.spaceId = registration.spaceId ?? config.spaceId;
|
|
5557
5586
|
await writeDeviceConfig(config);
|
|
@@ -5592,9 +5621,7 @@ async function runConnectorDaemon(launchConfig, options = {}) {
|
|
|
5592
5621
|
const workspaceRegistry = await LocalWorkspaceRegistry.open(config.workdirRoot);
|
|
5593
5622
|
bunnyDaemon = await startEmbeddedBunnyDaemon(config, launchConfig);
|
|
5594
5623
|
const activeBunnyDaemon = bunnyDaemon;
|
|
5595
|
-
const registration = await
|
|
5596
|
-
recoverMissingProfile: shouldRecoverMissingProfile(Boolean(existing), launchConfig)
|
|
5597
|
-
});
|
|
5624
|
+
const registration = options.explicitEnrollment ? await registerConnectorForExplicitEnrollment(config, launchConfig, activeBunnyDaemon) : await registerConnector(config, launchConfig, activeBunnyDaemon);
|
|
5598
5625
|
const connectorIdChanged = config.connectorId !== registration.connectorId;
|
|
5599
5626
|
if (connectorIdChanged) {
|
|
5600
5627
|
const registeredConfig = {
|
|
@@ -5703,7 +5730,6 @@ async function runConnectorDaemon(launchConfig, options = {}) {
|
|
|
5703
5730
|
throw error;
|
|
5704
5731
|
}
|
|
5705
5732
|
}
|
|
5706
|
-
var shouldRecoverMissingProfile = (hasExistingProfile, launchConfig) => !hasExistingProfile && Boolean(getConnectorToken(launchConfig)) && !launchConfig?.oauthToken?.trim();
|
|
5707
5733
|
|
|
5708
5734
|
// src/cli.ts
|
|
5709
5735
|
function printHelp() {
|
|
@@ -5795,6 +5821,7 @@ async function main() {
|
|
|
5795
5821
|
if (command === "daemon" && process.argv.includes("--internal-daemon")) {
|
|
5796
5822
|
await runConnectorDaemon(launchConfig, {
|
|
5797
5823
|
captureConsole: true,
|
|
5824
|
+
explicitEnrollment: process.argv.includes("--explicit-enrollment"),
|
|
5798
5825
|
mode: getDaemonModeFlag(),
|
|
5799
5826
|
version: CONNECTOR_RUNTIME_VERSION
|
|
5800
5827
|
});
|