@buda-ai/connector 0.1.12 → 0.1.14

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.
Files changed (2) hide show
  1. package/dist/cli.js +57 -37
  2. 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.12",
520
+ version: "0.1.14",
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(
@@ -2545,13 +2559,14 @@ var isProcessAlive2 = (pid) => {
2545
2559
  return !(typeof error === "object" && error !== null && "code" in error && error.code === "ESRCH");
2546
2560
  }
2547
2561
  };
2548
- var getRuntimeCommandArgs = (runtime, mode) => [
2562
+ var getRuntimeCommandArgs = (runtime, mode, options = {}) => [
2549
2563
  ...runtime.nodeArgs ?? [],
2550
2564
  runtime.entrypoint,
2551
2565
  "daemon",
2552
2566
  "--internal-daemon",
2553
2567
  "--daemon-mode",
2554
2568
  mode,
2569
+ ...options.explicitEnrollment ? ["--explicit-enrollment"] : [],
2555
2570
  "--plain"
2556
2571
  ];
2557
2572
  var compareVersions = (left, right) => {
@@ -2578,9 +2593,9 @@ var waitForDaemon = async (launchConfig, deadline) => {
2578
2593
  lastConfig ? "Connector daemon did not expose its control channel in time" : "Connector registration did not create a canonical local identity in time"
2579
2594
  );
2580
2595
  };
2581
- var spawnInternalDaemon = async (launchConfig, mode, preparedRuntime) => {
2596
+ var spawnInternalDaemon = async (launchConfig, mode, preparedRuntime, options = {}) => {
2582
2597
  const runtime = preparedRuntime ?? await ensureStableConnectorRuntime();
2583
- const child = spawn(runtime.nodeExecutable, getRuntimeCommandArgs(runtime, mode), {
2598
+ const child = spawn(runtime.nodeExecutable, getRuntimeCommandArgs(runtime, mode, options), {
2584
2599
  detached: true,
2585
2600
  env: {
2586
2601
  ...process.env,
@@ -2603,7 +2618,7 @@ var stopOlderIdleDaemon = async (config, status) => {
2603
2618
  }
2604
2619
  throw new Error("Older Connector daemon did not stop cleanly; existing identity was preserved");
2605
2620
  };
2606
- async function ensureConnectorDaemon(launchConfig, mode) {
2621
+ async function ensureConnectorDaemon(launchConfig, mode, options = {}) {
2607
2622
  const deviceId = await getOrCreateSystemDeviceId(getConfigRoot());
2608
2623
  const scope = await resolveConnectorScope(deviceId, launchConfig);
2609
2624
  launchConfig = { ...launchConfig, spaceId: scope.spaceId };
@@ -2623,7 +2638,7 @@ async function ensureConnectorDaemon(launchConfig, mode) {
2623
2638
  const status = mode === "persistent" ? await requestDaemonControl(existingConfig, "persist", getConfigRoot()) : existingStatus;
2624
2639
  return { config: existingConfig, status };
2625
2640
  }
2626
- await spawnInternalDaemon(launchConfig, mode, preparedRuntime);
2641
+ await spawnInternalDaemon(launchConfig, mode, preparedRuntime, options);
2627
2642
  return await waitForDaemon(launchConfig, Date.now() + START_TIMEOUT_MS);
2628
2643
  }
2629
2644
  const persistedStatus = await readPersistedDaemonStatus(
@@ -2636,7 +2651,7 @@ async function ensureConnectorDaemon(launchConfig, mode) {
2636
2651
  );
2637
2652
  }
2638
2653
  }
2639
- await spawnInternalDaemon(launchConfig, mode);
2654
+ await spawnInternalDaemon(launchConfig, mode, void 0, options);
2640
2655
  return await waitForDaemon(launchConfig, Date.now() + START_TIMEOUT_MS);
2641
2656
  } finally {
2642
2657
  await bootstrapLock.release();
@@ -2780,7 +2795,9 @@ async function runConnectorDashboard(launchConfig, options = {}) {
2780
2795
  plain: options.plain
2781
2796
  });
2782
2797
  if (!dashboard) {
2783
- const { config } = await ensureConnectorDaemon(launchConfig, "persistent");
2798
+ const { config } = await ensureConnectorDaemon(launchConfig, "persistent", {
2799
+ explicitEnrollment: true
2800
+ });
2784
2801
  const stopLogs2 = streamDaemonLogs({
2785
2802
  connectorId: config.connectorId,
2786
2803
  dashboardActive: false,
@@ -2835,7 +2852,7 @@ async function runConnectorDashboard(launchConfig, options = {}) {
2835
2852
  preferredConnectorId = config.connectorId;
2836
2853
  }).catch(() => void 0).finally(() => refresh());
2837
2854
  const timer = setInterval(() => void refresh(), 1e3);
2838
- void ensureConnectorDaemon(launchConfig, "persistent").then(async ({ config }) => {
2855
+ void ensureConnectorDaemon(launchConfig, "persistent", { explicitEnrollment: true }).then(async ({ config }) => {
2839
2856
  pendingConnector = void 0;
2840
2857
  preferredConnectorId = config.connectorId;
2841
2858
  await refresh();
@@ -3003,13 +3020,12 @@ var createTerminalSession = async (grant, nodePtyLoader) => {
3003
3020
  try {
3004
3021
  nodePty = await nodePtyLoader();
3005
3022
  } catch (error) {
3023
+ const message = serializeErrorMessage(error);
3006
3024
  void writeLog(
3007
3025
  "error",
3008
3026
  `local terminal could not load node-pty: ${serializeErrorMessage(error)}`
3009
3027
  );
3010
- throw new LocalTerminalUnavailableError(
3011
- "Local terminal is unavailable because node-pty could not be loaded. The connector remains available for other capabilities."
3012
- );
3028
+ throw new LocalTerminalUnavailableError(message);
3013
3029
  }
3014
3030
  const shell = process.platform === "win32" ? "powershell.exe" : process.env.SHELL || "/bin/bash";
3015
3031
  const shellArgs = process.platform === "win32" ? [] : ["-l"];
@@ -3199,7 +3215,7 @@ var proxyConnectorTerminalTunnel = async (input) => {
3199
3215
  let bridgeAccepted = false;
3200
3216
  let activityStarted = false;
3201
3217
  let activityEnded = false;
3202
- let cloudCloseAfterOpen = null;
3218
+ let localCloseAfterBridge = null;
3203
3219
  let localCloseAfterOpen = null;
3204
3220
  const endActivity = () => {
3205
3221
  if (!activityStarted || activityEnded) return;
@@ -3224,7 +3240,9 @@ var proxyConnectorTerminalTunnel = async (input) => {
3224
3240
  if (!bridgeAccepted) {
3225
3241
  if (!isBinary && data.toString() === '{"type":"bridge-accepted"}') {
3226
3242
  bridgeAccepted = true;
3227
- local.send(JSON.stringify({ type: "bridge-start" }));
3243
+ if (local.readyState === WebSocket.OPEN) {
3244
+ local.send(JSON.stringify({ type: "bridge-start" }));
3245
+ }
3228
3246
  for (const [frame, binary] of pendingCloudFrames) {
3229
3247
  if (local.readyState === WebSocket.OPEN) local.send(frame, { binary });
3230
3248
  }
@@ -3234,6 +3252,9 @@ var proxyConnectorTerminalTunnel = async (input) => {
3234
3252
  pendingCloudFrames.length = 0;
3235
3253
  pendingLocalFrames.length = 0;
3236
3254
  pendingBytes = 0;
3255
+ if (localCloseAfterBridge && cloud.readyState === WebSocket.OPEN) {
3256
+ cloud.close(localCloseAfterBridge.code, localCloseAfterBridge.reason);
3257
+ }
3237
3258
  return;
3238
3259
  }
3239
3260
  bufferFrame(pendingCloudFrames, data, isBinary);
@@ -3270,15 +3291,10 @@ var proxyConnectorTerminalTunnel = async (input) => {
3270
3291
  code: normalizeTerminalCloseCode(code),
3271
3292
  reason: truncateTerminalCloseReason(reason.toString())
3272
3293
  };
3273
- if (cloud.readyState === WebSocket.OPEN) {
3294
+ if (!bridgeAccepted) {
3295
+ localCloseAfterBridge = normalizedClose;
3296
+ } else if (cloud.readyState === WebSocket.OPEN) {
3274
3297
  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
3298
  }
3283
3299
  });
3284
3300
  local.once("open", () => {
@@ -3295,9 +3311,11 @@ var proxyConnectorTerminalTunnel = async (input) => {
3295
3311
  local.terminate();
3296
3312
  throw error;
3297
3313
  }
3298
- if (cloud.readyState !== WebSocket.OPEN || local.readyState !== WebSocket.OPEN) return;
3299
- activityStarted = true;
3300
- input.onActivityStart?.();
3314
+ if (cloud.readyState !== WebSocket.OPEN) return;
3315
+ if (local.readyState === WebSocket.OPEN) {
3316
+ activityStarted = true;
3317
+ input.onActivityStart?.();
3318
+ }
3301
3319
  cloud.send(JSON.stringify({ type: "bridge-ready" }));
3302
3320
  await writeLog(
3303
3321
  "info",
@@ -5421,9 +5439,7 @@ async function runOnboard(launchConfig, options = {}) {
5421
5439
  await migrateLegacyWorkspaceRoot(config2.workdirRoot);
5422
5440
  await provisionWorkdirLayout(config2.workdirRoot);
5423
5441
  try {
5424
- const registration = await registerConnector(config2, launchConfig, void 0, {
5425
- recoverMissingProfile: false
5426
- });
5442
+ const registration = await registerConnectorForExplicitEnrollment(config2, launchConfig);
5427
5443
  config2.connectorId = registration.connectorId;
5428
5444
  config2.spaceId = registration.spaceId ?? config2.spaceId;
5429
5445
  relayProtocol = registration.relayProtocol;
@@ -5455,7 +5471,16 @@ async function runOnboard(launchConfig, options = {}) {
5455
5471
  if (!existing) {
5456
5472
  } else {
5457
5473
  try {
5458
- relayProtocol = (await registerConnector(config, launchConfig, bunnyDaemon)).relayProtocol;
5474
+ const registration = await registerConnectorForExplicitEnrollment(
5475
+ config,
5476
+ launchConfig,
5477
+ bunnyDaemon
5478
+ );
5479
+ config.connectorId = registration.connectorId;
5480
+ config.spaceId = registration.spaceId ?? config.spaceId;
5481
+ if (!config.spaceId) throw new Error("Registration did not resolve a Space");
5482
+ relayProtocol = registration.relayProtocol;
5483
+ await writeDeviceConfig(config);
5459
5484
  } catch (error) {
5460
5485
  await stopEmbeddedBunnyDaemon(bunnyDaemon);
5461
5486
  s.stop("Failed to register");
@@ -5543,15 +5568,12 @@ async function stopRecoveredIdleDaemon(config, configRoot) {
5543
5568
  throw new Error(`Recovered Connector ${config.connectorId} did not stop cleanly.`);
5544
5569
  }
5545
5570
  async function runNewConnector(launchConfig) {
5546
- const existing = await readDeviceConfig(launchConfig);
5547
5571
  const config = await ensureDeviceConfig(launchConfig);
5548
5572
  const paths = getConnectorPaths(config.serverUrl);
5549
5573
  await migrateLegacyWorkspaceRoot(config.workdirRoot);
5550
5574
  await provisionWorkdirLayout(config.workdirRoot);
5551
5575
  await LocalWorkspaceRegistry.open(config.workdirRoot);
5552
- const registration = await registerConnector(config, launchConfig, void 0, {
5553
- recoverMissingProfile: shouldRecoverMissingProfile(Boolean(existing), launchConfig)
5554
- });
5576
+ const registration = await registerConnectorForExplicitEnrollment(config, launchConfig);
5555
5577
  config.connectorId = registration.connectorId;
5556
5578
  config.spaceId = registration.spaceId ?? config.spaceId;
5557
5579
  await writeDeviceConfig(config);
@@ -5592,9 +5614,7 @@ async function runConnectorDaemon(launchConfig, options = {}) {
5592
5614
  const workspaceRegistry = await LocalWorkspaceRegistry.open(config.workdirRoot);
5593
5615
  bunnyDaemon = await startEmbeddedBunnyDaemon(config, launchConfig);
5594
5616
  const activeBunnyDaemon = bunnyDaemon;
5595
- const registration = await registerConnector(config, launchConfig, activeBunnyDaemon, {
5596
- recoverMissingProfile: shouldRecoverMissingProfile(Boolean(existing), launchConfig)
5597
- });
5617
+ const registration = options.explicitEnrollment ? await registerConnectorForExplicitEnrollment(config, launchConfig, activeBunnyDaemon) : await registerConnector(config, launchConfig, activeBunnyDaemon);
5598
5618
  const connectorIdChanged = config.connectorId !== registration.connectorId;
5599
5619
  if (connectorIdChanged) {
5600
5620
  const registeredConfig = {
@@ -5703,7 +5723,6 @@ async function runConnectorDaemon(launchConfig, options = {}) {
5703
5723
  throw error;
5704
5724
  }
5705
5725
  }
5706
- var shouldRecoverMissingProfile = (hasExistingProfile, launchConfig) => !hasExistingProfile && Boolean(getConnectorToken(launchConfig)) && !launchConfig?.oauthToken?.trim();
5707
5726
 
5708
5727
  // src/cli.ts
5709
5728
  function printHelp() {
@@ -5795,6 +5814,7 @@ async function main() {
5795
5814
  if (command === "daemon" && process.argv.includes("--internal-daemon")) {
5796
5815
  await runConnectorDaemon(launchConfig, {
5797
5816
  captureConsole: true,
5817
+ explicitEnrollment: process.argv.includes("--explicit-enrollment"),
5798
5818
  mode: getDaemonModeFlag(),
5799
5819
  version: CONNECTOR_RUNTIME_VERSION
5800
5820
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buda-ai/connector",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "publishConfig": {