Files
RedditBot/docs/services.md
T
Jamie BruntonandClaude Opus 5 ac12a3146a feat: recover missing conversations, fix media attachment, add manual inbox tab
Missing conversations: recipient Reddit accounts that are deleted or suspended
left conversations unaccounted for. A new RecipientAccountStatusService polls
Reddit for the users behind cached conversations and records their account
status durably, with progressive backfill and delta-media fixes in ChatService
so history and images are no longer dropped mid-sync.

Media: attachMedia now surfaces download failures as MediaAttachmentError so the
sync cursor can be retried instead of silently losing an image, recognizes image
bytes when Matrix returns a generic content type, and keeps separate gallery
occurrences when the same asset appears in more than one event.

Manual inbox tab: the conversations list now carries the reply-loop status, so
the inbox can separate conversations the operator is driving by hand from the
ones automation is still handling. A Manual filter pill and a per-row chip
explain why each conversation was handed over.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 11:03:33 +01:00

101 lines
8.6 KiB
Markdown

# Service and module map
This is an ownership map, not an API dump. Read the owning implementation and tests before changing behavior.
## Lifecycle and account ownership
| Module | Owns | Important constraints |
| --- | --- | --- |
| `src/bootstrap.ts` | Dependency composition and startup wiring | Keep business policy in services; preserve initialization order and test seams. |
| `src/main-loop.ts` | Shared discovery/screening/dispatch workers and legacy loop | Loops are abortable; queue transitions and shutdown must remain recoverable. |
| `services/reddit-account-runtime.ts` | Immutable account runtime/factory/manager lifecycle | Same-account operations serialize; session refresh replaces one runtime. |
| `services/reddit-account-runtime-builder.ts` | Concrete account dependency graph and account loop | Account-specific browser, Matrix, repos, limiter, automation, chat, and media live here. |
| `services/reddit-accounts.ts` | Account import/activation orchestration | Verification must bind Reddit cookies and Matrix identity before activation. |
| `services/account-auth-context.ts` | Current verified identity snapshot | Account work pauses unless both sides authenticate. |
| `services/session-bound-runtime.ts` | Legacy auth-bound background lifecycle | Prevents background work while logged out. |
## Discovery, preparation, and delivery
| Module | Owns | Important constraints |
| --- | --- | --- |
| `services/monitor.ts` | Subreddit ordering, candidate fetching, age/gender/seller screening, rejection summaries | Cheap checks first; preserve exact rejection/deferred counts; listing 404 disables the subreddit. |
| `reddit/api.ts` | Reddit JSON calls, post parsing, seller/profile evidence, username resolution, error types | All reads must use the coordinator; redact error metadata. |
| `reddit/request-coordinator.ts` | Process-wide Reddit request spacing and cooldown | Space failed requests too; 429 cooldown is global. |
| `services/processor.ts` | Source-specific AI preparation and outbound safety | Returns prepared or explicit skip; performs no remote chat send. |
| `services/strategy-selector.ts` | Weighted explore/exploit selection and experiment metadata | Separate image/chat strategy sections; respect mature response window and sample floor. |
| `services/recipient-deduplicator.ts` | Global recipient history plus live reservation | Case-insensitive; release failures, commit successes, recover stale claims. |
| `utils/rate-limiter.ts` | Per-account send spacing/hour limits/jitter | Increment only for confirmed sends; reply priority may use the same limiter. |
| `database/candidate-queue-repository.ts` | Durable candidate state machine, leases, retries, counts | Mutations require the expected worker lease; recover expired/interrupted work. |
## Conversation, chat, and media
| Module | Owns | Important constraints |
| --- | --- | --- |
| `services/chat/service.ts` | Matrix conversation sync, cache updates, starts/replies, scoped cooldowns | Room-creation limits pause new outreach without blocking existing-room replies; Matrix acceptance and UI visibility are distinct. |
| `services/chat/matrix/client.ts` | Matrix HTTP protocol and error classification | Authentication/rate-limit errors need typed handling. |
| `services/chat/cache.ts` | Account-scoped cached conversations and sync state | SQLite is durable; do not share caches across accounts. |
| `services/chat/matrix/username-resolver.ts` | Matrix/Reddit identity mapping | Preserve unresolved internal IDs without leaking them in operator text. |
| `services/chat/matrix/token-refresher.ts` | Explicit refresh-unavailable behavior | New credentials come from verified extension dumps, not token sniffing. |
| `services/recipient-account-status.ts` | Periodic cached-conversation recipient profile checks | Only definitive Reddit results replace durable state; checks are authentication-bound and must not block the reply loop. |
| `services/conversation-automation.ts` | Reply-first policy, claims, retries, send-time refresh, handoffs, turn budgets | Snapshot policy; claim before send; supersede stale queued work; reconcile pending claims; fail closed. |
| `services/conversation-state.ts` | Pure conversation parsing/state/safety helpers | Conversation text is untrusted data; keep prompt boundaries explicit. |
| `services/conversation-boundaries.ts` | Sequence-aware media requests, refusals, and full-stop detection | Short ambiguous replies become boundaries only in the matching request context. |
| `services/outbound-message-safety.ts` | Final no-proximity/no-meeting rule | This is defense in depth beyond prompts. |
| `services/conversation-outcome*.ts` | Response outcome classification/recording | Keep analytics attribution account/message scoped. |
| `services/response-checker.ts` | Inbox/performance response checks and successful examples | Non-overlapping; do not confuse chat sync with outcome maturity. |
| `services/media.ts` | Download, verify, index, and list private media occurrences while reusing asset files | Preserve account ownership, retryable download failures, and authenticated serving. |
| `services/media-sync.ts` | Periodic authenticated media sync and operator-visible completion status | Stop while auth is unavailable and on runtime shutdown; do not report partial work as success. |
| `services/media-library.ts` | Shared operator uploads, image validation/re-encoding, classification state, and private files | Require consent confirmation; received media never enters this store. |
| `services/media-library-exchange.ts` | Inbound request detection, progressive selection, reservation, and image-first exchange | Never offer proactively; exact tags do not substitute; no asset reuse per conversation. |
| `database/media-library-repository.ts` | Shared asset metadata and durable account/conversation send audit | Reserve before remote send; uncertain sends stay consumed. |
## Persistence
| Module | Owns |
| --- | --- |
| `database/client.ts` | Database open settings and ordered migrations. |
| `database/repositories.ts` | Posts, messages, successes, activity, outbox, states, claims, outcomes, users, recipient history. |
| `database/account-repositories.ts` | Verified account records, conversations, sync cursors, and media content. |
| `database/ai-usage-repository.ts` | Model request/cost/reliability records. |
| `database/legacy-content-import.ts` | One-time ownership of legacy file-backed chat/media data. |
| `config/persistence.ts` | Secret-free application configuration in SQLite. |
Repositories should expose domain operations rather than raw SQL to callers. Multi-step state transitions belong in SQLite transactions when partial completion would break invariants.
## Web and agent surfaces
| Module | Owns |
| --- | --- |
| `web/server.ts` | Express lifecycle, middleware order, route registration, static dashboard/media. |
| `web/auth.ts` | Dashboard session and bearer-token authorization. |
| `web/context.ts` | Narrow route dependency container. |
| `web/routes/*.ts` | Focused endpoint families. |
| `web/api-catalog.ts` | Operation metadata, OpenAPI, and capability discovery. |
| `web/agent-job-manager.ts` | Bounded async sync jobs and job status. |
| `web/events/*` | Typed event publication, replay, subscriptions, and Express SSE. |
| `web/log-broadcaster.ts` | Recent logs plus legacy/typed stream adapters. |
| `mcp/api-client.ts`, `mcp/server.ts` | HTTP-backed stdio MCP tools. |
Authorization is semantic, not just authentication: read and control agent tokens intentionally cannot import sessions, send messages, activate accounts, mutate legacy config, or use debug routes.
## Frontend
| Area | Owns |
| --- | --- |
| `apps/dashboard/src/app/` | Shell, routing, providers, auth status, notifications, realtime repair. |
| `apps/dashboard/src/api/` | HTTP client, schema parsing, query keys/hooks. |
| `apps/dashboard/src/features/` | Route-level feature slices. |
| `apps/dashboard/src/components/` | Reusable domain-aware UI elements. |
| `packages/api-contracts/` | Shared strict transport schemas and inferred types. |
## Utility boundaries
- `utils/logger.ts`: Winston creation, child context, and attachable sinks. No production `console.log`.
- `utils/retry.ts`: bounded retry behavior for operations that are safe to repeat.
- `utils/image.ts`: download/MIME/size helpers.
- `utils/gender-tag.ts`: deterministic self-declared tag parsing.
- `utils/fetch-with-timeout.ts`: abortable HTTP timeout wrapper.
- `utils/json-safe.ts`: safe serialization for log/event data.
When a module starts owning two independent reasons to change, extract a narrow collaborator and inject it. Do not solve size alone by moving methods into a generic utility file.