switchroom 0.19.42 → 0.19.44
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 +4 -1
- package/dist/auth-broker/index.js +284 -124
- package/dist/cli/notion-write-pretool.mjs +4 -1
- package/dist/cli/switchroom.js +4094 -2711
- package/dist/host-control/main.js +472 -155
- package/dist/vault/approvals/kernel-server.js +231 -71
- package/dist/vault/broker/server.js +293 -133
- package/package.json +3 -3
- package/profiles/_base/start.sh.hbs +93 -8
- package/telegram-plugin/bridge/bridge.ts +1 -1
- package/telegram-plugin/card-layout.ts +63 -1
- package/telegram-plugin/dist/bridge/bridge.js +4 -1
- package/telegram-plugin/dist/gateway/gateway.js +1682 -936
- package/telegram-plugin/dist/server.js +5 -2
- package/telegram-plugin/flood-429-ledger.ts +5 -3
- package/telegram-plugin/flood-circuit-breaker.ts +11 -3
- package/telegram-plugin/format.ts +223 -13
- package/telegram-plugin/gateway/boot-card.ts +7 -2
- package/telegram-plugin/gateway/flood-reply-queue.ts +5 -0
- package/telegram-plugin/gateway/gateway.ts +49 -51
- package/telegram-plugin/gateway/handback-orphan-recovery.ts +69 -0
- package/telegram-plugin/gateway/handback-preturn-signal.ts +170 -32
- package/telegram-plugin/gateway/ipc-protocol.ts +31 -3
- package/telegram-plugin/gateway/ipc-server.ts +13 -4
- package/telegram-plugin/gateway/obligation-store.ts +55 -0
- package/telegram-plugin/gateway/outbound-send-path.ts +127 -11
- package/telegram-plugin/gateway/outbox-sweep.ts +371 -61
- package/telegram-plugin/gateway/rollout-status-edit.ts +175 -0
- package/telegram-plugin/gateway/stream-render.ts +5 -0
- package/telegram-plugin/gateway/update-announce.ts +11 -4
- package/telegram-plugin/hooks/audience-classify.d.mts +50 -0
- package/telegram-plugin/hooks/audience-classify.mjs +364 -0
- package/telegram-plugin/hooks/silent-end-interrupt-stop.mjs +86 -3
- package/telegram-plugin/hooks/silent-end-scan.mjs +80 -4
- package/telegram-plugin/outbox.ts +103 -2
- package/telegram-plugin/render/rich-render.ts +10 -2
- package/telegram-plugin/reply-quote.ts +150 -0
- package/telegram-plugin/retry-api-call.ts +254 -11
- package/telegram-plugin/shared/bot-runtime.ts +69 -34
- package/telegram-plugin/shared/gw-trace-gate.ts +14 -2
- package/telegram-plugin/silent-end.ts +34 -2
- package/telegram-plugin/status-no-truncate.ts +31 -16
- package/telegram-plugin/stream-controller.ts +44 -9
- package/telegram-plugin/stream-reply-handler.ts +5 -3
- package/telegram-plugin/tests/boot-card-render.test.ts +2 -1
- package/telegram-plugin/tests/card-budget-never-overflows.test.ts +165 -0
- package/telegram-plugin/tests/card-hard-truncate-entity-safe.test.ts +153 -0
- package/telegram-plugin/tests/card-variants.golden.txt +9 -9
- package/telegram-plugin/tests/flood-reply-queue.test.ts +89 -4
- package/telegram-plugin/tests/format-consistency.test.ts +160 -14
- package/telegram-plugin/tests/handback-orphan-recovery.test.ts +131 -0
- package/telegram-plugin/tests/handback-preturn-signal.test.ts +212 -17
- package/telegram-plugin/tests/nested-indent-idiom.test.ts +162 -0
- package/telegram-plugin/tests/nested-prefix-indent.test.ts +115 -0
- package/telegram-plugin/tests/no-robust-api-call-factory.test.ts +62 -0
- package/telegram-plugin/tests/obligation-store.test.ts +51 -0
- package/telegram-plugin/tests/outbox-audience-3865.test.ts +579 -0
- package/telegram-plugin/tests/outbox-provenance-4141.test.ts +1126 -0
- package/telegram-plugin/tests/outbox-sweep-single-flight.test.ts +138 -0
- package/telegram-plugin/tests/pinned-card-collapse.test.ts +12 -10
- package/telegram-plugin/tests/plain-fallback-4096-cap.test.ts +509 -0
- package/telegram-plugin/tests/reply-quote-wire.test.ts +433 -0
- package/telegram-plugin/tests/retry-grammy-http-error.test.ts +404 -0
- package/telegram-plugin/tests/rollout-narration-edit-socket.test.ts +170 -0
- package/telegram-plugin/tests/rollout-status-edit-retry-policy.test.ts +366 -0
- package/telegram-plugin/tests/rollout-status-edit.test.ts +140 -0
- package/telegram-plugin/tests/rollout-status-wiring.test.ts +40 -7
- package/telegram-plugin/tests/tg-post-logger-error-shape.test.ts +4 -0
- package/telegram-plugin/tests/tg-post-retry-attribution.test.ts +196 -0
- package/telegram-plugin/tests/tool-activity-summary.test.ts +23 -17
- package/telegram-plugin/tool-activity-summary.ts +58 -30
- package/telegram-plugin/uat/scenarios/jtbd-foreground-subagent-activity-dm.test.ts +3 -2
- package/vendor/hindsight-memory/scripts/lib/config.py +15 -0
- package/vendor/hindsight-memory/scripts/tests/test_retain_provenance_tag.py +135 -0
- package/vendor/hindsight-memory/settings.json +1 -1
|
@@ -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, 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, 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();
|
|
@@ -4551,6 +4551,7 @@ var init_schema = __esm(() => {
|
|
|
4551
4551
|
}).optional();
|
|
4552
4552
|
ObservationScopesSchema = exports_external.enum(OBSERVATION_SCOPES).optional().describe("Operator PIN for the per-row observation scope, overriding the " + 'default `curated` strategy (see docs/configuration.md). "shared" ' + "forces Hindsight's consolidation to write EVERY observation into ONE " + "global untagged scope — what several agents pooling one bank want so " + "their observations merge rather than sitting in parallel silos. " + '"combined" is the pin form of opting out (restores the pre-#4035 ' + "engine default). UNSET does NOT mean 'nothing on the wire': the " + "`curated` strategy still computes a scope per retain. Applies to " + "every retain path (Stop hook, " + "sidechain, boot reconcile, queue drain, backfill, session-handoff " + "mirror) and is carried on the queued payload, so a retain that fails " + "now and drains later still lands in this scope. Accepted values: " + `${OBSERVATION_SCOPES.join(", ")}. ` + "Cascade: override (per-agent wins over default).");
|
|
4553
4553
|
ObservationScopeStrategySchema = exports_external.enum(OBSERVATION_SCOPE_STRATEGIES).optional().describe("Per-retain strategy that decides how the observation scope is " + 'computed when no `observation_scopes` pin is set. "curated" ' + "(the default since #4035) strips volatile per-session provenance " + "tags from each retain's consolidation scope — keeping the stable " + "semantic ones on the source fact — so an agent's observations dedup " + "and merge across sessions instead of pocketing one-per-session. " + '"shared" sends every retain to the one global untagged scope. ' + '"combined" / "off" opt OUT: no per-row scope goes on the wire, ' + "restoring the pre-feature engine default (byte-identical to an " + "unconfigured client). OMITTED BY DEFAULT: unset leaves the plugin's " + "own default (`curated`) in force. A manual `observation_scopes` pin " + "wins over this strategy. Accepted values: " + `${OBSERVATION_SCOPE_STRATEGIES.join(", ")}. ` + "Cascade: override (per-agent wins over default).");
|
|
4554
|
+
AntiConfabulationDirectiveSchema = exports_external.union([exports_external.boolean(), exports_external.string().min(1)]).optional().describe("The seeded anti-confabulation directive: reflect has no relevance " + "floor (`min_scores` is a /recall-only parameter), so a bank holding " + "nothing relevant still yields a confident answer, and a question that " + "presupposes a decision reliably produces one. Directives ARE applied " + "during reflect, so this is the lever. Unset or true (the default) " + "seeds and maintains switchroom's own text; false disables seeding and " + "leaves any existing directive untouched; a string is operator-authored " + "text that wins outright. Switchroom only ever upgrades directive text " + "byte-equal to a default it shipped, so editing the directive in the " + "bank is also a permanent override. " + "Cascade: override (per-agent wins over default).");
|
|
4554
4555
|
AgentMemorySchema = exports_external.object({
|
|
4555
4556
|
collection: exports_external.string().describe("Hindsight collection name for this agent"),
|
|
4556
4557
|
auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
|
|
@@ -4586,6 +4587,7 @@ var init_schema = __esm(() => {
|
|
|
4586
4587
|
empathy: exports_external.number().int().min(1).max(5).optional().describe("How much the bank weights emotional/relational context (1-5; engine default 3).")
|
|
4587
4588
|
}).optional().describe("Personality traits (1-5 each) steering how this bank frames recall, " + "reflect, and observation synthesis — a coach leans empathy-high, a " + "lawyer/analyst leans skepticism/literalism-high. Maps to the engine's " + "flat `disposition_skepticism`/`_literalism`/`_empathy` fields. " + "Cascade: per-key merge (an agent overrides individual traits and " + "inherits the rest, matching `recall`)."),
|
|
4588
4589
|
directive_capture_nudge: exports_external.boolean().optional().describe("Deterministic directive-capture nudge (issue #2848 Stage B). When " + "on (switchroom default true — Stage A measured a ~55% miss rate on " + "durable corrections), the auto-recall hook regex-detects correction " + '/ standing-rule-shaped inbound ("always/never …", "from now on …", ' + `"stop doing …", a stated preference, "that's wrong, it's …") and ` + "appends a terse advisory to the turn's context telling the model to " + "persist the rule with mcp__hindsight__create_directive if it IS " + "durable. Detection is pure regex — the model does the judgment " + "in-session and calls create_directive itself (no model callsite, no " + "silent hook-side write). Set false to disable per-agent. " + "Cascade: override (per-agent wins over default)."),
|
|
4590
|
+
anti_confabulation_directive: AntiConfabulationDirectiveSchema,
|
|
4589
4591
|
observation_scopes: ObservationScopesSchema,
|
|
4590
4592
|
observation_scope_strategy: ObservationScopeStrategySchema,
|
|
4591
4593
|
recall: exports_external.object({
|
|
@@ -4856,7 +4858,7 @@ var init_schema = __esm(() => {
|
|
|
4856
4858
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
|
|
4857
4859
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
|
|
4858
4860
|
}).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."),
|
|
4859
|
-
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,
|
|
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).")
|
|
4860
4862
|
});
|
|
4861
4863
|
MicrosoftWorkspaceConfigSchema = exports_external.object({
|
|
4862
4864
|
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)."),
|
|
@@ -4990,6 +4992,7 @@ var init_schema = __esm(() => {
|
|
|
4990
4992
|
isolation: exports_external.enum(["default", "strict"]).optional(),
|
|
4991
4993
|
profile: exports_external.string().optional(),
|
|
4992
4994
|
directive_capture_nudge: exports_external.boolean().optional(),
|
|
4995
|
+
anti_confabulation_directive: AntiConfabulationDirectiveSchema,
|
|
4993
4996
|
observation_scopes: ObservationScopesSchema,
|
|
4994
4997
|
observation_scope_strategy: ObservationScopeStrategySchema,
|
|
4995
4998
|
recall: exports_external.object({
|
|
@@ -12763,8 +12766,8 @@ var require_dist = __commonJS((exports) => {
|
|
|
12763
12766
|
});
|
|
12764
12767
|
|
|
12765
12768
|
// src/config/paths.ts
|
|
12766
|
-
import { existsSync } from "node:fs";
|
|
12767
|
-
import { resolve } from "node:path";
|
|
12769
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
12770
|
+
import { resolve as resolve2 } from "node:path";
|
|
12768
12771
|
function home() {
|
|
12769
12772
|
return process.env.HOME ?? "/root";
|
|
12770
12773
|
}
|
|
@@ -12779,12 +12782,12 @@ function resolveDualPath(pathStr) {
|
|
|
12779
12782
|
const h = home();
|
|
12780
12783
|
if (pathStr.startsWith("~/")) {
|
|
12781
12784
|
const rest = pathStr.slice(2);
|
|
12782
|
-
const absolute =
|
|
12785
|
+
const absolute = resolve2(h, rest);
|
|
12783
12786
|
if (rest.startsWith(`${DEFAULT_STATE_DIR}/`)) {
|
|
12784
12787
|
const frag = rest.slice(DEFAULT_STATE_DIR.length + 1);
|
|
12785
|
-
if (!
|
|
12786
|
-
const legacy =
|
|
12787
|
-
if (
|
|
12788
|
+
if (!existsSync2(absolute)) {
|
|
12789
|
+
const legacy = resolve2(h, LEGACY_STATE_DIR, frag);
|
|
12790
|
+
if (existsSync2(legacy)) {
|
|
12788
12791
|
warnLegacyStateOnce(legacy);
|
|
12789
12792
|
return legacy;
|
|
12790
12793
|
}
|
|
@@ -12792,7 +12795,7 @@ function resolveDualPath(pathStr) {
|
|
|
12792
12795
|
}
|
|
12793
12796
|
return absolute;
|
|
12794
12797
|
}
|
|
12795
|
-
return
|
|
12798
|
+
return resolve2(pathStr);
|
|
12796
12799
|
}
|
|
12797
12800
|
var DEFAULT_STATE_DIR = ".switchroom", LEGACY_STATE_DIR = ".clerk", _legacyStateWarned = false;
|
|
12798
12801
|
var init_paths = () => {};
|
|
@@ -12809,8 +12812,8 @@ var init_overlay_schema = __esm(() => {
|
|
|
12809
12812
|
});
|
|
12810
12813
|
|
|
12811
12814
|
// src/config/overlay-loader.ts
|
|
12812
|
-
import { existsSync as
|
|
12813
|
-
import { basename, resolve as
|
|
12815
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, readdirSync, statSync } from "node:fs";
|
|
12816
|
+
import { basename, resolve as resolve3 } from "node:path";
|
|
12814
12817
|
function deriveOverlayTitle(raw, fileName) {
|
|
12815
12818
|
const titleFromComment = raw.match(/^#[^\S\n]*name:[^\S\n]*(\S.*?)[^\S\n]*$/m)?.[1];
|
|
12816
12819
|
if (titleFromComment)
|
|
@@ -12822,10 +12825,10 @@ function deriveOverlayTitle(raw, fileName) {
|
|
|
12822
12825
|
}
|
|
12823
12826
|
function overlayDirFor(agentName, subdir) {
|
|
12824
12827
|
const base = resolveDualPath(`~/.switchroom/agents/${agentName}/${subdir}`);
|
|
12825
|
-
return
|
|
12828
|
+
return resolve3(base);
|
|
12826
12829
|
}
|
|
12827
12830
|
function listYamlFiles(dir) {
|
|
12828
|
-
if (!
|
|
12831
|
+
if (!existsSync3(dir))
|
|
12829
12832
|
return [];
|
|
12830
12833
|
let entries;
|
|
12831
12834
|
try {
|
|
@@ -12837,7 +12840,7 @@ function listYamlFiles(dir) {
|
|
|
12837
12840
|
for (const name of entries) {
|
|
12838
12841
|
if (!/\.ya?ml$/i.test(name))
|
|
12839
12842
|
continue;
|
|
12840
|
-
const full =
|
|
12843
|
+
const full = resolve3(dir, name);
|
|
12841
12844
|
try {
|
|
12842
12845
|
if (statSync(full).isFile())
|
|
12843
12846
|
out.push(full);
|
|
@@ -12873,7 +12876,7 @@ function applyAgentOverlays(config) {
|
|
|
12873
12876
|
const merged = [...agentCfg.schedule ?? []];
|
|
12874
12877
|
for (const file of files) {
|
|
12875
12878
|
try {
|
|
12876
|
-
const raw =
|
|
12879
|
+
const raw = readFileSync2(file, "utf-8");
|
|
12877
12880
|
const parsed = import_yaml.parse(raw);
|
|
12878
12881
|
const doc = OverlayDocSchema.parse(parsed);
|
|
12879
12882
|
const title = deriveOverlayTitle(raw, basename(file));
|
|
@@ -12914,7 +12917,7 @@ function applyAgentOverlays(config) {
|
|
|
12914
12917
|
const seen = new Set(merged);
|
|
12915
12918
|
for (const file of skillFiles) {
|
|
12916
12919
|
try {
|
|
12917
|
-
const raw =
|
|
12920
|
+
const raw = readFileSync2(file, "utf-8");
|
|
12918
12921
|
const parsed = import_yaml.parse(raw);
|
|
12919
12922
|
const doc = OverlayDocSchema.parse(parsed);
|
|
12920
12923
|
for (const skillName of doc.skills ?? []) {
|
|
@@ -12989,9 +12992,9 @@ __export(exports_loader, {
|
|
|
12989
12992
|
findConfigFile: () => findConfigFile,
|
|
12990
12993
|
ConfigError: () => ConfigError
|
|
12991
12994
|
});
|
|
12992
|
-
import { readFileSync as
|
|
12995
|
+
import { readFileSync as readFileSync3, existsSync as existsSync4 } from "node:fs";
|
|
12993
12996
|
import { homedir } from "node:os";
|
|
12994
|
-
import { resolve as
|
|
12997
|
+
import { resolve as resolve4 } from "node:path";
|
|
12995
12998
|
function formatZodErrors(error) {
|
|
12996
12999
|
return error.errors.map((e) => {
|
|
12997
13000
|
const path = e.path.join(".");
|
|
@@ -13039,24 +13042,24 @@ function coerceLegacyGoogleWorkspaceKeys(parsed, filePath) {
|
|
|
13039
13042
|
function findConfigFile(startDir) {
|
|
13040
13043
|
const envPath = process.env.SWITCHROOM_CONFIG;
|
|
13041
13044
|
const home2 = homedir();
|
|
13042
|
-
const userDir =
|
|
13045
|
+
const userDir = resolve4(home2, ".switchroom");
|
|
13043
13046
|
const searchPaths = [
|
|
13044
|
-
envPath ?
|
|
13045
|
-
startDir ?
|
|
13046
|
-
startDir ?
|
|
13047
|
-
startDir ?
|
|
13048
|
-
startDir ?
|
|
13049
|
-
|
|
13050
|
-
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
|
|
13047
|
+
envPath ? resolve4(envPath) : null,
|
|
13048
|
+
startDir ? resolve4(startDir, "switchroom.yaml") : null,
|
|
13049
|
+
startDir ? resolve4(startDir, "switchroom.yml") : null,
|
|
13050
|
+
startDir ? resolve4(startDir, "clerk.yaml") : null,
|
|
13051
|
+
startDir ? resolve4(startDir, "clerk.yml") : null,
|
|
13052
|
+
resolve4(process.cwd(), "switchroom.yaml"),
|
|
13053
|
+
resolve4(process.cwd(), "switchroom.yml"),
|
|
13054
|
+
resolve4(process.cwd(), "clerk.yaml"),
|
|
13055
|
+
resolve4(process.cwd(), "clerk.yml"),
|
|
13056
|
+
resolve4(userDir, "switchroom.yaml"),
|
|
13057
|
+
resolve4(userDir, "switchroom.yml"),
|
|
13058
|
+
resolve4(userDir, "clerk.yaml"),
|
|
13059
|
+
resolve4(userDir, "clerk.yml")
|
|
13057
13060
|
].filter(Boolean);
|
|
13058
13061
|
for (const path of searchPaths) {
|
|
13059
|
-
if (
|
|
13062
|
+
if (existsSync4(path)) {
|
|
13060
13063
|
return path;
|
|
13061
13064
|
}
|
|
13062
13065
|
}
|
|
@@ -13064,12 +13067,12 @@ function findConfigFile(startDir) {
|
|
|
13064
13067
|
}
|
|
13065
13068
|
function loadConfig(configPath) {
|
|
13066
13069
|
const filePath = configPath ?? findConfigFile();
|
|
13067
|
-
if (!
|
|
13070
|
+
if (!existsSync4(filePath)) {
|
|
13068
13071
|
throw new ConfigError(`Config file not found: ${filePath}`);
|
|
13069
13072
|
}
|
|
13070
13073
|
let raw;
|
|
13071
13074
|
try {
|
|
13072
|
-
raw =
|
|
13075
|
+
raw = readFileSync3(filePath, "utf-8");
|
|
13073
13076
|
} catch (err) {
|
|
13074
13077
|
throw new ConfigError(`Failed to read config file: ${filePath}`, [
|
|
13075
13078
|
` ${err.message}`
|
|
@@ -18783,7 +18786,7 @@ var init_resolver = __esm(() => {
|
|
|
18783
18786
|
// src/vault/approvals/kernel-server.ts
|
|
18784
18787
|
init_protocol();
|
|
18785
18788
|
import * as net from "node:net";
|
|
18786
|
-
import { mkdirSync as mkdirSync2, chmodSync, chownSync, existsSync as
|
|
18789
|
+
import { mkdirSync as mkdirSync2, chmodSync, chownSync, existsSync as existsSync6, unlinkSync, readdirSync as readdirSync3, statSync as statSync3 } from "node:fs";
|
|
18787
18790
|
import { dirname as dirname2, resolve as resolve6, basename as basename2 } from "node:path";
|
|
18788
18791
|
import { Database } from "bun:sqlite";
|
|
18789
18792
|
|
|
@@ -19221,9 +19224,66 @@ function getNonce(db, request_id) {
|
|
|
19221
19224
|
init_schema();
|
|
19222
19225
|
|
|
19223
19226
|
// src/agents/scaffold.ts
|
|
19224
|
-
import { dirname, isAbsolute, join as join4, relative, resolve as resolve5 } from "node:path";
|
|
19225
19227
|
init_atomic();
|
|
19226
19228
|
|
|
19229
|
+
// src/util/shipped-assets.ts
|
|
19230
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
19231
|
+
import { dirname, resolve } from "node:path";
|
|
19232
|
+
var FHS_SHARE_ROOTS = [
|
|
19233
|
+
"/usr/local/share/switchroom",
|
|
19234
|
+
"/usr/share/switchroom"
|
|
19235
|
+
];
|
|
19236
|
+
var PROFILES_ASSET = {
|
|
19237
|
+
asset: "profiles",
|
|
19238
|
+
envVar: "SWITCHROOM_PROFILES_ROOT"
|
|
19239
|
+
};
|
|
19240
|
+
function orderedCandidates(spec, probe) {
|
|
19241
|
+
const out = [];
|
|
19242
|
+
const push = (path, source) => {
|
|
19243
|
+
if (!out.some((c) => c.path === path))
|
|
19244
|
+
out.push({ path, source });
|
|
19245
|
+
};
|
|
19246
|
+
if (probe.bundleDir) {
|
|
19247
|
+
push(resolve(probe.bundleDir, "../..", spec.asset), "npm");
|
|
19248
|
+
push(resolve(probe.bundleDir, spec.asset), "image");
|
|
19249
|
+
}
|
|
19250
|
+
if (probe.execPath) {
|
|
19251
|
+
push(resolve(dirname(probe.execPath), "../share/switchroom", spec.asset), "sea-sibling");
|
|
19252
|
+
}
|
|
19253
|
+
for (const root of FHS_SHARE_ROOTS) {
|
|
19254
|
+
push(resolve(root, spec.asset), "fhs");
|
|
19255
|
+
}
|
|
19256
|
+
return out;
|
|
19257
|
+
}
|
|
19258
|
+
function resolveShippedAsset(spec, probe) {
|
|
19259
|
+
const env = probe.env ?? process.env;
|
|
19260
|
+
const override = env[spec.envVar]?.trim();
|
|
19261
|
+
if (override) {
|
|
19262
|
+
const path = canonicalise(resolve(override), probe);
|
|
19263
|
+
return { path, candidates: [path], source: "env" };
|
|
19264
|
+
}
|
|
19265
|
+
const exists = probe.exists ?? existsSync;
|
|
19266
|
+
const candidates = orderedCandidates(spec, probe);
|
|
19267
|
+
for (const c of candidates) {
|
|
19268
|
+
if (exists(c.path)) {
|
|
19269
|
+
return {
|
|
19270
|
+
path: canonicalise(c.path, probe),
|
|
19271
|
+
candidates: candidates.map((x) => x.path),
|
|
19272
|
+
source: c.source
|
|
19273
|
+
};
|
|
19274
|
+
}
|
|
19275
|
+
}
|
|
19276
|
+
return { path: null, candidates: candidates.map((x) => x.path), source: "none" };
|
|
19277
|
+
}
|
|
19278
|
+
function canonicalise(path, probe) {
|
|
19279
|
+
const realpath = probe.realpath ?? realpathSync;
|
|
19280
|
+
try {
|
|
19281
|
+
return realpath(path);
|
|
19282
|
+
} catch {
|
|
19283
|
+
return path;
|
|
19284
|
+
}
|
|
19285
|
+
}
|
|
19286
|
+
|
|
19227
19287
|
// src/agents/agent-uid.ts
|
|
19228
19288
|
init_peercred();
|
|
19229
19289
|
import { createHash } from "node:crypto";
|
|
@@ -19282,37 +19342,29 @@ var AUDIT_ROOT = join(homedir2(), ".switchroom", "audit");
|
|
|
19282
19342
|
|
|
19283
19343
|
// src/agents/profiles.ts
|
|
19284
19344
|
var import_handlebars = __toESM(require_lib(), 1);
|
|
19285
|
-
import { readFileSync as
|
|
19286
|
-
import { resolve as
|
|
19287
|
-
function
|
|
19288
|
-
|
|
19289
|
-
|
|
19290
|
-
|
|
19291
|
-
}
|
|
19292
|
-
const candidates = [
|
|
19293
|
-
resolve4(import.meta.dirname, "../../profiles"),
|
|
19294
|
-
resolve4(import.meta.dirname, "profiles")
|
|
19295
|
-
];
|
|
19296
|
-
for (const candidate of candidates) {
|
|
19297
|
-
if (existsSync4(candidate)) {
|
|
19298
|
-
return candidate;
|
|
19299
|
-
}
|
|
19300
|
-
}
|
|
19301
|
-
return candidates[0];
|
|
19345
|
+
import { readFileSync as readFileSync4, writeFileSync, existsSync as existsSync5, readdirSync as readdirSync2, statSync as statSync2, copyFileSync, mkdirSync, realpathSync as realpathSync2 } from "node:fs";
|
|
19346
|
+
import { resolve as resolve5, join as join2, sep as pathSep } from "node:path";
|
|
19347
|
+
function resolveProfilesRootDetailed() {
|
|
19348
|
+
return resolveShippedAsset(PROFILES_ASSET, {
|
|
19349
|
+
bundleDir: import.meta.dirname,
|
|
19350
|
+
execPath: process.execPath
|
|
19351
|
+
});
|
|
19302
19352
|
}
|
|
19303
|
-
var
|
|
19353
|
+
var PROFILES_RESOLUTION = resolveProfilesRootDetailed();
|
|
19354
|
+
var PROFILES_ROOT = PROFILES_RESOLUTION.path ?? PROFILES_RESOLUTION.candidates[0];
|
|
19355
|
+
var PROFILES_ROOT_SEARCH = PROFILES_RESOLUTION.candidates;
|
|
19304
19356
|
import_handlebars.default.registerHelper("json", (value) => {
|
|
19305
19357
|
return new import_handlebars.default.SafeString(JSON.stringify(value, null, 2));
|
|
19306
19358
|
});
|
|
19307
19359
|
import_handlebars.default.registerHelper("isNumber", (value) => {
|
|
19308
19360
|
return typeof value === "number" && Number.isFinite(value);
|
|
19309
19361
|
});
|
|
19310
|
-
var SHARED_FRAGMENTS_DIR =
|
|
19362
|
+
var SHARED_FRAGMENTS_DIR = resolve5(PROFILES_ROOT, "_shared");
|
|
19311
19363
|
var SHARED_FRAGMENTS = ["vault-protocol", "agent-self-service", "execution-discipline", "reply-discipline", "dev-protocol"];
|
|
19312
19364
|
for (const name of SHARED_FRAGMENTS) {
|
|
19313
19365
|
const fragPath = join2(SHARED_FRAGMENTS_DIR, `${name}.md.hbs`);
|
|
19314
|
-
if (
|
|
19315
|
-
import_handlebars.default.registerPartial(name,
|
|
19366
|
+
if (existsSync5(fragPath)) {
|
|
19367
|
+
import_handlebars.default.registerPartial(name, readFileSync4(fragPath, "utf-8"));
|
|
19316
19368
|
}
|
|
19317
19369
|
}
|
|
19318
19370
|
|
|
@@ -19413,7 +19465,9 @@ var HINDSIGHT_DEFAULT_RECALL_MAX_CONCURRENT = 8;
|
|
|
19413
19465
|
var HINDSIGHT_DEFAULT_REFLECT_WALL_TIMEOUT_S = 600;
|
|
19414
19466
|
var HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_MEMORIES_PER_ROUND = 250;
|
|
19415
19467
|
var HINDSIGHT_DEFAULT_CONSOLIDATION_SLOT_LIMIT = 6;
|
|
19416
|
-
var
|
|
19468
|
+
var HINDSIGHT_DEFAULT_CONSOLIDATION_RESERVED_SLOTS = 1;
|
|
19469
|
+
var HINDSIGHT_DEFAULT_GRAPH_SEED_MIN_SIMILARITY = 0.3;
|
|
19470
|
+
var HINDSIGHT_DEFAULT_LLM_SUPPORTS_MAX_ITEMS = "false";
|
|
19417
19471
|
var HINDSIGHT_DEFAULT_RECENCY_DECAY_FUNCTION = "exponential";
|
|
19418
19472
|
var HINDSIGHT_DEFAULT_RECENCY_DECAY_HALFLIFE_DAYS = 30;
|
|
19419
19473
|
var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
@@ -19459,8 +19513,8 @@ var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
|
19459
19513
|
String(HINDSIGHT_DEFAULT_REFLECT_WALL_TIMEOUT_S)
|
|
19460
19514
|
],
|
|
19461
19515
|
[
|
|
19462
|
-
"
|
|
19463
|
-
String(
|
|
19516
|
+
"HINDSIGHT_API_WORKER_CONSOLIDATION_RESERVED_SLOTS",
|
|
19517
|
+
String(HINDSIGHT_DEFAULT_CONSOLIDATION_RESERVED_SLOTS)
|
|
19464
19518
|
],
|
|
19465
19519
|
[
|
|
19466
19520
|
"HINDSIGHT_API_WORKER_CONSOLIDATION_SLOT_LIMIT",
|
|
@@ -19477,6 +19531,10 @@ var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
|
19477
19531
|
[
|
|
19478
19532
|
"HINDSIGHT_API_RECENCY_DECAY_HALFLIFE_DAYS",
|
|
19479
19533
|
String(HINDSIGHT_DEFAULT_RECENCY_DECAY_HALFLIFE_DAYS)
|
|
19534
|
+
],
|
|
19535
|
+
[
|
|
19536
|
+
"HINDSIGHT_API_GRAPH_SEED_MIN_SIMILARITY",
|
|
19537
|
+
String(HINDSIGHT_DEFAULT_GRAPH_SEED_MIN_SIMILARITY)
|
|
19480
19538
|
]
|
|
19481
19539
|
];
|
|
19482
19540
|
var HINDSIGHT_PERF_DEFAULTS_GPU = [
|
|
@@ -19497,22 +19555,42 @@ var HINDSIGHT_PERF_DEFAULTS_LOCAL_LLM = [
|
|
|
19497
19555
|
String(HINDSIGHT_DEFAULT_CONSOLIDATION_LLM_MAX_CONCURRENT)
|
|
19498
19556
|
],
|
|
19499
19557
|
["HINDSIGHT_API_LLM_STRICT_SCHEMA", HINDSIGHT_DEFAULT_LLM_STRICT_SCHEMA],
|
|
19500
|
-
["HINDSIGHT_API_LLM_MAX_RETRIES", String(HINDSIGHT_DEFAULT_LLM_MAX_RETRIES)]
|
|
19558
|
+
["HINDSIGHT_API_LLM_MAX_RETRIES", String(HINDSIGHT_DEFAULT_LLM_MAX_RETRIES)],
|
|
19559
|
+
["HINDSIGHT_API_LLM_SUPPORTS_MAX_ITEMS", HINDSIGHT_DEFAULT_LLM_SUPPORTS_MAX_ITEMS]
|
|
19501
19560
|
];
|
|
19502
19561
|
var HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS = new Set([
|
|
19503
19562
|
"HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY",
|
|
19504
19563
|
"HINDSIGHT_CE_DECISIVE_RELATIVE_GAP",
|
|
19505
19564
|
"HINDSIGHT_API_RECENCY_DECAY_LINEAR_WINDOW_DAYS",
|
|
19506
19565
|
"HINDSIGHT_API_WORKER_MAX_SLOTS",
|
|
19507
|
-
"
|
|
19566
|
+
"HINDSIGHT_API_WORKER_RETAIN_RESERVED_SLOTS",
|
|
19567
|
+
"HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY",
|
|
19568
|
+
"HINDSIGHT_MCP_RECALL_BUDGET_MODE",
|
|
19569
|
+
"HINDSIGHT_API_LLM_TEMPERATURE_REFLECT",
|
|
19570
|
+
"HINDSIGHT_API_RETAIN_WALL_TIMEOUT",
|
|
19571
|
+
"HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT"
|
|
19508
19572
|
]);
|
|
19573
|
+
var HINDSIGHT_WORKER_SLOT_TYPES = [
|
|
19574
|
+
"consolidation",
|
|
19575
|
+
"file_convert_retain",
|
|
19576
|
+
"graph_maintenance",
|
|
19577
|
+
"import_documents",
|
|
19578
|
+
"refresh_mental_model",
|
|
19579
|
+
"retain"
|
|
19580
|
+
];
|
|
19581
|
+
var HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES = new Map(HINDSIGHT_WORKER_SLOT_TYPES.map((type) => [
|
|
19582
|
+
`HINDSIGHT_API_WORKER_${type.toUpperCase()}_MAX_SLOTS`,
|
|
19583
|
+
`HINDSIGHT_API_WORKER_${type.toUpperCase()}_RESERVED_SLOTS`
|
|
19584
|
+
]));
|
|
19509
19585
|
var HINDSIGHT_PERF_ENV_KEYS = new Set([
|
|
19510
19586
|
...[
|
|
19511
19587
|
...HINDSIGHT_PERF_DEFAULTS_UNGATED,
|
|
19512
19588
|
...HINDSIGHT_PERF_DEFAULTS_GPU,
|
|
19513
19589
|
...HINDSIGHT_PERF_DEFAULTS_LOCAL_LLM
|
|
19514
19590
|
].map(([k]) => k),
|
|
19515
|
-
...HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS
|
|
19591
|
+
...HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS,
|
|
19592
|
+
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.keys(),
|
|
19593
|
+
...HINDSIGHT_WORKER_RESERVED_SLOT_ALIASES.values()
|
|
19516
19594
|
]);
|
|
19517
19595
|
|
|
19518
19596
|
// src/setup/hindsight-context-budget.ts
|
|
@@ -19585,6 +19663,15 @@ var DEFAULT_RETAIN_MISSION = `Extract durable facts that will still be true and
|
|
|
19585
19663
|
` + `- Hindsight's own errors, retries, backlogs, or internal state — the memory
|
|
19586
19664
|
` + ` system's self-reports are not memories.
|
|
19587
19665
|
` + `- Restatements of the user's current request or the task in progress.
|
|
19666
|
+
` + `- The assistant's own answers, summaries, recaps, or reflect output. Before
|
|
19667
|
+
` + ` extracting, ask: does anything in this transcript support this claim OTHER
|
|
19668
|
+
` + ` than the assistant having asserted it? If not, drop it — a model's own
|
|
19669
|
+
` + ` synthesis re-extracted as a fact is how a guess becomes permanent.
|
|
19670
|
+
` + ` Concretely, never produce a fact whose only support is the assistant
|
|
19671
|
+
` + ` stating a date, a version, an attribution, a total, or a decision that the
|
|
19672
|
+
` + ` user never confirmed and no tool output shows. An unverified claim recalls
|
|
19673
|
+
` + ` later as though it had been established, which is worse than not
|
|
19674
|
+
` + ` remembering it at all.
|
|
19588
19675
|
` + `- Volatile state written as a timeless assertion. A version, count, size,
|
|
19589
19676
|
` + ` backlog, status, or any "X is running Y" / "X is at Y" / "X is currently Y"
|
|
19590
19677
|
` + ` claim is true only at the instant it was said. Concretely, never produce a
|
|
@@ -19740,6 +19827,64 @@ var SUPERSEDED_RETAIN_MISSIONS = [
|
|
|
19740
19827
|
` + `
|
|
19741
19828
|
` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
|
|
19742
19829
|
` + `nothing durable remains, return an empty facts list.
|
|
19830
|
+
`,
|
|
19831
|
+
`Extract durable facts that will still be true and useful weeks from now, once this session is forgotten.
|
|
19832
|
+
` + `
|
|
19833
|
+
` + `DURABILITY GATE. Emit a candidate ONLY if it is one of these five classes:
|
|
19834
|
+
` + `- PREFERENCE — what the user likes, wants, or always does; a standing rule or correction.
|
|
19835
|
+
` + `- DECISION — a settled choice that changes how future work is done, including a choice NOT to do something. A decision about the mechanics of the CURRENT task (which worker to dispatch, which branch to rebase, which PR to merge now, what to do next) is process narration, not a durable decision — drop it unless it establishes a standing rule or permanently changes a system.
|
|
19836
|
+
` + `- FINDING — a root cause, a measurement, or verified behaviour of a system. Include the number.
|
|
19837
|
+
` + `- OUTCOME — a completed result that changed the world: what shipped, what a thing turned out to be. Not the act of shipping it.
|
|
19838
|
+
` + `- RELATIONSHIP — who a person is, what a project or tool is, and how they connect.
|
|
19839
|
+
` + `If a candidate fits none of the five, it is not a memory. Drop it; do not reword it into one.
|
|
19840
|
+
` + `
|
|
19841
|
+
` + `A preference revealed by a request is durable — record the preference (what the user likes, wants, or always does), not the request itself.
|
|
19842
|
+
` + `
|
|
19843
|
+
` + `A TOOL RESULT IS NOT A FACT. Before extracting, ask: is the subject of this
|
|
19844
|
+
` + `candidate a file path, a command/process/agent/session id, a temp directory, or
|
|
19845
|
+
` + `the location where some output was written? If yes, drop it — it is transcript
|
|
19846
|
+
` + `exhaust, not memory.
|
|
19847
|
+
` + `
|
|
19848
|
+
` + `NEVER extract:
|
|
19849
|
+
` + `- Tool results verbatim or paraphrased. Concretely, never produce a fact whose
|
|
19850
|
+
` + ` text resembles any of these: "File created successfully at /path/to/file",
|
|
19851
|
+
` + ` "A background command with ID bctz4yskm is running, and its output will be
|
|
19852
|
+
` + ` written to /tmp/...", "Async agent a745598ba84e71df1 was launched successfully
|
|
19853
|
+
` + ` and is running in the background", "User executed a Bash command to sleep for
|
|
19854
|
+
` + ` 200 seconds", "The assistant used grep to locate 'truncateSync' in src/foo.ts".
|
|
19855
|
+
` + `- Anything mentioning a path under /tmp, a scratchpad directory, or a .tmp file.
|
|
19856
|
+
` + `- Agent tool-use traces or narration of what the assistant did (e.g. "the
|
|
19857
|
+
` + ` assistant used X to query Y", "ran a search", "sent the message").
|
|
19858
|
+
` + `- The act of delegating, dispatching, spawning, launching, steering or merging
|
|
19859
|
+
` + ` work — including when it succeeded. "X was dispatched and completed" is the
|
|
19860
|
+
` + ` session describing itself. Record only what the work LEARNED or CHANGED.
|
|
19861
|
+
` + `- In-flight workflow/process narration (a sub-task started, paused, or is still
|
|
19862
|
+
` + ` running) — retain the outcome only once the task completes or a decision is made.
|
|
19863
|
+
` + `- Operation, request, batch, agent, command or session IDs, UUIDs, hashes, or error codes.
|
|
19864
|
+
` + `- Slash commands the user typed and their effects (e.g. "User issued /clear to
|
|
19865
|
+
` + ` reset assistant state").
|
|
19866
|
+
` + `- Hindsight's own errors, retries, backlogs, or internal state — the memory
|
|
19867
|
+
` + ` system's self-reports are not memories.
|
|
19868
|
+
` + `- Restatements of the user's current request or the task in progress.
|
|
19869
|
+
` + `- Volatile state written as a timeless assertion. A version, count, size,
|
|
19870
|
+
` + ` backlog, status, or any "X is running Y" / "X is at Y" / "X is currently Y"
|
|
19871
|
+
` + ` claim is true only at the instant it was said. Concretely, never produce a
|
|
19872
|
+
` + ` fact whose text resembles any of these: "Switchroom fleet is running image
|
|
19873
|
+
` + ` version v0.18.19", "The switchroom repo is at /path/to/fleet, version
|
|
19874
|
+
` + ` v0.19.5", "Bank overlord has 43155 pending consolidations", "The build is
|
|
19875
|
+
` + ` currently green". If the claim is worth keeping, put the date INSIDE the
|
|
19876
|
+
` + ` fact text ("As of 2026-07-19 the fleet was running v0.18.19"); if you
|
|
19877
|
+
` + ` cannot date it, drop it. An undated one is recalled forever as though it
|
|
19878
|
+
` + ` were still true, which is worse than not remembering it at all.
|
|
19879
|
+
` + `- Transient state (unread counts, build status, what is running right now) unless
|
|
19880
|
+
` + ` the fact is explicitly dated, in which case record it as a dated observation.
|
|
19881
|
+
` + `- Greetings, acknowledgements, and routine operational chatter.
|
|
19882
|
+
` + `
|
|
19883
|
+
` + `Write each fact so it stands alone: name the thing, the number, and the date. A
|
|
19884
|
+
` + `sentence that only makes sense while reading this transcript is not durable.
|
|
19885
|
+
` + `
|
|
19886
|
+
` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
|
|
19887
|
+
` + `nothing durable remains, return an empty facts list.
|
|
19743
19888
|
`
|
|
19744
19889
|
];
|
|
19745
19890
|
var DEFAULT_OBSERVATIONS_MISSION = `Synthesise durable, standing knowledge about the people, projects, and systems this agent works with: preferences and standing rules, roles and relationships, skills and recurring patterns, technical and operational decisions with their rationale, and the state of long-running work once it lands.
|
|
@@ -19817,6 +19962,22 @@ var PROFILE_MEMORY_DEFAULTS = {
|
|
|
19817
19962
|
var warnedMissingPool = new Set;
|
|
19818
19963
|
var warnedMissingDefault = new Set;
|
|
19819
19964
|
|
|
19965
|
+
// src/memory/hindsight-retain-provenance.ts
|
|
19966
|
+
var RETAIN_PROVENANCE_TAG = "source:transcript";
|
|
19967
|
+
var RETAIN_TAGS_DEFAULT = Object.freeze([
|
|
19968
|
+
"{session_id}",
|
|
19969
|
+
RETAIN_PROVENANCE_TAG
|
|
19970
|
+
]);
|
|
19971
|
+
|
|
19972
|
+
// src/memory/hindsight-seed-directives.ts
|
|
19973
|
+
var ANTI_CONFABULATION_DIRECTIVE = `When the retrieved memories do not support an answer, say so instead of composing one.
|
|
19974
|
+
` + `
|
|
19975
|
+
` + `- If nothing retrieved scores meaningfully above zero, or what came back is off-topic, the honest answer is that the bank does not know. Say that plainly, and say what would settle it.
|
|
19976
|
+
` + `- Never assert a date, a version, a number, an attribution, a decision, or an outcome that no retrieved memory states. A question that presupposes something is not evidence for it: asked when a decision was made, when the bank records no such decision, answer that none is recorded — do not supply one.
|
|
19977
|
+
` + `- Keep what the bank RECORDED separate from what you INFER. State inferences as inferences, and say which memory a recorded fact came from.
|
|
19978
|
+
` + `- Treat a memory that was extracted from a conversation transcript as an unverified claim, not an established fact — it may be an assistant's own earlier guess. If it is the only support for an answer, say that it is.
|
|
19979
|
+
` + "- Partial knowledge with its gaps named is more useful than a fluent answer that fills them in.";
|
|
19980
|
+
|
|
19820
19981
|
// src/telegram/state.ts
|
|
19821
19982
|
init_paths();
|
|
19822
19983
|
|
|
@@ -19854,7 +20015,6 @@ var RECALL_PASSTHROUGH_DEFAULTS = Object.freeze({
|
|
|
19854
20015
|
init_paths();
|
|
19855
20016
|
|
|
19856
20017
|
// src/agents/scaffold.ts
|
|
19857
|
-
var REPO_ROOT = resolve5(import.meta.dirname, "../..");
|
|
19858
20018
|
var CLAUDE_MD_YOURS_PLACEHOLDER = "This space is yours. Add per-agent rules, exceptions, or context the " + "Switchroom template doesn't capture. Everything above the marker line is " + "regenerated on every apply; this section is preserved.";
|
|
19859
20019
|
var pendingBankOps = new Set;
|
|
19860
20020
|
var SWITCHROOM_OWNED_SETTINGS_KEYS = new Set([
|
|
@@ -19930,7 +20090,7 @@ async function bindAgentSocket(parentDir, agent, db) {
|
|
|
19930
20090
|
} catch {}
|
|
19931
20091
|
const uid = allocateAgentUid(agent);
|
|
19932
20092
|
const socketPath = resolve6(dir, "sock");
|
|
19933
|
-
if (
|
|
20093
|
+
if (existsSync6(socketPath)) {
|
|
19934
20094
|
try {
|
|
19935
20095
|
unlinkSync(socketPath);
|
|
19936
20096
|
} catch (err) {
|
|
@@ -19970,7 +20130,7 @@ async function bindOperatorSocket(parentDir, operatorUid, db) {
|
|
|
19970
20130
|
chmodSync(dir, 448);
|
|
19971
20131
|
} catch {}
|
|
19972
20132
|
const socketPath = resolve6(dir, "sock");
|
|
19973
|
-
if (
|
|
20133
|
+
if (existsSync6(socketPath)) {
|
|
19974
20134
|
try {
|
|
19975
20135
|
unlinkSync(socketPath);
|
|
19976
20136
|
} catch (err) {
|
|
@@ -20290,7 +20450,7 @@ async function bootstrap(opts) {
|
|
|
20290
20450
|
l.server.close();
|
|
20291
20451
|
} catch {}
|
|
20292
20452
|
try {
|
|
20293
|
-
if (
|
|
20453
|
+
if (existsSync6(l.socketPath))
|
|
20294
20454
|
unlinkSync(l.socketPath);
|
|
20295
20455
|
} catch {}
|
|
20296
20456
|
}
|
|
@@ -20309,7 +20469,7 @@ async function main() {
|
|
|
20309
20469
|
const operatorUid = operatorUidRaw && /^\d+$/.test(operatorUidRaw) ? Number(operatorUidRaw) : undefined;
|
|
20310
20470
|
let agents = [];
|
|
20311
20471
|
try {
|
|
20312
|
-
if (
|
|
20472
|
+
if (existsSync6(socketParent)) {
|
|
20313
20473
|
agents = readdirSync3(socketParent).filter((name) => {
|
|
20314
20474
|
if (name === KERNEL_OPERATOR_NAME)
|
|
20315
20475
|
return false;
|
|
@@ -20344,7 +20504,7 @@ async function main() {
|
|
|
20344
20504
|
} catch {}
|
|
20345
20505
|
const db = openKernelDb(dbPath);
|
|
20346
20506
|
const socketPath = resolve6(socketEnv);
|
|
20347
|
-
if (
|
|
20507
|
+
if (existsSync6(socketPath)) {
|
|
20348
20508
|
try {
|
|
20349
20509
|
unlinkSync(socketPath);
|
|
20350
20510
|
} catch {}
|
|
@@ -20366,7 +20526,7 @@ async function main() {
|
|
|
20366
20526
|
server.close();
|
|
20367
20527
|
} catch {}
|
|
20368
20528
|
try {
|
|
20369
|
-
if (
|
|
20529
|
+
if (existsSync6(socketPath))
|
|
20370
20530
|
unlinkSync(socketPath);
|
|
20371
20531
|
} catch {}
|
|
20372
20532
|
try {
|