annotate mrjunejune/inference/public_knowledge.py @ 279:b3b547563ec7

Add Google connector service and agent wiki Implement the C/Seobeo Google Drive and Gmail connector with encrypted OAuth storage, Zenbu authentication, browser testing, AI tool discovery, chunked HTTP decoding, and Bazel coverage. Consolidate repository guidance into progressive wiki documentation and enforce arena-first allocation for new first-party C code. Co-authored-by: Copilot <[email protected]> Copilot-Session: 84c338fd-0939-4bb3-b7f3-1062eb213e5d
author MrJuneJune <me@mrjunejune.com>
date Mon, 17 Aug 2026 22:22:36 -0700
parents 056790c4fb0d
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
265
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1 """
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2 Stdlib-only deterministic loader and compiler for the assistant knowledge base.
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
3
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
4 Loads prompt files from mrjunejune/assistant/ and compiles them with verified
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
5 public facts into a hashed, deterministic system prompt. Fails closed on any
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
6 malformed input.
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
7
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
8 Public API:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
9 compile_prompt(profile, assistant_dir=None) -> dict
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
10 Returns {"content": str, "version": int, "hash": str}.
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
11 Raises ValueError for unknown profile or any validation failure.
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
12 """
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
13
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
14 import hashlib
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
15 import json
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
16 import pathlib
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
17 import re
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
18 from typing import Optional
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
19 from urllib.parse import urlsplit
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
20
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
21 # ---------------------------------------------------------------------------
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
22 # Constants
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
23 # ---------------------------------------------------------------------------
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
24
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
25 _KNOWN_PROFILES: frozenset = frozenset({"public_visitor", "invited_friend", "june_admin"})
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
26
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
27 _REQUIRED_TOP_KEYS: frozenset = frozenset({"version", "facts"})
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
28 _REQUIRED_FACT_KEYS: frozenset = frozenset(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
29 {"id", "topic", "text", "sourceLabel", "sourceUrl", "visibility", "status"}
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
30 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
31
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
32 _EXPECTED_VERSION: int = 1
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
33 _MAX_PROMPT_FILE_BYTES: int = 8192 # 8 KB per prompt file
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
34 _MAX_COMPILED_BYTES: int = 16384 # 16 KB total compiled ceiling
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
35
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
36 _MAX_ID_LEN: int = 64
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
37 _MAX_TOPIC_LEN: int = 64
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
38 _MAX_TEXT_LEN: int = 500
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
39 _MAX_SOURCE_LABEL_LEN: int = 128
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
40
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
41 _SLUG_RE = re.compile(r"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
42
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
43 # Contact patterns: email and North-American-style phone numbers
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
44 _CONTACT_PATTERNS: list = [
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
45 re.compile(r"[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}"),
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
46 re.compile(r"(\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]\d{3}[-.\s]\d{4}"),
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
47 ]
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
48 _SECRET_VALUE_PATTERNS: list = [
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
49 re.compile(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
50 r"\b(password|passwd|secret|token|api[_\-]?key|private[_\-]?key)"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
51 r"\s*[:=]\s*\S+",
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
52 re.IGNORECASE,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
53 ),
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
54 re.compile(r"-----BEGIN [A-Z ]*PRIVATE KEY-----"),
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
55 ]
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
56 _CONTROL_PATTERN = re.compile(r"[\x00-\x1f\x7f]")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
57 _PROMPT_CONTROL_PATTERN = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
58 _RESERVED_CORPUS_PATTERNS: tuple[str, ...] = (
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
59 "--- knowledge corpus ---",
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
60 "system:",
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
61 "assistant:",
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
62 "user:",
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
63 "<system",
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
64 "ignore previous instructions",
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
65 "ignore prior instructions",
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
66 "follow these instructions",
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
67 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
68
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
69 # Credential / secret keyword patterns
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
70 _SECRET_PATTERNS: list = [
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
71 re.compile(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
72 r"\b(password|passwd|secret|token|api[_\-]?key|private[_\-]?key)\b",
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
73 re.IGNORECASE,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
74 ),
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
75 ]
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
76
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
77 _FACTS_DELIMITER: str = "--- KNOWLEDGE CORPUS ---"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
78
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
79
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
80 # ---------------------------------------------------------------------------
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
81 # Internal helpers
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
82 # ---------------------------------------------------------------------------
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
83
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
84
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
85 def _default_assistant_dir() -> pathlib.Path:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
86 return pathlib.Path(__file__).parent.parent / "assistant"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
87
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
88
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
89 def _validate_source_url(url: str, fact_id: str) -> None:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
90 if not isinstance(url, str) or not url:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
91 raise ValueError(f"Fact '{fact_id}': sourceUrl is empty")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
92 if _CONTROL_PATTERN.search(url) or "\\" in url:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
93 raise ValueError(f"Fact '{fact_id}': sourceUrl contains unsafe characters")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
94 if url.startswith("/"):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
95 if url.startswith("//") or any(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
96 segment in (".", "..") for segment in url.split("/")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
97 ):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
98 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
99 f"Fact '{fact_id}': sourceUrl must be a safe local path"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
100 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
101 return
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
102 parsed = urlsplit(url)
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
103 if (
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
104 parsed.scheme != "https"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
105 or not parsed.hostname
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
106 or parsed.username is not None
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
107 or parsed.password is not None
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
108 ):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
109 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
110 f"Fact '{fact_id}': sourceUrl must be HTTPS or a safe local path"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
111 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
112 try:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
113 parsed.port
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
114 except ValueError as exc:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
115 raise ValueError(f"Fact '{fact_id}': sourceUrl has an invalid port") from exc
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
116
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
117
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
118 def _check_no_contact_or_secret(text: str, fact_id: str, field: str) -> None:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
119 for pat in _CONTACT_PATTERNS:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
120 if pat.search(text):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
121 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
122 f"Fact '{fact_id}': {field} contains contact data (email or phone number)"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
123 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
124 for pat in _SECRET_PATTERNS:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
125 if pat.search(text):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
126 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
127 f"Fact '{fact_id}': {field} contains a secret or credential pattern"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
128 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
129
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
130 def _validate_corpus_text(text: str, fact_id: str, field: str) -> None:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
131 if _CONTROL_PATTERN.search(text):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
132 raise ValueError(f"Fact '{fact_id}': {field} contains control characters")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
133 lowered = text.lower()
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
134 for reserved in _RESERVED_CORPUS_PATTERNS:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
135 if reserved in lowered:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
136 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
137 f"Fact '{fact_id}': {field} contains reserved prompt instructions"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
138 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
139 _check_no_contact_or_secret(text, fact_id, field)
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
140
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
141
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
142 def _load_and_validate_facts(assistant_dir: pathlib.Path) -> list:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
143 facts_path = assistant_dir / "knowledge" / "public_facts.json"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
144 try:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
145 raw = facts_path.read_text(encoding="utf-8")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
146 except OSError as exc:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
147 raise ValueError(f"Cannot read facts file: {exc}") from exc
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
148
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
149 try:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
150 data = json.loads(raw)
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
151 except json.JSONDecodeError as exc:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
152 raise ValueError(f"Facts file is not valid JSON: {exc}") from exc
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
153
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
154 if not isinstance(data, dict):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
155 raise ValueError("Facts file top level must be a JSON object")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
156
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
157 extra_keys = set(data.keys()) - _REQUIRED_TOP_KEYS
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
158 missing_keys = _REQUIRED_TOP_KEYS - set(data.keys())
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
159 if extra_keys or missing_keys:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
160 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
161 f"Facts file top-level keys must be exactly {sorted(_REQUIRED_TOP_KEYS)}; "
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
162 f"extra={sorted(extra_keys)}, missing={sorted(missing_keys)}"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
163 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
164
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
165 if (
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
166 not isinstance(data["version"], int)
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
167 or isinstance(data["version"], bool)
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
168 or data["version"] != _EXPECTED_VERSION
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
169 ):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
170 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
171 f"Facts file version must be {_EXPECTED_VERSION}; got {data['version']!r}"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
172 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
173
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
174 raw_facts = data["facts"]
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
175 if not isinstance(raw_facts, list) or len(raw_facts) == 0:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
176 raise ValueError("Facts file 'facts' must be a non-empty list")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
177
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
178 seen_ids: set = set()
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
179 validated: list = []
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
180
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
181 for i, fact in enumerate(raw_facts):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
182 if not isinstance(fact, dict):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
183 raise ValueError(f"Fact at index {i} must be a JSON object")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
184
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
185 extra = set(fact.keys()) - _REQUIRED_FACT_KEYS
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
186 missing = _REQUIRED_FACT_KEYS - set(fact.keys())
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
187 if extra or missing:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
188 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
189 f"Fact at index {i}: keys must be exactly "
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
190 f"{sorted(_REQUIRED_FACT_KEYS)}; "
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
191 f"extra={sorted(extra)}, missing={sorted(missing)}"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
192 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
193
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
194 fid = fact["id"]
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
195 if not isinstance(fid, str) or not fid:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
196 raise ValueError(f"Fact at index {i}: 'id' must be a non-empty string")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
197 if len(fid) > _MAX_ID_LEN:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
198 raise ValueError(f"Fact '{fid}': id exceeds {_MAX_ID_LEN} characters")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
199 if not _SLUG_RE.match(fid):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
200 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
201 f"Fact '{fid}': id must be lowercase alphanumeric with hyphens"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
202 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
203 if fid in seen_ids:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
204 raise ValueError(f"Duplicate fact id: {fid!r}")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
205 seen_ids.add(fid)
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
206
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
207 topic = fact["topic"]
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
208 if not isinstance(topic, str) or not topic:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
209 raise ValueError(f"Fact '{fid}': 'topic' must be a non-empty string")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
210 if len(topic) > _MAX_TOPIC_LEN:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
211 raise ValueError(f"Fact '{fid}': topic exceeds {_MAX_TOPIC_LEN} characters")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
212 if not _SLUG_RE.match(topic):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
213 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
214 f"Fact '{fid}': topic must be lowercase alphanumeric with hyphens"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
215 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
216
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
217 text = fact["text"]
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
218 if not isinstance(text, str) or len(text) < 10:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
219 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
220 f"Fact '{fid}': 'text' must be a string of at least 10 characters"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
221 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
222 if len(text) > _MAX_TEXT_LEN:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
223 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
224 f"Fact '{fid}': text exceeds {_MAX_TEXT_LEN} characters"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
225 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
226 _validate_corpus_text(text, fid, "text")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
227
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
228 source_label = fact["sourceLabel"]
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
229 if not isinstance(source_label, str) or not source_label:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
230 raise ValueError(f"Fact '{fid}': 'sourceLabel' must be a non-empty string")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
231 if len(source_label) > _MAX_SOURCE_LABEL_LEN:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
232 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
233 f"Fact '{fid}': sourceLabel exceeds {_MAX_SOURCE_LABEL_LEN} characters"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
234 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
235 _validate_corpus_text(source_label, fid, "sourceLabel")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
236
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
237 _validate_source_url(fact["sourceUrl"], fid)
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
238
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
239 if not isinstance(fact["visibility"], str) or fact["visibility"] != "public":
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
240 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
241 f"Fact '{fid}': visibility must be 'public'; got {fact['visibility']!r}"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
242 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
243 if not isinstance(fact["status"], str) or fact["status"] != "verified":
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
244 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
245 f"Fact '{fid}': status must be 'verified'; got {fact['status']!r}"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
246 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
247
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
248 validated.append(fact)
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
249
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
250 validated.sort(key=lambda f: f["id"])
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
251 return validated
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
252
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
253
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
254 def _load_prompt_file(path: pathlib.Path) -> str:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
255 try:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
256 raw_bytes = path.read_bytes()
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
257 except OSError as exc:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
258 raise ValueError(f"Cannot read prompt file {path.name}: {exc}") from exc
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
259 if len(raw_bytes) > _MAX_PROMPT_FILE_BYTES:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
260 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
261 f"Prompt file {path.name} exceeds {_MAX_PROMPT_FILE_BYTES} bytes "
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
262 f"(got {len(raw_bytes)})"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
263 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
264 try:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
265 content = raw_bytes.decode("utf-8")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
266 except UnicodeDecodeError as exc:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
267 raise ValueError(f"Prompt file {path.name} is not valid UTF-8") from exc
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
268 if _PROMPT_CONTROL_PATTERN.search(content):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
269 raise ValueError(f"Prompt file {path.name} contains control characters")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
270 for pattern in _CONTACT_PATTERNS + _SECRET_VALUE_PATTERNS:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
271 if pattern.search(content):
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
272 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
273 f"Prompt file {path.name} contains contact data or a secret value"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
274 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
275 return content
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
276
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
277
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
278 def _format_facts(facts: list) -> str:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
279 lines: list = []
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
280 for fact in facts:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
281 lines.append(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
282 json.dumps(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
283 {
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
284 "fact": fact["text"],
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
285 "id": fact["id"],
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
286 "sourceLabel": fact["sourceLabel"],
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
287 "sourceUrl": fact["sourceUrl"],
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
288 "topic": fact["topic"],
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
289 },
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
290 ensure_ascii=False,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
291 separators=(",", ":"),
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
292 sort_keys=True,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
293 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
294 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
295 return "\n".join(lines)
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
296
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
297
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
298 # ---------------------------------------------------------------------------
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
299 # Public API
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
300 # ---------------------------------------------------------------------------
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
301
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
302
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
303 def compile_prompt(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
304 profile: str,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
305 assistant_dir: Optional[pathlib.Path] = None,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
306 ) -> dict:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
307 """
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
308 Compile a deterministic system prompt for *profile*.
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
309
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
310 Parameters
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
311 ----------
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
312 profile:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
313 One of ``"public_visitor"``, ``"invited_friend"``, or ``"june_admin"``.
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
314 assistant_dir:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
315 Path to the ``mrjunejune/assistant/`` directory. Defaults to the
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
316 sibling of the ``inference/`` package at runtime.
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
317
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
318 Returns
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
319 -------
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
320 dict with keys:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
321 - ``"content"`` (str): compiled prompt text
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
322 - ``"version"`` (int): schema version (always 1)
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
323 - ``"hash"`` (str): lowercase hex SHA-256 of ``content`` encoded UTF-8
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
324
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
325 Raises
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
326 ------
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
327 ValueError
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
328 On unknown profile, malformed files, validation failures, or size
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
329 limit exceeded.
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
330 """
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
331 if profile not in _KNOWN_PROFILES:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
332 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
333 f"Unknown profile {profile!r}; "
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
334 f"known profiles: {sorted(_KNOWN_PROFILES)}"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
335 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
336
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
337 base = pathlib.Path(assistant_dir) if assistant_dir is not None else _default_assistant_dir()
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
338
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
339 common = _load_prompt_file(base / "common.md")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
340 profile_section = _load_prompt_file(base / f"{profile}.md")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
341 facts = _load_and_validate_facts(base)
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
342 facts_block = _format_facts(facts)
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
343
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
344 content = (
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
345 common.rstrip()
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
346 + "\n\n"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
347 + profile_section.rstrip()
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
348 + "\n\n"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
349 + _FACTS_DELIMITER
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
350 + "\n\n"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
351 + facts_block
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
352 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
353
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
354 encoded = content.encode("utf-8")
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
355 if len(encoded) > _MAX_COMPILED_BYTES:
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
356 raise ValueError(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
357 f"Compiled prompt exceeds {_MAX_COMPILED_BYTES} bytes "
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
358 f"(got {len(encoded)})"
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
359 )
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
360
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
361 return {
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
362 "content": content,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
363 "version": _EXPECTED_VERSION,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
364 "hash": hashlib.sha256(encoded).hexdigest(),
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
365 }