opencode-acp 1.4.0 → 1.4.2
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.
- package/README.md +81 -102
- package/README.zh-CN.md +52 -71
- package/dist/index.js +0 -81
- package/dist/index.js.map +1 -1
- package/dist/lib/config-validation.d.ts +0 -1
- package/dist/lib/config-validation.d.ts.map +1 -1
- package/dist/lib/message-ids.d.ts +0 -1
- package/dist/lib/message-ids.d.ts.map +1 -1
- package/dist/lib/messages/prune.d.ts.map +1 -1
- package/dist/lib/messages/utils.d.ts +0 -4
- package/dist/lib/messages/utils.d.ts.map +1 -1
- package/dist/lib/state/state.d.ts.map +1 -1
- package/dist/lib/ui/notification.d.ts +0 -2
- package/dist/lib/ui/notification.d.ts.map +1 -1
- package/dist/lib/ui/utils.d.ts +0 -3
- package/dist/lib/ui/utils.d.ts.map +1 -1
- package/dist/lib/update.d.ts +0 -16
- package/dist/lib/update.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../lib/config.ts","../node_modules/jsonc-parser/lib/esm/impl/scanner.js","../node_modules/jsonc-parser/lib/esm/impl/string-intern.js","../node_modules/jsonc-parser/lib/esm/impl/parser.js","../node_modules/jsonc-parser/lib/esm/main.js","../lib/config-validation.ts","../lib/compress/message.ts","../lib/token-utils.ts","../lib/messages/shape.ts","../lib/messages/query.ts","../lib/prompts/extensions/tool.ts","../lib/message-ids.ts","../lib/compress/search.ts","../lib/compress/state.ts","../lib/compress/message-utils.ts","../lib/state/persistence.ts","../lib/state/utils.ts","../lib/compress/timing.ts","../lib/state/state.ts","../lib/state/tool-cache.ts","../lib/protected-patterns.ts","../lib/strategies/deduplication.ts","../lib/strategies/purge-errors.ts","../lib/ui/utils.ts","../lib/ui/notification.ts","../lib/compress/pipeline.ts","../lib/subagents/subagent-results.ts","../lib/compress/protected-content.ts","../lib/compress/range.ts","../lib/compress/range-utils.ts","../lib/compress/decompress.ts","../lib/messages/utils.ts","../lib/messages/prune.ts","../lib/messages/sync.ts","../lib/host-permissions.ts","../lib/compress-permission.ts","../lib/prompts/extensions/nudge.ts","../lib/messages/priority.ts","../lib/messages/inject/utils.ts","../lib/messages/inject/inject.ts","../lib/messages/inject/subagent-results.ts","../lib/messages/reasoning-strip.ts","../lib/commands/compression-targets.ts","../lib/compress/decompress-logic.ts","../lib/compress/mark-block.ts","../lib/logger.ts","../lib/prompts/store.ts","../lib/prompts/system.ts","../lib/prompts/compress-range.ts","../lib/prompts/compress-message.ts","../lib/prompts/context-limit-nudge.ts","../lib/prompts/turn-nudge.ts","../lib/prompts/iteration-nudge.ts","../lib/prompts/extensions/system.ts","../lib/prompts/index.ts","../lib/commands/context.ts","../lib/commands/decompress.ts","../lib/commands/help.ts","../lib/commands/manual.ts","../lib/commands/recompress.ts","../lib/commands/stats.ts","../lib/commands/sweep.ts","../lib/gc/truncate.ts","../lib/gc/merge.ts","../lib/hooks.ts","../lib/auth.ts","../lib/update.ts","../index.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync, copyFileSync } from \"fs\"\nimport { join, dirname } from \"path\"\nimport { homedir } from \"os\"\nimport { parse } from \"jsonc-parser/lib/esm/main.js\"\nimport type { PluginInput } from \"@opencode-ai/plugin\"\nimport { VALID_CONFIG_KEYS, getInvalidConfigKeys, validateConfigTypes, type ValidationError } from \"./config-validation\"\n\n\ntype Permission = \"ask\" | \"allow\" | \"deny\"\ntype CompressMode = \"range\" | \"message\"\n\nexport interface Deduplication {\n enabled: boolean\n protectedTools: string[]\n}\n\nexport interface CompressConfig {\n mode: CompressMode\n permission: Permission\n showCompression: boolean\n summaryBuffer: boolean\n maxContextLimit: number | `${number}%`\n minContextLimit: number | `${number}%`\n modelMaxLimits?: Record<string, number | `${number}%`>\n modelMinLimits?: Record<string, number | `${number}%`>\n nudgeFrequency: number\n iterationNudgeThreshold: number\n nudgeForce: \"strong\" | \"soft\"\n protectedTools: string[]\n protectTags: boolean\n protectUserMessages: boolean\n}\n\nexport interface Commands {\n enabled: boolean\n protectedTools: string[]\n}\n\nexport interface ManualModeConfig {\n enabled: boolean\n automaticStrategies: boolean\n}\n\nexport interface PurgeErrors {\n enabled: boolean\n turns: number\n protectedTools: string[]\n}\n\nexport interface TurnProtection {\n enabled: boolean\n turns: number\n}\n\nexport interface ExperimentalConfig {\n allowSubAgents: boolean\n customPrompts: boolean\n}\n\nexport interface BatchCleanupConfig {\n lowThreshold: number | `${number}%`\n highThreshold: number | `${number}%`\n forceThreshold: number | `${number}%`\n}\n\nexport interface GCConfig {\n algorithm: \"truncate\"\n promotionThreshold: number\n maxBlockAge: number\n maxOldGenSummaryLength: number\n majorGcThresholdPercent: number | `${number}%`\n batchCleanup: BatchCleanupConfig\n}\n\nexport interface PluginConfig {\n enabled: boolean\n autoUpdate: boolean\n debug: boolean\n pruneNotification: \"off\" | \"minimal\" | \"detailed\"\n pruneNotificationType: \"chat\" | \"toast\"\n commands: Commands\n manualMode: ManualModeConfig\n turnProtection: TurnProtection\n experimental: ExperimentalConfig\n protectedFilePatterns: string[]\n compress: CompressConfig\n gc: GCConfig\n strategies: {\n deduplication: Deduplication\n purgeErrors: PurgeErrors\n }\n}\n\ntype CompressOverride = Partial<CompressConfig>\n\nconst DEFAULT_PROTECTED_TOOLS = [\n \"task\",\n \"skill\",\n \"todowrite\",\n \"todoread\",\n \"compress\",\n \"decompress\",\n \"mark_block\",\n \"unmark_block\",\n \"batch\",\n \"plan_enter\",\n \"plan_exit\",\n \"write\",\n \"edit\",\n]\n\nconst COMPRESS_DEFAULT_PROTECTED_TOOLS = [\"task\", \"skill\", \"todowrite\", \"todoread\", \"decompress\"]\n\nexport { VALID_CONFIG_KEYS, getInvalidConfigKeys, validateConfigTypes, type ValidationError } from \"./config-validation\"\n\nfunction showConfigWarnings(\n ctx: PluginInput,\n configPath: string,\n configData: Record<string, any>,\n isProject: boolean,\n): void {\n const invalidKeys = getInvalidConfigKeys(configData)\n const typeErrors = validateConfigTypes(configData)\n\n if (invalidKeys.length === 0 && typeErrors.length === 0) {\n return\n }\n\n const configType = isProject ? \"project config\" : \"config\"\n const messages: string[] = []\n\n if (invalidKeys.length > 0) {\n const keyList = invalidKeys.slice(0, 3).join(\", \")\n const suffix = invalidKeys.length > 3 ? ` (+${invalidKeys.length - 3} more)` : \"\"\n messages.push(`Unknown keys: ${keyList}${suffix}`)\n }\n\n if (typeErrors.length > 0) {\n for (const err of typeErrors.slice(0, 2)) {\n messages.push(`${err.key}: expected ${err.expected}, got ${err.actual}`)\n }\n if (typeErrors.length > 2) {\n messages.push(`(+${typeErrors.length - 2} more type errors)`)\n }\n }\n\n setTimeout(() => {\n try {\n ctx.client.tui.showToast({\n body: {\n title: `ACP: ${configType} warning`,\n message: `${configPath}\\n${messages.join(\"\\n\")}`,\n variant: \"warning\",\n duration: 7000,\n },\n })\n } catch {}\n }, 7000)\n}\n\nconst defaultConfig: PluginConfig = {\n enabled: true,\n autoUpdate: true,\n debug: false,\n pruneNotification: \"detailed\",\n pruneNotificationType: \"chat\",\n commands: {\n enabled: true,\n protectedTools: [...DEFAULT_PROTECTED_TOOLS],\n },\n manualMode: {\n enabled: false,\n automaticStrategies: true,\n },\n turnProtection: {\n enabled: false,\n turns: 4,\n },\n experimental: {\n allowSubAgents: false,\n customPrompts: false,\n },\n protectedFilePatterns: [],\n compress: {\n mode: \"range\",\n permission: \"allow\",\n showCompression: true,\n summaryBuffer: true,\n maxContextLimit: \"55%\",\n minContextLimit: \"45%\",\n nudgeFrequency: 5,\n iterationNudgeThreshold: 15,\n nudgeForce: \"soft\",\n protectedTools: [...COMPRESS_DEFAULT_PROTECTED_TOOLS],\n protectTags: false,\n protectUserMessages: false,\n },\n strategies: {\n deduplication: {\n enabled: true,\n protectedTools: [],\n },\n purgeErrors: {\n enabled: true,\n turns: 4,\n protectedTools: [],\n },\n },\n gc: {\n algorithm: \"truncate\",\n promotionThreshold: 5,\n maxBlockAge: 15,\n maxOldGenSummaryLength: 3000,\n majorGcThresholdPercent: \"100%\",\n batchCleanup: {\n lowThreshold: \"60%\",\n highThreshold: \"75%\",\n forceThreshold: \"90%\",\n },\n },\n}\n\nconst GLOBAL_CONFIG_DIR = process.env.XDG_CONFIG_HOME\n ? join(process.env.XDG_CONFIG_HOME, \"opencode\")\n : join(homedir(), \".config\", \"opencode\")\nconst GLOBAL_CONFIG_PATH_JSONC = join(GLOBAL_CONFIG_DIR, \"acp.jsonc\")\nconst GLOBAL_CONFIG_PATH_JSON = join(GLOBAL_CONFIG_DIR, \"acp.json\")\nconst LEGACY_GLOBAL_CONFIG_PATH_JSONC = join(GLOBAL_CONFIG_DIR, \"dcp.jsonc\")\nconst LEGACY_GLOBAL_CONFIG_PATH_JSON = join(GLOBAL_CONFIG_DIR, \"dcp.json\")\n\nfunction findOpencodeDir(startDir: string): string | null {\n let current = startDir\n while (current !== \"/\") {\n const candidate = join(current, \".opencode\")\n if (existsSync(candidate) && statSync(candidate).isDirectory()) {\n return candidate\n }\n const parent = dirname(current)\n if (parent === current) {\n break\n }\n current = parent\n }\n return null\n}\n\nfunction getConfigPaths(ctx?: PluginInput): {\n global: string | null\n configDir: string | null\n project: string | null\n} {\n const global = existsSync(GLOBAL_CONFIG_PATH_JSONC)\n ? GLOBAL_CONFIG_PATH_JSONC\n : existsSync(GLOBAL_CONFIG_PATH_JSON)\n ? GLOBAL_CONFIG_PATH_JSON\n : existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSONC)\n ? LEGACY_GLOBAL_CONFIG_PATH_JSONC\n : existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSON)\n ? LEGACY_GLOBAL_CONFIG_PATH_JSON\n : null\n\n let configDir: string | null = null\n const opencodeConfigDir = process.env.OPENCODE_CONFIG_DIR\n if (opencodeConfigDir) {\n const configJsonc = join(opencodeConfigDir, \"acp.jsonc\")\n const configJson = join(opencodeConfigDir, \"acp.json\")\n const legacyJsonc = join(opencodeConfigDir, \"dcp.jsonc\")\n const legacyJson = join(opencodeConfigDir, \"dcp.json\")\n configDir = existsSync(configJsonc)\n ? configJsonc\n : existsSync(configJson)\n ? configJson\n : existsSync(legacyJsonc)\n ? legacyJsonc\n : existsSync(legacyJson)\n ? legacyJson\n : null\n }\n\n let project: string | null = null\n if (ctx?.directory) {\n const opencodeDir = findOpencodeDir(ctx.directory)\n if (opencodeDir) {\n const projectJsonc = join(opencodeDir, \"acp.jsonc\")\n const projectJson = join(opencodeDir, \"acp.json\")\n const legacyJsonc = join(opencodeDir, \"dcp.jsonc\")\n const legacyJson = join(opencodeDir, \"dcp.json\")\n project = existsSync(projectJsonc)\n ? projectJsonc\n : existsSync(projectJson)\n ? projectJson\n : existsSync(legacyJsonc)\n ? legacyJsonc\n : existsSync(legacyJson)\n ? legacyJson\n : null\n }\n }\n\n return { global, configDir, project }\n}\n\nfunction createDefaultConfig(): void {\n if (!existsSync(GLOBAL_CONFIG_DIR)) {\n mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true })\n }\n\n if (!existsSync(GLOBAL_CONFIG_PATH_JSONC)) {\n if (existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSONC)) {\n copyFileSync(LEGACY_GLOBAL_CONFIG_PATH_JSONC, GLOBAL_CONFIG_PATH_JSONC)\n console.log(\"[ACP] Migrated config from dcp.jsonc to acp.jsonc\")\n } else if (existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSON)) {\n copyFileSync(LEGACY_GLOBAL_CONFIG_PATH_JSON, GLOBAL_CONFIG_PATH_JSONC)\n console.log(\"[ACP] Migrated config from dcp.json to acp.jsonc\")\n } else {\n const configContent = `{\n \"$schema\": \"https://raw.githubusercontent.com/ranxianglei/opencode-acp/master/dcp.schema.json\"\n}\n`\n writeFileSync(GLOBAL_CONFIG_PATH_JSONC, configContent, \"utf-8\")\n }\n }\n}\n\ninterface ConfigLoadResult {\n data: Record<string, any> | null\n parseError?: string\n}\n\nfunction loadConfigFile(configPath: string): ConfigLoadResult {\n let fileContent = \"\"\n try {\n fileContent = readFileSync(configPath, \"utf-8\")\n } catch {\n return { data: null }\n }\n\n try {\n const parsed = parse(fileContent, undefined, { allowTrailingComma: true })\n if (parsed === undefined || parsed === null) {\n return { data: null, parseError: \"Config file is empty or invalid\" }\n }\n return { data: parsed }\n } catch (error: any) {\n return { data: null, parseError: error.message || \"Failed to parse config\" }\n }\n}\n\nfunction mergeStrategies(\n base: PluginConfig[\"strategies\"],\n override?: Partial<PluginConfig[\"strategies\"]>,\n): PluginConfig[\"strategies\"] {\n if (!override) {\n return base\n }\n\n return {\n deduplication: {\n enabled: override.deduplication?.enabled ?? base.deduplication.enabled,\n protectedTools: [\n ...new Set([\n ...base.deduplication.protectedTools,\n ...(override.deduplication?.protectedTools ?? []),\n ]),\n ],\n },\n purgeErrors: {\n enabled: override.purgeErrors?.enabled ?? base.purgeErrors.enabled,\n turns: override.purgeErrors?.turns ?? base.purgeErrors.turns,\n protectedTools: [\n ...new Set([\n ...base.purgeErrors.protectedTools,\n ...(override.purgeErrors?.protectedTools ?? []),\n ]),\n ],\n },\n }\n}\n\nfunction mergeCompress(\n base: PluginConfig[\"compress\"],\n override?: CompressOverride,\n): PluginConfig[\"compress\"] {\n if (!override) {\n return base\n }\n\n return {\n mode: override.mode ?? base.mode,\n permission: override.permission ?? base.permission,\n showCompression: override.showCompression ?? base.showCompression,\n summaryBuffer: override.summaryBuffer ?? base.summaryBuffer,\n maxContextLimit: override.maxContextLimit ?? base.maxContextLimit,\n minContextLimit: override.minContextLimit ?? base.minContextLimit,\n modelMaxLimits: override.modelMaxLimits ?? base.modelMaxLimits,\n modelMinLimits: override.modelMinLimits ?? base.modelMinLimits,\n nudgeFrequency: override.nudgeFrequency ?? base.nudgeFrequency,\n iterationNudgeThreshold: override.iterationNudgeThreshold ?? base.iterationNudgeThreshold,\n nudgeForce: override.nudgeForce ?? base.nudgeForce,\n protectedTools: [...new Set([...base.protectedTools, ...(override.protectedTools ?? [])])],\n protectTags: override.protectTags ?? base.protectTags,\n protectUserMessages: override.protectUserMessages ?? base.protectUserMessages,\n }\n}\n\nfunction mergeCommands(\n base: PluginConfig[\"commands\"],\n override?: Partial<PluginConfig[\"commands\"]>,\n): PluginConfig[\"commands\"] {\n if (!override) {\n return base\n }\n\n return {\n enabled: override.enabled ?? base.enabled,\n protectedTools: [...new Set([...base.protectedTools, ...(override.protectedTools ?? [])])],\n }\n}\n\nfunction mergeManualMode(\n base: PluginConfig[\"manualMode\"],\n override?: Partial<PluginConfig[\"manualMode\"]>,\n): PluginConfig[\"manualMode\"] {\n if (override === undefined) return base\n\n return {\n enabled: override.enabled ?? base.enabled,\n automaticStrategies: override.automaticStrategies ?? base.automaticStrategies,\n }\n}\n\nfunction mergeExperimental(\n base: PluginConfig[\"experimental\"],\n override?: Partial<PluginConfig[\"experimental\"]>,\n): PluginConfig[\"experimental\"] {\n if (override === undefined) return base\n\n return {\n allowSubAgents: override.allowSubAgents ?? base.allowSubAgents,\n customPrompts: override.customPrompts ?? base.customPrompts,\n }\n}\n\nfunction deepCloneConfig(config: PluginConfig): PluginConfig {\n return {\n ...config,\n commands: {\n enabled: config.commands.enabled,\n protectedTools: [...config.commands.protectedTools],\n },\n manualMode: {\n enabled: config.manualMode.enabled,\n automaticStrategies: config.manualMode.automaticStrategies,\n },\n turnProtection: { ...config.turnProtection },\n experimental: { ...config.experimental },\n protectedFilePatterns: [...config.protectedFilePatterns],\n compress: {\n ...config.compress,\n modelMaxLimits: { ...config.compress.modelMaxLimits },\n modelMinLimits: { ...config.compress.modelMinLimits },\n protectedTools: [...config.compress.protectedTools],\n },\n strategies: {\n deduplication: {\n ...config.strategies.deduplication,\n protectedTools: [...config.strategies.deduplication.protectedTools],\n },\n purgeErrors: {\n ...config.strategies.purgeErrors,\n protectedTools: [...config.strategies.purgeErrors.protectedTools],\n },\n },\n gc: {\n ...config.gc,\n batchCleanup: { ...config.gc.batchCleanup },\n },\n }\n}\n\nfunction mergeGC(base: GCConfig, override?: Partial<GCConfig>): GCConfig {\n if (!override) {\n return base\n }\n\n return {\n ...base,\n ...override,\n batchCleanup: { ...base.batchCleanup, ...(override.batchCleanup ?? {}) },\n }\n}\n\nfunction mergeLayer(config: PluginConfig, data: Record<string, any>): PluginConfig {\n return {\n enabled: data.enabled ?? config.enabled,\n autoUpdate: data.autoUpdate ?? config.autoUpdate,\n debug: data.debug ?? config.debug,\n pruneNotification: data.pruneNotification ?? config.pruneNotification,\n pruneNotificationType: data.pruneNotificationType ?? config.pruneNotificationType,\n commands: mergeCommands(config.commands, data.commands as any),\n manualMode: mergeManualMode(config.manualMode, data.manualMode as any),\n turnProtection: {\n enabled: data.turnProtection?.enabled ?? config.turnProtection.enabled,\n turns: data.turnProtection?.turns ?? config.turnProtection.turns,\n },\n experimental: mergeExperimental(config.experimental, data.experimental as any),\n protectedFilePatterns: [\n ...new Set([...config.protectedFilePatterns, ...(data.protectedFilePatterns ?? [])]),\n ],\n compress: mergeCompress(config.compress, data.compress as CompressOverride),\n gc: mergeGC(config.gc, data.gc as Partial<GCConfig>),\n strategies: mergeStrategies(config.strategies, data.strategies as any),\n }\n}\n\nfunction scheduleParseWarning(ctx: PluginInput, title: string, message: string): void {\n setTimeout(() => {\n try {\n ctx.client.tui.showToast({\n body: {\n title,\n message,\n variant: \"warning\",\n duration: 7000,\n },\n })\n } catch {}\n }, 7000)\n}\n\nexport function getConfig(ctx: PluginInput): PluginConfig {\n let config = deepCloneConfig(defaultConfig)\n const configPaths = getConfigPaths(ctx)\n\n // Migration: dcp.jsonc → acp.jsonc (must run before createDefaultConfig check)\n if (!existsSync(GLOBAL_CONFIG_PATH_JSONC) && !existsSync(GLOBAL_CONFIG_PATH_JSON)) {\n if (existsSync(GLOBAL_CONFIG_DIR) || existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSONC) || existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSON)) {\n if (!existsSync(GLOBAL_CONFIG_DIR)) {\n mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true })\n }\n if (existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSONC)) {\n copyFileSync(LEGACY_GLOBAL_CONFIG_PATH_JSONC, GLOBAL_CONFIG_PATH_JSONC)\n console.log(\"[ACP] Migrated config from dcp.jsonc to acp.jsonc\")\n } else if (existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSON)) {\n copyFileSync(LEGACY_GLOBAL_CONFIG_PATH_JSON, GLOBAL_CONFIG_PATH_JSONC)\n console.log(\"[ACP] Migrated config from dcp.json to acp.jsonc\")\n }\n }\n }\n\n if (!configPaths.global && !existsSync(GLOBAL_CONFIG_PATH_JSONC)) {\n createDefaultConfig()\n }\n\n const layers: Array<{ path: string | null; name: string; isProject: boolean }> = [\n { path: configPaths.global, name: \"config\", isProject: false },\n { path: configPaths.configDir, name: \"configDir config\", isProject: true },\n { path: configPaths.project, name: \"project config\", isProject: true },\n ]\n\n for (const layer of layers) {\n if (!layer.path) {\n continue\n }\n\n const result = loadConfigFile(layer.path)\n if (result.parseError) {\n scheduleParseWarning(\n ctx,\n `ACP: Invalid ${layer.name}`,\n `${layer.path}\\n${result.parseError}\\nUsing previous/default values`,\n )\n continue\n }\n\n if (!result.data) {\n continue\n }\n\n showConfigWarnings(ctx, layer.path, result.data, layer.isProject)\n config = mergeLayer(config, result.data)\n }\n\n return config\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\n/**\n * Creates a JSON scanner on the given text.\n * If ignoreTrivia is set, whitespaces or comments are ignored.\n */\nexport function createScanner(text, ignoreTrivia = false) {\n const len = text.length;\n let pos = 0, value = '', tokenOffset = 0, token = 16 /* SyntaxKind.Unknown */, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0 /* ScanError.None */;\n function scanHexDigits(count, exact) {\n let digits = 0;\n let value = 0;\n while (digits < count || !exact) {\n let ch = text.charCodeAt(pos);\n if (ch >= 48 /* CharacterCodes._0 */ && ch <= 57 /* CharacterCodes._9 */) {\n value = value * 16 + ch - 48 /* CharacterCodes._0 */;\n }\n else if (ch >= 65 /* CharacterCodes.A */ && ch <= 70 /* CharacterCodes.F */) {\n value = value * 16 + ch - 65 /* CharacterCodes.A */ + 10;\n }\n else if (ch >= 97 /* CharacterCodes.a */ && ch <= 102 /* CharacterCodes.f */) {\n value = value * 16 + ch - 97 /* CharacterCodes.a */ + 10;\n }\n else {\n break;\n }\n pos++;\n digits++;\n }\n if (digits < count) {\n value = -1;\n }\n return value;\n }\n function setPosition(newPosition) {\n pos = newPosition;\n value = '';\n tokenOffset = 0;\n token = 16 /* SyntaxKind.Unknown */;\n scanError = 0 /* ScanError.None */;\n }\n function scanNumber() {\n let start = pos;\n if (text.charCodeAt(pos) === 48 /* CharacterCodes._0 */) {\n pos++;\n }\n else {\n pos++;\n while (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n }\n }\n if (pos < text.length && text.charCodeAt(pos) === 46 /* CharacterCodes.dot */) {\n pos++;\n if (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n while (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n }\n }\n else {\n scanError = 3 /* ScanError.UnexpectedEndOfNumber */;\n return text.substring(start, pos);\n }\n }\n let end = pos;\n if (pos < text.length && (text.charCodeAt(pos) === 69 /* CharacterCodes.E */ || text.charCodeAt(pos) === 101 /* CharacterCodes.e */)) {\n pos++;\n if (pos < text.length && text.charCodeAt(pos) === 43 /* CharacterCodes.plus */ || text.charCodeAt(pos) === 45 /* CharacterCodes.minus */) {\n pos++;\n }\n if (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n while (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n }\n end = pos;\n }\n else {\n scanError = 3 /* ScanError.UnexpectedEndOfNumber */;\n }\n }\n return text.substring(start, end);\n }\n function scanString() {\n let result = '', start = pos;\n while (true) {\n if (pos >= len) {\n result += text.substring(start, pos);\n scanError = 2 /* ScanError.UnexpectedEndOfString */;\n break;\n }\n const ch = text.charCodeAt(pos);\n if (ch === 34 /* CharacterCodes.doubleQuote */) {\n result += text.substring(start, pos);\n pos++;\n break;\n }\n if (ch === 92 /* CharacterCodes.backslash */) {\n result += text.substring(start, pos);\n pos++;\n if (pos >= len) {\n scanError = 2 /* ScanError.UnexpectedEndOfString */;\n break;\n }\n const ch2 = text.charCodeAt(pos++);\n switch (ch2) {\n case 34 /* CharacterCodes.doubleQuote */:\n result += '\\\"';\n break;\n case 92 /* CharacterCodes.backslash */:\n result += '\\\\';\n break;\n case 47 /* CharacterCodes.slash */:\n result += '/';\n break;\n case 98 /* CharacterCodes.b */:\n result += '\\b';\n break;\n case 102 /* CharacterCodes.f */:\n result += '\\f';\n break;\n case 110 /* CharacterCodes.n */:\n result += '\\n';\n break;\n case 114 /* CharacterCodes.r */:\n result += '\\r';\n break;\n case 116 /* CharacterCodes.t */:\n result += '\\t';\n break;\n case 117 /* CharacterCodes.u */:\n const ch3 = scanHexDigits(4, true);\n if (ch3 >= 0) {\n result += String.fromCharCode(ch3);\n }\n else {\n scanError = 4 /* ScanError.InvalidUnicode */;\n }\n break;\n default:\n scanError = 5 /* ScanError.InvalidEscapeCharacter */;\n }\n start = pos;\n continue;\n }\n if (ch >= 0 && ch <= 0x1f) {\n if (isLineBreak(ch)) {\n result += text.substring(start, pos);\n scanError = 2 /* ScanError.UnexpectedEndOfString */;\n break;\n }\n else {\n scanError = 6 /* ScanError.InvalidCharacter */;\n // mark as error but continue with string\n }\n }\n pos++;\n }\n return result;\n }\n function scanNext() {\n value = '';\n scanError = 0 /* ScanError.None */;\n tokenOffset = pos;\n lineStartOffset = lineNumber;\n prevTokenLineStartOffset = tokenLineStartOffset;\n if (pos >= len) {\n // at the end\n tokenOffset = len;\n return token = 17 /* SyntaxKind.EOF */;\n }\n let code = text.charCodeAt(pos);\n // trivia: whitespace\n if (isWhiteSpace(code)) {\n do {\n pos++;\n value += String.fromCharCode(code);\n code = text.charCodeAt(pos);\n } while (isWhiteSpace(code));\n return token = 15 /* SyntaxKind.Trivia */;\n }\n // trivia: newlines\n if (isLineBreak(code)) {\n pos++;\n value += String.fromCharCode(code);\n if (code === 13 /* CharacterCodes.carriageReturn */ && text.charCodeAt(pos) === 10 /* CharacterCodes.lineFeed */) {\n pos++;\n value += '\\n';\n }\n lineNumber++;\n tokenLineStartOffset = pos;\n return token = 14 /* SyntaxKind.LineBreakTrivia */;\n }\n switch (code) {\n // tokens: []{}:,\n case 123 /* CharacterCodes.openBrace */:\n pos++;\n return token = 1 /* SyntaxKind.OpenBraceToken */;\n case 125 /* CharacterCodes.closeBrace */:\n pos++;\n return token = 2 /* SyntaxKind.CloseBraceToken */;\n case 91 /* CharacterCodes.openBracket */:\n pos++;\n return token = 3 /* SyntaxKind.OpenBracketToken */;\n case 93 /* CharacterCodes.closeBracket */:\n pos++;\n return token = 4 /* SyntaxKind.CloseBracketToken */;\n case 58 /* CharacterCodes.colon */:\n pos++;\n return token = 6 /* SyntaxKind.ColonToken */;\n case 44 /* CharacterCodes.comma */:\n pos++;\n return token = 5 /* SyntaxKind.CommaToken */;\n // strings\n case 34 /* CharacterCodes.doubleQuote */:\n pos++;\n value = scanString();\n return token = 10 /* SyntaxKind.StringLiteral */;\n // comments\n case 47 /* CharacterCodes.slash */:\n const start = pos - 1;\n // Single-line comment\n if (text.charCodeAt(pos + 1) === 47 /* CharacterCodes.slash */) {\n pos += 2;\n while (pos < len) {\n if (isLineBreak(text.charCodeAt(pos))) {\n break;\n }\n pos++;\n }\n value = text.substring(start, pos);\n return token = 12 /* SyntaxKind.LineCommentTrivia */;\n }\n // Multi-line comment\n if (text.charCodeAt(pos + 1) === 42 /* CharacterCodes.asterisk */) {\n pos += 2;\n const safeLength = len - 1; // For lookahead.\n let commentClosed = false;\n while (pos < safeLength) {\n const ch = text.charCodeAt(pos);\n if (ch === 42 /* CharacterCodes.asterisk */ && text.charCodeAt(pos + 1) === 47 /* CharacterCodes.slash */) {\n pos += 2;\n commentClosed = true;\n break;\n }\n pos++;\n if (isLineBreak(ch)) {\n if (ch === 13 /* CharacterCodes.carriageReturn */ && text.charCodeAt(pos) === 10 /* CharacterCodes.lineFeed */) {\n pos++;\n }\n lineNumber++;\n tokenLineStartOffset = pos;\n }\n }\n if (!commentClosed) {\n pos++;\n scanError = 1 /* ScanError.UnexpectedEndOfComment */;\n }\n value = text.substring(start, pos);\n return token = 13 /* SyntaxKind.BlockCommentTrivia */;\n }\n // just a single slash\n value += String.fromCharCode(code);\n pos++;\n return token = 16 /* SyntaxKind.Unknown */;\n // numbers\n case 45 /* CharacterCodes.minus */:\n value += String.fromCharCode(code);\n pos++;\n if (pos === len || !isDigit(text.charCodeAt(pos))) {\n return token = 16 /* SyntaxKind.Unknown */;\n }\n // found a minus, followed by a number so\n // we fall through to proceed with scanning\n // numbers\n case 48 /* CharacterCodes._0 */:\n case 49 /* CharacterCodes._1 */:\n case 50 /* CharacterCodes._2 */:\n case 51 /* CharacterCodes._3 */:\n case 52 /* CharacterCodes._4 */:\n case 53 /* CharacterCodes._5 */:\n case 54 /* CharacterCodes._6 */:\n case 55 /* CharacterCodes._7 */:\n case 56 /* CharacterCodes._8 */:\n case 57 /* CharacterCodes._9 */:\n value += scanNumber();\n return token = 11 /* SyntaxKind.NumericLiteral */;\n // literals and unknown symbols\n default:\n // is a literal? Read the full word.\n while (pos < len && isUnknownContentCharacter(code)) {\n pos++;\n code = text.charCodeAt(pos);\n }\n if (tokenOffset !== pos) {\n value = text.substring(tokenOffset, pos);\n // keywords: true, false, null\n switch (value) {\n case 'true': return token = 8 /* SyntaxKind.TrueKeyword */;\n case 'false': return token = 9 /* SyntaxKind.FalseKeyword */;\n case 'null': return token = 7 /* SyntaxKind.NullKeyword */;\n }\n return token = 16 /* SyntaxKind.Unknown */;\n }\n // some\n value += String.fromCharCode(code);\n pos++;\n return token = 16 /* SyntaxKind.Unknown */;\n }\n }\n function isUnknownContentCharacter(code) {\n if (isWhiteSpace(code) || isLineBreak(code)) {\n return false;\n }\n switch (code) {\n case 125 /* CharacterCodes.closeBrace */:\n case 93 /* CharacterCodes.closeBracket */:\n case 123 /* CharacterCodes.openBrace */:\n case 91 /* CharacterCodes.openBracket */:\n case 34 /* CharacterCodes.doubleQuote */:\n case 58 /* CharacterCodes.colon */:\n case 44 /* CharacterCodes.comma */:\n case 47 /* CharacterCodes.slash */:\n return false;\n }\n return true;\n }\n function scanNextNonTrivia() {\n let result;\n do {\n result = scanNext();\n } while (result >= 12 /* SyntaxKind.LineCommentTrivia */ && result <= 15 /* SyntaxKind.Trivia */);\n return result;\n }\n return {\n setPosition: setPosition,\n getPosition: () => pos,\n scan: ignoreTrivia ? scanNextNonTrivia : scanNext,\n getToken: () => token,\n getTokenValue: () => value,\n getTokenOffset: () => tokenOffset,\n getTokenLength: () => pos - tokenOffset,\n getTokenStartLine: () => lineStartOffset,\n getTokenStartCharacter: () => tokenOffset - prevTokenLineStartOffset,\n getTokenError: () => scanError,\n };\n}\nfunction isWhiteSpace(ch) {\n return ch === 32 /* CharacterCodes.space */ || ch === 9 /* CharacterCodes.tab */;\n}\nfunction isLineBreak(ch) {\n return ch === 10 /* CharacterCodes.lineFeed */ || ch === 13 /* CharacterCodes.carriageReturn */;\n}\nfunction isDigit(ch) {\n return ch >= 48 /* CharacterCodes._0 */ && ch <= 57 /* CharacterCodes._9 */;\n}\nvar CharacterCodes;\n(function (CharacterCodes) {\n CharacterCodes[CharacterCodes[\"lineFeed\"] = 10] = \"lineFeed\";\n CharacterCodes[CharacterCodes[\"carriageReturn\"] = 13] = \"carriageReturn\";\n CharacterCodes[CharacterCodes[\"space\"] = 32] = \"space\";\n CharacterCodes[CharacterCodes[\"_0\"] = 48] = \"_0\";\n CharacterCodes[CharacterCodes[\"_1\"] = 49] = \"_1\";\n CharacterCodes[CharacterCodes[\"_2\"] = 50] = \"_2\";\n CharacterCodes[CharacterCodes[\"_3\"] = 51] = \"_3\";\n CharacterCodes[CharacterCodes[\"_4\"] = 52] = \"_4\";\n CharacterCodes[CharacterCodes[\"_5\"] = 53] = \"_5\";\n CharacterCodes[CharacterCodes[\"_6\"] = 54] = \"_6\";\n CharacterCodes[CharacterCodes[\"_7\"] = 55] = \"_7\";\n CharacterCodes[CharacterCodes[\"_8\"] = 56] = \"_8\";\n CharacterCodes[CharacterCodes[\"_9\"] = 57] = \"_9\";\n CharacterCodes[CharacterCodes[\"a\"] = 97] = \"a\";\n CharacterCodes[CharacterCodes[\"b\"] = 98] = \"b\";\n CharacterCodes[CharacterCodes[\"c\"] = 99] = \"c\";\n CharacterCodes[CharacterCodes[\"d\"] = 100] = \"d\";\n CharacterCodes[CharacterCodes[\"e\"] = 101] = \"e\";\n CharacterCodes[CharacterCodes[\"f\"] = 102] = \"f\";\n CharacterCodes[CharacterCodes[\"g\"] = 103] = \"g\";\n CharacterCodes[CharacterCodes[\"h\"] = 104] = \"h\";\n CharacterCodes[CharacterCodes[\"i\"] = 105] = \"i\";\n CharacterCodes[CharacterCodes[\"j\"] = 106] = \"j\";\n CharacterCodes[CharacterCodes[\"k\"] = 107] = \"k\";\n CharacterCodes[CharacterCodes[\"l\"] = 108] = \"l\";\n CharacterCodes[CharacterCodes[\"m\"] = 109] = \"m\";\n CharacterCodes[CharacterCodes[\"n\"] = 110] = \"n\";\n CharacterCodes[CharacterCodes[\"o\"] = 111] = \"o\";\n CharacterCodes[CharacterCodes[\"p\"] = 112] = \"p\";\n CharacterCodes[CharacterCodes[\"q\"] = 113] = \"q\";\n CharacterCodes[CharacterCodes[\"r\"] = 114] = \"r\";\n CharacterCodes[CharacterCodes[\"s\"] = 115] = \"s\";\n CharacterCodes[CharacterCodes[\"t\"] = 116] = \"t\";\n CharacterCodes[CharacterCodes[\"u\"] = 117] = \"u\";\n CharacterCodes[CharacterCodes[\"v\"] = 118] = \"v\";\n CharacterCodes[CharacterCodes[\"w\"] = 119] = \"w\";\n CharacterCodes[CharacterCodes[\"x\"] = 120] = \"x\";\n CharacterCodes[CharacterCodes[\"y\"] = 121] = \"y\";\n CharacterCodes[CharacterCodes[\"z\"] = 122] = \"z\";\n CharacterCodes[CharacterCodes[\"A\"] = 65] = \"A\";\n CharacterCodes[CharacterCodes[\"B\"] = 66] = \"B\";\n CharacterCodes[CharacterCodes[\"C\"] = 67] = \"C\";\n CharacterCodes[CharacterCodes[\"D\"] = 68] = \"D\";\n CharacterCodes[CharacterCodes[\"E\"] = 69] = \"E\";\n CharacterCodes[CharacterCodes[\"F\"] = 70] = \"F\";\n CharacterCodes[CharacterCodes[\"G\"] = 71] = \"G\";\n CharacterCodes[CharacterCodes[\"H\"] = 72] = \"H\";\n CharacterCodes[CharacterCodes[\"I\"] = 73] = \"I\";\n CharacterCodes[CharacterCodes[\"J\"] = 74] = \"J\";\n CharacterCodes[CharacterCodes[\"K\"] = 75] = \"K\";\n CharacterCodes[CharacterCodes[\"L\"] = 76] = \"L\";\n CharacterCodes[CharacterCodes[\"M\"] = 77] = \"M\";\n CharacterCodes[CharacterCodes[\"N\"] = 78] = \"N\";\n CharacterCodes[CharacterCodes[\"O\"] = 79] = \"O\";\n CharacterCodes[CharacterCodes[\"P\"] = 80] = \"P\";\n CharacterCodes[CharacterCodes[\"Q\"] = 81] = \"Q\";\n CharacterCodes[CharacterCodes[\"R\"] = 82] = \"R\";\n CharacterCodes[CharacterCodes[\"S\"] = 83] = \"S\";\n CharacterCodes[CharacterCodes[\"T\"] = 84] = \"T\";\n CharacterCodes[CharacterCodes[\"U\"] = 85] = \"U\";\n CharacterCodes[CharacterCodes[\"V\"] = 86] = \"V\";\n CharacterCodes[CharacterCodes[\"W\"] = 87] = \"W\";\n CharacterCodes[CharacterCodes[\"X\"] = 88] = \"X\";\n CharacterCodes[CharacterCodes[\"Y\"] = 89] = \"Y\";\n CharacterCodes[CharacterCodes[\"Z\"] = 90] = \"Z\";\n CharacterCodes[CharacterCodes[\"asterisk\"] = 42] = \"asterisk\";\n CharacterCodes[CharacterCodes[\"backslash\"] = 92] = \"backslash\";\n CharacterCodes[CharacterCodes[\"closeBrace\"] = 125] = \"closeBrace\";\n CharacterCodes[CharacterCodes[\"closeBracket\"] = 93] = \"closeBracket\";\n CharacterCodes[CharacterCodes[\"colon\"] = 58] = \"colon\";\n CharacterCodes[CharacterCodes[\"comma\"] = 44] = \"comma\";\n CharacterCodes[CharacterCodes[\"dot\"] = 46] = \"dot\";\n CharacterCodes[CharacterCodes[\"doubleQuote\"] = 34] = \"doubleQuote\";\n CharacterCodes[CharacterCodes[\"minus\"] = 45] = \"minus\";\n CharacterCodes[CharacterCodes[\"openBrace\"] = 123] = \"openBrace\";\n CharacterCodes[CharacterCodes[\"openBracket\"] = 91] = \"openBracket\";\n CharacterCodes[CharacterCodes[\"plus\"] = 43] = \"plus\";\n CharacterCodes[CharacterCodes[\"slash\"] = 47] = \"slash\";\n CharacterCodes[CharacterCodes[\"formFeed\"] = 12] = \"formFeed\";\n CharacterCodes[CharacterCodes[\"tab\"] = 9] = \"tab\";\n})(CharacterCodes || (CharacterCodes = {}));\n","export const cachedSpaces = new Array(20).fill(0).map((_, index) => {\n return ' '.repeat(index);\n});\nconst maxCachedValues = 200;\nexport const cachedBreakLinesWithSpaces = {\n ' ': {\n '\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\n' + ' '.repeat(index);\n }),\n '\\r': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r' + ' '.repeat(index);\n }),\n '\\r\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r\\n' + ' '.repeat(index);\n }),\n },\n '\\t': {\n '\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\n' + '\\t'.repeat(index);\n }),\n '\\r': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r' + '\\t'.repeat(index);\n }),\n '\\r\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r\\n' + '\\t'.repeat(index);\n }),\n }\n};\nexport const supportedEols = ['\\n', '\\r', '\\r\\n'];\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\nimport { createScanner } from './scanner';\nvar ParseOptions;\n(function (ParseOptions) {\n ParseOptions.DEFAULT = {\n allowTrailingComma: false\n };\n})(ParseOptions || (ParseOptions = {}));\n/**\n * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.\n */\nexport function getLocation(text, position) {\n const segments = []; // strings or numbers\n const earlyReturnException = new Object();\n let previousNode = undefined;\n const previousNodeInst = {\n value: {},\n offset: 0,\n length: 0,\n type: 'object',\n parent: undefined\n };\n let isAtPropertyKey = false;\n function setPreviousNode(value, offset, length, type) {\n previousNodeInst.value = value;\n previousNodeInst.offset = offset;\n previousNodeInst.length = length;\n previousNodeInst.type = type;\n previousNodeInst.colonOffset = undefined;\n previousNode = previousNodeInst;\n }\n try {\n visit(text, {\n onObjectBegin: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n isAtPropertyKey = position > offset;\n segments.push(''); // push a placeholder (will be replaced)\n },\n onObjectProperty: (name, offset, length) => {\n if (position < offset) {\n throw earlyReturnException;\n }\n setPreviousNode(name, offset, length, 'property');\n segments[segments.length - 1] = name;\n if (position <= offset + length) {\n throw earlyReturnException;\n }\n },\n onObjectEnd: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.pop();\n },\n onArrayBegin: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.push(0);\n },\n onArrayEnd: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.pop();\n },\n onLiteralValue: (value, offset, length) => {\n if (position < offset) {\n throw earlyReturnException;\n }\n setPreviousNode(value, offset, length, getNodeType(value));\n if (position <= offset + length) {\n throw earlyReturnException;\n }\n },\n onSeparator: (sep, offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n if (sep === ':' && previousNode && previousNode.type === 'property') {\n previousNode.colonOffset = offset;\n isAtPropertyKey = false;\n previousNode = undefined;\n }\n else if (sep === ',') {\n const last = segments[segments.length - 1];\n if (typeof last === 'number') {\n segments[segments.length - 1] = last + 1;\n }\n else {\n isAtPropertyKey = true;\n segments[segments.length - 1] = '';\n }\n previousNode = undefined;\n }\n }\n });\n }\n catch (e) {\n if (e !== earlyReturnException) {\n throw e;\n }\n }\n return {\n path: segments,\n previousNode,\n isAtPropertyKey,\n matches: (pattern) => {\n let k = 0;\n for (let i = 0; k < pattern.length && i < segments.length; i++) {\n if (pattern[k] === segments[i] || pattern[k] === '*') {\n k++;\n }\n else if (pattern[k] !== '**') {\n return false;\n }\n }\n return k === pattern.length;\n }\n };\n}\n/**\n * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n * Therefore always check the errors list to find out if the input was valid.\n */\nexport function parse(text, errors = [], options = ParseOptions.DEFAULT) {\n let currentProperty = null;\n let currentParent = [];\n const previousParents = [];\n function onValue(value) {\n if (Array.isArray(currentParent)) {\n currentParent.push(value);\n }\n else if (currentProperty !== null) {\n currentParent[currentProperty] = value;\n }\n }\n const visitor = {\n onObjectBegin: () => {\n const object = {};\n onValue(object);\n previousParents.push(currentParent);\n currentParent = object;\n currentProperty = null;\n },\n onObjectProperty: (name) => {\n currentProperty = name;\n },\n onObjectEnd: () => {\n currentParent = previousParents.pop();\n },\n onArrayBegin: () => {\n const array = [];\n onValue(array);\n previousParents.push(currentParent);\n currentParent = array;\n currentProperty = null;\n },\n onArrayEnd: () => {\n currentParent = previousParents.pop();\n },\n onLiteralValue: onValue,\n onError: (error, offset, length) => {\n errors.push({ error, offset, length });\n }\n };\n visit(text, visitor, options);\n return currentParent[0];\n}\n/**\n * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n */\nexport function parseTree(text, errors = [], options = ParseOptions.DEFAULT) {\n let currentParent = { type: 'array', offset: -1, length: -1, children: [], parent: undefined }; // artificial root\n function ensurePropertyComplete(endOffset) {\n if (currentParent.type === 'property') {\n currentParent.length = endOffset - currentParent.offset;\n currentParent = currentParent.parent;\n }\n }\n function onValue(valueNode) {\n currentParent.children.push(valueNode);\n return valueNode;\n }\n const visitor = {\n onObjectBegin: (offset) => {\n currentParent = onValue({ type: 'object', offset, length: -1, parent: currentParent, children: [] });\n },\n onObjectProperty: (name, offset, length) => {\n currentParent = onValue({ type: 'property', offset, length: -1, parent: currentParent, children: [] });\n currentParent.children.push({ type: 'string', value: name, offset, length, parent: currentParent });\n },\n onObjectEnd: (offset, length) => {\n ensurePropertyComplete(offset + length); // in case of a missing value for a property: make sure property is complete\n currentParent.length = offset + length - currentParent.offset;\n currentParent = currentParent.parent;\n ensurePropertyComplete(offset + length);\n },\n onArrayBegin: (offset, length) => {\n currentParent = onValue({ type: 'array', offset, length: -1, parent: currentParent, children: [] });\n },\n onArrayEnd: (offset, length) => {\n currentParent.length = offset + length - currentParent.offset;\n currentParent = currentParent.parent;\n ensurePropertyComplete(offset + length);\n },\n onLiteralValue: (value, offset, length) => {\n onValue({ type: getNodeType(value), offset, length, parent: currentParent, value });\n ensurePropertyComplete(offset + length);\n },\n onSeparator: (sep, offset, length) => {\n if (currentParent.type === 'property') {\n if (sep === ':') {\n currentParent.colonOffset = offset;\n }\n else if (sep === ',') {\n ensurePropertyComplete(offset);\n }\n }\n },\n onError: (error, offset, length) => {\n errors.push({ error, offset, length });\n }\n };\n visit(text, visitor, options);\n const result = currentParent.children[0];\n if (result) {\n delete result.parent;\n }\n return result;\n}\n/**\n * Finds the node at the given path in a JSON DOM.\n */\nexport function findNodeAtLocation(root, path) {\n if (!root) {\n return undefined;\n }\n let node = root;\n for (let segment of path) {\n if (typeof segment === 'string') {\n if (node.type !== 'object' || !Array.isArray(node.children)) {\n return undefined;\n }\n let found = false;\n for (const propertyNode of node.children) {\n if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment && propertyNode.children.length === 2) {\n node = propertyNode.children[1];\n found = true;\n break;\n }\n }\n if (!found) {\n return undefined;\n }\n }\n else {\n const index = segment;\n if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {\n return undefined;\n }\n node = node.children[index];\n }\n }\n return node;\n}\n/**\n * Gets the JSON path of the given JSON DOM node\n */\nexport function getNodePath(node) {\n if (!node.parent || !node.parent.children) {\n return [];\n }\n const path = getNodePath(node.parent);\n if (node.parent.type === 'property') {\n const key = node.parent.children[0].value;\n path.push(key);\n }\n else if (node.parent.type === 'array') {\n const index = node.parent.children.indexOf(node);\n if (index !== -1) {\n path.push(index);\n }\n }\n return path;\n}\n/**\n * Evaluates the JavaScript object of the given JSON DOM node\n */\nexport function getNodeValue(node) {\n switch (node.type) {\n case 'array':\n return node.children.map(getNodeValue);\n case 'object':\n const obj = Object.create(null);\n for (let prop of node.children) {\n const valueNode = prop.children[1];\n if (valueNode) {\n obj[prop.children[0].value] = getNodeValue(valueNode);\n }\n }\n return obj;\n case 'null':\n case 'string':\n case 'number':\n case 'boolean':\n return node.value;\n default:\n return undefined;\n }\n}\nexport function contains(node, offset, includeRightBound = false) {\n return (offset >= node.offset && offset < (node.offset + node.length)) || includeRightBound && (offset === (node.offset + node.length));\n}\n/**\n * Finds the most inner node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.\n */\nexport function findNodeAtOffset(node, offset, includeRightBound = false) {\n if (contains(node, offset, includeRightBound)) {\n const children = node.children;\n if (Array.isArray(children)) {\n for (let i = 0; i < children.length && children[i].offset <= offset; i++) {\n const item = findNodeAtOffset(children[i], offset, includeRightBound);\n if (item) {\n return item;\n }\n }\n }\n return node;\n }\n return undefined;\n}\n/**\n * Parses the given text and invokes the visitor functions for each object, array and literal reached.\n */\nexport function visit(text, visitor, options = ParseOptions.DEFAULT) {\n const _scanner = createScanner(text, false);\n // Important: Only pass copies of this to visitor functions to prevent accidental modification, and\n // to not affect visitor functions which stored a reference to a previous JSONPath\n const _jsonPath = [];\n // Depth of onXXXBegin() callbacks suppressed. onXXXEnd() decrements this if it isn't 0 already.\n // Callbacks are only called when this value is 0.\n let suppressedCallbacks = 0;\n function toNoArgVisit(visitFunction) {\n return visitFunction ? () => suppressedCallbacks === 0 && visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;\n }\n function toOneArgVisit(visitFunction) {\n return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;\n }\n function toOneArgVisitWithPath(visitFunction) {\n return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice()) : () => true;\n }\n function toBeginVisit(visitFunction) {\n return visitFunction ?\n () => {\n if (suppressedCallbacks > 0) {\n suppressedCallbacks++;\n }\n else {\n let cbReturn = visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice());\n if (cbReturn === false) {\n suppressedCallbacks = 1;\n }\n }\n }\n : () => true;\n }\n function toEndVisit(visitFunction) {\n return visitFunction ?\n () => {\n if (suppressedCallbacks > 0) {\n suppressedCallbacks--;\n }\n if (suppressedCallbacks === 0) {\n visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());\n }\n }\n : () => true;\n }\n const onObjectBegin = toBeginVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisitWithPath(visitor.onObjectProperty), onObjectEnd = toEndVisit(visitor.onObjectEnd), onArrayBegin = toBeginVisit(visitor.onArrayBegin), onArrayEnd = toEndVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisitWithPath(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);\n const disallowComments = options && options.disallowComments;\n const allowTrailingComma = options && options.allowTrailingComma;\n function scanNext() {\n while (true) {\n const token = _scanner.scan();\n switch (_scanner.getTokenError()) {\n case 4 /* ScanError.InvalidUnicode */:\n handleError(14 /* ParseErrorCode.InvalidUnicode */);\n break;\n case 5 /* ScanError.InvalidEscapeCharacter */:\n handleError(15 /* ParseErrorCode.InvalidEscapeCharacter */);\n break;\n case 3 /* ScanError.UnexpectedEndOfNumber */:\n handleError(13 /* ParseErrorCode.UnexpectedEndOfNumber */);\n break;\n case 1 /* ScanError.UnexpectedEndOfComment */:\n if (!disallowComments) {\n handleError(11 /* ParseErrorCode.UnexpectedEndOfComment */);\n }\n break;\n case 2 /* ScanError.UnexpectedEndOfString */:\n handleError(12 /* ParseErrorCode.UnexpectedEndOfString */);\n break;\n case 6 /* ScanError.InvalidCharacter */:\n handleError(16 /* ParseErrorCode.InvalidCharacter */);\n break;\n }\n switch (token) {\n case 12 /* SyntaxKind.LineCommentTrivia */:\n case 13 /* SyntaxKind.BlockCommentTrivia */:\n if (disallowComments) {\n handleError(10 /* ParseErrorCode.InvalidCommentToken */);\n }\n else {\n onComment();\n }\n break;\n case 16 /* SyntaxKind.Unknown */:\n handleError(1 /* ParseErrorCode.InvalidSymbol */);\n break;\n case 15 /* SyntaxKind.Trivia */:\n case 14 /* SyntaxKind.LineBreakTrivia */:\n break;\n default:\n return token;\n }\n }\n }\n function handleError(error, skipUntilAfter = [], skipUntil = []) {\n onError(error);\n if (skipUntilAfter.length + skipUntil.length > 0) {\n let token = _scanner.getToken();\n while (token !== 17 /* SyntaxKind.EOF */) {\n if (skipUntilAfter.indexOf(token) !== -1) {\n scanNext();\n break;\n }\n else if (skipUntil.indexOf(token) !== -1) {\n break;\n }\n token = scanNext();\n }\n }\n }\n function parseString(isValue) {\n const value = _scanner.getTokenValue();\n if (isValue) {\n onLiteralValue(value);\n }\n else {\n onObjectProperty(value);\n // add property name afterwards\n _jsonPath.push(value);\n }\n scanNext();\n return true;\n }\n function parseLiteral() {\n switch (_scanner.getToken()) {\n case 11 /* SyntaxKind.NumericLiteral */:\n const tokenValue = _scanner.getTokenValue();\n let value = Number(tokenValue);\n if (isNaN(value)) {\n handleError(2 /* ParseErrorCode.InvalidNumberFormat */);\n value = 0;\n }\n onLiteralValue(value);\n break;\n case 7 /* SyntaxKind.NullKeyword */:\n onLiteralValue(null);\n break;\n case 8 /* SyntaxKind.TrueKeyword */:\n onLiteralValue(true);\n break;\n case 9 /* SyntaxKind.FalseKeyword */:\n onLiteralValue(false);\n break;\n default:\n return false;\n }\n scanNext();\n return true;\n }\n function parseProperty() {\n if (_scanner.getToken() !== 10 /* SyntaxKind.StringLiteral */) {\n handleError(3 /* ParseErrorCode.PropertyNameExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n return false;\n }\n parseString(false);\n if (_scanner.getToken() === 6 /* SyntaxKind.ColonToken */) {\n onSeparator(':');\n scanNext(); // consume colon\n if (!parseValue()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n }\n else {\n handleError(5 /* ParseErrorCode.ColonExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n _jsonPath.pop(); // remove processed property name\n return true;\n }\n function parseObject() {\n onObjectBegin();\n scanNext(); // consume open brace\n let needsComma = false;\n while (_scanner.getToken() !== 2 /* SyntaxKind.CloseBraceToken */ && _scanner.getToken() !== 17 /* SyntaxKind.EOF */) {\n if (_scanner.getToken() === 5 /* SyntaxKind.CommaToken */) {\n if (!needsComma) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n }\n onSeparator(',');\n scanNext(); // consume comma\n if (_scanner.getToken() === 2 /* SyntaxKind.CloseBraceToken */ && allowTrailingComma) {\n break;\n }\n }\n else if (needsComma) {\n handleError(6 /* ParseErrorCode.CommaExpected */, [], []);\n }\n if (!parseProperty()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n needsComma = true;\n }\n onObjectEnd();\n if (_scanner.getToken() !== 2 /* SyntaxKind.CloseBraceToken */) {\n handleError(7 /* ParseErrorCode.CloseBraceExpected */, [2 /* SyntaxKind.CloseBraceToken */], []);\n }\n else {\n scanNext(); // consume close brace\n }\n return true;\n }\n function parseArray() {\n onArrayBegin();\n scanNext(); // consume open bracket\n let isFirstElement = true;\n let needsComma = false;\n while (_scanner.getToken() !== 4 /* SyntaxKind.CloseBracketToken */ && _scanner.getToken() !== 17 /* SyntaxKind.EOF */) {\n if (_scanner.getToken() === 5 /* SyntaxKind.CommaToken */) {\n if (!needsComma) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n }\n onSeparator(',');\n scanNext(); // consume comma\n if (_scanner.getToken() === 4 /* SyntaxKind.CloseBracketToken */ && allowTrailingComma) {\n break;\n }\n }\n else if (needsComma) {\n handleError(6 /* ParseErrorCode.CommaExpected */, [], []);\n }\n if (isFirstElement) {\n _jsonPath.push(0);\n isFirstElement = false;\n }\n else {\n _jsonPath[_jsonPath.length - 1]++;\n }\n if (!parseValue()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], [4 /* SyntaxKind.CloseBracketToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n needsComma = true;\n }\n onArrayEnd();\n if (!isFirstElement) {\n _jsonPath.pop(); // remove array index\n }\n if (_scanner.getToken() !== 4 /* SyntaxKind.CloseBracketToken */) {\n handleError(8 /* ParseErrorCode.CloseBracketExpected */, [4 /* SyntaxKind.CloseBracketToken */], []);\n }\n else {\n scanNext(); // consume close bracket\n }\n return true;\n }\n function parseValue() {\n switch (_scanner.getToken()) {\n case 3 /* SyntaxKind.OpenBracketToken */:\n return parseArray();\n case 1 /* SyntaxKind.OpenBraceToken */:\n return parseObject();\n case 10 /* SyntaxKind.StringLiteral */:\n return parseString(true);\n default:\n return parseLiteral();\n }\n }\n scanNext();\n if (_scanner.getToken() === 17 /* SyntaxKind.EOF */) {\n if (options.allowEmptyContent) {\n return true;\n }\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n return false;\n }\n if (!parseValue()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n return false;\n }\n if (_scanner.getToken() !== 17 /* SyntaxKind.EOF */) {\n handleError(9 /* ParseErrorCode.EndOfFileExpected */, [], []);\n }\n return true;\n}\n/**\n * Takes JSON with JavaScript-style comments and remove\n * them. Optionally replaces every none-newline character\n * of comments with a replaceCharacter\n */\nexport function stripComments(text, replaceCh) {\n let _scanner = createScanner(text), parts = [], kind, offset = 0, pos;\n do {\n pos = _scanner.getPosition();\n kind = _scanner.scan();\n switch (kind) {\n case 12 /* SyntaxKind.LineCommentTrivia */:\n case 13 /* SyntaxKind.BlockCommentTrivia */:\n case 17 /* SyntaxKind.EOF */:\n if (offset !== pos) {\n parts.push(text.substring(offset, pos));\n }\n if (replaceCh !== undefined) {\n parts.push(_scanner.getTokenValue().replace(/[^\\r\\n]/g, replaceCh));\n }\n offset = _scanner.getPosition();\n break;\n }\n } while (kind !== 17 /* SyntaxKind.EOF */);\n return parts.join('');\n}\nexport function getNodeType(value) {\n switch (typeof value) {\n case 'boolean': return 'boolean';\n case 'number': return 'number';\n case 'string': return 'string';\n case 'object': {\n if (!value) {\n return 'null';\n }\n else if (Array.isArray(value)) {\n return 'array';\n }\n return 'object';\n }\n default: return 'null';\n }\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\nimport * as formatter from './impl/format';\nimport * as edit from './impl/edit';\nimport * as scanner from './impl/scanner';\nimport * as parser from './impl/parser';\n/**\n * Creates a JSON scanner on the given text.\n * If ignoreTrivia is set, whitespaces or comments are ignored.\n */\nexport const createScanner = scanner.createScanner;\nexport var ScanError;\n(function (ScanError) {\n ScanError[ScanError[\"None\"] = 0] = \"None\";\n ScanError[ScanError[\"UnexpectedEndOfComment\"] = 1] = \"UnexpectedEndOfComment\";\n ScanError[ScanError[\"UnexpectedEndOfString\"] = 2] = \"UnexpectedEndOfString\";\n ScanError[ScanError[\"UnexpectedEndOfNumber\"] = 3] = \"UnexpectedEndOfNumber\";\n ScanError[ScanError[\"InvalidUnicode\"] = 4] = \"InvalidUnicode\";\n ScanError[ScanError[\"InvalidEscapeCharacter\"] = 5] = \"InvalidEscapeCharacter\";\n ScanError[ScanError[\"InvalidCharacter\"] = 6] = \"InvalidCharacter\";\n})(ScanError || (ScanError = {}));\nexport var SyntaxKind;\n(function (SyntaxKind) {\n SyntaxKind[SyntaxKind[\"OpenBraceToken\"] = 1] = \"OpenBraceToken\";\n SyntaxKind[SyntaxKind[\"CloseBraceToken\"] = 2] = \"CloseBraceToken\";\n SyntaxKind[SyntaxKind[\"OpenBracketToken\"] = 3] = \"OpenBracketToken\";\n SyntaxKind[SyntaxKind[\"CloseBracketToken\"] = 4] = \"CloseBracketToken\";\n SyntaxKind[SyntaxKind[\"CommaToken\"] = 5] = \"CommaToken\";\n SyntaxKind[SyntaxKind[\"ColonToken\"] = 6] = \"ColonToken\";\n SyntaxKind[SyntaxKind[\"NullKeyword\"] = 7] = \"NullKeyword\";\n SyntaxKind[SyntaxKind[\"TrueKeyword\"] = 8] = \"TrueKeyword\";\n SyntaxKind[SyntaxKind[\"FalseKeyword\"] = 9] = \"FalseKeyword\";\n SyntaxKind[SyntaxKind[\"StringLiteral\"] = 10] = \"StringLiteral\";\n SyntaxKind[SyntaxKind[\"NumericLiteral\"] = 11] = \"NumericLiteral\";\n SyntaxKind[SyntaxKind[\"LineCommentTrivia\"] = 12] = \"LineCommentTrivia\";\n SyntaxKind[SyntaxKind[\"BlockCommentTrivia\"] = 13] = \"BlockCommentTrivia\";\n SyntaxKind[SyntaxKind[\"LineBreakTrivia\"] = 14] = \"LineBreakTrivia\";\n SyntaxKind[SyntaxKind[\"Trivia\"] = 15] = \"Trivia\";\n SyntaxKind[SyntaxKind[\"Unknown\"] = 16] = \"Unknown\";\n SyntaxKind[SyntaxKind[\"EOF\"] = 17] = \"EOF\";\n})(SyntaxKind || (SyntaxKind = {}));\n/**\n * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.\n */\nexport const getLocation = parser.getLocation;\n/**\n * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n * Therefore, always check the errors list to find out if the input was valid.\n */\nexport const parse = parser.parse;\n/**\n * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n */\nexport const parseTree = parser.parseTree;\n/**\n * Finds the node at the given path in a JSON DOM.\n */\nexport const findNodeAtLocation = parser.findNodeAtLocation;\n/**\n * Finds the innermost node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.\n */\nexport const findNodeAtOffset = parser.findNodeAtOffset;\n/**\n * Gets the JSON path of the given JSON DOM node\n */\nexport const getNodePath = parser.getNodePath;\n/**\n * Evaluates the JavaScript object of the given JSON DOM node\n */\nexport const getNodeValue = parser.getNodeValue;\n/**\n * Parses the given text and invokes the visitor functions for each object, array and literal reached.\n */\nexport const visit = parser.visit;\n/**\n * Takes JSON with JavaScript-style comments and remove\n * them. Optionally replaces every none-newline character\n * of comments with a replaceCharacter\n */\nexport const stripComments = parser.stripComments;\nexport var ParseErrorCode;\n(function (ParseErrorCode) {\n ParseErrorCode[ParseErrorCode[\"InvalidSymbol\"] = 1] = \"InvalidSymbol\";\n ParseErrorCode[ParseErrorCode[\"InvalidNumberFormat\"] = 2] = \"InvalidNumberFormat\";\n ParseErrorCode[ParseErrorCode[\"PropertyNameExpected\"] = 3] = \"PropertyNameExpected\";\n ParseErrorCode[ParseErrorCode[\"ValueExpected\"] = 4] = \"ValueExpected\";\n ParseErrorCode[ParseErrorCode[\"ColonExpected\"] = 5] = \"ColonExpected\";\n ParseErrorCode[ParseErrorCode[\"CommaExpected\"] = 6] = \"CommaExpected\";\n ParseErrorCode[ParseErrorCode[\"CloseBraceExpected\"] = 7] = \"CloseBraceExpected\";\n ParseErrorCode[ParseErrorCode[\"CloseBracketExpected\"] = 8] = \"CloseBracketExpected\";\n ParseErrorCode[ParseErrorCode[\"EndOfFileExpected\"] = 9] = \"EndOfFileExpected\";\n ParseErrorCode[ParseErrorCode[\"InvalidCommentToken\"] = 10] = \"InvalidCommentToken\";\n ParseErrorCode[ParseErrorCode[\"UnexpectedEndOfComment\"] = 11] = \"UnexpectedEndOfComment\";\n ParseErrorCode[ParseErrorCode[\"UnexpectedEndOfString\"] = 12] = \"UnexpectedEndOfString\";\n ParseErrorCode[ParseErrorCode[\"UnexpectedEndOfNumber\"] = 13] = \"UnexpectedEndOfNumber\";\n ParseErrorCode[ParseErrorCode[\"InvalidUnicode\"] = 14] = \"InvalidUnicode\";\n ParseErrorCode[ParseErrorCode[\"InvalidEscapeCharacter\"] = 15] = \"InvalidEscapeCharacter\";\n ParseErrorCode[ParseErrorCode[\"InvalidCharacter\"] = 16] = \"InvalidCharacter\";\n})(ParseErrorCode || (ParseErrorCode = {}));\nexport function printParseErrorCode(code) {\n switch (code) {\n case 1 /* ParseErrorCode.InvalidSymbol */: return 'InvalidSymbol';\n case 2 /* ParseErrorCode.InvalidNumberFormat */: return 'InvalidNumberFormat';\n case 3 /* ParseErrorCode.PropertyNameExpected */: return 'PropertyNameExpected';\n case 4 /* ParseErrorCode.ValueExpected */: return 'ValueExpected';\n case 5 /* ParseErrorCode.ColonExpected */: return 'ColonExpected';\n case 6 /* ParseErrorCode.CommaExpected */: return 'CommaExpected';\n case 7 /* ParseErrorCode.CloseBraceExpected */: return 'CloseBraceExpected';\n case 8 /* ParseErrorCode.CloseBracketExpected */: return 'CloseBracketExpected';\n case 9 /* ParseErrorCode.EndOfFileExpected */: return 'EndOfFileExpected';\n case 10 /* ParseErrorCode.InvalidCommentToken */: return 'InvalidCommentToken';\n case 11 /* ParseErrorCode.UnexpectedEndOfComment */: return 'UnexpectedEndOfComment';\n case 12 /* ParseErrorCode.UnexpectedEndOfString */: return 'UnexpectedEndOfString';\n case 13 /* ParseErrorCode.UnexpectedEndOfNumber */: return 'UnexpectedEndOfNumber';\n case 14 /* ParseErrorCode.InvalidUnicode */: return 'InvalidUnicode';\n case 15 /* ParseErrorCode.InvalidEscapeCharacter */: return 'InvalidEscapeCharacter';\n case 16 /* ParseErrorCode.InvalidCharacter */: return 'InvalidCharacter';\n }\n return '<unknown ParseErrorCode>';\n}\n/**\n * Computes the edit operations needed to format a JSON document.\n *\n * @param documentText The input text\n * @param range The range to format or `undefined` to format the full content\n * @param options The formatting options\n * @returns The edit operations describing the formatting changes to the original document following the format described in {@linkcode EditResult}.\n * To apply the edit operations to the input, use {@linkcode applyEdits}.\n */\nexport function format(documentText, range, options) {\n return formatter.format(documentText, range, options);\n}\n/**\n * Computes the edit operations needed to modify a value in the JSON document.\n *\n * @param documentText The input text\n * @param path The path of the value to change. The path represents either to the document root, a property or an array item.\n * If the path points to an non-existing property or item, it will be created.\n * @param value The new value for the specified property or item. If the value is undefined,\n * the property or item will be removed.\n * @param options Options\n * @returns The edit operations describing the changes to the original document, following the format described in {@linkcode EditResult}.\n * To apply the edit operations to the input, use {@linkcode applyEdits}.\n */\nexport function modify(text, path, value, options) {\n return edit.setProperty(text, path, value, options);\n}\n/**\n * Applies edits to an input string.\n * @param text The input text\n * @param edits Edit operations following the format described in {@linkcode EditResult}.\n * @returns The text with the applied edits.\n * @throws An error if the edit operations are not well-formed as described in {@linkcode EditResult}.\n */\nexport function applyEdits(text, edits) {\n let sortedEdits = edits.slice(0).sort((a, b) => {\n const diff = a.offset - b.offset;\n if (diff === 0) {\n return a.length - b.length;\n }\n return diff;\n });\n let lastModifiedOffset = text.length;\n for (let i = sortedEdits.length - 1; i >= 0; i--) {\n let e = sortedEdits[i];\n if (e.offset + e.length <= lastModifiedOffset) {\n text = edit.applyEdit(text, e);\n }\n else {\n throw new Error('Overlapping edit');\n }\n lastModifiedOffset = e.offset;\n }\n return text;\n}\n","/**\n * Pure config validation logic — no runtime dependencies (fs, jsonc-parser, etc.)\n * This module is extracted from config.ts to enable direct unit testing.\n */\n\nexport const VALID_CONFIG_KEYS = new Set([\n \"$schema\",\n \"enabled\",\n \"autoUpdate\",\n \"debug\",\n \"showUpdateToasts\",\n \"pruneNotification\",\n \"pruneNotificationType\",\n \"turnProtection\",\n \"turnProtection.enabled\",\n \"turnProtection.turns\",\n \"experimental\",\n \"experimental.allowSubAgents\",\n \"experimental.customPrompts\",\n \"protectedFilePatterns\",\n \"commands\",\n \"commands.enabled\",\n \"commands.protectedTools\",\n \"manualMode\",\n \"manualMode.enabled\",\n \"manualMode.automaticStrategies\",\n \"compress\",\n \"compress.mode\",\n \"compress.permission\",\n \"compress.showCompression\",\n \"compress.summaryBuffer\",\n \"compress.maxContextLimit\",\n \"compress.minContextLimit\",\n \"compress.modelMaxLimits\",\n \"compress.modelMinLimits\",\n \"compress.nudgeFrequency\",\n \"compress.iterationNudgeThreshold\",\n \"compress.nudgeForce\",\n \"compress.protectedTools\",\n \"compress.protectTags\",\n \"compress.protectUserMessages\",\n \"gc\",\n \"gc.algorithm\",\n \"gc.promotionThreshold\",\n \"gc.maxBlockAge\",\n \"gc.maxOldGenSummaryLength\",\n \"gc.majorGcThresholdPercent\",\n \"gc.batchCleanup\",\n \"gc.batchCleanup.lowThreshold\",\n \"gc.batchCleanup.highThreshold\",\n \"gc.batchCleanup.forceThreshold\",\n \"strategies\",\n \"strategies.deduplication\",\n \"strategies.deduplication.enabled\",\n \"strategies.deduplication.protectedTools\",\n \"strategies.purgeErrors\",\n \"strategies.purgeErrors.enabled\",\n \"strategies.purgeErrors.turns\",\n \"strategies.purgeErrors.protectedTools\",\n])\n\nexport function getConfigKeyPaths(obj: Record<string, any>, prefix = \"\"): string[] {\n const keys: string[] = []\n for (const key of Object.keys(obj)) {\n const fullKey = prefix ? `${prefix}.${key}` : key\n keys.push(fullKey)\n\n // model*Limits are dynamic maps keyed by providerID/modelID; do not recurse into arbitrary IDs.\n if (fullKey === \"compress.modelMaxLimits\" || fullKey === \"compress.modelMinLimits\") {\n continue\n }\n\n if (obj[key] && typeof obj[key] === \"object\" && !Array.isArray(obj[key])) {\n keys.push(...getConfigKeyPaths(obj[key], fullKey))\n }\n }\n return keys\n}\n\nexport function getInvalidConfigKeys(userConfig: Record<string, any>): string[] {\n const userKeys = getConfigKeyPaths(userConfig)\n return userKeys.filter((key) => !VALID_CONFIG_KEYS.has(key))\n}\n\nexport interface ValidationError {\n key: string\n expected: string\n actual: string\n}\n\nexport function validateConfigTypes(config: Record<string, any>): ValidationError[] {\n const errors: ValidationError[] = []\n\n if (config.enabled !== undefined && typeof config.enabled !== \"boolean\") {\n errors.push({ key: \"enabled\", expected: \"boolean\", actual: typeof config.enabled })\n }\n\n if (config.autoUpdate !== undefined && typeof config.autoUpdate !== \"boolean\") {\n errors.push({ key: \"autoUpdate\", expected: \"boolean\", actual: typeof config.autoUpdate })\n }\n\n if (config.debug !== undefined && typeof config.debug !== \"boolean\") {\n errors.push({ key: \"debug\", expected: \"boolean\", actual: typeof config.debug })\n }\n\n if (config.pruneNotification !== undefined) {\n const validValues = [\"off\", \"minimal\", \"detailed\"]\n if (!validValues.includes(config.pruneNotification)) {\n errors.push({\n key: \"pruneNotification\",\n expected: '\"off\" | \"minimal\" | \"detailed\"',\n actual: JSON.stringify(config.pruneNotification),\n })\n }\n }\n\n if (config.pruneNotificationType !== undefined) {\n const validValues = [\"chat\", \"toast\"]\n if (!validValues.includes(config.pruneNotificationType)) {\n errors.push({\n key: \"pruneNotificationType\",\n expected: '\"chat\" | \"toast\"',\n actual: JSON.stringify(config.pruneNotificationType),\n })\n }\n }\n\n if (config.protectedFilePatterns !== undefined) {\n if (!Array.isArray(config.protectedFilePatterns)) {\n errors.push({\n key: \"protectedFilePatterns\",\n expected: \"string[]\",\n actual: typeof config.protectedFilePatterns,\n })\n } else if (!config.protectedFilePatterns.every((v: unknown) => typeof v === \"string\")) {\n errors.push({\n key: \"protectedFilePatterns\",\n expected: \"string[]\",\n actual: \"non-string entries\",\n })\n }\n }\n\n if (config.turnProtection) {\n if (\n config.turnProtection.enabled !== undefined &&\n typeof config.turnProtection.enabled !== \"boolean\"\n ) {\n errors.push({\n key: \"turnProtection.enabled\",\n expected: \"boolean\",\n actual: typeof config.turnProtection.enabled,\n })\n }\n\n if (\n config.turnProtection.turns !== undefined &&\n typeof config.turnProtection.turns !== \"number\"\n ) {\n errors.push({\n key: \"turnProtection.turns\",\n expected: \"number\",\n actual: typeof config.turnProtection.turns,\n })\n }\n if (typeof config.turnProtection.turns === \"number\" && config.turnProtection.turns < 1) {\n errors.push({\n key: \"turnProtection.turns\",\n expected: \"positive number (>= 1)\",\n actual: `${config.turnProtection.turns}`,\n })\n }\n }\n\n const experimental = config.experimental\n if (experimental !== undefined) {\n if (\n typeof experimental !== \"object\" ||\n experimental === null ||\n Array.isArray(experimental)\n ) {\n errors.push({\n key: \"experimental\",\n expected: \"object\",\n actual: typeof experimental,\n })\n } else {\n if (\n experimental.allowSubAgents !== undefined &&\n typeof experimental.allowSubAgents !== \"boolean\"\n ) {\n errors.push({\n key: \"experimental.allowSubAgents\",\n expected: \"boolean\",\n actual: typeof experimental.allowSubAgents,\n })\n }\n\n if (\n experimental.customPrompts !== undefined &&\n typeof experimental.customPrompts !== \"boolean\"\n ) {\n errors.push({\n key: \"experimental.customPrompts\",\n expected: \"boolean\",\n actual: typeof experimental.customPrompts,\n })\n }\n }\n }\n\n const commands = config.commands\n if (commands !== undefined) {\n if (typeof commands !== \"object\" || commands === null || Array.isArray(commands)) {\n errors.push({\n key: \"commands\",\n expected: \"object\",\n actual: typeof commands,\n })\n } else {\n if (commands.enabled !== undefined && typeof commands.enabled !== \"boolean\") {\n errors.push({\n key: \"commands.enabled\",\n expected: \"boolean\",\n actual: typeof commands.enabled,\n })\n }\n if (commands.protectedTools !== undefined && !Array.isArray(commands.protectedTools)) {\n errors.push({\n key: \"commands.protectedTools\",\n expected: \"string[]\",\n actual: typeof commands.protectedTools,\n })\n }\n }\n }\n\n const manualMode = config.manualMode\n if (manualMode !== undefined) {\n if (typeof manualMode !== \"object\" || manualMode === null || Array.isArray(manualMode)) {\n errors.push({\n key: \"manualMode\",\n expected: \"object\",\n actual: typeof manualMode,\n })\n } else {\n if (manualMode.enabled !== undefined && typeof manualMode.enabled !== \"boolean\") {\n errors.push({\n key: \"manualMode.enabled\",\n expected: \"boolean\",\n actual: typeof manualMode.enabled,\n })\n }\n\n if (\n manualMode.automaticStrategies !== undefined &&\n typeof manualMode.automaticStrategies !== \"boolean\"\n ) {\n errors.push({\n key: \"manualMode.automaticStrategies\",\n expected: \"boolean\",\n actual: typeof manualMode.automaticStrategies,\n })\n }\n }\n }\n\n const compress = config.compress\n if (compress !== undefined) {\n if (typeof compress !== \"object\" || compress === null || Array.isArray(compress)) {\n errors.push({\n key: \"compress\",\n expected: \"object\",\n actual: typeof compress,\n })\n } else {\n if (\n compress.mode !== undefined &&\n compress.mode !== \"range\" &&\n compress.mode !== \"message\"\n ) {\n errors.push({\n key: \"compress.mode\",\n expected: '\"range\" | \"message\"',\n actual: JSON.stringify(compress.mode),\n })\n }\n\n if (\n compress.summaryBuffer !== undefined &&\n typeof compress.summaryBuffer !== \"boolean\"\n ) {\n errors.push({\n key: \"compress.summaryBuffer\",\n expected: \"boolean\",\n actual: typeof compress.summaryBuffer,\n })\n }\n\n if (\n compress.nudgeFrequency !== undefined &&\n typeof compress.nudgeFrequency !== \"number\"\n ) {\n errors.push({\n key: \"compress.nudgeFrequency\",\n expected: \"number\",\n actual: typeof compress.nudgeFrequency,\n })\n }\n\n if (typeof compress.nudgeFrequency === \"number\" && compress.nudgeFrequency < 1) {\n errors.push({\n key: \"compress.nudgeFrequency\",\n expected: \"positive number (>= 1)\",\n actual: `${compress.nudgeFrequency} (will be clamped to 1)`,\n })\n }\n\n if (\n compress.iterationNudgeThreshold !== undefined &&\n typeof compress.iterationNudgeThreshold !== \"number\"\n ) {\n errors.push({\n key: \"compress.iterationNudgeThreshold\",\n expected: \"number\",\n actual: typeof compress.iterationNudgeThreshold,\n })\n }\n\n if (\n compress.nudgeForce !== undefined &&\n compress.nudgeForce !== \"strong\" &&\n compress.nudgeForce !== \"soft\"\n ) {\n errors.push({\n key: \"compress.nudgeForce\",\n expected: '\"strong\" | \"soft\"',\n actual: JSON.stringify(compress.nudgeForce),\n })\n }\n\n if (compress.protectedTools !== undefined && !Array.isArray(compress.protectedTools)) {\n errors.push({\n key: \"compress.protectedTools\",\n expected: \"string[]\",\n actual: typeof compress.protectedTools,\n })\n }\n\n if (compress.protectTags !== undefined && typeof compress.protectTags !== \"boolean\") {\n errors.push({\n key: \"compress.protectTags\",\n expected: \"boolean\",\n actual: typeof compress.protectTags,\n })\n }\n\n if (\n compress.protectUserMessages !== undefined &&\n typeof compress.protectUserMessages !== \"boolean\"\n ) {\n errors.push({\n key: \"compress.protectUserMessages\",\n expected: \"boolean\",\n actual: typeof compress.protectUserMessages,\n })\n }\n\n if (\n typeof compress.iterationNudgeThreshold === \"number\" &&\n compress.iterationNudgeThreshold < 1\n ) {\n errors.push({\n key: \"compress.iterationNudgeThreshold\",\n expected: \"positive number (>= 1)\",\n actual: `${compress.iterationNudgeThreshold} (will be clamped to 1)`,\n })\n }\n\n const validateLimitValue = (\n key: string,\n value: unknown,\n actualValue: unknown = value,\n ): void => {\n const isValidNumber = typeof value === \"number\"\n const isPercentString = typeof value === \"string\" && value.endsWith(\"%\")\n\n if (!isValidNumber && !isPercentString) {\n errors.push({\n key,\n expected: 'number | \"${number}%\"',\n actual: JSON.stringify(actualValue),\n })\n }\n }\n\n const validateModelLimits = (\n key: \"compress.modelMaxLimits\" | \"compress.modelMinLimits\",\n limits: unknown,\n ): void => {\n if (limits === undefined) {\n return\n }\n\n if (typeof limits !== \"object\" || limits === null || Array.isArray(limits)) {\n errors.push({\n key,\n expected: \"Record<string, number | ${number}%>\",\n actual: typeof limits,\n })\n return\n }\n\n for (const [providerModelKey, limit] of Object.entries(limits)) {\n const isValidNumber = typeof limit === \"number\"\n const isPercentString =\n typeof limit === \"string\" && /^\\d+(?:\\.\\d+)?%$/.test(limit)\n if (!isValidNumber && !isPercentString) {\n errors.push({\n key: `${key}.${providerModelKey}`,\n expected: 'number | \"${number}%\"',\n actual: JSON.stringify(limit),\n })\n }\n }\n }\n\n if (compress.maxContextLimit !== undefined) {\n validateLimitValue(\"compress.maxContextLimit\", compress.maxContextLimit)\n }\n\n if (compress.minContextLimit !== undefined) {\n validateLimitValue(\"compress.minContextLimit\", compress.minContextLimit)\n }\n\n validateModelLimits(\"compress.modelMaxLimits\", compress.modelMaxLimits)\n validateModelLimits(\"compress.modelMinLimits\", compress.modelMinLimits)\n\n const validValues = [\"ask\", \"allow\", \"deny\"]\n if (compress.permission !== undefined && !validValues.includes(compress.permission)) {\n errors.push({\n key: \"compress.permission\",\n expected: '\"ask\" | \"allow\" | \"deny\"',\n actual: JSON.stringify(compress.permission),\n })\n }\n\n if (\n compress.showCompression !== undefined &&\n typeof compress.showCompression !== \"boolean\"\n ) {\n errors.push({\n key: \"compress.showCompression\",\n expected: \"boolean\",\n actual: typeof compress.showCompression,\n })\n }\n }\n }\n\n const gc = config.gc\n if (gc !== undefined) {\n if (typeof gc !== \"object\" || gc === null || Array.isArray(gc)) {\n errors.push({\n key: \"gc\",\n expected: \"object\",\n actual: typeof gc,\n })\n } else {\n if (gc.algorithm !== undefined && gc.algorithm !== \"truncate\") {\n errors.push({\n key: \"gc.algorithm\",\n expected: '\"truncate\"',\n actual: JSON.stringify(gc.algorithm),\n })\n }\n if (gc.promotionThreshold !== undefined && typeof gc.promotionThreshold !== \"number\") {\n errors.push({\n key: \"gc.promotionThreshold\",\n expected: \"number\",\n actual: typeof gc.promotionThreshold,\n })\n }\n if (gc.maxBlockAge !== undefined && typeof gc.maxBlockAge !== \"number\") {\n errors.push({\n key: \"gc.maxBlockAge\",\n expected: \"number\",\n actual: typeof gc.maxBlockAge,\n })\n }\n if (\n gc.maxOldGenSummaryLength !== undefined &&\n typeof gc.maxOldGenSummaryLength !== \"number\"\n ) {\n errors.push({\n key: \"gc.maxOldGenSummaryLength\",\n expected: \"number\",\n actual: typeof gc.maxOldGenSummaryLength,\n })\n }\n if (\n gc.majorGcThresholdPercent !== undefined\n ) {\n const isValidNumber = typeof gc.majorGcThresholdPercent === \"number\"\n const isPercentString =\n typeof gc.majorGcThresholdPercent === \"string\" &&\n /^\\d+(?:\\.\\d+)?%$/.test(gc.majorGcThresholdPercent)\n if (!isValidNumber && !isPercentString) {\n errors.push({\n key: \"gc.majorGcThresholdPercent\",\n expected: 'number | \"${number}%\"',\n actual: JSON.stringify(gc.majorGcThresholdPercent),\n })\n }\n }\n\n const validateBatchThreshold = (\n key: \"gc.batchCleanup.lowThreshold\" | \"gc.batchCleanup.highThreshold\" | \"gc.batchCleanup.forceThreshold\",\n value: unknown,\n ): void => {\n const isValidNumber = typeof value === \"number\"\n const isPercentString = typeof value === \"string\" && /^\\d+(?:\\.\\d+)?%$/.test(value)\n if (!isValidNumber && !isPercentString) {\n errors.push({\n key,\n expected: 'number | \"${number}%\"',\n actual: JSON.stringify(value),\n })\n }\n }\n\n if (gc.batchCleanup !== undefined) {\n if (\n typeof gc.batchCleanup !== \"object\" ||\n gc.batchCleanup === null ||\n Array.isArray(gc.batchCleanup)\n ) {\n errors.push({\n key: \"gc.batchCleanup\",\n expected: \"object\",\n actual: typeof gc.batchCleanup,\n })\n } else {\n if (gc.batchCleanup.lowThreshold !== undefined) {\n validateBatchThreshold(\"gc.batchCleanup.lowThreshold\", gc.batchCleanup.lowThreshold)\n }\n if (gc.batchCleanup.highThreshold !== undefined) {\n validateBatchThreshold(\"gc.batchCleanup.highThreshold\", gc.batchCleanup.highThreshold)\n }\n if (gc.batchCleanup.forceThreshold !== undefined) {\n validateBatchThreshold(\"gc.batchCleanup.forceThreshold\", gc.batchCleanup.forceThreshold)\n }\n }\n }\n }\n }\n\n const strategies = config.strategies\n if (strategies !== undefined) {\n if (typeof strategies !== \"object\" || strategies === null || Array.isArray(strategies)) {\n errors.push({\n key: \"strategies\",\n expected: \"object\",\n actual: typeof strategies,\n })\n } else {\n const dedup = strategies.deduplication\n if (dedup !== undefined) {\n if (typeof dedup !== \"object\" || dedup === null || Array.isArray(dedup)) {\n errors.push({\n key: \"strategies.deduplication\",\n expected: \"object\",\n actual: typeof dedup,\n })\n } else {\n if (dedup.enabled !== undefined && typeof dedup.enabled !== \"boolean\") {\n errors.push({\n key: \"strategies.deduplication.enabled\",\n expected: \"boolean\",\n actual: typeof dedup.enabled,\n })\n }\n if (dedup.protectedTools !== undefined && !Array.isArray(dedup.protectedTools)) {\n errors.push({\n key: \"strategies.deduplication.protectedTools\",\n expected: \"string[]\",\n actual: typeof dedup.protectedTools,\n })\n }\n }\n }\n\n const purge = strategies.purgeErrors\n if (purge !== undefined) {\n if (typeof purge !== \"object\" || purge === null || Array.isArray(purge)) {\n errors.push({\n key: \"strategies.purgeErrors\",\n expected: \"object\",\n actual: typeof purge,\n })\n } else {\n if (purge.enabled !== undefined && typeof purge.enabled !== \"boolean\") {\n errors.push({\n key: \"strategies.purgeErrors.enabled\",\n expected: \"boolean\",\n actual: typeof purge.enabled,\n })\n }\n if (purge.turns !== undefined && typeof purge.turns !== \"number\") {\n errors.push({\n key: \"strategies.purgeErrors.turns\",\n expected: \"number\",\n actual: typeof purge.turns,\n })\n }\n if (typeof purge.turns === \"number\" && purge.turns < 1) {\n errors.push({\n key: \"strategies.purgeErrors.turns\",\n expected: \"positive number (>= 1)\",\n actual: `${purge.turns} (will be clamped to 1)`,\n })\n }\n if (purge.protectedTools !== undefined && !Array.isArray(purge.protectedTools)) {\n errors.push({\n key: \"strategies.purgeErrors.protectedTools\",\n expected: \"string[]\",\n actual: typeof purge.protectedTools,\n })\n }\n }\n }\n }\n }\n\n return errors\n}\n","import { tool } from \"@opencode-ai/plugin\"\nimport type { ToolContext } from \"./types\"\nimport { countTokens } from \"../token-utils\"\nimport { MESSAGE_FORMAT_EXTENSION } from \"../prompts/extensions/tool\"\nimport { formatIssues, formatResult, resolveMessages, validateArgs } from \"./message-utils\"\nimport { finalizeSession, prepareSession, type NotificationEntry } from \"./pipeline\"\nimport { appendProtectedPromptInfo, appendProtectedTools } from \"./protected-content\"\nimport {\n allocateBlockId,\n allocateRunId,\n applyCompressionState,\n wrapCompressedSummary,\n} from \"./state\"\nimport type { CompressMessageToolArgs } from \"./types\"\n\nfunction buildSchema() {\n return {\n topic: tool.schema\n .string()\n .describe(\n \"Short label (3-5 words) for the overall batch - e.g., 'Closed Research Notes'\",\n ),\n content: tool.schema\n .array(\n tool.schema.object({\n messageId: tool.schema\n .string()\n .describe(\"Raw message ID to compress (e.g. m00001)\"),\n topic: tool.schema\n .string()\n .describe(\"Short label (3-5 words) for this one message summary\"),\n summary: tool.schema\n .string()\n .describe(\"Complete technical summary replacing that one message\"),\n }),\n )\n .describe(\"Batch of individual message summaries to create in one tool call\"),\n }\n}\n\nexport function createCompressMessageTool(ctx: ToolContext): ReturnType<typeof tool> {\n ctx.prompts.reload()\n const runtimePrompts = ctx.prompts.getRuntimePrompts()\n\n return tool({\n description: runtimePrompts.compressMessage + MESSAGE_FORMAT_EXTENSION,\n args: buildSchema(),\n async execute(args, toolCtx) {\n const input = args as CompressMessageToolArgs\n validateArgs(input)\n const callId =\n typeof (toolCtx as unknown as { callID?: unknown }).callID === \"string\"\n ? (toolCtx as unknown as { callID: string }).callID\n : undefined\n\n const { rawMessages, searchContext } = await prepareSession(\n ctx,\n toolCtx,\n `Compress Message: ${input.topic}`,\n )\n const { plans, skippedIssues, skippedCount } = resolveMessages(\n input,\n searchContext,\n ctx.state,\n ctx.config,\n )\n\n if (plans.length === 0 && skippedCount > 0) {\n throw new Error(formatIssues(skippedIssues, skippedCount))\n }\n\n const notifications: NotificationEntry[] = []\n\n const preparedPlans: Array<{\n plan: (typeof plans)[number]\n summaryWithTools: string\n }> = []\n\n for (const plan of plans) {\n const summaryWithPromptInfo = appendProtectedPromptInfo(\n plan.entry.summary,\n plan.selection,\n searchContext,\n ctx.state,\n ctx.config.compress.protectTags,\n )\n\n const summaryWithTools = await appendProtectedTools(\n ctx.client,\n ctx.state,\n ctx.config.experimental.allowSubAgents,\n summaryWithPromptInfo,\n plan.selection,\n searchContext,\n ctx.config.compress.protectedTools,\n ctx.config.protectedFilePatterns,\n )\n\n preparedPlans.push({\n plan,\n summaryWithTools,\n })\n }\n\n const runId = allocateRunId(ctx.state)\n\n for (const { plan, summaryWithTools } of preparedPlans) {\n const blockId = allocateBlockId(ctx.state)\n const storedSummary = wrapCompressedSummary(blockId, summaryWithTools)\n const summaryTokens = countTokens(storedSummary)\n\n applyCompressionState(\n ctx.state,\n {\n topic: plan.entry.topic,\n batchTopic: input.topic,\n startId: plan.entry.messageId,\n endId: plan.entry.messageId,\n mode: \"message\",\n runId,\n compressMessageId: toolCtx.messageID,\n compressCallId: callId,\n summaryTokens,\n },\n plan.selection,\n plan.anchorMessageId,\n blockId,\n storedSummary,\n [],\n ctx.config.gc,\n )\n\n notifications.push({\n blockId,\n runId,\n summary: summaryWithTools,\n summaryTokens,\n })\n }\n\n await finalizeSession(ctx, toolCtx, rawMessages, notifications, input.topic)\n\n return formatResult(plans.length, skippedIssues, skippedCount)\n },\n })\n}\n","import { SessionState, WithParts } from \"./state\"\nimport { AssistantMessage, UserMessage } from \"@opencode-ai/sdk/v2\"\nimport { Logger } from \"./logger\"\nimport * as _anthropicTokenizer from \"@anthropic-ai/tokenizer\"\nconst anthropicCountTokens = (_anthropicTokenizer.countTokens ??\n (_anthropicTokenizer as any).default?.countTokens) as typeof _anthropicTokenizer.countTokens\nimport { getLastUserMessage } from \"./messages/query\"\n\nexport function getCurrentTokenUsage(state: SessionState, messages: WithParts[]): number {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.info.role !== \"assistant\") {\n continue\n }\n\n const assistantInfo = msg.info as AssistantMessage\n if ((assistantInfo.tokens?.output || 0) <= 0) {\n continue\n }\n\n if (\n state.lastCompaction > 0 &&\n (msg.info.time.created < state.lastCompaction ||\n (msg.info.summary === true && msg.info.time.created === state.lastCompaction))\n ) {\n return 0\n }\n\n const input = assistantInfo.tokens?.input || 0\n const output = assistantInfo.tokens?.output || 0\n const reasoning = assistantInfo.tokens?.reasoning || 0\n const cacheRead = assistantInfo.tokens?.cache?.read || 0\n const cacheWrite = assistantInfo.tokens?.cache?.write || 0\n\n // [FIX Bug 17] Universal token estimation\n // opencode session.ts: adjustedInputTokens = inputTokens - cacheRead - cacheWrite\n // So: input + cacheRead + cacheWrite = prompt_tokens (total input)\n // Total context usage = prompt_tokens + output + reasoning\n return input + cacheRead + cacheWrite + output + reasoning\n }\n\n // [FIX Bug 5] fallback: estimate tokens from message content when no assistant\n // message has output tokens (first turn or after full compaction)\n let estimated = 0\n for (const m of messages) {\n const parts = Array.isArray(m.parts) ? m.parts : []\n for (const part of parts) {\n if (part.type === \"text\" && typeof part.text === \"string\") {\n estimated += countTokens(part.text)\n }\n }\n }\n return estimated\n}\n\nexport function getCurrentParams(\n state: SessionState,\n messages: WithParts[],\n logger: Logger,\n): {\n providerId: string | undefined\n modelId: string | undefined\n agent: string | undefined\n variant: string | undefined\n} {\n const userMsg = getLastUserMessage(messages)\n if (!userMsg) {\n logger.debug(\"No user message found when determining current params\")\n return {\n providerId: undefined,\n modelId: undefined,\n agent: undefined,\n variant: undefined,\n }\n }\n const userInfo = userMsg.info as UserMessage\n const agent: string = userInfo.agent\n const providerId: string | undefined = userInfo.model.providerID\n const modelId: string | undefined = userInfo.model.modelID\n const variant: string | undefined = userInfo.model.variant\n\n return { providerId, modelId, agent, variant }\n}\n\nexport function countTokens(text: string): number {\n if (!text) return 0\n try {\n return anthropicCountTokens(text)\n } catch {\n return Math.round(text.length / 4)\n }\n}\n\nexport function estimateTokensBatch(texts: string[]): number {\n if (texts.length === 0) return 0\n return countTokens(texts.join(\" \"))\n}\n\nexport const COMPACTED_TOOL_OUTPUT_PLACEHOLDER = \"[Old tool result content cleared]\"\n\nfunction stringifyToolContent(value: unknown): string {\n return typeof value === \"string\" ? value : JSON.stringify(value)\n}\n\nexport function extractCompletedToolOutput(part: any): string | undefined {\n if (\n part?.type !== \"tool\" ||\n part.state?.status !== \"completed\" ||\n part.state?.output === undefined\n ) {\n return undefined\n }\n\n if (part.state?.time?.compacted) {\n return COMPACTED_TOOL_OUTPUT_PLACEHOLDER\n }\n\n return stringifyToolContent(part.state.output)\n}\n\nexport function extractToolContent(part: any): string[] {\n const contents: string[] = []\n\n if (part?.type !== \"tool\") {\n return contents\n }\n\n if (part.state?.input !== undefined) {\n contents.push(stringifyToolContent(part.state.input))\n }\n\n const completedOutput = extractCompletedToolOutput(part)\n if (completedOutput !== undefined) {\n contents.push(completedOutput)\n } else if (part.state?.status === \"error\" && part.state?.error) {\n contents.push(stringifyToolContent(part.state.error))\n }\n\n return contents\n}\n\nexport function countToolTokens(part: any): number {\n const contents = extractToolContent(part)\n return estimateTokensBatch(contents)\n}\n\nexport function getTotalToolTokens(state: SessionState, toolIds: string[]): number {\n let total = 0\n for (const id of toolIds) {\n const entry = state.toolParameters.get(id)\n total += entry?.tokenCount ?? 0\n }\n return total\n}\n\nexport function countMessageTextTokens(msg: WithParts): number {\n const texts: string[] = []\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type === \"text\") {\n texts.push(part.text)\n }\n }\n if (texts.length === 0) return 0\n return estimateTokensBatch(texts)\n}\n\nexport function countAllMessageTokens(msg: WithParts): number {\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n const texts: string[] = []\n for (const part of parts) {\n if (part.type === \"text\") {\n texts.push(part.text)\n } else {\n texts.push(...extractToolContent(part))\n }\n }\n if (texts.length === 0) return 0\n return estimateTokensBatch(texts)\n}\n","import type { WithParts } from \"../state\"\n\nexport function isMessageWithInfo(message: unknown): message is WithParts {\n if (!message || typeof message !== \"object\") {\n return false\n }\n\n const info = (message as any).info\n const parts = (message as any).parts\n if (!info || typeof info !== \"object\") {\n return false\n }\n\n return (\n typeof info.id === \"string\" &&\n info.id.length > 0 &&\n typeof info.sessionID === \"string\" &&\n info.sessionID.length > 0 &&\n (info.role === \"user\" || info.role === \"assistant\") &&\n info.time &&\n typeof info.time === \"object\" &&\n typeof info.time.created === \"number\" &&\n Array.isArray(parts)\n )\n}\n\nexport function filterMessages(messages: unknown): WithParts[] {\n if (!Array.isArray(messages)) {\n return []\n }\n\n return messages.filter(isMessageWithInfo)\n}\n\nexport function filterMessagesInPlace(messages: unknown): WithParts[] {\n if (!Array.isArray(messages)) {\n return []\n }\n\n let writeIndex = 0\n\n for (const message of messages) {\n if (isMessageWithInfo(message)) {\n messages[writeIndex++] = message\n }\n }\n\n messages.length = writeIndex\n return messages as WithParts[]\n}\n","import type { PluginConfig } from \"../config\"\nimport type { WithParts } from \"../state\"\nimport { isMessageWithInfo } from \"./shape\"\n\nexport function isSyntheticMessage(message: WithParts): boolean {\n const id = message?.info?.id\n return typeof id === \"string\" && (id.startsWith(\"msg_dcp_summary_\") || id.startsWith(\"msg_dcp_text_\"))\n}\n\nexport const getLastUserMessage = (\n messages: WithParts[],\n startIndex?: number,\n): WithParts | null => {\n const start = startIndex ?? messages.length - 1\n for (let i = start; i >= 0; i--) {\n const msg = messages[i]\n if (!isMessageWithInfo(msg)) {\n continue\n }\n if (msg.info.role === \"user\" && !isIgnoredUserMessage(msg) && !isSyntheticMessage(msg)) {\n return msg\n }\n }\n return null\n}\n\nexport const messageHasCompress = (message: WithParts): boolean => {\n if (!isMessageWithInfo(message)) {\n return false\n }\n\n if (message.info.role !== \"assistant\") {\n return false\n }\n\n const parts = Array.isArray(message.parts) ? message.parts : []\n return parts.some(\n (part) =>\n part.type === \"tool\" && part.tool === \"compress\" && part.state?.status === \"completed\",\n )\n}\n\nexport const isIgnoredUserMessage = (message: WithParts): boolean => {\n if (!isMessageWithInfo(message)) {\n return false\n }\n\n if (message.info.role !== \"user\") {\n return false\n }\n\n const parts = Array.isArray(message.parts) ? message.parts : []\n if (parts.length === 0) {\n return true\n }\n\n for (const part of parts) {\n if (!(part as any).ignored) {\n return false\n }\n }\n\n return true\n}\n\nexport function isProtectedUserMessage(config: PluginConfig, message: WithParts): boolean {\n if (!isMessageWithInfo(message)) {\n return false\n }\n\n return (\n config.compress.mode === \"message\" &&\n config.compress.protectUserMessages &&\n message.info.role === \"user\" &&\n !isIgnoredUserMessage(message)\n )\n}\n","// These format schemas are kept separate from the editable compress prompts\n// so they cannot be modified via custom prompt overrides. The schemas must\n// match the tool's input validation and are not safe to change independently.\n\nexport const RANGE_FORMAT_EXTENSION = `\nTHE FORMAT OF COMPRESS\n\n\\`\\`\\`\n{\n topic: string, // Short label (3-5 words) - e.g., \"Auth System Exploration\"\n content: [ // One or more ranges to compress\n {\n startId: string, // Boundary ID at range start: mNNNNN or bN\n endId: string, // Boundary ID at range end: mNNNNN or bN\n summary: string // Complete technical summary replacing all content in range\n }\n ]\n}\n\\`\\`\\``\n\nexport const MESSAGE_FORMAT_EXTENSION = `\nTHE FORMAT OF COMPRESS\n\n\\`\\`\\`\n{\n topic: string, // Short label (3-5 words) for the overall batch\n content: [ // One or more messages to compress independently\n {\n messageId: string, // Raw message ID only: mNNNNN (ignore metadata attributes like priority)\n topic: string, // Short label (3-5 words) for this one message summary\n summary: string // Complete technical summary replacing that one message\n }\n ]\n}\n\\`\\`\\``\n","import type { SessionState, WithParts } from \"./state\"\nimport { isIgnoredUserMessage } from \"./messages/query\"\n\nconst MESSAGE_REF_REGEX = /^m(\\d{4,5})$/\nconst BLOCK_REF_REGEX = /^b([1-9]\\d*)$/\nconst MESSAGE_ID_TAG_NAME = \"dcp-message-id\"\n\nconst MESSAGE_REF_WIDTH = 5\nconst MESSAGE_REF_MIN_INDEX = 1\nexport const MESSAGE_REF_MAX_INDEX = 99999\n\nexport type ParsedBoundaryId =\n | {\n kind: \"message\"\n ref: string\n index: number\n }\n | {\n kind: \"compressed-block\"\n ref: string\n blockId: number\n }\n\nexport function formatMessageRef(index: number): string {\n if (\n !Number.isInteger(index) ||\n index < MESSAGE_REF_MIN_INDEX ||\n index > MESSAGE_REF_MAX_INDEX\n ) {\n throw new Error(\n `Message ID index out of bounds: ${index}. Supported range is ${MESSAGE_REF_MIN_INDEX}-${MESSAGE_REF_MAX_INDEX}.`,\n )\n }\n return `m${index.toString().padStart(MESSAGE_REF_WIDTH, \"0\")}`\n}\n\nexport function formatBlockRef(blockId: number): string {\n if (!Number.isInteger(blockId) || blockId < 1) {\n throw new Error(`Invalid block ID: ${blockId}`)\n }\n return `b${blockId}`\n}\n\nexport function parseMessageRef(ref: string): number | null {\n const normalized = ref.trim().toLowerCase()\n const match = normalized.match(MESSAGE_REF_REGEX)\n if (!match) {\n return null\n }\n const index = Number.parseInt(match[1], 10)\n if (!Number.isInteger(index)) {\n return null\n }\n if (index < MESSAGE_REF_MIN_INDEX || index > MESSAGE_REF_MAX_INDEX) {\n return null\n }\n return index\n}\n\nexport function parseBlockRef(ref: string): number | null {\n const normalized = ref.trim().toLowerCase()\n const match = normalized.match(BLOCK_REF_REGEX)\n if (!match) {\n return null\n }\n const id = Number.parseInt(match[1], 10)\n return Number.isInteger(id) ? id : null\n}\n\nexport function parseBoundaryId(id: string): ParsedBoundaryId | null {\n const normalized = id.trim().toLowerCase()\n const messageIndex = parseMessageRef(normalized)\n if (messageIndex !== null) {\n return {\n kind: \"message\",\n ref: formatMessageRef(messageIndex),\n index: messageIndex,\n }\n }\n\n const blockId = parseBlockRef(normalized)\n if (blockId !== null) {\n return {\n kind: \"compressed-block\",\n ref: formatBlockRef(blockId),\n blockId,\n }\n }\n\n return null\n}\n\nfunction escapeXmlAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n}\n\nexport function formatMessageIdTag(\n ref: string,\n attributes?: Record<string, string | undefined>,\n): string {\n const serializedAttributes = Object.entries(attributes || {})\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([name, value]) => {\n if (name.trim().length === 0 || typeof value !== \"string\" || value.length === 0) {\n return \"\"\n }\n\n return ` ${name}=\"${escapeXmlAttribute(value)}\"`\n })\n .join(\"\")\n\n return `\\n<${MESSAGE_ID_TAG_NAME}${serializedAttributes}>${ref}</${MESSAGE_ID_TAG_NAME}>`\n}\n\nexport function assignMessageRefs(state: SessionState, messages: WithParts[]): number {\n let assigned = 0\n let skippedSubAgentPrompt = false\n\n for (const message of messages) {\n if (isIgnoredUserMessage(message)) {\n continue\n }\n\n if (state.isSubAgent && !skippedSubAgentPrompt && message.info.role === \"user\") {\n skippedSubAgentPrompt = true\n continue\n }\n\n const rawMessageId = message.info.id\n if (typeof rawMessageId !== \"string\" || rawMessageId.length === 0) {\n continue\n }\n // [FIX Bug 29] Skip synthetic messages created by DCP\n if (rawMessageId.startsWith(\"msg_dcp_summary_\") || rawMessageId.startsWith(\"msg_dcp_text_\")) {\n continue\n }\n\n const existingRef = state.messageIds.byRawId.get(rawMessageId)\n if (existingRef) {\n if (state.messageIds.byRef.get(existingRef) !== rawMessageId) {\n state.messageIds.byRef.set(existingRef, rawMessageId)\n }\n continue\n }\n\n const ref = allocateNextMessageRef(state)\n state.messageIds.byRawId.set(rawMessageId, ref)\n state.messageIds.byRef.set(ref, rawMessageId)\n assigned++\n }\n\n return assigned\n}\n\nfunction allocateNextMessageRef(state: SessionState): string {\n let candidate = Number.isInteger(state.messageIds.nextRef)\n ? Math.max(MESSAGE_REF_MIN_INDEX, state.messageIds.nextRef)\n : MESSAGE_REF_MIN_INDEX\n\n while (candidate <= MESSAGE_REF_MAX_INDEX) {\n const ref = formatMessageRef(candidate)\n if (!state.messageIds.byRef.has(ref)) {\n state.messageIds.nextRef = candidate + 1\n return ref\n }\n candidate++\n }\n\n throw new Error(\n `Message ID alias capacity exceeded. Cannot allocate more than ${formatMessageRef(MESSAGE_REF_MAX_INDEX)} aliases in this session.`,\n )\n}\n","import type { SessionState, WithParts } from \"../state\"\nimport { formatBlockRef, parseBoundaryId } from \"../message-ids\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\nimport { filterMessages } from \"../messages/shape\"\nimport { countAllMessageTokens } from \"../token-utils\"\nimport type { BoundaryReference, SearchContext, SelectionResolution } from \"./types\"\n\nexport async function fetchSessionMessages(client: any, sessionId: string): Promise<WithParts[]> {\n const response = await client.session.messages({\n path: { id: sessionId },\n })\n\n return filterMessages(response?.data || response)\n}\n\nexport function buildSearchContext(state: SessionState, rawMessages: WithParts[]): SearchContext {\n const rawMessagesById = new Map<string, WithParts>()\n const rawIndexById = new Map<string, number>()\n for (const msg of rawMessages) {\n rawMessagesById.set(msg.info.id, msg)\n }\n for (let index = 0; index < rawMessages.length; index++) {\n const message = rawMessages[index]\n if (!message) {\n continue\n }\n rawIndexById.set(message.info.id, index)\n }\n\n const summaryByBlockId = new Map()\n for (const [blockId, block] of state.prune.messages.blocksById) {\n if (!block.active) {\n continue\n }\n summaryByBlockId.set(blockId, block)\n }\n\n return {\n rawMessages,\n rawMessagesById,\n rawIndexById,\n summaryByBlockId,\n }\n}\n\nexport function resolveBoundaryIds(\n context: SearchContext,\n state: SessionState,\n startId: string,\n endId: string,\n): { startReference: BoundaryReference; endReference: BoundaryReference } {\n const lookup = buildBoundaryLookup(context, state)\n const issues: string[] = []\n const parsedStartId = parseBoundaryId(startId)\n const parsedEndId = parseBoundaryId(endId)\n\n if (parsedStartId === null) {\n issues.push(\"startId is invalid. Use an injected message ID (mNNNNN) or block ID (bN).\")\n }\n\n if (parsedEndId === null) {\n issues.push(\"endId is invalid. Use an injected message ID (mNNNNN) or block ID (bN).\")\n }\n\n if (issues.length > 0) {\n throw new Error(\n issues.length === 1 ? issues[0] : issues.map((issue) => `- ${issue}`).join(\"\\n\"),\n )\n }\n\n if (!parsedStartId || !parsedEndId) {\n throw new Error(\"Invalid boundary ID(s)\")\n }\n\n let startReference = lookup.get(parsedStartId.ref)\n let endReference = lookup.get(parsedEndId.ref)\n\n if (!startReference) {\n issues.push(\n `startId ${parsedStartId.ref} is not available in the current conversation context. Choose an injected ID visible in context.`,\n )\n }\n\n if (!endReference) {\n issues.push(\n `endId ${parsedEndId.ref} is not available in the current conversation context. Choose an injected ID visible in context.`,\n )\n }\n\n if (issues.length > 0) {\n throw new Error(\n issues.length === 1 ? issues[0] : issues.map((issue) => `- ${issue}`).join(\"\\n\"),\n )\n }\n\n if (!startReference || !endReference) {\n throw new Error(\"Failed to resolve boundary IDs\")\n }\n\n // [FIX Bug 34] Auto-swap reversed boundaries instead of throwing.\n // Block IDs (bN) are assigned in creation order, which may not match\n // conversation order. Models naturally assume bN < bM means bN is earlier,\n // but anchor message ordering can differ. Auto-swap prevents compress failures\n // that cause models to give up without compressing.\n if (startReference.rawIndex > endReference.rawIndex) {\n [startReference, endReference] = [endReference, startReference]\n }\n\n return { startReference, endReference }\n}\n\nexport function resolveSelection(\n context: SearchContext,\n startReference: BoundaryReference,\n endReference: BoundaryReference,\n): SelectionResolution {\n const startRawIndex = startReference.rawIndex\n const endRawIndex = endReference.rawIndex\n const messageIds: string[] = []\n const messageSeen = new Set<string>()\n const toolIds: string[] = []\n const toolSeen = new Set<string>()\n const requiredBlockIds: number[] = []\n const requiredBlockSeen = new Set<number>()\n const messageTokenById = new Map<string, number>()\n\n for (let index = startRawIndex; index <= endRawIndex; index++) {\n const rawMessage = context.rawMessages[index]\n if (!rawMessage) {\n continue\n }\n if (isIgnoredUserMessage(rawMessage)) {\n continue\n }\n\n const messageId = rawMessage.info.id\n if (!messageSeen.has(messageId)) {\n messageSeen.add(messageId)\n messageIds.push(messageId)\n }\n\n if (!messageTokenById.has(messageId)) {\n messageTokenById.set(messageId, countAllMessageTokens(rawMessage))\n }\n\n const parts = Array.isArray(rawMessage.parts) ? rawMessage.parts : []\n for (const part of parts) {\n if (part.type !== \"tool\" || !part.callID) {\n continue\n }\n if (toolSeen.has(part.callID)) {\n continue\n }\n toolSeen.add(part.callID)\n toolIds.push(part.callID)\n }\n }\n\n const selectedMessageIds = new Set(messageIds)\n const summariesInSelection: Array<{ blockId: number; rawIndex: number }> = []\n for (const summary of context.summaryByBlockId.values()) {\n if (!selectedMessageIds.has(summary.anchorMessageId)) {\n continue\n }\n\n const anchorIndex = context.rawIndexById.get(summary.anchorMessageId)\n if (anchorIndex === undefined) {\n continue\n }\n\n summariesInSelection.push({\n blockId: summary.blockId,\n rawIndex: anchorIndex,\n })\n }\n\n summariesInSelection.sort((a, b) => a.rawIndex - b.rawIndex || a.blockId - b.blockId)\n for (const summary of summariesInSelection) {\n if (requiredBlockSeen.has(summary.blockId)) {\n continue\n }\n requiredBlockSeen.add(summary.blockId)\n requiredBlockIds.push(summary.blockId)\n }\n\n if (messageIds.length === 0) {\n throw new Error(\n \"Failed to map boundary matches back to raw messages. Choose boundaries that include original conversation messages.\",\n )\n }\n\n return {\n startReference,\n endReference,\n messageIds,\n messageTokenById,\n toolIds,\n requiredBlockIds,\n }\n}\n\nexport function resolveAnchorMessageId(startReference: BoundaryReference): string {\n if (startReference.kind === \"compressed-block\") {\n if (!startReference.anchorMessageId) {\n throw new Error(\"Failed to map boundary matches back to raw messages\")\n }\n return startReference.anchorMessageId\n }\n\n if (!startReference.messageId) {\n throw new Error(\"Failed to map boundary matches back to raw messages\")\n }\n return startReference.messageId\n}\n\nfunction buildBoundaryLookup(\n context: SearchContext,\n state: SessionState,\n): Map<string, BoundaryReference> {\n const lookup = new Map<string, BoundaryReference>()\n\n for (const [messageRef, messageId] of state.messageIds.byRef) {\n const rawMessage = context.rawMessagesById.get(messageId)\n if (!rawMessage) {\n continue\n }\n if (isIgnoredUserMessage(rawMessage)) {\n continue\n }\n\n const rawIndex = context.rawIndexById.get(messageId)\n if (rawIndex === undefined) {\n continue\n }\n lookup.set(messageRef, {\n kind: \"message\",\n rawIndex,\n messageId,\n })\n }\n\n const summaries = Array.from(context.summaryByBlockId.values()).sort(\n (a, b) => a.blockId - b.blockId,\n )\n for (const summary of summaries) {\n const anchorMessage = context.rawMessagesById.get(summary.anchorMessageId)\n if (!anchorMessage) {\n continue\n }\n if (isIgnoredUserMessage(anchorMessage)) {\n continue\n }\n\n const rawIndex = context.rawIndexById.get(summary.anchorMessageId)\n if (rawIndex === undefined) {\n continue\n }\n const blockRef = formatBlockRef(summary.blockId)\n if (!lookup.has(blockRef)) {\n lookup.set(blockRef, {\n kind: \"compressed-block\",\n rawIndex,\n blockId: summary.blockId,\n anchorMessageId: summary.anchorMessageId,\n })\n }\n }\n\n return lookup\n}\n","import type { CompressionBlock, PruneMessagesState, SessionState } from \"../state\"\nimport { formatBlockRef, formatMessageIdTag } from \"../message-ids\"\nimport type { AppliedCompressionResult, CompressionStateInput, SelectionResolution } from \"./types\"\nimport type { GCConfig } from \"../config\"\n\nconst DEFAULT_PROMOTION_THRESHOLD = 5\n\nexport const COMPRESSED_BLOCK_HEADER = \"[Compressed conversation section]\"\n\nexport function allocateBlockId(state: SessionState): number {\n const next = state.prune.messages.nextBlockId\n if (!Number.isInteger(next) || next < 1) {\n state.prune.messages.nextBlockId = 2\n return 1\n }\n\n state.prune.messages.nextBlockId = next + 1\n return next\n}\n\nexport function allocateRunId(state: SessionState): number {\n const next = state.prune.messages.nextRunId\n if (!Number.isInteger(next) || next < 1) {\n state.prune.messages.nextRunId = 2\n return 1\n }\n\n state.prune.messages.nextRunId = next + 1\n return next\n}\n\nexport function attachCompressionDuration(\n messagesState: PruneMessagesState,\n messageId: string,\n callId: string,\n durationMs: number,\n): number {\n if (typeof durationMs !== \"number\" || !Number.isFinite(durationMs)) {\n return 0\n }\n\n let updates = 0\n for (const block of messagesState.blocksById.values()) {\n if (block.compressMessageId !== messageId || block.compressCallId !== callId) {\n continue\n }\n\n block.durationMs = durationMs\n updates++\n }\n\n return updates\n}\n\nexport function wrapCompressedSummary(blockId: number, summary: string): string {\n const header = COMPRESSED_BLOCK_HEADER\n const footer = formatMessageIdTag(formatBlockRef(blockId))\n const body = summary.trim()\n if (body.length === 0) {\n return `${header}\\n${footer}`\n }\n return `${header}\\n${body}\\n\\n${footer}`\n}\n\nexport function applyCompressionState(\n state: SessionState,\n input: CompressionStateInput,\n selection: SelectionResolution,\n anchorMessageId: string,\n blockId: number,\n summary: string,\n consumedBlockIds: number[],\n gcConfig?: GCConfig,\n): AppliedCompressionResult {\n const messagesState = state.prune.messages\n const consumed = [...new Set(consumedBlockIds.filter((id) => Number.isInteger(id) && id > 0))]\n const included = [...consumed]\n\n const effectiveMessageIds = new Set<string>(selection.messageIds)\n const effectiveToolIds = new Set<string>(selection.toolIds)\n\n for (const consumedBlockId of consumed) {\n const consumedBlock = messagesState.blocksById.get(consumedBlockId)\n if (!consumedBlock) {\n continue\n }\n for (const messageId of consumedBlock.effectiveMessageIds) {\n effectiveMessageIds.add(messageId)\n }\n for (const toolId of consumedBlock.effectiveToolIds) {\n effectiveToolIds.add(toolId)\n }\n }\n\n const initiallyActiveMessages = new Set<string>()\n for (const messageId of effectiveMessageIds) {\n const entry = messagesState.byMessageId.get(messageId)\n if (entry && entry.activeBlockIds.length > 0) {\n initiallyActiveMessages.add(messageId)\n }\n }\n\n const initiallyActiveToolIds = new Set<string>()\n for (const activeBlockId of messagesState.activeBlockIds) {\n const activeBlock = messagesState.blocksById.get(activeBlockId)\n if (!activeBlock || !activeBlock.active) {\n continue\n }\n\n for (const toolId of activeBlock.effectiveToolIds) {\n initiallyActiveToolIds.add(toolId)\n }\n }\n\n const createdAt = Date.now()\n const block: CompressionBlock = {\n blockId,\n runId: input.runId,\n active: true,\n deactivatedByUser: false,\n compressedTokens: 0,\n summaryTokens: input.summaryTokens,\n durationMs: 0,\n mode: input.mode,\n topic: input.topic,\n batchTopic: input.batchTopic,\n startId: input.startId,\n endId: input.endId,\n anchorMessageId,\n compressMessageId: input.compressMessageId,\n compressCallId: input.compressCallId,\n includedBlockIds: included,\n consumedBlockIds: consumed,\n parentBlockIds: [],\n directMessageIds: [],\n directToolIds: [],\n effectiveMessageIds: [...effectiveMessageIds],\n effectiveToolIds: [...effectiveToolIds],\n createdAt,\n summary,\n survivedCount: 0,\n generation: \"young\",\n }\n\n const promotionThreshold = gcConfig?.promotionThreshold ?? DEFAULT_PROMOTION_THRESHOLD\n for (const [activeId, activeBlock] of messagesState.blocksById) {\n if (!activeBlock.active) continue\n if (consumed.includes(activeId)) continue\n activeBlock.survivedCount = (activeBlock.survivedCount || 0) + 1\n if (activeBlock.survivedCount >= promotionThreshold) {\n activeBlock.generation = \"old\"\n }\n }\n\n messagesState.blocksById.set(blockId, block)\n messagesState.activeBlockIds.add(blockId)\n messagesState.activeByAnchorMessageId.set(anchorMessageId, blockId)\n\n const deactivatedAt = Date.now()\n for (const consumedBlockId of consumed) {\n const consumedBlock = messagesState.blocksById.get(consumedBlockId)\n if (!consumedBlock || !consumedBlock.active) {\n continue\n }\n\n consumedBlock.active = false\n consumedBlock.deactivatedAt = deactivatedAt\n consumedBlock.deactivatedByBlockId = blockId\n if (!consumedBlock.parentBlockIds.includes(blockId)) {\n consumedBlock.parentBlockIds.push(blockId)\n }\n\n messagesState.activeBlockIds.delete(consumedBlockId)\n const mappedBlockId = messagesState.activeByAnchorMessageId.get(\n consumedBlock.anchorMessageId,\n )\n if (mappedBlockId === consumedBlockId) {\n messagesState.activeByAnchorMessageId.delete(consumedBlock.anchorMessageId)\n }\n }\n\n const removeActiveBlockId = (\n entry: { activeBlockIds: number[] },\n blockIdToRemove: number,\n ): void => {\n if (entry.activeBlockIds.length === 0) {\n return\n }\n entry.activeBlockIds = entry.activeBlockIds.filter((id) => id !== blockIdToRemove)\n }\n\n for (const consumedBlockId of consumed) {\n const consumedBlock = messagesState.blocksById.get(consumedBlockId)\n if (!consumedBlock) {\n continue\n }\n for (const messageId of consumedBlock.effectiveMessageIds) {\n const entry = messagesState.byMessageId.get(messageId)\n if (!entry) {\n continue\n }\n removeActiveBlockId(entry, consumedBlockId)\n }\n }\n\n for (const messageId of selection.messageIds) {\n const tokenCount = selection.messageTokenById.get(messageId) || 0\n const existing = messagesState.byMessageId.get(messageId)\n\n if (!existing) {\n messagesState.byMessageId.set(messageId, {\n tokenCount,\n allBlockIds: [blockId],\n activeBlockIds: [blockId],\n })\n continue\n }\n\n existing.tokenCount = Math.max(existing.tokenCount, tokenCount)\n if (!existing.allBlockIds.includes(blockId)) {\n existing.allBlockIds.push(blockId)\n }\n if (!existing.activeBlockIds.includes(blockId)) {\n existing.activeBlockIds.push(blockId)\n }\n }\n\n for (const messageId of block.effectiveMessageIds) {\n if (selection.messageTokenById.has(messageId)) {\n continue\n }\n\n const existing = messagesState.byMessageId.get(messageId)\n if (!existing) {\n continue\n }\n if (!existing.allBlockIds.includes(blockId)) {\n existing.allBlockIds.push(blockId)\n }\n if (!existing.activeBlockIds.includes(blockId)) {\n existing.activeBlockIds.push(blockId)\n }\n }\n\n let compressedTokens = 0\n const newlyCompressedMessageIds: string[] = []\n for (const messageId of effectiveMessageIds) {\n const entry = messagesState.byMessageId.get(messageId)\n if (!entry) {\n continue\n }\n\n const isNowActive = entry.activeBlockIds.length > 0\n const wasActive = initiallyActiveMessages.has(messageId)\n\n if (isNowActive && !wasActive) {\n compressedTokens += entry.tokenCount\n newlyCompressedMessageIds.push(messageId)\n }\n }\n\n const newlyCompressedToolIds: string[] = []\n for (const toolId of effectiveToolIds) {\n if (!initiallyActiveToolIds.has(toolId)) {\n newlyCompressedToolIds.push(toolId)\n }\n }\n\n block.directMessageIds = [...newlyCompressedMessageIds]\n block.directToolIds = [...newlyCompressedToolIds]\n\n block.compressedTokens = compressedTokens\n\n state.stats.pruneTokenCounter += compressedTokens\n state.stats.totalPruneTokens += state.stats.pruneTokenCounter\n state.stats.pruneTokenCounter = 0\n\n return {\n compressedTokens,\n messageIds: selection.messageIds,\n newlyCompressedMessageIds,\n newlyCompressedToolIds,\n }\n}\n","import type { PluginConfig } from \"../config\"\nimport type { SessionState } from \"../state\"\nimport { parseBoundaryId } from \"../message-ids\"\nimport { isIgnoredUserMessage, isProtectedUserMessage } from \"../messages/query\"\nimport { resolveAnchorMessageId, resolveBoundaryIds, resolveSelection } from \"./search\"\nimport { COMPRESSED_BLOCK_HEADER } from \"./state\"\nimport type {\n CompressMessageEntry,\n CompressMessageToolArgs,\n ResolvedMessageCompression,\n ResolvedMessageCompressionsResult,\n SearchContext,\n} from \"./types\"\n\ninterface SkippedIssue {\n kind: string\n messageId: string\n}\n\nclass SoftIssue extends Error {\n constructor(\n public readonly kind: string,\n public readonly messageId: string,\n message: string,\n ) {\n super(message)\n }\n}\n\nexport function validateArgs(args: CompressMessageToolArgs): void {\n if (typeof args.topic !== \"string\" || args.topic.trim().length === 0) {\n throw new Error(\"topic is required and must be a non-empty string\")\n }\n\n if (!Array.isArray(args.content) || args.content.length === 0) {\n throw new Error(\"content is required and must be a non-empty array\")\n }\n\n for (let index = 0; index < args.content.length; index++) {\n const entry = args.content[index]\n const prefix = `content[${index}]`\n\n if (typeof entry?.messageId !== \"string\" || entry.messageId.trim().length === 0) {\n throw new Error(`${prefix}.messageId is required and must be a non-empty string`)\n }\n\n if (typeof entry?.topic !== \"string\" || entry.topic.trim().length === 0) {\n throw new Error(`${prefix}.topic is required and must be a non-empty string`)\n }\n\n if (typeof entry?.summary !== \"string\" || entry.summary.trim().length === 0) {\n throw new Error(`${prefix}.summary is required and must be a non-empty string`)\n }\n }\n}\n\nexport function formatResult(\n processedCount: number,\n skippedIssues: string[],\n skippedCount: number,\n): string {\n const messageNoun = processedCount === 1 ? \"message\" : \"messages\"\n const processedText =\n processedCount > 0\n ? `Compressed ${processedCount} ${messageNoun} into ${COMPRESSED_BLOCK_HEADER}.`\n : \"Compressed 0 messages.\"\n // [FIX Bug 30] Prevent model from treating compress result as conversation end\n const instruction = \"\\nIMPORTANT: This was an automatic context compression. You MUST continue your previous task exactly where you left off. Do NOT ask the user what to do next.\"\n\n if (skippedCount === 0) {\n return processedText + instruction\n }\n\n const issueNoun = skippedCount === 1 ? \"issue\" : \"issues\"\n const issueLines = skippedIssues.map((issue) => `- ${issue}`).join(\"\\n\")\n return `${processedText}\\nSkipped ${skippedCount} ${issueNoun}:\\n${issueLines}${instruction}`\n}\n\nexport function formatIssues(skippedIssues: string[], skippedCount: number): string {\n const issueNoun = skippedCount === 1 ? \"issue\" : \"issues\"\n const issueLines = skippedIssues.map((issue) => `- ${issue}`).join(\"\\n\")\n return `Unable to compress any messages. Found ${skippedCount} ${issueNoun}:\\n${issueLines}`\n}\n\nconst ISSUE_TEMPLATES: Record<string, [singular: string, plural: string]> = {\n blocked: [\n \"refers to a protected message and cannot be compressed.\",\n \"refer to protected messages and cannot be compressed.\",\n ],\n \"invalid-format\": [\n \"is invalid. Use an injected raw message ID of the form mNNNNN.\",\n \"are invalid. Use injected raw message IDs of the form mNNNNN.\",\n ],\n \"block-id\": [\n \"is invalid here. Block IDs like bN are not allowed; use an mNNNNN message ID instead.\",\n \"are invalid here. Block IDs like bN are not allowed; use mNNNNN message IDs instead.\",\n ],\n \"not-in-context\": [\n \"is not available in the current conversation context. Choose an injected mNNNNN ID visible in context.\",\n \"are not available in the current conversation context. Choose injected mNNNNN IDs visible in context.\",\n ],\n protected: [\n \"refers to a protected message and cannot be compressed.\",\n \"refer to protected messages and cannot be compressed.\",\n ],\n \"already-compressed\": [\n \"is already part of an active compression.\",\n \"are already part of active compressions.\",\n ],\n duplicate: [\n \"was selected more than once in this batch.\",\n \"were each selected more than once in this batch.\",\n ],\n}\n\nfunction formatSkippedGroup(kind: string, messageIds: string[]): string {\n const templates = ISSUE_TEMPLATES[kind]\n const ids = messageIds.join(\", \")\n const single = messageIds.length === 1\n const prefix = single ? \"messageId\" : \"messageIds\"\n\n if (!templates) {\n return `${prefix} ${ids}: unknown issue.`\n }\n\n return `${prefix} ${ids} ${single ? templates[0] : templates[1]}`\n}\n\nfunction groupSkippedIssues(issues: SkippedIssue[]): string[] {\n const groups = new Map<string, string[]>()\n const order: string[] = []\n\n for (const issue of issues) {\n let ids = groups.get(issue.kind)\n if (!ids) {\n ids = []\n groups.set(issue.kind, ids)\n order.push(issue.kind)\n }\n ids.push(issue.messageId)\n }\n\n return order.map((kind) => {\n const ids = groups.get(kind)!\n return formatSkippedGroup(kind, ids)\n })\n}\n\nexport function resolveMessages(\n args: CompressMessageToolArgs,\n searchContext: SearchContext,\n state: SessionState,\n config: PluginConfig,\n): ResolvedMessageCompressionsResult {\n const issues: SkippedIssue[] = []\n const plans: ResolvedMessageCompression[] = []\n const seenMessageIds = new Set<string>()\n\n for (const entry of args.content) {\n const normalizedMessageId = entry.messageId.trim()\n if (seenMessageIds.has(normalizedMessageId)) {\n issues.push({ kind: \"duplicate\", messageId: normalizedMessageId })\n continue\n }\n\n try {\n const plan = resolveMessage(\n {\n ...entry,\n messageId: normalizedMessageId,\n },\n searchContext,\n state,\n config,\n )\n seenMessageIds.add(plan.entry.messageId)\n plans.push(plan)\n } catch (error: any) {\n if (error instanceof SoftIssue) {\n issues.push({ kind: error.kind, messageId: error.messageId })\n continue\n }\n\n throw error\n }\n }\n\n return {\n plans,\n skippedIssues: groupSkippedIssues(issues),\n skippedCount: issues.length,\n }\n}\n\nfunction resolveMessage(\n entry: CompressMessageEntry,\n searchContext: SearchContext,\n state: SessionState,\n config: PluginConfig,\n): ResolvedMessageCompression {\n if (entry.messageId.toUpperCase() === \"BLOCKED\") {\n throw new SoftIssue(\"blocked\", \"BLOCKED\", \"protected message\")\n }\n\n const parsed = parseBoundaryId(entry.messageId)\n\n if (!parsed) {\n throw new SoftIssue(\"invalid-format\", entry.messageId, \"invalid format\")\n }\n\n if (parsed.kind === \"compressed-block\") {\n throw new SoftIssue(\"block-id\", entry.messageId, \"block ID used\")\n }\n\n const messageId = state.messageIds.byRef.get(parsed.ref)\n const rawMessage = messageId ? searchContext.rawMessagesById.get(messageId) : undefined\n if (\n !messageId ||\n !rawMessage ||\n !searchContext.rawIndexById.has(messageId) ||\n isIgnoredUserMessage(rawMessage)\n ) {\n throw new SoftIssue(\"not-in-context\", parsed.ref, \"not in context\")\n }\n\n const { startReference, endReference } = resolveBoundaryIds(\n searchContext,\n state,\n parsed.ref,\n parsed.ref,\n )\n const selection = resolveSelection(searchContext, startReference, endReference)\n\n if (isProtectedUserMessage(config, rawMessage)) {\n throw new SoftIssue(\"protected\", parsed.ref, \"protected message\")\n }\n\n const pruneEntry = state.prune.messages.byMessageId.get(messageId)\n if (pruneEntry && pruneEntry.activeBlockIds.length > 0) {\n throw new SoftIssue(\"already-compressed\", parsed.ref, \"already compressed\")\n }\n\n return {\n entry: {\n messageId: parsed.ref,\n topic: entry.topic,\n summary: entry.summary,\n },\n selection,\n anchorMessageId: resolveAnchorMessageId(startReference),\n }\n}\n","/**\n * State persistence module for ACP plugin.\n * Persists pruned tool IDs across sessions so they survive OpenCode restarts.\n * Storage location: ~/.local/share/opencode/storage/plugin/acp/{sessionId}.json\n */\n\nimport * as fs from \"fs/promises\"\nimport { existsSync } from \"fs\"\nimport { homedir } from \"os\"\nimport { join } from \"path\"\nimport { cpSync, existsSync as existsSyncSync } from \"fs\"\nimport type { CompressionBlock, PrunedMessageEntry, SessionState, SessionStats } from \"./types\"\nimport type { Logger } from \"../logger\"\nimport { serializePruneMessagesState } from \"./utils\"\n\nconst LEGACY_STORAGE_DIR = join(\n process.env.XDG_DATA_HOME || join(homedir(), \".local\", \"share\"),\n \"opencode\",\n \"storage\",\n \"plugin\",\n \"dcp\",\n)\n\n/** Prune state as stored on disk */\nexport interface PersistedPruneMessagesState {\n byMessageId: Record<string, PrunedMessageEntry>\n blocksById: Record<string, CompressionBlock>\n activeBlockIds: number[]\n activeByAnchorMessageId: Record<string, number>\n nextBlockId: number\n nextRunId: number\n markedForCleanup?: number[]\n}\n\nexport interface PersistedPrune {\n tools?: Record<string, number>\n messages?: PersistedPruneMessagesState\n}\n\nexport interface PersistedNudges {\n contextLimitAnchors: string[]\n turnNudgeAnchors?: string[]\n iterationNudgeAnchors?: string[]\n}\n\nexport interface PersistedMessageIds {\n byRawId: Record<string, string>\n byRef: Record<string, string>\n nextRef: number\n}\n\nexport interface PersistedSessionState {\n sessionName?: string\n prune: PersistedPrune\n nudges: PersistedNudges\n stats: SessionStats\n lastUpdated: string\n messageIds?: PersistedMessageIds\n lastCompaction?: number\n}\n\nconst STORAGE_DIR = join(\n process.env.XDG_DATA_HOME || join(homedir(), \".local\", \"share\"),\n \"opencode\",\n \"storage\",\n \"plugin\",\n \"acp\",\n)\n\n/** One-time migration: copy plugin/dcp/ → plugin/acp/ if ACP dir doesn't exist yet */\nfunction migrateFromLegacyIfNeeded(logger: Logger): void {\n if (existsSyncSync(STORAGE_DIR)) return\n if (!existsSyncSync(LEGACY_STORAGE_DIR)) return\n try {\n cpSync(LEGACY_STORAGE_DIR, STORAGE_DIR, { recursive: true })\n logger.info(`[ACP] Migrated storage from ${LEGACY_STORAGE_DIR} → ${STORAGE_DIR}`)\n } catch (e: any) {\n logger.warn(`[ACP] Storage migration failed: ${e.message}`)\n }\n}\n\nasync function ensureStorageDir(logger: Logger): Promise<void> {\n if (!existsSync(STORAGE_DIR)) {\n migrateFromLegacyIfNeeded(logger)\n await fs.mkdir(STORAGE_DIR, { recursive: true })\n }\n}\n\nfunction getSessionFilePath(sessionId: string): string {\n return join(STORAGE_DIR, `${sessionId}.json`)\n}\n\nasync function writePersistedSessionState(\n sessionId: string,\n state: PersistedSessionState,\n logger: Logger,\n): Promise<void> {\n await ensureStorageDir(logger)\n\n const filePath = getSessionFilePath(sessionId)\n const content = JSON.stringify(state, null, 2)\n await fs.writeFile(filePath, content, \"utf-8\")\n\n logger.info(\"Saved session state to disk\", {\n sessionId,\n totalTokensSaved: state.stats.totalPruneTokens,\n })\n}\n\n// [FIX Bug 6] Removed try/catch — errors now propagate to callers so they know save failed\nexport async function saveSessionState(\n sessionState: SessionState,\n logger: Logger,\n sessionName?: string,\n): Promise<void> {\n if (!sessionState.sessionId) {\n return\n }\n\n const state: PersistedSessionState = {\n sessionName: sessionName,\n prune: {\n tools: Object.fromEntries(sessionState.prune.tools),\n messages: serializePruneMessagesState(sessionState.prune.messages),\n },\n nudges: {\n contextLimitAnchors: Array.from(sessionState.nudges.contextLimitAnchors),\n turnNudgeAnchors: Array.from(sessionState.nudges.turnNudgeAnchors),\n iterationNudgeAnchors: Array.from(sessionState.nudges.iterationNudgeAnchors),\n },\n stats: sessionState.stats,\n lastUpdated: new Date().toISOString(),\n messageIds: {\n byRawId: Object.fromEntries(sessionState.messageIds.byRawId),\n byRef: Object.fromEntries(sessionState.messageIds.byRef),\n nextRef: sessionState.messageIds.nextRef,\n },\n lastCompaction: sessionState.lastCompaction,\n }\n\n await writePersistedSessionState(sessionState.sessionId, state, logger)\n}\n\nexport async function loadSessionState(\n sessionId: string,\n logger: Logger,\n): Promise<PersistedSessionState | null> {\n try {\n const filePath = getSessionFilePath(sessionId)\n\n if (!existsSync(filePath)) {\n return null\n }\n\n const content = await fs.readFile(filePath, \"utf-8\")\n const state = JSON.parse(content) as PersistedSessionState\n\n const hasPruneTools = state?.prune?.tools && typeof state.prune.tools === \"object\"\n const hasPruneMessages = state?.prune?.messages && typeof state.prune.messages === \"object\"\n const hasNudgeFormat = state?.nudges && typeof state.nudges === \"object\"\n if (\n !state ||\n !state.prune ||\n !hasPruneTools ||\n !hasPruneMessages ||\n !state.stats ||\n !hasNudgeFormat\n ) {\n logger.warn(\"Invalid session state file, ignoring\", {\n sessionId: sessionId,\n })\n return null\n }\n\n const rawContextLimitAnchors = Array.isArray(state.nudges.contextLimitAnchors)\n ? state.nudges.contextLimitAnchors\n : []\n const validAnchors = rawContextLimitAnchors.filter(\n (entry): entry is string => typeof entry === \"string\",\n )\n const dedupedAnchors = [...new Set(validAnchors)]\n if (validAnchors.length !== rawContextLimitAnchors.length) {\n logger.warn(\"Filtered out malformed contextLimitAnchors entries\", {\n sessionId: sessionId,\n original: rawContextLimitAnchors.length,\n valid: validAnchors.length,\n })\n }\n state.nudges.contextLimitAnchors = dedupedAnchors\n\n const rawTurnNudgeAnchors = Array.isArray(state.nudges.turnNudgeAnchors)\n ? state.nudges.turnNudgeAnchors\n : []\n const validSoftAnchors = rawTurnNudgeAnchors.filter(\n (entry): entry is string => typeof entry === \"string\",\n )\n const dedupedSoftAnchors = [...new Set(validSoftAnchors)]\n if (validSoftAnchors.length !== rawTurnNudgeAnchors.length) {\n logger.warn(\"Filtered out malformed turnNudgeAnchors entries\", {\n sessionId: sessionId,\n original: rawTurnNudgeAnchors.length,\n valid: validSoftAnchors.length,\n })\n }\n state.nudges.turnNudgeAnchors = dedupedSoftAnchors\n\n const rawIterationNudgeAnchors = Array.isArray(state.nudges.iterationNudgeAnchors)\n ? state.nudges.iterationNudgeAnchors\n : []\n const validIterationAnchors = rawIterationNudgeAnchors.filter(\n (entry): entry is string => typeof entry === \"string\",\n )\n const dedupedIterationAnchors = [...new Set(validIterationAnchors)]\n if (validIterationAnchors.length !== rawIterationNudgeAnchors.length) {\n logger.warn(\"Filtered out malformed iterationNudgeAnchors entries\", {\n sessionId: sessionId,\n original: rawIterationNudgeAnchors.length,\n valid: validIterationAnchors.length,\n })\n }\n state.nudges.iterationNudgeAnchors = dedupedIterationAnchors\n\n const persistedMessageIds = (state as any).messageIds as PersistedMessageIds | undefined\n if (persistedMessageIds) {\n ;(state as any)._persistedMessageIds = persistedMessageIds\n }\n const persistedLastCompaction = (state as any).lastCompaction as number | undefined\n if (persistedLastCompaction !== undefined) {\n ;(state as any)._persistedLastCompaction = persistedLastCompaction\n }\n\n logger.info(\"Loaded session state from disk\", {\n sessionId: sessionId,\n })\n\n return state\n } catch (error: any) {\n logger.warn(\"Failed to load session state\", {\n sessionId: sessionId,\n error: error?.message,\n })\n return null\n }\n}\n\nexport interface AggregatedStats {\n totalTokens: number\n totalTools: number\n totalMessages: number\n sessionCount: number\n}\n\nexport async function loadAllSessionStats(logger: Logger): Promise<AggregatedStats> {\n const result: AggregatedStats = {\n totalTokens: 0,\n totalTools: 0,\n totalMessages: 0,\n sessionCount: 0,\n }\n\n try {\n if (!existsSync(STORAGE_DIR)) {\n return result\n }\n\n const files = await fs.readdir(STORAGE_DIR)\n const jsonFiles = files.filter((f) => f.endsWith(\".json\"))\n\n for (const file of jsonFiles) {\n try {\n const filePath = join(STORAGE_DIR, file)\n const content = await fs.readFile(filePath, \"utf-8\")\n const state = JSON.parse(content) as PersistedSessionState\n\n if (state?.stats?.totalPruneTokens && state?.prune) {\n result.totalTokens += state.stats.totalPruneTokens\n result.totalTools += state.prune.tools\n ? Object.keys(state.prune.tools).length\n : 0\n result.totalMessages += state.prune.messages?.byMessageId\n ? Object.keys(state.prune.messages.byMessageId).length\n : 0\n result.sessionCount++\n }\n } catch {\n // Skip invalid files\n }\n }\n\n logger.debug(\"Loaded all-time stats\", result)\n } catch (error: any) {\n logger.warn(\"Failed to load all-time stats\", { error: error?.message })\n }\n\n return result\n}\n","import type {\n CompressionBlock,\n PruneMessagesState,\n PrunedMessageEntry,\n SessionState,\n WithParts,\n} from \"./types\"\nimport { isIgnoredUserMessage, messageHasCompress } from \"../messages/query\"\nimport { isMessageWithInfo } from \"../messages/shape\"\nimport { countTokens } from \"../token-utils\"\n\n// [FIX Bug 3] Added summary check to match getCurrentTokenUsage exclusion logic\nexport const isMessageCompacted = (state: SessionState, msg: WithParts): boolean => {\n if (!isMessageWithInfo(msg)) {\n return false\n }\n\n if (state.lastCompaction <= 0) return false\n if (msg.info.time.created < state.lastCompaction) {\n return true\n }\n if (msg.info.summary === true && msg.info.time.created === state.lastCompaction) {\n return true\n }\n const pruneEntry = state.prune.messages.byMessageId.get(msg.info.id)\n if (pruneEntry && pruneEntry.activeBlockIds.length > 0) {\n return true\n }\n return false\n}\n\ninterface PersistedPruneMessagesState {\n byMessageId: Record<string, PrunedMessageEntry>\n blocksById: Record<string, CompressionBlock>\n activeBlockIds: number[]\n activeByAnchorMessageId: Record<string, number>\n nextBlockId: number\n nextRunId: number\n markedForCleanup?: number[]\n}\n\nexport function serializePruneMessagesState(\n messagesState: PruneMessagesState,\n): PersistedPruneMessagesState {\n return {\n byMessageId: Object.fromEntries(messagesState.byMessageId),\n blocksById: Object.fromEntries(\n Array.from(messagesState.blocksById.entries()).map(([blockId, block]) => [\n String(blockId),\n block,\n ]),\n ),\n activeBlockIds: Array.from(messagesState.activeBlockIds),\n activeByAnchorMessageId: Object.fromEntries(messagesState.activeByAnchorMessageId),\n nextBlockId: messagesState.nextBlockId,\n nextRunId: messagesState.nextRunId,\n markedForCleanup: Array.from(messagesState.markedForCleanup),\n }\n}\n\nexport async function isSubAgentSession(client: any, sessionID: string): Promise<boolean> {\n try {\n const result = await client.session.get({ path: { id: sessionID } })\n return !!result.data?.parentID\n } catch (error: any) {\n return false\n }\n}\n\nexport function findLastCompactionTimestamp(messages: WithParts[]): number {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (!isMessageWithInfo(msg)) {\n continue\n }\n if (msg.info.role === \"assistant\" && msg.info.summary === true) {\n return msg.info.time.created\n }\n }\n return 0\n}\n\nexport function countTurns(state: SessionState, messages: WithParts[]): number {\n let turnCount = 0\n for (const msg of messages) {\n if (!isMessageWithInfo(msg)) {\n continue\n }\n if (isMessageCompacted(state, msg)) {\n continue\n }\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type === \"step-start\") {\n turnCount++\n }\n }\n }\n return turnCount\n}\n\nexport function loadPruneMap(obj?: Record<string, number>): Map<string, number> {\n if (!obj || typeof obj !== \"object\") {\n return new Map()\n }\n\n const entries = Object.entries(obj).filter(\n (entry): entry is [string, number] =>\n typeof entry[0] === \"string\" && typeof entry[1] === \"number\",\n )\n return new Map(entries)\n}\n\nexport function createPruneMessagesState(): PruneMessagesState {\n return {\n byMessageId: new Map<string, PrunedMessageEntry>(),\n blocksById: new Map<number, CompressionBlock>(),\n activeBlockIds: new Set<number>(),\n activeByAnchorMessageId: new Map<string, number>(),\n nextBlockId: 1,\n nextRunId: 1,\n markedForCleanup: new Set<number>(),\n }\n}\n\nexport function loadPruneMessagesState(\n persisted?: PersistedPruneMessagesState,\n): PruneMessagesState {\n const state = createPruneMessagesState()\n if (!persisted || typeof persisted !== \"object\") {\n return state\n }\n\n if (typeof persisted.nextBlockId === \"number\" && Number.isInteger(persisted.nextBlockId)) {\n state.nextBlockId = Math.max(1, persisted.nextBlockId)\n }\n if (typeof persisted.nextRunId === \"number\" && Number.isInteger(persisted.nextRunId)) {\n state.nextRunId = Math.max(1, persisted.nextRunId)\n }\n\n if (persisted.byMessageId && typeof persisted.byMessageId === \"object\") {\n for (const [messageId, entry] of Object.entries(persisted.byMessageId)) {\n if (!entry || typeof entry !== \"object\") {\n continue\n }\n\n const tokenCount = typeof entry.tokenCount === \"number\" ? entry.tokenCount : 0\n const allBlockIds = Array.isArray(entry.allBlockIds)\n ? [\n ...new Set(\n entry.allBlockIds.filter(\n (id): id is number => Number.isInteger(id) && id > 0,\n ),\n ),\n ]\n : []\n const activeBlockIds = Array.isArray(entry.activeBlockIds)\n ? [\n ...new Set(\n entry.activeBlockIds.filter(\n (id): id is number => Number.isInteger(id) && id > 0,\n ),\n ),\n ]\n : []\n\n state.byMessageId.set(messageId, {\n tokenCount,\n allBlockIds,\n activeBlockIds,\n })\n }\n }\n\n if (persisted.blocksById && typeof persisted.blocksById === \"object\") {\n for (const [blockIdStr, block] of Object.entries(persisted.blocksById)) {\n const blockId = Number.parseInt(blockIdStr, 10)\n if (!Number.isInteger(blockId) || blockId < 1 || !block || typeof block !== \"object\") {\n continue\n }\n\n const toNumberArray = (value: unknown): number[] =>\n Array.isArray(value)\n ? [\n ...new Set(\n value.filter(\n (item): item is number => Number.isInteger(item) && item > 0,\n ),\n ),\n ]\n : []\n const toStringArray = (value: unknown): string[] =>\n Array.isArray(value)\n ? [...new Set(value.filter((item): item is string => typeof item === \"string\"))]\n : []\n\n state.blocksById.set(blockId, {\n blockId,\n runId:\n typeof block.runId === \"number\" &&\n Number.isInteger(block.runId) &&\n block.runId > 0\n ? block.runId\n : blockId,\n active: block.active === true,\n deactivatedByUser: block.deactivatedByUser === true,\n compressedTokens:\n typeof block.compressedTokens === \"number\" &&\n Number.isFinite(block.compressedTokens)\n ? Math.max(0, block.compressedTokens)\n : 0,\n summaryTokens:\n typeof block.summaryTokens === \"number\" && Number.isFinite(block.summaryTokens)\n ? Math.max(0, block.summaryTokens)\n : typeof block.summary === \"string\"\n ? countTokens(block.summary)\n : 0,\n durationMs:\n typeof block.durationMs === \"number\" && Number.isFinite(block.durationMs)\n ? Math.max(0, block.durationMs)\n : 0,\n mode: block.mode === \"range\" || block.mode === \"message\" ? block.mode : undefined,\n topic: typeof block.topic === \"string\" ? block.topic : \"\",\n batchTopic:\n typeof block.batchTopic === \"string\"\n ? block.batchTopic\n : typeof block.topic === \"string\"\n ? block.topic\n : \"\",\n startId: typeof block.startId === \"string\" ? block.startId : \"\",\n endId: typeof block.endId === \"string\" ? block.endId : \"\",\n anchorMessageId:\n typeof block.anchorMessageId === \"string\" ? block.anchorMessageId : \"\",\n compressMessageId:\n typeof block.compressMessageId === \"string\" ? block.compressMessageId : \"\",\n compressCallId:\n typeof block.compressCallId === \"string\" ? block.compressCallId : undefined,\n includedBlockIds: toNumberArray(block.includedBlockIds),\n consumedBlockIds: toNumberArray(block.consumedBlockIds),\n parentBlockIds: toNumberArray(block.parentBlockIds),\n directMessageIds: toStringArray(block.directMessageIds),\n directToolIds: toStringArray(block.directToolIds),\n effectiveMessageIds: toStringArray(block.effectiveMessageIds),\n effectiveToolIds: toStringArray(block.effectiveToolIds),\n createdAt: typeof block.createdAt === \"number\" ? block.createdAt : 0,\n deactivatedAt:\n typeof block.deactivatedAt === \"number\" ? block.deactivatedAt : undefined,\n deactivatedByBlockId:\n typeof block.deactivatedByBlockId === \"number\" &&\n Number.isInteger(block.deactivatedByBlockId)\n ? block.deactivatedByBlockId\n : undefined,\n summary: typeof block.summary === \"string\" ? block.summary : \"\",\n survivedCount:\n typeof block.survivedCount === \"number\" && Number.isFinite(block.survivedCount)\n ? Math.max(0, Math.floor(block.survivedCount))\n : 0,\n generation:\n block.generation === \"young\" || block.generation === \"old\"\n ? block.generation\n : undefined,\n })\n }\n }\n\n // [FIX Bug 11] Skip loading persisted activeBlockIds here.\n // They will be correctly rebuilt from blocksById below (lines 273-286).\n // Loading them here first caused stale IDs for blocks with active:false.\n\n if (\n persisted.activeByAnchorMessageId &&\n typeof persisted.activeByAnchorMessageId === \"object\"\n ) {\n for (const [anchorMessageId, blockId] of Object.entries(\n persisted.activeByAnchorMessageId,\n )) {\n if (typeof blockId !== \"number\" || !Number.isInteger(blockId) || blockId < 1) {\n continue\n }\n state.activeByAnchorMessageId.set(anchorMessageId, blockId)\n }\n }\n\n for (const [blockId, block] of state.blocksById) {\n if (block.active) {\n state.activeBlockIds.add(blockId)\n if (block.anchorMessageId) {\n state.activeByAnchorMessageId.set(block.anchorMessageId, blockId)\n }\n }\n if (blockId >= state.nextBlockId) {\n state.nextBlockId = blockId + 1\n }\n if (block.runId >= state.nextRunId) {\n state.nextRunId = block.runId + 1\n }\n }\n\n if (Array.isArray(persisted.markedForCleanup)) {\n for (const id of persisted.markedForCleanup) {\n if (Number.isInteger(id) && id > 0 && state.blocksById.has(id)) {\n state.markedForCleanup.add(id)\n }\n }\n }\n\n return state\n}\n\nexport function collectTurnNudgeAnchors(messages: WithParts[]): Set<string> {\n const anchors = new Set<string>()\n let pendingUserMessageId: string | null = null\n\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i]\n\n if (messageHasCompress(message)) {\n break\n }\n\n if (message.info.role === \"user\") {\n if (!isIgnoredUserMessage(message)) {\n pendingUserMessageId = message.info.id\n }\n continue\n }\n\n if (message.info.role === \"assistant\" && pendingUserMessageId) {\n anchors.add(message.info.id)\n anchors.add(pendingUserMessageId)\n pendingUserMessageId = null\n }\n }\n\n return anchors\n}\n\nexport function getActiveSummaryTokenUsage(state: SessionState): number {\n let total = 0\n for (const blockId of state.prune.messages.activeBlockIds) {\n const block = state.prune.messages.blocksById.get(blockId)\n if (!block || !block.active) {\n continue\n }\n total += block.summaryTokens\n }\n return total\n}\n\nexport function resetOnCompaction(state: SessionState): void {\n state.toolParameters.clear()\n state.prune.tools = new Map<string, number>()\n // [PATCH Bug 2] Preserve prune.messages (compression blocks) on compaction.\n // Only reset transient state. Compression blocks are still valid even after\n // opencode compacts — their summaries are still needed in context.\n state.nudges = {\n contextLimitAnchors: new Set<string>(),\n turnNudgeAnchors: new Set<string>(),\n iterationNudgeAnchors: new Set<string>(),\n }\n // [FIX] Reset message IDs on compaction — old mappings are stale after\n // compaction replaces messages with a summary. Keeping them causes\n // assignMessageRefs to allocate from stale nextRef positions.\n state.messageIds = {\n byRawId: new Map<string, string>(),\n byRef: new Map<string, string>(),\n nextRef: 1,\n }\n}\n","import type { SessionState } from \"../state/types\"\nimport { attachCompressionDuration } from \"./state\"\n\nexport interface PendingCompressionDuration {\n messageId: string\n callId: string\n durationMs: number\n}\n\nexport interface CompressionTimingState {\n startsByCallId: Map<string, number>\n pendingByCallId: Map<string, PendingCompressionDuration>\n}\n\nexport function buildCompressionTimingKey(messageId: string, callId: string): string {\n return `${messageId}:${callId}`\n}\n\nexport function consumeCompressionStart(\n state: SessionState,\n messageId: string,\n callId: string,\n): number | undefined {\n const key = buildCompressionTimingKey(messageId, callId)\n const start = state.compressionTiming.startsByCallId.get(key)\n state.compressionTiming.startsByCallId.delete(key)\n return start\n}\n\nexport function resolveCompressionDuration(\n startedAt: number | undefined,\n eventTime: number | undefined,\n partTime: { start?: unknown; end?: unknown } | undefined,\n): number | undefined {\n const runningAt =\n typeof partTime?.start === \"number\" && Number.isFinite(partTime.start)\n ? partTime.start\n : eventTime\n const pendingToRunningMs =\n typeof startedAt === \"number\" && typeof runningAt === \"number\"\n ? Math.max(0, runningAt - startedAt)\n : undefined\n\n const toolStart = partTime?.start\n const toolEnd = partTime?.end\n const runtimeMs =\n typeof toolStart === \"number\" &&\n Number.isFinite(toolStart) &&\n typeof toolEnd === \"number\" &&\n Number.isFinite(toolEnd)\n ? Math.max(0, toolEnd - toolStart)\n : undefined\n\n return typeof pendingToRunningMs === \"number\" ? pendingToRunningMs : runtimeMs\n}\n\nexport function applyPendingCompressionDurations(state: SessionState): number {\n if (state.compressionTiming.pendingByCallId.size === 0) {\n return 0\n }\n\n let updates = 0\n for (const [key, entry] of state.compressionTiming.pendingByCallId) {\n const applied = attachCompressionDuration(\n state.prune.messages,\n entry.messageId,\n entry.callId,\n entry.durationMs,\n )\n if (applied > 0) {\n updates += applied\n state.compressionTiming.pendingByCallId.delete(key)\n }\n }\n\n return updates\n}\n","import type { SessionState, ToolParameterEntry, WithParts } from \"./types\"\nimport type { Logger } from \"../logger\"\nimport { applyPendingCompressionDurations } from \"../compress/timing\"\nimport { loadSessionState, saveSessionState } from \"./persistence\"\nimport {\n isSubAgentSession,\n findLastCompactionTimestamp,\n countTurns,\n resetOnCompaction,\n createPruneMessagesState,\n loadPruneMessagesState,\n loadPruneMap,\n collectTurnNudgeAnchors,\n} from \"./utils\"\nimport { getLastUserMessage } from \"../messages/query\"\nimport { parseMessageRef, formatMessageRef } from \"../message-ids\"\n\nexport const checkSession = async (\n client: any,\n state: SessionState,\n logger: Logger,\n messages: WithParts[],\n manualModeDefault: boolean,\n): Promise<void> => {\n const lastUserMessage = getLastUserMessage(messages)\n if (!lastUserMessage) {\n return\n }\n\n const lastSessionId = lastUserMessage.info.sessionID\n\n if (state.sessionId === null || state.sessionId !== lastSessionId) {\n logger.info(`Session changed: ${state.sessionId} -> ${lastSessionId}`)\n try {\n await ensureSessionInitialized(\n client,\n state,\n lastSessionId,\n logger,\n messages,\n manualModeDefault,\n )\n } catch (err: any) {\n logger.error(\"Failed to initialize session state\", { error: err.message })\n }\n }\n\n const lastCompactionTimestamp = findLastCompactionTimestamp(messages)\n if (lastCompactionTimestamp > state.lastCompaction) {\n state.lastCompaction = lastCompactionTimestamp\n resetOnCompaction(state)\n logger.info(\"Detected compaction - reset stale state\", {\n timestamp: lastCompactionTimestamp,\n })\n\n saveSessionState(state, logger).catch((error) => {\n logger.warn(\"Failed to persist state reset after compaction\", {\n error: error instanceof Error ? error.message : String(error),\n })\n })\n }\n\n state.currentTurn = countTurns(state, messages)\n}\n\nexport function createSessionState(): SessionState {\n return {\n sessionId: null,\n isSubAgent: false,\n manualMode: false,\n compressPermission: undefined,\n pendingManualTrigger: null,\n prune: {\n tools: new Map<string, number>(),\n messages: createPruneMessagesState(),\n },\n nudges: {\n contextLimitAnchors: new Set<string>(),\n turnNudgeAnchors: new Set<string>(),\n iterationNudgeAnchors: new Set<string>(),\n },\n stats: {\n pruneTokenCounter: 0,\n totalPruneTokens: 0,\n },\n compressionTiming: {\n startsByCallId: new Map<string, number>(),\n pendingByCallId: new Map(),\n },\n toolParameters: new Map<string, ToolParameterEntry>(),\n subAgentResultCache: new Map<string, string>(),\n toolIdList: [],\n messageIds: {\n byRawId: new Map<string, string>(),\n byRef: new Map<string, string>(),\n nextRef: 1,\n },\n lastCompaction: 0,\n currentTurn: 0,\n modelContextLimit: undefined,\n systemPromptTokens: undefined,\n }\n}\n\nexport function resetSessionState(state: SessionState): void {\n state.sessionId = null\n state.isSubAgent = false\n state.manualMode = false\n state.compressPermission = undefined\n state.pendingManualTrigger = null\n state.prune = {\n tools: new Map<string, number>(),\n messages: createPruneMessagesState(),\n }\n state.nudges = {\n contextLimitAnchors: new Set<string>(),\n turnNudgeAnchors: new Set<string>(),\n iterationNudgeAnchors: new Set<string>(),\n }\n state.stats = {\n pruneTokenCounter: 0,\n totalPruneTokens: 0,\n }\n state.toolParameters.clear()\n state.subAgentResultCache.clear()\n state.toolIdList = []\n state.messageIds = {\n byRawId: new Map<string, string>(),\n byRef: new Map<string, string>(),\n nextRef: 1,\n }\n state.lastCompaction = 0\n state.currentTurn = 0\n state.modelContextLimit = undefined\n state.systemPromptTokens = undefined\n}\n\nexport async function ensureSessionInitialized(\n client: any,\n state: SessionState,\n sessionId: string,\n logger: Logger,\n messages: WithParts[],\n manualModeEnabled: boolean,\n): Promise<void> {\n if (state.sessionId === sessionId) {\n return\n }\n\n // logger.info(\"session ID = \" + sessionId)\n // logger.info(\"Initializing session state\", { sessionId: sessionId })\n\n resetSessionState(state)\n state.manualMode = manualModeEnabled ? \"active\" : false\n state.sessionId = sessionId\n\n const isSubAgent = await isSubAgentSession(client, sessionId)\n state.isSubAgent = isSubAgent\n // logger.info(\"isSubAgent = \" + isSubAgent)\n\n state.lastCompaction = findLastCompactionTimestamp(messages)\n state.currentTurn = countTurns(state, messages)\n state.nudges.turnNudgeAnchors = collectTurnNudgeAnchors(messages)\n\n const persisted = await loadSessionState(sessionId, logger)\n if (persisted === null) {\n return\n }\n\n state.prune.tools = loadPruneMap(persisted.prune.tools)\n state.prune.messages = loadPruneMessagesState(persisted.prune.messages)\n state.nudges.contextLimitAnchors = new Set<string>(persisted.nudges.contextLimitAnchors || [])\n state.nudges.turnNudgeAnchors = new Set<string>([\n ...state.nudges.turnNudgeAnchors,\n ...(persisted.nudges.turnNudgeAnchors || []),\n ])\n state.nudges.iterationNudgeAnchors = new Set<string>(\n persisted.nudges.iterationNudgeAnchors || [],\n )\n state.stats = {\n pruneTokenCounter: persisted.stats?.pruneTokenCounter || 0,\n totalPruneTokens: persisted.stats?.totalPruneTokens || 0,\n }\n\n const persistedAny = persisted as any\n if (persistedAny._persistedMessageIds) {\n state.messageIds = {\n byRawId: new Map(Object.entries(persistedAny._persistedMessageIds.byRawId || {})),\n byRef: new Map(Object.entries(persistedAny._persistedMessageIds.byRef || {})),\n nextRef: persistedAny._persistedMessageIds.nextRef || 1,\n }\n // [FIX Bug 29] Auto-cleanup stale synthetic message refs from persistence\n for (const [rawId, ref] of state.messageIds.byRawId) {\n if (rawId.startsWith(\"msg_dcp_summary_\") || rawId.startsWith(\"msg_dcp_text_\")) {\n state.messageIds.byRawId.delete(rawId)\n state.messageIds.byRef.delete(ref)\n }\n }\n // Migrate 4-digit refs (m0001) to 5-digit (m00001) for msgid expansion\n for (const [rawId, oldRef] of state.messageIds.byRawId) {\n const parsed = parseMessageRef(oldRef)\n if (parsed !== null) {\n const newRef = formatMessageRef(parsed)\n if (newRef !== oldRef) {\n state.messageIds.byRawId.set(rawId, newRef)\n state.messageIds.byRef.delete(oldRef)\n state.messageIds.byRef.set(newRef, rawId)\n }\n }\n }\n }\n if (persistedAny._persistedLastCompaction !== undefined) {\n state.lastCompaction = Math.max(state.lastCompaction, persistedAny._persistedLastCompaction)\n }\n\n const applied = applyPendingCompressionDurations(state)\n if (applied > 0) {\n await saveSessionState(state, logger)\n }\n // [FIX Bug 1] Always save after initialization to persist messageIds + lastCompaction\n await saveSessionState(state, logger)\n}\n","import type { SessionState, ToolStatus, WithParts } from \"./index\"\nimport type { Logger } from \"../logger\"\nimport { PluginConfig } from \"../config\"\nimport { isMessageCompacted } from \"./utils\"\nimport { countToolTokens, extractToolContent } from \"../token-utils\"\n\nconst MAX_TOOL_CACHE_SIZE = 1000\n\n/**\n * Sync tool parameters from session messages.\n */\nexport function syncToolCache(\n state: SessionState,\n config: PluginConfig,\n logger: Logger,\n messages: WithParts[],\n): void {\n try {\n logger.info(\"Syncing tool parameters from OpenCode messages\")\n\n let turnCounter = 0\n\n for (const msg of messages) {\n if (isMessageCompacted(state, msg)) {\n continue\n }\n\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type === \"step-start\") {\n turnCounter++\n continue\n }\n\n if (part.type !== \"tool\" || !part.callID) {\n continue\n }\n\n const turnProtectionEnabled = config.turnProtection.enabled\n const turnProtectionTurns = config.turnProtection.turns\n const isProtectedByTurn =\n turnProtectionEnabled &&\n turnProtectionTurns > 0 &&\n state.currentTurn - turnCounter < turnProtectionTurns\n\n if (state.toolParameters.has(part.callID)) {\n continue\n }\n\n if (isProtectedByTurn) {\n continue\n }\n\n // [FIX Bug 33] Use fast token estimate instead of expensive Anthropic tokenizer\n // The tokenizer takes ~50ms per call; with 500+ tools that's 25 seconds.\n // text.length / 4 is accurate enough for pruning decisions.\n const contents = extractToolContent(part)\n const rawLength = contents.reduce((sum: number, s: string) => sum + (s?.length ?? 0), 0)\n const tokenCount = Math.round(rawLength / 4)\n\n state.toolParameters.set(part.callID, {\n tool: part.tool,\n parameters: part.state?.input ?? {},\n status: part.state.status as ToolStatus | undefined,\n error: part.state.status === \"error\" ? part.state.error : undefined,\n turn: turnCounter,\n tokenCount,\n })\n logger.info(\n `Cached tool id: ${part.callID} (turn ${turnCounter}${tokenCount !== undefined ? `, ${tokenCount} tokens` : \"\"})`,\n )\n }\n }\n\n logger.info(\n `Synced cache - size: ${state.toolParameters.size}, currentTurn: ${state.currentTurn}`,\n )\n trimToolParametersCache(state)\n } catch (error) {\n logger.warn(\"Failed to sync tool parameters from OpenCode\", {\n error: error instanceof Error ? error.message : String(error),\n })\n }\n}\n\n/**\n * Trim the tool parameters cache to prevent unbounded memory growth.\n * Uses FIFO eviction - removes oldest entries first.\n */\nexport function trimToolParametersCache(state: SessionState): void {\n if (state.toolParameters.size <= MAX_TOOL_CACHE_SIZE) {\n return\n }\n\n const keysToRemove = Array.from(state.toolParameters.keys()).slice(\n 0,\n state.toolParameters.size - MAX_TOOL_CACHE_SIZE,\n )\n\n for (const key of keysToRemove) {\n state.toolParameters.delete(key)\n }\n}\n","function normalizePath(input: string): string {\n return input.replaceAll(\"\\\\\\\\\", \"/\")\n}\n\nfunction escapeRegExpChar(ch: string): string {\n return /[\\\\.^$+{}()|\\[\\]]/.test(ch) ? `\\\\${ch}` : ch\n}\n\nexport function matchesGlob(inputPath: string, pattern: string): boolean {\n if (!pattern) return false\n\n const input = normalizePath(inputPath)\n const pat = normalizePath(pattern)\n\n let regex = \"^\"\n\n for (let i = 0; i < pat.length; i++) {\n const ch = pat[i]\n\n if (ch === \"*\") {\n const next = pat[i + 1]\n if (next === \"*\") {\n const after = pat[i + 2]\n if (after === \"/\") {\n // **/ (zero or more directories)\n regex += \"(?:.*/)?\"\n i += 2\n continue\n }\n\n // **\n regex += \".*\"\n i++\n continue\n }\n\n // *\n regex += \"[^/]*\"\n continue\n }\n\n if (ch === \"?\") {\n regex += \"[^/]\"\n continue\n }\n\n if (ch === \"/\") {\n regex += \"/\"\n continue\n }\n\n regex += escapeRegExpChar(ch)\n }\n\n regex += \"$\"\n\n return new RegExp(regex).test(input)\n}\n\nexport function getFilePathsFromParameters(tool: string, parameters: unknown): string[] {\n if (typeof parameters !== \"object\" || parameters === null) {\n return []\n }\n\n const paths: string[] = []\n const params = parameters as Record<string, any>\n\n // 1. apply_patch uses patchText with embedded paths\n if (tool === \"apply_patch\" && typeof params.patchText === \"string\") {\n const pathRegex = /\\*\\*\\* (?:Add|Delete|Update) File: ([^\\n\\r]+)/g\n let match\n while ((match = pathRegex.exec(params.patchText)) !== null) {\n paths.push(match[1].trim())\n }\n }\n\n // 2. multiedit uses top-level filePath and nested edits array\n if (tool === \"multiedit\") {\n if (typeof params.filePath === \"string\") {\n paths.push(params.filePath)\n }\n if (Array.isArray(params.edits)) {\n for (const edit of params.edits) {\n if (edit && typeof edit.filePath === \"string\") {\n paths.push(edit.filePath)\n }\n }\n }\n }\n\n // 3. Default check for common filePath parameter (read, write, edit, etc)\n if (typeof params.filePath === \"string\") {\n paths.push(params.filePath)\n }\n\n // Return unique non-empty paths\n return [...new Set(paths)].filter((p) => p.length > 0)\n}\n\nexport function isFilePathProtected(filePaths: string[], patterns: string[]): boolean {\n if (!filePaths || filePaths.length === 0) return false\n if (!patterns || patterns.length === 0) return false\n\n return filePaths.some((path) => patterns.some((pattern) => matchesGlob(path, pattern)))\n}\n\nconst GLOB_CHARS = /[*?]/\n\nexport function isToolNameProtected(toolName: string, patterns: string[]): boolean {\n if (!toolName || !patterns || patterns.length === 0) return false\n\n const exactPatterns: Set<string> = new Set()\n const globPatterns: string[] = []\n\n for (const pattern of patterns) {\n if (GLOB_CHARS.test(pattern)) {\n globPatterns.push(pattern)\n } else {\n exactPatterns.add(pattern)\n }\n }\n\n if (exactPatterns.has(toolName)) {\n return true\n }\n\n return globPatterns.some((pattern) => matchesGlob(toolName, pattern))\n}\n","import { PluginConfig } from \"../config\"\nimport { Logger } from \"../logger\"\nimport type { SessionState, WithParts } from \"../state\"\nimport {\n getFilePathsFromParameters,\n isFilePathProtected,\n isToolNameProtected,\n} from \"../protected-patterns\"\nimport { getTotalToolTokens } from \"../token-utils\"\n\n/**\n * Deduplication strategy - prunes older tool calls that have identical\n * tool name and parameters, keeping only the most recent occurrence.\n * Modifies the session state in place to add pruned tool call IDs.\n */\nexport const deduplicate = (\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n messages: WithParts[],\n): void => {\n if (state.manualMode && !config.manualMode.automaticStrategies) {\n return\n }\n\n if (!config.strategies.deduplication.enabled) {\n return\n }\n\n const allToolIds = state.toolIdList\n if (allToolIds.length === 0) {\n return\n }\n\n // Filter out IDs already pruned\n const unprunedIds = allToolIds.filter((id) => !state.prune.tools.has(id))\n\n if (unprunedIds.length === 0) {\n return\n }\n\n const protectedTools = config.strategies.deduplication.protectedTools\n\n // Group by signature (tool name + normalized parameters)\n const signatureMap = new Map<string, string[]>()\n\n for (const id of unprunedIds) {\n const metadata = state.toolParameters.get(id)\n if (!metadata) {\n // logger.warn(`Missing metadata for tool call ID: ${id}`)\n continue\n }\n\n // Skip protected tools\n if (isToolNameProtected(metadata.tool, protectedTools)) {\n continue\n }\n\n const filePaths = getFilePathsFromParameters(metadata.tool, metadata.parameters)\n if (isFilePathProtected(filePaths, config.protectedFilePatterns)) {\n continue\n }\n\n const signature = createToolSignature(metadata.tool, metadata.parameters)\n if (!signatureMap.has(signature)) {\n signatureMap.set(signature, [])\n }\n const ids = signatureMap.get(signature)\n if (ids) {\n ids.push(id)\n }\n }\n\n // Find duplicates - keep only the most recent (last) in each group\n const newPruneIds: string[] = []\n\n for (const [, ids] of signatureMap.entries()) {\n if (ids.length > 1) {\n // All except last (most recent) should be pruned\n const idsToRemove = ids.slice(0, -1)\n newPruneIds.push(...idsToRemove)\n }\n }\n\n state.stats.totalPruneTokens += getTotalToolTokens(state, newPruneIds)\n\n if (newPruneIds.length > 0) {\n for (const id of newPruneIds) {\n const entry = state.toolParameters.get(id)\n state.prune.tools.set(id, entry?.tokenCount ?? 0)\n }\n logger.debug(`Marked ${newPruneIds.length} duplicate tool calls for pruning`)\n }\n}\n\nfunction createToolSignature(tool: string, parameters?: any): string {\n if (!parameters) {\n return tool\n }\n const normalized = normalizeParameters(parameters)\n const sorted = sortObjectKeys(normalized)\n return `${tool}::${JSON.stringify(sorted)}`\n}\n\nfunction normalizeParameters(params: any): any {\n if (typeof params !== \"object\" || params === null) return params\n if (Array.isArray(params)) return params\n\n const normalized: any = {}\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n normalized[key] = value\n }\n }\n return normalized\n}\n\nfunction sortObjectKeys(obj: any): any {\n if (typeof obj !== \"object\" || obj === null) return obj\n if (Array.isArray(obj)) return obj.map(sortObjectKeys)\n\n const sorted: any = {}\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = sortObjectKeys(obj[key])\n }\n return sorted\n}\n","import { PluginConfig } from \"../config\"\nimport { Logger } from \"../logger\"\nimport type { SessionState, WithParts } from \"../state\"\nimport {\n getFilePathsFromParameters,\n isFilePathProtected,\n isToolNameProtected,\n} from \"../protected-patterns\"\nimport { getTotalToolTokens } from \"../token-utils\"\n\n/**\n * Purge Errors strategy - prunes tool inputs for tools that errored\n * after they are older than a configurable number of turns.\n * The error message is preserved, but the (potentially large) inputs\n * are removed to save context.\n *\n * Modifies the session state in place to add pruned tool call IDs.\n */\nexport const purgeErrors = (\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n messages: WithParts[],\n): void => {\n if (state.manualMode && !config.manualMode.automaticStrategies) {\n return\n }\n\n if (!config.strategies.purgeErrors.enabled) {\n return\n }\n\n const allToolIds = state.toolIdList\n if (allToolIds.length === 0) {\n return\n }\n\n // Filter out IDs already pruned\n const unprunedIds = allToolIds.filter((id) => !state.prune.tools.has(id))\n\n if (unprunedIds.length === 0) {\n return\n }\n\n const protectedTools = config.strategies.purgeErrors.protectedTools\n const turnThreshold = Math.max(1, config.strategies.purgeErrors.turns)\n\n const newPruneIds: string[] = []\n\n for (const id of unprunedIds) {\n const metadata = state.toolParameters.get(id)\n if (!metadata) {\n continue\n }\n\n // Skip protected tools\n if (isToolNameProtected(metadata.tool, protectedTools)) {\n continue\n }\n\n const filePaths = getFilePathsFromParameters(metadata.tool, metadata.parameters)\n if (isFilePathProtected(filePaths, config.protectedFilePatterns)) {\n continue\n }\n\n // Only process error tools\n if (metadata.status !== \"error\") {\n continue\n }\n\n // Check if the tool is old enough to prune\n const turnAge = state.currentTurn - metadata.turn\n if (turnAge >= turnThreshold) {\n newPruneIds.push(id)\n }\n }\n\n if (newPruneIds.length > 0) {\n state.stats.totalPruneTokens += getTotalToolTokens(state, newPruneIds)\n for (const id of newPruneIds) {\n const entry = state.toolParameters.get(id)\n state.prune.tools.set(id, entry?.tokenCount ?? 0)\n }\n logger.debug(\n `Marked ${newPruneIds.length} error tool calls for pruning (older than ${turnThreshold} turns)`,\n )\n }\n}\n","import { SessionState, ToolParameterEntry, WithParts } from \"../state\"\nimport { countTokens } from \"../token-utils\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\n\nfunction extractParameterKey(tool: string, parameters: any): string {\n if (!parameters) return \"\"\n\n if (tool === \"read\" && parameters.filePath) {\n const offset = parameters.offset\n const limit = parameters.limit\n if (offset !== undefined && limit !== undefined) {\n return `${parameters.filePath} (lines ${offset}-${offset + limit})`\n }\n if (offset !== undefined) {\n return `${parameters.filePath} (lines ${offset}+)`\n }\n if (limit !== undefined) {\n return `${parameters.filePath} (lines 0-${limit})`\n }\n return parameters.filePath\n }\n\n if ((tool === \"write\" || tool === \"edit\" || tool === \"multiedit\") && parameters.filePath) {\n return parameters.filePath\n }\n\n if (tool === \"apply_patch\" && typeof parameters.patchText === \"string\") {\n const pathRegex = /\\*\\*\\* (?:Add|Delete|Update) File: ([^\\n\\r]+)/g\n const paths: string[] = []\n let match\n while ((match = pathRegex.exec(parameters.patchText)) !== null) {\n paths.push(match[1].trim())\n }\n if (paths.length > 0) {\n const uniquePaths = [...new Set(paths)]\n const count = uniquePaths.length\n const plural = count > 1 ? \"s\" : \"\"\n if (count === 1) return uniquePaths[0]\n if (count === 2) return uniquePaths.join(\", \")\n return `${count} file${plural}: ${uniquePaths[0]}, ${uniquePaths[1]}...`\n }\n return \"patch\"\n }\n\n if (tool === \"list\") {\n return parameters.path || \"(current directory)\"\n }\n\n if (tool === \"glob\") {\n if (parameters.pattern) {\n const pathInfo = parameters.path ? ` in ${parameters.path}` : \"\"\n return `\"${parameters.pattern}\"${pathInfo}`\n }\n return \"(unknown pattern)\"\n }\n\n if (tool === \"grep\") {\n if (parameters.pattern) {\n const pathInfo = parameters.path ? ` in ${parameters.path}` : \"\"\n return `\"${parameters.pattern}\"${pathInfo}`\n }\n return \"(unknown pattern)\"\n }\n\n if (tool === \"bash\") {\n if (parameters.description) return parameters.description\n if (parameters.command) {\n return parameters.command.length > 50\n ? parameters.command.substring(0, 50) + \"...\"\n : parameters.command\n }\n }\n\n if (tool === \"webfetch\" && parameters.url) {\n return parameters.url\n }\n if (tool === \"websearch\" && parameters.query) {\n return `\"${parameters.query}\"`\n }\n if (tool === \"codesearch\" && parameters.query) {\n return `\"${parameters.query}\"`\n }\n\n if (tool === \"todowrite\") {\n return `${parameters.todos?.length || 0} todos`\n }\n if (tool === \"todoread\") {\n return \"read todo list\"\n }\n\n if (tool === \"task\" && parameters.description) {\n return parameters.description\n }\n if (tool === \"skill\" && parameters.name) {\n return parameters.name\n }\n\n if (tool === \"lsp\") {\n const op = parameters.operation || \"lsp\"\n const path = parameters.filePath || \"\"\n const line = parameters.line\n const char = parameters.character\n if (path && line !== undefined && char !== undefined) {\n return `${op} ${path}:${line}:${char}`\n }\n if (path) {\n return `${op} ${path}`\n }\n return op\n }\n\n if (tool === \"question\") {\n const questions = parameters.questions\n if (Array.isArray(questions) && questions.length > 0) {\n const headers = questions\n .map((q: any) => q.header || \"\")\n .filter(Boolean)\n .slice(0, 3)\n\n const count = questions.length\n const plural = count > 1 ? \"s\" : \"\"\n\n if (headers.length > 0) {\n const suffix = count > 3 ? ` (+${count - 3} more)` : \"\"\n return `${count} question${plural}: ${headers.join(\", \")}${suffix}`\n }\n return `${count} question${plural}`\n }\n return \"question\"\n }\n\n const paramStr = JSON.stringify(parameters)\n if (paramStr === \"{}\" || paramStr === \"[]\" || paramStr === \"null\") {\n return \"\"\n }\n\n return paramStr.substring(0, 50)\n}\n\nexport function formatStatsHeader(totalTokensSaved: number, pruneTokenCounter: number): string {\n const totalTokensSavedStr = `~${formatTokenCount(totalTokensSaved + pruneTokenCounter)}`\n return [`▣ ACP | ${totalTokensSavedStr} saved total`].join(\"\\n\")\n}\n\nexport function formatTokenCount(tokens: number, compact?: boolean): string {\n const suffix = compact ? \"\" : \" tokens\"\n if (tokens >= 1000) {\n return `${(tokens / 1000).toFixed(1)}K`.replace(\".0K\", \"K\") + suffix\n }\n return tokens.toString() + suffix\n}\n\nexport function truncate(str: string, maxLen: number = 60): string {\n if (str.length <= maxLen) return str\n return str.slice(0, maxLen - 3) + \"...\"\n}\n\nexport function formatProgressBar(\n messageIds: string[],\n prunedMessages: Map<string, number>,\n recentMessageIds: string[],\n width: number = 50,\n): string {\n const ACTIVE = \"█\"\n const PRUNED = \"░\"\n const RECENT = \"⣿\"\n const recentSet = new Set(recentMessageIds)\n\n const total = messageIds.length\n if (total === 0) return `│${PRUNED.repeat(width)}│`\n\n const bar = new Array(width).fill(ACTIVE)\n\n for (let m = 0; m < total; m++) {\n const msgId = messageIds[m]\n const start = Math.floor((m / total) * width)\n const end = Math.floor(((m + 1) / total) * width)\n\n if (recentSet.has(msgId)) {\n for (let i = start; i < end; i++) {\n bar[i] = RECENT\n }\n } else if (prunedMessages.has(msgId)) {\n for (let i = start; i < end; i++) {\n bar[i] = PRUNED\n }\n }\n }\n\n return `│${bar.join(\"\")}│`\n}\n\nexport function cacheSystemPromptTokens(state: SessionState, messages: WithParts[]): void {\n let firstInputTokens = 0\n for (const msg of messages) {\n if (msg.info.role !== \"assistant\") {\n continue\n }\n const info = msg.info as any\n const input = info?.tokens?.input || 0\n const cacheRead = info?.tokens?.cache?.read || 0\n const cacheWrite = info?.tokens?.cache?.write || 0\n if (input > 0 || cacheRead > 0 || cacheWrite > 0) {\n firstInputTokens = input + cacheRead + cacheWrite\n break\n }\n }\n\n if (firstInputTokens <= 0) {\n state.systemPromptTokens = undefined\n return\n }\n\n let firstUserText = \"\"\n for (const msg of messages) {\n if (msg.info.role !== \"user\" || isIgnoredUserMessage(msg)) {\n continue\n }\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type === \"text\" && !(part as any).ignored) {\n firstUserText += part.text\n }\n }\n break\n }\n\n const estimatedSystemTokens = Math.max(0, firstInputTokens - countTokens(firstUserText))\n state.systemPromptTokens = estimatedSystemTokens > 0 ? estimatedSystemTokens : undefined\n}\n\nexport function shortenPath(input: string, workingDirectory?: string): string {\n const inPathMatch = input.match(/^(.+) in (.+)$/)\n if (inPathMatch) {\n const prefix = inPathMatch[1]\n const pathPart = inPathMatch[2]\n const shortenedPath = shortenSinglePath(pathPart, workingDirectory)\n return `${prefix} in ${shortenedPath}`\n }\n\n return shortenSinglePath(input, workingDirectory)\n}\n\nfunction shortenSinglePath(path: string, workingDirectory?: string): string {\n if (workingDirectory) {\n if (path.startsWith(workingDirectory + \"/\")) {\n return path.slice(workingDirectory.length + 1)\n }\n if (path === workingDirectory) {\n return \".\"\n }\n }\n\n return path\n}\n\nexport function formatPrunedItemsList(\n pruneToolIds: string[],\n toolMetadata: Map<string, ToolParameterEntry>,\n workingDirectory?: string,\n): string[] {\n const lines: string[] = []\n\n for (const id of pruneToolIds) {\n const metadata = toolMetadata.get(id)\n\n if (metadata) {\n const paramKey = extractParameterKey(metadata.tool, metadata.parameters)\n if (paramKey) {\n // Use 60 char limit to match notification style\n const displayKey = truncate(shortenPath(paramKey, workingDirectory), 60)\n lines.push(`→ ${metadata.tool}: ${displayKey}`)\n } else {\n lines.push(`→ ${metadata.tool}`)\n }\n }\n }\n\n const knownCount = pruneToolIds.filter((id) => toolMetadata.has(id)).length\n const unknownCount = pruneToolIds.length - knownCount\n\n if (unknownCount > 0) {\n lines.push(`→ (${unknownCount} tool${unknownCount > 1 ? \"s\" : \"\"} with unknown metadata)`)\n }\n\n return lines\n}\n\nexport function formatPruningResultForTool(\n prunedIds: string[],\n toolMetadata: Map<string, ToolParameterEntry>,\n workingDirectory?: string,\n): string {\n const lines: string[] = []\n lines.push(`Context pruning complete. Pruned ${prunedIds.length} tool outputs.`)\n lines.push(\"\")\n\n if (prunedIds.length > 0) {\n lines.push(`Semantically pruned (${prunedIds.length}):`)\n lines.push(...formatPrunedItemsList(prunedIds, toolMetadata, workingDirectory))\n }\n\n return lines.join(\"\\n\").trim()\n}\n","import type { Logger } from \"../logger\"\nimport type { SessionState } from \"../state\"\nimport {\n formatPrunedItemsList,\n formatProgressBar,\n formatStatsHeader,\n formatTokenCount,\n} from \"./utils\"\nimport { ToolParameterEntry } from \"../state\"\nimport { PluginConfig } from \"../config\"\nimport { getActiveSummaryTokenUsage } from \"../state/utils\"\n\nexport type PruneReason = \"completion\" | \"noise\" | \"extraction\"\nexport const PRUNE_REASON_LABELS: Record<PruneReason, string> = {\n completion: \"Task Complete\",\n noise: \"Noise Removal\",\n extraction: \"Extraction\",\n}\n\ninterface CompressionNotificationEntry {\n blockId: number\n runId: number\n summary: string\n summaryTokens: number\n}\n\nfunction buildMinimalMessage(state: SessionState, reason: PruneReason | undefined): string {\n const reasonSuffix = reason ? ` — ${PRUNE_REASON_LABELS[reason]}` : \"\"\n return (\n formatStatsHeader(state.stats.totalPruneTokens, state.stats.pruneTokenCounter) +\n reasonSuffix\n )\n}\n\nfunction buildDetailedMessage(\n state: SessionState,\n reason: PruneReason | undefined,\n pruneToolIds: string[],\n toolMetadata: Map<string, ToolParameterEntry>,\n workingDirectory: string,\n): string {\n let message = formatStatsHeader(state.stats.totalPruneTokens, state.stats.pruneTokenCounter)\n\n if (pruneToolIds.length > 0) {\n const pruneTokenCounterStr = `~${formatTokenCount(state.stats.pruneTokenCounter)}`\n const reasonLabel = reason ? ` — ${PRUNE_REASON_LABELS[reason]}` : \"\"\n message += `\\n\\n▣ Pruning (${pruneTokenCounterStr})${reasonLabel}`\n\n const itemLines = formatPrunedItemsList(pruneToolIds, toolMetadata, workingDirectory)\n message += \"\\n\" + itemLines.join(\"\\n\")\n }\n\n return message.trim()\n}\n\nconst TOAST_BODY_MAX_LINES = 12\nconst TOAST_SUMMARY_MAX_CHARS = 600\nconst NOTIFICATION_SUMMARY_MAX_CHARS = 1500\n\nfunction truncateToastBody(body: string, maxLines: number = TOAST_BODY_MAX_LINES): string {\n const lines = body.split(\"\\n\")\n if (lines.length <= maxLines) {\n return body\n }\n const kept = lines.slice(0, maxLines - 1)\n const remaining = lines.length - maxLines + 1\n return kept.join(\"\\n\") + `\\n... and ${remaining} more`\n}\n\nfunction truncateToastSummary(summary: string, maxChars: number = TOAST_SUMMARY_MAX_CHARS): string {\n if (summary.length <= maxChars) {\n return summary\n }\n return summary.slice(0, maxChars - 3) + \"...\"\n}\n\nfunction truncateExtractedSection(\n message: string,\n maxChars: number = TOAST_SUMMARY_MAX_CHARS,\n): string {\n const marker = \"\\n\\n▣ Extracted\"\n const index = message.indexOf(marker)\n if (index === -1) {\n return message\n }\n const extracted = message.slice(index)\n if (extracted.length <= maxChars) {\n return message\n }\n return message.slice(0, index) + truncateToastSummary(extracted, maxChars)\n}\n\nexport async function sendUnifiedNotification(\n client: any,\n logger: Logger,\n config: PluginConfig,\n state: SessionState,\n sessionId: string,\n pruneToolIds: string[],\n toolMetadata: Map<string, ToolParameterEntry>,\n reason: PruneReason | undefined,\n params: any,\n workingDirectory: string,\n): Promise<boolean> {\n const hasPruned = pruneToolIds.length > 0\n if (!hasPruned) {\n return false\n }\n\n if (config.pruneNotification === \"off\") {\n return false\n }\n\n const message =\n config.pruneNotification === \"minimal\"\n ? buildMinimalMessage(state, reason)\n : buildDetailedMessage(state, reason, pruneToolIds, toolMetadata, workingDirectory)\n\n if (config.pruneNotificationType === \"toast\") {\n let toastMessage = truncateExtractedSection(message)\n toastMessage =\n config.pruneNotification === \"minimal\" ? toastMessage : truncateToastBody(toastMessage)\n\n await client.tui.showToast({\n body: {\n title: \"ACP: Compress Notification\",\n message: toastMessage,\n variant: \"info\",\n duration: 5000,\n },\n })\n return true\n }\n\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n return true\n}\n\nfunction buildCompressionSummary(\n entries: CompressionNotificationEntry[],\n state: SessionState,\n): string {\n if (entries.length === 1) {\n return entries[0]?.summary ?? \"\"\n }\n\n let result = \"\"\n for (const entry of entries) {\n const topic =\n state.prune.messages.blocksById.get(entry.blockId)?.topic ?? \"(unknown topic)\"\n const section = `### ${topic}\\n${entry.summary}`\n if (result.length + section.length + 2 > NOTIFICATION_SUMMARY_MAX_CHARS) {\n result += `\\n\\n... and ${entries.length - entries.indexOf(entry)} more`\n break\n }\n result += (result ? \"\\n\\n\" : \"\") + section\n }\n return result\n}\n\nfunction getCompressionLabel(entries: CompressionNotificationEntry[]): string {\n const runId = entries[0]?.runId\n if (runId === undefined) {\n return \"Compression\"\n }\n\n return `Compression #${runId}`\n}\n\nfunction formatCompressionMetrics(removedTokens: number, summaryTokens: number): string {\n const metrics = [`-${formatTokenCount(removedTokens, true)} removed`]\n if (summaryTokens > 0) {\n metrics.push(`+${formatTokenCount(summaryTokens, true)} summary`)\n }\n return metrics.join(\", \")\n}\n\nexport async function sendCompressNotification(\n client: any,\n logger: Logger,\n config: PluginConfig,\n state: SessionState,\n sessionId: string,\n entries: CompressionNotificationEntry[],\n batchTopic: string | undefined,\n sessionMessageIds: string[],\n params: any,\n): Promise<boolean> {\n if (config.pruneNotification === \"off\") {\n return false\n }\n\n if (entries.length === 0) {\n return false\n }\n\n let message: string\n const compressionLabel = getCompressionLabel(entries)\n const summary = buildCompressionSummary(entries, state)\n const summaryTokens = entries.reduce((total, entry) => total + entry.summaryTokens, 0)\n const summaryTokensStr = formatTokenCount(summaryTokens)\n const compressedTokens = entries.reduce((total, entry) => {\n const compressionBlock = state.prune.messages.blocksById.get(entry.blockId)\n if (!compressionBlock) {\n logger.error(\"Compression block missing for notification\", {\n compressionId: entry.blockId,\n sessionId,\n })\n return total\n }\n\n return total + compressionBlock.compressedTokens\n }, 0)\n\n const newlyCompressedMessageIds: string[] = []\n const newlyCompressedToolIds: string[] = []\n const seenMessageIds = new Set<string>()\n const seenToolIds = new Set<string>()\n\n for (const entry of entries) {\n const compressionBlock = state.prune.messages.blocksById.get(entry.blockId)\n if (!compressionBlock) {\n continue\n }\n\n for (const messageId of compressionBlock.directMessageIds) {\n if (seenMessageIds.has(messageId)) {\n continue\n }\n seenMessageIds.add(messageId)\n newlyCompressedMessageIds.push(messageId)\n }\n\n for (const toolId of compressionBlock.directToolIds) {\n if (seenToolIds.has(toolId)) {\n continue\n }\n seenToolIds.add(toolId)\n newlyCompressedToolIds.push(toolId)\n }\n }\n\n const topic =\n batchTopic ??\n (entries.length === 1\n ? (state.prune.messages.blocksById.get(entries[0]?.blockId ?? -1)?.topic ??\n \"(unknown topic)\")\n : \"(unknown topic)\")\n\n const totalActiveSummaryTkns = getActiveSummaryTokenUsage(state)\n const totalGross = state.stats.totalPruneTokens + state.stats.pruneTokenCounter\n const notificationHeader = `▣ ACP | ${formatCompressionMetrics(totalGross, totalActiveSummaryTkns)}`\n\n if (config.pruneNotification === \"minimal\") {\n message = `${notificationHeader} — ${compressionLabel}`\n } else {\n message = notificationHeader\n\n const activePrunedMessages = new Map<string, number>()\n for (const [messageId, entry] of state.prune.messages.byMessageId) {\n if (entry.activeBlockIds.length > 0) {\n activePrunedMessages.set(messageId, entry.tokenCount)\n }\n }\n const progressBar = formatProgressBar(\n sessionMessageIds,\n activePrunedMessages,\n newlyCompressedMessageIds,\n 50,\n )\n message += `\\n\\n${progressBar}`\n message += `\\n▣ ${compressionLabel} ${formatCompressionMetrics(compressedTokens, summaryTokens)}`\n message += `\\n→ Topic: ${topic}`\n message += `\\n→ Items: ${newlyCompressedMessageIds.length} messages`\n if (newlyCompressedToolIds.length > 0) {\n message += ` and ${newlyCompressedToolIds.length} tools compressed`\n } else {\n message += ` compressed`\n }\n if (config.compress.showCompression) {\n const displaySummary =\n summary.length > NOTIFICATION_SUMMARY_MAX_CHARS\n ? truncateToastSummary(summary, NOTIFICATION_SUMMARY_MAX_CHARS)\n : summary\n message += `\\n→ Compression (~${summaryTokensStr}): ${displaySummary}`\n }\n }\n\n if (config.pruneNotificationType === \"toast\") {\n let toastMessage = message\n if (config.compress.showCompression) {\n const truncatedSummary = truncateToastSummary(summary)\n if (truncatedSummary !== summary) {\n toastMessage = toastMessage.replace(\n `\\n→ Compression (~${summaryTokensStr}): ${truncateToastSummary(summary, NOTIFICATION_SUMMARY_MAX_CHARS)}`,\n `\\n→ Compression (~${summaryTokensStr}): ${truncatedSummary}`,\n )\n }\n }\n toastMessage =\n config.pruneNotification === \"minimal\" ? toastMessage : truncateToastBody(toastMessage)\n\n await client.tui.showToast({\n body: {\n title: \"ACP: Compress Notification\",\n message: toastMessage,\n variant: \"info\",\n duration: 5000,\n },\n })\n return true\n }\n\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n return true\n}\n\nexport async function sendIgnoredMessage(\n client: any,\n sessionID: string,\n text: string,\n params: any,\n logger: Logger,\n): Promise<void> {\n const agent = params.agent || undefined\n const variant = params.variant || undefined\n const model =\n params.providerId && params.modelId\n ? {\n providerID: params.providerId,\n modelID: params.modelId,\n }\n : undefined\n\n try {\n await client.session.prompt({\n path: {\n id: sessionID,\n },\n body: {\n noReply: true,\n agent: agent,\n model: model,\n variant: variant,\n parts: [\n {\n type: \"text\",\n text: text,\n ignored: true,\n },\n ],\n },\n })\n } catch (error: any) {\n logger.error(\"Failed to send notification\", { error: error.message })\n }\n}\n","import type { WithParts } from \"../state\"\nimport { ensureSessionInitialized } from \"../state\"\nimport { saveSessionState } from \"../state/persistence\"\nimport { assignMessageRefs } from \"../message-ids\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\nimport { deduplicate, purgeErrors } from \"../strategies\"\nimport { getCurrentParams, getCurrentTokenUsage } from \"../token-utils\"\nimport { sendCompressNotification } from \"../ui/notification\"\nimport type { ToolContext } from \"./types\"\nimport { buildSearchContext, fetchSessionMessages } from \"./search\"\nimport type { SearchContext } from \"./types\"\nimport { applyPendingCompressionDurations } from \"./timing\"\n\ninterface RunContext {\n ask(input: {\n permission: string\n patterns: string[]\n always: string[]\n metadata: Record<string, unknown>\n }): Promise<void>\n metadata(input: { title: string }): void\n sessionID: string\n}\n\nexport interface NotificationEntry {\n blockId: number\n runId: number\n summary: string\n summaryTokens: number\n}\n\nexport interface PreparedSession {\n rawMessages: WithParts[]\n searchContext: SearchContext\n}\n\nexport async function prepareSession(\n ctx: ToolContext,\n toolCtx: RunContext,\n title: string,\n): Promise<PreparedSession> {\n if (ctx.state.manualMode && ctx.state.manualMode !== \"compress-pending\") {\n throw new Error(\n \"Manual mode: compress blocked. Do not retry until `<compress triggered manually>` appears in user context.\",\n )\n }\n\n await toolCtx.ask({\n permission: \"compress\",\n patterns: [\"*\"],\n always: [\"*\"],\n metadata: {},\n })\n\n toolCtx.metadata({ title })\n\n const rawMessages = await fetchSessionMessages(ctx.client, toolCtx.sessionID)\n\n await ensureSessionInitialized(\n ctx.client,\n ctx.state,\n toolCtx.sessionID,\n ctx.logger,\n rawMessages,\n ctx.config.manualMode.enabled,\n )\n\n assignMessageRefs(ctx.state, rawMessages)\n\n deduplicate(ctx.state, ctx.logger, ctx.config, rawMessages)\n purgeErrors(ctx.state, ctx.logger, ctx.config, rawMessages)\n\n return {\n rawMessages,\n searchContext: buildSearchContext(ctx.state, rawMessages),\n }\n}\n\nexport async function finalizeSession(\n ctx: ToolContext,\n toolCtx: RunContext,\n rawMessages: WithParts[],\n entries: NotificationEntry[],\n batchTopic: string | undefined,\n): Promise<void> {\n ctx.state.manualMode = ctx.state.manualMode ? \"active\" : false\n applyPendingCompressionDurations(ctx.state)\n await saveSessionState(ctx.state, ctx.logger)\n\n const params = getCurrentParams(ctx.state, rawMessages, ctx.logger)\n const sessionMessageIds = rawMessages\n .filter((msg) => !isIgnoredUserMessage(msg))\n .map((msg) => msg.info.id)\n\n await sendCompressNotification(\n ctx.client,\n ctx.logger,\n ctx.config,\n ctx.state,\n toolCtx.sessionID,\n entries,\n batchTopic,\n sessionMessageIds,\n params,\n )\n}\n","import type { WithParts } from \"../state\"\n\nconst SUB_AGENT_RESULT_BLOCK_REGEX = /(<task_result>\\s*)([\\s\\S]*?)(\\s*<\\/task_result>)/i\n\nexport function getSubAgentId(part: any): string | null {\n const sessionId = part?.state?.metadata?.sessionId\n if (typeof sessionId !== \"string\") {\n return null\n }\n\n const value = sessionId.trim()\n return value.length > 0 ? value : null\n}\n\nexport function buildSubagentResultText(messages: WithParts[]): string {\n const assistantMessages = messages.filter((message) => message.info.role === \"assistant\")\n if (assistantMessages.length === 0) {\n return \"\"\n }\n\n const lastAssistant = assistantMessages[assistantMessages.length - 1]\n const lastText = getLastTextPart(lastAssistant)\n\n if (assistantMessages.length < 2) {\n return lastText\n }\n\n const secondToLastAssistant = assistantMessages[assistantMessages.length - 2]\n if (!assistantMessageHasCompressTool(secondToLastAssistant)) {\n return lastText\n }\n\n const secondToLastText = getLastTextPart(secondToLastAssistant)\n return [secondToLastText, lastText].filter((text) => text.length > 0).join(\"\\n\\n\")\n}\n\nexport function mergeSubagentResult(output: string, subAgentResultText: string): string {\n if (!subAgentResultText || typeof output !== \"string\") {\n return output\n }\n\n return output.replace(\n SUB_AGENT_RESULT_BLOCK_REGEX,\n (_match, openTag: string, _body: string, closeTag: string) =>\n `${openTag}${subAgentResultText}${closeTag}`,\n )\n}\n\nfunction getLastTextPart(message: WithParts): string {\n const parts = Array.isArray(message.parts) ? message.parts : []\n for (let index = parts.length - 1; index >= 0; index--) {\n const part = parts[index]\n if (part.type !== \"text\" || typeof part.text !== \"string\") {\n continue\n }\n\n const text = part.text.trim()\n if (!text) {\n continue\n }\n\n return text\n }\n\n return \"\"\n}\n\nfunction assistantMessageHasCompressTool(message: WithParts): boolean {\n const parts = Array.isArray(message.parts) ? message.parts : []\n return parts.some(\n (part) =>\n part.type === \"tool\" && part.tool === \"compress\" && part.state?.status === \"completed\",\n )\n}\n","import type { SessionState } from \"../state\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\nimport {\n getFilePathsFromParameters,\n isFilePathProtected,\n isToolNameProtected,\n} from \"../protected-patterns\"\nimport {\n buildSubagentResultText,\n getSubAgentId,\n mergeSubagentResult,\n} from \"../subagents/subagent-results\"\nimport { fetchSessionMessages } from \"./search\"\nimport type { SearchContext, SelectionResolution } from \"./types\"\n\nexport function appendProtectedUserMessages(\n summary: string,\n selection: SelectionResolution,\n searchContext: SearchContext,\n state: SessionState,\n enabled: boolean,\n): string {\n if (!enabled) return summary\n\n const userTexts: string[] = []\n\n for (const messageId of selection.messageIds) {\n const existingCompressionEntry = state.prune.messages.byMessageId.get(messageId)\n if (existingCompressionEntry && existingCompressionEntry.activeBlockIds.length > 0) {\n continue\n }\n\n const message = searchContext.rawMessagesById.get(messageId)\n if (!message) continue\n if (message.info.role !== \"user\") continue\n if (isIgnoredUserMessage(message)) continue\n\n const parts = Array.isArray(message.parts) ? message.parts : []\n for (const part of parts) {\n if (part.type === \"text\" && typeof part.text === \"string\" && part.text.trim()) {\n userTexts.push(part.text)\n break\n }\n }\n }\n\n if (userTexts.length === 0) {\n return summary\n }\n\n const heading = \"\\n\\nThe following user messages were sent in this conversation verbatim:\"\n const body = userTexts.map((text) => `\\n${text}`).join(\"\")\n return summary + heading + body\n}\n\nexport function appendProtectedPromptInfo(\n summary: string,\n selection: SelectionResolution,\n searchContext: SearchContext,\n state: SessionState,\n enabled: boolean,\n): string {\n if (!enabled) return summary\n\n const protectedTexts: string[] = []\n\n for (const messageId of selection.messageIds) {\n const existingCompressionEntry = state.prune.messages.byMessageId.get(messageId)\n if (existingCompressionEntry && existingCompressionEntry.activeBlockIds.length > 0) {\n continue\n }\n\n const message = searchContext.rawMessagesById.get(messageId)\n if (!message) continue\n if (message.info.role !== \"user\") continue\n if (isIgnoredUserMessage(message)) continue\n\n const parts = Array.isArray(message.parts) ? message.parts : []\n for (const part of parts) {\n if (part.type !== \"text\" || typeof part.text !== \"string\") continue\n\n protectedTexts.push(...extractProtectedPromptInfo(part.text))\n }\n }\n\n if (protectedTexts.length === 0) {\n return summary\n }\n\n const heading =\n \"\\n\\nThe following protected prompt information was included in this conversation verbatim:\"\n const body = protectedTexts.map((text) => `\\n${text}`).join(\"\")\n return summary + heading + body\n}\n\nexport function extractProtectedPromptInfo(text: string): string[] {\n const protectedTexts: string[] = []\n const protectTagRegex = /<protect>([\\s\\S]*?)<\\/protect>/gi\n\n for (const match of text.matchAll(protectTagRegex)) {\n const protectedText = match[1]?.trim()\n if (protectedText) {\n protectedTexts.push(protectedText)\n }\n }\n\n return protectedTexts\n}\n\nexport async function appendProtectedTools(\n client: any,\n state: SessionState,\n allowSubAgents: boolean,\n summary: string,\n selection: SelectionResolution,\n searchContext: SearchContext,\n protectedTools: string[],\n protectedFilePatterns: string[] = [],\n): Promise<string> {\n const protectedOutputs: string[] = []\n\n for (const messageId of selection.messageIds) {\n const existingCompressionEntry = state.prune.messages.byMessageId.get(messageId)\n if (existingCompressionEntry && existingCompressionEntry.activeBlockIds.length > 0) {\n continue\n }\n\n const message = searchContext.rawMessagesById.get(messageId)\n if (!message) continue\n\n const parts = Array.isArray(message.parts) ? message.parts : []\n for (const part of parts) {\n if (part.type === \"tool\" && part.callID) {\n let isToolProtected = isToolNameProtected(part.tool, protectedTools)\n\n if (!isToolProtected && protectedFilePatterns.length > 0) {\n const filePaths = getFilePathsFromParameters(part.tool, part.state?.input)\n if (isFilePathProtected(filePaths, protectedFilePatterns)) {\n isToolProtected = true\n }\n }\n\n if (isToolProtected) {\n const title = `Tool: ${part.tool}`\n let output = \"\"\n\n if (part.state?.status === \"completed\" && part.state?.output) {\n output =\n typeof part.state.output === \"string\"\n ? part.state.output\n : JSON.stringify(part.state.output)\n }\n\n if (\n allowSubAgents &&\n part.tool === \"task\" &&\n part.state?.status === \"completed\" &&\n typeof part.state?.output === \"string\"\n ) {\n const cachedSubAgentResult = state.subAgentResultCache.get(part.callID)\n\n if (cachedSubAgentResult !== undefined) {\n if (cachedSubAgentResult) {\n output = mergeSubagentResult(\n part.state.output,\n cachedSubAgentResult,\n )\n }\n } else {\n const subAgentSessionId = getSubAgentId(part)\n if (subAgentSessionId) {\n let subAgentResultText = \"\"\n try {\n const subAgentMessages = await fetchSessionMessages(\n client,\n subAgentSessionId,\n )\n subAgentResultText = buildSubagentResultText(subAgentMessages)\n } catch {\n subAgentResultText = \"\"\n }\n\n if (subAgentResultText) {\n state.subAgentResultCache.set(part.callID, subAgentResultText)\n output = mergeSubagentResult(\n part.state.output,\n subAgentResultText,\n )\n }\n }\n }\n }\n\n if (output) {\n protectedOutputs.push(`\\n### ${title}\\n${output}`)\n }\n }\n }\n }\n }\n\n if (protectedOutputs.length === 0) {\n return summary\n }\n\n const heading = \"\\n\\nThe following protected tools were used in this conversation as well:\"\n return summary + heading + protectedOutputs.join(\"\")\n}\n","import { tool } from \"@opencode-ai/plugin\"\nimport type { ToolContext } from \"./types\"\nimport { countTokens } from \"../token-utils\"\nimport { RANGE_FORMAT_EXTENSION } from \"../prompts/extensions/tool\"\nimport { finalizeSession, prepareSession, type NotificationEntry } from \"./pipeline\"\nimport {\n appendProtectedPromptInfo,\n appendProtectedTools,\n appendProtectedUserMessages,\n} from \"./protected-content\"\nimport {\n appendMissingBlockSummaries,\n injectBlockPlaceholders,\n parseBlockPlaceholders,\n resolveRanges,\n validateArgs,\n validateNonOverlapping,\n validateSummaryPlaceholders,\n} from \"./range-utils\"\nimport {\n COMPRESSED_BLOCK_HEADER,\n allocateBlockId,\n allocateRunId,\n applyCompressionState,\n wrapCompressedSummary,\n} from \"./state\"\nimport type { CompressRangeToolArgs } from \"./types\"\n\nfunction buildSchema() {\n return {\n topic: tool.schema\n .string()\n .describe(\"Short label (3-5 words) for display - e.g., 'Auth System Exploration'\"),\n content: tool.schema\n .array(\n tool.schema.object({\n startId: tool.schema\n .string()\n .describe(\n \"Message or block ID marking the beginning of range (e.g. m00001, b2)\",\n ),\n endId: tool.schema\n .string()\n .describe(\"Message or block ID marking the end of range (e.g. m00012, b5)\"),\n summary: tool.schema\n .string()\n .describe(\"Complete technical summary replacing all content in range\"),\n }),\n )\n .describe(\n \"One or more ranges to compress, each with start/end boundaries and a summary\",\n ),\n }\n}\n\nexport function createCompressRangeTool(ctx: ToolContext): ReturnType<typeof tool> {\n ctx.prompts.reload()\n const runtimePrompts = ctx.prompts.getRuntimePrompts()\n\n return tool({\n description: runtimePrompts.compressRange + RANGE_FORMAT_EXTENSION,\n args: buildSchema(),\n async execute(args, toolCtx) {\n const input = args as CompressRangeToolArgs\n validateArgs(input)\n const callId =\n typeof (toolCtx as unknown as { callID?: unknown }).callID === \"string\"\n ? (toolCtx as unknown as { callID: string }).callID\n : undefined\n\n const { rawMessages, searchContext } = await prepareSession(\n ctx,\n toolCtx,\n `Compress Range: ${input.topic}`,\n )\n const resolvedPlans = resolveRanges(input, searchContext, ctx.state)\n validateNonOverlapping(resolvedPlans)\n\n const notifications: NotificationEntry[] = []\n const preparedPlans: Array<{\n entry: (typeof resolvedPlans)[number][\"entry\"]\n selection: (typeof resolvedPlans)[number][\"selection\"]\n anchorMessageId: string\n finalSummary: string\n consumedBlockIds: number[]\n }> = []\n let totalCompressedMessages = 0\n\n for (const plan of resolvedPlans) {\n const parsedPlaceholders = parseBlockPlaceholders(plan.entry.summary)\n validateSummaryPlaceholders(\n parsedPlaceholders,\n plan.selection.requiredBlockIds,\n plan.selection.startReference,\n plan.selection.endReference,\n searchContext.summaryByBlockId,\n )\n\n const injected = injectBlockPlaceholders(\n plan.entry.summary,\n parsedPlaceholders,\n searchContext.summaryByBlockId,\n plan.selection.startReference,\n plan.selection.endReference,\n )\n\n const summaryWithUsers = appendProtectedUserMessages(\n injected.expandedSummary,\n plan.selection,\n searchContext,\n ctx.state,\n ctx.config.compress.protectUserMessages,\n )\n\n const summaryWithPromptInfo = appendProtectedPromptInfo(\n summaryWithUsers,\n plan.selection,\n searchContext,\n ctx.state,\n ctx.config.compress.protectTags,\n )\n\n const summaryWithTools = await appendProtectedTools(\n ctx.client,\n ctx.state,\n ctx.config.experimental.allowSubAgents,\n summaryWithPromptInfo,\n plan.selection,\n searchContext,\n ctx.config.compress.protectedTools,\n ctx.config.protectedFilePatterns,\n )\n\n const completedSummary = appendMissingBlockSummaries(\n summaryWithTools,\n [],\n searchContext.summaryByBlockId,\n injected.consumedBlockIds,\n )\n\n const mergeConsumedBlockIds = extractBoundaryConsumedBlocks(\n plan.selection.startReference,\n plan.selection.endReference,\n )\n\n preparedPlans.push({\n entry: plan.entry,\n selection: plan.selection,\n anchorMessageId: plan.anchorMessageId,\n finalSummary: completedSummary.expandedSummary,\n consumedBlockIds: mergeConsumedBlockIds,\n })\n }\n\n const runId = allocateRunId(ctx.state)\n\n for (const preparedPlan of preparedPlans) {\n const blockId = allocateBlockId(ctx.state)\n const storedSummary = wrapCompressedSummary(blockId, preparedPlan.finalSummary)\n const summaryTokens = countTokens(storedSummary)\n\n const applied = applyCompressionState(\n ctx.state,\n {\n topic: input.topic,\n batchTopic: input.topic,\n startId: preparedPlan.entry.startId,\n endId: preparedPlan.entry.endId,\n mode: \"range\",\n runId,\n compressMessageId: toolCtx.messageID,\n compressCallId: callId,\n summaryTokens,\n },\n preparedPlan.selection,\n preparedPlan.anchorMessageId,\n blockId,\n storedSummary,\n preparedPlan.consumedBlockIds,\n ctx.config.gc,\n )\n\n totalCompressedMessages += applied.messageIds.length\n\n notifications.push({\n blockId,\n runId,\n summary: preparedPlan.finalSummary,\n summaryTokens,\n })\n }\n\n await finalizeSession(ctx, toolCtx, rawMessages, notifications, input.topic)\n\n return `Compressed ${totalCompressedMessages} messages into ${COMPRESSED_BLOCK_HEADER}.\\nIMPORTANT: This was an automatic context compression. You MUST continue your previous task exactly where you left off. Do NOT ask the user what to do next.`\n },\n })\n}\n\nfunction extractBoundaryConsumedBlocks(\n startReference: { kind: string; blockId?: number },\n endReference: { kind: string; blockId?: number },\n): number[] {\n const consumed: number[] = []\n const seen = new Set<number>()\n for (const ref of [startReference, endReference]) {\n if (ref.kind === \"compressed-block\" && ref.blockId !== undefined && !seen.has(ref.blockId)) {\n seen.add(ref.blockId)\n consumed.push(ref.blockId)\n }\n }\n return consumed\n}\n","import type { CompressionBlock, SessionState } from \"../state\"\nimport { resolveAnchorMessageId, resolveBoundaryIds, resolveSelection } from \"./search\"\nimport type {\n BoundaryReference,\n CompressRangeToolArgs,\n InjectedSummaryResult,\n ParsedBlockPlaceholder,\n ResolvedRangeCompression,\n SearchContext,\n} from \"./types\"\n\nconst BLOCK_PLACEHOLDER_REGEX = /\\(b(\\d+)\\)|\\{block_(\\d+)\\}/gi\n\nexport function validateArgs(args: CompressRangeToolArgs): void {\n if (typeof args.topic !== \"string\" || args.topic.trim().length === 0) {\n throw new Error(\"topic is required and must be a non-empty string\")\n }\n\n if (!Array.isArray(args.content) || args.content.length === 0) {\n throw new Error(\"content is required and must be a non-empty array\")\n }\n\n for (let index = 0; index < args.content.length; index++) {\n const entry = args.content[index]\n const prefix = `content[${index}]`\n\n if (typeof entry?.startId !== \"string\" || entry.startId.trim().length === 0) {\n throw new Error(`${prefix}.startId is required and must be a non-empty string`)\n }\n\n if (typeof entry?.endId !== \"string\" || entry.endId.trim().length === 0) {\n throw new Error(`${prefix}.endId is required and must be a non-empty string`)\n }\n\n if (typeof entry?.summary !== \"string\" || entry.summary.trim().length === 0) {\n throw new Error(`${prefix}.summary is required and must be a non-empty string`)\n }\n }\n}\n\nexport function resolveRanges(\n args: CompressRangeToolArgs,\n searchContext: SearchContext,\n state: SessionState,\n): ResolvedRangeCompression[] {\n return args.content.map((entry, index) => {\n const normalizedEntry = {\n startId: entry.startId.trim(),\n endId: entry.endId.trim(),\n summary: entry.summary,\n }\n\n const { startReference, endReference } = resolveBoundaryIds(\n searchContext,\n state,\n normalizedEntry.startId,\n normalizedEntry.endId,\n )\n const selection = resolveSelection(searchContext, startReference, endReference)\n\n return {\n index,\n entry: normalizedEntry,\n selection,\n anchorMessageId: resolveAnchorMessageId(startReference),\n }\n })\n}\n\nexport function validateNonOverlapping(plans: ResolvedRangeCompression[]): void {\n const sortedPlans = [...plans].sort(\n (left, right) =>\n left.selection.startReference.rawIndex - right.selection.startReference.rawIndex ||\n left.selection.endReference.rawIndex - right.selection.endReference.rawIndex ||\n left.index - right.index,\n )\n\n const issues: string[] = []\n\n for (let index = 1; index < sortedPlans.length; index++) {\n const previous = sortedPlans[index - 1]\n const current = sortedPlans[index]\n if (!previous || !current) {\n continue\n }\n\n if (current.selection.startReference.rawIndex > previous.selection.endReference.rawIndex) {\n continue\n }\n\n issues.push(\n `content[${previous.index}] (${previous.entry.startId}..${previous.entry.endId}) overlaps content[${current.index}] (${current.entry.startId}..${current.entry.endId}). Overlapping ranges cannot be compressed in the same batch.`,\n )\n }\n\n if (issues.length > 0) {\n throw new Error(\n issues.length === 1 ? issues[0] : issues.map((issue) => `- ${issue}`).join(\"\\n\"),\n )\n }\n}\n\nexport function parseBlockPlaceholders(summary: string): ParsedBlockPlaceholder[] {\n const placeholders: ParsedBlockPlaceholder[] = []\n const regex = new RegExp(BLOCK_PLACEHOLDER_REGEX)\n\n let match: RegExpExecArray | null\n while ((match = regex.exec(summary)) !== null) {\n const full = match[0]\n const blockIdPart = match[1] || match[2]\n const parsed = Number.parseInt(blockIdPart, 10)\n if (!Number.isInteger(parsed)) {\n continue\n }\n\n placeholders.push({\n raw: full,\n blockId: parsed,\n startIndex: match.index,\n endIndex: match.index + full.length,\n })\n }\n\n return placeholders\n}\n\nexport function validateSummaryPlaceholders(\n placeholders: ParsedBlockPlaceholder[],\n requiredBlockIds: number[],\n startReference: BoundaryReference,\n endReference: BoundaryReference,\n summaryByBlockId: Map<number, CompressionBlock>,\n): number[] {\n const boundaryOptionalIds = new Set<number>()\n if (startReference.kind === \"compressed-block\") {\n if (startReference.blockId === undefined) {\n throw new Error(\"Failed to map boundary matches back to raw messages\")\n }\n boundaryOptionalIds.add(startReference.blockId)\n }\n if (endReference.kind === \"compressed-block\") {\n if (endReference.blockId === undefined) {\n throw new Error(\"Failed to map boundary matches back to raw messages\")\n }\n boundaryOptionalIds.add(endReference.blockId)\n }\n\n const strictRequiredIds = requiredBlockIds.filter((id) => !boundaryOptionalIds.has(id))\n const requiredSet = new Set(requiredBlockIds)\n const keptPlaceholderIds = new Set<number>()\n const validPlaceholders: ParsedBlockPlaceholder[] = []\n\n for (const placeholder of placeholders) {\n const isKnown = summaryByBlockId.has(placeholder.blockId)\n const isRequired = requiredSet.has(placeholder.blockId)\n const isDuplicate = keptPlaceholderIds.has(placeholder.blockId)\n\n if (isKnown && isRequired && !isDuplicate) {\n validPlaceholders.push(placeholder)\n keptPlaceholderIds.add(placeholder.blockId)\n }\n }\n\n placeholders.length = 0\n placeholders.push(...validPlaceholders)\n\n return strictRequiredIds.filter((id) => !keptPlaceholderIds.has(id))\n}\n\nexport function injectBlockPlaceholders(\n summary: string,\n _placeholders: ParsedBlockPlaceholder[],\n _summaryByBlockId: Map<number, CompressionBlock>,\n _startReference: BoundaryReference,\n _endReference: BoundaryReference,\n): InjectedSummaryResult {\n return {\n expandedSummary: summary,\n consumedBlockIds: [],\n }\n}\n\nexport function appendMissingBlockSummaries(\n summary: string,\n _missingBlockIds: number[],\n _summaryByBlockId: Map<number, CompressionBlock>,\n consumedBlockIds: number[],\n): InjectedSummaryResult {\n return {\n expandedSummary: summary,\n consumedBlockIds: [...consumedBlockIds],\n }\n}\n\n","import { tool } from \"@opencode-ai/plugin\"\nimport type { ToolContext } from \"./types\"\nimport { ensureSessionInitialized } from \"../state\"\nimport { saveSessionState } from \"../state/persistence\"\nimport { assignMessageRefs } from \"../message-ids\"\nimport { syncCompressionBlocks } from \"../messages\"\nimport { getCurrentTokenUsage } from \"../token-utils\"\nimport { fetchSessionMessages } from \"./search\"\nimport { resolveCompressionTarget } from \"../commands/compression-targets\"\nimport {\n parseBlockIdArg,\n findActiveAncestorBlockId,\n snapshotActiveMessages,\n deactivateCompressionTarget,\n computeRestoredMessages,\n computeReactivatedBlockIds,\n buildRestoredContentPreview,\n} from \"./decompress-logic\"\nimport { formatTokenCount } from \"../ui/utils\"\n\ninterface RunContext {\n ask(input: {\n permission: string\n patterns: string[]\n always: string[]\n metadata: Record<string, unknown>\n }): Promise<void>\n metadata(input: { title: string }): void\n sessionID: string\n}\n\nasync function prepareDecompressSession(\n ctx: ToolContext,\n toolCtx: RunContext,\n): Promise<{ rawMessages: import(\"../state\").WithParts[] }> {\n await toolCtx.ask({\n permission: \"compress\",\n patterns: [\"*\"],\n always: [\"*\"],\n metadata: {},\n })\n\n toolCtx.metadata({ title: \"Decompress\" })\n\n const rawMessages = await fetchSessionMessages(ctx.client, toolCtx.sessionID)\n\n await ensureSessionInitialized(\n ctx.client,\n ctx.state,\n toolCtx.sessionID,\n ctx.logger,\n rawMessages,\n ctx.config.manualMode.enabled,\n )\n\n assignMessageRefs(ctx.state, rawMessages)\n\n return { rawMessages }\n}\n\nasync function finalizeDecompressSession(\n ctx: ToolContext,\n): Promise<void> {\n await saveSessionState(ctx.state, ctx.logger)\n}\n\nconst TOOL_DESCRIPTION = `Restores previously compressed content identified by a block ID.\n\nUse this tool when you need exact details from a compressed block that the summary cannot provide.\nThe tool returns a condensed preview of the restored content so you can reason about it immediately.\n\nArgument: blockId — the block reference to decompress (e.g., \"b0\", \"b2\")\n\nIMPORTANT:\n- Decompressing inflates context. Check context usage before decompressing.\n- Message-mode blocks from the same batch (same runId) are restored together.\n- After decompression, the restored messages will appear in full in your next context window.\n- Do NOT call this tool in parallel with compress — their state mutations may conflict.`\n\nfunction buildSchema() {\n return {\n blockId: tool.schema\n .string()\n .describe('Block reference to decompress (e.g., \"b0\", \"b2\")'),\n }\n}\n\nexport function createDecompressTool(ctx: ToolContext): ReturnType<typeof tool> {\n return tool({\n description: TOOL_DESCRIPTION,\n args: buildSchema(),\n async execute(args, toolCtx) {\n const { rawMessages } = await prepareDecompressSession(ctx, toolCtx)\n\n const contextUsageBefore = ctx.state.modelContextLimit\n ? Math.round(\n (getCurrentTokenUsage(ctx.state, rawMessages) /\n ctx.state.modelContextLimit) *\n 100,\n )\n : undefined\n\n const targetBlockId = parseBlockIdArg(args.blockId as string)\n if (targetBlockId === null) {\n return `Error: Invalid block ID \"${args.blockId}\". Use format \"b0\", \"b1\", etc.`\n }\n\n const messagesState = ctx.state.prune.messages\n\n const target = resolveCompressionTarget(messagesState, targetBlockId)\n if (!target) {\n return `Error: Block ${targetBlockId} does not exist. No compression found with that ID.`\n }\n\n const activeBlocks = target.blocks.filter((block) => block.active)\n if (activeBlocks.length === 0) {\n const activeAncestorBlockId = findActiveAncestorBlockId(messagesState, target)\n if (activeAncestorBlockId !== null) {\n return `Error: Block ${target.displayId} is nested inside active block ${activeAncestorBlockId}. Decompress block ${activeAncestorBlockId} first.`\n }\n return `Error: Block ${target.displayId} is not active. It may have already been decompressed.`\n }\n\n const activeMessagesBefore = snapshotActiveMessages(messagesState)\n const activeBlockIdsBefore = new Set(messagesState.activeBlockIds)\n\n deactivateCompressionTarget(messagesState, target)\n\n syncCompressionBlocks(ctx.state, ctx.logger, rawMessages)\n\n const { restoredMessageCount, restoredTokens } = computeRestoredMessages(\n messagesState,\n activeMessagesBefore,\n )\n const reactivatedBlockIds = computeReactivatedBlockIds(\n messagesState,\n activeBlockIdsBefore,\n )\n\n ctx.state.stats.totalPruneTokens = Math.max(\n 0,\n ctx.state.stats.totalPruneTokens - restoredTokens,\n )\n\n const contextUsageAfter = ctx.state.modelContextLimit\n ? Math.round(\n (getCurrentTokenUsage(ctx.state, rawMessages) /\n ctx.state.modelContextLimit) *\n 100,\n )\n : undefined\n\n await finalizeDecompressSession(ctx)\n\n const restoredContentPreview = buildRestoredContentPreview(\n rawMessages,\n activeMessagesBefore,\n messagesState,\n )\n\n const lines: string[] = []\n lines.push(\n `Decompressed block b${target.displayId}. Restored ${restoredMessageCount} message(s) (~${formatTokenCount(restoredTokens)}).`,\n )\n\n if (contextUsageBefore !== undefined && contextUsageAfter !== undefined) {\n lines.push(`Context usage: ${contextUsageBefore}% → ${contextUsageAfter}%.`)\n }\n\n if (reactivatedBlockIds.length > 0) {\n const refs = reactivatedBlockIds.map((id) => `b${id}`).join(\", \")\n lines.push(`Also restored nested block(s): ${refs}.`)\n }\n\n if (restoredContentPreview) {\n lines.push(\"\")\n lines.push(\"RESTORED CONTENT (condensed):\")\n lines.push(restoredContentPreview)\n }\n\n ctx.logger.info(\"Decompress tool completed\", {\n targetBlockId: target.displayId,\n targetRunId: target.runId,\n restoredMessageCount,\n restoredTokens,\n reactivatedBlockIds,\n })\n\n return lines.join(\"\\n\")\n },\n })\n}\n","import { createHash } from \"node:crypto\"\nimport type { SessionState, WithParts } from \"../state\"\nimport { isMessageCompacted } from \"../state/utils\"\nimport type { UserMessage } from \"@opencode-ai/sdk/v2\"\n\nconst SUMMARY_ID_HASH_LENGTH = 16\n\n// [FIX Bug 36] Delimiters wrapping a compression summary when it is merged into\n// an existing user message. The header embeds the block id so multiple blocks\n// landing on the same user message each get their own clearly delimited entry,\n// and so the prepend is idempotent across re-runs (guarded by the marker check).\nconst MERGED_SUMMARY_HEADER = (blockId: number | string) =>\n `[ACP compressed context summary (block ${blockId}) — prior conversation recap]\\n`\nconst MERGED_SUMMARY_FOOTER = `\\n[End ACP compressed context summary]\\n\\n`\nconst DCP_BLOCK_ID_TAG_REGEX = /(<dcp-message-id(?=[\\s>])[^>]*>)b\\d+(<\\/dcp-message-id>)/g\n// [FIX Bug 28] Regex to strip stale mNNNN refs from compressed summaries\nconst DCP_MESSAGE_REF_TAG_REGEX = /<dcp-message-id>m\\d+<\\/dcp-message-id>/g\nconst DCP_PAIRED_TAG_REGEX = /<dcp[^>]*>[\\s\\S]*?<\\/dcp[^>]*>/gi\nconst DCP_UNPAIRED_TAG_REGEX = /<\\/?dcp[^>]*>/gi\n\nconst generateStableId = (prefix: string, seed: string): string => {\n const hash = createHash(\"sha256\").update(seed).digest(\"hex\").slice(0, SUMMARY_ID_HASH_LENGTH)\n return `${prefix}_${hash}`\n}\n\nexport const createSyntheticUserMessage = (\n baseMessage: WithParts,\n content: string,\n stableSeed?: string,\n): WithParts => {\n const userInfo = baseMessage.info as UserMessage\n const now = Date.now()\n const deterministicSeed = stableSeed?.trim() || userInfo.id\n const messageId = generateStableId(\"msg_dcp_summary\", deterministicSeed)\n const partId = generateStableId(\"prt_dcp_summary\", deterministicSeed)\n\n return {\n info: {\n id: messageId,\n sessionID: userInfo.sessionID,\n role: \"user\" as const,\n agent: userInfo.agent,\n model: userInfo.model,\n time: { created: now },\n },\n parts: [\n {\n id: partId,\n sessionID: userInfo.sessionID,\n messageID: messageId,\n type: \"text\" as const,\n text: content,\n },\n ],\n }\n}\n\n// [FIX Bug 36] Merge a compression summary into an existing user message by\n// prepending it (clearly delimited) to that message's first text part. This\n// avoids emitting a standalone user-role summary message adjacent to the user's\n// real turn, which previously produced two consecutive user messages and caused\n// dialog role confusion / \"self-Q&A\" loops. Returns true when the summary is\n// present after the call — including the idempotent case where the block's\n// marker is already in the text (no-op), matching appendToTextPart so callers\n// never fall through to a standalone message merely because of a re-run.\nexport const prependCompressionSummary = (\n message: WithParts,\n summary: string,\n blockId: number | string,\n): boolean => {\n const parts = Array.isArray(message.parts) ? message.parts : []\n const header = MERGED_SUMMARY_HEADER(blockId)\n const marker = MERGED_SUMMARY_HEADER(blockId).trimEnd()\n\n for (const part of parts) {\n if (part.type !== \"text\") {\n continue\n }\n const textPart = part as TextPart\n const existing = typeof textPart.text === \"string\" ? textPart.text : \"\"\n if (existing.includes(marker)) {\n return true\n }\n textPart.text = `${header}${summary}${MERGED_SUMMARY_FOOTER}${existing}`\n return true\n }\n\n const sessionID = (message.info as { sessionID?: string }).sessionID ?? \"\"\n const messageId = (message.info as { id: string }).id\n parts.unshift({\n id: generateStableId(\"prt_dcp_prepend\", `${blockId}:${messageId}`),\n sessionID,\n messageID: messageId,\n type: \"text\" as const,\n text: `${header}${summary}${MERGED_SUMMARY_FOOTER}`,\n })\n message.parts = parts\n return true\n}\n\nexport const createSyntheticTextPart = (\n baseMessage: WithParts,\n content: string,\n stableSeed?: string,\n) => {\n const userInfo = baseMessage.info as UserMessage\n const deterministicSeed = stableSeed?.trim() || userInfo.id\n const partId = generateStableId(\"prt_dcp_text\", deterministicSeed)\n\n return {\n id: partId,\n sessionID: userInfo.sessionID,\n messageID: userInfo.id,\n type: \"text\" as const,\n text: content,\n }\n}\n\ntype MessagePart = WithParts[\"parts\"][number]\ntype ToolPart = Extract<MessagePart, { type: \"tool\" }>\ntype TextPart = Extract<MessagePart, { type: \"text\" }>\n\nexport const appendToLastTextPart = (message: WithParts, injection: string): boolean => {\n const textPart = findLastTextPart(message)\n if (!textPart) {\n return false\n }\n\n return appendToTextPart(textPart, injection)\n}\n\nconst findLastTextPart = (message: WithParts): TextPart | null => {\n for (let i = message.parts.length - 1; i >= 0; i--) {\n const part = message.parts[i]\n if (part.type === \"text\") {\n return part\n }\n }\n\n return null\n}\n\nexport const appendToTextPart = (part: TextPart, injection: string): boolean => {\n if (typeof part.text !== \"string\") {\n return false\n }\n\n const normalizedInjection = injection.replace(/^\\n+/, \"\")\n if (!normalizedInjection.trim()) {\n return false\n }\n if (part.text.includes(normalizedInjection)) {\n return true\n }\n\n const baseText = part.text.replace(/\\n*$/, \"\")\n part.text = baseText.length > 0 ? `${baseText}\\n\\n${normalizedInjection}` : normalizedInjection\n return true\n}\n\nexport const appendToAllToolParts = (message: WithParts, tag: string): boolean => {\n let injected = false\n for (const part of message.parts) {\n if (part.type === \"tool\") {\n injected = appendToToolPart(part, tag) || injected\n }\n }\n return injected\n}\n\nexport const appendToToolPart = (part: ToolPart, tag: string): boolean => {\n if (part.state?.status !== \"completed\" || typeof part.state.output !== \"string\") {\n return false\n }\n if (part.state.output.includes(tag)) {\n return true\n }\n\n part.state.output = `${part.state.output}${tag}`\n return true\n}\n\nexport const hasContent = (message: WithParts): boolean => {\n return message.parts.some(\n (part) =>\n (part.type === \"text\" &&\n typeof part.text === \"string\" &&\n part.text.trim().length > 0) ||\n (part.type === \"tool\" &&\n part.state?.status === \"completed\" &&\n typeof part.state.output === \"string\"),\n )\n}\n\nexport function buildToolIdList(state: SessionState, messages: WithParts[]): string[] {\n const toolIds: string[] = []\n for (const msg of messages) {\n if (isMessageCompacted(state, msg)) {\n continue\n }\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n if (parts.length > 0) {\n for (const part of parts) {\n if (part.type === \"tool\" && part.callID && part.tool) {\n toolIds.push(part.callID)\n }\n }\n }\n }\n state.toolIdList = toolIds\n return toolIds\n}\n\nexport const replaceBlockIdsWithBlocked = (text: string): string => {\n return text.replace(DCP_BLOCK_ID_TAG_REGEX, \"$1BLOCKED$2\")\n}\n\n// [FIX Bug 28] Strip stale mNNNN refs from compressed summaries before injection\nexport const stripStaleMessageRefs = (text: string): string => {\n return text.replace(DCP_MESSAGE_REF_TAG_REGEX, \"\")\n}\n\nexport const stripHallucinationsFromString = (text: string): string => {\n return text.replace(DCP_PAIRED_TAG_REGEX, \"\").replace(DCP_UNPAIRED_TAG_REGEX, \"\")\n}\n\nexport const stripHallucinations = (messages: WithParts[]): void => {\n for (const message of messages) {\n for (const part of message.parts) {\n if (part.type === \"text\" && typeof part.text === \"string\") {\n part.text = stripHallucinationsFromString(part.text)\n }\n\n if (\n part.type === \"tool\" &&\n part.state?.status === \"completed\" &&\n typeof part.state.output === \"string\"\n ) {\n part.state.output = stripHallucinationsFromString(part.state.output)\n }\n }\n }\n}\n","import type { SessionState, WithParts } from \"../state\"\nimport type { Logger } from \"../logger\"\nimport type { PluginConfig } from \"../config\"\nimport { isMessageCompacted } from \"../state/utils\"\nimport { createSyntheticUserMessage, prependCompressionSummary, replaceBlockIdsWithBlocked, stripStaleMessageRefs } from \"./utils\"\nimport { getLastUserMessage } from \"./query\"\nimport type { UserMessage } from \"@opencode-ai/sdk/v2\"\n\nconst PRUNED_TOOL_OUTPUT_REPLACEMENT =\n \"[Output removed to save context - information superseded or no longer needed]\"\nconst PRUNED_TOOL_ERROR_INPUT_REPLACEMENT = \"[input removed due to failed tool call]\"\nconst PRUNED_QUESTION_INPUT_REPLACEMENT = \"[questions removed - see output for user's answers]\"\n\nexport const prune = (\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n messages: WithParts[],\n): void => {\n filterCompressedRanges(state, logger, config, messages)\n // pruneFullTool(state, logger, messages)\n pruneToolOutputs(state, logger, messages)\n pruneToolInputs(state, logger, messages)\n pruneToolErrors(state, logger, messages)\n}\n\nconst pruneFullTool = (state: SessionState, logger: Logger, messages: WithParts[]): void => {\n const messagesToRemove: string[] = []\n\n for (const msg of messages) {\n if (isMessageCompacted(state, msg)) {\n continue\n }\n\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n const partsToRemove: string[] = []\n\n for (const part of parts) {\n if (part.type !== \"tool\") {\n continue\n }\n\n if (!state.prune.tools.has(part.callID)) {\n continue\n }\n if (part.tool !== \"edit\" && part.tool !== \"write\") {\n continue\n }\n\n partsToRemove.push(part.callID)\n }\n\n if (partsToRemove.length === 0) {\n continue\n }\n\n msg.parts = parts.filter(\n (part) => part.type !== \"tool\" || !partsToRemove.includes(part.callID),\n )\n\n if (msg.parts.length === 0) {\n messagesToRemove.push(msg.info.id)\n }\n }\n\n if (messagesToRemove.length > 0) {\n const result = messages.filter((msg) => !messagesToRemove.includes(msg.info.id))\n messages.length = 0\n messages.push(...result)\n }\n}\n\nconst pruneToolOutputs = (state: SessionState, logger: Logger, messages: WithParts[]): void => {\n for (const msg of messages) {\n if (isMessageCompacted(state, msg)) {\n continue\n }\n\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type !== \"tool\") {\n continue\n }\n if (!state.prune.tools.has(part.callID)) {\n continue\n }\n if (part.state.status !== \"completed\") {\n continue\n }\n if (part.tool === \"question\" || part.tool === \"edit\" || part.tool === \"write\") {\n continue\n }\n\n part.state.output = PRUNED_TOOL_OUTPUT_REPLACEMENT\n }\n }\n}\n\nconst pruneToolInputs = (state: SessionState, logger: Logger, messages: WithParts[]): void => {\n for (const msg of messages) {\n if (isMessageCompacted(state, msg)) {\n continue\n }\n\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type !== \"tool\") {\n continue\n }\n\n if (!state.prune.tools.has(part.callID)) {\n continue\n }\n if (part.state.status !== \"completed\") {\n continue\n }\n if (part.tool !== \"question\") {\n continue\n }\n\n if (part.state.input?.questions !== undefined) {\n part.state.input.questions = PRUNED_QUESTION_INPUT_REPLACEMENT\n }\n }\n }\n}\n\nconst pruneToolErrors = (state: SessionState, logger: Logger, messages: WithParts[]): void => {\n for (const msg of messages) {\n if (isMessageCompacted(state, msg)) {\n continue\n }\n\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type !== \"tool\") {\n continue\n }\n if (!state.prune.tools.has(part.callID)) {\n continue\n }\n if (part.state.status !== \"error\") {\n continue\n }\n\n // Prune all string inputs for errored tools\n const input = part.state.input\n if (input && typeof input === \"object\") {\n for (const key of Object.keys(input)) {\n if (typeof input[key] === \"string\") {\n input[key] = PRUNED_TOOL_ERROR_INPUT_REPLACEMENT\n }\n }\n }\n }\n }\n}\n\nconst filterCompressedRanges = (\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n messages: WithParts[],\n): void => {\n if (\n state.prune.messages.byMessageId.size === 0 &&\n state.prune.messages.activeByAnchorMessageId.size === 0\n ) {\n return\n }\n\n const result: WithParts[] = []\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i]!\n const msgId = msg.info.id\n\n // Check if there's a summary to inject at this anchor point\n const blockId = state.prune.messages.activeByAnchorMessageId.get(msgId)\n const summary =\n blockId !== undefined ? state.prune.messages.blocksById.get(blockId) : undefined\n if (summary) {\n const rawSummaryContent = (summary as { summary?: unknown }).summary\n if (\n summary.active !== true ||\n typeof rawSummaryContent !== \"string\" ||\n rawSummaryContent.length === 0\n ) {\n logger.warn(\"Skipping malformed compress summary\", {\n anchorMessageId: msgId,\n blockId: (summary as { blockId?: unknown }).blockId,\n })\n } else {\n // [FIX Bug 28] Strip stale mNNNN refs before injection\n const _cleaned = stripStaleMessageRefs(rawSummaryContent)\n const summaryContent =\n config.compress.mode === \"message\"\n ? replaceBlockIdsWithBlocked(_cleaned)\n : _cleaned\n\n // [FIX Bug 36] When the next surviving message is a user turn, merge the\n // summary into it instead of emitting a standalone user-role summary\n // message. The old behavior placed a synthetic user message immediately\n // before the user's real turn ([summary(user), user(user)]), which the\n // model often read as two user turns — misattributing the assistant's\n // prior output to the user and triggering \"self-Q&A\" loops. Merging\n // yields a single user turn ([user: recap ‖ real reply]) so no fake\n // conversational turn is perceived.\n const nextSurviving = findNextSurvivingMessage(messages, i, state)\n const merged =\n nextSurviving !== null &&\n nextSurviving.info.role === \"user\" &&\n prependCompressionSummary(nextSurviving, summaryContent, summary.blockId)\n\n if (merged) {\n logger.info(\"Merged compress summary into following user message\", {\n anchorMessageId: msgId,\n targetMessageId: nextSurviving!.info.id,\n summaryLength: summaryContent.length,\n })\n } else {\n // [FIX Bug 1] fallback when no suitable user message to merge into:\n // emit a standalone synthetic user message (prior behavior).\n const userMessage = getLastUserMessage(messages, i)\n const summarySeed = `${summary.blockId}:${summary.anchorMessageId}`\n if (userMessage) {\n result.push(\n createSyntheticUserMessage(userMessage, summaryContent, summarySeed),\n )\n\n logger.info(\"Injected compress summary\", {\n anchorMessageId: msgId,\n summaryLength: summaryContent.length,\n })\n } else {\n const anchorInfo = msg.info as any\n const fallbackBase: WithParts = {\n info: {\n id: anchorInfo.id || msgId,\n sessionID: anchorInfo.sessionID || \"\",\n role: \"user\" as const,\n agent: anchorInfo.agent || \"code\",\n model:\n anchorInfo.model || {\n providerID: \"\",\n modelID: \"\",\n variant: undefined,\n },\n time: { created: anchorInfo.time?.created || Date.now() },\n },\n parts: [],\n }\n result.push(\n createSyntheticUserMessage(fallbackBase, summaryContent, summarySeed),\n )\n\n logger.info(\"Injected compress summary (fallback, no preceding user message)\", {\n anchorMessageId: msgId,\n summaryLength: summaryContent.length,\n })\n }\n }\n }\n }\n\n // Skip messages that are in the prune list\n const pruneEntry = state.prune.messages.byMessageId.get(msgId)\n if (pruneEntry && pruneEntry.activeBlockIds.length > 0) {\n continue\n }\n\n // Normal message, include it\n result.push(msg)\n }\n\n // Replace messages array contents\n messages.length = 0\n messages.push(...result)\n}\n\n// [FIX Bug 36] First surviving (non-pruned) message at or after startIndex.\n// Starts the scan at startIndex inclusive to handle both anchor layouts: when\n// the anchor is itself part of the pruned range (message-start ranges) it is\n// skipped, and when the anchor survives (block-anchor ranges) it is returned —\n// in either case this yields the next real turn the model sees after the recap.\nconst findNextSurvivingMessage = (\n messages: WithParts[],\n startIndex: number,\n state: SessionState,\n): WithParts | null => {\n for (let j = startIndex; j < messages.length; j++) {\n const candidate = messages[j]!\n const entry = state.prune.messages.byMessageId.get(candidate.info.id)\n if (entry && entry.activeBlockIds.length > 0) {\n continue\n }\n return candidate\n }\n return null\n}\n","import type { SessionState, WithParts } from \"../state\"\nimport type { Logger } from \"../logger\"\n\nfunction sortBlocksByCreation(\n a: { createdAt: number; blockId: number },\n b: { createdAt: number; blockId: number },\n): number {\n const createdAtDiff = a.createdAt - b.createdAt\n if (createdAtDiff !== 0) {\n return createdAtDiff\n }\n return a.blockId - b.blockId\n}\n\nexport const syncCompressionBlocks = (\n state: SessionState,\n logger: Logger,\n messages: WithParts[],\n): void => {\n const messagesState = state.prune.messages\n if (!messagesState?.blocksById?.size) {\n return\n }\n\n const messageIds = new Set(messages.map((msg) => msg.info.id))\n const previousActiveBlockIds = new Set<number>(\n Array.from(messagesState.blocksById.values())\n .filter((block) => block.active)\n .map((block) => block.blockId),\n )\n\n messagesState.activeBlockIds.clear()\n messagesState.activeByAnchorMessageId.clear()\n\n const now = Date.now()\n const missingOriginBlockIds: number[] = []\n const orderedBlocks = Array.from(messagesState.blocksById.values()).sort(sortBlocksByCreation)\n\n // [PATCH Bug 3] Removed compressMessageId presence check.\n // Blocks should remain active even if the compress tool call message was\n // removed by opencode's internal compaction. The block's existence IS proof\n // that compression happened.\n for (const block of orderedBlocks) {\n if (block.deactivatedByUser) {\n block.active = false\n if (block.deactivatedAt === undefined) {\n block.deactivatedAt = now\n }\n block.deactivatedByBlockId = undefined\n continue\n }\n\n // Only deactivate if anchor message is completely gone from both current messages AND DCP tracked messages\n if (\n typeof block.anchorMessageId === \"string\" &&\n block.anchorMessageId.length > 0 &&\n !messageIds.has(block.anchorMessageId)\n ) {\n // If anchor exists in DCP's byMessageId (persisted), keep block active\n if (!messagesState.byMessageId.has(block.anchorMessageId)) {\n block.active = false\n block.deactivatedAt = now\n block.deactivatedByBlockId = undefined\n continue\n }\n }\n\n for (const consumedBlockId of block.consumedBlockIds) {\n if (!messagesState.activeBlockIds.has(consumedBlockId)) {\n continue\n }\n\n const consumedBlock = messagesState.blocksById.get(consumedBlockId)\n if (consumedBlock) {\n consumedBlock.active = false\n consumedBlock.deactivatedAt = now\n consumedBlock.deactivatedByBlockId = block.blockId\n\n const mappedBlockId = messagesState.activeByAnchorMessageId.get(\n consumedBlock.anchorMessageId,\n )\n if (mappedBlockId === consumedBlock.blockId) {\n messagesState.activeByAnchorMessageId.delete(consumedBlock.anchorMessageId)\n }\n }\n\n messagesState.activeBlockIds.delete(consumedBlockId)\n }\n\n block.active = true\n block.deactivatedAt = undefined\n block.deactivatedByBlockId = undefined\n messagesState.activeBlockIds.add(block.blockId)\n if (messageIds.has(block.anchorMessageId)) {\n messagesState.activeByAnchorMessageId.set(block.anchorMessageId, block.blockId)\n }\n }\n\n for (const entry of messagesState.byMessageId.values()) {\n const allBlockIds = Array.isArray(entry.allBlockIds)\n ? [...new Set(entry.allBlockIds.filter((id) => Number.isInteger(id) && id > 0))]\n : []\n\n entry.allBlockIds = allBlockIds\n entry.activeBlockIds = allBlockIds.filter((id) => messagesState.activeBlockIds.has(id))\n }\n\n const nextActiveBlockIds = messagesState.activeBlockIds\n let deactivatedCount = 0\n let reactivatedCount = 0\n\n for (const blockId of previousActiveBlockIds) {\n if (!nextActiveBlockIds.has(blockId)) {\n deactivatedCount++\n }\n }\n for (const blockId of nextActiveBlockIds) {\n if (!previousActiveBlockIds.has(blockId)) {\n reactivatedCount++\n }\n }\n\n if (missingOriginBlockIds.length > 0 || deactivatedCount > 0 || reactivatedCount > 0) {\n logger.info(\"Synced compress block state\", {\n missingOriginCount: missingOriginBlockIds.length,\n deactivatedCount,\n reactivatedCount,\n })\n }\n}\n","export type PermissionAction = \"ask\" | \"allow\" | \"deny\"\n\nexport type PermissionValue = PermissionAction | Record<string, PermissionAction>\n\nexport type PermissionConfig = Record<string, PermissionValue> | undefined\n\nexport interface HostPermissionSnapshot {\n global: PermissionConfig\n agents: Record<string, PermissionConfig>\n}\n\ntype PermissionRule = {\n permission: string\n pattern: string\n action: PermissionAction\n}\n\nconst findLastMatchingRule = (\n rules: PermissionRule[],\n predicate: (rule: PermissionRule) => boolean,\n): PermissionRule | undefined => {\n for (let index = rules.length - 1; index >= 0; index -= 1) {\n const rule = rules[index]\n if (rule && predicate(rule)) {\n return rule\n }\n }\n\n return undefined\n}\n\nconst wildcardMatch = (value: string, pattern: string): boolean => {\n const normalizedValue = value.replaceAll(\"\\\\\", \"/\")\n let escaped = pattern\n .replaceAll(\"\\\\\", \"/\")\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*/g, \".*\")\n .replace(/\\?/g, \".\")\n\n if (escaped.endsWith(\" .*\")) {\n escaped = escaped.slice(0, -3) + \"( .*)?\"\n }\n\n const flags = process.platform === \"win32\" ? \"si\" : \"s\"\n return new RegExp(`^${escaped}$`, flags).test(normalizedValue)\n}\n\nconst getPermissionRules = (permissionConfigs: PermissionConfig[]): PermissionRule[] => {\n const rules: PermissionRule[] = []\n for (const permissionConfig of permissionConfigs) {\n if (!permissionConfig) {\n continue\n }\n\n for (const [permission, value] of Object.entries(permissionConfig)) {\n if (value === \"ask\" || value === \"allow\" || value === \"deny\") {\n rules.push({ permission, pattern: \"*\", action: value })\n continue\n }\n\n for (const [pattern, action] of Object.entries(value)) {\n if (action === \"ask\" || action === \"allow\" || action === \"deny\") {\n rules.push({ permission, pattern, action })\n }\n }\n }\n }\n return rules\n}\n\nexport const compressDisabledByOpencode = (...permissionConfigs: PermissionConfig[]): boolean => {\n const match = findLastMatchingRule(getPermissionRules(permissionConfigs), (rule) =>\n wildcardMatch(\"compress\", rule.permission),\n )\n\n return match?.pattern === \"*\" && match.action === \"deny\"\n}\n\nexport const resolveEffectiveCompressPermission = (\n basePermission: PermissionAction,\n hostPermissions: HostPermissionSnapshot,\n agentName?: string,\n): PermissionAction => {\n if (basePermission === \"deny\") {\n return \"deny\"\n }\n\n return compressDisabledByOpencode(\n hostPermissions.global,\n agentName ? hostPermissions.agents[agentName] : undefined,\n )\n ? \"deny\"\n : basePermission\n}\n\nexport const hasExplicitToolPermission = (\n permissionConfig: PermissionConfig,\n tool: string,\n): boolean => {\n return permissionConfig ? Object.prototype.hasOwnProperty.call(permissionConfig, tool) : false\n}\n","import type { PluginConfig } from \"./config\"\nimport { type HostPermissionSnapshot, resolveEffectiveCompressPermission } from \"./host-permissions\"\nimport type { SessionState, WithParts } from \"./state\"\nimport { getLastUserMessage } from \"./messages/query\"\n\nexport const compressPermission = (\n state: SessionState,\n config: PluginConfig,\n): \"ask\" | \"allow\" | \"deny\" => {\n return state.compressPermission ?? config.compress.permission\n}\n\nexport const syncCompressPermissionState = (\n state: SessionState,\n config: PluginConfig,\n hostPermissions: HostPermissionSnapshot,\n messages: WithParts[],\n): void => {\n const activeAgent = getLastUserMessage(messages)?.info.agent\n state.compressPermission = resolveEffectiveCompressPermission(\n config.compress.permission,\n hostPermissions,\n activeAgent,\n )\n}\n","import type { SessionState, CompressionBlock } from \"../../state\"\nimport type { GCConfig } from \"../../config\"\n\nexport interface BlockGuidanceContext {\n currentTokens?: number\n modelContextLimit?: number\n}\n\nexport function buildCompressedBlockGuidance(\n state: SessionState,\n gcConfig?: GCConfig,\n context?: BlockGuidanceContext,\n): string {\n const activeBlockIds = Array.from(state.prune.messages.activeBlockIds)\n .filter((id) => Number.isInteger(id) && id > 0)\n .sort((a, b) => a - b)\n\n const refs = activeBlockIds.map((id) => `b${id}`)\n const blockCount = refs.length\n const blockList = blockCount > 0 ? refs.join(\", \") : \"none\"\n\n const lines = [\n \"Compressed block context:\",\n `- Active compressed blocks: ${blockCount} (${blockList})`,\n \"- If your selected compression range includes any listed block, include each required placeholder exactly once in the summary using `(bN)`.\",\n ]\n\n // [FIX Bug 35] Only show aging warnings when context usage is above 50%.\n // Showing warnings at low usage causes unnecessary compress operations that\n // waste tokens and attention — the model preemptively re-summarizes blocks\n // that aren't actually at risk of GC truncation.\n const usageRatio =\n context?.currentTokens && context?.modelContextLimit\n ? context.currentTokens / context.modelContextLimit\n : 0\n\n if (gcConfig && usageRatio > 0.5) {\n const promotionThreshold = gcConfig.promotionThreshold\n const agingBlocks: string[] = []\n\n for (const blockId of activeBlockIds) {\n const block = state.prune.messages.blocksById.get(blockId)\n if (!block) continue\n\n const survived = block.survivedCount ?? 0\n const gen = block.generation ?? \"young\"\n const sizeK = (block.summary.length / 1000).toFixed(1)\n const preview = block.summary.slice(0, 120).replace(/\\n/g, \" \")\n\n if (gen === \"old\" || survived >= promotionThreshold - 2) {\n agingBlocks.push(\n ` b${blockId}: age=${survived}/${promotionThreshold}, gen=${gen}, size=${sizeK}K chars — ${preview}...`,\n )\n }\n }\n\n if (agingBlocks.length > 0) {\n lines.push(\"\")\n lines.push(\"⚠️ Block aging warning — these blocks may be truncated by GC soon:\")\n lines.push(...agingBlocks)\n lines.push(\n \"To preserve important content: use the compress tool to re-summarize these blocks into new concise ones. Unhandled blocks will be auto-truncated.\",\n )\n }\n }\n\n return lines.join(\"\\n\")\n}\n\nexport function renderMessagePriorityGuidance(priorityLabel: string, refs: string[]): string {\n const refList = refs.length > 0 ? refs.join(\", \") : \"none\"\n\n return [\n \"Message priority context:\",\n \"- Higher-priority older messages consume more context and should be compressed right away if it is safe to do so.\",\n `- ${priorityLabel}-priority message IDs before this point: ${refList}`,\n ].join(\"\\n\")\n}\n\nexport function appendGuidanceToDcpTag(nudgeText: string, guidance: string): string {\n if (!guidance.trim()) {\n return nudgeText\n }\n\n const closeTag = \"</dcp-system-reminder>\"\n const closeTagIndex = nudgeText.lastIndexOf(closeTag)\n\n if (closeTagIndex === -1) {\n return nudgeText\n }\n\n const beforeClose = nudgeText.slice(0, closeTagIndex).trimEnd()\n const afterClose = nudgeText.slice(closeTagIndex)\n return `${beforeClose}\\n\\n${guidance}\\n${afterClose}`\n}\n","import type { PluginConfig } from \"../config\"\nimport { countAllMessageTokens } from \"../token-utils\"\nimport { isMessageCompacted } from \"../state/utils\"\nimport type { SessionState, WithParts } from \"../state\"\nimport { isIgnoredUserMessage, isProtectedUserMessage, messageHasCompress } from \"./query\"\n\nconst MEDIUM_PRIORITY_MIN_TOKENS = 500\nconst HIGH_PRIORITY_MIN_TOKENS = 5000\n\nexport type MessagePriority = \"low\" | \"medium\" | \"high\"\n\nexport interface CompressionPriorityEntry {\n ref: string\n tokenCount: number\n priority: MessagePriority\n}\n\nexport type CompressionPriorityMap = Map<string, CompressionPriorityEntry>\n\nexport function buildPriorityMap(\n config: PluginConfig,\n state: SessionState,\n messages: WithParts[],\n): CompressionPriorityMap {\n if (config.compress.mode !== \"message\") {\n return new Map()\n }\n const priorities: CompressionPriorityMap = new Map()\n\n for (const message of messages) {\n if (isIgnoredUserMessage(message)) {\n continue\n }\n\n if (isProtectedUserMessage(config, message)) {\n continue\n }\n\n if (isMessageCompacted(state, message)) {\n continue\n }\n\n const rawMessageId = message.info.id\n if (typeof rawMessageId !== \"string\" || rawMessageId.length === 0) {\n continue\n }\n\n const ref = state.messageIds.byRawId.get(rawMessageId)\n if (!ref) {\n continue\n }\n\n const tokenCount = countAllMessageTokens(message)\n priorities.set(rawMessageId, {\n ref,\n tokenCount,\n priority: messageHasCompress(message) ? \"high\" : classifyMessagePriority(tokenCount),\n })\n }\n\n return priorities\n}\n\nexport function classifyMessagePriority(tokenCount: number): MessagePriority {\n if (tokenCount >= HIGH_PRIORITY_MIN_TOKENS) {\n return \"high\"\n }\n\n if (tokenCount >= MEDIUM_PRIORITY_MIN_TOKENS) {\n return \"medium\"\n }\n\n return \"low\"\n}\n\nexport function listPriorityRefsBeforeIndex(\n messages: WithParts[],\n priorities: CompressionPriorityMap,\n anchorIndex: number,\n priority: MessagePriority,\n): string[] {\n const refs: string[] = []\n const seen = new Set<string>()\n const upperBound = Math.max(0, Math.min(anchorIndex, messages.length))\n\n for (let index = 0; index < upperBound; index++) {\n const rawMessageId = messages[index]?.info.id\n if (typeof rawMessageId !== \"string\") {\n continue\n }\n\n const entry = priorities.get(rawMessageId)\n if (!entry || entry.priority !== priority || seen.has(entry.ref)) {\n continue\n }\n\n seen.add(entry.ref)\n refs.push(entry.ref)\n }\n\n return refs\n}\n","import type { SessionState, WithParts } from \"../../state\"\nimport type { PluginConfig } from \"../../config\"\nimport {\n appendGuidanceToDcpTag,\n buildCompressedBlockGuidance,\n renderMessagePriorityGuidance,\n} from \"../../prompts/extensions/nudge\"\nimport type { RuntimePrompts } from \"../../prompts/store\"\nimport type { UserMessage } from \"@opencode-ai/sdk/v2\"\nimport {\n type CompressionPriorityMap,\n type MessagePriority,\n listPriorityRefsBeforeIndex,\n} from \"../priority\"\nimport {\n appendToTextPart,\n appendToLastTextPart,\n createSyntheticTextPart,\n hasContent,\n} from \"../utils\"\nimport { getLastUserMessage, isIgnoredUserMessage, isSyntheticMessage } from \"../query\"\nimport { getCurrentTokenUsage } from \"../../token-utils\"\nimport { getActiveSummaryTokenUsage } from \"../../state/utils\"\n\nconst MESSAGE_MODE_NUDGE_PRIORITY: MessagePriority = \"high\"\n\nexport interface LastUserModelContext {\n providerId: string | undefined\n modelId: string | undefined\n}\n\nexport interface LastNonIgnoredMessage {\n message: WithParts\n index: number\n}\n\ninterface ModelLimit {\n context: number\n input?: number\n output?: number\n}\n\nexport function computeInputBudget(limit: ModelLimit): number | undefined {\n if (!limit.context) {\n return undefined\n }\n\n return limit.input ?? Math.max(0, limit.context - (limit.output ?? 0))\n}\n\nexport function getNudgeFrequency(config: PluginConfig): number {\n return Math.max(1, Math.floor(config.compress.nudgeFrequency || 1))\n}\n\nexport function getIterationNudgeThreshold(config: PluginConfig): number {\n return Math.max(1, Math.floor(config.compress.iterationNudgeThreshold || 1))\n}\n\nexport function findLastNonIgnoredMessage(messages: WithParts[]): LastNonIgnoredMessage | null {\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i]\n if (isIgnoredUserMessage(message)) {\n continue\n }\n if (isSyntheticMessage(message)) {\n continue\n }\n return { message, index: i }\n }\n\n return null\n}\n\nexport function countMessagesAfterIndex(messages: WithParts[], index: number): number {\n let count = 0\n\n for (let i = index + 1; i < messages.length; i++) {\n const message = messages[i]\n if (isIgnoredUserMessage(message)) {\n continue\n }\n count++\n }\n\n return count\n}\n\nexport function getModelInfo(messages: WithParts[]): LastUserModelContext {\n const lastUserMessage = getLastUserMessage(messages)\n if (!lastUserMessage) {\n return {\n providerId: undefined,\n modelId: undefined,\n }\n }\n\n const userInfo = lastUserMessage.info as UserMessage\n return {\n providerId: userInfo.model.providerID,\n modelId: userInfo.model.modelID,\n }\n}\n\nfunction resolveContextTokenLimit(\n config: PluginConfig,\n state: SessionState,\n providerId: string | undefined,\n modelId: string | undefined,\n threshold: \"max\" | \"min\",\n): number | undefined {\n const parseLimitValue = (limit: number | `${number}%` | undefined): number | undefined => {\n if (limit === undefined) {\n return undefined\n }\n\n if (typeof limit === \"number\") {\n return limit\n }\n\n if (!limit.endsWith(\"%\") || state.modelContextLimit === undefined) {\n return undefined\n }\n\n const parsedPercent = parseFloat(limit.slice(0, -1))\n if (isNaN(parsedPercent)) {\n return undefined\n }\n\n const roundedPercent = Math.round(parsedPercent)\n const clampedPercent = Math.max(0, Math.min(100, roundedPercent))\n return Math.round((clampedPercent / 100) * state.modelContextLimit)\n }\n\n const modelLimits =\n threshold === \"max\" ? config.compress.modelMaxLimits : config.compress.modelMinLimits\n if (modelLimits && providerId !== undefined && modelId !== undefined) {\n const providerModelId = `${providerId}/${modelId}`\n const modelLimit = modelLimits[providerModelId]\n if (modelLimit !== undefined) {\n return parseLimitValue(modelLimit)\n }\n }\n\n const globalLimit =\n threshold === \"max\" ? config.compress.maxContextLimit : config.compress.minContextLimit\n return parseLimitValue(globalLimit)\n}\n\nexport function isContextOverLimits(\n config: PluginConfig,\n state: SessionState,\n providerId: string | undefined,\n modelId: string | undefined,\n messages: WithParts[],\n) {\n const summaryTokenExtension = config.compress.summaryBuffer\n ? getActiveSummaryTokenUsage(state)\n : 0\n const resolvedMaxContextLimit = resolveContextTokenLimit(\n config,\n state,\n providerId,\n modelId,\n \"max\",\n )\n const maxContextLimit =\n resolvedMaxContextLimit === undefined\n ? undefined\n : resolvedMaxContextLimit + summaryTokenExtension\n const minContextLimit = resolveContextTokenLimit(config, state, providerId, modelId, \"min\")\n const currentTokens = getCurrentTokenUsage(state, messages)\n\n let overMaxLimit = maxContextLimit === undefined ? false : currentTokens > maxContextLimit\n const overMinLimit = minContextLimit === undefined ? false : currentTokens >= minContextLimit\n\n // [FIX Bug 20] Suppress overMax while cacheRead hasn't updated after compress\n if (overMaxLimit) {\n const recentCompressCount = 3\n const recentMessages = messages.slice(-recentCompressCount)\n for (const msg of recentMessages) {\n if (msg.info.role === \"assistant\" && msg.parts) {\n for (const part of msg.parts) {\n if ((part as any).type === \"tool-invocation\" && (part as any).toolInvocation?.toolName === \"compress\") {\n overMaxLimit = false\n break\n }\n }\n }\n if (!overMaxLimit) break\n }\n }\n\n return {\n overMaxLimit,\n overMinLimit,\n currentTokens,\n modelContextLimit: state.modelContextLimit,\n }\n}\n\nexport function addAnchor(\n anchorMessageIds: Set<string>,\n anchorMessageId: string,\n anchorMessageIndex: number,\n messages: WithParts[],\n interval: number,\n): boolean {\n if (anchorMessageIndex < 0) {\n return false\n }\n\n let latestAnchorMessageIndex = -1\n for (let i = messages.length - 1; i >= 0; i--) {\n if (anchorMessageIds.has(messages[i].info.id)) {\n latestAnchorMessageIndex = i\n break\n }\n }\n\n const shouldAdd =\n latestAnchorMessageIndex < 0 || anchorMessageIndex - latestAnchorMessageIndex >= interval\n if (!shouldAdd) {\n return false\n }\n\n const previousSize = anchorMessageIds.size\n anchorMessageIds.add(anchorMessageId)\n return anchorMessageIds.size !== previousSize\n}\n\nfunction buildMessagePriorityGuidance(\n messages: WithParts[],\n compressionPriorities: CompressionPriorityMap | undefined,\n anchorIndex: number,\n priority: MessagePriority,\n): string {\n if (!compressionPriorities || compressionPriorities.size === 0) {\n return \"\"\n }\n\n const refs = listPriorityRefsBeforeIndex(messages, compressionPriorities, anchorIndex, priority)\n const priorityLabel = `${priority[0].toUpperCase()}${priority.slice(1)}`\n\n return renderMessagePriorityGuidance(priorityLabel, refs)\n}\n\nfunction injectAnchoredNudge(message: WithParts, nudgeText: string): void {\n if (!nudgeText.trim()) {\n return\n }\n\n if (message.info.role === \"user\") {\n if (appendToLastTextPart(message, nudgeText)) {\n return\n }\n\n message.parts.push(createSyntheticTextPart(message, nudgeText))\n return\n }\n\n if (message.info.role !== \"assistant\") {\n return\n }\n\n if (!hasContent(message)) {\n return\n }\n\n for (const part of message.parts) {\n if (part.type === \"text\") {\n if (appendToTextPart(part, nudgeText)) {\n return\n }\n }\n }\n\n const syntheticPart = createSyntheticTextPart(message, nudgeText)\n const firstToolIndex = message.parts.findIndex((p) => p.type === \"tool\")\n if (firstToolIndex === -1) {\n message.parts.push(syntheticPart)\n } else {\n message.parts.splice(firstToolIndex, 0, syntheticPart)\n }\n}\n\nfunction collectAnchoredMessages(\n anchorMessageIds: Set<string>,\n messages: WithParts[],\n): Array<{ message: WithParts; index: number }> {\n const anchoredMessages: Array<{ message: WithParts; index: number }> = []\n\n for (const anchorMessageId of anchorMessageIds) {\n const index = messages.findIndex((message) => message.info.id === anchorMessageId)\n if (index === -1) {\n continue\n }\n\n anchoredMessages.push({\n message: messages[index],\n index,\n })\n }\n\n return anchoredMessages\n}\n\nfunction collectTurnNudgeAnchors(\n state: SessionState,\n config: PluginConfig,\n messages: WithParts[],\n): Set<string> {\n const turnNudgeAnchors = new Set<string>()\n const targetRole = config.compress.nudgeForce === \"strong\" ? \"user\" : \"assistant\"\n\n for (const message of messages) {\n if (!state.nudges.turnNudgeAnchors.has(message.info.id)) continue\n\n if (message.info.role === targetRole) {\n turnNudgeAnchors.add(message.info.id)\n }\n }\n\n return turnNudgeAnchors\n}\n\nfunction applyRangeModeAnchoredNudge(\n anchorMessageIds: Set<string>,\n messages: WithParts[],\n baseNudgeText: string,\n compressedBlockGuidance: string,\n): void {\n const nudgeText = appendGuidanceToDcpTag(baseNudgeText, compressedBlockGuidance)\n if (!nudgeText.trim()) {\n return\n }\n\n for (const { message } of collectAnchoredMessages(anchorMessageIds, messages)) {\n injectAnchoredNudge(message, nudgeText)\n }\n}\n\nfunction applyMessageModeAnchoredNudge(\n anchorMessageIds: Set<string>,\n messages: WithParts[],\n baseNudgeText: string,\n compressionPriorities?: CompressionPriorityMap,\n): void {\n for (const { message, index } of collectAnchoredMessages(anchorMessageIds, messages)) {\n const priorityGuidance = buildMessagePriorityGuidance(\n messages,\n compressionPriorities,\n index,\n MESSAGE_MODE_NUDGE_PRIORITY,\n )\n const nudgeText = appendGuidanceToDcpTag(baseNudgeText, priorityGuidance)\n injectAnchoredNudge(message, nudgeText)\n }\n}\n\n/**\n * Resolve a config threshold (number | \"NN%\") to a percentage value.\n */\nfunction resolveThresholdPercent(\n threshold: number | `${number}%` | undefined,\n modelContextLimit: number | undefined,\n): number | undefined {\n if (threshold === undefined) return undefined\n if (typeof threshold === \"number\") {\n if (!modelContextLimit) return undefined\n return (threshold / modelContextLimit) * 100\n }\n const parsed = parseFloat(threshold)\n return isNaN(parsed) ? undefined : parsed\n}\n\n/**\n * Build tiered context usage guidance based on actual config thresholds.\n * Shared by inject.ts (suffix message) and utils.ts (anchored nudges).\n */\nexport function buildContextUsageGuidance(\n config: PluginConfig,\n currentTokens?: number,\n modelContextLimit?: number,\n): string {\n if (currentTokens === undefined || modelContextLimit === undefined || modelContextLimit === 0) {\n return \"\"\n }\n\n const pct = (currentTokens / modelContextLimit) * 100\n const percentage = pct.toFixed(1)\n const formatK = (n: number) => (n >= 1000 ? `${(n / 1000).toFixed(1)}K` : String(n))\n\n const minPct = resolveThresholdPercent(config.compress.minContextLimit, modelContextLimit) ?? 45\n const maxPct = resolveThresholdPercent(config.compress.maxContextLimit, modelContextLimit) ?? 55\n\n const base = `Context usage: ${formatK(currentTokens)} / ${formatK(modelContextLimit)} tokens (${percentage}%). ACP threshold: ${maxPct.toFixed(0)}%.`\n\n let guidance: string\n if (pct < minPct) {\n guidance = \" Context is ample — focus on your task. Only compress obvious waste (large terminal outputs, duplicated content).\"\n } else if (pct < maxPct) {\n guidance = \" Context is moderate — compress completed sections and high-token waste. Preserve key details.\"\n } else {\n guidance = \" Context is high — compress aggressively but selectively. Preserve only what is essential.\"\n }\n\n return `\\n\\n${base}${guidance}`\n}\n\nexport function applyAnchoredNudges(\n state: SessionState,\n config: PluginConfig,\n messages: WithParts[],\n prompts: RuntimePrompts,\n compressionPriorities?: CompressionPriorityMap,\n currentTokens?: number,\n modelContextLimit?: number,\n suffixMessage?: WithParts | null,\n): void {\n const contextUsageInfo = buildContextUsageGuidance(config, currentTokens, modelContextLimit)\n const contextLimitNudgeWithUsage = prompts.contextLimitNudge + contextUsageInfo\n const turnNudgeAnchors = collectTurnNudgeAnchors(state, config, messages)\n\n if (suffixMessage) {\n const nudgeParts: string[] = []\n\n if (config.compress.mode === \"message\") {\n if (state.nudges.contextLimitAnchors.size > 0) {\n for (const { index } of collectAnchoredMessages(state.nudges.contextLimitAnchors, messages)) {\n const guidance = buildMessagePriorityGuidance(messages, compressionPriorities, index, MESSAGE_MODE_NUDGE_PRIORITY)\n nudgeParts.push(appendGuidanceToDcpTag(contextLimitNudgeWithUsage, guidance))\n }\n }\n if (turnNudgeAnchors.size > 0) {\n for (const { index } of collectAnchoredMessages(turnNudgeAnchors, messages)) {\n const guidance = buildMessagePriorityGuidance(messages, compressionPriorities, index, MESSAGE_MODE_NUDGE_PRIORITY)\n nudgeParts.push(appendGuidanceToDcpTag(prompts.turnNudge, guidance))\n }\n }\n if (state.nudges.iterationNudgeAnchors.size > 0) {\n for (const { index } of collectAnchoredMessages(state.nudges.iterationNudgeAnchors, messages)) {\n const guidance = buildMessagePriorityGuidance(messages, compressionPriorities, index, MESSAGE_MODE_NUDGE_PRIORITY)\n nudgeParts.push(appendGuidanceToDcpTag(prompts.iterationNudge, guidance))\n }\n }\n } else {\n if (state.nudges.contextLimitAnchors.size > 0) {\n nudgeParts.push(contextLimitNudgeWithUsage)\n }\n if (turnNudgeAnchors.size > 0) {\n nudgeParts.push(prompts.turnNudge)\n }\n if (state.nudges.iterationNudgeAnchors.size > 0) {\n nudgeParts.push(prompts.iterationNudge)\n }\n }\n\n const combined = nudgeParts.join(\"\\n\\n\")\n if (combined.trim()) {\n injectAnchoredNudge(suffixMessage, combined)\n }\n return\n }\n\n if (config.compress.mode === \"message\") {\n applyMessageModeAnchoredNudge(\n state.nudges.contextLimitAnchors,\n messages,\n contextLimitNudgeWithUsage,\n compressionPriorities,\n )\n applyMessageModeAnchoredNudge(\n turnNudgeAnchors,\n messages,\n prompts.turnNudge,\n compressionPriorities,\n )\n applyMessageModeAnchoredNudge(\n state.nudges.iterationNudgeAnchors,\n messages,\n prompts.iterationNudge,\n compressionPriorities,\n )\n return\n }\n\n applyRangeModeAnchoredNudge(\n state.nudges.contextLimitAnchors,\n messages,\n contextLimitNudgeWithUsage,\n \"\",\n )\n applyRangeModeAnchoredNudge(\n turnNudgeAnchors,\n messages,\n prompts.turnNudge,\n \"\",\n )\n applyRangeModeAnchoredNudge(\n state.nudges.iterationNudgeAnchors,\n messages,\n prompts.iterationNudge,\n \"\",\n )\n}\n","import type { SessionState, WithParts } from \"../../state\"\nimport type { Logger } from \"../../logger\"\nimport type { PluginConfig } from \"../../config\"\nimport type { RuntimePrompts } from \"../../prompts/store\"\nimport { formatMessageIdTag } from \"../../message-ids\"\nimport type { CompressionPriorityMap } from \"../priority\"\nimport { compressPermission } from \"../../compress-permission\"\nimport {\n getLastUserMessage,\n isIgnoredUserMessage,\n isProtectedUserMessage,\n messageHasCompress,\n} from \"../query\"\nimport { saveSessionState } from \"../../state/persistence\"\nimport {\n appendToTextPart,\n appendToLastTextPart,\n appendToAllToolParts,\n createSyntheticTextPart,\n createSyntheticUserMessage,\n hasContent,\n} from \"../utils\"\nimport {\n addAnchor,\n applyAnchoredNudges,\n buildContextUsageGuidance,\n countMessagesAfterIndex,\n findLastNonIgnoredMessage,\n getIterationNudgeThreshold,\n getNudgeFrequency,\n getModelInfo,\n isContextOverLimits,\n} from \"./utils\"\nimport { buildCompressedBlockGuidance } from \"../../prompts/extensions/nudge\"\n\n/**\n * Stable seed for the ACP dynamic guidance suffix message.\n * Using a fixed seed ensures the synthetic message ID is deterministic,\n * so it won't be assigned a new mNNNNN ref on each transform call.\n */\nconst ACP_SUFFIX_SEED = \"acp-dynamic-guidance\"\n\n/**\n * Create a synthetic user message at the END of the messages array.\n * All per-turn dynamic ACP content (context usage, visible IDs, nudges, etc.)\n * is injected into this suffix message instead of historical user messages,\n * preserving OpenAI Responses prefix cache stability.\n */\nfunction createSuffixMessage(messages: WithParts[]): WithParts | null {\n if (messages.length === 0) return null\n // Use any user message as base for session/agent/model info\n const base = messages.find((m) => m.info.role === \"user\") || messages[messages.length - 1]\n const synthetic = createSyntheticUserMessage(base, \"\", ACP_SUFFIX_SEED)\n messages.push(synthetic)\n return synthetic\n}\n\nexport const injectCompressNudges = (\n state: SessionState,\n config: PluginConfig,\n logger: Logger,\n messages: WithParts[],\n prompts: RuntimePrompts,\n compressionPriorities?: CompressionPriorityMap,\n): void => {\n if (compressPermission(state, config) === \"deny\") {\n return\n }\n\n if (state.manualMode) {\n return\n }\n\n const lastMessage = findLastNonIgnoredMessage(messages)\n const lastAssistantMessage = messages.findLast((message) => message.info.role === \"assistant\")\n\n if (lastAssistantMessage && messageHasCompress(lastAssistantMessage)) {\n state.nudges.contextLimitAnchors.clear()\n state.nudges.turnNudgeAnchors.clear()\n state.nudges.iterationNudgeAnchors.clear()\n void saveSessionState(state, logger)\n return\n }\n\n const { providerId, modelId } = getModelInfo(messages)\n let anchorsChanged = false\n\n const { overMaxLimit, overMinLimit, currentTokens, modelContextLimit } = isContextOverLimits(\n config,\n state,\n providerId,\n modelId,\n messages,\n )\n\n if (!overMinLimit) {\n const hadTurnAnchors = state.nudges.turnNudgeAnchors.size > 0\n const hadIterationAnchors = state.nudges.iterationNudgeAnchors.size > 0\n\n if (hadTurnAnchors || hadIterationAnchors) {\n state.nudges.turnNudgeAnchors.clear()\n state.nudges.iterationNudgeAnchors.clear()\n anchorsChanged = true\n }\n }\n\n if (overMaxLimit) {\n if (lastMessage) {\n const interval = getNudgeFrequency(config)\n const added = addAnchor(\n state.nudges.contextLimitAnchors,\n lastMessage.message.info.id,\n lastMessage.index,\n messages,\n interval,\n )\n if (added) {\n anchorsChanged = true\n }\n }\n } else if (overMinLimit) {\n const isLastMessageUser = lastMessage?.message.info.role === \"user\"\n\n if (isLastMessageUser && lastAssistantMessage) {\n const previousSize = state.nudges.turnNudgeAnchors.size\n state.nudges.turnNudgeAnchors.add(lastMessage.message.info.id)\n state.nudges.turnNudgeAnchors.add(lastAssistantMessage.info.id)\n if (state.nudges.turnNudgeAnchors.size !== previousSize) {\n anchorsChanged = true\n }\n }\n\n const lastUserMessage = getLastUserMessage(messages)\n if (lastUserMessage && lastMessage) {\n const lastUserMessageIndex = messages.findIndex(\n (message) => message.info.id === lastUserMessage.info.id,\n )\n if (lastUserMessageIndex >= 0) {\n const messagesSinceUser = countMessagesAfterIndex(messages, lastUserMessageIndex)\n const iterationThreshold = getIterationNudgeThreshold(config)\n\n if (\n lastMessage.index > lastUserMessageIndex &&\n messagesSinceUser >= iterationThreshold\n ) {\n const interval = getNudgeFrequency(config)\n const added = addAnchor(\n state.nudges.iterationNudgeAnchors,\n lastMessage.message.info.id,\n lastMessage.index,\n messages,\n interval,\n )\n\n if (added) {\n anchorsChanged = true\n }\n }\n }\n }\n }\n\n const suffixMessage = createSuffixMessage(messages)\n\n applyAnchoredNudges(state, config, messages, prompts, compressionPriorities, currentTokens, modelContextLimit, suffixMessage)\n\n injectContextUsage(suffixMessage, config, currentTokens, modelContextLimit)\n\n if (config.compress.mode !== \"message\") {\n const blockGuidance = buildCompressedBlockGuidance(state, config.gc, { currentTokens, modelContextLimit })\n if (blockGuidance.trim() && suffixMessage) {\n appendToLastTextPart(suffixMessage, \"\\n\\n\" + blockGuidance)\n }\n }\n\n injectVisibleIdRange(state, messages, suffixMessage)\n\n if (anchorsChanged) {\n void saveSessionState(state, logger)\n }\n}\n\nfunction injectContextUsage(\n target: WithParts | null,\n config: PluginConfig,\n currentTokens?: number,\n modelContextLimit?: number,\n): void {\n if (!target) return\n const usageTag = buildContextUsageGuidance(config, currentTokens, modelContextLimit)\n if (!usageTag) return\n\n for (const part of target.parts) {\n if (part.type === \"text\") {\n appendToTextPart(part, usageTag)\n return\n }\n }\n target.parts.push(createSyntheticTextPart(target, usageTag))\n}\n\nfunction injectVisibleIdRange(state: SessionState, messages: WithParts[], target: WithParts | null): void {\n if (!target) return\n const visibleRefs: string[] = []\n for (const message of messages) {\n const ref = state.messageIds.byRawId.get(message.info.id)\n if (ref) {\n visibleRefs.push(ref)\n }\n }\n\n if (visibleRefs.length === 0) return\n\n visibleRefs.sort()\n const first = visibleRefs[0]\n const last = visibleRefs[visibleRefs.length - 1]\n const rangeTag = `\\n\\n[Visible message IDs: ${first} to ${last} (${visibleRefs.length} messages). Only use IDs in this range for compress.]`\n\n for (const part of target.parts) {\n if (part.type === \"text\") {\n appendToTextPart(part, rangeTag)\n return\n }\n }\n target.parts.push(createSyntheticTextPart(target, rangeTag))\n}\n\nexport const injectMessageIds = (\n state: SessionState,\n config: PluginConfig,\n messages: WithParts[],\n compressionPriorities?: CompressionPriorityMap,\n): void => {\n if (compressPermission(state, config) === \"deny\") {\n return\n }\n\n for (const message of messages) {\n if (isIgnoredUserMessage(message)) {\n continue\n }\n\n const messageRef = state.messageIds.byRawId.get(message.info.id)\n if (!messageRef) {\n continue\n }\n\n const isBlockedMessage = isProtectedUserMessage(config, message)\n const priority =\n config.compress.mode === \"message\" && !isBlockedMessage\n ? compressionPriorities?.get(message.info.id)?.priority\n : undefined\n const tag = formatMessageIdTag(\n isBlockedMessage ? \"BLOCKED\" : messageRef,\n priority ? { priority } : undefined,\n )\n\n if (message.info.role === \"user\") {\n let injected = false\n for (const part of message.parts) {\n if (part.type === \"text\") {\n injected = appendToTextPart(part, tag) || injected\n }\n }\n\n if (injected) {\n continue\n }\n\n message.parts.push(createSyntheticTextPart(message, tag))\n continue\n }\n\n if (message.info.role !== \"assistant\") {\n continue\n }\n\n if (!hasContent(message)) {\n continue\n }\n\n if (appendToAllToolParts(message, tag)) {\n continue\n }\n\n if (appendToLastTextPart(message, tag)) {\n continue\n }\n\n const syntheticPart = createSyntheticTextPart(message, tag)\n const firstToolIndex = message.parts.findIndex((p) => p.type === \"tool\")\n if (firstToolIndex === -1) {\n message.parts.push(syntheticPart)\n } else {\n message.parts.splice(firstToolIndex, 0, syntheticPart)\n }\n }\n}\n","import type { Logger } from \"../../logger\"\nimport type { SessionState, WithParts } from \"../../state\"\nimport { filterMessages } from \"../shape\"\nimport {\n buildSubagentResultText,\n getSubAgentId,\n mergeSubagentResult,\n} from \"../../subagents/subagent-results\"\nimport { stripHallucinationsFromString } from \"../utils\"\n\nasync function fetchSubAgentMessages(client: any, sessionId: string): Promise<WithParts[]> {\n const response = await client.session.messages({\n path: { id: sessionId },\n })\n\n return filterMessages(response?.data || response)\n}\n\nexport const injectExtendedSubAgentResults = async (\n client: any,\n state: SessionState,\n logger: Logger,\n messages: WithParts[],\n allowSubAgents: boolean,\n): Promise<void> => {\n if (!allowSubAgents) {\n return\n }\n\n for (const message of messages) {\n const parts = Array.isArray(message.parts) ? message.parts : []\n\n for (const part of parts) {\n if (part.type !== \"tool\" || part.tool !== \"task\" || !part.callID) {\n continue\n }\n if (state.prune.tools.has(part.callID)) {\n continue\n }\n if (part.state?.status !== \"completed\" || typeof part.state.output !== \"string\") {\n continue\n }\n\n const cachedResult = state.subAgentResultCache.get(part.callID)\n if (cachedResult !== undefined) {\n if (cachedResult) {\n part.state.output = stripHallucinationsFromString(\n mergeSubagentResult(part.state.output, cachedResult),\n )\n }\n continue\n }\n\n const subAgentSessionId = getSubAgentId(part)\n if (!subAgentSessionId) {\n continue\n }\n\n let subAgentMessages: WithParts[] = []\n try {\n subAgentMessages = await fetchSubAgentMessages(client, subAgentSessionId)\n } catch (error) {\n logger.warn(\"Failed to fetch subagent session for output expansion\", {\n subAgentSessionId,\n callID: part.callID,\n error: error instanceof Error ? error.message : String(error),\n })\n continue\n }\n\n const subAgentResultText = buildSubagentResultText(subAgentMessages)\n if (!subAgentResultText) {\n continue\n }\n\n state.subAgentResultCache.set(part.callID, subAgentResultText)\n part.state.output = stripHallucinationsFromString(\n mergeSubagentResult(part.state.output, subAgentResultText),\n )\n }\n }\n}\n","import type { WithParts } from \"../state\"\nimport { getLastUserMessage } from \"./query\"\n\n/**\n * Mirrors opencode's differentModel handling by preserving part content while\n * dropping provider metadata on assistant parts that came from a different\n * model/provider than the current turn's user message.\n */\nexport function stripStaleMetadata(messages: WithParts[]): void {\n const lastUserMessage = getLastUserMessage(messages)\n if (lastUserMessage?.info.role !== \"user\") {\n return\n }\n\n const modelID = lastUserMessage.info.model.modelID\n const providerID = lastUserMessage.info.model.providerID\n\n messages.forEach((message) => {\n if (message.info.role !== \"assistant\") {\n return\n }\n\n // [FIX Bug 8] Guard against undefined modelID/providerID\n const msgModelID = (message.info as any).modelID\n const msgProviderID = (message.info as any).providerID\n if (msgModelID === modelID && msgProviderID === providerID) {\n return\n }\n\n message.parts = message.parts.map((part) => {\n if (part.type !== \"text\" && part.type !== \"tool\" && part.type !== \"reasoning\") {\n return part\n }\n\n if (!(\"metadata\" in part)) {\n return part\n }\n\n const { metadata: _metadata, ...rest } = part\n return rest\n })\n })\n}\n","import type { CompressionBlock, PruneMessagesState } from \"../state\"\n\nexport interface CompressionTarget {\n displayId: number\n runId: number\n topic: string\n compressedTokens: number\n durationMs: number\n grouped: boolean\n blocks: CompressionBlock[]\n}\n\nfunction byBlockId(a: CompressionBlock, b: CompressionBlock): number {\n return a.blockId - b.blockId\n}\n\nfunction buildTarget(blocks: CompressionBlock[]): CompressionTarget {\n const ordered = [...blocks].sort(byBlockId)\n const first = ordered[0]\n if (!first) {\n throw new Error(\"Cannot build compression target from empty block list.\")\n }\n\n const grouped = first.mode === \"message\"\n return {\n displayId: first.blockId,\n runId: first.runId,\n topic: grouped ? first.batchTopic || first.topic : first.topic,\n compressedTokens: ordered.reduce((total, block) => total + block.compressedTokens, 0),\n durationMs: ordered.reduce((total, block) => Math.max(total, block.durationMs), 0),\n grouped,\n blocks: ordered,\n }\n}\n\nfunction groupMessageBlocks(blocks: CompressionBlock[]): CompressionTarget[] {\n const grouped = new Map<number, CompressionBlock[]>()\n\n for (const block of blocks) {\n const existing = grouped.get(block.runId)\n if (existing) {\n existing.push(block)\n continue\n }\n grouped.set(block.runId, [block])\n }\n\n return Array.from(grouped.values()).map(buildTarget)\n}\n\nfunction splitTargets(blocks: CompressionBlock[]): CompressionTarget[] {\n const messageBlocks: CompressionBlock[] = []\n const singleBlocks: CompressionBlock[] = []\n\n for (const block of blocks) {\n if (block.mode === \"message\") {\n messageBlocks.push(block)\n } else {\n singleBlocks.push(block)\n }\n }\n\n const targets = [\n ...singleBlocks.map((block) => buildTarget([block])),\n ...groupMessageBlocks(messageBlocks),\n ]\n return targets.sort((a, b) => a.displayId - b.displayId)\n}\n\nexport function getActiveCompressionTargets(\n messagesState: PruneMessagesState,\n): CompressionTarget[] {\n const activeBlocks = Array.from(messagesState.activeBlockIds)\n .map((blockId) => messagesState.blocksById.get(blockId))\n .filter((block): block is CompressionBlock => !!block && block.active)\n\n return splitTargets(activeBlocks)\n}\n\nexport function getRecompressibleCompressionTargets(\n messagesState: PruneMessagesState,\n availableMessageIds: Set<string>,\n): CompressionTarget[] {\n const allBlocks = Array.from(messagesState.blocksById.values()).filter((block) => {\n return availableMessageIds.has(block.compressMessageId)\n })\n\n const messageGroups = new Map<number, CompressionBlock[]>()\n const singleTargets: CompressionTarget[] = []\n\n for (const block of allBlocks) {\n if (block.mode === \"message\") {\n const existing = messageGroups.get(block.runId)\n if (existing) {\n existing.push(block)\n } else {\n messageGroups.set(block.runId, [block])\n }\n continue\n }\n\n if (block.deactivatedByUser && !block.active) {\n singleTargets.push(buildTarget([block]))\n }\n }\n\n for (const blocks of messageGroups.values()) {\n if (blocks.some((block) => block.deactivatedByUser && !block.active)) {\n singleTargets.push(buildTarget(blocks))\n }\n }\n\n return singleTargets.sort((a, b) => a.displayId - b.displayId)\n}\n\nexport function resolveCompressionTarget(\n messagesState: PruneMessagesState,\n blockId: number,\n): CompressionTarget | null {\n const block = messagesState.blocksById.get(blockId)\n if (!block) {\n return null\n }\n\n if (block.mode !== \"message\") {\n return buildTarget([block])\n }\n\n const blocks = Array.from(messagesState.blocksById.values()).filter(\n (candidate) => candidate.mode === \"message\" && candidate.runId === block.runId,\n )\n if (blocks.length === 0) {\n return null\n }\n\n return buildTarget(blocks)\n}\n","import type { CompressionBlock, PruneMessagesState, WithParts } from \"../state\"\nimport { parseBlockRef } from \"../message-ids\"\nimport type { CompressionTarget } from \"../commands/compression-targets\"\n\nexport function parseBlockIdArg(arg: string): number | null {\n const normalized = arg.trim().toLowerCase()\n const blockRef = parseBlockRef(normalized)\n if (blockRef !== null) {\n return blockRef\n }\n\n if (!/^[1-9]\\d*$/.test(normalized)) {\n return null\n }\n\n const parsed = Number.parseInt(normalized, 10)\n return Number.isInteger(parsed) && parsed > 0 ? parsed : null\n}\n\nexport function findActiveParentBlockId(\n messagesState: PruneMessagesState,\n block: CompressionBlock,\n): number | null {\n const queue = [...block.parentBlockIds]\n const visited = new Set<number>()\n\n while (queue.length > 0) {\n const parentBlockId = queue.shift()\n if (parentBlockId === undefined || visited.has(parentBlockId)) {\n continue\n }\n visited.add(parentBlockId)\n\n const parent = messagesState.blocksById.get(parentBlockId)\n if (!parent) {\n continue\n }\n\n if (parent.active) {\n return parent.blockId\n }\n\n for (const ancestorId of parent.parentBlockIds) {\n if (!visited.has(ancestorId)) {\n queue.push(ancestorId)\n }\n }\n }\n\n return null\n}\n\nexport function findActiveAncestorBlockId(\n messagesState: PruneMessagesState,\n target: CompressionTarget,\n): number | null {\n for (const block of target.blocks) {\n const activeAncestorBlockId = findActiveParentBlockId(messagesState, block)\n if (activeAncestorBlockId !== null) {\n return activeAncestorBlockId\n }\n }\n\n return null\n}\n\nexport function snapshotActiveMessages(messagesState: PruneMessagesState): Map<string, number> {\n const activeMessages = new Map<string, number>()\n for (const [messageId, entry] of messagesState.byMessageId) {\n if (entry.activeBlockIds.length > 0) {\n activeMessages.set(messageId, entry.tokenCount)\n }\n }\n return activeMessages\n}\n\nexport function deactivateCompressionTarget(\n messagesState: PruneMessagesState,\n target: CompressionTarget,\n): void {\n const deactivatedAt = Date.now()\n\n for (const block of target.blocks) {\n block.active = false\n block.deactivatedByUser = true\n block.deactivatedAt = deactivatedAt\n block.deactivatedByBlockId = undefined\n\n // [FIX Bug 10] Mark consumed inner blocks so syncCompressionBlocks won't re-activate them\n for (const consumedId of block.consumedBlockIds) {\n const consumedBlock = messagesState.blocksById.get(consumedId)\n if (consumedBlock) {\n consumedBlock.deactivatedByUser = true\n }\n }\n }\n}\n\nexport interface RestoredMessagesResult {\n restoredMessageCount: number\n restoredTokens: number\n}\n\nexport function computeRestoredMessages(\n messagesState: PruneMessagesState,\n activeMessagesBefore: Map<string, number>,\n): RestoredMessagesResult {\n let restoredMessageCount = 0\n let restoredTokens = 0\n for (const [messageId, tokenCount] of activeMessagesBefore) {\n const entry = messagesState.byMessageId.get(messageId)\n const isActiveNow = entry ? entry.activeBlockIds.length > 0 : false\n if (!isActiveNow) {\n restoredMessageCount++\n restoredTokens += tokenCount\n }\n }\n return { restoredMessageCount, restoredTokens }\n}\n\nexport function computeReactivatedBlockIds(\n messagesState: PruneMessagesState,\n activeBlockIdsBefore: Set<number>,\n): number[] {\n return Array.from(messagesState.activeBlockIds)\n .filter((blockId) => !activeBlockIdsBefore.has(blockId))\n .sort((a, b) => a - b)\n}\n\nconst MAX_PREVIEW_LENGTH = 2000\nconst MAX_MESSAGE_PREVIEW_LENGTH = 200\n\nexport function buildRestoredContentPreview(\n messages: WithParts[],\n activeMessagesBefore: Map<string, number>,\n messagesState: PruneMessagesState,\n): string {\n const restoredMessages: WithParts[] = []\n for (const msg of messages) {\n const msgId = msg.info.id\n if (activeMessagesBefore.has(msgId)) {\n const entry = messagesState.byMessageId.get(msgId)\n const isActiveNow = entry ? entry.activeBlockIds.length > 0 : false\n if (!isActiveNow) {\n restoredMessages.push(msg)\n }\n }\n }\n\n if (restoredMessages.length === 0) {\n return \"\"\n }\n\n const lines: string[] = []\n let totalLength = 0\n\n for (const msg of restoredMessages) {\n if (totalLength >= MAX_PREVIEW_LENGTH) break\n\n const role = msg.info.role ?? \"unknown\"\n const textContent = extractTextContent(msg)\n const truncated =\n textContent.length > MAX_MESSAGE_PREVIEW_LENGTH\n ? textContent.slice(0, MAX_MESSAGE_PREVIEW_LENGTH) + \"...\"\n : textContent\n\n const line = `[${role}] ${truncated}`\n lines.push(line)\n totalLength += line.length + 1\n }\n\n return lines.join(\"\\n\")\n}\n\nfunction extractTextContent(msg: WithParts): string {\n if (!msg.parts || msg.parts.length === 0) {\n return \"\"\n }\n\n const textParts: string[] = []\n for (const part of msg.parts) {\n if (typeof part === \"object\" && part !== null) {\n if (\"text\" in part && typeof part.text === \"string\") {\n textParts.push(part.text)\n } else if (\"type\" in part && part.type === \"tool\") {\n const toolName = \"tool\" in part && typeof part.tool === \"string\" ? part.tool : \"tool\"\n const state = part.state as Record<string, unknown> | undefined\n if (state && typeof state.output === \"string\") {\n const output =\n state.output.length > 80\n ? state.output.slice(0, 80) + \"...\"\n : state.output\n textParts.push(`[${toolName}] ${output}`)\n }\n }\n }\n }\n\n return textParts.join(\" \").replace(/\\s+/g, \" \").trim()\n}\n","import { tool } from \"@opencode-ai/plugin\"\nimport type { ToolContext } from \"./types\"\nimport { ensureSessionInitialized } from \"../state\"\nimport { saveSessionState } from \"../state/persistence\"\nimport { assignMessageRefs } from \"../message-ids\"\nimport { fetchSessionMessages } from \"./search\"\nimport { formatBlockRef, parseBlockRef } from \"../message-ids\"\n\ninterface RunContext {\n ask(input: {\n permission: string\n patterns: string[]\n always: string[]\n metadata: Record<string, unknown>\n }): Promise<void>\n metadata(input: { title: string }): void\n sessionID: string\n}\n\nasync function prepareMarkSession(\n ctx: ToolContext,\n toolCtx: RunContext,\n): Promise<void> {\n await toolCtx.ask({\n permission: \"compress\",\n patterns: [\"*\"],\n always: [\"*\"],\n metadata: {},\n })\n\n toolCtx.metadata({ title: \"Mark block\" })\n\n const rawMessages = await fetchSessionMessages(ctx.client, toolCtx.sessionID)\n\n await ensureSessionInitialized(\n ctx.client,\n ctx.state,\n toolCtx.sessionID,\n ctx.logger,\n rawMessages,\n ctx.config.manualMode.enabled,\n )\n\n assignMessageRefs(ctx.state, rawMessages)\n}\n\nconst MARK_DESCRIPTION = `Marks a compressed block for batch merge-cleanup.\n\nUse this for blocks whose detailed content you no longer need, but whose summaries\nyou want to keep in context for now (to preserve prompt cache). Marked blocks stay\nfully active with zero immediate effect on context or cache. When context pressure\nrises, all marked blocks are merge-compressed together into a single summary in one\ncache break, instead of being handled one at a time.\n\nArgument: blockId — the block reference to mark (e.g., \"b1\", \"b3\")\n\nUse mark_block instead of compress when you want deferred cleanup: the block keeps\nserving cache hits now and gets consolidated later only if context gets tight.`\n\nconst UNMARK_DESCRIPTION = `Removes the batch cleanup mark from a compressed block.\n\nReverses mark_block. The block returns to normal handling and will not be\nauto-merged during batch cleanup.\n\nArgument: blockId — the block reference to unmark (e.g., \"b1\", \"b3\")`\n\nfunction buildSchema() {\n return {\n blockId: tool.schema\n .string()\n .describe('Block reference to mark (e.g., \"b1\", \"b3\")'),\n }\n}\n\nfunction buildUnmarkSchema() {\n return {\n blockId: tool.schema\n .string()\n .describe('Block reference to unmark (e.g., \"b1\", \"b3\")'),\n }\n}\n\nexport function createMarkBlockTool(ctx: ToolContext): ReturnType<typeof tool> {\n return tool({\n description: MARK_DESCRIPTION,\n args: buildSchema(),\n async execute(args, toolCtx) {\n await prepareMarkSession(ctx, toolCtx)\n\n const targetBlockId = parseBlockRef(String(args.blockId))\n if (targetBlockId === null) {\n return `Error: Invalid block ID \"${args.blockId}\". Use format \"b0\", \"b1\", etc.`\n }\n\n const messagesState = ctx.state.prune.messages\n const block = messagesState.blocksById.get(targetBlockId)\n if (!block) {\n return `Error: Block ${formatBlockRef(targetBlockId)} does not exist.`\n }\n\n if (!block.active) {\n return `Error: Block ${formatBlockRef(targetBlockId)} is not active.`\n }\n\n messagesState.markedForCleanup.add(targetBlockId)\n await saveSessionState(ctx.state, ctx.logger)\n\n const ref = formatBlockRef(targetBlockId)\n const markedCount = messagesState.markedForCleanup.size\n\n ctx.logger.info(\"mark_block: block marked for cleanup\", {\n blockId: targetBlockId,\n markedCount,\n })\n\n return `Block ${ref} marked for cleanup. It will be merge-compressed together with other marked blocks when context pressure rises. No immediate effect on context or cache. (${markedCount} block(s) currently marked.)`\n },\n })\n}\n\nexport function createUnmarkBlockTool(ctx: ToolContext): ReturnType<typeof tool> {\n return tool({\n description: UNMARK_DESCRIPTION,\n args: buildUnmarkSchema(),\n async execute(args, toolCtx) {\n await prepareMarkSession(ctx, toolCtx)\n\n const targetBlockId = parseBlockRef(String(args.blockId))\n if (targetBlockId === null) {\n return `Error: Invalid block ID \"${args.blockId}\". Use format \"b0\", \"b1\", etc.`\n }\n\n const messagesState = ctx.state.prune.messages\n if (!messagesState.markedForCleanup.has(targetBlockId)) {\n return `Block ${formatBlockRef(targetBlockId)} was not marked for cleanup.`\n }\n\n messagesState.markedForCleanup.delete(targetBlockId)\n await saveSessionState(ctx.state, ctx.logger)\n\n ctx.logger.info(\"unmark_block: block unmarked\", {\n blockId: targetBlockId,\n })\n\n return `Block ${formatBlockRef(targetBlockId)} unmarked. It will no longer be auto-merged during batch cleanup.`\n },\n })\n}\n","import { writeFile, mkdir } from \"fs/promises\"\nimport { join } from \"path\"\nimport { existsSync } from \"fs\"\nimport { homedir } from \"os\"\n\nexport class Logger {\n private logDir: string\n public enabled: boolean\n\n constructor(enabled: boolean) {\n this.enabled = enabled\n const configHome = process.env.XDG_CONFIG_HOME || join(homedir(), \".config\")\n this.logDir = join(configHome, \"opencode\", \"logs\", \"acp\")\n }\n\n private async ensureLogDir() {\n if (!existsSync(this.logDir)) {\n await mkdir(this.logDir, { recursive: true })\n }\n }\n\n private formatData(data?: any): string {\n if (!data) return \"\"\n\n const parts: string[] = []\n for (const [key, value] of Object.entries(data)) {\n if (value === undefined || value === null) continue\n\n // Format arrays compactly\n if (Array.isArray(value)) {\n if (value.length === 0) continue\n parts.push(\n `${key}=[${value.slice(0, 3).join(\",\")}${value.length > 3 ? `...+${value.length - 3}` : \"\"}]`,\n )\n } else if (typeof value === \"object\") {\n const str = JSON.stringify(value)\n if (str.length < 50) {\n parts.push(`${key}=${str}`)\n }\n } else {\n parts.push(`${key}=${value}`)\n }\n }\n return parts.join(\" \")\n }\n\n private getCallerFile(skipFrames: number = 3): string {\n const originalPrepareStackTrace = Error.prepareStackTrace\n try {\n const err = new Error()\n Error.prepareStackTrace = (_, stack) => stack\n const stack = err.stack as unknown as NodeJS.CallSite[]\n Error.prepareStackTrace = originalPrepareStackTrace\n\n // Skip specified number of frames to get to actual caller\n for (let i = skipFrames; i < stack.length; i++) {\n const filename = stack[i]?.getFileName()\n if (filename && !filename.includes(\"/logger.\")) {\n // Extract just the filename without path and extension\n const match = filename.match(/([^/\\\\]+)\\.[tj]s$/)\n return match ? match[1] : filename\n }\n }\n return \"unknown\"\n } catch {\n return \"unknown\"\n }\n }\n\n private async write(level: string, component: string, message: string, data?: any) {\n if (!this.enabled) return\n\n try {\n await this.ensureLogDir()\n\n const timestamp = new Date().toISOString()\n const dataStr = this.formatData(data)\n\n const logLine = `${timestamp} ${level.padEnd(5)} ${component}: ${message}${dataStr ? \" | \" + dataStr : \"\"}\\n`\n\n const dailyLogDir = join(this.logDir, \"daily\")\n if (!existsSync(dailyLogDir)) {\n await mkdir(dailyLogDir, { recursive: true })\n }\n\n const logFile = join(dailyLogDir, `${new Date().toISOString().split(\"T\")[0]}.log`)\n await writeFile(logFile, logLine, { flag: \"a\" })\n } catch (error) {}\n }\n\n info(message: string, data?: any) {\n if (!this.enabled) return\n const component = this.getCallerFile(2)\n return this.write(\"INFO\", component, message, data)\n }\n\n debug(message: string, data?: any) {\n if (!this.enabled) return\n const component = this.getCallerFile(2)\n return this.write(\"DEBUG\", component, message, data)\n }\n\n warn(message: string, data?: any) {\n if (!this.enabled) return\n const component = this.getCallerFile(2)\n return this.write(\"WARN\", component, message, data)\n }\n\n error(message: string, data?: any) {\n if (!this.enabled) return\n const component = this.getCallerFile(2)\n return this.write(\"ERROR\", component, message, data)\n }\n\n /**\n * Strips unnecessary metadata from messages for cleaner debug logs.\n *\n * Removed:\n * - All IDs (id, sessionID, messageID, parentID)\n * - summary, path, cost, model, agent, mode, finish, providerID, modelID\n * - step-start and step-finish parts entirely\n * - snapshot fields\n * - ignored text parts\n *\n * Kept:\n * - role, time (created only), tokens (input, output, reasoning, cache)\n * - text, reasoning, tool parts with content\n * - tool calls with: tool, callID, input, output, metadata\n */\n private minimizeForDebug(messages: any[]): any[] {\n return messages.map((msg) => {\n const minimized: any = {\n role: msg.info?.role,\n }\n\n if (msg.info?.time?.created) {\n minimized.time = msg.info.time.created\n }\n\n if (msg.info?.tokens) {\n minimized.tokens = {\n input: msg.info.tokens.input,\n output: msg.info.tokens.output,\n reasoning: msg.info.tokens.reasoning,\n cache: msg.info.tokens.cache,\n }\n }\n\n if (msg.parts) {\n minimized.parts = msg.parts\n .map((part: any) => {\n if (part.type === \"step-start\" || part.type === \"step-finish\") {\n return null\n }\n\n if (part.type === \"text\") {\n if (part.ignored) return null\n const textPart: any = { type: \"text\", text: part.text }\n if (part.metadata) textPart.metadata = part.metadata\n return textPart\n }\n\n if (part.type === \"reasoning\") {\n const reasoningPart: any = { type: \"reasoning\", text: part.text }\n if (part.metadata) reasoningPart.metadata = part.metadata\n return reasoningPart\n }\n\n if (part.type === \"tool\") {\n const toolPart: any = {\n type: \"tool\",\n tool: part.tool,\n callID: part.callID,\n }\n\n if (part.state?.status) {\n toolPart.status = part.state.status\n }\n if (part.state?.input) {\n toolPart.input = part.state.input\n }\n if (part.state?.output) {\n toolPart.output = part.state.output\n }\n if (part.state?.error) {\n toolPart.error = part.state.error\n }\n if (part.metadata) {\n toolPart.metadata = part.metadata\n }\n if (part.state?.metadata) {\n toolPart.metadata = {\n ...(toolPart.metadata || {}),\n ...part.state.metadata,\n }\n }\n if (part.state?.title) {\n toolPart.title = part.state.title\n }\n\n return toolPart\n }\n\n return null\n })\n .filter(Boolean)\n }\n\n return minimized\n })\n }\n\n async saveContext(sessionId: string, messages: any[]) {\n if (!this.enabled) return\n\n try {\n const contextDir = join(this.logDir, \"context\", sessionId)\n if (!existsSync(contextDir)) {\n await mkdir(contextDir, { recursive: true })\n }\n\n const minimized = this.minimizeForDebug(messages).filter(\n (msg) => msg.parts && msg.parts.length > 0,\n )\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\")\n const contextFile = join(contextDir, `${timestamp}.json`)\n await writeFile(contextFile, JSON.stringify(minimized, null, 2))\n } catch (error) {}\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync, statSync, cpSync } from \"fs\"\nimport { join, dirname } from \"path\"\nimport { homedir } from \"os\"\nimport type { Logger } from \"../logger\"\nimport { SYSTEM as SYSTEM_PROMPT } from \"./system\"\nimport { COMPRESS_RANGE as COMPRESS_RANGE_PROMPT } from \"./compress-range\"\nimport { COMPRESS_MESSAGE as COMPRESS_MESSAGE_PROMPT } from \"./compress-message\"\nimport { CONTEXT_LIMIT_NUDGE } from \"./context-limit-nudge\"\nimport { TURN_NUDGE } from \"./turn-nudge\"\nimport { ITERATION_NUDGE } from \"./iteration-nudge\"\nimport { MANUAL_MODE_SYSTEM_EXTENSION, SUBAGENT_SYSTEM_EXTENSION, DECOMPRESS_SYSTEM_EXTENSION } from \"./extensions/system\"\n\nexport type PromptKey =\n | \"system\"\n | \"compress-range\"\n | \"compress-message\"\n | \"context-limit-nudge\"\n | \"turn-nudge\"\n | \"iteration-nudge\"\n\ntype EditablePromptField =\n | \"system\"\n | \"compressRange\"\n | \"compressMessage\"\n | \"contextLimitNudge\"\n | \"turnNudge\"\n | \"iterationNudge\"\n\ninterface PromptDefinition {\n key: PromptKey\n fileName: string\n label: string\n description: string\n usage: string\n runtimeField: EditablePromptField\n}\n\ninterface PromptOverrideCandidate {\n path: string\n}\n\ninterface PromptPaths {\n defaultsDir: string\n globalOverridesDir: string\n configDirOverridesDir: string | null\n projectOverridesDir: string | null\n}\n\nexport interface RuntimePrompts {\n system: string\n compressRange: string\n compressMessage: string\n contextLimitNudge: string\n turnNudge: string\n iterationNudge: string\n manualExtension: string\n subagentExtension: string\n decompressExtension: string\n}\n\nconst PROMPT_DEFINITIONS: PromptDefinition[] = [\n {\n key: \"system\",\n fileName: \"system.md\",\n label: \"System\",\n description: \"Core system-level ACP instruction block\",\n usage: \"Injected into the model system prompt on every request\",\n runtimeField: \"system\",\n },\n {\n key: \"compress-range\",\n fileName: \"compress-range.md\",\n label: \"Compress Range\",\n description: \"range-mode compress tool instructions and summary constraints\",\n usage: \"Registered as the range-mode compress tool description\",\n runtimeField: \"compressRange\",\n },\n {\n key: \"compress-message\",\n fileName: \"compress-message.md\",\n label: \"Compress Message\",\n description: \"message-mode compress tool instructions and summary constraints\",\n usage: \"Registered as the message-mode compress tool description\",\n runtimeField: \"compressMessage\",\n },\n {\n key: \"context-limit-nudge\",\n fileName: \"context-limit-nudge.md\",\n label: \"Context Limit Nudge\",\n description: \"High-priority nudge when context is over max threshold\",\n usage: \"Injected when context usage is beyond configured max limits\",\n runtimeField: \"contextLimitNudge\",\n },\n {\n key: \"turn-nudge\",\n fileName: \"turn-nudge.md\",\n label: \"Turn Nudge\",\n description: \"Nudge to compress closed ranges at turn boundaries\",\n usage: \"Injected when context is between min and max limits at a new user turn\",\n runtimeField: \"turnNudge\",\n },\n {\n key: \"iteration-nudge\",\n fileName: \"iteration-nudge.md\",\n label: \"Iteration Nudge\",\n description: \"Nudge after many iterations without user input\",\n usage: \"Injected when iteration threshold is crossed\",\n runtimeField: \"iterationNudge\",\n },\n]\n\nexport const PROMPT_KEYS: PromptKey[] = [\n \"system\",\n \"compress-range\",\n \"compress-message\",\n \"context-limit-nudge\",\n \"turn-nudge\",\n \"iteration-nudge\",\n]\n\nconst HTML_COMMENT_REGEX = /<!--[\\s\\S]*?-->/g\nconst LEGACY_INLINE_COMMENT_LINE_REGEX = /^[ \\t]*\\/\\/.*?\\/\\/[ \\t]*$/gm\nconst DCP_SYSTEM_REMINDER_TAG_REGEX =\n /^\\s*<dcp-system-reminder\\b[^>]*>[\\s\\S]*<\\/dcp-system-reminder>\\s*$/i\nconst DEFAULTS_README_FILE = \"README.md\"\n\nconst BUNDLED_EDITABLE_PROMPTS: Record<EditablePromptField, string> = {\n system: SYSTEM_PROMPT,\n compressRange: COMPRESS_RANGE_PROMPT,\n compressMessage: COMPRESS_MESSAGE_PROMPT,\n contextLimitNudge: CONTEXT_LIMIT_NUDGE,\n turnNudge: TURN_NUDGE,\n iterationNudge: ITERATION_NUDGE,\n}\n\nconst INTERNAL_PROMPT_EXTENSIONS = {\n manualExtension: MANUAL_MODE_SYSTEM_EXTENSION,\n subagentExtension: SUBAGENT_SYSTEM_EXTENSION,\n decompressExtension: DECOMPRESS_SYSTEM_EXTENSION,\n}\n\nfunction createBundledRuntimePrompts(): RuntimePrompts {\n return {\n system: BUNDLED_EDITABLE_PROMPTS.system,\n compressRange: BUNDLED_EDITABLE_PROMPTS.compressRange,\n compressMessage: BUNDLED_EDITABLE_PROMPTS.compressMessage,\n contextLimitNudge: BUNDLED_EDITABLE_PROMPTS.contextLimitNudge,\n turnNudge: BUNDLED_EDITABLE_PROMPTS.turnNudge,\n iterationNudge: BUNDLED_EDITABLE_PROMPTS.iterationNudge,\n manualExtension: INTERNAL_PROMPT_EXTENSIONS.manualExtension,\n subagentExtension: INTERNAL_PROMPT_EXTENSIONS.subagentExtension,\n decompressExtension: INTERNAL_PROMPT_EXTENSIONS.decompressExtension,\n }\n}\n\nfunction findOpencodeDir(startDir: string): string | null {\n let current = startDir\n while (current !== \"/\") {\n const candidate = join(current, \".opencode\")\n if (existsSync(candidate)) {\n try {\n if (statSync(candidate).isDirectory()) {\n return candidate\n }\n } catch {\n // ignore inaccessible entries while walking upward\n }\n }\n const parent = dirname(current)\n if (parent === current) {\n break\n }\n current = parent\n }\n return null\n}\n\nfunction resolvePromptPaths(workingDirectory: string): PromptPaths {\n const configHome = process.env.XDG_CONFIG_HOME || join(homedir(), \".config\")\n const globalRoot = join(configHome, \"opencode\", \"acp-prompts\")\n const legacyGlobalRoot = join(configHome, \"opencode\", \"dcp-prompts\")\n\n if (!existsSync(globalRoot) && existsSync(legacyGlobalRoot)) {\n try {\n cpSync(legacyGlobalRoot, globalRoot, { recursive: true })\n console.log(\"[ACP] Migrated prompts from dcp-prompts to acp-prompts\")\n } catch (e: any) {\n console.warn(`[ACP] Prompts migration failed: ${e.message}`)\n }\n }\n\n const defaultsDir = join(globalRoot, \"defaults\")\n const globalOverridesDir = join(globalRoot, \"overrides\")\n\n const configDirOverridesDir = process.env.OPENCODE_CONFIG_DIR\n ? join(process.env.OPENCODE_CONFIG_DIR, \"acp-prompts\", \"overrides\")\n : null\n\n const opencodeDir = findOpencodeDir(workingDirectory)\n const projectOverridesDir = opencodeDir ? join(opencodeDir, \"acp-prompts\", \"overrides\") : null\n\n return {\n defaultsDir,\n globalOverridesDir,\n configDirOverridesDir,\n projectOverridesDir,\n }\n}\n\nfunction stripConditionalTag(content: string, tagName: string): string {\n const regex = new RegExp(`<${tagName}>[\\\\s\\\\S]*?<\\/${tagName}>`, \"gi\")\n return content.replace(regex, \"\")\n}\n\nfunction unwrapDcpTagIfWrapped(content: string): string {\n const trimmed = content.trim()\n\n if (DCP_SYSTEM_REMINDER_TAG_REGEX.test(trimmed)) {\n return trimmed\n .replace(/^\\s*<dcp-system-reminder\\b[^>]*>\\s*/i, \"\")\n .replace(/\\s*<\\/dcp-system-reminder>\\s*$/i, \"\")\n .trim()\n }\n\n return trimmed\n}\n\nfunction normalizeReminderPromptContent(content: string): string {\n const normalized = content.trim()\n\n if (!normalized) {\n return \"\"\n }\n\n const startsWrapped = /^\\s*<dcp-system-reminder\\b[^>]*>/i.test(normalized)\n const endsWrapped = /<\\/dcp-system-reminder>\\s*$/i.test(normalized)\n\n if (startsWrapped !== endsWrapped) {\n return \"\"\n }\n\n return unwrapDcpTagIfWrapped(normalized)\n}\n\nfunction stripPromptComments(content: string): string {\n return content\n .replace(/^\\uFEFF/, \"\")\n .replace(/\\r\\n?/g, \"\\n\")\n .replace(HTML_COMMENT_REGEX, \"\")\n .replace(LEGACY_INLINE_COMMENT_LINE_REGEX, \"\")\n}\n\nfunction toEditablePromptText(definition: PromptDefinition, rawContent: string): string {\n let normalized = stripPromptComments(rawContent).trim()\n if (!normalized) {\n return \"\"\n }\n\n if (definition.key === \"system\") {\n normalized = stripConditionalTag(normalized, \"manual\")\n normalized = stripConditionalTag(normalized, \"subagent\")\n }\n\n if (definition.key !== \"compress-range\" && definition.key !== \"compress-message\") {\n normalized = normalizeReminderPromptContent(normalized)\n }\n\n return normalized.trim()\n}\n\nfunction wrapRuntimePromptContent(definition: PromptDefinition, editableText: string): string {\n const trimmed = editableText.trim()\n if (!trimmed) {\n return \"\"\n }\n\n if (definition.key === \"compress-range\" || definition.key === \"compress-message\") {\n return trimmed\n }\n\n return `<dcp-system-reminder>\\n${trimmed}\\n</dcp-system-reminder>`\n}\n\nfunction buildDefaultPromptFileContent(bundledEditableText: string): string {\n return `${bundledEditableText.trim()}\\n`\n}\n\nfunction buildDefaultsReadmeContent(): string {\n const lines: string[] = []\n lines.push(\"# ACP Prompt Defaults\")\n lines.push(\"\")\n lines.push(\"This directory stores the ACP prompts.\")\n lines.push(\"Each prompt file here should contain plain text only (no XML wrappers).\")\n lines.push(\"\")\n lines.push(\"## Creating Overrides\")\n lines.push(\"\")\n lines.push(\n \"1. Copy a prompt file from this directory into an overrides directory using the same filename.\",\n )\n lines.push(\"2. Edit the copied file using plain text.\")\n lines.push(\"3. Restart OpenCode.\")\n lines.push(\"\")\n lines.push(\"To reset an override, delete the matching file from your overrides directory.\")\n lines.push(\"\")\n lines.push(\n \"Do not edit the default prompt files directly, they are just for reference, only files in the overrides directory are used.\",\n )\n lines.push(\"\")\n lines.push(\"Override precedence (highest first):\")\n lines.push(\"1. `.opencode/acp-prompts/overrides/` (project)\")\n lines.push(\"2. `$OPENCODE_CONFIG_DIR/acp-prompts/overrides/` (config dir)\")\n lines.push(\"3. `~/.config/opencode/acp-prompts/overrides/` (global)\")\n lines.push(\"\")\n lines.push(\"## Prompt Files\")\n lines.push(\"\")\n\n for (const definition of PROMPT_DEFINITIONS) {\n lines.push(`- \\`${definition.fileName}\\``)\n lines.push(` - Purpose: ${definition.description}.`)\n lines.push(` - Runtime use: ${definition.usage}.`)\n }\n\n return `${lines.join(\"\\n\")}\\n`\n}\n\nfunction readFileIfExists(filePath: string): string | null {\n if (!existsSync(filePath)) {\n return null\n }\n\n try {\n return readFileSync(filePath, \"utf-8\")\n } catch {\n return null\n }\n}\n\nexport class PromptStore {\n private readonly logger: Logger\n private readonly paths: PromptPaths\n private readonly customPromptsEnabled: boolean\n private runtimePrompts: RuntimePrompts\n\n constructor(logger: Logger, workingDirectory: string, customPromptsEnabled = false) {\n this.logger = logger\n this.paths = resolvePromptPaths(workingDirectory)\n this.customPromptsEnabled = customPromptsEnabled\n this.runtimePrompts = createBundledRuntimePrompts()\n\n if (this.customPromptsEnabled) {\n this.ensureDefaultFiles()\n }\n this.reload()\n }\n\n getRuntimePrompts(): RuntimePrompts {\n return { ...this.runtimePrompts }\n }\n\n reload(): void {\n const nextPrompts = createBundledRuntimePrompts()\n\n if (!this.customPromptsEnabled) {\n this.runtimePrompts = nextPrompts\n return\n }\n\n for (const definition of PROMPT_DEFINITIONS) {\n const bundledSource = BUNDLED_EDITABLE_PROMPTS[definition.runtimeField]\n const bundledEditable = toEditablePromptText(definition, bundledSource)\n const bundledRuntime = wrapRuntimePromptContent(definition, bundledEditable)\n const fallbackValue = bundledRuntime || bundledSource.trim()\n let effectiveValue = fallbackValue\n\n for (const candidate of this.getOverrideCandidates(definition.fileName)) {\n const rawOverride = readFileIfExists(candidate.path)\n if (rawOverride === null) {\n continue\n }\n\n const editableOverride = toEditablePromptText(definition, rawOverride)\n if (!editableOverride) {\n this.logger.warn(\"Prompt override is empty or invalid after normalization\", {\n key: definition.key,\n path: candidate.path,\n })\n continue\n }\n\n const wrappedOverride = wrapRuntimePromptContent(definition, editableOverride)\n if (!wrappedOverride) {\n this.logger.warn(\"Prompt override could not be wrapped for runtime\", {\n key: definition.key,\n path: candidate.path,\n })\n continue\n }\n\n effectiveValue = wrappedOverride\n break\n }\n\n nextPrompts[definition.runtimeField] = effectiveValue\n }\n\n this.runtimePrompts = nextPrompts\n }\n\n private getOverrideCandidates(fileName: string): PromptOverrideCandidate[] {\n const candidates: PromptOverrideCandidate[] = []\n\n if (this.paths.projectOverridesDir) {\n candidates.push({\n path: join(this.paths.projectOverridesDir, fileName),\n })\n }\n\n if (this.paths.configDirOverridesDir) {\n candidates.push({\n path: join(this.paths.configDirOverridesDir, fileName),\n })\n }\n\n candidates.push({\n path: join(this.paths.globalOverridesDir, fileName),\n })\n\n return candidates\n }\n\n private ensureDefaultFiles(): void {\n try {\n mkdirSync(this.paths.defaultsDir, { recursive: true })\n mkdirSync(this.paths.globalOverridesDir, { recursive: true })\n } catch {\n this.logger.warn(\"Failed to initialize prompt directories\", {\n defaultsDir: this.paths.defaultsDir,\n globalOverridesDir: this.paths.globalOverridesDir,\n })\n return\n }\n\n for (const definition of PROMPT_DEFINITIONS) {\n const bundledEditable = toEditablePromptText(\n definition,\n BUNDLED_EDITABLE_PROMPTS[definition.runtimeField],\n )\n const managedContent = buildDefaultPromptFileContent(\n bundledEditable || BUNDLED_EDITABLE_PROMPTS[definition.runtimeField],\n )\n const filePath = join(this.paths.defaultsDir, definition.fileName)\n\n try {\n const existing = readFileIfExists(filePath)\n if (existing === managedContent) {\n continue\n }\n writeFileSync(filePath, managedContent, \"utf-8\")\n } catch {\n this.logger.warn(\"Failed to write default prompt file\", {\n key: definition.key,\n path: filePath,\n })\n }\n }\n\n const readmePath = join(this.paths.defaultsDir, DEFAULTS_README_FILE)\n const readmeContent = buildDefaultsReadmeContent()\n\n try {\n const existing = readFileIfExists(readmePath)\n if (existing !== readmeContent) {\n writeFileSync(readmePath, readmeContent, \"utf-8\")\n }\n } catch {\n this.logger.warn(\"Failed to write defaults README\", {\n path: readmePath,\n })\n }\n }\n}\n","export const SYSTEM = `\n\nYou operate in a context-constrained environment. Context management helps preserve retrieval quality, but your primary goal is completing the task at hand. Do not let context management distract from the actual work.\n\nThe tools you have for context management are \\`compress\\`, \\`decompress\\`, \\`mark_block\\`, and \\`unmark_block\\`. \\`compress\\` replaces older conversation content with technical summaries you produce. \\`decompress\\` restores previously compressed content when you need exact details. \\`mark_block\\` flags a compressed block for deferred batch merge-cleanup — it has zero immediate effect on context or cache, but marked blocks are merge-compressed together in a single cache break when context pressure rises. Use it for blocks you no longer need in detail but want to keep cached for now. \\`unmark_block\\` removes that flag.\n\n\\`<dcp-message-id>\\` and \\`<dcp-system-reminder>\\` tags are environment-injected metadata. Do not output them.\n\nCOMPRESSION PHILOSOPHY\n\nCompression replaces raw conversation content with dense summaries. When used correctly, it keeps your context sharp and focused. When used carelessly, it destroys information you need.\n\nThe key principle: compress based on context pressure, not habit. When context is ample, compress rarely or not at all. When context is tight, compress aggressively but selectively. The runtime context usage indicator tells you the current pressure level.\n\nTarget the largest UNCOMPRESSED content first. Savings scale with original size — compressing a 5000-token tool output frees far more than re-shrinking an already-summarized 300-token block.\n\nCONTEXT PRESSURE LEVELS\n\n- Ample: Context is well below the threshold. Do NOT compress unless there is obvious waste (huge terminal dumps, duplicated content). Focus entirely on your task.\n- Moderate: Context is approaching the threshold. Compress completed sections proactively. Prioritize high-token waste over minor cleanup.\n- High: Context has exceeded the threshold. Compress aggressively. Every compression should free meaningful tokens. Preserve only what is essential for the current task.\n\nWHAT TO COMPRESS FIRST (high value, low risk)\n\n- Agent/subagent review and consultation results: Prime compression targets when context pressure rises — the surrounding reasoning and tool-call chatter is typically the largest block of uncompressed content. Note: if the agent tool is in your protected list, its output is auto-preserved in the summary, so the savings come from the surrounding conversation, not the agent output itself. Compress once you have fully consumed the results (all recommended actions applied or recorded in files). Recover via \\`decompress\\` while the block is still active. Re-invoking the agent is a last resort — it is a fresh run, not a cache hit.\n- Verbose command output (build/test runs, git diff/log/status, publish logs, directory listings): Once you have read the result, compress. Keep only the verdict — pass/fail status, commit hash, version number, or count. For failures, keep the specific error messages and file/line references needed to act on them. The full output is reproducible by re-running the command.\n- Exploration that led nowhere (failed approaches, dead-end searches): Compress to a one-line note about what was tried and why it failed.\n- Redundant tool results (reading the same file multiple times, repeated status checks, exhausted search results): Keep only the most recent result.\n- Intermediate steps of completed multi-step tasks: Once the task is done, compress the process. Keep only the final outcome.\n- Resolved discussion threads (clarification rounds, negotiated requirements, design debate that reached a decision): Once a conclusion is recorded, compress the back-and-forth. Keep the decision and its rationale.\n- Large file contents that have already been used and are no longer needed: Compress to a summary of key functions, types, or patterns.\n\nDO NOT RE-COMPRESS (low value, diminishing returns)\n\n- Already-compressed block summaries: Re-compressing a summary into a shorter summary saves negligible tokens. If a block needs better detail, use \\`decompress\\` to restore it, then compress the original content properly. Exception: if a block-aging warning flags specific block IDs as facing GC truncation, re-summarize exactly those flagged blocks into a fresh range — this preserves detail that GC would otherwise destroy.\n- Short messages (1-3 sentences): The compression overhead (block metadata, summary structure) may exceed the tokens saved.\n- Content whose immediate use is complete — the task it supported is done and no open todo/plan references it. If still in active use, let it stay.\n- User instructions and requirements: These must remain visible until the task is complete.\n- Tool calls that are still pending or in-progress: Wait until the result is returned and consumed.\n\nWHAT TO COMPRESS CAREFULLY (high risk - verify before compressing)\n\n- Temporary secrets/keys/tokens needed later: Do NOT compress unless recorded elsewhere\n- File paths and directory structures: Keep in summary - losing these wastes tokens rediscovering them\n- Key function/method signatures and APIs: Summarize with exact names and signatures\n- Critical error messages and stack traces: Keep the error type and key detail in summary\n- User preferences and requirements: These must survive compression intact\n- Architectural decisions and rationale: Summarize the decision, not just the conclusion\n\nBEFORE COMPRESSING IMPORTANT CONTENT\n\nVerify the information is persisted in one of:\n- A file you have written or edited\n- An issue, PR, or devlog entry\n- The compression summary itself (include the critical bits explicitly)\n\nIf it is not persisted anywhere, either persist it first or include it explicitly in your compression summary.\n\nAFTER COMPRESSING\n\nGenerate recovery breadcrumbs in your summary so future-you can reconstruct the context:\n- Reference specific files by path\n- Include key variable names, function signatures, or configuration values\n- Note what was decided and why, not just what was done\n- Example: \"Implemented auth check in src/middleware.ts using validateToken() from auth.ts - user table is users not user\"\n\nIf you later realize you need the original details from a compressed block, use \\`decompress\\` to restore them. You can decompress, read the content, then re-compress if needed.\n\nUse \\`compress\\` and \\`decompress\\` deliberately with quality-first summaries. Prioritize stale content intelligently to maintain a high-signal context window.\n`\n","export const COMPRESS_RANGE = `Collapse a range in the conversation into a detailed summary.\n\nTHE SUMMARY\nYour summary must be EXHAUSTIVE. Capture file paths, function signatures, decisions made, constraints discovered, key findings... EVERYTHING that maintains context integrity. This is not a brief note - it is an authoritative record so faithful that the original conversation adds no value.\n\nUSER INTENT FIDELITY\nWhen the compressed range includes user messages, preserve the user's intent with extra care. Do not change scope, constraints, priorities, acceptance criteria, or requested outcomes.\nDirectly quote user messages when they are short enough to include safely. Direct quotes are preferred when they best preserve exact meaning.\n\nYet be LEAN. Strip away the noise: failed attempts that led nowhere, verbose tool outputs, back-and-forth exploration. What remains should be pure signal - golden nuggets of detail that preserve full understanding with zero ambiguity.\n\nCOMPRESSED BLOCK PLACEHOLDERS\nWhen the selected range includes previously compressed blocks, use this exact placeholder format when referencing one:\n\n- \\`(bN)\\`\n\nCompressed block sections in context are clearly marked with a header:\n\n- \\`[Compressed conversation section]\\`\n\nCompressed block IDs always use the \\`bN\\` form (never \\`mNNNNN\\`) and are represented in the same XML metadata tag format.\n\nRules:\n\n- Include every required block placeholder exactly once.\n- Do not invent placeholders for blocks outside the selected range.\n- Treat \\`(bN)\\` placeholders as RESERVED TOKENS. Do not emit \\`(bN)\\` text anywhere except intentional placeholders.\n- If you need to mention a block in prose, use plain text like \\`compressed bN\\` (not as a placeholder).\n- Preflight check before finalizing: the set of \\`(bN)\\` placeholders in your summary must exactly match the required set, with no duplicates.\n\nThese placeholders are semantic references. They will be replaced with the full stored compressed block content when the tool processes your output.\n\nFLOW PRESERVATION WITH PLACEHOLDERS\nWhen you use compressed block placeholders, write the surrounding summary text so it still reads correctly AFTER placeholder expansion.\n\n- Treat each placeholder as a stand-in for a full conversation segment, not as a short label.\n- Ensure transitions before and after each placeholder preserve chronology and causality.\n- Do not write text that depends on the placeholder staying literal (for example, \"as noted in \\`(b2)\\`\").\n- Your final meaning must be coherent once each placeholder is replaced with its full compressed block content.\n\nBOUNDARY IDS\nYou specify boundaries by ID using the injected IDs visible in the conversation:\n\n- \\`mNNNNN\\` IDs identify raw messages\n- \\`bN\\` IDs identify previously compressed blocks\n\nEach message has an ID inside XML metadata tags like \\`<dcp-message-id>...</dcp-message-id>\\`.\nThe same ID tag appears in every tool output of the message it belongs to — each unique ID identifies one complete message.\nTreat these tags as boundary metadata only, not as tool result content.\n\nRules:\n\n- Pick \\`startId\\` and \\`endId\\` directly from injected IDs in context.\n- IDs must exist in the current visible context. If you cannot see an ID in the messages above, it is stale and will fail.\n- \\`startId\\` must appear before \\`endId\\`.\n- Do not invent IDs. Use only IDs that are present in context.\n- NEVER use IDs from compressed block summaries, previous nudges, or your own memory — only IDs currently visible as XML metadata tags in the conversation.\n\nBATCHING\nWhen multiple independent ranges are ready and their boundaries do not overlap, include all of them as separate entries in the \\`content\\` array of a single tool call. Each entry should have its own \\`startId\\`, \\`endId\\`, and \\`summary\\`.\n`\n","export const COMPRESS_MESSAGE = `Collapse selected individual messages in the conversation into detailed summaries.\n\nTHE SUMMARY\nYour summary must be EXHAUSTIVE. Capture file paths, function signatures, decisions made, constraints discovered, key findings, tool outcomes, and user intent details that matter... EVERYTHING that preserves the value of the selected message after the raw message is removed.\n\nUSER INTENT FIDELITY\nWhen a selected message contains user intent, preserve that intent with extra care. Do not change scope, constraints, priorities, acceptance criteria, or requested outcomes.\nDirectly quote short user instructions when that best preserves exact meaning.\n\nYet be LEAN. Strip away the noise: failed attempts that led nowhere, verbose tool output, and repetition. What remains should be pure signal - golden nuggets of detail that preserve full understanding with zero ambiguity.\nIf a message contains no significant technical decisions, code changes, or user requirements, produce a minimal one-line summary rather than a detailed one.\n\nMESSAGE IDS\nYou specify individual raw messages by ID using the injected IDs visible in the conversation:\n\n- \\`mNNNNN\\` IDs identify raw messages\n\nEach message has an ID inside XML metadata tags like \\`<dcp-message-id priority=\"high\">m0007</dcp-message-id>\\`.\nThe same ID tag appears in every tool output of the message it belongs to — each unique ID identifies one complete message.\nTreat these tags as message metadata only, not as content to summarize. Use only the inner \\`mNNNNN\\` value as the \\`messageId\\`.\nThe \\`priority\\` attribute indicates relative context cost. You MUST compress high-priority messages when their full text is no longer necessary for the active task.\nIf prior compress-tool results are present, always compress and summarize them minimally only as part of a broader compression pass. Do not invoke the compress tool solely to re-compress an earlier compression result.\nMessages marked as \\`<dcp-message-id>BLOCKED</dcp-message-id>\\` cannot be compressed.\n\nRules:\n\n- Pick each \\`messageId\\` directly from injected IDs visible in context.\n- Only use raw message IDs of the form \\`mNNNNN\\`.\n- Ignore XML attributes such as \\`priority\\` when copying the ID; use only the inner \\`mNNNNN\\` value.\n- Do not invent IDs. Use only IDs that are present in context.\n\nBATCHING\nSelect MANY messages in a single tool call when they are safe to compress.\nEach entry should summarize exactly one message, and the tool can receive as many entries as needed in one batch.\n\nGENERAL CLEANUP\nUse the topic \"general cleanup\" for broad cleanup passes.\nDuring general cleanup, compress all medium and high-priority messages that are not relevant to the active task.\nOptimize for reducing context footprint, not for grouping messages by topic.\nDo not compress away still-active instructions, unresolved questions, or constraints that are likely to matter soon.\nPrioritize the earliest messages in the context as they will be the least relevant to the active task.\nGeneral cleanup should be done periodically between other normal compression tool passes, not as the primary form of compression.\n`\n","export const CONTEXT_LIMIT_NUDGE = `\n<system-reminder>\n⚠️ CRITICAL: Context limit reached. You MUST use the \\`compress\\` tool NOW.\n\nIf mid-atomic-operation, finish that step first, then compress immediately.\n\nHOW TO CALL COMPRESS:\n{\n \"topic\": \"Short Label\",\n \"content\": [\n {\n \"startId\": \"<ID from early in this conversation>\",\n \"endId\": \"<ID from later in this conversation>\",\n \"summary\": \"Complete technical summary of everything in the range\"\n }\n ]\n}\n\n⚠️ ID RULES — MOST COMMON CAUSE OF ERRORS:\n- ONLY use IDs you can see in <dcp-message-id> tags in the messages ABOVE.\n- Do NOT copy IDs from this example. Do NOT invent IDs.\n- Do NOT use IDs from compressed block summaries — they are stale.\n- startId must appear BEFORE endId in the conversation.\n\nSUMMARY RULES:\n- Capture ALL essential details: file paths, decisions, constraints, key findings.\n- Preserve user intent exactly. Direct-quote short user messages.\n- Prefer one large range over multiple small ones.\n- Compress OLDER resolved history first. Keep recent active work.\n</system-reminder>\n`\n","export const TURN_NUDGE = `\n<system-reminder>\nContext is getting full. Compress closed/older conversation ranges now.\n\n{\n \"topic\": \"Short Label\",\n \"content\": [{ \"startId\": \"<visible message ID>\", \"endId\": \"<visible message ID>\", \"summary\": \"...\" }]\n}\n\n⚠️ ONLY use IDs from <dcp-message-id> tags visible above. Do NOT invent or copy example IDs.\n</system-reminder>\n`\n","export const ITERATION_NUDGE = `\n<system-reminder>\nYou've been iterating for a while. If any earlier work is closed and unlikely to be referenced, compress it now.\n\n{\n \"topic\": \"Short Label\",\n \"content\": [{ \"startId\": \"<visible message ID>\", \"endId\": \"<visible message ID>\", \"summary\": \"...\" }]\n}\n\n⚠️ ONLY use IDs from <dcp-message-id> tags visible above. Do NOT invent or copy example IDs.\n</system-reminder>\n`\n","export 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`\n\nexport 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`\n\nexport function buildProtectedToolsExtension(protectedTools: string[]): string {\n if (protectedTools.length === 0) {\n return \"\"\n }\n\n const toolList = protectedTools.map((t) => `\\`${t}\\``).join(\", \")\n return `<dcp-system-reminder>\nThe following tools are environment-managed: ${toolList}.\nTheir outputs are automatically preserved during compression.\nDo not include their content in compress tool summaries — the environment retains it independently.\n</dcp-system-reminder>`\n}\n\nexport const DECOMPRESS_SYSTEM_EXTENSION = `<dcp-system-reminder>\nTHE PHILOSOPHY OF DECOMPRESS\n\\`decompress\\` restores previously compressed content. Use it when you need exact details\nthat were lost in compression.\n\nDECOMPRESS WHEN\n- You need exact code, error messages, or file contents from a compressed block\n- A summary lacks the precision needed for your next step\n- You discovered the compressed content is still relevant\n\nDO NOT DECOMPRESS IF\n- Context usage is already high (>70%) — decompressing inflates context\n- The summary is sufficient for your needs\n- You plan to immediately recompress the same content\n\nBefore decompressing, check context usage. Decompressing restores full messages,\nwhich can significantly increase context size.\n\nNOTE: Message-mode blocks created in the same batch (same runId) are restored together.\nDecompressing one block from a batch restores all blocks in that batch.\n</dcp-system-reminder>\n`\n","import type { RuntimePrompts } from \"./store\"\nexport type { PromptStore, RuntimePrompts } from \"./store\"\n\nexport function renderSystemPrompt(\n prompts: RuntimePrompts,\n protectedToolsExtension?: string,\n manual?: boolean,\n subagent?: boolean,\n): string {\n const extensions: string[] = []\n\n if (protectedToolsExtension) {\n extensions.push(protectedToolsExtension.trim())\n }\n\n if (manual) {\n extensions.push(prompts.manualExtension.trim())\n }\n\n if (subagent) {\n extensions.push(prompts.subagentExtension.trim())\n }\n\n // decompress extension is always included when compress is not denied\n // (the caller guards on permission === \"deny\" before reaching renderSystemPrompt)\n extensions.push(prompts.decompressExtension.trim())\n\n return [prompts.system.trim(), ...extensions]\n .filter(Boolean)\n .join(\"\\n\\n\")\n .replace(/\\n([ \\t]*\\n)+/g, \"\\n\\n\")\n .trim()\n}\n","/**\n * DCP Context Command\n * Shows a visual breakdown of token usage in the current session.\n *\n * TOKEN CALCULATION STRATEGY\n * ==========================\n * We minimize tokenizer estimation by leveraging API-reported values wherever possible.\n *\n * WHAT WE GET FROM THE API (exact):\n * - tokens.input : Input tokens for each assistant response\n * - tokens.output : Output tokens generated (includes text + tool calls)\n * - tokens.reasoning: Reasoning tokens used\n * - tokens.cache : Cache read/write tokens\n *\n * HOW WE CALCULATE EACH CATEGORY:\n *\n * SYSTEM = firstAssistant.input + cache.read + cache.write - tokenizer(firstUserMessage)\n * The first response's total input (input + cache.read + cache.write)\n * contains system + first user message. On the first request of a\n * session, the system prompt appears in cache.write (cache creation),\n * not cache.read.\n *\n * TOOLS = tokenizer(toolInputs + toolOutputs) - prunedTokens\n * We must tokenize tools anyway for pruning decisions.\n *\n * USER = tokenizer(all user messages)\n * User messages are typically small, so estimation is acceptable.\n *\n * ASSISTANT = total - system - user - tools\n * Calculated as residual. This absorbs:\n * - Assistant text output tokens\n * - Reasoning tokens (if persisted by the model)\n * - Any estimation errors\n *\n * TOTAL = input + output + reasoning + cache.read + cache.write\n * Matches opencode's UI display.\n *\n * WHY ASSISTANT IS THE RESIDUAL:\n * If reasoning tokens persist in context (model-dependent), they semantically\n * belong with \"Assistant\" since reasoning IS assistant-generated content.\n */\n\nimport type { Logger } from \"../logger\"\nimport type { SessionState, WithParts } from \"../state\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { formatTokenCount } from \"../ui/utils\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\nimport { isMessageCompacted } from \"../state/utils\"\nimport { countTokens, extractCompletedToolOutput, getCurrentParams } from \"../token-utils\"\nimport type { AssistantMessage, TextPart, ToolPart } from \"@opencode-ai/sdk/v2\"\n\nexport interface ContextCommandContext {\n client: any\n state: SessionState\n logger: Logger\n sessionId: string\n messages: WithParts[]\n}\n\ninterface TokenBreakdown {\n system: number\n user: number\n assistant: number\n tools: number\n toolCount: number\n toolsInContextCount: number\n prunedTokens: number\n prunedToolCount: number\n prunedMessageCount: number\n total: number\n}\n\nfunction analyzeTokens(state: SessionState, messages: WithParts[]): TokenBreakdown {\n const breakdown: TokenBreakdown = {\n system: 0,\n user: 0,\n assistant: 0,\n tools: 0,\n toolCount: 0,\n toolsInContextCount: 0,\n prunedTokens: state.stats.totalPruneTokens,\n prunedToolCount: 0,\n prunedMessageCount: 0,\n total: 0,\n }\n\n let firstAssistant: AssistantMessage | undefined\n for (const msg of messages) {\n if (msg.info.role === \"assistant\") {\n const assistantInfo = msg.info as AssistantMessage\n if (\n assistantInfo.tokens?.input > 0 ||\n assistantInfo.tokens?.cache?.read > 0 ||\n assistantInfo.tokens?.cache?.write > 0\n ) {\n firstAssistant = assistantInfo\n break\n }\n }\n }\n\n let lastAssistant: AssistantMessage | undefined\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.info.role === \"assistant\") {\n const assistantInfo = msg.info as AssistantMessage\n if (assistantInfo.tokens?.output > 0) {\n lastAssistant = assistantInfo\n break\n }\n }\n }\n\n const apiInput = lastAssistant?.tokens?.input || 0\n const apiOutput = lastAssistant?.tokens?.output || 0\n const apiReasoning = lastAssistant?.tokens?.reasoning || 0\n const apiCacheRead = lastAssistant?.tokens?.cache?.read || 0\n const apiCacheWrite = lastAssistant?.tokens?.cache?.write || 0\n breakdown.total = apiInput + apiOutput + apiReasoning + apiCacheRead + apiCacheWrite\n\n const userTextParts: string[] = []\n const toolInputParts: string[] = []\n const toolOutputParts: string[] = []\n let firstUserText = \"\"\n let foundFirstUser = false\n const allToolIds = new Set<string>()\n const activeToolIds = new Set<string>()\n const prunedByMessageToolIds = new Set<string>()\n const allMessageIds = new Set<string>()\n\n for (const msg of messages) {\n allMessageIds.add(msg.info.id)\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n const isCompacted = isMessageCompacted(state, msg)\n const pruneEntry = state.prune.messages.byMessageId.get(msg.info.id)\n const isMessagePruned = !!pruneEntry && pruneEntry.activeBlockIds.length > 0\n const isIgnoredUser = isIgnoredUserMessage(msg)\n\n for (const part of parts) {\n if (part.type === \"tool\") {\n const toolPart = part as ToolPart\n if (toolPart.callID) {\n allToolIds.add(toolPart.callID)\n if (!isCompacted) {\n activeToolIds.add(toolPart.callID)\n }\n if (isMessagePruned) {\n prunedByMessageToolIds.add(toolPart.callID)\n }\n }\n\n const isPruned = toolPart.callID && state.prune.tools.has(toolPart.callID)\n if (!isCompacted && !isPruned) {\n if (toolPart.state?.input) {\n const inputStr =\n typeof toolPart.state.input === \"string\"\n ? toolPart.state.input\n : JSON.stringify(toolPart.state.input)\n toolInputParts.push(inputStr)\n }\n\n const outputStr = extractCompletedToolOutput(toolPart)\n if (outputStr !== undefined) {\n toolOutputParts.push(outputStr)\n }\n }\n } else if (\n part.type === \"text\" &&\n msg.info.role === \"user\" &&\n !isCompacted &&\n !isIgnoredUser\n ) {\n const textPart = part as TextPart\n const text = textPart.text || \"\"\n userTextParts.push(text)\n if (!foundFirstUser) {\n firstUserText += text\n }\n }\n }\n\n if (msg.info.role === \"user\" && !isIgnoredUser && !foundFirstUser) {\n foundFirstUser = true\n }\n }\n\n const prunedByToolIds = new Set<string>()\n for (const id of allToolIds) {\n if (state.prune.tools.has(id)) {\n prunedByToolIds.add(id)\n }\n }\n\n const prunedToolIds = new Set<string>([...prunedByToolIds, ...prunedByMessageToolIds])\n const toolsInContextCount = [...activeToolIds].filter((id) => !prunedByToolIds.has(id)).length\n\n let prunedMessageCount = 0\n for (const [id, entry] of state.prune.messages.byMessageId) {\n if (allMessageIds.has(id) && entry.activeBlockIds.length > 0) {\n prunedMessageCount++\n }\n }\n\n breakdown.toolCount = allToolIds.size\n breakdown.toolsInContextCount = toolsInContextCount\n breakdown.prunedToolCount = prunedToolIds.size\n breakdown.prunedMessageCount = prunedMessageCount\n\n const firstUserTokens = countTokens(firstUserText)\n breakdown.user = countTokens(userTextParts.join(\"\\n\"))\n const toolInputTokens = countTokens(toolInputParts.join(\"\\n\"))\n const toolOutputTokens = countTokens(toolOutputParts.join(\"\\n\"))\n\n if (firstAssistant) {\n const firstInput =\n (firstAssistant.tokens?.input || 0) +\n (firstAssistant.tokens?.cache?.read || 0) +\n (firstAssistant.tokens?.cache?.write || 0)\n breakdown.system = Math.max(0, firstInput - firstUserTokens)\n }\n\n breakdown.tools = toolInputTokens + toolOutputTokens\n breakdown.assistant = Math.max(\n 0,\n breakdown.total - breakdown.system - breakdown.user - breakdown.tools,\n )\n\n return breakdown\n}\n\nfunction createBar(value: number, maxValue: number, width: number, char: string = \"█\"): string {\n if (maxValue === 0) return \"\"\n const filled = Math.round((value / maxValue) * width)\n const bar = char.repeat(Math.max(0, filled))\n return bar\n}\n\nfunction formatContextMessage(breakdown: TokenBreakdown): string {\n const lines: string[] = []\n const barWidth = 30\n\n const toolsLabel = `Tools (${breakdown.toolsInContextCount})`\n\n const categories = [\n { label: \"System\", value: breakdown.system, char: \"█\" },\n { label: \"User\", value: breakdown.user, char: \"▓\" },\n { label: \"Assistant\", value: breakdown.assistant, char: \"▒\" },\n { label: toolsLabel, value: breakdown.tools, char: \"░\" },\n ] as const\n\n const maxLabelLen = Math.max(...categories.map((c) => c.label.length))\n\n lines.push(\"╭───────────────────────────────────────────────────────────╮\")\n lines.push(\"│ ACP Context Analysis │\")\n lines.push(\"╰───────────────────────────────────────────────────────────╯\")\n lines.push(\"\")\n lines.push(\"Session Context Breakdown:\")\n lines.push(\"─\".repeat(60))\n lines.push(\"\")\n\n for (const cat of categories) {\n const bar = createBar(cat.value, breakdown.total, barWidth, cat.char)\n const percentage =\n breakdown.total > 0 ? ((cat.value / breakdown.total) * 100).toFixed(1) : \"0.0\"\n const labelWithPct = `${cat.label.padEnd(maxLabelLen)} ${percentage.padStart(5)}% `\n const valueStr = formatTokenCount(cat.value).padStart(13)\n lines.push(`${labelWithPct}│${bar.padEnd(barWidth)}│${valueStr}`)\n }\n\n lines.push(\"\")\n lines.push(\"─\".repeat(60))\n lines.push(\"\")\n\n lines.push(\"Summary:\")\n\n if (breakdown.prunedTokens > 0) {\n const withoutPruning = breakdown.total + breakdown.prunedTokens\n const pruned = []\n if (breakdown.prunedToolCount > 0) pruned.push(`${breakdown.prunedToolCount} tools`)\n if (breakdown.prunedMessageCount > 0)\n pruned.push(`${breakdown.prunedMessageCount} messages`)\n lines.push(\n ` Pruned: ${pruned.join(\", \")} (~${formatTokenCount(breakdown.prunedTokens)})`,\n )\n lines.push(` Current context: ~${formatTokenCount(breakdown.total)}`)\n lines.push(` Without ACP: ~${formatTokenCount(withoutPruning)}`)\n } else {\n lines.push(` Current context: ~${formatTokenCount(breakdown.total)}`)\n }\n\n lines.push(\"\")\n\n return lines.join(\"\\n\")\n}\n\nexport async function handleContextCommand(ctx: ContextCommandContext): Promise<void> {\n const { client, state, logger, sessionId, messages } = ctx\n\n const breakdown = analyzeTokens(state, messages)\n\n const message = formatContextMessage(breakdown)\n\n const params = getCurrentParams(state, messages, logger)\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n}\n","import type { Logger } from \"../logger\"\nimport type { SessionState, WithParts } from \"../state\"\nimport { syncCompressionBlocks } from \"../messages\"\nimport { getCurrentParams } from \"../token-utils\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { formatTokenCount } from \"../ui/utils\"\nimport {\n getActiveCompressionTargets,\n resolveCompressionTarget,\n type CompressionTarget,\n} from \"./compression-targets\"\nimport {\n parseBlockIdArg,\n findActiveAncestorBlockId,\n snapshotActiveMessages,\n deactivateCompressionTarget,\n computeRestoredMessages,\n computeReactivatedBlockIds,\n} from \"../compress/decompress-logic\"\nimport { saveSessionState } from \"../state/persistence\"\n\nexport interface DecompressCommandContext {\n client: any\n state: SessionState\n logger: Logger\n sessionId: string\n messages: WithParts[]\n args: string[]\n}\n\nfunction formatDecompressMessage(\n target: CompressionTarget,\n restoredMessageCount: number,\n restoredTokens: number,\n reactivatedBlockIds: number[],\n): string {\n const lines: string[] = []\n\n lines.push(`Restored compression ${target.displayId}.`)\n if (target.runId !== target.displayId || target.grouped) {\n lines.push(`Tool call label: Compression #${target.runId}.`)\n }\n if (reactivatedBlockIds.length > 0) {\n const refs = reactivatedBlockIds.map((id) => String(id)).join(\", \")\n lines.push(`Also restored nested compression(s): ${refs}.`)\n }\n\n if (restoredMessageCount > 0) {\n lines.push(\n `Restored ${restoredMessageCount} message(s) (~${formatTokenCount(restoredTokens)}).`,\n )\n } else {\n lines.push(\"No messages were restored.\")\n }\n\n return lines.join(\"\\n\")\n}\n\nfunction formatAvailableBlocksMessage(availableTargets: CompressionTarget[]): string {\n const lines: string[] = []\n\n lines.push(\"Usage: /acp decompress <n>\")\n lines.push(\"\")\n\n if (availableTargets.length === 0) {\n lines.push(\"No compressions are available to restore.\")\n return lines.join(\"\\n\")\n }\n\n lines.push(\"Available compressions:\")\n const entries = availableTargets.map((target) => {\n const topic = target.topic.replace(/\\s+/g, \" \").trim() || \"(no topic)\"\n const label = `${target.displayId} (${formatTokenCount(target.compressedTokens)})`\n const details = target.grouped\n ? `Compression #${target.runId} - ${target.blocks.length} messages`\n : `Compression #${target.runId}`\n return { label, topic: `${details} - ${topic}` }\n })\n\n const labelWidth = Math.max(...entries.map((entry) => entry.label.length)) + 4\n for (const entry of entries) {\n lines.push(` ${entry.label.padEnd(labelWidth)}${entry.topic}`)\n }\n\n return lines.join(\"\\n\")\n}\n\nexport async function handleDecompressCommand(ctx: DecompressCommandContext): Promise<void> {\n const { client, state, logger, sessionId, messages, args } = ctx\n\n const params = getCurrentParams(state, messages, logger)\n const targetArg = args[0]\n\n if (args.length > 1) {\n await sendIgnoredMessage(\n client,\n sessionId,\n \"Invalid arguments. Usage: /acp decompress <n>\",\n params,\n logger,\n )\n return\n }\n\n syncCompressionBlocks(state, logger, messages)\n const messagesState = state.prune.messages\n\n if (!targetArg) {\n const availableTargets = getActiveCompressionTargets(messagesState)\n const message = formatAvailableBlocksMessage(availableTargets)\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n return\n }\n\n const targetBlockId = parseBlockIdArg(targetArg)\n if (targetBlockId === null) {\n await sendIgnoredMessage(\n client,\n sessionId,\n `Please enter a compression number. Example: /acp decompress 2`,\n params,\n logger,\n )\n return\n }\n\n const target = resolveCompressionTarget(messagesState, targetBlockId)\n if (!target) {\n await sendIgnoredMessage(\n client,\n sessionId,\n `Compression ${targetBlockId} does not exist.`,\n params,\n logger,\n )\n return\n }\n\n const activeBlocks = target.blocks.filter((block) => block.active)\n if (activeBlocks.length === 0) {\n const activeAncestorBlockId = findActiveAncestorBlockId(messagesState, target)\n if (activeAncestorBlockId !== null) {\n await sendIgnoredMessage(\n client,\n sessionId,\n `Compression ${target.displayId} is inside compression ${activeAncestorBlockId}. Restore compression ${activeAncestorBlockId} first.`,\n params,\n logger,\n )\n return\n }\n\n await sendIgnoredMessage(\n client,\n sessionId,\n `Compression ${target.displayId} is not active.`,\n params,\n logger,\n )\n return\n }\n\n const activeMessagesBefore = snapshotActiveMessages(messagesState)\n const activeBlockIdsBefore = new Set(messagesState.activeBlockIds)\n\n deactivateCompressionTarget(messagesState, target)\n\n syncCompressionBlocks(state, logger, messages)\n\n const { restoredMessageCount, restoredTokens } = computeRestoredMessages(\n messagesState,\n activeMessagesBefore,\n )\n\n state.stats.totalPruneTokens = Math.max(0, state.stats.totalPruneTokens - restoredTokens)\n\n const reactivatedBlockIds = computeReactivatedBlockIds(messagesState, activeBlockIdsBefore)\n\n await saveSessionState(state, logger)\n\n const message = formatDecompressMessage(\n target,\n restoredMessageCount,\n restoredTokens,\n reactivatedBlockIds,\n )\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n\n logger.info(\"Decompress command completed\", {\n targetBlockId: target.displayId,\n targetRunId: target.runId,\n restoredMessageCount,\n restoredTokens,\n reactivatedBlockIds,\n })\n}\n","/**\n * ACP Help command handler.\n * Shows available ACP commands and their descriptions.\n */\n\nimport type { Logger } from \"../logger\"\nimport type { PluginConfig } from \"../config\"\nimport type { SessionState, WithParts } from \"../state\"\nimport { compressPermission } from \"../compress-permission\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { getCurrentParams } from \"../token-utils\"\n\nexport interface HelpCommandContext {\n client: any\n state: SessionState\n config: PluginConfig\n logger: Logger\n sessionId: string\n messages: WithParts[]\n}\n\nconst BASE_COMMANDS: [string, string][] = [\n [\"/acp context\", \"Show token usage breakdown for current session\"],\n [\"/acp stats\", \"Show ACP pruning statistics\"],\n [\"/acp sweep [n]\", \"Prune tools since last user message, or last n tools\"],\n [\"/acp manual [on|off]\", \"Toggle manual mode or set explicit state\"],\n]\n\nconst TOOL_COMMANDS: Record<string, [string, string]> = {\n compress: [\"/acp compress [focus]\", \"Trigger manual compress tool execution\"],\n decompress: [\"/acp decompress <n>\", \"Restore selected compression\"],\n recompress: [\"/acp recompress <n>\", \"Re-apply a user-decompressed compression\"],\n}\n\nfunction getVisibleCommands(state: SessionState, config: PluginConfig): [string, string][] {\n const commands = [...BASE_COMMANDS]\n\n if (compressPermission(state, config) !== \"deny\") {\n commands.push(TOOL_COMMANDS.compress)\n commands.push(TOOL_COMMANDS.decompress)\n commands.push(TOOL_COMMANDS.recompress)\n }\n\n return commands\n}\n\nfunction formatHelpMessage(state: SessionState, config: PluginConfig): string {\n const commands = getVisibleCommands(state, config)\n const colWidth = Math.max(...commands.map(([cmd]) => cmd.length)) + 4\n const lines: string[] = []\n\n lines.push(\"╭─────────────────────────────────────────────────────────────────────────╮\")\n lines.push(\"│ ACP Commands │\")\n lines.push(\"╰─────────────────────────────────────────────────────────────────────────╯\")\n lines.push(\"\")\n lines.push(` ${\"Manual mode:\".padEnd(colWidth)}${state.manualMode ? \"ON\" : \"OFF\"}`)\n lines.push(\"\")\n for (const [cmd, desc] of commands) {\n lines.push(` ${cmd.padEnd(colWidth)}${desc}`)\n }\n lines.push(\"\")\n\n return lines.join(\"\\n\")\n}\n\nexport async function handleHelpCommand(ctx: HelpCommandContext): Promise<void> {\n const { client, state, logger, sessionId, messages } = ctx\n\n const { config } = ctx\n const message = formatHelpMessage(state, config)\n\n const params = getCurrentParams(state, messages, logger)\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n\n logger.info(\"Help command executed\")\n}\n","/**\n * DCP Manual mode command handler.\n * Handles toggling manual mode and triggering individual tool executions.\n *\n * Usage:\n * /acp manual [on|off] - Toggle manual mode or set explicit state\n * /acp compress [focus] - Trigger manual compress execution\n */\n\nimport type { Logger } from \"../logger\"\nimport type { SessionState, WithParts } from \"../state\"\nimport type { PluginConfig } from \"../config\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { getCurrentParams } from \"../token-utils\"\nimport { buildCompressedBlockGuidance } from \"../prompts/extensions/nudge\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\n\nconst MANUAL_MODE_ON = \"Manual mode is now ON. Use /acp compress to trigger context tools manually.\"\n\nconst MANUAL_MODE_OFF = \"Manual mode is now OFF.\"\n\nconst COMPRESS_TRIGGER_PROMPT = [\n \"<compress triggered manually>\",\n \"Manual mode trigger received. You must now use the compress tool.\",\n \"Find the most significant completed conversation content that can be compressed into a high-fidelity technical summary.\",\n \"Follow the active compress mode, preserve all critical implementation details, and choose safe targets.\",\n \"Return after compress with a brief explanation of what content was compressed.\",\n].join(\"\\n\\n\")\n\nfunction getTriggerPrompt(\n tool: \"compress\",\n state: SessionState,\n config: PluginConfig,\n userFocus?: string,\n): string {\n const base = COMPRESS_TRIGGER_PROMPT\n const compressedBlockGuidance =\n config.compress.mode === \"message\" ? \"\" : buildCompressedBlockGuidance(state, config.gc)\n\n const sections = [base, compressedBlockGuidance]\n if (userFocus && userFocus.trim().length > 0) {\n sections.push(`Additional user focus:\\n${userFocus.trim()}`)\n }\n\n return sections.join(\"\\n\\n\")\n}\n\nexport interface ManualCommandContext {\n client: any\n state: SessionState\n config: PluginConfig\n logger: Logger\n sessionId: string\n messages: WithParts[]\n}\n\nexport async function handleManualToggleCommand(\n ctx: ManualCommandContext,\n modeArg?: string,\n): Promise<void> {\n const { client, state, logger, sessionId, messages } = ctx\n\n if (modeArg === \"on\") {\n state.manualMode = \"active\"\n } else if (modeArg === \"off\") {\n state.manualMode = false\n } else {\n state.manualMode = state.manualMode ? false : \"active\"\n }\n\n const params = getCurrentParams(state, messages, logger)\n await sendIgnoredMessage(\n client,\n sessionId,\n state.manualMode ? MANUAL_MODE_ON : MANUAL_MODE_OFF,\n params,\n logger,\n )\n\n logger.info(\"Manual mode toggled\", { manualMode: state.manualMode })\n}\n\nexport async function handleManualTriggerCommand(\n ctx: ManualCommandContext,\n tool: \"compress\",\n userFocus?: string,\n): Promise<string | null> {\n return getTriggerPrompt(tool, ctx.state, ctx.config, userFocus)\n}\n\nexport function applyPendingManualTrigger(\n state: SessionState,\n messages: WithParts[],\n logger: Logger,\n): void {\n const pending = state.pendingManualTrigger\n if (!pending) {\n return\n }\n\n if (!state.sessionId || pending.sessionId !== state.sessionId) {\n state.pendingManualTrigger = null\n return\n }\n\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.info.role !== \"user\" || isIgnoredUserMessage(msg)) {\n continue\n }\n\n for (const part of msg.parts) {\n if (part.type !== \"text\" || part.ignored || part.synthetic) {\n continue\n }\n\n part.text = pending.prompt\n state.pendingManualTrigger = null\n logger.debug(\"Applied manual prompt\", { sessionId: pending.sessionId })\n return\n }\n }\n\n state.pendingManualTrigger = null\n}\n","import type { Logger } from \"../logger\"\nimport type { PruneMessagesState, SessionState, WithParts } from \"../state\"\nimport { syncCompressionBlocks } from \"../messages\"\nimport { parseBlockRef } from \"../message-ids\"\nimport { getCurrentParams } from \"../token-utils\"\nimport { saveSessionState } from \"../state/persistence\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { formatTokenCount } from \"../ui/utils\"\nimport {\n getRecompressibleCompressionTargets,\n resolveCompressionTarget,\n type CompressionTarget,\n} from \"./compression-targets\"\n\nexport interface RecompressCommandContext {\n client: any\n state: SessionState\n logger: Logger\n sessionId: string\n messages: WithParts[]\n args: string[]\n}\n\nfunction parseBlockIdArg(arg: string): number | null {\n const normalized = arg.trim().toLowerCase()\n const blockRef = parseBlockRef(normalized)\n if (blockRef !== null) {\n return blockRef\n }\n\n if (!/^[1-9]\\d*$/.test(normalized)) {\n return null\n }\n\n const parsed = Number.parseInt(normalized, 10)\n return Number.isInteger(parsed) && parsed > 0 ? parsed : null\n}\n\nfunction snapshotActiveMessages(messagesState: PruneMessagesState): Set<string> {\n const activeMessages = new Set<string>()\n for (const [messageId, entry] of messagesState.byMessageId) {\n if (entry.activeBlockIds.length > 0) {\n activeMessages.add(messageId)\n }\n }\n return activeMessages\n}\n\nfunction formatRecompressMessage(\n target: CompressionTarget,\n recompressedMessageCount: number,\n recompressedTokens: number,\n deactivatedBlockIds: number[],\n): string {\n const lines: string[] = []\n\n lines.push(`Re-applied compression ${target.displayId}.`)\n if (target.runId !== target.displayId || target.grouped) {\n lines.push(`Tool call label: Compression #${target.runId}.`)\n }\n if (deactivatedBlockIds.length > 0) {\n const refs = deactivatedBlockIds.map((id) => String(id)).join(\", \")\n lines.push(`Also re-compressed nested compression(s): ${refs}.`)\n }\n\n if (recompressedMessageCount > 0) {\n lines.push(\n `Re-compressed ${recompressedMessageCount} message(s) (~${formatTokenCount(recompressedTokens)}).`,\n )\n } else {\n lines.push(\"No messages were re-compressed.\")\n }\n\n return lines.join(\"\\n\")\n}\n\nfunction formatAvailableBlocksMessage(availableTargets: CompressionTarget[]): string {\n const lines: string[] = []\n\n lines.push(\"Usage: /acp recompress <n>\")\n lines.push(\"\")\n\n if (availableTargets.length === 0) {\n lines.push(\"No user-decompressed blocks are available to re-compress.\")\n return lines.join(\"\\n\")\n }\n\n lines.push(\"Available user-decompressed compressions:\")\n const entries = availableTargets.map((target) => {\n const topic = target.topic.replace(/\\s+/g, \" \").trim() || \"(no topic)\"\n const label = `${target.displayId} (${formatTokenCount(target.compressedTokens)})`\n const details = target.grouped\n ? `Compression #${target.runId} - ${target.blocks.length} messages`\n : `Compression #${target.runId}`\n return { label, topic: `${details} - ${topic}` }\n })\n\n const labelWidth = Math.max(...entries.map((entry) => entry.label.length)) + 4\n for (const entry of entries) {\n lines.push(` ${entry.label.padEnd(labelWidth)}${entry.topic}`)\n }\n\n return lines.join(\"\\n\")\n}\n\nexport async function handleRecompressCommand(ctx: RecompressCommandContext): Promise<void> {\n const { client, state, logger, sessionId, messages, args } = ctx\n\n const params = getCurrentParams(state, messages, logger)\n const targetArg = args[0]\n\n if (args.length > 1) {\n await sendIgnoredMessage(\n client,\n sessionId,\n \"Invalid arguments. Usage: /acp recompress <n>\",\n params,\n logger,\n )\n return\n }\n\n syncCompressionBlocks(state, logger, messages)\n const messagesState = state.prune.messages\n const availableMessageIds = new Set(messages.map((msg) => msg.info.id))\n\n if (!targetArg) {\n const availableTargets = getRecompressibleCompressionTargets(\n messagesState,\n availableMessageIds,\n )\n const message = formatAvailableBlocksMessage(availableTargets)\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n return\n }\n\n const targetBlockId = parseBlockIdArg(targetArg)\n if (targetBlockId === null) {\n await sendIgnoredMessage(\n client,\n sessionId,\n `Please enter a compression number. Example: /acp recompress 2`,\n params,\n logger,\n )\n return\n }\n\n const target = resolveCompressionTarget(messagesState, targetBlockId)\n if (!target) {\n await sendIgnoredMessage(\n client,\n sessionId,\n `Compression ${targetBlockId} does not exist.`,\n params,\n logger,\n )\n return\n }\n\n if (target.blocks.some((block) => !availableMessageIds.has(block.compressMessageId))) {\n await sendIgnoredMessage(\n client,\n sessionId,\n `Compression ${target.displayId} can no longer be re-applied because its origin message is no longer in this session.`,\n params,\n logger,\n )\n return\n }\n\n if (!target.blocks.some((block) => block.deactivatedByUser)) {\n const message = target.blocks.some((block) => block.active)\n ? `Compression ${target.displayId} is already active.`\n : `Compression ${target.displayId} is not user-decompressed.`\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n return\n }\n\n const activeMessagesBefore = snapshotActiveMessages(messagesState)\n const activeBlockIdsBefore = new Set(messagesState.activeBlockIds)\n\n for (const block of target.blocks) {\n block.deactivatedByUser = false\n block.deactivatedAt = undefined\n block.deactivatedByBlockId = undefined\n }\n\n syncCompressionBlocks(state, logger, messages)\n\n let recompressedMessageCount = 0\n let recompressedTokens = 0\n for (const [messageId, entry] of messagesState.byMessageId) {\n const isActiveNow = entry.activeBlockIds.length > 0\n if (isActiveNow && !activeMessagesBefore.has(messageId)) {\n recompressedMessageCount++\n recompressedTokens += entry.tokenCount\n }\n }\n\n state.stats.totalPruneTokens += recompressedTokens\n\n const deactivatedBlockIds = Array.from(activeBlockIdsBefore)\n .filter((blockId) => !messagesState.activeBlockIds.has(blockId))\n .sort((a, b) => a - b)\n\n await saveSessionState(state, logger)\n\n const message = formatRecompressMessage(\n target,\n recompressedMessageCount,\n recompressedTokens,\n deactivatedBlockIds,\n )\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n\n logger.info(\"Recompress command completed\", {\n targetBlockId: target.displayId,\n targetRunId: target.runId,\n recompressedMessageCount,\n recompressedTokens,\n deactivatedBlockIds,\n })\n}\n","/**\n * DCP Stats command handler.\n * Shows pruning statistics for the current session and all-time totals.\n */\n\nimport type { Logger } from \"../logger\"\nimport type { SessionState, WithParts } from \"../state\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { formatTokenCount } from \"../ui/utils\"\nimport { loadAllSessionStats, type AggregatedStats } from \"../state/persistence\"\nimport { getCurrentParams } from \"../token-utils\"\nimport { getActiveCompressionTargets } from \"./compression-targets\"\n\nexport interface StatsCommandContext {\n client: any\n state: SessionState\n logger: Logger\n sessionId: string\n messages: WithParts[]\n}\n\nfunction formatStatsMessage(\n sessionTokens: number,\n sessionSummaryTokens: number,\n sessionTools: number,\n sessionMessages: number,\n sessionDurationMs: number,\n allTime: AggregatedStats,\n): string {\n const lines: string[] = []\n\n lines.push(\"╭───────────────────────────────────────────────────────────╮\")\n lines.push(\"│ ACP Statistics │\")\n lines.push(\"╰───────────────────────────────────────────────────────────╯\")\n lines.push(\"\")\n lines.push(\"Compression:\")\n lines.push(\"─\".repeat(60))\n lines.push(\n ` Tokens in|out: ~${formatTokenCount(sessionTokens)} | ~${formatTokenCount(sessionSummaryTokens)}`,\n )\n lines.push(` Ratio: ${formatCompressionRatio(sessionTokens, sessionSummaryTokens)}`)\n lines.push(` Time: ${formatCompressionTime(sessionDurationMs)}`)\n lines.push(` Messages: ${sessionMessages}`)\n lines.push(` Tools: ${sessionTools}`)\n lines.push(\"\")\n lines.push(\"All-time:\")\n lines.push(\"─\".repeat(60))\n lines.push(` Tokens saved: ~${formatTokenCount(allTime.totalTokens)}`)\n lines.push(` Tools pruned: ${allTime.totalTools}`)\n lines.push(` Messages pruned: ${allTime.totalMessages}`)\n lines.push(` Sessions: ${allTime.sessionCount}`)\n\n return lines.join(\"\\n\")\n}\n\nfunction formatCompressionRatio(inputTokens: number, outputTokens: number): string {\n if (inputTokens <= 0) {\n return \"0:1\"\n }\n\n if (outputTokens <= 0) {\n return \"∞:1\"\n }\n\n const ratio = Math.max(1, Math.round(inputTokens / outputTokens))\n return `${ratio}:1`\n}\n\nfunction formatCompressionTime(ms: number): string {\n const safeMs = Math.max(0, Math.round(ms))\n if (safeMs < 1000) {\n return `${safeMs} ms`\n }\n\n const totalSeconds = safeMs / 1000\n if (totalSeconds < 60) {\n return `${totalSeconds.toFixed(1)} s`\n }\n\n const wholeSeconds = Math.floor(totalSeconds)\n const hours = Math.floor(wholeSeconds / 3600)\n const minutes = Math.floor((wholeSeconds % 3600) / 60)\n const seconds = wholeSeconds % 60\n\n if (hours > 0) {\n return `${hours}h ${minutes}m ${seconds}s`\n }\n\n return `${minutes}m ${seconds}s`\n}\n\nexport async function handleStatsCommand(ctx: StatsCommandContext): Promise<void> {\n const { client, state, logger, sessionId, messages } = ctx\n\n // Session stats from in-memory state\n const sessionTokens = state.stats.totalPruneTokens\n const sessionSummaryTokens = Array.from(state.prune.messages.blocksById.values()).reduce(\n (total, block) => (block.active ? total + block.summaryTokens : total),\n 0,\n )\n const sessionDurationMs = getActiveCompressionTargets(state.prune.messages).reduce(\n (total, target) => total + target.durationMs,\n 0,\n )\n\n const prunedToolIds = new Set<string>(state.prune.tools.keys())\n for (const block of state.prune.messages.blocksById.values()) {\n if (block.active) {\n for (const toolId of block.effectiveToolIds) {\n prunedToolIds.add(toolId)\n }\n }\n }\n const sessionTools = prunedToolIds.size\n\n let sessionMessages = 0\n for (const entry of state.prune.messages.byMessageId.values()) {\n if (entry.activeBlockIds.length > 0) {\n sessionMessages++\n }\n }\n\n // All-time stats from storage files\n const allTime = await loadAllSessionStats(logger)\n\n const message = formatStatsMessage(\n sessionTokens,\n sessionSummaryTokens,\n sessionTools,\n sessionMessages,\n sessionDurationMs,\n allTime,\n )\n\n const params = getCurrentParams(state, messages, logger)\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n\n logger.info(\"Stats command executed\", {\n sessionTokens,\n sessionSummaryTokens,\n sessionTools,\n sessionMessages,\n sessionDurationMs,\n allTimeTokens: allTime.totalTokens,\n allTimeTools: allTime.totalTools,\n allTimeMessages: allTime.totalMessages,\n })\n}\n","/**\n * DCP Sweep command handler.\n * Prunes tool outputs since the last user message, or the last N tools.\n *\n * Usage:\n * /acp sweep - Prune all tools since the previous user message\n * /acp sweep 10 - Prune the last 10 tools\n */\n\nimport type { Logger } from \"../logger\"\nimport type { SessionState, WithParts, ToolParameterEntry } from \"../state\"\nimport type { PluginConfig } from \"../config\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { formatPrunedItemsList } from \"../ui/utils\"\nimport { getCurrentParams, getTotalToolTokens } from \"../token-utils\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\nimport { buildToolIdList } from \"../messages/utils\"\nimport { saveSessionState } from \"../state/persistence\"\nimport { isMessageCompacted } from \"../state/utils\"\nimport {\n getFilePathsFromParameters,\n isFilePathProtected,\n isToolNameProtected,\n} from \"../protected-patterns\"\nimport { syncToolCache } from \"../state/tool-cache\"\n\nexport interface SweepCommandContext {\n client: any\n state: SessionState\n config: PluginConfig\n logger: Logger\n sessionId: string\n messages: WithParts[]\n args: string[]\n workingDirectory: string\n}\n\nfunction findLastUserMessageIndex(messages: WithParts[]): number {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.info.role === \"user\" && !isIgnoredUserMessage(msg)) {\n return i\n }\n }\n\n return -1\n}\n\nfunction collectToolIdsAfterIndex(\n state: SessionState,\n messages: WithParts[],\n afterIndex: number,\n): string[] {\n const toolIds: string[] = []\n\n for (let i = afterIndex + 1; i < messages.length; i++) {\n const msg = messages[i]\n if (isMessageCompacted(state, msg)) {\n continue\n }\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n if (parts.length > 0) {\n for (const part of parts) {\n if (part.type === \"tool\" && part.callID && part.tool) {\n toolIds.push(part.callID)\n }\n }\n }\n }\n\n return toolIds\n}\n\nfunction formatNoUserMessage(): string {\n const lines: string[] = []\n\n lines.push(\"╭───────────────────────────────────────────────────────────╮\")\n lines.push(\"│ ACP Sweep │\")\n lines.push(\"╰───────────────────────────────────────────────────────────╯\")\n lines.push(\"\")\n lines.push(\"Nothing swept: no user message found.\")\n\n return lines.join(\"\\n\")\n}\n\nfunction formatSweepMessage(\n toolCount: number,\n tokensSaved: number,\n mode: \"since-user\" | \"last-n\",\n toolIds: string[],\n toolMetadata: Map<string, ToolParameterEntry>,\n workingDirectory?: string,\n skippedProtected?: number,\n): string {\n const lines: string[] = []\n\n lines.push(\"╭───────────────────────────────────────────────────────────╮\")\n lines.push(\"│ ACP Sweep │\")\n lines.push(\"╰───────────────────────────────────────────────────────────╯\")\n lines.push(\"\")\n\n if (toolCount === 0) {\n if (mode === \"since-user\") {\n lines.push(\"No tools found since the previous user message.\")\n } else {\n lines.push(`No tools found to sweep.`)\n }\n if (skippedProtected && skippedProtected > 0) {\n lines.push(`(${skippedProtected} protected tool(s) skipped)`)\n }\n } else {\n if (mode === \"since-user\") {\n lines.push(`Swept ${toolCount} tool(s) since the previous user message.`)\n } else {\n lines.push(`Swept the last ${toolCount} tool(s).`)\n }\n lines.push(`Tokens saved: ~${tokensSaved.toLocaleString()}`)\n if (skippedProtected && skippedProtected > 0) {\n lines.push(`(${skippedProtected} protected tool(s) skipped)`)\n }\n lines.push(\"\")\n const itemLines = formatPrunedItemsList(toolIds, toolMetadata, workingDirectory)\n lines.push(...itemLines)\n }\n\n return lines.join(\"\\n\")\n}\n\nexport async function handleSweepCommand(ctx: SweepCommandContext): Promise<void> {\n const { client, state, config, logger, sessionId, messages, args, workingDirectory } = ctx\n\n const params = getCurrentParams(state, messages, logger)\n const protectedTools = config.commands.protectedTools\n\n syncToolCache(state, config, logger, messages)\n buildToolIdList(state, messages)\n\n // Parse optional numeric argument\n const numArg = args[0] ? parseInt(args[0], 10) : null\n const isLastNMode = numArg !== null && !isNaN(numArg) && numArg > 0\n\n let toolIdsToSweep: string[]\n let mode: \"since-user\" | \"last-n\"\n\n if (isLastNMode) {\n // Mode: Sweep last N tools\n mode = \"last-n\"\n const startIndex = Math.max(0, state.toolIdList.length - numArg!)\n toolIdsToSweep = state.toolIdList.slice(startIndex)\n logger.info(`Sweep command: last ${numArg} mode, found ${toolIdsToSweep.length} tools`)\n } else {\n // Mode: Sweep since last user message\n mode = \"since-user\"\n const lastUserMsgIndex = findLastUserMessageIndex(messages)\n\n if (lastUserMsgIndex === -1) {\n // No user message found - show message and return\n const message = formatNoUserMessage()\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n logger.info(\"Sweep command: no user message found\")\n return\n } else {\n toolIdsToSweep = collectToolIdsAfterIndex(state, messages, lastUserMsgIndex)\n logger.info(\n `Sweep command: found last user at index ${lastUserMsgIndex}, sweeping ${toolIdsToSweep.length} tools`,\n )\n }\n }\n\n // Filter out already-pruned tools, protected tools, and protected file paths\n const newToolIds = toolIdsToSweep.filter((id) => {\n if (state.prune.tools.has(id)) {\n return false\n }\n const entry = state.toolParameters.get(id)\n if (!entry) {\n return true\n }\n if (isToolNameProtected(entry.tool, protectedTools)) {\n logger.debug(`Sweep: skipping protected tool ${entry.tool} (${id})`)\n return false\n }\n const filePaths = getFilePathsFromParameters(entry.tool, entry.parameters)\n if (isFilePathProtected(filePaths, config.protectedFilePatterns)) {\n logger.debug(`Sweep: skipping protected file path(s) ${filePaths.join(\", \")} (${id})`)\n return false\n }\n return true\n })\n\n // Count how many were skipped due to protection\n const skippedProtected = toolIdsToSweep.filter((id) => {\n const entry = state.toolParameters.get(id)\n if (!entry) {\n return false\n }\n if (isToolNameProtected(entry.tool, protectedTools)) {\n return true\n }\n const filePaths = getFilePathsFromParameters(entry.tool, entry.parameters)\n if (isFilePathProtected(filePaths, config.protectedFilePatterns)) {\n return true\n }\n return false\n }).length\n\n if (newToolIds.length === 0) {\n const message = formatSweepMessage(\n 0,\n 0,\n mode,\n [],\n new Map(),\n workingDirectory,\n skippedProtected,\n )\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n logger.info(\"Sweep command: no new tools to sweep\", { skippedProtected })\n return\n }\n\n const tokensSaved = getTotalToolTokens(state, newToolIds)\n\n // Add to prune list\n for (const id of newToolIds) {\n const entry = state.toolParameters.get(id)\n state.prune.tools.set(id, entry?.tokenCount ?? 0)\n }\n state.stats.pruneTokenCounter += tokensSaved\n state.stats.totalPruneTokens += state.stats.pruneTokenCounter\n state.stats.pruneTokenCounter = 0\n\n // Collect metadata for logging\n const toolMetadata: Map<string, ToolParameterEntry> = new Map()\n for (const id of newToolIds) {\n const entry = state.toolParameters.get(id)\n if (entry) {\n toolMetadata.set(id, entry)\n }\n }\n\n // Persist state\n saveSessionState(state, logger).catch((err) =>\n logger.error(\"Failed to persist state after sweep\", { error: err.message }),\n )\n\n const message = formatSweepMessage(\n newToolIds.length,\n tokensSaved,\n mode,\n newToolIds,\n toolMetadata,\n workingDirectory,\n skippedProtected,\n )\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n\n logger.info(\"Sweep command completed\", {\n toolsSwept: newToolIds.length,\n tokensSaved,\n skippedProtected,\n mode,\n tools: Array.from(toolMetadata.entries()).map(([id, entry]) => ({\n id,\n tool: entry.tool,\n })),\n })\n}\n","import type { CompressionBlock } from \"../state\"\nimport type { GCConfig } from \"../config\"\n\nexport interface CompactionResult {\n compactedBlocks: number\n savedTokens: number\n}\n\nexport interface GCParams {\n maxOldGenSummaryLength: number\n modelContextLimit: number\n currentTokens: number\n}\n\nexport function runTruncateGC(\n blocks: CompressionBlock[],\n params: GCParams,\n): CompactionResult {\n let compactedBlocks = 0\n let savedTokens = 0\n\n for (const block of blocks) {\n if (!block.active) continue\n if (block.summary.length <= params.maxOldGenSummaryLength) continue\n\n const originalLength = block.summary.length\n const truncated = truncateSummary(block.summary, params.maxOldGenSummaryLength, block.blockId)\n const savedChars = originalLength - truncated.length\n if (savedChars > 0) {\n block.summary = truncated\n block.summaryTokens = Math.round(truncated.length / 4)\n compactedBlocks++\n savedTokens += Math.round(savedChars / 4)\n }\n }\n\n return { compactedBlocks, savedTokens }\n}\n\nfunction truncateSummary(summary: string, maxLength: number, _blockId: number): string {\n if (summary.length <= maxLength) return summary\n\n const headerEnd = summary.indexOf(\"\\n\")\n if (headerEnd === -1) return summary.slice(0, maxLength) + \"\\n...\\n[GC truncated]\"\n\n const header = summary.slice(0, headerEnd + 1)\n const footerStart = summary.lastIndexOf(\"\\n\\n\")\n const footer = footerStart > headerEnd ? summary.slice(footerStart) : \"\"\n\n const availableForContent = maxLength - header.length - footer.length - 20\n if (availableForContent < 100) {\n return header + \"...\\n[GC truncated]\" + footer\n }\n\n const content = summary.slice(headerEnd + 1, headerEnd + 1 + availableForContent)\n return header + content + \"\\n...\\n[GC truncated]\" + footer\n}\n\nexport function shouldRunMajorGC(\n currentTokens: number,\n modelContextLimit: number | undefined,\n gcConfig: GCConfig,\n): boolean {\n if (!modelContextLimit || modelContextLimit === 0) return false\n\n const threshold = parseGcThreshold(gcConfig.majorGcThresholdPercent, modelContextLimit)\n return currentTokens >= threshold\n}\n\nexport function getGCParams(gcConfig: GCConfig, modelContextLimit: number, currentTokens: number): GCParams {\n return {\n maxOldGenSummaryLength: gcConfig.maxOldGenSummaryLength,\n modelContextLimit,\n currentTokens,\n }\n}\n\nfunction parseGcThreshold(limit: number | `${number}%`, modelContextLimit: number): number {\n if (typeof limit === \"number\") return limit\n const percent = parseFloat(limit.slice(0, -1))\n if (isNaN(percent)) return modelContextLimit\n return Math.round((Math.max(0, Math.min(100, Math.round(percent))) / 100) * modelContextLimit)\n}\n","import type { CompressionBlock, SessionState, WithParts } from \"../state\"\nimport type { BatchCleanupConfig, GCConfig, PluginConfig } from \"../config\"\nimport type { Logger } from \"../logger\"\nimport { countTokens, getCurrentTokenUsage } from \"../token-utils\"\nimport {\n COMPRESSED_BLOCK_HEADER,\n allocateBlockId,\n allocateRunId,\n wrapCompressedSummary,\n} from \"../compress/state\"\nimport { formatBlockRef } from \"../message-ids\"\n\nexport interface MergeMarkedResult {\n mergedCount: number\n savedTokens: number\n}\n\nexport interface BatchCleanupResult {\n tier: 0 | 1 | 2 | 3\n action: \"none\" | \"nudge\" | \"merge\"\n mergedCount: number\n savedTokens: number\n nudgeText?: string\n}\n\nconst DEFAULT_BATCH_CLEANUP: BatchCleanupConfig = {\n lowThreshold: \"60%\",\n highThreshold: \"75%\",\n forceThreshold: \"90%\",\n}\n\nfunction resolveBatchCleanup(gc: GCConfig): BatchCleanupConfig {\n return gc.batchCleanup ?? DEFAULT_BATCH_CLEANUP\n}\n\nfunction percentToTokens(\n value: number | `${number}%`,\n modelContextLimit: number,\n): number {\n if (typeof value === \"number\") return value\n const percent = parseFloat(value.slice(0, -1))\n if (isNaN(percent)) return modelContextLimit\n const clamped = Math.max(0, Math.min(100, Math.round(percent)))\n return Math.round((clamped / 100) * modelContextLimit)\n}\n\nfunction collectActiveOldGenBlocks(state: SessionState, maxOldGenSummaryLength: number): CompressionBlock[] {\n const blocks: CompressionBlock[] = []\n const ids = Array.from(state.prune.messages.activeBlockIds).sort((a, b) => a - b)\n for (const id of ids) {\n const block = state.prune.messages.blocksById.get(id)\n if (!block || !block.active) continue\n if (\n block.generation === \"old\" ||\n block.generation === undefined ||\n block.summary.length > maxOldGenSummaryLength\n ) {\n blocks.push(block)\n }\n }\n return blocks\n}\n\nfunction collectActiveMarkedBlocks(state: SessionState): CompressionBlock[] {\n const ids = Array.from(state.prune.messages.markedForCleanup).sort((a, b) => a - b)\n const blocks: CompressionBlock[] = []\n for (const id of ids) {\n const block = state.prune.messages.blocksById.get(id)\n if (!block || !block.active) continue\n blocks.push(block)\n }\n return blocks\n}\n\nfunction extractSummaryBody(summary: string): string {\n let body = summary\n const headerPrefix = COMPRESSED_BLOCK_HEADER + \"\\n\"\n if (body.startsWith(headerPrefix)) {\n body = body.slice(headerPrefix.length)\n }\n body = body.replace(/\\n<dcp-message-id[^>]*>b\\d+<\\/dcp-message-id>$/, \"\")\n return body.trim()\n}\n\nfunction truncateMergedSummary(merged: string, maxLength: number): string {\n if (merged.length <= maxLength) return merged\n\n const blocks = merged.split(\"\\n---\\n\")\n const headers = blocks\n .map((b) => b.split(\"\\n\")[0] ?? \"\")\n .filter((h) => h.trim().length > 0)\n\n const marker = \"\\n...\\n[merged and truncated by batch cleanup]\"\n const budget = Math.max(0, maxLength - marker.length)\n const headerJoin = headers.join(\"\\n\")\n\n if (headerJoin.length <= budget) {\n return headerJoin + marker\n }\n return headerJoin.slice(0, budget) + marker\n}\n\nexport function mergeMarkedBlocks(\n state: SessionState,\n markedIds: number[],\n maxMergedLength: number,\n): MergeMarkedResult {\n const sortedIds = [...new Set(markedIds)].filter(\n (id) => Number.isInteger(id) && id > 0,\n ).sort((a, b) => a - b)\n\n const sourceBlocks: CompressionBlock[] = []\n for (const id of sortedIds) {\n const block = state.prune.messages.blocksById.get(id)\n if (!block || !block.active) continue\n if (!sourceBlocks.some((b) => b.blockId === id)) {\n sourceBlocks.push(block)\n }\n }\n\n if (sourceBlocks.length < 2) {\n return { mergedCount: 0, savedTokens: 0 }\n }\n\n const messagesState = state.prune.messages\n const newBlockId = allocateBlockId(state)\n const newRunId = allocateRunId(state)\n\n const bodies = sourceBlocks.map((block) => extractSummaryBody(block.summary))\n const mergedRaw = bodies.join(\"\\n---\\n\")\n const mergedBody = truncateMergedSummary(mergedRaw, maxMergedLength)\n const newSummary = wrapCompressedSummary(newBlockId, mergedBody)\n const newSummaryTokens = countTokens(newSummary)\n\n const oldest = sourceBlocks[0]\n const newest = sourceBlocks[sourceBlocks.length - 1]\n\n const effectiveMessageIds = new Set<string>()\n const effectiveToolIds = new Set<string>()\n for (const block of sourceBlocks) {\n for (const id of block.effectiveMessageIds) effectiveMessageIds.add(id)\n for (const id of block.effectiveToolIds) effectiveToolIds.add(id)\n }\n\n const sourceIds = sourceBlocks.map((b) => b.blockId)\n const createdAt = Date.now()\n\n const mergedBlock: CompressionBlock = {\n blockId: newBlockId,\n runId: newRunId,\n active: true,\n deactivatedByUser: false,\n compressedTokens: 0,\n summaryTokens: newSummaryTokens,\n durationMs: 0,\n mode: \"range\",\n topic: \"Batch merge cleanup\",\n batchTopic: \"Batch merge cleanup\",\n startId: oldest.startId,\n endId: newest.endId,\n anchorMessageId: oldest.anchorMessageId,\n compressMessageId: \"\",\n compressCallId: undefined,\n includedBlockIds: [...sourceIds],\n consumedBlockIds: [...sourceIds],\n parentBlockIds: [],\n directMessageIds: [],\n directToolIds: [],\n effectiveMessageIds: [...effectiveMessageIds],\n effectiveToolIds: [...effectiveToolIds],\n createdAt,\n summary: newSummary,\n survivedCount: 0,\n generation: \"old\",\n }\n\n const now = Date.now()\n for (const block of sourceBlocks) {\n block.active = false\n block.deactivatedAt = now\n block.deactivatedByBlockId = newBlockId\n if (!block.parentBlockIds.includes(newBlockId)) {\n block.parentBlockIds.push(newBlockId)\n }\n messagesState.activeBlockIds.delete(block.blockId)\n const mappedId = messagesState.activeByAnchorMessageId.get(block.anchorMessageId)\n if (mappedId === block.blockId) {\n messagesState.activeByAnchorMessageId.delete(block.anchorMessageId)\n }\n }\n\n messagesState.blocksById.set(newBlockId, mergedBlock)\n messagesState.activeBlockIds.add(newBlockId)\n messagesState.activeByAnchorMessageId.set(mergedBlock.anchorMessageId, newBlockId)\n\n for (const messageId of effectiveMessageIds) {\n const entry = messagesState.byMessageId.get(messageId)\n if (!entry) continue\n entry.activeBlockIds = entry.activeBlockIds.filter((id) => !sourceIds.includes(id))\n if (!entry.activeBlockIds.includes(newBlockId)) {\n entry.activeBlockIds.push(newBlockId)\n }\n if (!entry.allBlockIds.includes(newBlockId)) {\n entry.allBlockIds.push(newBlockId)\n }\n }\n\n for (const id of sourceIds) {\n messagesState.markedForCleanup.delete(id)\n }\n\n const sourceTokens = sourceBlocks.reduce(\n (sum, block) => sum + (block.summaryTokens || Math.round(block.summary.length / 4)),\n 0,\n )\n const savedTokens = Math.max(0, sourceTokens - newSummaryTokens)\n\n return { mergedCount: sourceBlocks.length, savedTokens }\n}\n\nfunction buildNudgeText(state: SessionState, maxMergedLength: number): string | undefined {\n const blocks = collectActiveMarkedBlocks(state)\n if (blocks.length < 1) return undefined\n\n const refs = blocks.map((b) => formatBlockRef(b.blockId)).join(\", \")\n const sourceTokens = blocks.reduce(\n (sum, block) => sum + (block.summaryTokens || Math.round(block.summary.length / 4)),\n 0,\n )\n const estimatedMergedTokens = Math.round(maxMergedLength / 4)\n const estimatedSavings = Math.max(0, sourceTokens - estimatedMergedTokens)\n\n return [\n `⚠️ ${blocks.length} block(s) marked for batch cleanup (${refs}).`,\n `Merge-compressing them would free ~${estimatedSavings} tokens.`,\n blocks.length >= 2\n ? \"They will auto-merge when context pressure reaches the high threshold.\"\n : \"A single marked block won't auto-merge on its own — use compress to consolidate it, or unmark_block if no longer needed.\",\n \"To act now, use compress with a range covering these blocks.\",\n ].join(\" \")\n}\n\nexport function runBatchCleanup(\n state: SessionState,\n config: PluginConfig,\n logger: Logger,\n messages: WithParts[],\n): BatchCleanupResult {\n const noop: BatchCleanupResult = {\n tier: 0,\n action: \"none\",\n mergedCount: 0,\n savedTokens: 0,\n }\n\n if (!state.modelContextLimit || state.modelContextLimit <= 0) {\n return noop\n }\n\n const currentTokens = getCurrentTokenUsage(state, messages)\n const limit = state.modelContextLimit\n const batchCleanup = resolveBatchCleanup(config.gc)\n const maxMergedLength = config.gc.maxOldGenSummaryLength\n\n const forceTokens = percentToTokens(batchCleanup.forceThreshold, limit)\n const highTokens = percentToTokens(batchCleanup.highThreshold, limit)\n const lowTokens = percentToTokens(batchCleanup.lowThreshold, limit)\n\n if (currentTokens >= forceTokens) {\n const oldGenBlocks = collectActiveOldGenBlocks(state, maxMergedLength)\n if (oldGenBlocks.length < 2) {\n return noop\n }\n const ids = oldGenBlocks.map((b) => b.blockId)\n const result = mergeMarkedBlocks(state, ids, maxMergedLength)\n if (result.mergedCount === 0) {\n return noop\n }\n logger.info(\"Batch cleanup tier 3 (force): merged old-gen blocks\", {\n mergedCount: result.mergedCount,\n savedTokens: result.savedTokens,\n currentTokens,\n forceThreshold: batchCleanup.forceThreshold,\n })\n return {\n tier: 3,\n action: \"merge\",\n mergedCount: result.mergedCount,\n savedTokens: result.savedTokens,\n }\n }\n\n if (currentTokens >= highTokens) {\n const marked = collectActiveMarkedBlocks(state)\n if (marked.length < 2) {\n return noop\n }\n const ids = marked.map((b) => b.blockId)\n const result = mergeMarkedBlocks(state, ids, maxMergedLength)\n if (result.mergedCount === 0) {\n return noop\n }\n logger.info(\"Batch cleanup tier 2 (high): merged marked blocks\", {\n mergedCount: result.mergedCount,\n savedTokens: result.savedTokens,\n currentTokens,\n highThreshold: batchCleanup.highThreshold,\n })\n return {\n tier: 2,\n action: \"merge\",\n mergedCount: result.mergedCount,\n savedTokens: result.savedTokens,\n }\n }\n\n if (currentTokens >= lowTokens) {\n const nudgeText = buildNudgeText(state, maxMergedLength)\n if (!nudgeText) {\n return noop\n }\n logger.info(\"Batch cleanup tier 1 (low): nudge injected\", {\n currentTokens,\n lowThreshold: batchCleanup.lowThreshold,\n })\n return {\n tier: 1,\n action: \"nudge\",\n mergedCount: 0,\n savedTokens: 0,\n nudgeText,\n }\n }\n\n return noop\n}\n","import type { SessionState, WithParts } from \"./state\"\nimport type { Logger } from \"./logger\"\nimport type { PluginConfig } from \"./config\"\nimport { assignMessageRefs } from \"./message-ids\"\nimport {\n buildPriorityMap,\n buildToolIdList,\n injectCompressNudges,\n injectExtendedSubAgentResults,\n injectMessageIds,\n prune,\n stripHallucinations,\n stripHallucinationsFromString,\n stripStaleMetadata,\n syncCompressionBlocks,\n computeInputBudget,\n} from \"./messages\"\nimport { renderSystemPrompt, type PromptStore } from \"./prompts\"\nimport { buildProtectedToolsExtension } from \"./prompts/extensions/system\"\nimport {\n applyPendingCompressionDurations,\n buildCompressionTimingKey,\n consumeCompressionStart,\n resolveCompressionDuration,\n} from \"./compress/timing\"\nimport { filterMessages, filterMessagesInPlace } from \"./messages/shape\"\nimport { getLastUserMessage } from \"./messages/query\"\nimport {\n applyPendingManualTrigger,\n handleContextCommand,\n handleDecompressCommand,\n handleHelpCommand,\n handleManualToggleCommand,\n handleManualTriggerCommand,\n handleRecompressCommand,\n handleStatsCommand,\n handleSweepCommand,\n} from \"./commands\"\nimport { type HostPermissionSnapshot } from \"./host-permissions\"\nimport { compressPermission, syncCompressPermissionState } from \"./compress-permission\"\nimport { checkSession, ensureSessionInitialized, saveSessionState, syncToolCache } from \"./state\"\nimport { cacheSystemPromptTokens } from \"./ui/utils\"\nimport { runTruncateGC, shouldRunMajorGC, getGCParams } from \"./gc/truncate\"\nimport { runBatchCleanup } from \"./gc/merge\"\nimport { getCurrentTokenUsage } from \"./token-utils\"\nimport { appendToLastTextPart } from \"./messages/utils\"\n\nconst INTERNAL_AGENT_SIGNATURES = [\n \"You are a title generator\",\n \"You are a helpful AI assistant tasked with summarizing conversations\",\n \"You are an anchored context summarization assistant for coding sessions\",\n \"Summarize what was done in this conversation\",\n]\n\n// [FIX Bug 37] OpenCode built-in hidden primary-mode agents that must NOT be\n// run through the message-transform pipeline. These small internal LLM\n// requests (title/summary/compaction generation) carry the agent name on the\n// user message's `info.agent` field. Mutating them corrupts the request and\n// shared session state (e.g. countTurns runs on the wrong message set).\n// Keep in sync with INTERNAL_AGENT_SIGNATURES (system-prompt layer) and the\n// agent IDs defined in OpenCode's packages/core/src/plugin/agent.ts.\nconst INTERNAL_AGENT_NAMES = new Set([\"title\", \"summary\", \"compaction\"])\n\nfunction isInternalAgentRequest(messages: WithParts[]): boolean {\n const lastUserMessage = getLastUserMessage(messages)\n if (!lastUserMessage) {\n return false\n }\n const agent = (lastUserMessage.info as { agent?: unknown }).agent\n return typeof agent === \"string\" && INTERNAL_AGENT_NAMES.has(agent)\n}\n\nexport function createSystemPromptHandler(\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n prompts: PromptStore,\n) {\n return async (\n input: {\n sessionID?: string\n model: { limit: { context: number; input?: number; output?: number } }\n },\n output: { system: string[] },\n ) => {\n if (input.model?.limit?.context) {\n state.modelContextLimit = input.model.limit.context\n }\n\n if (state.isSubAgent && !config.experimental.allowSubAgents) {\n return\n }\n\n const systemText = output.system.join(\"\\n\")\n if (INTERNAL_AGENT_SIGNATURES.some((sig) => systemText.includes(sig))) {\n logger.info(\"Skipping DCP system prompt injection for internal agent\")\n return\n }\n\n const effectivePermission =\n input.sessionID && state.sessionId === input.sessionID\n ? compressPermission(state, config)\n : config.compress.permission\n\n if (effectivePermission === \"deny\") {\n return\n }\n\n prompts.reload()\n const runtimePrompts = prompts.getRuntimePrompts()\n const newPrompt = renderSystemPrompt(\n runtimePrompts,\n buildProtectedToolsExtension(config.compress.protectedTools),\n !!state.manualMode,\n state.isSubAgent && config.experimental.allowSubAgents,\n )\n if (output.system.length > 0) {\n output.system[output.system.length - 1] += \"\\n\\n\" + newPrompt\n } else {\n output.system.push(newPrompt)\n }\n }\n}\n\nfunction runMajorGC(\n state: SessionState,\n config: PluginConfig,\n logger: Logger,\n messages: WithParts[],\n): void {\n // [FIX Bug 32] Age-based deactivation does NOT depend on modelContextLimit.\n // modelContextLimit is set in the system prompt hook, which runs AFTER the\n // messages transform hook. If we guard this with modelContextLimit, age-based\n // deactivation never runs after restart (modelContextLimit starts as undefined).\n const maxBlockAge = config.gc.maxBlockAge ?? 15\n let agedOutCount = 0\n let agedOutTokens = 0\n const now = Date.now()\n for (const [blockId, block] of state.prune.messages.blocksById) {\n if (!block.active) continue\n const age = block.survivedCount ?? 0\n if (age > maxBlockAge) {\n block.active = false\n block.deactivatedAt = now\n block.deactivatedByBlockId = undefined\n state.prune.messages.activeBlockIds.delete(Number(blockId))\n const anchorMapped = state.prune.messages.activeByAnchorMessageId.get(block.anchorMessageId)\n if (anchorMapped === Number(blockId)) {\n state.prune.messages.activeByAnchorMessageId.delete(block.anchorMessageId)\n }\n agedOutCount++\n agedOutTokens += block.summaryTokens ?? Math.round(block.summary.length / 4)\n }\n }\n\n if (agedOutCount > 0) {\n logger.info(\"Major GC: deactivated aged-out blocks\", {\n agedOutCount,\n agedOutTokens,\n maxBlockAge,\n })\n void saveSessionState(state, logger)\n }\n\n if (!state.modelContextLimit) return\n\n const currentTokens = getCurrentTokenUsage(state, messages)\n\n // Check if any active block is oversized (summary > 2x maxOldGenSummaryLength)\n // These should always be truncated regardless of token threshold\n const oversizedThreshold = config.gc.maxOldGenSummaryLength * 2\n let hasOversizedBlocks = false\n for (const [, block] of state.prune.messages.blocksById) {\n if (block.active && block.summary.length > oversizedThreshold) {\n hasOversizedBlocks = true\n break\n }\n }\n\n if (!shouldRunMajorGC(currentTokens, state.modelContextLimit, config.gc) && !hasOversizedBlocks) return\n\n const oldBlocks: import(\"./state\").CompressionBlock[] = []\n for (const [blockId, block] of state.prune.messages.blocksById) {\n if (!block.active) continue\n if (\n block.generation === \"old\" ||\n block.generation === undefined ||\n block.summary.length > config.gc.maxOldGenSummaryLength\n ) {\n oldBlocks.push(block)\n }\n }\n\n if (oldBlocks.length === 0) return\n\n const params = getGCParams(config.gc, state.modelContextLimit, currentTokens)\n const result = runTruncateGC(oldBlocks, params)\n\n if (result.compactedBlocks > 0) {\n logger.info(\"Major GC: truncated old-gen blocks\", {\n compactedBlocks: result.compactedBlocks,\n savedTokens: result.savedTokens,\n currentTokens,\n threshold: config.gc.majorGcThresholdPercent,\n })\n void saveSessionState(state, logger)\n }\n}\n\nfunction appendBatchCleanupNudge(messages: WithParts[], nudgeText: string): void {\n const lastUser = getLastUserMessage(messages)\n if (!lastUser) return\n appendToLastTextPart(lastUser, nudgeText)\n}\n\nexport function createChatMessageTransformHandler(\n client: any,\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n prompts: PromptStore,\n hostPermissions: HostPermissionSnapshot,\n) {\n return async (input: {}, output: { messages: WithParts[] }) => {\n const receivedMessages = Array.isArray(output.messages) ? output.messages.length : 0\n const messages = filterMessagesInPlace(output.messages)\n if (messages.length !== receivedMessages) {\n logger.warn(\"Skipping messages with unexpected shape during chat transform\", {\n received: receivedMessages,\n usable: messages.length,\n })\n }\n\n // [FIX Bug 37] Skip OpenCode internal agents (title/summary/compaction).\n // These small hidden LLM requests must not be mutated, and running\n // checkSession on them would corrupt shared state (currentTurn, etc.).\n if (isInternalAgentRequest(messages)) {\n logger.debug(\"Skipping message transform for internal agent request\")\n return\n }\n\n await checkSession(client, state, logger, output.messages, config.manualMode.enabled)\n\n syncCompressPermissionState(state, config, hostPermissions, output.messages)\n\n if (state.isSubAgent && !config.experimental.allowSubAgents) {\n return\n }\n\n stripHallucinations(output.messages)\n cacheSystemPromptTokens(state, output.messages)\n assignMessageRefs(state, output.messages)\n const activeBlockCountBefore = state.prune.messages.activeBlockIds.size // [FIX Bug 4]\n syncCompressionBlocks(state, logger, output.messages)\n if (state.prune.messages.activeBlockIds.size !== activeBlockCountBefore) { // [FIX Bug 4]\n void saveSessionState(state, logger) // [FIX Bug 4] persist deactivations\n }\n syncToolCache(state, config, logger, output.messages)\n buildToolIdList(state, output.messages)\n runMajorGC(state, config, logger, output.messages)\n const batchResult = runBatchCleanup(state, config, logger, output.messages)\n if (batchResult.tier === 1 && batchResult.nudgeText) {\n appendBatchCleanupNudge(output.messages, batchResult.nudgeText)\n }\n if (batchResult.mergedCount > 0) {\n void saveSessionState(state, logger)\n }\n prune(state, logger, config, output.messages)\n // [FIX Bug 2] assign refs to newly created synthetic messages from prune/filterCompressedRanges\n assignMessageRefs(state, output.messages)\n await injectExtendedSubAgentResults(\n client,\n state,\n logger,\n output.messages,\n config.experimental.allowSubAgents,\n )\n const compressionPriorities = buildPriorityMap(config, state, output.messages)\n prompts.reload()\n injectCompressNudges(\n state,\n config,\n logger,\n output.messages,\n prompts.getRuntimePrompts(),\n compressionPriorities,\n )\n injectMessageIds(state, config, output.messages, compressionPriorities)\n applyPendingManualTrigger(state, output.messages, logger)\n stripStaleMetadata(output.messages)\n\n if (state.sessionId) {\n await logger.saveContext(state.sessionId, output.messages)\n }\n }\n}\n\nexport function createCommandExecuteHandler(\n client: any,\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n workingDirectory: string,\n hostPermissions: HostPermissionSnapshot,\n) {\n return async (\n input: { command: string; sessionID: string; arguments: string },\n output: { parts: any[] },\n ) => {\n if (!config.commands.enabled) {\n return\n }\n\n if (input.command === \"acp\" || input.command === \"dcp\") {\n const messagesResponse = await client.session.messages({\n path: { id: input.sessionID },\n })\n const messages = filterMessages(messagesResponse.data || messagesResponse)\n\n await ensureSessionInitialized(\n client,\n state,\n input.sessionID,\n logger,\n messages,\n config.manualMode.enabled,\n )\n\n syncCompressPermissionState(state, config, hostPermissions, messages)\n\n const effectivePermission = compressPermission(state, config)\n if (effectivePermission === \"deny\") {\n return\n }\n\n const args = (input.arguments || \"\").trim().split(/\\s+/).filter(Boolean)\n const subcommand = args[0]?.toLowerCase() || \"\"\n const subArgs = args.slice(1)\n\n const commandCtx = {\n client,\n state,\n config,\n logger,\n sessionId: input.sessionID,\n messages,\n }\n\n if (subcommand === \"context\") {\n await handleContextCommand(commandCtx)\n throw new Error(\"__DCP_CONTEXT_HANDLED__\")\n }\n\n if (subcommand === \"stats\") {\n await handleStatsCommand(commandCtx)\n throw new Error(\"__DCP_STATS_HANDLED__\")\n }\n\n if (subcommand === \"sweep\") {\n await handleSweepCommand({\n ...commandCtx,\n args: subArgs,\n workingDirectory,\n })\n throw new Error(\"__DCP_SWEEP_HANDLED__\")\n }\n\n if (subcommand === \"manual\") {\n await handleManualToggleCommand(commandCtx, subArgs[0]?.toLowerCase())\n throw new Error(\"__DCP_MANUAL_HANDLED__\")\n }\n\n if (subcommand === \"compress\") {\n const userFocus = subArgs.join(\" \").trim()\n const prompt = await handleManualTriggerCommand(commandCtx, \"compress\", userFocus)\n if (!prompt) {\n throw new Error(\"__DCP_MANUAL_TRIGGER_BLOCKED__\")\n }\n\n state.manualMode = \"compress-pending\"\n state.pendingManualTrigger = {\n sessionId: input.sessionID,\n prompt,\n }\n const rawArgs = (input.arguments || \"\").trim()\n output.parts.length = 0\n output.parts.push({\n type: \"text\",\n text: rawArgs ? `/dcp ${rawArgs}` : `/dcp ${subcommand}`,\n })\n return\n }\n\n if (subcommand === \"decompress\") {\n await handleDecompressCommand({\n ...commandCtx,\n args: subArgs,\n })\n throw new Error(\"__DCP_DECOMPRESS_HANDLED__\")\n }\n\n if (subcommand === \"recompress\") {\n await handleRecompressCommand({\n ...commandCtx,\n args: subArgs,\n })\n throw new Error(\"__DCP_RECOMPRESS_HANDLED__\")\n }\n\n await handleHelpCommand(commandCtx)\n throw new Error(\"__DCP_HELP_HANDLED__\")\n }\n }\n}\n\nexport function createTextCompleteHandler() {\n return async (\n _input: { sessionID: string; messageID: string; partID: string },\n output: { text: string },\n ) => {\n output.text = stripHallucinationsFromString(output.text)\n }\n}\n\nexport function createEventHandler(state: SessionState, logger: Logger) {\n return async (input: { event: any }) => {\n const eventTime =\n typeof input.event?.time === \"number\" && Number.isFinite(input.event.time)\n ? input.event.time\n : typeof input.event?.properties?.time === \"number\" &&\n Number.isFinite(input.event.properties.time)\n ? input.event.properties.time\n : undefined\n\n if (input.event.type !== \"message.part.updated\") {\n return\n }\n\n const part = input.event.properties?.part\n if (part?.type !== \"tool\" || part.tool !== \"compress\") {\n return\n }\n\n if (part.state.status === \"pending\") {\n if (typeof part.callID !== \"string\" || typeof part.messageID !== \"string\") {\n return\n }\n\n const startedAt = eventTime ?? Date.now()\n const key = buildCompressionTimingKey(part.messageID, part.callID)\n if (state.compressionTiming.startsByCallId.has(key)) {\n return\n }\n state.compressionTiming.startsByCallId.set(key, startedAt)\n logger.debug(\"Recorded compression start\", {\n messageID: part.messageID,\n callID: part.callID,\n startedAt,\n })\n return\n }\n\n if (part.state.status === \"completed\") {\n if (typeof part.callID !== \"string\" || typeof part.messageID !== \"string\") {\n return\n }\n\n const key = buildCompressionTimingKey(part.messageID, part.callID)\n const start = consumeCompressionStart(state, part.messageID, part.callID)\n const durationMs = resolveCompressionDuration(start, eventTime, part.state.time)\n if (typeof durationMs !== \"number\") {\n return\n }\n\n state.compressionTiming.pendingByCallId.set(key, {\n messageId: part.messageID,\n callId: part.callID,\n durationMs,\n })\n\n const updates = applyPendingCompressionDurations(state)\n if (updates === 0) {\n return\n }\n\n await saveSessionState(state, logger)\n\n logger.info(\"Attached compression time to blocks\", {\n messageID: part.messageID,\n callID: part.callID,\n blocks: updates,\n durationMs,\n })\n return\n }\n\n if (part.state.status === \"running\") {\n return\n }\n\n if (typeof part.callID === \"string\" && typeof part.messageID === \"string\") {\n state.compressionTiming.startsByCallId.delete(\n buildCompressionTimingKey(part.messageID, part.callID),\n )\n }\n }\n}\n","export function isSecureMode(): boolean {\n return !!process.env.OPENCODE_SERVER_PASSWORD\n}\n\nexport function getAuthorizationHeader(): string | undefined {\n const password = process.env.OPENCODE_SERVER_PASSWORD\n if (!password) return undefined\n\n const username = process.env.OPENCODE_SERVER_USERNAME ?? \"opencode\"\n // Use Buffer for Node.js base64 encoding (btoa may not be available in all Node versions)\n const credentials = Buffer.from(`${username}:${password}`).toString(\"base64\")\n return `Basic ${credentials}`\n}\n\nexport function configureClientAuth(client: any): any {\n const authHeader = getAuthorizationHeader()\n\n if (!authHeader) {\n return client\n }\n\n // The SDK client has an internal client with request interceptors\n // Access the underlying client to add the interceptor\n const innerClient = client._client || client.client\n\n if (innerClient?.interceptors?.request) {\n innerClient.interceptors.request.use((request: Request) => {\n // Only add auth header if not already present\n if (!request.headers.has(\"Authorization\")) {\n request.headers.set(\"Authorization\", authHeader)\n }\n return request\n })\n }\n\n return client\n}\n","import { readFile, rm } from \"node:fs/promises\"\nimport { basename, dirname, join } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport type { PluginInput } from \"@opencode-ai/plugin\"\n\ntype PackageJson = {\n name?: string\n version?: string\n dependencies?: Record<string, string>\n}\n\ntype UpdateResult =\n | { updated: true; name: string; current: string; latest: string }\n | { updated: false; error: \"remove_failed\"; name: string; current: string; latest: string }\n | { updated: false }\n\nconst PACKAGE_NAME = \"opencode-acp\"\n\nexport function startAutoUpdate(ctx: PluginInput, enabled: boolean): void {\n if (!enabled) return\n\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 10_000)\n void checkAutoUpdate(controller.signal)\n .then((result) => {\n if (!result.updated) return\n setTimeout(() => {\n ctx.client.tui.showToast({\n body: {\n title: \"ACP update ready\",\n message: `Updated ${result.name} from ${result.current} to ${result.latest}. Restart OpenCode to finish.`,\n variant: \"info\",\n duration: 7000,\n },\n })\n }, 5000)\n })\n .catch(() => {})\n .finally(() => clearTimeout(timeout))\n}\n\nexport async function checkAutoUpdate(signal: AbortSignal): Promise<UpdateResult> {\n const packageDir = await findPackageDir(PACKAGE_NAME)\n if (!packageDir) return { updated: false }\n\n const pkg = await readPackageJson(join(packageDir, \"package.json\"))\n if (!pkg?.name || !pkg.version) return { updated: false }\n\n const latest = await fetchLatestVersion(pkg.name, signal)\n if (!latest || !isVersionNewer(latest, pkg.version)) return { updated: false }\n\n const removeDir = await updateRemoveDir(packageDir, pkg.name)\n if (!removeDir) return { updated: false }\n\n try {\n await rm(removeDir, { recursive: true, force: true })\n } catch {\n return {\n updated: false,\n error: \"remove_failed\",\n name: pkg.name,\n current: pkg.version,\n latest,\n }\n }\n\n return { updated: true, name: pkg.name, current: pkg.version, latest }\n}\n\nasync function findPackageDir(name: string) {\n let dir = dirname(fileURLToPath(import.meta.url))\n for (;;) {\n const pkg = await readPackageJson(join(dir, \"package.json\"))\n if (pkg?.name === name) return dir\n\n const parent = dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\nexport async function updateRemoveDir(packageDir: string, name: string) {\n const packageParent = dirname(packageDir)\n const nodeModulesDir = basename(packageParent).startsWith(\"@\")\n ? dirname(packageParent)\n : packageParent\n if (basename(nodeModulesDir) !== \"node_modules\") return undefined\n\n const wrapperDir = dirname(nodeModulesDir)\n const wrapperPkg = await readPackageJson(join(wrapperDir, \"package.json\"))\n const spec = wrapperSpec(wrapperDir, name) ?? wrapperPkg?.dependencies?.[name]\n if (!spec || !isAutoUpdatableSpec(spec)) return undefined\n\n return wrapperDir\n}\n\nfunction wrapperSpec(wrapperDir: string, name: string) {\n if (name.startsWith(\"@\")) {\n const [scope, pkg] = name.split(\"/\")\n if (!scope || !pkg || basename(dirname(wrapperDir)) !== scope) return undefined\n const prefix = `${pkg}@`\n const base = basename(wrapperDir)\n return base.startsWith(prefix) ? base.slice(prefix.length) : undefined\n }\n\n const prefix = `${name}@`\n const base = basename(wrapperDir)\n return base.startsWith(prefix) ? base.slice(prefix.length) : undefined\n}\n\nexport function isAutoUpdatableSpec(spec: string) {\n const value = spec.trim()\n if (!value) return false\n if (value === \"latest\" || value === \"*\") return true\n if (/^[~^]/.test(value)) return true\n if (/^(?:>=|>|<=|<)/.test(value)) return true\n if (/\\s+(?:\\|\\||-|[<>=])\\s+/.test(value)) return true\n return false\n}\n\nasync function readPackageJson(path: string): Promise<PackageJson | undefined> {\n try {\n const data = JSON.parse(await readFile(path, \"utf-8\"))\n return data && typeof data === \"object\" ? (data as PackageJson) : undefined\n } catch {\n return undefined\n }\n}\n\nasync function fetchLatestVersion(name: string, signal: AbortSignal) {\n try {\n const response = await fetch(\n `https://registry.npmjs.org/${encodeURIComponent(name)}/latest`,\n {\n signal,\n },\n )\n if (!response.ok) return undefined\n const data: unknown = await response.json()\n if (!data || typeof data !== \"object\") return undefined\n const version = (data as { version?: unknown }).version\n return typeof version === \"string\" ? version : undefined\n } catch {\n return undefined\n }\n}\n\nexport function isVersionNewer(latest: string, current: string) {\n const next = parseVersion(latest)\n const prev = parseVersion(current)\n if (!next || !prev) return false\n\n for (let i = 0; i < 3; i++) {\n if (next.parts[i] !== prev.parts[i]) return next.parts[i] > prev.parts[i]\n }\n\n if (!next.pre.length && prev.pre.length) return true\n if (next.pre.length && !prev.pre.length) return false\n\n for (let i = 0; i < Math.max(next.pre.length, prev.pre.length); i++) {\n const a = next.pre[i]\n const b = prev.pre[i]\n if (a === undefined) return false\n if (b === undefined) return true\n if (a === b) continue\n\n const aNumber = /^\\d+$/.test(a) ? Number(a) : undefined\n const bNumber = /^\\d+$/.test(b) ? Number(b) : undefined\n if (aNumber !== undefined && bNumber !== undefined) return aNumber > bNumber\n if (aNumber !== undefined) return false\n if (bNumber !== undefined) return true\n return a > b\n }\n\n return false\n}\n\nfunction parseVersion(version: string) {\n const match = version.match(/^v?(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+.+)?$/)\n if (!match) return undefined\n return {\n parts: [Number(match[1]), Number(match[2]), Number(match[3])],\n pre: match[4]?.split(\".\") ?? [],\n }\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { getConfig } from \"./lib/config\"\nimport {\n createCompressMessageTool,\n createCompressRangeTool,\n createDecompressTool,\n createMarkBlockTool,\n createUnmarkBlockTool,\n} from \"./lib/compress\"\nimport {\n compressDisabledByOpencode,\n hasExplicitToolPermission,\n type HostPermissionSnapshot,\n} from \"./lib/host-permissions\"\nimport { Logger } from \"./lib/logger\"\nimport { createSessionState } from \"./lib/state\"\nimport { PromptStore } from \"./lib/prompts/store\"\nimport {\n createChatMessageTransformHandler,\n createCommandExecuteHandler,\n createEventHandler,\n createSystemPromptHandler,\n createTextCompleteHandler,\n} from \"./lib/hooks\"\nimport { configureClientAuth, isSecureMode } from \"./lib/auth\"\nimport { startAutoUpdate } from \"./lib/update\"\n\nconst server: Plugin = (async (ctx) => {\n const config = getConfig(ctx)\n\n if (!config.enabled) {\n return {}\n }\n\n const logger = new Logger(config.debug)\n const state = createSessionState()\n const prompts = new PromptStore(logger, ctx.directory, config.experimental.customPrompts)\n const hostPermissions: HostPermissionSnapshot = {\n global: undefined,\n agents: {},\n }\n\n if (isSecureMode()) {\n configureClientAuth(ctx.client)\n // logger.info(\"Secure mode detected, configured client authentication\")\n }\n\n logger.info(\"DCP initialized\", {\n strategies: config.strategies,\n })\n\n startAutoUpdate(ctx, config.autoUpdate)\n\n const compressToolContext = {\n client: ctx.client,\n state,\n logger,\n config,\n prompts,\n }\n\n return {\n \"experimental.chat.system.transform\": createSystemPromptHandler(\n state,\n logger,\n config,\n prompts,\n ),\n \"experimental.chat.messages.transform\": createChatMessageTransformHandler(\n ctx.client,\n state,\n logger,\n config,\n prompts,\n hostPermissions,\n ) as any,\n \"experimental.text.complete\": createTextCompleteHandler(),\n \"command.execute.before\": createCommandExecuteHandler(\n ctx.client,\n state,\n logger,\n config,\n ctx.directory,\n hostPermissions,\n ),\n event: createEventHandler(state, logger),\n tool: {\n ...(config.compress.permission !== \"deny\" && {\n compress:\n config.compress.mode === \"message\"\n ? createCompressMessageTool(compressToolContext)\n : createCompressRangeTool(compressToolContext),\n decompress: createDecompressTool(compressToolContext),\n mark_block: createMarkBlockTool(compressToolContext),\n unmark_block: createUnmarkBlockTool(compressToolContext),\n }),\n },\n config: async (opencodeConfig) => {\n if (\n config.compress.permission !== \"deny\" &&\n compressDisabledByOpencode(opencodeConfig.permission)\n ) {\n config.compress.permission = \"deny\"\n }\n\n if (config.commands.enabled && config.compress.permission !== \"deny\") {\n opencodeConfig.command ??= {}\n opencodeConfig.command[\"acp\"] = {\n template: \"\",\n description: \"Show available ACP commands\",\n }\n }\n\n const toolsToAdd: string[] = []\n if (config.compress.permission !== \"deny\" && !config.experimental.allowSubAgents) {\n toolsToAdd.push(\"compress\", \"decompress\", \"mark_block\", \"unmark_block\")\n }\n\n if (toolsToAdd.length > 0) {\n const existingPrimaryTools = opencodeConfig.experimental?.primary_tools ?? []\n opencodeConfig.experimental = {\n ...opencodeConfig.experimental,\n primary_tools: [...existingPrimaryTools, ...toolsToAdd],\n }\n }\n\n if (!hasExplicitToolPermission(opencodeConfig.permission, \"compress\")) {\n const permission = opencodeConfig.permission ?? {}\n opencodeConfig.permission = {\n ...permission,\n compress: config.compress.permission,\n } as typeof permission\n }\n\n hostPermissions.global = opencodeConfig.permission\n hostPermissions.agents = Object.fromEntries(\n Object.entries(opencodeConfig.agent ?? {}).map(([name, agent]) => [\n name,\n agent?.permission,\n ]),\n )\n },\n }\n}) satisfies Plugin\n\nexport default server\n"],"mappings":"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AAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAA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","names":["value","CharacterCodes","ParseOptions","ScanError","SyntaxKind","parse","ParseErrorCode","parse","countTokens","existsSync","homedir","join","countTokens","join","homedir","existsSync","tool","tool","tool","countTokens","countTokens","tool","validateArgs","buildSchema","tool","validateArgs","countTokens","tool","tool","collectTurnNudgeAnchors","buildSchema","tool","tool","buildSchema","tool","writeFile","mkdir","join","existsSync","homedir","stack","existsSync","mkdirSync","readFileSync","writeFileSync","statSync","cpSync","join","dirname","homedir","findOpencodeDir","join","existsSync","statSync","dirname","homedir","cpSync","readFileSync","mkdirSync","writeFileSync","countTokens","message","tool","parseBlockIdArg","snapshotActiveMessages","formatAvailableBlocksMessage","message","message","countTokens","readFile","dirname","join","prefix","base"]}
|
|
1
|
+
{"version":3,"sources":["../lib/config.ts","../node_modules/jsonc-parser/lib/esm/impl/scanner.js","../node_modules/jsonc-parser/lib/esm/impl/string-intern.js","../node_modules/jsonc-parser/lib/esm/impl/parser.js","../node_modules/jsonc-parser/lib/esm/main.js","../lib/config-validation.ts","../lib/compress/message.ts","../lib/token-utils.ts","../lib/messages/shape.ts","../lib/messages/query.ts","../lib/prompts/extensions/tool.ts","../lib/message-ids.ts","../lib/compress/search.ts","../lib/compress/state.ts","../lib/compress/message-utils.ts","../lib/state/persistence.ts","../lib/state/utils.ts","../lib/compress/timing.ts","../lib/state/state.ts","../lib/state/tool-cache.ts","../lib/protected-patterns.ts","../lib/strategies/deduplication.ts","../lib/strategies/purge-errors.ts","../lib/ui/utils.ts","../lib/ui/notification.ts","../lib/compress/pipeline.ts","../lib/subagents/subagent-results.ts","../lib/compress/protected-content.ts","../lib/compress/range.ts","../lib/compress/range-utils.ts","../lib/compress/decompress.ts","../lib/messages/utils.ts","../lib/messages/prune.ts","../lib/messages/sync.ts","../lib/host-permissions.ts","../lib/compress-permission.ts","../lib/prompts/extensions/nudge.ts","../lib/messages/priority.ts","../lib/messages/inject/utils.ts","../lib/messages/inject/inject.ts","../lib/messages/inject/subagent-results.ts","../lib/messages/reasoning-strip.ts","../lib/commands/compression-targets.ts","../lib/compress/decompress-logic.ts","../lib/compress/mark-block.ts","../lib/logger.ts","../lib/prompts/store.ts","../lib/prompts/system.ts","../lib/prompts/compress-range.ts","../lib/prompts/compress-message.ts","../lib/prompts/context-limit-nudge.ts","../lib/prompts/turn-nudge.ts","../lib/prompts/iteration-nudge.ts","../lib/prompts/extensions/system.ts","../lib/prompts/index.ts","../lib/commands/context.ts","../lib/commands/decompress.ts","../lib/commands/help.ts","../lib/commands/manual.ts","../lib/commands/recompress.ts","../lib/commands/stats.ts","../lib/commands/sweep.ts","../lib/gc/truncate.ts","../lib/gc/merge.ts","../lib/hooks.ts","../lib/auth.ts","../lib/update.ts","../index.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync, copyFileSync } from \"fs\"\nimport { join, dirname } from \"path\"\nimport { homedir } from \"os\"\nimport { parse } from \"jsonc-parser/lib/esm/main.js\"\nimport type { PluginInput } from \"@opencode-ai/plugin\"\nimport { VALID_CONFIG_KEYS, getInvalidConfigKeys, validateConfigTypes, type ValidationError } from \"./config-validation\"\n\n\ntype Permission = \"ask\" | \"allow\" | \"deny\"\ntype CompressMode = \"range\" | \"message\"\n\nexport interface Deduplication {\n enabled: boolean\n protectedTools: string[]\n}\n\nexport interface CompressConfig {\n mode: CompressMode\n permission: Permission\n showCompression: boolean\n summaryBuffer: boolean\n maxContextLimit: number | `${number}%`\n minContextLimit: number | `${number}%`\n modelMaxLimits?: Record<string, number | `${number}%`>\n modelMinLimits?: Record<string, number | `${number}%`>\n nudgeFrequency: number\n iterationNudgeThreshold: number\n nudgeForce: \"strong\" | \"soft\"\n protectedTools: string[]\n protectTags: boolean\n protectUserMessages: boolean\n}\n\nexport interface Commands {\n enabled: boolean\n protectedTools: string[]\n}\n\nexport interface ManualModeConfig {\n enabled: boolean\n automaticStrategies: boolean\n}\n\nexport interface PurgeErrors {\n enabled: boolean\n turns: number\n protectedTools: string[]\n}\n\nexport interface TurnProtection {\n enabled: boolean\n turns: number\n}\n\nexport interface ExperimentalConfig {\n allowSubAgents: boolean\n customPrompts: boolean\n}\n\nexport interface BatchCleanupConfig {\n lowThreshold: number | `${number}%`\n highThreshold: number | `${number}%`\n forceThreshold: number | `${number}%`\n}\n\nexport interface GCConfig {\n algorithm: \"truncate\"\n promotionThreshold: number\n maxBlockAge: number\n maxOldGenSummaryLength: number\n majorGcThresholdPercent: number | `${number}%`\n batchCleanup: BatchCleanupConfig\n}\n\nexport interface PluginConfig {\n enabled: boolean\n autoUpdate: boolean\n debug: boolean\n pruneNotification: \"off\" | \"minimal\" | \"detailed\"\n pruneNotificationType: \"chat\" | \"toast\"\n commands: Commands\n manualMode: ManualModeConfig\n turnProtection: TurnProtection\n experimental: ExperimentalConfig\n protectedFilePatterns: string[]\n compress: CompressConfig\n gc: GCConfig\n strategies: {\n deduplication: Deduplication\n purgeErrors: PurgeErrors\n }\n}\n\ntype CompressOverride = Partial<CompressConfig>\n\nconst DEFAULT_PROTECTED_TOOLS = [\n \"task\",\n \"skill\",\n \"todowrite\",\n \"todoread\",\n \"compress\",\n \"decompress\",\n \"mark_block\",\n \"unmark_block\",\n \"batch\",\n \"plan_enter\",\n \"plan_exit\",\n \"write\",\n \"edit\",\n]\n\nconst COMPRESS_DEFAULT_PROTECTED_TOOLS = [\"task\", \"skill\", \"todowrite\", \"todoread\", \"decompress\"]\n\nexport { VALID_CONFIG_KEYS, getInvalidConfigKeys, validateConfigTypes, type ValidationError } from \"./config-validation\"\n\nfunction showConfigWarnings(\n ctx: PluginInput,\n configPath: string,\n configData: Record<string, any>,\n isProject: boolean,\n): void {\n const invalidKeys = getInvalidConfigKeys(configData)\n const typeErrors = validateConfigTypes(configData)\n\n if (invalidKeys.length === 0 && typeErrors.length === 0) {\n return\n }\n\n const configType = isProject ? \"project config\" : \"config\"\n const messages: string[] = []\n\n if (invalidKeys.length > 0) {\n const keyList = invalidKeys.slice(0, 3).join(\", \")\n const suffix = invalidKeys.length > 3 ? ` (+${invalidKeys.length - 3} more)` : \"\"\n messages.push(`Unknown keys: ${keyList}${suffix}`)\n }\n\n if (typeErrors.length > 0) {\n for (const err of typeErrors.slice(0, 2)) {\n messages.push(`${err.key}: expected ${err.expected}, got ${err.actual}`)\n }\n if (typeErrors.length > 2) {\n messages.push(`(+${typeErrors.length - 2} more type errors)`)\n }\n }\n\n setTimeout(() => {\n try {\n ctx.client.tui.showToast({\n body: {\n title: `ACP: ${configType} warning`,\n message: `${configPath}\\n${messages.join(\"\\n\")}`,\n variant: \"warning\",\n duration: 7000,\n },\n })\n } catch {}\n }, 7000)\n}\n\nconst defaultConfig: PluginConfig = {\n enabled: true,\n autoUpdate: true,\n debug: false,\n pruneNotification: \"detailed\",\n pruneNotificationType: \"chat\",\n commands: {\n enabled: true,\n protectedTools: [...DEFAULT_PROTECTED_TOOLS],\n },\n manualMode: {\n enabled: false,\n automaticStrategies: true,\n },\n turnProtection: {\n enabled: false,\n turns: 4,\n },\n experimental: {\n allowSubAgents: false,\n customPrompts: false,\n },\n protectedFilePatterns: [],\n compress: {\n mode: \"range\",\n permission: \"allow\",\n showCompression: true,\n summaryBuffer: true,\n maxContextLimit: \"55%\",\n minContextLimit: \"45%\",\n nudgeFrequency: 5,\n iterationNudgeThreshold: 15,\n nudgeForce: \"soft\",\n protectedTools: [...COMPRESS_DEFAULT_PROTECTED_TOOLS],\n protectTags: false,\n protectUserMessages: false,\n },\n strategies: {\n deduplication: {\n enabled: true,\n protectedTools: [],\n },\n purgeErrors: {\n enabled: true,\n turns: 4,\n protectedTools: [],\n },\n },\n gc: {\n algorithm: \"truncate\",\n promotionThreshold: 5,\n maxBlockAge: 15,\n maxOldGenSummaryLength: 3000,\n majorGcThresholdPercent: \"100%\",\n batchCleanup: {\n lowThreshold: \"60%\",\n highThreshold: \"75%\",\n forceThreshold: \"90%\",\n },\n },\n}\n\nconst GLOBAL_CONFIG_DIR = process.env.XDG_CONFIG_HOME\n ? join(process.env.XDG_CONFIG_HOME, \"opencode\")\n : join(homedir(), \".config\", \"opencode\")\nconst GLOBAL_CONFIG_PATH_JSONC = join(GLOBAL_CONFIG_DIR, \"acp.jsonc\")\nconst GLOBAL_CONFIG_PATH_JSON = join(GLOBAL_CONFIG_DIR, \"acp.json\")\nconst LEGACY_GLOBAL_CONFIG_PATH_JSONC = join(GLOBAL_CONFIG_DIR, \"dcp.jsonc\")\nconst LEGACY_GLOBAL_CONFIG_PATH_JSON = join(GLOBAL_CONFIG_DIR, \"dcp.json\")\n\nfunction findOpencodeDir(startDir: string): string | null {\n let current = startDir\n while (current !== \"/\") {\n const candidate = join(current, \".opencode\")\n if (existsSync(candidate) && statSync(candidate).isDirectory()) {\n return candidate\n }\n const parent = dirname(current)\n if (parent === current) {\n break\n }\n current = parent\n }\n return null\n}\n\nfunction getConfigPaths(ctx?: PluginInput): {\n global: string | null\n configDir: string | null\n project: string | null\n} {\n const global = existsSync(GLOBAL_CONFIG_PATH_JSONC)\n ? GLOBAL_CONFIG_PATH_JSONC\n : existsSync(GLOBAL_CONFIG_PATH_JSON)\n ? GLOBAL_CONFIG_PATH_JSON\n : existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSONC)\n ? LEGACY_GLOBAL_CONFIG_PATH_JSONC\n : existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSON)\n ? LEGACY_GLOBAL_CONFIG_PATH_JSON\n : null\n\n let configDir: string | null = null\n const opencodeConfigDir = process.env.OPENCODE_CONFIG_DIR\n if (opencodeConfigDir) {\n const configJsonc = join(opencodeConfigDir, \"acp.jsonc\")\n const configJson = join(opencodeConfigDir, \"acp.json\")\n const legacyJsonc = join(opencodeConfigDir, \"dcp.jsonc\")\n const legacyJson = join(opencodeConfigDir, \"dcp.json\")\n configDir = existsSync(configJsonc)\n ? configJsonc\n : existsSync(configJson)\n ? configJson\n : existsSync(legacyJsonc)\n ? legacyJsonc\n : existsSync(legacyJson)\n ? legacyJson\n : null\n }\n\n let project: string | null = null\n if (ctx?.directory) {\n const opencodeDir = findOpencodeDir(ctx.directory)\n if (opencodeDir) {\n const projectJsonc = join(opencodeDir, \"acp.jsonc\")\n const projectJson = join(opencodeDir, \"acp.json\")\n const legacyJsonc = join(opencodeDir, \"dcp.jsonc\")\n const legacyJson = join(opencodeDir, \"dcp.json\")\n project = existsSync(projectJsonc)\n ? projectJsonc\n : existsSync(projectJson)\n ? projectJson\n : existsSync(legacyJsonc)\n ? legacyJsonc\n : existsSync(legacyJson)\n ? legacyJson\n : null\n }\n }\n\n return { global, configDir, project }\n}\n\nfunction createDefaultConfig(): void {\n if (!existsSync(GLOBAL_CONFIG_DIR)) {\n mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true })\n }\n\n if (!existsSync(GLOBAL_CONFIG_PATH_JSONC)) {\n if (existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSONC)) {\n copyFileSync(LEGACY_GLOBAL_CONFIG_PATH_JSONC, GLOBAL_CONFIG_PATH_JSONC)\n console.log(\"[ACP] Migrated config from dcp.jsonc to acp.jsonc\")\n } else if (existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSON)) {\n copyFileSync(LEGACY_GLOBAL_CONFIG_PATH_JSON, GLOBAL_CONFIG_PATH_JSONC)\n console.log(\"[ACP] Migrated config from dcp.json to acp.jsonc\")\n } else {\n const configContent = `{\n \"$schema\": \"https://raw.githubusercontent.com/ranxianglei/opencode-acp/master/dcp.schema.json\"\n}\n`\n writeFileSync(GLOBAL_CONFIG_PATH_JSONC, configContent, \"utf-8\")\n }\n }\n}\n\ninterface ConfigLoadResult {\n data: Record<string, any> | null\n parseError?: string\n}\n\nfunction loadConfigFile(configPath: string): ConfigLoadResult {\n let fileContent = \"\"\n try {\n fileContent = readFileSync(configPath, \"utf-8\")\n } catch {\n return { data: null }\n }\n\n try {\n const parsed = parse(fileContent, undefined, { allowTrailingComma: true })\n if (parsed === undefined || parsed === null) {\n return { data: null, parseError: \"Config file is empty or invalid\" }\n }\n return { data: parsed }\n } catch (error: any) {\n return { data: null, parseError: error.message || \"Failed to parse config\" }\n }\n}\n\nfunction mergeStrategies(\n base: PluginConfig[\"strategies\"],\n override?: Partial<PluginConfig[\"strategies\"]>,\n): PluginConfig[\"strategies\"] {\n if (!override) {\n return base\n }\n\n return {\n deduplication: {\n enabled: override.deduplication?.enabled ?? base.deduplication.enabled,\n protectedTools: [\n ...new Set([\n ...base.deduplication.protectedTools,\n ...(override.deduplication?.protectedTools ?? []),\n ]),\n ],\n },\n purgeErrors: {\n enabled: override.purgeErrors?.enabled ?? base.purgeErrors.enabled,\n turns: override.purgeErrors?.turns ?? base.purgeErrors.turns,\n protectedTools: [\n ...new Set([\n ...base.purgeErrors.protectedTools,\n ...(override.purgeErrors?.protectedTools ?? []),\n ]),\n ],\n },\n }\n}\n\nfunction mergeCompress(\n base: PluginConfig[\"compress\"],\n override?: CompressOverride,\n): PluginConfig[\"compress\"] {\n if (!override) {\n return base\n }\n\n return {\n mode: override.mode ?? base.mode,\n permission: override.permission ?? base.permission,\n showCompression: override.showCompression ?? base.showCompression,\n summaryBuffer: override.summaryBuffer ?? base.summaryBuffer,\n maxContextLimit: override.maxContextLimit ?? base.maxContextLimit,\n minContextLimit: override.minContextLimit ?? base.minContextLimit,\n modelMaxLimits: override.modelMaxLimits ?? base.modelMaxLimits,\n modelMinLimits: override.modelMinLimits ?? base.modelMinLimits,\n nudgeFrequency: override.nudgeFrequency ?? base.nudgeFrequency,\n iterationNudgeThreshold: override.iterationNudgeThreshold ?? base.iterationNudgeThreshold,\n nudgeForce: override.nudgeForce ?? base.nudgeForce,\n protectedTools: [...new Set([...base.protectedTools, ...(override.protectedTools ?? [])])],\n protectTags: override.protectTags ?? base.protectTags,\n protectUserMessages: override.protectUserMessages ?? base.protectUserMessages,\n }\n}\n\nfunction mergeCommands(\n base: PluginConfig[\"commands\"],\n override?: Partial<PluginConfig[\"commands\"]>,\n): PluginConfig[\"commands\"] {\n if (!override) {\n return base\n }\n\n return {\n enabled: override.enabled ?? base.enabled,\n protectedTools: [...new Set([...base.protectedTools, ...(override.protectedTools ?? [])])],\n }\n}\n\nfunction mergeManualMode(\n base: PluginConfig[\"manualMode\"],\n override?: Partial<PluginConfig[\"manualMode\"]>,\n): PluginConfig[\"manualMode\"] {\n if (override === undefined) return base\n\n return {\n enabled: override.enabled ?? base.enabled,\n automaticStrategies: override.automaticStrategies ?? base.automaticStrategies,\n }\n}\n\nfunction mergeExperimental(\n base: PluginConfig[\"experimental\"],\n override?: Partial<PluginConfig[\"experimental\"]>,\n): PluginConfig[\"experimental\"] {\n if (override === undefined) return base\n\n return {\n allowSubAgents: override.allowSubAgents ?? base.allowSubAgents,\n customPrompts: override.customPrompts ?? base.customPrompts,\n }\n}\n\nfunction deepCloneConfig(config: PluginConfig): PluginConfig {\n return {\n ...config,\n commands: {\n enabled: config.commands.enabled,\n protectedTools: [...config.commands.protectedTools],\n },\n manualMode: {\n enabled: config.manualMode.enabled,\n automaticStrategies: config.manualMode.automaticStrategies,\n },\n turnProtection: { ...config.turnProtection },\n experimental: { ...config.experimental },\n protectedFilePatterns: [...config.protectedFilePatterns],\n compress: {\n ...config.compress,\n modelMaxLimits: { ...config.compress.modelMaxLimits },\n modelMinLimits: { ...config.compress.modelMinLimits },\n protectedTools: [...config.compress.protectedTools],\n },\n strategies: {\n deduplication: {\n ...config.strategies.deduplication,\n protectedTools: [...config.strategies.deduplication.protectedTools],\n },\n purgeErrors: {\n ...config.strategies.purgeErrors,\n protectedTools: [...config.strategies.purgeErrors.protectedTools],\n },\n },\n gc: {\n ...config.gc,\n batchCleanup: { ...config.gc.batchCleanup },\n },\n }\n}\n\nfunction mergeGC(base: GCConfig, override?: Partial<GCConfig>): GCConfig {\n if (!override) {\n return base\n }\n\n return {\n ...base,\n ...override,\n batchCleanup: { ...base.batchCleanup, ...(override.batchCleanup ?? {}) },\n }\n}\n\nfunction mergeLayer(config: PluginConfig, data: Record<string, any>): PluginConfig {\n return {\n enabled: data.enabled ?? config.enabled,\n autoUpdate: data.autoUpdate ?? config.autoUpdate,\n debug: data.debug ?? config.debug,\n pruneNotification: data.pruneNotification ?? config.pruneNotification,\n pruneNotificationType: data.pruneNotificationType ?? config.pruneNotificationType,\n commands: mergeCommands(config.commands, data.commands as any),\n manualMode: mergeManualMode(config.manualMode, data.manualMode as any),\n turnProtection: {\n enabled: data.turnProtection?.enabled ?? config.turnProtection.enabled,\n turns: data.turnProtection?.turns ?? config.turnProtection.turns,\n },\n experimental: mergeExperimental(config.experimental, data.experimental as any),\n protectedFilePatterns: [\n ...new Set([...config.protectedFilePatterns, ...(data.protectedFilePatterns ?? [])]),\n ],\n compress: mergeCompress(config.compress, data.compress as CompressOverride),\n gc: mergeGC(config.gc, data.gc as Partial<GCConfig>),\n strategies: mergeStrategies(config.strategies, data.strategies as any),\n }\n}\n\nfunction scheduleParseWarning(ctx: PluginInput, title: string, message: string): void {\n setTimeout(() => {\n try {\n ctx.client.tui.showToast({\n body: {\n title,\n message,\n variant: \"warning\",\n duration: 7000,\n },\n })\n } catch {}\n }, 7000)\n}\n\nexport function getConfig(ctx: PluginInput): PluginConfig {\n let config = deepCloneConfig(defaultConfig)\n const configPaths = getConfigPaths(ctx)\n\n // Migration: dcp.jsonc → acp.jsonc (must run before createDefaultConfig check)\n if (!existsSync(GLOBAL_CONFIG_PATH_JSONC) && !existsSync(GLOBAL_CONFIG_PATH_JSON)) {\n if (existsSync(GLOBAL_CONFIG_DIR) || existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSONC) || existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSON)) {\n if (!existsSync(GLOBAL_CONFIG_DIR)) {\n mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true })\n }\n if (existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSONC)) {\n copyFileSync(LEGACY_GLOBAL_CONFIG_PATH_JSONC, GLOBAL_CONFIG_PATH_JSONC)\n console.log(\"[ACP] Migrated config from dcp.jsonc to acp.jsonc\")\n } else if (existsSync(LEGACY_GLOBAL_CONFIG_PATH_JSON)) {\n copyFileSync(LEGACY_GLOBAL_CONFIG_PATH_JSON, GLOBAL_CONFIG_PATH_JSONC)\n console.log(\"[ACP] Migrated config from dcp.json to acp.jsonc\")\n }\n }\n }\n\n if (!configPaths.global && !existsSync(GLOBAL_CONFIG_PATH_JSONC)) {\n createDefaultConfig()\n }\n\n const layers: Array<{ path: string | null; name: string; isProject: boolean }> = [\n { path: configPaths.global, name: \"config\", isProject: false },\n { path: configPaths.configDir, name: \"configDir config\", isProject: true },\n { path: configPaths.project, name: \"project config\", isProject: true },\n ]\n\n for (const layer of layers) {\n if (!layer.path) {\n continue\n }\n\n const result = loadConfigFile(layer.path)\n if (result.parseError) {\n scheduleParseWarning(\n ctx,\n `ACP: Invalid ${layer.name}`,\n `${layer.path}\\n${result.parseError}\\nUsing previous/default values`,\n )\n continue\n }\n\n if (!result.data) {\n continue\n }\n\n showConfigWarnings(ctx, layer.path, result.data, layer.isProject)\n config = mergeLayer(config, result.data)\n }\n\n return config\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\n/**\n * Creates a JSON scanner on the given text.\n * If ignoreTrivia is set, whitespaces or comments are ignored.\n */\nexport function createScanner(text, ignoreTrivia = false) {\n const len = text.length;\n let pos = 0, value = '', tokenOffset = 0, token = 16 /* SyntaxKind.Unknown */, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0 /* ScanError.None */;\n function scanHexDigits(count, exact) {\n let digits = 0;\n let value = 0;\n while (digits < count || !exact) {\n let ch = text.charCodeAt(pos);\n if (ch >= 48 /* CharacterCodes._0 */ && ch <= 57 /* CharacterCodes._9 */) {\n value = value * 16 + ch - 48 /* CharacterCodes._0 */;\n }\n else if (ch >= 65 /* CharacterCodes.A */ && ch <= 70 /* CharacterCodes.F */) {\n value = value * 16 + ch - 65 /* CharacterCodes.A */ + 10;\n }\n else if (ch >= 97 /* CharacterCodes.a */ && ch <= 102 /* CharacterCodes.f */) {\n value = value * 16 + ch - 97 /* CharacterCodes.a */ + 10;\n }\n else {\n break;\n }\n pos++;\n digits++;\n }\n if (digits < count) {\n value = -1;\n }\n return value;\n }\n function setPosition(newPosition) {\n pos = newPosition;\n value = '';\n tokenOffset = 0;\n token = 16 /* SyntaxKind.Unknown */;\n scanError = 0 /* ScanError.None */;\n }\n function scanNumber() {\n let start = pos;\n if (text.charCodeAt(pos) === 48 /* CharacterCodes._0 */) {\n pos++;\n }\n else {\n pos++;\n while (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n }\n }\n if (pos < text.length && text.charCodeAt(pos) === 46 /* CharacterCodes.dot */) {\n pos++;\n if (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n while (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n }\n }\n else {\n scanError = 3 /* ScanError.UnexpectedEndOfNumber */;\n return text.substring(start, pos);\n }\n }\n let end = pos;\n if (pos < text.length && (text.charCodeAt(pos) === 69 /* CharacterCodes.E */ || text.charCodeAt(pos) === 101 /* CharacterCodes.e */)) {\n pos++;\n if (pos < text.length && text.charCodeAt(pos) === 43 /* CharacterCodes.plus */ || text.charCodeAt(pos) === 45 /* CharacterCodes.minus */) {\n pos++;\n }\n if (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n while (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n }\n end = pos;\n }\n else {\n scanError = 3 /* ScanError.UnexpectedEndOfNumber */;\n }\n }\n return text.substring(start, end);\n }\n function scanString() {\n let result = '', start = pos;\n while (true) {\n if (pos >= len) {\n result += text.substring(start, pos);\n scanError = 2 /* ScanError.UnexpectedEndOfString */;\n break;\n }\n const ch = text.charCodeAt(pos);\n if (ch === 34 /* CharacterCodes.doubleQuote */) {\n result += text.substring(start, pos);\n pos++;\n break;\n }\n if (ch === 92 /* CharacterCodes.backslash */) {\n result += text.substring(start, pos);\n pos++;\n if (pos >= len) {\n scanError = 2 /* ScanError.UnexpectedEndOfString */;\n break;\n }\n const ch2 = text.charCodeAt(pos++);\n switch (ch2) {\n case 34 /* CharacterCodes.doubleQuote */:\n result += '\\\"';\n break;\n case 92 /* CharacterCodes.backslash */:\n result += '\\\\';\n break;\n case 47 /* CharacterCodes.slash */:\n result += '/';\n break;\n case 98 /* CharacterCodes.b */:\n result += '\\b';\n break;\n case 102 /* CharacterCodes.f */:\n result += '\\f';\n break;\n case 110 /* CharacterCodes.n */:\n result += '\\n';\n break;\n case 114 /* CharacterCodes.r */:\n result += '\\r';\n break;\n case 116 /* CharacterCodes.t */:\n result += '\\t';\n break;\n case 117 /* CharacterCodes.u */:\n const ch3 = scanHexDigits(4, true);\n if (ch3 >= 0) {\n result += String.fromCharCode(ch3);\n }\n else {\n scanError = 4 /* ScanError.InvalidUnicode */;\n }\n break;\n default:\n scanError = 5 /* ScanError.InvalidEscapeCharacter */;\n }\n start = pos;\n continue;\n }\n if (ch >= 0 && ch <= 0x1f) {\n if (isLineBreak(ch)) {\n result += text.substring(start, pos);\n scanError = 2 /* ScanError.UnexpectedEndOfString */;\n break;\n }\n else {\n scanError = 6 /* ScanError.InvalidCharacter */;\n // mark as error but continue with string\n }\n }\n pos++;\n }\n return result;\n }\n function scanNext() {\n value = '';\n scanError = 0 /* ScanError.None */;\n tokenOffset = pos;\n lineStartOffset = lineNumber;\n prevTokenLineStartOffset = tokenLineStartOffset;\n if (pos >= len) {\n // at the end\n tokenOffset = len;\n return token = 17 /* SyntaxKind.EOF */;\n }\n let code = text.charCodeAt(pos);\n // trivia: whitespace\n if (isWhiteSpace(code)) {\n do {\n pos++;\n value += String.fromCharCode(code);\n code = text.charCodeAt(pos);\n } while (isWhiteSpace(code));\n return token = 15 /* SyntaxKind.Trivia */;\n }\n // trivia: newlines\n if (isLineBreak(code)) {\n pos++;\n value += String.fromCharCode(code);\n if (code === 13 /* CharacterCodes.carriageReturn */ && text.charCodeAt(pos) === 10 /* CharacterCodes.lineFeed */) {\n pos++;\n value += '\\n';\n }\n lineNumber++;\n tokenLineStartOffset = pos;\n return token = 14 /* SyntaxKind.LineBreakTrivia */;\n }\n switch (code) {\n // tokens: []{}:,\n case 123 /* CharacterCodes.openBrace */:\n pos++;\n return token = 1 /* SyntaxKind.OpenBraceToken */;\n case 125 /* CharacterCodes.closeBrace */:\n pos++;\n return token = 2 /* SyntaxKind.CloseBraceToken */;\n case 91 /* CharacterCodes.openBracket */:\n pos++;\n return token = 3 /* SyntaxKind.OpenBracketToken */;\n case 93 /* CharacterCodes.closeBracket */:\n pos++;\n return token = 4 /* SyntaxKind.CloseBracketToken */;\n case 58 /* CharacterCodes.colon */:\n pos++;\n return token = 6 /* SyntaxKind.ColonToken */;\n case 44 /* CharacterCodes.comma */:\n pos++;\n return token = 5 /* SyntaxKind.CommaToken */;\n // strings\n case 34 /* CharacterCodes.doubleQuote */:\n pos++;\n value = scanString();\n return token = 10 /* SyntaxKind.StringLiteral */;\n // comments\n case 47 /* CharacterCodes.slash */:\n const start = pos - 1;\n // Single-line comment\n if (text.charCodeAt(pos + 1) === 47 /* CharacterCodes.slash */) {\n pos += 2;\n while (pos < len) {\n if (isLineBreak(text.charCodeAt(pos))) {\n break;\n }\n pos++;\n }\n value = text.substring(start, pos);\n return token = 12 /* SyntaxKind.LineCommentTrivia */;\n }\n // Multi-line comment\n if (text.charCodeAt(pos + 1) === 42 /* CharacterCodes.asterisk */) {\n pos += 2;\n const safeLength = len - 1; // For lookahead.\n let commentClosed = false;\n while (pos < safeLength) {\n const ch = text.charCodeAt(pos);\n if (ch === 42 /* CharacterCodes.asterisk */ && text.charCodeAt(pos + 1) === 47 /* CharacterCodes.slash */) {\n pos += 2;\n commentClosed = true;\n break;\n }\n pos++;\n if (isLineBreak(ch)) {\n if (ch === 13 /* CharacterCodes.carriageReturn */ && text.charCodeAt(pos) === 10 /* CharacterCodes.lineFeed */) {\n pos++;\n }\n lineNumber++;\n tokenLineStartOffset = pos;\n }\n }\n if (!commentClosed) {\n pos++;\n scanError = 1 /* ScanError.UnexpectedEndOfComment */;\n }\n value = text.substring(start, pos);\n return token = 13 /* SyntaxKind.BlockCommentTrivia */;\n }\n // just a single slash\n value += String.fromCharCode(code);\n pos++;\n return token = 16 /* SyntaxKind.Unknown */;\n // numbers\n case 45 /* CharacterCodes.minus */:\n value += String.fromCharCode(code);\n pos++;\n if (pos === len || !isDigit(text.charCodeAt(pos))) {\n return token = 16 /* SyntaxKind.Unknown */;\n }\n // found a minus, followed by a number so\n // we fall through to proceed with scanning\n // numbers\n case 48 /* CharacterCodes._0 */:\n case 49 /* CharacterCodes._1 */:\n case 50 /* CharacterCodes._2 */:\n case 51 /* CharacterCodes._3 */:\n case 52 /* CharacterCodes._4 */:\n case 53 /* CharacterCodes._5 */:\n case 54 /* CharacterCodes._6 */:\n case 55 /* CharacterCodes._7 */:\n case 56 /* CharacterCodes._8 */:\n case 57 /* CharacterCodes._9 */:\n value += scanNumber();\n return token = 11 /* SyntaxKind.NumericLiteral */;\n // literals and unknown symbols\n default:\n // is a literal? Read the full word.\n while (pos < len && isUnknownContentCharacter(code)) {\n pos++;\n code = text.charCodeAt(pos);\n }\n if (tokenOffset !== pos) {\n value = text.substring(tokenOffset, pos);\n // keywords: true, false, null\n switch (value) {\n case 'true': return token = 8 /* SyntaxKind.TrueKeyword */;\n case 'false': return token = 9 /* SyntaxKind.FalseKeyword */;\n case 'null': return token = 7 /* SyntaxKind.NullKeyword */;\n }\n return token = 16 /* SyntaxKind.Unknown */;\n }\n // some\n value += String.fromCharCode(code);\n pos++;\n return token = 16 /* SyntaxKind.Unknown */;\n }\n }\n function isUnknownContentCharacter(code) {\n if (isWhiteSpace(code) || isLineBreak(code)) {\n return false;\n }\n switch (code) {\n case 125 /* CharacterCodes.closeBrace */:\n case 93 /* CharacterCodes.closeBracket */:\n case 123 /* CharacterCodes.openBrace */:\n case 91 /* CharacterCodes.openBracket */:\n case 34 /* CharacterCodes.doubleQuote */:\n case 58 /* CharacterCodes.colon */:\n case 44 /* CharacterCodes.comma */:\n case 47 /* CharacterCodes.slash */:\n return false;\n }\n return true;\n }\n function scanNextNonTrivia() {\n let result;\n do {\n result = scanNext();\n } while (result >= 12 /* SyntaxKind.LineCommentTrivia */ && result <= 15 /* SyntaxKind.Trivia */);\n return result;\n }\n return {\n setPosition: setPosition,\n getPosition: () => pos,\n scan: ignoreTrivia ? scanNextNonTrivia : scanNext,\n getToken: () => token,\n getTokenValue: () => value,\n getTokenOffset: () => tokenOffset,\n getTokenLength: () => pos - tokenOffset,\n getTokenStartLine: () => lineStartOffset,\n getTokenStartCharacter: () => tokenOffset - prevTokenLineStartOffset,\n getTokenError: () => scanError,\n };\n}\nfunction isWhiteSpace(ch) {\n return ch === 32 /* CharacterCodes.space */ || ch === 9 /* CharacterCodes.tab */;\n}\nfunction isLineBreak(ch) {\n return ch === 10 /* CharacterCodes.lineFeed */ || ch === 13 /* CharacterCodes.carriageReturn */;\n}\nfunction isDigit(ch) {\n return ch >= 48 /* CharacterCodes._0 */ && ch <= 57 /* CharacterCodes._9 */;\n}\nvar CharacterCodes;\n(function (CharacterCodes) {\n CharacterCodes[CharacterCodes[\"lineFeed\"] = 10] = \"lineFeed\";\n CharacterCodes[CharacterCodes[\"carriageReturn\"] = 13] = \"carriageReturn\";\n CharacterCodes[CharacterCodes[\"space\"] = 32] = \"space\";\n CharacterCodes[CharacterCodes[\"_0\"] = 48] = \"_0\";\n CharacterCodes[CharacterCodes[\"_1\"] = 49] = \"_1\";\n CharacterCodes[CharacterCodes[\"_2\"] = 50] = \"_2\";\n CharacterCodes[CharacterCodes[\"_3\"] = 51] = \"_3\";\n CharacterCodes[CharacterCodes[\"_4\"] = 52] = \"_4\";\n CharacterCodes[CharacterCodes[\"_5\"] = 53] = \"_5\";\n CharacterCodes[CharacterCodes[\"_6\"] = 54] = \"_6\";\n CharacterCodes[CharacterCodes[\"_7\"] = 55] = \"_7\";\n CharacterCodes[CharacterCodes[\"_8\"] = 56] = \"_8\";\n CharacterCodes[CharacterCodes[\"_9\"] = 57] = \"_9\";\n CharacterCodes[CharacterCodes[\"a\"] = 97] = \"a\";\n CharacterCodes[CharacterCodes[\"b\"] = 98] = \"b\";\n CharacterCodes[CharacterCodes[\"c\"] = 99] = \"c\";\n CharacterCodes[CharacterCodes[\"d\"] = 100] = \"d\";\n CharacterCodes[CharacterCodes[\"e\"] = 101] = \"e\";\n CharacterCodes[CharacterCodes[\"f\"] = 102] = \"f\";\n CharacterCodes[CharacterCodes[\"g\"] = 103] = \"g\";\n CharacterCodes[CharacterCodes[\"h\"] = 104] = \"h\";\n CharacterCodes[CharacterCodes[\"i\"] = 105] = \"i\";\n CharacterCodes[CharacterCodes[\"j\"] = 106] = \"j\";\n CharacterCodes[CharacterCodes[\"k\"] = 107] = \"k\";\n CharacterCodes[CharacterCodes[\"l\"] = 108] = \"l\";\n CharacterCodes[CharacterCodes[\"m\"] = 109] = \"m\";\n CharacterCodes[CharacterCodes[\"n\"] = 110] = \"n\";\n CharacterCodes[CharacterCodes[\"o\"] = 111] = \"o\";\n CharacterCodes[CharacterCodes[\"p\"] = 112] = \"p\";\n CharacterCodes[CharacterCodes[\"q\"] = 113] = \"q\";\n CharacterCodes[CharacterCodes[\"r\"] = 114] = \"r\";\n CharacterCodes[CharacterCodes[\"s\"] = 115] = \"s\";\n CharacterCodes[CharacterCodes[\"t\"] = 116] = \"t\";\n CharacterCodes[CharacterCodes[\"u\"] = 117] = \"u\";\n CharacterCodes[CharacterCodes[\"v\"] = 118] = \"v\";\n CharacterCodes[CharacterCodes[\"w\"] = 119] = \"w\";\n CharacterCodes[CharacterCodes[\"x\"] = 120] = \"x\";\n CharacterCodes[CharacterCodes[\"y\"] = 121] = \"y\";\n CharacterCodes[CharacterCodes[\"z\"] = 122] = \"z\";\n CharacterCodes[CharacterCodes[\"A\"] = 65] = \"A\";\n CharacterCodes[CharacterCodes[\"B\"] = 66] = \"B\";\n CharacterCodes[CharacterCodes[\"C\"] = 67] = \"C\";\n CharacterCodes[CharacterCodes[\"D\"] = 68] = \"D\";\n CharacterCodes[CharacterCodes[\"E\"] = 69] = \"E\";\n CharacterCodes[CharacterCodes[\"F\"] = 70] = \"F\";\n CharacterCodes[CharacterCodes[\"G\"] = 71] = \"G\";\n CharacterCodes[CharacterCodes[\"H\"] = 72] = \"H\";\n CharacterCodes[CharacterCodes[\"I\"] = 73] = \"I\";\n CharacterCodes[CharacterCodes[\"J\"] = 74] = \"J\";\n CharacterCodes[CharacterCodes[\"K\"] = 75] = \"K\";\n CharacterCodes[CharacterCodes[\"L\"] = 76] = \"L\";\n CharacterCodes[CharacterCodes[\"M\"] = 77] = \"M\";\n CharacterCodes[CharacterCodes[\"N\"] = 78] = \"N\";\n CharacterCodes[CharacterCodes[\"O\"] = 79] = \"O\";\n CharacterCodes[CharacterCodes[\"P\"] = 80] = \"P\";\n CharacterCodes[CharacterCodes[\"Q\"] = 81] = \"Q\";\n CharacterCodes[CharacterCodes[\"R\"] = 82] = \"R\";\n CharacterCodes[CharacterCodes[\"S\"] = 83] = \"S\";\n CharacterCodes[CharacterCodes[\"T\"] = 84] = \"T\";\n CharacterCodes[CharacterCodes[\"U\"] = 85] = \"U\";\n CharacterCodes[CharacterCodes[\"V\"] = 86] = \"V\";\n CharacterCodes[CharacterCodes[\"W\"] = 87] = \"W\";\n CharacterCodes[CharacterCodes[\"X\"] = 88] = \"X\";\n CharacterCodes[CharacterCodes[\"Y\"] = 89] = \"Y\";\n CharacterCodes[CharacterCodes[\"Z\"] = 90] = \"Z\";\n CharacterCodes[CharacterCodes[\"asterisk\"] = 42] = \"asterisk\";\n CharacterCodes[CharacterCodes[\"backslash\"] = 92] = \"backslash\";\n CharacterCodes[CharacterCodes[\"closeBrace\"] = 125] = \"closeBrace\";\n CharacterCodes[CharacterCodes[\"closeBracket\"] = 93] = \"closeBracket\";\n CharacterCodes[CharacterCodes[\"colon\"] = 58] = \"colon\";\n CharacterCodes[CharacterCodes[\"comma\"] = 44] = \"comma\";\n CharacterCodes[CharacterCodes[\"dot\"] = 46] = \"dot\";\n CharacterCodes[CharacterCodes[\"doubleQuote\"] = 34] = \"doubleQuote\";\n CharacterCodes[CharacterCodes[\"minus\"] = 45] = \"minus\";\n CharacterCodes[CharacterCodes[\"openBrace\"] = 123] = \"openBrace\";\n CharacterCodes[CharacterCodes[\"openBracket\"] = 91] = \"openBracket\";\n CharacterCodes[CharacterCodes[\"plus\"] = 43] = \"plus\";\n CharacterCodes[CharacterCodes[\"slash\"] = 47] = \"slash\";\n CharacterCodes[CharacterCodes[\"formFeed\"] = 12] = \"formFeed\";\n CharacterCodes[CharacterCodes[\"tab\"] = 9] = \"tab\";\n})(CharacterCodes || (CharacterCodes = {}));\n","export const cachedSpaces = new Array(20).fill(0).map((_, index) => {\n return ' '.repeat(index);\n});\nconst maxCachedValues = 200;\nexport const cachedBreakLinesWithSpaces = {\n ' ': {\n '\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\n' + ' '.repeat(index);\n }),\n '\\r': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r' + ' '.repeat(index);\n }),\n '\\r\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r\\n' + ' '.repeat(index);\n }),\n },\n '\\t': {\n '\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\n' + '\\t'.repeat(index);\n }),\n '\\r': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r' + '\\t'.repeat(index);\n }),\n '\\r\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r\\n' + '\\t'.repeat(index);\n }),\n }\n};\nexport const supportedEols = ['\\n', '\\r', '\\r\\n'];\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\nimport { createScanner } from './scanner';\nvar ParseOptions;\n(function (ParseOptions) {\n ParseOptions.DEFAULT = {\n allowTrailingComma: false\n };\n})(ParseOptions || (ParseOptions = {}));\n/**\n * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.\n */\nexport function getLocation(text, position) {\n const segments = []; // strings or numbers\n const earlyReturnException = new Object();\n let previousNode = undefined;\n const previousNodeInst = {\n value: {},\n offset: 0,\n length: 0,\n type: 'object',\n parent: undefined\n };\n let isAtPropertyKey = false;\n function setPreviousNode(value, offset, length, type) {\n previousNodeInst.value = value;\n previousNodeInst.offset = offset;\n previousNodeInst.length = length;\n previousNodeInst.type = type;\n previousNodeInst.colonOffset = undefined;\n previousNode = previousNodeInst;\n }\n try {\n visit(text, {\n onObjectBegin: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n isAtPropertyKey = position > offset;\n segments.push(''); // push a placeholder (will be replaced)\n },\n onObjectProperty: (name, offset, length) => {\n if (position < offset) {\n throw earlyReturnException;\n }\n setPreviousNode(name, offset, length, 'property');\n segments[segments.length - 1] = name;\n if (position <= offset + length) {\n throw earlyReturnException;\n }\n },\n onObjectEnd: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.pop();\n },\n onArrayBegin: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.push(0);\n },\n onArrayEnd: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.pop();\n },\n onLiteralValue: (value, offset, length) => {\n if (position < offset) {\n throw earlyReturnException;\n }\n setPreviousNode(value, offset, length, getNodeType(value));\n if (position <= offset + length) {\n throw earlyReturnException;\n }\n },\n onSeparator: (sep, offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n if (sep === ':' && previousNode && previousNode.type === 'property') {\n previousNode.colonOffset = offset;\n isAtPropertyKey = false;\n previousNode = undefined;\n }\n else if (sep === ',') {\n const last = segments[segments.length - 1];\n if (typeof last === 'number') {\n segments[segments.length - 1] = last + 1;\n }\n else {\n isAtPropertyKey = true;\n segments[segments.length - 1] = '';\n }\n previousNode = undefined;\n }\n }\n });\n }\n catch (e) {\n if (e !== earlyReturnException) {\n throw e;\n }\n }\n return {\n path: segments,\n previousNode,\n isAtPropertyKey,\n matches: (pattern) => {\n let k = 0;\n for (let i = 0; k < pattern.length && i < segments.length; i++) {\n if (pattern[k] === segments[i] || pattern[k] === '*') {\n k++;\n }\n else if (pattern[k] !== '**') {\n return false;\n }\n }\n return k === pattern.length;\n }\n };\n}\n/**\n * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n * Therefore always check the errors list to find out if the input was valid.\n */\nexport function parse(text, errors = [], options = ParseOptions.DEFAULT) {\n let currentProperty = null;\n let currentParent = [];\n const previousParents = [];\n function onValue(value) {\n if (Array.isArray(currentParent)) {\n currentParent.push(value);\n }\n else if (currentProperty !== null) {\n currentParent[currentProperty] = value;\n }\n }\n const visitor = {\n onObjectBegin: () => {\n const object = {};\n onValue(object);\n previousParents.push(currentParent);\n currentParent = object;\n currentProperty = null;\n },\n onObjectProperty: (name) => {\n currentProperty = name;\n },\n onObjectEnd: () => {\n currentParent = previousParents.pop();\n },\n onArrayBegin: () => {\n const array = [];\n onValue(array);\n previousParents.push(currentParent);\n currentParent = array;\n currentProperty = null;\n },\n onArrayEnd: () => {\n currentParent = previousParents.pop();\n },\n onLiteralValue: onValue,\n onError: (error, offset, length) => {\n errors.push({ error, offset, length });\n }\n };\n visit(text, visitor, options);\n return currentParent[0];\n}\n/**\n * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n */\nexport function parseTree(text, errors = [], options = ParseOptions.DEFAULT) {\n let currentParent = { type: 'array', offset: -1, length: -1, children: [], parent: undefined }; // artificial root\n function ensurePropertyComplete(endOffset) {\n if (currentParent.type === 'property') {\n currentParent.length = endOffset - currentParent.offset;\n currentParent = currentParent.parent;\n }\n }\n function onValue(valueNode) {\n currentParent.children.push(valueNode);\n return valueNode;\n }\n const visitor = {\n onObjectBegin: (offset) => {\n currentParent = onValue({ type: 'object', offset, length: -1, parent: currentParent, children: [] });\n },\n onObjectProperty: (name, offset, length) => {\n currentParent = onValue({ type: 'property', offset, length: -1, parent: currentParent, children: [] });\n currentParent.children.push({ type: 'string', value: name, offset, length, parent: currentParent });\n },\n onObjectEnd: (offset, length) => {\n ensurePropertyComplete(offset + length); // in case of a missing value for a property: make sure property is complete\n currentParent.length = offset + length - currentParent.offset;\n currentParent = currentParent.parent;\n ensurePropertyComplete(offset + length);\n },\n onArrayBegin: (offset, length) => {\n currentParent = onValue({ type: 'array', offset, length: -1, parent: currentParent, children: [] });\n },\n onArrayEnd: (offset, length) => {\n currentParent.length = offset + length - currentParent.offset;\n currentParent = currentParent.parent;\n ensurePropertyComplete(offset + length);\n },\n onLiteralValue: (value, offset, length) => {\n onValue({ type: getNodeType(value), offset, length, parent: currentParent, value });\n ensurePropertyComplete(offset + length);\n },\n onSeparator: (sep, offset, length) => {\n if (currentParent.type === 'property') {\n if (sep === ':') {\n currentParent.colonOffset = offset;\n }\n else if (sep === ',') {\n ensurePropertyComplete(offset);\n }\n }\n },\n onError: (error, offset, length) => {\n errors.push({ error, offset, length });\n }\n };\n visit(text, visitor, options);\n const result = currentParent.children[0];\n if (result) {\n delete result.parent;\n }\n return result;\n}\n/**\n * Finds the node at the given path in a JSON DOM.\n */\nexport function findNodeAtLocation(root, path) {\n if (!root) {\n return undefined;\n }\n let node = root;\n for (let segment of path) {\n if (typeof segment === 'string') {\n if (node.type !== 'object' || !Array.isArray(node.children)) {\n return undefined;\n }\n let found = false;\n for (const propertyNode of node.children) {\n if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment && propertyNode.children.length === 2) {\n node = propertyNode.children[1];\n found = true;\n break;\n }\n }\n if (!found) {\n return undefined;\n }\n }\n else {\n const index = segment;\n if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {\n return undefined;\n }\n node = node.children[index];\n }\n }\n return node;\n}\n/**\n * Gets the JSON path of the given JSON DOM node\n */\nexport function getNodePath(node) {\n if (!node.parent || !node.parent.children) {\n return [];\n }\n const path = getNodePath(node.parent);\n if (node.parent.type === 'property') {\n const key = node.parent.children[0].value;\n path.push(key);\n }\n else if (node.parent.type === 'array') {\n const index = node.parent.children.indexOf(node);\n if (index !== -1) {\n path.push(index);\n }\n }\n return path;\n}\n/**\n * Evaluates the JavaScript object of the given JSON DOM node\n */\nexport function getNodeValue(node) {\n switch (node.type) {\n case 'array':\n return node.children.map(getNodeValue);\n case 'object':\n const obj = Object.create(null);\n for (let prop of node.children) {\n const valueNode = prop.children[1];\n if (valueNode) {\n obj[prop.children[0].value] = getNodeValue(valueNode);\n }\n }\n return obj;\n case 'null':\n case 'string':\n case 'number':\n case 'boolean':\n return node.value;\n default:\n return undefined;\n }\n}\nexport function contains(node, offset, includeRightBound = false) {\n return (offset >= node.offset && offset < (node.offset + node.length)) || includeRightBound && (offset === (node.offset + node.length));\n}\n/**\n * Finds the most inner node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.\n */\nexport function findNodeAtOffset(node, offset, includeRightBound = false) {\n if (contains(node, offset, includeRightBound)) {\n const children = node.children;\n if (Array.isArray(children)) {\n for (let i = 0; i < children.length && children[i].offset <= offset; i++) {\n const item = findNodeAtOffset(children[i], offset, includeRightBound);\n if (item) {\n return item;\n }\n }\n }\n return node;\n }\n return undefined;\n}\n/**\n * Parses the given text and invokes the visitor functions for each object, array and literal reached.\n */\nexport function visit(text, visitor, options = ParseOptions.DEFAULT) {\n const _scanner = createScanner(text, false);\n // Important: Only pass copies of this to visitor functions to prevent accidental modification, and\n // to not affect visitor functions which stored a reference to a previous JSONPath\n const _jsonPath = [];\n // Depth of onXXXBegin() callbacks suppressed. onXXXEnd() decrements this if it isn't 0 already.\n // Callbacks are only called when this value is 0.\n let suppressedCallbacks = 0;\n function toNoArgVisit(visitFunction) {\n return visitFunction ? () => suppressedCallbacks === 0 && visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;\n }\n function toOneArgVisit(visitFunction) {\n return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;\n }\n function toOneArgVisitWithPath(visitFunction) {\n return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice()) : () => true;\n }\n function toBeginVisit(visitFunction) {\n return visitFunction ?\n () => {\n if (suppressedCallbacks > 0) {\n suppressedCallbacks++;\n }\n else {\n let cbReturn = visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice());\n if (cbReturn === false) {\n suppressedCallbacks = 1;\n }\n }\n }\n : () => true;\n }\n function toEndVisit(visitFunction) {\n return visitFunction ?\n () => {\n if (suppressedCallbacks > 0) {\n suppressedCallbacks--;\n }\n if (suppressedCallbacks === 0) {\n visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());\n }\n }\n : () => true;\n }\n const onObjectBegin = toBeginVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisitWithPath(visitor.onObjectProperty), onObjectEnd = toEndVisit(visitor.onObjectEnd), onArrayBegin = toBeginVisit(visitor.onArrayBegin), onArrayEnd = toEndVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisitWithPath(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);\n const disallowComments = options && options.disallowComments;\n const allowTrailingComma = options && options.allowTrailingComma;\n function scanNext() {\n while (true) {\n const token = _scanner.scan();\n switch (_scanner.getTokenError()) {\n case 4 /* ScanError.InvalidUnicode */:\n handleError(14 /* ParseErrorCode.InvalidUnicode */);\n break;\n case 5 /* ScanError.InvalidEscapeCharacter */:\n handleError(15 /* ParseErrorCode.InvalidEscapeCharacter */);\n break;\n case 3 /* ScanError.UnexpectedEndOfNumber */:\n handleError(13 /* ParseErrorCode.UnexpectedEndOfNumber */);\n break;\n case 1 /* ScanError.UnexpectedEndOfComment */:\n if (!disallowComments) {\n handleError(11 /* ParseErrorCode.UnexpectedEndOfComment */);\n }\n break;\n case 2 /* ScanError.UnexpectedEndOfString */:\n handleError(12 /* ParseErrorCode.UnexpectedEndOfString */);\n break;\n case 6 /* ScanError.InvalidCharacter */:\n handleError(16 /* ParseErrorCode.InvalidCharacter */);\n break;\n }\n switch (token) {\n case 12 /* SyntaxKind.LineCommentTrivia */:\n case 13 /* SyntaxKind.BlockCommentTrivia */:\n if (disallowComments) {\n handleError(10 /* ParseErrorCode.InvalidCommentToken */);\n }\n else {\n onComment();\n }\n break;\n case 16 /* SyntaxKind.Unknown */:\n handleError(1 /* ParseErrorCode.InvalidSymbol */);\n break;\n case 15 /* SyntaxKind.Trivia */:\n case 14 /* SyntaxKind.LineBreakTrivia */:\n break;\n default:\n return token;\n }\n }\n }\n function handleError(error, skipUntilAfter = [], skipUntil = []) {\n onError(error);\n if (skipUntilAfter.length + skipUntil.length > 0) {\n let token = _scanner.getToken();\n while (token !== 17 /* SyntaxKind.EOF */) {\n if (skipUntilAfter.indexOf(token) !== -1) {\n scanNext();\n break;\n }\n else if (skipUntil.indexOf(token) !== -1) {\n break;\n }\n token = scanNext();\n }\n }\n }\n function parseString(isValue) {\n const value = _scanner.getTokenValue();\n if (isValue) {\n onLiteralValue(value);\n }\n else {\n onObjectProperty(value);\n // add property name afterwards\n _jsonPath.push(value);\n }\n scanNext();\n return true;\n }\n function parseLiteral() {\n switch (_scanner.getToken()) {\n case 11 /* SyntaxKind.NumericLiteral */:\n const tokenValue = _scanner.getTokenValue();\n let value = Number(tokenValue);\n if (isNaN(value)) {\n handleError(2 /* ParseErrorCode.InvalidNumberFormat */);\n value = 0;\n }\n onLiteralValue(value);\n break;\n case 7 /* SyntaxKind.NullKeyword */:\n onLiteralValue(null);\n break;\n case 8 /* SyntaxKind.TrueKeyword */:\n onLiteralValue(true);\n break;\n case 9 /* SyntaxKind.FalseKeyword */:\n onLiteralValue(false);\n break;\n default:\n return false;\n }\n scanNext();\n return true;\n }\n function parseProperty() {\n if (_scanner.getToken() !== 10 /* SyntaxKind.StringLiteral */) {\n handleError(3 /* ParseErrorCode.PropertyNameExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n return false;\n }\n parseString(false);\n if (_scanner.getToken() === 6 /* SyntaxKind.ColonToken */) {\n onSeparator(':');\n scanNext(); // consume colon\n if (!parseValue()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n }\n else {\n handleError(5 /* ParseErrorCode.ColonExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n _jsonPath.pop(); // remove processed property name\n return true;\n }\n function parseObject() {\n onObjectBegin();\n scanNext(); // consume open brace\n let needsComma = false;\n while (_scanner.getToken() !== 2 /* SyntaxKind.CloseBraceToken */ && _scanner.getToken() !== 17 /* SyntaxKind.EOF */) {\n if (_scanner.getToken() === 5 /* SyntaxKind.CommaToken */) {\n if (!needsComma) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n }\n onSeparator(',');\n scanNext(); // consume comma\n if (_scanner.getToken() === 2 /* SyntaxKind.CloseBraceToken */ && allowTrailingComma) {\n break;\n }\n }\n else if (needsComma) {\n handleError(6 /* ParseErrorCode.CommaExpected */, [], []);\n }\n if (!parseProperty()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n needsComma = true;\n }\n onObjectEnd();\n if (_scanner.getToken() !== 2 /* SyntaxKind.CloseBraceToken */) {\n handleError(7 /* ParseErrorCode.CloseBraceExpected */, [2 /* SyntaxKind.CloseBraceToken */], []);\n }\n else {\n scanNext(); // consume close brace\n }\n return true;\n }\n function parseArray() {\n onArrayBegin();\n scanNext(); // consume open bracket\n let isFirstElement = true;\n let needsComma = false;\n while (_scanner.getToken() !== 4 /* SyntaxKind.CloseBracketToken */ && _scanner.getToken() !== 17 /* SyntaxKind.EOF */) {\n if (_scanner.getToken() === 5 /* SyntaxKind.CommaToken */) {\n if (!needsComma) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n }\n onSeparator(',');\n scanNext(); // consume comma\n if (_scanner.getToken() === 4 /* SyntaxKind.CloseBracketToken */ && allowTrailingComma) {\n break;\n }\n }\n else if (needsComma) {\n handleError(6 /* ParseErrorCode.CommaExpected */, [], []);\n }\n if (isFirstElement) {\n _jsonPath.push(0);\n isFirstElement = false;\n }\n else {\n _jsonPath[_jsonPath.length - 1]++;\n }\n if (!parseValue()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], [4 /* SyntaxKind.CloseBracketToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n needsComma = true;\n }\n onArrayEnd();\n if (!isFirstElement) {\n _jsonPath.pop(); // remove array index\n }\n if (_scanner.getToken() !== 4 /* SyntaxKind.CloseBracketToken */) {\n handleError(8 /* ParseErrorCode.CloseBracketExpected */, [4 /* SyntaxKind.CloseBracketToken */], []);\n }\n else {\n scanNext(); // consume close bracket\n }\n return true;\n }\n function parseValue() {\n switch (_scanner.getToken()) {\n case 3 /* SyntaxKind.OpenBracketToken */:\n return parseArray();\n case 1 /* SyntaxKind.OpenBraceToken */:\n return parseObject();\n case 10 /* SyntaxKind.StringLiteral */:\n return parseString(true);\n default:\n return parseLiteral();\n }\n }\n scanNext();\n if (_scanner.getToken() === 17 /* SyntaxKind.EOF */) {\n if (options.allowEmptyContent) {\n return true;\n }\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n return false;\n }\n if (!parseValue()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n return false;\n }\n if (_scanner.getToken() !== 17 /* SyntaxKind.EOF */) {\n handleError(9 /* ParseErrorCode.EndOfFileExpected */, [], []);\n }\n return true;\n}\n/**\n * Takes JSON with JavaScript-style comments and remove\n * them. Optionally replaces every none-newline character\n * of comments with a replaceCharacter\n */\nexport function stripComments(text, replaceCh) {\n let _scanner = createScanner(text), parts = [], kind, offset = 0, pos;\n do {\n pos = _scanner.getPosition();\n kind = _scanner.scan();\n switch (kind) {\n case 12 /* SyntaxKind.LineCommentTrivia */:\n case 13 /* SyntaxKind.BlockCommentTrivia */:\n case 17 /* SyntaxKind.EOF */:\n if (offset !== pos) {\n parts.push(text.substring(offset, pos));\n }\n if (replaceCh !== undefined) {\n parts.push(_scanner.getTokenValue().replace(/[^\\r\\n]/g, replaceCh));\n }\n offset = _scanner.getPosition();\n break;\n }\n } while (kind !== 17 /* SyntaxKind.EOF */);\n return parts.join('');\n}\nexport function getNodeType(value) {\n switch (typeof value) {\n case 'boolean': return 'boolean';\n case 'number': return 'number';\n case 'string': return 'string';\n case 'object': {\n if (!value) {\n return 'null';\n }\n else if (Array.isArray(value)) {\n return 'array';\n }\n return 'object';\n }\n default: return 'null';\n }\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\nimport * as formatter from './impl/format';\nimport * as edit from './impl/edit';\nimport * as scanner from './impl/scanner';\nimport * as parser from './impl/parser';\n/**\n * Creates a JSON scanner on the given text.\n * If ignoreTrivia is set, whitespaces or comments are ignored.\n */\nexport const createScanner = scanner.createScanner;\nexport var ScanError;\n(function (ScanError) {\n ScanError[ScanError[\"None\"] = 0] = \"None\";\n ScanError[ScanError[\"UnexpectedEndOfComment\"] = 1] = \"UnexpectedEndOfComment\";\n ScanError[ScanError[\"UnexpectedEndOfString\"] = 2] = \"UnexpectedEndOfString\";\n ScanError[ScanError[\"UnexpectedEndOfNumber\"] = 3] = \"UnexpectedEndOfNumber\";\n ScanError[ScanError[\"InvalidUnicode\"] = 4] = \"InvalidUnicode\";\n ScanError[ScanError[\"InvalidEscapeCharacter\"] = 5] = \"InvalidEscapeCharacter\";\n ScanError[ScanError[\"InvalidCharacter\"] = 6] = \"InvalidCharacter\";\n})(ScanError || (ScanError = {}));\nexport var SyntaxKind;\n(function (SyntaxKind) {\n SyntaxKind[SyntaxKind[\"OpenBraceToken\"] = 1] = \"OpenBraceToken\";\n SyntaxKind[SyntaxKind[\"CloseBraceToken\"] = 2] = \"CloseBraceToken\";\n SyntaxKind[SyntaxKind[\"OpenBracketToken\"] = 3] = \"OpenBracketToken\";\n SyntaxKind[SyntaxKind[\"CloseBracketToken\"] = 4] = \"CloseBracketToken\";\n SyntaxKind[SyntaxKind[\"CommaToken\"] = 5] = \"CommaToken\";\n SyntaxKind[SyntaxKind[\"ColonToken\"] = 6] = \"ColonToken\";\n SyntaxKind[SyntaxKind[\"NullKeyword\"] = 7] = \"NullKeyword\";\n SyntaxKind[SyntaxKind[\"TrueKeyword\"] = 8] = \"TrueKeyword\";\n SyntaxKind[SyntaxKind[\"FalseKeyword\"] = 9] = \"FalseKeyword\";\n SyntaxKind[SyntaxKind[\"StringLiteral\"] = 10] = \"StringLiteral\";\n SyntaxKind[SyntaxKind[\"NumericLiteral\"] = 11] = \"NumericLiteral\";\n SyntaxKind[SyntaxKind[\"LineCommentTrivia\"] = 12] = \"LineCommentTrivia\";\n SyntaxKind[SyntaxKind[\"BlockCommentTrivia\"] = 13] = \"BlockCommentTrivia\";\n SyntaxKind[SyntaxKind[\"LineBreakTrivia\"] = 14] = \"LineBreakTrivia\";\n SyntaxKind[SyntaxKind[\"Trivia\"] = 15] = \"Trivia\";\n SyntaxKind[SyntaxKind[\"Unknown\"] = 16] = \"Unknown\";\n SyntaxKind[SyntaxKind[\"EOF\"] = 17] = \"EOF\";\n})(SyntaxKind || (SyntaxKind = {}));\n/**\n * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.\n */\nexport const getLocation = parser.getLocation;\n/**\n * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n * Therefore, always check the errors list to find out if the input was valid.\n */\nexport const parse = parser.parse;\n/**\n * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n */\nexport const parseTree = parser.parseTree;\n/**\n * Finds the node at the given path in a JSON DOM.\n */\nexport const findNodeAtLocation = parser.findNodeAtLocation;\n/**\n * Finds the innermost node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.\n */\nexport const findNodeAtOffset = parser.findNodeAtOffset;\n/**\n * Gets the JSON path of the given JSON DOM node\n */\nexport const getNodePath = parser.getNodePath;\n/**\n * Evaluates the JavaScript object of the given JSON DOM node\n */\nexport const getNodeValue = parser.getNodeValue;\n/**\n * Parses the given text and invokes the visitor functions for each object, array and literal reached.\n */\nexport const visit = parser.visit;\n/**\n * Takes JSON with JavaScript-style comments and remove\n * them. Optionally replaces every none-newline character\n * of comments with a replaceCharacter\n */\nexport const stripComments = parser.stripComments;\nexport var ParseErrorCode;\n(function (ParseErrorCode) {\n ParseErrorCode[ParseErrorCode[\"InvalidSymbol\"] = 1] = \"InvalidSymbol\";\n ParseErrorCode[ParseErrorCode[\"InvalidNumberFormat\"] = 2] = \"InvalidNumberFormat\";\n ParseErrorCode[ParseErrorCode[\"PropertyNameExpected\"] = 3] = \"PropertyNameExpected\";\n ParseErrorCode[ParseErrorCode[\"ValueExpected\"] = 4] = \"ValueExpected\";\n ParseErrorCode[ParseErrorCode[\"ColonExpected\"] = 5] = \"ColonExpected\";\n ParseErrorCode[ParseErrorCode[\"CommaExpected\"] = 6] = \"CommaExpected\";\n ParseErrorCode[ParseErrorCode[\"CloseBraceExpected\"] = 7] = \"CloseBraceExpected\";\n ParseErrorCode[ParseErrorCode[\"CloseBracketExpected\"] = 8] = \"CloseBracketExpected\";\n ParseErrorCode[ParseErrorCode[\"EndOfFileExpected\"] = 9] = \"EndOfFileExpected\";\n ParseErrorCode[ParseErrorCode[\"InvalidCommentToken\"] = 10] = \"InvalidCommentToken\";\n ParseErrorCode[ParseErrorCode[\"UnexpectedEndOfComment\"] = 11] = \"UnexpectedEndOfComment\";\n ParseErrorCode[ParseErrorCode[\"UnexpectedEndOfString\"] = 12] = \"UnexpectedEndOfString\";\n ParseErrorCode[ParseErrorCode[\"UnexpectedEndOfNumber\"] = 13] = \"UnexpectedEndOfNumber\";\n ParseErrorCode[ParseErrorCode[\"InvalidUnicode\"] = 14] = \"InvalidUnicode\";\n ParseErrorCode[ParseErrorCode[\"InvalidEscapeCharacter\"] = 15] = \"InvalidEscapeCharacter\";\n ParseErrorCode[ParseErrorCode[\"InvalidCharacter\"] = 16] = \"InvalidCharacter\";\n})(ParseErrorCode || (ParseErrorCode = {}));\nexport function printParseErrorCode(code) {\n switch (code) {\n case 1 /* ParseErrorCode.InvalidSymbol */: return 'InvalidSymbol';\n case 2 /* ParseErrorCode.InvalidNumberFormat */: return 'InvalidNumberFormat';\n case 3 /* ParseErrorCode.PropertyNameExpected */: return 'PropertyNameExpected';\n case 4 /* ParseErrorCode.ValueExpected */: return 'ValueExpected';\n case 5 /* ParseErrorCode.ColonExpected */: return 'ColonExpected';\n case 6 /* ParseErrorCode.CommaExpected */: return 'CommaExpected';\n case 7 /* ParseErrorCode.CloseBraceExpected */: return 'CloseBraceExpected';\n case 8 /* ParseErrorCode.CloseBracketExpected */: return 'CloseBracketExpected';\n case 9 /* ParseErrorCode.EndOfFileExpected */: return 'EndOfFileExpected';\n case 10 /* ParseErrorCode.InvalidCommentToken */: return 'InvalidCommentToken';\n case 11 /* ParseErrorCode.UnexpectedEndOfComment */: return 'UnexpectedEndOfComment';\n case 12 /* ParseErrorCode.UnexpectedEndOfString */: return 'UnexpectedEndOfString';\n case 13 /* ParseErrorCode.UnexpectedEndOfNumber */: return 'UnexpectedEndOfNumber';\n case 14 /* ParseErrorCode.InvalidUnicode */: return 'InvalidUnicode';\n case 15 /* ParseErrorCode.InvalidEscapeCharacter */: return 'InvalidEscapeCharacter';\n case 16 /* ParseErrorCode.InvalidCharacter */: return 'InvalidCharacter';\n }\n return '<unknown ParseErrorCode>';\n}\n/**\n * Computes the edit operations needed to format a JSON document.\n *\n * @param documentText The input text\n * @param range The range to format or `undefined` to format the full content\n * @param options The formatting options\n * @returns The edit operations describing the formatting changes to the original document following the format described in {@linkcode EditResult}.\n * To apply the edit operations to the input, use {@linkcode applyEdits}.\n */\nexport function format(documentText, range, options) {\n return formatter.format(documentText, range, options);\n}\n/**\n * Computes the edit operations needed to modify a value in the JSON document.\n *\n * @param documentText The input text\n * @param path The path of the value to change. The path represents either to the document root, a property or an array item.\n * If the path points to an non-existing property or item, it will be created.\n * @param value The new value for the specified property or item. If the value is undefined,\n * the property or item will be removed.\n * @param options Options\n * @returns The edit operations describing the changes to the original document, following the format described in {@linkcode EditResult}.\n * To apply the edit operations to the input, use {@linkcode applyEdits}.\n */\nexport function modify(text, path, value, options) {\n return edit.setProperty(text, path, value, options);\n}\n/**\n * Applies edits to an input string.\n * @param text The input text\n * @param edits Edit operations following the format described in {@linkcode EditResult}.\n * @returns The text with the applied edits.\n * @throws An error if the edit operations are not well-formed as described in {@linkcode EditResult}.\n */\nexport function applyEdits(text, edits) {\n let sortedEdits = edits.slice(0).sort((a, b) => {\n const diff = a.offset - b.offset;\n if (diff === 0) {\n return a.length - b.length;\n }\n return diff;\n });\n let lastModifiedOffset = text.length;\n for (let i = sortedEdits.length - 1; i >= 0; i--) {\n let e = sortedEdits[i];\n if (e.offset + e.length <= lastModifiedOffset) {\n text = edit.applyEdit(text, e);\n }\n else {\n throw new Error('Overlapping edit');\n }\n lastModifiedOffset = e.offset;\n }\n return text;\n}\n","/**\n * Pure config validation logic — no runtime dependencies (fs, jsonc-parser, etc.)\n * This module is extracted from config.ts to enable direct unit testing.\n */\n\nexport const VALID_CONFIG_KEYS = new Set([\n \"$schema\",\n \"enabled\",\n \"autoUpdate\",\n \"debug\",\n \"showUpdateToasts\",\n \"pruneNotification\",\n \"pruneNotificationType\",\n \"turnProtection\",\n \"turnProtection.enabled\",\n \"turnProtection.turns\",\n \"experimental\",\n \"experimental.allowSubAgents\",\n \"experimental.customPrompts\",\n \"protectedFilePatterns\",\n \"commands\",\n \"commands.enabled\",\n \"commands.protectedTools\",\n \"manualMode\",\n \"manualMode.enabled\",\n \"manualMode.automaticStrategies\",\n \"compress\",\n \"compress.mode\",\n \"compress.permission\",\n \"compress.showCompression\",\n \"compress.summaryBuffer\",\n \"compress.maxContextLimit\",\n \"compress.minContextLimit\",\n \"compress.modelMaxLimits\",\n \"compress.modelMinLimits\",\n \"compress.nudgeFrequency\",\n \"compress.iterationNudgeThreshold\",\n \"compress.nudgeForce\",\n \"compress.protectedTools\",\n \"compress.protectTags\",\n \"compress.protectUserMessages\",\n \"gc\",\n \"gc.algorithm\",\n \"gc.promotionThreshold\",\n \"gc.maxBlockAge\",\n \"gc.maxOldGenSummaryLength\",\n \"gc.majorGcThresholdPercent\",\n \"gc.batchCleanup\",\n \"gc.batchCleanup.lowThreshold\",\n \"gc.batchCleanup.highThreshold\",\n \"gc.batchCleanup.forceThreshold\",\n \"strategies\",\n \"strategies.deduplication\",\n \"strategies.deduplication.enabled\",\n \"strategies.deduplication.protectedTools\",\n \"strategies.purgeErrors\",\n \"strategies.purgeErrors.enabled\",\n \"strategies.purgeErrors.turns\",\n \"strategies.purgeErrors.protectedTools\",\n])\n\nfunction getConfigKeyPaths(obj: Record<string, any>, prefix = \"\"): string[] {\n const keys: string[] = []\n for (const key of Object.keys(obj)) {\n const fullKey = prefix ? `${prefix}.${key}` : key\n keys.push(fullKey)\n\n // model*Limits are dynamic maps keyed by providerID/modelID; do not recurse into arbitrary IDs.\n if (fullKey === \"compress.modelMaxLimits\" || fullKey === \"compress.modelMinLimits\") {\n continue\n }\n\n if (obj[key] && typeof obj[key] === \"object\" && !Array.isArray(obj[key])) {\n keys.push(...getConfigKeyPaths(obj[key], fullKey))\n }\n }\n return keys\n}\n\nexport function getInvalidConfigKeys(userConfig: Record<string, any>): string[] {\n const userKeys = getConfigKeyPaths(userConfig)\n return userKeys.filter((key) => !VALID_CONFIG_KEYS.has(key))\n}\n\nexport interface ValidationError {\n key: string\n expected: string\n actual: string\n}\n\nexport function validateConfigTypes(config: Record<string, any>): ValidationError[] {\n const errors: ValidationError[] = []\n\n if (config.enabled !== undefined && typeof config.enabled !== \"boolean\") {\n errors.push({ key: \"enabled\", expected: \"boolean\", actual: typeof config.enabled })\n }\n\n if (config.autoUpdate !== undefined && typeof config.autoUpdate !== \"boolean\") {\n errors.push({ key: \"autoUpdate\", expected: \"boolean\", actual: typeof config.autoUpdate })\n }\n\n if (config.debug !== undefined && typeof config.debug !== \"boolean\") {\n errors.push({ key: \"debug\", expected: \"boolean\", actual: typeof config.debug })\n }\n\n if (config.pruneNotification !== undefined) {\n const validValues = [\"off\", \"minimal\", \"detailed\"]\n if (!validValues.includes(config.pruneNotification)) {\n errors.push({\n key: \"pruneNotification\",\n expected: '\"off\" | \"minimal\" | \"detailed\"',\n actual: JSON.stringify(config.pruneNotification),\n })\n }\n }\n\n if (config.pruneNotificationType !== undefined) {\n const validValues = [\"chat\", \"toast\"]\n if (!validValues.includes(config.pruneNotificationType)) {\n errors.push({\n key: \"pruneNotificationType\",\n expected: '\"chat\" | \"toast\"',\n actual: JSON.stringify(config.pruneNotificationType),\n })\n }\n }\n\n if (config.protectedFilePatterns !== undefined) {\n if (!Array.isArray(config.protectedFilePatterns)) {\n errors.push({\n key: \"protectedFilePatterns\",\n expected: \"string[]\",\n actual: typeof config.protectedFilePatterns,\n })\n } else if (!config.protectedFilePatterns.every((v: unknown) => typeof v === \"string\")) {\n errors.push({\n key: \"protectedFilePatterns\",\n expected: \"string[]\",\n actual: \"non-string entries\",\n })\n }\n }\n\n if (config.turnProtection) {\n if (\n config.turnProtection.enabled !== undefined &&\n typeof config.turnProtection.enabled !== \"boolean\"\n ) {\n errors.push({\n key: \"turnProtection.enabled\",\n expected: \"boolean\",\n actual: typeof config.turnProtection.enabled,\n })\n }\n\n if (\n config.turnProtection.turns !== undefined &&\n typeof config.turnProtection.turns !== \"number\"\n ) {\n errors.push({\n key: \"turnProtection.turns\",\n expected: \"number\",\n actual: typeof config.turnProtection.turns,\n })\n }\n if (typeof config.turnProtection.turns === \"number\" && config.turnProtection.turns < 1) {\n errors.push({\n key: \"turnProtection.turns\",\n expected: \"positive number (>= 1)\",\n actual: `${config.turnProtection.turns}`,\n })\n }\n }\n\n const experimental = config.experimental\n if (experimental !== undefined) {\n if (\n typeof experimental !== \"object\" ||\n experimental === null ||\n Array.isArray(experimental)\n ) {\n errors.push({\n key: \"experimental\",\n expected: \"object\",\n actual: typeof experimental,\n })\n } else {\n if (\n experimental.allowSubAgents !== undefined &&\n typeof experimental.allowSubAgents !== \"boolean\"\n ) {\n errors.push({\n key: \"experimental.allowSubAgents\",\n expected: \"boolean\",\n actual: typeof experimental.allowSubAgents,\n })\n }\n\n if (\n experimental.customPrompts !== undefined &&\n typeof experimental.customPrompts !== \"boolean\"\n ) {\n errors.push({\n key: \"experimental.customPrompts\",\n expected: \"boolean\",\n actual: typeof experimental.customPrompts,\n })\n }\n }\n }\n\n const commands = config.commands\n if (commands !== undefined) {\n if (typeof commands !== \"object\" || commands === null || Array.isArray(commands)) {\n errors.push({\n key: \"commands\",\n expected: \"object\",\n actual: typeof commands,\n })\n } else {\n if (commands.enabled !== undefined && typeof commands.enabled !== \"boolean\") {\n errors.push({\n key: \"commands.enabled\",\n expected: \"boolean\",\n actual: typeof commands.enabled,\n })\n }\n if (commands.protectedTools !== undefined && !Array.isArray(commands.protectedTools)) {\n errors.push({\n key: \"commands.protectedTools\",\n expected: \"string[]\",\n actual: typeof commands.protectedTools,\n })\n }\n }\n }\n\n const manualMode = config.manualMode\n if (manualMode !== undefined) {\n if (typeof manualMode !== \"object\" || manualMode === null || Array.isArray(manualMode)) {\n errors.push({\n key: \"manualMode\",\n expected: \"object\",\n actual: typeof manualMode,\n })\n } else {\n if (manualMode.enabled !== undefined && typeof manualMode.enabled !== \"boolean\") {\n errors.push({\n key: \"manualMode.enabled\",\n expected: \"boolean\",\n actual: typeof manualMode.enabled,\n })\n }\n\n if (\n manualMode.automaticStrategies !== undefined &&\n typeof manualMode.automaticStrategies !== \"boolean\"\n ) {\n errors.push({\n key: \"manualMode.automaticStrategies\",\n expected: \"boolean\",\n actual: typeof manualMode.automaticStrategies,\n })\n }\n }\n }\n\n const compress = config.compress\n if (compress !== undefined) {\n if (typeof compress !== \"object\" || compress === null || Array.isArray(compress)) {\n errors.push({\n key: \"compress\",\n expected: \"object\",\n actual: typeof compress,\n })\n } else {\n if (\n compress.mode !== undefined &&\n compress.mode !== \"range\" &&\n compress.mode !== \"message\"\n ) {\n errors.push({\n key: \"compress.mode\",\n expected: '\"range\" | \"message\"',\n actual: JSON.stringify(compress.mode),\n })\n }\n\n if (\n compress.summaryBuffer !== undefined &&\n typeof compress.summaryBuffer !== \"boolean\"\n ) {\n errors.push({\n key: \"compress.summaryBuffer\",\n expected: \"boolean\",\n actual: typeof compress.summaryBuffer,\n })\n }\n\n if (\n compress.nudgeFrequency !== undefined &&\n typeof compress.nudgeFrequency !== \"number\"\n ) {\n errors.push({\n key: \"compress.nudgeFrequency\",\n expected: \"number\",\n actual: typeof compress.nudgeFrequency,\n })\n }\n\n if (typeof compress.nudgeFrequency === \"number\" && compress.nudgeFrequency < 1) {\n errors.push({\n key: \"compress.nudgeFrequency\",\n expected: \"positive number (>= 1)\",\n actual: `${compress.nudgeFrequency} (will be clamped to 1)`,\n })\n }\n\n if (\n compress.iterationNudgeThreshold !== undefined &&\n typeof compress.iterationNudgeThreshold !== \"number\"\n ) {\n errors.push({\n key: \"compress.iterationNudgeThreshold\",\n expected: \"number\",\n actual: typeof compress.iterationNudgeThreshold,\n })\n }\n\n if (\n compress.nudgeForce !== undefined &&\n compress.nudgeForce !== \"strong\" &&\n compress.nudgeForce !== \"soft\"\n ) {\n errors.push({\n key: \"compress.nudgeForce\",\n expected: '\"strong\" | \"soft\"',\n actual: JSON.stringify(compress.nudgeForce),\n })\n }\n\n if (compress.protectedTools !== undefined && !Array.isArray(compress.protectedTools)) {\n errors.push({\n key: \"compress.protectedTools\",\n expected: \"string[]\",\n actual: typeof compress.protectedTools,\n })\n }\n\n if (compress.protectTags !== undefined && typeof compress.protectTags !== \"boolean\") {\n errors.push({\n key: \"compress.protectTags\",\n expected: \"boolean\",\n actual: typeof compress.protectTags,\n })\n }\n\n if (\n compress.protectUserMessages !== undefined &&\n typeof compress.protectUserMessages !== \"boolean\"\n ) {\n errors.push({\n key: \"compress.protectUserMessages\",\n expected: \"boolean\",\n actual: typeof compress.protectUserMessages,\n })\n }\n\n if (\n typeof compress.iterationNudgeThreshold === \"number\" &&\n compress.iterationNudgeThreshold < 1\n ) {\n errors.push({\n key: \"compress.iterationNudgeThreshold\",\n expected: \"positive number (>= 1)\",\n actual: `${compress.iterationNudgeThreshold} (will be clamped to 1)`,\n })\n }\n\n const validateLimitValue = (\n key: string,\n value: unknown,\n actualValue: unknown = value,\n ): void => {\n const isValidNumber = typeof value === \"number\"\n const isPercentString = typeof value === \"string\" && value.endsWith(\"%\")\n\n if (!isValidNumber && !isPercentString) {\n errors.push({\n key,\n expected: 'number | \"${number}%\"',\n actual: JSON.stringify(actualValue),\n })\n }\n }\n\n const validateModelLimits = (\n key: \"compress.modelMaxLimits\" | \"compress.modelMinLimits\",\n limits: unknown,\n ): void => {\n if (limits === undefined) {\n return\n }\n\n if (typeof limits !== \"object\" || limits === null || Array.isArray(limits)) {\n errors.push({\n key,\n expected: \"Record<string, number | ${number}%>\",\n actual: typeof limits,\n })\n return\n }\n\n for (const [providerModelKey, limit] of Object.entries(limits)) {\n const isValidNumber = typeof limit === \"number\"\n const isPercentString =\n typeof limit === \"string\" && /^\\d+(?:\\.\\d+)?%$/.test(limit)\n if (!isValidNumber && !isPercentString) {\n errors.push({\n key: `${key}.${providerModelKey}`,\n expected: 'number | \"${number}%\"',\n actual: JSON.stringify(limit),\n })\n }\n }\n }\n\n if (compress.maxContextLimit !== undefined) {\n validateLimitValue(\"compress.maxContextLimit\", compress.maxContextLimit)\n }\n\n if (compress.minContextLimit !== undefined) {\n validateLimitValue(\"compress.minContextLimit\", compress.minContextLimit)\n }\n\n validateModelLimits(\"compress.modelMaxLimits\", compress.modelMaxLimits)\n validateModelLimits(\"compress.modelMinLimits\", compress.modelMinLimits)\n\n const validValues = [\"ask\", \"allow\", \"deny\"]\n if (compress.permission !== undefined && !validValues.includes(compress.permission)) {\n errors.push({\n key: \"compress.permission\",\n expected: '\"ask\" | \"allow\" | \"deny\"',\n actual: JSON.stringify(compress.permission),\n })\n }\n\n if (\n compress.showCompression !== undefined &&\n typeof compress.showCompression !== \"boolean\"\n ) {\n errors.push({\n key: \"compress.showCompression\",\n expected: \"boolean\",\n actual: typeof compress.showCompression,\n })\n }\n }\n }\n\n const gc = config.gc\n if (gc !== undefined) {\n if (typeof gc !== \"object\" || gc === null || Array.isArray(gc)) {\n errors.push({\n key: \"gc\",\n expected: \"object\",\n actual: typeof gc,\n })\n } else {\n if (gc.algorithm !== undefined && gc.algorithm !== \"truncate\") {\n errors.push({\n key: \"gc.algorithm\",\n expected: '\"truncate\"',\n actual: JSON.stringify(gc.algorithm),\n })\n }\n if (gc.promotionThreshold !== undefined && typeof gc.promotionThreshold !== \"number\") {\n errors.push({\n key: \"gc.promotionThreshold\",\n expected: \"number\",\n actual: typeof gc.promotionThreshold,\n })\n }\n if (gc.maxBlockAge !== undefined && typeof gc.maxBlockAge !== \"number\") {\n errors.push({\n key: \"gc.maxBlockAge\",\n expected: \"number\",\n actual: typeof gc.maxBlockAge,\n })\n }\n if (\n gc.maxOldGenSummaryLength !== undefined &&\n typeof gc.maxOldGenSummaryLength !== \"number\"\n ) {\n errors.push({\n key: \"gc.maxOldGenSummaryLength\",\n expected: \"number\",\n actual: typeof gc.maxOldGenSummaryLength,\n })\n }\n if (\n gc.majorGcThresholdPercent !== undefined\n ) {\n const isValidNumber = typeof gc.majorGcThresholdPercent === \"number\"\n const isPercentString =\n typeof gc.majorGcThresholdPercent === \"string\" &&\n /^\\d+(?:\\.\\d+)?%$/.test(gc.majorGcThresholdPercent)\n if (!isValidNumber && !isPercentString) {\n errors.push({\n key: \"gc.majorGcThresholdPercent\",\n expected: 'number | \"${number}%\"',\n actual: JSON.stringify(gc.majorGcThresholdPercent),\n })\n }\n }\n\n const validateBatchThreshold = (\n key: \"gc.batchCleanup.lowThreshold\" | \"gc.batchCleanup.highThreshold\" | \"gc.batchCleanup.forceThreshold\",\n value: unknown,\n ): void => {\n const isValidNumber = typeof value === \"number\"\n const isPercentString = typeof value === \"string\" && /^\\d+(?:\\.\\d+)?%$/.test(value)\n if (!isValidNumber && !isPercentString) {\n errors.push({\n key,\n expected: 'number | \"${number}%\"',\n actual: JSON.stringify(value),\n })\n }\n }\n\n if (gc.batchCleanup !== undefined) {\n if (\n typeof gc.batchCleanup !== \"object\" ||\n gc.batchCleanup === null ||\n Array.isArray(gc.batchCleanup)\n ) {\n errors.push({\n key: \"gc.batchCleanup\",\n expected: \"object\",\n actual: typeof gc.batchCleanup,\n })\n } else {\n if (gc.batchCleanup.lowThreshold !== undefined) {\n validateBatchThreshold(\"gc.batchCleanup.lowThreshold\", gc.batchCleanup.lowThreshold)\n }\n if (gc.batchCleanup.highThreshold !== undefined) {\n validateBatchThreshold(\"gc.batchCleanup.highThreshold\", gc.batchCleanup.highThreshold)\n }\n if (gc.batchCleanup.forceThreshold !== undefined) {\n validateBatchThreshold(\"gc.batchCleanup.forceThreshold\", gc.batchCleanup.forceThreshold)\n }\n }\n }\n }\n }\n\n const strategies = config.strategies\n if (strategies !== undefined) {\n if (typeof strategies !== \"object\" || strategies === null || Array.isArray(strategies)) {\n errors.push({\n key: \"strategies\",\n expected: \"object\",\n actual: typeof strategies,\n })\n } else {\n const dedup = strategies.deduplication\n if (dedup !== undefined) {\n if (typeof dedup !== \"object\" || dedup === null || Array.isArray(dedup)) {\n errors.push({\n key: \"strategies.deduplication\",\n expected: \"object\",\n actual: typeof dedup,\n })\n } else {\n if (dedup.enabled !== undefined && typeof dedup.enabled !== \"boolean\") {\n errors.push({\n key: \"strategies.deduplication.enabled\",\n expected: \"boolean\",\n actual: typeof dedup.enabled,\n })\n }\n if (dedup.protectedTools !== undefined && !Array.isArray(dedup.protectedTools)) {\n errors.push({\n key: \"strategies.deduplication.protectedTools\",\n expected: \"string[]\",\n actual: typeof dedup.protectedTools,\n })\n }\n }\n }\n\n const purge = strategies.purgeErrors\n if (purge !== undefined) {\n if (typeof purge !== \"object\" || purge === null || Array.isArray(purge)) {\n errors.push({\n key: \"strategies.purgeErrors\",\n expected: \"object\",\n actual: typeof purge,\n })\n } else {\n if (purge.enabled !== undefined && typeof purge.enabled !== \"boolean\") {\n errors.push({\n key: \"strategies.purgeErrors.enabled\",\n expected: \"boolean\",\n actual: typeof purge.enabled,\n })\n }\n if (purge.turns !== undefined && typeof purge.turns !== \"number\") {\n errors.push({\n key: \"strategies.purgeErrors.turns\",\n expected: \"number\",\n actual: typeof purge.turns,\n })\n }\n if (typeof purge.turns === \"number\" && purge.turns < 1) {\n errors.push({\n key: \"strategies.purgeErrors.turns\",\n expected: \"positive number (>= 1)\",\n actual: `${purge.turns} (will be clamped to 1)`,\n })\n }\n if (purge.protectedTools !== undefined && !Array.isArray(purge.protectedTools)) {\n errors.push({\n key: \"strategies.purgeErrors.protectedTools\",\n expected: \"string[]\",\n actual: typeof purge.protectedTools,\n })\n }\n }\n }\n }\n }\n\n return errors\n}\n","import { tool } from \"@opencode-ai/plugin\"\nimport type { ToolContext } from \"./types\"\nimport { countTokens } from \"../token-utils\"\nimport { MESSAGE_FORMAT_EXTENSION } from \"../prompts/extensions/tool\"\nimport { formatIssues, formatResult, resolveMessages, validateArgs } from \"./message-utils\"\nimport { finalizeSession, prepareSession, type NotificationEntry } from \"./pipeline\"\nimport { appendProtectedPromptInfo, appendProtectedTools } from \"./protected-content\"\nimport {\n allocateBlockId,\n allocateRunId,\n applyCompressionState,\n wrapCompressedSummary,\n} from \"./state\"\nimport type { CompressMessageToolArgs } from \"./types\"\n\nfunction buildSchema() {\n return {\n topic: tool.schema\n .string()\n .describe(\n \"Short label (3-5 words) for the overall batch - e.g., 'Closed Research Notes'\",\n ),\n content: tool.schema\n .array(\n tool.schema.object({\n messageId: tool.schema\n .string()\n .describe(\"Raw message ID to compress (e.g. m00001)\"),\n topic: tool.schema\n .string()\n .describe(\"Short label (3-5 words) for this one message summary\"),\n summary: tool.schema\n .string()\n .describe(\"Complete technical summary replacing that one message\"),\n }),\n )\n .describe(\"Batch of individual message summaries to create in one tool call\"),\n }\n}\n\nexport function createCompressMessageTool(ctx: ToolContext): ReturnType<typeof tool> {\n ctx.prompts.reload()\n const runtimePrompts = ctx.prompts.getRuntimePrompts()\n\n return tool({\n description: runtimePrompts.compressMessage + MESSAGE_FORMAT_EXTENSION,\n args: buildSchema(),\n async execute(args, toolCtx) {\n const input = args as CompressMessageToolArgs\n validateArgs(input)\n const callId =\n typeof (toolCtx as unknown as { callID?: unknown }).callID === \"string\"\n ? (toolCtx as unknown as { callID: string }).callID\n : undefined\n\n const { rawMessages, searchContext } = await prepareSession(\n ctx,\n toolCtx,\n `Compress Message: ${input.topic}`,\n )\n const { plans, skippedIssues, skippedCount } = resolveMessages(\n input,\n searchContext,\n ctx.state,\n ctx.config,\n )\n\n if (plans.length === 0 && skippedCount > 0) {\n throw new Error(formatIssues(skippedIssues, skippedCount))\n }\n\n const notifications: NotificationEntry[] = []\n\n const preparedPlans: Array<{\n plan: (typeof plans)[number]\n summaryWithTools: string\n }> = []\n\n for (const plan of plans) {\n const summaryWithPromptInfo = appendProtectedPromptInfo(\n plan.entry.summary,\n plan.selection,\n searchContext,\n ctx.state,\n ctx.config.compress.protectTags,\n )\n\n const summaryWithTools = await appendProtectedTools(\n ctx.client,\n ctx.state,\n ctx.config.experimental.allowSubAgents,\n summaryWithPromptInfo,\n plan.selection,\n searchContext,\n ctx.config.compress.protectedTools,\n ctx.config.protectedFilePatterns,\n )\n\n preparedPlans.push({\n plan,\n summaryWithTools,\n })\n }\n\n const runId = allocateRunId(ctx.state)\n\n for (const { plan, summaryWithTools } of preparedPlans) {\n const blockId = allocateBlockId(ctx.state)\n const storedSummary = wrapCompressedSummary(blockId, summaryWithTools)\n const summaryTokens = countTokens(storedSummary)\n\n applyCompressionState(\n ctx.state,\n {\n topic: plan.entry.topic,\n batchTopic: input.topic,\n startId: plan.entry.messageId,\n endId: plan.entry.messageId,\n mode: \"message\",\n runId,\n compressMessageId: toolCtx.messageID,\n compressCallId: callId,\n summaryTokens,\n },\n plan.selection,\n plan.anchorMessageId,\n blockId,\n storedSummary,\n [],\n ctx.config.gc,\n )\n\n notifications.push({\n blockId,\n runId,\n summary: summaryWithTools,\n summaryTokens,\n })\n }\n\n await finalizeSession(ctx, toolCtx, rawMessages, notifications, input.topic)\n\n return formatResult(plans.length, skippedIssues, skippedCount)\n },\n })\n}\n","import { SessionState, WithParts } from \"./state\"\nimport { AssistantMessage, UserMessage } from \"@opencode-ai/sdk/v2\"\nimport { Logger } from \"./logger\"\nimport * as _anthropicTokenizer from \"@anthropic-ai/tokenizer\"\nconst anthropicCountTokens = (_anthropicTokenizer.countTokens ??\n (_anthropicTokenizer as any).default?.countTokens) as typeof _anthropicTokenizer.countTokens\nimport { getLastUserMessage } from \"./messages/query\"\n\nexport function getCurrentTokenUsage(state: SessionState, messages: WithParts[]): number {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.info.role !== \"assistant\") {\n continue\n }\n\n const assistantInfo = msg.info as AssistantMessage\n if ((assistantInfo.tokens?.output || 0) <= 0) {\n continue\n }\n\n if (\n state.lastCompaction > 0 &&\n (msg.info.time.created < state.lastCompaction ||\n (msg.info.summary === true && msg.info.time.created === state.lastCompaction))\n ) {\n return 0\n }\n\n const input = assistantInfo.tokens?.input || 0\n const output = assistantInfo.tokens?.output || 0\n const reasoning = assistantInfo.tokens?.reasoning || 0\n const cacheRead = assistantInfo.tokens?.cache?.read || 0\n const cacheWrite = assistantInfo.tokens?.cache?.write || 0\n\n // [FIX Bug 17] Universal token estimation\n // opencode session.ts: adjustedInputTokens = inputTokens - cacheRead - cacheWrite\n // So: input + cacheRead + cacheWrite = prompt_tokens (total input)\n // Total context usage = prompt_tokens + output + reasoning\n return input + cacheRead + cacheWrite + output + reasoning\n }\n\n // [FIX Bug 5] fallback: estimate tokens from message content when no assistant\n // message has output tokens (first turn or after full compaction)\n let estimated = 0\n for (const m of messages) {\n const parts = Array.isArray(m.parts) ? m.parts : []\n for (const part of parts) {\n if (part.type === \"text\" && typeof part.text === \"string\") {\n estimated += countTokens(part.text)\n }\n }\n }\n return estimated\n}\n\nexport function getCurrentParams(\n state: SessionState,\n messages: WithParts[],\n logger: Logger,\n): {\n providerId: string | undefined\n modelId: string | undefined\n agent: string | undefined\n variant: string | undefined\n} {\n const userMsg = getLastUserMessage(messages)\n if (!userMsg) {\n logger.debug(\"No user message found when determining current params\")\n return {\n providerId: undefined,\n modelId: undefined,\n agent: undefined,\n variant: undefined,\n }\n }\n const userInfo = userMsg.info as UserMessage\n const agent: string = userInfo.agent\n const providerId: string | undefined = userInfo.model.providerID\n const modelId: string | undefined = userInfo.model.modelID\n const variant: string | undefined = userInfo.model.variant\n\n return { providerId, modelId, agent, variant }\n}\n\nexport function countTokens(text: string): number {\n if (!text) return 0\n try {\n return anthropicCountTokens(text)\n } catch {\n return Math.round(text.length / 4)\n }\n}\n\nexport function estimateTokensBatch(texts: string[]): number {\n if (texts.length === 0) return 0\n return countTokens(texts.join(\" \"))\n}\n\nexport const COMPACTED_TOOL_OUTPUT_PLACEHOLDER = \"[Old tool result content cleared]\"\n\nfunction stringifyToolContent(value: unknown): string {\n return typeof value === \"string\" ? value : JSON.stringify(value)\n}\n\nexport function extractCompletedToolOutput(part: any): string | undefined {\n if (\n part?.type !== \"tool\" ||\n part.state?.status !== \"completed\" ||\n part.state?.output === undefined\n ) {\n return undefined\n }\n\n if (part.state?.time?.compacted) {\n return COMPACTED_TOOL_OUTPUT_PLACEHOLDER\n }\n\n return stringifyToolContent(part.state.output)\n}\n\nexport function extractToolContent(part: any): string[] {\n const contents: string[] = []\n\n if (part?.type !== \"tool\") {\n return contents\n }\n\n if (part.state?.input !== undefined) {\n contents.push(stringifyToolContent(part.state.input))\n }\n\n const completedOutput = extractCompletedToolOutput(part)\n if (completedOutput !== undefined) {\n contents.push(completedOutput)\n } else if (part.state?.status === \"error\" && part.state?.error) {\n contents.push(stringifyToolContent(part.state.error))\n }\n\n return contents\n}\n\nexport function countToolTokens(part: any): number {\n const contents = extractToolContent(part)\n return estimateTokensBatch(contents)\n}\n\nexport function getTotalToolTokens(state: SessionState, toolIds: string[]): number {\n let total = 0\n for (const id of toolIds) {\n const entry = state.toolParameters.get(id)\n total += entry?.tokenCount ?? 0\n }\n return total\n}\n\nexport function countMessageTextTokens(msg: WithParts): number {\n const texts: string[] = []\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type === \"text\") {\n texts.push(part.text)\n }\n }\n if (texts.length === 0) return 0\n return estimateTokensBatch(texts)\n}\n\nexport function countAllMessageTokens(msg: WithParts): number {\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n const texts: string[] = []\n for (const part of parts) {\n if (part.type === \"text\") {\n texts.push(part.text)\n } else {\n texts.push(...extractToolContent(part))\n }\n }\n if (texts.length === 0) return 0\n return estimateTokensBatch(texts)\n}\n","import type { WithParts } from \"../state\"\n\nexport function isMessageWithInfo(message: unknown): message is WithParts {\n if (!message || typeof message !== \"object\") {\n return false\n }\n\n const info = (message as any).info\n const parts = (message as any).parts\n if (!info || typeof info !== \"object\") {\n return false\n }\n\n return (\n typeof info.id === \"string\" &&\n info.id.length > 0 &&\n typeof info.sessionID === \"string\" &&\n info.sessionID.length > 0 &&\n (info.role === \"user\" || info.role === \"assistant\") &&\n info.time &&\n typeof info.time === \"object\" &&\n typeof info.time.created === \"number\" &&\n Array.isArray(parts)\n )\n}\n\nexport function filterMessages(messages: unknown): WithParts[] {\n if (!Array.isArray(messages)) {\n return []\n }\n\n return messages.filter(isMessageWithInfo)\n}\n\nexport function filterMessagesInPlace(messages: unknown): WithParts[] {\n if (!Array.isArray(messages)) {\n return []\n }\n\n let writeIndex = 0\n\n for (const message of messages) {\n if (isMessageWithInfo(message)) {\n messages[writeIndex++] = message\n }\n }\n\n messages.length = writeIndex\n return messages as WithParts[]\n}\n","import type { PluginConfig } from \"../config\"\nimport type { WithParts } from \"../state\"\nimport { isMessageWithInfo } from \"./shape\"\n\nexport function isSyntheticMessage(message: WithParts): boolean {\n const id = message?.info?.id\n return typeof id === \"string\" && (id.startsWith(\"msg_dcp_summary_\") || id.startsWith(\"msg_dcp_text_\"))\n}\n\nexport const getLastUserMessage = (\n messages: WithParts[],\n startIndex?: number,\n): WithParts | null => {\n const start = startIndex ?? messages.length - 1\n for (let i = start; i >= 0; i--) {\n const msg = messages[i]\n if (!isMessageWithInfo(msg)) {\n continue\n }\n if (msg.info.role === \"user\" && !isIgnoredUserMessage(msg) && !isSyntheticMessage(msg)) {\n return msg\n }\n }\n return null\n}\n\nexport const messageHasCompress = (message: WithParts): boolean => {\n if (!isMessageWithInfo(message)) {\n return false\n }\n\n if (message.info.role !== \"assistant\") {\n return false\n }\n\n const parts = Array.isArray(message.parts) ? message.parts : []\n return parts.some(\n (part) =>\n part.type === \"tool\" && part.tool === \"compress\" && part.state?.status === \"completed\",\n )\n}\n\nexport const isIgnoredUserMessage = (message: WithParts): boolean => {\n if (!isMessageWithInfo(message)) {\n return false\n }\n\n if (message.info.role !== \"user\") {\n return false\n }\n\n const parts = Array.isArray(message.parts) ? message.parts : []\n if (parts.length === 0) {\n return true\n }\n\n for (const part of parts) {\n if (!(part as any).ignored) {\n return false\n }\n }\n\n return true\n}\n\nexport function isProtectedUserMessage(config: PluginConfig, message: WithParts): boolean {\n if (!isMessageWithInfo(message)) {\n return false\n }\n\n return (\n config.compress.mode === \"message\" &&\n config.compress.protectUserMessages &&\n message.info.role === \"user\" &&\n !isIgnoredUserMessage(message)\n )\n}\n","// These format schemas are kept separate from the editable compress prompts\n// so they cannot be modified via custom prompt overrides. The schemas must\n// match the tool's input validation and are not safe to change independently.\n\nexport const RANGE_FORMAT_EXTENSION = `\nTHE FORMAT OF COMPRESS\n\n\\`\\`\\`\n{\n topic: string, // Short label (3-5 words) - e.g., \"Auth System Exploration\"\n content: [ // One or more ranges to compress\n {\n startId: string, // Boundary ID at range start: mNNNNN or bN\n endId: string, // Boundary ID at range end: mNNNNN or bN\n summary: string // Complete technical summary replacing all content in range\n }\n ]\n}\n\\`\\`\\``\n\nexport const MESSAGE_FORMAT_EXTENSION = `\nTHE FORMAT OF COMPRESS\n\n\\`\\`\\`\n{\n topic: string, // Short label (3-5 words) for the overall batch\n content: [ // One or more messages to compress independently\n {\n messageId: string, // Raw message ID only: mNNNNN (ignore metadata attributes like priority)\n topic: string, // Short label (3-5 words) for this one message summary\n summary: string // Complete technical summary replacing that one message\n }\n ]\n}\n\\`\\`\\``\n","import type { SessionState, WithParts } from \"./state\"\nimport { isIgnoredUserMessage } from \"./messages/query\"\n\nconst MESSAGE_REF_REGEX = /^m(\\d{4,5})$/\nconst BLOCK_REF_REGEX = /^b([1-9]\\d*)$/\nconst MESSAGE_ID_TAG_NAME = \"dcp-message-id\"\n\nconst MESSAGE_REF_WIDTH = 5\nconst MESSAGE_REF_MIN_INDEX = 1\nconst MESSAGE_REF_MAX_INDEX = 99999\n\nexport type ParsedBoundaryId =\n | {\n kind: \"message\"\n ref: string\n index: number\n }\n | {\n kind: \"compressed-block\"\n ref: string\n blockId: number\n }\n\nexport function formatMessageRef(index: number): string {\n if (\n !Number.isInteger(index) ||\n index < MESSAGE_REF_MIN_INDEX ||\n index > MESSAGE_REF_MAX_INDEX\n ) {\n throw new Error(\n `Message ID index out of bounds: ${index}. Supported range is ${MESSAGE_REF_MIN_INDEX}-${MESSAGE_REF_MAX_INDEX}.`,\n )\n }\n return `m${index.toString().padStart(MESSAGE_REF_WIDTH, \"0\")}`\n}\n\nexport function formatBlockRef(blockId: number): string {\n if (!Number.isInteger(blockId) || blockId < 1) {\n throw new Error(`Invalid block ID: ${blockId}`)\n }\n return `b${blockId}`\n}\n\nexport function parseMessageRef(ref: string): number | null {\n const normalized = ref.trim().toLowerCase()\n const match = normalized.match(MESSAGE_REF_REGEX)\n if (!match) {\n return null\n }\n const index = Number.parseInt(match[1], 10)\n if (!Number.isInteger(index)) {\n return null\n }\n if (index < MESSAGE_REF_MIN_INDEX || index > MESSAGE_REF_MAX_INDEX) {\n return null\n }\n return index\n}\n\nexport function parseBlockRef(ref: string): number | null {\n const normalized = ref.trim().toLowerCase()\n const match = normalized.match(BLOCK_REF_REGEX)\n if (!match) {\n return null\n }\n const id = Number.parseInt(match[1], 10)\n return Number.isInteger(id) ? id : null\n}\n\nexport function parseBoundaryId(id: string): ParsedBoundaryId | null {\n const normalized = id.trim().toLowerCase()\n const messageIndex = parseMessageRef(normalized)\n if (messageIndex !== null) {\n return {\n kind: \"message\",\n ref: formatMessageRef(messageIndex),\n index: messageIndex,\n }\n }\n\n const blockId = parseBlockRef(normalized)\n if (blockId !== null) {\n return {\n kind: \"compressed-block\",\n ref: formatBlockRef(blockId),\n blockId,\n }\n }\n\n return null\n}\n\nfunction escapeXmlAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n}\n\nexport function formatMessageIdTag(\n ref: string,\n attributes?: Record<string, string | undefined>,\n): string {\n const serializedAttributes = Object.entries(attributes || {})\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([name, value]) => {\n if (name.trim().length === 0 || typeof value !== \"string\" || value.length === 0) {\n return \"\"\n }\n\n return ` ${name}=\"${escapeXmlAttribute(value)}\"`\n })\n .join(\"\")\n\n return `\\n<${MESSAGE_ID_TAG_NAME}${serializedAttributes}>${ref}</${MESSAGE_ID_TAG_NAME}>`\n}\n\nexport function assignMessageRefs(state: SessionState, messages: WithParts[]): number {\n let assigned = 0\n let skippedSubAgentPrompt = false\n\n for (const message of messages) {\n if (isIgnoredUserMessage(message)) {\n continue\n }\n\n if (state.isSubAgent && !skippedSubAgentPrompt && message.info.role === \"user\") {\n skippedSubAgentPrompt = true\n continue\n }\n\n const rawMessageId = message.info.id\n if (typeof rawMessageId !== \"string\" || rawMessageId.length === 0) {\n continue\n }\n // [FIX Bug 29] Skip synthetic messages created by DCP\n if (rawMessageId.startsWith(\"msg_dcp_summary_\") || rawMessageId.startsWith(\"msg_dcp_text_\")) {\n continue\n }\n\n const existingRef = state.messageIds.byRawId.get(rawMessageId)\n if (existingRef) {\n if (state.messageIds.byRef.get(existingRef) !== rawMessageId) {\n state.messageIds.byRef.set(existingRef, rawMessageId)\n }\n continue\n }\n\n const ref = allocateNextMessageRef(state)\n state.messageIds.byRawId.set(rawMessageId, ref)\n state.messageIds.byRef.set(ref, rawMessageId)\n assigned++\n }\n\n return assigned\n}\n\nfunction allocateNextMessageRef(state: SessionState): string {\n let candidate = Number.isInteger(state.messageIds.nextRef)\n ? Math.max(MESSAGE_REF_MIN_INDEX, state.messageIds.nextRef)\n : MESSAGE_REF_MIN_INDEX\n\n while (candidate <= MESSAGE_REF_MAX_INDEX) {\n const ref = formatMessageRef(candidate)\n if (!state.messageIds.byRef.has(ref)) {\n state.messageIds.nextRef = candidate + 1\n return ref\n }\n candidate++\n }\n\n throw new Error(\n `Message ID alias capacity exceeded. Cannot allocate more than ${formatMessageRef(MESSAGE_REF_MAX_INDEX)} aliases in this session.`,\n )\n}\n","import type { SessionState, WithParts } from \"../state\"\nimport { formatBlockRef, parseBoundaryId } from \"../message-ids\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\nimport { filterMessages } from \"../messages/shape\"\nimport { countAllMessageTokens } from \"../token-utils\"\nimport type { BoundaryReference, SearchContext, SelectionResolution } from \"./types\"\n\nexport async function fetchSessionMessages(client: any, sessionId: string): Promise<WithParts[]> {\n const response = await client.session.messages({\n path: { id: sessionId },\n })\n\n return filterMessages(response?.data || response)\n}\n\nexport function buildSearchContext(state: SessionState, rawMessages: WithParts[]): SearchContext {\n const rawMessagesById = new Map<string, WithParts>()\n const rawIndexById = new Map<string, number>()\n for (const msg of rawMessages) {\n rawMessagesById.set(msg.info.id, msg)\n }\n for (let index = 0; index < rawMessages.length; index++) {\n const message = rawMessages[index]\n if (!message) {\n continue\n }\n rawIndexById.set(message.info.id, index)\n }\n\n const summaryByBlockId = new Map()\n for (const [blockId, block] of state.prune.messages.blocksById) {\n if (!block.active) {\n continue\n }\n summaryByBlockId.set(blockId, block)\n }\n\n return {\n rawMessages,\n rawMessagesById,\n rawIndexById,\n summaryByBlockId,\n }\n}\n\nexport function resolveBoundaryIds(\n context: SearchContext,\n state: SessionState,\n startId: string,\n endId: string,\n): { startReference: BoundaryReference; endReference: BoundaryReference } {\n const lookup = buildBoundaryLookup(context, state)\n const issues: string[] = []\n const parsedStartId = parseBoundaryId(startId)\n const parsedEndId = parseBoundaryId(endId)\n\n if (parsedStartId === null) {\n issues.push(\"startId is invalid. Use an injected message ID (mNNNNN) or block ID (bN).\")\n }\n\n if (parsedEndId === null) {\n issues.push(\"endId is invalid. Use an injected message ID (mNNNNN) or block ID (bN).\")\n }\n\n if (issues.length > 0) {\n throw new Error(\n issues.length === 1 ? issues[0] : issues.map((issue) => `- ${issue}`).join(\"\\n\"),\n )\n }\n\n if (!parsedStartId || !parsedEndId) {\n throw new Error(\"Invalid boundary ID(s)\")\n }\n\n let startReference = lookup.get(parsedStartId.ref)\n let endReference = lookup.get(parsedEndId.ref)\n\n if (!startReference) {\n issues.push(\n `startId ${parsedStartId.ref} is not available in the current conversation context. Choose an injected ID visible in context.`,\n )\n }\n\n if (!endReference) {\n issues.push(\n `endId ${parsedEndId.ref} is not available in the current conversation context. Choose an injected ID visible in context.`,\n )\n }\n\n if (issues.length > 0) {\n throw new Error(\n issues.length === 1 ? issues[0] : issues.map((issue) => `- ${issue}`).join(\"\\n\"),\n )\n }\n\n if (!startReference || !endReference) {\n throw new Error(\"Failed to resolve boundary IDs\")\n }\n\n // [FIX Bug 34] Auto-swap reversed boundaries instead of throwing.\n // Block IDs (bN) are assigned in creation order, which may not match\n // conversation order. Models naturally assume bN < bM means bN is earlier,\n // but anchor message ordering can differ. Auto-swap prevents compress failures\n // that cause models to give up without compressing.\n if (startReference.rawIndex > endReference.rawIndex) {\n [startReference, endReference] = [endReference, startReference]\n }\n\n return { startReference, endReference }\n}\n\nexport function resolveSelection(\n context: SearchContext,\n startReference: BoundaryReference,\n endReference: BoundaryReference,\n): SelectionResolution {\n const startRawIndex = startReference.rawIndex\n const endRawIndex = endReference.rawIndex\n const messageIds: string[] = []\n const messageSeen = new Set<string>()\n const toolIds: string[] = []\n const toolSeen = new Set<string>()\n const requiredBlockIds: number[] = []\n const requiredBlockSeen = new Set<number>()\n const messageTokenById = new Map<string, number>()\n\n for (let index = startRawIndex; index <= endRawIndex; index++) {\n const rawMessage = context.rawMessages[index]\n if (!rawMessage) {\n continue\n }\n if (isIgnoredUserMessage(rawMessage)) {\n continue\n }\n\n const messageId = rawMessage.info.id\n if (!messageSeen.has(messageId)) {\n messageSeen.add(messageId)\n messageIds.push(messageId)\n }\n\n if (!messageTokenById.has(messageId)) {\n messageTokenById.set(messageId, countAllMessageTokens(rawMessage))\n }\n\n const parts = Array.isArray(rawMessage.parts) ? rawMessage.parts : []\n for (const part of parts) {\n if (part.type !== \"tool\" || !part.callID) {\n continue\n }\n if (toolSeen.has(part.callID)) {\n continue\n }\n toolSeen.add(part.callID)\n toolIds.push(part.callID)\n }\n }\n\n const selectedMessageIds = new Set(messageIds)\n const summariesInSelection: Array<{ blockId: number; rawIndex: number }> = []\n for (const summary of context.summaryByBlockId.values()) {\n if (!selectedMessageIds.has(summary.anchorMessageId)) {\n continue\n }\n\n const anchorIndex = context.rawIndexById.get(summary.anchorMessageId)\n if (anchorIndex === undefined) {\n continue\n }\n\n summariesInSelection.push({\n blockId: summary.blockId,\n rawIndex: anchorIndex,\n })\n }\n\n summariesInSelection.sort((a, b) => a.rawIndex - b.rawIndex || a.blockId - b.blockId)\n for (const summary of summariesInSelection) {\n if (requiredBlockSeen.has(summary.blockId)) {\n continue\n }\n requiredBlockSeen.add(summary.blockId)\n requiredBlockIds.push(summary.blockId)\n }\n\n if (messageIds.length === 0) {\n throw new Error(\n \"Failed to map boundary matches back to raw messages. Choose boundaries that include original conversation messages.\",\n )\n }\n\n return {\n startReference,\n endReference,\n messageIds,\n messageTokenById,\n toolIds,\n requiredBlockIds,\n }\n}\n\nexport function resolveAnchorMessageId(startReference: BoundaryReference): string {\n if (startReference.kind === \"compressed-block\") {\n if (!startReference.anchorMessageId) {\n throw new Error(\"Failed to map boundary matches back to raw messages\")\n }\n return startReference.anchorMessageId\n }\n\n if (!startReference.messageId) {\n throw new Error(\"Failed to map boundary matches back to raw messages\")\n }\n return startReference.messageId\n}\n\nfunction buildBoundaryLookup(\n context: SearchContext,\n state: SessionState,\n): Map<string, BoundaryReference> {\n const lookup = new Map<string, BoundaryReference>()\n\n for (const [messageRef, messageId] of state.messageIds.byRef) {\n const rawMessage = context.rawMessagesById.get(messageId)\n if (!rawMessage) {\n continue\n }\n if (isIgnoredUserMessage(rawMessage)) {\n continue\n }\n\n const rawIndex = context.rawIndexById.get(messageId)\n if (rawIndex === undefined) {\n continue\n }\n lookup.set(messageRef, {\n kind: \"message\",\n rawIndex,\n messageId,\n })\n }\n\n const summaries = Array.from(context.summaryByBlockId.values()).sort(\n (a, b) => a.blockId - b.blockId,\n )\n for (const summary of summaries) {\n const anchorMessage = context.rawMessagesById.get(summary.anchorMessageId)\n if (!anchorMessage) {\n continue\n }\n if (isIgnoredUserMessage(anchorMessage)) {\n continue\n }\n\n const rawIndex = context.rawIndexById.get(summary.anchorMessageId)\n if (rawIndex === undefined) {\n continue\n }\n const blockRef = formatBlockRef(summary.blockId)\n if (!lookup.has(blockRef)) {\n lookup.set(blockRef, {\n kind: \"compressed-block\",\n rawIndex,\n blockId: summary.blockId,\n anchorMessageId: summary.anchorMessageId,\n })\n }\n }\n\n return lookup\n}\n","import type { CompressionBlock, PruneMessagesState, SessionState } from \"../state\"\nimport { formatBlockRef, formatMessageIdTag } from \"../message-ids\"\nimport type { AppliedCompressionResult, CompressionStateInput, SelectionResolution } from \"./types\"\nimport type { GCConfig } from \"../config\"\n\nconst DEFAULT_PROMOTION_THRESHOLD = 5\n\nexport const COMPRESSED_BLOCK_HEADER = \"[Compressed conversation section]\"\n\nexport function allocateBlockId(state: SessionState): number {\n const next = state.prune.messages.nextBlockId\n if (!Number.isInteger(next) || next < 1) {\n state.prune.messages.nextBlockId = 2\n return 1\n }\n\n state.prune.messages.nextBlockId = next + 1\n return next\n}\n\nexport function allocateRunId(state: SessionState): number {\n const next = state.prune.messages.nextRunId\n if (!Number.isInteger(next) || next < 1) {\n state.prune.messages.nextRunId = 2\n return 1\n }\n\n state.prune.messages.nextRunId = next + 1\n return next\n}\n\nexport function attachCompressionDuration(\n messagesState: PruneMessagesState,\n messageId: string,\n callId: string,\n durationMs: number,\n): number {\n if (typeof durationMs !== \"number\" || !Number.isFinite(durationMs)) {\n return 0\n }\n\n let updates = 0\n for (const block of messagesState.blocksById.values()) {\n if (block.compressMessageId !== messageId || block.compressCallId !== callId) {\n continue\n }\n\n block.durationMs = durationMs\n updates++\n }\n\n return updates\n}\n\nexport function wrapCompressedSummary(blockId: number, summary: string): string {\n const header = COMPRESSED_BLOCK_HEADER\n const footer = formatMessageIdTag(formatBlockRef(blockId))\n const body = summary.trim()\n if (body.length === 0) {\n return `${header}\\n${footer}`\n }\n return `${header}\\n${body}\\n\\n${footer}`\n}\n\nexport function applyCompressionState(\n state: SessionState,\n input: CompressionStateInput,\n selection: SelectionResolution,\n anchorMessageId: string,\n blockId: number,\n summary: string,\n consumedBlockIds: number[],\n gcConfig?: GCConfig,\n): AppliedCompressionResult {\n const messagesState = state.prune.messages\n const consumed = [...new Set(consumedBlockIds.filter((id) => Number.isInteger(id) && id > 0))]\n const included = [...consumed]\n\n const effectiveMessageIds = new Set<string>(selection.messageIds)\n const effectiveToolIds = new Set<string>(selection.toolIds)\n\n for (const consumedBlockId of consumed) {\n const consumedBlock = messagesState.blocksById.get(consumedBlockId)\n if (!consumedBlock) {\n continue\n }\n for (const messageId of consumedBlock.effectiveMessageIds) {\n effectiveMessageIds.add(messageId)\n }\n for (const toolId of consumedBlock.effectiveToolIds) {\n effectiveToolIds.add(toolId)\n }\n }\n\n const initiallyActiveMessages = new Set<string>()\n for (const messageId of effectiveMessageIds) {\n const entry = messagesState.byMessageId.get(messageId)\n if (entry && entry.activeBlockIds.length > 0) {\n initiallyActiveMessages.add(messageId)\n }\n }\n\n const initiallyActiveToolIds = new Set<string>()\n for (const activeBlockId of messagesState.activeBlockIds) {\n const activeBlock = messagesState.blocksById.get(activeBlockId)\n if (!activeBlock || !activeBlock.active) {\n continue\n }\n\n for (const toolId of activeBlock.effectiveToolIds) {\n initiallyActiveToolIds.add(toolId)\n }\n }\n\n const createdAt = Date.now()\n const block: CompressionBlock = {\n blockId,\n runId: input.runId,\n active: true,\n deactivatedByUser: false,\n compressedTokens: 0,\n summaryTokens: input.summaryTokens,\n durationMs: 0,\n mode: input.mode,\n topic: input.topic,\n batchTopic: input.batchTopic,\n startId: input.startId,\n endId: input.endId,\n anchorMessageId,\n compressMessageId: input.compressMessageId,\n compressCallId: input.compressCallId,\n includedBlockIds: included,\n consumedBlockIds: consumed,\n parentBlockIds: [],\n directMessageIds: [],\n directToolIds: [],\n effectiveMessageIds: [...effectiveMessageIds],\n effectiveToolIds: [...effectiveToolIds],\n createdAt,\n summary,\n survivedCount: 0,\n generation: \"young\",\n }\n\n const promotionThreshold = gcConfig?.promotionThreshold ?? DEFAULT_PROMOTION_THRESHOLD\n for (const [activeId, activeBlock] of messagesState.blocksById) {\n if (!activeBlock.active) continue\n if (consumed.includes(activeId)) continue\n activeBlock.survivedCount = (activeBlock.survivedCount || 0) + 1\n if (activeBlock.survivedCount >= promotionThreshold) {\n activeBlock.generation = \"old\"\n }\n }\n\n messagesState.blocksById.set(blockId, block)\n messagesState.activeBlockIds.add(blockId)\n messagesState.activeByAnchorMessageId.set(anchorMessageId, blockId)\n\n const deactivatedAt = Date.now()\n for (const consumedBlockId of consumed) {\n const consumedBlock = messagesState.blocksById.get(consumedBlockId)\n if (!consumedBlock || !consumedBlock.active) {\n continue\n }\n\n consumedBlock.active = false\n consumedBlock.deactivatedAt = deactivatedAt\n consumedBlock.deactivatedByBlockId = blockId\n if (!consumedBlock.parentBlockIds.includes(blockId)) {\n consumedBlock.parentBlockIds.push(blockId)\n }\n\n messagesState.activeBlockIds.delete(consumedBlockId)\n const mappedBlockId = messagesState.activeByAnchorMessageId.get(\n consumedBlock.anchorMessageId,\n )\n if (mappedBlockId === consumedBlockId) {\n messagesState.activeByAnchorMessageId.delete(consumedBlock.anchorMessageId)\n }\n }\n\n const removeActiveBlockId = (\n entry: { activeBlockIds: number[] },\n blockIdToRemove: number,\n ): void => {\n if (entry.activeBlockIds.length === 0) {\n return\n }\n entry.activeBlockIds = entry.activeBlockIds.filter((id) => id !== blockIdToRemove)\n }\n\n for (const consumedBlockId of consumed) {\n const consumedBlock = messagesState.blocksById.get(consumedBlockId)\n if (!consumedBlock) {\n continue\n }\n for (const messageId of consumedBlock.effectiveMessageIds) {\n const entry = messagesState.byMessageId.get(messageId)\n if (!entry) {\n continue\n }\n removeActiveBlockId(entry, consumedBlockId)\n }\n }\n\n for (const messageId of selection.messageIds) {\n const tokenCount = selection.messageTokenById.get(messageId) || 0\n const existing = messagesState.byMessageId.get(messageId)\n\n if (!existing) {\n messagesState.byMessageId.set(messageId, {\n tokenCount,\n allBlockIds: [blockId],\n activeBlockIds: [blockId],\n })\n continue\n }\n\n existing.tokenCount = Math.max(existing.tokenCount, tokenCount)\n if (!existing.allBlockIds.includes(blockId)) {\n existing.allBlockIds.push(blockId)\n }\n if (!existing.activeBlockIds.includes(blockId)) {\n existing.activeBlockIds.push(blockId)\n }\n }\n\n for (const messageId of block.effectiveMessageIds) {\n if (selection.messageTokenById.has(messageId)) {\n continue\n }\n\n const existing = messagesState.byMessageId.get(messageId)\n if (!existing) {\n continue\n }\n if (!existing.allBlockIds.includes(blockId)) {\n existing.allBlockIds.push(blockId)\n }\n if (!existing.activeBlockIds.includes(blockId)) {\n existing.activeBlockIds.push(blockId)\n }\n }\n\n let compressedTokens = 0\n const newlyCompressedMessageIds: string[] = []\n for (const messageId of effectiveMessageIds) {\n const entry = messagesState.byMessageId.get(messageId)\n if (!entry) {\n continue\n }\n\n const isNowActive = entry.activeBlockIds.length > 0\n const wasActive = initiallyActiveMessages.has(messageId)\n\n if (isNowActive && !wasActive) {\n compressedTokens += entry.tokenCount\n newlyCompressedMessageIds.push(messageId)\n }\n }\n\n const newlyCompressedToolIds: string[] = []\n for (const toolId of effectiveToolIds) {\n if (!initiallyActiveToolIds.has(toolId)) {\n newlyCompressedToolIds.push(toolId)\n }\n }\n\n block.directMessageIds = [...newlyCompressedMessageIds]\n block.directToolIds = [...newlyCompressedToolIds]\n\n block.compressedTokens = compressedTokens\n\n state.stats.pruneTokenCounter += compressedTokens\n state.stats.totalPruneTokens += state.stats.pruneTokenCounter\n state.stats.pruneTokenCounter = 0\n\n return {\n compressedTokens,\n messageIds: selection.messageIds,\n newlyCompressedMessageIds,\n newlyCompressedToolIds,\n }\n}\n","import type { PluginConfig } from \"../config\"\nimport type { SessionState } from \"../state\"\nimport { parseBoundaryId } from \"../message-ids\"\nimport { isIgnoredUserMessage, isProtectedUserMessage } from \"../messages/query\"\nimport { resolveAnchorMessageId, resolveBoundaryIds, resolveSelection } from \"./search\"\nimport { COMPRESSED_BLOCK_HEADER } from \"./state\"\nimport type {\n CompressMessageEntry,\n CompressMessageToolArgs,\n ResolvedMessageCompression,\n ResolvedMessageCompressionsResult,\n SearchContext,\n} from \"./types\"\n\ninterface SkippedIssue {\n kind: string\n messageId: string\n}\n\nclass SoftIssue extends Error {\n constructor(\n public readonly kind: string,\n public readonly messageId: string,\n message: string,\n ) {\n super(message)\n }\n}\n\nexport function validateArgs(args: CompressMessageToolArgs): void {\n if (typeof args.topic !== \"string\" || args.topic.trim().length === 0) {\n throw new Error(\"topic is required and must be a non-empty string\")\n }\n\n if (!Array.isArray(args.content) || args.content.length === 0) {\n throw new Error(\"content is required and must be a non-empty array\")\n }\n\n for (let index = 0; index < args.content.length; index++) {\n const entry = args.content[index]\n const prefix = `content[${index}]`\n\n if (typeof entry?.messageId !== \"string\" || entry.messageId.trim().length === 0) {\n throw new Error(`${prefix}.messageId is required and must be a non-empty string`)\n }\n\n if (typeof entry?.topic !== \"string\" || entry.topic.trim().length === 0) {\n throw new Error(`${prefix}.topic is required and must be a non-empty string`)\n }\n\n if (typeof entry?.summary !== \"string\" || entry.summary.trim().length === 0) {\n throw new Error(`${prefix}.summary is required and must be a non-empty string`)\n }\n }\n}\n\nexport function formatResult(\n processedCount: number,\n skippedIssues: string[],\n skippedCount: number,\n): string {\n const messageNoun = processedCount === 1 ? \"message\" : \"messages\"\n const processedText =\n processedCount > 0\n ? `Compressed ${processedCount} ${messageNoun} into ${COMPRESSED_BLOCK_HEADER}.`\n : \"Compressed 0 messages.\"\n // [FIX Bug 30] Prevent model from treating compress result as conversation end\n const instruction = \"\\nIMPORTANT: This was an automatic context compression. You MUST continue your previous task exactly where you left off. Do NOT ask the user what to do next.\"\n\n if (skippedCount === 0) {\n return processedText + instruction\n }\n\n const issueNoun = skippedCount === 1 ? \"issue\" : \"issues\"\n const issueLines = skippedIssues.map((issue) => `- ${issue}`).join(\"\\n\")\n return `${processedText}\\nSkipped ${skippedCount} ${issueNoun}:\\n${issueLines}${instruction}`\n}\n\nexport function formatIssues(skippedIssues: string[], skippedCount: number): string {\n const issueNoun = skippedCount === 1 ? \"issue\" : \"issues\"\n const issueLines = skippedIssues.map((issue) => `- ${issue}`).join(\"\\n\")\n return `Unable to compress any messages. Found ${skippedCount} ${issueNoun}:\\n${issueLines}`\n}\n\nconst ISSUE_TEMPLATES: Record<string, [singular: string, plural: string]> = {\n blocked: [\n \"refers to a protected message and cannot be compressed.\",\n \"refer to protected messages and cannot be compressed.\",\n ],\n \"invalid-format\": [\n \"is invalid. Use an injected raw message ID of the form mNNNNN.\",\n \"are invalid. Use injected raw message IDs of the form mNNNNN.\",\n ],\n \"block-id\": [\n \"is invalid here. Block IDs like bN are not allowed; use an mNNNNN message ID instead.\",\n \"are invalid here. Block IDs like bN are not allowed; use mNNNNN message IDs instead.\",\n ],\n \"not-in-context\": [\n \"is not available in the current conversation context. Choose an injected mNNNNN ID visible in context.\",\n \"are not available in the current conversation context. Choose injected mNNNNN IDs visible in context.\",\n ],\n protected: [\n \"refers to a protected message and cannot be compressed.\",\n \"refer to protected messages and cannot be compressed.\",\n ],\n \"already-compressed\": [\n \"is already part of an active compression.\",\n \"are already part of active compressions.\",\n ],\n duplicate: [\n \"was selected more than once in this batch.\",\n \"were each selected more than once in this batch.\",\n ],\n}\n\nfunction formatSkippedGroup(kind: string, messageIds: string[]): string {\n const templates = ISSUE_TEMPLATES[kind]\n const ids = messageIds.join(\", \")\n const single = messageIds.length === 1\n const prefix = single ? \"messageId\" : \"messageIds\"\n\n if (!templates) {\n return `${prefix} ${ids}: unknown issue.`\n }\n\n return `${prefix} ${ids} ${single ? templates[0] : templates[1]}`\n}\n\nfunction groupSkippedIssues(issues: SkippedIssue[]): string[] {\n const groups = new Map<string, string[]>()\n const order: string[] = []\n\n for (const issue of issues) {\n let ids = groups.get(issue.kind)\n if (!ids) {\n ids = []\n groups.set(issue.kind, ids)\n order.push(issue.kind)\n }\n ids.push(issue.messageId)\n }\n\n return order.map((kind) => {\n const ids = groups.get(kind)!\n return formatSkippedGroup(kind, ids)\n })\n}\n\nexport function resolveMessages(\n args: CompressMessageToolArgs,\n searchContext: SearchContext,\n state: SessionState,\n config: PluginConfig,\n): ResolvedMessageCompressionsResult {\n const issues: SkippedIssue[] = []\n const plans: ResolvedMessageCompression[] = []\n const seenMessageIds = new Set<string>()\n\n for (const entry of args.content) {\n const normalizedMessageId = entry.messageId.trim()\n if (seenMessageIds.has(normalizedMessageId)) {\n issues.push({ kind: \"duplicate\", messageId: normalizedMessageId })\n continue\n }\n\n try {\n const plan = resolveMessage(\n {\n ...entry,\n messageId: normalizedMessageId,\n },\n searchContext,\n state,\n config,\n )\n seenMessageIds.add(plan.entry.messageId)\n plans.push(plan)\n } catch (error: any) {\n if (error instanceof SoftIssue) {\n issues.push({ kind: error.kind, messageId: error.messageId })\n continue\n }\n\n throw error\n }\n }\n\n return {\n plans,\n skippedIssues: groupSkippedIssues(issues),\n skippedCount: issues.length,\n }\n}\n\nfunction resolveMessage(\n entry: CompressMessageEntry,\n searchContext: SearchContext,\n state: SessionState,\n config: PluginConfig,\n): ResolvedMessageCompression {\n if (entry.messageId.toUpperCase() === \"BLOCKED\") {\n throw new SoftIssue(\"blocked\", \"BLOCKED\", \"protected message\")\n }\n\n const parsed = parseBoundaryId(entry.messageId)\n\n if (!parsed) {\n throw new SoftIssue(\"invalid-format\", entry.messageId, \"invalid format\")\n }\n\n if (parsed.kind === \"compressed-block\") {\n throw new SoftIssue(\"block-id\", entry.messageId, \"block ID used\")\n }\n\n const messageId = state.messageIds.byRef.get(parsed.ref)\n const rawMessage = messageId ? searchContext.rawMessagesById.get(messageId) : undefined\n if (\n !messageId ||\n !rawMessage ||\n !searchContext.rawIndexById.has(messageId) ||\n isIgnoredUserMessage(rawMessage)\n ) {\n throw new SoftIssue(\"not-in-context\", parsed.ref, \"not in context\")\n }\n\n const { startReference, endReference } = resolveBoundaryIds(\n searchContext,\n state,\n parsed.ref,\n parsed.ref,\n )\n const selection = resolveSelection(searchContext, startReference, endReference)\n\n if (isProtectedUserMessage(config, rawMessage)) {\n throw new SoftIssue(\"protected\", parsed.ref, \"protected message\")\n }\n\n const pruneEntry = state.prune.messages.byMessageId.get(messageId)\n if (pruneEntry && pruneEntry.activeBlockIds.length > 0) {\n throw new SoftIssue(\"already-compressed\", parsed.ref, \"already compressed\")\n }\n\n return {\n entry: {\n messageId: parsed.ref,\n topic: entry.topic,\n summary: entry.summary,\n },\n selection,\n anchorMessageId: resolveAnchorMessageId(startReference),\n }\n}\n","/**\n * State persistence module for ACP plugin.\n * Persists pruned tool IDs across sessions so they survive OpenCode restarts.\n * Storage location: ~/.local/share/opencode/storage/plugin/acp/{sessionId}.json\n */\n\nimport * as fs from \"fs/promises\"\nimport { existsSync } from \"fs\"\nimport { homedir } from \"os\"\nimport { join } from \"path\"\nimport { cpSync, existsSync as existsSyncSync } from \"fs\"\nimport type { CompressionBlock, PrunedMessageEntry, SessionState, SessionStats } from \"./types\"\nimport type { Logger } from \"../logger\"\nimport { serializePruneMessagesState } from \"./utils\"\n\nconst LEGACY_STORAGE_DIR = join(\n process.env.XDG_DATA_HOME || join(homedir(), \".local\", \"share\"),\n \"opencode\",\n \"storage\",\n \"plugin\",\n \"dcp\",\n)\n\n/** Prune state as stored on disk */\nexport interface PersistedPruneMessagesState {\n byMessageId: Record<string, PrunedMessageEntry>\n blocksById: Record<string, CompressionBlock>\n activeBlockIds: number[]\n activeByAnchorMessageId: Record<string, number>\n nextBlockId: number\n nextRunId: number\n markedForCleanup?: number[]\n}\n\nexport interface PersistedPrune {\n tools?: Record<string, number>\n messages?: PersistedPruneMessagesState\n}\n\nexport interface PersistedNudges {\n contextLimitAnchors: string[]\n turnNudgeAnchors?: string[]\n iterationNudgeAnchors?: string[]\n}\n\nexport interface PersistedMessageIds {\n byRawId: Record<string, string>\n byRef: Record<string, string>\n nextRef: number\n}\n\nexport interface PersistedSessionState {\n sessionName?: string\n prune: PersistedPrune\n nudges: PersistedNudges\n stats: SessionStats\n lastUpdated: string\n messageIds?: PersistedMessageIds\n lastCompaction?: number\n}\n\nconst STORAGE_DIR = join(\n process.env.XDG_DATA_HOME || join(homedir(), \".local\", \"share\"),\n \"opencode\",\n \"storage\",\n \"plugin\",\n \"acp\",\n)\n\n/** One-time migration: copy plugin/dcp/ → plugin/acp/ if ACP dir doesn't exist yet */\nfunction migrateFromLegacyIfNeeded(logger: Logger): void {\n if (existsSyncSync(STORAGE_DIR)) return\n if (!existsSyncSync(LEGACY_STORAGE_DIR)) return\n try {\n cpSync(LEGACY_STORAGE_DIR, STORAGE_DIR, { recursive: true })\n logger.info(`[ACP] Migrated storage from ${LEGACY_STORAGE_DIR} → ${STORAGE_DIR}`)\n } catch (e: any) {\n logger.warn(`[ACP] Storage migration failed: ${e.message}`)\n }\n}\n\nasync function ensureStorageDir(logger: Logger): Promise<void> {\n if (!existsSync(STORAGE_DIR)) {\n migrateFromLegacyIfNeeded(logger)\n await fs.mkdir(STORAGE_DIR, { recursive: true })\n }\n}\n\nfunction getSessionFilePath(sessionId: string): string {\n return join(STORAGE_DIR, `${sessionId}.json`)\n}\n\nasync function writePersistedSessionState(\n sessionId: string,\n state: PersistedSessionState,\n logger: Logger,\n): Promise<void> {\n await ensureStorageDir(logger)\n\n const filePath = getSessionFilePath(sessionId)\n const content = JSON.stringify(state, null, 2)\n await fs.writeFile(filePath, content, \"utf-8\")\n\n logger.info(\"Saved session state to disk\", {\n sessionId,\n totalTokensSaved: state.stats.totalPruneTokens,\n })\n}\n\n// [FIX Bug 6] Removed try/catch — errors now propagate to callers so they know save failed\nexport async function saveSessionState(\n sessionState: SessionState,\n logger: Logger,\n sessionName?: string,\n): Promise<void> {\n if (!sessionState.sessionId) {\n return\n }\n\n const state: PersistedSessionState = {\n sessionName: sessionName,\n prune: {\n tools: Object.fromEntries(sessionState.prune.tools),\n messages: serializePruneMessagesState(sessionState.prune.messages),\n },\n nudges: {\n contextLimitAnchors: Array.from(sessionState.nudges.contextLimitAnchors),\n turnNudgeAnchors: Array.from(sessionState.nudges.turnNudgeAnchors),\n iterationNudgeAnchors: Array.from(sessionState.nudges.iterationNudgeAnchors),\n },\n stats: sessionState.stats,\n lastUpdated: new Date().toISOString(),\n messageIds: {\n byRawId: Object.fromEntries(sessionState.messageIds.byRawId),\n byRef: Object.fromEntries(sessionState.messageIds.byRef),\n nextRef: sessionState.messageIds.nextRef,\n },\n lastCompaction: sessionState.lastCompaction,\n }\n\n await writePersistedSessionState(sessionState.sessionId, state, logger)\n}\n\nexport async function loadSessionState(\n sessionId: string,\n logger: Logger,\n): Promise<PersistedSessionState | null> {\n try {\n const filePath = getSessionFilePath(sessionId)\n\n if (!existsSync(filePath)) {\n return null\n }\n\n const content = await fs.readFile(filePath, \"utf-8\")\n const state = JSON.parse(content) as PersistedSessionState\n\n const hasPruneTools = state?.prune?.tools && typeof state.prune.tools === \"object\"\n const hasPruneMessages = state?.prune?.messages && typeof state.prune.messages === \"object\"\n const hasNudgeFormat = state?.nudges && typeof state.nudges === \"object\"\n if (\n !state ||\n !state.prune ||\n !hasPruneTools ||\n !hasPruneMessages ||\n !state.stats ||\n !hasNudgeFormat\n ) {\n logger.warn(\"Invalid session state file, ignoring\", {\n sessionId: sessionId,\n })\n return null\n }\n\n const rawContextLimitAnchors = Array.isArray(state.nudges.contextLimitAnchors)\n ? state.nudges.contextLimitAnchors\n : []\n const validAnchors = rawContextLimitAnchors.filter(\n (entry): entry is string => typeof entry === \"string\",\n )\n const dedupedAnchors = [...new Set(validAnchors)]\n if (validAnchors.length !== rawContextLimitAnchors.length) {\n logger.warn(\"Filtered out malformed contextLimitAnchors entries\", {\n sessionId: sessionId,\n original: rawContextLimitAnchors.length,\n valid: validAnchors.length,\n })\n }\n state.nudges.contextLimitAnchors = dedupedAnchors\n\n const rawTurnNudgeAnchors = Array.isArray(state.nudges.turnNudgeAnchors)\n ? state.nudges.turnNudgeAnchors\n : []\n const validSoftAnchors = rawTurnNudgeAnchors.filter(\n (entry): entry is string => typeof entry === \"string\",\n )\n const dedupedSoftAnchors = [...new Set(validSoftAnchors)]\n if (validSoftAnchors.length !== rawTurnNudgeAnchors.length) {\n logger.warn(\"Filtered out malformed turnNudgeAnchors entries\", {\n sessionId: sessionId,\n original: rawTurnNudgeAnchors.length,\n valid: validSoftAnchors.length,\n })\n }\n state.nudges.turnNudgeAnchors = dedupedSoftAnchors\n\n const rawIterationNudgeAnchors = Array.isArray(state.nudges.iterationNudgeAnchors)\n ? state.nudges.iterationNudgeAnchors\n : []\n const validIterationAnchors = rawIterationNudgeAnchors.filter(\n (entry): entry is string => typeof entry === \"string\",\n )\n const dedupedIterationAnchors = [...new Set(validIterationAnchors)]\n if (validIterationAnchors.length !== rawIterationNudgeAnchors.length) {\n logger.warn(\"Filtered out malformed iterationNudgeAnchors entries\", {\n sessionId: sessionId,\n original: rawIterationNudgeAnchors.length,\n valid: validIterationAnchors.length,\n })\n }\n state.nudges.iterationNudgeAnchors = dedupedIterationAnchors\n\n const persistedMessageIds = (state as any).messageIds as PersistedMessageIds | undefined\n if (persistedMessageIds) {\n ;(state as any)._persistedMessageIds = persistedMessageIds\n }\n const persistedLastCompaction = (state as any).lastCompaction as number | undefined\n if (persistedLastCompaction !== undefined) {\n ;(state as any)._persistedLastCompaction = persistedLastCompaction\n }\n\n logger.info(\"Loaded session state from disk\", {\n sessionId: sessionId,\n })\n\n return state\n } catch (error: any) {\n logger.warn(\"Failed to load session state\", {\n sessionId: sessionId,\n error: error?.message,\n })\n return null\n }\n}\n\nexport interface AggregatedStats {\n totalTokens: number\n totalTools: number\n totalMessages: number\n sessionCount: number\n}\n\nexport async function loadAllSessionStats(logger: Logger): Promise<AggregatedStats> {\n const result: AggregatedStats = {\n totalTokens: 0,\n totalTools: 0,\n totalMessages: 0,\n sessionCount: 0,\n }\n\n try {\n if (!existsSync(STORAGE_DIR)) {\n return result\n }\n\n const files = await fs.readdir(STORAGE_DIR)\n const jsonFiles = files.filter((f) => f.endsWith(\".json\"))\n\n for (const file of jsonFiles) {\n try {\n const filePath = join(STORAGE_DIR, file)\n const content = await fs.readFile(filePath, \"utf-8\")\n const state = JSON.parse(content) as PersistedSessionState\n\n if (state?.stats?.totalPruneTokens && state?.prune) {\n result.totalTokens += state.stats.totalPruneTokens\n result.totalTools += state.prune.tools\n ? Object.keys(state.prune.tools).length\n : 0\n result.totalMessages += state.prune.messages?.byMessageId\n ? Object.keys(state.prune.messages.byMessageId).length\n : 0\n result.sessionCount++\n }\n } catch {\n // Skip invalid files\n }\n }\n\n logger.debug(\"Loaded all-time stats\", result)\n } catch (error: any) {\n logger.warn(\"Failed to load all-time stats\", { error: error?.message })\n }\n\n return result\n}\n","import type {\n CompressionBlock,\n PruneMessagesState,\n PrunedMessageEntry,\n SessionState,\n WithParts,\n} from \"./types\"\nimport { isIgnoredUserMessage, messageHasCompress } from \"../messages/query\"\nimport { isMessageWithInfo } from \"../messages/shape\"\nimport { countTokens } from \"../token-utils\"\n\n// [FIX Bug 3] Added summary check to match getCurrentTokenUsage exclusion logic\nexport const isMessageCompacted = (state: SessionState, msg: WithParts): boolean => {\n if (!isMessageWithInfo(msg)) {\n return false\n }\n\n if (state.lastCompaction <= 0) return false\n if (msg.info.time.created < state.lastCompaction) {\n return true\n }\n if (msg.info.summary === true && msg.info.time.created === state.lastCompaction) {\n return true\n }\n const pruneEntry = state.prune.messages.byMessageId.get(msg.info.id)\n if (pruneEntry && pruneEntry.activeBlockIds.length > 0) {\n return true\n }\n return false\n}\n\ninterface PersistedPruneMessagesState {\n byMessageId: Record<string, PrunedMessageEntry>\n blocksById: Record<string, CompressionBlock>\n activeBlockIds: number[]\n activeByAnchorMessageId: Record<string, number>\n nextBlockId: number\n nextRunId: number\n markedForCleanup?: number[]\n}\n\nexport function serializePruneMessagesState(\n messagesState: PruneMessagesState,\n): PersistedPruneMessagesState {\n return {\n byMessageId: Object.fromEntries(messagesState.byMessageId),\n blocksById: Object.fromEntries(\n Array.from(messagesState.blocksById.entries()).map(([blockId, block]) => [\n String(blockId),\n block,\n ]),\n ),\n activeBlockIds: Array.from(messagesState.activeBlockIds),\n activeByAnchorMessageId: Object.fromEntries(messagesState.activeByAnchorMessageId),\n nextBlockId: messagesState.nextBlockId,\n nextRunId: messagesState.nextRunId,\n markedForCleanup: Array.from(messagesState.markedForCleanup),\n }\n}\n\nexport async function isSubAgentSession(client: any, sessionID: string): Promise<boolean> {\n try {\n const result = await client.session.get({ path: { id: sessionID } })\n return !!result.data?.parentID\n } catch (error: any) {\n return false\n }\n}\n\nexport function findLastCompactionTimestamp(messages: WithParts[]): number {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (!isMessageWithInfo(msg)) {\n continue\n }\n if (msg.info.role === \"assistant\" && msg.info.summary === true) {\n return msg.info.time.created\n }\n }\n return 0\n}\n\nexport function countTurns(state: SessionState, messages: WithParts[]): number {\n let turnCount = 0\n for (const msg of messages) {\n if (!isMessageWithInfo(msg)) {\n continue\n }\n if (isMessageCompacted(state, msg)) {\n continue\n }\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type === \"step-start\") {\n turnCount++\n }\n }\n }\n return turnCount\n}\n\nexport function loadPruneMap(obj?: Record<string, number>): Map<string, number> {\n if (!obj || typeof obj !== \"object\") {\n return new Map()\n }\n\n const entries = Object.entries(obj).filter(\n (entry): entry is [string, number] =>\n typeof entry[0] === \"string\" && typeof entry[1] === \"number\",\n )\n return new Map(entries)\n}\n\nexport function createPruneMessagesState(): PruneMessagesState {\n return {\n byMessageId: new Map<string, PrunedMessageEntry>(),\n blocksById: new Map<number, CompressionBlock>(),\n activeBlockIds: new Set<number>(),\n activeByAnchorMessageId: new Map<string, number>(),\n nextBlockId: 1,\n nextRunId: 1,\n markedForCleanup: new Set<number>(),\n }\n}\n\nexport function loadPruneMessagesState(\n persisted?: PersistedPruneMessagesState,\n): PruneMessagesState {\n const state = createPruneMessagesState()\n if (!persisted || typeof persisted !== \"object\") {\n return state\n }\n\n if (typeof persisted.nextBlockId === \"number\" && Number.isInteger(persisted.nextBlockId)) {\n state.nextBlockId = Math.max(1, persisted.nextBlockId)\n }\n if (typeof persisted.nextRunId === \"number\" && Number.isInteger(persisted.nextRunId)) {\n state.nextRunId = Math.max(1, persisted.nextRunId)\n }\n\n if (persisted.byMessageId && typeof persisted.byMessageId === \"object\") {\n for (const [messageId, entry] of Object.entries(persisted.byMessageId)) {\n if (!entry || typeof entry !== \"object\") {\n continue\n }\n\n const tokenCount = typeof entry.tokenCount === \"number\" ? entry.tokenCount : 0\n const allBlockIds = Array.isArray(entry.allBlockIds)\n ? [\n ...new Set(\n entry.allBlockIds.filter(\n (id): id is number => Number.isInteger(id) && id > 0,\n ),\n ),\n ]\n : []\n const activeBlockIds = Array.isArray(entry.activeBlockIds)\n ? [\n ...new Set(\n entry.activeBlockIds.filter(\n (id): id is number => Number.isInteger(id) && id > 0,\n ),\n ),\n ]\n : []\n\n state.byMessageId.set(messageId, {\n tokenCount,\n allBlockIds,\n activeBlockIds,\n })\n }\n }\n\n if (persisted.blocksById && typeof persisted.blocksById === \"object\") {\n for (const [blockIdStr, block] of Object.entries(persisted.blocksById)) {\n const blockId = Number.parseInt(blockIdStr, 10)\n if (!Number.isInteger(blockId) || blockId < 1 || !block || typeof block !== \"object\") {\n continue\n }\n\n const toNumberArray = (value: unknown): number[] =>\n Array.isArray(value)\n ? [\n ...new Set(\n value.filter(\n (item): item is number => Number.isInteger(item) && item > 0,\n ),\n ),\n ]\n : []\n const toStringArray = (value: unknown): string[] =>\n Array.isArray(value)\n ? [...new Set(value.filter((item): item is string => typeof item === \"string\"))]\n : []\n\n state.blocksById.set(blockId, {\n blockId,\n runId:\n typeof block.runId === \"number\" &&\n Number.isInteger(block.runId) &&\n block.runId > 0\n ? block.runId\n : blockId,\n active: block.active === true,\n deactivatedByUser: block.deactivatedByUser === true,\n compressedTokens:\n typeof block.compressedTokens === \"number\" &&\n Number.isFinite(block.compressedTokens)\n ? Math.max(0, block.compressedTokens)\n : 0,\n summaryTokens:\n typeof block.summaryTokens === \"number\" && Number.isFinite(block.summaryTokens)\n ? Math.max(0, block.summaryTokens)\n : typeof block.summary === \"string\"\n ? countTokens(block.summary)\n : 0,\n durationMs:\n typeof block.durationMs === \"number\" && Number.isFinite(block.durationMs)\n ? Math.max(0, block.durationMs)\n : 0,\n mode: block.mode === \"range\" || block.mode === \"message\" ? block.mode : undefined,\n topic: typeof block.topic === \"string\" ? block.topic : \"\",\n batchTopic:\n typeof block.batchTopic === \"string\"\n ? block.batchTopic\n : typeof block.topic === \"string\"\n ? block.topic\n : \"\",\n startId: typeof block.startId === \"string\" ? block.startId : \"\",\n endId: typeof block.endId === \"string\" ? block.endId : \"\",\n anchorMessageId:\n typeof block.anchorMessageId === \"string\" ? block.anchorMessageId : \"\",\n compressMessageId:\n typeof block.compressMessageId === \"string\" ? block.compressMessageId : \"\",\n compressCallId:\n typeof block.compressCallId === \"string\" ? block.compressCallId : undefined,\n includedBlockIds: toNumberArray(block.includedBlockIds),\n consumedBlockIds: toNumberArray(block.consumedBlockIds),\n parentBlockIds: toNumberArray(block.parentBlockIds),\n directMessageIds: toStringArray(block.directMessageIds),\n directToolIds: toStringArray(block.directToolIds),\n effectiveMessageIds: toStringArray(block.effectiveMessageIds),\n effectiveToolIds: toStringArray(block.effectiveToolIds),\n createdAt: typeof block.createdAt === \"number\" ? block.createdAt : 0,\n deactivatedAt:\n typeof block.deactivatedAt === \"number\" ? block.deactivatedAt : undefined,\n deactivatedByBlockId:\n typeof block.deactivatedByBlockId === \"number\" &&\n Number.isInteger(block.deactivatedByBlockId)\n ? block.deactivatedByBlockId\n : undefined,\n summary: typeof block.summary === \"string\" ? block.summary : \"\",\n survivedCount:\n typeof block.survivedCount === \"number\" && Number.isFinite(block.survivedCount)\n ? Math.max(0, Math.floor(block.survivedCount))\n : 0,\n generation:\n block.generation === \"young\" || block.generation === \"old\"\n ? block.generation\n : undefined,\n })\n }\n }\n\n // [FIX Bug 11] Skip loading persisted activeBlockIds here.\n // They will be correctly rebuilt from blocksById below (lines 273-286).\n // Loading them here first caused stale IDs for blocks with active:false.\n\n if (\n persisted.activeByAnchorMessageId &&\n typeof persisted.activeByAnchorMessageId === \"object\"\n ) {\n for (const [anchorMessageId, blockId] of Object.entries(\n persisted.activeByAnchorMessageId,\n )) {\n if (typeof blockId !== \"number\" || !Number.isInteger(blockId) || blockId < 1) {\n continue\n }\n state.activeByAnchorMessageId.set(anchorMessageId, blockId)\n }\n }\n\n for (const [blockId, block] of state.blocksById) {\n if (block.active) {\n state.activeBlockIds.add(blockId)\n if (block.anchorMessageId) {\n state.activeByAnchorMessageId.set(block.anchorMessageId, blockId)\n }\n }\n if (blockId >= state.nextBlockId) {\n state.nextBlockId = blockId + 1\n }\n if (block.runId >= state.nextRunId) {\n state.nextRunId = block.runId + 1\n }\n }\n\n if (Array.isArray(persisted.markedForCleanup)) {\n for (const id of persisted.markedForCleanup) {\n if (Number.isInteger(id) && id > 0 && state.blocksById.has(id)) {\n state.markedForCleanup.add(id)\n }\n }\n }\n\n return state\n}\n\nexport function collectTurnNudgeAnchors(messages: WithParts[]): Set<string> {\n const anchors = new Set<string>()\n let pendingUserMessageId: string | null = null\n\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i]\n\n if (messageHasCompress(message)) {\n break\n }\n\n if (message.info.role === \"user\") {\n if (!isIgnoredUserMessage(message)) {\n pendingUserMessageId = message.info.id\n }\n continue\n }\n\n if (message.info.role === \"assistant\" && pendingUserMessageId) {\n anchors.add(message.info.id)\n anchors.add(pendingUserMessageId)\n pendingUserMessageId = null\n }\n }\n\n return anchors\n}\n\nexport function getActiveSummaryTokenUsage(state: SessionState): number {\n let total = 0\n for (const blockId of state.prune.messages.activeBlockIds) {\n const block = state.prune.messages.blocksById.get(blockId)\n if (!block || !block.active) {\n continue\n }\n total += block.summaryTokens\n }\n return total\n}\n\nexport function resetOnCompaction(state: SessionState): void {\n state.toolParameters.clear()\n state.prune.tools = new Map<string, number>()\n // [PATCH Bug 2] Preserve prune.messages (compression blocks) on compaction.\n // Only reset transient state. Compression blocks are still valid even after\n // opencode compacts — their summaries are still needed in context.\n state.nudges = {\n contextLimitAnchors: new Set<string>(),\n turnNudgeAnchors: new Set<string>(),\n iterationNudgeAnchors: new Set<string>(),\n }\n // [FIX] Reset message IDs on compaction — old mappings are stale after\n // compaction replaces messages with a summary. Keeping them causes\n // assignMessageRefs to allocate from stale nextRef positions.\n state.messageIds = {\n byRawId: new Map<string, string>(),\n byRef: new Map<string, string>(),\n nextRef: 1,\n }\n}\n","import type { SessionState } from \"../state/types\"\nimport { attachCompressionDuration } from \"./state\"\n\nexport interface PendingCompressionDuration {\n messageId: string\n callId: string\n durationMs: number\n}\n\nexport interface CompressionTimingState {\n startsByCallId: Map<string, number>\n pendingByCallId: Map<string, PendingCompressionDuration>\n}\n\nexport function buildCompressionTimingKey(messageId: string, callId: string): string {\n return `${messageId}:${callId}`\n}\n\nexport function consumeCompressionStart(\n state: SessionState,\n messageId: string,\n callId: string,\n): number | undefined {\n const key = buildCompressionTimingKey(messageId, callId)\n const start = state.compressionTiming.startsByCallId.get(key)\n state.compressionTiming.startsByCallId.delete(key)\n return start\n}\n\nexport function resolveCompressionDuration(\n startedAt: number | undefined,\n eventTime: number | undefined,\n partTime: { start?: unknown; end?: unknown } | undefined,\n): number | undefined {\n const runningAt =\n typeof partTime?.start === \"number\" && Number.isFinite(partTime.start)\n ? partTime.start\n : eventTime\n const pendingToRunningMs =\n typeof startedAt === \"number\" && typeof runningAt === \"number\"\n ? Math.max(0, runningAt - startedAt)\n : undefined\n\n const toolStart = partTime?.start\n const toolEnd = partTime?.end\n const runtimeMs =\n typeof toolStart === \"number\" &&\n Number.isFinite(toolStart) &&\n typeof toolEnd === \"number\" &&\n Number.isFinite(toolEnd)\n ? Math.max(0, toolEnd - toolStart)\n : undefined\n\n return typeof pendingToRunningMs === \"number\" ? pendingToRunningMs : runtimeMs\n}\n\nexport function applyPendingCompressionDurations(state: SessionState): number {\n if (state.compressionTiming.pendingByCallId.size === 0) {\n return 0\n }\n\n let updates = 0\n for (const [key, entry] of state.compressionTiming.pendingByCallId) {\n const applied = attachCompressionDuration(\n state.prune.messages,\n entry.messageId,\n entry.callId,\n entry.durationMs,\n )\n if (applied > 0) {\n updates += applied\n state.compressionTiming.pendingByCallId.delete(key)\n }\n }\n\n return updates\n}\n","import type { SessionState, ToolParameterEntry, WithParts } from \"./types\"\nimport type { Logger } from \"../logger\"\nimport { applyPendingCompressionDurations } from \"../compress/timing\"\nimport { loadSessionState, saveSessionState } from \"./persistence\"\nimport {\n isSubAgentSession,\n findLastCompactionTimestamp,\n countTurns,\n resetOnCompaction,\n createPruneMessagesState,\n loadPruneMessagesState,\n loadPruneMap,\n collectTurnNudgeAnchors,\n} from \"./utils\"\nimport { getLastUserMessage } from \"../messages/query\"\nimport { parseMessageRef, formatMessageRef } from \"../message-ids\"\n\nexport const checkSession = async (\n client: any,\n state: SessionState,\n logger: Logger,\n messages: WithParts[],\n manualModeDefault: boolean,\n): Promise<void> => {\n const lastUserMessage = getLastUserMessage(messages)\n if (!lastUserMessage) {\n return\n }\n\n const lastSessionId = lastUserMessage.info.sessionID\n\n if (state.sessionId === null || state.sessionId !== lastSessionId) {\n logger.info(`Session changed: ${state.sessionId} -> ${lastSessionId}`)\n try {\n await ensureSessionInitialized(\n client,\n state,\n lastSessionId,\n logger,\n messages,\n manualModeDefault,\n )\n } catch (err: any) {\n logger.error(\"Failed to initialize session state\", { error: err.message })\n }\n }\n\n const lastCompactionTimestamp = findLastCompactionTimestamp(messages)\n if (lastCompactionTimestamp > state.lastCompaction) {\n state.lastCompaction = lastCompactionTimestamp\n resetOnCompaction(state)\n logger.info(\"Detected compaction - reset stale state\", {\n timestamp: lastCompactionTimestamp,\n })\n\n saveSessionState(state, logger).catch((error) => {\n logger.warn(\"Failed to persist state reset after compaction\", {\n error: error instanceof Error ? error.message : String(error),\n })\n })\n }\n\n state.currentTurn = countTurns(state, messages)\n}\n\nexport function createSessionState(): SessionState {\n return {\n sessionId: null,\n isSubAgent: false,\n manualMode: false,\n compressPermission: undefined,\n pendingManualTrigger: null,\n prune: {\n tools: new Map<string, number>(),\n messages: createPruneMessagesState(),\n },\n nudges: {\n contextLimitAnchors: new Set<string>(),\n turnNudgeAnchors: new Set<string>(),\n iterationNudgeAnchors: new Set<string>(),\n },\n stats: {\n pruneTokenCounter: 0,\n totalPruneTokens: 0,\n },\n compressionTiming: {\n startsByCallId: new Map<string, number>(),\n pendingByCallId: new Map(),\n },\n toolParameters: new Map<string, ToolParameterEntry>(),\n subAgentResultCache: new Map<string, string>(),\n toolIdList: [],\n messageIds: {\n byRawId: new Map<string, string>(),\n byRef: new Map<string, string>(),\n nextRef: 1,\n },\n lastCompaction: 0,\n currentTurn: 0,\n modelContextLimit: undefined,\n systemPromptTokens: undefined,\n }\n}\n\nexport function resetSessionState(state: SessionState): void {\n state.sessionId = null\n state.isSubAgent = false\n state.manualMode = false\n state.compressPermission = undefined\n state.pendingManualTrigger = null\n state.prune = {\n tools: new Map<string, number>(),\n messages: createPruneMessagesState(),\n }\n state.nudges = {\n contextLimitAnchors: new Set<string>(),\n turnNudgeAnchors: new Set<string>(),\n iterationNudgeAnchors: new Set<string>(),\n }\n state.stats = {\n pruneTokenCounter: 0,\n totalPruneTokens: 0,\n }\n state.toolParameters.clear()\n state.subAgentResultCache.clear()\n state.toolIdList = []\n state.messageIds = {\n byRawId: new Map<string, string>(),\n byRef: new Map<string, string>(),\n nextRef: 1,\n }\n state.lastCompaction = 0\n state.currentTurn = 0\n state.modelContextLimit = undefined\n state.systemPromptTokens = undefined\n}\n\nexport async function ensureSessionInitialized(\n client: any,\n state: SessionState,\n sessionId: string,\n logger: Logger,\n messages: WithParts[],\n manualModeEnabled: boolean,\n): Promise<void> {\n if (state.sessionId === sessionId) {\n return\n }\n\n resetSessionState(state)\n state.manualMode = manualModeEnabled ? \"active\" : false\n state.sessionId = sessionId\n\n const isSubAgent = await isSubAgentSession(client, sessionId)\n state.isSubAgent = isSubAgent\n\n state.lastCompaction = findLastCompactionTimestamp(messages)\n state.currentTurn = countTurns(state, messages)\n state.nudges.turnNudgeAnchors = collectTurnNudgeAnchors(messages)\n\n const persisted = await loadSessionState(sessionId, logger)\n if (persisted === null) {\n return\n }\n\n state.prune.tools = loadPruneMap(persisted.prune.tools)\n state.prune.messages = loadPruneMessagesState(persisted.prune.messages)\n state.nudges.contextLimitAnchors = new Set<string>(persisted.nudges.contextLimitAnchors || [])\n state.nudges.turnNudgeAnchors = new Set<string>([\n ...state.nudges.turnNudgeAnchors,\n ...(persisted.nudges.turnNudgeAnchors || []),\n ])\n state.nudges.iterationNudgeAnchors = new Set<string>(\n persisted.nudges.iterationNudgeAnchors || [],\n )\n state.stats = {\n pruneTokenCounter: persisted.stats?.pruneTokenCounter || 0,\n totalPruneTokens: persisted.stats?.totalPruneTokens || 0,\n }\n\n const persistedAny = persisted as any\n if (persistedAny._persistedMessageIds) {\n state.messageIds = {\n byRawId: new Map(Object.entries(persistedAny._persistedMessageIds.byRawId || {})),\n byRef: new Map(Object.entries(persistedAny._persistedMessageIds.byRef || {})),\n nextRef: persistedAny._persistedMessageIds.nextRef || 1,\n }\n // [FIX Bug 29] Auto-cleanup stale synthetic message refs from persistence\n for (const [rawId, ref] of state.messageIds.byRawId) {\n if (rawId.startsWith(\"msg_dcp_summary_\") || rawId.startsWith(\"msg_dcp_text_\")) {\n state.messageIds.byRawId.delete(rawId)\n state.messageIds.byRef.delete(ref)\n }\n }\n // Migrate 4-digit refs (m0001) to 5-digit (m00001) for msgid expansion\n for (const [rawId, oldRef] of state.messageIds.byRawId) {\n const parsed = parseMessageRef(oldRef)\n if (parsed !== null) {\n const newRef = formatMessageRef(parsed)\n if (newRef !== oldRef) {\n state.messageIds.byRawId.set(rawId, newRef)\n state.messageIds.byRef.delete(oldRef)\n state.messageIds.byRef.set(newRef, rawId)\n }\n }\n }\n }\n if (persistedAny._persistedLastCompaction !== undefined) {\n state.lastCompaction = Math.max(state.lastCompaction, persistedAny._persistedLastCompaction)\n }\n\n const applied = applyPendingCompressionDurations(state)\n if (applied > 0) {\n await saveSessionState(state, logger)\n }\n // [FIX Bug 1] Always save after initialization to persist messageIds + lastCompaction\n await saveSessionState(state, logger)\n}\n","import type { SessionState, ToolStatus, WithParts } from \"./index\"\nimport type { Logger } from \"../logger\"\nimport { PluginConfig } from \"../config\"\nimport { isMessageCompacted } from \"./utils\"\nimport { countToolTokens, extractToolContent } from \"../token-utils\"\n\nconst MAX_TOOL_CACHE_SIZE = 1000\n\n/**\n * Sync tool parameters from session messages.\n */\nexport function syncToolCache(\n state: SessionState,\n config: PluginConfig,\n logger: Logger,\n messages: WithParts[],\n): void {\n try {\n logger.info(\"Syncing tool parameters from OpenCode messages\")\n\n let turnCounter = 0\n\n for (const msg of messages) {\n if (isMessageCompacted(state, msg)) {\n continue\n }\n\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type === \"step-start\") {\n turnCounter++\n continue\n }\n\n if (part.type !== \"tool\" || !part.callID) {\n continue\n }\n\n const turnProtectionEnabled = config.turnProtection.enabled\n const turnProtectionTurns = config.turnProtection.turns\n const isProtectedByTurn =\n turnProtectionEnabled &&\n turnProtectionTurns > 0 &&\n state.currentTurn - turnCounter < turnProtectionTurns\n\n if (state.toolParameters.has(part.callID)) {\n continue\n }\n\n if (isProtectedByTurn) {\n continue\n }\n\n // [FIX Bug 33] Use fast token estimate instead of expensive Anthropic tokenizer\n // The tokenizer takes ~50ms per call; with 500+ tools that's 25 seconds.\n // text.length / 4 is accurate enough for pruning decisions.\n const contents = extractToolContent(part)\n const rawLength = contents.reduce((sum: number, s: string) => sum + (s?.length ?? 0), 0)\n const tokenCount = Math.round(rawLength / 4)\n\n state.toolParameters.set(part.callID, {\n tool: part.tool,\n parameters: part.state?.input ?? {},\n status: part.state.status as ToolStatus | undefined,\n error: part.state.status === \"error\" ? part.state.error : undefined,\n turn: turnCounter,\n tokenCount,\n })\n logger.info(\n `Cached tool id: ${part.callID} (turn ${turnCounter}${tokenCount !== undefined ? `, ${tokenCount} tokens` : \"\"})`,\n )\n }\n }\n\n logger.info(\n `Synced cache - size: ${state.toolParameters.size}, currentTurn: ${state.currentTurn}`,\n )\n trimToolParametersCache(state)\n } catch (error) {\n logger.warn(\"Failed to sync tool parameters from OpenCode\", {\n error: error instanceof Error ? error.message : String(error),\n })\n }\n}\n\n/**\n * Trim the tool parameters cache to prevent unbounded memory growth.\n * Uses FIFO eviction - removes oldest entries first.\n */\nexport function trimToolParametersCache(state: SessionState): void {\n if (state.toolParameters.size <= MAX_TOOL_CACHE_SIZE) {\n return\n }\n\n const keysToRemove = Array.from(state.toolParameters.keys()).slice(\n 0,\n state.toolParameters.size - MAX_TOOL_CACHE_SIZE,\n )\n\n for (const key of keysToRemove) {\n state.toolParameters.delete(key)\n }\n}\n","function normalizePath(input: string): string {\n return input.replaceAll(\"\\\\\\\\\", \"/\")\n}\n\nfunction escapeRegExpChar(ch: string): string {\n return /[\\\\.^$+{}()|\\[\\]]/.test(ch) ? `\\\\${ch}` : ch\n}\n\nexport function matchesGlob(inputPath: string, pattern: string): boolean {\n if (!pattern) return false\n\n const input = normalizePath(inputPath)\n const pat = normalizePath(pattern)\n\n let regex = \"^\"\n\n for (let i = 0; i < pat.length; i++) {\n const ch = pat[i]\n\n if (ch === \"*\") {\n const next = pat[i + 1]\n if (next === \"*\") {\n const after = pat[i + 2]\n if (after === \"/\") {\n // **/ (zero or more directories)\n regex += \"(?:.*/)?\"\n i += 2\n continue\n }\n\n // **\n regex += \".*\"\n i++\n continue\n }\n\n // *\n regex += \"[^/]*\"\n continue\n }\n\n if (ch === \"?\") {\n regex += \"[^/]\"\n continue\n }\n\n if (ch === \"/\") {\n regex += \"/\"\n continue\n }\n\n regex += escapeRegExpChar(ch)\n }\n\n regex += \"$\"\n\n return new RegExp(regex).test(input)\n}\n\nexport function getFilePathsFromParameters(tool: string, parameters: unknown): string[] {\n if (typeof parameters !== \"object\" || parameters === null) {\n return []\n }\n\n const paths: string[] = []\n const params = parameters as Record<string, any>\n\n // 1. apply_patch uses patchText with embedded paths\n if (tool === \"apply_patch\" && typeof params.patchText === \"string\") {\n const pathRegex = /\\*\\*\\* (?:Add|Delete|Update) File: ([^\\n\\r]+)/g\n let match\n while ((match = pathRegex.exec(params.patchText)) !== null) {\n paths.push(match[1].trim())\n }\n }\n\n // 2. multiedit uses top-level filePath and nested edits array\n if (tool === \"multiedit\") {\n if (typeof params.filePath === \"string\") {\n paths.push(params.filePath)\n }\n if (Array.isArray(params.edits)) {\n for (const edit of params.edits) {\n if (edit && typeof edit.filePath === \"string\") {\n paths.push(edit.filePath)\n }\n }\n }\n }\n\n // 3. Default check for common filePath parameter (read, write, edit, etc)\n if (typeof params.filePath === \"string\") {\n paths.push(params.filePath)\n }\n\n // Return unique non-empty paths\n return [...new Set(paths)].filter((p) => p.length > 0)\n}\n\nexport function isFilePathProtected(filePaths: string[], patterns: string[]): boolean {\n if (!filePaths || filePaths.length === 0) return false\n if (!patterns || patterns.length === 0) return false\n\n return filePaths.some((path) => patterns.some((pattern) => matchesGlob(path, pattern)))\n}\n\nconst GLOB_CHARS = /[*?]/\n\nexport function isToolNameProtected(toolName: string, patterns: string[]): boolean {\n if (!toolName || !patterns || patterns.length === 0) return false\n\n const exactPatterns: Set<string> = new Set()\n const globPatterns: string[] = []\n\n for (const pattern of patterns) {\n if (GLOB_CHARS.test(pattern)) {\n globPatterns.push(pattern)\n } else {\n exactPatterns.add(pattern)\n }\n }\n\n if (exactPatterns.has(toolName)) {\n return true\n }\n\n return globPatterns.some((pattern) => matchesGlob(toolName, pattern))\n}\n","import { PluginConfig } from \"../config\"\nimport { Logger } from \"../logger\"\nimport type { SessionState, WithParts } from \"../state\"\nimport {\n getFilePathsFromParameters,\n isFilePathProtected,\n isToolNameProtected,\n} from \"../protected-patterns\"\nimport { getTotalToolTokens } from \"../token-utils\"\n\n/**\n * Deduplication strategy - prunes older tool calls that have identical\n * tool name and parameters, keeping only the most recent occurrence.\n * Modifies the session state in place to add pruned tool call IDs.\n */\nexport const deduplicate = (\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n messages: WithParts[],\n): void => {\n if (state.manualMode && !config.manualMode.automaticStrategies) {\n return\n }\n\n if (!config.strategies.deduplication.enabled) {\n return\n }\n\n const allToolIds = state.toolIdList\n if (allToolIds.length === 0) {\n return\n }\n\n // Filter out IDs already pruned\n const unprunedIds = allToolIds.filter((id) => !state.prune.tools.has(id))\n\n if (unprunedIds.length === 0) {\n return\n }\n\n const protectedTools = config.strategies.deduplication.protectedTools\n\n // Group by signature (tool name + normalized parameters)\n const signatureMap = new Map<string, string[]>()\n\n for (const id of unprunedIds) {\n const metadata = state.toolParameters.get(id)\n if (!metadata) {\n // logger.warn(`Missing metadata for tool call ID: ${id}`)\n continue\n }\n\n // Skip protected tools\n if (isToolNameProtected(metadata.tool, protectedTools)) {\n continue\n }\n\n const filePaths = getFilePathsFromParameters(metadata.tool, metadata.parameters)\n if (isFilePathProtected(filePaths, config.protectedFilePatterns)) {\n continue\n }\n\n const signature = createToolSignature(metadata.tool, metadata.parameters)\n if (!signatureMap.has(signature)) {\n signatureMap.set(signature, [])\n }\n const ids = signatureMap.get(signature)\n if (ids) {\n ids.push(id)\n }\n }\n\n // Find duplicates - keep only the most recent (last) in each group\n const newPruneIds: string[] = []\n\n for (const [, ids] of signatureMap.entries()) {\n if (ids.length > 1) {\n // All except last (most recent) should be pruned\n const idsToRemove = ids.slice(0, -1)\n newPruneIds.push(...idsToRemove)\n }\n }\n\n state.stats.totalPruneTokens += getTotalToolTokens(state, newPruneIds)\n\n if (newPruneIds.length > 0) {\n for (const id of newPruneIds) {\n const entry = state.toolParameters.get(id)\n state.prune.tools.set(id, entry?.tokenCount ?? 0)\n }\n logger.debug(`Marked ${newPruneIds.length} duplicate tool calls for pruning`)\n }\n}\n\nfunction createToolSignature(tool: string, parameters?: any): string {\n if (!parameters) {\n return tool\n }\n const normalized = normalizeParameters(parameters)\n const sorted = sortObjectKeys(normalized)\n return `${tool}::${JSON.stringify(sorted)}`\n}\n\nfunction normalizeParameters(params: any): any {\n if (typeof params !== \"object\" || params === null) return params\n if (Array.isArray(params)) return params\n\n const normalized: any = {}\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n normalized[key] = value\n }\n }\n return normalized\n}\n\nfunction sortObjectKeys(obj: any): any {\n if (typeof obj !== \"object\" || obj === null) return obj\n if (Array.isArray(obj)) return obj.map(sortObjectKeys)\n\n const sorted: any = {}\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = sortObjectKeys(obj[key])\n }\n return sorted\n}\n","import { PluginConfig } from \"../config\"\nimport { Logger } from \"../logger\"\nimport type { SessionState, WithParts } from \"../state\"\nimport {\n getFilePathsFromParameters,\n isFilePathProtected,\n isToolNameProtected,\n} from \"../protected-patterns\"\nimport { getTotalToolTokens } from \"../token-utils\"\n\n/**\n * Purge Errors strategy - prunes tool inputs for tools that errored\n * after they are older than a configurable number of turns.\n * The error message is preserved, but the (potentially large) inputs\n * are removed to save context.\n *\n * Modifies the session state in place to add pruned tool call IDs.\n */\nexport const purgeErrors = (\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n messages: WithParts[],\n): void => {\n if (state.manualMode && !config.manualMode.automaticStrategies) {\n return\n }\n\n if (!config.strategies.purgeErrors.enabled) {\n return\n }\n\n const allToolIds = state.toolIdList\n if (allToolIds.length === 0) {\n return\n }\n\n // Filter out IDs already pruned\n const unprunedIds = allToolIds.filter((id) => !state.prune.tools.has(id))\n\n if (unprunedIds.length === 0) {\n return\n }\n\n const protectedTools = config.strategies.purgeErrors.protectedTools\n const turnThreshold = Math.max(1, config.strategies.purgeErrors.turns)\n\n const newPruneIds: string[] = []\n\n for (const id of unprunedIds) {\n const metadata = state.toolParameters.get(id)\n if (!metadata) {\n continue\n }\n\n // Skip protected tools\n if (isToolNameProtected(metadata.tool, protectedTools)) {\n continue\n }\n\n const filePaths = getFilePathsFromParameters(metadata.tool, metadata.parameters)\n if (isFilePathProtected(filePaths, config.protectedFilePatterns)) {\n continue\n }\n\n // Only process error tools\n if (metadata.status !== \"error\") {\n continue\n }\n\n // Check if the tool is old enough to prune\n const turnAge = state.currentTurn - metadata.turn\n if (turnAge >= turnThreshold) {\n newPruneIds.push(id)\n }\n }\n\n if (newPruneIds.length > 0) {\n state.stats.totalPruneTokens += getTotalToolTokens(state, newPruneIds)\n for (const id of newPruneIds) {\n const entry = state.toolParameters.get(id)\n state.prune.tools.set(id, entry?.tokenCount ?? 0)\n }\n logger.debug(\n `Marked ${newPruneIds.length} error tool calls for pruning (older than ${turnThreshold} turns)`,\n )\n }\n}\n","import { SessionState, ToolParameterEntry, WithParts } from \"../state\"\nimport { countTokens } from \"../token-utils\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\n\nfunction extractParameterKey(tool: string, parameters: any): string {\n if (!parameters) return \"\"\n\n if (tool === \"read\" && parameters.filePath) {\n const offset = parameters.offset\n const limit = parameters.limit\n if (offset !== undefined && limit !== undefined) {\n return `${parameters.filePath} (lines ${offset}-${offset + limit})`\n }\n if (offset !== undefined) {\n return `${parameters.filePath} (lines ${offset}+)`\n }\n if (limit !== undefined) {\n return `${parameters.filePath} (lines 0-${limit})`\n }\n return parameters.filePath\n }\n\n if ((tool === \"write\" || tool === \"edit\" || tool === \"multiedit\") && parameters.filePath) {\n return parameters.filePath\n }\n\n if (tool === \"apply_patch\" && typeof parameters.patchText === \"string\") {\n const pathRegex = /\\*\\*\\* (?:Add|Delete|Update) File: ([^\\n\\r]+)/g\n const paths: string[] = []\n let match\n while ((match = pathRegex.exec(parameters.patchText)) !== null) {\n paths.push(match[1].trim())\n }\n if (paths.length > 0) {\n const uniquePaths = [...new Set(paths)]\n const count = uniquePaths.length\n const plural = count > 1 ? \"s\" : \"\"\n if (count === 1) return uniquePaths[0]\n if (count === 2) return uniquePaths.join(\", \")\n return `${count} file${plural}: ${uniquePaths[0]}, ${uniquePaths[1]}...`\n }\n return \"patch\"\n }\n\n if (tool === \"list\") {\n return parameters.path || \"(current directory)\"\n }\n\n if (tool === \"glob\") {\n if (parameters.pattern) {\n const pathInfo = parameters.path ? ` in ${parameters.path}` : \"\"\n return `\"${parameters.pattern}\"${pathInfo}`\n }\n return \"(unknown pattern)\"\n }\n\n if (tool === \"grep\") {\n if (parameters.pattern) {\n const pathInfo = parameters.path ? ` in ${parameters.path}` : \"\"\n return `\"${parameters.pattern}\"${pathInfo}`\n }\n return \"(unknown pattern)\"\n }\n\n if (tool === \"bash\") {\n if (parameters.description) return parameters.description\n if (parameters.command) {\n return parameters.command.length > 50\n ? parameters.command.substring(0, 50) + \"...\"\n : parameters.command\n }\n }\n\n if (tool === \"webfetch\" && parameters.url) {\n return parameters.url\n }\n if (tool === \"websearch\" && parameters.query) {\n return `\"${parameters.query}\"`\n }\n if (tool === \"codesearch\" && parameters.query) {\n return `\"${parameters.query}\"`\n }\n\n if (tool === \"todowrite\") {\n return `${parameters.todos?.length || 0} todos`\n }\n if (tool === \"todoread\") {\n return \"read todo list\"\n }\n\n if (tool === \"task\" && parameters.description) {\n return parameters.description\n }\n if (tool === \"skill\" && parameters.name) {\n return parameters.name\n }\n\n if (tool === \"lsp\") {\n const op = parameters.operation || \"lsp\"\n const path = parameters.filePath || \"\"\n const line = parameters.line\n const char = parameters.character\n if (path && line !== undefined && char !== undefined) {\n return `${op} ${path}:${line}:${char}`\n }\n if (path) {\n return `${op} ${path}`\n }\n return op\n }\n\n if (tool === \"question\") {\n const questions = parameters.questions\n if (Array.isArray(questions) && questions.length > 0) {\n const headers = questions\n .map((q: any) => q.header || \"\")\n .filter(Boolean)\n .slice(0, 3)\n\n const count = questions.length\n const plural = count > 1 ? \"s\" : \"\"\n\n if (headers.length > 0) {\n const suffix = count > 3 ? ` (+${count - 3} more)` : \"\"\n return `${count} question${plural}: ${headers.join(\", \")}${suffix}`\n }\n return `${count} question${plural}`\n }\n return \"question\"\n }\n\n const paramStr = JSON.stringify(parameters)\n if (paramStr === \"{}\" || paramStr === \"[]\" || paramStr === \"null\") {\n return \"\"\n }\n\n return paramStr.substring(0, 50)\n}\n\nexport function formatStatsHeader(totalTokensSaved: number, pruneTokenCounter: number): string {\n const totalTokensSavedStr = `~${formatTokenCount(totalTokensSaved + pruneTokenCounter)}`\n return [`▣ ACP | ${totalTokensSavedStr} saved total`].join(\"\\n\")\n}\n\nexport function formatTokenCount(tokens: number, compact?: boolean): string {\n const suffix = compact ? \"\" : \" tokens\"\n if (tokens >= 1000) {\n return `${(tokens / 1000).toFixed(1)}K`.replace(\".0K\", \"K\") + suffix\n }\n return tokens.toString() + suffix\n}\n\nfunction truncate(str: string, maxLen: number = 60): string {\n if (str.length <= maxLen) return str\n return str.slice(0, maxLen - 3) + \"...\"\n}\n\nexport function formatProgressBar(\n messageIds: string[],\n prunedMessages: Map<string, number>,\n recentMessageIds: string[],\n width: number = 50,\n): string {\n const ACTIVE = \"█\"\n const PRUNED = \"░\"\n const RECENT = \"⣿\"\n const recentSet = new Set(recentMessageIds)\n\n const total = messageIds.length\n if (total === 0) return `│${PRUNED.repeat(width)}│`\n\n const bar = new Array(width).fill(ACTIVE)\n\n for (let m = 0; m < total; m++) {\n const msgId = messageIds[m]\n const start = Math.floor((m / total) * width)\n const end = Math.floor(((m + 1) / total) * width)\n\n if (recentSet.has(msgId)) {\n for (let i = start; i < end; i++) {\n bar[i] = RECENT\n }\n } else if (prunedMessages.has(msgId)) {\n for (let i = start; i < end; i++) {\n bar[i] = PRUNED\n }\n }\n }\n\n return `│${bar.join(\"\")}│`\n}\n\nexport function cacheSystemPromptTokens(state: SessionState, messages: WithParts[]): void {\n let firstInputTokens = 0\n for (const msg of messages) {\n if (msg.info.role !== \"assistant\") {\n continue\n }\n const info = msg.info as any\n const input = info?.tokens?.input || 0\n const cacheRead = info?.tokens?.cache?.read || 0\n const cacheWrite = info?.tokens?.cache?.write || 0\n if (input > 0 || cacheRead > 0 || cacheWrite > 0) {\n firstInputTokens = input + cacheRead + cacheWrite\n break\n }\n }\n\n if (firstInputTokens <= 0) {\n state.systemPromptTokens = undefined\n return\n }\n\n let firstUserText = \"\"\n for (const msg of messages) {\n if (msg.info.role !== \"user\" || isIgnoredUserMessage(msg)) {\n continue\n }\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type === \"text\" && !(part as any).ignored) {\n firstUserText += part.text\n }\n }\n break\n }\n\n const estimatedSystemTokens = Math.max(0, firstInputTokens - countTokens(firstUserText))\n state.systemPromptTokens = estimatedSystemTokens > 0 ? estimatedSystemTokens : undefined\n}\n\nfunction shortenPath(input: string, workingDirectory?: string): string {\n const inPathMatch = input.match(/^(.+) in (.+)$/)\n if (inPathMatch) {\n const prefix = inPathMatch[1]\n const pathPart = inPathMatch[2]\n const shortenedPath = shortenSinglePath(pathPart, workingDirectory)\n return `${prefix} in ${shortenedPath}`\n }\n\n return shortenSinglePath(input, workingDirectory)\n}\n\nfunction shortenSinglePath(path: string, workingDirectory?: string): string {\n if (workingDirectory) {\n if (path.startsWith(workingDirectory + \"/\")) {\n return path.slice(workingDirectory.length + 1)\n }\n if (path === workingDirectory) {\n return \".\"\n }\n }\n\n return path\n}\n\nexport function formatPrunedItemsList(\n pruneToolIds: string[],\n toolMetadata: Map<string, ToolParameterEntry>,\n workingDirectory?: string,\n): string[] {\n const lines: string[] = []\n\n for (const id of pruneToolIds) {\n const metadata = toolMetadata.get(id)\n\n if (metadata) {\n const paramKey = extractParameterKey(metadata.tool, metadata.parameters)\n if (paramKey) {\n // Use 60 char limit to match notification style\n const displayKey = truncate(shortenPath(paramKey, workingDirectory), 60)\n lines.push(`→ ${metadata.tool}: ${displayKey}`)\n } else {\n lines.push(`→ ${metadata.tool}`)\n }\n }\n }\n\n const knownCount = pruneToolIds.filter((id) => toolMetadata.has(id)).length\n const unknownCount = pruneToolIds.length - knownCount\n\n if (unknownCount > 0) {\n lines.push(`→ (${unknownCount} tool${unknownCount > 1 ? \"s\" : \"\"} with unknown metadata)`)\n }\n\n return lines\n}\n\n\n","import type { Logger } from \"../logger\"\nimport type { SessionState } from \"../state\"\nimport {\n formatPrunedItemsList,\n formatProgressBar,\n formatStatsHeader,\n formatTokenCount,\n} from \"./utils\"\nimport { ToolParameterEntry } from \"../state\"\nimport { PluginConfig } from \"../config\"\nimport { getActiveSummaryTokenUsage } from \"../state/utils\"\n\nexport type PruneReason = \"completion\" | \"noise\" | \"extraction\"\nexport const PRUNE_REASON_LABELS: Record<PruneReason, string> = {\n completion: \"Task Complete\",\n noise: \"Noise Removal\",\n extraction: \"Extraction\",\n}\n\ninterface CompressionNotificationEntry {\n blockId: number\n runId: number\n summary: string\n summaryTokens: number\n}\n\nfunction buildMinimalMessage(state: SessionState, reason: PruneReason | undefined): string {\n const reasonSuffix = reason ? ` — ${PRUNE_REASON_LABELS[reason]}` : \"\"\n return (\n formatStatsHeader(state.stats.totalPruneTokens, state.stats.pruneTokenCounter) +\n reasonSuffix\n )\n}\n\nfunction buildDetailedMessage(\n state: SessionState,\n reason: PruneReason | undefined,\n pruneToolIds: string[],\n toolMetadata: Map<string, ToolParameterEntry>,\n workingDirectory: string,\n): string {\n let message = formatStatsHeader(state.stats.totalPruneTokens, state.stats.pruneTokenCounter)\n\n if (pruneToolIds.length > 0) {\n const pruneTokenCounterStr = `~${formatTokenCount(state.stats.pruneTokenCounter)}`\n const reasonLabel = reason ? ` — ${PRUNE_REASON_LABELS[reason]}` : \"\"\n message += `\\n\\n▣ Pruning (${pruneTokenCounterStr})${reasonLabel}`\n\n const itemLines = formatPrunedItemsList(pruneToolIds, toolMetadata, workingDirectory)\n message += \"\\n\" + itemLines.join(\"\\n\")\n }\n\n return message.trim()\n}\n\nconst TOAST_BODY_MAX_LINES = 12\nconst TOAST_SUMMARY_MAX_CHARS = 600\nconst NOTIFICATION_SUMMARY_MAX_CHARS = 1500\n\nfunction truncateToastBody(body: string, maxLines: number = TOAST_BODY_MAX_LINES): string {\n const lines = body.split(\"\\n\")\n if (lines.length <= maxLines) {\n return body\n }\n const kept = lines.slice(0, maxLines - 1)\n const remaining = lines.length - maxLines + 1\n return kept.join(\"\\n\") + `\\n... and ${remaining} more`\n}\n\nfunction truncateToastSummary(summary: string, maxChars: number = TOAST_SUMMARY_MAX_CHARS): string {\n if (summary.length <= maxChars) {\n return summary\n }\n return summary.slice(0, maxChars - 3) + \"...\"\n}\n\nfunction buildCompressionSummary(\n entries: CompressionNotificationEntry[],\n state: SessionState,\n): string {\n if (entries.length === 1) {\n return entries[0]?.summary ?? \"\"\n }\n\n let result = \"\"\n for (const entry of entries) {\n const topic =\n state.prune.messages.blocksById.get(entry.blockId)?.topic ?? \"(unknown topic)\"\n const section = `### ${topic}\\n${entry.summary}`\n if (result.length + section.length + 2 > NOTIFICATION_SUMMARY_MAX_CHARS) {\n result += `\\n\\n... and ${entries.length - entries.indexOf(entry)} more`\n break\n }\n result += (result ? \"\\n\\n\" : \"\") + section\n }\n return result\n}\n\nfunction getCompressionLabel(entries: CompressionNotificationEntry[]): string {\n const runId = entries[0]?.runId\n if (runId === undefined) {\n return \"Compression\"\n }\n\n return `Compression #${runId}`\n}\n\nfunction formatCompressionMetrics(removedTokens: number, summaryTokens: number): string {\n const metrics = [`-${formatTokenCount(removedTokens, true)} removed`]\n if (summaryTokens > 0) {\n metrics.push(`+${formatTokenCount(summaryTokens, true)} summary`)\n }\n return metrics.join(\", \")\n}\n\nexport async function sendCompressNotification(\n client: any,\n logger: Logger,\n config: PluginConfig,\n state: SessionState,\n sessionId: string,\n entries: CompressionNotificationEntry[],\n batchTopic: string | undefined,\n sessionMessageIds: string[],\n params: any,\n): Promise<boolean> {\n if (config.pruneNotification === \"off\") {\n return false\n }\n\n if (entries.length === 0) {\n return false\n }\n\n let message: string\n const compressionLabel = getCompressionLabel(entries)\n const summary = buildCompressionSummary(entries, state)\n const summaryTokens = entries.reduce((total, entry) => total + entry.summaryTokens, 0)\n const summaryTokensStr = formatTokenCount(summaryTokens)\n const compressedTokens = entries.reduce((total, entry) => {\n const compressionBlock = state.prune.messages.blocksById.get(entry.blockId)\n if (!compressionBlock) {\n logger.error(\"Compression block missing for notification\", {\n compressionId: entry.blockId,\n sessionId,\n })\n return total\n }\n\n return total + compressionBlock.compressedTokens\n }, 0)\n\n const newlyCompressedMessageIds: string[] = []\n const newlyCompressedToolIds: string[] = []\n const seenMessageIds = new Set<string>()\n const seenToolIds = new Set<string>()\n\n for (const entry of entries) {\n const compressionBlock = state.prune.messages.blocksById.get(entry.blockId)\n if (!compressionBlock) {\n continue\n }\n\n for (const messageId of compressionBlock.directMessageIds) {\n if (seenMessageIds.has(messageId)) {\n continue\n }\n seenMessageIds.add(messageId)\n newlyCompressedMessageIds.push(messageId)\n }\n\n for (const toolId of compressionBlock.directToolIds) {\n if (seenToolIds.has(toolId)) {\n continue\n }\n seenToolIds.add(toolId)\n newlyCompressedToolIds.push(toolId)\n }\n }\n\n const topic =\n batchTopic ??\n (entries.length === 1\n ? (state.prune.messages.blocksById.get(entries[0]?.blockId ?? -1)?.topic ??\n \"(unknown topic)\")\n : \"(unknown topic)\")\n\n const totalActiveSummaryTkns = getActiveSummaryTokenUsage(state)\n const totalGross = state.stats.totalPruneTokens + state.stats.pruneTokenCounter\n const notificationHeader = `▣ ACP | ${formatCompressionMetrics(totalGross, totalActiveSummaryTkns)}`\n\n if (config.pruneNotification === \"minimal\") {\n message = `${notificationHeader} — ${compressionLabel}`\n } else {\n message = notificationHeader\n\n const activePrunedMessages = new Map<string, number>()\n for (const [messageId, entry] of state.prune.messages.byMessageId) {\n if (entry.activeBlockIds.length > 0) {\n activePrunedMessages.set(messageId, entry.tokenCount)\n }\n }\n const progressBar = formatProgressBar(\n sessionMessageIds,\n activePrunedMessages,\n newlyCompressedMessageIds,\n 50,\n )\n message += `\\n\\n${progressBar}`\n message += `\\n▣ ${compressionLabel} ${formatCompressionMetrics(compressedTokens, summaryTokens)}`\n message += `\\n→ Topic: ${topic}`\n message += `\\n→ Items: ${newlyCompressedMessageIds.length} messages`\n if (newlyCompressedToolIds.length > 0) {\n message += ` and ${newlyCompressedToolIds.length} tools compressed`\n } else {\n message += ` compressed`\n }\n if (config.compress.showCompression) {\n const displaySummary =\n summary.length > NOTIFICATION_SUMMARY_MAX_CHARS\n ? truncateToastSummary(summary, NOTIFICATION_SUMMARY_MAX_CHARS)\n : summary\n message += `\\n→ Compression (~${summaryTokensStr}): ${displaySummary}`\n }\n }\n\n if (config.pruneNotificationType === \"toast\") {\n let toastMessage = message\n if (config.compress.showCompression) {\n const truncatedSummary = truncateToastSummary(summary)\n if (truncatedSummary !== summary) {\n toastMessage = toastMessage.replace(\n `\\n→ Compression (~${summaryTokensStr}): ${truncateToastSummary(summary, NOTIFICATION_SUMMARY_MAX_CHARS)}`,\n `\\n→ Compression (~${summaryTokensStr}): ${truncatedSummary}`,\n )\n }\n }\n toastMessage =\n config.pruneNotification === \"minimal\" ? toastMessage : truncateToastBody(toastMessage)\n\n await client.tui.showToast({\n body: {\n title: \"ACP: Compress Notification\",\n message: toastMessage,\n variant: \"info\",\n duration: 5000,\n },\n })\n return true\n }\n\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n return true\n}\n\nexport async function sendIgnoredMessage(\n client: any,\n sessionID: string,\n text: string,\n params: any,\n logger: Logger,\n): Promise<void> {\n const agent = params.agent || undefined\n const variant = params.variant || undefined\n const model =\n params.providerId && params.modelId\n ? {\n providerID: params.providerId,\n modelID: params.modelId,\n }\n : undefined\n\n try {\n await client.session.prompt({\n path: {\n id: sessionID,\n },\n body: {\n noReply: true,\n agent: agent,\n model: model,\n variant: variant,\n parts: [\n {\n type: \"text\",\n text: text,\n ignored: true,\n },\n ],\n },\n })\n } catch (error: any) {\n logger.error(\"Failed to send notification\", { error: error.message })\n }\n}\n","import type { WithParts } from \"../state\"\nimport { ensureSessionInitialized } from \"../state\"\nimport { saveSessionState } from \"../state/persistence\"\nimport { assignMessageRefs } from \"../message-ids\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\nimport { deduplicate, purgeErrors } from \"../strategies\"\nimport { getCurrentParams, getCurrentTokenUsage } from \"../token-utils\"\nimport { sendCompressNotification } from \"../ui/notification\"\nimport type { ToolContext } from \"./types\"\nimport { buildSearchContext, fetchSessionMessages } from \"./search\"\nimport type { SearchContext } from \"./types\"\nimport { applyPendingCompressionDurations } from \"./timing\"\n\ninterface RunContext {\n ask(input: {\n permission: string\n patterns: string[]\n always: string[]\n metadata: Record<string, unknown>\n }): Promise<void>\n metadata(input: { title: string }): void\n sessionID: string\n}\n\nexport interface NotificationEntry {\n blockId: number\n runId: number\n summary: string\n summaryTokens: number\n}\n\nexport interface PreparedSession {\n rawMessages: WithParts[]\n searchContext: SearchContext\n}\n\nexport async function prepareSession(\n ctx: ToolContext,\n toolCtx: RunContext,\n title: string,\n): Promise<PreparedSession> {\n if (ctx.state.manualMode && ctx.state.manualMode !== \"compress-pending\") {\n throw new Error(\n \"Manual mode: compress blocked. Do not retry until `<compress triggered manually>` appears in user context.\",\n )\n }\n\n await toolCtx.ask({\n permission: \"compress\",\n patterns: [\"*\"],\n always: [\"*\"],\n metadata: {},\n })\n\n toolCtx.metadata({ title })\n\n const rawMessages = await fetchSessionMessages(ctx.client, toolCtx.sessionID)\n\n await ensureSessionInitialized(\n ctx.client,\n ctx.state,\n toolCtx.sessionID,\n ctx.logger,\n rawMessages,\n ctx.config.manualMode.enabled,\n )\n\n assignMessageRefs(ctx.state, rawMessages)\n\n deduplicate(ctx.state, ctx.logger, ctx.config, rawMessages)\n purgeErrors(ctx.state, ctx.logger, ctx.config, rawMessages)\n\n return {\n rawMessages,\n searchContext: buildSearchContext(ctx.state, rawMessages),\n }\n}\n\nexport async function finalizeSession(\n ctx: ToolContext,\n toolCtx: RunContext,\n rawMessages: WithParts[],\n entries: NotificationEntry[],\n batchTopic: string | undefined,\n): Promise<void> {\n ctx.state.manualMode = ctx.state.manualMode ? \"active\" : false\n applyPendingCompressionDurations(ctx.state)\n await saveSessionState(ctx.state, ctx.logger)\n\n const params = getCurrentParams(ctx.state, rawMessages, ctx.logger)\n const sessionMessageIds = rawMessages\n .filter((msg) => !isIgnoredUserMessage(msg))\n .map((msg) => msg.info.id)\n\n await sendCompressNotification(\n ctx.client,\n ctx.logger,\n ctx.config,\n ctx.state,\n toolCtx.sessionID,\n entries,\n batchTopic,\n sessionMessageIds,\n params,\n )\n}\n","import type { WithParts } from \"../state\"\n\nconst SUB_AGENT_RESULT_BLOCK_REGEX = /(<task_result>\\s*)([\\s\\S]*?)(\\s*<\\/task_result>)/i\n\nexport function getSubAgentId(part: any): string | null {\n const sessionId = part?.state?.metadata?.sessionId\n if (typeof sessionId !== \"string\") {\n return null\n }\n\n const value = sessionId.trim()\n return value.length > 0 ? value : null\n}\n\nexport function buildSubagentResultText(messages: WithParts[]): string {\n const assistantMessages = messages.filter((message) => message.info.role === \"assistant\")\n if (assistantMessages.length === 0) {\n return \"\"\n }\n\n const lastAssistant = assistantMessages[assistantMessages.length - 1]\n const lastText = getLastTextPart(lastAssistant)\n\n if (assistantMessages.length < 2) {\n return lastText\n }\n\n const secondToLastAssistant = assistantMessages[assistantMessages.length - 2]\n if (!assistantMessageHasCompressTool(secondToLastAssistant)) {\n return lastText\n }\n\n const secondToLastText = getLastTextPart(secondToLastAssistant)\n return [secondToLastText, lastText].filter((text) => text.length > 0).join(\"\\n\\n\")\n}\n\nexport function mergeSubagentResult(output: string, subAgentResultText: string): string {\n if (!subAgentResultText || typeof output !== \"string\") {\n return output\n }\n\n return output.replace(\n SUB_AGENT_RESULT_BLOCK_REGEX,\n (_match, openTag: string, _body: string, closeTag: string) =>\n `${openTag}${subAgentResultText}${closeTag}`,\n )\n}\n\nfunction getLastTextPart(message: WithParts): string {\n const parts = Array.isArray(message.parts) ? message.parts : []\n for (let index = parts.length - 1; index >= 0; index--) {\n const part = parts[index]\n if (part.type !== \"text\" || typeof part.text !== \"string\") {\n continue\n }\n\n const text = part.text.trim()\n if (!text) {\n continue\n }\n\n return text\n }\n\n return \"\"\n}\n\nfunction assistantMessageHasCompressTool(message: WithParts): boolean {\n const parts = Array.isArray(message.parts) ? message.parts : []\n return parts.some(\n (part) =>\n part.type === \"tool\" && part.tool === \"compress\" && part.state?.status === \"completed\",\n )\n}\n","import type { SessionState } from \"../state\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\nimport {\n getFilePathsFromParameters,\n isFilePathProtected,\n isToolNameProtected,\n} from \"../protected-patterns\"\nimport {\n buildSubagentResultText,\n getSubAgentId,\n mergeSubagentResult,\n} from \"../subagents/subagent-results\"\nimport { fetchSessionMessages } from \"./search\"\nimport type { SearchContext, SelectionResolution } from \"./types\"\n\nexport function appendProtectedUserMessages(\n summary: string,\n selection: SelectionResolution,\n searchContext: SearchContext,\n state: SessionState,\n enabled: boolean,\n): string {\n if (!enabled) return summary\n\n const userTexts: string[] = []\n\n for (const messageId of selection.messageIds) {\n const existingCompressionEntry = state.prune.messages.byMessageId.get(messageId)\n if (existingCompressionEntry && existingCompressionEntry.activeBlockIds.length > 0) {\n continue\n }\n\n const message = searchContext.rawMessagesById.get(messageId)\n if (!message) continue\n if (message.info.role !== \"user\") continue\n if (isIgnoredUserMessage(message)) continue\n\n const parts = Array.isArray(message.parts) ? message.parts : []\n for (const part of parts) {\n if (part.type === \"text\" && typeof part.text === \"string\" && part.text.trim()) {\n userTexts.push(part.text)\n break\n }\n }\n }\n\n if (userTexts.length === 0) {\n return summary\n }\n\n const heading = \"\\n\\nThe following user messages were sent in this conversation verbatim:\"\n const body = userTexts.map((text) => `\\n${text}`).join(\"\")\n return summary + heading + body\n}\n\nexport function appendProtectedPromptInfo(\n summary: string,\n selection: SelectionResolution,\n searchContext: SearchContext,\n state: SessionState,\n enabled: boolean,\n): string {\n if (!enabled) return summary\n\n const protectedTexts: string[] = []\n\n for (const messageId of selection.messageIds) {\n const existingCompressionEntry = state.prune.messages.byMessageId.get(messageId)\n if (existingCompressionEntry && existingCompressionEntry.activeBlockIds.length > 0) {\n continue\n }\n\n const message = searchContext.rawMessagesById.get(messageId)\n if (!message) continue\n if (message.info.role !== \"user\") continue\n if (isIgnoredUserMessage(message)) continue\n\n const parts = Array.isArray(message.parts) ? message.parts : []\n for (const part of parts) {\n if (part.type !== \"text\" || typeof part.text !== \"string\") continue\n\n protectedTexts.push(...extractProtectedPromptInfo(part.text))\n }\n }\n\n if (protectedTexts.length === 0) {\n return summary\n }\n\n const heading =\n \"\\n\\nThe following protected prompt information was included in this conversation verbatim:\"\n const body = protectedTexts.map((text) => `\\n${text}`).join(\"\")\n return summary + heading + body\n}\n\nexport function extractProtectedPromptInfo(text: string): string[] {\n const protectedTexts: string[] = []\n const protectTagRegex = /<protect>([\\s\\S]*?)<\\/protect>/gi\n\n for (const match of text.matchAll(protectTagRegex)) {\n const protectedText = match[1]?.trim()\n if (protectedText) {\n protectedTexts.push(protectedText)\n }\n }\n\n return protectedTexts\n}\n\nexport async function appendProtectedTools(\n client: any,\n state: SessionState,\n allowSubAgents: boolean,\n summary: string,\n selection: SelectionResolution,\n searchContext: SearchContext,\n protectedTools: string[],\n protectedFilePatterns: string[] = [],\n): Promise<string> {\n const protectedOutputs: string[] = []\n\n for (const messageId of selection.messageIds) {\n const existingCompressionEntry = state.prune.messages.byMessageId.get(messageId)\n if (existingCompressionEntry && existingCompressionEntry.activeBlockIds.length > 0) {\n continue\n }\n\n const message = searchContext.rawMessagesById.get(messageId)\n if (!message) continue\n\n const parts = Array.isArray(message.parts) ? message.parts : []\n for (const part of parts) {\n if (part.type === \"tool\" && part.callID) {\n let isToolProtected = isToolNameProtected(part.tool, protectedTools)\n\n if (!isToolProtected && protectedFilePatterns.length > 0) {\n const filePaths = getFilePathsFromParameters(part.tool, part.state?.input)\n if (isFilePathProtected(filePaths, protectedFilePatterns)) {\n isToolProtected = true\n }\n }\n\n if (isToolProtected) {\n const title = `Tool: ${part.tool}`\n let output = \"\"\n\n if (part.state?.status === \"completed\" && part.state?.output) {\n output =\n typeof part.state.output === \"string\"\n ? part.state.output\n : JSON.stringify(part.state.output)\n }\n\n if (\n allowSubAgents &&\n part.tool === \"task\" &&\n part.state?.status === \"completed\" &&\n typeof part.state?.output === \"string\"\n ) {\n const cachedSubAgentResult = state.subAgentResultCache.get(part.callID)\n\n if (cachedSubAgentResult !== undefined) {\n if (cachedSubAgentResult) {\n output = mergeSubagentResult(\n part.state.output,\n cachedSubAgentResult,\n )\n }\n } else {\n const subAgentSessionId = getSubAgentId(part)\n if (subAgentSessionId) {\n let subAgentResultText = \"\"\n try {\n const subAgentMessages = await fetchSessionMessages(\n client,\n subAgentSessionId,\n )\n subAgentResultText = buildSubagentResultText(subAgentMessages)\n } catch {\n subAgentResultText = \"\"\n }\n\n if (subAgentResultText) {\n state.subAgentResultCache.set(part.callID, subAgentResultText)\n output = mergeSubagentResult(\n part.state.output,\n subAgentResultText,\n )\n }\n }\n }\n }\n\n if (output) {\n protectedOutputs.push(`\\n### ${title}\\n${output}`)\n }\n }\n }\n }\n }\n\n if (protectedOutputs.length === 0) {\n return summary\n }\n\n const heading = \"\\n\\nThe following protected tools were used in this conversation as well:\"\n return summary + heading + protectedOutputs.join(\"\")\n}\n","import { tool } from \"@opencode-ai/plugin\"\nimport type { ToolContext } from \"./types\"\nimport { countTokens } from \"../token-utils\"\nimport { RANGE_FORMAT_EXTENSION } from \"../prompts/extensions/tool\"\nimport { finalizeSession, prepareSession, type NotificationEntry } from \"./pipeline\"\nimport {\n appendProtectedPromptInfo,\n appendProtectedTools,\n appendProtectedUserMessages,\n} from \"./protected-content\"\nimport {\n appendMissingBlockSummaries,\n injectBlockPlaceholders,\n parseBlockPlaceholders,\n resolveRanges,\n validateArgs,\n validateNonOverlapping,\n validateSummaryPlaceholders,\n} from \"./range-utils\"\nimport {\n COMPRESSED_BLOCK_HEADER,\n allocateBlockId,\n allocateRunId,\n applyCompressionState,\n wrapCompressedSummary,\n} from \"./state\"\nimport type { CompressRangeToolArgs } from \"./types\"\n\nfunction buildSchema() {\n return {\n topic: tool.schema\n .string()\n .describe(\"Short label (3-5 words) for display - e.g., 'Auth System Exploration'\"),\n content: tool.schema\n .array(\n tool.schema.object({\n startId: tool.schema\n .string()\n .describe(\n \"Message or block ID marking the beginning of range (e.g. m00001, b2)\",\n ),\n endId: tool.schema\n .string()\n .describe(\"Message or block ID marking the end of range (e.g. m00012, b5)\"),\n summary: tool.schema\n .string()\n .describe(\"Complete technical summary replacing all content in range\"),\n }),\n )\n .describe(\n \"One or more ranges to compress, each with start/end boundaries and a summary\",\n ),\n }\n}\n\nexport function createCompressRangeTool(ctx: ToolContext): ReturnType<typeof tool> {\n ctx.prompts.reload()\n const runtimePrompts = ctx.prompts.getRuntimePrompts()\n\n return tool({\n description: runtimePrompts.compressRange + RANGE_FORMAT_EXTENSION,\n args: buildSchema(),\n async execute(args, toolCtx) {\n const input = args as CompressRangeToolArgs\n validateArgs(input)\n const callId =\n typeof (toolCtx as unknown as { callID?: unknown }).callID === \"string\"\n ? (toolCtx as unknown as { callID: string }).callID\n : undefined\n\n const { rawMessages, searchContext } = await prepareSession(\n ctx,\n toolCtx,\n `Compress Range: ${input.topic}`,\n )\n const resolvedPlans = resolveRanges(input, searchContext, ctx.state)\n validateNonOverlapping(resolvedPlans)\n\n const notifications: NotificationEntry[] = []\n const preparedPlans: Array<{\n entry: (typeof resolvedPlans)[number][\"entry\"]\n selection: (typeof resolvedPlans)[number][\"selection\"]\n anchorMessageId: string\n finalSummary: string\n consumedBlockIds: number[]\n }> = []\n let totalCompressedMessages = 0\n\n for (const plan of resolvedPlans) {\n const parsedPlaceholders = parseBlockPlaceholders(plan.entry.summary)\n validateSummaryPlaceholders(\n parsedPlaceholders,\n plan.selection.requiredBlockIds,\n plan.selection.startReference,\n plan.selection.endReference,\n searchContext.summaryByBlockId,\n )\n\n const injected = injectBlockPlaceholders(\n plan.entry.summary,\n parsedPlaceholders,\n searchContext.summaryByBlockId,\n plan.selection.startReference,\n plan.selection.endReference,\n )\n\n const summaryWithUsers = appendProtectedUserMessages(\n injected.expandedSummary,\n plan.selection,\n searchContext,\n ctx.state,\n ctx.config.compress.protectUserMessages,\n )\n\n const summaryWithPromptInfo = appendProtectedPromptInfo(\n summaryWithUsers,\n plan.selection,\n searchContext,\n ctx.state,\n ctx.config.compress.protectTags,\n )\n\n const summaryWithTools = await appendProtectedTools(\n ctx.client,\n ctx.state,\n ctx.config.experimental.allowSubAgents,\n summaryWithPromptInfo,\n plan.selection,\n searchContext,\n ctx.config.compress.protectedTools,\n ctx.config.protectedFilePatterns,\n )\n\n const completedSummary = appendMissingBlockSummaries(\n summaryWithTools,\n [],\n searchContext.summaryByBlockId,\n injected.consumedBlockIds,\n )\n\n const mergeConsumedBlockIds = extractBoundaryConsumedBlocks(\n plan.selection.startReference,\n plan.selection.endReference,\n )\n\n preparedPlans.push({\n entry: plan.entry,\n selection: plan.selection,\n anchorMessageId: plan.anchorMessageId,\n finalSummary: completedSummary.expandedSummary,\n consumedBlockIds: mergeConsumedBlockIds,\n })\n }\n\n const runId = allocateRunId(ctx.state)\n\n for (const preparedPlan of preparedPlans) {\n const blockId = allocateBlockId(ctx.state)\n const storedSummary = wrapCompressedSummary(blockId, preparedPlan.finalSummary)\n const summaryTokens = countTokens(storedSummary)\n\n const applied = applyCompressionState(\n ctx.state,\n {\n topic: input.topic,\n batchTopic: input.topic,\n startId: preparedPlan.entry.startId,\n endId: preparedPlan.entry.endId,\n mode: \"range\",\n runId,\n compressMessageId: toolCtx.messageID,\n compressCallId: callId,\n summaryTokens,\n },\n preparedPlan.selection,\n preparedPlan.anchorMessageId,\n blockId,\n storedSummary,\n preparedPlan.consumedBlockIds,\n ctx.config.gc,\n )\n\n totalCompressedMessages += applied.messageIds.length\n\n notifications.push({\n blockId,\n runId,\n summary: preparedPlan.finalSummary,\n summaryTokens,\n })\n }\n\n await finalizeSession(ctx, toolCtx, rawMessages, notifications, input.topic)\n\n return `Compressed ${totalCompressedMessages} messages into ${COMPRESSED_BLOCK_HEADER}.\\nIMPORTANT: This was an automatic context compression. You MUST continue your previous task exactly where you left off. Do NOT ask the user what to do next.`\n },\n })\n}\n\nfunction extractBoundaryConsumedBlocks(\n startReference: { kind: string; blockId?: number },\n endReference: { kind: string; blockId?: number },\n): number[] {\n const consumed: number[] = []\n const seen = new Set<number>()\n for (const ref of [startReference, endReference]) {\n if (ref.kind === \"compressed-block\" && ref.blockId !== undefined && !seen.has(ref.blockId)) {\n seen.add(ref.blockId)\n consumed.push(ref.blockId)\n }\n }\n return consumed\n}\n","import type { CompressionBlock, SessionState } from \"../state\"\nimport { resolveAnchorMessageId, resolveBoundaryIds, resolveSelection } from \"./search\"\nimport type {\n BoundaryReference,\n CompressRangeToolArgs,\n InjectedSummaryResult,\n ParsedBlockPlaceholder,\n ResolvedRangeCompression,\n SearchContext,\n} from \"./types\"\n\nconst BLOCK_PLACEHOLDER_REGEX = /\\(b(\\d+)\\)|\\{block_(\\d+)\\}/gi\n\nexport function validateArgs(args: CompressRangeToolArgs): void {\n if (typeof args.topic !== \"string\" || args.topic.trim().length === 0) {\n throw new Error(\"topic is required and must be a non-empty string\")\n }\n\n if (!Array.isArray(args.content) || args.content.length === 0) {\n throw new Error(\"content is required and must be a non-empty array\")\n }\n\n for (let index = 0; index < args.content.length; index++) {\n const entry = args.content[index]\n const prefix = `content[${index}]`\n\n if (typeof entry?.startId !== \"string\" || entry.startId.trim().length === 0) {\n throw new Error(`${prefix}.startId is required and must be a non-empty string`)\n }\n\n if (typeof entry?.endId !== \"string\" || entry.endId.trim().length === 0) {\n throw new Error(`${prefix}.endId is required and must be a non-empty string`)\n }\n\n if (typeof entry?.summary !== \"string\" || entry.summary.trim().length === 0) {\n throw new Error(`${prefix}.summary is required and must be a non-empty string`)\n }\n }\n}\n\nexport function resolveRanges(\n args: CompressRangeToolArgs,\n searchContext: SearchContext,\n state: SessionState,\n): ResolvedRangeCompression[] {\n return args.content.map((entry, index) => {\n const normalizedEntry = {\n startId: entry.startId.trim(),\n endId: entry.endId.trim(),\n summary: entry.summary,\n }\n\n const { startReference, endReference } = resolveBoundaryIds(\n searchContext,\n state,\n normalizedEntry.startId,\n normalizedEntry.endId,\n )\n const selection = resolveSelection(searchContext, startReference, endReference)\n\n return {\n index,\n entry: normalizedEntry,\n selection,\n anchorMessageId: resolveAnchorMessageId(startReference),\n }\n })\n}\n\nexport function validateNonOverlapping(plans: ResolvedRangeCompression[]): void {\n const sortedPlans = [...plans].sort(\n (left, right) =>\n left.selection.startReference.rawIndex - right.selection.startReference.rawIndex ||\n left.selection.endReference.rawIndex - right.selection.endReference.rawIndex ||\n left.index - right.index,\n )\n\n const issues: string[] = []\n\n for (let index = 1; index < sortedPlans.length; index++) {\n const previous = sortedPlans[index - 1]\n const current = sortedPlans[index]\n if (!previous || !current) {\n continue\n }\n\n if (current.selection.startReference.rawIndex > previous.selection.endReference.rawIndex) {\n continue\n }\n\n issues.push(\n `content[${previous.index}] (${previous.entry.startId}..${previous.entry.endId}) overlaps content[${current.index}] (${current.entry.startId}..${current.entry.endId}). Overlapping ranges cannot be compressed in the same batch.`,\n )\n }\n\n if (issues.length > 0) {\n throw new Error(\n issues.length === 1 ? issues[0] : issues.map((issue) => `- ${issue}`).join(\"\\n\"),\n )\n }\n}\n\nexport function parseBlockPlaceholders(summary: string): ParsedBlockPlaceholder[] {\n const placeholders: ParsedBlockPlaceholder[] = []\n const regex = new RegExp(BLOCK_PLACEHOLDER_REGEX)\n\n let match: RegExpExecArray | null\n while ((match = regex.exec(summary)) !== null) {\n const full = match[0]\n const blockIdPart = match[1] || match[2]\n const parsed = Number.parseInt(blockIdPart, 10)\n if (!Number.isInteger(parsed)) {\n continue\n }\n\n placeholders.push({\n raw: full,\n blockId: parsed,\n startIndex: match.index,\n endIndex: match.index + full.length,\n })\n }\n\n return placeholders\n}\n\nexport function validateSummaryPlaceholders(\n placeholders: ParsedBlockPlaceholder[],\n requiredBlockIds: number[],\n startReference: BoundaryReference,\n endReference: BoundaryReference,\n summaryByBlockId: Map<number, CompressionBlock>,\n): number[] {\n const boundaryOptionalIds = new Set<number>()\n if (startReference.kind === \"compressed-block\") {\n if (startReference.blockId === undefined) {\n throw new Error(\"Failed to map boundary matches back to raw messages\")\n }\n boundaryOptionalIds.add(startReference.blockId)\n }\n if (endReference.kind === \"compressed-block\") {\n if (endReference.blockId === undefined) {\n throw new Error(\"Failed to map boundary matches back to raw messages\")\n }\n boundaryOptionalIds.add(endReference.blockId)\n }\n\n const strictRequiredIds = requiredBlockIds.filter((id) => !boundaryOptionalIds.has(id))\n const requiredSet = new Set(requiredBlockIds)\n const keptPlaceholderIds = new Set<number>()\n const validPlaceholders: ParsedBlockPlaceholder[] = []\n\n for (const placeholder of placeholders) {\n const isKnown = summaryByBlockId.has(placeholder.blockId)\n const isRequired = requiredSet.has(placeholder.blockId)\n const isDuplicate = keptPlaceholderIds.has(placeholder.blockId)\n\n if (isKnown && isRequired && !isDuplicate) {\n validPlaceholders.push(placeholder)\n keptPlaceholderIds.add(placeholder.blockId)\n }\n }\n\n placeholders.length = 0\n placeholders.push(...validPlaceholders)\n\n return strictRequiredIds.filter((id) => !keptPlaceholderIds.has(id))\n}\n\nexport function injectBlockPlaceholders(\n summary: string,\n _placeholders: ParsedBlockPlaceholder[],\n _summaryByBlockId: Map<number, CompressionBlock>,\n _startReference: BoundaryReference,\n _endReference: BoundaryReference,\n): InjectedSummaryResult {\n return {\n expandedSummary: summary,\n consumedBlockIds: [],\n }\n}\n\nexport function appendMissingBlockSummaries(\n summary: string,\n _missingBlockIds: number[],\n _summaryByBlockId: Map<number, CompressionBlock>,\n consumedBlockIds: number[],\n): InjectedSummaryResult {\n return {\n expandedSummary: summary,\n consumedBlockIds: [...consumedBlockIds],\n }\n}\n\n","import { tool } from \"@opencode-ai/plugin\"\nimport type { ToolContext } from \"./types\"\nimport { ensureSessionInitialized } from \"../state\"\nimport { saveSessionState } from \"../state/persistence\"\nimport { assignMessageRefs } from \"../message-ids\"\nimport { syncCompressionBlocks } from \"../messages\"\nimport { getCurrentTokenUsage } from \"../token-utils\"\nimport { fetchSessionMessages } from \"./search\"\nimport { resolveCompressionTarget } from \"../commands/compression-targets\"\nimport {\n parseBlockIdArg,\n findActiveAncestorBlockId,\n snapshotActiveMessages,\n deactivateCompressionTarget,\n computeRestoredMessages,\n computeReactivatedBlockIds,\n buildRestoredContentPreview,\n} from \"./decompress-logic\"\nimport { formatTokenCount } from \"../ui/utils\"\n\ninterface RunContext {\n ask(input: {\n permission: string\n patterns: string[]\n always: string[]\n metadata: Record<string, unknown>\n }): Promise<void>\n metadata(input: { title: string }): void\n sessionID: string\n}\n\nasync function prepareDecompressSession(\n ctx: ToolContext,\n toolCtx: RunContext,\n): Promise<{ rawMessages: import(\"../state\").WithParts[] }> {\n await toolCtx.ask({\n permission: \"compress\",\n patterns: [\"*\"],\n always: [\"*\"],\n metadata: {},\n })\n\n toolCtx.metadata({ title: \"Decompress\" })\n\n const rawMessages = await fetchSessionMessages(ctx.client, toolCtx.sessionID)\n\n await ensureSessionInitialized(\n ctx.client,\n ctx.state,\n toolCtx.sessionID,\n ctx.logger,\n rawMessages,\n ctx.config.manualMode.enabled,\n )\n\n assignMessageRefs(ctx.state, rawMessages)\n\n return { rawMessages }\n}\n\nasync function finalizeDecompressSession(\n ctx: ToolContext,\n): Promise<void> {\n await saveSessionState(ctx.state, ctx.logger)\n}\n\nconst TOOL_DESCRIPTION = `Restores previously compressed content identified by a block ID.\n\nUse this tool when you need exact details from a compressed block that the summary cannot provide.\nThe tool returns a condensed preview of the restored content so you can reason about it immediately.\n\nArgument: blockId — the block reference to decompress (e.g., \"b0\", \"b2\")\n\nIMPORTANT:\n- Decompressing inflates context. Check context usage before decompressing.\n- Message-mode blocks from the same batch (same runId) are restored together.\n- After decompression, the restored messages will appear in full in your next context window.\n- Do NOT call this tool in parallel with compress — their state mutations may conflict.`\n\nfunction buildSchema() {\n return {\n blockId: tool.schema\n .string()\n .describe('Block reference to decompress (e.g., \"b0\", \"b2\")'),\n }\n}\n\nexport function createDecompressTool(ctx: ToolContext): ReturnType<typeof tool> {\n return tool({\n description: TOOL_DESCRIPTION,\n args: buildSchema(),\n async execute(args, toolCtx) {\n const { rawMessages } = await prepareDecompressSession(ctx, toolCtx)\n\n const contextUsageBefore = ctx.state.modelContextLimit\n ? Math.round(\n (getCurrentTokenUsage(ctx.state, rawMessages) /\n ctx.state.modelContextLimit) *\n 100,\n )\n : undefined\n\n const targetBlockId = parseBlockIdArg(args.blockId as string)\n if (targetBlockId === null) {\n return `Error: Invalid block ID \"${args.blockId}\". Use format \"b0\", \"b1\", etc.`\n }\n\n const messagesState = ctx.state.prune.messages\n\n const target = resolveCompressionTarget(messagesState, targetBlockId)\n if (!target) {\n return `Error: Block ${targetBlockId} does not exist. No compression found with that ID.`\n }\n\n const activeBlocks = target.blocks.filter((block) => block.active)\n if (activeBlocks.length === 0) {\n const activeAncestorBlockId = findActiveAncestorBlockId(messagesState, target)\n if (activeAncestorBlockId !== null) {\n return `Error: Block ${target.displayId} is nested inside active block ${activeAncestorBlockId}. Decompress block ${activeAncestorBlockId} first.`\n }\n return `Error: Block ${target.displayId} is not active. It may have already been decompressed.`\n }\n\n const activeMessagesBefore = snapshotActiveMessages(messagesState)\n const activeBlockIdsBefore = new Set(messagesState.activeBlockIds)\n\n deactivateCompressionTarget(messagesState, target)\n\n syncCompressionBlocks(ctx.state, ctx.logger, rawMessages)\n\n const { restoredMessageCount, restoredTokens } = computeRestoredMessages(\n messagesState,\n activeMessagesBefore,\n )\n const reactivatedBlockIds = computeReactivatedBlockIds(\n messagesState,\n activeBlockIdsBefore,\n )\n\n ctx.state.stats.totalPruneTokens = Math.max(\n 0,\n ctx.state.stats.totalPruneTokens - restoredTokens,\n )\n\n const contextUsageAfter = ctx.state.modelContextLimit\n ? Math.round(\n (getCurrentTokenUsage(ctx.state, rawMessages) /\n ctx.state.modelContextLimit) *\n 100,\n )\n : undefined\n\n await finalizeDecompressSession(ctx)\n\n const restoredContentPreview = buildRestoredContentPreview(\n rawMessages,\n activeMessagesBefore,\n messagesState,\n )\n\n const lines: string[] = []\n lines.push(\n `Decompressed block b${target.displayId}. Restored ${restoredMessageCount} message(s) (~${formatTokenCount(restoredTokens)}).`,\n )\n\n if (contextUsageBefore !== undefined && contextUsageAfter !== undefined) {\n lines.push(`Context usage: ${contextUsageBefore}% → ${contextUsageAfter}%.`)\n }\n\n if (reactivatedBlockIds.length > 0) {\n const refs = reactivatedBlockIds.map((id) => `b${id}`).join(\", \")\n lines.push(`Also restored nested block(s): ${refs}.`)\n }\n\n if (restoredContentPreview) {\n lines.push(\"\")\n lines.push(\"RESTORED CONTENT (condensed):\")\n lines.push(restoredContentPreview)\n }\n\n ctx.logger.info(\"Decompress tool completed\", {\n targetBlockId: target.displayId,\n targetRunId: target.runId,\n restoredMessageCount,\n restoredTokens,\n reactivatedBlockIds,\n })\n\n return lines.join(\"\\n\")\n },\n })\n}\n","import { createHash } from \"node:crypto\"\nimport type { SessionState, WithParts } from \"../state\"\nimport { isMessageCompacted } from \"../state/utils\"\nimport type { UserMessage } from \"@opencode-ai/sdk/v2\"\n\nconst SUMMARY_ID_HASH_LENGTH = 16\n\n// [FIX Bug 36] Delimiters wrapping a compression summary when it is merged into\n// an existing user message. The header embeds the block id so multiple blocks\n// landing on the same user message each get their own clearly delimited entry,\n// and so the prepend is idempotent across re-runs (guarded by the marker check).\nconst MERGED_SUMMARY_HEADER = (blockId: number | string) =>\n `[ACP compressed context summary (block ${blockId}) — prior conversation recap]\\n`\nconst MERGED_SUMMARY_FOOTER = `\\n[End ACP compressed context summary]\\n\\n`\nconst DCP_BLOCK_ID_TAG_REGEX = /(<dcp-message-id(?=[\\s>])[^>]*>)b\\d+(<\\/dcp-message-id>)/g\n// [FIX Bug 28] Regex to strip stale mNNNN refs from compressed summaries\nconst DCP_MESSAGE_REF_TAG_REGEX = /<dcp-message-id>m\\d+<\\/dcp-message-id>/g\nconst DCP_PAIRED_TAG_REGEX = /<dcp[^>]*>[\\s\\S]*?<\\/dcp[^>]*>/gi\nconst DCP_UNPAIRED_TAG_REGEX = /<\\/?dcp[^>]*>/gi\n\nconst generateStableId = (prefix: string, seed: string): string => {\n const hash = createHash(\"sha256\").update(seed).digest(\"hex\").slice(0, SUMMARY_ID_HASH_LENGTH)\n return `${prefix}_${hash}`\n}\n\nexport const createSyntheticUserMessage = (\n baseMessage: WithParts,\n content: string,\n stableSeed?: string,\n): WithParts => {\n const userInfo = baseMessage.info as UserMessage\n const now = Date.now()\n const deterministicSeed = stableSeed?.trim() || userInfo.id\n const messageId = generateStableId(\"msg_dcp_summary\", deterministicSeed)\n const partId = generateStableId(\"prt_dcp_summary\", deterministicSeed)\n\n return {\n info: {\n id: messageId,\n sessionID: userInfo.sessionID,\n role: \"user\" as const,\n agent: userInfo.agent,\n model: userInfo.model,\n time: { created: now },\n },\n parts: [\n {\n id: partId,\n sessionID: userInfo.sessionID,\n messageID: messageId,\n type: \"text\" as const,\n text: content,\n },\n ],\n }\n}\n\n// [FIX Bug 36] Merge a compression summary into an existing user message by\n// prepending it (clearly delimited) to that message's first text part. This\n// avoids emitting a standalone user-role summary message adjacent to the user's\n// real turn, which previously produced two consecutive user messages and caused\n// dialog role confusion / \"self-Q&A\" loops. Returns true when the summary is\n// present after the call — including the idempotent case where the block's\n// marker is already in the text (no-op), matching appendToTextPart so callers\n// never fall through to a standalone message merely because of a re-run.\nexport const prependCompressionSummary = (\n message: WithParts,\n summary: string,\n blockId: number | string,\n): boolean => {\n const parts = Array.isArray(message.parts) ? message.parts : []\n const header = MERGED_SUMMARY_HEADER(blockId)\n const marker = MERGED_SUMMARY_HEADER(blockId).trimEnd()\n\n for (const part of parts) {\n if (part.type !== \"text\") {\n continue\n }\n const textPart = part as TextPart\n const existing = typeof textPart.text === \"string\" ? textPart.text : \"\"\n if (existing.includes(marker)) {\n return true\n }\n textPart.text = `${header}${summary}${MERGED_SUMMARY_FOOTER}${existing}`\n return true\n }\n\n const sessionID = (message.info as { sessionID?: string }).sessionID ?? \"\"\n const messageId = (message.info as { id: string }).id\n parts.unshift({\n id: generateStableId(\"prt_dcp_prepend\", `${blockId}:${messageId}`),\n sessionID,\n messageID: messageId,\n type: \"text\" as const,\n text: `${header}${summary}${MERGED_SUMMARY_FOOTER}`,\n })\n message.parts = parts\n return true\n}\n\nexport const createSyntheticTextPart = (\n baseMessage: WithParts,\n content: string,\n stableSeed?: string,\n) => {\n const userInfo = baseMessage.info as UserMessage\n const deterministicSeed = stableSeed?.trim() || userInfo.id\n const partId = generateStableId(\"prt_dcp_text\", deterministicSeed)\n\n return {\n id: partId,\n sessionID: userInfo.sessionID,\n messageID: userInfo.id,\n type: \"text\" as const,\n text: content,\n }\n}\n\ntype MessagePart = WithParts[\"parts\"][number]\ntype ToolPart = Extract<MessagePart, { type: \"tool\" }>\ntype TextPart = Extract<MessagePart, { type: \"text\" }>\n\nexport const appendToLastTextPart = (message: WithParts, injection: string): boolean => {\n const textPart = findLastTextPart(message)\n if (!textPart) {\n return false\n }\n\n return appendToTextPart(textPart, injection)\n}\n\nconst findLastTextPart = (message: WithParts): TextPart | null => {\n for (let i = message.parts.length - 1; i >= 0; i--) {\n const part = message.parts[i]\n if (part.type === \"text\") {\n return part\n }\n }\n\n return null\n}\n\nexport const appendToTextPart = (part: TextPart, injection: string): boolean => {\n if (typeof part.text !== \"string\") {\n return false\n }\n\n const normalizedInjection = injection.replace(/^\\n+/, \"\")\n if (!normalizedInjection.trim()) {\n return false\n }\n if (part.text.includes(normalizedInjection)) {\n return true\n }\n\n const baseText = part.text.replace(/\\n*$/, \"\")\n part.text = baseText.length > 0 ? `${baseText}\\n\\n${normalizedInjection}` : normalizedInjection\n return true\n}\n\nexport const appendToAllToolParts = (message: WithParts, tag: string): boolean => {\n let injected = false\n for (const part of message.parts) {\n if (part.type === \"tool\") {\n injected = appendToToolPart(part, tag) || injected\n }\n }\n return injected\n}\n\nconst appendToToolPart = (part: ToolPart, tag: string): boolean => {\n if (part.state?.status !== \"completed\" || typeof part.state.output !== \"string\") {\n return false\n }\n if (part.state.output.includes(tag)) {\n return true\n }\n\n part.state.output = `${part.state.output}${tag}`\n return true\n}\n\nexport const hasContent = (message: WithParts): boolean => {\n return message.parts.some(\n (part) =>\n (part.type === \"text\" &&\n typeof part.text === \"string\" &&\n part.text.trim().length > 0) ||\n (part.type === \"tool\" &&\n part.state?.status === \"completed\" &&\n typeof part.state.output === \"string\"),\n )\n}\n\nexport function buildToolIdList(state: SessionState, messages: WithParts[]): string[] {\n const toolIds: string[] = []\n for (const msg of messages) {\n if (isMessageCompacted(state, msg)) {\n continue\n }\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n if (parts.length > 0) {\n for (const part of parts) {\n if (part.type === \"tool\" && part.callID && part.tool) {\n toolIds.push(part.callID)\n }\n }\n }\n }\n state.toolIdList = toolIds\n return toolIds\n}\n\nexport const replaceBlockIdsWithBlocked = (text: string): string => {\n return text.replace(DCP_BLOCK_ID_TAG_REGEX, \"$1BLOCKED$2\")\n}\n\n// [FIX Bug 28] Strip stale mNNNN refs from compressed summaries before injection\nexport const stripStaleMessageRefs = (text: string): string => {\n return text.replace(DCP_MESSAGE_REF_TAG_REGEX, \"\")\n}\n\nexport const stripHallucinationsFromString = (text: string): string => {\n return text.replace(DCP_PAIRED_TAG_REGEX, \"\").replace(DCP_UNPAIRED_TAG_REGEX, \"\")\n}\n\nexport const stripHallucinations = (messages: WithParts[]): void => {\n for (const message of messages) {\n for (const part of message.parts) {\n if (part.type === \"text\" && typeof part.text === \"string\") {\n part.text = stripHallucinationsFromString(part.text)\n }\n\n if (\n part.type === \"tool\" &&\n part.state?.status === \"completed\" &&\n typeof part.state.output === \"string\"\n ) {\n part.state.output = stripHallucinationsFromString(part.state.output)\n }\n }\n }\n}\n","import type { SessionState, WithParts } from \"../state\"\nimport type { Logger } from \"../logger\"\nimport type { PluginConfig } from \"../config\"\nimport { isMessageCompacted } from \"../state/utils\"\nimport { createSyntheticUserMessage, prependCompressionSummary, replaceBlockIdsWithBlocked, stripStaleMessageRefs } from \"./utils\"\nimport { getLastUserMessage } from \"./query\"\nimport type { UserMessage } from \"@opencode-ai/sdk/v2\"\n\nconst PRUNED_TOOL_OUTPUT_REPLACEMENT =\n \"[Output removed to save context - information superseded or no longer needed]\"\nconst PRUNED_TOOL_ERROR_INPUT_REPLACEMENT = \"[input removed due to failed tool call]\"\nconst PRUNED_QUESTION_INPUT_REPLACEMENT = \"[questions removed - see output for user's answers]\"\n\nexport const prune = (\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n messages: WithParts[],\n): void => {\n filterCompressedRanges(state, logger, config, messages)\n // [HOTFIX] Disabled pruneToolOutputs/pruneToolInputs/pruneToolErrors — they mutate\n // existing messages in-place, breaking GLM prefix cache. Compression still works\n // via filterCompressedRanges + model-initiated compress tool.\n // pruneToolOutputs(state, logger, messages)\n // pruneToolInputs(state, logger, messages)\n // pruneToolErrors(state, logger, messages)\n}\n\nconst pruneFullTool = (state: SessionState, logger: Logger, messages: WithParts[]): void => {\n const messagesToRemove: string[] = []\n\n for (const msg of messages) {\n if (isMessageCompacted(state, msg)) {\n continue\n }\n\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n const partsToRemove: string[] = []\n\n for (const part of parts) {\n if (part.type !== \"tool\") {\n continue\n }\n\n if (!state.prune.tools.has(part.callID)) {\n continue\n }\n if (part.tool !== \"edit\" && part.tool !== \"write\") {\n continue\n }\n\n partsToRemove.push(part.callID)\n }\n\n if (partsToRemove.length === 0) {\n continue\n }\n\n msg.parts = parts.filter(\n (part) => part.type !== \"tool\" || !partsToRemove.includes(part.callID),\n )\n\n if (msg.parts.length === 0) {\n messagesToRemove.push(msg.info.id)\n }\n }\n\n if (messagesToRemove.length > 0) {\n const result = messages.filter((msg) => !messagesToRemove.includes(msg.info.id))\n messages.length = 0\n messages.push(...result)\n }\n}\n\nconst pruneToolOutputs = (state: SessionState, logger: Logger, messages: WithParts[]): void => {\n for (const msg of messages) {\n if (isMessageCompacted(state, msg)) {\n continue\n }\n\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type !== \"tool\") {\n continue\n }\n if (!state.prune.tools.has(part.callID)) {\n continue\n }\n if (part.state.status !== \"completed\") {\n continue\n }\n if (part.tool === \"question\" || part.tool === \"edit\" || part.tool === \"write\") {\n continue\n }\n\n part.state.output = PRUNED_TOOL_OUTPUT_REPLACEMENT\n }\n }\n}\n\nconst pruneToolInputs = (state: SessionState, logger: Logger, messages: WithParts[]): void => {\n for (const msg of messages) {\n if (isMessageCompacted(state, msg)) {\n continue\n }\n\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type !== \"tool\") {\n continue\n }\n\n if (!state.prune.tools.has(part.callID)) {\n continue\n }\n if (part.state.status !== \"completed\") {\n continue\n }\n if (part.tool !== \"question\") {\n continue\n }\n\n if (part.state.input?.questions !== undefined) {\n part.state.input.questions = PRUNED_QUESTION_INPUT_REPLACEMENT\n }\n }\n }\n}\n\nconst pruneToolErrors = (state: SessionState, logger: Logger, messages: WithParts[]): void => {\n for (const msg of messages) {\n if (isMessageCompacted(state, msg)) {\n continue\n }\n\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n for (const part of parts) {\n if (part.type !== \"tool\") {\n continue\n }\n if (!state.prune.tools.has(part.callID)) {\n continue\n }\n if (part.state.status !== \"error\") {\n continue\n }\n\n // Prune all string inputs for errored tools\n const input = part.state.input\n if (input && typeof input === \"object\") {\n for (const key of Object.keys(input)) {\n if (typeof input[key] === \"string\") {\n input[key] = PRUNED_TOOL_ERROR_INPUT_REPLACEMENT\n }\n }\n }\n }\n }\n}\n\nconst filterCompressedRanges = (\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n messages: WithParts[],\n): void => {\n if (\n state.prune.messages.byMessageId.size === 0 &&\n state.prune.messages.activeByAnchorMessageId.size === 0\n ) {\n return\n }\n\n const result: WithParts[] = []\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i]!\n const msgId = msg.info.id\n\n // Check if there's a summary to inject at this anchor point\n const blockId = state.prune.messages.activeByAnchorMessageId.get(msgId)\n const summary =\n blockId !== undefined ? state.prune.messages.blocksById.get(blockId) : undefined\n if (summary) {\n const rawSummaryContent = (summary as { summary?: unknown }).summary\n if (\n summary.active !== true ||\n typeof rawSummaryContent !== \"string\" ||\n rawSummaryContent.length === 0\n ) {\n logger.warn(\"Skipping malformed compress summary\", {\n anchorMessageId: msgId,\n blockId: (summary as { blockId?: unknown }).blockId,\n })\n } else {\n // [FIX Bug 28] Strip stale mNNNN refs before injection\n const _cleaned = stripStaleMessageRefs(rawSummaryContent)\n const summaryContent =\n config.compress.mode === \"message\"\n ? replaceBlockIdsWithBlocked(_cleaned)\n : _cleaned\n\n // [FIX Bug 36] When the next surviving message is a user turn, merge the\n // summary into it instead of emitting a standalone user-role summary\n // message. The old behavior placed a synthetic user message immediately\n // before the user's real turn ([summary(user), user(user)]), which the\n // model often read as two user turns — misattributing the assistant's\n // prior output to the user and triggering \"self-Q&A\" loops. Merging\n // yields a single user turn ([user: recap ‖ real reply]) so no fake\n // conversational turn is perceived.\n const nextSurviving = findNextSurvivingMessage(messages, i, state)\n const merged =\n nextSurviving !== null &&\n nextSurviving.info.role === \"user\" &&\n prependCompressionSummary(nextSurviving, summaryContent, summary.blockId)\n\n if (merged) {\n logger.info(\"Merged compress summary into following user message\", {\n anchorMessageId: msgId,\n targetMessageId: nextSurviving!.info.id,\n summaryLength: summaryContent.length,\n })\n } else {\n // [FIX Bug 1] fallback when no suitable user message to merge into:\n // emit a standalone synthetic user message (prior behavior).\n const userMessage = getLastUserMessage(messages, i)\n const summarySeed = `${summary.blockId}:${summary.anchorMessageId}`\n if (userMessage) {\n result.push(\n createSyntheticUserMessage(userMessage, summaryContent, summarySeed),\n )\n\n logger.info(\"Injected compress summary\", {\n anchorMessageId: msgId,\n summaryLength: summaryContent.length,\n })\n } else {\n const anchorInfo = msg.info as any\n const fallbackBase: WithParts = {\n info: {\n id: anchorInfo.id || msgId,\n sessionID: anchorInfo.sessionID || \"\",\n role: \"user\" as const,\n agent: anchorInfo.agent || \"code\",\n model:\n anchorInfo.model || {\n providerID: \"\",\n modelID: \"\",\n variant: undefined,\n },\n time: { created: anchorInfo.time?.created || Date.now() },\n },\n parts: [],\n }\n result.push(\n createSyntheticUserMessage(fallbackBase, summaryContent, summarySeed),\n )\n\n logger.info(\"Injected compress summary (fallback, no preceding user message)\", {\n anchorMessageId: msgId,\n summaryLength: summaryContent.length,\n })\n }\n }\n }\n }\n\n // Skip messages that are in the prune list\n const pruneEntry = state.prune.messages.byMessageId.get(msgId)\n if (pruneEntry && pruneEntry.activeBlockIds.length > 0) {\n continue\n }\n\n // Normal message, include it\n result.push(msg)\n }\n\n // Replace messages array contents\n messages.length = 0\n messages.push(...result)\n}\n\n// [FIX Bug 36] First surviving (non-pruned) message at or after startIndex.\n// Starts the scan at startIndex inclusive to handle both anchor layouts: when\n// the anchor is itself part of the pruned range (message-start ranges) it is\n// skipped, and when the anchor survives (block-anchor ranges) it is returned —\n// in either case this yields the next real turn the model sees after the recap.\nconst findNextSurvivingMessage = (\n messages: WithParts[],\n startIndex: number,\n state: SessionState,\n): WithParts | null => {\n for (let j = startIndex; j < messages.length; j++) {\n const candidate = messages[j]!\n const entry = state.prune.messages.byMessageId.get(candidate.info.id)\n if (entry && entry.activeBlockIds.length > 0) {\n continue\n }\n return candidate\n }\n return null\n}\n","import type { SessionState, WithParts } from \"../state\"\nimport type { Logger } from \"../logger\"\n\nfunction sortBlocksByCreation(\n a: { createdAt: number; blockId: number },\n b: { createdAt: number; blockId: number },\n): number {\n const createdAtDiff = a.createdAt - b.createdAt\n if (createdAtDiff !== 0) {\n return createdAtDiff\n }\n return a.blockId - b.blockId\n}\n\nexport const syncCompressionBlocks = (\n state: SessionState,\n logger: Logger,\n messages: WithParts[],\n): void => {\n const messagesState = state.prune.messages\n if (!messagesState?.blocksById?.size) {\n return\n }\n\n const messageIds = new Set(messages.map((msg) => msg.info.id))\n const previousActiveBlockIds = new Set<number>(\n Array.from(messagesState.blocksById.values())\n .filter((block) => block.active)\n .map((block) => block.blockId),\n )\n\n messagesState.activeBlockIds.clear()\n messagesState.activeByAnchorMessageId.clear()\n\n const now = Date.now()\n const missingOriginBlockIds: number[] = []\n const orderedBlocks = Array.from(messagesState.blocksById.values()).sort(sortBlocksByCreation)\n\n // [PATCH Bug 3] Removed compressMessageId presence check.\n // Blocks should remain active even if the compress tool call message was\n // removed by opencode's internal compaction. The block's existence IS proof\n // that compression happened.\n for (const block of orderedBlocks) {\n if (block.deactivatedByUser) {\n block.active = false\n if (block.deactivatedAt === undefined) {\n block.deactivatedAt = now\n }\n block.deactivatedByBlockId = undefined\n continue\n }\n\n // Only deactivate if anchor message is completely gone from both current messages AND DCP tracked messages\n if (\n typeof block.anchorMessageId === \"string\" &&\n block.anchorMessageId.length > 0 &&\n !messageIds.has(block.anchorMessageId)\n ) {\n // If anchor exists in DCP's byMessageId (persisted), keep block active\n if (!messagesState.byMessageId.has(block.anchorMessageId)) {\n block.active = false\n block.deactivatedAt = now\n block.deactivatedByBlockId = undefined\n continue\n }\n }\n\n for (const consumedBlockId of block.consumedBlockIds) {\n if (!messagesState.activeBlockIds.has(consumedBlockId)) {\n continue\n }\n\n const consumedBlock = messagesState.blocksById.get(consumedBlockId)\n if (consumedBlock) {\n consumedBlock.active = false\n consumedBlock.deactivatedAt = now\n consumedBlock.deactivatedByBlockId = block.blockId\n\n const mappedBlockId = messagesState.activeByAnchorMessageId.get(\n consumedBlock.anchorMessageId,\n )\n if (mappedBlockId === consumedBlock.blockId) {\n messagesState.activeByAnchorMessageId.delete(consumedBlock.anchorMessageId)\n }\n }\n\n messagesState.activeBlockIds.delete(consumedBlockId)\n }\n\n block.active = true\n block.deactivatedAt = undefined\n block.deactivatedByBlockId = undefined\n messagesState.activeBlockIds.add(block.blockId)\n if (messageIds.has(block.anchorMessageId)) {\n messagesState.activeByAnchorMessageId.set(block.anchorMessageId, block.blockId)\n }\n }\n\n for (const entry of messagesState.byMessageId.values()) {\n const allBlockIds = Array.isArray(entry.allBlockIds)\n ? [...new Set(entry.allBlockIds.filter((id) => Number.isInteger(id) && id > 0))]\n : []\n\n entry.allBlockIds = allBlockIds\n entry.activeBlockIds = allBlockIds.filter((id) => messagesState.activeBlockIds.has(id))\n }\n\n const nextActiveBlockIds = messagesState.activeBlockIds\n let deactivatedCount = 0\n let reactivatedCount = 0\n\n for (const blockId of previousActiveBlockIds) {\n if (!nextActiveBlockIds.has(blockId)) {\n deactivatedCount++\n }\n }\n for (const blockId of nextActiveBlockIds) {\n if (!previousActiveBlockIds.has(blockId)) {\n reactivatedCount++\n }\n }\n\n if (missingOriginBlockIds.length > 0 || deactivatedCount > 0 || reactivatedCount > 0) {\n logger.info(\"Synced compress block state\", {\n missingOriginCount: missingOriginBlockIds.length,\n deactivatedCount,\n reactivatedCount,\n })\n }\n}\n","export type PermissionAction = \"ask\" | \"allow\" | \"deny\"\n\nexport type PermissionValue = PermissionAction | Record<string, PermissionAction>\n\nexport type PermissionConfig = Record<string, PermissionValue> | undefined\n\nexport interface HostPermissionSnapshot {\n global: PermissionConfig\n agents: Record<string, PermissionConfig>\n}\n\ntype PermissionRule = {\n permission: string\n pattern: string\n action: PermissionAction\n}\n\nconst findLastMatchingRule = (\n rules: PermissionRule[],\n predicate: (rule: PermissionRule) => boolean,\n): PermissionRule | undefined => {\n for (let index = rules.length - 1; index >= 0; index -= 1) {\n const rule = rules[index]\n if (rule && predicate(rule)) {\n return rule\n }\n }\n\n return undefined\n}\n\nconst wildcardMatch = (value: string, pattern: string): boolean => {\n const normalizedValue = value.replaceAll(\"\\\\\", \"/\")\n let escaped = pattern\n .replaceAll(\"\\\\\", \"/\")\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*/g, \".*\")\n .replace(/\\?/g, \".\")\n\n if (escaped.endsWith(\" .*\")) {\n escaped = escaped.slice(0, -3) + \"( .*)?\"\n }\n\n const flags = process.platform === \"win32\" ? \"si\" : \"s\"\n return new RegExp(`^${escaped}$`, flags).test(normalizedValue)\n}\n\nconst getPermissionRules = (permissionConfigs: PermissionConfig[]): PermissionRule[] => {\n const rules: PermissionRule[] = []\n for (const permissionConfig of permissionConfigs) {\n if (!permissionConfig) {\n continue\n }\n\n for (const [permission, value] of Object.entries(permissionConfig)) {\n if (value === \"ask\" || value === \"allow\" || value === \"deny\") {\n rules.push({ permission, pattern: \"*\", action: value })\n continue\n }\n\n for (const [pattern, action] of Object.entries(value)) {\n if (action === \"ask\" || action === \"allow\" || action === \"deny\") {\n rules.push({ permission, pattern, action })\n }\n }\n }\n }\n return rules\n}\n\nexport const compressDisabledByOpencode = (...permissionConfigs: PermissionConfig[]): boolean => {\n const match = findLastMatchingRule(getPermissionRules(permissionConfigs), (rule) =>\n wildcardMatch(\"compress\", rule.permission),\n )\n\n return match?.pattern === \"*\" && match.action === \"deny\"\n}\n\nexport const resolveEffectiveCompressPermission = (\n basePermission: PermissionAction,\n hostPermissions: HostPermissionSnapshot,\n agentName?: string,\n): PermissionAction => {\n if (basePermission === \"deny\") {\n return \"deny\"\n }\n\n return compressDisabledByOpencode(\n hostPermissions.global,\n agentName ? hostPermissions.agents[agentName] : undefined,\n )\n ? \"deny\"\n : basePermission\n}\n\nexport const hasExplicitToolPermission = (\n permissionConfig: PermissionConfig,\n tool: string,\n): boolean => {\n return permissionConfig ? Object.prototype.hasOwnProperty.call(permissionConfig, tool) : false\n}\n","import type { PluginConfig } from \"./config\"\nimport { type HostPermissionSnapshot, resolveEffectiveCompressPermission } from \"./host-permissions\"\nimport type { SessionState, WithParts } from \"./state\"\nimport { getLastUserMessage } from \"./messages/query\"\n\nexport const compressPermission = (\n state: SessionState,\n config: PluginConfig,\n): \"ask\" | \"allow\" | \"deny\" => {\n return state.compressPermission ?? config.compress.permission\n}\n\nexport const syncCompressPermissionState = (\n state: SessionState,\n config: PluginConfig,\n hostPermissions: HostPermissionSnapshot,\n messages: WithParts[],\n): void => {\n const activeAgent = getLastUserMessage(messages)?.info.agent\n state.compressPermission = resolveEffectiveCompressPermission(\n config.compress.permission,\n hostPermissions,\n activeAgent,\n )\n}\n","import type { SessionState, CompressionBlock } from \"../../state\"\nimport type { GCConfig } from \"../../config\"\n\nexport interface BlockGuidanceContext {\n currentTokens?: number\n modelContextLimit?: number\n}\n\nexport function buildCompressedBlockGuidance(\n state: SessionState,\n gcConfig?: GCConfig,\n context?: BlockGuidanceContext,\n): string {\n const activeBlockIds = Array.from(state.prune.messages.activeBlockIds)\n .filter((id) => Number.isInteger(id) && id > 0)\n .sort((a, b) => a - b)\n\n const refs = activeBlockIds.map((id) => `b${id}`)\n const blockCount = refs.length\n const blockList = blockCount > 0 ? refs.join(\", \") : \"none\"\n\n const lines = [\n \"Compressed block context:\",\n `- Active compressed blocks: ${blockCount} (${blockList})`,\n \"- If your selected compression range includes any listed block, include each required placeholder exactly once in the summary using `(bN)`.\",\n ]\n\n // [FIX Bug 35] Only show aging warnings when context usage is above 50%.\n // Showing warnings at low usage causes unnecessary compress operations that\n // waste tokens and attention — the model preemptively re-summarizes blocks\n // that aren't actually at risk of GC truncation.\n const usageRatio =\n context?.currentTokens && context?.modelContextLimit\n ? context.currentTokens / context.modelContextLimit\n : 0\n\n if (gcConfig && usageRatio > 0.5) {\n const promotionThreshold = gcConfig.promotionThreshold\n const agingBlocks: string[] = []\n\n for (const blockId of activeBlockIds) {\n const block = state.prune.messages.blocksById.get(blockId)\n if (!block) continue\n\n const survived = block.survivedCount ?? 0\n const gen = block.generation ?? \"young\"\n const sizeK = (block.summary.length / 1000).toFixed(1)\n const preview = block.summary.slice(0, 120).replace(/\\n/g, \" \")\n\n if (gen === \"old\" || survived >= promotionThreshold - 2) {\n agingBlocks.push(\n ` b${blockId}: age=${survived}/${promotionThreshold}, gen=${gen}, size=${sizeK}K chars — ${preview}...`,\n )\n }\n }\n\n if (agingBlocks.length > 0) {\n lines.push(\"\")\n lines.push(\"⚠️ Block aging warning — these blocks may be truncated by GC soon:\")\n lines.push(...agingBlocks)\n lines.push(\n \"To preserve important content: use the compress tool to re-summarize these blocks into new concise ones. Unhandled blocks will be auto-truncated.\",\n )\n }\n }\n\n return lines.join(\"\\n\")\n}\n\nexport function renderMessagePriorityGuidance(priorityLabel: string, refs: string[]): string {\n const refList = refs.length > 0 ? refs.join(\", \") : \"none\"\n\n return [\n \"Message priority context:\",\n \"- Higher-priority older messages consume more context and should be compressed right away if it is safe to do so.\",\n `- ${priorityLabel}-priority message IDs before this point: ${refList}`,\n ].join(\"\\n\")\n}\n\nexport function appendGuidanceToDcpTag(nudgeText: string, guidance: string): string {\n if (!guidance.trim()) {\n return nudgeText\n }\n\n const closeTag = \"</dcp-system-reminder>\"\n const closeTagIndex = nudgeText.lastIndexOf(closeTag)\n\n if (closeTagIndex === -1) {\n return nudgeText\n }\n\n const beforeClose = nudgeText.slice(0, closeTagIndex).trimEnd()\n const afterClose = nudgeText.slice(closeTagIndex)\n return `${beforeClose}\\n\\n${guidance}\\n${afterClose}`\n}\n","import type { PluginConfig } from \"../config\"\nimport { countAllMessageTokens } from \"../token-utils\"\nimport { isMessageCompacted } from \"../state/utils\"\nimport type { SessionState, WithParts } from \"../state\"\nimport { isIgnoredUserMessage, isProtectedUserMessage, messageHasCompress } from \"./query\"\n\nconst MEDIUM_PRIORITY_MIN_TOKENS = 500\nconst HIGH_PRIORITY_MIN_TOKENS = 5000\n\nexport type MessagePriority = \"low\" | \"medium\" | \"high\"\n\nexport interface CompressionPriorityEntry {\n ref: string\n tokenCount: number\n priority: MessagePriority\n}\n\nexport type CompressionPriorityMap = Map<string, CompressionPriorityEntry>\n\nexport function buildPriorityMap(\n config: PluginConfig,\n state: SessionState,\n messages: WithParts[],\n): CompressionPriorityMap {\n if (config.compress.mode !== \"message\") {\n return new Map()\n }\n const priorities: CompressionPriorityMap = new Map()\n\n for (const message of messages) {\n if (isIgnoredUserMessage(message)) {\n continue\n }\n\n if (isProtectedUserMessage(config, message)) {\n continue\n }\n\n if (isMessageCompacted(state, message)) {\n continue\n }\n\n const rawMessageId = message.info.id\n if (typeof rawMessageId !== \"string\" || rawMessageId.length === 0) {\n continue\n }\n\n const ref = state.messageIds.byRawId.get(rawMessageId)\n if (!ref) {\n continue\n }\n\n const tokenCount = countAllMessageTokens(message)\n priorities.set(rawMessageId, {\n ref,\n tokenCount,\n priority: messageHasCompress(message) ? \"high\" : classifyMessagePriority(tokenCount),\n })\n }\n\n return priorities\n}\n\nexport function classifyMessagePriority(tokenCount: number): MessagePriority {\n if (tokenCount >= HIGH_PRIORITY_MIN_TOKENS) {\n return \"high\"\n }\n\n if (tokenCount >= MEDIUM_PRIORITY_MIN_TOKENS) {\n return \"medium\"\n }\n\n return \"low\"\n}\n\nexport function listPriorityRefsBeforeIndex(\n messages: WithParts[],\n priorities: CompressionPriorityMap,\n anchorIndex: number,\n priority: MessagePriority,\n): string[] {\n const refs: string[] = []\n const seen = new Set<string>()\n const upperBound = Math.max(0, Math.min(anchorIndex, messages.length))\n\n for (let index = 0; index < upperBound; index++) {\n const rawMessageId = messages[index]?.info.id\n if (typeof rawMessageId !== \"string\") {\n continue\n }\n\n const entry = priorities.get(rawMessageId)\n if (!entry || entry.priority !== priority || seen.has(entry.ref)) {\n continue\n }\n\n seen.add(entry.ref)\n refs.push(entry.ref)\n }\n\n return refs\n}\n","import type { SessionState, WithParts } from \"../../state\"\nimport type { PluginConfig } from \"../../config\"\nimport {\n appendGuidanceToDcpTag,\n buildCompressedBlockGuidance,\n renderMessagePriorityGuidance,\n} from \"../../prompts/extensions/nudge\"\nimport type { RuntimePrompts } from \"../../prompts/store\"\nimport type { UserMessage } from \"@opencode-ai/sdk/v2\"\nimport {\n type CompressionPriorityMap,\n type MessagePriority,\n listPriorityRefsBeforeIndex,\n} from \"../priority\"\nimport {\n appendToTextPart,\n appendToLastTextPart,\n createSyntheticTextPart,\n hasContent,\n} from \"../utils\"\nimport { getLastUserMessage, isIgnoredUserMessage, isSyntheticMessage } from \"../query\"\nimport { getCurrentTokenUsage } from \"../../token-utils\"\nimport { getActiveSummaryTokenUsage } from \"../../state/utils\"\n\nconst MESSAGE_MODE_NUDGE_PRIORITY: MessagePriority = \"high\"\n\nexport interface LastUserModelContext {\n providerId: string | undefined\n modelId: string | undefined\n}\n\nexport interface LastNonIgnoredMessage {\n message: WithParts\n index: number\n}\n\ninterface ModelLimit {\n context: number\n input?: number\n output?: number\n}\n\nexport function computeInputBudget(limit: ModelLimit): number | undefined {\n if (!limit.context) {\n return undefined\n }\n\n return limit.input ?? Math.max(0, limit.context - (limit.output ?? 0))\n}\n\nexport function getNudgeFrequency(config: PluginConfig): number {\n return Math.max(1, Math.floor(config.compress.nudgeFrequency || 1))\n}\n\nexport function getIterationNudgeThreshold(config: PluginConfig): number {\n return Math.max(1, Math.floor(config.compress.iterationNudgeThreshold || 1))\n}\n\nexport function findLastNonIgnoredMessage(messages: WithParts[]): LastNonIgnoredMessage | null {\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i]\n if (isIgnoredUserMessage(message)) {\n continue\n }\n if (isSyntheticMessage(message)) {\n continue\n }\n return { message, index: i }\n }\n\n return null\n}\n\nexport function countMessagesAfterIndex(messages: WithParts[], index: number): number {\n let count = 0\n\n for (let i = index + 1; i < messages.length; i++) {\n const message = messages[i]\n if (isIgnoredUserMessage(message)) {\n continue\n }\n count++\n }\n\n return count\n}\n\nexport function getModelInfo(messages: WithParts[]): LastUserModelContext {\n const lastUserMessage = getLastUserMessage(messages)\n if (!lastUserMessage) {\n return {\n providerId: undefined,\n modelId: undefined,\n }\n }\n\n const userInfo = lastUserMessage.info as UserMessage\n return {\n providerId: userInfo.model.providerID,\n modelId: userInfo.model.modelID,\n }\n}\n\nfunction resolveContextTokenLimit(\n config: PluginConfig,\n state: SessionState,\n providerId: string | undefined,\n modelId: string | undefined,\n threshold: \"max\" | \"min\",\n): number | undefined {\n const parseLimitValue = (limit: number | `${number}%` | undefined): number | undefined => {\n if (limit === undefined) {\n return undefined\n }\n\n if (typeof limit === \"number\") {\n return limit\n }\n\n if (!limit.endsWith(\"%\") || state.modelContextLimit === undefined) {\n return undefined\n }\n\n const parsedPercent = parseFloat(limit.slice(0, -1))\n if (isNaN(parsedPercent)) {\n return undefined\n }\n\n const roundedPercent = Math.round(parsedPercent)\n const clampedPercent = Math.max(0, Math.min(100, roundedPercent))\n return Math.round((clampedPercent / 100) * state.modelContextLimit)\n }\n\n const modelLimits =\n threshold === \"max\" ? config.compress.modelMaxLimits : config.compress.modelMinLimits\n if (modelLimits && providerId !== undefined && modelId !== undefined) {\n const providerModelId = `${providerId}/${modelId}`\n const modelLimit = modelLimits[providerModelId]\n if (modelLimit !== undefined) {\n return parseLimitValue(modelLimit)\n }\n }\n\n const globalLimit =\n threshold === \"max\" ? config.compress.maxContextLimit : config.compress.minContextLimit\n return parseLimitValue(globalLimit)\n}\n\nexport function isContextOverLimits(\n config: PluginConfig,\n state: SessionState,\n providerId: string | undefined,\n modelId: string | undefined,\n messages: WithParts[],\n) {\n const summaryTokenExtension = config.compress.summaryBuffer\n ? getActiveSummaryTokenUsage(state)\n : 0\n const resolvedMaxContextLimit = resolveContextTokenLimit(\n config,\n state,\n providerId,\n modelId,\n \"max\",\n )\n const maxContextLimit =\n resolvedMaxContextLimit === undefined\n ? undefined\n : resolvedMaxContextLimit + summaryTokenExtension\n const minContextLimit = resolveContextTokenLimit(config, state, providerId, modelId, \"min\")\n const currentTokens = getCurrentTokenUsage(state, messages)\n\n let overMaxLimit = maxContextLimit === undefined ? false : currentTokens > maxContextLimit\n const overMinLimit = minContextLimit === undefined ? false : currentTokens >= minContextLimit\n\n // [FIX Bug 20] Suppress overMax while cacheRead hasn't updated after compress\n if (overMaxLimit) {\n const recentCompressCount = 3\n const recentMessages = messages.slice(-recentCompressCount)\n for (const msg of recentMessages) {\n if (msg.info.role === \"assistant\" && msg.parts) {\n for (const part of msg.parts) {\n if ((part as any).type === \"tool-invocation\" && (part as any).toolInvocation?.toolName === \"compress\") {\n overMaxLimit = false\n break\n }\n }\n }\n if (!overMaxLimit) break\n }\n }\n\n return {\n overMaxLimit,\n overMinLimit,\n currentTokens,\n modelContextLimit: state.modelContextLimit,\n }\n}\n\nexport function addAnchor(\n anchorMessageIds: Set<string>,\n anchorMessageId: string,\n anchorMessageIndex: number,\n messages: WithParts[],\n interval: number,\n): boolean {\n if (anchorMessageIndex < 0) {\n return false\n }\n\n let latestAnchorMessageIndex = -1\n for (let i = messages.length - 1; i >= 0; i--) {\n if (anchorMessageIds.has(messages[i].info.id)) {\n latestAnchorMessageIndex = i\n break\n }\n }\n\n const shouldAdd =\n latestAnchorMessageIndex < 0 || anchorMessageIndex - latestAnchorMessageIndex >= interval\n if (!shouldAdd) {\n return false\n }\n\n const previousSize = anchorMessageIds.size\n anchorMessageIds.add(anchorMessageId)\n return anchorMessageIds.size !== previousSize\n}\n\nfunction buildMessagePriorityGuidance(\n messages: WithParts[],\n compressionPriorities: CompressionPriorityMap | undefined,\n anchorIndex: number,\n priority: MessagePriority,\n): string {\n if (!compressionPriorities || compressionPriorities.size === 0) {\n return \"\"\n }\n\n const refs = listPriorityRefsBeforeIndex(messages, compressionPriorities, anchorIndex, priority)\n const priorityLabel = `${priority[0].toUpperCase()}${priority.slice(1)}`\n\n return renderMessagePriorityGuidance(priorityLabel, refs)\n}\n\nfunction injectAnchoredNudge(message: WithParts, nudgeText: string): void {\n if (!nudgeText.trim()) {\n return\n }\n\n if (message.info.role === \"user\") {\n if (appendToLastTextPart(message, nudgeText)) {\n return\n }\n\n message.parts.push(createSyntheticTextPart(message, nudgeText))\n return\n }\n\n if (message.info.role !== \"assistant\") {\n return\n }\n\n if (!hasContent(message)) {\n return\n }\n\n for (const part of message.parts) {\n if (part.type === \"text\") {\n if (appendToTextPart(part, nudgeText)) {\n return\n }\n }\n }\n\n const syntheticPart = createSyntheticTextPart(message, nudgeText)\n const firstToolIndex = message.parts.findIndex((p) => p.type === \"tool\")\n if (firstToolIndex === -1) {\n message.parts.push(syntheticPart)\n } else {\n message.parts.splice(firstToolIndex, 0, syntheticPart)\n }\n}\n\nfunction collectAnchoredMessages(\n anchorMessageIds: Set<string>,\n messages: WithParts[],\n): Array<{ message: WithParts; index: number }> {\n const anchoredMessages: Array<{ message: WithParts; index: number }> = []\n\n for (const anchorMessageId of anchorMessageIds) {\n const index = messages.findIndex((message) => message.info.id === anchorMessageId)\n if (index === -1) {\n continue\n }\n\n anchoredMessages.push({\n message: messages[index],\n index,\n })\n }\n\n return anchoredMessages\n}\n\nfunction collectTurnNudgeAnchors(\n state: SessionState,\n config: PluginConfig,\n messages: WithParts[],\n): Set<string> {\n const turnNudgeAnchors = new Set<string>()\n const targetRole = config.compress.nudgeForce === \"strong\" ? \"user\" : \"assistant\"\n\n for (const message of messages) {\n if (!state.nudges.turnNudgeAnchors.has(message.info.id)) continue\n\n if (message.info.role === targetRole) {\n turnNudgeAnchors.add(message.info.id)\n }\n }\n\n return turnNudgeAnchors\n}\n\nfunction applyRangeModeAnchoredNudge(\n anchorMessageIds: Set<string>,\n messages: WithParts[],\n baseNudgeText: string,\n compressedBlockGuidance: string,\n): void {\n const nudgeText = appendGuidanceToDcpTag(baseNudgeText, compressedBlockGuidance)\n if (!nudgeText.trim()) {\n return\n }\n\n for (const { message } of collectAnchoredMessages(anchorMessageIds, messages)) {\n injectAnchoredNudge(message, nudgeText)\n }\n}\n\nfunction applyMessageModeAnchoredNudge(\n anchorMessageIds: Set<string>,\n messages: WithParts[],\n baseNudgeText: string,\n compressionPriorities?: CompressionPriorityMap,\n): void {\n for (const { message, index } of collectAnchoredMessages(anchorMessageIds, messages)) {\n const priorityGuidance = buildMessagePriorityGuidance(\n messages,\n compressionPriorities,\n index,\n MESSAGE_MODE_NUDGE_PRIORITY,\n )\n const nudgeText = appendGuidanceToDcpTag(baseNudgeText, priorityGuidance)\n injectAnchoredNudge(message, nudgeText)\n }\n}\n\n/**\n * Resolve a config threshold (number | \"NN%\") to a percentage value.\n */\nfunction resolveThresholdPercent(\n threshold: number | `${number}%` | undefined,\n modelContextLimit: number | undefined,\n): number | undefined {\n if (threshold === undefined) return undefined\n if (typeof threshold === \"number\") {\n if (!modelContextLimit) return undefined\n return (threshold / modelContextLimit) * 100\n }\n const parsed = parseFloat(threshold)\n return isNaN(parsed) ? undefined : parsed\n}\n\n/**\n * Build tiered context usage guidance based on actual config thresholds.\n * Shared by inject.ts (suffix message) and utils.ts (anchored nudges).\n */\nexport function buildContextUsageGuidance(\n config: PluginConfig,\n currentTokens?: number,\n modelContextLimit?: number,\n): string {\n if (currentTokens === undefined || modelContextLimit === undefined || modelContextLimit === 0) {\n return \"\"\n }\n\n const pct = (currentTokens / modelContextLimit) * 100\n const percentage = pct.toFixed(1)\n const formatK = (n: number) => (n >= 1000 ? `${(n / 1000).toFixed(1)}K` : String(n))\n\n const minPct = resolveThresholdPercent(config.compress.minContextLimit, modelContextLimit) ?? 45\n const maxPct = resolveThresholdPercent(config.compress.maxContextLimit, modelContextLimit) ?? 55\n\n const base = `Context usage: ${formatK(currentTokens)} / ${formatK(modelContextLimit)} tokens (${percentage}%). ACP threshold: ${maxPct.toFixed(0)}%.`\n\n let guidance: string\n if (pct < minPct) {\n guidance = \" Context is ample — focus on your task. Only compress obvious waste (large terminal outputs, duplicated content).\"\n } else if (pct < maxPct) {\n guidance = \" Context is moderate — compress completed sections and high-token waste. Preserve key details.\"\n } else {\n guidance = \" Context is high — compress aggressively but selectively. Preserve only what is essential.\"\n }\n\n return `\\n\\n${base}${guidance}`\n}\n\nexport function applyAnchoredNudges(\n state: SessionState,\n config: PluginConfig,\n messages: WithParts[],\n prompts: RuntimePrompts,\n compressionPriorities?: CompressionPriorityMap,\n currentTokens?: number,\n modelContextLimit?: number,\n suffixMessage?: WithParts | null,\n): void {\n const contextUsageInfo = buildContextUsageGuidance(config, currentTokens, modelContextLimit)\n const contextLimitNudgeWithUsage = prompts.contextLimitNudge + contextUsageInfo\n const turnNudgeAnchors = collectTurnNudgeAnchors(state, config, messages)\n\n if (suffixMessage) {\n const nudgeParts: string[] = []\n\n if (config.compress.mode === \"message\") {\n if (state.nudges.contextLimitAnchors.size > 0) {\n for (const { index } of collectAnchoredMessages(state.nudges.contextLimitAnchors, messages)) {\n const guidance = buildMessagePriorityGuidance(messages, compressionPriorities, index, MESSAGE_MODE_NUDGE_PRIORITY)\n nudgeParts.push(appendGuidanceToDcpTag(contextLimitNudgeWithUsage, guidance))\n }\n }\n if (turnNudgeAnchors.size > 0) {\n for (const { index } of collectAnchoredMessages(turnNudgeAnchors, messages)) {\n const guidance = buildMessagePriorityGuidance(messages, compressionPriorities, index, MESSAGE_MODE_NUDGE_PRIORITY)\n nudgeParts.push(appendGuidanceToDcpTag(prompts.turnNudge, guidance))\n }\n }\n if (state.nudges.iterationNudgeAnchors.size > 0) {\n for (const { index } of collectAnchoredMessages(state.nudges.iterationNudgeAnchors, messages)) {\n const guidance = buildMessagePriorityGuidance(messages, compressionPriorities, index, MESSAGE_MODE_NUDGE_PRIORITY)\n nudgeParts.push(appendGuidanceToDcpTag(prompts.iterationNudge, guidance))\n }\n }\n } else {\n if (state.nudges.contextLimitAnchors.size > 0) {\n nudgeParts.push(contextLimitNudgeWithUsage)\n }\n if (turnNudgeAnchors.size > 0) {\n nudgeParts.push(prompts.turnNudge)\n }\n if (state.nudges.iterationNudgeAnchors.size > 0) {\n nudgeParts.push(prompts.iterationNudge)\n }\n }\n\n const combined = nudgeParts.join(\"\\n\\n\")\n if (combined.trim()) {\n injectAnchoredNudge(suffixMessage, combined)\n }\n return\n }\n\n if (config.compress.mode === \"message\") {\n applyMessageModeAnchoredNudge(\n state.nudges.contextLimitAnchors,\n messages,\n contextLimitNudgeWithUsage,\n compressionPriorities,\n )\n applyMessageModeAnchoredNudge(\n turnNudgeAnchors,\n messages,\n prompts.turnNudge,\n compressionPriorities,\n )\n applyMessageModeAnchoredNudge(\n state.nudges.iterationNudgeAnchors,\n messages,\n prompts.iterationNudge,\n compressionPriorities,\n )\n return\n }\n\n applyRangeModeAnchoredNudge(\n state.nudges.contextLimitAnchors,\n messages,\n contextLimitNudgeWithUsage,\n \"\",\n )\n applyRangeModeAnchoredNudge(\n turnNudgeAnchors,\n messages,\n prompts.turnNudge,\n \"\",\n )\n applyRangeModeAnchoredNudge(\n state.nudges.iterationNudgeAnchors,\n messages,\n prompts.iterationNudge,\n \"\",\n )\n}\n","import type { SessionState, WithParts } from \"../../state\"\nimport type { Logger } from \"../../logger\"\nimport type { PluginConfig } from \"../../config\"\nimport type { RuntimePrompts } from \"../../prompts/store\"\nimport { formatMessageIdTag } from \"../../message-ids\"\nimport type { CompressionPriorityMap } from \"../priority\"\nimport { compressPermission } from \"../../compress-permission\"\nimport {\n getLastUserMessage,\n isIgnoredUserMessage,\n isProtectedUserMessage,\n messageHasCompress,\n} from \"../query\"\nimport { saveSessionState } from \"../../state/persistence\"\nimport {\n appendToTextPart,\n appendToLastTextPart,\n appendToAllToolParts,\n createSyntheticTextPart,\n createSyntheticUserMessage,\n hasContent,\n} from \"../utils\"\nimport {\n addAnchor,\n applyAnchoredNudges,\n buildContextUsageGuidance,\n countMessagesAfterIndex,\n findLastNonIgnoredMessage,\n getIterationNudgeThreshold,\n getNudgeFrequency,\n getModelInfo,\n isContextOverLimits,\n} from \"./utils\"\nimport { buildCompressedBlockGuidance } from \"../../prompts/extensions/nudge\"\n\n/**\n * Stable seed for the ACP dynamic guidance suffix message.\n * Using a fixed seed ensures the synthetic message ID is deterministic,\n * so it won't be assigned a new mNNNNN ref on each transform call.\n */\nconst ACP_SUFFIX_SEED = \"acp-dynamic-guidance\"\n\n/**\n * Create a synthetic user message at the END of the messages array.\n * All per-turn dynamic ACP content (context usage, visible IDs, nudges, etc.)\n * is injected into this suffix message instead of historical user messages,\n * preserving OpenAI Responses prefix cache stability.\n */\nfunction createSuffixMessage(messages: WithParts[]): WithParts | null {\n if (messages.length === 0) return null\n // Use any user message as base for session/agent/model info\n const base = messages.find((m) => m.info.role === \"user\") || messages[messages.length - 1]\n const synthetic = createSyntheticUserMessage(base, \"\", ACP_SUFFIX_SEED)\n messages.push(synthetic)\n return synthetic\n}\n\nexport const injectCompressNudges = (\n state: SessionState,\n config: PluginConfig,\n logger: Logger,\n messages: WithParts[],\n prompts: RuntimePrompts,\n compressionPriorities?: CompressionPriorityMap,\n): void => {\n if (compressPermission(state, config) === \"deny\") {\n return\n }\n\n if (state.manualMode) {\n return\n }\n\n const lastMessage = findLastNonIgnoredMessage(messages)\n const lastAssistantMessage = messages.findLast((message) => message.info.role === \"assistant\")\n\n if (lastAssistantMessage && messageHasCompress(lastAssistantMessage)) {\n state.nudges.contextLimitAnchors.clear()\n state.nudges.turnNudgeAnchors.clear()\n state.nudges.iterationNudgeAnchors.clear()\n void saveSessionState(state, logger)\n return\n }\n\n const { providerId, modelId } = getModelInfo(messages)\n let anchorsChanged = false\n\n const { overMaxLimit, overMinLimit, currentTokens, modelContextLimit } = isContextOverLimits(\n config,\n state,\n providerId,\n modelId,\n messages,\n )\n\n if (!overMinLimit) {\n const hadTurnAnchors = state.nudges.turnNudgeAnchors.size > 0\n const hadIterationAnchors = state.nudges.iterationNudgeAnchors.size > 0\n\n if (hadTurnAnchors || hadIterationAnchors) {\n state.nudges.turnNudgeAnchors.clear()\n state.nudges.iterationNudgeAnchors.clear()\n anchorsChanged = true\n }\n }\n\n if (overMaxLimit) {\n if (lastMessage) {\n const interval = getNudgeFrequency(config)\n const added = addAnchor(\n state.nudges.contextLimitAnchors,\n lastMessage.message.info.id,\n lastMessage.index,\n messages,\n interval,\n )\n if (added) {\n anchorsChanged = true\n }\n }\n } else if (overMinLimit) {\n const isLastMessageUser = lastMessage?.message.info.role === \"user\"\n\n if (isLastMessageUser && lastAssistantMessage) {\n const previousSize = state.nudges.turnNudgeAnchors.size\n state.nudges.turnNudgeAnchors.add(lastMessage.message.info.id)\n state.nudges.turnNudgeAnchors.add(lastAssistantMessage.info.id)\n if (state.nudges.turnNudgeAnchors.size !== previousSize) {\n anchorsChanged = true\n }\n }\n\n const lastUserMessage = getLastUserMessage(messages)\n if (lastUserMessage && lastMessage) {\n const lastUserMessageIndex = messages.findIndex(\n (message) => message.info.id === lastUserMessage.info.id,\n )\n if (lastUserMessageIndex >= 0) {\n const messagesSinceUser = countMessagesAfterIndex(messages, lastUserMessageIndex)\n const iterationThreshold = getIterationNudgeThreshold(config)\n\n if (\n lastMessage.index > lastUserMessageIndex &&\n messagesSinceUser >= iterationThreshold\n ) {\n const interval = getNudgeFrequency(config)\n const added = addAnchor(\n state.nudges.iterationNudgeAnchors,\n lastMessage.message.info.id,\n lastMessage.index,\n messages,\n interval,\n )\n\n if (added) {\n anchorsChanged = true\n }\n }\n }\n }\n }\n\n const suffixMessage = createSuffixMessage(messages)\n\n applyAnchoredNudges(state, config, messages, prompts, compressionPriorities, currentTokens, modelContextLimit, suffixMessage)\n\n injectContextUsage(suffixMessage, config, currentTokens, modelContextLimit)\n\n if (config.compress.mode !== \"message\") {\n const blockGuidance = buildCompressedBlockGuidance(state, config.gc, { currentTokens, modelContextLimit })\n if (blockGuidance.trim() && suffixMessage) {\n appendToLastTextPart(suffixMessage, \"\\n\\n\" + blockGuidance)\n }\n }\n\n injectVisibleIdRange(state, messages, suffixMessage)\n\n if (anchorsChanged) {\n void saveSessionState(state, logger)\n }\n}\n\nfunction injectContextUsage(\n target: WithParts | null,\n config: PluginConfig,\n currentTokens?: number,\n modelContextLimit?: number,\n): void {\n if (!target) return\n const usageTag = buildContextUsageGuidance(config, currentTokens, modelContextLimit)\n if (!usageTag) return\n\n for (const part of target.parts) {\n if (part.type === \"text\") {\n appendToTextPart(part, usageTag)\n return\n }\n }\n target.parts.push(createSyntheticTextPart(target, usageTag))\n}\n\nfunction injectVisibleIdRange(state: SessionState, messages: WithParts[], target: WithParts | null): void {\n if (!target) return\n const visibleRefs: string[] = []\n for (const message of messages) {\n const ref = state.messageIds.byRawId.get(message.info.id)\n if (ref) {\n visibleRefs.push(ref)\n }\n }\n\n if (visibleRefs.length === 0) return\n\n visibleRefs.sort()\n const first = visibleRefs[0]\n const last = visibleRefs[visibleRefs.length - 1]\n const rangeTag = `\\n\\n[Visible message IDs: ${first} to ${last} (${visibleRefs.length} messages). Only use IDs in this range for compress.]`\n\n for (const part of target.parts) {\n if (part.type === \"text\") {\n appendToTextPart(part, rangeTag)\n return\n }\n }\n target.parts.push(createSyntheticTextPart(target, rangeTag))\n}\n\nexport const injectMessageIds = (\n state: SessionState,\n config: PluginConfig,\n messages: WithParts[],\n compressionPriorities?: CompressionPriorityMap,\n): void => {\n if (compressPermission(state, config) === \"deny\") {\n return\n }\n\n for (const message of messages) {\n if (isIgnoredUserMessage(message)) {\n continue\n }\n\n const messageRef = state.messageIds.byRawId.get(message.info.id)\n if (!messageRef) {\n continue\n }\n\n const isBlockedMessage = isProtectedUserMessage(config, message)\n const priority =\n config.compress.mode === \"message\" && !isBlockedMessage\n ? compressionPriorities?.get(message.info.id)?.priority\n : undefined\n const tag = formatMessageIdTag(\n isBlockedMessage ? \"BLOCKED\" : messageRef,\n priority ? { priority } : undefined,\n )\n\n if (message.info.role === \"user\") {\n let injected = false\n for (const part of message.parts) {\n if (part.type === \"text\") {\n injected = appendToTextPart(part, tag) || injected\n }\n }\n\n if (injected) {\n continue\n }\n\n message.parts.push(createSyntheticTextPart(message, tag))\n continue\n }\n\n if (message.info.role !== \"assistant\") {\n continue\n }\n\n if (!hasContent(message)) {\n continue\n }\n\n if (appendToAllToolParts(message, tag)) {\n continue\n }\n\n if (appendToLastTextPart(message, tag)) {\n continue\n }\n\n const syntheticPart = createSyntheticTextPart(message, tag)\n const firstToolIndex = message.parts.findIndex((p) => p.type === \"tool\")\n if (firstToolIndex === -1) {\n message.parts.push(syntheticPart)\n } else {\n message.parts.splice(firstToolIndex, 0, syntheticPart)\n }\n }\n}\n","import type { Logger } from \"../../logger\"\nimport type { SessionState, WithParts } from \"../../state\"\nimport { filterMessages } from \"../shape\"\nimport {\n buildSubagentResultText,\n getSubAgentId,\n mergeSubagentResult,\n} from \"../../subagents/subagent-results\"\nimport { stripHallucinationsFromString } from \"../utils\"\n\nasync function fetchSubAgentMessages(client: any, sessionId: string): Promise<WithParts[]> {\n const response = await client.session.messages({\n path: { id: sessionId },\n })\n\n return filterMessages(response?.data || response)\n}\n\nexport const injectExtendedSubAgentResults = async (\n client: any,\n state: SessionState,\n logger: Logger,\n messages: WithParts[],\n allowSubAgents: boolean,\n): Promise<void> => {\n if (!allowSubAgents) {\n return\n }\n\n for (const message of messages) {\n const parts = Array.isArray(message.parts) ? message.parts : []\n\n for (const part of parts) {\n if (part.type !== \"tool\" || part.tool !== \"task\" || !part.callID) {\n continue\n }\n if (state.prune.tools.has(part.callID)) {\n continue\n }\n if (part.state?.status !== \"completed\" || typeof part.state.output !== \"string\") {\n continue\n }\n\n const cachedResult = state.subAgentResultCache.get(part.callID)\n if (cachedResult !== undefined) {\n if (cachedResult) {\n part.state.output = stripHallucinationsFromString(\n mergeSubagentResult(part.state.output, cachedResult),\n )\n }\n continue\n }\n\n const subAgentSessionId = getSubAgentId(part)\n if (!subAgentSessionId) {\n continue\n }\n\n let subAgentMessages: WithParts[] = []\n try {\n subAgentMessages = await fetchSubAgentMessages(client, subAgentSessionId)\n } catch (error) {\n logger.warn(\"Failed to fetch subagent session for output expansion\", {\n subAgentSessionId,\n callID: part.callID,\n error: error instanceof Error ? error.message : String(error),\n })\n continue\n }\n\n const subAgentResultText = buildSubagentResultText(subAgentMessages)\n if (!subAgentResultText) {\n continue\n }\n\n state.subAgentResultCache.set(part.callID, subAgentResultText)\n part.state.output = stripHallucinationsFromString(\n mergeSubagentResult(part.state.output, subAgentResultText),\n )\n }\n }\n}\n","import type { WithParts } from \"../state\"\nimport { getLastUserMessage } from \"./query\"\n\n/**\n * Mirrors opencode's differentModel handling by preserving part content while\n * dropping provider metadata on assistant parts that came from a different\n * model/provider than the current turn's user message.\n */\nexport function stripStaleMetadata(messages: WithParts[]): void {\n const lastUserMessage = getLastUserMessage(messages)\n if (lastUserMessage?.info.role !== \"user\") {\n return\n }\n\n const modelID = lastUserMessage.info.model.modelID\n const providerID = lastUserMessage.info.model.providerID\n\n messages.forEach((message) => {\n if (message.info.role !== \"assistant\") {\n return\n }\n\n // [FIX Bug 8] Guard against undefined modelID/providerID\n const msgModelID = (message.info as any).modelID\n const msgProviderID = (message.info as any).providerID\n if (msgModelID === modelID && msgProviderID === providerID) {\n return\n }\n\n message.parts = message.parts.map((part) => {\n if (part.type !== \"text\" && part.type !== \"tool\" && part.type !== \"reasoning\") {\n return part\n }\n\n if (!(\"metadata\" in part)) {\n return part\n }\n\n const { metadata: _metadata, ...rest } = part\n return rest\n })\n })\n}\n","import type { CompressionBlock, PruneMessagesState } from \"../state\"\n\nexport interface CompressionTarget {\n displayId: number\n runId: number\n topic: string\n compressedTokens: number\n durationMs: number\n grouped: boolean\n blocks: CompressionBlock[]\n}\n\nfunction byBlockId(a: CompressionBlock, b: CompressionBlock): number {\n return a.blockId - b.blockId\n}\n\nfunction buildTarget(blocks: CompressionBlock[]): CompressionTarget {\n const ordered = [...blocks].sort(byBlockId)\n const first = ordered[0]\n if (!first) {\n throw new Error(\"Cannot build compression target from empty block list.\")\n }\n\n const grouped = first.mode === \"message\"\n return {\n displayId: first.blockId,\n runId: first.runId,\n topic: grouped ? first.batchTopic || first.topic : first.topic,\n compressedTokens: ordered.reduce((total, block) => total + block.compressedTokens, 0),\n durationMs: ordered.reduce((total, block) => Math.max(total, block.durationMs), 0),\n grouped,\n blocks: ordered,\n }\n}\n\nfunction groupMessageBlocks(blocks: CompressionBlock[]): CompressionTarget[] {\n const grouped = new Map<number, CompressionBlock[]>()\n\n for (const block of blocks) {\n const existing = grouped.get(block.runId)\n if (existing) {\n existing.push(block)\n continue\n }\n grouped.set(block.runId, [block])\n }\n\n return Array.from(grouped.values()).map(buildTarget)\n}\n\nfunction splitTargets(blocks: CompressionBlock[]): CompressionTarget[] {\n const messageBlocks: CompressionBlock[] = []\n const singleBlocks: CompressionBlock[] = []\n\n for (const block of blocks) {\n if (block.mode === \"message\") {\n messageBlocks.push(block)\n } else {\n singleBlocks.push(block)\n }\n }\n\n const targets = [\n ...singleBlocks.map((block) => buildTarget([block])),\n ...groupMessageBlocks(messageBlocks),\n ]\n return targets.sort((a, b) => a.displayId - b.displayId)\n}\n\nexport function getActiveCompressionTargets(\n messagesState: PruneMessagesState,\n): CompressionTarget[] {\n const activeBlocks = Array.from(messagesState.activeBlockIds)\n .map((blockId) => messagesState.blocksById.get(blockId))\n .filter((block): block is CompressionBlock => !!block && block.active)\n\n return splitTargets(activeBlocks)\n}\n\nexport function getRecompressibleCompressionTargets(\n messagesState: PruneMessagesState,\n availableMessageIds: Set<string>,\n): CompressionTarget[] {\n const allBlocks = Array.from(messagesState.blocksById.values()).filter((block) => {\n return availableMessageIds.has(block.compressMessageId)\n })\n\n const messageGroups = new Map<number, CompressionBlock[]>()\n const singleTargets: CompressionTarget[] = []\n\n for (const block of allBlocks) {\n if (block.mode === \"message\") {\n const existing = messageGroups.get(block.runId)\n if (existing) {\n existing.push(block)\n } else {\n messageGroups.set(block.runId, [block])\n }\n continue\n }\n\n if (block.deactivatedByUser && !block.active) {\n singleTargets.push(buildTarget([block]))\n }\n }\n\n for (const blocks of messageGroups.values()) {\n if (blocks.some((block) => block.deactivatedByUser && !block.active)) {\n singleTargets.push(buildTarget(blocks))\n }\n }\n\n return singleTargets.sort((a, b) => a.displayId - b.displayId)\n}\n\nexport function resolveCompressionTarget(\n messagesState: PruneMessagesState,\n blockId: number,\n): CompressionTarget | null {\n const block = messagesState.blocksById.get(blockId)\n if (!block) {\n return null\n }\n\n if (block.mode !== \"message\") {\n return buildTarget([block])\n }\n\n const blocks = Array.from(messagesState.blocksById.values()).filter(\n (candidate) => candidate.mode === \"message\" && candidate.runId === block.runId,\n )\n if (blocks.length === 0) {\n return null\n }\n\n return buildTarget(blocks)\n}\n","import type { CompressionBlock, PruneMessagesState, WithParts } from \"../state\"\nimport { parseBlockRef } from \"../message-ids\"\nimport type { CompressionTarget } from \"../commands/compression-targets\"\n\nexport function parseBlockIdArg(arg: string): number | null {\n const normalized = arg.trim().toLowerCase()\n const blockRef = parseBlockRef(normalized)\n if (blockRef !== null) {\n return blockRef\n }\n\n if (!/^[1-9]\\d*$/.test(normalized)) {\n return null\n }\n\n const parsed = Number.parseInt(normalized, 10)\n return Number.isInteger(parsed) && parsed > 0 ? parsed : null\n}\n\nexport function findActiveParentBlockId(\n messagesState: PruneMessagesState,\n block: CompressionBlock,\n): number | null {\n const queue = [...block.parentBlockIds]\n const visited = new Set<number>()\n\n while (queue.length > 0) {\n const parentBlockId = queue.shift()\n if (parentBlockId === undefined || visited.has(parentBlockId)) {\n continue\n }\n visited.add(parentBlockId)\n\n const parent = messagesState.blocksById.get(parentBlockId)\n if (!parent) {\n continue\n }\n\n if (parent.active) {\n return parent.blockId\n }\n\n for (const ancestorId of parent.parentBlockIds) {\n if (!visited.has(ancestorId)) {\n queue.push(ancestorId)\n }\n }\n }\n\n return null\n}\n\nexport function findActiveAncestorBlockId(\n messagesState: PruneMessagesState,\n target: CompressionTarget,\n): number | null {\n for (const block of target.blocks) {\n const activeAncestorBlockId = findActiveParentBlockId(messagesState, block)\n if (activeAncestorBlockId !== null) {\n return activeAncestorBlockId\n }\n }\n\n return null\n}\n\nexport function snapshotActiveMessages(messagesState: PruneMessagesState): Map<string, number> {\n const activeMessages = new Map<string, number>()\n for (const [messageId, entry] of messagesState.byMessageId) {\n if (entry.activeBlockIds.length > 0) {\n activeMessages.set(messageId, entry.tokenCount)\n }\n }\n return activeMessages\n}\n\nexport function deactivateCompressionTarget(\n messagesState: PruneMessagesState,\n target: CompressionTarget,\n): void {\n const deactivatedAt = Date.now()\n\n for (const block of target.blocks) {\n block.active = false\n block.deactivatedByUser = true\n block.deactivatedAt = deactivatedAt\n block.deactivatedByBlockId = undefined\n\n // [FIX Bug 10] Mark consumed inner blocks so syncCompressionBlocks won't re-activate them\n for (const consumedId of block.consumedBlockIds) {\n const consumedBlock = messagesState.blocksById.get(consumedId)\n if (consumedBlock) {\n consumedBlock.deactivatedByUser = true\n }\n }\n }\n}\n\nexport interface RestoredMessagesResult {\n restoredMessageCount: number\n restoredTokens: number\n}\n\nexport function computeRestoredMessages(\n messagesState: PruneMessagesState,\n activeMessagesBefore: Map<string, number>,\n): RestoredMessagesResult {\n let restoredMessageCount = 0\n let restoredTokens = 0\n for (const [messageId, tokenCount] of activeMessagesBefore) {\n const entry = messagesState.byMessageId.get(messageId)\n const isActiveNow = entry ? entry.activeBlockIds.length > 0 : false\n if (!isActiveNow) {\n restoredMessageCount++\n restoredTokens += tokenCount\n }\n }\n return { restoredMessageCount, restoredTokens }\n}\n\nexport function computeReactivatedBlockIds(\n messagesState: PruneMessagesState,\n activeBlockIdsBefore: Set<number>,\n): number[] {\n return Array.from(messagesState.activeBlockIds)\n .filter((blockId) => !activeBlockIdsBefore.has(blockId))\n .sort((a, b) => a - b)\n}\n\nconst MAX_PREVIEW_LENGTH = 2000\nconst MAX_MESSAGE_PREVIEW_LENGTH = 200\n\nexport function buildRestoredContentPreview(\n messages: WithParts[],\n activeMessagesBefore: Map<string, number>,\n messagesState: PruneMessagesState,\n): string {\n const restoredMessages: WithParts[] = []\n for (const msg of messages) {\n const msgId = msg.info.id\n if (activeMessagesBefore.has(msgId)) {\n const entry = messagesState.byMessageId.get(msgId)\n const isActiveNow = entry ? entry.activeBlockIds.length > 0 : false\n if (!isActiveNow) {\n restoredMessages.push(msg)\n }\n }\n }\n\n if (restoredMessages.length === 0) {\n return \"\"\n }\n\n const lines: string[] = []\n let totalLength = 0\n\n for (const msg of restoredMessages) {\n if (totalLength >= MAX_PREVIEW_LENGTH) break\n\n const role = msg.info.role ?? \"unknown\"\n const textContent = extractTextContent(msg)\n const truncated =\n textContent.length > MAX_MESSAGE_PREVIEW_LENGTH\n ? textContent.slice(0, MAX_MESSAGE_PREVIEW_LENGTH) + \"...\"\n : textContent\n\n const line = `[${role}] ${truncated}`\n lines.push(line)\n totalLength += line.length + 1\n }\n\n return lines.join(\"\\n\")\n}\n\nfunction extractTextContent(msg: WithParts): string {\n if (!msg.parts || msg.parts.length === 0) {\n return \"\"\n }\n\n const textParts: string[] = []\n for (const part of msg.parts) {\n if (typeof part === \"object\" && part !== null) {\n if (\"text\" in part && typeof part.text === \"string\") {\n textParts.push(part.text)\n } else if (\"type\" in part && part.type === \"tool\") {\n const toolName = \"tool\" in part && typeof part.tool === \"string\" ? part.tool : \"tool\"\n const state = part.state as Record<string, unknown> | undefined\n if (state && typeof state.output === \"string\") {\n const output =\n state.output.length > 80\n ? state.output.slice(0, 80) + \"...\"\n : state.output\n textParts.push(`[${toolName}] ${output}`)\n }\n }\n }\n }\n\n return textParts.join(\" \").replace(/\\s+/g, \" \").trim()\n}\n","import { tool } from \"@opencode-ai/plugin\"\nimport type { ToolContext } from \"./types\"\nimport { ensureSessionInitialized } from \"../state\"\nimport { saveSessionState } from \"../state/persistence\"\nimport { assignMessageRefs } from \"../message-ids\"\nimport { fetchSessionMessages } from \"./search\"\nimport { formatBlockRef, parseBlockRef } from \"../message-ids\"\n\ninterface RunContext {\n ask(input: {\n permission: string\n patterns: string[]\n always: string[]\n metadata: Record<string, unknown>\n }): Promise<void>\n metadata(input: { title: string }): void\n sessionID: string\n}\n\nasync function prepareMarkSession(\n ctx: ToolContext,\n toolCtx: RunContext,\n): Promise<void> {\n await toolCtx.ask({\n permission: \"compress\",\n patterns: [\"*\"],\n always: [\"*\"],\n metadata: {},\n })\n\n toolCtx.metadata({ title: \"Mark block\" })\n\n const rawMessages = await fetchSessionMessages(ctx.client, toolCtx.sessionID)\n\n await ensureSessionInitialized(\n ctx.client,\n ctx.state,\n toolCtx.sessionID,\n ctx.logger,\n rawMessages,\n ctx.config.manualMode.enabled,\n )\n\n assignMessageRefs(ctx.state, rawMessages)\n}\n\nconst MARK_DESCRIPTION = `Marks a compressed block for batch merge-cleanup.\n\nUse this for blocks whose detailed content you no longer need, but whose summaries\nyou want to keep in context for now (to preserve prompt cache). Marked blocks stay\nfully active with zero immediate effect on context or cache. When context pressure\nrises, all marked blocks are merge-compressed together into a single summary in one\ncache break, instead of being handled one at a time.\n\nArgument: blockId — the block reference to mark (e.g., \"b1\", \"b3\")\n\nUse mark_block instead of compress when you want deferred cleanup: the block keeps\nserving cache hits now and gets consolidated later only if context gets tight.`\n\nconst UNMARK_DESCRIPTION = `Removes the batch cleanup mark from a compressed block.\n\nReverses mark_block. The block returns to normal handling and will not be\nauto-merged during batch cleanup.\n\nArgument: blockId — the block reference to unmark (e.g., \"b1\", \"b3\")`\n\nfunction buildSchema() {\n return {\n blockId: tool.schema\n .string()\n .describe('Block reference to mark (e.g., \"b1\", \"b3\")'),\n }\n}\n\nfunction buildUnmarkSchema() {\n return {\n blockId: tool.schema\n .string()\n .describe('Block reference to unmark (e.g., \"b1\", \"b3\")'),\n }\n}\n\nexport function createMarkBlockTool(ctx: ToolContext): ReturnType<typeof tool> {\n return tool({\n description: MARK_DESCRIPTION,\n args: buildSchema(),\n async execute(args, toolCtx) {\n await prepareMarkSession(ctx, toolCtx)\n\n const targetBlockId = parseBlockRef(String(args.blockId))\n if (targetBlockId === null) {\n return `Error: Invalid block ID \"${args.blockId}\". Use format \"b0\", \"b1\", etc.`\n }\n\n const messagesState = ctx.state.prune.messages\n const block = messagesState.blocksById.get(targetBlockId)\n if (!block) {\n return `Error: Block ${formatBlockRef(targetBlockId)} does not exist.`\n }\n\n if (!block.active) {\n return `Error: Block ${formatBlockRef(targetBlockId)} is not active.`\n }\n\n messagesState.markedForCleanup.add(targetBlockId)\n await saveSessionState(ctx.state, ctx.logger)\n\n const ref = formatBlockRef(targetBlockId)\n const markedCount = messagesState.markedForCleanup.size\n\n ctx.logger.info(\"mark_block: block marked for cleanup\", {\n blockId: targetBlockId,\n markedCount,\n })\n\n return `Block ${ref} marked for cleanup. It will be merge-compressed together with other marked blocks when context pressure rises. No immediate effect on context or cache. (${markedCount} block(s) currently marked.)`\n },\n })\n}\n\nexport function createUnmarkBlockTool(ctx: ToolContext): ReturnType<typeof tool> {\n return tool({\n description: UNMARK_DESCRIPTION,\n args: buildUnmarkSchema(),\n async execute(args, toolCtx) {\n await prepareMarkSession(ctx, toolCtx)\n\n const targetBlockId = parseBlockRef(String(args.blockId))\n if (targetBlockId === null) {\n return `Error: Invalid block ID \"${args.blockId}\". Use format \"b0\", \"b1\", etc.`\n }\n\n const messagesState = ctx.state.prune.messages\n if (!messagesState.markedForCleanup.has(targetBlockId)) {\n return `Block ${formatBlockRef(targetBlockId)} was not marked for cleanup.`\n }\n\n messagesState.markedForCleanup.delete(targetBlockId)\n await saveSessionState(ctx.state, ctx.logger)\n\n ctx.logger.info(\"unmark_block: block unmarked\", {\n blockId: targetBlockId,\n })\n\n return `Block ${formatBlockRef(targetBlockId)} unmarked. It will no longer be auto-merged during batch cleanup.`\n },\n })\n}\n","import { writeFile, mkdir } from \"fs/promises\"\nimport { join } from \"path\"\nimport { existsSync } from \"fs\"\nimport { homedir } from \"os\"\n\nexport class Logger {\n private logDir: string\n public enabled: boolean\n\n constructor(enabled: boolean) {\n this.enabled = enabled\n const configHome = process.env.XDG_CONFIG_HOME || join(homedir(), \".config\")\n this.logDir = join(configHome, \"opencode\", \"logs\", \"acp\")\n }\n\n private async ensureLogDir() {\n if (!existsSync(this.logDir)) {\n await mkdir(this.logDir, { recursive: true })\n }\n }\n\n private formatData(data?: any): string {\n if (!data) return \"\"\n\n const parts: string[] = []\n for (const [key, value] of Object.entries(data)) {\n if (value === undefined || value === null) continue\n\n // Format arrays compactly\n if (Array.isArray(value)) {\n if (value.length === 0) continue\n parts.push(\n `${key}=[${value.slice(0, 3).join(\",\")}${value.length > 3 ? `...+${value.length - 3}` : \"\"}]`,\n )\n } else if (typeof value === \"object\") {\n const str = JSON.stringify(value)\n if (str.length < 50) {\n parts.push(`${key}=${str}`)\n }\n } else {\n parts.push(`${key}=${value}`)\n }\n }\n return parts.join(\" \")\n }\n\n private getCallerFile(skipFrames: number = 3): string {\n const originalPrepareStackTrace = Error.prepareStackTrace\n try {\n const err = new Error()\n Error.prepareStackTrace = (_, stack) => stack\n const stack = err.stack as unknown as NodeJS.CallSite[]\n Error.prepareStackTrace = originalPrepareStackTrace\n\n // Skip specified number of frames to get to actual caller\n for (let i = skipFrames; i < stack.length; i++) {\n const filename = stack[i]?.getFileName()\n if (filename && !filename.includes(\"/logger.\")) {\n // Extract just the filename without path and extension\n const match = filename.match(/([^/\\\\]+)\\.[tj]s$/)\n return match ? match[1] : filename\n }\n }\n return \"unknown\"\n } catch {\n return \"unknown\"\n }\n }\n\n private async write(level: string, component: string, message: string, data?: any) {\n if (!this.enabled) return\n\n try {\n await this.ensureLogDir()\n\n const timestamp = new Date().toISOString()\n const dataStr = this.formatData(data)\n\n const logLine = `${timestamp} ${level.padEnd(5)} ${component}: ${message}${dataStr ? \" | \" + dataStr : \"\"}\\n`\n\n const dailyLogDir = join(this.logDir, \"daily\")\n if (!existsSync(dailyLogDir)) {\n await mkdir(dailyLogDir, { recursive: true })\n }\n\n const logFile = join(dailyLogDir, `${new Date().toISOString().split(\"T\")[0]}.log`)\n await writeFile(logFile, logLine, { flag: \"a\" })\n } catch (error) {}\n }\n\n info(message: string, data?: any) {\n if (!this.enabled) return\n const component = this.getCallerFile(2)\n return this.write(\"INFO\", component, message, data)\n }\n\n debug(message: string, data?: any) {\n if (!this.enabled) return\n const component = this.getCallerFile(2)\n return this.write(\"DEBUG\", component, message, data)\n }\n\n warn(message: string, data?: any) {\n if (!this.enabled) return\n const component = this.getCallerFile(2)\n return this.write(\"WARN\", component, message, data)\n }\n\n error(message: string, data?: any) {\n if (!this.enabled) return\n const component = this.getCallerFile(2)\n return this.write(\"ERROR\", component, message, data)\n }\n\n /**\n * Strips unnecessary metadata from messages for cleaner debug logs.\n *\n * Removed:\n * - All IDs (id, sessionID, messageID, parentID)\n * - summary, path, cost, model, agent, mode, finish, providerID, modelID\n * - step-start and step-finish parts entirely\n * - snapshot fields\n * - ignored text parts\n *\n * Kept:\n * - role, time (created only), tokens (input, output, reasoning, cache)\n * - text, reasoning, tool parts with content\n * - tool calls with: tool, callID, input, output, metadata\n */\n private minimizeForDebug(messages: any[]): any[] {\n return messages.map((msg) => {\n const minimized: any = {\n role: msg.info?.role,\n }\n\n if (msg.info?.time?.created) {\n minimized.time = msg.info.time.created\n }\n\n if (msg.info?.tokens) {\n minimized.tokens = {\n input: msg.info.tokens.input,\n output: msg.info.tokens.output,\n reasoning: msg.info.tokens.reasoning,\n cache: msg.info.tokens.cache,\n }\n }\n\n if (msg.parts) {\n minimized.parts = msg.parts\n .map((part: any) => {\n if (part.type === \"step-start\" || part.type === \"step-finish\") {\n return null\n }\n\n if (part.type === \"text\") {\n if (part.ignored) return null\n const textPart: any = { type: \"text\", text: part.text }\n if (part.metadata) textPart.metadata = part.metadata\n return textPart\n }\n\n if (part.type === \"reasoning\") {\n const reasoningPart: any = { type: \"reasoning\", text: part.text }\n if (part.metadata) reasoningPart.metadata = part.metadata\n return reasoningPart\n }\n\n if (part.type === \"tool\") {\n const toolPart: any = {\n type: \"tool\",\n tool: part.tool,\n callID: part.callID,\n }\n\n if (part.state?.status) {\n toolPart.status = part.state.status\n }\n if (part.state?.input) {\n toolPart.input = part.state.input\n }\n if (part.state?.output) {\n toolPart.output = part.state.output\n }\n if (part.state?.error) {\n toolPart.error = part.state.error\n }\n if (part.metadata) {\n toolPart.metadata = part.metadata\n }\n if (part.state?.metadata) {\n toolPart.metadata = {\n ...(toolPart.metadata || {}),\n ...part.state.metadata,\n }\n }\n if (part.state?.title) {\n toolPart.title = part.state.title\n }\n\n return toolPart\n }\n\n return null\n })\n .filter(Boolean)\n }\n\n return minimized\n })\n }\n\n async saveContext(sessionId: string, messages: any[]) {\n if (!this.enabled) return\n\n try {\n const contextDir = join(this.logDir, \"context\", sessionId)\n if (!existsSync(contextDir)) {\n await mkdir(contextDir, { recursive: true })\n }\n\n const minimized = this.minimizeForDebug(messages).filter(\n (msg) => msg.parts && msg.parts.length > 0,\n )\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\")\n const contextFile = join(contextDir, `${timestamp}.json`)\n await writeFile(contextFile, JSON.stringify(minimized, null, 2))\n } catch (error) {}\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync, statSync, cpSync } from \"fs\"\nimport { join, dirname } from \"path\"\nimport { homedir } from \"os\"\nimport type { Logger } from \"../logger\"\nimport { SYSTEM as SYSTEM_PROMPT } from \"./system\"\nimport { COMPRESS_RANGE as COMPRESS_RANGE_PROMPT } from \"./compress-range\"\nimport { COMPRESS_MESSAGE as COMPRESS_MESSAGE_PROMPT } from \"./compress-message\"\nimport { CONTEXT_LIMIT_NUDGE } from \"./context-limit-nudge\"\nimport { TURN_NUDGE } from \"./turn-nudge\"\nimport { ITERATION_NUDGE } from \"./iteration-nudge\"\nimport { MANUAL_MODE_SYSTEM_EXTENSION, SUBAGENT_SYSTEM_EXTENSION, DECOMPRESS_SYSTEM_EXTENSION } from \"./extensions/system\"\n\nexport type PromptKey =\n | \"system\"\n | \"compress-range\"\n | \"compress-message\"\n | \"context-limit-nudge\"\n | \"turn-nudge\"\n | \"iteration-nudge\"\n\ntype EditablePromptField =\n | \"system\"\n | \"compressRange\"\n | \"compressMessage\"\n | \"contextLimitNudge\"\n | \"turnNudge\"\n | \"iterationNudge\"\n\ninterface PromptDefinition {\n key: PromptKey\n fileName: string\n label: string\n description: string\n usage: string\n runtimeField: EditablePromptField\n}\n\ninterface PromptOverrideCandidate {\n path: string\n}\n\ninterface PromptPaths {\n defaultsDir: string\n globalOverridesDir: string\n configDirOverridesDir: string | null\n projectOverridesDir: string | null\n}\n\nexport interface RuntimePrompts {\n system: string\n compressRange: string\n compressMessage: string\n contextLimitNudge: string\n turnNudge: string\n iterationNudge: string\n manualExtension: string\n subagentExtension: string\n decompressExtension: string\n}\n\nconst PROMPT_DEFINITIONS: PromptDefinition[] = [\n {\n key: \"system\",\n fileName: \"system.md\",\n label: \"System\",\n description: \"Core system-level ACP instruction block\",\n usage: \"Injected into the model system prompt on every request\",\n runtimeField: \"system\",\n },\n {\n key: \"compress-range\",\n fileName: \"compress-range.md\",\n label: \"Compress Range\",\n description: \"range-mode compress tool instructions and summary constraints\",\n usage: \"Registered as the range-mode compress tool description\",\n runtimeField: \"compressRange\",\n },\n {\n key: \"compress-message\",\n fileName: \"compress-message.md\",\n label: \"Compress Message\",\n description: \"message-mode compress tool instructions and summary constraints\",\n usage: \"Registered as the message-mode compress tool description\",\n runtimeField: \"compressMessage\",\n },\n {\n key: \"context-limit-nudge\",\n fileName: \"context-limit-nudge.md\",\n label: \"Context Limit Nudge\",\n description: \"High-priority nudge when context is over max threshold\",\n usage: \"Injected when context usage is beyond configured max limits\",\n runtimeField: \"contextLimitNudge\",\n },\n {\n key: \"turn-nudge\",\n fileName: \"turn-nudge.md\",\n label: \"Turn Nudge\",\n description: \"Nudge to compress closed ranges at turn boundaries\",\n usage: \"Injected when context is between min and max limits at a new user turn\",\n runtimeField: \"turnNudge\",\n },\n {\n key: \"iteration-nudge\",\n fileName: \"iteration-nudge.md\",\n label: \"Iteration Nudge\",\n description: \"Nudge after many iterations without user input\",\n usage: \"Injected when iteration threshold is crossed\",\n runtimeField: \"iterationNudge\",\n },\n]\n\nexport const PROMPT_KEYS: PromptKey[] = [\n \"system\",\n \"compress-range\",\n \"compress-message\",\n \"context-limit-nudge\",\n \"turn-nudge\",\n \"iteration-nudge\",\n]\n\nconst HTML_COMMENT_REGEX = /<!--[\\s\\S]*?-->/g\nconst LEGACY_INLINE_COMMENT_LINE_REGEX = /^[ \\t]*\\/\\/.*?\\/\\/[ \\t]*$/gm\nconst DCP_SYSTEM_REMINDER_TAG_REGEX =\n /^\\s*<dcp-system-reminder\\b[^>]*>[\\s\\S]*<\\/dcp-system-reminder>\\s*$/i\nconst DEFAULTS_README_FILE = \"README.md\"\n\nconst BUNDLED_EDITABLE_PROMPTS: Record<EditablePromptField, string> = {\n system: SYSTEM_PROMPT,\n compressRange: COMPRESS_RANGE_PROMPT,\n compressMessage: COMPRESS_MESSAGE_PROMPT,\n contextLimitNudge: CONTEXT_LIMIT_NUDGE,\n turnNudge: TURN_NUDGE,\n iterationNudge: ITERATION_NUDGE,\n}\n\nconst INTERNAL_PROMPT_EXTENSIONS = {\n manualExtension: MANUAL_MODE_SYSTEM_EXTENSION,\n subagentExtension: SUBAGENT_SYSTEM_EXTENSION,\n decompressExtension: DECOMPRESS_SYSTEM_EXTENSION,\n}\n\nfunction createBundledRuntimePrompts(): RuntimePrompts {\n return {\n system: BUNDLED_EDITABLE_PROMPTS.system,\n compressRange: BUNDLED_EDITABLE_PROMPTS.compressRange,\n compressMessage: BUNDLED_EDITABLE_PROMPTS.compressMessage,\n contextLimitNudge: BUNDLED_EDITABLE_PROMPTS.contextLimitNudge,\n turnNudge: BUNDLED_EDITABLE_PROMPTS.turnNudge,\n iterationNudge: BUNDLED_EDITABLE_PROMPTS.iterationNudge,\n manualExtension: INTERNAL_PROMPT_EXTENSIONS.manualExtension,\n subagentExtension: INTERNAL_PROMPT_EXTENSIONS.subagentExtension,\n decompressExtension: INTERNAL_PROMPT_EXTENSIONS.decompressExtension,\n }\n}\n\nfunction findOpencodeDir(startDir: string): string | null {\n let current = startDir\n while (current !== \"/\") {\n const candidate = join(current, \".opencode\")\n if (existsSync(candidate)) {\n try {\n if (statSync(candidate).isDirectory()) {\n return candidate\n }\n } catch {\n // ignore inaccessible entries while walking upward\n }\n }\n const parent = dirname(current)\n if (parent === current) {\n break\n }\n current = parent\n }\n return null\n}\n\nfunction resolvePromptPaths(workingDirectory: string): PromptPaths {\n const configHome = process.env.XDG_CONFIG_HOME || join(homedir(), \".config\")\n const globalRoot = join(configHome, \"opencode\", \"acp-prompts\")\n const legacyGlobalRoot = join(configHome, \"opencode\", \"dcp-prompts\")\n\n if (!existsSync(globalRoot) && existsSync(legacyGlobalRoot)) {\n try {\n cpSync(legacyGlobalRoot, globalRoot, { recursive: true })\n console.log(\"[ACP] Migrated prompts from dcp-prompts to acp-prompts\")\n } catch (e: any) {\n console.warn(`[ACP] Prompts migration failed: ${e.message}`)\n }\n }\n\n const defaultsDir = join(globalRoot, \"defaults\")\n const globalOverridesDir = join(globalRoot, \"overrides\")\n\n const configDirOverridesDir = process.env.OPENCODE_CONFIG_DIR\n ? join(process.env.OPENCODE_CONFIG_DIR, \"acp-prompts\", \"overrides\")\n : null\n\n const opencodeDir = findOpencodeDir(workingDirectory)\n const projectOverridesDir = opencodeDir ? join(opencodeDir, \"acp-prompts\", \"overrides\") : null\n\n return {\n defaultsDir,\n globalOverridesDir,\n configDirOverridesDir,\n projectOverridesDir,\n }\n}\n\nfunction stripConditionalTag(content: string, tagName: string): string {\n const regex = new RegExp(`<${tagName}>[\\\\s\\\\S]*?<\\/${tagName}>`, \"gi\")\n return content.replace(regex, \"\")\n}\n\nfunction unwrapDcpTagIfWrapped(content: string): string {\n const trimmed = content.trim()\n\n if (DCP_SYSTEM_REMINDER_TAG_REGEX.test(trimmed)) {\n return trimmed\n .replace(/^\\s*<dcp-system-reminder\\b[^>]*>\\s*/i, \"\")\n .replace(/\\s*<\\/dcp-system-reminder>\\s*$/i, \"\")\n .trim()\n }\n\n return trimmed\n}\n\nfunction normalizeReminderPromptContent(content: string): string {\n const normalized = content.trim()\n\n if (!normalized) {\n return \"\"\n }\n\n const startsWrapped = /^\\s*<dcp-system-reminder\\b[^>]*>/i.test(normalized)\n const endsWrapped = /<\\/dcp-system-reminder>\\s*$/i.test(normalized)\n\n if (startsWrapped !== endsWrapped) {\n return \"\"\n }\n\n return unwrapDcpTagIfWrapped(normalized)\n}\n\nfunction stripPromptComments(content: string): string {\n return content\n .replace(/^\\uFEFF/, \"\")\n .replace(/\\r\\n?/g, \"\\n\")\n .replace(HTML_COMMENT_REGEX, \"\")\n .replace(LEGACY_INLINE_COMMENT_LINE_REGEX, \"\")\n}\n\nfunction toEditablePromptText(definition: PromptDefinition, rawContent: string): string {\n let normalized = stripPromptComments(rawContent).trim()\n if (!normalized) {\n return \"\"\n }\n\n if (definition.key === \"system\") {\n normalized = stripConditionalTag(normalized, \"manual\")\n normalized = stripConditionalTag(normalized, \"subagent\")\n }\n\n if (definition.key !== \"compress-range\" && definition.key !== \"compress-message\") {\n normalized = normalizeReminderPromptContent(normalized)\n }\n\n return normalized.trim()\n}\n\nfunction wrapRuntimePromptContent(definition: PromptDefinition, editableText: string): string {\n const trimmed = editableText.trim()\n if (!trimmed) {\n return \"\"\n }\n\n if (definition.key === \"compress-range\" || definition.key === \"compress-message\") {\n return trimmed\n }\n\n return `<dcp-system-reminder>\\n${trimmed}\\n</dcp-system-reminder>`\n}\n\nfunction buildDefaultPromptFileContent(bundledEditableText: string): string {\n return `${bundledEditableText.trim()}\\n`\n}\n\nfunction buildDefaultsReadmeContent(): string {\n const lines: string[] = []\n lines.push(\"# ACP Prompt Defaults\")\n lines.push(\"\")\n lines.push(\"This directory stores the ACP prompts.\")\n lines.push(\"Each prompt file here should contain plain text only (no XML wrappers).\")\n lines.push(\"\")\n lines.push(\"## Creating Overrides\")\n lines.push(\"\")\n lines.push(\n \"1. Copy a prompt file from this directory into an overrides directory using the same filename.\",\n )\n lines.push(\"2. Edit the copied file using plain text.\")\n lines.push(\"3. Restart OpenCode.\")\n lines.push(\"\")\n lines.push(\"To reset an override, delete the matching file from your overrides directory.\")\n lines.push(\"\")\n lines.push(\n \"Do not edit the default prompt files directly, they are just for reference, only files in the overrides directory are used.\",\n )\n lines.push(\"\")\n lines.push(\"Override precedence (highest first):\")\n lines.push(\"1. `.opencode/acp-prompts/overrides/` (project)\")\n lines.push(\"2. `$OPENCODE_CONFIG_DIR/acp-prompts/overrides/` (config dir)\")\n lines.push(\"3. `~/.config/opencode/acp-prompts/overrides/` (global)\")\n lines.push(\"\")\n lines.push(\"## Prompt Files\")\n lines.push(\"\")\n\n for (const definition of PROMPT_DEFINITIONS) {\n lines.push(`- \\`${definition.fileName}\\``)\n lines.push(` - Purpose: ${definition.description}.`)\n lines.push(` - Runtime use: ${definition.usage}.`)\n }\n\n return `${lines.join(\"\\n\")}\\n`\n}\n\nfunction readFileIfExists(filePath: string): string | null {\n if (!existsSync(filePath)) {\n return null\n }\n\n try {\n return readFileSync(filePath, \"utf-8\")\n } catch {\n return null\n }\n}\n\nexport class PromptStore {\n private readonly logger: Logger\n private readonly paths: PromptPaths\n private readonly customPromptsEnabled: boolean\n private runtimePrompts: RuntimePrompts\n\n constructor(logger: Logger, workingDirectory: string, customPromptsEnabled = false) {\n this.logger = logger\n this.paths = resolvePromptPaths(workingDirectory)\n this.customPromptsEnabled = customPromptsEnabled\n this.runtimePrompts = createBundledRuntimePrompts()\n\n if (this.customPromptsEnabled) {\n this.ensureDefaultFiles()\n }\n this.reload()\n }\n\n getRuntimePrompts(): RuntimePrompts {\n return { ...this.runtimePrompts }\n }\n\n reload(): void {\n const nextPrompts = createBundledRuntimePrompts()\n\n if (!this.customPromptsEnabled) {\n this.runtimePrompts = nextPrompts\n return\n }\n\n for (const definition of PROMPT_DEFINITIONS) {\n const bundledSource = BUNDLED_EDITABLE_PROMPTS[definition.runtimeField]\n const bundledEditable = toEditablePromptText(definition, bundledSource)\n const bundledRuntime = wrapRuntimePromptContent(definition, bundledEditable)\n const fallbackValue = bundledRuntime || bundledSource.trim()\n let effectiveValue = fallbackValue\n\n for (const candidate of this.getOverrideCandidates(definition.fileName)) {\n const rawOverride = readFileIfExists(candidate.path)\n if (rawOverride === null) {\n continue\n }\n\n const editableOverride = toEditablePromptText(definition, rawOverride)\n if (!editableOverride) {\n this.logger.warn(\"Prompt override is empty or invalid after normalization\", {\n key: definition.key,\n path: candidate.path,\n })\n continue\n }\n\n const wrappedOverride = wrapRuntimePromptContent(definition, editableOverride)\n if (!wrappedOverride) {\n this.logger.warn(\"Prompt override could not be wrapped for runtime\", {\n key: definition.key,\n path: candidate.path,\n })\n continue\n }\n\n effectiveValue = wrappedOverride\n break\n }\n\n nextPrompts[definition.runtimeField] = effectiveValue\n }\n\n this.runtimePrompts = nextPrompts\n }\n\n private getOverrideCandidates(fileName: string): PromptOverrideCandidate[] {\n const candidates: PromptOverrideCandidate[] = []\n\n if (this.paths.projectOverridesDir) {\n candidates.push({\n path: join(this.paths.projectOverridesDir, fileName),\n })\n }\n\n if (this.paths.configDirOverridesDir) {\n candidates.push({\n path: join(this.paths.configDirOverridesDir, fileName),\n })\n }\n\n candidates.push({\n path: join(this.paths.globalOverridesDir, fileName),\n })\n\n return candidates\n }\n\n private ensureDefaultFiles(): void {\n try {\n mkdirSync(this.paths.defaultsDir, { recursive: true })\n mkdirSync(this.paths.globalOverridesDir, { recursive: true })\n } catch {\n this.logger.warn(\"Failed to initialize prompt directories\", {\n defaultsDir: this.paths.defaultsDir,\n globalOverridesDir: this.paths.globalOverridesDir,\n })\n return\n }\n\n for (const definition of PROMPT_DEFINITIONS) {\n const bundledEditable = toEditablePromptText(\n definition,\n BUNDLED_EDITABLE_PROMPTS[definition.runtimeField],\n )\n const managedContent = buildDefaultPromptFileContent(\n bundledEditable || BUNDLED_EDITABLE_PROMPTS[definition.runtimeField],\n )\n const filePath = join(this.paths.defaultsDir, definition.fileName)\n\n try {\n const existing = readFileIfExists(filePath)\n if (existing === managedContent) {\n continue\n }\n writeFileSync(filePath, managedContent, \"utf-8\")\n } catch {\n this.logger.warn(\"Failed to write default prompt file\", {\n key: definition.key,\n path: filePath,\n })\n }\n }\n\n const readmePath = join(this.paths.defaultsDir, DEFAULTS_README_FILE)\n const readmeContent = buildDefaultsReadmeContent()\n\n try {\n const existing = readFileIfExists(readmePath)\n if (existing !== readmeContent) {\n writeFileSync(readmePath, readmeContent, \"utf-8\")\n }\n } catch {\n this.logger.warn(\"Failed to write defaults README\", {\n path: readmePath,\n })\n }\n }\n}\n","export const SYSTEM = `\n\nYou operate in a context-constrained environment. Context management helps preserve retrieval quality, but your primary goal is completing the task at hand. Do not let context management distract from the actual work.\n\nThe tools you have for context management are \\`compress\\`, \\`decompress\\`, \\`mark_block\\`, and \\`unmark_block\\`. \\`compress\\` replaces older conversation content with technical summaries you produce. \\`decompress\\` restores previously compressed content when you need exact details. \\`mark_block\\` flags a compressed block for deferred batch merge-cleanup — it has zero immediate effect on context or cache, but marked blocks are merge-compressed together in a single cache break when context pressure rises. Use it for blocks you no longer need in detail but want to keep cached for now. \\`unmark_block\\` removes that flag.\n\n\\`<dcp-message-id>\\` and \\`<dcp-system-reminder>\\` tags are environment-injected metadata. Do not output them.\n\nCOMPRESSION PHILOSOPHY\n\nCompression replaces raw conversation content with dense summaries. When used correctly, it keeps your context sharp and focused. When used carelessly, it destroys information you need.\n\nThe key principle: compress based on context pressure, not habit. When context is ample, compress rarely or not at all. When context is tight, compress aggressively but selectively. The runtime context usage indicator tells you the current pressure level.\n\nTarget the largest UNCOMPRESSED content first. Savings scale with original size — compressing a 5000-token tool output frees far more than re-shrinking an already-summarized 300-token block.\n\nCONTEXT PRESSURE LEVELS\n\n- Ample: Context is well below the threshold. Do NOT compress unless there is obvious waste (huge terminal dumps, duplicated content). Focus entirely on your task.\n- Moderate: Context is approaching the threshold. Compress completed sections proactively. Prioritize high-token waste over minor cleanup.\n- High: Context has exceeded the threshold. Compress aggressively. Every compression should free meaningful tokens. Preserve only what is essential for the current task.\n\nWHAT TO COMPRESS FIRST (high value, low risk)\n\n- Agent/subagent review and consultation results: Prime compression targets when context pressure rises — the surrounding reasoning and tool-call chatter is typically the largest block of uncompressed content. Note: if the agent tool is in your protected list, its output is auto-preserved in the summary, so the savings come from the surrounding conversation, not the agent output itself. Compress once you have fully consumed the results (all recommended actions applied or recorded in files). Recover via \\`decompress\\` while the block is still active. Re-invoking the agent is a last resort — it is a fresh run, not a cache hit.\n- Verbose command output (build/test runs, git diff/log/status, publish logs, directory listings): Once you have read the result, compress. Keep only the verdict — pass/fail status, commit hash, version number, or count. For failures, keep the specific error messages and file/line references needed to act on them. The full output is reproducible by re-running the command.\n- Exploration that led nowhere (failed approaches, dead-end searches): Compress to a one-line note about what was tried and why it failed.\n- Redundant tool results (reading the same file multiple times, repeated status checks, exhausted search results): Keep only the most recent result.\n- Intermediate steps of completed multi-step tasks: Once the task is done, compress the process. Keep only the final outcome.\n- Resolved discussion threads (clarification rounds, negotiated requirements, design debate that reached a decision): Once a conclusion is recorded, compress the back-and-forth. Keep the decision and its rationale.\n- Large file contents that have already been used and are no longer needed: Compress to a summary of key functions, types, or patterns.\n\nDO NOT RE-COMPRESS (low value, diminishing returns)\n\n- Already-compressed block summaries: Re-compressing a summary into a shorter summary saves negligible tokens. If a block needs better detail, use \\`decompress\\` to restore it, then compress the original content properly. Exception: if a block-aging warning flags specific block IDs as facing GC truncation, re-summarize exactly those flagged blocks into a fresh range — this preserves detail that GC would otherwise destroy.\n- Short messages (1-3 sentences): The compression overhead (block metadata, summary structure) may exceed the tokens saved.\n- Content whose immediate use is complete — the task it supported is done and no open todo/plan references it. If still in active use, let it stay.\n- User instructions and requirements: These must remain visible until the task is complete.\n- Tool calls that are still pending or in-progress: Wait until the result is returned and consumed.\n\nWHAT TO COMPRESS CAREFULLY (high risk - verify before compressing)\n\n- Temporary secrets/keys/tokens needed later: Do NOT compress unless recorded elsewhere\n- File paths and directory structures: Keep in summary - losing these wastes tokens rediscovering them\n- Key function/method signatures and APIs: Summarize with exact names and signatures\n- Critical error messages and stack traces: Keep the error type and key detail in summary\n- User preferences and requirements: These must survive compression intact\n- Architectural decisions and rationale: Summarize the decision, not just the conclusion\n\nBEFORE COMPRESSING IMPORTANT CONTENT\n\nVerify the information is persisted in one of:\n- A file you have written or edited\n- An issue, PR, or devlog entry\n- The compression summary itself (include the critical bits explicitly)\n\nIf it is not persisted anywhere, either persist it first or include it explicitly in your compression summary.\n\nAFTER COMPRESSING\n\nGenerate recovery breadcrumbs in your summary so future-you can reconstruct the context:\n- Reference specific files by path\n- Include key variable names, function signatures, or configuration values\n- Note what was decided and why, not just what was done\n- Example: \"Implemented auth check in src/middleware.ts using validateToken() from auth.ts - user table is users not user\"\n\nIf you later realize you need the original details from a compressed block, use \\`decompress\\` to restore them. You can decompress, read the content, then re-compress if needed.\n\nUse \\`compress\\` and \\`decompress\\` deliberately with quality-first summaries. Prioritize stale content intelligently to maintain a high-signal context window.\n`\n","export const COMPRESS_RANGE = `Collapse a range in the conversation into a detailed summary.\n\nTHE SUMMARY\nYour summary must be EXHAUSTIVE. Capture file paths, function signatures, decisions made, constraints discovered, key findings... EVERYTHING that maintains context integrity. This is not a brief note - it is an authoritative record so faithful that the original conversation adds no value.\n\nUSER INTENT FIDELITY\nWhen the compressed range includes user messages, preserve the user's intent with extra care. Do not change scope, constraints, priorities, acceptance criteria, or requested outcomes.\nDirectly quote user messages when they are short enough to include safely. Direct quotes are preferred when they best preserve exact meaning.\n\nYet be LEAN. Strip away the noise: failed attempts that led nowhere, verbose tool outputs, back-and-forth exploration. What remains should be pure signal - golden nuggets of detail that preserve full understanding with zero ambiguity.\n\nCOMPRESSED BLOCK PLACEHOLDERS\nWhen the selected range includes previously compressed blocks, use this exact placeholder format when referencing one:\n\n- \\`(bN)\\`\n\nCompressed block sections in context are clearly marked with a header:\n\n- \\`[Compressed conversation section]\\`\n\nCompressed block IDs always use the \\`bN\\` form (never \\`mNNNNN\\`) and are represented in the same XML metadata tag format.\n\nRules:\n\n- Include every required block placeholder exactly once.\n- Do not invent placeholders for blocks outside the selected range.\n- Treat \\`(bN)\\` placeholders as RESERVED TOKENS. Do not emit \\`(bN)\\` text anywhere except intentional placeholders.\n- If you need to mention a block in prose, use plain text like \\`compressed bN\\` (not as a placeholder).\n- Preflight check before finalizing: the set of \\`(bN)\\` placeholders in your summary must exactly match the required set, with no duplicates.\n\nThese placeholders are semantic references. They will be replaced with the full stored compressed block content when the tool processes your output.\n\nFLOW PRESERVATION WITH PLACEHOLDERS\nWhen you use compressed block placeholders, write the surrounding summary text so it still reads correctly AFTER placeholder expansion.\n\n- Treat each placeholder as a stand-in for a full conversation segment, not as a short label.\n- Ensure transitions before and after each placeholder preserve chronology and causality.\n- Do not write text that depends on the placeholder staying literal (for example, \"as noted in \\`(b2)\\`\").\n- Your final meaning must be coherent once each placeholder is replaced with its full compressed block content.\n\nBOUNDARY IDS\nYou specify boundaries by ID using the injected IDs visible in the conversation:\n\n- \\`mNNNNN\\` IDs identify raw messages\n- \\`bN\\` IDs identify previously compressed blocks\n\nEach message has an ID inside XML metadata tags like \\`<dcp-message-id>...</dcp-message-id>\\`.\nThe same ID tag appears in every tool output of the message it belongs to — each unique ID identifies one complete message.\nTreat these tags as boundary metadata only, not as tool result content.\n\nRules:\n\n- Pick \\`startId\\` and \\`endId\\` directly from injected IDs in context.\n- IDs must exist in the current visible context. If you cannot see an ID in the messages above, it is stale and will fail.\n- \\`startId\\` must appear before \\`endId\\`.\n- Do not invent IDs. Use only IDs that are present in context.\n- NEVER use IDs from compressed block summaries, previous nudges, or your own memory — only IDs currently visible as XML metadata tags in the conversation.\n\nBATCHING\nWhen multiple independent ranges are ready and their boundaries do not overlap, include all of them as separate entries in the \\`content\\` array of a single tool call. Each entry should have its own \\`startId\\`, \\`endId\\`, and \\`summary\\`.\n`\n","export const COMPRESS_MESSAGE = `Collapse selected individual messages in the conversation into detailed summaries.\n\nTHE SUMMARY\nYour summary must be EXHAUSTIVE. Capture file paths, function signatures, decisions made, constraints discovered, key findings, tool outcomes, and user intent details that matter... EVERYTHING that preserves the value of the selected message after the raw message is removed.\n\nUSER INTENT FIDELITY\nWhen a selected message contains user intent, preserve that intent with extra care. Do not change scope, constraints, priorities, acceptance criteria, or requested outcomes.\nDirectly quote short user instructions when that best preserves exact meaning.\n\nYet be LEAN. Strip away the noise: failed attempts that led nowhere, verbose tool output, and repetition. What remains should be pure signal - golden nuggets of detail that preserve full understanding with zero ambiguity.\nIf a message contains no significant technical decisions, code changes, or user requirements, produce a minimal one-line summary rather than a detailed one.\n\nMESSAGE IDS\nYou specify individual raw messages by ID using the injected IDs visible in the conversation:\n\n- \\`mNNNNN\\` IDs identify raw messages\n\nEach message has an ID inside XML metadata tags like \\`<dcp-message-id priority=\"high\">m0007</dcp-message-id>\\`.\nThe same ID tag appears in every tool output of the message it belongs to — each unique ID identifies one complete message.\nTreat these tags as message metadata only, not as content to summarize. Use only the inner \\`mNNNNN\\` value as the \\`messageId\\`.\nThe \\`priority\\` attribute indicates relative context cost. You MUST compress high-priority messages when their full text is no longer necessary for the active task.\nIf prior compress-tool results are present, always compress and summarize them minimally only as part of a broader compression pass. Do not invoke the compress tool solely to re-compress an earlier compression result.\nMessages marked as \\`<dcp-message-id>BLOCKED</dcp-message-id>\\` cannot be compressed.\n\nRules:\n\n- Pick each \\`messageId\\` directly from injected IDs visible in context.\n- Only use raw message IDs of the form \\`mNNNNN\\`.\n- Ignore XML attributes such as \\`priority\\` when copying the ID; use only the inner \\`mNNNNN\\` value.\n- Do not invent IDs. Use only IDs that are present in context.\n\nBATCHING\nSelect MANY messages in a single tool call when they are safe to compress.\nEach entry should summarize exactly one message, and the tool can receive as many entries as needed in one batch.\n\nGENERAL CLEANUP\nUse the topic \"general cleanup\" for broad cleanup passes.\nDuring general cleanup, compress all medium and high-priority messages that are not relevant to the active task.\nOptimize for reducing context footprint, not for grouping messages by topic.\nDo not compress away still-active instructions, unresolved questions, or constraints that are likely to matter soon.\nPrioritize the earliest messages in the context as they will be the least relevant to the active task.\nGeneral cleanup should be done periodically between other normal compression tool passes, not as the primary form of compression.\n`\n","export const CONTEXT_LIMIT_NUDGE = `\n<system-reminder>\n⚠️ CRITICAL: Context limit reached. You MUST use the \\`compress\\` tool NOW.\n\nIf mid-atomic-operation, finish that step first, then compress immediately.\n\nHOW TO CALL COMPRESS:\n{\n \"topic\": \"Short Label\",\n \"content\": [\n {\n \"startId\": \"<ID from early in this conversation>\",\n \"endId\": \"<ID from later in this conversation>\",\n \"summary\": \"Complete technical summary of everything in the range\"\n }\n ]\n}\n\n⚠️ ID RULES — MOST COMMON CAUSE OF ERRORS:\n- ONLY use IDs you can see in <dcp-message-id> tags in the messages ABOVE.\n- Do NOT copy IDs from this example. Do NOT invent IDs.\n- Do NOT use IDs from compressed block summaries — they are stale.\n- startId must appear BEFORE endId in the conversation.\n\nSUMMARY RULES:\n- Capture ALL essential details: file paths, decisions, constraints, key findings.\n- Preserve user intent exactly. Direct-quote short user messages.\n- Prefer one large range over multiple small ones.\n- Compress OLDER resolved history first. Keep recent active work.\n</system-reminder>\n`\n","export const TURN_NUDGE = `\n<system-reminder>\nContext is getting full. Compress closed/older conversation ranges now.\n\n{\n \"topic\": \"Short Label\",\n \"content\": [{ \"startId\": \"<visible message ID>\", \"endId\": \"<visible message ID>\", \"summary\": \"...\" }]\n}\n\n⚠️ ONLY use IDs from <dcp-message-id> tags visible above. Do NOT invent or copy example IDs.\n</system-reminder>\n`\n","export const ITERATION_NUDGE = `\n<system-reminder>\nYou've been iterating for a while. If any earlier work is closed and unlikely to be referenced, compress it now.\n\n{\n \"topic\": \"Short Label\",\n \"content\": [{ \"startId\": \"<visible message ID>\", \"endId\": \"<visible message ID>\", \"summary\": \"...\" }]\n}\n\n⚠️ ONLY use IDs from <dcp-message-id> tags visible above. Do NOT invent or copy example IDs.\n</system-reminder>\n`\n","export 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`\n\nexport 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`\n\nexport function buildProtectedToolsExtension(protectedTools: string[]): string {\n if (protectedTools.length === 0) {\n return \"\"\n }\n\n const toolList = protectedTools.map((t) => `\\`${t}\\``).join(\", \")\n return `<dcp-system-reminder>\nThe following tools are environment-managed: ${toolList}.\nTheir outputs are automatically preserved during compression.\nDo not include their content in compress tool summaries — the environment retains it independently.\n</dcp-system-reminder>`\n}\n\nexport const DECOMPRESS_SYSTEM_EXTENSION = `<dcp-system-reminder>\nTHE PHILOSOPHY OF DECOMPRESS\n\\`decompress\\` restores previously compressed content. Use it when you need exact details\nthat were lost in compression.\n\nDECOMPRESS WHEN\n- You need exact code, error messages, or file contents from a compressed block\n- A summary lacks the precision needed for your next step\n- You discovered the compressed content is still relevant\n\nDO NOT DECOMPRESS IF\n- Context usage is already high (>70%) — decompressing inflates context\n- The summary is sufficient for your needs\n- You plan to immediately recompress the same content\n\nBefore decompressing, check context usage. Decompressing restores full messages,\nwhich can significantly increase context size.\n\nNOTE: Message-mode blocks created in the same batch (same runId) are restored together.\nDecompressing one block from a batch restores all blocks in that batch.\n</dcp-system-reminder>\n`\n","import type { RuntimePrompts } from \"./store\"\nexport type { PromptStore, RuntimePrompts } from \"./store\"\n\nexport function renderSystemPrompt(\n prompts: RuntimePrompts,\n protectedToolsExtension?: string,\n manual?: boolean,\n subagent?: boolean,\n): string {\n const extensions: string[] = []\n\n if (protectedToolsExtension) {\n extensions.push(protectedToolsExtension.trim())\n }\n\n if (manual) {\n extensions.push(prompts.manualExtension.trim())\n }\n\n if (subagent) {\n extensions.push(prompts.subagentExtension.trim())\n }\n\n // decompress extension is always included when compress is not denied\n // (the caller guards on permission === \"deny\" before reaching renderSystemPrompt)\n extensions.push(prompts.decompressExtension.trim())\n\n return [prompts.system.trim(), ...extensions]\n .filter(Boolean)\n .join(\"\\n\\n\")\n .replace(/\\n([ \\t]*\\n)+/g, \"\\n\\n\")\n .trim()\n}\n","/**\n * DCP Context Command\n * Shows a visual breakdown of token usage in the current session.\n *\n * TOKEN CALCULATION STRATEGY\n * ==========================\n * We minimize tokenizer estimation by leveraging API-reported values wherever possible.\n *\n * WHAT WE GET FROM THE API (exact):\n * - tokens.input : Input tokens for each assistant response\n * - tokens.output : Output tokens generated (includes text + tool calls)\n * - tokens.reasoning: Reasoning tokens used\n * - tokens.cache : Cache read/write tokens\n *\n * HOW WE CALCULATE EACH CATEGORY:\n *\n * SYSTEM = firstAssistant.input + cache.read + cache.write - tokenizer(firstUserMessage)\n * The first response's total input (input + cache.read + cache.write)\n * contains system + first user message. On the first request of a\n * session, the system prompt appears in cache.write (cache creation),\n * not cache.read.\n *\n * TOOLS = tokenizer(toolInputs + toolOutputs) - prunedTokens\n * We must tokenize tools anyway for pruning decisions.\n *\n * USER = tokenizer(all user messages)\n * User messages are typically small, so estimation is acceptable.\n *\n * ASSISTANT = total - system - user - tools\n * Calculated as residual. This absorbs:\n * - Assistant text output tokens\n * - Reasoning tokens (if persisted by the model)\n * - Any estimation errors\n *\n * TOTAL = input + output + reasoning + cache.read + cache.write\n * Matches opencode's UI display.\n *\n * WHY ASSISTANT IS THE RESIDUAL:\n * If reasoning tokens persist in context (model-dependent), they semantically\n * belong with \"Assistant\" since reasoning IS assistant-generated content.\n */\n\nimport type { Logger } from \"../logger\"\nimport type { SessionState, WithParts } from \"../state\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { formatTokenCount } from \"../ui/utils\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\nimport { isMessageCompacted } from \"../state/utils\"\nimport { countTokens, extractCompletedToolOutput, getCurrentParams } from \"../token-utils\"\nimport type { AssistantMessage, TextPart, ToolPart } from \"@opencode-ai/sdk/v2\"\n\nexport interface ContextCommandContext {\n client: any\n state: SessionState\n logger: Logger\n sessionId: string\n messages: WithParts[]\n}\n\ninterface TokenBreakdown {\n system: number\n user: number\n assistant: number\n tools: number\n toolCount: number\n toolsInContextCount: number\n prunedTokens: number\n prunedToolCount: number\n prunedMessageCount: number\n total: number\n}\n\nfunction analyzeTokens(state: SessionState, messages: WithParts[]): TokenBreakdown {\n const breakdown: TokenBreakdown = {\n system: 0,\n user: 0,\n assistant: 0,\n tools: 0,\n toolCount: 0,\n toolsInContextCount: 0,\n prunedTokens: state.stats.totalPruneTokens,\n prunedToolCount: 0,\n prunedMessageCount: 0,\n total: 0,\n }\n\n let firstAssistant: AssistantMessage | undefined\n for (const msg of messages) {\n if (msg.info.role === \"assistant\") {\n const assistantInfo = msg.info as AssistantMessage\n if (\n assistantInfo.tokens?.input > 0 ||\n assistantInfo.tokens?.cache?.read > 0 ||\n assistantInfo.tokens?.cache?.write > 0\n ) {\n firstAssistant = assistantInfo\n break\n }\n }\n }\n\n let lastAssistant: AssistantMessage | undefined\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.info.role === \"assistant\") {\n const assistantInfo = msg.info as AssistantMessage\n if (assistantInfo.tokens?.output > 0) {\n lastAssistant = assistantInfo\n break\n }\n }\n }\n\n const apiInput = lastAssistant?.tokens?.input || 0\n const apiOutput = lastAssistant?.tokens?.output || 0\n const apiReasoning = lastAssistant?.tokens?.reasoning || 0\n const apiCacheRead = lastAssistant?.tokens?.cache?.read || 0\n const apiCacheWrite = lastAssistant?.tokens?.cache?.write || 0\n breakdown.total = apiInput + apiOutput + apiReasoning + apiCacheRead + apiCacheWrite\n\n const userTextParts: string[] = []\n const toolInputParts: string[] = []\n const toolOutputParts: string[] = []\n let firstUserText = \"\"\n let foundFirstUser = false\n const allToolIds = new Set<string>()\n const activeToolIds = new Set<string>()\n const prunedByMessageToolIds = new Set<string>()\n const allMessageIds = new Set<string>()\n\n for (const msg of messages) {\n allMessageIds.add(msg.info.id)\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n const isCompacted = isMessageCompacted(state, msg)\n const pruneEntry = state.prune.messages.byMessageId.get(msg.info.id)\n const isMessagePruned = !!pruneEntry && pruneEntry.activeBlockIds.length > 0\n const isIgnoredUser = isIgnoredUserMessage(msg)\n\n for (const part of parts) {\n if (part.type === \"tool\") {\n const toolPart = part as ToolPart\n if (toolPart.callID) {\n allToolIds.add(toolPart.callID)\n if (!isCompacted) {\n activeToolIds.add(toolPart.callID)\n }\n if (isMessagePruned) {\n prunedByMessageToolIds.add(toolPart.callID)\n }\n }\n\n const isPruned = toolPart.callID && state.prune.tools.has(toolPart.callID)\n if (!isCompacted && !isPruned) {\n if (toolPart.state?.input) {\n const inputStr =\n typeof toolPart.state.input === \"string\"\n ? toolPart.state.input\n : JSON.stringify(toolPart.state.input)\n toolInputParts.push(inputStr)\n }\n\n const outputStr = extractCompletedToolOutput(toolPart)\n if (outputStr !== undefined) {\n toolOutputParts.push(outputStr)\n }\n }\n } else if (\n part.type === \"text\" &&\n msg.info.role === \"user\" &&\n !isCompacted &&\n !isIgnoredUser\n ) {\n const textPart = part as TextPart\n const text = textPart.text || \"\"\n userTextParts.push(text)\n if (!foundFirstUser) {\n firstUserText += text\n }\n }\n }\n\n if (msg.info.role === \"user\" && !isIgnoredUser && !foundFirstUser) {\n foundFirstUser = true\n }\n }\n\n const prunedByToolIds = new Set<string>()\n for (const id of allToolIds) {\n if (state.prune.tools.has(id)) {\n prunedByToolIds.add(id)\n }\n }\n\n const prunedToolIds = new Set<string>([...prunedByToolIds, ...prunedByMessageToolIds])\n const toolsInContextCount = [...activeToolIds].filter((id) => !prunedByToolIds.has(id)).length\n\n let prunedMessageCount = 0\n for (const [id, entry] of state.prune.messages.byMessageId) {\n if (allMessageIds.has(id) && entry.activeBlockIds.length > 0) {\n prunedMessageCount++\n }\n }\n\n breakdown.toolCount = allToolIds.size\n breakdown.toolsInContextCount = toolsInContextCount\n breakdown.prunedToolCount = prunedToolIds.size\n breakdown.prunedMessageCount = prunedMessageCount\n\n const firstUserTokens = countTokens(firstUserText)\n breakdown.user = countTokens(userTextParts.join(\"\\n\"))\n const toolInputTokens = countTokens(toolInputParts.join(\"\\n\"))\n const toolOutputTokens = countTokens(toolOutputParts.join(\"\\n\"))\n\n if (firstAssistant) {\n const firstInput =\n (firstAssistant.tokens?.input || 0) +\n (firstAssistant.tokens?.cache?.read || 0) +\n (firstAssistant.tokens?.cache?.write || 0)\n breakdown.system = Math.max(0, firstInput - firstUserTokens)\n }\n\n breakdown.tools = toolInputTokens + toolOutputTokens\n breakdown.assistant = Math.max(\n 0,\n breakdown.total - breakdown.system - breakdown.user - breakdown.tools,\n )\n\n return breakdown\n}\n\nfunction createBar(value: number, maxValue: number, width: number, char: string = \"█\"): string {\n if (maxValue === 0) return \"\"\n const filled = Math.round((value / maxValue) * width)\n const bar = char.repeat(Math.max(0, filled))\n return bar\n}\n\nfunction formatContextMessage(breakdown: TokenBreakdown): string {\n const lines: string[] = []\n const barWidth = 30\n\n const toolsLabel = `Tools (${breakdown.toolsInContextCount})`\n\n const categories = [\n { label: \"System\", value: breakdown.system, char: \"█\" },\n { label: \"User\", value: breakdown.user, char: \"▓\" },\n { label: \"Assistant\", value: breakdown.assistant, char: \"▒\" },\n { label: toolsLabel, value: breakdown.tools, char: \"░\" },\n ] as const\n\n const maxLabelLen = Math.max(...categories.map((c) => c.label.length))\n\n lines.push(\"╭───────────────────────────────────────────────────────────╮\")\n lines.push(\"│ ACP Context Analysis │\")\n lines.push(\"╰───────────────────────────────────────────────────────────╯\")\n lines.push(\"\")\n lines.push(\"Session Context Breakdown:\")\n lines.push(\"─\".repeat(60))\n lines.push(\"\")\n\n for (const cat of categories) {\n const bar = createBar(cat.value, breakdown.total, barWidth, cat.char)\n const percentage =\n breakdown.total > 0 ? ((cat.value / breakdown.total) * 100).toFixed(1) : \"0.0\"\n const labelWithPct = `${cat.label.padEnd(maxLabelLen)} ${percentage.padStart(5)}% `\n const valueStr = formatTokenCount(cat.value).padStart(13)\n lines.push(`${labelWithPct}│${bar.padEnd(barWidth)}│${valueStr}`)\n }\n\n lines.push(\"\")\n lines.push(\"─\".repeat(60))\n lines.push(\"\")\n\n lines.push(\"Summary:\")\n\n if (breakdown.prunedTokens > 0) {\n const withoutPruning = breakdown.total + breakdown.prunedTokens\n const pruned = []\n if (breakdown.prunedToolCount > 0) pruned.push(`${breakdown.prunedToolCount} tools`)\n if (breakdown.prunedMessageCount > 0)\n pruned.push(`${breakdown.prunedMessageCount} messages`)\n lines.push(\n ` Pruned: ${pruned.join(\", \")} (~${formatTokenCount(breakdown.prunedTokens)})`,\n )\n lines.push(` Current context: ~${formatTokenCount(breakdown.total)}`)\n lines.push(` Without ACP: ~${formatTokenCount(withoutPruning)}`)\n } else {\n lines.push(` Current context: ~${formatTokenCount(breakdown.total)}`)\n }\n\n lines.push(\"\")\n\n return lines.join(\"\\n\")\n}\n\nexport async function handleContextCommand(ctx: ContextCommandContext): Promise<void> {\n const { client, state, logger, sessionId, messages } = ctx\n\n const breakdown = analyzeTokens(state, messages)\n\n const message = formatContextMessage(breakdown)\n\n const params = getCurrentParams(state, messages, logger)\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n}\n","import type { Logger } from \"../logger\"\nimport type { SessionState, WithParts } from \"../state\"\nimport { syncCompressionBlocks } from \"../messages\"\nimport { getCurrentParams } from \"../token-utils\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { formatTokenCount } from \"../ui/utils\"\nimport {\n getActiveCompressionTargets,\n resolveCompressionTarget,\n type CompressionTarget,\n} from \"./compression-targets\"\nimport {\n parseBlockIdArg,\n findActiveAncestorBlockId,\n snapshotActiveMessages,\n deactivateCompressionTarget,\n computeRestoredMessages,\n computeReactivatedBlockIds,\n} from \"../compress/decompress-logic\"\nimport { saveSessionState } from \"../state/persistence\"\n\nexport interface DecompressCommandContext {\n client: any\n state: SessionState\n logger: Logger\n sessionId: string\n messages: WithParts[]\n args: string[]\n}\n\nfunction formatDecompressMessage(\n target: CompressionTarget,\n restoredMessageCount: number,\n restoredTokens: number,\n reactivatedBlockIds: number[],\n): string {\n const lines: string[] = []\n\n lines.push(`Restored compression ${target.displayId}.`)\n if (target.runId !== target.displayId || target.grouped) {\n lines.push(`Tool call label: Compression #${target.runId}.`)\n }\n if (reactivatedBlockIds.length > 0) {\n const refs = reactivatedBlockIds.map((id) => String(id)).join(\", \")\n lines.push(`Also restored nested compression(s): ${refs}.`)\n }\n\n if (restoredMessageCount > 0) {\n lines.push(\n `Restored ${restoredMessageCount} message(s) (~${formatTokenCount(restoredTokens)}).`,\n )\n } else {\n lines.push(\"No messages were restored.\")\n }\n\n return lines.join(\"\\n\")\n}\n\nfunction formatAvailableBlocksMessage(availableTargets: CompressionTarget[]): string {\n const lines: string[] = []\n\n lines.push(\"Usage: /acp decompress <n>\")\n lines.push(\"\")\n\n if (availableTargets.length === 0) {\n lines.push(\"No compressions are available to restore.\")\n return lines.join(\"\\n\")\n }\n\n lines.push(\"Available compressions:\")\n const entries = availableTargets.map((target) => {\n const topic = target.topic.replace(/\\s+/g, \" \").trim() || \"(no topic)\"\n const label = `${target.displayId} (${formatTokenCount(target.compressedTokens)})`\n const details = target.grouped\n ? `Compression #${target.runId} - ${target.blocks.length} messages`\n : `Compression #${target.runId}`\n return { label, topic: `${details} - ${topic}` }\n })\n\n const labelWidth = Math.max(...entries.map((entry) => entry.label.length)) + 4\n for (const entry of entries) {\n lines.push(` ${entry.label.padEnd(labelWidth)}${entry.topic}`)\n }\n\n return lines.join(\"\\n\")\n}\n\nexport async function handleDecompressCommand(ctx: DecompressCommandContext): Promise<void> {\n const { client, state, logger, sessionId, messages, args } = ctx\n\n const params = getCurrentParams(state, messages, logger)\n const targetArg = args[0]\n\n if (args.length > 1) {\n await sendIgnoredMessage(\n client,\n sessionId,\n \"Invalid arguments. Usage: /acp decompress <n>\",\n params,\n logger,\n )\n return\n }\n\n syncCompressionBlocks(state, logger, messages)\n const messagesState = state.prune.messages\n\n if (!targetArg) {\n const availableTargets = getActiveCompressionTargets(messagesState)\n const message = formatAvailableBlocksMessage(availableTargets)\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n return\n }\n\n const targetBlockId = parseBlockIdArg(targetArg)\n if (targetBlockId === null) {\n await sendIgnoredMessage(\n client,\n sessionId,\n `Please enter a compression number. Example: /acp decompress 2`,\n params,\n logger,\n )\n return\n }\n\n const target = resolveCompressionTarget(messagesState, targetBlockId)\n if (!target) {\n await sendIgnoredMessage(\n client,\n sessionId,\n `Compression ${targetBlockId} does not exist.`,\n params,\n logger,\n )\n return\n }\n\n const activeBlocks = target.blocks.filter((block) => block.active)\n if (activeBlocks.length === 0) {\n const activeAncestorBlockId = findActiveAncestorBlockId(messagesState, target)\n if (activeAncestorBlockId !== null) {\n await sendIgnoredMessage(\n client,\n sessionId,\n `Compression ${target.displayId} is inside compression ${activeAncestorBlockId}. Restore compression ${activeAncestorBlockId} first.`,\n params,\n logger,\n )\n return\n }\n\n await sendIgnoredMessage(\n client,\n sessionId,\n `Compression ${target.displayId} is not active.`,\n params,\n logger,\n )\n return\n }\n\n const activeMessagesBefore = snapshotActiveMessages(messagesState)\n const activeBlockIdsBefore = new Set(messagesState.activeBlockIds)\n\n deactivateCompressionTarget(messagesState, target)\n\n syncCompressionBlocks(state, logger, messages)\n\n const { restoredMessageCount, restoredTokens } = computeRestoredMessages(\n messagesState,\n activeMessagesBefore,\n )\n\n state.stats.totalPruneTokens = Math.max(0, state.stats.totalPruneTokens - restoredTokens)\n\n const reactivatedBlockIds = computeReactivatedBlockIds(messagesState, activeBlockIdsBefore)\n\n await saveSessionState(state, logger)\n\n const message = formatDecompressMessage(\n target,\n restoredMessageCount,\n restoredTokens,\n reactivatedBlockIds,\n )\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n\n logger.info(\"Decompress command completed\", {\n targetBlockId: target.displayId,\n targetRunId: target.runId,\n restoredMessageCount,\n restoredTokens,\n reactivatedBlockIds,\n })\n}\n","/**\n * ACP Help command handler.\n * Shows available ACP commands and their descriptions.\n */\n\nimport type { Logger } from \"../logger\"\nimport type { PluginConfig } from \"../config\"\nimport type { SessionState, WithParts } from \"../state\"\nimport { compressPermission } from \"../compress-permission\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { getCurrentParams } from \"../token-utils\"\n\nexport interface HelpCommandContext {\n client: any\n state: SessionState\n config: PluginConfig\n logger: Logger\n sessionId: string\n messages: WithParts[]\n}\n\nconst BASE_COMMANDS: [string, string][] = [\n [\"/acp context\", \"Show token usage breakdown for current session\"],\n [\"/acp stats\", \"Show ACP pruning statistics\"],\n [\"/acp sweep [n]\", \"Prune tools since last user message, or last n tools\"],\n [\"/acp manual [on|off]\", \"Toggle manual mode or set explicit state\"],\n]\n\nconst TOOL_COMMANDS: Record<string, [string, string]> = {\n compress: [\"/acp compress [focus]\", \"Trigger manual compress tool execution\"],\n decompress: [\"/acp decompress <n>\", \"Restore selected compression\"],\n recompress: [\"/acp recompress <n>\", \"Re-apply a user-decompressed compression\"],\n}\n\nfunction getVisibleCommands(state: SessionState, config: PluginConfig): [string, string][] {\n const commands = [...BASE_COMMANDS]\n\n if (compressPermission(state, config) !== \"deny\") {\n commands.push(TOOL_COMMANDS.compress)\n commands.push(TOOL_COMMANDS.decompress)\n commands.push(TOOL_COMMANDS.recompress)\n }\n\n return commands\n}\n\nfunction formatHelpMessage(state: SessionState, config: PluginConfig): string {\n const commands = getVisibleCommands(state, config)\n const colWidth = Math.max(...commands.map(([cmd]) => cmd.length)) + 4\n const lines: string[] = []\n\n lines.push(\"╭─────────────────────────────────────────────────────────────────────────╮\")\n lines.push(\"│ ACP Commands │\")\n lines.push(\"╰─────────────────────────────────────────────────────────────────────────╯\")\n lines.push(\"\")\n lines.push(` ${\"Manual mode:\".padEnd(colWidth)}${state.manualMode ? \"ON\" : \"OFF\"}`)\n lines.push(\"\")\n for (const [cmd, desc] of commands) {\n lines.push(` ${cmd.padEnd(colWidth)}${desc}`)\n }\n lines.push(\"\")\n\n return lines.join(\"\\n\")\n}\n\nexport async function handleHelpCommand(ctx: HelpCommandContext): Promise<void> {\n const { client, state, logger, sessionId, messages } = ctx\n\n const { config } = ctx\n const message = formatHelpMessage(state, config)\n\n const params = getCurrentParams(state, messages, logger)\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n\n logger.info(\"Help command executed\")\n}\n","/**\n * DCP Manual mode command handler.\n * Handles toggling manual mode and triggering individual tool executions.\n *\n * Usage:\n * /acp manual [on|off] - Toggle manual mode or set explicit state\n * /acp compress [focus] - Trigger manual compress execution\n */\n\nimport type { Logger } from \"../logger\"\nimport type { SessionState, WithParts } from \"../state\"\nimport type { PluginConfig } from \"../config\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { getCurrentParams } from \"../token-utils\"\nimport { buildCompressedBlockGuidance } from \"../prompts/extensions/nudge\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\n\nconst MANUAL_MODE_ON = \"Manual mode is now ON. Use /acp compress to trigger context tools manually.\"\n\nconst MANUAL_MODE_OFF = \"Manual mode is now OFF.\"\n\nconst COMPRESS_TRIGGER_PROMPT = [\n \"<compress triggered manually>\",\n \"Manual mode trigger received. You must now use the compress tool.\",\n \"Find the most significant completed conversation content that can be compressed into a high-fidelity technical summary.\",\n \"Follow the active compress mode, preserve all critical implementation details, and choose safe targets.\",\n \"Return after compress with a brief explanation of what content was compressed.\",\n].join(\"\\n\\n\")\n\nfunction getTriggerPrompt(\n tool: \"compress\",\n state: SessionState,\n config: PluginConfig,\n userFocus?: string,\n): string {\n const base = COMPRESS_TRIGGER_PROMPT\n const compressedBlockGuidance =\n config.compress.mode === \"message\" ? \"\" : buildCompressedBlockGuidance(state, config.gc)\n\n const sections = [base, compressedBlockGuidance]\n if (userFocus && userFocus.trim().length > 0) {\n sections.push(`Additional user focus:\\n${userFocus.trim()}`)\n }\n\n return sections.join(\"\\n\\n\")\n}\n\nexport interface ManualCommandContext {\n client: any\n state: SessionState\n config: PluginConfig\n logger: Logger\n sessionId: string\n messages: WithParts[]\n}\n\nexport async function handleManualToggleCommand(\n ctx: ManualCommandContext,\n modeArg?: string,\n): Promise<void> {\n const { client, state, logger, sessionId, messages } = ctx\n\n if (modeArg === \"on\") {\n state.manualMode = \"active\"\n } else if (modeArg === \"off\") {\n state.manualMode = false\n } else {\n state.manualMode = state.manualMode ? false : \"active\"\n }\n\n const params = getCurrentParams(state, messages, logger)\n await sendIgnoredMessage(\n client,\n sessionId,\n state.manualMode ? MANUAL_MODE_ON : MANUAL_MODE_OFF,\n params,\n logger,\n )\n\n logger.info(\"Manual mode toggled\", { manualMode: state.manualMode })\n}\n\nexport async function handleManualTriggerCommand(\n ctx: ManualCommandContext,\n tool: \"compress\",\n userFocus?: string,\n): Promise<string | null> {\n return getTriggerPrompt(tool, ctx.state, ctx.config, userFocus)\n}\n\nexport function applyPendingManualTrigger(\n state: SessionState,\n messages: WithParts[],\n logger: Logger,\n): void {\n const pending = state.pendingManualTrigger\n if (!pending) {\n return\n }\n\n if (!state.sessionId || pending.sessionId !== state.sessionId) {\n state.pendingManualTrigger = null\n return\n }\n\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.info.role !== \"user\" || isIgnoredUserMessage(msg)) {\n continue\n }\n\n for (const part of msg.parts) {\n if (part.type !== \"text\" || part.ignored || part.synthetic) {\n continue\n }\n\n part.text = pending.prompt\n state.pendingManualTrigger = null\n logger.debug(\"Applied manual prompt\", { sessionId: pending.sessionId })\n return\n }\n }\n\n state.pendingManualTrigger = null\n}\n","import type { Logger } from \"../logger\"\nimport type { PruneMessagesState, SessionState, WithParts } from \"../state\"\nimport { syncCompressionBlocks } from \"../messages\"\nimport { parseBlockRef } from \"../message-ids\"\nimport { getCurrentParams } from \"../token-utils\"\nimport { saveSessionState } from \"../state/persistence\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { formatTokenCount } from \"../ui/utils\"\nimport {\n getRecompressibleCompressionTargets,\n resolveCompressionTarget,\n type CompressionTarget,\n} from \"./compression-targets\"\n\nexport interface RecompressCommandContext {\n client: any\n state: SessionState\n logger: Logger\n sessionId: string\n messages: WithParts[]\n args: string[]\n}\n\nfunction parseBlockIdArg(arg: string): number | null {\n const normalized = arg.trim().toLowerCase()\n const blockRef = parseBlockRef(normalized)\n if (blockRef !== null) {\n return blockRef\n }\n\n if (!/^[1-9]\\d*$/.test(normalized)) {\n return null\n }\n\n const parsed = Number.parseInt(normalized, 10)\n return Number.isInteger(parsed) && parsed > 0 ? parsed : null\n}\n\nfunction snapshotActiveMessages(messagesState: PruneMessagesState): Set<string> {\n const activeMessages = new Set<string>()\n for (const [messageId, entry] of messagesState.byMessageId) {\n if (entry.activeBlockIds.length > 0) {\n activeMessages.add(messageId)\n }\n }\n return activeMessages\n}\n\nfunction formatRecompressMessage(\n target: CompressionTarget,\n recompressedMessageCount: number,\n recompressedTokens: number,\n deactivatedBlockIds: number[],\n): string {\n const lines: string[] = []\n\n lines.push(`Re-applied compression ${target.displayId}.`)\n if (target.runId !== target.displayId || target.grouped) {\n lines.push(`Tool call label: Compression #${target.runId}.`)\n }\n if (deactivatedBlockIds.length > 0) {\n const refs = deactivatedBlockIds.map((id) => String(id)).join(\", \")\n lines.push(`Also re-compressed nested compression(s): ${refs}.`)\n }\n\n if (recompressedMessageCount > 0) {\n lines.push(\n `Re-compressed ${recompressedMessageCount} message(s) (~${formatTokenCount(recompressedTokens)}).`,\n )\n } else {\n lines.push(\"No messages were re-compressed.\")\n }\n\n return lines.join(\"\\n\")\n}\n\nfunction formatAvailableBlocksMessage(availableTargets: CompressionTarget[]): string {\n const lines: string[] = []\n\n lines.push(\"Usage: /acp recompress <n>\")\n lines.push(\"\")\n\n if (availableTargets.length === 0) {\n lines.push(\"No user-decompressed blocks are available to re-compress.\")\n return lines.join(\"\\n\")\n }\n\n lines.push(\"Available user-decompressed compressions:\")\n const entries = availableTargets.map((target) => {\n const topic = target.topic.replace(/\\s+/g, \" \").trim() || \"(no topic)\"\n const label = `${target.displayId} (${formatTokenCount(target.compressedTokens)})`\n const details = target.grouped\n ? `Compression #${target.runId} - ${target.blocks.length} messages`\n : `Compression #${target.runId}`\n return { label, topic: `${details} - ${topic}` }\n })\n\n const labelWidth = Math.max(...entries.map((entry) => entry.label.length)) + 4\n for (const entry of entries) {\n lines.push(` ${entry.label.padEnd(labelWidth)}${entry.topic}`)\n }\n\n return lines.join(\"\\n\")\n}\n\nexport async function handleRecompressCommand(ctx: RecompressCommandContext): Promise<void> {\n const { client, state, logger, sessionId, messages, args } = ctx\n\n const params = getCurrentParams(state, messages, logger)\n const targetArg = args[0]\n\n if (args.length > 1) {\n await sendIgnoredMessage(\n client,\n sessionId,\n \"Invalid arguments. Usage: /acp recompress <n>\",\n params,\n logger,\n )\n return\n }\n\n syncCompressionBlocks(state, logger, messages)\n const messagesState = state.prune.messages\n const availableMessageIds = new Set(messages.map((msg) => msg.info.id))\n\n if (!targetArg) {\n const availableTargets = getRecompressibleCompressionTargets(\n messagesState,\n availableMessageIds,\n )\n const message = formatAvailableBlocksMessage(availableTargets)\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n return\n }\n\n const targetBlockId = parseBlockIdArg(targetArg)\n if (targetBlockId === null) {\n await sendIgnoredMessage(\n client,\n sessionId,\n `Please enter a compression number. Example: /acp recompress 2`,\n params,\n logger,\n )\n return\n }\n\n const target = resolveCompressionTarget(messagesState, targetBlockId)\n if (!target) {\n await sendIgnoredMessage(\n client,\n sessionId,\n `Compression ${targetBlockId} does not exist.`,\n params,\n logger,\n )\n return\n }\n\n if (target.blocks.some((block) => !availableMessageIds.has(block.compressMessageId))) {\n await sendIgnoredMessage(\n client,\n sessionId,\n `Compression ${target.displayId} can no longer be re-applied because its origin message is no longer in this session.`,\n params,\n logger,\n )\n return\n }\n\n if (!target.blocks.some((block) => block.deactivatedByUser)) {\n const message = target.blocks.some((block) => block.active)\n ? `Compression ${target.displayId} is already active.`\n : `Compression ${target.displayId} is not user-decompressed.`\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n return\n }\n\n const activeMessagesBefore = snapshotActiveMessages(messagesState)\n const activeBlockIdsBefore = new Set(messagesState.activeBlockIds)\n\n for (const block of target.blocks) {\n block.deactivatedByUser = false\n block.deactivatedAt = undefined\n block.deactivatedByBlockId = undefined\n }\n\n syncCompressionBlocks(state, logger, messages)\n\n let recompressedMessageCount = 0\n let recompressedTokens = 0\n for (const [messageId, entry] of messagesState.byMessageId) {\n const isActiveNow = entry.activeBlockIds.length > 0\n if (isActiveNow && !activeMessagesBefore.has(messageId)) {\n recompressedMessageCount++\n recompressedTokens += entry.tokenCount\n }\n }\n\n state.stats.totalPruneTokens += recompressedTokens\n\n const deactivatedBlockIds = Array.from(activeBlockIdsBefore)\n .filter((blockId) => !messagesState.activeBlockIds.has(blockId))\n .sort((a, b) => a - b)\n\n await saveSessionState(state, logger)\n\n const message = formatRecompressMessage(\n target,\n recompressedMessageCount,\n recompressedTokens,\n deactivatedBlockIds,\n )\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n\n logger.info(\"Recompress command completed\", {\n targetBlockId: target.displayId,\n targetRunId: target.runId,\n recompressedMessageCount,\n recompressedTokens,\n deactivatedBlockIds,\n })\n}\n","/**\n * DCP Stats command handler.\n * Shows pruning statistics for the current session and all-time totals.\n */\n\nimport type { Logger } from \"../logger\"\nimport type { SessionState, WithParts } from \"../state\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { formatTokenCount } from \"../ui/utils\"\nimport { loadAllSessionStats, type AggregatedStats } from \"../state/persistence\"\nimport { getCurrentParams } from \"../token-utils\"\nimport { getActiveCompressionTargets } from \"./compression-targets\"\n\nexport interface StatsCommandContext {\n client: any\n state: SessionState\n logger: Logger\n sessionId: string\n messages: WithParts[]\n}\n\nfunction formatStatsMessage(\n sessionTokens: number,\n sessionSummaryTokens: number,\n sessionTools: number,\n sessionMessages: number,\n sessionDurationMs: number,\n allTime: AggregatedStats,\n): string {\n const lines: string[] = []\n\n lines.push(\"╭───────────────────────────────────────────────────────────╮\")\n lines.push(\"│ ACP Statistics │\")\n lines.push(\"╰───────────────────────────────────────────────────────────╯\")\n lines.push(\"\")\n lines.push(\"Compression:\")\n lines.push(\"─\".repeat(60))\n lines.push(\n ` Tokens in|out: ~${formatTokenCount(sessionTokens)} | ~${formatTokenCount(sessionSummaryTokens)}`,\n )\n lines.push(` Ratio: ${formatCompressionRatio(sessionTokens, sessionSummaryTokens)}`)\n lines.push(` Time: ${formatCompressionTime(sessionDurationMs)}`)\n lines.push(` Messages: ${sessionMessages}`)\n lines.push(` Tools: ${sessionTools}`)\n lines.push(\"\")\n lines.push(\"All-time:\")\n lines.push(\"─\".repeat(60))\n lines.push(` Tokens saved: ~${formatTokenCount(allTime.totalTokens)}`)\n lines.push(` Tools pruned: ${allTime.totalTools}`)\n lines.push(` Messages pruned: ${allTime.totalMessages}`)\n lines.push(` Sessions: ${allTime.sessionCount}`)\n\n return lines.join(\"\\n\")\n}\n\nfunction formatCompressionRatio(inputTokens: number, outputTokens: number): string {\n if (inputTokens <= 0) {\n return \"0:1\"\n }\n\n if (outputTokens <= 0) {\n return \"∞:1\"\n }\n\n const ratio = Math.max(1, Math.round(inputTokens / outputTokens))\n return `${ratio}:1`\n}\n\nfunction formatCompressionTime(ms: number): string {\n const safeMs = Math.max(0, Math.round(ms))\n if (safeMs < 1000) {\n return `${safeMs} ms`\n }\n\n const totalSeconds = safeMs / 1000\n if (totalSeconds < 60) {\n return `${totalSeconds.toFixed(1)} s`\n }\n\n const wholeSeconds = Math.floor(totalSeconds)\n const hours = Math.floor(wholeSeconds / 3600)\n const minutes = Math.floor((wholeSeconds % 3600) / 60)\n const seconds = wholeSeconds % 60\n\n if (hours > 0) {\n return `${hours}h ${minutes}m ${seconds}s`\n }\n\n return `${minutes}m ${seconds}s`\n}\n\nexport async function handleStatsCommand(ctx: StatsCommandContext): Promise<void> {\n const { client, state, logger, sessionId, messages } = ctx\n\n // Session stats from in-memory state\n const sessionTokens = state.stats.totalPruneTokens\n const sessionSummaryTokens = Array.from(state.prune.messages.blocksById.values()).reduce(\n (total, block) => (block.active ? total + block.summaryTokens : total),\n 0,\n )\n const sessionDurationMs = getActiveCompressionTargets(state.prune.messages).reduce(\n (total, target) => total + target.durationMs,\n 0,\n )\n\n const prunedToolIds = new Set<string>(state.prune.tools.keys())\n for (const block of state.prune.messages.blocksById.values()) {\n if (block.active) {\n for (const toolId of block.effectiveToolIds) {\n prunedToolIds.add(toolId)\n }\n }\n }\n const sessionTools = prunedToolIds.size\n\n let sessionMessages = 0\n for (const entry of state.prune.messages.byMessageId.values()) {\n if (entry.activeBlockIds.length > 0) {\n sessionMessages++\n }\n }\n\n // All-time stats from storage files\n const allTime = await loadAllSessionStats(logger)\n\n const message = formatStatsMessage(\n sessionTokens,\n sessionSummaryTokens,\n sessionTools,\n sessionMessages,\n sessionDurationMs,\n allTime,\n )\n\n const params = getCurrentParams(state, messages, logger)\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n\n logger.info(\"Stats command executed\", {\n sessionTokens,\n sessionSummaryTokens,\n sessionTools,\n sessionMessages,\n sessionDurationMs,\n allTimeTokens: allTime.totalTokens,\n allTimeTools: allTime.totalTools,\n allTimeMessages: allTime.totalMessages,\n })\n}\n","/**\n * DCP Sweep command handler.\n * Prunes tool outputs since the last user message, or the last N tools.\n *\n * Usage:\n * /acp sweep - Prune all tools since the previous user message\n * /acp sweep 10 - Prune the last 10 tools\n */\n\nimport type { Logger } from \"../logger\"\nimport type { SessionState, WithParts, ToolParameterEntry } from \"../state\"\nimport type { PluginConfig } from \"../config\"\nimport { sendIgnoredMessage } from \"../ui/notification\"\nimport { formatPrunedItemsList } from \"../ui/utils\"\nimport { getCurrentParams, getTotalToolTokens } from \"../token-utils\"\nimport { isIgnoredUserMessage } from \"../messages/query\"\nimport { buildToolIdList } from \"../messages/utils\"\nimport { saveSessionState } from \"../state/persistence\"\nimport { isMessageCompacted } from \"../state/utils\"\nimport {\n getFilePathsFromParameters,\n isFilePathProtected,\n isToolNameProtected,\n} from \"../protected-patterns\"\nimport { syncToolCache } from \"../state/tool-cache\"\n\nexport interface SweepCommandContext {\n client: any\n state: SessionState\n config: PluginConfig\n logger: Logger\n sessionId: string\n messages: WithParts[]\n args: string[]\n workingDirectory: string\n}\n\nfunction findLastUserMessageIndex(messages: WithParts[]): number {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.info.role === \"user\" && !isIgnoredUserMessage(msg)) {\n return i\n }\n }\n\n return -1\n}\n\nfunction collectToolIdsAfterIndex(\n state: SessionState,\n messages: WithParts[],\n afterIndex: number,\n): string[] {\n const toolIds: string[] = []\n\n for (let i = afterIndex + 1; i < messages.length; i++) {\n const msg = messages[i]\n if (isMessageCompacted(state, msg)) {\n continue\n }\n const parts = Array.isArray(msg.parts) ? msg.parts : []\n if (parts.length > 0) {\n for (const part of parts) {\n if (part.type === \"tool\" && part.callID && part.tool) {\n toolIds.push(part.callID)\n }\n }\n }\n }\n\n return toolIds\n}\n\nfunction formatNoUserMessage(): string {\n const lines: string[] = []\n\n lines.push(\"╭───────────────────────────────────────────────────────────╮\")\n lines.push(\"│ ACP Sweep │\")\n lines.push(\"╰───────────────────────────────────────────────────────────╯\")\n lines.push(\"\")\n lines.push(\"Nothing swept: no user message found.\")\n\n return lines.join(\"\\n\")\n}\n\nfunction formatSweepMessage(\n toolCount: number,\n tokensSaved: number,\n mode: \"since-user\" | \"last-n\",\n toolIds: string[],\n toolMetadata: Map<string, ToolParameterEntry>,\n workingDirectory?: string,\n skippedProtected?: number,\n): string {\n const lines: string[] = []\n\n lines.push(\"╭───────────────────────────────────────────────────────────╮\")\n lines.push(\"│ ACP Sweep │\")\n lines.push(\"╰───────────────────────────────────────────────────────────╯\")\n lines.push(\"\")\n\n if (toolCount === 0) {\n if (mode === \"since-user\") {\n lines.push(\"No tools found since the previous user message.\")\n } else {\n lines.push(`No tools found to sweep.`)\n }\n if (skippedProtected && skippedProtected > 0) {\n lines.push(`(${skippedProtected} protected tool(s) skipped)`)\n }\n } else {\n if (mode === \"since-user\") {\n lines.push(`Swept ${toolCount} tool(s) since the previous user message.`)\n } else {\n lines.push(`Swept the last ${toolCount} tool(s).`)\n }\n lines.push(`Tokens saved: ~${tokensSaved.toLocaleString()}`)\n if (skippedProtected && skippedProtected > 0) {\n lines.push(`(${skippedProtected} protected tool(s) skipped)`)\n }\n lines.push(\"\")\n const itemLines = formatPrunedItemsList(toolIds, toolMetadata, workingDirectory)\n lines.push(...itemLines)\n }\n\n return lines.join(\"\\n\")\n}\n\nexport async function handleSweepCommand(ctx: SweepCommandContext): Promise<void> {\n const { client, state, config, logger, sessionId, messages, args, workingDirectory } = ctx\n\n const params = getCurrentParams(state, messages, logger)\n const protectedTools = config.commands.protectedTools\n\n syncToolCache(state, config, logger, messages)\n buildToolIdList(state, messages)\n\n // Parse optional numeric argument\n const numArg = args[0] ? parseInt(args[0], 10) : null\n const isLastNMode = numArg !== null && !isNaN(numArg) && numArg > 0\n\n let toolIdsToSweep: string[]\n let mode: \"since-user\" | \"last-n\"\n\n if (isLastNMode) {\n // Mode: Sweep last N tools\n mode = \"last-n\"\n const startIndex = Math.max(0, state.toolIdList.length - numArg!)\n toolIdsToSweep = state.toolIdList.slice(startIndex)\n logger.info(`Sweep command: last ${numArg} mode, found ${toolIdsToSweep.length} tools`)\n } else {\n // Mode: Sweep since last user message\n mode = \"since-user\"\n const lastUserMsgIndex = findLastUserMessageIndex(messages)\n\n if (lastUserMsgIndex === -1) {\n // No user message found - show message and return\n const message = formatNoUserMessage()\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n logger.info(\"Sweep command: no user message found\")\n return\n } else {\n toolIdsToSweep = collectToolIdsAfterIndex(state, messages, lastUserMsgIndex)\n logger.info(\n `Sweep command: found last user at index ${lastUserMsgIndex}, sweeping ${toolIdsToSweep.length} tools`,\n )\n }\n }\n\n // Filter out already-pruned tools, protected tools, and protected file paths\n const newToolIds = toolIdsToSweep.filter((id) => {\n if (state.prune.tools.has(id)) {\n return false\n }\n const entry = state.toolParameters.get(id)\n if (!entry) {\n return true\n }\n if (isToolNameProtected(entry.tool, protectedTools)) {\n logger.debug(`Sweep: skipping protected tool ${entry.tool} (${id})`)\n return false\n }\n const filePaths = getFilePathsFromParameters(entry.tool, entry.parameters)\n if (isFilePathProtected(filePaths, config.protectedFilePatterns)) {\n logger.debug(`Sweep: skipping protected file path(s) ${filePaths.join(\", \")} (${id})`)\n return false\n }\n return true\n })\n\n // Count how many were skipped due to protection\n const skippedProtected = toolIdsToSweep.filter((id) => {\n const entry = state.toolParameters.get(id)\n if (!entry) {\n return false\n }\n if (isToolNameProtected(entry.tool, protectedTools)) {\n return true\n }\n const filePaths = getFilePathsFromParameters(entry.tool, entry.parameters)\n if (isFilePathProtected(filePaths, config.protectedFilePatterns)) {\n return true\n }\n return false\n }).length\n\n if (newToolIds.length === 0) {\n const message = formatSweepMessage(\n 0,\n 0,\n mode,\n [],\n new Map(),\n workingDirectory,\n skippedProtected,\n )\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n logger.info(\"Sweep command: no new tools to sweep\", { skippedProtected })\n return\n }\n\n const tokensSaved = getTotalToolTokens(state, newToolIds)\n\n // Add to prune list\n for (const id of newToolIds) {\n const entry = state.toolParameters.get(id)\n state.prune.tools.set(id, entry?.tokenCount ?? 0)\n }\n state.stats.pruneTokenCounter += tokensSaved\n state.stats.totalPruneTokens += state.stats.pruneTokenCounter\n state.stats.pruneTokenCounter = 0\n\n // Collect metadata for logging\n const toolMetadata: Map<string, ToolParameterEntry> = new Map()\n for (const id of newToolIds) {\n const entry = state.toolParameters.get(id)\n if (entry) {\n toolMetadata.set(id, entry)\n }\n }\n\n // Persist state\n saveSessionState(state, logger).catch((err) =>\n logger.error(\"Failed to persist state after sweep\", { error: err.message }),\n )\n\n const message = formatSweepMessage(\n newToolIds.length,\n tokensSaved,\n mode,\n newToolIds,\n toolMetadata,\n workingDirectory,\n skippedProtected,\n )\n await sendIgnoredMessage(client, sessionId, message, params, logger)\n\n logger.info(\"Sweep command completed\", {\n toolsSwept: newToolIds.length,\n tokensSaved,\n skippedProtected,\n mode,\n tools: Array.from(toolMetadata.entries()).map(([id, entry]) => ({\n id,\n tool: entry.tool,\n })),\n })\n}\n","import type { CompressionBlock } from \"../state\"\nimport type { GCConfig } from \"../config\"\n\nexport interface CompactionResult {\n compactedBlocks: number\n savedTokens: number\n}\n\nexport interface GCParams {\n maxOldGenSummaryLength: number\n modelContextLimit: number\n currentTokens: number\n}\n\nexport function runTruncateGC(\n blocks: CompressionBlock[],\n params: GCParams,\n): CompactionResult {\n let compactedBlocks = 0\n let savedTokens = 0\n\n for (const block of blocks) {\n if (!block.active) continue\n if (block.summary.length <= params.maxOldGenSummaryLength) continue\n\n const originalLength = block.summary.length\n const truncated = truncateSummary(block.summary, params.maxOldGenSummaryLength, block.blockId)\n const savedChars = originalLength - truncated.length\n if (savedChars > 0) {\n block.summary = truncated\n block.summaryTokens = Math.round(truncated.length / 4)\n compactedBlocks++\n savedTokens += Math.round(savedChars / 4)\n }\n }\n\n return { compactedBlocks, savedTokens }\n}\n\nfunction truncateSummary(summary: string, maxLength: number, _blockId: number): string {\n if (summary.length <= maxLength) return summary\n\n const headerEnd = summary.indexOf(\"\\n\")\n if (headerEnd === -1) return summary.slice(0, maxLength) + \"\\n...\\n[GC truncated]\"\n\n const header = summary.slice(0, headerEnd + 1)\n const footerStart = summary.lastIndexOf(\"\\n\\n\")\n const footer = footerStart > headerEnd ? summary.slice(footerStart) : \"\"\n\n const availableForContent = maxLength - header.length - footer.length - 20\n if (availableForContent < 100) {\n return header + \"...\\n[GC truncated]\" + footer\n }\n\n const content = summary.slice(headerEnd + 1, headerEnd + 1 + availableForContent)\n return header + content + \"\\n...\\n[GC truncated]\" + footer\n}\n\nexport function shouldRunMajorGC(\n currentTokens: number,\n modelContextLimit: number | undefined,\n gcConfig: GCConfig,\n): boolean {\n if (!modelContextLimit || modelContextLimit === 0) return false\n\n const threshold = parseGcThreshold(gcConfig.majorGcThresholdPercent, modelContextLimit)\n return currentTokens >= threshold\n}\n\nexport function getGCParams(gcConfig: GCConfig, modelContextLimit: number, currentTokens: number): GCParams {\n return {\n maxOldGenSummaryLength: gcConfig.maxOldGenSummaryLength,\n modelContextLimit,\n currentTokens,\n }\n}\n\nfunction parseGcThreshold(limit: number | `${number}%`, modelContextLimit: number): number {\n if (typeof limit === \"number\") return limit\n const percent = parseFloat(limit.slice(0, -1))\n if (isNaN(percent)) return modelContextLimit\n return Math.round((Math.max(0, Math.min(100, Math.round(percent))) / 100) * modelContextLimit)\n}\n","import type { CompressionBlock, SessionState, WithParts } from \"../state\"\nimport type { BatchCleanupConfig, GCConfig, PluginConfig } from \"../config\"\nimport type { Logger } from \"../logger\"\nimport { countTokens, getCurrentTokenUsage } from \"../token-utils\"\nimport {\n COMPRESSED_BLOCK_HEADER,\n allocateBlockId,\n allocateRunId,\n wrapCompressedSummary,\n} from \"../compress/state\"\nimport { formatBlockRef } from \"../message-ids\"\n\nexport interface MergeMarkedResult {\n mergedCount: number\n savedTokens: number\n}\n\nexport interface BatchCleanupResult {\n tier: 0 | 1 | 2 | 3\n action: \"none\" | \"nudge\" | \"merge\"\n mergedCount: number\n savedTokens: number\n nudgeText?: string\n}\n\nconst DEFAULT_BATCH_CLEANUP: BatchCleanupConfig = {\n lowThreshold: \"60%\",\n highThreshold: \"75%\",\n forceThreshold: \"90%\",\n}\n\nfunction resolveBatchCleanup(gc: GCConfig): BatchCleanupConfig {\n return gc.batchCleanup ?? DEFAULT_BATCH_CLEANUP\n}\n\nfunction percentToTokens(\n value: number | `${number}%`,\n modelContextLimit: number,\n): number {\n if (typeof value === \"number\") return value\n const percent = parseFloat(value.slice(0, -1))\n if (isNaN(percent)) return modelContextLimit\n const clamped = Math.max(0, Math.min(100, Math.round(percent)))\n return Math.round((clamped / 100) * modelContextLimit)\n}\n\nfunction collectActiveOldGenBlocks(state: SessionState, maxOldGenSummaryLength: number): CompressionBlock[] {\n const blocks: CompressionBlock[] = []\n const ids = Array.from(state.prune.messages.activeBlockIds).sort((a, b) => a - b)\n for (const id of ids) {\n const block = state.prune.messages.blocksById.get(id)\n if (!block || !block.active) continue\n if (\n block.generation === \"old\" ||\n block.generation === undefined ||\n block.summary.length > maxOldGenSummaryLength\n ) {\n blocks.push(block)\n }\n }\n return blocks\n}\n\nfunction collectActiveMarkedBlocks(state: SessionState): CompressionBlock[] {\n const ids = Array.from(state.prune.messages.markedForCleanup).sort((a, b) => a - b)\n const blocks: CompressionBlock[] = []\n for (const id of ids) {\n const block = state.prune.messages.blocksById.get(id)\n if (!block || !block.active) continue\n blocks.push(block)\n }\n return blocks\n}\n\nfunction extractSummaryBody(summary: string): string {\n let body = summary\n const headerPrefix = COMPRESSED_BLOCK_HEADER + \"\\n\"\n if (body.startsWith(headerPrefix)) {\n body = body.slice(headerPrefix.length)\n }\n body = body.replace(/\\n<dcp-message-id[^>]*>b\\d+<\\/dcp-message-id>$/, \"\")\n return body.trim()\n}\n\nfunction truncateMergedSummary(merged: string, maxLength: number): string {\n if (merged.length <= maxLength) return merged\n\n const blocks = merged.split(\"\\n---\\n\")\n const headers = blocks\n .map((b) => b.split(\"\\n\")[0] ?? \"\")\n .filter((h) => h.trim().length > 0)\n\n const marker = \"\\n...\\n[merged and truncated by batch cleanup]\"\n const budget = Math.max(0, maxLength - marker.length)\n const headerJoin = headers.join(\"\\n\")\n\n if (headerJoin.length <= budget) {\n return headerJoin + marker\n }\n return headerJoin.slice(0, budget) + marker\n}\n\nexport function mergeMarkedBlocks(\n state: SessionState,\n markedIds: number[],\n maxMergedLength: number,\n): MergeMarkedResult {\n const sortedIds = [...new Set(markedIds)].filter(\n (id) => Number.isInteger(id) && id > 0,\n ).sort((a, b) => a - b)\n\n const sourceBlocks: CompressionBlock[] = []\n for (const id of sortedIds) {\n const block = state.prune.messages.blocksById.get(id)\n if (!block || !block.active) continue\n if (!sourceBlocks.some((b) => b.blockId === id)) {\n sourceBlocks.push(block)\n }\n }\n\n if (sourceBlocks.length < 2) {\n return { mergedCount: 0, savedTokens: 0 }\n }\n\n const messagesState = state.prune.messages\n const newBlockId = allocateBlockId(state)\n const newRunId = allocateRunId(state)\n\n const bodies = sourceBlocks.map((block) => extractSummaryBody(block.summary))\n const mergedRaw = bodies.join(\"\\n---\\n\")\n const mergedBody = truncateMergedSummary(mergedRaw, maxMergedLength)\n const newSummary = wrapCompressedSummary(newBlockId, mergedBody)\n const newSummaryTokens = countTokens(newSummary)\n\n const oldest = sourceBlocks[0]\n const newest = sourceBlocks[sourceBlocks.length - 1]\n\n const effectiveMessageIds = new Set<string>()\n const effectiveToolIds = new Set<string>()\n for (const block of sourceBlocks) {\n for (const id of block.effectiveMessageIds) effectiveMessageIds.add(id)\n for (const id of block.effectiveToolIds) effectiveToolIds.add(id)\n }\n\n const sourceIds = sourceBlocks.map((b) => b.blockId)\n const createdAt = Date.now()\n\n const mergedBlock: CompressionBlock = {\n blockId: newBlockId,\n runId: newRunId,\n active: true,\n deactivatedByUser: false,\n compressedTokens: 0,\n summaryTokens: newSummaryTokens,\n durationMs: 0,\n mode: \"range\",\n topic: \"Batch merge cleanup\",\n batchTopic: \"Batch merge cleanup\",\n startId: oldest.startId,\n endId: newest.endId,\n anchorMessageId: oldest.anchorMessageId,\n compressMessageId: \"\",\n compressCallId: undefined,\n includedBlockIds: [...sourceIds],\n consumedBlockIds: [...sourceIds],\n parentBlockIds: [],\n directMessageIds: [],\n directToolIds: [],\n effectiveMessageIds: [...effectiveMessageIds],\n effectiveToolIds: [...effectiveToolIds],\n createdAt,\n summary: newSummary,\n survivedCount: 0,\n generation: \"old\",\n }\n\n const now = Date.now()\n for (const block of sourceBlocks) {\n block.active = false\n block.deactivatedAt = now\n block.deactivatedByBlockId = newBlockId\n if (!block.parentBlockIds.includes(newBlockId)) {\n block.parentBlockIds.push(newBlockId)\n }\n messagesState.activeBlockIds.delete(block.blockId)\n const mappedId = messagesState.activeByAnchorMessageId.get(block.anchorMessageId)\n if (mappedId === block.blockId) {\n messagesState.activeByAnchorMessageId.delete(block.anchorMessageId)\n }\n }\n\n messagesState.blocksById.set(newBlockId, mergedBlock)\n messagesState.activeBlockIds.add(newBlockId)\n messagesState.activeByAnchorMessageId.set(mergedBlock.anchorMessageId, newBlockId)\n\n for (const messageId of effectiveMessageIds) {\n const entry = messagesState.byMessageId.get(messageId)\n if (!entry) continue\n entry.activeBlockIds = entry.activeBlockIds.filter((id) => !sourceIds.includes(id))\n if (!entry.activeBlockIds.includes(newBlockId)) {\n entry.activeBlockIds.push(newBlockId)\n }\n if (!entry.allBlockIds.includes(newBlockId)) {\n entry.allBlockIds.push(newBlockId)\n }\n }\n\n for (const id of sourceIds) {\n messagesState.markedForCleanup.delete(id)\n }\n\n const sourceTokens = sourceBlocks.reduce(\n (sum, block) => sum + (block.summaryTokens || Math.round(block.summary.length / 4)),\n 0,\n )\n const savedTokens = Math.max(0, sourceTokens - newSummaryTokens)\n\n return { mergedCount: sourceBlocks.length, savedTokens }\n}\n\nfunction buildNudgeText(state: SessionState, maxMergedLength: number): string | undefined {\n const blocks = collectActiveMarkedBlocks(state)\n if (blocks.length < 1) return undefined\n\n const refs = blocks.map((b) => formatBlockRef(b.blockId)).join(\", \")\n const sourceTokens = blocks.reduce(\n (sum, block) => sum + (block.summaryTokens || Math.round(block.summary.length / 4)),\n 0,\n )\n const estimatedMergedTokens = Math.round(maxMergedLength / 4)\n const estimatedSavings = Math.max(0, sourceTokens - estimatedMergedTokens)\n\n return [\n `⚠️ ${blocks.length} block(s) marked for batch cleanup (${refs}).`,\n `Merge-compressing them would free ~${estimatedSavings} tokens.`,\n blocks.length >= 2\n ? \"They will auto-merge when context pressure reaches the high threshold.\"\n : \"A single marked block won't auto-merge on its own — use compress to consolidate it, or unmark_block if no longer needed.\",\n \"To act now, use compress with a range covering these blocks.\",\n ].join(\" \")\n}\n\nexport function runBatchCleanup(\n state: SessionState,\n config: PluginConfig,\n logger: Logger,\n messages: WithParts[],\n): BatchCleanupResult {\n const noop: BatchCleanupResult = {\n tier: 0,\n action: \"none\",\n mergedCount: 0,\n savedTokens: 0,\n }\n\n if (!state.modelContextLimit || state.modelContextLimit <= 0) {\n return noop\n }\n\n const currentTokens = getCurrentTokenUsage(state, messages)\n const limit = state.modelContextLimit\n const batchCleanup = resolveBatchCleanup(config.gc)\n const maxMergedLength = config.gc.maxOldGenSummaryLength\n\n const forceTokens = percentToTokens(batchCleanup.forceThreshold, limit)\n const highTokens = percentToTokens(batchCleanup.highThreshold, limit)\n const lowTokens = percentToTokens(batchCleanup.lowThreshold, limit)\n\n if (currentTokens >= forceTokens) {\n const oldGenBlocks = collectActiveOldGenBlocks(state, maxMergedLength)\n if (oldGenBlocks.length < 2) {\n return noop\n }\n const ids = oldGenBlocks.map((b) => b.blockId)\n const result = mergeMarkedBlocks(state, ids, maxMergedLength)\n if (result.mergedCount === 0) {\n return noop\n }\n logger.info(\"Batch cleanup tier 3 (force): merged old-gen blocks\", {\n mergedCount: result.mergedCount,\n savedTokens: result.savedTokens,\n currentTokens,\n forceThreshold: batchCleanup.forceThreshold,\n })\n return {\n tier: 3,\n action: \"merge\",\n mergedCount: result.mergedCount,\n savedTokens: result.savedTokens,\n }\n }\n\n if (currentTokens >= highTokens) {\n const marked = collectActiveMarkedBlocks(state)\n if (marked.length < 2) {\n return noop\n }\n const ids = marked.map((b) => b.blockId)\n const result = mergeMarkedBlocks(state, ids, maxMergedLength)\n if (result.mergedCount === 0) {\n return noop\n }\n logger.info(\"Batch cleanup tier 2 (high): merged marked blocks\", {\n mergedCount: result.mergedCount,\n savedTokens: result.savedTokens,\n currentTokens,\n highThreshold: batchCleanup.highThreshold,\n })\n return {\n tier: 2,\n action: \"merge\",\n mergedCount: result.mergedCount,\n savedTokens: result.savedTokens,\n }\n }\n\n if (currentTokens >= lowTokens) {\n const nudgeText = buildNudgeText(state, maxMergedLength)\n if (!nudgeText) {\n return noop\n }\n logger.info(\"Batch cleanup tier 1 (low): nudge injected\", {\n currentTokens,\n lowThreshold: batchCleanup.lowThreshold,\n })\n return {\n tier: 1,\n action: \"nudge\",\n mergedCount: 0,\n savedTokens: 0,\n nudgeText,\n }\n }\n\n return noop\n}\n","import type { SessionState, WithParts } from \"./state\"\nimport type { Logger } from \"./logger\"\nimport type { PluginConfig } from \"./config\"\nimport { assignMessageRefs } from \"./message-ids\"\nimport {\n buildPriorityMap,\n buildToolIdList,\n injectCompressNudges,\n injectExtendedSubAgentResults,\n injectMessageIds,\n prune,\n stripHallucinations,\n stripHallucinationsFromString,\n stripStaleMetadata,\n syncCompressionBlocks,\n computeInputBudget,\n} from \"./messages\"\nimport { renderSystemPrompt, type PromptStore } from \"./prompts\"\nimport { buildProtectedToolsExtension } from \"./prompts/extensions/system\"\nimport {\n applyPendingCompressionDurations,\n buildCompressionTimingKey,\n consumeCompressionStart,\n resolveCompressionDuration,\n} from \"./compress/timing\"\nimport { filterMessages, filterMessagesInPlace } from \"./messages/shape\"\nimport { getLastUserMessage } from \"./messages/query\"\nimport {\n applyPendingManualTrigger,\n handleContextCommand,\n handleDecompressCommand,\n handleHelpCommand,\n handleManualToggleCommand,\n handleManualTriggerCommand,\n handleRecompressCommand,\n handleStatsCommand,\n handleSweepCommand,\n} from \"./commands\"\nimport { type HostPermissionSnapshot } from \"./host-permissions\"\nimport { compressPermission, syncCompressPermissionState } from \"./compress-permission\"\nimport { checkSession, ensureSessionInitialized, saveSessionState, syncToolCache } from \"./state\"\nimport { cacheSystemPromptTokens } from \"./ui/utils\"\nimport { runTruncateGC, shouldRunMajorGC, getGCParams } from \"./gc/truncate\"\nimport { runBatchCleanup } from \"./gc/merge\"\nimport { getCurrentTokenUsage } from \"./token-utils\"\nimport { appendToLastTextPart } from \"./messages/utils\"\n\nconst INTERNAL_AGENT_SIGNATURES = [\n \"You are a title generator\",\n \"You are a helpful AI assistant tasked with summarizing conversations\",\n \"You are an anchored context summarization assistant for coding sessions\",\n \"Summarize what was done in this conversation\",\n]\n\n// [FIX Bug 37] OpenCode built-in hidden primary-mode agents that must NOT be\n// run through the message-transform pipeline. These small internal LLM\n// requests (title/summary/compaction generation) carry the agent name on the\n// user message's `info.agent` field. Mutating them corrupts the request and\n// shared session state (e.g. countTurns runs on the wrong message set).\n// Keep in sync with INTERNAL_AGENT_SIGNATURES (system-prompt layer) and the\n// agent IDs defined in OpenCode's packages/core/src/plugin/agent.ts.\nconst INTERNAL_AGENT_NAMES = new Set([\"title\", \"summary\", \"compaction\"])\n\nfunction isInternalAgentRequest(messages: WithParts[]): boolean {\n const lastUserMessage = getLastUserMessage(messages)\n if (!lastUserMessage) {\n return false\n }\n const agent = (lastUserMessage.info as { agent?: unknown }).agent\n return typeof agent === \"string\" && INTERNAL_AGENT_NAMES.has(agent)\n}\n\nexport function createSystemPromptHandler(\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n prompts: PromptStore,\n) {\n return async (\n input: {\n sessionID?: string\n model: { limit: { context: number; input?: number; output?: number } }\n },\n output: { system: string[] },\n ) => {\n if (input.model?.limit?.context) {\n state.modelContextLimit = input.model.limit.context\n }\n\n if (state.isSubAgent && !config.experimental.allowSubAgents) {\n return\n }\n\n const systemText = output.system.join(\"\\n\")\n if (INTERNAL_AGENT_SIGNATURES.some((sig) => systemText.includes(sig))) {\n logger.info(\"Skipping DCP system prompt injection for internal agent\")\n return\n }\n\n const effectivePermission =\n input.sessionID && state.sessionId === input.sessionID\n ? compressPermission(state, config)\n : config.compress.permission\n\n if (effectivePermission === \"deny\") {\n return\n }\n\n prompts.reload()\n const runtimePrompts = prompts.getRuntimePrompts()\n const newPrompt = renderSystemPrompt(\n runtimePrompts,\n buildProtectedToolsExtension(config.compress.protectedTools),\n !!state.manualMode,\n state.isSubAgent && config.experimental.allowSubAgents,\n )\n if (output.system.length > 0) {\n output.system[output.system.length - 1] += \"\\n\\n\" + newPrompt\n } else {\n output.system.push(newPrompt)\n }\n }\n}\n\nfunction runMajorGC(\n state: SessionState,\n config: PluginConfig,\n logger: Logger,\n messages: WithParts[],\n): void {\n // [FIX Bug 32] Age-based deactivation does NOT depend on modelContextLimit.\n // modelContextLimit is set in the system prompt hook, which runs AFTER the\n // messages transform hook. If we guard this with modelContextLimit, age-based\n // deactivation never runs after restart (modelContextLimit starts as undefined).\n const maxBlockAge = config.gc.maxBlockAge ?? 15\n let agedOutCount = 0\n let agedOutTokens = 0\n const now = Date.now()\n for (const [blockId, block] of state.prune.messages.blocksById) {\n if (!block.active) continue\n const age = block.survivedCount ?? 0\n if (age > maxBlockAge) {\n block.active = false\n block.deactivatedAt = now\n block.deactivatedByBlockId = undefined\n state.prune.messages.activeBlockIds.delete(Number(blockId))\n const anchorMapped = state.prune.messages.activeByAnchorMessageId.get(block.anchorMessageId)\n if (anchorMapped === Number(blockId)) {\n state.prune.messages.activeByAnchorMessageId.delete(block.anchorMessageId)\n }\n agedOutCount++\n agedOutTokens += block.summaryTokens ?? Math.round(block.summary.length / 4)\n }\n }\n\n if (agedOutCount > 0) {\n logger.info(\"Major GC: deactivated aged-out blocks\", {\n agedOutCount,\n agedOutTokens,\n maxBlockAge,\n })\n void saveSessionState(state, logger)\n }\n\n if (!state.modelContextLimit) return\n\n const currentTokens = getCurrentTokenUsage(state, messages)\n\n // Check if any active block is oversized (summary > 2x maxOldGenSummaryLength)\n // These should always be truncated regardless of token threshold\n const oversizedThreshold = config.gc.maxOldGenSummaryLength * 2\n let hasOversizedBlocks = false\n for (const [, block] of state.prune.messages.blocksById) {\n if (block.active && block.summary.length > oversizedThreshold) {\n hasOversizedBlocks = true\n break\n }\n }\n\n if (!shouldRunMajorGC(currentTokens, state.modelContextLimit, config.gc) && !hasOversizedBlocks) return\n\n const oldBlocks: import(\"./state\").CompressionBlock[] = []\n for (const [blockId, block] of state.prune.messages.blocksById) {\n if (!block.active) continue\n if (\n block.generation === \"old\" ||\n block.generation === undefined ||\n block.summary.length > config.gc.maxOldGenSummaryLength\n ) {\n oldBlocks.push(block)\n }\n }\n\n if (oldBlocks.length === 0) return\n\n const params = getGCParams(config.gc, state.modelContextLimit, currentTokens)\n const result = runTruncateGC(oldBlocks, params)\n\n if (result.compactedBlocks > 0) {\n logger.info(\"Major GC: truncated old-gen blocks\", {\n compactedBlocks: result.compactedBlocks,\n savedTokens: result.savedTokens,\n currentTokens,\n threshold: config.gc.majorGcThresholdPercent,\n })\n void saveSessionState(state, logger)\n }\n}\n\nfunction appendBatchCleanupNudge(messages: WithParts[], nudgeText: string): void {\n const lastUser = getLastUserMessage(messages)\n if (!lastUser) return\n appendToLastTextPart(lastUser, nudgeText)\n}\n\nexport function createChatMessageTransformHandler(\n client: any,\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n prompts: PromptStore,\n hostPermissions: HostPermissionSnapshot,\n) {\n return async (input: {}, output: { messages: WithParts[] }) => {\n const receivedMessages = Array.isArray(output.messages) ? output.messages.length : 0\n const messages = filterMessagesInPlace(output.messages)\n if (messages.length !== receivedMessages) {\n logger.warn(\"Skipping messages with unexpected shape during chat transform\", {\n received: receivedMessages,\n usable: messages.length,\n })\n }\n\n // [FIX Bug 37] Skip OpenCode internal agents (title/summary/compaction).\n // These small hidden LLM requests must not be mutated, and running\n // checkSession on them would corrupt shared state (currentTurn, etc.).\n if (isInternalAgentRequest(messages)) {\n logger.debug(\"Skipping message transform for internal agent request\")\n return\n }\n\n await checkSession(client, state, logger, output.messages, config.manualMode.enabled)\n\n syncCompressPermissionState(state, config, hostPermissions, output.messages)\n\n if (state.isSubAgent && !config.experimental.allowSubAgents) {\n return\n }\n\n stripHallucinations(output.messages)\n cacheSystemPromptTokens(state, output.messages)\n assignMessageRefs(state, output.messages)\n const activeBlockCountBefore = state.prune.messages.activeBlockIds.size // [FIX Bug 4]\n syncCompressionBlocks(state, logger, output.messages)\n if (state.prune.messages.activeBlockIds.size !== activeBlockCountBefore) { // [FIX Bug 4]\n void saveSessionState(state, logger) // [FIX Bug 4] persist deactivations\n }\n syncToolCache(state, config, logger, output.messages)\n buildToolIdList(state, output.messages)\n runMajorGC(state, config, logger, output.messages)\n const batchResult = runBatchCleanup(state, config, logger, output.messages)\n if (batchResult.tier === 1 && batchResult.nudgeText) {\n appendBatchCleanupNudge(output.messages, batchResult.nudgeText)\n }\n if (batchResult.mergedCount > 0) {\n void saveSessionState(state, logger)\n }\n prune(state, logger, config, output.messages)\n // [FIX Bug 2] assign refs to newly created synthetic messages from prune/filterCompressedRanges\n assignMessageRefs(state, output.messages)\n await injectExtendedSubAgentResults(\n client,\n state,\n logger,\n output.messages,\n config.experimental.allowSubAgents,\n )\n const compressionPriorities = buildPriorityMap(config, state, output.messages)\n prompts.reload()\n injectCompressNudges(\n state,\n config,\n logger,\n output.messages,\n prompts.getRuntimePrompts(),\n compressionPriorities,\n )\n injectMessageIds(state, config, output.messages, compressionPriorities)\n applyPendingManualTrigger(state, output.messages, logger)\n stripStaleMetadata(output.messages)\n\n if (state.sessionId) {\n await logger.saveContext(state.sessionId, output.messages)\n }\n }\n}\n\nexport function createCommandExecuteHandler(\n client: any,\n state: SessionState,\n logger: Logger,\n config: PluginConfig,\n workingDirectory: string,\n hostPermissions: HostPermissionSnapshot,\n) {\n return async (\n input: { command: string; sessionID: string; arguments: string },\n output: { parts: any[] },\n ) => {\n if (!config.commands.enabled) {\n return\n }\n\n if (input.command === \"acp\" || input.command === \"dcp\") {\n const messagesResponse = await client.session.messages({\n path: { id: input.sessionID },\n })\n const messages = filterMessages(messagesResponse.data || messagesResponse)\n\n await ensureSessionInitialized(\n client,\n state,\n input.sessionID,\n logger,\n messages,\n config.manualMode.enabled,\n )\n\n syncCompressPermissionState(state, config, hostPermissions, messages)\n\n const effectivePermission = compressPermission(state, config)\n if (effectivePermission === \"deny\") {\n return\n }\n\n const args = (input.arguments || \"\").trim().split(/\\s+/).filter(Boolean)\n const subcommand = args[0]?.toLowerCase() || \"\"\n const subArgs = args.slice(1)\n\n const commandCtx = {\n client,\n state,\n config,\n logger,\n sessionId: input.sessionID,\n messages,\n }\n\n if (subcommand === \"context\") {\n await handleContextCommand(commandCtx)\n throw new Error(\"__DCP_CONTEXT_HANDLED__\")\n }\n\n if (subcommand === \"stats\") {\n await handleStatsCommand(commandCtx)\n throw new Error(\"__DCP_STATS_HANDLED__\")\n }\n\n if (subcommand === \"sweep\") {\n await handleSweepCommand({\n ...commandCtx,\n args: subArgs,\n workingDirectory,\n })\n throw new Error(\"__DCP_SWEEP_HANDLED__\")\n }\n\n if (subcommand === \"manual\") {\n await handleManualToggleCommand(commandCtx, subArgs[0]?.toLowerCase())\n throw new Error(\"__DCP_MANUAL_HANDLED__\")\n }\n\n if (subcommand === \"compress\") {\n const userFocus = subArgs.join(\" \").trim()\n const prompt = await handleManualTriggerCommand(commandCtx, \"compress\", userFocus)\n if (!prompt) {\n throw new Error(\"__DCP_MANUAL_TRIGGER_BLOCKED__\")\n }\n\n state.manualMode = \"compress-pending\"\n state.pendingManualTrigger = {\n sessionId: input.sessionID,\n prompt,\n }\n const rawArgs = (input.arguments || \"\").trim()\n output.parts.length = 0\n output.parts.push({\n type: \"text\",\n text: rawArgs ? `/dcp ${rawArgs}` : `/dcp ${subcommand}`,\n })\n return\n }\n\n if (subcommand === \"decompress\") {\n await handleDecompressCommand({\n ...commandCtx,\n args: subArgs,\n })\n throw new Error(\"__DCP_DECOMPRESS_HANDLED__\")\n }\n\n if (subcommand === \"recompress\") {\n await handleRecompressCommand({\n ...commandCtx,\n args: subArgs,\n })\n throw new Error(\"__DCP_RECOMPRESS_HANDLED__\")\n }\n\n await handleHelpCommand(commandCtx)\n throw new Error(\"__DCP_HELP_HANDLED__\")\n }\n }\n}\n\nexport function createTextCompleteHandler() {\n return async (\n _input: { sessionID: string; messageID: string; partID: string },\n output: { text: string },\n ) => {\n output.text = stripHallucinationsFromString(output.text)\n }\n}\n\nexport function createEventHandler(state: SessionState, logger: Logger) {\n return async (input: { event: any }) => {\n const eventTime =\n typeof input.event?.time === \"number\" && Number.isFinite(input.event.time)\n ? input.event.time\n : typeof input.event?.properties?.time === \"number\" &&\n Number.isFinite(input.event.properties.time)\n ? input.event.properties.time\n : undefined\n\n if (input.event.type !== \"message.part.updated\") {\n return\n }\n\n const part = input.event.properties?.part\n if (part?.type !== \"tool\" || part.tool !== \"compress\") {\n return\n }\n\n if (part.state.status === \"pending\") {\n if (typeof part.callID !== \"string\" || typeof part.messageID !== \"string\") {\n return\n }\n\n const startedAt = eventTime ?? Date.now()\n const key = buildCompressionTimingKey(part.messageID, part.callID)\n if (state.compressionTiming.startsByCallId.has(key)) {\n return\n }\n state.compressionTiming.startsByCallId.set(key, startedAt)\n logger.debug(\"Recorded compression start\", {\n messageID: part.messageID,\n callID: part.callID,\n startedAt,\n })\n return\n }\n\n if (part.state.status === \"completed\") {\n if (typeof part.callID !== \"string\" || typeof part.messageID !== \"string\") {\n return\n }\n\n const key = buildCompressionTimingKey(part.messageID, part.callID)\n const start = consumeCompressionStart(state, part.messageID, part.callID)\n const durationMs = resolveCompressionDuration(start, eventTime, part.state.time)\n if (typeof durationMs !== \"number\") {\n return\n }\n\n state.compressionTiming.pendingByCallId.set(key, {\n messageId: part.messageID,\n callId: part.callID,\n durationMs,\n })\n\n const updates = applyPendingCompressionDurations(state)\n if (updates === 0) {\n return\n }\n\n await saveSessionState(state, logger)\n\n logger.info(\"Attached compression time to blocks\", {\n messageID: part.messageID,\n callID: part.callID,\n blocks: updates,\n durationMs,\n })\n return\n }\n\n if (part.state.status === \"running\") {\n return\n }\n\n if (typeof part.callID === \"string\" && typeof part.messageID === \"string\") {\n state.compressionTiming.startsByCallId.delete(\n buildCompressionTimingKey(part.messageID, part.callID),\n )\n }\n }\n}\n","export function isSecureMode(): boolean {\n return !!process.env.OPENCODE_SERVER_PASSWORD\n}\n\nexport function getAuthorizationHeader(): string | undefined {\n const password = process.env.OPENCODE_SERVER_PASSWORD\n if (!password) return undefined\n\n const username = process.env.OPENCODE_SERVER_USERNAME ?? \"opencode\"\n // Use Buffer for Node.js base64 encoding (btoa may not be available in all Node versions)\n const credentials = Buffer.from(`${username}:${password}`).toString(\"base64\")\n return `Basic ${credentials}`\n}\n\nexport function configureClientAuth(client: any): any {\n const authHeader = getAuthorizationHeader()\n\n if (!authHeader) {\n return client\n }\n\n // The SDK client has an internal client with request interceptors\n // Access the underlying client to add the interceptor\n const innerClient = client._client || client.client\n\n if (innerClient?.interceptors?.request) {\n innerClient.interceptors.request.use((request: Request) => {\n // Only add auth header if not already present\n if (!request.headers.has(\"Authorization\")) {\n request.headers.set(\"Authorization\", authHeader)\n }\n return request\n })\n }\n\n return client\n}\n","import { readFile, rm } from \"node:fs/promises\"\nimport { basename, dirname, join } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport type { PluginInput } from \"@opencode-ai/plugin\"\n\ntype PackageJson = {\n name?: string\n version?: string\n dependencies?: Record<string, string>\n}\n\ntype UpdateResult =\n | { updated: true; name: string; current: string; latest: string }\n | { updated: false; error: \"remove_failed\"; name: string; current: string; latest: string }\n | { updated: false }\n\nconst PACKAGE_NAME = \"opencode-acp\"\n\nexport function startAutoUpdate(ctx: PluginInput, enabled: boolean): void {\n if (!enabled) return\n\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 10_000)\n void checkAutoUpdate(controller.signal)\n .then((result) => {\n if (!result.updated) return\n setTimeout(() => {\n ctx.client.tui.showToast({\n body: {\n title: \"ACP update ready\",\n message: `Updated ${result.name} from ${result.current} to ${result.latest}. Restart OpenCode to finish.`,\n variant: \"info\",\n duration: 7000,\n },\n })\n }, 5000)\n })\n .catch(() => {})\n .finally(() => clearTimeout(timeout))\n}\n\nasync function checkAutoUpdate(signal: AbortSignal): Promise<UpdateResult> {\n const packageDir = await findPackageDir(PACKAGE_NAME)\n if (!packageDir) return { updated: false }\n\n const pkg = await readPackageJson(join(packageDir, \"package.json\"))\n if (!pkg?.name || !pkg.version) return { updated: false }\n\n const latest = await fetchLatestVersion(pkg.name, signal)\n if (!latest || !isVersionNewer(latest, pkg.version)) return { updated: false }\n\n const removeDir = await updateRemoveDir(packageDir, pkg.name)\n if (!removeDir) return { updated: false }\n\n try {\n await rm(removeDir, { recursive: true, force: true })\n } catch {\n return {\n updated: false,\n error: \"remove_failed\",\n name: pkg.name,\n current: pkg.version,\n latest,\n }\n }\n\n return { updated: true, name: pkg.name, current: pkg.version, latest }\n}\n\nasync function findPackageDir(name: string) {\n let dir = dirname(fileURLToPath(import.meta.url))\n for (;;) {\n const pkg = await readPackageJson(join(dir, \"package.json\"))\n if (pkg?.name === name) return dir\n\n const parent = dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\nexport async function updateRemoveDir(packageDir: string, name: string) {\n const packageParent = dirname(packageDir)\n const nodeModulesDir = basename(packageParent).startsWith(\"@\")\n ? dirname(packageParent)\n : packageParent\n if (basename(nodeModulesDir) !== \"node_modules\") return undefined\n\n const wrapperDir = dirname(nodeModulesDir)\n const wrapperPkg = await readPackageJson(join(wrapperDir, \"package.json\"))\n const spec = wrapperSpec(wrapperDir, name) ?? wrapperPkg?.dependencies?.[name]\n if (!spec || !isAutoUpdatableSpec(spec)) return undefined\n\n return wrapperDir\n}\n\nfunction wrapperSpec(wrapperDir: string, name: string) {\n if (name.startsWith(\"@\")) {\n const [scope, pkg] = name.split(\"/\")\n if (!scope || !pkg || basename(dirname(wrapperDir)) !== scope) return undefined\n const prefix = `${pkg}@`\n const base = basename(wrapperDir)\n return base.startsWith(prefix) ? base.slice(prefix.length) : undefined\n }\n\n const prefix = `${name}@`\n const base = basename(wrapperDir)\n return base.startsWith(prefix) ? base.slice(prefix.length) : undefined\n}\n\nexport function isAutoUpdatableSpec(spec: string) {\n const value = spec.trim()\n if (!value) return false\n if (value === \"latest\" || value === \"*\") return true\n if (/^[~^]/.test(value)) return true\n if (/^(?:>=|>|<=|<)/.test(value)) return true\n if (/\\s+(?:\\|\\||-|[<>=])\\s+/.test(value)) return true\n return false\n}\n\nasync function readPackageJson(path: string): Promise<PackageJson | undefined> {\n try {\n const data = JSON.parse(await readFile(path, \"utf-8\"))\n return data && typeof data === \"object\" ? (data as PackageJson) : undefined\n } catch {\n return undefined\n }\n}\n\nasync function fetchLatestVersion(name: string, signal: AbortSignal) {\n try {\n const response = await fetch(\n `https://registry.npmjs.org/${encodeURIComponent(name)}/latest`,\n {\n signal,\n },\n )\n if (!response.ok) return undefined\n const data: unknown = await response.json()\n if (!data || typeof data !== \"object\") return undefined\n const version = (data as { version?: unknown }).version\n return typeof version === \"string\" ? version : undefined\n } catch {\n return undefined\n }\n}\n\nexport function isVersionNewer(latest: string, current: string) {\n const next = parseVersion(latest)\n const prev = parseVersion(current)\n if (!next || !prev) return false\n\n for (let i = 0; i < 3; i++) {\n if (next.parts[i] !== prev.parts[i]) return next.parts[i] > prev.parts[i]\n }\n\n if (!next.pre.length && prev.pre.length) return true\n if (next.pre.length && !prev.pre.length) return false\n\n for (let i = 0; i < Math.max(next.pre.length, prev.pre.length); i++) {\n const a = next.pre[i]\n const b = prev.pre[i]\n if (a === undefined) return false\n if (b === undefined) return true\n if (a === b) continue\n\n const aNumber = /^\\d+$/.test(a) ? Number(a) : undefined\n const bNumber = /^\\d+$/.test(b) ? Number(b) : undefined\n if (aNumber !== undefined && bNumber !== undefined) return aNumber > bNumber\n if (aNumber !== undefined) return false\n if (bNumber !== undefined) return true\n return a > b\n }\n\n return false\n}\n\nfunction parseVersion(version: string) {\n const match = version.match(/^v?(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+.+)?$/)\n if (!match) return undefined\n return {\n parts: [Number(match[1]), Number(match[2]), Number(match[3])],\n pre: match[4]?.split(\".\") ?? [],\n }\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { getConfig } from \"./lib/config\"\nimport {\n createCompressMessageTool,\n createCompressRangeTool,\n createDecompressTool,\n createMarkBlockTool,\n createUnmarkBlockTool,\n} from \"./lib/compress\"\nimport {\n compressDisabledByOpencode,\n hasExplicitToolPermission,\n type HostPermissionSnapshot,\n} from \"./lib/host-permissions\"\nimport { Logger } from \"./lib/logger\"\nimport { createSessionState } from \"./lib/state\"\nimport { PromptStore } from \"./lib/prompts/store\"\nimport {\n createChatMessageTransformHandler,\n createCommandExecuteHandler,\n createEventHandler,\n createSystemPromptHandler,\n createTextCompleteHandler,\n} from \"./lib/hooks\"\nimport { configureClientAuth, isSecureMode } from \"./lib/auth\"\nimport { startAutoUpdate } from \"./lib/update\"\n\nconst server: Plugin = (async (ctx) => {\n const config = getConfig(ctx)\n\n if (!config.enabled) {\n return {}\n }\n\n const logger = new Logger(config.debug)\n const state = createSessionState()\n const prompts = new PromptStore(logger, ctx.directory, config.experimental.customPrompts)\n const hostPermissions: HostPermissionSnapshot = {\n global: undefined,\n agents: {},\n }\n\n if (isSecureMode()) {\n configureClientAuth(ctx.client)\n // logger.info(\"Secure mode detected, configured client authentication\")\n }\n\n logger.info(\"DCP initialized\", {\n strategies: config.strategies,\n })\n\n startAutoUpdate(ctx, config.autoUpdate)\n\n const compressToolContext = {\n client: ctx.client,\n state,\n logger,\n config,\n prompts,\n }\n\n return {\n \"experimental.chat.system.transform\": createSystemPromptHandler(\n state,\n logger,\n config,\n prompts,\n ),\n \"experimental.chat.messages.transform\": createChatMessageTransformHandler(\n ctx.client,\n state,\n logger,\n config,\n prompts,\n hostPermissions,\n ) as any,\n \"experimental.text.complete\": createTextCompleteHandler(),\n \"command.execute.before\": createCommandExecuteHandler(\n ctx.client,\n state,\n logger,\n config,\n ctx.directory,\n hostPermissions,\n ),\n event: createEventHandler(state, logger),\n tool: {\n ...(config.compress.permission !== \"deny\" && {\n compress:\n config.compress.mode === \"message\"\n ? createCompressMessageTool(compressToolContext)\n : createCompressRangeTool(compressToolContext),\n decompress: createDecompressTool(compressToolContext),\n mark_block: createMarkBlockTool(compressToolContext),\n unmark_block: createUnmarkBlockTool(compressToolContext),\n }),\n },\n config: async (opencodeConfig) => {\n if (\n config.compress.permission !== \"deny\" &&\n compressDisabledByOpencode(opencodeConfig.permission)\n ) {\n config.compress.permission = \"deny\"\n }\n\n if (config.commands.enabled && config.compress.permission !== \"deny\") {\n opencodeConfig.command ??= {}\n opencodeConfig.command[\"acp\"] = {\n template: \"\",\n description: \"Show available ACP commands\",\n }\n }\n\n const toolsToAdd: string[] = []\n if (config.compress.permission !== \"deny\" && !config.experimental.allowSubAgents) {\n toolsToAdd.push(\"compress\", \"decompress\", \"mark_block\", \"unmark_block\")\n }\n\n if (toolsToAdd.length > 0) {\n const existingPrimaryTools = opencodeConfig.experimental?.primary_tools ?? []\n opencodeConfig.experimental = {\n ...opencodeConfig.experimental,\n primary_tools: [...existingPrimaryTools, ...toolsToAdd],\n }\n }\n\n if (!hasExplicitToolPermission(opencodeConfig.permission, \"compress\")) {\n const permission = opencodeConfig.permission ?? {}\n opencodeConfig.permission = {\n ...permission,\n compress: config.compress.permission,\n } as typeof permission\n }\n\n hostPermissions.global = opencodeConfig.permission\n hostPermissions.agents = Object.fromEntries(\n Object.entries(opencodeConfig.agent ?? {}).map(([name, agent]) => [\n name,\n agent?.permission,\n ]),\n )\n },\n }\n}) satisfies Plugin\n\nexport default server\n"],"mappings":"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AAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,IAAI,IAAI,EAAE,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAA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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAf,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAvB,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAzB,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA5B,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAnB,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAxB,IAAM,+BAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWr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","names":["value","CharacterCodes","ParseOptions","ScanError","SyntaxKind","parse","ParseErrorCode","parse","countTokens","existsSync","homedir","join","countTokens","join","homedir","existsSync","tool","tool","tool","countTokens","countTokens","tool","validateArgs","buildSchema","tool","validateArgs","countTokens","tool","tool","collectTurnNudgeAnchors","buildSchema","tool","tool","buildSchema","tool","writeFile","mkdir","join","existsSync","homedir","stack","existsSync","mkdirSync","readFileSync","writeFileSync","statSync","cpSync","join","dirname","homedir","findOpencodeDir","join","existsSync","statSync","dirname","homedir","cpSync","readFileSync","mkdirSync","writeFileSync","countTokens","message","tool","parseBlockIdArg","snapshotActiveMessages","formatAvailableBlocksMessage","message","message","countTokens","readFile","dirname","join","prefix","base"]}
|