feat: add local service detection and reliable SMS fallback#133
Conversation
Adds local (chat.db-backed) messaging-service intelligence to `imsg send` and SIP-free `--local` modes to the bridge-backed intro commands, so common availability/account/contact lookups work without disabling SIP or running `imsg launch`. Motivated by daemon/headless use where SIP must stay enabled. send: - Auto service resolution in `--service auto`: for direct (`--to`) phone/email sends, infer iMessage vs SMS from local chat.db history before sending. Chat-target sends and explicit `--service` are unchanged. - iMessage->SMS fallback: on a failed iMessage send to a phone-number recipient, automatically retry over SMS. On by default; add `--no-sms-fallback` to disable. Never engages for chat targets or email recipients. whois: - New `--local` flag: infer the preferred service (imessage/sms/unknown) from local chat.db history instead of the IMCore bridge. No SIP required. Unknown handles (no local history) are reported honestly as "unknown". account: - New `--local` flag: list iMessage account login(s) recorded in local chat.db, ranked by chat count. No SIP required. Reflects accounts observed in history rather than the live signed-in account. nickname: - New `--local` flag: return the local AddressBook contact name for a handle. Clearly relabeled as `local_contact_name` with a caveat that this is NOT the iMessage-shared nickname (which remains bridge-only). core: - MessageStore.preferredService(forHandle:) ports mac_messages_mcp's availability heuristic (handle.service + non-errored message history) with phone-format candidate expansion (bare / country-coded / +-prefixed). - MessageStore.localAccounts() enumerates distinct account_login/account_id from chat.db. Both are schema-guarded and degrade gracefully. All new behavior is additive and SIP-free; existing bridge/RPC/send paths are unchanged (verified: other MessageSendOptions call sites use chat targets, so SMS fallback never triggers there). 21 new tests; full suite 309 passing. swift-format lint clean.
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: feat: add local service detection and reliable SMS fallback This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: da74ce3df8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if includeAnyForSMS, !trimmed.isEmpty { | ||
| candidates = ["SMS;-;\(trimmed)", "any;-;\(trimmed)", "any;+;\(trimmed)"] |
There was a problem hiding this comment.
Normalize SMS bridge lookup candidates
When an RPC direct send is service:auto and local history marks the recipient as SMS via region normalization (for example to:"07700 900000", region:"GB" with an existing chat stored as SMS;-;+447700900000), handleSend switches effectiveService to SMS but this exact bridge lookup only tries identifiers built from the raw recipient. In that case directChatInfo stays nil, so transport:"bridge" incorrectly reports no existing chat and auto transport skips the ready bridge path, even though the local SMS chat is present.
Useful? React with 👍 / 👎.
Summary
--locallookups #132 via maintainer branch with hardened send service routingProof