@ouro.bot/cli 0.1.0-alpha.568 → 0.1.0-alpha.569
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/heart/core.js +1 -5
- package/dist/senses/bluebubbles/index.js +37 -0
- 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.569",
|
|
6
|
+
"changes": [
|
|
7
|
+
"BlueBubbles ordinary chat turns no longer trigger external-state proof retry loops merely because the inbound text populated currentObligation.",
|
|
8
|
+
"BlueBubbles now suppresses duplicate normalized outward text within a single inbound turn across flush and flushNow delivery paths, preventing retry loops from sending repeated iMessages.",
|
|
9
|
+
"Regression coverage locks the 2026-05-08 duplicate outward-send incident while preserving distinct same-turn replies and per-turn re-sends."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
4
12
|
{
|
|
5
13
|
"version": "0.1.0-alpha.568",
|
|
6
14
|
"changes": [
|
package/dist/heart/core.js
CHANGED
|
@@ -296,7 +296,7 @@ function isExternalStateQuery(toolName, args) {
|
|
|
296
296
|
const cmd = String(args.command ?? "");
|
|
297
297
|
return /\bgh\s+(pr|run|api|issue)\b/.test(cmd) || /\bnpm\s+(view|info|show)\b/.test(cmd);
|
|
298
298
|
}
|
|
299
|
-
function getSettleRetryError(mustResolveBeforeHandoff, intent, sawSteeringFollowUp, _delegationDecision, sawSendMessageSelf, sawPonder, _sawQuerySession, currentObligation, innerJob,
|
|
299
|
+
function getSettleRetryError(mustResolveBeforeHandoff, intent, sawSteeringFollowUp, _delegationDecision, sawSendMessageSelf, sawPonder, _sawQuerySession, currentObligation, innerJob, _sawExternalStateQuery) {
|
|
300
300
|
// Delegation adherence removed: the delegation decision is surfaced in the
|
|
301
301
|
// system prompt as a suggestion. Hard-gating settle caused infinite
|
|
302
302
|
// rejection loops where the agent couldn't respond to the user at all.
|
|
@@ -317,10 +317,6 @@ function getSettleRetryError(mustResolveBeforeHandoff, intent, sawSteeringFollow
|
|
|
317
317
|
if (mustResolveBeforeHandoff && intent === "complete" && currentObligation && !sawSteeringFollowUp) {
|
|
318
318
|
return "you still owe the live session a visible return on this work. don't end the turn yet — continue until you've brought back the external-state update, or use intent=blocked with the concrete blocker.";
|
|
319
319
|
}
|
|
320
|
-
// 6. External-state grounding: obligation + complete requires fresh external verification
|
|
321
|
-
if (intent === "complete" && currentObligation && !sawExternalStateQuery && !sawSteeringFollowUp) {
|
|
322
|
-
return "you're claiming this work is complete, but the external state hasn't been verified this turn. ground your claim with a fresh check (gh pr view, npm view, gh run view, etc.) before calling settle.";
|
|
323
|
-
}
|
|
324
320
|
return null;
|
|
325
321
|
}
|
|
326
322
|
function upsertSystemPrompt(messages, systemText) {
|
|
@@ -458,6 +458,15 @@ function createBlueBubblesCallbacks(client, chat, replyTarget, isGroupChat, onVi
|
|
|
458
458
|
let queue = Promise.resolve();
|
|
459
459
|
let lastVisibleActivityMs = Date.now();
|
|
460
460
|
let silenceWatchdog = null;
|
|
461
|
+
// Per-turn outward-send dedupe. A single createBlueBubblesCallbacks lifetime
|
|
462
|
+
// serves one inbound turn, so collapsing identical outward bodies inside
|
|
463
|
+
// this closure is scoped tightly: each fresh inbound turn starts with an
|
|
464
|
+
// empty set. Mid-turn settle/proof retry loops historically caused the
|
|
465
|
+
// agent to re-emit the same answer through multiple speak calls and a
|
|
466
|
+
// final flush, surfacing as 4 near-identical iMessages from one ask
|
|
467
|
+
// (2026-05-08 06:18 incident). The guard lets the engine retry harmlessly
|
|
468
|
+
// without duplicating outward delivery to the friend.
|
|
469
|
+
const sentOutwardTextNorms = new Set();
|
|
461
470
|
function enqueue(operation, task) {
|
|
462
471
|
queue = queue.then(task).catch((error) => {
|
|
463
472
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -491,6 +500,26 @@ function createBlueBubblesCallbacks(client, chat, replyTarget, isGroupChat, onVi
|
|
|
491
500
|
lastVisibleActivityMs = Date.now();
|
|
492
501
|
onVisibleActivity?.();
|
|
493
502
|
}
|
|
503
|
+
function isDuplicateOutwardText(trimmed) {
|
|
504
|
+
const norm = trimmed.replace(/\s+/g, " ").trim().toLowerCase();
|
|
505
|
+
if (sentOutwardTextNorms.has(norm))
|
|
506
|
+
return true;
|
|
507
|
+
sentOutwardTextNorms.add(norm);
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
function emitDuplicateOutwardSuppressed(site, messageLength) {
|
|
511
|
+
(0, runtime_1.emitNervesEvent)({
|
|
512
|
+
level: "warn",
|
|
513
|
+
component: "senses",
|
|
514
|
+
event: "bluebubbles.duplicate_outward_suppressed",
|
|
515
|
+
message: "suppressed near-identical outward send within single inbound turn",
|
|
516
|
+
meta: {
|
|
517
|
+
site,
|
|
518
|
+
chatGuid: chat.chatGuid ?? null,
|
|
519
|
+
messageLength,
|
|
520
|
+
},
|
|
521
|
+
});
|
|
522
|
+
}
|
|
494
523
|
function stopSilenceWatchdog() {
|
|
495
524
|
if (silenceWatchdog === null)
|
|
496
525
|
return;
|
|
@@ -628,6 +657,10 @@ function createBlueBubblesCallbacks(client, chat, replyTarget, isGroupChat, onVi
|
|
|
628
657
|
});
|
|
629
658
|
return;
|
|
630
659
|
}
|
|
660
|
+
if (isDuplicateOutwardText(trimmed)) {
|
|
661
|
+
emitDuplicateOutwardSuppressed("flushNow", trimmed.length);
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
631
664
|
await client.sendText({
|
|
632
665
|
chat,
|
|
633
666
|
text: trimmed,
|
|
@@ -673,6 +706,10 @@ function createBlueBubblesCallbacks(client, chat, replyTarget, isGroupChat, onVi
|
|
|
673
706
|
});
|
|
674
707
|
return;
|
|
675
708
|
}
|
|
709
|
+
if (isDuplicateOutwardText(trimmed)) {
|
|
710
|
+
emitDuplicateOutwardSuppressed("flush", trimmed.length);
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
676
713
|
await client.sendText({
|
|
677
714
|
chat,
|
|
678
715
|
text: trimmed,
|