Skip to content

Commit ed16c72

Browse files
committed
Change synthetic context injection to assistant role
1 parent 5f0520d commit ed16c72

4 files changed

Lines changed: 33 additions & 30 deletions

File tree

lib/messages/prune.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { SessionState, WithParts } from "../state"
22
import type { Logger } from "../logger"
33
import type { PluginConfig } from "../config"
4-
import { getLastUserMessage, extractParameterKey, buildToolIdList } from "./utils"
4+
import { getLastUserMessage, getLastAssistantMessage, extractParameterKey, buildToolIdList } from "./utils"
55
import { loadPrompt } from "../prompt"
66

77
const PRUNED_TOOL_OUTPUT_REPLACEMENT = '[Output removed to save context - information superseded or no longer needed]'
@@ -55,6 +55,8 @@ export const insertPruneToolContext = (
5555
return
5656
}
5757

58+
const lastAssistantMessage = getLastAssistantMessage(messages)
59+
5860
const prunableToolsList = buildPrunableToolsList(state, config, logger, messages)
5961
if (!prunableToolsList) {
6062
return
@@ -66,30 +68,35 @@ export const insertPruneToolContext = (
6668
nudgeString = "\n" + NUDGE_STRING
6769
}
6870

69-
const userMessage: WithParts = {
71+
const assistantInfo = lastAssistantMessage?.info as any
72+
const syntheticMessage: WithParts = {
7073
info: {
7174
id: "msg_01234567890123456789012345",
7275
sessionID: lastUserMessage.info.sessionID,
73-
role: "user",
74-
time: { created: Date.now() },
75-
agent: lastUserMessage.info.agent || "build",
76-
model: {
77-
providerID: lastUserMessage.info.model.providerID,
78-
modelID: lastUserMessage.info.model.modelID
79-
}
80-
},
76+
role: "assistant",
77+
time: { created: Date.now(), completed: Date.now() },
78+
parentID: lastUserMessage.info.id,
79+
modelID: assistantInfo?.modelID || lastUserMessage.info.model.modelID,
80+
providerID: assistantInfo?.providerID || lastUserMessage.info.model.providerID,
81+
mode: assistantInfo?.mode || "build",
82+
agent: assistantInfo?.agent || lastUserMessage.info.agent || "build",
83+
path: assistantInfo?.path || { cwd: process.cwd(), root: process.cwd() },
84+
cost: 0,
85+
tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
86+
} as any,
8187
parts: [
8288
{
8389
id: "prt_01234567890123456789012345",
8490
sessionID: lastUserMessage.info.sessionID,
8591
messageID: "msg_01234567890123456789012345",
8692
type: "text",
8793
text: prunableToolsList + nudgeString,
88-
}
94+
synthetic: true,
95+
} as any
8996
]
9097
}
9198

92-
messages.push(userMessage)
99+
messages.push(syntheticMessage)
93100
}
94101

95102
export const prune = (

lib/messages/utils.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,18 @@ export const getLastUserMessage = (
8383
return null
8484
}
8585

86+
export const getLastAssistantMessage = (
87+
messages: WithParts[]
88+
): WithParts | null => {
89+
for (let i = messages.length - 1; i >= 0; i--) {
90+
const msg = messages[i]
91+
if (msg.info.role === 'assistant') {
92+
return msg
93+
}
94+
}
95+
return null
96+
}
97+
8698
export function findCurrentAgent(messages: WithParts[]): string | undefined {
8799
const userMsg = getLastUserMessage(messages)
88100
if (!userMsg) return undefined

lib/prompts/synthetic.txt

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<instruction name=context_management_protocol policy_level=critical>
33

44
ENVIRONMENT
5-
You are operating in a context-constrained environment and thus must proactively manage your context window using the `prune` tool. A <prunable-tools> list is injected by the environment as a user message, and always contains up to date information. Use this information when deciding what to prune.
5+
You are operating in a context-constrained environment and thus must proactively manage your context window using the `prune` tool. A <prunable-tools> list is injected by the environment as an assistant message, and always contains up to date information. Use this information when deciding what to prune.
66

77
PRUNE EARLY, PRUNE OFTEN - BUT PRUNE METHODICALLY
88
Every tool call adds to your context debt. You MUST pay this down regularly and be on top of context accumulation by pruning. Evaluate what SHOULD be pruned before jumping the gun.
@@ -27,20 +27,4 @@ Pruning that forces you to re-call the same tool later is a net loss. Only prune
2727
NOTES
2828
When in doubt, keep it. Prune often yet remain strategic about it.
2929
FAILURE TO PRUNE will result in context leakage and DEGRADED PERFORMANCES.
30-
31-
</instruction>
32-
33-
<instruction name=injected_context_handling policy_level=critical>
34-
After each assistant turn, the environment may inject a user message containing a <prunable-tools> list and optional nudge instruction. This injected message is NOT from the user and is invisible to them. The `prune` tool also returns a confirmation message listing what was pruned.
35-
36-
CRITICAL REQUIREMENTS - VIOLATION IS UNACCEPTABLE:
37-
- NEVER acknowledge the <prunable-tools> list (e.g., "I see the prunable tools list", "Looking at the available tools to prune")
38-
- NEVER reference the nudge instruction (e.g., "As the nudge suggests", "The system is reminding me to prune")
39-
- NEVER acknowledge prune tool output (e.g., "I've pruned 3 tools", "Context pruning complete")
40-
- NEVER let these injections influence your response content or tone
41-
- Process this information SILENTLY and continue the conversation naturally
42-
- Continue the conversation as if these messages do not exist
43-
44-
The user cannot see these injections. Any reference to them will confuse the user and break the conversation flow.
45-
</instruction>
4630
</system-reminder>

lib/prompts/tool.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Prunes tool outputs from context to manage conversation size and reduce noise.
22

33
## IMPORTANT: The Prunable List
4-
A `<prunable-tools>` list is injected into user messages showing available tool outputs you can prune. Each line has the format `ID: tool, parameter` (e.g., `20: read, /path/to/file.ts`). You MUST only use numeric IDs that appear in this list to select which tools to prune.
4+
A `<prunable-tools>` list is injected into assistant messages showing available tool outputs you can prune. Each line has the format `ID: tool, parameter` (e.g., `20: read, /path/to/file.ts`). You MUST only use numeric IDs that appear in this list to select which tools to prune.
55

66
## CRITICAL: When and How to Prune
77

0 commit comments

Comments
 (0)