switchroom 0.20.18 → 0.20.20
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/dist/agent-scheduler/index.js +6 -0
- package/dist/auth-broker/index.js +17 -1
- package/dist/cli/notion-write-pretool.mjs +6 -0
- package/dist/cli/switchroom.js +1647 -430
- package/dist/host-control/main.js +18 -2
- package/dist/vault/approvals/kernel-server.js +17 -1
- package/dist/vault/broker/server.js +17 -1
- package/package.json +1 -1
- package/telegram-plugin/dist/gateway/gateway.js +26 -9
- package/telegram-plugin/telegraph.ts +23 -5
- package/telegram-plugin/tests/telegraph.test.ts +34 -0
|
@@ -11445,6 +11445,12 @@ var init_schema = __esm(() => {
|
|
|
11445
11445
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
|
|
11446
11446
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
|
|
11447
11447
|
}).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."),
|
|
11448
|
+
recall_pool: exports_external.object({
|
|
11449
|
+
enabled: exports_external.boolean().optional().describe("Turn on the recall/background WORKER SPLIT: a second container, " + "`switchroom-hindsight-recall`, serves recall/reflect only with N " + "uvicorn workers, while the existing `switchroom-hindsight` " + "container keeps pg0, the single background WorkerPoller, the " + "healthcheck and all consolidation/retain processing but moves off " + "the public port onto public+1. The public port (memory.config.url) " + "does not change — the pool binds it instead. Absent/false (the " + "default) → the single-container topology, unchanged. Opt-in only. " + "Raises recall throughput ~2.2x on the fleet (2.6→5.6 rps)."),
|
|
11450
|
+
workers: exports_external.number().int().positive().optional().describe("uvicorn `--workers` for the recall pool (HINDSIGHT_API_WORKERS). " + "Default 4. Each worker holds its own GPU cross-encoder reranker, " + "so past ~4 workers contend for VRAM rather than adding throughput " + "on a single GPU — raise only on a bigger GPU or a CPU reranker. " + "The per-worker DB pools are auto-sized down from the pg0 " + "connection budget so N*(write+read)+60 background stays under " + "max_connections=250; a worker count that would overflow that " + "budget is rejected at launch."),
|
|
11451
|
+
db_pool_max_size: exports_external.number().int().positive().optional().describe("Override the per-worker WRITE pool cap " + "(HINDSIGHT_API_DB_POOL_MAX_SIZE). Absent → auto-sized from the " + "worker count. Set this only to override the auto-sizing; the " + "connection-budget check still applies and rejects an overflow."),
|
|
11452
|
+
read_db_pool_max_size: exports_external.number().int().positive().optional().describe("Override the per-worker READ pool cap " + "(HINDSIGHT_API_READ_DB_POOL_MAX_SIZE). Absent → auto-sized from " + "the worker count. Set this only to override the auto-sizing; the " + "connection-budget check still applies and rejects an overflow.")
|
|
11453
|
+
}).optional().describe("Optional recall/background container split for the hindsight " + "singleton. Off by default; see `enabled`. Provisioned by " + "`switchroom memory setup` (src/setup/hindsight-recall-pool.ts) so it " + "survives `switchroom apply` — the hand-applied topology it replaces " + "did not."),
|
|
11448
11454
|
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_QUERY_ANALYZER_LANGUAGES — the language set dateparser is " + "restricted to during temporal query analysis (upstream #3154, which " + "superseded switchroom's own temporal-language image patch at v0.9.0); " + "comma-separated; switchroom EMITS `en` on every host because upstream's " + "unset default auto-detects across 200+ locales inline on the shared " + "asyncio loop (~165x slower per call), set e.g. `en,es` for i18n parsing; " + "and " + "HINDSIGHT_API_TEMPORAL_MAX_QUERY_CHARS — the max chars of query text " + "dateparser.search_dates() is handed during temporal analysis (0 = " + "unlimited), made live by switchroom's temporal-offload image patch " + "(which moved the synchronous extraction off the shared asyncio loop onto " + "a single-worker thread and bounds its input, ending multi-second loop " + "stalls on multi-KB consolidation queries); unset means the image's baked " + "2000, set 0 to restore an unbounded full scan); and " + "HINDSIGHT_API_TEXT_SEARCH_EXTENSION_NATIVE_LANGUAGE — the Postgres " + "text-search regconfig the native BM25 arms and the search_vector index " + "write run to_tsvector/to_tsquery against; unset means upstream's " + "always-safe `english`, set `hindsight_english` to use switchroom's " + "junk-stopping config (dict + stopword file provisioned durably by the " + "image entrypoint, recall degrading to semantic-only if it is ever " + "missing); and " + "HINDSIGHT_API_BM25_MAX_QUERY_TERMS — the max number of query tokens the " + "keyword (BM25) recall arm searches for; unset means upstream's 0 = " + "unbounded, which makes a multi-KB consolidation query a disjunction " + "over hundreds of terms; set e.g. 64 to cap it, at the cost of " + "silently dropping the tail of a long query; and " + "HINDSIGHT_API_EMBEDDINGS_PROVIDER with the four " + "HINDSIGHT_API_EMBEDDINGS_ONNX_{MODEL_ID,POOLING,QUERY_PREFIX," + "PASSAGE_PREFIX} keys — the ONNX-embeddings cutover: unset keeps " + "upstream's slower `local` (PyTorch) backend, set `onnx` plus the model " + "id/pooling to run the SAME model on ONNX-CPU at a fraction of the " + "latency; the two _PREFIX keys are the query/passage affixes and are " + "set to the empty string for bge parity (vectors are byte-identical " + "between the two backends, so no re-embedding is needed) — unusually " + "for this block an EMPTY value here is honoured, not dropped, because an " + "affix-free prefix is the intended value; and the v0.9.0 knobs " + "switchroom allowlists for reach but emits no value for — " + "HINDSIGHT_API_RERANKER_MAX_CANDIDATES_{LOW,MID,HIGH} (per-recall-budget " + "rerank caps; unset/0 falls back to the global " + "HINDSIGHT_API_RERANKER_MAX_CANDIDATES switchroom does pin), " + "HINDSIGHT_API_EMBEDDINGS_MAX_INPUT_TOKENS (embedding-input truncation " + "ceiling; unset means the model's own limit), " + "HINDSIGHT_API_ENTITY_TRGM_SIMILARITY_THRESHOLD (entity-resolution fuzzy " + "match floor; unset means upstream's 0.15) and " + "HINDSIGHT_API_ENABLE_{TEMPORAL_RETRIEVAL,GRAPH_RETRIEVAL,RERANKING} " + "(global per-stage kill switches, all default true — the emergency lever " + "if one retrieval stage is implicated in a latency incident, at the cost " + "of recall quality); 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).")
|
|
11449
11455
|
});
|
|
11450
11456
|
MicrosoftWorkspaceConfigSchema = exports_external.object({
|
|
@@ -21559,7 +21565,7 @@ function allocateAgentUid(name) {
|
|
|
21559
21565
|
}
|
|
21560
21566
|
|
|
21561
21567
|
// src/build-info.ts
|
|
21562
|
-
var VERSION = "0.20.
|
|
21568
|
+
var VERSION = "0.20.20";
|
|
21563
21569
|
|
|
21564
21570
|
// src/setup/hindsight-recall-passthrough.ts
|
|
21565
21571
|
var HINDSIGHT_RECALL_TAG_WEIGHT_SEED = Object.freeze({ sidechain: 0.8 });
|
|
@@ -21897,6 +21903,15 @@ var HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES = new Map(HINDSIGHT_WORKER_SLOT_TYPES
|
|
|
21897
21903
|
`HINDSIGHT_API_WORKER_${type.toUpperCase()}_MAX_SLOTS`,
|
|
21898
21904
|
`HINDSIGHT_API_WORKER_${type.toUpperCase()}_RESERVED_SLOTS`
|
|
21899
21905
|
]));
|
|
21906
|
+
var HINDSIGHT_RECALL_POOL_ENV_KEYS = [
|
|
21907
|
+
"HINDSIGHT_API_WORKERS",
|
|
21908
|
+
"HINDSIGHT_API_WORKER_ENABLED",
|
|
21909
|
+
"HINDSIGHT_API_DATABASE_URL",
|
|
21910
|
+
"HINDSIGHT_API_DB_URL",
|
|
21911
|
+
"HINDSIGHT_API_DB_POOL_MAX_SIZE",
|
|
21912
|
+
"HINDSIGHT_API_READ_DB_POOL_MAX_SIZE",
|
|
21913
|
+
"HINDSIGHT_API_RUN_MIGRATIONS_ON_STARTUP"
|
|
21914
|
+
];
|
|
21900
21915
|
var HINDSIGHT_PERF_ENV_KEYS = new Set([
|
|
21901
21916
|
...[
|
|
21902
21917
|
...HINDSIGHT_PERF_DEFAULTS_UNGATED,
|
|
@@ -21905,7 +21920,8 @@ var HINDSIGHT_PERF_ENV_KEYS = new Set([
|
|
|
21905
21920
|
].map(([k]) => k),
|
|
21906
21921
|
...HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS,
|
|
21907
21922
|
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.keys(),
|
|
21908
|
-
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.values()
|
|
21923
|
+
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.values(),
|
|
21924
|
+
...HINDSIGHT_RECALL_POOL_ENV_KEYS
|
|
21909
21925
|
]);
|
|
21910
21926
|
|
|
21911
21927
|
// src/setup/hindsight-context-budget.ts
|
|
@@ -4885,6 +4885,12 @@ var init_schema = __esm(() => {
|
|
|
4885
4885
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
|
|
4886
4886
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
|
|
4887
4887
|
}).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."),
|
|
4888
|
+
recall_pool: exports_external.object({
|
|
4889
|
+
enabled: exports_external.boolean().optional().describe("Turn on the recall/background WORKER SPLIT: a second container, " + "`switchroom-hindsight-recall`, serves recall/reflect only with N " + "uvicorn workers, while the existing `switchroom-hindsight` " + "container keeps pg0, the single background WorkerPoller, the " + "healthcheck and all consolidation/retain processing but moves off " + "the public port onto public+1. The public port (memory.config.url) " + "does not change — the pool binds it instead. Absent/false (the " + "default) → the single-container topology, unchanged. Opt-in only. " + "Raises recall throughput ~2.2x on the fleet (2.6→5.6 rps)."),
|
|
4890
|
+
workers: exports_external.number().int().positive().optional().describe("uvicorn `--workers` for the recall pool (HINDSIGHT_API_WORKERS). " + "Default 4. Each worker holds its own GPU cross-encoder reranker, " + "so past ~4 workers contend for VRAM rather than adding throughput " + "on a single GPU — raise only on a bigger GPU or a CPU reranker. " + "The per-worker DB pools are auto-sized down from the pg0 " + "connection budget so N*(write+read)+60 background stays under " + "max_connections=250; a worker count that would overflow that " + "budget is rejected at launch."),
|
|
4891
|
+
db_pool_max_size: exports_external.number().int().positive().optional().describe("Override the per-worker WRITE pool cap " + "(HINDSIGHT_API_DB_POOL_MAX_SIZE). Absent → auto-sized from the " + "worker count. Set this only to override the auto-sizing; the " + "connection-budget check still applies and rejects an overflow."),
|
|
4892
|
+
read_db_pool_max_size: exports_external.number().int().positive().optional().describe("Override the per-worker READ pool cap " + "(HINDSIGHT_API_READ_DB_POOL_MAX_SIZE). Absent → auto-sized from " + "the worker count. Set this only to override the auto-sizing; the " + "connection-budget check still applies and rejects an overflow.")
|
|
4893
|
+
}).optional().describe("Optional recall/background container split for the hindsight " + "singleton. Off by default; see `enabled`. Provisioned by " + "`switchroom memory setup` (src/setup/hindsight-recall-pool.ts) so it " + "survives `switchroom apply` — the hand-applied topology it replaces " + "did not."),
|
|
4888
4894
|
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_QUERY_ANALYZER_LANGUAGES — the language set dateparser is " + "restricted to during temporal query analysis (upstream #3154, which " + "superseded switchroom's own temporal-language image patch at v0.9.0); " + "comma-separated; switchroom EMITS `en` on every host because upstream's " + "unset default auto-detects across 200+ locales inline on the shared " + "asyncio loop (~165x slower per call), set e.g. `en,es` for i18n parsing; " + "and " + "HINDSIGHT_API_TEMPORAL_MAX_QUERY_CHARS — the max chars of query text " + "dateparser.search_dates() is handed during temporal analysis (0 = " + "unlimited), made live by switchroom's temporal-offload image patch " + "(which moved the synchronous extraction off the shared asyncio loop onto " + "a single-worker thread and bounds its input, ending multi-second loop " + "stalls on multi-KB consolidation queries); unset means the image's baked " + "2000, set 0 to restore an unbounded full scan); and " + "HINDSIGHT_API_TEXT_SEARCH_EXTENSION_NATIVE_LANGUAGE — the Postgres " + "text-search regconfig the native BM25 arms and the search_vector index " + "write run to_tsvector/to_tsquery against; unset means upstream's " + "always-safe `english`, set `hindsight_english` to use switchroom's " + "junk-stopping config (dict + stopword file provisioned durably by the " + "image entrypoint, recall degrading to semantic-only if it is ever " + "missing); and " + "HINDSIGHT_API_BM25_MAX_QUERY_TERMS — the max number of query tokens the " + "keyword (BM25) recall arm searches for; unset means upstream's 0 = " + "unbounded, which makes a multi-KB consolidation query a disjunction " + "over hundreds of terms; set e.g. 64 to cap it, at the cost of " + "silently dropping the tail of a long query; and " + "HINDSIGHT_API_EMBEDDINGS_PROVIDER with the four " + "HINDSIGHT_API_EMBEDDINGS_ONNX_{MODEL_ID,POOLING,QUERY_PREFIX," + "PASSAGE_PREFIX} keys — the ONNX-embeddings cutover: unset keeps " + "upstream's slower `local` (PyTorch) backend, set `onnx` plus the model " + "id/pooling to run the SAME model on ONNX-CPU at a fraction of the " + "latency; the two _PREFIX keys are the query/passage affixes and are " + "set to the empty string for bge parity (vectors are byte-identical " + "between the two backends, so no re-embedding is needed) — unusually " + "for this block an EMPTY value here is honoured, not dropped, because an " + "affix-free prefix is the intended value; and the v0.9.0 knobs " + "switchroom allowlists for reach but emits no value for — " + "HINDSIGHT_API_RERANKER_MAX_CANDIDATES_{LOW,MID,HIGH} (per-recall-budget " + "rerank caps; unset/0 falls back to the global " + "HINDSIGHT_API_RERANKER_MAX_CANDIDATES switchroom does pin), " + "HINDSIGHT_API_EMBEDDINGS_MAX_INPUT_TOKENS (embedding-input truncation " + "ceiling; unset means the model's own limit), " + "HINDSIGHT_API_ENTITY_TRGM_SIMILARITY_THRESHOLD (entity-resolution fuzzy " + "match floor; unset means upstream's 0.15) and " + "HINDSIGHT_API_ENABLE_{TEMPORAL_RETRIEVAL,GRAPH_RETRIEVAL,RERANKING} " + "(global per-stage kill switches, all default true — the emergency lever " + "if one retrieval stage is implicated in a latency incident, at the cost " + "of recall quality); 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).")
|
|
4889
4895
|
});
|
|
4890
4896
|
MicrosoftWorkspaceConfigSchema = exports_external.object({
|
|
@@ -19792,6 +19798,15 @@ var HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES = new Map(HINDSIGHT_WORKER_SLOT_TYPES
|
|
|
19792
19798
|
`HINDSIGHT_API_WORKER_${type.toUpperCase()}_MAX_SLOTS`,
|
|
19793
19799
|
`HINDSIGHT_API_WORKER_${type.toUpperCase()}_RESERVED_SLOTS`
|
|
19794
19800
|
]));
|
|
19801
|
+
var HINDSIGHT_RECALL_POOL_ENV_KEYS = [
|
|
19802
|
+
"HINDSIGHT_API_WORKERS",
|
|
19803
|
+
"HINDSIGHT_API_WORKER_ENABLED",
|
|
19804
|
+
"HINDSIGHT_API_DATABASE_URL",
|
|
19805
|
+
"HINDSIGHT_API_DB_URL",
|
|
19806
|
+
"HINDSIGHT_API_DB_POOL_MAX_SIZE",
|
|
19807
|
+
"HINDSIGHT_API_READ_DB_POOL_MAX_SIZE",
|
|
19808
|
+
"HINDSIGHT_API_RUN_MIGRATIONS_ON_STARTUP"
|
|
19809
|
+
];
|
|
19795
19810
|
var HINDSIGHT_PERF_ENV_KEYS = new Set([
|
|
19796
19811
|
...[
|
|
19797
19812
|
...HINDSIGHT_PERF_DEFAULTS_UNGATED,
|
|
@@ -19800,7 +19815,8 @@ var HINDSIGHT_PERF_ENV_KEYS = new Set([
|
|
|
19800
19815
|
].map(([k]) => k),
|
|
19801
19816
|
...HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS,
|
|
19802
19817
|
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.keys(),
|
|
19803
|
-
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.values()
|
|
19818
|
+
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.values(),
|
|
19819
|
+
...HINDSIGHT_RECALL_POOL_ENV_KEYS
|
|
19804
19820
|
]);
|
|
19805
19821
|
|
|
19806
19822
|
// src/setup/hindsight-context-budget.ts
|
|
@@ -4481,6 +4481,12 @@ var init_schema = __esm(() => {
|
|
|
4481
4481
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
|
|
4482
4482
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
|
|
4483
4483
|
}).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."),
|
|
4484
|
+
recall_pool: exports_external.object({
|
|
4485
|
+
enabled: exports_external.boolean().optional().describe("Turn on the recall/background WORKER SPLIT: a second container, " + "`switchroom-hindsight-recall`, serves recall/reflect only with N " + "uvicorn workers, while the existing `switchroom-hindsight` " + "container keeps pg0, the single background WorkerPoller, the " + "healthcheck and all consolidation/retain processing but moves off " + "the public port onto public+1. The public port (memory.config.url) " + "does not change — the pool binds it instead. Absent/false (the " + "default) → the single-container topology, unchanged. Opt-in only. " + "Raises recall throughput ~2.2x on the fleet (2.6→5.6 rps)."),
|
|
4486
|
+
workers: exports_external.number().int().positive().optional().describe("uvicorn `--workers` for the recall pool (HINDSIGHT_API_WORKERS). " + "Default 4. Each worker holds its own GPU cross-encoder reranker, " + "so past ~4 workers contend for VRAM rather than adding throughput " + "on a single GPU — raise only on a bigger GPU or a CPU reranker. " + "The per-worker DB pools are auto-sized down from the pg0 " + "connection budget so N*(write+read)+60 background stays under " + "max_connections=250; a worker count that would overflow that " + "budget is rejected at launch."),
|
|
4487
|
+
db_pool_max_size: exports_external.number().int().positive().optional().describe("Override the per-worker WRITE pool cap " + "(HINDSIGHT_API_DB_POOL_MAX_SIZE). Absent → auto-sized from the " + "worker count. Set this only to override the auto-sizing; the " + "connection-budget check still applies and rejects an overflow."),
|
|
4488
|
+
read_db_pool_max_size: exports_external.number().int().positive().optional().describe("Override the per-worker READ pool cap " + "(HINDSIGHT_API_READ_DB_POOL_MAX_SIZE). Absent → auto-sized from " + "the worker count. Set this only to override the auto-sizing; the " + "connection-budget check still applies and rejects an overflow.")
|
|
4489
|
+
}).optional().describe("Optional recall/background container split for the hindsight " + "singleton. Off by default; see `enabled`. Provisioned by " + "`switchroom memory setup` (src/setup/hindsight-recall-pool.ts) so it " + "survives `switchroom apply` — the hand-applied topology it replaces " + "did not."),
|
|
4484
4490
|
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_QUERY_ANALYZER_LANGUAGES — the language set dateparser is " + "restricted to during temporal query analysis (upstream #3154, which " + "superseded switchroom's own temporal-language image patch at v0.9.0); " + "comma-separated; switchroom EMITS `en` on every host because upstream's " + "unset default auto-detects across 200+ locales inline on the shared " + "asyncio loop (~165x slower per call), set e.g. `en,es` for i18n parsing; " + "and " + "HINDSIGHT_API_TEMPORAL_MAX_QUERY_CHARS — the max chars of query text " + "dateparser.search_dates() is handed during temporal analysis (0 = " + "unlimited), made live by switchroom's temporal-offload image patch " + "(which moved the synchronous extraction off the shared asyncio loop onto " + "a single-worker thread and bounds its input, ending multi-second loop " + "stalls on multi-KB consolidation queries); unset means the image's baked " + "2000, set 0 to restore an unbounded full scan); and " + "HINDSIGHT_API_TEXT_SEARCH_EXTENSION_NATIVE_LANGUAGE — the Postgres " + "text-search regconfig the native BM25 arms and the search_vector index " + "write run to_tsvector/to_tsquery against; unset means upstream's " + "always-safe `english`, set `hindsight_english` to use switchroom's " + "junk-stopping config (dict + stopword file provisioned durably by the " + "image entrypoint, recall degrading to semantic-only if it is ever " + "missing); and " + "HINDSIGHT_API_BM25_MAX_QUERY_TERMS — the max number of query tokens the " + "keyword (BM25) recall arm searches for; unset means upstream's 0 = " + "unbounded, which makes a multi-KB consolidation query a disjunction " + "over hundreds of terms; set e.g. 64 to cap it, at the cost of " + "silently dropping the tail of a long query; and " + "HINDSIGHT_API_EMBEDDINGS_PROVIDER with the four " + "HINDSIGHT_API_EMBEDDINGS_ONNX_{MODEL_ID,POOLING,QUERY_PREFIX," + "PASSAGE_PREFIX} keys — the ONNX-embeddings cutover: unset keeps " + "upstream's slower `local` (PyTorch) backend, set `onnx` plus the model " + "id/pooling to run the SAME model on ONNX-CPU at a fraction of the " + "latency; the two _PREFIX keys are the query/passage affixes and are " + "set to the empty string for bge parity (vectors are byte-identical " + "between the two backends, so no re-embedding is needed) — unusually " + "for this block an EMPTY value here is honoured, not dropped, because an " + "affix-free prefix is the intended value; and the v0.9.0 knobs " + "switchroom allowlists for reach but emits no value for — " + "HINDSIGHT_API_RERANKER_MAX_CANDIDATES_{LOW,MID,HIGH} (per-recall-budget " + "rerank caps; unset/0 falls back to the global " + "HINDSIGHT_API_RERANKER_MAX_CANDIDATES switchroom does pin), " + "HINDSIGHT_API_EMBEDDINGS_MAX_INPUT_TOKENS (embedding-input truncation " + "ceiling; unset means the model's own limit), " + "HINDSIGHT_API_ENTITY_TRGM_SIMILARITY_THRESHOLD (entity-resolution fuzzy " + "match floor; unset means upstream's 0.15) and " + "HINDSIGHT_API_ENABLE_{TEMPORAL_RETRIEVAL,GRAPH_RETRIEVAL,RERANKING} " + "(global per-stage kill switches, all default true — the emergency lever " + "if one retrieval stage is implicated in a latency incident, at the cost " + "of recall quality); 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).")
|
|
4485
4491
|
});
|
|
4486
4492
|
MicrosoftWorkspaceConfigSchema = exports_external.object({
|
|
@@ -20205,6 +20211,15 @@ var HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES = new Map(HINDSIGHT_WORKER_SLOT_TYPES
|
|
|
20205
20211
|
`HINDSIGHT_API_WORKER_${type.toUpperCase()}_MAX_SLOTS`,
|
|
20206
20212
|
`HINDSIGHT_API_WORKER_${type.toUpperCase()}_RESERVED_SLOTS`
|
|
20207
20213
|
]));
|
|
20214
|
+
var HINDSIGHT_RECALL_POOL_ENV_KEYS = [
|
|
20215
|
+
"HINDSIGHT_API_WORKERS",
|
|
20216
|
+
"HINDSIGHT_API_WORKER_ENABLED",
|
|
20217
|
+
"HINDSIGHT_API_DATABASE_URL",
|
|
20218
|
+
"HINDSIGHT_API_DB_URL",
|
|
20219
|
+
"HINDSIGHT_API_DB_POOL_MAX_SIZE",
|
|
20220
|
+
"HINDSIGHT_API_READ_DB_POOL_MAX_SIZE",
|
|
20221
|
+
"HINDSIGHT_API_RUN_MIGRATIONS_ON_STARTUP"
|
|
20222
|
+
];
|
|
20208
20223
|
var HINDSIGHT_PERF_ENV_KEYS = new Set([
|
|
20209
20224
|
...[
|
|
20210
20225
|
...HINDSIGHT_PERF_DEFAULTS_UNGATED,
|
|
@@ -20213,7 +20228,8 @@ var HINDSIGHT_PERF_ENV_KEYS = new Set([
|
|
|
20213
20228
|
].map(([k]) => k),
|
|
20214
20229
|
...HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS,
|
|
20215
20230
|
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.keys(),
|
|
20216
|
-
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.values()
|
|
20231
|
+
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.values(),
|
|
20232
|
+
...HINDSIGHT_RECALL_POOL_ENV_KEYS
|
|
20217
20233
|
]);
|
|
20218
20234
|
|
|
20219
20235
|
// src/setup/hindsight-context-budget.ts
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "switchroom",
|
|
3
3
|
"//version": "NOT the release version — source of truth is the git tag, resolved by scripts/build.mjs:resolveVersion() (see CLAUDE.md > Standard release process). This field is stale by design and only the Layer-4 dev/non-tag fallback for build.mjs + src/cli/resolve-version.ts; do NOT bump it expecting a release to pick it up. npm-pack tarball naming needs a real version — do that as an UNCOMMITTED pack-time bump (see release step 6), never a committed one.",
|
|
4
|
-
"version": "0.20.
|
|
4
|
+
"version": "0.20.20",
|
|
5
5
|
"description": "Run Claude Code 24/7 on your Claude Pro/Max subscription over Telegram. Open-source alternative to OpenClaw and NanoClaw — no API keys.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -22037,6 +22037,12 @@ var init_schema = __esm(() => {
|
|
|
22037
22037
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent \u2192 uses global."),
|
|
22038
22038
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent \u2192 global.")
|
|
22039
22039
|
}).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."),
|
|
22040
|
+
recall_pool: exports_external.object({
|
|
22041
|
+
enabled: exports_external.boolean().optional().describe("Turn on the recall/background WORKER SPLIT: a second container, " + "`switchroom-hindsight-recall`, serves recall/reflect only with N " + "uvicorn workers, while the existing `switchroom-hindsight` " + "container keeps pg0, the single background WorkerPoller, the " + "healthcheck and all consolidation/retain processing but moves off " + "the public port onto public+1. The public port (memory.config.url) " + "does not change \u2014 the pool binds it instead. Absent/false (the " + "default) \u2192 the single-container topology, unchanged. Opt-in only. " + "Raises recall throughput ~2.2x on the fleet (2.6\u21925.6 rps)."),
|
|
22042
|
+
workers: exports_external.number().int().positive().optional().describe("uvicorn `--workers` for the recall pool (HINDSIGHT_API_WORKERS). " + "Default 4. Each worker holds its own GPU cross-encoder reranker, " + "so past ~4 workers contend for VRAM rather than adding throughput " + "on a single GPU \u2014 raise only on a bigger GPU or a CPU reranker. " + "The per-worker DB pools are auto-sized down from the pg0 " + "connection budget so N*(write+read)+60 background stays under " + "max_connections=250; a worker count that would overflow that " + "budget is rejected at launch."),
|
|
22043
|
+
db_pool_max_size: exports_external.number().int().positive().optional().describe("Override the per-worker WRITE pool cap " + "(HINDSIGHT_API_DB_POOL_MAX_SIZE). Absent \u2192 auto-sized from the " + "worker count. Set this only to override the auto-sizing; the " + "connection-budget check still applies and rejects an overflow."),
|
|
22044
|
+
read_db_pool_max_size: exports_external.number().int().positive().optional().describe("Override the per-worker READ pool cap " + "(HINDSIGHT_API_READ_DB_POOL_MAX_SIZE). Absent \u2192 auto-sized from " + "the worker count. Set this only to override the auto-sizing; the " + "connection-budget check still applies and rejects an overflow.")
|
|
22045
|
+
}).optional().describe("Optional recall/background container split for the hindsight " + "singleton. Off by default; see `enabled`. Provisioned by " + "`switchroom memory setup` (src/setup/hindsight-recall-pool.ts) so it " + "survives `switchroom apply` \u2014 the hand-applied topology it replaces " + "did not."),
|
|
22040
22046
|
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 \u2014 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 \u2014 a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP \u2014 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 \u2014 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 \u2014 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 \u2014 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 \u2014 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 \u2014 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 \u2014 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 \u2014 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 \u2014 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_QUERY_ANALYZER_LANGUAGES \u2014 the language set dateparser is " + "restricted to during temporal query analysis (upstream #3154, which " + "superseded switchroom's own temporal-language image patch at v0.9.0); " + "comma-separated; switchroom EMITS `en` on every host because upstream's " + "unset default auto-detects across 200+ locales inline on the shared " + "asyncio loop (~165x slower per call), set e.g. `en,es` for i18n parsing; " + "and " + "HINDSIGHT_API_TEMPORAL_MAX_QUERY_CHARS \u2014 the max chars of query text " + "dateparser.search_dates() is handed during temporal analysis (0 = " + "unlimited), made live by switchroom's temporal-offload image patch " + "(which moved the synchronous extraction off the shared asyncio loop onto " + "a single-worker thread and bounds its input, ending multi-second loop " + "stalls on multi-KB consolidation queries); unset means the image's baked " + "2000, set 0 to restore an unbounded full scan); and " + "HINDSIGHT_API_TEXT_SEARCH_EXTENSION_NATIVE_LANGUAGE \u2014 the Postgres " + "text-search regconfig the native BM25 arms and the search_vector index " + "write run to_tsvector/to_tsquery against; unset means upstream's " + "always-safe `english`, set `hindsight_english` to use switchroom's " + "junk-stopping config (dict + stopword file provisioned durably by the " + "image entrypoint, recall degrading to semantic-only if it is ever " + "missing); and " + "HINDSIGHT_API_BM25_MAX_QUERY_TERMS \u2014 the max number of query tokens the " + "keyword (BM25) recall arm searches for; unset means upstream's 0 = " + "unbounded, which makes a multi-KB consolidation query a disjunction " + "over hundreds of terms; set e.g. 64 to cap it, at the cost of " + "silently dropping the tail of a long query; and " + "HINDSIGHT_API_EMBEDDINGS_PROVIDER with the four " + "HINDSIGHT_API_EMBEDDINGS_ONNX_{MODEL_ID,POOLING,QUERY_PREFIX," + "PASSAGE_PREFIX} keys \u2014 the ONNX-embeddings cutover: unset keeps " + "upstream's slower `local` (PyTorch) backend, set `onnx` plus the model " + "id/pooling to run the SAME model on ONNX-CPU at a fraction of the " + "latency; the two _PREFIX keys are the query/passage affixes and are " + "set to the empty string for bge parity (vectors are byte-identical " + "between the two backends, so no re-embedding is needed) \u2014 unusually " + "for this block an EMPTY value here is honoured, not dropped, because an " + "affix-free prefix is the intended value; and the v0.9.0 knobs " + "switchroom allowlists for reach but emits no value for \u2014 " + "HINDSIGHT_API_RERANKER_MAX_CANDIDATES_{LOW,MID,HIGH} (per-recall-budget " + "rerank caps; unset/0 falls back to the global " + "HINDSIGHT_API_RERANKER_MAX_CANDIDATES switchroom does pin), " + "HINDSIGHT_API_EMBEDDINGS_MAX_INPUT_TOKENS (embedding-input truncation " + "ceiling; unset means the model's own limit), " + "HINDSIGHT_API_ENTITY_TRGM_SIMILARITY_THRESHOLD (entity-resolution fuzzy " + "match floor; unset means upstream's 0.15) and " + "HINDSIGHT_API_ENABLE_{TEMPORAL_RETRIEVAL,GRAPH_RETRIEVAL,RERANKING} " + "(global per-stage kill switches, all default true \u2014 the emergency lever " + "if one retrieval stage is implicated in a latency incident, at the cost " + "of recall quality); 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 \u2014 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 \u2014 a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
|
|
22041
22047
|
});
|
|
22042
22048
|
MicrosoftWorkspaceConfigSchema = exports_external.object({
|
|
@@ -41878,6 +41884,7 @@ async function createTelegraphPage(args) {
|
|
|
41878
41884
|
}
|
|
41879
41885
|
};
|
|
41880
41886
|
}
|
|
41887
|
+
var TELEGRAPH_QUOTE_LINE = /^(?:\*\*)?>\s?/;
|
|
41881
41888
|
function markdownToTelegraphNodes(text) {
|
|
41882
41889
|
const nodes = [];
|
|
41883
41890
|
const lines = text.split(/\r?\n/);
|
|
@@ -41933,10 +41940,10 @@ function markdownToTelegraphNodes(text) {
|
|
|
41933
41940
|
nodes.push({ tag: "ol", children: items });
|
|
41934
41941
|
continue;
|
|
41935
41942
|
}
|
|
41936
|
-
if (
|
|
41943
|
+
if (TELEGRAPH_QUOTE_LINE.test(line)) {
|
|
41937
41944
|
const quoted = [];
|
|
41938
|
-
while (i < lines.length &&
|
|
41939
|
-
quoted.push(lines[i].replace(
|
|
41945
|
+
while (i < lines.length && TELEGRAPH_QUOTE_LINE.test(lines[i])) {
|
|
41946
|
+
quoted.push(lines[i].replace(TELEGRAPH_QUOTE_LINE, ""));
|
|
41940
41947
|
i++;
|
|
41941
41948
|
}
|
|
41942
41949
|
nodes.push({ tag: "blockquote", children: parseInline(quoted.join(" ")) });
|
|
@@ -41953,7 +41960,7 @@ function markdownToTelegraphNodes(text) {
|
|
|
41953
41960
|
return nodes;
|
|
41954
41961
|
}
|
|
41955
41962
|
function isBlockStart(line) {
|
|
41956
|
-
return /^#{1,2}\s/.test(line) || /^[-*]\s+/.test(line) || /^\d+\.\s+/.test(line) || line.trim().startsWith("```") ||
|
|
41963
|
+
return /^#{1,2}\s/.test(line) || /^[-*]\s+/.test(line) || /^\d+\.\s+/.test(line) || line.trim().startsWith("```") || TELEGRAPH_QUOTE_LINE.test(line);
|
|
41957
41964
|
}
|
|
41958
41965
|
function parseInline(text) {
|
|
41959
41966
|
const out = [];
|
|
@@ -88175,6 +88182,15 @@ var HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES = new Map(HINDSIGHT_WORKER_SLOT_TYPES
|
|
|
88175
88182
|
`HINDSIGHT_API_WORKER_${type.toUpperCase()}_MAX_SLOTS`,
|
|
88176
88183
|
`HINDSIGHT_API_WORKER_${type.toUpperCase()}_RESERVED_SLOTS`
|
|
88177
88184
|
]));
|
|
88185
|
+
var HINDSIGHT_RECALL_POOL_ENV_KEYS = [
|
|
88186
|
+
"HINDSIGHT_API_WORKERS",
|
|
88187
|
+
"HINDSIGHT_API_WORKER_ENABLED",
|
|
88188
|
+
"HINDSIGHT_API_DATABASE_URL",
|
|
88189
|
+
"HINDSIGHT_API_DB_URL",
|
|
88190
|
+
"HINDSIGHT_API_DB_POOL_MAX_SIZE",
|
|
88191
|
+
"HINDSIGHT_API_READ_DB_POOL_MAX_SIZE",
|
|
88192
|
+
"HINDSIGHT_API_RUN_MIGRATIONS_ON_STARTUP"
|
|
88193
|
+
];
|
|
88178
88194
|
var HINDSIGHT_PERF_ENV_KEYS = new Set([
|
|
88179
88195
|
...[
|
|
88180
88196
|
...HINDSIGHT_PERF_DEFAULTS_UNGATED,
|
|
@@ -88183,7 +88199,8 @@ var HINDSIGHT_PERF_ENV_KEYS = new Set([
|
|
|
88183
88199
|
].map(([k]) => k),
|
|
88184
88200
|
...HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS,
|
|
88185
88201
|
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.keys(),
|
|
88186
|
-
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.values()
|
|
88202
|
+
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.values(),
|
|
88203
|
+
...HINDSIGHT_RECALL_POOL_ENV_KEYS
|
|
88187
88204
|
]);
|
|
88188
88205
|
|
|
88189
88206
|
// ../src/setup/hindsight-context-budget.ts
|
|
@@ -103466,10 +103483,10 @@ function startOutboxSweep(deps) {
|
|
|
103466
103483
|
}
|
|
103467
103484
|
|
|
103468
103485
|
// ../src/build-info.ts
|
|
103469
|
-
var VERSION2 = "0.20.
|
|
103470
|
-
var COMMIT_SHA = "
|
|
103471
|
-
var COMMIT_DATE = "2026-08-
|
|
103472
|
-
var LATEST_PR =
|
|
103486
|
+
var VERSION2 = "0.20.20";
|
|
103487
|
+
var COMMIT_SHA = "f444ea4a";
|
|
103488
|
+
var COMMIT_DATE = "2026-08-09T02:39:19Z";
|
|
103489
|
+
var LATEST_PR = 4564;
|
|
103473
103490
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
103474
103491
|
|
|
103475
103492
|
// gateway/boot-version.ts
|
|
@@ -192,6 +192,18 @@ export async function createTelegraphPage(
|
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
/**
|
|
196
|
+
* A blockquote line: a plain `> ` marker OR the expandable-blockquote opener
|
|
197
|
+
* `**> ` (Bot API 10.1 syntax the switchroom render path emits on the first
|
|
198
|
+
* line of an expandable quote — see `render/render.ts` and
|
|
199
|
+
* `reference/telegram-formatting-guide.md`). Telegra.ph has no collapsible
|
|
200
|
+
* blockquote tag, so an expandable quote degrades to a normal `<blockquote>`;
|
|
201
|
+
* the `**` prefix must still be recognised and stripped here, else the
|
|
202
|
+
* unterminated `**` renders as literal `**>` text and the `>` continuation
|
|
203
|
+
* lines split off into a second, detached quote.
|
|
204
|
+
*/
|
|
205
|
+
const TELEGRAPH_QUOTE_LINE = /^(?:\*\*)?>\s?/
|
|
206
|
+
|
|
195
207
|
/**
|
|
196
208
|
* Convert reply text (markdown-ish) into Telegraph node structure.
|
|
197
209
|
*
|
|
@@ -278,11 +290,15 @@ export function markdownToTelegraphNodes(text: string): TelegraphNode[] {
|
|
|
278
290
|
continue
|
|
279
291
|
}
|
|
280
292
|
|
|
281
|
-
// Blockquote
|
|
282
|
-
|
|
293
|
+
// Blockquote — plain `> …` OR an expandable `**> …` opener followed by
|
|
294
|
+
// `> …` continuation lines. Both collapse into one <blockquote> with the
|
|
295
|
+
// markers stripped (Telegra.ph has no expandable-blockquote tag, so the
|
|
296
|
+
// expandable quote degrades faithfully to a normal one; the `**>` marker is
|
|
297
|
+
// stripped so no literal `**>` leaks and the summary stays with its body).
|
|
298
|
+
if (TELEGRAPH_QUOTE_LINE.test(line)) {
|
|
283
299
|
const quoted: string[] = []
|
|
284
|
-
while (i < lines.length &&
|
|
285
|
-
quoted.push(lines[i].replace(
|
|
300
|
+
while (i < lines.length && TELEGRAPH_QUOTE_LINE.test(lines[i])) {
|
|
301
|
+
quoted.push(lines[i].replace(TELEGRAPH_QUOTE_LINE, ''))
|
|
286
302
|
i++
|
|
287
303
|
}
|
|
288
304
|
nodes.push({ tag: 'blockquote', children: parseInline(quoted.join(' ')) })
|
|
@@ -310,7 +326,9 @@ function isBlockStart(line: string): boolean {
|
|
|
310
326
|
/^[-*]\s+/.test(line) ||
|
|
311
327
|
/^\d+\.\s+/.test(line) ||
|
|
312
328
|
line.trim().startsWith('```') ||
|
|
313
|
-
|
|
329
|
+
// A `**>` expandable-quote opener is a block start too, so a preceding
|
|
330
|
+
// paragraph does not absorb it (which is what left the `**>` literal).
|
|
331
|
+
TELEGRAPH_QUOTE_LINE.test(line)
|
|
314
332
|
)
|
|
315
333
|
}
|
|
316
334
|
|
|
@@ -164,6 +164,40 @@ describe('markdownToTelegraphNodes — block elements', () => {
|
|
|
164
164
|
expect(r[0].tag).toBe('blockquote')
|
|
165
165
|
})
|
|
166
166
|
|
|
167
|
+
it('folds an expandable `**>` quote into one blockquote, marker stripped', () => {
|
|
168
|
+
// The Bot API 10.1 expandable-blockquote syntax: `**>` opener on the first
|
|
169
|
+
// line, `>` continuation lines. Telegra.ph has no collapsible-blockquote
|
|
170
|
+
// tag, so it degrades to a normal blockquote — but the `**>` marker MUST be
|
|
171
|
+
// recognised. Before the fix the `**>` line became a paragraph with literal
|
|
172
|
+
// `**>` text and the `>` lines split into a detached second quote.
|
|
173
|
+
const r = markdownToTelegraphNodes('**> summary of the thing\n> body one\n> body two')
|
|
174
|
+
expect(r).toHaveLength(1)
|
|
175
|
+
expect(r[0].tag).toBe('blockquote')
|
|
176
|
+
// Summary and body are joined in the single quote, no literal `**>` leaks.
|
|
177
|
+
const flat = JSON.stringify(r)
|
|
178
|
+
expect(flat).not.toContain('**>')
|
|
179
|
+
expect(flat).not.toContain('*') // no stray bold delimiter survives
|
|
180
|
+
expect(flat).toContain('summary of the thing')
|
|
181
|
+
expect(flat).toContain('body one')
|
|
182
|
+
expect(flat).toContain('body two')
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
it('does not let a paragraph absorb a following `**>` opener', () => {
|
|
186
|
+
// isBlockStart must treat `**>` as a block start so the preceding line ends
|
|
187
|
+
// the paragraph instead of swallowing the quote (which left the `**>`
|
|
188
|
+
// literal glued into prose).
|
|
189
|
+
const r = markdownToTelegraphNodes('Intro line\n**> quoted summary')
|
|
190
|
+
expect(r.map((n) => n.tag)).toEqual(['p', 'blockquote'])
|
|
191
|
+
expect(r[0].children).toEqual(['Intro line'])
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
it('does not misread a line that merely opens with bold text', () => {
|
|
195
|
+
// `**` is only a quote marker when `>` follows it immediately. A line
|
|
196
|
+
// starting with real bold must stay a paragraph, not become a blockquote.
|
|
197
|
+
const r = markdownToTelegraphNodes('**bold** > x')
|
|
198
|
+
expect(r.map((n) => n.tag)).toEqual(['p'])
|
|
199
|
+
})
|
|
200
|
+
|
|
167
201
|
it('handles a mixed document end-to-end', () => {
|
|
168
202
|
const md = '# Title\n\nIntro paragraph.\n\n## Steps\n\n- one\n- two\n\nFinal note.'
|
|
169
203
|
const r = markdownToTelegraphNodes(md)
|