switchroom 0.19.22 → 0.19.24
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 +5 -2
- package/dist/auth-broker/index.js +95 -2
- package/dist/cli/notion-write-pretool.mjs +5 -2
- package/dist/cli/switchroom.js +749 -357
- package/dist/host-control/main.js +96 -3
- package/dist/vault/approvals/kernel-server.js +98 -5
- package/dist/vault/broker/server.js +98 -5
- 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 +12 -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 +97 -107
- package/skills/switchroom-release/SKILL.md +2 -1
- package/telegram-plugin/bunfig.toml +10 -0
- package/telegram-plugin/dist/gateway/gateway.js +267 -52
- 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 +43 -42
- package/telegram-plugin/gateway/latest-turn-lookup.ts +60 -0
- package/telegram-plugin/gateway/outbound-send-path.ts +61 -22
- package/telegram-plugin/gateway/stream-render.ts +6 -0
- package/telegram-plugin/gateway/subagent-handback-marker.ts +1 -1
- package/telegram-plugin/gateway/turn-end.ts +1 -1
- package/telegram-plugin/gateway/turn-record-status.ts +19 -0
- package/telegram-plugin/gateway/turns-jsonl-rotate.ts +65 -0
- package/telegram-plugin/reply-owner-resolve.ts +110 -9
- package/telegram-plugin/send-gate-degraded.test.ts +45 -16
- package/telegram-plugin/send-gate.ts +185 -24
- package/telegram-plugin/tests/activity-card-send-gate.test.ts +9 -9
- 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/latest-turn-lookup.test.ts +77 -0
- package/telegram-plugin/tests/narrative-lane-golden.test.ts +23 -1
- package/telegram-plugin/tests/reply-owner-resolve.test.ts +531 -0
- package/telegram-plugin/tests/send-reply-golden.test.ts +296 -28
- package/telegram-plugin/tests/stream-controller-send-gate.test.ts +134 -28
- package/telegram-plugin/tests/stream-render-golden.test.ts +25 -3
- 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
|
@@ -21042,16 +21042,19 @@ var init_schema = __esm(() => {
|
|
|
21042
21042
|
model: exports_external.string().min(1).optional().describe("Per-op model (upstream `HINDSIGHT_API_<OP>_LLM_MODEL`). Absent \u2192 " + "inherit the global `hindsight.llm.model`."),
|
|
21043
21043
|
provider: exports_external.string().min(1).optional().describe("Per-op provider (upstream `HINDSIGHT_API_<OP>_LLM_PROVIDER`). " + "Absent \u2192 inherit the global `hindsight.llm.provider`."),
|
|
21044
21044
|
base_url: exports_external.string().min(1).optional().describe("Per-op base URL (upstream `HINDSIGHT_API_<OP>_LLM_BASE_URL`). " + "Optional passthrough; absent \u2192 inherit the global."),
|
|
21045
|
-
api_key: exports_external.string().min(1).optional().describe("Per-op API key (upstream `HINDSIGHT_API_<OP>_LLM_API_KEY`). Literal " + "or `vault:` reference. Optional passthrough; absent \u2192 inherit global.")
|
|
21045
|
+
api_key: exports_external.string().min(1).optional().describe("Per-op API key (upstream `HINDSIGHT_API_<OP>_LLM_API_KEY`). Literal " + "or `vault:` reference. Optional passthrough; absent \u2192 inherit global."),
|
|
21046
|
+
context_window: exports_external.number().int().positive().optional().describe("Context window (tokens) of the backend serving THIS op. NOT an " + "upstream env var \u2014 switchroom derives the op's token budget " + "(consolidation batch size / max-completion caps / reflect " + "max-context cap) from it so a single call can never overflow the " + "window. Absent \u2192 inherit " + "`hindsight.llm.context_window`, else a per-provider default " + "(conservative for non-`claude-code` providers, which usually mean " + "a local llama.cpp/Ollama slot; a self-hosted `base_url` \u2014 loopback, " + "RFC1918, `.local`/`.internal` \u2014 forces the conservative default too, " + "regardless of the provider NAME, since the endpoint is where the " + "traffic actually terminates). All three lanes (`retain`, " + "`reflect`, `consolidation`) are budgeted independently.")
|
|
21046
21047
|
}).describe("Per-operation LLM override. Every field optional; an unset field (or " + "an omitted op block) inherits the global `hindsight.llm.*`, which is " + "already the engine's fallback \u2014 switchroom emits only the vars set.");
|
|
21047
21048
|
HindsightConfigSchema = exports_external.object({
|
|
21048
21049
|
llm: exports_external.object({
|
|
21049
21050
|
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."),
|
|
21050
21051
|
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."),
|
|
21052
|
+
context_window: exports_external.number().int().positive().optional().describe("GLOBAL context window (tokens) of the backend serving hindsight's " + "LLM ops \u2014 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 \u2192 a per-provider default: 200000 for `claude-code`, a " + "conservative 32768 for everything else. Overflowing a local " + "backend's window does NOT error \u2014 llama.cpp context-shift silently " + "drops the system prompt and the model answers conversationally " + "with HTTP 200 \u2014 so this value is what makes the failure " + "detectable at setup time instead of never."),
|
|
21051
21053
|
retain: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `retain` LLM op (memory ingestion). Emits " + "`HINDSIGHT_API_RETAIN_LLM_*`. Absent \u2192 uses the global model/provider."),
|
|
21052
21054
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent \u2192 uses global."),
|
|
21053
21055
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent \u2192 global.")
|
|
21054
|
-
}).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.")
|
|
21056
|
+
}).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."),
|
|
21057
|
+
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, " + "RECALL_MAX_CANDIDATES_PER_SOURCE, LINK_EXPANSION_PER_ENTITY_LIMIT, " + "LINK_EXPANSION_TIMEOUT, LLM_REASONING_EFFORT), the override-only keys " + "switchroom manages but ships NO default for " + "(`HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS`: " + "HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY \u2014 a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks), plus the " + "embedded-PostgreSQL (pg0) sizing keys switchroom manages in " + "src/setup/hindsight-pg-defaults.ts (`HINDSIGHT_PG_ENV_KEYS`: " + "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE, " + "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS \u2014 a postgres size string such " + "as `4GB`, or the sentinel `off` to leave pg0's own default for that " + "one knob). A value set here " + "REPLACES switchroom's default and is emitted even when the gating " + "capability is absent, so an operator can always force a knob. Other " + "`HINDSIGHT_API_*` keys are deliberately IGNORED \u2014 a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
|
|
21055
21058
|
});
|
|
21056
21059
|
MicrosoftWorkspaceConfigSchema = exports_external.object({
|
|
21057
21060
|
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 \u2014 omit it to use " + "switchroom's shipped default Microsoft app (zero-config). " + "Set it only to bring your own Entra app (BYO)."),
|
|
@@ -63264,7 +63267,8 @@ function createSendGate(config) {
|
|
|
63264
63267
|
pending: null,
|
|
63265
63268
|
running: false,
|
|
63266
63269
|
suppressedUntilMs: 0,
|
|
63267
|
-
editWindowTs: []
|
|
63270
|
+
editWindowTs: [],
|
|
63271
|
+
criticalWake: null
|
|
63268
63272
|
};
|
|
63269
63273
|
perMessage.set(key, state);
|
|
63270
63274
|
}
|
|
@@ -63350,9 +63354,11 @@ function createSendGate(config) {
|
|
|
63350
63354
|
}
|
|
63351
63355
|
}
|
|
63352
63356
|
}
|
|
63353
|
-
async function admitLoop(buckets, deadline) {
|
|
63357
|
+
async function admitLoop(buckets, deadline, interrupt) {
|
|
63354
63358
|
let counted = false;
|
|
63355
63359
|
for (;; ) {
|
|
63360
|
+
if (interrupt?.fired)
|
|
63361
|
+
return false;
|
|
63356
63362
|
const now = clock.now();
|
|
63357
63363
|
let wait = 0;
|
|
63358
63364
|
for (const b of buckets)
|
|
@@ -63368,11 +63374,12 @@ function createSendGate(config) {
|
|
|
63368
63374
|
counters.queued++;
|
|
63369
63375
|
counted = true;
|
|
63370
63376
|
}
|
|
63371
|
-
|
|
63377
|
+
const nap = clock.sleep(deadline !== undefined ? Math.min(wait, deadline - now) : wait);
|
|
63378
|
+
await (interrupt ? Promise.race([nap, interrupt.promise]) : nap);
|
|
63372
63379
|
}
|
|
63373
63380
|
}
|
|
63374
|
-
function admit(buckets) {
|
|
63375
|
-
return admitLoop(buckets);
|
|
63381
|
+
function admit(buckets, interrupt) {
|
|
63382
|
+
return admitLoop(buckets, undefined, interrupt);
|
|
63376
63383
|
}
|
|
63377
63384
|
let criticalTail = Promise.resolve();
|
|
63378
63385
|
function criticalSerialize(job) {
|
|
@@ -63390,6 +63397,24 @@ function createSendGate(config) {
|
|
|
63390
63397
|
}
|
|
63391
63398
|
})();
|
|
63392
63399
|
}
|
|
63400
|
+
function makeInterrupt() {
|
|
63401
|
+
let resolve6;
|
|
63402
|
+
const interrupt = {
|
|
63403
|
+
fired: false,
|
|
63404
|
+
promise: new Promise((r) => {
|
|
63405
|
+
resolve6 = r;
|
|
63406
|
+
})
|
|
63407
|
+
};
|
|
63408
|
+
return {
|
|
63409
|
+
interrupt,
|
|
63410
|
+
fire: () => {
|
|
63411
|
+
if (interrupt.fired)
|
|
63412
|
+
return;
|
|
63413
|
+
interrupt.fired = true;
|
|
63414
|
+
resolve6();
|
|
63415
|
+
}
|
|
63416
|
+
};
|
|
63417
|
+
}
|
|
63393
63418
|
async function admitPriority(buckets, priority) {
|
|
63394
63419
|
const now = clock.now();
|
|
63395
63420
|
if (priority === "cosmetic") {
|
|
@@ -63487,7 +63512,18 @@ function createSendGate(config) {
|
|
|
63487
63512
|
continue;
|
|
63488
63513
|
}
|
|
63489
63514
|
} else {
|
|
63490
|
-
|
|
63515
|
+
const { interrupt, fire } = makeInterrupt();
|
|
63516
|
+
state.criticalWake = fire;
|
|
63517
|
+
let admitted;
|
|
63518
|
+
try {
|
|
63519
|
+
admitted = await admit(bucketsFor(opts), interrupt);
|
|
63520
|
+
} finally {
|
|
63521
|
+
state.criticalWake = null;
|
|
63522
|
+
}
|
|
63523
|
+
if (!admitted) {
|
|
63524
|
+
supersede(state, p);
|
|
63525
|
+
continue;
|
|
63526
|
+
}
|
|
63491
63527
|
}
|
|
63492
63528
|
state.lastSentMs = clock.now();
|
|
63493
63529
|
if (perMessageEditMaxPerWindow > 0 && p.priorityClass === "cosmetic") {
|
|
@@ -63512,6 +63548,31 @@ function createSendGate(config) {
|
|
|
63512
63548
|
state.running = false;
|
|
63513
63549
|
}
|
|
63514
63550
|
}
|
|
63551
|
+
function supersede(state, p) {
|
|
63552
|
+
const next = state.pending;
|
|
63553
|
+
if (!next) {
|
|
63554
|
+
state.pending = p;
|
|
63555
|
+
return;
|
|
63556
|
+
}
|
|
63557
|
+
next.priorityClass = maxPriority(next.priorityClass, p.priorityClass);
|
|
63558
|
+
next.promise.then(p.resolve, p.reject);
|
|
63559
|
+
}
|
|
63560
|
+
function editUnderPressure(state, opts, now) {
|
|
63561
|
+
if (state.suppressedUntilMs > now)
|
|
63562
|
+
return true;
|
|
63563
|
+
for (const b of bucketsFor(opts)) {
|
|
63564
|
+
if (b.msUntilAvailable(now) > 0)
|
|
63565
|
+
return true;
|
|
63566
|
+
}
|
|
63567
|
+
return false;
|
|
63568
|
+
}
|
|
63569
|
+
function settleForCaller(state, pending, opts, priority, now) {
|
|
63570
|
+
if (priority !== "cosmetic" || !editUnderPressure(state, opts, now)) {
|
|
63571
|
+
return pending.promise;
|
|
63572
|
+
}
|
|
63573
|
+
pending.promise.catch(() => {});
|
|
63574
|
+
return Promise.resolve(undefined);
|
|
63575
|
+
}
|
|
63515
63576
|
function handleEdit(fn, opts) {
|
|
63516
63577
|
const messageId = opts.messageId;
|
|
63517
63578
|
const key = messageKey(opts.chat_id, messageId);
|
|
@@ -63520,16 +63581,6 @@ function createSendGate(config) {
|
|
|
63520
63581
|
const existing = perMessage.get(key);
|
|
63521
63582
|
maybeEvict(now, existing === undefined);
|
|
63522
63583
|
const state = existing ?? messageState(key);
|
|
63523
|
-
if ((opts.priorityClass ?? "useful") === "cosmetic") {
|
|
63524
|
-
let wait = 0;
|
|
63525
|
-
for (const b of bucketsFor(opts))
|
|
63526
|
-
wait = Math.max(wait, b.msUntilAvailable(now));
|
|
63527
|
-
const msgWait = state.suppressedUntilMs > now ? state.suppressedUntilMs - now : 0;
|
|
63528
|
-
if (wait > 0 || msgWait > 0) {
|
|
63529
|
-
counters.shed++;
|
|
63530
|
-
return Promise.resolve(SEND_GATE_SHED2);
|
|
63531
|
-
}
|
|
63532
|
-
}
|
|
63533
63584
|
if (state.pending) {
|
|
63534
63585
|
state.pending.priorityClass = maxPriority(state.pending.priorityClass, opts.priorityClass ?? "useful");
|
|
63535
63586
|
if (state.pending.hash !== hash) {
|
|
@@ -63537,7 +63588,9 @@ function createSendGate(config) {
|
|
|
63537
63588
|
state.pending.hash = hash;
|
|
63538
63589
|
state.pending.fn = fn;
|
|
63539
63590
|
}
|
|
63540
|
-
|
|
63591
|
+
if (state.pending.priorityClass === "critical")
|
|
63592
|
+
state.criticalWake?.();
|
|
63593
|
+
return settleForCaller(state, state.pending, opts, opts.priorityClass ?? "useful", now);
|
|
63541
63594
|
}
|
|
63542
63595
|
if (hash === state.lastHash) {
|
|
63543
63596
|
counters.dropped++;
|
|
@@ -63558,9 +63611,13 @@ function createSendGate(config) {
|
|
|
63558
63611
|
priorityClass: opts.priorityClass ?? "useful"
|
|
63559
63612
|
};
|
|
63560
63613
|
state.pending = pending;
|
|
63561
|
-
if (
|
|
63614
|
+
if (state.running) {
|
|
63615
|
+
if (pending.priorityClass === "critical")
|
|
63616
|
+
state.criticalWake?.();
|
|
63617
|
+
} else {
|
|
63562
63618
|
drive(state, opts);
|
|
63563
|
-
|
|
63619
|
+
}
|
|
63620
|
+
return settleForCaller(state, pending, opts, pending.priorityClass, now);
|
|
63564
63621
|
}
|
|
63565
63622
|
async function gate(fn, opts) {
|
|
63566
63623
|
if (!enabled2)
|
|
@@ -75868,6 +75925,30 @@ function makeKey3(chatId, threadId) {
|
|
|
75868
75925
|
}
|
|
75869
75926
|
|
|
75870
75927
|
// reply-owner-resolve.ts
|
|
75928
|
+
function latestEndedAccepted(candidates) {
|
|
75929
|
+
if (candidates.latestEndedTurnId == null)
|
|
75930
|
+
return false;
|
|
75931
|
+
const age = candidates.latestEndedAgeMs;
|
|
75932
|
+
const ttl = candidates.latestEndedTtlMs;
|
|
75933
|
+
if (age === null)
|
|
75934
|
+
return false;
|
|
75935
|
+
if (age === undefined || ttl == null)
|
|
75936
|
+
return true;
|
|
75937
|
+
return age <= ttl;
|
|
75938
|
+
}
|
|
75939
|
+
function decideContentGateBypass(input) {
|
|
75940
|
+
if (input.tier === "live")
|
|
75941
|
+
return true;
|
|
75942
|
+
if (input.tier === "none")
|
|
75943
|
+
return false;
|
|
75944
|
+
if (input.handbackCouldOwnReply)
|
|
75945
|
+
return false;
|
|
75946
|
+
if (input.candidates == null)
|
|
75947
|
+
return false;
|
|
75948
|
+
if (!latestEndedAccepted(input.candidates))
|
|
75949
|
+
return false;
|
|
75950
|
+
return input.resolvedTurnId != null && input.resolvedTurnId === input.candidates.latestEndedTurnId;
|
|
75951
|
+
}
|
|
75871
75952
|
function decideAnswerLatchSuppression(input) {
|
|
75872
75953
|
if (input.superseded)
|
|
75873
75954
|
return false;
|
|
@@ -76376,7 +76457,9 @@ function createBackstopReadBack(w) {
|
|
|
76376
76457
|
};
|
|
76377
76458
|
try {
|
|
76378
76459
|
const r = await w.gate(() => w.editMessageText(messageId, body, editApiOpts), gateOpts);
|
|
76379
|
-
|
|
76460
|
+
if (w.isShed(r) || r === undefined)
|
|
76461
|
+
return "ambiguous";
|
|
76462
|
+
return "exists";
|
|
76380
76463
|
} catch (err) {
|
|
76381
76464
|
return classifyReadBackError(err);
|
|
76382
76465
|
}
|
|
@@ -76497,14 +76580,23 @@ async function sendReply(deps, req) {
|
|
|
76497
76580
|
let supersedeFlushIds = [];
|
|
76498
76581
|
{
|
|
76499
76582
|
const replyThreadId = args.message_thread_id != null ? Number(args.message_thread_id) : undefined;
|
|
76500
|
-
const {
|
|
76583
|
+
const {
|
|
76584
|
+
turn: ownerTurn,
|
|
76585
|
+
tier: ownerTier,
|
|
76586
|
+
candidates: ownerCandidates
|
|
76587
|
+
} = resolveReplyOwnerTurn(turn, chat_id, args);
|
|
76501
76588
|
const resolvedTurnId = ownerTurn?.turnId ?? null;
|
|
76502
76589
|
const ownerEndedAt = ownerTurn?.endedAt ?? null;
|
|
76503
76590
|
const gateThreadId = ownerTurn?.sessionThreadId ?? replyThreadId;
|
|
76504
76591
|
const handbackAt = getLastSubagentHandbackAt(chat_id);
|
|
76505
76592
|
const now = Date.now();
|
|
76506
76593
|
const handbackCouldOwnReply = handbackAt != null && ownerEndedAt != null && handbackAt > ownerEndedAt && now - handbackAt <= DEFAULT_SUPERSEDE_TTL_MS2;
|
|
76507
|
-
const replyIsOwnAnswer =
|
|
76594
|
+
const replyIsOwnAnswer = decideContentGateBypass({
|
|
76595
|
+
tier: ownerTier,
|
|
76596
|
+
resolvedTurnId,
|
|
76597
|
+
candidates: ownerCandidates,
|
|
76598
|
+
handbackCouldOwnReply
|
|
76599
|
+
});
|
|
76508
76600
|
const decision = flushedTurnSupersede.take(chat_id, gateThreadId, { liveTurnId: resolvedTurnId, replyText: text4, positiveAttribution: replyIsOwnAnswer, now });
|
|
76509
76601
|
if (decision.supersede) {
|
|
76510
76602
|
process.stderr.write(`telegram gateway: reply: superseding flushed turn message(s) ` + `chatId=${chat_id} ids=${JSON.stringify(decision.deleteMessageIds)}
|
|
@@ -76529,7 +76621,7 @@ async function sendReply(deps, req) {
|
|
|
76529
76621
|
replyMatchesFlushedAnswer
|
|
76530
76622
|
});
|
|
76531
76623
|
if (decision.reason === "new-content") {
|
|
76532
|
-
process.stderr.write(`telegram gateway: reply: flush supersede declined \u2014 new content (#3429) ` + `chatId=${chat_id} ownerTurnId=${JSON.stringify(resolvedTurnId)}; sending fresh
|
|
76624
|
+
process.stderr.write(`telegram gateway: reply: flush supersede declined \u2014 new content (#3429) ` + `chatId=${chat_id} ownerTurnId=${JSON.stringify(resolvedTurnId)} ` + `tier=${ownerTier} latestEnded=${JSON.stringify(ownerCandidates.latestEndedTurnId)} ` + `handbackInWindow=${handbackCouldOwnReply}; sending fresh
|
|
76533
76625
|
`);
|
|
76534
76626
|
}
|
|
76535
76627
|
if (suppressByLatch) {
|
|
@@ -79124,6 +79216,7 @@ function handleSessionEvent(deps, ev) {
|
|
|
79124
79216
|
sentIds = delivery.sentIds;
|
|
79125
79217
|
chunkCount = delivery.chunkCount;
|
|
79126
79218
|
delivered = delivery.delivered;
|
|
79219
|
+
turn.landedUnconfirmed = delivery.landedUnconfirmed;
|
|
79127
79220
|
outboundDedup.record(backstopChatId, backstopThreadId, capturedText, Date.now(), getCurrentTurn()?.registryKey ?? null);
|
|
79128
79221
|
if (sentIds.length > 0) {
|
|
79129
79222
|
flushedTurnSupersede.record(backstopChatId, backstopThreadId, { turnId: turn.turnId, messageIds: sentIds, text: capturedText }, Date.now());
|
|
@@ -80058,12 +80151,14 @@ function isTurnFlushSafetyEnabled(env = process.env) {
|
|
|
80058
80151
|
}
|
|
80059
80152
|
|
|
80060
80153
|
// reply-owner-resolve.ts
|
|
80061
|
-
function
|
|
80154
|
+
function latestEndedAccepted2(candidates) {
|
|
80062
80155
|
if (candidates.latestEndedTurnId == null)
|
|
80063
80156
|
return false;
|
|
80064
80157
|
const age = candidates.latestEndedAgeMs;
|
|
80065
80158
|
const ttl = candidates.latestEndedTtlMs;
|
|
80066
|
-
if (age
|
|
80159
|
+
if (age === null)
|
|
80160
|
+
return false;
|
|
80161
|
+
if (age === undefined || ttl == null)
|
|
80067
80162
|
return true;
|
|
80068
80163
|
return age <= ttl;
|
|
80069
80164
|
}
|
|
@@ -80074,7 +80169,7 @@ function resolveReplyOwnerTier(candidates) {
|
|
|
80074
80169
|
return "origin";
|
|
80075
80170
|
if (candidates.quotedTurnId != null)
|
|
80076
80171
|
return "quoted";
|
|
80077
|
-
if (
|
|
80172
|
+
if (latestEndedAccepted2(candidates))
|
|
80078
80173
|
return "latest-ended";
|
|
80079
80174
|
return "none";
|
|
80080
80175
|
}
|
|
@@ -83021,6 +83116,99 @@ function assertPositive(value, label) {
|
|
|
83021
83116
|
}
|
|
83022
83117
|
}
|
|
83023
83118
|
|
|
83119
|
+
// ../src/setup/host-capabilities.ts
|
|
83120
|
+
init_paths();
|
|
83121
|
+
|
|
83122
|
+
// ../src/setup/hindsight-perf-defaults.ts
|
|
83123
|
+
var HINDSIGHT_RERANKER_MAX_CANDIDATES_FOR_DERIVATION = 150;
|
|
83124
|
+
var HINDSIGHT_DEFAULT_RECALL_MAX_CANDIDATES_PER_SOURCE = Math.ceil(HINDSIGHT_RERANKER_MAX_CANDIDATES_FOR_DERIVATION * 0.4);
|
|
83125
|
+
var HINDSIGHT_DEFAULT_LINK_EXPANSION_PER_ENTITY_LIMIT = 50;
|
|
83126
|
+
var HINDSIGHT_DEFAULT_LINK_EXPANSION_TIMEOUT_S = 2;
|
|
83127
|
+
var HINDSIGHT_DEFAULT_LLM_REASONING_EFFORT = "low";
|
|
83128
|
+
var HINDSIGHT_DEFAULT_LLM_MAX_CONCURRENT = 4;
|
|
83129
|
+
var HINDSIGHT_DEFAULT_RETAIN_LLM_MAX_CONCURRENT = 1;
|
|
83130
|
+
var HINDSIGHT_DEFAULT_CONSOLIDATION_LLM_MAX_CONCURRENT = 1;
|
|
83131
|
+
var HINDSIGHT_DEFAULT_RERANKER_LOCAL_FP16 = "true";
|
|
83132
|
+
var HINDSIGHT_DEFAULT_RERANKER_LOCAL_BATCH_SIZE = 128;
|
|
83133
|
+
var HINDSIGHT_DEFAULT_LLM_STRICT_SCHEMA = "true";
|
|
83134
|
+
var HINDSIGHT_DEFAULT_LLM_MAX_RETRIES = 2;
|
|
83135
|
+
var HINDSIGHT_DEFAULT_CONSOLIDATION_LLM_PARALLELISM = 2;
|
|
83136
|
+
var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
83137
|
+
[
|
|
83138
|
+
"HINDSIGHT_API_RECALL_MAX_CANDIDATES_PER_SOURCE",
|
|
83139
|
+
String(HINDSIGHT_DEFAULT_RECALL_MAX_CANDIDATES_PER_SOURCE)
|
|
83140
|
+
],
|
|
83141
|
+
[
|
|
83142
|
+
"HINDSIGHT_API_LINK_EXPANSION_PER_ENTITY_LIMIT",
|
|
83143
|
+
String(HINDSIGHT_DEFAULT_LINK_EXPANSION_PER_ENTITY_LIMIT)
|
|
83144
|
+
],
|
|
83145
|
+
[
|
|
83146
|
+
"HINDSIGHT_API_LINK_EXPANSION_TIMEOUT",
|
|
83147
|
+
String(HINDSIGHT_DEFAULT_LINK_EXPANSION_TIMEOUT_S)
|
|
83148
|
+
],
|
|
83149
|
+
["HINDSIGHT_API_LLM_REASONING_EFFORT", HINDSIGHT_DEFAULT_LLM_REASONING_EFFORT],
|
|
83150
|
+
[
|
|
83151
|
+
"HINDSIGHT_API_CONSOLIDATION_LLM_PARALLELISM",
|
|
83152
|
+
String(HINDSIGHT_DEFAULT_CONSOLIDATION_LLM_PARALLELISM)
|
|
83153
|
+
]
|
|
83154
|
+
];
|
|
83155
|
+
var HINDSIGHT_PERF_DEFAULTS_GPU = [
|
|
83156
|
+
["HINDSIGHT_API_RERANKER_LOCAL_FP16", HINDSIGHT_DEFAULT_RERANKER_LOCAL_FP16],
|
|
83157
|
+
[
|
|
83158
|
+
"HINDSIGHT_API_RERANKER_LOCAL_BATCH_SIZE",
|
|
83159
|
+
String(HINDSIGHT_DEFAULT_RERANKER_LOCAL_BATCH_SIZE)
|
|
83160
|
+
]
|
|
83161
|
+
];
|
|
83162
|
+
var HINDSIGHT_PERF_DEFAULTS_LOCAL_LLM = [
|
|
83163
|
+
["HINDSIGHT_API_LLM_MAX_CONCURRENT", String(HINDSIGHT_DEFAULT_LLM_MAX_CONCURRENT)],
|
|
83164
|
+
[
|
|
83165
|
+
"HINDSIGHT_API_RETAIN_LLM_MAX_CONCURRENT",
|
|
83166
|
+
String(HINDSIGHT_DEFAULT_RETAIN_LLM_MAX_CONCURRENT)
|
|
83167
|
+
],
|
|
83168
|
+
[
|
|
83169
|
+
"HINDSIGHT_API_CONSOLIDATION_LLM_MAX_CONCURRENT",
|
|
83170
|
+
String(HINDSIGHT_DEFAULT_CONSOLIDATION_LLM_MAX_CONCURRENT)
|
|
83171
|
+
],
|
|
83172
|
+
["HINDSIGHT_API_LLM_STRICT_SCHEMA", HINDSIGHT_DEFAULT_LLM_STRICT_SCHEMA],
|
|
83173
|
+
["HINDSIGHT_API_LLM_MAX_RETRIES", String(HINDSIGHT_DEFAULT_LLM_MAX_RETRIES)]
|
|
83174
|
+
];
|
|
83175
|
+
var HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS = new Set([
|
|
83176
|
+
"HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY"
|
|
83177
|
+
]);
|
|
83178
|
+
var HINDSIGHT_PERF_ENV_KEYS = new Set([
|
|
83179
|
+
...[
|
|
83180
|
+
...HINDSIGHT_PERF_DEFAULTS_UNGATED,
|
|
83181
|
+
...HINDSIGHT_PERF_DEFAULTS_GPU,
|
|
83182
|
+
...HINDSIGHT_PERF_DEFAULTS_LOCAL_LLM
|
|
83183
|
+
].map(([k]) => k),
|
|
83184
|
+
...HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS
|
|
83185
|
+
]);
|
|
83186
|
+
|
|
83187
|
+
// ../src/setup/hindsight-pg-defaults.ts
|
|
83188
|
+
var HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION = 8 * 1024;
|
|
83189
|
+
var HINDSIGHT_PG_APP_ANON_MIB = 2560;
|
|
83190
|
+
var HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB = 2048;
|
|
83191
|
+
var HINDSIGHT_PG_SHARED_BUFFERS_BUDGET_MIB = HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION - HINDSIGHT_PG_APP_ANON_MIB - HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB;
|
|
83192
|
+
var HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 1536;
|
|
83193
|
+
var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 4096;
|
|
83194
|
+
function pgMib(mib) {
|
|
83195
|
+
return `${mib}MB`;
|
|
83196
|
+
}
|
|
83197
|
+
var HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE_ENV = "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE";
|
|
83198
|
+
var HINDSIGHT_PG_SHARED_BUFFERS_ENV = "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS";
|
|
83199
|
+
var HINDSIGHT_PG_DEFAULTS = [
|
|
83200
|
+
[
|
|
83201
|
+
HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE_ENV,
|
|
83202
|
+
pgMib(HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB)
|
|
83203
|
+
],
|
|
83204
|
+
[HINDSIGHT_PG_SHARED_BUFFERS_ENV, pgMib(HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB)]
|
|
83205
|
+
];
|
|
83206
|
+
var HINDSIGHT_PG_ENV_KEYS = new Set(HINDSIGHT_PG_DEFAULTS.map(([k]) => k));
|
|
83207
|
+
|
|
83208
|
+
// ../src/setup/hindsight-context-budget.ts
|
|
83209
|
+
var HINDSIGHT_UPSTREAM_RETAIN_CHUNK_SIZE = 3000;
|
|
83210
|
+
var HINDSIGHT_RETAIN_MAX_COMPLETION_FLOOR = HINDSIGHT_UPSTREAM_RETAIN_CHUNK_SIZE + 72;
|
|
83211
|
+
|
|
83024
83212
|
// ../src/setup/hindsight.ts
|
|
83025
83213
|
var HINDSIGHT_DEFAULT_API_PORT = 18888;
|
|
83026
83214
|
var HINDSIGHT_DEFAULT_MCP_URL = `http://127.0.0.1:${HINDSIGHT_DEFAULT_API_PORT}/mcp/`;
|
|
@@ -87593,10 +87781,10 @@ function createCapturedResumeDispatcher(ports) {
|
|
|
87593
87781
|
if (delivered) {
|
|
87594
87782
|
ports.obligationLedger.close(o.originTurnId);
|
|
87595
87783
|
ports.backstopDeliveryLedger.clear(o.originTurnId);
|
|
87596
|
-
stderr(`telegram gateway: captured-answer resume delivered \u2014 origin=${o.originTurnId} ` + `${sentIds.length}
|
|
87784
|
+
stderr(`telegram gateway: captured-answer resume delivered \u2014 origin=${o.originTurnId} ` + `${sentIds.length} message id(s) landed; obligation closed
|
|
87597
87785
|
`);
|
|
87598
87786
|
} else {
|
|
87599
|
-
stderr(`telegram gateway: captured-answer resume partial \u2014 origin=${o.originTurnId} ` + `tail still not
|
|
87787
|
+
stderr(`telegram gateway: captured-answer resume partial \u2014 origin=${o.originTurnId} ` + `tail still not landed; left OPEN for retry
|
|
87600
87788
|
`);
|
|
87601
87789
|
}
|
|
87602
87790
|
} catch (err) {
|
|
@@ -88467,8 +88655,29 @@ function resolveAnswerThreadId(input) {
|
|
|
88467
88655
|
return input.liveThreadId;
|
|
88468
88656
|
}
|
|
88469
88657
|
|
|
88658
|
+
// gateway/latest-turn-lookup.ts
|
|
88659
|
+
function latestTurnForChat(turns, chatId, opts) {
|
|
88660
|
+
let latest = null;
|
|
88661
|
+
for (const t of turns) {
|
|
88662
|
+
if (t.sessionChatId !== chatId)
|
|
88663
|
+
continue;
|
|
88664
|
+
if (opts.endedOnly && t.endedAt == null)
|
|
88665
|
+
continue;
|
|
88666
|
+
latest = t;
|
|
88667
|
+
}
|
|
88668
|
+
return latest;
|
|
88669
|
+
}
|
|
88670
|
+
|
|
88470
88671
|
// gateway/turns-jsonl-rotate.ts
|
|
88471
88672
|
var TURNS_JSONL_MAX_BYTES = 5 * 1024 * 1024;
|
|
88673
|
+
var DEFAULT_AGENT_STATE_DIR = "/state/agent";
|
|
88674
|
+
function resolveAgentStateDir(env = process.env) {
|
|
88675
|
+
const dir = env.SWITCHROOM_AGENT_STATE_DIR?.trim();
|
|
88676
|
+
return dir != null && dir !== "" ? dir.replace(/\/+$/, "") : DEFAULT_AGENT_STATE_DIR;
|
|
88677
|
+
}
|
|
88678
|
+
function resolveTurnsJsonlPath(env = process.env) {
|
|
88679
|
+
return `${resolveAgentStateDir(env)}/turns.jsonl`;
|
|
88680
|
+
}
|
|
88472
88681
|
function maybeRotate(path3, fs3, maxBytes = TURNS_JSONL_MAX_BYTES) {
|
|
88473
88682
|
const size = fs3.statSize(path3);
|
|
88474
88683
|
if (size == null || size < maxBytes)
|
|
@@ -88497,7 +88706,8 @@ function buildTurnRecord(turn, endedAt) {
|
|
|
88497
88706
|
duration_ms: turn.startedAt > 0 ? endedAt - turn.startedAt : 0,
|
|
88498
88707
|
tools: turn.toolCallCount ?? 0,
|
|
88499
88708
|
status: computeTurnStatus(turn),
|
|
88500
|
-
turn_id: turn.turnId
|
|
88709
|
+
turn_id: turn.turnId,
|
|
88710
|
+
...turn.landedUnconfirmed != null && turn.landedUnconfirmed > 0 ? { landed_unconfirmed: turn.landedUnconfirmed } : {}
|
|
88501
88711
|
};
|
|
88502
88712
|
}
|
|
88503
88713
|
|
|
@@ -88679,8 +88889,16 @@ async function runBackstopDelivery(ledger, turnId, chunks, cardMessageId, deps,
|
|
|
88679
88889
|
break;
|
|
88680
88890
|
}
|
|
88681
88891
|
const sentIds = ledger.sentIds(turnId);
|
|
88682
|
-
const
|
|
88892
|
+
const confirmed = ledger.allConfirmed(turnId, chunkCount);
|
|
88893
|
+
const allLanded = chunkCount > 0 && ledger.unsentIndices(turnId, chunkCount).length === 0;
|
|
88894
|
+
const delivered = allLanded && backstopReceiptIds(sentIds, cardMessageId).length > 0;
|
|
88683
88895
|
const exhausted = !delivered;
|
|
88896
|
+
const confirmedSet = new Set(ledger.confirmedIds(turnId));
|
|
88897
|
+
const landedUnconfirmedIds = sentIds.filter((id) => !confirmedSet.has(id));
|
|
88898
|
+
if (delivered && !confirmed) {
|
|
88899
|
+
stderr(`telegram gateway: backstop delivery landed-unconfirmed for turn ${turnId} \u2014 ` + `every chunk returned a fresh message id but the read-back probe was ` + `inconclusive for ${landedUnconfirmedIds.length} of ${sentIds.length} landed ` + `id(s); counting it delivered (an ambiguous probe is not a failure)
|
|
88900
|
+
`);
|
|
88901
|
+
}
|
|
88684
88902
|
if (deps.recordOutbound && sentIds.length > 0) {
|
|
88685
88903
|
const texts = [];
|
|
88686
88904
|
const ids = [];
|
|
@@ -88692,7 +88910,7 @@ async function runBackstopDelivery(ledger, turnId, chunks, cardMessageId, deps,
|
|
|
88692
88910
|
}
|
|
88693
88911
|
deps.recordOutbound(ids, texts);
|
|
88694
88912
|
}
|
|
88695
|
-
return { sentIds, chunkCount, delivered, attempts, exhausted };
|
|
88913
|
+
return { sentIds, chunkCount, delivered, confirmed, landedUnconfirmedIds, attempts, exhausted };
|
|
88696
88914
|
}
|
|
88697
88915
|
|
|
88698
88916
|
// gateway/inbound-delivery-confirm.ts
|
|
@@ -96331,10 +96549,10 @@ function startOutboxSweep(deps) {
|
|
|
96331
96549
|
}
|
|
96332
96550
|
|
|
96333
96551
|
// ../src/build-info.ts
|
|
96334
|
-
var VERSION2 = "0.19.
|
|
96335
|
-
var COMMIT_SHA = "
|
|
96336
|
-
var COMMIT_DATE = "2026-07-
|
|
96337
|
-
var LATEST_PR =
|
|
96552
|
+
var VERSION2 = "0.19.24";
|
|
96553
|
+
var COMMIT_SHA = "0fa8ffb8";
|
|
96554
|
+
var COMMIT_DATE = "2026-07-27T05:19:34Z";
|
|
96555
|
+
var LATEST_PR = 3744;
|
|
96338
96556
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
96339
96557
|
|
|
96340
96558
|
// gateway/boot-version.ts
|
|
@@ -98194,7 +98412,7 @@ var STATE_DIR = process.env.TELEGRAM_STATE_DIR ?? join65(homedir19(), ".claude",
|
|
|
98194
98412
|
var permCardStore = createPermissionCardStore(STATE_DIR);
|
|
98195
98413
|
var BLOCKED_APPROVALS_DIR = process.env.SWITCHROOM_BLOCKED_APPROVALS_DIR ?? "/state/blocked-approvals";
|
|
98196
98414
|
var AGENT_NAME = process.env.SWITCHROOM_AGENT_NAME ?? "agent";
|
|
98197
|
-
var blockedApprovalStore = createBlockedApprovalStore(BLOCKED_APPROVALS_DIR, AGENT_NAME,
|
|
98415
|
+
var blockedApprovalStore = createBlockedApprovalStore(BLOCKED_APPROVALS_DIR, AGENT_NAME, resolveAgentStateDir());
|
|
98198
98416
|
function reconcileBlockedApprovals() {
|
|
98199
98417
|
const oldest = selectOldestHeld(pendingPermissions);
|
|
98200
98418
|
if (oldest == null) {
|
|
@@ -98975,7 +99193,8 @@ async function deliverAnswer(args) {
|
|
|
98975
99193
|
sentIds: result.sentIds,
|
|
98976
99194
|
chunkCount: result.chunkCount,
|
|
98977
99195
|
delivered: result.delivered,
|
|
98978
|
-
exhausted: result.exhausted
|
|
99196
|
+
exhausted: result.exhausted,
|
|
99197
|
+
landedUnconfirmed: result.landedUnconfirmedIds.length
|
|
98979
99198
|
};
|
|
98980
99199
|
}
|
|
98981
99200
|
var chatAvailableReactions = new Map;
|
|
@@ -99304,18 +99523,13 @@ function findTurnByOriginId(originTurnId) {
|
|
|
99304
99523
|
return recentTurnsById.get(originTurnId) ?? null;
|
|
99305
99524
|
}
|
|
99306
99525
|
var LATE_REPLY_TOPIC_RECOVERY_ENABLED = process.env.SWITCHROOM_LATE_REPLY_TOPIC_RECOVERY !== "0";
|
|
99307
|
-
function
|
|
99308
|
-
|
|
99309
|
-
for (const t of recentTurnsById.values()) {
|
|
99310
|
-
if (t.sessionChatId === chatId)
|
|
99311
|
-
latest = t;
|
|
99312
|
-
}
|
|
99313
|
-
return latest;
|
|
99526
|
+
function findLatestTurnForChat(chatId, opts) {
|
|
99527
|
+
return latestTurnForChat(recentTurnsById.values(), chatId, opts);
|
|
99314
99528
|
}
|
|
99315
99529
|
function resolveReplyOwnerTurn(liveTurn, chatId, args) {
|
|
99316
99530
|
const origin = findTurnByOriginId(args.origin_turn_id);
|
|
99317
99531
|
const quoted = findTurnByQuotedMessageId(chatId, args.reply_to);
|
|
99318
|
-
const latestEnded =
|
|
99532
|
+
const latestEnded = findLatestTurnForChat(chatId, { endedOnly: true });
|
|
99319
99533
|
const byId = new Map;
|
|
99320
99534
|
for (const t of [latestEnded, quoted, origin, liveTurn]) {
|
|
99321
99535
|
if (t != null)
|
|
@@ -99332,10 +99546,10 @@ function resolveReplyOwnerTurn(liveTurn, chatId, args) {
|
|
|
99332
99546
|
};
|
|
99333
99547
|
const tier = resolveReplyOwnerTier(candidates);
|
|
99334
99548
|
const winnerId = resolveReplyOwnerTurnId(candidates);
|
|
99335
|
-
return { turn: winnerId != null ? byId.get(winnerId) ?? null : null, tier };
|
|
99549
|
+
return { turn: winnerId != null ? byId.get(winnerId) ?? null : null, tier, candidates };
|
|
99336
99550
|
}
|
|
99337
99551
|
function resolveAnswerThreadWithLog(chatId, explicitThreadId, originTurn, originVia, liveTurn, surface) {
|
|
99338
|
-
const recovered = LATE_REPLY_TOPIC_RECOVERY_ENABLED && explicitThreadId == null && originTurn == null && liveTurn == null ?
|
|
99552
|
+
const recovered = LATE_REPLY_TOPIC_RECOVERY_ENABLED && explicitThreadId == null && originTurn == null && liveTurn == null ? findLatestTurnForChat(chatId, { endedOnly: false }) : null;
|
|
99339
99553
|
const threadId = resolveAnswerThreadId({
|
|
99340
99554
|
explicitThreadId,
|
|
99341
99555
|
originResolved: originTurn != null,
|
|
@@ -99802,7 +100016,7 @@ function snapshotContextOccupancy() {
|
|
|
99802
100016
|
} catch {
|
|
99803
100017
|
cap = null;
|
|
99804
100018
|
}
|
|
99805
|
-
const stateDir =
|
|
100019
|
+
const stateDir = resolveAgentStateDir();
|
|
99806
100020
|
writeContextOccupancySnapshot(stateDir, buildContextOccupancy(occupancy, cap, Date.now()));
|
|
99807
100021
|
} catch {}
|
|
99808
100022
|
}
|
|
@@ -99814,10 +100028,11 @@ function emitTurnRecord(turn, endedAt) {
|
|
|
99814
100028
|
toolCallCount: turn.toolCallCount ?? 0,
|
|
99815
100029
|
turnId: turn.turnId,
|
|
99816
100030
|
finalAnswerDelivered: turn.finalAnswerDelivered,
|
|
99817
|
-
deliveryOutcome: turn.deliveryOutcome
|
|
100031
|
+
deliveryOutcome: turn.deliveryOutcome,
|
|
100032
|
+
landedUnconfirmed: turn.landedUnconfirmed
|
|
99818
100033
|
}, endedAt)) + `
|
|
99819
100034
|
`;
|
|
99820
|
-
const turnsPath =
|
|
100035
|
+
const turnsPath = resolveTurnsJsonlPath();
|
|
99821
100036
|
maybeRotate(turnsPath, {
|
|
99822
100037
|
statSize: (p) => {
|
|
99823
100038
|
try {
|