@autohq/cli 0.1.400 → 0.1.401

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.
@@ -30819,7 +30819,7 @@ Object.assign(lookup, {
30819
30819
  // package.json
30820
30820
  var package_default = {
30821
30821
  name: "@autohq/cli",
30822
- version: "0.1.400",
30822
+ version: "0.1.401",
30823
30823
  license: "SEE LICENSE IN README.md",
30824
30824
  publishConfig: {
30825
30825
  access: "public"
@@ -30912,6 +30912,7 @@ var AgentBridgeOutputAckTimeoutError = class extends Error {
30912
30912
  this.name = "AgentBridgeOutputAckTimeoutError";
30913
30913
  }
30914
30914
  };
30915
+ var AGENT_BRIDGE_TERMINAL_AUTH_DRAIN_TIMEOUT_MS = 6e4;
30915
30916
  async function runAgentBridgeSocket(options) {
30916
30917
  const socket = lookup(`${options.bridgeUrl}${RUNTIME_BRIDGE_NAMESPACE}`, {
30917
30918
  auth: {
@@ -30923,6 +30924,13 @@ async function runAgentBridgeSocket(options) {
30923
30924
  });
30924
30925
  let handler = null;
30925
30926
  const reconnectLoop = createReconnectLoop(socket);
30927
+ const terminalAuthDrain = createTerminalAuthDrainController({
30928
+ socket,
30929
+ token: options.token,
30930
+ getHandler: () => handler,
30931
+ writeOutput: options.writeOutput,
30932
+ runtimeLogger: options.runtimeLogger
30933
+ });
30926
30934
  let hasConnected = false;
30927
30935
  await new Promise((resolve2, reject) => {
30928
30936
  const shutdown = () => {
@@ -30934,15 +30942,23 @@ async function runAgentBridgeSocket(options) {
30934
30942
  process.once("SIGINT", shutdown);
30935
30943
  process.once("SIGTERM", shutdown);
30936
30944
  socket.on("connect_error", (error51) => {
30945
+ if (terminalAuthDrain.handleConnectError(error51)) {
30946
+ return;
30947
+ }
30937
30948
  if (!hasConnected) {
30938
30949
  reject(error51);
30939
30950
  return;
30940
30951
  }
30941
30952
  if (isTerminalAuthError(error51)) {
30942
30953
  reconnectLoop.stop();
30943
- handler?.shutdown?.();
30944
- socket.disconnect();
30945
- reject(new AgentBridgeTerminalAuthError(error51.message));
30954
+ void terminalAuthDrain.begin().catch((drainError) => {
30955
+ options.writeOutput?.(
30956
+ `agent_bridge_terminal_auth_drain_failed error=${errorMessage(drainError)}`
30957
+ );
30958
+ }).finally(() => {
30959
+ socket.disconnect();
30960
+ reject(new AgentBridgeTerminalAuthError(error51.message));
30961
+ });
30946
30962
  return;
30947
30963
  }
30948
30964
  options.writeOutput?.(
@@ -30955,6 +30971,9 @@ async function runAgentBridgeSocket(options) {
30955
30971
  return;
30956
30972
  }
30957
30973
  options.writeOutput?.(`agent_bridge_disconnected reason=${reason}`);
30974
+ if (terminalAuthDrain.suppressesReconnect()) {
30975
+ return;
30976
+ }
30958
30977
  reconnectLoop.start();
30959
30978
  });
30960
30979
  socket.on(
@@ -30993,6 +31012,9 @@ async function runAgentBridgeSocket(options) {
30993
31012
  })
30994
31013
  );
30995
31014
  socket.on(RUNTIME_BRIDGE_CONNECTED_EVENT, (rawContext) => {
31015
+ if (terminalAuthDrain.handleConnected(rawContext)) {
31016
+ return;
31017
+ }
30996
31018
  const context = RuntimeBridgeConnectedPayloadSchema.parse(rawContext);
30997
31019
  if (!handler) {
30998
31020
  reject(new Error("Bridge connected before bootstrap completed"));
@@ -31237,6 +31259,113 @@ function createReconnectLoop(socket) {
31237
31259
  };
31238
31260
  return { start, stop };
31239
31261
  }
31262
+ function createTerminalAuthDrainController(input) {
31263
+ let terminalAuthExit = false;
31264
+ let state = null;
31265
+ const settle = (callback) => {
31266
+ const current = state;
31267
+ if (!current) {
31268
+ return;
31269
+ }
31270
+ clearTimeout(current.timeout);
31271
+ state = null;
31272
+ callback();
31273
+ };
31274
+ const begin = () => {
31275
+ terminalAuthExit = true;
31276
+ if (state) {
31277
+ return state.promise;
31278
+ }
31279
+ const handler = input.getHandler();
31280
+ handler?.shutdown?.();
31281
+ if (!handler) {
31282
+ input.writeOutput?.(
31283
+ "agent_bridge_terminal_auth_drain_skipped reason=no_handler"
31284
+ );
31285
+ return Promise.resolve();
31286
+ }
31287
+ const startedAt = Date.now();
31288
+ let resolveDrain = () => {
31289
+ };
31290
+ let rejectDrain = () => {
31291
+ };
31292
+ const promise2 = new Promise((resolve2, reject) => {
31293
+ resolveDrain = resolve2;
31294
+ rejectDrain = reject;
31295
+ });
31296
+ const timeout = setTimeout(() => {
31297
+ settle(() => {
31298
+ rejectDrain(
31299
+ new Error(
31300
+ `Timed out draining pending bridge output after terminal auth in ${AGENT_BRIDGE_TERMINAL_AUTH_DRAIN_TIMEOUT_MS}ms`
31301
+ )
31302
+ );
31303
+ });
31304
+ }, AGENT_BRIDGE_TERMINAL_AUTH_DRAIN_TIMEOUT_MS);
31305
+ timeout.unref?.();
31306
+ state = {
31307
+ promise: promise2,
31308
+ reject: rejectDrain,
31309
+ resolve: resolveDrain,
31310
+ startedAt,
31311
+ timeout
31312
+ };
31313
+ input.writeOutput?.("agent_bridge_terminal_auth_drain_started");
31314
+ input.runtimeLogger?.warn("agent_bridge_terminal_auth_drain_started");
31315
+ input.socket.auth = { token: input.token, terminalDrain: true };
31316
+ input.socket.connect();
31317
+ return promise2;
31318
+ };
31319
+ const handleConnected = (rawContext) => {
31320
+ const current = state;
31321
+ if (!current) {
31322
+ return false;
31323
+ }
31324
+ void (async () => {
31325
+ const context = RuntimeBridgeConnectedPayloadSchema.parse(rawContext);
31326
+ input.writeOutput?.(
31327
+ `agent_bridge_terminal_auth_drain_connected session_id=${context.sessionId} runtime_id=${context.runtimeId} bridge_lease_id=${context.bridgeLeaseId}`
31328
+ );
31329
+ input.runtimeLogger?.warn("agent_bridge_terminal_auth_drain_connected", {
31330
+ session_id: context.sessionId,
31331
+ runtime_id: context.runtimeId,
31332
+ bridge_lease_id: context.bridgeLeaseId
31333
+ });
31334
+ const handler = input.getHandler();
31335
+ if (!handler) {
31336
+ throw new Error("Terminal auth drain connected without a handler");
31337
+ }
31338
+ await handler.replayPendingOutputs();
31339
+ settle(() => {
31340
+ input.writeOutput?.(
31341
+ `agent_bridge_terminal_auth_drain_completed duration_ms=${Date.now() - current.startedAt}`
31342
+ );
31343
+ input.runtimeLogger?.warn(
31344
+ "agent_bridge_terminal_auth_drain_completed",
31345
+ { duration_ms: Date.now() - current.startedAt }
31346
+ );
31347
+ current.resolve();
31348
+ });
31349
+ })().catch((error51) => {
31350
+ settle(() => current.reject(error51));
31351
+ });
31352
+ return true;
31353
+ };
31354
+ const handleConnectError = (error51) => {
31355
+ const current = state;
31356
+ if (!current) {
31357
+ return false;
31358
+ }
31359
+ settle(() => current.reject(error51));
31360
+ return true;
31361
+ };
31362
+ return {
31363
+ begin,
31364
+ handleConnected,
31365
+ handleConnectError,
31366
+ suppressesReconnect: () => terminalAuthExit || state !== null
31367
+ };
31368
+ }
31240
31369
  function bridgeForwardingHeaders(url3) {
31241
31370
  if (!isNgrokFreeUrl(url3)) {
31242
31371
  return {};
package/dist/index.js CHANGED
@@ -35072,7 +35072,7 @@ var init_package = __esm({
35072
35072
  "package.json"() {
35073
35073
  package_default = {
35074
35074
  name: "@autohq/cli",
35075
- version: "0.1.400",
35075
+ version: "0.1.401",
35076
35076
  license: "SEE LICENSE IN README.md",
35077
35077
  publishConfig: {
35078
35078
  access: "public"
@@ -45523,6 +45523,7 @@ var AgentBridgeOutputAckTimeoutError = class extends Error {
45523
45523
  this.name = "AgentBridgeOutputAckTimeoutError";
45524
45524
  }
45525
45525
  };
45526
+ var AGENT_BRIDGE_TERMINAL_AUTH_DRAIN_TIMEOUT_MS = 6e4;
45526
45527
  async function runAgentBridgeSocket(options) {
45527
45528
  const socket = io(`${options.bridgeUrl}${RUNTIME_BRIDGE_NAMESPACE}`, {
45528
45529
  auth: {
@@ -45534,6 +45535,13 @@ async function runAgentBridgeSocket(options) {
45534
45535
  });
45535
45536
  let handler = null;
45536
45537
  const reconnectLoop = createReconnectLoop(socket);
45538
+ const terminalAuthDrain = createTerminalAuthDrainController({
45539
+ socket,
45540
+ token: options.token,
45541
+ getHandler: () => handler,
45542
+ writeOutput: options.writeOutput,
45543
+ runtimeLogger: options.runtimeLogger
45544
+ });
45537
45545
  let hasConnected = false;
45538
45546
  await new Promise((resolve4, reject) => {
45539
45547
  const shutdown = () => {
@@ -45545,15 +45553,23 @@ async function runAgentBridgeSocket(options) {
45545
45553
  process.once("SIGINT", shutdown);
45546
45554
  process.once("SIGTERM", shutdown);
45547
45555
  socket.on("connect_error", (error51) => {
45556
+ if (terminalAuthDrain.handleConnectError(error51)) {
45557
+ return;
45558
+ }
45548
45559
  if (!hasConnected) {
45549
45560
  reject(error51);
45550
45561
  return;
45551
45562
  }
45552
45563
  if (isTerminalAuthError(error51)) {
45553
45564
  reconnectLoop.stop();
45554
- handler?.shutdown?.();
45555
- socket.disconnect();
45556
- reject(new AgentBridgeTerminalAuthError(error51.message));
45565
+ void terminalAuthDrain.begin().catch((drainError) => {
45566
+ options.writeOutput?.(
45567
+ `agent_bridge_terminal_auth_drain_failed error=${errorMessage(drainError)}`
45568
+ );
45569
+ }).finally(() => {
45570
+ socket.disconnect();
45571
+ reject(new AgentBridgeTerminalAuthError(error51.message));
45572
+ });
45557
45573
  return;
45558
45574
  }
45559
45575
  options.writeOutput?.(
@@ -45566,6 +45582,9 @@ async function runAgentBridgeSocket(options) {
45566
45582
  return;
45567
45583
  }
45568
45584
  options.writeOutput?.(`agent_bridge_disconnected reason=${reason}`);
45585
+ if (terminalAuthDrain.suppressesReconnect()) {
45586
+ return;
45587
+ }
45569
45588
  reconnectLoop.start();
45570
45589
  });
45571
45590
  socket.on(
@@ -45604,6 +45623,9 @@ async function runAgentBridgeSocket(options) {
45604
45623
  })
45605
45624
  );
45606
45625
  socket.on(RUNTIME_BRIDGE_CONNECTED_EVENT, (rawContext) => {
45626
+ if (terminalAuthDrain.handleConnected(rawContext)) {
45627
+ return;
45628
+ }
45607
45629
  const context = RuntimeBridgeConnectedPayloadSchema.parse(rawContext);
45608
45630
  if (!handler) {
45609
45631
  reject(new Error("Bridge connected before bootstrap completed"));
@@ -45848,6 +45870,113 @@ function createReconnectLoop(socket) {
45848
45870
  };
45849
45871
  return { start, stop };
45850
45872
  }
45873
+ function createTerminalAuthDrainController(input) {
45874
+ let terminalAuthExit = false;
45875
+ let state = null;
45876
+ const settle = (callback) => {
45877
+ const current = state;
45878
+ if (!current) {
45879
+ return;
45880
+ }
45881
+ clearTimeout(current.timeout);
45882
+ state = null;
45883
+ callback();
45884
+ };
45885
+ const begin = () => {
45886
+ terminalAuthExit = true;
45887
+ if (state) {
45888
+ return state.promise;
45889
+ }
45890
+ const handler = input.getHandler();
45891
+ handler?.shutdown?.();
45892
+ if (!handler) {
45893
+ input.writeOutput?.(
45894
+ "agent_bridge_terminal_auth_drain_skipped reason=no_handler"
45895
+ );
45896
+ return Promise.resolve();
45897
+ }
45898
+ const startedAt = Date.now();
45899
+ let resolveDrain = () => {
45900
+ };
45901
+ let rejectDrain = () => {
45902
+ };
45903
+ const promise2 = new Promise((resolve4, reject) => {
45904
+ resolveDrain = resolve4;
45905
+ rejectDrain = reject;
45906
+ });
45907
+ const timeout = setTimeout(() => {
45908
+ settle(() => {
45909
+ rejectDrain(
45910
+ new Error(
45911
+ `Timed out draining pending bridge output after terminal auth in ${AGENT_BRIDGE_TERMINAL_AUTH_DRAIN_TIMEOUT_MS}ms`
45912
+ )
45913
+ );
45914
+ });
45915
+ }, AGENT_BRIDGE_TERMINAL_AUTH_DRAIN_TIMEOUT_MS);
45916
+ timeout.unref?.();
45917
+ state = {
45918
+ promise: promise2,
45919
+ reject: rejectDrain,
45920
+ resolve: resolveDrain,
45921
+ startedAt,
45922
+ timeout
45923
+ };
45924
+ input.writeOutput?.("agent_bridge_terminal_auth_drain_started");
45925
+ input.runtimeLogger?.warn("agent_bridge_terminal_auth_drain_started");
45926
+ input.socket.auth = { token: input.token, terminalDrain: true };
45927
+ input.socket.connect();
45928
+ return promise2;
45929
+ };
45930
+ const handleConnected = (rawContext) => {
45931
+ const current = state;
45932
+ if (!current) {
45933
+ return false;
45934
+ }
45935
+ void (async () => {
45936
+ const context = RuntimeBridgeConnectedPayloadSchema.parse(rawContext);
45937
+ input.writeOutput?.(
45938
+ `agent_bridge_terminal_auth_drain_connected session_id=${context.sessionId} runtime_id=${context.runtimeId} bridge_lease_id=${context.bridgeLeaseId}`
45939
+ );
45940
+ input.runtimeLogger?.warn("agent_bridge_terminal_auth_drain_connected", {
45941
+ session_id: context.sessionId,
45942
+ runtime_id: context.runtimeId,
45943
+ bridge_lease_id: context.bridgeLeaseId
45944
+ });
45945
+ const handler = input.getHandler();
45946
+ if (!handler) {
45947
+ throw new Error("Terminal auth drain connected without a handler");
45948
+ }
45949
+ await handler.replayPendingOutputs();
45950
+ settle(() => {
45951
+ input.writeOutput?.(
45952
+ `agent_bridge_terminal_auth_drain_completed duration_ms=${Date.now() - current.startedAt}`
45953
+ );
45954
+ input.runtimeLogger?.warn(
45955
+ "agent_bridge_terminal_auth_drain_completed",
45956
+ { duration_ms: Date.now() - current.startedAt }
45957
+ );
45958
+ current.resolve();
45959
+ });
45960
+ })().catch((error51) => {
45961
+ settle(() => current.reject(error51));
45962
+ });
45963
+ return true;
45964
+ };
45965
+ const handleConnectError = (error51) => {
45966
+ const current = state;
45967
+ if (!current) {
45968
+ return false;
45969
+ }
45970
+ settle(() => current.reject(error51));
45971
+ return true;
45972
+ };
45973
+ return {
45974
+ begin,
45975
+ handleConnected,
45976
+ handleConnectError,
45977
+ suppressesReconnect: () => terminalAuthExit || state !== null
45978
+ };
45979
+ }
45851
45980
  function bridgeForwardingHeaders(url2) {
45852
45981
  if (!isNgrokFreeUrl(url2)) {
45853
45982
  return {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.400",
3
+ "version": "0.1.401",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"