3 Commits

Author SHA1 Message Date
9f20110f56 🐾 feat(library): add 'email' library type
Kairos is about to provision per-user app-managed (workspace) libraries for
synced mail, and none of the existing types fit correspondence. New entry in
LIBRARY_TYPE_DEFAULTS mirrors journal's entry-level chunking (one message ≈
one entry) with instructions tuned for email: correspondents, dates,
requests/commitments, and quoted-reply context. Registered in the Library
node choices and the API serializer choice list; forms and
load_library_types derive from the registry, and the compose init sidecar
re-runs the seeder on deploy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 08:03:28 -04:00
d6b541636a Merge pull request '🐾 feat(settings): register kairos-mail source bucket for ingest' (#3) from feat/kairos-mail-bucket into main
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 4m22s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m26s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m53s
Reviewed-on: #3
2026-07-12 11:50:53 +00:00
d01afd6203 🐾 feat(settings): register kairos-mail source bucket for ingest
Kairos is about to start announcing rendered mail documents to
POST /library/api/ingest/ with source="kairos-mail". Without a registry
entry, unknown sources fall back to the daedalus bucket and every worker
fetch fails — this adds the KAIROS_S3_* env vars (pattern-copy of the
spelunker block) and the SOURCE_S3_BUCKETS["kairos-mail"] entry, plumbed
through .env.example and the worker service in docker-compose.

Settings-only; no code changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 07:36:12 -04:00
7 changed files with 74 additions and 1 deletions

View File

@@ -91,6 +91,19 @@ SPELUNKER_S3_REGION_NAME=us-east-1
SPELUNKER_S3_USE_SSL=True
SPELUNKER_S3_VERIFY=True
# --- Kairos S3 (cross-bucket reads for ingest, source="kairos-mail") ---
# Consumed by: worker only
# Kairos renders synced mail to text documents in its own bucket and posts
# ingest requests with source="kairos-mail". These creds should be scoped
# read-only to the Kairos bucket in your secret manager.
KAIROS_S3_ENDPOINT_URL=https://nyx.helu.ca:8555
KAIROS_S3_ACCESS_KEY_ID=
KAIROS_S3_SECRET_ACCESS_KEY=
KAIROS_S3_BUCKET_NAME=kairos
KAIROS_S3_REGION_NAME=us-east-1
KAIROS_S3_USE_SSL=True
KAIROS_S3_VERIFY=True
# --- Celery / RabbitMQ (Oberon) ---------------------------------------------
# Consumed by: app (producer), worker (consumer). NOT mcp.
# Remember to percent-encode any password characters that have meaning in a

View File

@@ -346,6 +346,13 @@ services:
- SPELUNKER_S3_REGION_NAME=${SPELUNKER_S3_REGION_NAME}
- SPELUNKER_S3_USE_SSL=${SPELUNKER_S3_USE_SSL}
- SPELUNKER_S3_VERIFY=${SPELUNKER_S3_VERIFY}
- KAIROS_S3_ENDPOINT_URL=${KAIROS_S3_ENDPOINT_URL}
- KAIROS_S3_ACCESS_KEY_ID=${KAIROS_S3_ACCESS_KEY_ID}
- KAIROS_S3_SECRET_ACCESS_KEY=${KAIROS_S3_SECRET_ACCESS_KEY}
- KAIROS_S3_BUCKET_NAME=${KAIROS_S3_BUCKET_NAME}
- KAIROS_S3_REGION_NAME=${KAIROS_S3_REGION_NAME}
- KAIROS_S3_USE_SSL=${KAIROS_S3_USE_SSL}
- KAIROS_S3_VERIFY=${KAIROS_S3_VERIFY}
# Celery / RabbitMQ
- CELERY_BROKER_URL=${CELERY_BROKER_URL}
- CELERY_RESULT_BACKEND=${CELERY_RESULT_BACKEND}

View File

@@ -15,6 +15,7 @@ LIBRARY_TYPE_CHOICES = [
"film",
"art",
"journal",
"email",
"business",
"finance",
]

View File

@@ -241,6 +241,38 @@ LIBRARY_TYPE_DEFAULTS = {
"4) The commercial purpose — positioning, pricing, capability demonstration."
),
},
"email": {
"chunking_config": {
"strategy": "entry_level",
"chunk_size": 512,
"chunk_overlap": 32,
"respect_boundaries": ["message", "quote", "paragraph"],
},
"embedding_instruction": (
"Represent this email message for retrieval. "
"Focus on the sender, recipients, subject, dates, requests and "
"commitments made, and the people, organizations, and events discussed."
),
"reranker_instruction": (
"Re-rank email messages based on relevance to the query. "
"Prioritize messages matching the correspondents, subject matter, "
"time period, and any specific commitments or requests mentioned."
),
"llm_context_prompt": (
"The following excerpts are from personal email correspondence. "
"This is private content — answer with discretion. Attribute "
"statements to their senders, note dates, and distinguish what was "
"asked from what was agreed. Quoted text below a reply is earlier "
"context, not the sender's own words."
),
"vision_prompt": (
"Analyze this image from an email message. Identify:\n"
"1) Image type (photograph, screenshot, scanned document, chart, signature graphic).\n"
"2) What it depicts — people, places, documents, data.\n"
"3) Any visible text, dates, or figures.\n"
"4) Its role in the message — attachment content, inline illustration, or boilerplate."
),
},
"finance": {
"chunking_config": {
"strategy": "section_aware",
@@ -282,7 +314,7 @@ def get_library_type_config(library_type):
Args:
library_type: One of 'fiction', 'nonfiction', 'technical', 'music',
'film', 'art', 'journal', 'business', 'finance'
'film', 'art', 'journal', 'email', 'business', 'finance'
Returns:
dict with keys: chunking_config, embedding_instruction,

View File

@@ -77,6 +77,7 @@ class Library(StructuredNode):
"film": "Film",
"art": "Art",
"journal": "Journal",
"email": "Email",
"business": "Business",
"finance": "Finance",
},

View File

@@ -21,6 +21,7 @@ class LibraryTypeDefaultsTests(TestCase):
"film",
"art",
"journal",
"email",
"business",
"finance",
}

View File

@@ -268,6 +268,15 @@ SPELUNKER_S3_REGION_NAME = env("SPELUNKER_S3_REGION_NAME", default="us-east-1")
SPELUNKER_S3_USE_SSL = env.bool("SPELUNKER_S3_USE_SSL", default=False)
SPELUNKER_S3_VERIFY = env.bool("SPELUNKER_S3_VERIFY", default=True)
# Kairos renders synced mail to text documents in its own bucket.
KAIROS_S3_ENDPOINT_URL = env("KAIROS_S3_ENDPOINT_URL", default="")
KAIROS_S3_ACCESS_KEY_ID = env("KAIROS_S3_ACCESS_KEY_ID", default="")
KAIROS_S3_SECRET_ACCESS_KEY = env("KAIROS_S3_SECRET_ACCESS_KEY", default="")
KAIROS_S3_BUCKET_NAME = env("KAIROS_S3_BUCKET_NAME", default="kairos")
KAIROS_S3_REGION_NAME = env("KAIROS_S3_REGION_NAME", default="us-east-1")
KAIROS_S3_USE_SSL = env.bool("KAIROS_S3_USE_SSL", default=False)
KAIROS_S3_VERIFY = env.bool("KAIROS_S3_VERIFY", default=True)
# Registry keyed by the ingest `source` field. Unknown/blank sources fall
# back to "daedalus" for backwards compatibility.
SOURCE_S3_BUCKETS = {
@@ -289,6 +298,15 @@ SOURCE_S3_BUCKETS = {
"use_ssl": SPELUNKER_S3_USE_SSL,
"verify": SPELUNKER_S3_VERIFY,
},
"kairos-mail": {
"endpoint_url": KAIROS_S3_ENDPOINT_URL,
"access_key_id": KAIROS_S3_ACCESS_KEY_ID,
"secret_access_key": KAIROS_S3_SECRET_ACCESS_KEY,
"bucket_name": KAIROS_S3_BUCKET_NAME,
"region_name": KAIROS_S3_REGION_NAME,
"use_ssl": KAIROS_S3_USE_SSL,
"verify": KAIROS_S3_VERIFY,
},
}
# --- Celery / RabbitMQ ---