switchroom 0.19.40 → 0.19.42
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 +22 -2
- package/dist/auth-broker/index.js +22 -2
- package/dist/cli/notion-write-pretool.mjs +22 -2
- package/dist/cli/switchroom.js +810 -241
- package/dist/host-control/main.js +94 -19
- package/dist/vault/approvals/kernel-server.js +22 -2
- package/dist/vault/broker/server.js +22 -2
- package/package.json +1 -1
- package/telegram-plugin/bridge/bridge.ts +2 -2
- package/telegram-plugin/dist/bridge/bridge.js +2 -2
- package/telegram-plugin/dist/gateway/gateway.js +332 -124
- package/telegram-plugin/dist/server.js +2 -2
- package/telegram-plugin/gateway/approval-callback-consume-record.test.ts +132 -0
- package/telegram-plugin/gateway/checklist-fallback.ts +370 -0
- package/telegram-plugin/gateway/gateway.ts +76 -76
- package/telegram-plugin/gateway/liveness-wiring.ts +12 -0
- package/telegram-plugin/gateway/model-command.ts +21 -109
- package/telegram-plugin/gateway/stream-render.ts +57 -0
- package/telegram-plugin/gateway/turn-record-status.ts +80 -0
- package/telegram-plugin/tests/checklist-fallback.test.ts +317 -0
- package/telegram-plugin/tests/framework-fallback-drains-parked.test.ts +134 -0
- package/telegram-plugin/tests/gateway-outbound-redact.test.ts +10 -6
- package/telegram-plugin/tests/helpers/liveness-wiring-fixture.ts +3 -0
- package/telegram-plugin/tests/turn-record-status.test.ts +62 -0
- package/vendor/hindsight-memory/CHANGELOG.md +28 -0
- package/vendor/hindsight-memory/docs/measurements/subagent-volume-gate-3994.md +84 -0
- package/vendor/hindsight-memory/scripts/backfill_transcripts.py +254 -40
- package/vendor/hindsight-memory/scripts/lib/content.py +11 -2
- package/vendor/hindsight-memory/scripts/recall.py +18 -3
- package/vendor/hindsight-memory/scripts/subagent_retain.py +59 -38
- package/vendor/hindsight-memory/scripts/tests/data/replay_volume_gate_3994.py +295 -0
- package/vendor/hindsight-memory/scripts/tests/test_backfill_from_logs.py +109 -0
- package/vendor/hindsight-memory/scripts/tests/test_overlap_tokens.py +135 -0
- package/vendor/hindsight-memory/scripts/tests/test_recall_no_lexical_gate.py +20 -23
- package/vendor/hindsight-memory/scripts/tests/test_recall_query_shaping.py +48 -0
- package/vendor/hindsight-memory/scripts/tests/test_subagent_retain.py +94 -1
- package/vendor/hindsight-memory/scripts/tests/test_subagent_retain_learnings.py +98 -42
|
@@ -11116,6 +11116,7 @@ var init_schema = __esm(() => {
|
|
|
11116
11116
|
auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
|
|
11117
11117
|
file: exports_external.boolean().default(true).describe("Maintain a curated workspace MEMORY.md file (seeded once, " + "auto-loaded every turn). Set false for hindsight-only memory: " + "the file is not seeded or re-created, so once migrated into " + "Hindsight and deleted it stays gone. Recall + directives carry " + "the memory instead. Cascade: override (per-agent wins over default)."),
|
|
11118
11118
|
isolation: exports_external.enum(["default", "strict"]).default("default").describe("strict = never shared cross-agent, default = eligible for reflect"),
|
|
11119
|
+
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`."),
|
|
11119
11120
|
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."),
|
|
11120
11121
|
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."),
|
|
11121
11122
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain. Cascade: override."),
|
|
@@ -11409,6 +11410,8 @@ var init_schema = __esm(() => {
|
|
|
11409
11410
|
provider: exports_external.string().min(1).optional().describe("Hindsight LLM provider (upstream `HINDSIGHT_API_LLM_PROVIDER`). " + "Defaults to `claude-code` (subscription-honest, broker-fed OAuth). " + "Any litellm-routable provider the upstream image supports is valid. " + "Serves as the GLOBAL default for every op absent a per-op override."),
|
|
11410
11411
|
model: exports_external.string().min(1).optional().describe("Hindsight LLM model (upstream `HINDSIGHT_API_LLM_MODEL`). Defaults " + "to HINDSIGHT_DEFAULT_MODEL. Any model your LiteLLM proxy can route " + "is valid, e.g. `openrouter/z-ai/glm-5.2` when routing through the " + "fleet proxy. With provider=claude-code this value is ALSO exported " + "as `ANTHROPIC_MODEL` to the claude subprocess. Serves as the GLOBAL " + "default for every op absent a per-op override."),
|
|
11411
11412
|
context_window: exports_external.number().int().positive().optional().describe("GLOBAL context window (tokens) of the backend serving hindsight's " + "LLM ops — the declared size switchroom derives every token budget " + "from. Set this to the real window of whatever you point " + "`hindsight.llm` at (e.g. 32768 for a llama.cpp slot launched with " + "`-c 65536 -np 2`, 131072 for a large-window OpenRouter model). " + "Absent → a per-provider default: 200000 for `claude-code`, a " + "conservative 32768 for everything else. Overflowing a local " + "backend's window does NOT error — llama.cpp context-shift silently " + "drops the system prompt and the model answers conversationally " + "with HTTP 200 — so this value is what makes the failure " + "detectable at setup time instead of never."),
|
|
11413
|
+
base_url: exports_external.string().min(1).optional().describe("GLOBAL LLM base URL (upstream `HINDSIGHT_API_LLM_BASE_URL`). The " + "default endpoint every op inherits absent a per-op " + "`hindsight.llm.<op>.base_url`. Optional passthrough; unset → the " + "engine's provider default. When this points at host loopback the " + "hindsight container is forced onto host networking, same as a " + "per-op base URL, so the endpoint stays reachable (#3687)."),
|
|
11414
|
+
api_key: exports_external.string().min(1).optional().describe("GLOBAL LLM API key (upstream `HINDSIGHT_API_LLM_API_KEY`). Literal " + "or `vault:` reference. The default credential every op inherits " + "absent a per-op `hindsight.llm.<op>.api_key`; the engine reads it as " + "a plain env fallback. Optional passthrough (#3687)."),
|
|
11412
11415
|
retain: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `retain` LLM op (memory ingestion). Emits " + "`HINDSIGHT_API_RETAIN_LLM_*`. Absent → uses the global model/provider."),
|
|
11413
11416
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
|
|
11414
11417
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
|
|
@@ -11545,6 +11548,7 @@ var init_schema = __esm(() => {
|
|
|
11545
11548
|
auto_recall: exports_external.boolean().optional(),
|
|
11546
11549
|
file: exports_external.boolean().optional(),
|
|
11547
11550
|
isolation: exports_external.enum(["default", "strict"]).optional(),
|
|
11551
|
+
profile: exports_external.string().optional(),
|
|
11548
11552
|
directive_capture_nudge: exports_external.boolean().optional(),
|
|
11549
11553
|
observation_scopes: ObservationScopesSchema,
|
|
11550
11554
|
observation_scope_strategy: ObservationScopeStrategySchema,
|
|
@@ -11586,7 +11590,23 @@ var init_schema = __esm(() => {
|
|
|
11586
11590
|
max_query_chars: exports_external.number().int().min(1).optional(),
|
|
11587
11591
|
parallel: exports_external.boolean().optional(),
|
|
11588
11592
|
additional_banks: exports_external.array(exports_external.string()).optional(),
|
|
11589
|
-
sender_banks: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
11593
|
+
sender_banks: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
11594
|
+
types: exports_external.array(exports_external.string()).optional(),
|
|
11595
|
+
skip_trivial: exports_external.boolean().optional(),
|
|
11596
|
+
topic_filter_mode: exports_external.enum(["soft-preamble", "hard-filter"]).optional()
|
|
11597
|
+
}).optional(),
|
|
11598
|
+
retain: exports_external.object({
|
|
11599
|
+
every_n_turns: exports_external.number().int().min(1).optional(),
|
|
11600
|
+
overlap_turns: exports_external.number().int().min(0).optional()
|
|
11601
|
+
}).optional(),
|
|
11602
|
+
bank_mission: exports_external.string().optional(),
|
|
11603
|
+
reflect_mission: exports_external.string().optional(),
|
|
11604
|
+
retain_mission: exports_external.string().optional(),
|
|
11605
|
+
observations_mission: exports_external.string().optional(),
|
|
11606
|
+
disposition: exports_external.object({
|
|
11607
|
+
skepticism: exports_external.number().int().min(1).max(5).optional(),
|
|
11608
|
+
literalism: exports_external.number().int().min(1).max(5).optional(),
|
|
11609
|
+
empathy: exports_external.number().int().min(1).max(5).optional()
|
|
11590
11610
|
}).optional()
|
|
11591
11611
|
}).optional(),
|
|
11592
11612
|
schedule: exports_external.array(ScheduleEntrySchema).optional(),
|
|
@@ -18753,11 +18773,11 @@ var init_protocol = __esm(() => {
|
|
|
18753
18773
|
OkRevokeGrantResponseSchema,
|
|
18754
18774
|
OkApprovalRequestResponseSchema,
|
|
18755
18775
|
OkApprovalLookupResponseSchema,
|
|
18776
|
+
OkApprovalConsumeRecordResponseSchema,
|
|
18756
18777
|
OkApprovalConsumeResponseSchema,
|
|
18757
18778
|
OkApprovalRevokeResponseSchema,
|
|
18758
18779
|
OkApprovalListResponseSchema,
|
|
18759
18780
|
OkApprovalRecordResponseSchema,
|
|
18760
|
-
OkApprovalConsumeRecordResponseSchema,
|
|
18761
18781
|
ErrorResponseSchema
|
|
18762
18782
|
]);
|
|
18763
18783
|
});
|
|
@@ -21010,6 +21030,7 @@ function parsePendingRolloutMarker(raw) {
|
|
|
21010
21030
|
if (o.allow_downgrade !== undefined && typeof o.allow_downgrade !== "boolean") {
|
|
21011
21031
|
return null;
|
|
21012
21032
|
}
|
|
21033
|
+
const narrationIdValid = typeof o.narration_message_id === "number" && Number.isInteger(o.narration_message_id) && o.narration_message_id > 0;
|
|
21013
21034
|
return {
|
|
21014
21035
|
v: 1,
|
|
21015
21036
|
request_id: o.request_id,
|
|
@@ -21017,6 +21038,7 @@ function parsePendingRolloutMarker(raw) {
|
|
|
21017
21038
|
...o.agents !== undefined ? { agents: o.agents } : {},
|
|
21018
21039
|
...o.skip_web !== undefined ? { skip_web: o.skip_web } : {},
|
|
21019
21040
|
...o.allow_downgrade !== undefined ? { allow_downgrade: o.allow_downgrade } : {},
|
|
21041
|
+
...narrationIdValid ? { narration_message_id: o.narration_message_id } : {},
|
|
21020
21042
|
caller: caller.kind === "agent" ? { kind: "agent", name: caller.name } : { kind: "operator" },
|
|
21021
21043
|
created_at: o.created_at,
|
|
21022
21044
|
prior_hostd_version: o.prior_hostd_version
|
|
@@ -21320,7 +21342,7 @@ function allocateAgentUid(name) {
|
|
|
21320
21342
|
}
|
|
21321
21343
|
|
|
21322
21344
|
// src/build-info.ts
|
|
21323
|
-
var VERSION = "0.19.
|
|
21345
|
+
var VERSION = "0.19.42";
|
|
21324
21346
|
|
|
21325
21347
|
// src/setup/hindsight-recall-tunables.ts
|
|
21326
21348
|
var RECALL_DEADLINE_HEADROOM_SECONDS = 2;
|
|
@@ -30786,6 +30808,27 @@ class HostdServer {
|
|
|
30786
30808
|
})
|
|
30787
30809
|
};
|
|
30788
30810
|
}
|
|
30811
|
+
persistNarrationMessageId(requestId, messageId) {
|
|
30812
|
+
try {
|
|
30813
|
+
if (!Number.isInteger(messageId) || messageId <= 0)
|
|
30814
|
+
return;
|
|
30815
|
+
const markerPath = join13(this.hostdDirPath(), SELF_BUMP_MARKER_FILENAME);
|
|
30816
|
+
if (!existsSync15(markerPath))
|
|
30817
|
+
return;
|
|
30818
|
+
const marker = parsePendingRolloutMarker(readFileSync11(markerPath, "utf8"));
|
|
30819
|
+
if (!marker)
|
|
30820
|
+
return;
|
|
30821
|
+
if (marker.request_id !== requestId)
|
|
30822
|
+
return;
|
|
30823
|
+
const updated = {
|
|
30824
|
+
...marker,
|
|
30825
|
+
narration_message_id: messageId
|
|
30826
|
+
};
|
|
30827
|
+
const tmp = `${markerPath}.tmp`;
|
|
30828
|
+
writeFileSync6(tmp, encodePendingRolloutMarker(updated), { mode: 384 });
|
|
30829
|
+
renameSync5(tmp, markerPath);
|
|
30830
|
+
} catch {}
|
|
30831
|
+
}
|
|
30789
30832
|
async resumePendingSelfBumpRollout() {
|
|
30790
30833
|
const markerPath = join13(this.hostdDirPath(), SELF_BUMP_MARKER_FILENAME);
|
|
30791
30834
|
if (!existsSync15(markerPath))
|
|
@@ -30854,6 +30897,9 @@ class HostdServer {
|
|
|
30854
30897
|
...marker.skip_web ? { skip_web: true } : {},
|
|
30855
30898
|
...marker.allow_downgrade ? { allow_downgrade: true } : {}
|
|
30856
30899
|
}, marker.request_id, caller, Date.now());
|
|
30900
|
+
if (marker.narration_message_id !== undefined && caller.kind === "agent") {
|
|
30901
|
+
this.rolloutNarrator?.seedPostedMessage?.(marker.request_id, caller.name, marker.narration_message_id);
|
|
30902
|
+
}
|
|
30857
30903
|
this.onRolloutPhase(entry, { phase: "self-bump-done", target: marker.pin });
|
|
30858
30904
|
}
|
|
30859
30905
|
async handleAgentStart(req, started) {
|
|
@@ -32672,28 +32718,49 @@ class LogTailRolloutNarrator {
|
|
|
32672
32718
|
}
|
|
32673
32719
|
}
|
|
32674
32720
|
}
|
|
32721
|
+
freshState(agentName, target) {
|
|
32722
|
+
return {
|
|
32723
|
+
agentName,
|
|
32724
|
+
lastAppliedSeq: -1,
|
|
32725
|
+
messageId: null,
|
|
32726
|
+
posting: false,
|
|
32727
|
+
postAttempts: 0,
|
|
32728
|
+
postFailed: false,
|
|
32729
|
+
render: { target },
|
|
32730
|
+
agents: [],
|
|
32731
|
+
singletons: initialSingletons(),
|
|
32732
|
+
frozen: false,
|
|
32733
|
+
timer: null,
|
|
32734
|
+
pendingEditAfterPost: false
|
|
32735
|
+
};
|
|
32736
|
+
}
|
|
32675
32737
|
ensureState(entry) {
|
|
32676
32738
|
let st = this.states.get(entry.request_id);
|
|
32677
32739
|
if (!st) {
|
|
32678
32740
|
const agentName = entry.caller.kind === "agent" ? entry.caller.name : "";
|
|
32679
|
-
st =
|
|
32680
|
-
agentName,
|
|
32681
|
-
lastAppliedSeq: -1,
|
|
32682
|
-
messageId: null,
|
|
32683
|
-
posting: false,
|
|
32684
|
-
postAttempts: 0,
|
|
32685
|
-
postFailed: false,
|
|
32686
|
-
render: { target: entry.pin ?? "" },
|
|
32687
|
-
agents: [],
|
|
32688
|
-
singletons: initialSingletons(),
|
|
32689
|
-
frozen: false,
|
|
32690
|
-
timer: null,
|
|
32691
|
-
pendingEditAfterPost: false
|
|
32692
|
-
};
|
|
32741
|
+
st = this.freshState(agentName, entry.pin ?? "");
|
|
32693
32742
|
this.states.set(entry.request_id, st);
|
|
32694
32743
|
}
|
|
32695
32744
|
return st;
|
|
32696
32745
|
}
|
|
32746
|
+
seedPostedMessage(requestId, agentName, messageId) {
|
|
32747
|
+
const existing = this.states.get(requestId);
|
|
32748
|
+
if (existing) {
|
|
32749
|
+
if (existing.messageId === null) {
|
|
32750
|
+
existing.messageId = messageId;
|
|
32751
|
+
existing.posting = false;
|
|
32752
|
+
existing.postFailed = false;
|
|
32753
|
+
if (existing.postAttempts < 1)
|
|
32754
|
+
existing.postAttempts = 1;
|
|
32755
|
+
existing.pendingEditAfterPost = false;
|
|
32756
|
+
}
|
|
32757
|
+
return;
|
|
32758
|
+
}
|
|
32759
|
+
const st = this.freshState(agentName, "");
|
|
32760
|
+
st.messageId = messageId;
|
|
32761
|
+
st.postAttempts = 1;
|
|
32762
|
+
this.states.set(requestId, st);
|
|
32763
|
+
}
|
|
32697
32764
|
scheduleRenderOrPost(requestId) {
|
|
32698
32765
|
const st = this.states.get(requestId);
|
|
32699
32766
|
if (!st)
|
|
@@ -32734,6 +32801,11 @@ class LogTailRolloutNarrator {
|
|
|
32734
32801
|
}
|
|
32735
32802
|
st.messageId = mid;
|
|
32736
32803
|
st.postFailed = false;
|
|
32804
|
+
try {
|
|
32805
|
+
this.opts.onMessageId?.(requestId, mid);
|
|
32806
|
+
} catch (e) {
|
|
32807
|
+
this.opts.log?.(`onMessageId sink threw (non-fatal): ${e.message}`);
|
|
32808
|
+
}
|
|
32737
32809
|
if (st.pendingEditAfterPost) {
|
|
32738
32810
|
st.pendingEditAfterPost = false;
|
|
32739
32811
|
this.flush(requestId, false);
|
|
@@ -33378,8 +33450,11 @@ async function main() {
|
|
|
33378
33450
|
resolveGatewaySocket,
|
|
33379
33451
|
log: (m) => process.stderr.write(`hostd: rollout-narration — ${m}
|
|
33380
33452
|
`)
|
|
33381
|
-
}), {
|
|
33382
|
-
|
|
33453
|
+
}), {
|
|
33454
|
+
log: (m) => process.stderr.write(`hostd: rollout-narration — ${m}
|
|
33455
|
+
`),
|
|
33456
|
+
onMessageId: (rid, mid) => server?.persistNarrationMessageId(rid, mid)
|
|
33457
|
+
});
|
|
33383
33458
|
const server = new HostdServer({
|
|
33384
33459
|
homeDir: homedir8(),
|
|
33385
33460
|
agentUids,
|
|
@@ -4407,11 +4407,11 @@ var init_protocol = __esm(() => {
|
|
|
4407
4407
|
OkRevokeGrantResponseSchema,
|
|
4408
4408
|
OkApprovalRequestResponseSchema,
|
|
4409
4409
|
OkApprovalLookupResponseSchema,
|
|
4410
|
+
OkApprovalConsumeRecordResponseSchema,
|
|
4410
4411
|
OkApprovalConsumeResponseSchema,
|
|
4411
4412
|
OkApprovalRevokeResponseSchema,
|
|
4412
4413
|
OkApprovalListResponseSchema,
|
|
4413
4414
|
OkApprovalRecordResponseSchema,
|
|
4414
|
-
OkApprovalConsumeRecordResponseSchema,
|
|
4415
4415
|
ErrorResponseSchema
|
|
4416
4416
|
]);
|
|
4417
4417
|
});
|
|
@@ -4556,6 +4556,7 @@ var init_schema = __esm(() => {
|
|
|
4556
4556
|
auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
|
|
4557
4557
|
file: exports_external.boolean().default(true).describe("Maintain a curated workspace MEMORY.md file (seeded once, " + "auto-loaded every turn). Set false for hindsight-only memory: " + "the file is not seeded or re-created, so once migrated into " + "Hindsight and deleted it stays gone. Recall + directives carry " + "the memory instead. Cascade: override (per-agent wins over default)."),
|
|
4558
4558
|
isolation: exports_external.enum(["default", "strict"]).default("default").describe("strict = never shared cross-agent, default = eligible for reflect"),
|
|
4559
|
+
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`."),
|
|
4559
4560
|
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."),
|
|
4560
4561
|
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."),
|
|
4561
4562
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain. Cascade: override."),
|
|
@@ -4849,6 +4850,8 @@ var init_schema = __esm(() => {
|
|
|
4849
4850
|
provider: exports_external.string().min(1).optional().describe("Hindsight LLM provider (upstream `HINDSIGHT_API_LLM_PROVIDER`). " + "Defaults to `claude-code` (subscription-honest, broker-fed OAuth). " + "Any litellm-routable provider the upstream image supports is valid. " + "Serves as the GLOBAL default for every op absent a per-op override."),
|
|
4850
4851
|
model: exports_external.string().min(1).optional().describe("Hindsight LLM model (upstream `HINDSIGHT_API_LLM_MODEL`). Defaults " + "to HINDSIGHT_DEFAULT_MODEL. Any model your LiteLLM proxy can route " + "is valid, e.g. `openrouter/z-ai/glm-5.2` when routing through the " + "fleet proxy. With provider=claude-code this value is ALSO exported " + "as `ANTHROPIC_MODEL` to the claude subprocess. Serves as the GLOBAL " + "default for every op absent a per-op override."),
|
|
4851
4852
|
context_window: exports_external.number().int().positive().optional().describe("GLOBAL context window (tokens) of the backend serving hindsight's " + "LLM ops — the declared size switchroom derives every token budget " + "from. Set this to the real window of whatever you point " + "`hindsight.llm` at (e.g. 32768 for a llama.cpp slot launched with " + "`-c 65536 -np 2`, 131072 for a large-window OpenRouter model). " + "Absent → a per-provider default: 200000 for `claude-code`, a " + "conservative 32768 for everything else. Overflowing a local " + "backend's window does NOT error — llama.cpp context-shift silently " + "drops the system prompt and the model answers conversationally " + "with HTTP 200 — so this value is what makes the failure " + "detectable at setup time instead of never."),
|
|
4853
|
+
base_url: exports_external.string().min(1).optional().describe("GLOBAL LLM base URL (upstream `HINDSIGHT_API_LLM_BASE_URL`). The " + "default endpoint every op inherits absent a per-op " + "`hindsight.llm.<op>.base_url`. Optional passthrough; unset → the " + "engine's provider default. When this points at host loopback the " + "hindsight container is forced onto host networking, same as a " + "per-op base URL, so the endpoint stays reachable (#3687)."),
|
|
4854
|
+
api_key: exports_external.string().min(1).optional().describe("GLOBAL LLM API key (upstream `HINDSIGHT_API_LLM_API_KEY`). Literal " + "or `vault:` reference. The default credential every op inherits " + "absent a per-op `hindsight.llm.<op>.api_key`; the engine reads it as " + "a plain env fallback. Optional passthrough (#3687)."),
|
|
4852
4855
|
retain: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `retain` LLM op (memory ingestion). Emits " + "`HINDSIGHT_API_RETAIN_LLM_*`. Absent → uses the global model/provider."),
|
|
4853
4856
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
|
|
4854
4857
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
|
|
@@ -4985,6 +4988,7 @@ var init_schema = __esm(() => {
|
|
|
4985
4988
|
auto_recall: exports_external.boolean().optional(),
|
|
4986
4989
|
file: exports_external.boolean().optional(),
|
|
4987
4990
|
isolation: exports_external.enum(["default", "strict"]).optional(),
|
|
4991
|
+
profile: exports_external.string().optional(),
|
|
4988
4992
|
directive_capture_nudge: exports_external.boolean().optional(),
|
|
4989
4993
|
observation_scopes: ObservationScopesSchema,
|
|
4990
4994
|
observation_scope_strategy: ObservationScopeStrategySchema,
|
|
@@ -5026,7 +5030,23 @@ var init_schema = __esm(() => {
|
|
|
5026
5030
|
max_query_chars: exports_external.number().int().min(1).optional(),
|
|
5027
5031
|
parallel: exports_external.boolean().optional(),
|
|
5028
5032
|
additional_banks: exports_external.array(exports_external.string()).optional(),
|
|
5029
|
-
sender_banks: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
5033
|
+
sender_banks: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
5034
|
+
types: exports_external.array(exports_external.string()).optional(),
|
|
5035
|
+
skip_trivial: exports_external.boolean().optional(),
|
|
5036
|
+
topic_filter_mode: exports_external.enum(["soft-preamble", "hard-filter"]).optional()
|
|
5037
|
+
}).optional(),
|
|
5038
|
+
retain: exports_external.object({
|
|
5039
|
+
every_n_turns: exports_external.number().int().min(1).optional(),
|
|
5040
|
+
overlap_turns: exports_external.number().int().min(0).optional()
|
|
5041
|
+
}).optional(),
|
|
5042
|
+
bank_mission: exports_external.string().optional(),
|
|
5043
|
+
reflect_mission: exports_external.string().optional(),
|
|
5044
|
+
retain_mission: exports_external.string().optional(),
|
|
5045
|
+
observations_mission: exports_external.string().optional(),
|
|
5046
|
+
disposition: exports_external.object({
|
|
5047
|
+
skepticism: exports_external.number().int().min(1).max(5).optional(),
|
|
5048
|
+
literalism: exports_external.number().int().min(1).max(5).optional(),
|
|
5049
|
+
empathy: exports_external.number().int().min(1).max(5).optional()
|
|
5030
5050
|
}).optional()
|
|
5031
5051
|
}).optional(),
|
|
5032
5052
|
schedule: exports_external.array(ScheduleEntrySchema).optional(),
|
|
@@ -4152,6 +4152,7 @@ var init_schema = __esm(() => {
|
|
|
4152
4152
|
auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
|
|
4153
4153
|
file: exports_external.boolean().default(true).describe("Maintain a curated workspace MEMORY.md file (seeded once, " + "auto-loaded every turn). Set false for hindsight-only memory: " + "the file is not seeded or re-created, so once migrated into " + "Hindsight and deleted it stays gone. Recall + directives carry " + "the memory instead. Cascade: override (per-agent wins over default)."),
|
|
4154
4154
|
isolation: exports_external.enum(["default", "strict"]).default("default").describe("strict = never shared cross-agent, default = eligible for reflect"),
|
|
4155
|
+
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`."),
|
|
4155
4156
|
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."),
|
|
4156
4157
|
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."),
|
|
4157
4158
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain. Cascade: override."),
|
|
@@ -4445,6 +4446,8 @@ var init_schema = __esm(() => {
|
|
|
4445
4446
|
provider: exports_external.string().min(1).optional().describe("Hindsight LLM provider (upstream `HINDSIGHT_API_LLM_PROVIDER`). " + "Defaults to `claude-code` (subscription-honest, broker-fed OAuth). " + "Any litellm-routable provider the upstream image supports is valid. " + "Serves as the GLOBAL default for every op absent a per-op override."),
|
|
4446
4447
|
model: exports_external.string().min(1).optional().describe("Hindsight LLM model (upstream `HINDSIGHT_API_LLM_MODEL`). Defaults " + "to HINDSIGHT_DEFAULT_MODEL. Any model your LiteLLM proxy can route " + "is valid, e.g. `openrouter/z-ai/glm-5.2` when routing through the " + "fleet proxy. With provider=claude-code this value is ALSO exported " + "as `ANTHROPIC_MODEL` to the claude subprocess. Serves as the GLOBAL " + "default for every op absent a per-op override."),
|
|
4447
4448
|
context_window: exports_external.number().int().positive().optional().describe("GLOBAL context window (tokens) of the backend serving hindsight's " + "LLM ops — the declared size switchroom derives every token budget " + "from. Set this to the real window of whatever you point " + "`hindsight.llm` at (e.g. 32768 for a llama.cpp slot launched with " + "`-c 65536 -np 2`, 131072 for a large-window OpenRouter model). " + "Absent → a per-provider default: 200000 for `claude-code`, a " + "conservative 32768 for everything else. Overflowing a local " + "backend's window does NOT error — llama.cpp context-shift silently " + "drops the system prompt and the model answers conversationally " + "with HTTP 200 — so this value is what makes the failure " + "detectable at setup time instead of never."),
|
|
4449
|
+
base_url: exports_external.string().min(1).optional().describe("GLOBAL LLM base URL (upstream `HINDSIGHT_API_LLM_BASE_URL`). The " + "default endpoint every op inherits absent a per-op " + "`hindsight.llm.<op>.base_url`. Optional passthrough; unset → the " + "engine's provider default. When this points at host loopback the " + "hindsight container is forced onto host networking, same as a " + "per-op base URL, so the endpoint stays reachable (#3687)."),
|
|
4450
|
+
api_key: exports_external.string().min(1).optional().describe("GLOBAL LLM API key (upstream `HINDSIGHT_API_LLM_API_KEY`). Literal " + "or `vault:` reference. The default credential every op inherits " + "absent a per-op `hindsight.llm.<op>.api_key`; the engine reads it as " + "a plain env fallback. Optional passthrough (#3687)."),
|
|
4448
4451
|
retain: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `retain` LLM op (memory ingestion). Emits " + "`HINDSIGHT_API_RETAIN_LLM_*`. Absent → uses the global model/provider."),
|
|
4449
4452
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
|
|
4450
4453
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
|
|
@@ -4581,6 +4584,7 @@ var init_schema = __esm(() => {
|
|
|
4581
4584
|
auto_recall: exports_external.boolean().optional(),
|
|
4582
4585
|
file: exports_external.boolean().optional(),
|
|
4583
4586
|
isolation: exports_external.enum(["default", "strict"]).optional(),
|
|
4587
|
+
profile: exports_external.string().optional(),
|
|
4584
4588
|
directive_capture_nudge: exports_external.boolean().optional(),
|
|
4585
4589
|
observation_scopes: ObservationScopesSchema,
|
|
4586
4590
|
observation_scope_strategy: ObservationScopeStrategySchema,
|
|
@@ -4622,7 +4626,23 @@ var init_schema = __esm(() => {
|
|
|
4622
4626
|
max_query_chars: exports_external.number().int().min(1).optional(),
|
|
4623
4627
|
parallel: exports_external.boolean().optional(),
|
|
4624
4628
|
additional_banks: exports_external.array(exports_external.string()).optional(),
|
|
4625
|
-
sender_banks: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
4629
|
+
sender_banks: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
4630
|
+
types: exports_external.array(exports_external.string()).optional(),
|
|
4631
|
+
skip_trivial: exports_external.boolean().optional(),
|
|
4632
|
+
topic_filter_mode: exports_external.enum(["soft-preamble", "hard-filter"]).optional()
|
|
4633
|
+
}).optional(),
|
|
4634
|
+
retain: exports_external.object({
|
|
4635
|
+
every_n_turns: exports_external.number().int().min(1).optional(),
|
|
4636
|
+
overlap_turns: exports_external.number().int().min(0).optional()
|
|
4637
|
+
}).optional(),
|
|
4638
|
+
bank_mission: exports_external.string().optional(),
|
|
4639
|
+
reflect_mission: exports_external.string().optional(),
|
|
4640
|
+
retain_mission: exports_external.string().optional(),
|
|
4641
|
+
observations_mission: exports_external.string().optional(),
|
|
4642
|
+
disposition: exports_external.object({
|
|
4643
|
+
skepticism: exports_external.number().int().min(1).max(5).optional(),
|
|
4644
|
+
literalism: exports_external.number().int().min(1).max(5).optional(),
|
|
4645
|
+
empathy: exports_external.number().int().min(1).max(5).optional()
|
|
4626
4646
|
}).optional()
|
|
4627
4647
|
}).optional(),
|
|
4628
4648
|
schedule: exports_external.array(ScheduleEntrySchema).optional(),
|
|
@@ -19406,11 +19426,11 @@ var init_protocol = __esm(() => {
|
|
|
19406
19426
|
OkRevokeGrantResponseSchema,
|
|
19407
19427
|
OkApprovalRequestResponseSchema,
|
|
19408
19428
|
OkApprovalLookupResponseSchema,
|
|
19429
|
+
OkApprovalConsumeRecordResponseSchema,
|
|
19409
19430
|
OkApprovalConsumeResponseSchema,
|
|
19410
19431
|
OkApprovalRevokeResponseSchema,
|
|
19411
19432
|
OkApprovalListResponseSchema,
|
|
19412
19433
|
OkApprovalRecordResponseSchema,
|
|
19413
|
-
OkApprovalConsumeRecordResponseSchema,
|
|
19414
19434
|
ErrorResponseSchema
|
|
19415
19435
|
]);
|
|
19416
19436
|
});
|
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.42",
|
|
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": {
|
|
@@ -268,7 +268,7 @@ const TOOL_SCHEMAS = [
|
|
|
268
268
|
{
|
|
269
269
|
name: 'send_checklist',
|
|
270
270
|
description:
|
|
271
|
-
'Send a
|
|
271
|
+
'Send a checklist (task list) to a chat. Native interactive Telegram checklists require a Business-account connection, which most deployments do not have — in that normal case the checklist is sent as a formatted TEXT message (bold title + ✅/⬜ task lines) and the result carries degraded:"text": tasks are NOT tappable, and you tick them yourself via update_checklist (task ids are 1..N in send order). With a Business connection configured, the checklist is sent natively and tick events arrive as channel events with kind="checklist_task_changed". Returns JSON with message_id and mode. Limit: 30 tasks.',
|
|
272
272
|
inputSchema: {
|
|
273
273
|
type: 'object',
|
|
274
274
|
properties: {
|
|
@@ -357,7 +357,7 @@ const TOOL_SCHEMAS = [
|
|
|
357
357
|
{
|
|
358
358
|
name: 'update_checklist',
|
|
359
359
|
description:
|
|
360
|
-
'Patch
|
|
360
|
+
'Patch a checklist previously sent with send_checklist: update the title, append tasks, or mark tasks done/undone. Tasks with an id target existing items (ids are 1..N in send order for text-mode checklists); tasks without an id are appended. Removal is not supported. The edit re-renders in the mode the checklist was sent in (text for most deployments). Returns JSON { ok, ... }; after a gateway restart the stored task state may be gone — then it returns ok:false with reason "unknown_checklist" unless you pass a full replacement (title + every task\'s text).',
|
|
361
361
|
inputSchema: {
|
|
362
362
|
type: 'object',
|
|
363
363
|
properties: {
|
|
@@ -25241,7 +25241,7 @@ var TOOL_SCHEMAS = [
|
|
|
25241
25241
|
},
|
|
25242
25242
|
{
|
|
25243
25243
|
name: "send_checklist",
|
|
25244
|
-
description: 'Send a
|
|
25244
|
+
description: 'Send a checklist (task list) to a chat. Native interactive Telegram checklists require a Business-account connection, which most deployments do not have \u2014 in that normal case the checklist is sent as a formatted TEXT message (bold title + \u2705/\u2B1C task lines) and the result carries degraded:"text": tasks are NOT tappable, and you tick them yourself via update_checklist (task ids are 1..N in send order). With a Business connection configured, the checklist is sent natively and tick events arrive as channel events with kind="checklist_task_changed". Returns JSON with message_id and mode. Limit: 30 tasks.',
|
|
25245
25245
|
inputSchema: {
|
|
25246
25246
|
type: "object",
|
|
25247
25247
|
properties: {
|
|
@@ -25326,7 +25326,7 @@ var TOOL_SCHEMAS = [
|
|
|
25326
25326
|
},
|
|
25327
25327
|
{
|
|
25328
25328
|
name: "update_checklist",
|
|
25329
|
-
description:
|
|
25329
|
+
description: `Patch a checklist previously sent with send_checklist: update the title, append tasks, or mark tasks done/undone. Tasks with an id target existing items (ids are 1..N in send order for text-mode checklists); tasks without an id are appended. Removal is not supported. The edit re-renders in the mode the checklist was sent in (text for most deployments). Returns JSON { ok, ... }; after a gateway restart the stored task state may be gone \u2014 then it returns ok:false with reason "unknown_checklist" unless you pass a full replacement (title + every task's text).`,
|
|
25330
25330
|
inputSchema: {
|
|
25331
25331
|
type: "object",
|
|
25332
25332
|
properties: {
|