openclaw - 💡(How to fix) Fix [Feature]: Broaden BlueBubbles contact-name enrichment from groups to 1:1 DMs [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#68731Fetched 2026-04-19 15:08:12
View on GitHub
Comments
1
Participants
2
Timeline
1
Reactions
0
Timeline (top)
commented ×1

Extend enrichBlueBubblesParticipantsWithContactNames (currently invoked only on the group-chat path) to also resolve 1:1 inbound sender names from the agent user's local Contacts.app.

Error Message

  • Consequence: Agent context reads cold (user:+14155551234); relationship-aware replies degrade; no runtime error.

Root Cause

Extend enrichBlueBubblesParticipantsWithContactNames (currently invoked only on the group-chat path) to also resolve 1:1 inbound sender names from the agent user's local Contacts.app.

Fix Action

Fix / Workaround

Evidence/examples

Implementation reference (overlay patch + tests) in our downstream repo:

Additional information

  • AI-assisted (Claude Code). Testing level: fully tested (14 unit tests + E2E on production BlueBubbles + macOS 26.4.1).
  • Backwards compat guaranteed via the flag shim. Existing enrichGroupParticipantsFromContacts = true configs keep working unchanged.
  • Scope note: we also overlay a reaction-dispatch-skip + message:reaction_received hook alongside this enrichment work in our downstream, but that's a separate semantic decision — we are NOT proposing it upstream in this issue.
  • If there's interest, happy to file the PR. Existing sender-enrichment patch already patch -p1 clean against the current main layout.
RAW_BUFFERClick to expand / collapse

Summary

Extend enrichBlueBubblesParticipantsWithContactNames (currently invoked only on the group-chat path) to also resolve 1:1 inbound sender names from the agent user's local Contacts.app.

Problem to solve

Today, monitor-processing.ts only calls enrichBlueBubblesParticipantsWithContactNames when isGroup && enrichGroupParticipantsFromContacts === true. For 1:1 inbound DMs, BlueBubbles's native Contacts.framework lookup normally populates senderName before the webhook fires — but it returns empty (or the raw phone digits) in several observable cases:

  • macOS 26 Tahoe Contacts.framework regressions where BB's native lookup silently misses records that sqlite3 can still read.
  • TCC permission glitches where BB can't read Contacts but a child sqlite3 subprocess can (different Mach bootstrap context).
  • Synthetic handles / BB bridges that skip BB's own resolver (observed during any;-; vs iMessage;-; GUID-prefix rewrites).
  • Group participant records delivered as bare handles without names.

The downstream effect is that agents see user:+14155551234 and address the sender by phone number — cold, and the wrong context for most conversational use cases.

Proposed solution

Minimal, backwards-compatible extension of the existing resolver:

  1. participant-contact-names.ts:

    • Add hasUsableSenderName(senderName, senderId): boolean predicate that returns false for empty, whitespace, senderId-echo, and phone-shape (≥7 digits, /^[\s+().\-\d]+$/) values.
    • Add resolveInboundSenderName(senderId): Promise<string | undefined> that synthesizes a one-element participants array and delegates to the existing enrichBlueBubblesParticipantsWithContactNames — preserves the shared cache (1h positive TTL, 5min negative TTL, LRU 2048).
  2. config-schema.ts + types.ts:

    • Rename enrichGroupParticipantsFromContactsenrichParticipantsFromContacts (covers both 1:1 and group paths).
    • Keep the legacy flag as @deprecated with its existing default true. Call site reads the new flag first, falls back to the legacy flag, then defaults to true.
    • The new flag has no default so the shim can distinguish unset from explicit false.
  3. monitor-processing.ts:

    • Broaden the existing enrichment conditional. Group path unchanged. 1:1 path calls resolveInboundSenderName only when senderIdExplicit === true and !hasUsableSenderName(message.senderName, message.senderId). senderIdExplicit === false senders (BB bridge/synthetic) are explicitly skipped with a logVerbose breadcrumb.

No schema changes downstream of the webhook. No new external dependencies (sqlite3 subprocess already used by the group path).

Alternatives considered

  • Do nothing — relies on BB's native Contacts.framework lookup being reliable. Observably isn't on Tahoe.
  • Move enrichment to a third-party plugin via the plugin SDK — the existing group-path enrichment lives inside the bluebubbles extension (not a plugin), so a plugin wrapper would need to duplicate the sqlite3 + cache machinery. The wrapper would still need the hook point in monitor-processing.ts that this PR adds.
  • Skip the flag rename — keep enrichGroupParticipantsFromContacts and reuse it for 1:1. Works, but the name becomes inaccurate once the scope is broader. The rename + legacy shim is a 2-line shim and a deprecation comment.

Impact

  • Affected: BlueBubbles channel users who receive 1:1 inbound from senders whose phone numbers aren't in BB's native Contacts-cache hit set.
  • Severity: Medium. Agents still reply correctly — they just address the sender by phone number instead of name.
  • Frequency: Common on fresh BB installs, after macOS 26 Tahoe upgrades, for BB-bridge synthetic handles, and for group-participant records delivered as handles.
  • Consequence: Agent context reads cold (user:+14155551234); relationship-aware replies degrade; no runtime error.

Evidence/examples

Implementation reference (overlay patch + tests) in our downstream repo:

Downstream tracking: markthebest12/openclaw-infra#765

Additional information

  • AI-assisted (Claude Code). Testing level: fully tested (14 unit tests + E2E on production BlueBubbles + macOS 26.4.1).
  • Backwards compat guaranteed via the flag shim. Existing enrichGroupParticipantsFromContacts = true configs keep working unchanged.
  • Scope note: we also overlay a reaction-dispatch-skip + message:reaction_received hook alongside this enrichment work in our downstream, but that's a separate semantic decision — we are NOT proposing it upstream in this issue.
  • If there's interest, happy to file the PR. Existing sender-enrichment patch already patch -p1 clean against the current main layout.

extent analysis

TL;DR

Extend the enrichBlueBubblesParticipantsWithContactNames function to resolve 1:1 inbound sender names from the agent user's local Contacts.app by adding a new resolveInboundSenderName function and updating the monitor-processing.ts file.

Guidance

  • Update the participant-contact-names.ts file to include the new hasUsableSenderName predicate and resolveInboundSenderName function.
  • Rename the enrichGroupParticipantsFromContacts flag to enrichParticipantsFromContacts in config-schema.ts and types.ts to cover both 1:1 and group paths.
  • Update the monitor-processing.ts file to call resolveInboundSenderName for 1:1 inbound messages when senderIdExplicit is true and the sender name is not usable.
  • Test the changes thoroughly to ensure backwards compatibility and correct functionality.

Example

// participant-contact-names.ts
export function hasUsableSenderName(senderName: string, senderId: string): boolean {
  // implementation of the predicate
}

export function resolveInboundSenderName(senderId: string): Promise<string | undefined> {
  // implementation of the function
}

Notes

The proposed solution is backwards compatible and does not introduce any new external dependencies. However, it's essential to test the changes thoroughly to ensure correct functionality and backwards compatibility.

Recommendation

Apply the proposed workaround by extending the enrichBlueBubblesParticipantsWithContactNames function and updating the monitor-processing.ts file. This solution is backwards compatible and addresses the issue of resolving 1:1 inbound sender names from the agent user's local Contacts.app.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix [Feature]: Broaden BlueBubbles contact-name enrichment from groups to 1:1 DMs [1 comments, 2 participants]