feat(server): add DCP clean-room context pruning

- Deduplication: removes consecutive identical tool_call+tool_result pairs
- Purge-errors: removes failed/empty tool results
- Transform orchestrator runs strategies in sequence pre-payload
- Wired into turn.ts before buildMessagesPayload
- Clean-room reimplementation (AGPL reference: behavior only)
This commit is contained in:
2026-06-07 17:57:39 +00:00
parent ee749d8698
commit b8b2666fdc
11 changed files with 327 additions and 1 deletions

View File

@@ -21,6 +21,7 @@ import {
buildMessagesPayload,
loadContext,
} from './payload.js';
import { toDcpMessages, transformMessages, fromDcpMessages } from './dcp/index.js';
import {
finalizeCompletion,
finalizeEmpty,
@@ -156,9 +157,20 @@ export async function runAssistantTurn(
ctx.log.warn({ sessionId }, 'inference: session or project missing mid-loop');
break;
}
const { session: iterSession, project: iterProject, history } = loaded;
let { session: iterSession, project: iterProject, history } = loaded;
const projectRoot = await resolveProjectRoot(iterProject.path);
try {
const dcpMsgs = toDcpMessages(history);
const { messages: pruned, stats } = transformMessages(chatId, dcpMsgs);
if (stats.removedCount > 0) {
ctx.log.info({ chatId, ...stats }, 'dcp: transform removed messages');
history = fromDcpMessages(pruned) as typeof history;
}
} catch (err) {
ctx.log.warn({ err: err instanceof Error ? err.message : String(err), chatId }, 'dcp: transform skipped');
}
// v1.14.0: log step boundary for instrumentation. step_start parts are in
// the schema CHECK but not emitted here — writing to the assistant message
// before the stream phase creates a sequence-0 collision with