11import { tool } from "@opencode-ai/plugin"
22import type { SessionState , ToolParameterEntry , WithParts } from "../state"
33import type { PluginConfig } from "../config"
4- import { findCurrentAgent , buildToolIdList , getPruneToolIds } from "../utils"
4+ import { findCurrentAgent , buildToolIdList , getPruneToolIds , calculateTokensSaved } from "../utils"
55import { PruneReason , sendUnifiedNotification } from "../ui/notification"
66import { formatPruningResultForTool } from "../ui/display-utils"
77import { ensureSessionInitialized } from "../state"
88import { saveSessionState } from "../state/persistence"
99import type { Logger } from "../logger"
10- import { estimateTokensBatch } from "../tokenizer"
1110import { loadPrompt } from "../prompt"
1211
1312/** Tool description loaded from prompts/tool.txt */
@@ -67,29 +66,28 @@ export function createPruneTool(
6766 const messagesResponse = await client . session . messages ( {
6867 path : { id : sessionId }
6968 } )
70- const messages = messagesResponse . data || messagesResponse
69+ const messages : WithParts [ ] = messagesResponse . data || messagesResponse
7170
7271 const currentAgent : string | undefined = findCurrentAgent ( messages )
7372 const toolIdList : string [ ] = buildToolIdList ( messages )
7473 const pruneToolIds : string [ ] = getPruneToolIds ( numericToolIds , toolIdList )
75- const tokensSaved = await calculateTokensSavedFromMessages ( messages , pruneToolIds )
76-
77- state . stats . pruneTokenCounter += tokensSaved
7874 state . prune . toolIds . push ( ...pruneToolIds )
7975
8076 saveSessionState ( state , logger )
81- . catch ( err => logger . error ( "prune-tool" , " Failed to persist state", { error : err . message } ) )
77+ . catch ( err => logger . error ( "Failed to persist state" , { error : err . message } ) )
8278
8379 const toolMetadata = new Map < string , ToolParameterEntry > ( )
8480 for ( const id of pruneToolIds ) {
8581 const toolParameters = state . toolParameters . get ( id )
8682 if ( toolParameters ) {
8783 toolMetadata . set ( id , toolParameters )
8884 } else {
89- logger . debug ( "prune-tool" , " No metadata found for ID", { id } )
85+ logger . debug ( "No metadata found for ID" , { id } )
9086 }
9187 }
9288
89+ state . stats . pruneTokenCounter += calculateTokensSaved ( messages , pruneToolIds )
90+
9391 await sendUnifiedNotification (
9492 client ,
9593 logger ,
@@ -102,6 +100,8 @@ export function createPruneTool(
102100 currentAgent ,
103101 workingDirectory
104102 )
103+ state . stats . totalPruneTokens += state . stats . pruneTokenCounter
104+ state . stats . pruneTokenCounter = 0
105105
106106 return formatPruningResultForTool (
107107 pruneToolIds ,
@@ -112,50 +112,3 @@ export function createPruneTool(
112112 } )
113113}
114114
115- /**
116- * Calculates approximate tokens saved by pruning the given tool call IDs.
117- * Uses pre-fetched messages to avoid duplicate API calls.
118- */
119- async function calculateTokensSavedFromMessages (
120- messages : any [ ] ,
121- prunedIds : string [ ]
122- ) : Promise < number > {
123- try {
124- const toolOutputs = new Map < string , string > ( )
125- for ( const msg of messages ) {
126- if ( msg . role === 'tool' && msg . tool_call_id ) {
127- const content = typeof msg . content === 'string'
128- ? msg . content
129- : JSON . stringify ( msg . content )
130- toolOutputs . set ( msg . tool_call_id . toLowerCase ( ) , content )
131- }
132- if ( msg . role === 'user' && Array . isArray ( msg . content ) ) {
133- for ( const part of msg . content ) {
134- if ( part . type === 'tool_result' && part . tool_use_id ) {
135- const content = typeof part . content === 'string'
136- ? part . content
137- : JSON . stringify ( part . content )
138- toolOutputs . set ( part . tool_use_id . toLowerCase ( ) , content )
139- }
140- }
141- }
142- }
143-
144- const contents : string [ ] = [ ]
145- for ( const id of prunedIds ) {
146- const content = toolOutputs . get ( id . toLowerCase ( ) )
147- if ( content ) {
148- contents . push ( content )
149- }
150- }
151-
152- if ( contents . length === 0 ) {
153- return prunedIds . length * 500
154- }
155-
156- const tokenCounts = await estimateTokensBatch ( contents )
157- return tokenCounts . reduce ( ( sum , count ) => sum + count , 0 )
158- } catch ( error : any ) {
159- return prunedIds . length * 500
160- }
161- }
0 commit comments