switchroom 0.20.0 → 0.20.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/bin/handoff-briefing.sh +213 -74
  2. package/dist/agent-scheduler/index.js +2 -2
  3. package/dist/auth-broker/index.js +4 -3
  4. package/dist/buzz-gateway/index.js +166 -6
  5. package/dist/cli/notion-write-pretool.mjs +2 -2
  6. package/dist/cli/switchroom.js +24704 -16399
  7. package/dist/host-control/main.js +44 -10
  8. package/dist/vault/approvals/kernel-server.js +4 -3
  9. package/dist/vault/broker/server.js +4 -3
  10. package/package.json +3 -2
  11. package/profiles/_base/start.sh.hbs +79 -10
  12. package/telegram-plugin/dist/gateway/gateway.js +1400 -964
  13. package/telegram-plugin/gateway/access-store.test.ts +234 -0
  14. package/telegram-plugin/gateway/access-store.ts +194 -0
  15. package/telegram-plugin/gateway/boot-briefing-builder.ts +135 -7
  16. package/telegram-plugin/gateway/boot-briefing-capability.ts +31 -0
  17. package/telegram-plugin/gateway/boot-briefing-wiring.ts +166 -4
  18. package/telegram-plugin/gateway/buzz-mirror-correlation-store.ts +285 -0
  19. package/telegram-plugin/gateway/buzz-mirror.ts +177 -12
  20. package/telegram-plugin/gateway/gateway.ts +43 -123
  21. package/telegram-plugin/gateway/inbound-router.ts +93 -3
  22. package/telegram-plugin/gateway/outbound-send-path.ts +48 -1
  23. package/telegram-plugin/gateway/pending-turn-env.ts +10 -1
  24. package/telegram-plugin/tests/boot-briefing-builder.test.ts +422 -31
  25. package/telegram-plugin/tests/buzz-mirror-correlation-store.test.ts +173 -0
  26. package/telegram-plugin/tests/buzz-mirror.test.ts +297 -1
  27. package/telegram-plugin/tests/outbound-send-path.test.ts +24 -0
  28. package/telegram-plugin/tests/reply-to-buffer-fallback.test.ts +273 -0
  29. package/telegram-plugin/tests/reply-to-buffer-history.test.ts +134 -0
@@ -47,7 +47,29 @@ HINDSIGHT_BANK="${HINDSIGHT_BANK_ID:-}"
47
47
  AGENT_DIR="${AGENT_DIR:-}"
48
48
  WORKSPACE_DIR="${WORKSPACE_DIR:-$AGENT_DIR}"
49
49
  MAX_MESSAGES="${HANDOFF_BRIEFING_MAX_MESSAGES:-20}"
50
- HINDSIGHT_TIMEOUT="${HANDOFF_BRIEFING_HINDSIGHT_TIMEOUT:-4}"
50
+ # Hindsight is the only network hop; cap it at 3s so it finishes well inside
51
+ # start.sh's outer `timeout 10` kill budget (was 4s under a 5s outer, which
52
+ # left almost no margin — a slow recall could be killed mid-write). Local
53
+ # SQLite + daily-memory reads are sub-second, so 3s is the whole network cost.
54
+ HINDSIGHT_TIMEOUT="${HANDOFF_BRIEFING_HINDSIGHT_TIMEOUT:-3}"
55
+
56
+ # Chat/thread scope for the recent-conversation section (#continuity). A
57
+ # forum/group agent's history.db holds messages from many topics; an unscoped
58
+ # "last 20" briefing pollutes the reorientation with unrelated threads. Prefer
59
+ # the surface that was mid-turn when the prior session ended (exported by
60
+ # start.sh from the pending-turn env on an interrupted boot); otherwise the
61
+ # python fallback derives the single most-recently-active (chat_id, thread_id)
62
+ # surface straight from the DB. Empty chat ⇒ let python derive it.
63
+ #
64
+ # TARGET_THREAD_ID is tri-state: a numbered thread scopes to that topic; the
65
+ # literal sentinel `NULL` means the surface's thread is genuinely NULL (a DM /
66
+ # forum General topic) and scopes with `thread_id IS NULL`; empty means the
67
+ # thread is UNKNOWN and falls back to chat-only scope (all threads). The
68
+ # pending-turn env writer emits `NULL` when it knows the interrupted turn's
69
+ # thread was null, so a General-topic interrupt reboots correctly scoped
70
+ # instead of pulling in every other topic's messages.
71
+ TARGET_CHAT_ID="${SWITCHROOM_PENDING_CHAT_ID:-}"
72
+ TARGET_THREAD_ID="${SWITCHROOM_PENDING_THREAD_ID:-}"
51
73
 
52
74
  # Determine output mode
53
75
  STDOUT_MODE=0
@@ -61,28 +83,119 @@ if [ -n "$TELEGRAM_STATE" ] && [ -d "$TELEGRAM_STATE" ]; then
61
83
  HISTORY_DB="$TELEGRAM_STATE/history.db"
62
84
  if [ -f "$HISTORY_DB" ] && command -v python3 >/dev/null 2>&1; then
63
85
  # Use python3's stdlib sqlite3 — no bun:sqlite, no extra deps.
64
- # Query the most recent $MAX_MESSAGES rows ordered by ts DESC, then
65
- # reverse for chronological display. We skip system messages (role NULL).
66
- TELEGRAM_ROWS=$(python3 - "$HISTORY_DB" "$MAX_MESSAGES" 2>/dev/null <<'PYEOF'
86
+ # Query the most recent $MAX_MESSAGES rows for the ACTIVE surface only
87
+ # (chat/thread-scoped, see above), ordered by ts DESC, then reverse for
88
+ # chronological display. We skip system messages (role NULL). The scope
89
+ # source is logged to stderr for boot diagnostics.
90
+ # python stderr is NOT suppressed: the script's only stderr output is the
91
+ # intentional scope breadcrumb + a single graceful line on any caught error
92
+ # (every DB path is wrapped in try/except → sys.exit(0)). start.sh runs this
93
+ # under `2>/dev/null`, so the breadcrumb is a debug/manual-run diagnostic.
94
+ TELEGRAM_ROWS=$(python3 - "$HISTORY_DB" "$MAX_MESSAGES" "$TARGET_CHAT_ID" "$TARGET_THREAD_ID" <<'PYEOF'
67
95
  import sys, sqlite3, datetime
68
96
 
69
97
  db_path = sys.argv[1]
70
98
  limit = int(sys.argv[2])
99
+ target_chat = sys.argv[3] if len(sys.argv) > 3 else ""
100
+ target_thread = sys.argv[4] if len(sys.argv) > 4 else ""
71
101
 
72
102
  try:
73
103
  conn = sqlite3.connect(db_path)
74
104
  conn.row_factory = sqlite3.Row
75
105
  cur = conn.cursor()
76
- # Fetch most recent rows; reverse for chronological output.
106
+
107
+ # Resolve the surface to scope to.
108
+ # - explicit env target (pending-turn chat/thread) wins — UNLESS that chat
109
+ # has zero rows (rotated/fresh DB), in which case we fall through to
110
+ # db-latest so a stale env target doesn't yield an empty section;
111
+ # - else derive the single most-recently-active (chat_id, thread_id).
112
+ # thread is tri-state: a real value, NULL (DM / general), or unknown.
113
+ # - target_thread == "NULL" (sentinel from start.sh / pending-turn-env)
114
+ # means the surface's thread is GENUINELY NULL (DM / general topic) —
115
+ # scope with `thread_id IS NULL`, do NOT pull in numbered-thread rows.
116
+ # - target_thread == "" (empty) means UNKNOWN — chat-only scope (all
117
+ # threads), the safe backward-compatible fallback.
118
+ scope_chat = None
119
+ scope_thread = None # int thread id
120
+ scope_thread_known = False # True once we know the exact thread (incl. NULL)
121
+ scope_thread_is_null = False # True when the surface's thread is NULL
122
+ scope_source = "unscoped"
123
+
124
+ def _chat_has_rows(chat_id):
125
+ cur.execute(
126
+ "SELECT 1 FROM messages WHERE role IN ('user', 'assistant') "
127
+ "AND chat_id = ? LIMIT 1",
128
+ [chat_id],
129
+ )
130
+ return cur.fetchone() is not None
131
+
132
+ def _derive_db_latest():
133
+ # The single most-recently-active (chat_id, thread_id) surface.
134
+ cur.execute(
135
+ """
136
+ SELECT chat_id, thread_id
137
+ FROM messages
138
+ WHERE role IN ('user', 'assistant')
139
+ ORDER BY ts DESC
140
+ LIMIT 1
141
+ """
142
+ )
143
+ return cur.fetchone()
144
+
145
+ # Env target — accept it only when its chat actually has rows (2b). A
146
+ # rotated/fresh DB can leave a pending-turn chat with no persisted
147
+ # messages; scoping to it would silently emit an empty section, so we
148
+ # fall through to db-latest instead.
149
+ if target_chat and _chat_has_rows(target_chat):
150
+ scope_chat = target_chat
151
+ scope_source = "env"
152
+ if target_thread == "NULL":
153
+ scope_thread_is_null = True
154
+ scope_thread_known = True
155
+ elif target_thread != "":
156
+ try:
157
+ scope_thread = int(target_thread)
158
+ scope_thread_known = True
159
+ except ValueError:
160
+ scope_thread = None # unparseable → chat-only scope
161
+ # else: unknown thread → chat-only scope (all threads of the chat)
162
+
163
+ if scope_chat is None:
164
+ latest = _derive_db_latest()
165
+ if latest is not None:
166
+ scope_chat = latest["chat_id"]
167
+ scope_source = "db-latest"
168
+ scope_thread_known = True
169
+ if latest["thread_id"] is None:
170
+ scope_thread_is_null = True
171
+ else:
172
+ scope_thread = latest["thread_id"]
173
+
174
+ if scope_chat is None:
175
+ # Empty DB (nothing to scope) — nothing to show.
176
+ sys.stderr.write("handoff-briefing: no messages to scope; empty section\n")
177
+ sys.exit(0)
178
+
179
+ where = ["role IN ('user', 'assistant')", "chat_id = ?"]
180
+ params = [scope_chat]
181
+ if scope_thread_known:
182
+ if scope_thread_is_null:
183
+ where.append("thread_id IS NULL")
184
+ else:
185
+ where.append("thread_id = ?")
186
+ params.append(scope_thread)
187
+ params.append(limit)
188
+
189
+ sys.stderr.write(
190
+ "handoff-briefing: scoping recent conversation to chat=%s thread=%s (source=%s)\n"
191
+ % (scope_chat, "NULL" if scope_thread_is_null else (scope_thread if scope_thread_known else "any"), scope_source)
192
+ )
193
+
77
194
  cur.execute(
78
- """
79
- SELECT role, user, ts, text
80
- FROM messages
81
- WHERE role IN ('user', 'assistant')
82
- ORDER BY ts DESC
83
- LIMIT ?
84
- """,
85
- (limit,),
195
+ "SELECT role, user, ts, text FROM messages WHERE "
196
+ + " AND ".join(where)
197
+ + " ORDER BY ts DESC LIMIT ?",
198
+ params,
86
199
  )
87
200
  rows = list(reversed(cur.fetchall()))
88
201
  conn.close()
@@ -110,6 +223,70 @@ $TELEGRAM_ROWS"
110
223
  fi
111
224
  fi
112
225
 
226
+ # ── Header (cheap, no network) — computed early so the recent-conversation
227
+ # section can be flushed to disk BEFORE the slow Hindsight hop. ──────────────
228
+ # Restart timestamp — model-facing: it lands in the resume-turn system prompt
229
+ # via --append-system-prompt ("You just restarted at …"). Render the agent's
230
+ # LOCAL am/pm wall clock, NOT UTC, so the restart turn never sees a competing
231
+ # UTC "now". Same SWITCHROOM_TIMEZONE → TZ → UTC cascade the daily section uses.
232
+ _TZ_VAL="${SWITCHROOM_TIMEZONE:-${TZ:-UTC}}"
233
+ TIMESTAMP=$(TZ="$_TZ_VAL" date '+%A %Y-%m-%d %I:%M %p %Z' 2>/dev/null || date '+%A %Y-%m-%d %I:%M %p %Z')
234
+ RESTART_REASON="unknown"
235
+ if [ -n "$AGENT_DIR" ] && [ -f "$AGENT_DIR/.restart-reason" ]; then
236
+ RESTART_REASON=$(cat "$AGENT_DIR/.restart-reason" 2>/dev/null | head -1 | tr -d '\r\n')
237
+ fi
238
+ if [ -n "${SWITCHROOM_PENDING_ENDED_VIA:-}" ]; then
239
+ RESTART_REASON="$SWITCHROOM_PENDING_ENDED_VIA"
240
+ fi
241
+ BRIEFING_HEADER="You just restarted at ${TIMESTAMP}. Previous session ended via: ${RESTART_REASON}. Consult this briefing before responding."
242
+
243
+ # Resolve the output destination up front (file mode only).
244
+ OUTPUT_FILE=""
245
+ OUTPUT_TMP=""
246
+ if [ "$STDOUT_MODE" != "1" ] && [ -n "$AGENT_DIR" ]; then
247
+ OUTPUT_FILE="$AGENT_DIR/.handoff-briefing.md"
248
+ OUTPUT_TMP="${OUTPUT_FILE}.tmp.$$"
249
+ fi
250
+
251
+ # Incremental emit (#continuity). Sections are flushed to the output file as
252
+ # each source resolves — the recent-conversation section (the highest-value,
253
+ # always-local part) is written BEFORE the network-bound Hindsight hop. So a
254
+ # late-stage kill (e.g. start.sh's outer `timeout`, SIGTERM by default) mid-Hindsight still
255
+ # leaves the recent conversation on disk instead of nothing. The first flush
256
+ # writes header+section atomically via tmp+mv; later sections append. In
257
+ # stdout/no-AGENT_DIR mode we buffer and print once at the end instead.
258
+ FILE_STARTED=0
259
+ STDOUT_BUFFER=""
260
+ emit_section() {
261
+ # $1 = section content (assumed non-empty)
262
+ section="$1"
263
+ if [ -n "$OUTPUT_FILE" ]; then
264
+ if [ "$FILE_STARTED" = "0" ]; then
265
+ # First section: header + divider + section, written atomically.
266
+ printf '%s\n\n---\n\n%s' "$BRIEFING_HEADER" "$section" > "$OUTPUT_TMP" \
267
+ && mv -f "$OUTPUT_TMP" "$OUTPUT_FILE"
268
+ FILE_STARTED=1
269
+ else
270
+ printf '\n\n---\n\n%s' "$section" >> "$OUTPUT_FILE"
271
+ fi
272
+ else
273
+ if [ -z "$STDOUT_BUFFER" ]; then
274
+ STDOUT_BUFFER="$section"
275
+ else
276
+ STDOUT_BUFFER="$STDOUT_BUFFER
277
+
278
+ ---
279
+
280
+ $section"
281
+ fi
282
+ fi
283
+ }
284
+
285
+ # Flush the recent-conversation section NOW, before Hindsight.
286
+ if [ -n "$TELEGRAM_SECTION" ]; then
287
+ emit_section "$TELEGRAM_SECTION"
288
+ fi
289
+
113
290
  # ── Source 2: Hindsight recall ──────────────────────────────────────────────────
114
291
  HINDSIGHT_SECTION=""
115
292
  if [ -n "$HINDSIGHT_URL" ] && [ -n "$HINDSIGHT_BANK" ] && command -v curl >/dev/null 2>&1 && command -v jq >/dev/null 2>&1; then
@@ -133,14 +310,16 @@ $RECALL_TEXT"
133
310
  fi
134
311
  fi
135
312
  fi
313
+ if [ -n "$HINDSIGHT_SECTION" ]; then
314
+ emit_section "$HINDSIGHT_SECTION"
315
+ fi
136
316
 
137
317
  # ── Source 3: Today's daily memory ─────────────────────────────────────────────
138
- # Resolve "today" in the agent's LOCAL time — NOT the process default (UTC on
139
- # most hosts/CI). TODAY keys the daily-memory lookup (memory/${TODAY}.md); using
140
- # UTC here would look up the wrong day's file during the window where the local
141
- # date is ahead of/behind UTC, silently dropping today's memory. Same
142
- # SWITCHROOM_TIMEZONE TZ → UTC cascade the restart-timestamp render below uses.
143
- _TZ_VAL="${SWITCHROOM_TIMEZONE:-${TZ:-UTC}}"
318
+ # TODAY keys the daily-memory lookup (memory/${TODAY}.md) in the agent's LOCAL
319
+ # time (_TZ_VAL, resolved in the header block above) — NOT the process default
320
+ # (UTC on most hosts/CI). Using UTC here would look up the wrong day's file
321
+ # during the window where the local date is ahead of/behind UTC, silently
322
+ # dropping today's memory.
144
323
  DAILY_SECTION=""
145
324
  TODAY=$(TZ="$_TZ_VAL" date +%Y-%m-%d 2>/dev/null || date +%Y-%m-%d 2>/dev/null || true)
146
325
  if [ -n "$TODAY" ] && [ -n "$WORKSPACE_DIR" ]; then
@@ -154,66 +333,26 @@ $DAILY_CONTENT"
154
333
  fi
155
334
  fi
156
335
  fi
157
-
158
- # ── Assemble briefing ───────────────────────────────────────────────────────────
159
- # Restart timestamp — model-facing: it lands in the resume-turn system prompt
160
- # via --append-system-prompt ("You just restarted at …"). Render the agent's
161
- # LOCAL am/pm wall clock, NOT UTC, so the restart turn never sees a competing
162
- # UTC "now" (the whole point of the deterministic-local-time work). Same
163
- # SWITCHROOM_TIMEZONE → TZ → UTC cascade and `%A %Y-%m-%d %I:%M %p %Z` am/pm
164
- # format the UserPromptSubmit local-time hook (bin/timezone-hook.sh) uses.
165
- # (_TZ_VAL is computed once above, in the daily-memory section.)
166
- TIMESTAMP=$(TZ="$_TZ_VAL" date '+%A %Y-%m-%d %I:%M %p %Z' 2>/dev/null || date '+%A %Y-%m-%d %I:%M %p %Z')
167
-
168
- # Determine restart reason if available
169
- RESTART_REASON="unknown"
170
- if [ -n "$AGENT_DIR" ] && [ -f "$AGENT_DIR/.restart-reason" ]; then
171
- RESTART_REASON=$(cat "$AGENT_DIR/.restart-reason" 2>/dev/null | head -1 | tr -d '\r\n')
336
+ if [ -n "$DAILY_SECTION" ]; then
337
+ emit_section "$DAILY_SECTION"
172
338
  fi
173
- # Also check SWITCHROOM_PENDING_ENDED_VIA if set by start.sh
174
- if [ -n "${SWITCHROOM_PENDING_ENDED_VIA:-}" ]; then
175
- RESTART_REASON="$SWITCHROOM_PENDING_ENDED_VIA"
176
- fi
177
-
178
- # Build the briefing body
179
- SECTIONS=""
180
- for section in "$TELEGRAM_SECTION" "$HINDSIGHT_SECTION" "$DAILY_SECTION"; do
181
- if [ -n "$section" ]; then
182
- if [ -n "$SECTIONS" ]; then
183
- SECTIONS="$SECTIONS
184
-
185
- ---
186
339
 
187
- $section"
188
- else
189
- SECTIONS="$section"
190
- fi
340
+ # ── Finalize ────────────────────────────────────────────────────────────────────
341
+ # Every section was flushed as it resolved (emit_section). Here we only close
342
+ # out the chosen sink. An all-empty briefing wrote nothing — leave it that way
343
+ # so start.sh skips the --append-system-prompt arg.
344
+ if [ -n "$OUTPUT_FILE" ]; then
345
+ # File mode. FILE_STARTED=1 means at least one section was written atomically
346
+ # (header+first) with the rest appended; add the trailing newline the
347
+ # single-shot writer used to emit. If nothing was written, no file exists.
348
+ if [ "$FILE_STARTED" = "1" ]; then
349
+ printf '\n' >> "$OUTPUT_FILE"
191
350
  fi
192
- done
193
-
194
- # Empty briefing — nothing to inject
195
- if [ -z "$SECTIONS" ]; then
196
- exit 0
197
- fi
198
-
199
- BRIEFING="You just restarted at ${TIMESTAMP}. Previous session ended via: ${RESTART_REASON}. Consult this briefing before responding.
200
-
201
- ---
202
-
203
- ${SECTIONS}"
204
-
205
- # ── Output ──────────────────────────────────────────────────────────────────────
206
- if [ "$STDOUT_MODE" = "1" ]; then
207
- printf '%s\n' "$BRIEFING"
208
351
  else
209
- if [ -z "$AGENT_DIR" ]; then
210
- # Fallback: write to stdout if AGENT_DIR is not set
211
- printf '%s\n' "$BRIEFING"
212
- exit 0
352
+ # stdout / no-AGENT_DIR mode — buffered; print the whole briefing once.
353
+ if [ -n "$STDOUT_BUFFER" ]; then
354
+ printf '%s\n\n---\n\n%s\n' "$BRIEFING_HEADER" "$STDOUT_BUFFER"
213
355
  fi
214
- OUTPUT_FILE="$AGENT_DIR/.handoff-briefing.md"
215
- OUTPUT_TMP="${OUTPUT_FILE}.tmp.$$"
216
- printf '%s\n' "$BRIEFING" > "$OUTPUT_TMP" && mv -f "$OUTPUT_TMP" "$OUTPUT_FILE"
217
356
  fi
218
357
 
219
358
  exit 0
@@ -11362,7 +11362,7 @@ var BuzzChannelSchema = exports_external.object({
11362
11362
  default_channel_id: exports_external.string().describe("Relay-minted group UUID (the NIP-29 `h` tag) the sidecar subscribes " + "to and stamps on injected turns."),
11363
11363
  channel_map: exports_external.record(exports_external.string(), exports_external.string()).default({}).describe("Optional map of extra group UUIDs → friendly labels."),
11364
11364
  pubkey_names: exports_external.record(exports_external.string(), exports_external.string()).default({}).describe("Optional petnames: hex/npub pubkey → display name, used to label " + "the sender on injected turns."),
11365
- pinned_relay_digest: exports_external.string().optional().describe("Pinned relay image digest (M4). The compat-check warns on mismatch; " + "advisory in Phase 1.")
11365
+ pinned_relay_digest: exports_external.string().optional().describe("Pinned relay image digest (M4). RESERVED — no consumer of this field " + "exists; the existing compat-check (compat-check.ts) validates only " + "the wire contract (AUTH kind, message kind, tag names) and does not " + "read this field. Kept in the schema so the intended digest-pin can " + "be wired without a config shape change.")
11366
11366
  }).strict();
11367
11367
  var ChannelsSchema = exports_external.object({
11368
11368
  telegram: TelegramChannelSchema,
@@ -11419,7 +11419,7 @@ var HindsightConfigSchema = exports_external.object({
11419
11419
  reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
11420
11420
  consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
11421
11421
  }).optional().describe("LLM knob for the hindsight container. The flat `provider`/`model` set " + "the global default (backward-compatible); optional `retain`/`reflect`/" + "`consolidation` blocks override individual ops. All fields optional; " + "unset fields fall back to the hard-coded defaults."),
11422
- env: exports_external.record(exports_external.union([exports_external.string(), exports_external.number(), exports_external.boolean()])).optional().describe("Operator overrides for switchroom's capability-gated Hindsight " + "performance defaults. Only the keys switchroom actually manages are " + "honoured (`HINDSIGHT_PERF_ENV_KEYS` in " + "src/setup/hindsight-perf-defaults.ts: RERANKER_LOCAL_FP16, " + "RERANKER_LOCAL_BATCH_SIZE, LLM_MAX_CONCURRENT, " + "RETAIN/CONSOLIDATION_LLM_MAX_CONCURRENT, LLM_STRICT_SCHEMA, " + "LLM_MAX_RETRIES, CONSOLIDATION_LLM_PARALLELISM, " + "MAX_OBSERVATIONS_PER_SCOPE, " + "RECALL_MAX_CANDIDATES_PER_SOURCE, LINK_EXPANSION_PER_ENTITY_LIMIT, " + "LINK_EXPANSION_TIMEOUT, LLM_REASONING_EFFORT, " + "RERANKER_LOCAL_BUCKET_BATCHING, RERANKER_MAX_CANDIDATES, " + "RERANKER_LOCAL_MAX_CONCURRENT, RECALL_MAX_CONCURRENT, " + "REFLECT_WALL_TIMEOUT, WORKER_CONSOLIDATION_RESERVED_SLOTS, " + "WORKER_CONSOLIDATION_SLOT_LIMIT, " + "CONSOLIDATION_MAX_MEMORIES_PER_ROUND, GRAPH_SEED_MIN_SIMILARITY, " + "LLM_SUPPORTS_MAX_ITEMS, RECENCY_DECAY_FUNCTION, " + "RECENCY_DECAY_HALFLIFE_DAYS — switchroom defaults recall's recency " + "curve to `exponential` with a 30-day half-life so a fact retained " + "today outranks a stale one, instead of upstream's near-flat " + "linear/365-day window), the override-only keys " + "switchroom manages but ships NO default for " + "(`HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS`: " + "HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY — a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP — the rollback knob for " + "switchroom's CE-saturation damping patch, a float; >= ~0.65 backs the " + "damping out entirely, unset means the patch's own derived gap; and " + "HINDSIGHT_API_RECENCY_DECAY_LINEAR_WINDOW_DAYS — only read when the " + "decay function is `linear`, so switchroom ships no default for it but " + "still honours an operator who flips the function back; and " + "HINDSIGHT_API_WORKER_MAX_SLOTS — the worker poller's TOTAL in-flight " + "task budget, the pool WORKER_CONSOLIDATION_RESERVED_SLOTS reserves out of; " + "unset means upstream's own default; and " + "HINDSIGHT_API_WORKER_RETAIN_RESERVED_SLOTS — the reserved slot FLOOR for the " + "retain (memory write) lane, carved from that same total; unset means " + "upstream's own 0, i.e. no floor and retain competes for the shared " + "pool; and " + "the pre-0.8.6 name HINDSIGHT_API_WORKER_<TYPE>_MAX_SLOTS is still " + "accepted for every operation type and normalised to " + "..._RESERVED_SLOTS on the way in, because setting both names for " + "one type is a hard boot failure in the engine and switchroom " + "therefore emits only the canonical name; and " + "HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY — the cosine-similarity floor a " + "candidate must reach to be returned by the semantic retrieval arm at " + "all (0..1); unset means upstream's own 0.3, and where it should sit " + "depends on the bank's embedding model and phrasing diversity, so " + "switchroom ships no opinion; and " + "HINDSIGHT_MCP_RECALL_BUDGET_MODE — the rollback knob for switchroom's " + "mcp-recall-token-budget image patch; `legacy` restores upstream's " + "exact pre-patch recall returns, anything else or unset is the " + "honest-envelope mode; and " + "HINDSIGHT_API_LLM_TEMPERATURE_REFLECT — upstream's own per-op reflect " + "temperature knob, made live by switchroom's reflect-temperature image " + "patch; a float, or `none` to omit the kwarg (provider default, " + "upstream's accidental pre-patch behaviour); unset means the image's " + "baked default 0.1; and " + "HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT — the background " + "half of switchroom's recall-admission split (#3660): of the " + "RECALL_MAX_CONCURRENT admission slots, at most this many may be held " + "by background consolidation recalls at once, so foreground per-turn " + "recall always keeps the remainder; must be >= 1 and strictly less " + "than RECALL_MAX_CONCURRENT or the engine refuses to boot; unset " + "means the image's derived default min(2, RECALL_MAX_CONCURRENT - 1); " + "1 biases hard toward the interactive lane while a consolidation " + "backlog drains; and " + "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S — the rollback/tuning knob for " + "switchroom's MM-refresh-debounce image patch: the minimum seconds " + "between consolidation-triggered refreshes of one mental model; unset " + "means the image's baked 3600, 0 restores upstream's " + "refresh-every-round behaviour; explicit and cron-scheduled refreshes " + "are never debounced), plus the " + "embedded-PostgreSQL (pg0) sizing keys switchroom manages in " + "src/setup/hindsight-pg-defaults.ts (`HINDSIGHT_PG_ENV_KEYS`: " + "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE, " + "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS — a postgres size string such " + "as `4GB`, or the sentinel `off` to leave pg0's own default for that " + "one knob). A value set here " + "REPLACES switchroom's default and is emitted even when the gating " + "capability is absent, so an operator can always force a knob. Other " + "`HINDSIGHT_API_*` keys are deliberately IGNORED — a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
11422
+ env: exports_external.record(exports_external.union([exports_external.string(), exports_external.number(), exports_external.boolean()])).optional().describe("Operator overrides for switchroom's capability-gated Hindsight " + "performance defaults. Only the keys switchroom actually manages are " + "honoured (`HINDSIGHT_PERF_ENV_KEYS` in " + "src/setup/hindsight-perf-defaults.ts: RERANKER_LOCAL_FP16, " + "RERANKER_LOCAL_BATCH_SIZE, LLM_MAX_CONCURRENT, " + "RETAIN/CONSOLIDATION_LLM_MAX_CONCURRENT, LLM_STRICT_SCHEMA, " + "LLM_MAX_RETRIES, CONSOLIDATION_LLM_PARALLELISM, " + "MAX_OBSERVATIONS_PER_SCOPE, " + "RECALL_MAX_CANDIDATES_PER_SOURCE, LINK_EXPANSION_PER_ENTITY_LIMIT, " + "LINK_EXPANSION_TIMEOUT, LLM_REASONING_EFFORT, " + "RERANKER_LOCAL_BUCKET_BATCHING, RERANKER_MAX_CANDIDATES, " + "RERANKER_LOCAL_MAX_CONCURRENT, RECALL_MAX_CONCURRENT, " + "REFLECT_WALL_TIMEOUT, WORKER_CONSOLIDATION_RESERVED_SLOTS, " + "WORKER_CONSOLIDATION_SLOT_LIMIT, " + "CONSOLIDATION_MAX_MEMORIES_PER_ROUND, GRAPH_SEED_MIN_SIMILARITY, " + "LLM_SUPPORTS_MAX_ITEMS, RECENCY_DECAY_FUNCTION, " + "RECENCY_DECAY_HALFLIFE_DAYS — switchroom defaults recall's recency " + "curve to `exponential` with a 30-day half-life so a fact retained " + "today outranks a stale one, instead of upstream's near-flat " + "linear/365-day window), the override-only keys " + "switchroom manages but ships NO default for " + "(`HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS`: " + "HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY — a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP — the rollback knob for " + "switchroom's CE-saturation damping patch, a float; >= ~0.65 backs the " + "damping out entirely, unset means the patch's own derived gap; and " + "HINDSIGHT_API_RECENCY_DECAY_LINEAR_WINDOW_DAYS — only read when the " + "decay function is `linear`, so switchroom ships no default for it but " + "still honours an operator who flips the function back; and " + "HINDSIGHT_API_WORKER_MAX_SLOTS — the worker poller's TOTAL in-flight " + "task budget, the pool WORKER_CONSOLIDATION_RESERVED_SLOTS reserves out of; " + "unset means upstream's own default; and " + "HINDSIGHT_API_WORKER_RETAIN_RESERVED_SLOTS — the reserved slot FLOOR for the " + "retain (memory write) lane, carved from that same total; unset means " + "upstream's own 0, i.e. no floor and retain competes for the shared " + "pool; and " + "the pre-0.8.6 name HINDSIGHT_API_WORKER_<TYPE>_MAX_SLOTS is still " + "accepted for every operation type and normalised to " + "..._RESERVED_SLOTS on the way in, because setting both names for " + "one type is a hard boot failure in the engine and switchroom " + "therefore emits only the canonical name; and " + "HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY — the cosine-similarity floor a " + "candidate must reach to be returned by the semantic retrieval arm at " + "all (0..1); unset means upstream's own 0.3, and where it should sit " + "depends on the bank's embedding model and phrasing diversity, so " + "switchroom ships no opinion; and " + "HINDSIGHT_MCP_RECALL_BUDGET_MODE — the rollback knob for switchroom's " + "mcp-recall-token-budget image patch; `legacy` restores upstream's " + "exact pre-patch recall returns, anything else or unset is the " + "honest-envelope mode; and " + "HINDSIGHT_API_LLM_TEMPERATURE_REFLECT — upstream's own per-op reflect " + "temperature knob, made live by switchroom's reflect-temperature image " + "patch; a float, or `none` to omit the kwarg (provider default, " + "upstream's accidental pre-patch behaviour); unset means the image's " + "baked default 0.1; and " + "HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT — the background " + "half of switchroom's recall-admission split (#3660): of the " + "RECALL_MAX_CONCURRENT admission slots, at most this many may be held " + "by background consolidation recalls at once, so foreground per-turn " + "recall always keeps the remainder; must be >= 1 and strictly less " + "than RECALL_MAX_CONCURRENT or the engine refuses to boot; unset " + "means the image's derived default min(2, RECALL_MAX_CONCURRENT - 1); " + "1 biases hard toward the interactive lane while a consolidation " + "backlog drains; and " + "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S — the rollback/tuning knob for " + "switchroom's MM-refresh-debounce image patch: the minimum seconds " + "between consolidation-triggered refreshes of one mental model; unset " + "means the image's baked 3600, 0 restores upstream's " + "refresh-every-round behaviour; explicit and cron-scheduled refreshes " + "are never debounced; and " + "HINDSIGHT_API_TEMPORAL_LANGUAGES — the language set dateparser is " + "restricted to during temporal query analysis, made live by switchroom's " + "temporal-language image patch (which ended a 200+-locale auto-detection " + "pass that blocked the shared asyncio loop on every recall); " + "comma-separated, unset means the image's baked `en`, set e.g. `en,es` to " + "restore i18n parsing), plus the " + "embedded-PostgreSQL (pg0) sizing keys switchroom manages in " + "src/setup/hindsight-pg-defaults.ts (`HINDSIGHT_PG_ENV_KEYS`: " + "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE, " + "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS — a postgres size string such " + "as `4GB`, or the sentinel `off` to leave pg0's own default for that " + "one knob). A value set here " + "REPLACES switchroom's default and is emitted even when the gating " + "capability is absent, so an operator can always force a knob. Other " + "`HINDSIGHT_API_*` keys are deliberately IGNORED — a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
11423
11423
  });
11424
11424
  var MicrosoftWorkspaceConfigSchema = exports_external.object({
11425
11425
  microsoft_client_id: exports_external.string().min(1).optional().describe("Microsoft OAuth application (client) ID from Entra portal " + "(literal string or vault reference e.g. " + "'vault:microsoft-oauth-client-id'). OPTIONAL — omit it to use " + "switchroom's shipped default Microsoft app (zero-config). " + "Set it only to bring your own Entra app (BYO)."),
@@ -11387,7 +11387,7 @@ var init_schema = __esm(() => {
11387
11387
  default_channel_id: exports_external.string().describe("Relay-minted group UUID (the NIP-29 `h` tag) the sidecar subscribes " + "to and stamps on injected turns."),
11388
11388
  channel_map: exports_external.record(exports_external.string(), exports_external.string()).default({}).describe("Optional map of extra group UUIDs → friendly labels."),
11389
11389
  pubkey_names: exports_external.record(exports_external.string(), exports_external.string()).default({}).describe("Optional petnames: hex/npub pubkey → display name, used to label " + "the sender on injected turns."),
11390
- pinned_relay_digest: exports_external.string().optional().describe("Pinned relay image digest (M4). The compat-check warns on mismatch; " + "advisory in Phase 1.")
11390
+ pinned_relay_digest: exports_external.string().optional().describe("Pinned relay image digest (M4). RESERVED — no consumer of this field " + "exists; the existing compat-check (compat-check.ts) validates only " + "the wire contract (AUTH kind, message kind, tag names) and does not " + "read this field. Kept in the schema so the intended digest-pin can " + "be wired without a config shape change.")
11391
11391
  }).strict();
11392
11392
  ChannelsSchema = exports_external.object({
11393
11393
  telegram: TelegramChannelSchema,
@@ -11444,7 +11444,7 @@ var init_schema = __esm(() => {
11444
11444
  reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
11445
11445
  consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
11446
11446
  }).optional().describe("LLM knob for the hindsight container. The flat `provider`/`model` set " + "the global default (backward-compatible); optional `retain`/`reflect`/" + "`consolidation` blocks override individual ops. All fields optional; " + "unset fields fall back to the hard-coded defaults."),
11447
- env: exports_external.record(exports_external.union([exports_external.string(), exports_external.number(), exports_external.boolean()])).optional().describe("Operator overrides for switchroom's capability-gated Hindsight " + "performance defaults. Only the keys switchroom actually manages are " + "honoured (`HINDSIGHT_PERF_ENV_KEYS` in " + "src/setup/hindsight-perf-defaults.ts: RERANKER_LOCAL_FP16, " + "RERANKER_LOCAL_BATCH_SIZE, LLM_MAX_CONCURRENT, " + "RETAIN/CONSOLIDATION_LLM_MAX_CONCURRENT, LLM_STRICT_SCHEMA, " + "LLM_MAX_RETRIES, CONSOLIDATION_LLM_PARALLELISM, " + "MAX_OBSERVATIONS_PER_SCOPE, " + "RECALL_MAX_CANDIDATES_PER_SOURCE, LINK_EXPANSION_PER_ENTITY_LIMIT, " + "LINK_EXPANSION_TIMEOUT, LLM_REASONING_EFFORT, " + "RERANKER_LOCAL_BUCKET_BATCHING, RERANKER_MAX_CANDIDATES, " + "RERANKER_LOCAL_MAX_CONCURRENT, RECALL_MAX_CONCURRENT, " + "REFLECT_WALL_TIMEOUT, WORKER_CONSOLIDATION_RESERVED_SLOTS, " + "WORKER_CONSOLIDATION_SLOT_LIMIT, " + "CONSOLIDATION_MAX_MEMORIES_PER_ROUND, GRAPH_SEED_MIN_SIMILARITY, " + "LLM_SUPPORTS_MAX_ITEMS, RECENCY_DECAY_FUNCTION, " + "RECENCY_DECAY_HALFLIFE_DAYS — switchroom defaults recall's recency " + "curve to `exponential` with a 30-day half-life so a fact retained " + "today outranks a stale one, instead of upstream's near-flat " + "linear/365-day window), the override-only keys " + "switchroom manages but ships NO default for " + "(`HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS`: " + "HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY — a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP — the rollback knob for " + "switchroom's CE-saturation damping patch, a float; >= ~0.65 backs the " + "damping out entirely, unset means the patch's own derived gap; and " + "HINDSIGHT_API_RECENCY_DECAY_LINEAR_WINDOW_DAYS — only read when the " + "decay function is `linear`, so switchroom ships no default for it but " + "still honours an operator who flips the function back; and " + "HINDSIGHT_API_WORKER_MAX_SLOTS — the worker poller's TOTAL in-flight " + "task budget, the pool WORKER_CONSOLIDATION_RESERVED_SLOTS reserves out of; " + "unset means upstream's own default; and " + "HINDSIGHT_API_WORKER_RETAIN_RESERVED_SLOTS — the reserved slot FLOOR for the " + "retain (memory write) lane, carved from that same total; unset means " + "upstream's own 0, i.e. no floor and retain competes for the shared " + "pool; and " + "the pre-0.8.6 name HINDSIGHT_API_WORKER_<TYPE>_MAX_SLOTS is still " + "accepted for every operation type and normalised to " + "..._RESERVED_SLOTS on the way in, because setting both names for " + "one type is a hard boot failure in the engine and switchroom " + "therefore emits only the canonical name; and " + "HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY — the cosine-similarity floor a " + "candidate must reach to be returned by the semantic retrieval arm at " + "all (0..1); unset means upstream's own 0.3, and where it should sit " + "depends on the bank's embedding model and phrasing diversity, so " + "switchroom ships no opinion; and " + "HINDSIGHT_MCP_RECALL_BUDGET_MODE — the rollback knob for switchroom's " + "mcp-recall-token-budget image patch; `legacy` restores upstream's " + "exact pre-patch recall returns, anything else or unset is the " + "honest-envelope mode; and " + "HINDSIGHT_API_LLM_TEMPERATURE_REFLECT — upstream's own per-op reflect " + "temperature knob, made live by switchroom's reflect-temperature image " + "patch; a float, or `none` to omit the kwarg (provider default, " + "upstream's accidental pre-patch behaviour); unset means the image's " + "baked default 0.1; and " + "HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT — the background " + "half of switchroom's recall-admission split (#3660): of the " + "RECALL_MAX_CONCURRENT admission slots, at most this many may be held " + "by background consolidation recalls at once, so foreground per-turn " + "recall always keeps the remainder; must be >= 1 and strictly less " + "than RECALL_MAX_CONCURRENT or the engine refuses to boot; unset " + "means the image's derived default min(2, RECALL_MAX_CONCURRENT - 1); " + "1 biases hard toward the interactive lane while a consolidation " + "backlog drains; and " + "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S — the rollback/tuning knob for " + "switchroom's MM-refresh-debounce image patch: the minimum seconds " + "between consolidation-triggered refreshes of one mental model; unset " + "means the image's baked 3600, 0 restores upstream's " + "refresh-every-round behaviour; explicit and cron-scheduled refreshes " + "are never debounced), plus the " + "embedded-PostgreSQL (pg0) sizing keys switchroom manages in " + "src/setup/hindsight-pg-defaults.ts (`HINDSIGHT_PG_ENV_KEYS`: " + "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE, " + "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS — a postgres size string such " + "as `4GB`, or the sentinel `off` to leave pg0's own default for that " + "one knob). A value set here " + "REPLACES switchroom's default and is emitted even when the gating " + "capability is absent, so an operator can always force a knob. Other " + "`HINDSIGHT_API_*` keys are deliberately IGNORED — a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
11447
+ env: exports_external.record(exports_external.union([exports_external.string(), exports_external.number(), exports_external.boolean()])).optional().describe("Operator overrides for switchroom's capability-gated Hindsight " + "performance defaults. Only the keys switchroom actually manages are " + "honoured (`HINDSIGHT_PERF_ENV_KEYS` in " + "src/setup/hindsight-perf-defaults.ts: RERANKER_LOCAL_FP16, " + "RERANKER_LOCAL_BATCH_SIZE, LLM_MAX_CONCURRENT, " + "RETAIN/CONSOLIDATION_LLM_MAX_CONCURRENT, LLM_STRICT_SCHEMA, " + "LLM_MAX_RETRIES, CONSOLIDATION_LLM_PARALLELISM, " + "MAX_OBSERVATIONS_PER_SCOPE, " + "RECALL_MAX_CANDIDATES_PER_SOURCE, LINK_EXPANSION_PER_ENTITY_LIMIT, " + "LINK_EXPANSION_TIMEOUT, LLM_REASONING_EFFORT, " + "RERANKER_LOCAL_BUCKET_BATCHING, RERANKER_MAX_CANDIDATES, " + "RERANKER_LOCAL_MAX_CONCURRENT, RECALL_MAX_CONCURRENT, " + "REFLECT_WALL_TIMEOUT, WORKER_CONSOLIDATION_RESERVED_SLOTS, " + "WORKER_CONSOLIDATION_SLOT_LIMIT, " + "CONSOLIDATION_MAX_MEMORIES_PER_ROUND, GRAPH_SEED_MIN_SIMILARITY, " + "LLM_SUPPORTS_MAX_ITEMS, RECENCY_DECAY_FUNCTION, " + "RECENCY_DECAY_HALFLIFE_DAYS — switchroom defaults recall's recency " + "curve to `exponential` with a 30-day half-life so a fact retained " + "today outranks a stale one, instead of upstream's near-flat " + "linear/365-day window), the override-only keys " + "switchroom manages but ships NO default for " + "(`HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS`: " + "HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY — a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP — the rollback knob for " + "switchroom's CE-saturation damping patch, a float; >= ~0.65 backs the " + "damping out entirely, unset means the patch's own derived gap; and " + "HINDSIGHT_API_RECENCY_DECAY_LINEAR_WINDOW_DAYS — only read when the " + "decay function is `linear`, so switchroom ships no default for it but " + "still honours an operator who flips the function back; and " + "HINDSIGHT_API_WORKER_MAX_SLOTS — the worker poller's TOTAL in-flight " + "task budget, the pool WORKER_CONSOLIDATION_RESERVED_SLOTS reserves out of; " + "unset means upstream's own default; and " + "HINDSIGHT_API_WORKER_RETAIN_RESERVED_SLOTS — the reserved slot FLOOR for the " + "retain (memory write) lane, carved from that same total; unset means " + "upstream's own 0, i.e. no floor and retain competes for the shared " + "pool; and " + "the pre-0.8.6 name HINDSIGHT_API_WORKER_<TYPE>_MAX_SLOTS is still " + "accepted for every operation type and normalised to " + "..._RESERVED_SLOTS on the way in, because setting both names for " + "one type is a hard boot failure in the engine and switchroom " + "therefore emits only the canonical name; and " + "HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY — the cosine-similarity floor a " + "candidate must reach to be returned by the semantic retrieval arm at " + "all (0..1); unset means upstream's own 0.3, and where it should sit " + "depends on the bank's embedding model and phrasing diversity, so " + "switchroom ships no opinion; and " + "HINDSIGHT_MCP_RECALL_BUDGET_MODE — the rollback knob for switchroom's " + "mcp-recall-token-budget image patch; `legacy` restores upstream's " + "exact pre-patch recall returns, anything else or unset is the " + "honest-envelope mode; and " + "HINDSIGHT_API_LLM_TEMPERATURE_REFLECT — upstream's own per-op reflect " + "temperature knob, made live by switchroom's reflect-temperature image " + "patch; a float, or `none` to omit the kwarg (provider default, " + "upstream's accidental pre-patch behaviour); unset means the image's " + "baked default 0.1; and " + "HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT — the background " + "half of switchroom's recall-admission split (#3660): of the " + "RECALL_MAX_CONCURRENT admission slots, at most this many may be held " + "by background consolidation recalls at once, so foreground per-turn " + "recall always keeps the remainder; must be >= 1 and strictly less " + "than RECALL_MAX_CONCURRENT or the engine refuses to boot; unset " + "means the image's derived default min(2, RECALL_MAX_CONCURRENT - 1); " + "1 biases hard toward the interactive lane while a consolidation " + "backlog drains; and " + "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S — the rollback/tuning knob for " + "switchroom's MM-refresh-debounce image patch: the minimum seconds " + "between consolidation-triggered refreshes of one mental model; unset " + "means the image's baked 3600, 0 restores upstream's " + "refresh-every-round behaviour; explicit and cron-scheduled refreshes " + "are never debounced; and " + "HINDSIGHT_API_TEMPORAL_LANGUAGES — the language set dateparser is " + "restricted to during temporal query analysis, made live by switchroom's " + "temporal-language image patch (which ended a 200+-locale auto-detection " + "pass that blocked the shared asyncio loop on every recall); " + "comma-separated, unset means the image's baked `en`, set e.g. `en,es` to " + "restore i18n parsing), plus the " + "embedded-PostgreSQL (pg0) sizing keys switchroom manages in " + "src/setup/hindsight-pg-defaults.ts (`HINDSIGHT_PG_ENV_KEYS`: " + "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE, " + "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS — a postgres size string such " + "as `4GB`, or the sentinel `off` to leave pg0's own default for that " + "one knob). A value set here " + "REPLACES switchroom's default and is emitted even when the gating " + "capability is absent, so an operator can always force a knob. Other " + "`HINDSIGHT_API_*` keys are deliberately IGNORED — a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
11448
11448
  });
11449
11449
  MicrosoftWorkspaceConfigSchema = exports_external.object({
11450
11450
  microsoft_client_id: exports_external.string().min(1).optional().describe("Microsoft OAuth application (client) ID from Entra portal " + "(literal string or vault reference e.g. " + "'vault:microsoft-oauth-client-id'). OPTIONAL — omit it to use " + "switchroom's shipped default Microsoft app (zero-config). " + "Set it only to bring your own Entra app (BYO)."),
@@ -19169,7 +19169,8 @@ var HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS = new Set([
19169
19169
  "HINDSIGHT_API_LLM_TEMPERATURE_REFLECT",
19170
19170
  "HINDSIGHT_API_RETAIN_WALL_TIMEOUT",
19171
19171
  "HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT",
19172
- "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S"
19172
+ "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S",
19173
+ "HINDSIGHT_API_TEMPORAL_LANGUAGES"
19173
19174
  ]);
19174
19175
  var HINDSIGHT_WORKER_SLOT_TYPES = [
19175
19176
  "consolidation",