@ouro.bot/cli 0.1.0-alpha.521 → 0.1.0-alpha.522

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/changelog.json CHANGED
@@ -1,6 +1,14 @@
1
1
  {
2
2
  "_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
3
3
  "versions": [
4
+ {
5
+ "version": "0.1.0-alpha.522",
6
+ "changes": [
7
+ "Keeps the BlueBubbles production HTTP worker responsive by changing runtime health sync to queue/discover missed iMessage recovery work instead of running full recovered agent turns inline.",
8
+ "Counts captured inbound sidecars and mutation backlog as pending recovery in BlueBubbles runtime state, so `ouro status`/health truth can show that live transport is up while old messages still need recovery.",
9
+ "Queues upstream catch-up candidates into the inbound sidecar during runtime sync without hydrating or invoking the agent, preserving idempotent recovery while preventing startup catch-up from starving live webhooks."
10
+ ]
11
+ },
4
12
  {
5
13
  "version": "0.1.0-alpha.521",
6
14
  "changes": [
@@ -1165,6 +1165,18 @@ function countPendingRecoveryCandidates(agentName) {
1165
1165
  .filter((entry) => !(0, processed_log_1.hasProcessedBlueBubblesMessage)(agentName, entry.sessionKey, entry.messageGuid))
1166
1166
  .length;
1167
1167
  }
1168
+ function countPendingCapturedInboundMessages(agentName) {
1169
+ const seenMessageGuids = new Set();
1170
+ return (0, inbound_log_1.listRecordedBlueBubblesInbound)(agentName)
1171
+ .filter((entry) => {
1172
+ if (seenMessageGuids.has(entry.messageGuid))
1173
+ return false;
1174
+ seenMessageGuids.add(entry.messageGuid);
1175
+ return true;
1176
+ })
1177
+ .filter((entry) => !(0, processed_log_1.hasProcessedBlueBubblesMessage)(agentName, entry.sessionKey, entry.messageGuid))
1178
+ .length;
1179
+ }
1168
1180
  function parseTimestampMs(value) {
1169
1181
  if (!value)
1170
1182
  return null;
@@ -1181,9 +1193,6 @@ function resolveBlueBubblesCatchUpSince(previousState, nowMs = Date.now()) {
1181
1193
  }
1182
1194
  return nowMs - BLUEBUBBLES_FIRST_CATCHUP_LOOKBACK_MS;
1183
1195
  }
1184
- function formatRecoveredCount(count) {
1185
- return `caught up ${count} missed message(s)`;
1186
- }
1187
1196
  async function syncBlueBubblesRuntime(deps = {}) {
1188
1197
  const resolvedDeps = { ...defaultDeps, ...deps };
1189
1198
  const agentName = resolvedDeps.getAgentName();
@@ -1192,11 +1201,13 @@ async function syncBlueBubblesRuntime(deps = {}) {
1192
1201
  const previousState = (0, runtime_state_1.readBlueBubblesRuntimeState)(agentName);
1193
1202
  try {
1194
1203
  await client.checkHealth();
1195
- const captured = await recoverCapturedBlueBubblesInboundMessages(resolvedDeps);
1196
- const recovery = await recoverMissedBlueBubblesMessages(resolvedDeps);
1197
- const catchUp = await catchUpMissedBlueBubblesMessages(resolvedDeps, previousState);
1198
- const failed = captured.failed + recovery.failed + catchUp.failed;
1199
- const recovered = captured.recovered + recovery.recovered + catchUp.recovered;
1204
+ const capturedPending = countPendingCapturedInboundMessages(agentName);
1205
+ const recoveryPending = countPendingRecoveryCandidates(agentName);
1206
+ const catchUp = await catchUpMissedBlueBubblesMessages(resolvedDeps, previousState, {
1207
+ processTurns: false,
1208
+ });
1209
+ const failed = catchUp.failed;
1210
+ const queued = capturedPending + recoveryPending + (catchUp.queued ?? 0);
1200
1211
  // upstreamStatus reflects whether BlueBubbles itself is healthy and we
1201
1212
  // have unprocessed work (pendingRecoveryCount). Per-cycle recovery
1202
1213
  // failures are noted in `detail` for transparency but do NOT flip the
@@ -1204,18 +1215,16 @@ async function syncBlueBubblesRuntime(deps = {}) {
1204
1215
  // otherwise stick the sense in "error" forever, contradicting `ouro
1205
1216
  // doctor` which only checks upstream reachability.
1206
1217
  (0, runtime_state_1.writeBlueBubblesRuntimeState)(agentName, {
1207
- upstreamStatus: recovery.pending > 0 ? "error" : "ok",
1208
- detail: recovery.pending > 0
1209
- ? `pending recovery: ${recovery.pending}`
1218
+ upstreamStatus: queued > 0 ? "error" : "ok",
1219
+ detail: queued > 0
1220
+ ? `pending recovery: ${queued}`
1210
1221
  : failed > 0
1211
1222
  ? `${failed} message(s) unrecoverable this cycle; upstream ok`
1212
- : catchUp.recovered > 0
1213
- ? formatRecoveredCount(catchUp.recovered)
1214
- : "upstream reachable",
1223
+ : "upstream reachable",
1215
1224
  lastCheckedAt: checkedAt,
1216
- pendingRecoveryCount: recovery.pending,
1217
- lastRecoveredAt: recovered > 0 ? checkedAt : previousState.lastRecoveredAt,
1218
- lastRecoveredMessageGuid: catchUp.lastRecoveredMessageGuid ?? previousState.lastRecoveredMessageGuid,
1225
+ pendingRecoveryCount: queued,
1226
+ lastRecoveredAt: previousState.lastRecoveredAt,
1227
+ lastRecoveredMessageGuid: previousState.lastRecoveredMessageGuid,
1219
1228
  });
1220
1229
  }
1221
1230
  catch (error) {
@@ -1223,17 +1232,18 @@ async function syncBlueBubblesRuntime(deps = {}) {
1223
1232
  upstreamStatus: "error",
1224
1233
  detail: error instanceof Error ? error.message : String(error),
1225
1234
  lastCheckedAt: checkedAt,
1226
- pendingRecoveryCount: countPendingRecoveryCandidates(agentName),
1235
+ pendingRecoveryCount: countPendingCapturedInboundMessages(agentName) + countPendingRecoveryCandidates(agentName),
1227
1236
  });
1228
1237
  }
1229
1238
  }
1230
- async function catchUpMissedBlueBubblesMessages(deps = {}, previousState) {
1239
+ async function catchUpMissedBlueBubblesMessages(deps = {}, previousState, options = {}) {
1231
1240
  const resolvedDeps = { ...defaultDeps, ...deps };
1232
1241
  const agentName = resolvedDeps.getAgentName();
1233
1242
  const client = resolvedDeps.createClient();
1234
1243
  const result = { inspected: 0, recovered: 0, skipped: 0, failed: 0 };
1235
1244
  const state = previousState ?? (0, runtime_state_1.readBlueBubblesRuntimeState)(agentName);
1236
1245
  const catchUpSince = resolveBlueBubblesCatchUpSince(state);
1246
+ const processTurns = options.processTurns !== false;
1237
1247
  /* v8 ignore next -- older injected test doubles may omit the catch-up query method */
1238
1248
  if (!client.listRecentMessages)
1239
1249
  return result;
@@ -1311,6 +1321,15 @@ async function catchUpMissedBlueBubblesMessages(deps = {}, previousState) {
1311
1321
  result.skipped++;
1312
1322
  continue;
1313
1323
  }
1324
+ if (!processTurns) {
1325
+ if ((0, inbound_log_1.hasRecordedBlueBubblesInbound)(agentName, event.chat.sessionKey, event.messageGuid)) {
1326
+ result.skipped++;
1327
+ continue;
1328
+ }
1329
+ (0, inbound_log_1.recordBlueBubblesInbound)(agentName, event, "upstream-catchup");
1330
+ result.queued = (result.queued ?? 0) + 1;
1331
+ continue;
1332
+ }
1314
1333
  try {
1315
1334
  const repaired = await client.repairEvent(event);
1316
1335
  if (repaired.kind !== "message") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.521",
3
+ "version": "0.1.0-alpha.522",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",