@autohq/cli 0.1.400 → 0.1.402

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.402",
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.402",
35076
35076
  license: "SEE LICENSE IN README.md",
35077
35077
  publishConfig: {
35078
35078
  access: "public"
@@ -36814,6 +36814,10 @@ var init_agent_fields = __esm({
36814
36814
  replace: specField(),
36815
36815
  onReplace: fileBackedStringField(),
36816
36816
  manages: specField(),
36817
+ // Per-target binding constraints (lifecycle / continuity / bind axes).
36818
+ // Spec scalar so the map deep-merges across imports (variants inherit
36819
+ // staff-engineer declarations unless they override a target entry).
36820
+ bindings: specField(),
36817
36821
  workingDirectory: specField(),
36818
36822
  tools: namedMapField()
36819
36823
  };
@@ -45523,6 +45527,7 @@ var AgentBridgeOutputAckTimeoutError = class extends Error {
45523
45527
  this.name = "AgentBridgeOutputAckTimeoutError";
45524
45528
  }
45525
45529
  };
45530
+ var AGENT_BRIDGE_TERMINAL_AUTH_DRAIN_TIMEOUT_MS = 6e4;
45526
45531
  async function runAgentBridgeSocket(options) {
45527
45532
  const socket = io(`${options.bridgeUrl}${RUNTIME_BRIDGE_NAMESPACE}`, {
45528
45533
  auth: {
@@ -45534,6 +45539,13 @@ async function runAgentBridgeSocket(options) {
45534
45539
  });
45535
45540
  let handler = null;
45536
45541
  const reconnectLoop = createReconnectLoop(socket);
45542
+ const terminalAuthDrain = createTerminalAuthDrainController({
45543
+ socket,
45544
+ token: options.token,
45545
+ getHandler: () => handler,
45546
+ writeOutput: options.writeOutput,
45547
+ runtimeLogger: options.runtimeLogger
45548
+ });
45537
45549
  let hasConnected = false;
45538
45550
  await new Promise((resolve4, reject) => {
45539
45551
  const shutdown = () => {
@@ -45545,15 +45557,23 @@ async function runAgentBridgeSocket(options) {
45545
45557
  process.once("SIGINT", shutdown);
45546
45558
  process.once("SIGTERM", shutdown);
45547
45559
  socket.on("connect_error", (error51) => {
45560
+ if (terminalAuthDrain.handleConnectError(error51)) {
45561
+ return;
45562
+ }
45548
45563
  if (!hasConnected) {
45549
45564
  reject(error51);
45550
45565
  return;
45551
45566
  }
45552
45567
  if (isTerminalAuthError(error51)) {
45553
45568
  reconnectLoop.stop();
45554
- handler?.shutdown?.();
45555
- socket.disconnect();
45556
- reject(new AgentBridgeTerminalAuthError(error51.message));
45569
+ void terminalAuthDrain.begin().catch((drainError) => {
45570
+ options.writeOutput?.(
45571
+ `agent_bridge_terminal_auth_drain_failed error=${errorMessage(drainError)}`
45572
+ );
45573
+ }).finally(() => {
45574
+ socket.disconnect();
45575
+ reject(new AgentBridgeTerminalAuthError(error51.message));
45576
+ });
45557
45577
  return;
45558
45578
  }
45559
45579
  options.writeOutput?.(
@@ -45566,6 +45586,9 @@ async function runAgentBridgeSocket(options) {
45566
45586
  return;
45567
45587
  }
45568
45588
  options.writeOutput?.(`agent_bridge_disconnected reason=${reason}`);
45589
+ if (terminalAuthDrain.suppressesReconnect()) {
45590
+ return;
45591
+ }
45569
45592
  reconnectLoop.start();
45570
45593
  });
45571
45594
  socket.on(
@@ -45604,6 +45627,9 @@ async function runAgentBridgeSocket(options) {
45604
45627
  })
45605
45628
  );
45606
45629
  socket.on(RUNTIME_BRIDGE_CONNECTED_EVENT, (rawContext) => {
45630
+ if (terminalAuthDrain.handleConnected(rawContext)) {
45631
+ return;
45632
+ }
45607
45633
  const context = RuntimeBridgeConnectedPayloadSchema.parse(rawContext);
45608
45634
  if (!handler) {
45609
45635
  reject(new Error("Bridge connected before bootstrap completed"));
@@ -45848,6 +45874,113 @@ function createReconnectLoop(socket) {
45848
45874
  };
45849
45875
  return { start, stop };
45850
45876
  }
45877
+ function createTerminalAuthDrainController(input) {
45878
+ let terminalAuthExit = false;
45879
+ let state = null;
45880
+ const settle = (callback) => {
45881
+ const current = state;
45882
+ if (!current) {
45883
+ return;
45884
+ }
45885
+ clearTimeout(current.timeout);
45886
+ state = null;
45887
+ callback();
45888
+ };
45889
+ const begin = () => {
45890
+ terminalAuthExit = true;
45891
+ if (state) {
45892
+ return state.promise;
45893
+ }
45894
+ const handler = input.getHandler();
45895
+ handler?.shutdown?.();
45896
+ if (!handler) {
45897
+ input.writeOutput?.(
45898
+ "agent_bridge_terminal_auth_drain_skipped reason=no_handler"
45899
+ );
45900
+ return Promise.resolve();
45901
+ }
45902
+ const startedAt = Date.now();
45903
+ let resolveDrain = () => {
45904
+ };
45905
+ let rejectDrain = () => {
45906
+ };
45907
+ const promise2 = new Promise((resolve4, reject) => {
45908
+ resolveDrain = resolve4;
45909
+ rejectDrain = reject;
45910
+ });
45911
+ const timeout = setTimeout(() => {
45912
+ settle(() => {
45913
+ rejectDrain(
45914
+ new Error(
45915
+ `Timed out draining pending bridge output after terminal auth in ${AGENT_BRIDGE_TERMINAL_AUTH_DRAIN_TIMEOUT_MS}ms`
45916
+ )
45917
+ );
45918
+ });
45919
+ }, AGENT_BRIDGE_TERMINAL_AUTH_DRAIN_TIMEOUT_MS);
45920
+ timeout.unref?.();
45921
+ state = {
45922
+ promise: promise2,
45923
+ reject: rejectDrain,
45924
+ resolve: resolveDrain,
45925
+ startedAt,
45926
+ timeout
45927
+ };
45928
+ input.writeOutput?.("agent_bridge_terminal_auth_drain_started");
45929
+ input.runtimeLogger?.warn("agent_bridge_terminal_auth_drain_started");
45930
+ input.socket.auth = { token: input.token, terminalDrain: true };
45931
+ input.socket.connect();
45932
+ return promise2;
45933
+ };
45934
+ const handleConnected = (rawContext) => {
45935
+ const current = state;
45936
+ if (!current) {
45937
+ return false;
45938
+ }
45939
+ void (async () => {
45940
+ const context = RuntimeBridgeConnectedPayloadSchema.parse(rawContext);
45941
+ input.writeOutput?.(
45942
+ `agent_bridge_terminal_auth_drain_connected session_id=${context.sessionId} runtime_id=${context.runtimeId} bridge_lease_id=${context.bridgeLeaseId}`
45943
+ );
45944
+ input.runtimeLogger?.warn("agent_bridge_terminal_auth_drain_connected", {
45945
+ session_id: context.sessionId,
45946
+ runtime_id: context.runtimeId,
45947
+ bridge_lease_id: context.bridgeLeaseId
45948
+ });
45949
+ const handler = input.getHandler();
45950
+ if (!handler) {
45951
+ throw new Error("Terminal auth drain connected without a handler");
45952
+ }
45953
+ await handler.replayPendingOutputs();
45954
+ settle(() => {
45955
+ input.writeOutput?.(
45956
+ `agent_bridge_terminal_auth_drain_completed duration_ms=${Date.now() - current.startedAt}`
45957
+ );
45958
+ input.runtimeLogger?.warn(
45959
+ "agent_bridge_terminal_auth_drain_completed",
45960
+ { duration_ms: Date.now() - current.startedAt }
45961
+ );
45962
+ current.resolve();
45963
+ });
45964
+ })().catch((error51) => {
45965
+ settle(() => current.reject(error51));
45966
+ });
45967
+ return true;
45968
+ };
45969
+ const handleConnectError = (error51) => {
45970
+ const current = state;
45971
+ if (!current) {
45972
+ return false;
45973
+ }
45974
+ settle(() => current.reject(error51));
45975
+ return true;
45976
+ };
45977
+ return {
45978
+ begin,
45979
+ handleConnected,
45980
+ handleConnectError,
45981
+ suppressesReconnect: () => terminalAuthExit || state !== null
45982
+ };
45983
+ }
45851
45984
  function bridgeForwardingHeaders(url2) {
45852
45985
  if (!isNgrokFreeUrl(url2)) {
45853
45986
  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.402",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"