@autohq/cli 0.1.342 → 0.1.343

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.
@@ -19833,12 +19833,24 @@ var RuntimeBridgeOutputUiMessageCompletedEnvelopeSchema = external_exports.objec
19833
19833
  createdAt: external_exports.string().datetime(),
19834
19834
  completedAt: external_exports.string().datetime().nullable()
19835
19835
  });
19836
+ var RuntimeBridgeOutputLivenessEnvelopeSchema = external_exports.object({
19837
+ type: external_exports.literal("runtime.liveness"),
19838
+ sessionId: SessionIdSchema,
19839
+ runtimeId: RuntimeIdSchema,
19840
+ bridgeLeaseId: RuntimeBridgeLeaseIdSchema,
19841
+ outputSeq: external_exports.number().int().positive(),
19842
+ // The emitter's beat cadence, so watchdog thresholds stay interpretable
19843
+ // against the runtime that produced them.
19844
+ intervalMs: external_exports.number().int().positive(),
19845
+ createdAt: external_exports.string().datetime()
19846
+ });
19836
19847
  var RuntimeBridgeOutputEnvelopeSchema = external_exports.union([
19837
19848
  RuntimeBridgeOutputEntryEnvelopeSchema,
19838
19849
  RuntimeBridgeOutputDeltaEnvelopeSchema,
19839
19850
  RuntimeBridgeOutputUiMessageChunkEnvelopeSchema,
19840
19851
  RuntimeBridgeOutputUiMessagePartEnvelopeSchema,
19841
- RuntimeBridgeOutputUiMessageCompletedEnvelopeSchema
19852
+ RuntimeBridgeOutputUiMessageCompletedEnvelopeSchema,
19853
+ RuntimeBridgeOutputLivenessEnvelopeSchema
19842
19854
  ]);
19843
19855
  function isLiveOnlyRuntimeOutputEnvelope(envelope) {
19844
19856
  return envelope.type === "ui.message.chunk" || envelope.type === "conversation.delta";
@@ -23480,7 +23492,7 @@ Object.assign(lookup, {
23480
23492
  // package.json
23481
23493
  var package_default = {
23482
23494
  name: "@autohq/cli",
23483
- version: "0.1.342",
23495
+ version: "0.1.343",
23484
23496
  license: "SEE LICENSE IN README.md",
23485
23497
  publishConfig: {
23486
23498
  access: "public"
@@ -28506,6 +28518,10 @@ var SessionTurnRecordSchema = external_exports.object({
28506
28518
  acceptedAt: external_exports.string().datetime().nullable(),
28507
28519
  startedAt: external_exports.string().datetime().nullable(),
28508
28520
  lastProgressAt: external_exports.string().datetime().nullable(),
28521
+ // Last runtime liveness beat that vouched for this open turn (null before
28522
+ // the first beat, and always null on runtimes that predate liveness).
28523
+ // Distinct from lastProgressAt: pipeline liveness, not durable progress.
28524
+ livenessAt: external_exports.string().datetime().nullable().default(null),
28509
28525
  completedAt: external_exports.string().datetime().nullable(),
28510
28526
  failedAt: external_exports.string().datetime().nullable(),
28511
28527
  staleAt: external_exports.string().datetime().nullable(),
@@ -35863,6 +35879,23 @@ var ProjectUsageResponseSchema = external_exports.object({
35863
35879
  daily: external_exports.array(ProjectUsageDayPointSchema)
35864
35880
  });
35865
35881
 
35882
+ // src/commands/agent-bridge/harness/liveness-ticker.ts
35883
+ var RUNTIME_LIVENESS_INTERVAL_MS = 2e4;
35884
+ function startRuntimeLivenessTicker(input) {
35885
+ const intervalMs = input.intervalMs ?? RUNTIME_LIVENESS_INTERVAL_MS;
35886
+ const timer = setInterval(() => {
35887
+ void input.emitBeat().catch((error51) => {
35888
+ input.writeOutput?.(
35889
+ `agent_bridge_liveness_beat_failed error=${error51 instanceof Error ? error51.message : String(error51)}`
35890
+ );
35891
+ });
35892
+ }, intervalMs);
35893
+ timer.unref?.();
35894
+ return {
35895
+ stop: () => clearInterval(timer)
35896
+ };
35897
+ }
35898
+
35866
35899
  // src/commands/agent-bridge/harness/output-buffer.ts
35867
35900
  import { setTimeout as sleep } from "timers/promises";
35868
35901
 
@@ -44514,6 +44547,9 @@ var AgentBridgeOutputBuffer = class {
44514
44547
  uiMessagePartTracker = new UiMessagePartTracker();
44515
44548
  drainBlocked = false;
44516
44549
  drainPromise = null;
44550
+ // Sequence of the most recent liveness beat, for the skip-while-pending
44551
+ // gate in emitLivenessBeat.
44552
+ pendingLivenessSeq = null;
44517
44553
  // Ack-retry-ladder exhausts per pending output sequence, for the poison
44518
44554
  // quarantine; entries clear when the sequence finally acks.
44519
44555
  ackExhaustsBySeq = /* @__PURE__ */ new Map();
@@ -44544,6 +44580,29 @@ var AgentBridgeOutputBuffer = class {
44544
44580
  await this.flushPendingDelta({ force: true });
44545
44581
  await this.drainPendingOutputs({ force: true });
44546
44582
  }
44583
+ // Emits one runtime liveness beat through the same ordered, acked drain as
44584
+ // content envelopes — deliberately, so a beat landing at the bridge proves
44585
+ // the pipeline is healthy end to end. While a previous beat is still
44586
+ // pending (stalled drain, retry ladder, reconnect) new beats are skipped
44587
+ // rather than queued: an unhealthy pipeline must show up as beats
44588
+ // *stopping*, and a backlog of parked beats replaying after recovery would
44589
+ // stamp liveness for exactly the window the runtime was mute.
44590
+ async emitLivenessBeat(context, intervalMs) {
44591
+ if (this.pendingLivenessSeq !== null && this.pendingOutputs.has(this.pendingLivenessSeq)) {
44592
+ return;
44593
+ }
44594
+ this.outputSeq += 1;
44595
+ this.pendingLivenessSeq = this.outputSeq;
44596
+ this.enqueueOutput(
44597
+ buildLivenessOutputEnvelope({
44598
+ context,
44599
+ outputSeq: this.outputSeq,
44600
+ intervalMs,
44601
+ createdAt: now2()
44602
+ })
44603
+ );
44604
+ await this.drainPendingOutputs();
44605
+ }
44547
44606
  async emitUiMessageChunk(context, projection) {
44548
44607
  await this.flushPendingDelta();
44549
44608
  await this.emitLiveUiMessageChunk(context, projection.chunk);
@@ -45240,6 +45299,18 @@ function buildUiMessageChunkOutputEnvelope(input) {
45240
45299
  createdAt: input.createdAt
45241
45300
  });
45242
45301
  }
45302
+ function buildLivenessOutputEnvelope(input) {
45303
+ const { context } = input;
45304
+ return RuntimeBridgeOutputEnvelopeSchema.parse({
45305
+ type: "runtime.liveness",
45306
+ sessionId: context.sessionId,
45307
+ runtimeId: context.runtimeId,
45308
+ bridgeLeaseId: context.bridgeLeaseId,
45309
+ outputSeq: input.outputSeq,
45310
+ intervalMs: input.intervalMs,
45311
+ createdAt: input.createdAt
45312
+ });
45313
+ }
45243
45314
  function buildUiMessagePartOutputEnvelope(input) {
45244
45315
  const { context, snapshot } = input;
45245
45316
  return RuntimeBridgeOutputEnvelopeSchema.parse({
@@ -66496,11 +66567,16 @@ var ClaudeCodeCommandHandler = class {
66496
66567
  pendingQuestions = /* @__PURE__ */ new Map();
66497
66568
  outputBuffer;
66498
66569
  projector = new ClaudeCodeProjector();
66570
+ livenessTicker = null;
66499
66571
  // -----------------------------------------------------------------------------
66500
66572
  // Lifecycle (public API)
66501
66573
  // -----------------------------------------------------------------------------
66502
66574
  setContext(nextContext) {
66503
66575
  this.context = RuntimeBridgeConnectedPayloadSchema.parse(nextContext);
66576
+ this.livenessTicker ??= startRuntimeLivenessTicker({
66577
+ emitBeat: () => this.emitLivenessBeat(),
66578
+ writeOutput: this.input.writeOutput
66579
+ });
66504
66580
  }
66505
66581
  async replayPendingOutputs() {
66506
66582
  await this.outputBuffer.replayPendingOutputs();
@@ -66509,6 +66585,8 @@ var ClaudeCodeCommandHandler = class {
66509
66585
  await this.ensureAgentSession().prepare();
66510
66586
  }
66511
66587
  shutdown() {
66588
+ this.livenessTicker?.stop();
66589
+ this.livenessTicker = null;
66512
66590
  this.agentSession?.close();
66513
66591
  this.agentSession = null;
66514
66592
  this.settlePendingQuestions("Runtime is shutting down");
@@ -66840,6 +66918,16 @@ var ClaudeCodeCommandHandler = class {
66840
66918
  // -----------------------------------------------------------------------------
66841
66919
  // SDK callbacks
66842
66920
  // -----------------------------------------------------------------------------
66921
+ async emitLivenessBeat() {
66922
+ const activeContext = this.context;
66923
+ if (!activeContext) {
66924
+ return;
66925
+ }
66926
+ await this.outputBuffer.emitLivenessBeat(
66927
+ activeContext,
66928
+ RUNTIME_LIVENESS_INTERVAL_MS
66929
+ );
66930
+ }
66843
66931
  async emitBridgeOutput(activeContext, projection) {
66844
66932
  try {
66845
66933
  await this.outputBuffer.emitProjection(activeContext, projection);
@@ -68301,12 +68389,17 @@ var CodexCommandHandler = class {
68301
68389
  pendingApprovals = /* @__PURE__ */ new Map();
68302
68390
  outputBuffer;
68303
68391
  projector = new CodexProjector();
68392
+ livenessTicker = null;
68304
68393
  skipResumeForNextSession = false;
68305
68394
  // ---------------------------------------------------------------------------
68306
68395
  // Lifecycle (public API)
68307
68396
  // ---------------------------------------------------------------------------
68308
68397
  setContext(nextContext) {
68309
68398
  this.context = RuntimeBridgeConnectedPayloadSchema.parse(nextContext);
68399
+ this.livenessTicker ??= startRuntimeLivenessTicker({
68400
+ emitBeat: () => this.emitLivenessBeat(),
68401
+ writeOutput: this.input.writeOutput
68402
+ });
68310
68403
  }
68311
68404
  async replayPendingOutputs() {
68312
68405
  await this.outputBuffer.replayPendingOutputs();
@@ -68315,6 +68408,8 @@ var CodexCommandHandler = class {
68315
68408
  await this.ensureSession().prepare();
68316
68409
  }
68317
68410
  shutdown() {
68411
+ this.livenessTicker?.stop();
68412
+ this.livenessTicker = null;
68318
68413
  this.session?.close();
68319
68414
  this.session = null;
68320
68415
  this.pendingApprovals.clear();
@@ -68482,6 +68577,16 @@ var CodexCommandHandler = class {
68482
68577
  this.projector.projectSessionFailure(errorMessage3(error51))
68483
68578
  );
68484
68579
  }
68580
+ async emitLivenessBeat() {
68581
+ const activeContext = this.context;
68582
+ if (!activeContext) {
68583
+ return;
68584
+ }
68585
+ await this.outputBuffer.emitLivenessBeat(
68586
+ activeContext,
68587
+ RUNTIME_LIVENESS_INTERVAL_MS
68588
+ );
68589
+ }
68485
68590
  async emit(activeContext, projection) {
68486
68591
  try {
68487
68592
  await this.outputBuffer.emitProjection(activeContext, projection);
package/dist/index.js CHANGED
@@ -20227,6 +20227,10 @@ var init_session_turns = __esm({
20227
20227
  acceptedAt: external_exports.string().datetime().nullable(),
20228
20228
  startedAt: external_exports.string().datetime().nullable(),
20229
20229
  lastProgressAt: external_exports.string().datetime().nullable(),
20230
+ // Last runtime liveness beat that vouched for this open turn (null before
20231
+ // the first beat, and always null on runtimes that predate liveness).
20232
+ // Distinct from lastProgressAt: pipeline liveness, not durable progress.
20233
+ livenessAt: external_exports.string().datetime().nullable().default(null),
20230
20234
  completedAt: external_exports.string().datetime().nullable(),
20231
20235
  failedAt: external_exports.string().datetime().nullable(),
20232
20236
  staleAt: external_exports.string().datetime().nullable(),
@@ -30499,7 +30503,7 @@ var init_package = __esm({
30499
30503
  "package.json"() {
30500
30504
  package_default = {
30501
30505
  name: "@autohq/cli",
30502
- version: "0.1.342",
30506
+ version: "0.1.343",
30503
30507
  license: "SEE LICENSE IN README.md",
30504
30508
  publishConfig: {
30505
30509
  access: "public"
@@ -40758,12 +40762,24 @@ var RuntimeBridgeOutputUiMessageCompletedEnvelopeSchema = external_exports.objec
40758
40762
  createdAt: external_exports.string().datetime(),
40759
40763
  completedAt: external_exports.string().datetime().nullable()
40760
40764
  });
40765
+ var RuntimeBridgeOutputLivenessEnvelopeSchema = external_exports.object({
40766
+ type: external_exports.literal("runtime.liveness"),
40767
+ sessionId: SessionIdSchema2,
40768
+ runtimeId: RuntimeIdSchema2,
40769
+ bridgeLeaseId: RuntimeBridgeLeaseIdSchema2,
40770
+ outputSeq: external_exports.number().int().positive(),
40771
+ // The emitter's beat cadence, so watchdog thresholds stay interpretable
40772
+ // against the runtime that produced them.
40773
+ intervalMs: external_exports.number().int().positive(),
40774
+ createdAt: external_exports.string().datetime()
40775
+ });
40761
40776
  var RuntimeBridgeOutputEnvelopeSchema = external_exports.union([
40762
40777
  RuntimeBridgeOutputEntryEnvelopeSchema,
40763
40778
  RuntimeBridgeOutputDeltaEnvelopeSchema,
40764
40779
  RuntimeBridgeOutputUiMessageChunkEnvelopeSchema,
40765
40780
  RuntimeBridgeOutputUiMessagePartEnvelopeSchema,
40766
- RuntimeBridgeOutputUiMessageCompletedEnvelopeSchema
40781
+ RuntimeBridgeOutputUiMessageCompletedEnvelopeSchema,
40782
+ RuntimeBridgeOutputLivenessEnvelopeSchema
40767
40783
  ]);
40768
40784
  function isLiveOnlyRuntimeOutputEnvelope(envelope) {
40769
40785
  return envelope.type === "ui.message.chunk" || envelope.type === "conversation.delta";
@@ -41278,6 +41294,23 @@ function jsonRecordString(value, key) {
41278
41294
  // src/commands/agent-bridge/harness/claude-code/index.ts
41279
41295
  init_src();
41280
41296
 
41297
+ // src/commands/agent-bridge/harness/liveness-ticker.ts
41298
+ var RUNTIME_LIVENESS_INTERVAL_MS = 2e4;
41299
+ function startRuntimeLivenessTicker(input) {
41300
+ const intervalMs = input.intervalMs ?? RUNTIME_LIVENESS_INTERVAL_MS;
41301
+ const timer = setInterval(() => {
41302
+ void input.emitBeat().catch((error51) => {
41303
+ input.writeOutput?.(
41304
+ `agent_bridge_liveness_beat_failed error=${error51 instanceof Error ? error51.message : String(error51)}`
41305
+ );
41306
+ });
41307
+ }, intervalMs);
41308
+ timer.unref?.();
41309
+ return {
41310
+ stop: () => clearInterval(timer)
41311
+ };
41312
+ }
41313
+
41281
41314
  // src/commands/agent-bridge/harness/output-buffer.ts
41282
41315
  import { setTimeout as sleep2 } from "timers/promises";
41283
41316
  init_src();
@@ -41730,6 +41763,9 @@ var AgentBridgeOutputBuffer = class {
41730
41763
  uiMessagePartTracker = new UiMessagePartTracker();
41731
41764
  drainBlocked = false;
41732
41765
  drainPromise = null;
41766
+ // Sequence of the most recent liveness beat, for the skip-while-pending
41767
+ // gate in emitLivenessBeat.
41768
+ pendingLivenessSeq = null;
41733
41769
  // Ack-retry-ladder exhausts per pending output sequence, for the poison
41734
41770
  // quarantine; entries clear when the sequence finally acks.
41735
41771
  ackExhaustsBySeq = /* @__PURE__ */ new Map();
@@ -41760,6 +41796,29 @@ var AgentBridgeOutputBuffer = class {
41760
41796
  await this.flushPendingDelta({ force: true });
41761
41797
  await this.drainPendingOutputs({ force: true });
41762
41798
  }
41799
+ // Emits one runtime liveness beat through the same ordered, acked drain as
41800
+ // content envelopes — deliberately, so a beat landing at the bridge proves
41801
+ // the pipeline is healthy end to end. While a previous beat is still
41802
+ // pending (stalled drain, retry ladder, reconnect) new beats are skipped
41803
+ // rather than queued: an unhealthy pipeline must show up as beats
41804
+ // *stopping*, and a backlog of parked beats replaying after recovery would
41805
+ // stamp liveness for exactly the window the runtime was mute.
41806
+ async emitLivenessBeat(context, intervalMs) {
41807
+ if (this.pendingLivenessSeq !== null && this.pendingOutputs.has(this.pendingLivenessSeq)) {
41808
+ return;
41809
+ }
41810
+ this.outputSeq += 1;
41811
+ this.pendingLivenessSeq = this.outputSeq;
41812
+ this.enqueueOutput(
41813
+ buildLivenessOutputEnvelope({
41814
+ context,
41815
+ outputSeq: this.outputSeq,
41816
+ intervalMs,
41817
+ createdAt: now2()
41818
+ })
41819
+ );
41820
+ await this.drainPendingOutputs();
41821
+ }
41763
41822
  async emitUiMessageChunk(context, projection) {
41764
41823
  await this.flushPendingDelta();
41765
41824
  await this.emitLiveUiMessageChunk(context, projection.chunk);
@@ -42456,6 +42515,18 @@ function buildUiMessageChunkOutputEnvelope(input) {
42456
42515
  createdAt: input.createdAt
42457
42516
  });
42458
42517
  }
42518
+ function buildLivenessOutputEnvelope(input) {
42519
+ const { context } = input;
42520
+ return RuntimeBridgeOutputEnvelopeSchema.parse({
42521
+ type: "runtime.liveness",
42522
+ sessionId: context.sessionId,
42523
+ runtimeId: context.runtimeId,
42524
+ bridgeLeaseId: context.bridgeLeaseId,
42525
+ outputSeq: input.outputSeq,
42526
+ intervalMs: input.intervalMs,
42527
+ createdAt: input.createdAt
42528
+ });
42529
+ }
42459
42530
  function buildUiMessagePartOutputEnvelope(input) {
42460
42531
  const { context, snapshot } = input;
42461
42532
  return RuntimeBridgeOutputEnvelopeSchema.parse({
@@ -44141,11 +44212,16 @@ var ClaudeCodeCommandHandler = class {
44141
44212
  pendingQuestions = /* @__PURE__ */ new Map();
44142
44213
  outputBuffer;
44143
44214
  projector = new ClaudeCodeProjector();
44215
+ livenessTicker = null;
44144
44216
  // -----------------------------------------------------------------------------
44145
44217
  // Lifecycle (public API)
44146
44218
  // -----------------------------------------------------------------------------
44147
44219
  setContext(nextContext) {
44148
44220
  this.context = RuntimeBridgeConnectedPayloadSchema.parse(nextContext);
44221
+ this.livenessTicker ??= startRuntimeLivenessTicker({
44222
+ emitBeat: () => this.emitLivenessBeat(),
44223
+ writeOutput: this.input.writeOutput
44224
+ });
44149
44225
  }
44150
44226
  async replayPendingOutputs() {
44151
44227
  await this.outputBuffer.replayPendingOutputs();
@@ -44154,6 +44230,8 @@ var ClaudeCodeCommandHandler = class {
44154
44230
  await this.ensureAgentSession().prepare();
44155
44231
  }
44156
44232
  shutdown() {
44233
+ this.livenessTicker?.stop();
44234
+ this.livenessTicker = null;
44157
44235
  this.agentSession?.close();
44158
44236
  this.agentSession = null;
44159
44237
  this.settlePendingQuestions("Runtime is shutting down");
@@ -44485,6 +44563,16 @@ var ClaudeCodeCommandHandler = class {
44485
44563
  // -----------------------------------------------------------------------------
44486
44564
  // SDK callbacks
44487
44565
  // -----------------------------------------------------------------------------
44566
+ async emitLivenessBeat() {
44567
+ const activeContext = this.context;
44568
+ if (!activeContext) {
44569
+ return;
44570
+ }
44571
+ await this.outputBuffer.emitLivenessBeat(
44572
+ activeContext,
44573
+ RUNTIME_LIVENESS_INTERVAL_MS
44574
+ );
44575
+ }
44488
44576
  async emitBridgeOutput(activeContext, projection) {
44489
44577
  try {
44490
44578
  await this.outputBuffer.emitProjection(activeContext, projection);
@@ -45951,12 +46039,17 @@ var CodexCommandHandler = class {
45951
46039
  pendingApprovals = /* @__PURE__ */ new Map();
45952
46040
  outputBuffer;
45953
46041
  projector = new CodexProjector();
46042
+ livenessTicker = null;
45954
46043
  skipResumeForNextSession = false;
45955
46044
  // ---------------------------------------------------------------------------
45956
46045
  // Lifecycle (public API)
45957
46046
  // ---------------------------------------------------------------------------
45958
46047
  setContext(nextContext) {
45959
46048
  this.context = RuntimeBridgeConnectedPayloadSchema.parse(nextContext);
46049
+ this.livenessTicker ??= startRuntimeLivenessTicker({
46050
+ emitBeat: () => this.emitLivenessBeat(),
46051
+ writeOutput: this.input.writeOutput
46052
+ });
45960
46053
  }
45961
46054
  async replayPendingOutputs() {
45962
46055
  await this.outputBuffer.replayPendingOutputs();
@@ -45965,6 +46058,8 @@ var CodexCommandHandler = class {
45965
46058
  await this.ensureSession().prepare();
45966
46059
  }
45967
46060
  shutdown() {
46061
+ this.livenessTicker?.stop();
46062
+ this.livenessTicker = null;
45968
46063
  this.session?.close();
45969
46064
  this.session = null;
45970
46065
  this.pendingApprovals.clear();
@@ -46132,6 +46227,16 @@ var CodexCommandHandler = class {
46132
46227
  this.projector.projectSessionFailure(errorMessage3(error51))
46133
46228
  );
46134
46229
  }
46230
+ async emitLivenessBeat() {
46231
+ const activeContext = this.context;
46232
+ if (!activeContext) {
46233
+ return;
46234
+ }
46235
+ await this.outputBuffer.emitLivenessBeat(
46236
+ activeContext,
46237
+ RUNTIME_LIVENESS_INTERVAL_MS
46238
+ );
46239
+ }
46135
46240
  async emit(activeContext, projection) {
46136
46241
  try {
46137
46242
  await this.outputBuffer.emitProjection(activeContext, projection);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.342",
3
+ "version": "0.1.343",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"