switchroom 0.19.46 → 0.19.48
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 +16 -3
- package/dist/auth-broker/index.js +22 -5
- package/dist/cli/notion-write-pretool.mjs +16 -3
- package/dist/cli/switchroom.js +428 -53
- package/dist/host-control/main.js +23 -6
- package/dist/vault/approvals/kernel-server.js +22 -5
- package/dist/vault/broker/server.js +22 -5
- package/package.json +1 -1
- package/telegram-plugin/answer-ready-flush.ts +118 -6
- package/telegram-plugin/dist/gateway/gateway.js +118 -13
- package/telegram-plugin/gateway/gateway.ts +19 -18
- package/telegram-plugin/gateway/handback-preturn-signal.ts +44 -6
- package/telegram-plugin/gateway/session-consume-signal.ts +72 -0
- package/telegram-plugin/gateway/stream-render.ts +5 -0
- package/telegram-plugin/tests/answer-ready-flush.test.ts +147 -3
- package/telegram-plugin/tests/handback-preturn-signal.test.ts +77 -0
|
@@ -10994,7 +10994,7 @@ var init_observation_scopes = __esm(() => {
|
|
|
10994
10994
|
});
|
|
10995
10995
|
|
|
10996
10996
|
// src/config/schema.ts
|
|
10997
|
-
var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AntiConfabulationDirectiveSchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleWorkspaceConfigSchema, LiteLLMConfigSchema, HindsightPerOpLlmSchema, HindsightConfigSchema, MicrosoftWorkspaceConfigSchema, NotionWorkspaceConfigSchema, AgentGoogleWorkspaceConfigSchema, MicrosoftAccountEmailSchema, MicrosoftToolTokenSchema, MicrosoftAccountBindingSchema, AgentMicrosoftWorkspaceConfigSchema, AgentNotionWorkspaceConfigSchema, ReactionsSchema, ReactionDispatchSchema, releaseBlockFields, ReleaseBlock, RootReleaseBlock, NetworkIsolationSchema, servesField, knowsField, profileFields, ProfileSchema, _omitExtends, defaultsFields, AgentDefaultsSchema, AgentSchema, TelegramConfigSchema, MemoryBackendConfigSchema, VaultConfigSchema, QuotaConfigSchema, AutoReleaseCheckSchema, HostControlConfigSchema, WebServiceConfigSchema, FleetHealthConfigSchema, HostdConfigSchema, CronEgressSchema, CronConfigSchema, UserSchema, SwitchroomConfigSchema;
|
|
10997
|
+
var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AntiConfabulationDirectiveSchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleServiceTokenSchema, GoogleWorkspaceConfigSchema, LiteLLMConfigSchema, HindsightPerOpLlmSchema, HindsightConfigSchema, MicrosoftWorkspaceConfigSchema, NotionWorkspaceConfigSchema, AgentGoogleWorkspaceConfigSchema, MicrosoftAccountEmailSchema, MicrosoftToolTokenSchema, MicrosoftAccountBindingSchema, AgentMicrosoftWorkspaceConfigSchema, AgentNotionWorkspaceConfigSchema, ReactionsSchema, ReactionDispatchSchema, releaseBlockFields, ReleaseBlock, RootReleaseBlock, NetworkIsolationSchema, servesField, knowsField, profileFields, ProfileSchema, _omitExtends, defaultsFields, AgentDefaultsSchema, AgentSchema, TelegramConfigSchema, MemoryBackendConfigSchema, VaultConfigSchema, QuotaConfigSchema, AutoReleaseCheckSchema, HostControlConfigSchema, WebServiceConfigSchema, FleetHealthConfigSchema, HostdConfigSchema, CronEgressSchema, CronConfigSchema, UserSchema, SwitchroomConfigSchema;
|
|
10998
10998
|
var init_schema = __esm(() => {
|
|
10999
10999
|
init_zod();
|
|
11000
11000
|
init_observation_scopes();
|
|
@@ -11120,6 +11120,8 @@ var init_schema = __esm(() => {
|
|
|
11120
11120
|
profile: exports_external.string().optional().describe("Memory profile bank this agent's curated memory defaults key off — " + "the built-in disposition + observations_mission in PROFILE_MEMORY_DEFAULTS. " + "Decouples the memory profile from `extends` (the filesystem persona " + "profile), so an agent on `extends: default` can opt into the `coding` " + "memory bundle via `memory.profile: coding` without inheriting the coding " + "persona. Resolution: memory.profile → extends → DEFAULT_PROFILE (see " + "resolveMemoryProfile). Unset ⇒ byte-identical to keying off `extends`."),
|
|
11121
11121
|
bank_mission: exports_external.string().optional().describe("Bank-level mission statement used during recall to contextualize " + "results. NOTE: this is an alias for the Hindsight engine's " + "`reflect_mission` field (verified live: switchroom's bank_mission " + "lands in `config.reflect_mission`). Prefer `reflect_mission` going " + "forward; `bank_mission` is retained for back-compat. If both are " + "set, `reflect_mission` wins. Cascade: override."),
|
|
11122
11122
|
reflect_mission: exports_external.string().optional().describe("Mission/context steering Hindsight Reflect operations (the bank's " + "'who am I / what matters' framing applied during recall). The " + "engine-accurate name for what `bank_mission` sets. Cascade: override."),
|
|
11123
|
+
reflect_budget: exports_external.enum(["low", "mid", "high"]).optional().describe("Thinking/retrieval budget injected into reflect MCP calls when the " + "caller omits budget. Unset ⇒ shim default (mid). Explicit per-call " + "budget always wins. Higher = better recall on fuzzy queries, more " + "backend latency/compute. stdio-shim transport only (ignored under " + "memory.config.mcp_transport: http). Cascade: override (per-agent " + "wins over default)."),
|
|
11124
|
+
reflect_max_tokens: exports_external.number().int().positive().max(8192).optional().describe("Token cap injected into reflect MCP calls when caller omits " + "max_tokens. Unset ⇒ shim default 1024. Values much above ~2048 risk " + "exceeding Claude Code's MCP output cap, silently dropping the " + "payload — raise deliberately. Explicit per-call values always win. " + "stdio-shim transport only. Cascade: override."),
|
|
11123
11125
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain. Cascade: override."),
|
|
11124
11126
|
mental_models: exports_external.array(exports_external.object({
|
|
11125
11127
|
name: exports_external.string().min(1).describe("Stable model name (identity key for idempotent ensure). Two " + "declarations with the same name in one agent are rejected."),
|
|
@@ -11381,11 +11383,18 @@ var init_schema = __esm(() => {
|
|
|
11381
11383
|
"extended",
|
|
11382
11384
|
"complete"
|
|
11383
11385
|
]);
|
|
11386
|
+
GoogleServiceTokenSchema = exports_external.enum([
|
|
11387
|
+
"cal",
|
|
11388
|
+
"drive",
|
|
11389
|
+
"docs",
|
|
11390
|
+
"sheets",
|
|
11391
|
+
"slides"
|
|
11392
|
+
]);
|
|
11384
11393
|
GoogleWorkspaceConfigSchema = exports_external.object({
|
|
11385
11394
|
google_client_id: exports_external.string().min(1).describe("Google OAuth client ID (literal string or vault reference e.g. 'vault:google-oauth-client-id')"),
|
|
11386
11395
|
google_client_secret: exports_external.string().min(1).describe("Google OAuth client secret (literal string or vault reference e.g. 'vault:google-oauth-client-secret')"),
|
|
11387
11396
|
approvers: exports_external.array(ApproverIdSchema).min(1).describe("Array of numeric Telegram user IDs authorized to approve drive onboarding. " + "At least one must be specified."),
|
|
11388
|
-
tier: GoogleWorkspaceTierSchema.optional().describe("RFC G Phase 1: which upstream MCP tier to expose. " + "core (default) = ~16 tools (Drive+Docs+Sheets+Calendar). " + "extended = ~40 tools (+Slides, Forms, Tasks, Chat). " + "complete = ~60+ tools (+Gmail; not recommended yet — see RFC G §5).")
|
|
11397
|
+
tier: GoogleWorkspaceTierSchema.optional().describe("RFC G Phase 1: which upstream MCP tier to expose. " + "core (default) = ~16 tools (Drive+Docs+Sheets+Calendar tools; the " + "Calendar tools only authenticate when the account holds the opt-in " + "calendar scope — no tier mints it). " + "extended = ~40 tools (+Slides, Forms, Tasks, Chat). " + "complete = ~60+ tools (+Gmail; not recommended yet — see RFC G §5).")
|
|
11389
11398
|
}).optional();
|
|
11390
11399
|
LiteLLMConfigSchema = exports_external.object({
|
|
11391
11400
|
enabled: exports_external.boolean().optional().describe("Opt-in toggle. When true, `switchroom apply` provisions a per-agent " + "LiteLLM virtual key and injects routing env into the container. " + "Default OFF."),
|
|
@@ -11418,7 +11427,7 @@ var init_schema = __esm(() => {
|
|
|
11418
11427
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
|
|
11419
11428
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
|
|
11420
11429
|
}).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."),
|
|
11421
|
-
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), 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).")
|
|
11430
|
+
env: exports_external.record(exports_external.union([exports_external.string(), exports_external.number(), exports_external.boolean()])).optional().describe("Operator overrides for switchroom's capability-gated Hindsight " + "performance defaults. Only the keys switchroom actually manages are " + "honoured (`HINDSIGHT_PERF_ENV_KEYS` in " + "src/setup/hindsight-perf-defaults.ts: RERANKER_LOCAL_FP16, " + "RERANKER_LOCAL_BATCH_SIZE, LLM_MAX_CONCURRENT, " + "RETAIN/CONSOLIDATION_LLM_MAX_CONCURRENT, LLM_STRICT_SCHEMA, " + "LLM_MAX_RETRIES, CONSOLIDATION_LLM_PARALLELISM, " + "MAX_OBSERVATIONS_PER_SCOPE, " + "RECALL_MAX_CANDIDATES_PER_SOURCE, LINK_EXPANSION_PER_ENTITY_LIMIT, " + "LINK_EXPANSION_TIMEOUT, LLM_REASONING_EFFORT, " + "RERANKER_LOCAL_BUCKET_BATCHING, RERANKER_MAX_CANDIDATES, " + "RERANKER_LOCAL_MAX_CONCURRENT, RECALL_MAX_CONCURRENT, " + "REFLECT_WALL_TIMEOUT, WORKER_CONSOLIDATION_RESERVED_SLOTS, " + "WORKER_CONSOLIDATION_SLOT_LIMIT, " + "CONSOLIDATION_MAX_MEMORIES_PER_ROUND, GRAPH_SEED_MIN_SIMILARITY, " + "LLM_SUPPORTS_MAX_ITEMS, RECENCY_DECAY_FUNCTION, " + "RECENCY_DECAY_HALFLIFE_DAYS — switchroom defaults recall's recency " + "curve to `exponential` with a 30-day half-life so a fact retained " + "today outranks a stale one, instead of upstream's near-flat " + "linear/365-day window), the override-only keys " + "switchroom manages but ships NO default for " + "(`HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS`: " + "HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY — a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP — the rollback knob for " + "switchroom's CE-saturation damping patch, a float; >= ~0.65 backs the " + "damping out entirely, unset means the patch's own derived gap; and " + "HINDSIGHT_API_RECENCY_DECAY_LINEAR_WINDOW_DAYS — only read when the " + "decay function is `linear`, so switchroom ships no default for it but " + "still honours an operator who flips the function back; and " + "HINDSIGHT_API_WORKER_MAX_SLOTS — the worker poller's TOTAL in-flight " + "task budget, the pool WORKER_CONSOLIDATION_RESERVED_SLOTS reserves out of; " + "unset means upstream's own default; and " + "HINDSIGHT_API_WORKER_RETAIN_RESERVED_SLOTS — the reserved slot FLOOR for the " + "retain (memory write) lane, carved from that same total; unset means " + "upstream's own 0, i.e. no floor and retain competes for the shared " + "pool; and " + "the pre-0.8.6 name HINDSIGHT_API_WORKER_<TYPE>_MAX_SLOTS is still " + "accepted for every operation type and normalised to " + "..._RESERVED_SLOTS on the way in, because setting both names for " + "one type is a hard boot failure in the engine and switchroom " + "therefore emits only the canonical name; and " + "HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY — the cosine-similarity floor a " + "candidate must reach to be returned by the semantic retrieval arm at " + "all (0..1); unset means upstream's own 0.3, and where it should sit " + "depends on the bank's embedding model and phrasing diversity, so " + "switchroom ships no opinion; and " + "HINDSIGHT_MCP_RECALL_BUDGET_MODE — the rollback knob for switchroom's " + "mcp-recall-token-budget image patch; `legacy` restores upstream's " + "exact pre-patch recall returns, anything else or unset is the " + "honest-envelope mode; and " + "HINDSIGHT_API_LLM_TEMPERATURE_REFLECT — upstream's own per-op reflect " + "temperature knob, made live by switchroom's reflect-temperature image " + "patch; a float, or `none` to omit the kwarg (provider default, " + "upstream's accidental pre-patch behaviour); unset means the image's " + "baked default 0.1; and " + "HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT — the background " + "half of switchroom's recall-admission split (#3660): of the " + "RECALL_MAX_CONCURRENT admission slots, at most this many may be held " + "by background consolidation recalls at once, so foreground per-turn " + "recall always keeps the remainder; must be >= 1 and strictly less " + "than RECALL_MAX_CONCURRENT or the engine refuses to boot; unset " + "means the image's derived default min(2, RECALL_MAX_CONCURRENT - 1); " + "1 biases hard toward the interactive lane while a consolidation " + "backlog drains; and " + "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S — the rollback/tuning knob for " + "switchroom's MM-refresh-debounce image patch: the minimum seconds " + "between consolidation-triggered refreshes of one mental model; unset " + "means the image's baked 3600, 0 restores upstream's " + "refresh-every-round behaviour; explicit and cron-scheduled refreshes " + "are never debounced), plus the " + "embedded-PostgreSQL (pg0) sizing keys switchroom manages in " + "src/setup/hindsight-pg-defaults.ts (`HINDSIGHT_PG_ENV_KEYS`: " + "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE, " + "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS — a postgres size string such " + "as `4GB`, or the sentinel `off` to leave pg0's own default for that " + "one knob). A value set here " + "REPLACES switchroom's default and is emitted even when the gating " + "capability is absent, so an operator can always force a knob. Other " + "`HINDSIGHT_API_*` keys are deliberately IGNORED — a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
|
|
11422
11431
|
});
|
|
11423
11432
|
MicrosoftWorkspaceConfigSchema = exports_external.object({
|
|
11424
11433
|
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)."),
|
|
@@ -11604,6 +11613,8 @@ var init_schema = __esm(() => {
|
|
|
11604
11613
|
}).optional(),
|
|
11605
11614
|
bank_mission: exports_external.string().optional(),
|
|
11606
11615
|
reflect_mission: exports_external.string().optional(),
|
|
11616
|
+
reflect_budget: exports_external.enum(["low", "mid", "high"]).optional(),
|
|
11617
|
+
reflect_max_tokens: exports_external.number().int().positive().max(8192).optional(),
|
|
11607
11618
|
retain_mission: exports_external.string().optional(),
|
|
11608
11619
|
observations_mission: exports_external.string().optional(),
|
|
11609
11620
|
disposition: exports_external.object({
|
|
@@ -11892,7 +11903,9 @@ var init_schema = __esm(() => {
|
|
|
11892
11903
|
}).transform((v) => v.trim().toLowerCase()), exports_external.object({
|
|
11893
11904
|
enabled_for: exports_external.array(exports_external.string().regex(/^[a-z0-9][a-z0-9_-]{0,50}$/, {
|
|
11894
11905
|
message: "Agent name must match the standard agent-name pattern"
|
|
11895
|
-
})).describe("Agent slugs that may read this account's vault slots " + "(`google:<account>:refresh_token` etc). Per-agent ACL is " + "enforced at the broker, not at the agent identity layer — " + "the agent still authenticates via socket-path-as-identity " + "per RFC D §4.1, broker just gates the cross-agent token share.")
|
|
11906
|
+
})).describe("Agent slugs that may read this account's vault slots " + "(`google:<account>:refresh_token` etc). Per-agent ACL is " + "enforced at the broker, not at the agent identity layer — " + "the agent still authenticates via socket-path-as-identity " + "per RFC D §4.1, broker just gates the cross-agent token share."),
|
|
11907
|
+
readonly: exports_external.boolean().optional().describe("Per-account read-only selection (v1 scope model). true → the " + "token minted by `auth google account add` carries ONLY " + ".readonly scope variants (zero write scopes), and the gdrive " + "MCP launcher passes upstream `--read-only` so write tools are " + "not exposed. Written by `account add --readonly`; re-read on " + "`--replace` so a re-consent cannot silently re-widen. Omitted " + "= legacy behaviour (tier-tied read-write document scopes)."),
|
|
11908
|
+
services: exports_external.array(GoogleServiceTokenSchema).min(1).optional().describe("Per-account service selection (v1 scope model). Which Google " + "services the minted token covers AND the gdrive MCP exposes " + "(upstream `--tools`): cal, drive, docs, sheets, slides. " + "Written by `account add --services`; re-read on `--replace`. " + "Omitted = the tier's default services (drive,docs,sheets; " + "+slides at extended/complete).")
|
|
11896
11909
|
})).optional().describe("RFC G Phase 2: per-Google-account ACL for vault slots holding " + "OAuth refresh tokens. Maps account email → list of agents " + "permitted to read that account's slots. Written by `switchroom " + "auth google enable|disable` (Phase 3); read by the broker on " + "every Google slot access. Replaces RFC D's per-agent vault slot " + "scope (which can't express 'two agents share one Google account')."),
|
|
11897
11910
|
microsoft_accounts: exports_external.record(exports_external.string().regex(/^[^@\s:]+@[^@\s:]+\.[^@\s:]+$/, {
|
|
11898
11911
|
message: "Account key must be a Microsoft account email like 'alice@outlook.com' or 'alice@contoso.com' (colons not allowed)"
|
|
@@ -21402,7 +21415,7 @@ function allocateAgentUid(name) {
|
|
|
21402
21415
|
}
|
|
21403
21416
|
|
|
21404
21417
|
// src/build-info.ts
|
|
21405
|
-
var VERSION = "0.19.
|
|
21418
|
+
var VERSION = "0.19.48";
|
|
21406
21419
|
|
|
21407
21420
|
// src/setup/hindsight-recall-tunables.ts
|
|
21408
21421
|
var RECALL_DEADLINE_HEADROOM_SECONDS = 2;
|
|
@@ -21473,6 +21486,9 @@ for (const name of SHARED_FRAGMENTS) {
|
|
|
21473
21486
|
}
|
|
21474
21487
|
}
|
|
21475
21488
|
|
|
21489
|
+
// src/memory/scaffold-integration.ts
|
|
21490
|
+
init_merge();
|
|
21491
|
+
|
|
21476
21492
|
// src/litellm/timeout-budget.ts
|
|
21477
21493
|
var LITELLM_ROUTER_MARGIN_S = 10;
|
|
21478
21494
|
var LITELLM_TIMEOUT_TIERS = {
|
|
@@ -21673,7 +21689,8 @@ var HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS = new Set([
|
|
|
21673
21689
|
"HINDSIGHT_MCP_RECALL_BUDGET_MODE",
|
|
21674
21690
|
"HINDSIGHT_API_LLM_TEMPERATURE_REFLECT",
|
|
21675
21691
|
"HINDSIGHT_API_RETAIN_WALL_TIMEOUT",
|
|
21676
|
-
"HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT"
|
|
21692
|
+
"HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT",
|
|
21693
|
+
"HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S"
|
|
21677
21694
|
]);
|
|
21678
21695
|
var HINDSIGHT_WORKER_SLOT_TYPES = [
|
|
21679
21696
|
"consolidation",
|
|
@@ -4434,7 +4434,7 @@ var init_observation_scopes = __esm(() => {
|
|
|
4434
4434
|
});
|
|
4435
4435
|
|
|
4436
4436
|
// src/config/schema.ts
|
|
4437
|
-
var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AntiConfabulationDirectiveSchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleWorkspaceConfigSchema, LiteLLMConfigSchema, HindsightPerOpLlmSchema, HindsightConfigSchema, MicrosoftWorkspaceConfigSchema, NotionWorkspaceConfigSchema, AgentGoogleWorkspaceConfigSchema, MicrosoftAccountEmailSchema, MicrosoftToolTokenSchema, MicrosoftAccountBindingSchema, AgentMicrosoftWorkspaceConfigSchema, AgentNotionWorkspaceConfigSchema, ReactionsSchema, ReactionDispatchSchema, releaseBlockFields, ReleaseBlock, RootReleaseBlock, NetworkIsolationSchema, servesField, knowsField, profileFields, ProfileSchema, _omitExtends, defaultsFields, AgentDefaultsSchema, AgentSchema, TelegramConfigSchema, MemoryBackendConfigSchema, VaultConfigSchema, QuotaConfigSchema, AutoReleaseCheckSchema, HostControlConfigSchema, WebServiceConfigSchema, FleetHealthConfigSchema, HostdConfigSchema, CronEgressSchema, CronConfigSchema, UserSchema, SwitchroomConfigSchema;
|
|
4437
|
+
var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AntiConfabulationDirectiveSchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleServiceTokenSchema, GoogleWorkspaceConfigSchema, LiteLLMConfigSchema, HindsightPerOpLlmSchema, HindsightConfigSchema, MicrosoftWorkspaceConfigSchema, NotionWorkspaceConfigSchema, AgentGoogleWorkspaceConfigSchema, MicrosoftAccountEmailSchema, MicrosoftToolTokenSchema, MicrosoftAccountBindingSchema, AgentMicrosoftWorkspaceConfigSchema, AgentNotionWorkspaceConfigSchema, ReactionsSchema, ReactionDispatchSchema, releaseBlockFields, ReleaseBlock, RootReleaseBlock, NetworkIsolationSchema, servesField, knowsField, profileFields, ProfileSchema, _omitExtends, defaultsFields, AgentDefaultsSchema, AgentSchema, TelegramConfigSchema, MemoryBackendConfigSchema, VaultConfigSchema, QuotaConfigSchema, AutoReleaseCheckSchema, HostControlConfigSchema, WebServiceConfigSchema, FleetHealthConfigSchema, HostdConfigSchema, CronEgressSchema, CronConfigSchema, UserSchema, SwitchroomConfigSchema;
|
|
4438
4438
|
var init_schema = __esm(() => {
|
|
4439
4439
|
init_zod();
|
|
4440
4440
|
init_observation_scopes();
|
|
@@ -4560,6 +4560,8 @@ var init_schema = __esm(() => {
|
|
|
4560
4560
|
profile: exports_external.string().optional().describe("Memory profile bank this agent's curated memory defaults key off — " + "the built-in disposition + observations_mission in PROFILE_MEMORY_DEFAULTS. " + "Decouples the memory profile from `extends` (the filesystem persona " + "profile), so an agent on `extends: default` can opt into the `coding` " + "memory bundle via `memory.profile: coding` without inheriting the coding " + "persona. Resolution: memory.profile → extends → DEFAULT_PROFILE (see " + "resolveMemoryProfile). Unset ⇒ byte-identical to keying off `extends`."),
|
|
4561
4561
|
bank_mission: exports_external.string().optional().describe("Bank-level mission statement used during recall to contextualize " + "results. NOTE: this is an alias for the Hindsight engine's " + "`reflect_mission` field (verified live: switchroom's bank_mission " + "lands in `config.reflect_mission`). Prefer `reflect_mission` going " + "forward; `bank_mission` is retained for back-compat. If both are " + "set, `reflect_mission` wins. Cascade: override."),
|
|
4562
4562
|
reflect_mission: exports_external.string().optional().describe("Mission/context steering Hindsight Reflect operations (the bank's " + "'who am I / what matters' framing applied during recall). The " + "engine-accurate name for what `bank_mission` sets. Cascade: override."),
|
|
4563
|
+
reflect_budget: exports_external.enum(["low", "mid", "high"]).optional().describe("Thinking/retrieval budget injected into reflect MCP calls when the " + "caller omits budget. Unset ⇒ shim default (mid). Explicit per-call " + "budget always wins. Higher = better recall on fuzzy queries, more " + "backend latency/compute. stdio-shim transport only (ignored under " + "memory.config.mcp_transport: http). Cascade: override (per-agent " + "wins over default)."),
|
|
4564
|
+
reflect_max_tokens: exports_external.number().int().positive().max(8192).optional().describe("Token cap injected into reflect MCP calls when caller omits " + "max_tokens. Unset ⇒ shim default 1024. Values much above ~2048 risk " + "exceeding Claude Code's MCP output cap, silently dropping the " + "payload — raise deliberately. Explicit per-call values always win. " + "stdio-shim transport only. Cascade: override."),
|
|
4563
4565
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain. Cascade: override."),
|
|
4564
4566
|
mental_models: exports_external.array(exports_external.object({
|
|
4565
4567
|
name: exports_external.string().min(1).describe("Stable model name (identity key for idempotent ensure). Two " + "declarations with the same name in one agent are rejected."),
|
|
@@ -4821,11 +4823,18 @@ var init_schema = __esm(() => {
|
|
|
4821
4823
|
"extended",
|
|
4822
4824
|
"complete"
|
|
4823
4825
|
]);
|
|
4826
|
+
GoogleServiceTokenSchema = exports_external.enum([
|
|
4827
|
+
"cal",
|
|
4828
|
+
"drive",
|
|
4829
|
+
"docs",
|
|
4830
|
+
"sheets",
|
|
4831
|
+
"slides"
|
|
4832
|
+
]);
|
|
4824
4833
|
GoogleWorkspaceConfigSchema = exports_external.object({
|
|
4825
4834
|
google_client_id: exports_external.string().min(1).describe("Google OAuth client ID (literal string or vault reference e.g. 'vault:google-oauth-client-id')"),
|
|
4826
4835
|
google_client_secret: exports_external.string().min(1).describe("Google OAuth client secret (literal string or vault reference e.g. 'vault:google-oauth-client-secret')"),
|
|
4827
4836
|
approvers: exports_external.array(ApproverIdSchema).min(1).describe("Array of numeric Telegram user IDs authorized to approve drive onboarding. " + "At least one must be specified."),
|
|
4828
|
-
tier: GoogleWorkspaceTierSchema.optional().describe("RFC G Phase 1: which upstream MCP tier to expose. " + "core (default) = ~16 tools (Drive+Docs+Sheets+Calendar). " + "extended = ~40 tools (+Slides, Forms, Tasks, Chat). " + "complete = ~60+ tools (+Gmail; not recommended yet — see RFC G §5).")
|
|
4837
|
+
tier: GoogleWorkspaceTierSchema.optional().describe("RFC G Phase 1: which upstream MCP tier to expose. " + "core (default) = ~16 tools (Drive+Docs+Sheets+Calendar tools; the " + "Calendar tools only authenticate when the account holds the opt-in " + "calendar scope — no tier mints it). " + "extended = ~40 tools (+Slides, Forms, Tasks, Chat). " + "complete = ~60+ tools (+Gmail; not recommended yet — see RFC G §5).")
|
|
4829
4838
|
}).optional();
|
|
4830
4839
|
LiteLLMConfigSchema = exports_external.object({
|
|
4831
4840
|
enabled: exports_external.boolean().optional().describe("Opt-in toggle. When true, `switchroom apply` provisions a per-agent " + "LiteLLM virtual key and injects routing env into the container. " + "Default OFF."),
|
|
@@ -4858,7 +4867,7 @@ var init_schema = __esm(() => {
|
|
|
4858
4867
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
|
|
4859
4868
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
|
|
4860
4869
|
}).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."),
|
|
4861
|
-
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), 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).")
|
|
4870
|
+
env: exports_external.record(exports_external.union([exports_external.string(), exports_external.number(), exports_external.boolean()])).optional().describe("Operator overrides for switchroom's capability-gated Hindsight " + "performance defaults. Only the keys switchroom actually manages are " + "honoured (`HINDSIGHT_PERF_ENV_KEYS` in " + "src/setup/hindsight-perf-defaults.ts: RERANKER_LOCAL_FP16, " + "RERANKER_LOCAL_BATCH_SIZE, LLM_MAX_CONCURRENT, " + "RETAIN/CONSOLIDATION_LLM_MAX_CONCURRENT, LLM_STRICT_SCHEMA, " + "LLM_MAX_RETRIES, CONSOLIDATION_LLM_PARALLELISM, " + "MAX_OBSERVATIONS_PER_SCOPE, " + "RECALL_MAX_CANDIDATES_PER_SOURCE, LINK_EXPANSION_PER_ENTITY_LIMIT, " + "LINK_EXPANSION_TIMEOUT, LLM_REASONING_EFFORT, " + "RERANKER_LOCAL_BUCKET_BATCHING, RERANKER_MAX_CANDIDATES, " + "RERANKER_LOCAL_MAX_CONCURRENT, RECALL_MAX_CONCURRENT, " + "REFLECT_WALL_TIMEOUT, WORKER_CONSOLIDATION_RESERVED_SLOTS, " + "WORKER_CONSOLIDATION_SLOT_LIMIT, " + "CONSOLIDATION_MAX_MEMORIES_PER_ROUND, GRAPH_SEED_MIN_SIMILARITY, " + "LLM_SUPPORTS_MAX_ITEMS, RECENCY_DECAY_FUNCTION, " + "RECENCY_DECAY_HALFLIFE_DAYS — switchroom defaults recall's recency " + "curve to `exponential` with a 30-day half-life so a fact retained " + "today outranks a stale one, instead of upstream's near-flat " + "linear/365-day window), the override-only keys " + "switchroom manages but ships NO default for " + "(`HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS`: " + "HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY — a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP — the rollback knob for " + "switchroom's CE-saturation damping patch, a float; >= ~0.65 backs the " + "damping out entirely, unset means the patch's own derived gap; and " + "HINDSIGHT_API_RECENCY_DECAY_LINEAR_WINDOW_DAYS — only read when the " + "decay function is `linear`, so switchroom ships no default for it but " + "still honours an operator who flips the function back; and " + "HINDSIGHT_API_WORKER_MAX_SLOTS — the worker poller's TOTAL in-flight " + "task budget, the pool WORKER_CONSOLIDATION_RESERVED_SLOTS reserves out of; " + "unset means upstream's own default; and " + "HINDSIGHT_API_WORKER_RETAIN_RESERVED_SLOTS — the reserved slot FLOOR for the " + "retain (memory write) lane, carved from that same total; unset means " + "upstream's own 0, i.e. no floor and retain competes for the shared " + "pool; and " + "the pre-0.8.6 name HINDSIGHT_API_WORKER_<TYPE>_MAX_SLOTS is still " + "accepted for every operation type and normalised to " + "..._RESERVED_SLOTS on the way in, because setting both names for " + "one type is a hard boot failure in the engine and switchroom " + "therefore emits only the canonical name; and " + "HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY — the cosine-similarity floor a " + "candidate must reach to be returned by the semantic retrieval arm at " + "all (0..1); unset means upstream's own 0.3, and where it should sit " + "depends on the bank's embedding model and phrasing diversity, so " + "switchroom ships no opinion; and " + "HINDSIGHT_MCP_RECALL_BUDGET_MODE — the rollback knob for switchroom's " + "mcp-recall-token-budget image patch; `legacy` restores upstream's " + "exact pre-patch recall returns, anything else or unset is the " + "honest-envelope mode; and " + "HINDSIGHT_API_LLM_TEMPERATURE_REFLECT — upstream's own per-op reflect " + "temperature knob, made live by switchroom's reflect-temperature image " + "patch; a float, or `none` to omit the kwarg (provider default, " + "upstream's accidental pre-patch behaviour); unset means the image's " + "baked default 0.1; and " + "HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT — the background " + "half of switchroom's recall-admission split (#3660): of the " + "RECALL_MAX_CONCURRENT admission slots, at most this many may be held " + "by background consolidation recalls at once, so foreground per-turn " + "recall always keeps the remainder; must be >= 1 and strictly less " + "than RECALL_MAX_CONCURRENT or the engine refuses to boot; unset " + "means the image's derived default min(2, RECALL_MAX_CONCURRENT - 1); " + "1 biases hard toward the interactive lane while a consolidation " + "backlog drains; and " + "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S — the rollback/tuning knob for " + "switchroom's MM-refresh-debounce image patch: the minimum seconds " + "between consolidation-triggered refreshes of one mental model; unset " + "means the image's baked 3600, 0 restores upstream's " + "refresh-every-round behaviour; explicit and cron-scheduled refreshes " + "are never debounced), plus the " + "embedded-PostgreSQL (pg0) sizing keys switchroom manages in " + "src/setup/hindsight-pg-defaults.ts (`HINDSIGHT_PG_ENV_KEYS`: " + "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE, " + "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS — a postgres size string such " + "as `4GB`, or the sentinel `off` to leave pg0's own default for that " + "one knob). A value set here " + "REPLACES switchroom's default and is emitted even when the gating " + "capability is absent, so an operator can always force a knob. Other " + "`HINDSIGHT_API_*` keys are deliberately IGNORED — a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
|
|
4862
4871
|
});
|
|
4863
4872
|
MicrosoftWorkspaceConfigSchema = exports_external.object({
|
|
4864
4873
|
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)."),
|
|
@@ -5044,6 +5053,8 @@ var init_schema = __esm(() => {
|
|
|
5044
5053
|
}).optional(),
|
|
5045
5054
|
bank_mission: exports_external.string().optional(),
|
|
5046
5055
|
reflect_mission: exports_external.string().optional(),
|
|
5056
|
+
reflect_budget: exports_external.enum(["low", "mid", "high"]).optional(),
|
|
5057
|
+
reflect_max_tokens: exports_external.number().int().positive().max(8192).optional(),
|
|
5047
5058
|
retain_mission: exports_external.string().optional(),
|
|
5048
5059
|
observations_mission: exports_external.string().optional(),
|
|
5049
5060
|
disposition: exports_external.object({
|
|
@@ -5332,7 +5343,9 @@ var init_schema = __esm(() => {
|
|
|
5332
5343
|
}).transform((v) => v.trim().toLowerCase()), exports_external.object({
|
|
5333
5344
|
enabled_for: exports_external.array(exports_external.string().regex(/^[a-z0-9][a-z0-9_-]{0,50}$/, {
|
|
5334
5345
|
message: "Agent name must match the standard agent-name pattern"
|
|
5335
|
-
})).describe("Agent slugs that may read this account's vault slots " + "(`google:<account>:refresh_token` etc). Per-agent ACL is " + "enforced at the broker, not at the agent identity layer — " + "the agent still authenticates via socket-path-as-identity " + "per RFC D §4.1, broker just gates the cross-agent token share.")
|
|
5346
|
+
})).describe("Agent slugs that may read this account's vault slots " + "(`google:<account>:refresh_token` etc). Per-agent ACL is " + "enforced at the broker, not at the agent identity layer — " + "the agent still authenticates via socket-path-as-identity " + "per RFC D §4.1, broker just gates the cross-agent token share."),
|
|
5347
|
+
readonly: exports_external.boolean().optional().describe("Per-account read-only selection (v1 scope model). true → the " + "token minted by `auth google account add` carries ONLY " + ".readonly scope variants (zero write scopes), and the gdrive " + "MCP launcher passes upstream `--read-only` so write tools are " + "not exposed. Written by `account add --readonly`; re-read on " + "`--replace` so a re-consent cannot silently re-widen. Omitted " + "= legacy behaviour (tier-tied read-write document scopes)."),
|
|
5348
|
+
services: exports_external.array(GoogleServiceTokenSchema).min(1).optional().describe("Per-account service selection (v1 scope model). Which Google " + "services the minted token covers AND the gdrive MCP exposes " + "(upstream `--tools`): cal, drive, docs, sheets, slides. " + "Written by `account add --services`; re-read on `--replace`. " + "Omitted = the tier's default services (drive,docs,sheets; " + "+slides at extended/complete).")
|
|
5336
5349
|
})).optional().describe("RFC G Phase 2: per-Google-account ACL for vault slots holding " + "OAuth refresh tokens. Maps account email → list of agents " + "permitted to read that account's slots. Written by `switchroom " + "auth google enable|disable` (Phase 3); read by the broker on " + "every Google slot access. Replaces RFC D's per-agent vault slot " + "scope (which can't express 'two agents share one Google account')."),
|
|
5337
5350
|
microsoft_accounts: exports_external.record(exports_external.string().regex(/^[^@\s:]+@[^@\s:]+\.[^@\s:]+$/, {
|
|
5338
5351
|
message: "Account key must be a Microsoft account email like 'alice@outlook.com' or 'alice@contoso.com' (colons not allowed)"
|
|
@@ -19368,6 +19381,9 @@ for (const name of SHARED_FRAGMENTS) {
|
|
|
19368
19381
|
}
|
|
19369
19382
|
}
|
|
19370
19383
|
|
|
19384
|
+
// src/memory/scaffold-integration.ts
|
|
19385
|
+
init_merge();
|
|
19386
|
+
|
|
19371
19387
|
// src/litellm/timeout-budget.ts
|
|
19372
19388
|
var LITELLM_ROUTER_MARGIN_S = 10;
|
|
19373
19389
|
var LITELLM_TIMEOUT_TIERS = {
|
|
@@ -19568,7 +19584,8 @@ var HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS = new Set([
|
|
|
19568
19584
|
"HINDSIGHT_MCP_RECALL_BUDGET_MODE",
|
|
19569
19585
|
"HINDSIGHT_API_LLM_TEMPERATURE_REFLECT",
|
|
19570
19586
|
"HINDSIGHT_API_RETAIN_WALL_TIMEOUT",
|
|
19571
|
-
"HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT"
|
|
19587
|
+
"HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT",
|
|
19588
|
+
"HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S"
|
|
19572
19589
|
]);
|
|
19573
19590
|
var HINDSIGHT_WORKER_SLOT_TYPES = [
|
|
19574
19591
|
"consolidation",
|
|
@@ -4030,7 +4030,7 @@ var init_observation_scopes = __esm(() => {
|
|
|
4030
4030
|
});
|
|
4031
4031
|
|
|
4032
4032
|
// src/config/schema.ts
|
|
4033
|
-
var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AntiConfabulationDirectiveSchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleWorkspaceConfigSchema, LiteLLMConfigSchema, HindsightPerOpLlmSchema, HindsightConfigSchema, MicrosoftWorkspaceConfigSchema, NotionWorkspaceConfigSchema, AgentGoogleWorkspaceConfigSchema, MicrosoftAccountEmailSchema, MicrosoftToolTokenSchema, MicrosoftAccountBindingSchema, AgentMicrosoftWorkspaceConfigSchema, AgentNotionWorkspaceConfigSchema, ReactionsSchema, ReactionDispatchSchema, releaseBlockFields, ReleaseBlock, RootReleaseBlock, NetworkIsolationSchema, servesField, knowsField, profileFields, ProfileSchema, _omitExtends, defaultsFields, AgentDefaultsSchema, AgentSchema, TelegramConfigSchema, MemoryBackendConfigSchema, VaultConfigSchema, QuotaConfigSchema, AutoReleaseCheckSchema, HostControlConfigSchema, WebServiceConfigSchema, FleetHealthConfigSchema, HostdConfigSchema, CronEgressSchema, CronConfigSchema, UserSchema, SwitchroomConfigSchema;
|
|
4033
|
+
var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AntiConfabulationDirectiveSchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleServiceTokenSchema, GoogleWorkspaceConfigSchema, LiteLLMConfigSchema, HindsightPerOpLlmSchema, HindsightConfigSchema, MicrosoftWorkspaceConfigSchema, NotionWorkspaceConfigSchema, AgentGoogleWorkspaceConfigSchema, MicrosoftAccountEmailSchema, MicrosoftToolTokenSchema, MicrosoftAccountBindingSchema, AgentMicrosoftWorkspaceConfigSchema, AgentNotionWorkspaceConfigSchema, ReactionsSchema, ReactionDispatchSchema, releaseBlockFields, ReleaseBlock, RootReleaseBlock, NetworkIsolationSchema, servesField, knowsField, profileFields, ProfileSchema, _omitExtends, defaultsFields, AgentDefaultsSchema, AgentSchema, TelegramConfigSchema, MemoryBackendConfigSchema, VaultConfigSchema, QuotaConfigSchema, AutoReleaseCheckSchema, HostControlConfigSchema, WebServiceConfigSchema, FleetHealthConfigSchema, HostdConfigSchema, CronEgressSchema, CronConfigSchema, UserSchema, SwitchroomConfigSchema;
|
|
4034
4034
|
var init_schema = __esm(() => {
|
|
4035
4035
|
init_zod();
|
|
4036
4036
|
init_observation_scopes();
|
|
@@ -4156,6 +4156,8 @@ var init_schema = __esm(() => {
|
|
|
4156
4156
|
profile: exports_external.string().optional().describe("Memory profile bank this agent's curated memory defaults key off — " + "the built-in disposition + observations_mission in PROFILE_MEMORY_DEFAULTS. " + "Decouples the memory profile from `extends` (the filesystem persona " + "profile), so an agent on `extends: default` can opt into the `coding` " + "memory bundle via `memory.profile: coding` without inheriting the coding " + "persona. Resolution: memory.profile → extends → DEFAULT_PROFILE (see " + "resolveMemoryProfile). Unset ⇒ byte-identical to keying off `extends`."),
|
|
4157
4157
|
bank_mission: exports_external.string().optional().describe("Bank-level mission statement used during recall to contextualize " + "results. NOTE: this is an alias for the Hindsight engine's " + "`reflect_mission` field (verified live: switchroom's bank_mission " + "lands in `config.reflect_mission`). Prefer `reflect_mission` going " + "forward; `bank_mission` is retained for back-compat. If both are " + "set, `reflect_mission` wins. Cascade: override."),
|
|
4158
4158
|
reflect_mission: exports_external.string().optional().describe("Mission/context steering Hindsight Reflect operations (the bank's " + "'who am I / what matters' framing applied during recall). The " + "engine-accurate name for what `bank_mission` sets. Cascade: override."),
|
|
4159
|
+
reflect_budget: exports_external.enum(["low", "mid", "high"]).optional().describe("Thinking/retrieval budget injected into reflect MCP calls when the " + "caller omits budget. Unset ⇒ shim default (mid). Explicit per-call " + "budget always wins. Higher = better recall on fuzzy queries, more " + "backend latency/compute. stdio-shim transport only (ignored under " + "memory.config.mcp_transport: http). Cascade: override (per-agent " + "wins over default)."),
|
|
4160
|
+
reflect_max_tokens: exports_external.number().int().positive().max(8192).optional().describe("Token cap injected into reflect MCP calls when caller omits " + "max_tokens. Unset ⇒ shim default 1024. Values much above ~2048 risk " + "exceeding Claude Code's MCP output cap, silently dropping the " + "payload — raise deliberately. Explicit per-call values always win. " + "stdio-shim transport only. Cascade: override."),
|
|
4159
4161
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain. Cascade: override."),
|
|
4160
4162
|
mental_models: exports_external.array(exports_external.object({
|
|
4161
4163
|
name: exports_external.string().min(1).describe("Stable model name (identity key for idempotent ensure). Two " + "declarations with the same name in one agent are rejected."),
|
|
@@ -4417,11 +4419,18 @@ var init_schema = __esm(() => {
|
|
|
4417
4419
|
"extended",
|
|
4418
4420
|
"complete"
|
|
4419
4421
|
]);
|
|
4422
|
+
GoogleServiceTokenSchema = exports_external.enum([
|
|
4423
|
+
"cal",
|
|
4424
|
+
"drive",
|
|
4425
|
+
"docs",
|
|
4426
|
+
"sheets",
|
|
4427
|
+
"slides"
|
|
4428
|
+
]);
|
|
4420
4429
|
GoogleWorkspaceConfigSchema = exports_external.object({
|
|
4421
4430
|
google_client_id: exports_external.string().min(1).describe("Google OAuth client ID (literal string or vault reference e.g. 'vault:google-oauth-client-id')"),
|
|
4422
4431
|
google_client_secret: exports_external.string().min(1).describe("Google OAuth client secret (literal string or vault reference e.g. 'vault:google-oauth-client-secret')"),
|
|
4423
4432
|
approvers: exports_external.array(ApproverIdSchema).min(1).describe("Array of numeric Telegram user IDs authorized to approve drive onboarding. " + "At least one must be specified."),
|
|
4424
|
-
tier: GoogleWorkspaceTierSchema.optional().describe("RFC G Phase 1: which upstream MCP tier to expose. " + "core (default) = ~16 tools (Drive+Docs+Sheets+Calendar). " + "extended = ~40 tools (+Slides, Forms, Tasks, Chat). " + "complete = ~60+ tools (+Gmail; not recommended yet — see RFC G §5).")
|
|
4433
|
+
tier: GoogleWorkspaceTierSchema.optional().describe("RFC G Phase 1: which upstream MCP tier to expose. " + "core (default) = ~16 tools (Drive+Docs+Sheets+Calendar tools; the " + "Calendar tools only authenticate when the account holds the opt-in " + "calendar scope — no tier mints it). " + "extended = ~40 tools (+Slides, Forms, Tasks, Chat). " + "complete = ~60+ tools (+Gmail; not recommended yet — see RFC G §5).")
|
|
4425
4434
|
}).optional();
|
|
4426
4435
|
LiteLLMConfigSchema = exports_external.object({
|
|
4427
4436
|
enabled: exports_external.boolean().optional().describe("Opt-in toggle. When true, `switchroom apply` provisions a per-agent " + "LiteLLM virtual key and injects routing env into the container. " + "Default OFF."),
|
|
@@ -4454,7 +4463,7 @@ var init_schema = __esm(() => {
|
|
|
4454
4463
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
|
|
4455
4464
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
|
|
4456
4465
|
}).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."),
|
|
4457
|
-
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), 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).")
|
|
4466
|
+
env: exports_external.record(exports_external.union([exports_external.string(), exports_external.number(), exports_external.boolean()])).optional().describe("Operator overrides for switchroom's capability-gated Hindsight " + "performance defaults. Only the keys switchroom actually manages are " + "honoured (`HINDSIGHT_PERF_ENV_KEYS` in " + "src/setup/hindsight-perf-defaults.ts: RERANKER_LOCAL_FP16, " + "RERANKER_LOCAL_BATCH_SIZE, LLM_MAX_CONCURRENT, " + "RETAIN/CONSOLIDATION_LLM_MAX_CONCURRENT, LLM_STRICT_SCHEMA, " + "LLM_MAX_RETRIES, CONSOLIDATION_LLM_PARALLELISM, " + "MAX_OBSERVATIONS_PER_SCOPE, " + "RECALL_MAX_CANDIDATES_PER_SOURCE, LINK_EXPANSION_PER_ENTITY_LIMIT, " + "LINK_EXPANSION_TIMEOUT, LLM_REASONING_EFFORT, " + "RERANKER_LOCAL_BUCKET_BATCHING, RERANKER_MAX_CANDIDATES, " + "RERANKER_LOCAL_MAX_CONCURRENT, RECALL_MAX_CONCURRENT, " + "REFLECT_WALL_TIMEOUT, WORKER_CONSOLIDATION_RESERVED_SLOTS, " + "WORKER_CONSOLIDATION_SLOT_LIMIT, " + "CONSOLIDATION_MAX_MEMORIES_PER_ROUND, GRAPH_SEED_MIN_SIMILARITY, " + "LLM_SUPPORTS_MAX_ITEMS, RECENCY_DECAY_FUNCTION, " + "RECENCY_DECAY_HALFLIFE_DAYS — switchroom defaults recall's recency " + "curve to `exponential` with a 30-day half-life so a fact retained " + "today outranks a stale one, instead of upstream's near-flat " + "linear/365-day window), the override-only keys " + "switchroom manages but ships NO default for " + "(`HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS`: " + "HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY — a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP — the rollback knob for " + "switchroom's CE-saturation damping patch, a float; >= ~0.65 backs the " + "damping out entirely, unset means the patch's own derived gap; and " + "HINDSIGHT_API_RECENCY_DECAY_LINEAR_WINDOW_DAYS — only read when the " + "decay function is `linear`, so switchroom ships no default for it but " + "still honours an operator who flips the function back; and " + "HINDSIGHT_API_WORKER_MAX_SLOTS — the worker poller's TOTAL in-flight " + "task budget, the pool WORKER_CONSOLIDATION_RESERVED_SLOTS reserves out of; " + "unset means upstream's own default; and " + "HINDSIGHT_API_WORKER_RETAIN_RESERVED_SLOTS — the reserved slot FLOOR for the " + "retain (memory write) lane, carved from that same total; unset means " + "upstream's own 0, i.e. no floor and retain competes for the shared " + "pool; and " + "the pre-0.8.6 name HINDSIGHT_API_WORKER_<TYPE>_MAX_SLOTS is still " + "accepted for every operation type and normalised to " + "..._RESERVED_SLOTS on the way in, because setting both names for " + "one type is a hard boot failure in the engine and switchroom " + "therefore emits only the canonical name; and " + "HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY — the cosine-similarity floor a " + "candidate must reach to be returned by the semantic retrieval arm at " + "all (0..1); unset means upstream's own 0.3, and where it should sit " + "depends on the bank's embedding model and phrasing diversity, so " + "switchroom ships no opinion; and " + "HINDSIGHT_MCP_RECALL_BUDGET_MODE — the rollback knob for switchroom's " + "mcp-recall-token-budget image patch; `legacy` restores upstream's " + "exact pre-patch recall returns, anything else or unset is the " + "honest-envelope mode; and " + "HINDSIGHT_API_LLM_TEMPERATURE_REFLECT — upstream's own per-op reflect " + "temperature knob, made live by switchroom's reflect-temperature image " + "patch; a float, or `none` to omit the kwarg (provider default, " + "upstream's accidental pre-patch behaviour); unset means the image's " + "baked default 0.1; and " + "HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT — the background " + "half of switchroom's recall-admission split (#3660): of the " + "RECALL_MAX_CONCURRENT admission slots, at most this many may be held " + "by background consolidation recalls at once, so foreground per-turn " + "recall always keeps the remainder; must be >= 1 and strictly less " + "than RECALL_MAX_CONCURRENT or the engine refuses to boot; unset " + "means the image's derived default min(2, RECALL_MAX_CONCURRENT - 1); " + "1 biases hard toward the interactive lane while a consolidation " + "backlog drains; and " + "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S — the rollback/tuning knob for " + "switchroom's MM-refresh-debounce image patch: the minimum seconds " + "between consolidation-triggered refreshes of one mental model; unset " + "means the image's baked 3600, 0 restores upstream's " + "refresh-every-round behaviour; explicit and cron-scheduled refreshes " + "are never debounced), plus the " + "embedded-PostgreSQL (pg0) sizing keys switchroom manages in " + "src/setup/hindsight-pg-defaults.ts (`HINDSIGHT_PG_ENV_KEYS`: " + "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE, " + "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS — a postgres size string such " + "as `4GB`, or the sentinel `off` to leave pg0's own default for that " + "one knob). A value set here " + "REPLACES switchroom's default and is emitted even when the gating " + "capability is absent, so an operator can always force a knob. Other " + "`HINDSIGHT_API_*` keys are deliberately IGNORED — a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
|
|
4458
4467
|
});
|
|
4459
4468
|
MicrosoftWorkspaceConfigSchema = exports_external.object({
|
|
4460
4469
|
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)."),
|
|
@@ -4640,6 +4649,8 @@ var init_schema = __esm(() => {
|
|
|
4640
4649
|
}).optional(),
|
|
4641
4650
|
bank_mission: exports_external.string().optional(),
|
|
4642
4651
|
reflect_mission: exports_external.string().optional(),
|
|
4652
|
+
reflect_budget: exports_external.enum(["low", "mid", "high"]).optional(),
|
|
4653
|
+
reflect_max_tokens: exports_external.number().int().positive().max(8192).optional(),
|
|
4643
4654
|
retain_mission: exports_external.string().optional(),
|
|
4644
4655
|
observations_mission: exports_external.string().optional(),
|
|
4645
4656
|
disposition: exports_external.object({
|
|
@@ -4928,7 +4939,9 @@ var init_schema = __esm(() => {
|
|
|
4928
4939
|
}).transform((v) => v.trim().toLowerCase()), exports_external.object({
|
|
4929
4940
|
enabled_for: exports_external.array(exports_external.string().regex(/^[a-z0-9][a-z0-9_-]{0,50}$/, {
|
|
4930
4941
|
message: "Agent name must match the standard agent-name pattern"
|
|
4931
|
-
})).describe("Agent slugs that may read this account's vault slots " + "(`google:<account>:refresh_token` etc). Per-agent ACL is " + "enforced at the broker, not at the agent identity layer — " + "the agent still authenticates via socket-path-as-identity " + "per RFC D §4.1, broker just gates the cross-agent token share.")
|
|
4942
|
+
})).describe("Agent slugs that may read this account's vault slots " + "(`google:<account>:refresh_token` etc). Per-agent ACL is " + "enforced at the broker, not at the agent identity layer — " + "the agent still authenticates via socket-path-as-identity " + "per RFC D §4.1, broker just gates the cross-agent token share."),
|
|
4943
|
+
readonly: exports_external.boolean().optional().describe("Per-account read-only selection (v1 scope model). true → the " + "token minted by `auth google account add` carries ONLY " + ".readonly scope variants (zero write scopes), and the gdrive " + "MCP launcher passes upstream `--read-only` so write tools are " + "not exposed. Written by `account add --readonly`; re-read on " + "`--replace` so a re-consent cannot silently re-widen. Omitted " + "= legacy behaviour (tier-tied read-write document scopes)."),
|
|
4944
|
+
services: exports_external.array(GoogleServiceTokenSchema).min(1).optional().describe("Per-account service selection (v1 scope model). Which Google " + "services the minted token covers AND the gdrive MCP exposes " + "(upstream `--tools`): cal, drive, docs, sheets, slides. " + "Written by `account add --services`; re-read on `--replace`. " + "Omitted = the tier's default services (drive,docs,sheets; " + "+slides at extended/complete).")
|
|
4932
4945
|
})).optional().describe("RFC G Phase 2: per-Google-account ACL for vault slots holding " + "OAuth refresh tokens. Maps account email → list of agents " + "permitted to read that account's slots. Written by `switchroom " + "auth google enable|disable` (Phase 3); read by the broker on " + "every Google slot access. Replaces RFC D's per-agent vault slot " + "scope (which can't express 'two agents share one Google account')."),
|
|
4933
4946
|
microsoft_accounts: exports_external.record(exports_external.string().regex(/^[^@\s:]+@[^@\s:]+\.[^@\s:]+$/, {
|
|
4934
4947
|
message: "Account key must be a Microsoft account email like 'alice@outlook.com' or 'alice@contoso.com' (colons not allowed)"
|
|
@@ -19781,6 +19794,9 @@ for (const name of SHARED_FRAGMENTS) {
|
|
|
19781
19794
|
}
|
|
19782
19795
|
}
|
|
19783
19796
|
|
|
19797
|
+
// src/memory/scaffold-integration.ts
|
|
19798
|
+
init_merge();
|
|
19799
|
+
|
|
19784
19800
|
// src/litellm/timeout-budget.ts
|
|
19785
19801
|
var LITELLM_ROUTER_MARGIN_S = 10;
|
|
19786
19802
|
var LITELLM_TIMEOUT_TIERS = {
|
|
@@ -19981,7 +19997,8 @@ var HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS = new Set([
|
|
|
19981
19997
|
"HINDSIGHT_MCP_RECALL_BUDGET_MODE",
|
|
19982
19998
|
"HINDSIGHT_API_LLM_TEMPERATURE_REFLECT",
|
|
19983
19999
|
"HINDSIGHT_API_RETAIN_WALL_TIMEOUT",
|
|
19984
|
-
"HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT"
|
|
20000
|
+
"HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT",
|
|
20001
|
+
"HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S"
|
|
19985
20002
|
]);
|
|
19986
20003
|
var HINDSIGHT_WORKER_SLOT_TYPES = [
|
|
19987
20004
|
"consolidation",
|
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.19.
|
|
4
|
+
"version": "0.19.48",
|
|
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": {
|
|
@@ -33,6 +33,61 @@ import { decideTurnFlush, type FlushDecisionInput } from './turn-flush-safety.js
|
|
|
33
33
|
* matching the repo's env-flag convention. */
|
|
34
34
|
export const ANSWER_READY_FLUSH_MS = 1000
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Default STAGE window (ms) — the stage-don't-send fix for the live
|
|
38
|
+
* flush-then-late-reply duplicate (2026-08-02, klanker DM, msgs 25843/25844).
|
|
39
|
+
*
|
|
40
|
+
* The quiescence flush used to SEND the composed terminal answer the moment the
|
|
41
|
+
* ~1 s debounce fired. But quiescence is a heuristic, not a completion signal:
|
|
42
|
+
* the model routinely goes quiet for a few seconds BETWEEN its terminal
|
|
43
|
+
* narration and its `reply` tool call (observed gap: 6 s). The flush then posts
|
|
44
|
+
* a PROVISIONAL message that the supersede machinery must claw back — and the
|
|
45
|
+
* claw-back is deliberately conservative (#3429 content gate, #4176 sub-agent
|
|
46
|
+
* liveness hold), so a REWORDED own-answer with a background sub-agent live
|
|
47
|
+
* ships as a visible duplicate even on current main (the accepted residual
|
|
48
|
+
* documented in gateway/subagent-reply-authority.ts).
|
|
49
|
+
*
|
|
50
|
+
* Stage-don't-send removes the provisional send instead of reconciling it:
|
|
51
|
+
* when the quiescence debounce fires, the composed answer is STAGED (held on
|
|
52
|
+
* the still-live turn — the turn is NOT ended, so the typing indicator keeps
|
|
53
|
+
* running) and promoted to a real send only when the completion window closes
|
|
54
|
+
* with no reply:
|
|
55
|
+
*
|
|
56
|
+
* - the model's `reply` lands → the staged text is DISCARDED (fire-time
|
|
57
|
+
* re-verify declines on `replyCalled`) — exactly one message, the canonical
|
|
58
|
+
* reply, on its normal path;
|
|
59
|
+
* - the REAL turn_end lands first → the turn-flush branch at turn_end
|
|
60
|
+
* delivers the captured answer (the pre-PR-A path) — promotion at the true
|
|
61
|
+
* completion signal, usually seconds;
|
|
62
|
+
* - neither arrives within this window (the KNOWN-UNRELIABLE turn_end case
|
|
63
|
+
* PR A was built for) → the stage timer promotes through the same
|
|
64
|
+
* synthetic-turn_end flush path as before.
|
|
65
|
+
*
|
|
66
|
+
* Worst-case added latency for a silent no-op turn whose turn_end never lands
|
|
67
|
+
* is this window (30 s) — still ~5× faster than the ~150 s orphaned-reply
|
|
68
|
+
* backstop PR A replaced, and it buys the hard guarantee that a composing
|
|
69
|
+
* model can no longer race the flush into a duplicate. Env-tunable via
|
|
70
|
+
* SWITCHROOM_ANSWER_STAGE_MS; 0 (or any non-positive value) disables staging
|
|
71
|
+
* and restores the legacy immediate flush.
|
|
72
|
+
*/
|
|
73
|
+
export const ANSWER_STAGE_MS = 30_000
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Resolve the stage window from the environment. Returns a positive integer
|
|
77
|
+
* ms, or 0 when explicitly disabled (non-positive value = legacy immediate
|
|
78
|
+
* flush). Unparseable values fail safe to the default.
|
|
79
|
+
*/
|
|
80
|
+
export function resolveAnswerStageMs(
|
|
81
|
+
env: Record<string, string | undefined>,
|
|
82
|
+
): number {
|
|
83
|
+
const raw = env.SWITCHROOM_ANSWER_STAGE_MS
|
|
84
|
+
if (raw == null || raw.trim() === '') return ANSWER_STAGE_MS
|
|
85
|
+
const n = Number(raw)
|
|
86
|
+
if (!Number.isFinite(n)) return ANSWER_STAGE_MS
|
|
87
|
+
if (n <= 0) return 0
|
|
88
|
+
return Math.floor(n)
|
|
89
|
+
}
|
|
90
|
+
|
|
36
91
|
/**
|
|
37
92
|
* Resolve the debounce window from the environment. Returns a positive integer
|
|
38
93
|
* ms, or 0 when disabled (kill-switch) / unparseable / non-positive. The
|
|
@@ -117,6 +172,17 @@ export interface AnswerReadyFlushDeps<Turn> {
|
|
|
117
172
|
* short-circuits — the exactly-once guarantee.
|
|
118
173
|
*/
|
|
119
174
|
onFlush(turn: Turn): void
|
|
175
|
+
/**
|
|
176
|
+
* Stage-don't-send window (ms) — see {@link ANSWER_STAGE_MS}. When > 0 the
|
|
177
|
+
* quiescence expiry STAGES the answer (turn stays live, typing hold) and
|
|
178
|
+
* arms a promotion timer for this many ms instead of flushing immediately;
|
|
179
|
+
* the promotion re-verifies before delivering, so a `reply` that landed in
|
|
180
|
+
* the window discards the staged text, and a real turn_end that landed first
|
|
181
|
+
* delivered it through the turn-flush branch already (its
|
|
182
|
+
* `endCurrentTurnAtomic` → `clear` cancels the promotion). 0 / undefined =
|
|
183
|
+
* legacy immediate flush at quiescence.
|
|
184
|
+
*/
|
|
185
|
+
stageWindowMs?: number
|
|
120
186
|
/** Injectable timer primitives (default to the globals). */
|
|
121
187
|
setTimeoutFn?: (fn: () => void, ms: number) => FlushTimerHandle
|
|
122
188
|
clearTimeoutFn?: (handle: FlushTimerHandle) => void
|
|
@@ -139,9 +205,14 @@ export interface AnswerReadyFlushDeps<Turn> {
|
|
|
139
205
|
* landed since the arm cancels the flush deterministically), then dispatches
|
|
140
206
|
* exactly one `onFlush`.
|
|
141
207
|
*/
|
|
142
|
-
export class AnswerReadyFlushController<Turn> {
|
|
208
|
+
export class AnswerReadyFlushController<Turn extends object> {
|
|
143
209
|
constructor(private readonly deps: AnswerReadyFlushDeps<Turn>) {}
|
|
144
210
|
|
|
211
|
+
/** Turns whose composed answer is currently STAGED (stage-don't-send): the
|
|
212
|
+
* quiescence debounce fired, but delivery is held for the promotion window.
|
|
213
|
+
* WeakSet so a superseded/ended turn atom can never leak an entry. */
|
|
214
|
+
private readonly staged = new WeakSet<Turn>()
|
|
215
|
+
|
|
145
216
|
private get setTimeoutFn(): (fn: () => void, ms: number) => FlushTimerHandle {
|
|
146
217
|
return this.deps.setTimeoutFn ?? ((fn, ms) => setTimeout(fn, ms))
|
|
147
218
|
}
|
|
@@ -150,9 +221,11 @@ export class AnswerReadyFlushController<Turn> {
|
|
|
150
221
|
return this.deps.clearTimeoutFn ?? ((h) => clearTimeout(h))
|
|
151
222
|
}
|
|
152
223
|
|
|
153
|
-
/** Disarm the flush timer for a turn (idempotent).
|
|
224
|
+
/** Disarm the flush timer for a turn (idempotent). Clears BOTH phases: a
|
|
225
|
+
* pending quiescence debounce or a pending staged promotion. */
|
|
154
226
|
clear(turn: Turn | null): void {
|
|
155
227
|
if (turn == null) return
|
|
228
|
+
this.staged.delete(turn)
|
|
156
229
|
const handle = this.deps.getTimerHandle(turn)
|
|
157
230
|
if (handle != null) {
|
|
158
231
|
this.clearTimeoutFn(handle)
|
|
@@ -160,6 +233,11 @@ export class AnswerReadyFlushController<Turn> {
|
|
|
160
233
|
}
|
|
161
234
|
}
|
|
162
235
|
|
|
236
|
+
/** True IFF `turn`'s composed answer is currently staged (test/diagnostics). */
|
|
237
|
+
isStaged(turn: Turn): boolean {
|
|
238
|
+
return this.staged.has(turn)
|
|
239
|
+
}
|
|
240
|
+
|
|
163
241
|
/** (Re)arm the flush timer for the current turn — the debounce. */
|
|
164
242
|
reset(): void {
|
|
165
243
|
const turn = this.deps.getCurrentTurn()
|
|
@@ -171,7 +249,10 @@ export class AnswerReadyFlushController<Turn> {
|
|
|
171
249
|
this.deps.setTimerHandle(turn, handle)
|
|
172
250
|
}
|
|
173
251
|
|
|
174
|
-
/** Timer-expiry callback. Re-pins the turn,
|
|
252
|
+
/** Timer-expiry callback — BOTH phases share it. Re-pins the turn,
|
|
253
|
+
* re-verifies quiescence, then either STAGES (first fire, window > 0) or
|
|
254
|
+
* delivers (legacy immediate mode, or the staged promotion firing after the
|
|
255
|
+
* completion window closed with no reply). */
|
|
175
256
|
private onExpiry(armedTurn: Turn): void {
|
|
176
257
|
const live = this.deps.getCurrentTurn()
|
|
177
258
|
// Rollover guard: a superseded turn's timer must not fire against a fresh atom.
|
|
@@ -179,9 +260,40 @@ export class AnswerReadyFlushController<Turn> {
|
|
|
179
260
|
this.deps.setTimerHandle(live, null)
|
|
180
261
|
// Fire-time re-verification: a tool that started (or a reply that landed)
|
|
181
262
|
// since the arm deterministically cancels the flush even if the explicit
|
|
182
|
-
// disarm was somehow missed.
|
|
183
|
-
|
|
184
|
-
|
|
263
|
+
// disarm was somehow missed. On a staged promotion this is the DISCARD
|
|
264
|
+
// path: the reply landed inside the window, so the staged provisional text
|
|
265
|
+
// is dropped and the canonical reply is the one message the user sees.
|
|
266
|
+
if (!shouldArmAnswerReadyFlush(this.deps.getArmInput(live))) {
|
|
267
|
+
if (this.staged.delete(live)) {
|
|
268
|
+
this.deps.log?.(
|
|
269
|
+
'answer-ready stage discarded — reply/tool activity landed inside the completion window',
|
|
270
|
+
)
|
|
271
|
+
}
|
|
272
|
+
return
|
|
273
|
+
}
|
|
274
|
+
const stageMs = this.deps.stageWindowMs ?? 0
|
|
275
|
+
if (stageMs > 0 && !this.staged.has(live)) {
|
|
276
|
+
// STAGE-DON'T-SEND (see ANSWER_STAGE_MS): hold the composed answer on
|
|
277
|
+
// the still-live turn instead of posting a provisional message. The turn
|
|
278
|
+
// is NOT ended, so the typing indicator keeps running (the "typing
|
|
279
|
+
// hold") and a real turn_end landing first delivers through the normal
|
|
280
|
+
// turn-flush branch (endCurrentTurnAtomic's `clear` cancels this timer).
|
|
281
|
+
this.staged.add(live)
|
|
282
|
+
this.deps.log?.(
|
|
283
|
+
`answer-ready quiescence — staging composed terminal answer ` +
|
|
284
|
+
`(promotes in ${stageMs}ms unless the reply lands or the turn completes)`,
|
|
285
|
+
)
|
|
286
|
+
const handle = this.setTimeoutFn(() => this.onExpiry(live), stageMs)
|
|
287
|
+
this.deps.setTimerHandle(live, handle)
|
|
288
|
+
return
|
|
289
|
+
}
|
|
290
|
+
if (this.staged.delete(live)) {
|
|
291
|
+
this.deps.log?.(
|
|
292
|
+
'answer-ready stage promoted — completion window closed with no reply; delivering composed terminal answer',
|
|
293
|
+
)
|
|
294
|
+
} else {
|
|
295
|
+
this.deps.log?.('answer-ready quiescence flush — delivering composed terminal answer')
|
|
296
|
+
}
|
|
185
297
|
this.deps.onFlush(live)
|
|
186
298
|
}
|
|
187
299
|
}
|