Repository navigation
Expand file tree
/
Copy pathdev.edn
More file actions
76 lines (64 loc) · 4.66 KB
/
Copy pathdev.edn
File metadata and controls
76 lines (64 loc) · 4.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
{:reader.log/publisher {:pretty? true}
:reader.concerns/http-kit {:opts {:port 3000}}
:reader.web/csrf {:site-origin "http://localhost:3000"}
;; Points at the shared dev Hanko Cloud project (Hanko dashboard → your
;; project). `api-url` is the bare project base; the middleware derives the
;; JWKS URL (base + /.well-known/jwks.json) from it, and the login element
;; (below) talks to the same base — swap both to use your own project.
;; `issuer` is intentionally left unset — the project-specific JWKS already
;; binds tokens to this project; pin it later if you want defense in depth.
;; allowed-emails is the dev invite list. It's a single throwaway identity,
;; `test@example.com`, which `bb db:seed` also provisions as a user with a
;; populated queue — make a Hanko user for it and sign in to land on real data.
:reader.auth/middleware {:api-url "https://61ea63c0-a1ce-428e-8f22-30fa5c5cb455.hanko.io"
:allowed-emails #{"test@example.com"}}
:reader.handlers.auth/login {:api-url "https://61ea63c0-a1ce-428e-8f22-30fa5c5cb455.hanko.io"}
;; Persist the embedded-postgres data dir so the dev DB (and your seeded user
;; + queue) survives a server restart or REPL `(reset)`. Tests leave this unset,
;; so each run still gets a fresh throwaway cluster. Delete the dir for a clean
;; slate (e.g. after a destructive migration).
:reader.dev.infra/postgres {:data-dir "/tmp/reader-dev-db"}
;; Dev uses the local-filesystem blob store (no uploads), rooted at the
;; configurable const from embedded-db.edn — override there to relocate it.
:reader.storage/store {:backend :file :root #ig/ref :reader.storage/file-root}
;; The :ingest-email handler reads the raw .eml from blob storage (the local
;; file store in dev — a REPL can seed it to exercise the path locally).
:reader.ingest/ingest-email-handler {:storage #ig/ref :reader.storage/store}
:reader.ingest/reprocess-newsletter-handler {:storage #ig/ref :reader.storage/store}
;; Tagging model clients. Default to OpenRouter, but stay stubbed until a key is
;; set: no LLM_API_KEY → the title-derived stub tagger and deterministic stub
;; embedder, so dev runs the tag pipeline with no account. Set LLM_API_KEY (and
;; EMBED_API_KEY) to exercise a real model; override LLM_MODEL / *_API_URL for a
;; different model or a local endpoint.
:reader.ai/complete {:api-url #env/opt ["LLM_API_URL" "https://openrouter.ai/api/v1"]
:api-key #env/opt "LLM_API_KEY"
:model #env/opt ["LLM_MODEL" "openai/gpt-4o-mini"]
:max-tokens 512}
:reader.ai/embed {:api-url #env/opt ["EMBED_API_URL" "https://openrouter.ai/api/v1"]
:api-key #env/opt "EMBED_API_KEY"
:model #env/opt ["EMBED_MODEL" "openai/text-embedding-3-small"]
:dimensions 256}
;; :response-format pins the tagger's output shape. :json-schema (strict
;; Structured Outputs) suits the default model; switch to :json-object or :none
;; for an endpoint that doesn't support it.
:reader.ingest.tag/tagger {:model #env/opt ["LLM_MODEL" "openai/gpt-4o-mini"]
:response-format :json-schema}
:reader.ingest.tag-job/handler {:embed-model #env/opt ["EMBED_MODEL" "openai/text-embedding-3-small"]}
;; Background worker draining the ingest jobs (manual URL + inbound email + tagging).
:reader.jobs/worker {:datasource #ig/ref :reader.db/migrator
:handlers {"extract-article" #ig/ref :reader.ingest/extract-article-handler
"ingest-email" #ig/ref :reader.ingest/ingest-email-handler
"reprocess-newsletter" #ig/ref :reader.ingest/reprocess-newsletter-handler
"extract-paper" #ig/ref :reader.papers/extract-paper-handler
"tag-readable" #ig/ref :reader.ingest.tag-job/handler}
:poll-ms 1000
:max-attempts 5
:backoff-base-secs 10}
;; The seeded test user can see the eval dashboard in dev.
:reader.handlers.admin/extractions {:admin-emails #{"test@example.com"}}
;; Placeholder inbound-email domain for dev — the :direct receiver below takes
;; injected .eml, but no real mail is delivered (no Cloudflare worker / domain).
:reader.inbound/domain "inbox.reader.test"
;; Dev receives inbound email directly: POST a raw .eml to /api/inbound?alias=…
;; (no HMAC/worker/R2). Open on localhost; set :token for a reachable tenant.
:reader.handlers/inbound {:impl :direct :storage #ig/ref :reader.storage/store}}