Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/codex-compact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ export function extractBiliSummary(item: unknown): string | undefined {
return text.length > 0 ? text : undefined;
}

/** User-role handoff prefix for a client-echoed compaction item (#1106/#1113).
* Exported so the output-side echo guard derives its line head from this same
* constant — guard and carrier share one identifier (#1635). */
export const COMPACT_ECHO_PREFIX = "[bili] context summary after compaction:";

// An echoed fc_bili_ compaction item is REPLACED (in place) by a plain user
// message carrying the extracted summary — a history-borne handoff the kernel
// can fold again and codex's retention keeps. Rare bounded duplication (a
Expand All @@ -91,7 +96,7 @@ export function replaceBiliCompactionItems<T>(input: T[]): { items: T[]; replace
items.push({
type: "message",
role: "user",
content: [{ type: "input_text", text: `[bili] context summary after compaction:\n${summary}` }],
content: [{ type: "input_text", text: `${COMPACT_ECHO_PREFIX}\n${summary}` }],
} as T);
replaced++;
}
Expand Down Expand Up @@ -150,7 +155,9 @@ export function buildTriggerForgeBody(
// The kernel renders block summaries as system messages with this header
// (acp-kernel SUMMARY_HEADER). Reuse the exact format so the model reads a
// captured handoff summary the same way it reads a live kernel-rendered one.
const FORGED_SUMMARY_HEADER = "[Compressed conversation section]";
// Exported: the output-side echo guard derives its line head from this same
// constant so guard and carrier share one identifier (#1635).
export const FORGED_SUMMARY_HEADER = "[Compressed conversation section]";

export function renderForgedSummary(block: Pick<CompressionBlock, "summary" | "topic">): string {
const body = block.summary.trim();
Expand Down
8 changes: 7 additions & 1 deletion src/loop/adapter-anthropic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { CoreMessage } from "acp-kernel";
import { coreToAnthropic, extractSystem, buildSystem, type AnthropicRequestBody } from "acp-kernel/wire";
import { stampAnthropicSystemCacheControl } from "./cache-control.js";
import { buildVisibilityMarker } from "./core.js";
import { composeStreamFilters, createMarkerLineFilter, createTagEchoFilter } from "./tag-echo-filter.js";
import { composeStreamFilters, createBiliChainTagFilter, createInternalArtifactLineFilter, createMarkerLineFilter, createTagEchoFilter } from "./tag-echo-filter.js";
import { degenerateTurnWarning } from "../degenerate-turn.js";
import { log as loggerLog } from "../logger.js";
import type {
Expand Down Expand Up @@ -270,6 +270,12 @@ export function createAnthropicAdapter(requestBody: Record<string, unknown>, ori
createMarkerLineFilter((snippet) => {
loggerLog("warn", `[marker-echo] stripped model-emitted ACP confirmation marker: ${snippet.slice(0, 80).replace(/\n/g, " ")}`);
}),
createBiliChainTagFilter((snippet) => {
loggerLog("warn", `[bili-chain-echo] stripped model-emitted chain checkpoint tag: ${snippet.slice(0, 80).replace(/\n/g, " ")}`);
}),
createInternalArtifactLineFilter((snippet) => {
loggerLog("warn", `[artifact-echo] stripped model-emitted internal summary artifact line: ${snippet.slice(0, 80).replace(/\n/g, " ")}`);
}),
);
let lastTextIndex: number | null = null;
let sawThinking = false;
Expand Down
8 changes: 7 additions & 1 deletion src/loop/adapter-google.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { CoreMessage } from "acp-kernel";
import { coreToGoogle } from "acp-kernel/wire";
import type { GooglePart } from "acp-kernel/wire";
import { buildVisibilityMarker } from "./core.js";
import { composeStreamFilters, createMarkerLineFilter, createTagEchoFilter } from "./tag-echo-filter.js";
import { composeStreamFilters, createBiliChainTagFilter, createInternalArtifactLineFilter, createMarkerLineFilter, createTagEchoFilter } from "./tag-echo-filter.js";
import { degenerateTurnWarning } from "../degenerate-turn.js";
import { log as loggerLog } from "../logger.js";

Expand Down Expand Up @@ -294,6 +294,12 @@ export function createGoogleAdapter(
createMarkerLineFilter((snippet) => {
loggerLog("warn", `[marker-echo] stripped model-emitted ACP confirmation marker: ${snippet.slice(0, 80).replace(/\n/g, " ")}`);
}),
createBiliChainTagFilter((snippet) => {
loggerLog("warn", `[bili-chain-echo] stripped model-emitted chain checkpoint tag: ${snippet.slice(0, 80).replace(/\n/g, " ")}`);
}),
createInternalArtifactLineFilter((snippet) => {
loggerLog("warn", `[artifact-echo] stripped model-emitted internal summary artifact line: ${snippet.slice(0, 80).replace(/\n/g, " ")}`);
}),
);
const flushFilter = function* (): Generator<ParsedStreamEvent> {
const tail = tagFilter.flush();
Expand Down
8 changes: 7 additions & 1 deletion src/loop/adapter-openai.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { CoreMessage } from "acp-kernel";
import { coreToOpenai, injectOpenaiSystem } from "acp-kernel/wire";
import { buildVisibilityMarker } from "./core.js";
import { composeStreamFilters, createMarkerLineFilter, createTagEchoFilter } from "./tag-echo-filter.js";
import { composeStreamFilters, createBiliChainTagFilter, createInternalArtifactLineFilter, createMarkerLineFilter, createTagEchoFilter } from "./tag-echo-filter.js";
import { degenerateTurnWarning } from "../degenerate-turn.js";
import { log as loggerLog } from "../logger.js";
import { hardenOpenaiAssistantContent, systemToUser } from "../util.js";
Expand Down Expand Up @@ -224,6 +224,12 @@ export function createOpenaiAdapter(requestBody: Record<string, unknown>, client
createMarkerLineFilter((snippet) => {
loggerLog("warn", `[marker-echo] stripped model-emitted ACP confirmation marker: ${snippet.slice(0, 80).replace(/\n/g, " ")}`);
}),
createBiliChainTagFilter((snippet) => {
loggerLog("warn", `[bili-chain-echo] stripped model-emitted chain checkpoint tag: ${snippet.slice(0, 80).replace(/\n/g, " ")}`);
}),
createInternalArtifactLineFilter((snippet) => {
loggerLog("warn", `[artifact-echo] stripped model-emitted internal summary artifact line: ${snippet.slice(0, 80).replace(/\n/g, " ")}`);
}),
);
const flushFilter = function* (): Generator<ParsedStreamEvent> {
const tail = tagFilter.flush();
Expand Down
8 changes: 7 additions & 1 deletion src/loop/adapter-responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { coreToResponsesWithToolImages as coreToResponses, patchResponsesInputWi
import { buildVisibilityMarker } from "./core.js";
import { hoistTrappedToolItems } from "../tool-pair-order.js";
import { hashId } from "../util.js";
import { composeStreamFilters, createMarkerLineFilter, createTagEchoFilter, stripResponsesText, containsMarkerLineText, containsRenderTagText, ACP_NAME_ALT } from "./tag-echo-filter.js";
import { composeStreamFilters, createBiliChainTagFilter, createInternalArtifactLineFilter, createMarkerLineFilter, createTagEchoFilter, stripResponsesText, containsMarkerLineText, containsRenderTagText, ACP_NAME_ALT } from "./tag-echo-filter.js";
import { degenerateTurnWarning } from "../degenerate-turn.js";
import { log as loggerLog } from "../logger.js";
import { extractResponsesTextTriggers, PROXY_TOOL_NAMES } from "../compress-tool.js";
Expand Down Expand Up @@ -340,6 +340,12 @@ export function createResponsesAdapter(textProtocol?: boolean, projection?: Resp
createMarkerLineFilter((snippet) => {
loggerLog("warn", `[marker-echo] stripped model-emitted ACP confirmation marker: ${snippet.slice(0, 80).replace(/\n/g, " ")}`);
}),
createBiliChainTagFilter((snippet) => {
loggerLog("warn", `[bili-chain-echo] stripped model-emitted chain checkpoint tag: ${snippet.slice(0, 80).replace(/\n/g, " ")}`);
}),
createInternalArtifactLineFilter((snippet) => {
loggerLog("warn", `[artifact-echo] stripped model-emitted internal summary artifact line: ${snippet.slice(0, 80).replace(/\n/g, " ")}`);
}),
);
let lastTextRef: { itemId: string; outputIndex: number } | null = null;
const flushFilter = function* (): Generator<ParsedStreamEvent> {
Expand Down
Loading
Loading