switchroom 0.19.22 → 0.19.23
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 +2 -1
- package/dist/auth-broker/index.js +68 -1
- package/dist/cli/notion-write-pretool.mjs +2 -1
- package/dist/cli/switchroom.js +552 -320
- package/dist/host-control/main.js +69 -2
- package/dist/vault/approvals/kernel-server.js +71 -4
- package/dist/vault/broker/server.js +71 -4
- package/package.json +5 -4
- package/profiles/_base/start.sh.hbs +101 -0
- package/profiles/_shared/agent-self-service.md.hbs +64 -109
- package/profiles/_shared/delegation-golden-rule.md.hbs +5 -5
- package/profiles/_shared/dev-protocol.md.hbs +13 -42
- package/profiles/_shared/execution-discipline.md.hbs +7 -14
- package/profiles/coding/CLAUDE.md.hbs +0 -6
- package/profiles/default/CLAUDE.md.hbs +21 -50
- package/skills/dev-protocol/SKILL.md +90 -107
- package/telegram-plugin/bunfig.toml +10 -0
- package/telegram-plugin/dist/gateway/gateway.js +108 -16
- package/telegram-plugin/gateway/backstop-delivery.ts +97 -16
- package/telegram-plugin/gateway/captured-answer-resume.ts +46 -17
- package/telegram-plugin/gateway/gateway.ts +9 -7
- package/telegram-plugin/gateway/outbound-send-path.ts +8 -1
- package/telegram-plugin/gateway/stream-render.ts +6 -0
- package/telegram-plugin/gateway/turn-record-status.ts +19 -0
- package/telegram-plugin/gateway/turns-jsonl-rotate.ts +65 -0
- package/telegram-plugin/tests/agent-state-dir-preload.test.ts +33 -0
- package/telegram-plugin/tests/backstop-delivery.test.ts +204 -7
- package/telegram-plugin/tests/backstop-readback-probe.test.ts +12 -0
- package/telegram-plugin/tests/captured-answer-resume.test.ts +104 -0
- package/telegram-plugin/tests/turns-jsonl-rotate.test.ts +92 -1
- package/vendor/hindsight-memory/scripts/drain_pending.py +113 -11
- package/vendor/hindsight-memory/scripts/lib/pending.py +802 -65
- package/vendor/hindsight-memory/scripts/lib/retain_split.py +54 -7
- package/vendor/hindsight-memory/scripts/tests/test_pending_drops.py +1445 -11
- package/vendor/hindsight-memory/scripts/tests/test_retain_split.py +78 -6
- package/vendor/hindsight-memory/tests/test_drain_pending.py +17 -2
- package/vendor/hindsight-memory/tests/test_pending.py +12 -4
|
@@ -68,7 +68,8 @@ from typing import Optional
|
|
|
68
68
|
# The bound — derived, not chosen
|
|
69
69
|
# ---------------------------------------------------------------------------
|
|
70
70
|
#
|
|
71
|
-
# max_content_chars = retain_chunk_size
|
|
71
|
+
# max_content_chars = retain_chunk_size
|
|
72
|
+
# × floor(client_deadline × deadline_safety / chunk_latency)
|
|
72
73
|
#
|
|
73
74
|
# Each input is a measured or read property of the deployment, not a taste
|
|
74
75
|
# call, and each is env-overridable so the bound tracks the deployment:
|
|
@@ -112,16 +113,45 @@ from typing import Optional
|
|
|
112
113
|
# NOT a hand-set number on either side — change
|
|
113
114
|
# `src/litellm/timeout-budget.ts` and both move.
|
|
114
115
|
#
|
|
115
|
-
#
|
|
116
|
+
# deadline_safety 0.7 — the FRACTION of the deadline a maximally-sized
|
|
117
|
+
# part is allowed to consume. See below; this
|
|
118
|
+
# input did not exist until #3693 and was
|
|
119
|
+
# effectively 1.0.
|
|
116
120
|
#
|
|
117
|
-
#
|
|
118
|
-
#
|
|
119
|
-
#
|
|
120
|
-
#
|
|
121
|
+
# floor(310 × 0.7 / 18.4) = 11 chunks → 11 × 3000 = 33,000 chars
|
|
122
|
+
#
|
|
123
|
+
# WHY THERE IS A SAFETY FRACTION AT ALL (#3693). Without it the bound was
|
|
124
|
+
# `floor(deadline / latency)`, which sizes a maximally-sized part to consume
|
|
125
|
+
# ~100% of the deadline BY CONSTRUCTION: 16 × 18.4 = 294.4s against a 310s
|
|
126
|
+
# deadline is 15.6s — 5% — of headroom for the POST/response, server queueing,
|
|
127
|
+
# and any chunk slower than the n=752 MEAN the latency input is. Half the
|
|
128
|
+
# extraction calls are slower than the mean; a part sized to the mean therefore
|
|
129
|
+
# misses the deadline roughly half the time. `drain_pending._backlog_timeout()`
|
|
130
|
+
# defaults to the SAME deadline, so the drainer inherits the same zero margin,
|
|
131
|
+
# times the entry out, bumps its attempt count, and after MAX_ATTEMPTS ages it
|
|
132
|
+
# to `.dead`. That is not a theory: on this fleet every `.dead` marker measured
|
|
133
|
+
# on 2026-07-26 held content of 16,076–44,568 chars — every one of them UNDER
|
|
134
|
+
# the then-current 45,000 bound. The bound was manufacturing dead memories.
|
|
135
|
+
#
|
|
136
|
+
# 0.7 is not a taste call either: it is the utilisation at which the observed
|
|
137
|
+
# per-chunk latency distribution fits, and it independently matches the 30,000
|
|
138
|
+
# char limit the host-side stopgap converged on empirically before this landed.
|
|
139
|
+
# At 0.7 a maximally-sized part is 11 × 18.4 = 202.4s against 310s, leaving
|
|
140
|
+
# 107.6s — enough for a chunk distribution ~50% worse than its own mean.
|
|
141
|
+
#
|
|
142
|
+
# The trade is more parts per logical memory (33,000 rather than 48,000 chars
|
|
143
|
+
# each). That costs nothing in total LLM work — the chunk count across the
|
|
144
|
+
# whole memory is unchanged, only its grouping — and each part now finishes.
|
|
145
|
+
# A part that finishes is worth strictly more than a larger part that does not.
|
|
121
146
|
DEFAULT_RETAIN_CHUNK_SIZE = 3000
|
|
122
147
|
DEFAULT_RETAIN_CHUNK_LATENCY_S = 18.4
|
|
123
148
|
DEFAULT_RETAIN_CLIENT_DEADLINE_S = 310.0
|
|
124
149
|
|
|
150
|
+
# Fraction of the client deadline a maximally-sized part may consume.
|
|
151
|
+
# Clamped to (0, 1]: a value above 1.0 would size parts to overrun the
|
|
152
|
+
# deadline outright, which is the defect this input exists to prevent.
|
|
153
|
+
DEFAULT_RETAIN_DEADLINE_SAFETY = 0.7
|
|
154
|
+
|
|
125
155
|
# Absolute floor: one chunk. A bound below one chunk would split every
|
|
126
156
|
# transcript into extraction-sized confetti and is never the right answer.
|
|
127
157
|
MIN_RETAIN_CONTENT_CHARS = DEFAULT_RETAIN_CHUNK_SIZE
|
|
@@ -151,6 +181,18 @@ def retain_client_deadline() -> float:
|
|
|
151
181
|
return _env_number("HINDSIGHT_RETAIN_CLIENT_DEADLINE_S", DEFAULT_RETAIN_CLIENT_DEADLINE_S)
|
|
152
182
|
|
|
153
183
|
|
|
184
|
+
def retain_deadline_safety() -> float:
|
|
185
|
+
"""Fraction of the client deadline a maximally-sized part may consume.
|
|
186
|
+
|
|
187
|
+
Clamped to ``(0, 1]``. A value above 1.0 is not honoured: it would size
|
|
188
|
+
parts to overrun the deadline by construction, which is exactly the defect
|
|
189
|
+
(#3693) this input exists to prevent, so it is treated as "no margin at
|
|
190
|
+
all" — 1.0 — rather than as a licence to go further.
|
|
191
|
+
"""
|
|
192
|
+
value = _env_number("HINDSIGHT_RETAIN_DEADLINE_SAFETY", DEFAULT_RETAIN_DEADLINE_SAFETY)
|
|
193
|
+
return min(1.0, value)
|
|
194
|
+
|
|
195
|
+
|
|
154
196
|
def retain_content_limit() -> int:
|
|
155
197
|
"""Max chars of retain content that can complete inside the client deadline.
|
|
156
198
|
|
|
@@ -170,7 +212,12 @@ def retain_content_limit() -> int:
|
|
|
170
212
|
latency = _env_number("HINDSIGHT_RETAIN_CHUNK_LATENCY_S", DEFAULT_RETAIN_CHUNK_LATENCY_S)
|
|
171
213
|
deadline = retain_client_deadline()
|
|
172
214
|
|
|
173
|
-
|
|
215
|
+
# A FRACTION of the deadline, not all of it (#3693). Sizing to the whole
|
|
216
|
+
# deadline leaves a maximally-sized part no headroom for the POST itself,
|
|
217
|
+
# server queueing, or a chunk slower than the MEAN `latency` is measured
|
|
218
|
+
# as — so the part times out, the drain bumps its attempt count, and it
|
|
219
|
+
# ages to `.dead`. See the derivation block at the top of this module.
|
|
220
|
+
chunks = int((deadline * retain_deadline_safety()) // latency)
|
|
174
221
|
if chunks < 1:
|
|
175
222
|
chunks = 1
|
|
176
223
|
return max(MIN_RETAIN_CONTENT_CHARS, chunk_size * chunks)
|