Skip to content

Desktop: whatsapp integration#8462

Open
PriyanshuDangi wants to merge 33 commits into
BasedHardware:mainfrom
PriyanshuDangi:desktop-whatsapp
Open

Desktop: whatsapp integration#8462
PriyanshuDangi wants to merge 33 commits into
BasedHardware:mainfrom
PriyanshuDangi:desktop-whatsapp

Conversation

@PriyanshuDangi

@PriyanshuDangi PriyanshuDangi commented Jun 27, 2026

Copy link
Copy Markdown

Summary

This PR adds WhatsApp support to Omi Desktop so users can connect WhatsApp, view their chats, and let Omi help draft or send replies in the user's own tone.

Main features:

  • Connect WhatsApp from the desktop app by scanning a QR code.
  • Add a new Messages page for viewing WhatsApp chats and messages.
  • Let Omi read recent WhatsApp context and generate reply drafts.
  • Support approve, dismiss, and always-auto-reply flows for generated drafts.
  • Add optional auto-reply mode with guardrails like allowlists, kill switch, rate limits, quiet hours, sensitive-content checks, and audit logs.
  • Build a lightweight tone profile from the user's sent WhatsApp messages so replies sound closer to how the user writes.
  • Optionally sync WhatsApp history into Omi memories only when the user enables WhatsApp sync.
  • Expose WhatsApp tools to the desktop agent through the existing Omi bridge, with guarded manual sending.

Why @openclaw/wacli

The goal is to make Omi act more like an AI clone that can understand the user's messaging style and reply on their behalf when allowed. For that, Omi needs access to WhatsApp chats, recent conversation context, and the user's own sent messages for tone matching.

@openclaw/wacli gives us a simple local way to do this on desktop: the user just scans a WhatsApp QR code, like linking a normal WhatsApp device. We do not need to build backend WhatsApp infrastructure for this flow, and the WhatsApp session stays local to the desktop app.

Design Notes

  • WhatsApp connection, sync, reading, and sending are handled locally by the Swift desktop app through wacli.
  • The new Messages UI uses a generic provider layer so future messaging apps can be added later.
  • Reply automation is draft-first by default. Auto-send requires explicit settings and allowlisting.
  • Memory import is opt-in, so WhatsApp messages are only added to Omi memories when the user enables sync.
  • The agent uses Swift-backed WhatsApp tools through the existing desktop bridge so the same user settings and safety checks apply everywhere.

Review Notes

This is a privacy-sensitive feature because it touches WhatsApp messages, contacts, memory sync, and reply sending. The main review areas are product/privacy approval, send/auto-reply guardrails, and the packaging/provenance decision for the WhatsApp CLI dependency.

Review in cubic

PriyanshuDangi and others added 23 commits June 26, 2026 18:30
Machine-specific run.sh signing/libwebp fixes and local Swift compile tweaks.

Co-authored-by: Cursor <cursoragent@cursor.com>
Adds the desktop WhatsApp linking surface and wacli runtime staging so users can pair WhatsApp via QR and see connection status locally.

Co-authored-by: Cursor <cursoragent@cursor.com>
Adds Swift-backed wacli read and manual send tool execution so the agent can list chats, read/search threads, and send a guarded text reply.

Co-authored-by: Cursor <cursoragent@cursor.com>
Adds a stdio MCP server that exposes WhatsApp read and manual send tools through the existing Swift bridge.

Co-authored-by: Cursor <cursoragent@cursor.com>
Registers the WhatsApp stdio MCP server alongside omi-tools so agent chats can invoke Swift-backed WhatsApp tools.

Co-authored-by: Cursor <cursoragent@cursor.com>
Adds the inbound WhatsApp reply coordinator and routes received sync events into an autonomous draft flow through the existing agent tools.

Co-authored-by: Cursor <cursoragent@cursor.com>
Adds reply-mode settings, allowlist checks, rate limiting, sensitive-content draft fallback, kill-switch enforcement, and audit logging for WhatsApp sends.

Co-authored-by: Cursor <cursoragent@cursor.com>
Stores pending WhatsApp drafts, exposes approve/dismiss/always-auto actions, and surfaces draft-ready notifications through the floating bar.

Co-authored-by: Cursor <cursoragent@cursor.com>
Builds a lightweight WhatsApp writing-style profile from sent messages and injects it into autonomous reply drafting with a tone-match opt-out.

Co-authored-by: Cursor <cursoragent@cursor.com>
Adds settings controls for reply mode, kill switch, drafts, auto-send allowlist, rate limits, quiet hours, tone matching, and audit history.

Co-authored-by: Cursor <cursoragent@cursor.com>
Prefers the verified openclaw wacli build for local desktop runs and surfaces a clear error when an older binary lacks QR auth flags.

Co-authored-by: Cursor <cursoragent@cursor.com>
Uses wacli sync webhook delivery for live inbound WhatsApp messages, resumes sync for authenticated stores, and parses wacli message JSON keys.

Co-authored-by: Cursor <cursoragent@cursor.com>
Handles wacli live webhook keys like ID, Chat, and PushName so inbound messages reach the draft coordinator.

Co-authored-by: Cursor <cursoragent@cursor.com>
Surface draft failures clearly and gate autonomous WhatsApp drafts on a fresh backend quota check while keeping transient sync reconnects from forcing reauth.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Improve the Messages page so WhatsApp chats stay current, drafts attach to the right conversations, and generated replies do not leak reasoning into visible or sent text.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

39 issues found across 35 files

Confidence score: 2/5

  • desktop/macos/Desktop/Sources/WhatsApp/WhatsAppWebhookServer.swift has multiple merge-blocking request-handling flaws: negative Content-Length can crash parsing, rejected requests still return 200 {"ok":true} (so upstream won’t retry), and inbound webhook origin is not authenticated. Merging as-is risks crashes, silent message loss, and spoofed local requests—add strict header validation, return non-2xx on internal rejection, and enforce request authentication before dispatch.
  • In desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReplyCoordinator.swift, processedMessageIDs is updated before draft creation succeeds, so transient failures become permanent drops on redelivery. This can cause user-visible missed replies—only mark IDs processed after successful draft creation (or remove them on failure) before merging.
  • desktop/macos/agent/src/wa-tools-stdio.ts and desktop/macos/Desktop/Sources/WhatsApp/WhatsAppService.swift both have hang paths (wa-tools pending calls never time out/clean up, and runOneShot can deadlock on full pipes before output is drained). The consequence is stuck workflows and leaked in-flight state—add timeout/reject+cleanup on bridge loss and drain stdout/stderr concurrently before waitUntilExit().
  • There are correctness regressions in state/audit/dedup logic: desktop/macos/Desktop/Sources/WhatsApp/WhatsAppService.swift may report false .connected, desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReplyGuardrails.swift fails to decode audit entries due to date-strategy mismatch, and desktop/macos/Desktop/Sources/WhatsApp/WhatsAppMemoryImportService.swift uses unstable hashValue for persisted dedup IDs. This can mislead connection state and corrupt operational history/dedup behavior—switch to structured state checks, match ISO-8601 decode strategy, and use a stable deterministic hash/ID scheme.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="desktop/macos/run.sh">

<violation number="1" location="desktop/macos/run.sh:592">
P1: Auto-detected signing identity now uses the SHA-1 hash, but the team-ID extraction still expects the display-name format, causing a false profile/team mismatch and an unintended fallback that strips the Sign In with Apple entitlement.</violation>
</file>

<file name="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift">

<violation number="1" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift:3">
P2: `@MainActor` isolation keeps expensive JSON parsing on the main actor, risking UI stalls despite the CLI execution being detached.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread desktop/macos/run.sh
SIGN_IDENTITY=$(security find-identity -v -p codesigning | grep "Apple Development" | head -1 | sed 's/.*"\(.*\)"/\1/')
# Skip revoked certs and use the SHA-1 hash — duplicate display names (revoked + valid)
# make name-based signing ambiguous.
SIGN_IDENTITY=$(security find-identity -v -p codesigning | grep -v REVOKED | grep "Apple Development" | head -1 | awk '{print $2}')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Auto-detected signing identity now uses the SHA-1 hash, but the team-ID extraction still expects the display-name format, causing a false profile/team mismatch and an unintended fallback that strips the Sign In with Apple entitlement.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At desktop/macos/run.sh, line 592:

<comment>Auto-detected signing identity now uses the SHA-1 hash, but the team-ID extraction still expects the display-name format, causing a false profile/team mismatch and an unintended fallback that strips the Sign In with Apple entitlement.</comment>

<file context>
@@ -574,9 +587,11 @@ step "Signing app with hardened runtime..."
-    SIGN_IDENTITY=$(security find-identity -v -p codesigning | grep "Apple Development" | head -1 | sed 's/.*"\(.*\)"/\1/')
+    # Skip revoked certs and use the SHA-1 hash — duplicate display names (revoked + valid)
+    # make name-based signing ambiguous.
+    SIGN_IDENTITY=$(security find-identity -v -p codesigning | grep -v REVOKED | grep "Apple Development" | head -1 | awk '{print $2}')
     if [ -z "$SIGN_IDENTITY" ]; then
-        SIGN_IDENTITY=$(security find-identity -v -p codesigning | grep "Developer ID Application" | head -1 | sed 's/.*"\(.*\)"/\1/')
</file context>

Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppWebhookServer.swift Outdated
Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppWebhookServer.swift Outdated
Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppWebhookServer.swift Outdated
Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReplyGuardrails.swift Outdated
Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppService.swift Outdated
Comment thread desktop/macos/Desktop/Sources/MainWindow/DesktopHomeView.swift
Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift Outdated
Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift Outdated
Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift
@Git-on-my-level Git-on-my-level added security-review Needs security/privacy review dependency-review Touches dependencies or lockfiles; needs dependency review workflow-review Needs maintainer review for workflow, automation, hooks, or CI behavior needs-maintainer-review Needs a human maintainer to review/approve (e.g. stacked, product, or architecture judgment) needs-tests Needs additional or corrected test coverage feature-fit-review PR touches feature direction; qualitative fit assessed labels Jun 27, 2026
@Git-on-my-level Git-on-my-level added the needs-scope-reduction PR scope is too large or combines too many concerns for effective review label Jun 27, 2026

@Git-on-my-level Git-on-my-level left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution. I’m going to request changes rather than approve this because the PR introduces a broad, security/privacy-sensitive WhatsApp integration and bundles a new executable.

Blocking concerns:

  • desktop/macos/Desktop/Sources/Resources/wacli is a ~44 MB Mach-O universal executable added directly to the PR. I can’t treat an opaque binary from a first-time contributor as reviewable or safe to ship. Please remove the bundled binary from the PR and instead document or implement a trusted, reproducible supply-chain path for obtaining/building it, including version/source/provenance and maintainer-controlled release packaging.
  • The feature gives the desktop app access to WhatsApp messages/contacts, can import private messages into Omi memories, starts a local webhook, exposes WhatsApp tools to the agent, and includes message-sending/auto-reply flows. That needs explicit maintainer product/security/privacy review before merge.
  • The change is very large and difficult to review as one unit (35 files / ~6k changed lines), with only a very small test addition. Please split this into smaller PRs, e.g. UI shell, wacli/runtime packaging, read-only message sync, memory import, and send/auto-reply guardrails, with focused tests for each.
  • For any future version that can send or auto-send messages, please add tests and documentation around consent, allowlisting, kill switch behavior, rate limits, quiet hours, audit logs, and prompt/tool-call boundaries.

This is not a rejection of the idea; WhatsApp could be valuable for Omi. But this specific PR needs a much narrower, reviewable shape and maintainer-owned security/provenance decisions before it can proceed.

Fix validated WhatsApp webhook, draft, sync, and tool-runtime failure modes so local message handling is safer and avoids silent data loss, stale UI, and hung subprocesses.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 issues found across 17 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="desktop/macos/run.sh">

<violation number="1" location="desktop/macos/run.sh:592">
P1: Auto-detected signing identity now uses the SHA-1 hash, but the team-ID extraction still expects the display-name format, causing a false profile/team mismatch and an unintended fallback that strips the Sign In with Apple entitlement.</violation>
</file>

<file name="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift">

<violation number="1" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift:3">
P2: `@MainActor` isolation keeps expensive JSON parsing on the main actor, risking UI stalls despite the CLI execution being detached.</violation>

<violation number="2" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift:41">
P1: New diagnostics log raw WhatsApp CLI arguments and output, leaking JIDs/phone numbers and potential message content into local logs and Sentry breadcrumbs.</violation>

<violation number="3" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift:181">
P2: New guard in collectMessages drops text-only messages that lack senderJid, timestamp, or explicit ID; previously they were retained with a synthesized fallback ID.</violation>

<violation number="4" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift:244">
P2: Strict JID suffix filtering may exclude legitimate WhatsApp chat types not in the hard-coded list.</violation>
</file>

<file name="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppContactResolver.swift">

<violation number="1" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppContactResolver.swift:273">
P1: Restrictive JID allowlist silently rewrites valid explicit JIDs as phone-number `@s.whatsapp.net` recipients and may drop valid contacts from wacli output</violation>
</file>

<file name="desktop/macos/agent/src/wa-tools-stdio.ts">

<violation number="1" location="desktop/macos/agent/src/wa-tools-stdio.ts:131">
P1: Tool-call timeout rejects the caller without cancelling the Swift work or ensuring idempotency, risking duplicate side effects for mutating tools like wa_send_message.</violation>
</file>

<file name="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppMemoryImportService.swift">

<violation number="1" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppMemoryImportService.swift:337">
P1: Deterministic fallback message ID can cause persistent false deduplication when messages lack both an explicit source ID and a timestamp. Any later message with the same chat, sender, and text will map to the same persisted dedupe key and be silently skipped.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift Outdated
Comment thread desktop/macos/agent/src/wa-tools-stdio.ts
Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppMemoryImportService.swift Outdated
Comment thread desktop/macos/Desktop/Sources/Messaging/WhatsAppMessagingProvider.swift Outdated
Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppContactResolver.swift Outdated
Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift Outdated
Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift Outdated
PriyanshuDangi and others added 2 commits June 28, 2026 02:46
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 9 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppContactResolver.swift">

<violation number="1" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppContactResolver.swift:62">
P1: Recursive `detailLabel(for:)` follows `canonicalJid` pointers without cycle detection, which can stack-overflow on cyclic alias mappings from the cache or future `rememberAlias` calls.</violation>

<violation number="2" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppContactResolver.swift:82">
P2: canonicalJid(for:) performs only a one-hop alias lookup, while detailLabel(for:) recursively follows the same alias chain. displayName, phoneDigits, and resolveRecipient rely on canonicalJid and will therefore operate on an intermediate alias JID while detailLabel reaches the terminal canonical JID, producing inconsistent contact resolution and potentially returning a wrong recipient JID.</violation>
</file>

<file name="desktop/macos/Desktop/Sources/Messaging/WhatsAppMessagingProvider.swift">

<violation number="1" location="desktop/macos/Desktop/Sources/Messaging/WhatsAppMessagingProvider.swift:24">
P1: Thread loading now introduces serial N+1 `wacli` child-process calls per refresh, which can cause significant UI stalls on the @MainActor provider.</violation>

<violation number="2" location="desktop/macos/Desktop/Sources/Messaging/WhatsAppMessagingProvider.swift:161">
P2: Recent-activity verification can regress `lastActivity` by overwriting the provider-supplied timestamp with an older value derived from a limited message sample.</violation>

<violation number="3" location="desktop/macos/Desktop/Sources/Messaging/WhatsAppMessagingProvider.swift:196">
P1: Heuristic `@lid` aliasing plus thread-ID rewriting can mis-associate conversations, risking wrong-thread draft/message routing when a weak heuristic produces a false match.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppContactResolver.swift Outdated
Comment thread desktop/macos/Desktop/Sources/Messaging/WhatsAppMessagingProvider.swift Outdated
Comment thread desktop/macos/Desktop/Sources/Messaging/WhatsAppMessagingProvider.swift Outdated
Replace generic message icons with the bundled WhatsApp brand mark across
Messages and Settings, and stop double-dismissing the connect sheet so
closing it no longer sends the app to the background.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 9 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="desktop/macos/run.sh">

<violation number="1" location="desktop/macos/run.sh:592">
P1: Auto-detected signing identity now uses the SHA-1 hash, but the team-ID extraction still expects the display-name format, causing a false profile/team mismatch and an unintended fallback that strips the Sign In with Apple entitlement.</violation>
</file>

<file name="desktop/macos/Desktop/Sources/Messaging/MessagingProviderIcon.swift">

<violation number="1" location="desktop/macos/Desktop/Sources/Messaging/MessagingProviderIcon.swift:9">
P2: WhatsApp icon selection is hard-coded against the magic string `"whatsapp"`, tying the view to the provider's exact ID spelling instead of a typed brand or shared constant. This is brittle and easy to break when adding or renaming providers.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread desktop/macos/Desktop/Sources/Messaging/MessagingProviderIcon.swift Outdated

@Git-on-my-level Git-on-my-level left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for continuing to iterate on this. I’m still requesting changes on the current head (ce8e263) rather than approving.

The main blockers remain:

  • desktop/macos/Desktop/Sources/Resources/wacli is still a bundled ~44 MB Mach-O executable (3667afdad78021daa6825780208b8e2459701a91582479d4ca18e27248ceed2c). An opaque binary from a first-time contributor is not reviewable enough for this repo. Please remove it from the PR and use a maintainer-controlled, reproducible/provenance-backed packaging path for any WhatsApp runtime dependency.
  • This PR adds a high-risk surface: WhatsApp message/contact access, importing private WhatsApp history into Omi memories, a local webhook, agent-exposed WhatsApp tools, direct sending, and auto-reply/draft flows. That needs explicit product, privacy, and security review before merge.
  • The change is still too broad for safe review as one unit (38 files / ~6.6k changed lines) and has very limited tests relative to the risk. Please split this into narrower PRs such as runtime/provenance, UI shell, read-only sync, memory import, and send/auto-reply guardrails.
  • Before any send or auto-reply functionality can be considered, it needs focused tests/docs around consent, allowlisting, kill switch behavior, rate limits/quiet hours, audit logs, prompt/tool-call boundaries, and wrong-recipient prevention.

The idea may be valuable for Omi, but this needs a much narrower, source-reviewable shape plus maintainer-owned security/provenance decisions before it can proceed.

@PriyanshuDangi

Copy link
Copy Markdown
Author

@Git-on-my-level thanks for the feedback

  1. I will add more tests and add a doc or summary explaining all the design and decisions
  2. I'll resolve the cubic comments
  3. I am working on the AI clone feature in which the requirement is
    I want omi Omi to respond to people on my behalf using my apps
    And for this I am using @openclaw/wacli using which people can just login with a QR and can simply have draft and auto reply features
    (And it already syncs in with the brain only if the user clicks on the allow sync for whatsapp)

PriyanshuDangi and others added 4 commits June 28, 2026 23:30
…top-whatsapp

Co-authored-by: Cursor <cursoragent@cursor.com>
Redact sensitive WhatsApp diagnostics, preserve valid JIDs/messages during parsing, and add cancellation plus idempotency protection for timed-out WhatsApp tool calls.
Avoid coupling messaging icon rendering to provider ID strings by exposing typed connector brand metadata.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found across 10 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="desktop/macos/run.sh">

<violation number="1" location="desktop/macos/run.sh:592">
P1: Auto-detected signing identity now uses the SHA-1 hash, but the team-ID extraction still expects the display-name format, causing a false profile/team mismatch and an unintended fallback that strips the Sign In with Apple entitlement.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread desktop/macos/Desktop/Sources/Messaging/WhatsAppMessagingProvider.swift Outdated
Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppContactResolver.swift Outdated
Comment thread desktop/macos/agent/src/wa-tools-stdio.ts Outdated
Comment thread desktop/macos/agent/src/wa-tools-stdio.ts Outdated
Comment thread desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift Outdated
PriyanshuDangi and others added 2 commits June 29, 2026 00:55
Keep provider-facing pi-mono schemas compatible with models that reject root-level composite keywords, while preserving privacy-safe WhatsApp diagnostics.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 issues found across 9 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReplyCoordinator.swift">

<violation number="1" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReplyCoordinator.swift:549">
P1: The redacted JID label uses `String.hashValue`, which is randomized per-process launch and therefore not stable across app restarts. This makes the same WhatsApp chat/user/group appear under different pseudonyms in persistent logs, hindering log correlation and incident investigation. Replace it with a stable keyed digest (e.g., HMAC-SHA256).</violation>
</file>

<file name="desktop/macos/Desktop/Sources/Messaging/WhatsAppMessagingProvider.swift">

<violation number="1" location="desktop/macos/Desktop/Sources/Messaging/WhatsAppMessagingProvider.swift:133">
P1: Persisted canonical alias is preferred over the unique phone-number match when resolving @lid draft threads, without validating that the alias is still correct. A stale or ambiguous cached alias can attach a pending draft to the wrong conversation.</violation>
</file>

<file name="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppContactResolver.swift">

<violation number="1" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppContactResolver.swift:86">
P2: The first cycle-detection branch (`if let cycleStart = visitedIndex[current]`) is unreachable. It is redundant with the second branch and only adds dead code that may confuse maintenance of the alias-resolution logic.</violation>

<violation number="2" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppContactResolver.swift:340">
P1: Hard-coded WhatsApp JID server allowlist is missing valid server types defined by the underlying `whatsmeow` library, so contacts/JIDs from `msgr`, `interop`, `hosted`, `hosted.lid`, and `bot` servers will be silently rejected.</violation>
</file>

<file name="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift">

<violation number="1" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift:281">
P1: New WhatsApp JID server allowlist may silently drop valid chats whose server namespace is not enumerated</violation>

<violation number="2" location="desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift:365">
P1: Replacing ISO8601DateFormatter with strict ISO8601FormatStyle may fail to parse RFC3339 timestamps with colon-separated timezone offsets (e.g., `+02:00`), causing missing timestamps and duplicate fallback message IDs.</violation>
</file>

<file name="desktop/macos/agent/src/wa-tools-stdio.ts">

<violation number="1" location="desktop/macos/agent/src/wa-tools-stdio.ts:101">
P1: WhatsApp send idempotency is now tied to the JSON-RPC request id, breaking deduplication for MCP retries that use a different id and removing generated idempotency for idless tool calls.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

} else {
kind = "user"
}
return "\(kind)@\(server)#\(String(normalized.hashValue, radix: 16))"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The redacted JID label uses String.hashValue, which is randomized per-process launch and therefore not stable across app restarts. This makes the same WhatsApp chat/user/group appear under different pseudonyms in persistent logs, hindering log correlation and incident investigation. Replace it with a stable keyed digest (e.g., HMAC-SHA256).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReplyCoordinator.swift, line 549:

<comment>The redacted JID label uses `String.hashValue`, which is randomized per-process launch and therefore not stable across app restarts. This makes the same WhatsApp chat/user/group appear under different pseudonyms in persistent logs, hindering log correlation and incident investigation. Replace it with a stable keyed digest (e.g., HMAC-SHA256).</comment>

<file context>
@@ -536,6 +534,21 @@ final class WhatsAppReplyCoordinator: ObservableObject {
+    } else {
+      kind = "user"
+    }
+    return "\(kind)@\(server)#\(String(normalized.hashValue, radix: 16))"
+  }
+
</file context>

Comment on lines +133 to +134
if let match = canonicalAliasMatchedThreadId(for: draft, in: threads)
?? phoneMatchedThreadId(for: draft, in: threads)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Persisted canonical alias is preferred over the unique phone-number match when resolving @lid draft threads, without validating that the alias is still correct. A stale or ambiguous cached alias can attach a pending draft to the wrong conversation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At desktop/macos/Desktop/Sources/Messaging/WhatsAppMessagingProvider.swift, line 133:

<comment>Persisted canonical alias is preferred over the unique phone-number match when resolving @lid draft threads, without validating that the alias is still correct. A stale or ambiguous cached alias can attach a pending draft to the wrong conversation.</comment>

<file context>
@@ -130,7 +130,9 @@ final class WhatsAppMessagingProvider: MessagingProvider {
 
     for draft in drafts where draft.chatJid.contains("@lid") {
-      if let match = phoneMatchedThreadId(for: draft, in: threads) {
+      if let match = canonicalAliasMatchedThreadId(for: draft, in: threads)
+        ?? phoneMatchedThreadId(for: draft, in: threads)
+      {
</file context>
Suggested change
if let match = canonicalAliasMatchedThreadId(for: draft, in: threads)
?? phoneMatchedThreadId(for: draft, in: threads)
if let match = phoneMatchedThreadId(for: draft, in: threads)
?? canonicalAliasMatchedThreadId(for: draft, in: threads)
{


private func isKnownWhatsAppServer(_ server: String) -> Bool {
switch server {
case "s.whatsapp.net", "c.us", "g.us", "lid", "broadcast", "newsletter":

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Hard-coded WhatsApp JID server allowlist is missing valid server types defined by the underlying whatsmeow library, so contacts/JIDs from msgr, interop, hosted, hosted.lid, and bot servers will be silently rejected.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At desktop/macos/Desktop/Sources/WhatsApp/WhatsAppContactResolver.swift, line 340:

<comment>Hard-coded WhatsApp JID server allowlist is missing valid server types defined by the underlying `whatsmeow` library, so contacts/JIDs from `msgr`, `interop`, `hosted`, `hosted.lid`, and `bot` servers will be silently rejected.</comment>

<file context>
@@ -326,7 +331,38 @@ final class WhatsAppContactResolver: ObservableObject {
+
+  private func isKnownWhatsAppServer(_ server: String) -> Bool {
+    switch server {
+    case "s.whatsapp.net", "c.us", "g.us", "lid", "broadcast", "newsletter":
+      return true
+    default:
</file context>
Suggested change
case "s.whatsapp.net", "c.us", "g.us", "lid", "broadcast", "newsletter":
case "s.whatsapp.net", "c.us", "g.us", "lid", "broadcast", "newsletter", "msgr", "interop", "hosted", "hosted.lid", "bot":

return nil
}

private static func parseISO8601Date(_ value: String) -> Date? {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Replacing ISO8601DateFormatter with strict ISO8601FormatStyle may fail to parse RFC3339 timestamps with colon-separated timezone offsets (e.g., +02:00), causing missing timestamps and duplicate fallback message IDs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift, line 365:

<comment>Replacing ISO8601DateFormatter with strict ISO8601FormatStyle may fail to parse RFC3339 timestamps with colon-separated timezone offsets (e.g., `+02:00`), causing missing timestamps and duplicate fallback message IDs.</comment>

<file context>
@@ -349,6 +362,13 @@ enum WhatsAppReader {
     return nil
   }
 
+  private static func parseISO8601Date(_ value: String) -> Date? {
+    if let date = try? iso8601FractionalDateStyle.parse(value) {
+      return date
</file context>


private static func isKnownWhatsAppServer(_ server: String) -> Bool {
switch server {
case "s.whatsapp.net", "c.us", "g.us", "lid", "broadcast", "newsletter":

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: New WhatsApp JID server allowlist may silently drop valid chats whose server namespace is not enumerated

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At desktop/macos/Desktop/Sources/WhatsApp/WhatsAppReader.swift, line 281:

<comment>New WhatsApp JID server allowlist may silently drop valid chats whose server namespace is not enumerated</comment>

<file context>
@@ -269,7 +272,17 @@ enum WhatsAppReader {
+
+  private static func isKnownWhatsAppServer(_ server: String) -> Bool {
+    switch server {
+    case "s.whatsapp.net", "c.us", "g.us", "lid", "broadcast", "newsletter":
+      return true
+    default:
</file context>

return input;
}
const scope = {
mcpRequestId,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: WhatsApp send idempotency is now tied to the JSON-RPC request id, breaking deduplication for MCP retries that use a different id and removing generated idempotency for idless tool calls.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At desktop/macos/agent/src/wa-tools-stdio.ts, line 101:

<comment>WhatsApp send idempotency is now tied to the JSON-RPC request id, breaking deduplication for MCP retries that use a different id and removing generated idempotency for idless tool calls.</comment>

<file context>
@@ -67,18 +67,38 @@ function stableJSONStringify(value: unknown): string {
+    return input;
+  }
   const scope = {
+    mcpRequestId,
     requestId: context.requestId,
     clientId: context.clientId,
</file context>

while let canonical = contactsByJid[current]?.canonicalJid?.nilIfEmpty.map(normalizeJid),
canonical != current
{
if let cycleStart = visitedIndex[current] {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The first cycle-detection branch (if let cycleStart = visitedIndex[current]) is unreachable. It is redundant with the second branch and only adds dead code that may confuse maintenance of the alias-resolution logic.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At desktop/macos/Desktop/Sources/WhatsApp/WhatsAppContactResolver.swift, line 86:

<comment>The first cycle-detection branch (`if let cycleStart = visitedIndex[current]`) is unreachable. It is redundant with the second branch and only adds dead code that may confuse maintenance of the alias-resolution logic.</comment>

<file context>
@@ -78,14 +78,19 @@ final class WhatsAppContactResolver: ObservableObject {
     {
-      guard !visited.contains(current), !visited.contains(canonical) else {
-        return current
+      if let cycleStart = visitedIndex[current] {
+        return stableCycleRepresentative(Array(path[cycleStart...]))
+      }
</file context>

@Git-on-my-level Git-on-my-level left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the continued iteration. I’m requesting changes on the current head (de83fa2) rather than approving.

The existing high-level blockers still apply: this is a broad WhatsApp integration touching private message/contact access, memory import, local webhook handling, agent-exposed WhatsApp tools, direct sending, auto-reply, runtime packaging, and an opaque bundled wacli executable. It needs maintainer product/security/privacy/provenance review and a much smaller split before merge.

One specific blocker I want to call out on this head:

  • WhatsAppReplyCoordinator.draftReply exposes the full ChatToolExecutor.execute tool surface to a model session whose prompt includes untrusted WhatsApp message text and recent thread content. Because that tool surface includes wa_send_message, a malicious incoming WhatsApp message could try to prompt-inject the drafting agent into sending messages during draft generation, before the UI approval/allowlist/auto-reply decision path. Draft generation should be read-only by construction: expose only safe read/context tools there, block wa_send_message from that session, and route all sends exclusively through explicit user approval or the separately reviewed auto-reply guardrail path.

Additional blockers remain:

  • desktop/macos/Desktop/Sources/Resources/wacli is still a bundled ~44 MB Mach-O universal executable (3667afdad78021daa6825780208b8e2459701a91582479d4ca18e27248ceed2c). Please remove opaque binaries from the PR and use a maintainer-controlled, reproducible/provenance-backed packaging path.
  • The PR is still too large for safe review as one unit (43 files / ~6.7k changed lines) with very limited tests relative to the risk. Please split into narrower PRs, e.g. runtime/provenance, UI shell, read-only sync, memory import, and send/auto-reply guardrails.
  • Send/auto-reply functionality needs focused tests/docs for consent, prompt/tool-call boundaries, wrong-recipient prevention, allowlisting, kill switch behavior, rate limits/quiet hours, audit logs, and failure/retry semantics.

The product idea may be valuable for Omi, but this needs a much narrower and source-reviewable shape before it can proceed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependency-review Touches dependencies or lockfiles; needs dependency review feature-fit-review PR touches feature direction; qualitative fit assessed needs-maintainer-review Needs a human maintainer to review/approve (e.g. stacked, product, or architecture judgment) needs-scope-reduction PR scope is too large or combines too many concerns for effective review needs-tests Needs additional or corrected test coverage security-review Needs security/privacy review workflow-review Needs maintainer review for workflow, automation, hooks, or CI behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants