@murphai/inboxd
v0.1.15
Published
Local inbox ingestion runtime for Murph.
Readme
@murphai/inboxd
Source-agnostic inbox ingestion for Murph.
This package keeps canonical inbox evidence in the vault and uses a local SQLite runtime database for source cursors, a durable local capture mutation cursor, transient dedupe caches, capture-local search tables, and attachment job state.
Stateless provider ingress semantics that need to be shared with hosted callers
now live in @murphai/messaging-ingress. @murphai/inboxd consumes that package
for provider webhook parsing/minimization and keeps ownership of polling
drivers, runtime state, and capture persistence.
Runtime expectations
- Run on Node.js
>=22.16.0. @murphai/inboxdresolves runtime paths and opens its SQLite runtime database through@murphai/runtime-state, storing machine-local state under<vault>/.runtime/inboxd.sqlite.- Query-owned lexical search state lives separately under
<vault>/.runtime/search.sqlite. - The package writes runtime state next to the vault and expects normal local filesystem read/write access there.
Core model
- every inbound source normalizes into a single
InboundCaptureenvelope - raw source evidence is persisted under
raw/inbox/<source>/... - append-only
ledger/inbox-captures/YYYY/YYYY-MM.jsonlrecords the authoritative structured inbox-capture trail - append-only vault events and audits remain compatibility and audit projections layered on top of that canonical capture log
- inbox SQLite runtime state lives under
<vault>/.runtime/inboxd.sqlite - any idempotent promotion from inbox captures into canonical records must be
derivable from canonical vault evidence rather than local
.runtimestate alone
Current scope
- connector contracts for polling and webhook sources
- a generic normalized chat-poll connector factory for source-specific transports
- iMessage and Telegram poll connectors over injected driver boundaries
- source-specific checkpoints for connectors whose cursors are not derivable from
occurredAt/externalId - capture pipeline with atomic raw persistence, inbox-capture ledger append, compatibility event/audit append, dedupe, FTS, and a durable local capture mutation cursor for downstream projections like the gateway store
- runtime list, show, and search helpers for future CLI/agent surfaces
vault-cli inbox ...is the intended human/operator surface layered on top of this package
Parser-facing runtime operations
The inbox runtime exposes attachment-job primitives that stay safely outside canonical storage:
claimNextAttachmentParseJob(...)completeAttachmentParseJob(...)failAttachmentParseJob(...)requeueAttachmentParseJobs(...)
These methods mutate only inbox-local runtime state such as .runtime/inboxd.sqlite and attachment parse metadata. They do not write canonical health records directly.
When combined with @murphai/parsers, operators can drive those queues through vault-cli inbox setup|doctor|parse|requeue without mixing parser state into canonical health records.
@murphai/inboxd also owns the optional inbox-plus-parser composition helpers
createParsedInboxPipeline(...) and runInboxDaemonWithParsers(...), so the
parser package stays focused on parser contracts, registry/toolchain discovery,
and parse execution rather than on inbox runtime orchestration.
Telegram adapter contract
The Telegram connector is local-first and poll-first by default.
- Use
createTelegramBotApiPollDriver(...)when you want the package to construct a grammY-backed poll driver from a bot token. - Use
createTelegramApiPollDriver({ api })when you already have a grammYApiinstance. - The connector stores source-native cursors such as Telegram
update_idcheckpoints instead of forcing every source through the sameoccurredAt/externalIdcursor shape. - Downloaded media can be persisted directly from in-memory bytes, so remote transports do not need temp files just to enter the vault.
- Telegram backfill drains pending updates page-by-page so source-native cursors only advance after captures have been normalized and persisted locally.
- Local Bot API servers that return absolute file paths from
getFileare supported during attachment hydration. - The CLI runtime expects a bot token in
TELEGRAM_BOT_TOKENorTELEGRAM_BOT_TOKENwhen it instantiates the grammY-backed Telegram poll driver.
iMessage adapter contract
The iMessage connector is macOS-only. @murphai/inboxd now depends directly
on @photon-ai/imessage-kit, and loadImessageKitDriver() adapts its
IMessageSDK surface onto the inboxd polling driver contract.
- Any workspace that runs
@murphai/inboxdorvault-climust install the package dependency tree, including the native SQLite dependency chain that@photon-ai/imessage-kitexpects at runtime. vault-cli inbox doctorstill separates adapter wiring from the live probe:driver-importconfirms the driver boundary is available, whileprobeexercises the actual SDK/database access.- Other inbox connectors remain source-agnostic, but the package install now always includes the iMessage adapter.
Operator notes
- Use
vault-cli inbox doctor --source-id imessage:selfbeforebackfillorrunto confirm macOS access, Messages database readability, and adapter importability. - A
probefailure usually means macOS denied Messages database access or the underlying SQLite/native dependency stack failed to initialize cleanly.
