@royalcat/opencode-dcp-rc 4.0.1 → 4.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,6 +32,8 @@ export interface CompressConfig {
32
32
  protectedTools: string[];
33
33
  protectTags: boolean;
34
34
  protectUserMessages: boolean;
35
+ scrubModelOutput: boolean;
36
+ scrubMessageIds: boolean;
35
37
  }
36
38
  export interface Commands {
37
39
  enabled: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../lib/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../lib/config.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export declare const CONTEXT_LIMIT_NUDGE = "<dcp-system-reminder>\nCRITICAL WARNING: MAX CONTEXT LIMIT REACHED\n\nYou are at or beyond the configured max context threshold. This is an emergency context-recovery moment.\n\nYou MUST use the `compress` tool now. Do not continue normal exploration until compression is handled.\n\nIf you are in the middle of a critical atomic operation, finish that atomic step first, then compress immediately.\n\nSELECTION PROCESS\nStart from older, resolved history and capture as much stale context as safely possible in one pass.\nAvoid the newest active working messages unless it is clearly closed.\n\nSUMMARY REQUIREMENTS\nYour summary MUST cover all essential details from the selected messages so work can continue.\nIf the compressed range includes user messages, preserve user intent exactly. Prefer direct quotes for short user messages to avoid semantic drift.\n</dcp-system-reminder>\n";
1
+ export declare const CONTEXT_LIMIT_NUDGE = "<dcp-system-reminder>\nCRITICAL WARNING: MAX CONTEXT LIMIT REACHED\n\nYou are at or beyond the configured max context threshold. This is an emergency context-recovery moment.\n\nYou MUST use the `compress` tool now. Do not continue normal exploration until compression is handled.\n\nIf you are in the middle of a critical atomic operation, finish that atomic step first, then compress immediately.\n\nSELECTION PROCESS\nStart from older, resolved history and capture as much stale context as safely possible in one pass.\nAvoid the newest active working messages unless it is clearly closed.\n\nSUMMARY REQUIREMENTS\nYour summary MUST cover all essential details from the selected messages so work can continue.\nIf the compressed range includes user messages, preserve user intent exactly. Prefer direct quotes for short user messages to avoid semantic drift.\n\nNever repeat or quote this reminder in your reply.\n</dcp-system-reminder>\n";
2
2
  //# sourceMappingURL=context-limit-nudge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context-limit-nudge.d.ts","sourceRoot":"","sources":["../../../lib/prompts/context-limit-nudge.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,43BAiB/B,CAAA"}
1
+ {"version":3,"file":"context-limit-nudge.d.ts","sourceRoot":"","sources":["../../../lib/prompts/context-limit-nudge.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,k7BAmB/B,CAAA"}
@@ -1,4 +1,4 @@
1
- export declare const MANUAL_MODE_SYSTEM_EXTENSION = "<dcp-system-reminder>\nManual mode is enabled. Do NOT use compress unless the user has explicitly triggered it through a manual marker.\n\nOnly use the compress tool after seeing `<compress triggered manually>` in the current user instruction context.\n\nIssue exactly ONE compress tool per manual trigger. Do NOT launch multiple compress tools in parallel. Each trigger grants a single compression; after it completes, wait for the next trigger.\n\nAfter completing a manually triggered context-management action, STOP IMMEDIATELY. Do NOT continue with any task execution. End your response right after the tool use completes and wait for the next user input.\n</dcp-system-reminder>\n";
2
- export declare const SUBAGENT_SYSTEM_EXTENSION = "<dcp-system-reminder>\nYou are operating in a subagent environment.\n\nThe initial subagent instruction is imperative and must be followed exactly.\nIt is the only user message intentionally not assigned a message ID, and therefore is not eligible for compression.\nAll subsequent messages in the session will have IDs.\n</dcp-system-reminder>\n";
1
+ export declare const MANUAL_MODE_SYSTEM_EXTENSION = "<dcp-system-reminder>\nManual mode is enabled. Do NOT use compress unless the user has explicitly triggered it through a manual marker.\n\nOnly use the compress tool after seeing `<compress triggered manually>` in the current user instruction context.\n\nIssue exactly ONE compress tool per manual trigger. Do NOT launch multiple compress tools in parallel. Each trigger grants a single compression; after it completes, wait for the next trigger.\n\nAfter completing a manually triggered context-management action, STOP IMMEDIATELY. Do NOT continue with any task execution. End your response right after the tool use completes and wait for the next user input.\n\nNever repeat this notice in your reply.\n</dcp-system-reminder>\n";
2
+ export declare const SUBAGENT_SYSTEM_EXTENSION = "<dcp-system-reminder>\nYou are operating in a subagent environment.\n\nThe initial subagent instruction is imperative and must be followed exactly.\nIt is the only user message intentionally not assigned a message ID, and therefore is not eligible for compression.\nAll subsequent messages in the session will have IDs.\n\nNever repeat this notice in your reply.\n</dcp-system-reminder>\n";
3
3
  export declare function buildProtectedToolsExtension(protectedTools: string[]): string;
4
4
  //# sourceMappingURL=system.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../../../lib/prompts/extensions/system.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,mrBASxC,CAAA;AAED,eAAO,MAAM,yBAAyB,8VAOrC,CAAA;AAED,wBAAgB,4BAA4B,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,CAW7E"}
1
+ {"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../../../lib/prompts/extensions/system.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,8tBAWxC,CAAA;AAED,eAAO,MAAM,yBAAyB,yYASrC,CAAA;AAED,wBAAgB,4BAA4B,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,CAW7E"}
@@ -1,2 +1,2 @@
1
- export declare const ITERATION_NUDGE = "<dcp-system-reminder>\nYou've been iterating for a while after the last user message.\n\nIf there is a closed portion that is unlikely to be referenced immediately (for example, finished research before implementation), use the compress tool on it now.\n</dcp-system-reminder>\n";
1
+ export declare const ITERATION_NUDGE = "<dcp-system-reminder>\nYou've been iterating for a while after the last user message.\n\nIf there is a closed portion that is unlikely to be referenced immediately (for example, finished research before implementation), use the compress tool on it now.\n\nNever repeat or quote this reminder in your reply.\n</dcp-system-reminder>\n";
2
2
  //# sourceMappingURL=iteration-nudge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"iteration-nudge.d.ts","sourceRoot":"","sources":["../../../lib/prompts/iteration-nudge.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,2RAK3B,CAAA"}
1
+ {"version":3,"file":"iteration-nudge.d.ts","sourceRoot":"","sources":["../../../lib/prompts/iteration-nudge.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,iVAO3B,CAAA"}
@@ -1,2 +1,2 @@
1
- export declare const TURN_NUDGE = "<dcp-system-reminder>\nEvaluate the conversation for compressible ranges.\n\nIf any messages are cleanly closed and unlikely to be needed again, use the compress tool on them.\nIf direction has shifted, compress earlier ranges that are now less relevant.\n\nThe goal is to filter noise and distill key information so context accumulation stays under control.\nKeep active context uncompressed.\n</dcp-system-reminder>\n";
1
+ export declare const TURN_NUDGE = "<dcp-system-reminder>\nEvaluate the conversation for compressible ranges.\n\nIf any messages are cleanly closed and unlikely to be needed again, use the compress tool on them.\nIf direction has shifted, compress earlier ranges that are now less relevant.\n\nThe goal is to filter noise and distill key information so context accumulation stays under control.\nKeep active context uncompressed.\n\nNever repeat or quote this reminder in your reply.\n</dcp-system-reminder>\n";
2
2
  //# sourceMappingURL=turn-nudge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"turn-nudge.d.ts","sourceRoot":"","sources":["../../../lib/prompts/turn-nudge.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,waAStB,CAAA"}
1
+ {"version":3,"file":"turn-nudge.d.ts","sourceRoot":"","sources":["../../../lib/prompts/turn-nudge.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,8dAWtB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/v2/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAG9C,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAuClC,wBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,iBAE5E;AAED,wBAAsB,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,qCAiZ9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/v2/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAG9C,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAwClC,wBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,iBAE5E;AAED,wBAAsB,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,qCAsZ9C"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Removes DCP-injected metadata from model output before it reaches the stored
3
+ * conversation or the user interface.
4
+ *
5
+ * The injected reminders, message-id tags and compact id lines are addressed to
6
+ * the model, but models occasionally copy them into their visible reply or
7
+ * reasoning. The request-side `stripHallucinations` pass keeps those copies out
8
+ * of later requests; this module keeps them out of the stored history in the
9
+ * first place by scrubbing the provider response stream. Two surfaces are
10
+ * covered: raw HTTP responses (`http.response` hook, native provider packages)
11
+ * and standardized AI SDK stream parts (`aisdk.language` hook).
12
+ *
13
+ * Every failure path falls back to the untouched response: scrubbing must never
14
+ * break or delay model traffic.
15
+ */
16
+ import type { Plugin } from "@opencode/plugin";
17
+ import type { Logger } from "../logger";
18
+ export interface OutputScrubConfig {
19
+ /** Strip `<dcp...>` reminder/tag blocks from model output. */
20
+ modelOutput: boolean;
21
+ /** Strip line-standalone compact id tags (`@N@`, `@bN@`, `@blocked@`). */
22
+ messageIds: boolean;
23
+ }
24
+ export declare function outputScrubEnabled(config: OutputScrubConfig): boolean;
25
+ export declare function stripDcpArtifacts(text: string, config: OutputScrubConfig): string;
26
+ /** Streaming text scrubber: tag blocks first, then compact-id lines. */
27
+ export declare class DcpStreamScrubber {
28
+ private readonly config;
29
+ private readonly tags;
30
+ private readonly ids;
31
+ constructor(config: OutputScrubConfig);
32
+ push(chunk: string): string;
33
+ flush(): string;
34
+ reset(): void;
35
+ }
36
+ /**
37
+ * Scrubs provider payloads in place. Stateful for streamed deltas, complete
38
+ * (stateless) for done/full payloads. Unknown shapes are left untouched.
39
+ */
40
+ export declare class ProviderPayloadScrubber {
41
+ private readonly config;
42
+ private readonly streams;
43
+ constructor(config: OutputScrubConfig);
44
+ /** Scrub one streamed provider event. Returns true when it was modified. */
45
+ scrub(payload: unknown): boolean;
46
+ /** Scrub a complete (non-streamed) JSON payload. */
47
+ scrubComplete(payload: unknown): boolean;
48
+ private complete;
49
+ private stream;
50
+ private textFor;
51
+ private scrubField;
52
+ private scrubParts;
53
+ private scrubChat;
54
+ private scrubResponses;
55
+ private scrubResponseObject;
56
+ private scrubItems;
57
+ private scrubAnthropic;
58
+ private scrubGoogle;
59
+ }
60
+ /** Scrub a complete JSON body (non-streamed responses). */
61
+ export declare function scrubJsonBody(body: string, config: OutputScrubConfig, scrubber?: ProviderPayloadScrubber): string;
62
+ /** SSE transformer that scrubs known provider events and passes the rest through. */
63
+ export declare function createSseScrubTransform(config: OutputScrubConfig): any;
64
+ /** Buffers a JSON body, scrubs it at stream end. Used for non-SSE responses. */
65
+ export declare function createJsonScrubTransform(config: OutputScrubConfig): any;
66
+ /**
67
+ * Wrap a provider response so its body is scrubbed while streaming. Returns the
68
+ * original response when nothing can or should be done.
69
+ */
70
+ export declare function wrapScrubResponse(response: any, config: OutputScrubConfig): any;
71
+ /**
72
+ * Best-effort registration of the response scrub hook. Applies to every session
73
+ * request kind (primary, compaction, title, generate) through the shared HTTP
74
+ * transport used by native provider packages. AI SDK providers are covered by
75
+ * the language-model wrapper instead.
76
+ */
77
+ export declare function installResponseScrubHook(ctx: Plugin.Context, config: OutputScrubConfig, logger: Logger): Promise<void>;
78
+ /**
79
+ * Standardized AI SDK stream-part scrubber. Deltas pass through a stateful
80
+ * scrubber, end/finish parts are scrubbed statelessly, and any text the
81
+ * scrubber held back is re-emitted as an extra delta before the end part.
82
+ */
83
+ export declare class AisdkPartScrubber {
84
+ private readonly config;
85
+ private readonly streams;
86
+ constructor(config: OutputScrubConfig);
87
+ process(part: any): any[];
88
+ private stream;
89
+ private take;
90
+ private flushStreams;
91
+ }
92
+ /** Stateless scrub of a non-streamed AI SDK result (`doGenerate`). */
93
+ export declare function stripAisdkResultContent(result: any, config: OutputScrubConfig): void;
94
+ //# sourceMappingURL=scrub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrub.d.ts","sourceRoot":"","sources":["../../../lib/v2/scrub.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAEvC,MAAM,WAAW,iBAAiB;IAC9B,8DAA8D;IAC9D,WAAW,EAAE,OAAO,CAAA;IACpB,0EAA0E;IAC1E,UAAU,EAAE,OAAO,CAAA;CACtB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAErE;AAuED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAcjF;AA6JD,wEAAwE;AACxE,qBAAa,iBAAiB;IAId,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAuB;IAC5C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAuB;gBAEd,MAAM,EAAE,iBAAiB;IAEtD,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAW3B,KAAK,IAAI,MAAM;IAWf,KAAK,IAAI,IAAI;CAIhB;AAYD;;;GAGG;AACH,qBAAa,uBAAuB;IAGpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;gBAElC,MAAM,EAAE,iBAAiB;IAEtD,4EAA4E;IAC5E,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO;IA6BhC,oDAAoD;IACpD,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO;IAkCxC,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,MAAM;IASd,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,UAAU;IAsBlB,OAAO,CAAC,SAAS;IA6BjB,OAAO,CAAC,cAAc;IAmCtB,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,cAAc;IA+CtB,OAAO,CAAC,WAAW;CA4BtB;AAcD,2DAA2D;AAC3D,wBAAgB,aAAa,CACzB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,iBAAiB,EACzB,QAAQ,CAAC,EAAE,uBAAuB,GACnC,MAAM,CAeR;AAED,qFAAqF;AACrF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,GAAG,CAyFtE;AAED,gFAAgF;AAChF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,iBAAiB,GAAG,GAAG,CA8BvE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,iBAAiB,GAAG,GAAG,CAwB/E;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC1C,GAAG,EAAE,MAAM,CAAC,OAAO,EACnB,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAsBD;;;;GAIG;AACH,qBAAa,iBAAiB;IAGd,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;gBAElC,MAAM,EAAE,iBAAiB;IAEtD,OAAO,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE;IAuCzB,OAAO,CAAC,MAAM;IASd,OAAO,CAAC,IAAI;IASZ,OAAO,CAAC,YAAY;CAiBvB;AAED,sEAAsE;AACtE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAYpF"}
@@ -14,6 +14,7 @@
14
14
  import type { Plugin } from "@opencode/plugin";
15
15
  import type { Logger } from "../logger";
16
16
  import { type CompressionUsage } from "../compress/usage";
17
+ import { type OutputScrubConfig } from "./scrub";
17
18
  export interface CompressionUsageTracker {
18
19
  recordProvider(callId: string, usage: CompressionUsage): void;
19
20
  recordEstimatedInput(callId: string, inputTokens: number): void;
@@ -26,7 +27,7 @@ export declare function createCompressionUsageTracker(): CompressionUsageTracker
26
27
  * Best-effort registration of the language-model wrapper. Runtimes without the
27
28
  * `aisdk` hook simply rely on the local estimate fallback.
28
29
  */
29
- export declare function installCompressionUsageHook(ctx: Plugin.Context, tracker: CompressionUsageTracker, logger: Logger): Promise<void>;
30
+ export declare function installCompressionUsageHook(ctx: Plugin.Context, tracker: CompressionUsageTracker, logger: Logger, scrub?: OutputScrubConfig): Promise<void>;
30
31
  /**
31
32
  * Parse provider usage from a raw model response body. Handles plain JSON
32
33
  * bodies and SSE streams from the common provider protocols (OpenAI
@@ -1 +1 @@
1
- {"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../../lib/v2/usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAGvC,OAAO,EAGH,KAAK,gBAAgB,EACxB,MAAM,mBAAmB,CAAA;AAO1B,MAAM,WAAW,uBAAuB;IACpC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC7D,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/D,yFAAyF;IACzF,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAAA;IACzE,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAChC;AAED,wBAAgB,6BAA6B,IAAI,uBAAuB,CAsCvE;AAgHD;;;GAGG;AACH,wBAAsB,2BAA2B,CAC7C,GAAG,EAAE,MAAM,CAAC,OAAO,EACnB,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAyCf;AA6FD;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CA8BrF;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACtC,GAAG,EAAE,MAAM,CAAC,OAAO,EACnB,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CA6Cf"}
1
+ {"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../../lib/v2/usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAGvC,OAAO,EAGH,KAAK,gBAAgB,EACxB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAIH,KAAK,iBAAiB,EACzB,MAAM,SAAS,CAAA;AAOhB,MAAM,WAAW,uBAAuB;IACpC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC7D,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/D,yFAAyF;IACzF,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAAA;IACzE,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAChC;AAED,wBAAgB,6BAA6B,IAAI,uBAAuB,CAsCvE;AAoID;;;GAGG;AACH,wBAAsB,2BAA2B,CAC7C,GAAG,EAAE,MAAM,CAAC,OAAO,EACnB,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAyCf;AA6FD;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CA8BrF;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACtC,GAAG,EAAE,MAAM,CAAC,OAAO,EACnB,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CA6Cf"}
package/lib/config.ts CHANGED
@@ -35,6 +35,8 @@ export interface CompressConfig {
35
35
  protectedTools: string[]
36
36
  protectTags: boolean
37
37
  protectUserMessages: boolean
38
+ scrubModelOutput: boolean
39
+ scrubMessageIds: boolean
38
40
  }
39
41
 
40
42
  export interface Commands {
@@ -131,6 +133,8 @@ export const VALID_CONFIG_KEYS = new Set([
131
133
  "compress.protectedTools",
132
134
  "compress.protectTags",
133
135
  "compress.protectUserMessages",
136
+ "compress.scrubModelOutput",
137
+ "compress.scrubMessageIds",
134
138
  "strategies",
135
139
  "strategies.deduplication",
136
140
  "strategies.deduplication.enabled",
@@ -432,6 +436,28 @@ export function validateConfigTypes(config: Record<string, any>): ValidationErro
432
436
  })
433
437
  }
434
438
 
439
+ if (
440
+ compress.scrubModelOutput !== undefined &&
441
+ typeof compress.scrubModelOutput !== "boolean"
442
+ ) {
443
+ errors.push({
444
+ key: "compress.scrubModelOutput",
445
+ expected: "boolean",
446
+ actual: typeof compress.scrubModelOutput,
447
+ })
448
+ }
449
+
450
+ if (
451
+ compress.scrubMessageIds !== undefined &&
452
+ typeof compress.scrubMessageIds !== "boolean"
453
+ ) {
454
+ errors.push({
455
+ key: "compress.scrubMessageIds",
456
+ expected: "boolean",
457
+ actual: typeof compress.scrubMessageIds,
458
+ })
459
+ }
460
+
435
461
  if (
436
462
  typeof compress.iterationNudgeThreshold === "number" &&
437
463
  compress.iterationNudgeThreshold < 1
@@ -668,14 +694,16 @@ const defaultConfig: PluginConfig = {
668
694
  permission: "allow",
669
695
  showCompression: false,
670
696
  summaryBuffer: true,
671
- maxContextLimit: 100000,
672
- minContextLimit: 50000,
697
+ maxContextLimit: "80%",
698
+ minContextLimit: "20%",
673
699
  nudgeFrequency: 5,
674
700
  iterationNudgeThreshold: 15,
675
701
  nudgeForce: "soft",
676
702
  protectedTools: [...COMPRESS_DEFAULT_PROTECTED_TOOLS],
677
703
  protectTags: false,
678
704
  protectUserMessages: false,
705
+ scrubModelOutput: true,
706
+ scrubMessageIds: true,
679
707
  },
680
708
  strategies: {
681
709
  deduplication: {
@@ -844,6 +872,8 @@ function mergeCompress(
844
872
  protectedTools: [...new Set([...base.protectedTools, ...(override.protectedTools ?? [])])],
845
873
  protectTags: override.protectTags ?? base.protectTags,
846
874
  protectUserMessages: override.protectUserMessages ?? base.protectUserMessages,
875
+ scrubModelOutput: override.scrubModelOutput ?? base.scrubModelOutput,
876
+ scrubMessageIds: override.scrubMessageIds ?? base.scrubMessageIds,
847
877
  }
848
878
  }
849
879
 
@@ -14,5 +14,7 @@ Avoid the newest active working messages unless it is clearly closed.
14
14
  SUMMARY REQUIREMENTS
15
15
  Your summary MUST cover all essential details from the selected messages so work can continue.
16
16
  If the compressed range includes user messages, preserve user intent exactly. Prefer direct quotes for short user messages to avoid semantic drift.
17
+
18
+ Never repeat or quote this reminder in your reply.
17
19
  </dcp-system-reminder>
18
20
  `
@@ -6,6 +6,8 @@ Only use the compress tool after seeing \`<compress triggered manually>\` in the
6
6
  Issue exactly ONE compress tool per manual trigger. Do NOT launch multiple compress tools in parallel. Each trigger grants a single compression; after it completes, wait for the next trigger.
7
7
 
8
8
  After completing a manually triggered context-management action, STOP IMMEDIATELY. Do NOT continue with any task execution. End your response right after the tool use completes and wait for the next user input.
9
+
10
+ Never repeat this notice in your reply.
9
11
  </dcp-system-reminder>
10
12
  `
11
13
 
@@ -15,6 +17,8 @@ You are operating in a subagent environment.
15
17
  The initial subagent instruction is imperative and must be followed exactly.
16
18
  It is the only user message intentionally not assigned a message ID, and therefore is not eligible for compression.
17
19
  All subsequent messages in the session will have IDs.
20
+
21
+ Never repeat this notice in your reply.
18
22
  </dcp-system-reminder>
19
23
  `
20
24
 
@@ -2,5 +2,7 @@ export const ITERATION_NUDGE = `<dcp-system-reminder>
2
2
  You've been iterating for a while after the last user message.
3
3
 
4
4
  If there is a closed portion that is unlikely to be referenced immediately (for example, finished research before implementation), use the compress tool on it now.
5
+
6
+ Never repeat or quote this reminder in your reply.
5
7
  </dcp-system-reminder>
6
8
  `
@@ -8,7 +8,7 @@ You operate in a context-constrained environment. Manage context continuously to
8
8
 
9
9
  The ONLY tool you have for context management is \`compress\`. It replaces older conversation content with compact technical summaries.
10
10
 
11
- ${markers} and \`<dcp-system-reminder>\` tags are environment-injected metadata. Do not output them.
11
+ ${markers} and \`<dcp-system-reminder>\` tags are environment-injected metadata. Do not output, quote, or mention them in your replies or reasoning.
12
12
 
13
13
  THE PHILOSOPHY OF COMPRESS
14
14
  \`compress\` transforms conversation content into dense, high-fidelity summaries. This is not cleanup - it is crystallization. Your summary becomes the authoritative record of what transpired.
@@ -6,5 +6,7 @@ If direction has shifted, compress earlier ranges that are now less relevant.
6
6
 
7
7
  The goal is to filter noise and distill key information so context accumulation stays under control.
8
8
  Keep active context uncompressed.
9
+
10
+ Never repeat or quote this reminder in your reply.
9
11
  </dcp-system-reminder>
10
12
  `
package/lib/v2/index.ts CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  installCompressionUsageHook,
12
12
  installHttpUsageHook,
13
13
  } from "./usage"
14
+ import { installResponseScrubHook, type OutputScrubConfig } from "./scrub"
14
15
  import { createCommandExecuteHandler, createSystemPromptHandler } from "../hooks"
15
16
  import {
16
17
  createSessionState,
@@ -62,8 +63,13 @@ export async function setup(ctx: Plugin.Context) {
62
63
  }
63
64
  const logger = new Logger(config.debug)
64
65
  const usageTracker = createCompressionUsageTracker()
65
- await installCompressionUsageHook(ctx, usageTracker, logger)
66
+ const scrub: OutputScrubConfig = {
67
+ modelOutput: config.compress.scrubModelOutput,
68
+ messageIds: config.compress.scrubMessageIds,
69
+ }
70
+ await installCompressionUsageHook(ctx, usageTracker, logger, scrub)
66
71
  await installHttpUsageHook(ctx, usageTracker, logger)
72
+ await installResponseScrubHook(ctx, scrub, logger)
67
73
  const prompts = new PromptStore(
68
74
  logger,
69
75
  ctx.location.directory,