diff --git a/README.md b/README.md index 9e2efec..a8e7661 100644 --- a/README.md +++ b/README.md @@ -58,8 +58,6 @@ DCP uses its own config file: "enabled": true, // Enable debug logging to ~/.config/opencode/logs/dcp/ "debug": false, - // Show toast notifications when a new version is available - "showUpdateToasts": true, // Summary display: "off", "minimal", or "detailed" "pruningSummary": "detailed", // Strategies for pruning tokens from chat history diff --git a/lib/config.ts b/lib/config.ts index 594a046..1887442 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -31,7 +31,6 @@ export interface PruneTool { export interface PluginConfig { enabled: boolean debug: boolean - showUpdateToasts?: boolean pruningSummary: "off" | "minimal" | "detailed" strategies: { deduplication: Deduplication @@ -47,7 +46,7 @@ export const VALID_CONFIG_KEYS = new Set([ // Top-level keys 'enabled', 'debug', - 'showUpdateToasts', + 'showUpdateToasts', // Deprecated but kept for backwards compatibility 'pruningSummary', 'strategies', // strategies.deduplication @@ -106,9 +105,6 @@ function validateConfigTypes(config: Record): ValidationError[] { if (config.debug !== undefined && typeof config.debug !== 'boolean') { errors.push({ key: 'debug', expected: 'boolean', actual: typeof config.debug }) } - if (config.showUpdateToasts !== undefined && typeof config.showUpdateToasts !== 'boolean') { - errors.push({ key: 'showUpdateToasts', expected: 'boolean', actual: typeof config.showUpdateToasts }) - } if (config.pruningSummary !== undefined) { const validValues = ['off', 'minimal', 'detailed'] if (!validValues.includes(config.pruningSummary)) { @@ -217,7 +213,6 @@ function showConfigValidationWarnings( const defaultConfig: PluginConfig = { enabled: true, debug: false, - showUpdateToasts: true, pruningSummary: 'detailed', strategies: { deduplication: { @@ -310,8 +305,6 @@ function createDefaultConfig(): void { "enabled": true, // Enable debug logging to ~/.config/opencode/logs/dcp/ "debug": false, - // Show toast notifications when a new version is available - "showUpdateToasts": true, // Summary display: "off", "minimal", or "detailed" "pruningSummary": "detailed", // Strategies for pruning tokens from chat history @@ -468,7 +461,6 @@ export function getConfig(ctx: PluginInput): PluginConfig { config = { enabled: result.data.enabled ?? config.enabled, debug: result.data.debug ?? config.debug, - showUpdateToasts: result.data.showUpdateToasts ?? config.showUpdateToasts, pruningSummary: result.data.pruningSummary ?? config.pruningSummary, strategies: mergeStrategies(config.strategies, result.data.strategies as any) } @@ -500,7 +492,6 @@ export function getConfig(ctx: PluginInput): PluginConfig { config = { enabled: result.data.enabled ?? config.enabled, debug: result.data.debug ?? config.debug, - showUpdateToasts: result.data.showUpdateToasts ?? config.showUpdateToasts, pruningSummary: result.data.pruningSummary ?? config.pruningSummary, strategies: mergeStrategies(config.strategies, result.data.strategies as any) } @@ -529,7 +520,6 @@ export function getConfig(ctx: PluginInput): PluginConfig { config = { enabled: result.data.enabled ?? config.enabled, debug: result.data.debug ?? config.debug, - showUpdateToasts: result.data.showUpdateToasts ?? config.showUpdateToasts, pruningSummary: result.data.pruningSummary ?? config.pruningSummary, strategies: mergeStrategies(config.strategies, result.data.strategies as any) } diff --git a/lib/hooks.ts b/lib/hooks.ts index f24d52c..72fda69 100644 --- a/lib/hooks.ts +++ b/lib/hooks.ts @@ -48,11 +48,6 @@ export function createEventHandler( return } - if (event.type === "session.compacted") { - logger.info("Session compaction detected - updating state") - state.lastCompaction = Date.now() - } - if (event.type === "session.status" && event.properties.status.type === "idle") { if (!config.strategies.onIdle.enabled) { return diff --git a/lib/messages/prune.ts b/lib/messages/prune.ts index 918056e..33d9a7a 100644 --- a/lib/messages/prune.ts +++ b/lib/messages/prune.ts @@ -27,6 +27,10 @@ const buildPrunableToolsList = ( return } const numericId = toolIdList.indexOf(toolCallId) + if (numericId === -1) { + logger.warn(`Tool in cache but not in toolIdList - possible stale entry`, { toolCallId, tool: toolParameterEntry.tool }) + return + } const paramKey = extractParameterKey(toolParameterEntry.tool, toolParameterEntry.parameters) const description = paramKey ? `${toolParameterEntry.tool}, ${paramKey}` : toolParameterEntry.tool lines.push(`${numericId}: ${description}`) diff --git a/lib/shared-utils.ts b/lib/shared-utils.ts index 9cb60a1..fe6fbd6 100644 --- a/lib/shared-utils.ts +++ b/lib/shared-utils.ts @@ -1,4 +1,3 @@ -import { Logger } from "./logger" import { SessionState, WithParts } from "./state" export const isMessageCompacted = ( @@ -20,12 +19,4 @@ export const getLastUserMessage = ( return null } -export const checkForCompaction = ( - state: SessionState, - messages: WithParts[], - logger: Logger -): void => { - for (const msg of messages) { - } -} diff --git a/lib/state/persistence.ts b/lib/state/persistence.ts index 89d6772..eb97551 100644 --- a/lib/state/persistence.ts +++ b/lib/state/persistence.ts @@ -16,7 +16,6 @@ export interface PersistedSessionState { prune: Prune stats: SessionStats; lastUpdated: string; - lastCompacted: number } const STORAGE_DIR = join( @@ -55,8 +54,7 @@ export async function saveSessionState( sessionName: sessionName, prune: sessionState.prune, stats: sessionState.stats, - lastUpdated: new Date().toISOString(), - lastCompacted: sessionState.lastCompaction + lastUpdated: new Date().toISOString() }; const filePath = getSessionFilePath(sessionState.sessionId); diff --git a/lib/state/state.ts b/lib/state/state.ts index 035f81b..7ad2617 100644 --- a/lib/state/state.ts +++ b/lib/state/state.ts @@ -21,11 +21,19 @@ export const checkSession = async ( if (state.sessionId === null || state.sessionId !== lastSessionId) { logger.info(`Session changed: ${state.sessionId} -> ${lastSessionId}`) try { - await ensureSessionInitialized(client, state, lastSessionId, logger) + await ensureSessionInitialized(client, state, lastSessionId, logger, messages) } catch (err: any) { logger.error("Failed to initialize session state", { error: err.message }) } } + + const lastCompactionTimestamp = findLastCompactionTimestamp(messages) + if (lastCompactionTimestamp > state.lastCompaction) { + state.lastCompaction = lastCompactionTimestamp + state.toolParameters.clear() + state.prune.toolIds = [] + logger.info("Detected compaction from messages - cleared tool cache", { timestamp: lastCompactionTimestamp }) + } } export function createSessionState(): SessionState { @@ -66,7 +74,8 @@ export async function ensureSessionInitialized( client: any, state: SessionState, sessionId: string, - logger: Logger + logger: Logger, + messages: WithParts[] ): Promise { if (state.sessionId === sessionId) { return; @@ -97,5 +106,14 @@ export async function ensureSessionInitialized( pruneTokenCounter: persisted.stats?.pruneTokenCounter || 0, totalPruneTokens: persisted.stats?.totalPruneTokens || 0, } - state.lastCompaction = persisted.lastCompacted || 0 +} + +function findLastCompactionTimestamp(messages: WithParts[]): number { + for (let i = messages.length - 1; i >= 0; i--) { + const msg = messages[i] + if (msg.info.role === "assistant" && msg.info.summary === true) { + return msg.info.time.created + } + } + return 0 } diff --git a/lib/strategies/prune-tool.ts b/lib/strategies/prune-tool.ts index e361325..6cf9052 100644 --- a/lib/strategies/prune-tool.ts +++ b/lib/strategies/prune-tool.ts @@ -66,14 +66,14 @@ export function createPruneTool( return "No numeric IDs provided. Format: [reason, id1, id2, ...] where reason is 'completion', 'noise', or 'consolidation'." } - await ensureSessionInitialized(ctx.client, state, sessionId, logger) - // Fetch messages to calculate tokens and find current agent const messagesResponse = await client.session.messages({ path: { id: sessionId } }) const messages: WithParts[] = messagesResponse.data || messagesResponse + await ensureSessionInitialized(ctx.client, state, sessionId, logger, messages) + const currentParams = getCurrentParams(messages, logger) const toolIdList: string[] = buildToolIdList(state, messages, logger)