Files
RedditBot/docs/services.md
T

13 KiB

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-user-messenger.ts Account selection for explicit API/MCP messages Prefer the newest existing conversation owner; otherwise choose the authenticated running account with the fewest hourly sends.
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/account-runtime-event-wiring.ts Per-account chat-to-realtime event bridge Every account runtime publishes reply, media, and sync events into the shared dashboard/push stream; sync IDs remain account-scoped.
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, post/comment candidate fetching, reaction/age/gender/seller screening, rejection summaries Comment reactions fail closed at the confidence and target-gender gates; cheap checks run first; preserve exact rejection/deferred counts; listing 404 disables the subreddit.
reddit/api.ts Reddit JSON calls, post/comment 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/physique-targeting.ts Pure optional score-range decision for image candidates Disabled means pass; enabled ranges reject unknown and out-of-range scores before opener generation.
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, prepared-message replacement, counts, and manual clearing Mutations require an eligible state or expected worker lease; recover expired/interrupted work; operator edits clear AI attribution; manual removals preserve sending leases and terminal audit rows.

Account growth

Comment-based growth exists so a new account accumulates the age/karma history Reddit requires before it will accept chat invitations. It is account-scoped rather than part of the shared outreach funnel, it is the lowest-priority work an account runtime performs, and it deliberately keeps running while the account is held out of outbound messaging — building that history is what lifts the hold.

Module Owns Important constraints
services/account-growth.ts Per-account discovery, generation, posting, verification, and trust updates Auto-posts without operator review, so both screening stages fail closed; due retries and existing queue work run before discovery; an interrupted post is never retried.
services/growth-pacer.ts Adaptive allowance ladder, the operator limit override, promote/demote/pause decisions, quiet hours, spacing Pure and clock-injected. Pause beats demote beats promote; an operator limit replaces the earned allowance but never the pause; jitter is derived from the previous post so the gate cannot flap.
services/growth-thread-screening.ts Pure thread eligibility (age window, comment count, locked/stickied/NSFW) A comment on a dead or saturated thread wastes a scarce daily allowance.
services/growth-comment-safety.ts Deterministic pre-publication gate on generated comment text Rejects links, contact solicitation, user tags, filler, and any text revealing the generator. Independent of prompt wording.
reddit/comment-client.ts Comment submission and comment-state lookups for one account Classifies Reddit's error codes into retry/abandon/disable/re-auth/stop; runs inside the account's own browser session and shares the request coordinator.
database/growth-repository.ts Growth settings, per-account community list, durable comment records One comment per thread across every account; mutations require the expected worker lease; queue clearing deletes only unposted discovered/retryable rows.
services/account-browsing-simulation.ts Durable pacing, eligibility, post/comment weighting, selection, and optional vote dispatch Runs below comment growth; votes require the per-account opt-in plus running mode outside dry-run, and uncertain writes are never retried.
database/browsing-simulation-repository.ts Per-account browsing policy, cross-account selection checks, and minimal decision audit Stores identity/permalink, safe reasons, and durable vote state without copying Reddit content; browsing never feeds comment trust.

Verification is the safety mechanism that matters most. Posted comments are swept at roughly 15 minutes, 2 hours, and 24 hours using one batched info.json request, and a single signed-out probe on the second sweep decides whether the comment is publicly visible at all. Two consecutive removals, or one invisible comment, hard-pauses the account until an operator clears it; a failed probe never pauses anything.

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. Learning responsibilities are deliberately split: conversation-attribution.ts reconciles authorship, conversation-learning-extractor.ts derives credit and decisions, conversation-learning-redactor.ts enforces data minimisation, conversation-learning-provider.ts retrieves bounded examples, and conversation-learning-evaluator.ts runs offline hard gates. SQLite ownership stays in the event and learning repositories. ChatService only calls the narrow observer interface after authoritative synchronization.