From 8a04c21b718f5e88583f82d0604902e0cf411041 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Mon, 22 Jun 2026 01:31:29 +0900 Subject: feat(compaction): conversation compacting + auto-compact threshold MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consume the compaction handoff (wire@0.11.0, transport-contract@0.15.0). Re-pinned file: deps + re-mirrored .dispatch/*.reference.md. - New 'Compaction' sidebar view (CompactionView.svelte): - 'Compact now' button → POST /conversations/:id/compact (loading indicator + result: 'N messages summarized, M kept') - Auto-compact threshold number input → GET/PUT /conversations/:id/compact-threshold (0 = disabled, default 350000) - Re-mounts per conversation via {#key} - App store: compactNow() + compactThreshold reactive state + setCompactThreshold(), seeded on focus change (like reasoning-effort + cwd) - conversation.compacted WS handler: reloads the SAME conversation's history (ID unchanged — old history forked to an archive, not a tab switch) - WS adapter parses newConversationId field on ConversationCompactedMessage - conformance guards + tests cover the new type 686 tests green. --- .dispatch/wire.reference.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to '.dispatch/wire.reference.md') diff --git a/.dispatch/wire.reference.md b/.dispatch/wire.reference.md index ead4d9c..44b0fe7 100644 --- a/.dispatch/wire.reference.md +++ b/.dispatch/wire.reference.md @@ -4,9 +4,14 @@ > types WITHOUT following the `file:` dep symlink out of this repo (which hangs on a permission > prompt). Your CODE still imports `@dispatch/wire` normally — this file is for READING only. > -> **Orchestrator:** SNAPSHOT of `wire@0.10.0` (conversation lifecycle status). Regenerate +> **Orchestrator:** SNAPSHOT of `wire@0.11.0` (compaction). Regenerate > whenever `@dispatch/wire` changes. > +> **2026-06-22 delta (compaction handoff — package bumped `0.10.0` → `0.11.0`, ADDITIVE):** +> adds `CompactionResult` — the result of a compaction operation (`summary`, `messagesSummarized`, +> `messagesKept`). The summary text is the model's output; the FE doesn't render it directly (it +> becomes the conversation's first system message after compaction). +> > **2026-06-22 delta (conversation lifecycle handoff — package bumped `0.9.0` → `0.10.0`, ADDITIVE):** > adds `ConversationStatus` (`"active" | "idle" | "closed"`) — the per-conversation lifecycle > status. `ConversationMeta` gains a `status` field. `active` = a turn is generating; `idle` = @@ -612,5 +617,21 @@ export interface ConversationMeta { readonly lastActivityAt: number; readonly title: string; readonly status: ConversationStatus; + /** Points to the archive conversation with full pre-compaction history. */ + readonly compactedFrom?: string; +} + +// ─── Compaction ────────────────────────────────────────────────────────────── + +/** + * Result of a compaction operation. `summary` is the text the model produced; + * `messagesKept` is how many recent messages were retained after the summary; + * `messagesSummarized` is how many old messages were replaced by the summary. + */ +export interface CompactionResult { + readonly summary: string; + readonly newConversationId: string; + readonly messagesSummarized: number; + readonly messagesKept: number; } ``` -- cgit v1.2.3