정우용 72b6a11a83
fix: preserve persona and language continuity in compaction summaries (#10456)
Merged via squash.

Prepared head SHA: 4518fb20e1037f87493e3668621cb1a45ab8233e
Co-authored-by: keepitmello <71975659+keepitmello@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-13 07:40:32 -07:00

103 lines
3.9 KiB
TypeScript

import type { Api, Model } from "@mariozechner/pi-ai";
import type { ExtensionFactory, SessionManager } from "@mariozechner/pi-coding-agent";
import type { OpenClawConfig } from "../../config/config.js";
import { resolveContextWindowInfo } from "../context-window-guard.js";
import { DEFAULT_CONTEXT_TOKENS } from "../defaults.js";
import { setCompactionSafeguardRuntime } from "../pi-extensions/compaction-safeguard-runtime.js";
import compactionSafeguardExtension from "../pi-extensions/compaction-safeguard.js";
import contextPruningExtension from "../pi-extensions/context-pruning.js";
import { setContextPruningRuntime } from "../pi-extensions/context-pruning/runtime.js";
import { computeEffectiveSettings } from "../pi-extensions/context-pruning/settings.js";
import { makeToolPrunablePredicate } from "../pi-extensions/context-pruning/tools.js";
import { ensurePiCompactionReserveTokens } from "../pi-settings.js";
import { isCacheTtlEligibleProvider, readLastCacheTtlTimestamp } from "./cache-ttl.js";
function resolveContextWindowTokens(params: {
cfg: OpenClawConfig | undefined;
provider: string;
modelId: string;
model: Model<Api> | undefined;
}): number {
return resolveContextWindowInfo({
cfg: params.cfg,
provider: params.provider,
modelId: params.modelId,
modelContextWindow: params.model?.contextWindow,
defaultTokens: DEFAULT_CONTEXT_TOKENS,
}).tokens;
}
function buildContextPruningFactory(params: {
cfg: OpenClawConfig | undefined;
sessionManager: SessionManager;
provider: string;
modelId: string;
model: Model<Api> | undefined;
}): ExtensionFactory | undefined {
const raw = params.cfg?.agents?.defaults?.contextPruning;
if (raw?.mode !== "cache-ttl") {
return undefined;
}
if (!isCacheTtlEligibleProvider(params.provider, params.modelId)) {
return undefined;
}
const settings = computeEffectiveSettings(raw);
if (!settings) {
return undefined;
}
setContextPruningRuntime(params.sessionManager, {
settings,
contextWindowTokens: resolveContextWindowTokens(params),
isToolPrunable: makeToolPrunablePredicate(settings.tools),
lastCacheTouchAt: readLastCacheTtlTimestamp(params.sessionManager),
});
return contextPruningExtension;
}
function resolveCompactionMode(cfg?: OpenClawConfig): "default" | "safeguard" {
return cfg?.agents?.defaults?.compaction?.mode === "safeguard" ? "safeguard" : "default";
}
export function buildEmbeddedExtensionFactories(params: {
cfg: OpenClawConfig | undefined;
sessionManager: SessionManager;
provider: string;
modelId: string;
model: Model<Api> | undefined;
}): ExtensionFactory[] {
const factories: ExtensionFactory[] = [];
if (resolveCompactionMode(params.cfg) === "safeguard") {
const compactionCfg = params.cfg?.agents?.defaults?.compaction;
const qualityGuardCfg = compactionCfg?.qualityGuard;
const contextWindowInfo = resolveContextWindowInfo({
cfg: params.cfg,
provider: params.provider,
modelId: params.modelId,
modelContextWindow: params.model?.contextWindow,
defaultTokens: DEFAULT_CONTEXT_TOKENS,
});
setCompactionSafeguardRuntime(params.sessionManager, {
maxHistoryShare: compactionCfg?.maxHistoryShare,
contextWindowTokens: contextWindowInfo.tokens,
identifierPolicy: compactionCfg?.identifierPolicy,
identifierInstructions: compactionCfg?.identifierInstructions,
customInstructions: compactionCfg?.customInstructions,
qualityGuardEnabled: qualityGuardCfg?.enabled ?? false,
qualityGuardMaxRetries: qualityGuardCfg?.maxRetries,
model: params.model,
recentTurnsPreserve: compactionCfg?.recentTurnsPreserve,
});
factories.push(compactionSafeguardExtension);
}
const pruningFactory = buildContextPruningFactory(params);
if (pruningFactory) {
factories.push(pruningFactory);
}
return factories;
}
export { ensurePiCompactionReserveTokens };