@@ -2,12 +2,15 @@ import type { SessionState, WithParts } from "../state"
22import type { Logger } from "../logger"
33import type { PluginConfig } from "../config"
44import type { UserMessage } from "@opencode-ai/sdk/v2"
5+ import { formatMessageIdTag } from "../message-ids"
56import { renderNudge , renderCompressNudge } from "../prompts"
67import {
78 extractParameterKey ,
89 createSyntheticTextPart ,
910 createSyntheticToolPart ,
1011 isIgnoredUserMessage ,
12+ appendMessageIdTagToToolOutput ,
13+ findLastToolPart ,
1114} from "./utils"
1215import { getFilePathsFromParameters , isProtected } from "../protected-file-patterns"
1316import { getLastUserMessage , isMessageCompacted } from "../shared-utils"
@@ -38,7 +41,7 @@ ${content}
3841export const wrapCompressContext = ( messageCount : number ) : string => `<compress-context>
3942Compress available. Conversation: ${ messageCount } messages.
4043Compress collapses completed task sequences or exploration phases into summaries.
41- Uses text boundaries [startString, endString , topic, summary].
44+ Uses ID boundaries [startId, endId , topic, summary].
4245</compress-context>`
4346
4447export const wrapCooldownMessage = ( flags : {
@@ -274,7 +277,7 @@ export const insertPruneToolContext = (
274277 contentParts . push ( renderCompressNudge ( ) )
275278 } else if (
276279 config . tools . settings . nudgeEnabled &&
277- state . nudgeCounter >= config . tools . settings . nudgeFrequency
280+ state . nudgeCounter >= Math . max ( 1 , config . tools . settings . nudgeFrequency )
278281 ) {
279282 logger . info ( "Inserting prune nudge message" )
280283 contentParts . push ( getNudgeString ( config ) )
@@ -291,8 +294,6 @@ export const insertPruneToolContext = (
291294 return
292295 }
293296
294- const userInfo = lastUserMessage . info as UserMessage
295-
296297 const lastNonIgnoredMessage = messages . findLast (
297298 ( msg ) => ! ( msg . info . role === "user" && isIgnoredUserMessage ( msg ) ) ,
298299 )
@@ -306,11 +307,56 @@ export const insertPruneToolContext = (
306307 // For all other cases, append a synthetic tool part to the last message which works
307308 // across all models without disrupting their behavior.
308309 if ( lastNonIgnoredMessage . info . role === "user" ) {
309- const textPart = createSyntheticTextPart ( lastNonIgnoredMessage , combinedContent )
310+ const textPart = createSyntheticTextPart (
311+ lastNonIgnoredMessage ,
312+ combinedContent ,
313+ `${ lastNonIgnoredMessage . info . id } :context` ,
314+ )
310315 lastNonIgnoredMessage . parts . push ( textPart )
311316 } else {
312- const modelID = userInfo . model ?. modelID || ""
313- const toolPart = createSyntheticToolPart ( lastNonIgnoredMessage , combinedContent , modelID )
317+ const toolPart = createSyntheticToolPart (
318+ lastNonIgnoredMessage ,
319+ combinedContent ,
320+ modelId ?? "" ,
321+ `${ lastNonIgnoredMessage . info . id } :context` ,
322+ )
314323 lastNonIgnoredMessage . parts . push ( toolPart )
315324 }
316325}
326+
327+ export const insertMessageIdContext = ( state : SessionState , messages : WithParts [ ] ) : void => {
328+ const lastUserMessage = getLastUserMessage ( messages )
329+ const toolModelId = lastUserMessage
330+ ? ( ( lastUserMessage . info as UserMessage ) . model . modelID ?? "" )
331+ : ""
332+
333+ for ( const message of messages ) {
334+ if ( message . info . role === "user" && isIgnoredUserMessage ( message ) ) {
335+ continue
336+ }
337+
338+ const messageRef = state . messageIds . byRawId . get ( message . info . id )
339+ if ( ! messageRef ) {
340+ continue
341+ }
342+
343+ const tag = formatMessageIdTag ( messageRef )
344+ const messageIdSeed = `${ message . info . id } :message-id:${ messageRef } `
345+
346+ if ( message . info . role === "user" ) {
347+ message . parts . push ( createSyntheticTextPart ( message , tag , messageIdSeed ) )
348+ continue
349+ }
350+
351+ if ( message . info . role !== "assistant" ) {
352+ continue
353+ }
354+
355+ const lastToolPart = findLastToolPart ( message )
356+ if ( lastToolPart && appendMessageIdTagToToolOutput ( lastToolPart , tag ) ) {
357+ continue
358+ }
359+
360+ message . parts . push ( createSyntheticToolPart ( message , tag , toolModelId , messageIdSeed ) )
361+ }
362+ }
0 commit comments