switchroom 0.19.26 → 0.19.28
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.
- package/bin/git-agent-attribution-hook.sh +144 -0
- package/dist/agent-scheduler/index.js +60 -2
- package/dist/auth-broker/index.js +244 -13
- package/dist/cli/autoaccept-poll.js +225 -17
- package/dist/cli/notion-write-pretool.mjs +60 -2
- package/dist/cli/switchroom.js +2843 -1220
- package/dist/host-control/main.js +245 -14
- package/dist/vault/approvals/kernel-server.js +242 -13
- package/dist/vault/broker/server.js +242 -13
- package/package.json +7 -2
- package/profiles/_base/cron-session.sh.hbs +8 -0
- package/profiles/_base/start.sh.hbs +175 -15
- package/telegram-plugin/card-layout.ts +328 -0
- package/telegram-plugin/dist/bridge/bridge.js +94 -1
- package/telegram-plugin/dist/gateway/gateway.js +2544 -1182
- package/telegram-plugin/dist/server.js +97 -1
- package/telegram-plugin/edit-flood-fuse.ts +841 -57
- package/telegram-plugin/flood-429-ledger.ts +526 -0
- package/telegram-plugin/flood-circuit-breaker.ts +18 -0
- package/telegram-plugin/gateway/callback-query-handlers.ts +6 -0
- package/telegram-plugin/gateway/flood-reply-queue.ts +168 -0
- package/telegram-plugin/gateway/gateway.ts +67 -70
- package/telegram-plugin/gateway/mcp-failure-hook.ts +74 -0
- package/telegram-plugin/gateway/narrative-lane.ts +14 -0
- package/telegram-plugin/gateway/outbound-send-path.ts +36 -0
- package/telegram-plugin/gateway/outbox-sweep.ts +183 -6
- package/telegram-plugin/gateway/pinned-message-handler.ts +12 -16
- package/telegram-plugin/gateway/status-pin-retarget.ts +72 -36
- package/telegram-plugin/gateway/status-pin-store.ts +58 -9
- package/telegram-plugin/gateway/worker-pin-reaper.ts +56 -7
- package/telegram-plugin/inline-keyboard-callbacks.ts +202 -21
- package/telegram-plugin/llm-error-present.ts +61 -2
- package/telegram-plugin/mcp-credential-failure.ts +459 -0
- package/telegram-plugin/model-unavailable.ts +8 -0
- package/telegram-plugin/operator-events.ts +110 -5
- package/telegram-plugin/outbound-class.ts +81 -0
- package/telegram-plugin/provider-credit.ts +237 -0
- package/telegram-plugin/scripts/bun-test-ci.sh +36 -6
- package/telegram-plugin/send-gate.ts +24 -2
- package/telegram-plugin/status-no-truncate.ts +10 -48
- package/telegram-plugin/status-pin-driver.ts +33 -45
- package/telegram-plugin/status-pin.ts +18 -1
- package/telegram-plugin/tests/card-golden.test.ts +69 -0
- package/telegram-plugin/tests/card-lifecycle-render.test.ts +362 -0
- package/telegram-plugin/tests/card-type-distinguishability.test.ts +187 -164
- package/telegram-plugin/tests/card-variants.golden.txt +211 -0
- package/telegram-plugin/tests/card-variants.ts +366 -0
- package/telegram-plugin/tests/edit-flood-fuse-ban-awareness.test.ts +373 -0
- package/telegram-plugin/tests/edit-flood-fuse-default-deny.test.ts +319 -0
- package/telegram-plugin/tests/edit-flood-fuse-reply-reserve.test.ts +340 -0
- package/telegram-plugin/tests/edit-flood-fuse.test.ts +11 -2
- package/telegram-plugin/tests/feed-edit-rate-ceiling.test.ts +462 -0
- package/telegram-plugin/tests/finalize-callback-flood-policy.test.ts +298 -0
- package/telegram-plugin/tests/finalize-callback.test.ts +41 -8
- package/telegram-plugin/tests/fixtures/real-429-stream.ts +220 -0
- package/telegram-plugin/tests/flood-429-ledger.test.ts +278 -0
- package/telegram-plugin/tests/flood-429-recorder-wiring.test.ts +128 -0
- package/telegram-plugin/tests/flood-reply-queue.test.ts +418 -0
- package/telegram-plugin/tests/mcp-credential-failure.test.ts +310 -0
- package/telegram-plugin/tests/outbox-sweep-flood-breaker.test.ts +221 -0
- package/telegram-plugin/tests/pinned-card-collapse.test.ts +19 -24
- package/telegram-plugin/tests/pinned-message-handler.test.ts +15 -15
- package/telegram-plugin/tests/provider-credit-402.test.ts +243 -0
- package/telegram-plugin/tests/status-pin-api.test.ts +11 -11
- package/telegram-plugin/tests/status-pin-boot-recovery.test.ts +36 -37
- package/telegram-plugin/tests/status-pin-lifecycle.test.ts +602 -0
- package/telegram-plugin/tests/status-pin-retarget.test.ts +90 -62
- package/telegram-plugin/tests/status-pin-service-message-suppression.test.ts +7 -3
- package/telegram-plugin/tests/status-pin-store.test.ts +109 -60
- package/telegram-plugin/tests/status-pin.test.ts +56 -5
- package/telegram-plugin/tests/test-runner-coverage.test.ts +133 -0
- package/telegram-plugin/tests/worker-activity-feed.test.ts +12 -10
- package/telegram-plugin/tests/worker-feed-coalesce.test.ts +23 -29
- package/telegram-plugin/tests/worker-feed-pin-persistence.test.ts +56 -59
- package/telegram-plugin/tests/worker-feed-terminal-edit-class.test.ts +335 -0
- package/telegram-plugin/tests/worker-visibility-prose-silent-harness.test.ts +1 -1
- package/telegram-plugin/tool-activity-summary.ts +239 -365
- package/telegram-plugin/uat/assertions.ts +22 -11
- package/telegram-plugin/uat/feed-matcher.test.ts +24 -17
- package/telegram-plugin/worker-activity-feed.ts +105 -47
- package/vendor/hindsight-memory/CLAUDE.md +45 -0
- package/vendor/hindsight-memory/scripts/drain_pending.py +433 -11
- package/vendor/hindsight-memory/scripts/lib/config.py +33 -0
- package/vendor/hindsight-memory/scripts/lib/pending.py +193 -28
- package/vendor/hindsight-memory/scripts/recall.py +176 -7
- package/vendor/hindsight-memory/scripts/tests/test_config_recall_passthrough_env.py +170 -0
- package/vendor/hindsight-memory/scripts/tests/test_drain_circuit_breaker.py +401 -0
- package/vendor/hindsight-memory/scripts/tests/test_drain_serialisation.py +286 -0
- package/vendor/hindsight-memory/scripts/tests/test_pending_drops.py +817 -8
- package/vendor/hindsight-memory/scripts/tests/test_recall_min_score.py +464 -0
- package/vendor/hindsight-memory/settings.json +1 -1
- package/vendor/hindsight-memory/tests/test_hooks.py +11 -2
|
@@ -4171,10 +4171,37 @@ var init_schema = __esm(() => {
|
|
|
4171
4171
|
request_timeout_seconds: exports_external.number().int().min(1).optional().describe("Per-bank HTTP read timeout, in seconds, for one recall " + "request. Even parallelised, each bank carries its own deadline " + "so ONE hung bank returns empty instead of consuming the shared " + "deadline and starving its siblings. The plugin default is 12 " + "(raised from a hardcoded 8 in #3757, which fired on 96.8% of " + "one agent's own-bank recalls). Switchroom defaults it to the " + "effective `parallel_deadline_seconds` instead — 10 at the " + "shipped ceiling — because the shared fan-out deadline is " + "already the tighter outer guard, so a per-bank value above it " + "can never bind. An explicitly configured value above the " + "effective deadline is clamped down to it, and the clamp is " + "reported."),
|
|
4172
4172
|
own_bank_min_slots: exports_external.number().int().min(0).optional().describe("Slots inside `max_memories` reserved as a FLOOR for the agent's " + "own bank when recall fans out to more than one bank. The merged " + "set is sorted globally by relevance and head-sliced, which is " + "winner-take-all across banks: when both banks return more " + "candidates than the cap, one bank's score distribution can fill " + "every slot and the agent gets a dossier about its operator with " + "none of its own session memory. A floor, not a quota: at most " + "this many slots, only if the own bank returned that many, and " + "only up to HALF the cap shared with `additional_bank_min_slots` " + "— the rest is always won on pure relevance, so composition still " + "moves with the scores. Fixes score-based crowd-out only; a " + "timed-out bank returns no candidates and reservation is a no-op " + "there. 0 disables (default). Switchroom-managed agents use 2 " + "against the fleet-deployed cap of 6."),
|
|
4173
4173
|
additional_bank_min_slots: exports_external.number().int().min(0).optional().describe("Slots inside `max_memories` reserved as a FLOOR for the " + "additional (profile / shared / sender) banks. Symmetric with " + "`own_bank_min_slots` — same floor-not-quota semantics, and the " + "two share the same half-of-cap reservation budget. When they sum " + "above that budget the own-bank floor is honoured first. 0 " + "disables (default). Switchroom-managed agents use 1 against the " + "fleet-deployed cap of 6. Observe `injected_own_bank_count` / " + "`injected_additional_bank_count` via " + "`switchroom memory recall-log`."),
|
|
4174
|
+
min_score: exports_external.number().min(0).optional().describe("Absolute floor on a memory's engine relevance score " + "(`scores.final`) for it to be injected. 0 disables (default, " + "and the shipped fleet behaviour). Exists for one measured " + "failure: when the agent's own bank times out, recall still " + "injects side-bank residue under the banner 'Relevant memories " + "from past conversations' — 98.4% of degraded turns have a best " + "injected score below 0.01, against 28.4% of healthy ones. Six " + "noise memories are worse than none, because the agent cannot " + "tell them apart. Below-floor results are dropped BEFORE " + "rendering, and when the floor empties the set the turn says so " + "rather than going silent. Do NOT read this as a general " + "precision control: `scores.final` is not calibrated across " + "queries, and #3761 measured that an unconditional 0.01 floor " + "empties ~28% of HEALTHY recalls — which is why " + "`min_score_scope` defaults to degraded turns only. Observe " + "`dropped_below_min_score` via `switchroom memory recall-log`."),
|
|
4175
|
+
min_score_scope: exports_external.enum(["degraded", "all"]).optional().describe('Which turns `min_score` binds on. "degraded" (default) — only ' + "turns where the agent's OWN bank timed out or was unreachable, " + "the population where a below-floor score actually predicts " + "noise and where the agent already receives the degraded-recall " + 'disclosure. "all" — every turn; only for an operator who has ' + "measured their own bank's score distribution, since it " + "re-creates the empty-recall failure of #3541 at any floor " + "calibrated on degraded data. No effect while `min_score` is 0."),
|
|
4174
4176
|
types: exports_external.array(exports_external.string()).optional().describe("Hindsight fact types to recall. Switchroom default is " + '["world", "experience", "observation"] — the synthesized ' + "`observation` tier is on by default. Set to " + '["world", "experience"] to opt out of observation-backed ' + "recall for this agent (or fleet-wide under defaults)."),
|
|
4175
4177
|
additional_banks: exports_external.array(exports_external.string()).optional().describe("Extra Hindsight banks to recall from on every turn, merged into " + "the agent's own bank results — e.g. a shared operator/household " + "profile bank authored via `switchroom memory profile`. Each is " + "recalled with the `request_timeout_seconds` per-bank timeout " + "(defaults to the effective `parallel_deadline_seconds`, 10s at " + "the shipped ceiling) and is non-fatal on failure. Stays " + "within the single tenant: all banks are the operator's data, in " + "the operator's Hindsight instance (see the `single-tenant` " + "invariant). Defaults to [] (no extra banks)."),
|
|
4176
4178
|
sender_banks: exports_external.record(exports_external.string(), exports_external.string()).optional().describe("Per-speaker recall routing: a map of Telegram sender → extra " + "recall bank. When a message arrives, the agent also recalls the " + "speaker's bank (matched by Telegram username — a leading @ is " + "optional — or numeric user_id), merged " + "into its own results — so each trusted user gets their own " + "profile context. Additive recall scoping within the single " + "tenant: never an access boundary (who may drive an agent stays " + "the per-agent user assignment in `access.allowFrom`). Author the " + "banks via `switchroom memory profile`."),
|
|
4177
4179
|
skip_trivial: exports_external.boolean().optional().describe("Skip recall on plausibly-stateless trivial turns (time/date/" + "greeting). Switchroom default true — saves the recall arm + " + "injected tokens on turns that never need memory, guarded so it " + "never skips a turn that references user/project/session state. " + "Set false to always run recall."),
|
|
4180
|
+
budget: exports_external.enum(["low", "mid", "high"]).optional().describe('How hard Hindsight searches. "low" (switchroom default) = ' + 'vector retrieval only, ~1-2s. "mid" adds the LLM rerank pass ' + "and measured ~5s of hook latency on real fleet turns — the " + "second-largest contributor to perceived dead air after model " + 'TTFT. "high" is thorough and slower still. Raise it for an ' + "agent whose recall quality matters more than its reply latency " + "(a research or audit role); leave it at low for chat."),
|
|
4181
|
+
max_tokens: exports_external.number().int().min(1).optional().describe("Token budget for the injected memory block. Default 1024. This " + "is the TOKEN bound; `max_memories` is the separate COUNT bound " + "and the tighter of the two wins. Raise it only alongside " + "`max_memories` — on its own it buys nothing once the count cap " + "binds."),
|
|
4182
|
+
prefer_observations: exports_external.boolean().optional().describe("Bias recall toward the synthesized `observation` tier, " + "backfilling the slots freed by superseded raw facts for denser " + "coverage inside the same budget. Default true. Set false to " + "rank raw `world`/`experience` facts on equal footing — useful " + "when auditing what the consolidation engine actually stored, or " + "if a bank's observations are stale."),
|
|
4183
|
+
context_turns: exports_external.number().int().min(1).optional().describe("How many recent human turns are composed into the recall query. " + 'Default 2, so a bare follow-up ("and the port?") embeds with ' + "its antecedent instead of recalling on the pronoun alone. 1 = " + "the latest turn only. Raising it costs BM25 terms, which is the " + "real recall cost driver — `query_max_tokens` still bounds the " + "result, so a large value mostly shifts which terms survive."),
|
|
4184
|
+
roles: exports_external.array(exports_external.string().min(1)).min(1).optional().describe("Transcript roles the multi-turn composition may draw from. " + 'Default ["user", "assistant"]. Set ["user"] to compose ' + "the query from the human's words only — worth trying when an " + "agent's own verbose replies are dominating the query terms. No " + "effect while `context_turns` is 1."),
|
|
4185
|
+
prompt_preamble: exports_external.string().min(1).optional().describe("The banner rendered above injected memories. The agent reads " + "this line as the instruction for how to treat the block, so it " + "is a behaviour knob, not cosmetics. Default tells the model to " + "prioritise recent memories on conflict and ignore irrelevant " + "ones. Override to tighten that framing for a specialised agent."),
|
|
4186
|
+
tags: exports_external.array(exports_external.string().min(1)).optional().describe("Restrict recall to memories carrying these tags. Default [] = " + "no filter (match everything). This is a HARD filter applied " + "server-side — a memory without the tags cannot surface at any " + "score — so it is for a genuinely scoped agent, not for " + "ranking. Use `tag_weights` when you want a preference rather " + "than an exclusion."),
|
|
4187
|
+
tags_match: exports_external.enum(["any", "all", "any_strict", "all_strict"]).optional().describe('How `tags` combine. "any" (default) = at least one; ' + '"all" = every tag. The `_strict` forms additionally require ' + "the memory to actually carry the tags rather than merely rank " + "for them. No effect while `tags` and `tag_groups` are empty."),
|
|
4188
|
+
tag_groups: exports_external.union([
|
|
4189
|
+
exports_external.array(exports_external.array(exports_external.string().min(1))),
|
|
4190
|
+
exports_external.record(exports_external.string(), exports_external.array(exports_external.string().min(1)))
|
|
4191
|
+
]).optional().describe("Tag filtering with grouping — either an OR-of-ANDs list " + '([["a","b"],["c"]] = (a AND b) OR c) or a named ' + "{group: [tags]} map. Default unset (no grouping). Use when a " + "flat `tags` + `tags_match` cannot express the scope you need."),
|
|
4192
|
+
tag_weights: exports_external.record(exports_external.string(), exports_external.number().min(0)).optional().describe("Per-tag multipliers applied to `scores.final` just before the " + "final sort — a DEMOTION/PROMOTION, never a drop, so a " + "down-weighted memory still surfaces when it is the only " + "relevant hit. MERGED over switchroom's seed " + '({"sidechain": 0.8}, which ranks delegated sub-agent ' + "process-memories just under first-party ones), so setting one " + "unrelated weight does not silently undo it; pass " + "`sidechain: 1.0` to neutralise the seed. Reach for this when " + "recall_log shows one class of memory crowding the block."),
|
|
4193
|
+
additional_bank_filters: exports_external.record(exports_external.string(), exports_external.object({
|
|
4194
|
+
tags: exports_external.array(exports_external.string().min(1)).optional(),
|
|
4195
|
+
tags_match: exports_external.enum(["any", "all", "any_strict", "all_strict"]).optional(),
|
|
4196
|
+
tag_groups: exports_external.union([
|
|
4197
|
+
exports_external.array(exports_external.array(exports_external.string().min(1))),
|
|
4198
|
+
exports_external.record(exports_external.string(), exports_external.array(exports_external.string().min(1)))
|
|
4199
|
+
]).optional()
|
|
4200
|
+
}).strict()).optional().describe("Per-bank overrides of the tag filters above, keyed by bank id " + "(applies to `additional_banks` AND to sender banks). Default " + "{} = every extra bank inherits the global filters. Use it to " + "scope a shared bank — e.g. recall only `profile`-tagged " + "memories from the operator's profile bank while leaving the " + "agent's own bank unfiltered."),
|
|
4201
|
+
transcript_fallback: exports_external.boolean().optional().describe("When every bank returns zero results AND no bank hit its " + "deadline, grep the current session's transcript tail for turns " + "matching the query and inject them as a clearly-labelled " + "lower-confidence block. Default true — it covers the window " + "between an abrupt kill and the next boot reconciliation, where " + "the fact layer was never told about the lost turns. Set false " + "if you never want un-consolidated transcript text in context."),
|
|
4202
|
+
transcript_tail_bytes: exports_external.number().int().min(0).optional().describe("Bytes of the session transcript read from the tail for the " + "multi-turn query composition. Default 262144 (256 KiB), which " + "keeps the per-turn read O(1) on a session log that can grow to " + "many MB. 0 = read the whole file (the pre-bound behaviour, and " + "the rollback lever if a composition ever needs older turns)."),
|
|
4203
|
+
max_query_chars: exports_external.number().int().min(1).optional().describe("Character bound on the composed recall query, applied before " + "`query_max_tokens` shapes it. Default 800. Truncation preserves " + "the latest turn and drops the oldest context first. Lower it " + "for an agent whose turns are long pasted payloads."),
|
|
4204
|
+
parallel: exports_external.boolean().optional().describe("Run the directives fetch and every bank recall concurrently " + "under one shared deadline, so total latency is the SLOWEST slot " + "rather than their SUM. Default true. false restores the serial " + "path — the rollback lever if the parallel path ever misbehaves; " + "expect multi-bank recall latency to add up."),
|
|
4178
4205
|
topic_filter_mode: exports_external.enum(["soft-preamble", "hard-filter"]).optional().describe("Supergroup-mode cross-topic memory behaviour. Default " + "(unset) → soft-preamble: recall returns memories from all " + "topics, and a 'Current topic: …' preamble tells the model " + "to self-scope. hard-filter: drop any recalled memory whose " + "metadata.thread_id differs from the active inbound's topic. " + "Flip to hard-filter when the recall_log shows binding " + "failures (model surfacing the right memory but applying " + "it to the wrong topic).")
|
|
4179
4206
|
}).optional().describe("Auto-recall tuning knobs"),
|
|
4180
4207
|
retain: exports_external.object({
|
|
@@ -4377,7 +4404,10 @@ var init_schema = __esm(() => {
|
|
|
4377
4404
|
admin_key: exports_external.string().optional().describe("LiteLLM master/admin key used at apply time to provision the team + " + "virtual key. Supports a vault reference (e.g. " + "'vault:litellm/master-key') — resolution happens at apply time via " + "the vault-broker. Never injected into the agent container."),
|
|
4378
4405
|
team: exports_external.string().optional().describe("LiteLLM team alias the per-agent key is created under. Defaults to " + "'switchroom' (applied in code, not as a schema default)."),
|
|
4379
4406
|
small_fast_model: exports_external.string().optional().describe("Model id exported as ANTHROPIC_SMALL_FAST_MODEL for the claude CLI's " + "background/fast lane, e.g. 'claude-haiku-4-5-20251001'."),
|
|
4380
|
-
tags: exports_external.record(exports_external.string(), exports_external.string()).optional().describe("Extra key/value metadata tags attached to the provisioned LiteLLM " + "virtual key. Merged per-key across cascade layers (agent wins).")
|
|
4407
|
+
tags: exports_external.record(exports_external.string(), exports_external.string()).optional().describe("Extra key/value metadata tags attached to the provisioned LiteLLM " + "virtual key. Merged per-key across cascade layers (agent wins)."),
|
|
4408
|
+
max_budget: exports_external.number().positive().optional().describe("HARD spend cap in USD for this agent's virtual key over one " + "`budget_duration` window. LiteLLM refuses the request once the key's " + "tracked spend exceeds it, so a runaway loop costs at most this much " + "before it is stopped. Defaults to " + "DEFAULT_KEY_MAX_BUDGET_USD (see src/litellm/budget.ts) — deliberately " + "conservative; raise it per-agent rather than removing it. Set 0 or " + "omit `budget_duration` at your own risk: an uncapped key is only as " + "bounded as the upstream account balance."),
|
|
4409
|
+
soft_budget: exports_external.number().positive().optional().describe("ADVISORY spend threshold in USD. LiteLLM keeps serving past it and " + "raises a budget alert instead. Must be < max_budget. NOTE: LiteLLM " + "accepts soft_budget only on POST /key/generate (GenerateKeyRequest); " + "UpdateKeyRequest does NOT carry it, so changing this value only takes " + "effect on a key that is (re)generated, not on an existing one."),
|
|
4410
|
+
budget_duration: exports_external.string().regex(/^\d+(s|m|h|d|mo)$/, "budget_duration must be a LiteLLM duration like '30d', '24h', '1mo'").optional().describe("Rolling window the budget resets on, in LiteLLM duration syntax " + "('30d', '24h', '1mo'). Defaults to DEFAULT_KEY_BUDGET_DURATION. " + "WITHOUT a duration LiteLLM treats max_budget as a LIFETIME cap that " + "never resets — the key silently dies for good once it is hit.")
|
|
4381
4411
|
}).optional().describe("LiteLLM routing config — opt-in per-agent virtual-key auto-provisioning " + "+ routing env. Default OFF. See LiteLLMConfigSchema doc for the full flow.");
|
|
4382
4412
|
HindsightPerOpLlmSchema = exports_external.object({
|
|
4383
4413
|
model: exports_external.string().min(1).optional().describe("Per-op model (upstream `HINDSIGHT_API_<OP>_LLM_MODEL`). Absent → " + "inherit the global `hindsight.llm.model`."),
|
|
@@ -4387,6 +4417,7 @@ var init_schema = __esm(() => {
|
|
|
4387
4417
|
context_window: exports_external.number().int().positive().optional().describe("Context window (tokens) of the backend serving THIS op. NOT an " + "upstream env var — switchroom derives the op's token budget " + "(consolidation batch size / max-completion caps / reflect " + "max-context cap) from it so a single call can never overflow the " + "window. Absent → inherit " + "`hindsight.llm.context_window`, else a per-provider default " + "(conservative for non-`claude-code` providers, which usually mean " + "a local llama.cpp/Ollama slot; a self-hosted `base_url` — loopback, " + "RFC1918, `.local`/`.internal` — forces the conservative default too, " + "regardless of the provider NAME, since the endpoint is where the " + "traffic actually terminates). All three lanes (`retain`, " + "`reflect`, `consolidation`) are budgeted independently.")
|
|
4388
4418
|
}).describe("Per-operation LLM override. Every field optional; an unset field (or " + "an omitted op block) inherits the global `hindsight.llm.*`, which is " + "already the engine's fallback — switchroom emits only the vars set.");
|
|
4389
4419
|
HindsightConfigSchema = exports_external.object({
|
|
4420
|
+
gpu: exports_external.boolean().optional().describe("Force GPU passthrough for the hindsight container on (`true`) or off " + "(`false`), overriding host autodetection in BOTH directions. Absent " + "(the default) → autodetect from the persisted host-capabilities " + "verdict (`~/.switchroom/host-capabilities.json`), which enables " + "`--gpus all` only when that file proves BOTH a GPU and the nvidia " + "container toolkit. Set `true` when that verdict is wrong or unreadable " + "and you know the host has a working toolkit — switchroom cannot verify " + "it for you, and `docker run --gpus all` hard-fails container create on " + "a host without one. Set `false` to pin the container to CPU on a GPU " + "host. This is also the declarative opt-out for the recreate-time GPU " + "drop guard (`switchroom memory setup --recreate` refuses to silently " + "turn a GPU container into a CPU one). `--gpu`/`--no-gpu` on `memory " + "setup` override this for a single run."),
|
|
4390
4421
|
llm: exports_external.object({
|
|
4391
4422
|
provider: exports_external.string().min(1).optional().describe("Hindsight LLM provider (upstream `HINDSIGHT_API_LLM_PROVIDER`). " + "Defaults to `claude-code` (subscription-honest, broker-fed OAuth). " + "Any litellm-routable provider the upstream image supports is valid. " + "Serves as the GLOBAL default for every op absent a per-op override."),
|
|
4392
4423
|
model: exports_external.string().min(1).optional().describe("Hindsight LLM model (upstream `HINDSIGHT_API_LLM_MODEL`). Defaults " + "to HINDSIGHT_DEFAULT_MODEL. Any model your LiteLLM proxy can route " + "is valid, e.g. `openrouter/z-ai/glm-5.2` when routing through the " + "fleet proxy. With provider=claude-code this value is ALSO exported " + "as `ANTHROPIC_MODEL` to the claude subprocess. Serves as the GLOBAL " + "default for every op absent a per-op override."),
|
|
@@ -4395,7 +4426,7 @@ var init_schema = __esm(() => {
|
|
|
4395
4426
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
|
|
4396
4427
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
|
|
4397
4428
|
}).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."),
|
|
4398
|
-
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_MAX_SLOTS, " + "WORKER_CONSOLIDATION_SLOT_LIMIT, " + "CONSOLIDATION_MAX_MEMORIES_PER_ROUND), 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), 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).")
|
|
4429
|
+
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_MAX_SLOTS, " + "WORKER_CONSOLIDATION_SLOT_LIMIT, " + "CONSOLIDATION_MAX_MEMORIES_PER_ROUND, 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_MAX_SLOTS reserves out of; " + "unset means upstream's own default), 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).")
|
|
4399
4430
|
});
|
|
4400
4431
|
MicrosoftWorkspaceConfigSchema = exports_external.object({
|
|
4401
4432
|
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)."),
|
|
@@ -4538,6 +4569,33 @@ var init_schema = __esm(() => {
|
|
|
4538
4569
|
request_timeout_seconds: exports_external.number().int().min(1).optional(),
|
|
4539
4570
|
own_bank_min_slots: exports_external.number().int().min(0).optional(),
|
|
4540
4571
|
additional_bank_min_slots: exports_external.number().int().min(0).optional(),
|
|
4572
|
+
min_score: exports_external.number().min(0).optional(),
|
|
4573
|
+
min_score_scope: exports_external.enum(["degraded", "all"]).optional(),
|
|
4574
|
+
budget: exports_external.enum(["low", "mid", "high"]).optional(),
|
|
4575
|
+
max_tokens: exports_external.number().int().min(1).optional(),
|
|
4576
|
+
prefer_observations: exports_external.boolean().optional(),
|
|
4577
|
+
context_turns: exports_external.number().int().min(1).optional(),
|
|
4578
|
+
roles: exports_external.array(exports_external.string().min(1)).min(1).optional(),
|
|
4579
|
+
prompt_preamble: exports_external.string().min(1).optional(),
|
|
4580
|
+
tags: exports_external.array(exports_external.string().min(1)).optional(),
|
|
4581
|
+
tags_match: exports_external.enum(["any", "all", "any_strict", "all_strict"]).optional(),
|
|
4582
|
+
tag_groups: exports_external.union([
|
|
4583
|
+
exports_external.array(exports_external.array(exports_external.string().min(1))),
|
|
4584
|
+
exports_external.record(exports_external.string(), exports_external.array(exports_external.string().min(1)))
|
|
4585
|
+
]).optional(),
|
|
4586
|
+
tag_weights: exports_external.record(exports_external.string(), exports_external.number().min(0)).optional(),
|
|
4587
|
+
additional_bank_filters: exports_external.record(exports_external.string(), exports_external.object({
|
|
4588
|
+
tags: exports_external.array(exports_external.string().min(1)).optional(),
|
|
4589
|
+
tags_match: exports_external.enum(["any", "all", "any_strict", "all_strict"]).optional(),
|
|
4590
|
+
tag_groups: exports_external.union([
|
|
4591
|
+
exports_external.array(exports_external.array(exports_external.string().min(1))),
|
|
4592
|
+
exports_external.record(exports_external.string(), exports_external.array(exports_external.string().min(1)))
|
|
4593
|
+
]).optional()
|
|
4594
|
+
}).strict()).optional(),
|
|
4595
|
+
transcript_fallback: exports_external.boolean().optional(),
|
|
4596
|
+
transcript_tail_bytes: exports_external.number().int().min(0).optional(),
|
|
4597
|
+
max_query_chars: exports_external.number().int().min(1).optional(),
|
|
4598
|
+
parallel: exports_external.boolean().optional(),
|
|
4541
4599
|
additional_banks: exports_external.array(exports_external.string()).optional(),
|
|
4542
4600
|
sender_banks: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
4543
4601
|
}).optional()
|
|
@@ -19211,6 +19269,7 @@ function assertPositive(value, label) {
|
|
|
19211
19269
|
|
|
19212
19270
|
// src/setup/host-capabilities.ts
|
|
19213
19271
|
init_paths();
|
|
19272
|
+
var _warnedReads = new Set;
|
|
19214
19273
|
|
|
19215
19274
|
// src/setup/hindsight-pg-defaults.ts
|
|
19216
19275
|
var HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION = 8 * 1024;
|
|
@@ -19241,7 +19300,13 @@ var HINDSIGHT_DEFAULT_LINK_EXPANSION_TIMEOUT_S = 2;
|
|
|
19241
19300
|
var HINDSIGHT_DEFAULT_LLM_REASONING_EFFORT = "low";
|
|
19242
19301
|
var HINDSIGHT_DEFAULT_LLM_MAX_CONCURRENT = 4;
|
|
19243
19302
|
var HINDSIGHT_DEFAULT_RETAIN_LLM_MAX_CONCURRENT = 1;
|
|
19244
|
-
|
|
19303
|
+
function hindsightConsolidationLlmMaxConcurrentDefault(globalMaxConcurrent = HINDSIGHT_DEFAULT_LLM_MAX_CONCURRENT, retainMaxConcurrent = HINDSIGHT_DEFAULT_RETAIN_LLM_MAX_CONCURRENT) {
|
|
19304
|
+
const globalCap = Number.isFinite(globalMaxConcurrent) && globalMaxConcurrent >= 1 ? Math.floor(globalMaxConcurrent) : HINDSIGHT_DEFAULT_LLM_MAX_CONCURRENT;
|
|
19305
|
+
const retainCap = Number.isFinite(retainMaxConcurrent) && retainMaxConcurrent >= 0 ? Math.floor(retainMaxConcurrent) : HINDSIGHT_DEFAULT_RETAIN_LLM_MAX_CONCURRENT;
|
|
19306
|
+
const headroomBound = Math.max(1, globalCap - 1);
|
|
19307
|
+
return Math.min(headroomBound, Math.max(1, globalCap - retainCap - 1));
|
|
19308
|
+
}
|
|
19309
|
+
var HINDSIGHT_DEFAULT_CONSOLIDATION_LLM_MAX_CONCURRENT = hindsightConsolidationLlmMaxConcurrentDefault();
|
|
19245
19310
|
var HINDSIGHT_DEFAULT_RERANKER_LOCAL_FP16 = "true";
|
|
19246
19311
|
var HINDSIGHT_DEFAULT_RERANKER_LOCAL_BATCH_SIZE = 128;
|
|
19247
19312
|
var HINDSIGHT_DEFAULT_LLM_STRICT_SCHEMA = "true";
|
|
@@ -19256,6 +19321,8 @@ var HINDSIGHT_DEFAULT_REFLECT_WALL_TIMEOUT_S = 600;
|
|
|
19256
19321
|
var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_MEMORIES_PER_ROUND = 500;
|
|
19257
19322
|
var HINDSIGHT_DEFAULT_CONSOLIDATION_SLOT_LIMIT = 6;
|
|
19258
19323
|
var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_SLOTS = 1;
|
|
19324
|
+
var HINDSIGHT_DEFAULT_RECENCY_DECAY_FUNCTION = "exponential";
|
|
19325
|
+
var HINDSIGHT_DEFAULT_RECENCY_DECAY_HALFLIFE_DAYS = 30;
|
|
19259
19326
|
var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
19260
19327
|
[
|
|
19261
19328
|
"HINDSIGHT_API_RECALL_MAX_CANDIDATES_PER_SOURCE",
|
|
@@ -19309,6 +19376,14 @@ var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
|
19309
19376
|
[
|
|
19310
19377
|
"HINDSIGHT_API_CONSOLIDATION_MAX_MEMORIES_PER_ROUND",
|
|
19311
19378
|
String(HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_MEMORIES_PER_ROUND)
|
|
19379
|
+
],
|
|
19380
|
+
[
|
|
19381
|
+
"HINDSIGHT_API_RECENCY_DECAY_FUNCTION",
|
|
19382
|
+
HINDSIGHT_DEFAULT_RECENCY_DECAY_FUNCTION
|
|
19383
|
+
],
|
|
19384
|
+
[
|
|
19385
|
+
"HINDSIGHT_API_RECENCY_DECAY_HALFLIFE_DAYS",
|
|
19386
|
+
String(HINDSIGHT_DEFAULT_RECENCY_DECAY_HALFLIFE_DAYS)
|
|
19312
19387
|
]
|
|
19313
19388
|
];
|
|
19314
19389
|
var HINDSIGHT_PERF_DEFAULTS_GPU = [
|
|
@@ -19333,7 +19408,9 @@ var HINDSIGHT_PERF_DEFAULTS_LOCAL_LLM = [
|
|
|
19333
19408
|
];
|
|
19334
19409
|
var HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS = new Set([
|
|
19335
19410
|
"HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY",
|
|
19336
|
-
"HINDSIGHT_CE_DECISIVE_RELATIVE_GAP"
|
|
19411
|
+
"HINDSIGHT_CE_DECISIVE_RELATIVE_GAP",
|
|
19412
|
+
"HINDSIGHT_API_RECENCY_DECAY_LINEAR_WINDOW_DAYS",
|
|
19413
|
+
"HINDSIGHT_API_WORKER_MAX_SLOTS"
|
|
19337
19414
|
]);
|
|
19338
19415
|
var HINDSIGHT_PERF_ENV_KEYS = new Set([
|
|
19339
19416
|
...[
|
|
@@ -19374,7 +19451,52 @@ var HINDSIGHT_HEALTHCHECK_CMD = `python3 -c '${HINDSIGHT_HEALTHCHECK_PY}'`;
|
|
|
19374
19451
|
var DOCKER_PROBE_TIMEOUT_MS = 60 * 1000;
|
|
19375
19452
|
|
|
19376
19453
|
// src/memory/hindsight.ts
|
|
19377
|
-
var DEFAULT_RETAIN_MISSION =
|
|
19454
|
+
var DEFAULT_RETAIN_MISSION = `Extract durable facts that will still be true and useful weeks from now: user preferences and standing rules, ongoing projects and recurring commitments, technical and architectural decisions with their rationale, and people/tool relationships. A preference revealed by a request is durable — record the preference (what the user likes, wants, or always does), not the request itself.
|
|
19455
|
+
` + `
|
|
19456
|
+
` + `A TOOL RESULT IS NOT A FACT. Before extracting, ask: is the subject of this
|
|
19457
|
+
` + `candidate a file path, a command/process/agent/session id, a temp directory, or
|
|
19458
|
+
` + `the location where some output was written? If yes, drop it — it is transcript
|
|
19459
|
+
` + `exhaust, not memory.
|
|
19460
|
+
` + `
|
|
19461
|
+
` + `NEVER extract:
|
|
19462
|
+
` + `- Tool results verbatim or paraphrased. Concretely, never produce a fact whose
|
|
19463
|
+
` + ` text resembles any of these: "File created successfully at /path/to/file",
|
|
19464
|
+
` + ` "A background command with ID bctz4yskm is running, and its output will be
|
|
19465
|
+
` + ` written to /tmp/...", "Async agent a745598ba84e71df1 was launched successfully
|
|
19466
|
+
` + ` and is running in the background", "User executed a Bash command to sleep for
|
|
19467
|
+
` + ` 200 seconds", "The assistant used grep to locate 'truncateSync' in src/foo.ts".
|
|
19468
|
+
` + `- Anything mentioning a path under /tmp, a scratchpad directory, or a .tmp file.
|
|
19469
|
+
` + `- Agent tool-use traces or narration of what the assistant did (e.g. "the
|
|
19470
|
+
` + ` assistant used X to query Y", "ran a search", "sent the message").
|
|
19471
|
+
` + `- In-flight workflow/process narration (a sub-task started, paused, or is still
|
|
19472
|
+
` + ` running) — retain the outcome only once the task completes or a decision is made.
|
|
19473
|
+
` + `- Operation, request, batch, agent, command or session IDs, UUIDs, hashes, or error codes.
|
|
19474
|
+
` + `- Slash commands the user typed and their effects (e.g. "User issued /clear to
|
|
19475
|
+
` + ` reset assistant state").
|
|
19476
|
+
` + `- Hindsight's own errors, retries, backlogs, or internal state — the memory
|
|
19477
|
+
` + ` system's self-reports are not memories.
|
|
19478
|
+
` + `- Restatements of the user's current request or the task in progress.
|
|
19479
|
+
` + `- Volatile state written as a timeless assertion. A version, count, size,
|
|
19480
|
+
` + ` backlog, status, or any "X is running Y" / "X is at Y" / "X is currently Y"
|
|
19481
|
+
` + ` claim is true only at the instant it was said. Concretely, never produce a
|
|
19482
|
+
` + ` fact whose text resembles any of these: "Switchroom fleet is running image
|
|
19483
|
+
` + ` version v0.18.19", "The switchroom repo is at /path/to/fleet, version
|
|
19484
|
+
` + ` v0.19.5", "Bank overlord has 43155 pending consolidations", "The build is
|
|
19485
|
+
` + ` currently green". If the claim is worth keeping, put the date INSIDE the
|
|
19486
|
+
` + ` fact text ("As of 2026-07-19 the fleet was running v0.18.19"); if you
|
|
19487
|
+
` + ` cannot date it, drop it. An undated one is recalled forever as though it
|
|
19488
|
+
` + ` were still true, which is worse than not remembering it at all.
|
|
19489
|
+
` + `- Transient state (unread counts, build status, what is running right now) unless
|
|
19490
|
+
` + ` the fact is explicitly dated, in which case record it as a dated observation.
|
|
19491
|
+
` + `- Greetings, acknowledgements, and routine operational chatter.
|
|
19492
|
+
` + `
|
|
19493
|
+
` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
|
|
19494
|
+
` + "nothing durable remains, return an empty facts list.";
|
|
19495
|
+
var SUPERSEDED_RETAIN_MISSIONS = [
|
|
19496
|
+
"Extract technical decisions, architectural choices, user preferences, project context, and people/tool relationships. Ignore routine greetings and transient operational details.",
|
|
19497
|
+
"Extract user preferences, ongoing projects, recurring commitments, " + "important context, and durable facts that should help across future " + "conversations. Skip one-off chatter and temporary task noise.",
|
|
19498
|
+
"Extract user preferences, ongoing projects, recurring commitments, " + "important context, and durable facts that should help across future " + "conversations. Skip one-off chatter and temporary task noise, " + "including in-flight workflow/process narration (a sub-task started, " + "paused, or is still running) — only retain the outcome once a task " + "actually completes or a decision is made.",
|
|
19499
|
+
"Extract durable facts that will still be true and useful weeks from now: " + "user preferences and standing rules, ongoing projects and recurring " + "commitments, technical and architectural decisions with their rationale, " + "and people/tool relationships. A preference revealed by a request is " + "durable — record the preference (what the user likes, wants, or always " + `does), not the request itself.
|
|
19378
19500
|
|
|
19379
19501
|
` + `NEVER extract:
|
|
19380
19502
|
` + "- Agent tool-use traces or narration of what the assistant did (e.g. " + `"the assistant used X to query Y", "ran a search", "sent the message").
|
|
@@ -19385,22 +19507,108 @@ var DEFAULT_RETAIN_MISSION = "Extract durable facts that will still be true and
|
|
|
19385
19507
|
` + "- Transient state (unread counts, build status, what is running right now) " + "unless the fact is explicitly dated, in which case record it as a dated " + `observation.
|
|
19386
19508
|
` + `- Greetings, acknowledgements, and routine operational chatter.
|
|
19387
19509
|
|
|
19388
|
-
` + "If a candidate fact matches an exclusion, drop it rather than rewording " + "it. If nothing durable remains, return an empty facts list."
|
|
19389
|
-
|
|
19390
|
-
|
|
19391
|
-
|
|
19392
|
-
|
|
19510
|
+
` + "If a candidate fact matches an exclusion, drop it rather than rewording " + "it. If nothing durable remains, return an empty facts list.",
|
|
19511
|
+
`Extract durable facts that will still be true and useful weeks from now: user preferences and standing rules, ongoing projects and recurring commitments, technical and architectural decisions with their rationale, and people/tool relationships. A preference revealed by a request is durable — record the preference (what the user likes, wants, or always does), not the request itself.
|
|
19512
|
+
` + `
|
|
19513
|
+
` + `A TOOL RESULT IS NOT A FACT. Before extracting, ask: is the subject of this
|
|
19514
|
+
` + `candidate a file path, a command/process/agent/session id, a temp directory, or
|
|
19515
|
+
` + `the location where some output was written? If yes, drop it — it is transcript
|
|
19516
|
+
` + `exhaust, not memory.
|
|
19517
|
+
` + `
|
|
19518
|
+
` + `NEVER extract:
|
|
19519
|
+
` + `- Tool results verbatim or paraphrased. Concretely, never produce a fact whose
|
|
19520
|
+
` + ` text resembles any of these: "File created successfully at /path/to/file",
|
|
19521
|
+
` + ` "A background command with ID bctz4yskm is running, and its output will be
|
|
19522
|
+
` + ` written to /tmp/...", "Async agent a745598ba84e71df1 was launched successfully
|
|
19523
|
+
` + ` and is running in the background", "User executed a Bash command to sleep for
|
|
19524
|
+
` + ` 200 seconds", "The assistant used grep to locate 'truncateSync' in src/foo.ts".
|
|
19525
|
+
` + `- Anything mentioning a path under /tmp, a scratchpad directory, or a .tmp file.
|
|
19526
|
+
` + `- Agent tool-use traces or narration of what the assistant did (e.g. "the
|
|
19527
|
+
` + ` assistant used X to query Y", "ran a search", "sent the message").
|
|
19528
|
+
` + `- In-flight workflow/process narration (a sub-task started, paused, or is still
|
|
19529
|
+
` + ` running) — retain the outcome only once the task completes or a decision is made.
|
|
19530
|
+
` + `- Operation, request, batch, agent, command or session IDs, UUIDs, hashes, or error codes.
|
|
19531
|
+
` + `- Slash commands the user typed and their effects (e.g. "User issued /clear to
|
|
19532
|
+
` + ` reset assistant state").
|
|
19533
|
+
` + `- Hindsight's own errors, retries, backlogs, or internal state — the memory
|
|
19534
|
+
` + ` system's self-reports are not memories.
|
|
19535
|
+
` + `- Restatements of the user's current request or the task in progress.
|
|
19536
|
+
` + `- Transient state (unread counts, build status, what is running right now) unless
|
|
19537
|
+
` + ` the fact is explicitly dated, in which case record it as a dated observation.
|
|
19538
|
+
` + `- Greetings, acknowledgements, and routine operational chatter.
|
|
19539
|
+
` + `
|
|
19540
|
+
` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
|
|
19541
|
+
` + "nothing durable remains, return an empty facts list."
|
|
19542
|
+
];
|
|
19543
|
+
var DEFAULT_OBSERVATIONS_MISSION = `Synthesise durable, standing knowledge about the people, projects, and systems this agent works with: preferences and standing rules, roles and relationships, skills and recurring patterns, technical and operational decisions with their rationale, and the state of long-running work once it lands.
|
|
19544
|
+
` + `
|
|
19545
|
+
` + `The test is durability, not notability: an observation must still be worth reading weeks from now. A single dated event belongs in an observation only when it establishes or changes a standing fact.
|
|
19546
|
+
` + `
|
|
19547
|
+
` + `Do NOT synthesise observations from:
|
|
19548
|
+
` + `- Transcript exhaust — tool calls and their results, file paths, temp or scratchpad directories, where some output was written, or narration of what an assistant did.
|
|
19549
|
+
` + `- Identifiers with no standing meaning: session, agent, request, batch or command IDs, UUIDs, hashes, error codes.
|
|
19550
|
+
` + `- In-flight process narration — a task started, paused, or still running. Record the outcome once it lands, not the running state.
|
|
19551
|
+
` + `- The memory system's own errors, retries, backlogs, or internal state.
|
|
19552
|
+
` + `- Transient state (what is running right now, unread counts, build status) unless the fact is explicitly dated, in which case record it as dated.
|
|
19553
|
+
` + `
|
|
19554
|
+
` + "If the new facts contain nothing durable, record nothing rather than synthesising a weak observation.";
|
|
19555
|
+
var SUPERSEDED_OBSERVATIONS_MISSIONS = [
|
|
19556
|
+
"Synthesise the person's wellbeing patterns, motivations, and emotional " + "context — how habits, setbacks, and encouragement connect over time."
|
|
19393
19557
|
];
|
|
19394
19558
|
var PROFILE_MEMORY_DEFAULTS = {
|
|
19395
19559
|
"health-coach": {
|
|
19396
19560
|
disposition: { skepticism: 2, literalism: 2, empathy: 5 },
|
|
19397
|
-
observations_mission:
|
|
19561
|
+
observations_mission: `You consolidate the memory of a health and fitness coach working with one person. This bank records how that person actually lives and trains.
|
|
19562
|
+
` + `
|
|
19563
|
+
` + `Synthesise into durable observations:
|
|
19564
|
+
` + `- Goals, targets, and the plan currently in force, with the reasoning behind each.
|
|
19565
|
+
` + `- Training, nutrition, sleep, and alcohol patterns as they hold over weeks — what the person reliably does, not what they did once.
|
|
19566
|
+
` + `- Constraints that shape the plan: injuries, medical guidance, schedule, equipment, foods and sessions they refuse.
|
|
19567
|
+
` + `- Motivations, and what actually helps or backfires when they slip.
|
|
19568
|
+
` + `- Trends in the numbers: direction and range over time, not any single reading.
|
|
19569
|
+
` + `- Corrections to earlier beliefs, recorded explicitly as corrections.
|
|
19570
|
+
` + `
|
|
19571
|
+
` + `A single day's log, weight reading, or session is evidence, not an observation. Record one only when it establishes or changes a standing pattern, target, or constraint — then fold it into the observation for that pattern and say what changed and roughly when.
|
|
19572
|
+
` + `
|
|
19573
|
+
` + `Granularity: one observation per habit, target, constraint, or trend. Aggregate repeated daily evidence into the observation for that pattern rather than creating one per day, and keep training, nutrition, and sleep as separate observations.
|
|
19574
|
+
` + `
|
|
19575
|
+
` + "Word observations as the person's own pattern and framing, never as a verdict on them."
|
|
19398
19576
|
},
|
|
19399
19577
|
"executive-assistant": {
|
|
19400
|
-
disposition: { skepticism: 4, literalism: 4, empathy: 3 }
|
|
19578
|
+
disposition: { skepticism: 4, literalism: 4, empathy: 3 },
|
|
19579
|
+
observations_mission: `You consolidate the memory of an executive assistant working for one person. This bank records that person's commitments, people, and standing arrangements.
|
|
19580
|
+
` + `
|
|
19581
|
+
` + `Synthesise into durable observations:
|
|
19582
|
+
` + `- Standing rules and preferences: how they want things scheduled, written, and filed, and when they want to be interrupted.
|
|
19583
|
+
` + `- People and organisations, and the relationship: who they are, what they are involved in, how to reach them.
|
|
19584
|
+
` + `- Recurring commitments and routines, and the constraints around them.
|
|
19585
|
+
` + `- Obligations and their state: what was promised to whom, the deadline, and what is still outstanding.
|
|
19586
|
+
` + `- Decisions made and decisions deferred, with the reasoning and the trade accepted.
|
|
19587
|
+
` + `- Corrections to earlier beliefs, recorded explicitly as corrections.
|
|
19588
|
+
` + `
|
|
19589
|
+
` + `Live commitment state IS durable knowledge here, not ephemeral chatter. An outstanding obligation, a travel window, an unanswered request, a "currently X" arrangement — these are precisely what this agent must recall later. Keep them, and embed the date inside the observation text so a later reader can judge staleness. Do not drop them as ephemeral.
|
|
19590
|
+
` + `
|
|
19591
|
+
` + `Granularity: one observation per person, arrangement, or obligation. Aggregate repeated mentions into that observation rather than creating siblings; never merge two different people or two different commitments into one.
|
|
19592
|
+
` + `
|
|
19593
|
+
` + "Do not synthesise from transcript exhaust: tool calls and their results, message or event identifiers, or narration of what the assistant did."
|
|
19401
19594
|
},
|
|
19402
19595
|
coding: {
|
|
19403
|
-
disposition: { skepticism: 4, literalism: 5, empathy: 2 }
|
|
19596
|
+
disposition: { skepticism: 4, literalism: 5, empathy: 2 },
|
|
19597
|
+
observations_mission: `You consolidate the memory of a software-engineering agent. This bank records real work on real codebases.
|
|
19598
|
+
` + `
|
|
19599
|
+
` + `Synthesise into durable observations:
|
|
19600
|
+
` + `- Architecture and design decisions, each with its rationale and the trade accepted.
|
|
19601
|
+
` + `- Root causes, with the evidence chain, and negative results — what was ruled out matters as much as what was found.
|
|
19602
|
+
` + `- How the repository works: build, test, and lint commands, conventions, CI gates, and where things live.
|
|
19603
|
+
` + `- Outcomes of code work: issue and PR numbers, what changed, whether it merged, what review found.
|
|
19604
|
+
` + `- The user's standing rules, preferences, and corrections to this agent's behaviour.
|
|
19605
|
+
` + `- Corrections to earlier beliefs, recorded explicitly as corrections.
|
|
19606
|
+
` + `
|
|
19607
|
+
` + `Repository and service state IS durable knowledge here, not ephemeral chatter. Versions, a failing gate, an open PR, a measured number, a "currently X" claim — these are precisely what this agent must recall later. Keep them, and embed the date inside the observation text so a later reader can judge staleness. Do not drop them as ephemeral.
|
|
19608
|
+
` + `
|
|
19609
|
+
` + `Granularity: one observation per distinct decision, cause, convention, or work item. Aggregate repeated evidence about the same one into that observation rather than creating siblings; never merge two separate decisions into a single summary.
|
|
19610
|
+
` + `
|
|
19611
|
+
` + "Do not synthesise from transcript exhaust: tool calls and their results, scratch paths, session or request identifiers, or narration of what the agent did. Prefer specific and falsifiable — naming the file, the number, the commit, or the decision beats summarising the topic."
|
|
19404
19612
|
}
|
|
19405
19613
|
};
|
|
19406
19614
|
// src/agents/reconcile-default-skills.ts
|
|
@@ -19439,6 +19647,27 @@ var materializedDirs = new Set;
|
|
|
19439
19647
|
// src/setup/onboarding.ts
|
|
19440
19648
|
init_paths();
|
|
19441
19649
|
|
|
19650
|
+
// src/setup/hindsight-recall-passthrough.ts
|
|
19651
|
+
var HINDSIGHT_RECALL_TAG_WEIGHT_SEED = Object.freeze({ sidechain: 0.8 });
|
|
19652
|
+
var HINDSIGHT_RECALL_PROMPT_PREAMBLE_DEFAULT = "Relevant memories from past conversations (prioritize recent when " + "conflicting). Only use memories that are directly useful to continue " + "this conversation; ignore the rest:";
|
|
19653
|
+
var RECALL_PASSTHROUGH_DEFAULTS = Object.freeze({
|
|
19654
|
+
budget: "low",
|
|
19655
|
+
maxTokens: 1024,
|
|
19656
|
+
preferObservations: true,
|
|
19657
|
+
contextTurns: 2,
|
|
19658
|
+
roles: ["user", "assistant"],
|
|
19659
|
+
promptPreamble: HINDSIGHT_RECALL_PROMPT_PREAMBLE_DEFAULT,
|
|
19660
|
+
tags: [],
|
|
19661
|
+
tagsMatch: "any",
|
|
19662
|
+
tagGroups: {},
|
|
19663
|
+
tagWeights: HINDSIGHT_RECALL_TAG_WEIGHT_SEED,
|
|
19664
|
+
additionalBankFilters: {},
|
|
19665
|
+
transcriptFallback: true,
|
|
19666
|
+
transcriptTailBytes: 262144,
|
|
19667
|
+
maxQueryChars: 800,
|
|
19668
|
+
parallel: true
|
|
19669
|
+
});
|
|
19670
|
+
|
|
19442
19671
|
// src/repos/bare-clone.ts
|
|
19443
19672
|
init_paths();
|
|
19444
19673
|
|