Skip to content

Commit 860fd02

Browse files
Merge pull request #36 from MyPrototypeWhat/m13t/summarize-history-export
feat: expose summarizeHistory / summarizeMessages for durable compaction
2 parents 219ed86 + e7d4fcc commit 860fd02

16 files changed

Lines changed: 895 additions & 34 deletions

File tree

.agents/skills/integrate/references/api-reference.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import {
1919
getAdapter, // Standalone adapter factory
2020
TokenUtils, // Token counting utilities
2121
XmlGenerator, // XML generation utilities
22+
Prompts, // formatCompactSummary / getCompactSummaryWrapper
23+
summarizeHistory, // Standalone summarization primitive (see History Compaction)
2224
} from "context-chef";
2325
```
2426

@@ -170,6 +172,18 @@ const compacted = chef.getJanitor().compact(history, {
170172
});
171173
```
172174

175+
**Standalone summarization — `summarizeHistory`:** provider-agnostic primitive behind the LLM compression path. Compress a slice in your own store (durable compaction) instead of via `compile()`.
176+
177+
```typescript
178+
function summarizeHistory(
179+
messages: Message[],
180+
compress: (messages: Message[]) => Promise<string>,
181+
opts?: { customCompressionInstructions?: string; toolResultStubThreshold?: number },
182+
): Promise<string>;
183+
```
184+
185+
Empty slice → `''` (no model call); stateless, **throws** if `compress` throws; `compress` **must role-flatten** `tool` / assistant-tool-call messages (providers reject raw `tool` roles). Wrap the result with `Prompts.getCompactSummaryWrapper` for continuation framing. AI-SDK users: prefer `summarizeMessages` from `@context-chef/ai-sdk-middleware`.
186+
173187
## Payload Types
174188

175189
### OpenAIPayload
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'@context-chef/core': patch
3+
'@context-chef/ai-sdk-middleware': patch
4+
---
5+
6+
Expose one-shot history summarization as a standalone API.
7+
8+
- **`summarizeHistory(messages, compress, opts?)`** (core): produces a compression summary for a message slice using the same prompt, attachment/tool-result stripping, and `<summary>` extraction as the in-flight `compress` path. Extracted from `Janitor.executeCompression`, which now delegates to it (behavior-identical). Pure — an empty slice returns `''` without a model call, and it throws on model failure (the Janitor keeps its own circuit breaker + fallback). The `compress` callback must role-flatten tool/assistant-tool-call messages.
9+
- **`summarizeMessages(prompt, model, opts?)`** (ai-sdk-middleware): thin AI-SDK wrapper — `fromAISDK` (drops system messages) → compression adapter (role-flattening) → `summarizeHistory`. Returns the raw summary text (wrap with `Prompts.getCompactSummaryWrapper` for the continuation framing).
10+
11+
For hosts that own their conversation store and persist compression themselves (durable compaction) rather than relying on in-flight middleware compression. When driving summarization this way, do not also configure `compress` (with a `model`) on the same path — that would compress twice. A notification-only `onCompress`, plus `truncate`/`clear`/`dynamicState`, remain safe alongside.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,8 @@ chef.reportTokenUsage(response.usage.prompt_tokens);
286286

287287
**Circuit breaker.** If `compressionModel` throws three times in a row, `compress()` becomes a no-op until the next successful compression or an explicit `janitor.reset()` / `chef.clearHistory()`. The failure counter is preserved by `chef.snapshot()` / `chef.restore()`.
288288

289+
**Standalone summarization.** `summarizeHistory(messages, compress, opts?): Promise<string>` is the provider-agnostic primitive behind this path — call it directly to compress a slice in your own store (durable compaction). Empty slice → `''`; stateless and **throws** if `compress` throws; the `compress` callback **must role-flatten** `tool` roles. See the [core package README](./packages/core) for the full contract. ai-sdk users should prefer `summarizeMessages` from [`@context-chef/ai-sdk-middleware`](./packages/ai-sdk-middleware), which wires the flattening adapter for you.
290+
289291
#### `chef.reportTokenUsage(tokenCount): this`
290292

291293
Feed the API-reported token count. On the next `compile()`, if this value exceeds `contextWindow`, compression is triggered. In the tokenizer path, the default is to take the higher of the local calculation and the fed value; switch via `usagePreference` if you want `'feedFirst'` (trust the API truth) or `'tokenizerFirst'` (ignore fed entirely).

README.zh-CN.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ chef.reportTokenUsage(response.usage.prompt_tokens);
228228

229229
**熔断器。** 如果 `compressionModel` 连续 3 次失败,`compress()` 将直接返回原始历史(不再调用压缩模型),直到下一次成功或显式调用 `janitor.reset()` / `chef.clearHistory()`。失败计数由 `chef.snapshot()` / `chef.restore()` 保存。
230230

231+
**独立摘要。** `summarizeHistory(messages, compress, opts?): Promise<string>` 是该路径背后与具体 provider 无关的原语 —— 可直接调用它在你自己的存储中压缩一段切片(持久化压缩)。空切片返回 `''`;无状态,且 `compress` 抛出时**直接抛出**`compress` 回调**必须扁平化** `tool` 角色。完整契约见 [core 包 README](./packages/core)。ai-sdk 用户应优先使用 [`@context-chef/ai-sdk-middleware`](./packages/ai-sdk-middleware)`summarizeMessages`,它已为你接好扁平化适配器。
232+
231233
#### `chef.reportTokenUsage(tokenCount): this`
232234

233235
传入 API 返回的 token 用量。下次 `compile()` 时,如果该值超过 `contextWindow`,则触发压缩。在 tokenizer 路径中,默认取本地计算值和传入值中的较大值;可通过 `usagePreference` 切换为 `'feedFirst'`(信任 API 真值)或 `'tokenizerFirst'`(完全忽略传入值)。

0 commit comments

Comments
 (0)