From c539f176ccfda56183da6beee874cd3cab227348 Mon Sep 17 00:00:00 2001 From: Daniel Smolsky Date: Sun, 30 Nov 2025 13:51:52 -0500 Subject: [PATCH 1/2] fix: preserve agent context when sending pruning notifications When the context_pruning tool or idle pruning runs while an agent (such as 'build') is active, the notification message should be sent with the same agent context. This prevents the notification from incorrectly appearing outside the agent's message flow. The fix extracts the current agent from the last user message and passes it through the notification chain to sendIgnoredMessage, which includes it in the session.prompt call. --- lib/janitor.ts | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/lib/janitor.ts b/lib/janitor.ts index 24ffb299..5a2b2f02 100644 --- a/lib/janitor.ts +++ b/lib/janitor.ts @@ -44,12 +44,13 @@ export class Janitor { private workingDirectory?: string ) { } - private async sendIgnoredMessage(sessionID: string, text: string) { + private async sendIgnoredMessage(sessionID: string, text: string, agent?: string) { try { await this.client.session.prompt({ path: { id: sessionID }, body: { noReply: true, + agent: agent, parts: [{ type: 'text', text: text, @@ -96,6 +97,18 @@ export class Janitor { return null } + // Extract the current agent from the last user message to preserve agent context + // Following the same pattern as OpenCode's server.ts + let currentAgent: string | undefined = undefined + for (let i = messages.length - 1; i >= 0; i--) { + const msg = messages[i] + const info = msg.info + if (info?.role === 'user') { + currentAgent = info.agent || 'build' + break + } + } + const toolCallIds: string[] = [] const toolOutputs = new Map() const toolMetadata = new Map() @@ -299,7 +312,8 @@ export class Janitor { expandedLlmPrunedIds, toolMetadata, tokensSaved, - sessionStats + sessionStats, + currentAgent ) } else { await this.sendAutoModeNotification( @@ -307,7 +321,8 @@ export class Janitor { deduplicatedIds, deduplicationDetails, tokensSaved, - sessionStats + sessionStats, + currentAgent ) } @@ -534,7 +549,8 @@ export class Janitor { sessionID: string, totalPruned: number, tokensSaved: number, - sessionStats: SessionStats + sessionStats: SessionStats, + agent?: string ) { if (totalPruned === 0) return @@ -547,7 +563,7 @@ export class Janitor { message += ` │ Session: ~${formatTokenCount(sessionStats.totalTokensSaved)} tokens, ${sessionStats.totalToolsPruned} tools` } - await this.sendIgnoredMessage(sessionID, message) + await this.sendIgnoredMessage(sessionID, message, agent) } private async sendAutoModeNotification( @@ -555,13 +571,14 @@ export class Janitor { deduplicatedIds: string[], deduplicationDetails: Map, tokensSaved: number, - sessionStats: SessionStats + sessionStats: SessionStats, + agent?: string ) { if (deduplicatedIds.length === 0) return if (this.pruningSummary === 'off') return if (this.pruningSummary === 'minimal') { - await this.sendMinimalNotification(sessionID, deduplicatedIds.length, tokensSaved, sessionStats) + await this.sendMinimalNotification(sessionID, deduplicatedIds.length, tokensSaved, sessionStats, agent) return } @@ -590,7 +607,7 @@ export class Janitor { } } - await this.sendIgnoredMessage(sessionID, message.trim()) + await this.sendIgnoredMessage(sessionID, message.trim(), agent) } formatPruningResultForTool(result: PruningResult): string { @@ -621,14 +638,15 @@ export class Janitor { llmPrunedIds: string[], toolMetadata: Map, tokensSaved: number, - sessionStats: SessionStats + sessionStats: SessionStats, + agent?: string ) { const totalPruned = deduplicatedIds.length + llmPrunedIds.length if (totalPruned === 0) return if (this.pruningSummary === 'off') return if (this.pruningSummary === 'minimal') { - await this.sendMinimalNotification(sessionID, totalPruned, tokensSaved, sessionStats) + await this.sendMinimalNotification(sessionID, totalPruned, tokensSaved, sessionStats, agent) return } @@ -680,6 +698,6 @@ export class Janitor { } } - await this.sendIgnoredMessage(sessionID, message.trim()) + await this.sendIgnoredMessage(sessionID, message.trim(), agent) } } From ac68e28511b44080f3f007ec66ffd6c8248ae31d Mon Sep 17 00:00:00 2001 From: Daniel Smolsky Date: Sun, 30 Nov 2025 13:52:12 -0500 Subject: [PATCH 2/2] v0.3.26 - Bump version --- README.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1d937923..8dd9e568 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Add to your OpenCode config: ```jsonc // opencode.jsonc { - "plugin": ["@tarquinen/opencode-dcp@0.3.25"] + "plugin": ["@tarquinen/opencode-dcp@0.3.26"] } ``` diff --git a/package-lock.json b/package-lock.json index 9b944338..a90cd2ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@tarquinen/opencode-dcp", - "version": "0.3.25", + "version": "0.3.26", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@tarquinen/opencode-dcp", - "version": "0.3.25", + "version": "0.3.26", "license": "MIT", "dependencies": { "@ai-sdk/openai-compatible": "^1.0.27", diff --git a/package.json b/package.json index 6242e485..96a8b3b7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@tarquinen/opencode-dcp", - "version": "0.3.25", + "version": "0.3.26", "type": "module", "description": "OpenCode plugin that optimizes token usage by pruning obsolete tool outputs from conversation context", "main": "./dist/index.js",