Merge master into codex/simp-session-log-representation

This commit is contained in:
Tianyi Cui
2026-07-17 22:33:42 +08:00
310 files changed
+4718 -1903

No files matched your search

+16 -10
View File
@@ -227,21 +227,26 @@ export class BasicCompactService extends CompactService {
/**
* Summarize through a direct one-shot `ctx.llm.stream()` call, not an agent
* step or `agent/request` dispatch. Failure finishes and truncated summaries
* reject; the signal is forwarded and only text reaches the checkpoint.
* reject; the signal is forwarded, only text reaches the checkpoint, and the
* returned envelope identifies the provider/model actually used.
*
* @param text - plain-text rendering of the conversation region to condense.
* @param agent - supplies the fallback model and the session id stamped on
* the call; throws when neither it nor the config names a model.
* @param agent - supplies the request-header/creation fallback target and the
* session id stamped on the call; throws when no complete target exists.
* @param signal - optional abort signal, forwarded into the model call.
* @returns the text-only summary blocks plus the call envelope used
* (`model`, and `maxTokens` when the summarizer has a cap).
* (`provider`, `model`, and `maxTokens` when the summarizer has a cap).
*/
async summarize(
text: string, agent: Agent, signal?: AbortSignal,
): Promise<{ summary: ContentBlock[]; model: string; maxTokens?: number }> {
): Promise<{ summary: ContentBlock[]; provider: string; model: string; maxTokens?: number }> {
const assembler = new BlockAssembler()
const logged = agent.session.requestHeader()?.config
const provider = this.config.summarizationProvider || logged?.provider || agent.options.provider || ''
const model = this.config.summarizationModel || logged?.model || agent.options.model || ''
const options: GenerateOptions = {
model: this.config.summarizationModel || agent.options.model || '',
provider,
model,
messages: [{
role: 'user',
content: [{ type: 'text', text: `Summarize this conversation history:\n\n${text}\n\nSummary:` }],
@@ -253,8 +258,8 @@ export class BasicCompactService extends CompactService {
// exactOptionalPropertyTypes: only set `signal` when present — assigning
// `undefined` to an optional `signal?: AbortSignal` is a type error.
if (signal) options.signal = signal
if (!options.model) {
throw new Error('no model available for summarization: set BasicCompactConfig.summarizationModel or AgentOptions.model')
if (!options.provider || !options.model) {
throw new Error('no provider/model available for summarization: set both summarization fields or provide a logged/agent target')
}
for await (const chunk of this.ctx.llm.stream(options)) {
assembler.push(chunk)
@@ -271,7 +276,7 @@ export class BasicCompactService extends CompactService {
// config.maxTokens is required and validated positive, so this backend's
// envelope always carries the cap; the return type's optionality exists
// for overriding subclasses whose summarizer has none.
return { summary, model: options.model, maxTokens: this.config.maxTokens }
return { summary, provider: options.provider, model: options.model, maxTokens: this.config.maxTokens }
}
// ---- Core API (implements the abstract contract) ----
@@ -378,7 +383,7 @@ export class BasicCompactService extends CompactService {
try {
// --- Extract text and summarize ---
const text = renderTranscript(session.events, shadowedSeqs)
const { summary, model, maxTokens } = await this.summarize(text, agent, signal)
const { summary, provider, model, maxTokens } = await this.summarize(text, agent, signal)
// Estimate token count of the shadowed content for provenance.
let shadowedTokenCount = 0
@@ -400,6 +405,7 @@ export class BasicCompactService extends CompactService {
shadowedRange: { start, end },
shadowedSeqs,
shadowedTokenCount,
provider,
model,
...maxTokens !== undefined ? { maxTokens } : {},
})
+9 -1
View File
@@ -24,7 +24,9 @@ export interface BasicCompactConfig {
thresholdRatio: number
/** Number of tokens of recent context to retain during compaction. */
retainTokens: number
/** Model to use for summarization (`''` — uses the agent's model). */
/** Provider to use for summarization (`''` with an empty model inherits the conversation target). */
summarizationProvider: string
/** Model to use for summarization (`''` with an empty provider inherits the conversation target). */
summarizationModel: string
/** Provider generation cap for the summarization call. */
maxTokens: number
@@ -63,6 +65,12 @@ export function resolveConfig(config: BasicCompactConfig): ResolvedConfig {
if (typeof resolved.summarizationModel !== 'string') {
throw new Error('BasicCompactConfig: summarizationModel must be a string.')
}
if (typeof resolved.summarizationProvider !== 'string') {
throw new Error('BasicCompactConfig: summarizationProvider must be a string.')
}
if ((resolved.summarizationProvider.length === 0) !== (resolved.summarizationModel.length === 0)) {
throw new Error('BasicCompactConfig: summarizationProvider and summarizationModel must both be empty or both be set.')
}
if (typeof resolved.auto !== 'boolean') {
throw new Error('BasicCompactConfig: auto must be a boolean.')
}