@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 +8 -0
- package/dist/senses/bluebubbles/index.js +38 -19
- package/package.json +1 -1
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
|
|
1196
|
-
const
|
|
1197
|
-
const catchUp = await catchUpMissedBlueBubblesMessages(resolvedDeps, previousState
|
|
1198
|
-
|
|
1199
|
-
|
|
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:
|
|
1208
|
-
detail:
|
|
1209
|
-
? `pending recovery: ${
|
|
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
|
-
:
|
|
1213
|
-
? formatRecoveredCount(catchUp.recovered)
|
|
1214
|
-
: "upstream reachable",
|
|
1223
|
+
: "upstream reachable",
|
|
1215
1224
|
lastCheckedAt: checkedAt,
|
|
1216
|
-
pendingRecoveryCount:
|
|
1217
|
-
lastRecoveredAt:
|
|
1218
|
-
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") {
|