summaryrefslogtreecommitdiffhomepage
path: root/.dispatch
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-22 01:31:29 +0900
committerAdam Malczewski <[email protected]>2026-06-22 01:31:29 +0900
commit2772e0723cfc7898443320515e165a625de1db46 (patch)
treec65e8a7c1a9ffb1ca6b44147cd3eb8629aa47830 /.dispatch
parent54e88b71efd9a6fd9d880b6e90d844a875808662 (diff)
downloaddispatch-web-2772e0723cfc7898443320515e165a625de1db46.tar.gz
dispatch-web-2772e0723cfc7898443320515e165a625de1db46.zip
feat(compaction): conversation compacting + auto-compact threshold
Consume the compaction handoff ([email protected], [email protected]). 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.
Diffstat (limited to '.dispatch')
-rw-r--r--.dispatch/transport-contract.reference.md43
-rw-r--r--.dispatch/wire.reference.md23
2 files changed, 63 insertions, 3 deletions
diff --git a/.dispatch/transport-contract.reference.md b/.dispatch/transport-contract.reference.md
index e599eb3..608211d 100644
--- a/.dispatch/transport-contract.reference.md
+++ b/.dispatch/transport-contract.reference.md
@@ -5,10 +5,18 @@
> hangs on a permission prompt). Your CODE still imports `@dispatch/transport-contract` normally —
> this file is for READING only.
>
-> **Orchestrator:** SNAPSHOT of `[email protected]` (conversation lifecycle).
-> Depends on `@dispatch/[email protected]` (see `wire.reference.md`) + `@dispatch/[email protected]` (see
+> **Orchestrator:** SNAPSHOT of `[email protected]` (compaction).
+> Depends on `@dispatch/[email protected]` (see `wire.reference.md`) + `@dispatch/[email protected]` (see
> `ui-contract.reference.md`).
>
+> **2026-06-22 delta (compaction handoff — package bumped `0.14.0` → `0.15.0`, ADDITIVE):**
+> adds conversation compaction — summarize old history + retain recent N messages. Manual:
+> `POST /conversations/:id/compact` (optional `{ keepLastN, modelName }`) → `CompactResponse`.
+> Automatic: after each turn settles, if the last turn's input tokens exceeded the per-conversation
+> `compactThreshold`, compaction runs automatically. `GET`/`PUT /conversations/:id/compact-threshold`
+> (`CompactThresholdResponse`/`SetCompactThresholdRequest`) — `threshold: 0` = disabled; default
+> 350000 when not stored. Re-exports `CompactionResult` from `[email protected]`.
+>
> **2026-06-22 delta (conversation lifecycle handoff — package bumped `0.13.0` → `0.14.0`, ADDITIVE):**
> adds conversation lifecycle **status** (`active`/`idle`/`closed`) for cross-device tab
> persistence. `ConversationMeta` (re-exported from `[email protected]`) gains a `status` field. New
@@ -712,6 +720,7 @@ export interface ConversationStatusChangedMessage {
export interface ConversationCompactedMessage {
readonly type: "conversation.compacted";
readonly conversationId: string;
+ readonly newConversationId: string;
readonly messagesSummarized: number;
readonly messagesKept: number;
}
@@ -760,4 +769,34 @@ export interface TitleResponse {
readonly conversationId: string;
readonly title: string;
}
+
+// ─── Compaction ──────────────────────────────────────────────────────────────
+
+/**
+ * Response for `POST /conversations/:id/compact` — confirms the conversation
+ * history was compacted (old messages summarized, recent messages retained).
+ */
+export interface CompactResponse {
+ readonly conversationId: string;
+ readonly newConversationId: string;
+ readonly messagesSummarized: number;
+ readonly messagesKept: number;
+}
+
+/**
+ * Response for `GET /conversations/:id/compact-threshold` — the token count
+ * at which automatic compaction triggers (0 = manual only; default 350000
+ * when not stored).
+ */
+export interface CompactThresholdResponse {
+ readonly conversationId: string;
+ readonly threshold: number;
+}
+
+/**
+ * Request body for `PUT /conversations/:id/compact-threshold`.
+ */
+export interface SetCompactThresholdRequest {
+ readonly threshold: number;
+}
```
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 `[email protected]` (conversation lifecycle status). Regenerate
+> **Orchestrator:** SNAPSHOT of `[email protected]` (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;
}
```