Skip to content

Commit ae0415c

Browse files
authored
Merge pull request #204 from Opencode-DCP/refactor/remove-assistant-message-injection
refactor: remove assistant message injection support
2 parents 1fc3709 + 79f4a9b commit ae0415c

File tree

12 files changed

+24
-256
lines changed

12 files changed

+24
-256
lines changed

index.ts

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { Plugin } from "@opencode-ai/plugin"
2-
import type { Model } from "@opencode-ai/sdk"
32
import { getConfig } from "./lib/config"
43
import { Logger } from "./lib/logger"
54
import { loadPrompt } from "./lib/prompt"
@@ -27,40 +26,20 @@ const plugin: Plugin = (async (ctx) => {
2726
})
2827

2928
return {
30-
"chat.params": async (
31-
input: { sessionID: string; agent: string; model: Model; provider: any; message: any },
32-
_output: { temperature: number; topP: number; options: Record<string, any> },
33-
) => {
34-
const isReasoning = input.model.capabilities?.reasoning ?? false
35-
if (state.isReasoningModel !== isReasoning) {
36-
logger.info(
37-
`Reasoning model status changed: ${state.isReasoningModel} -> ${isReasoning}`,
38-
{
39-
modelId: input.model.id,
40-
providerId: input.model.providerID,
41-
},
42-
)
43-
}
44-
state.isReasoningModel = isReasoning
45-
},
4629
"experimental.chat.system.transform": async (
4730
_input: unknown,
4831
output: { system: string[] },
4932
) => {
5033
const discardEnabled = config.tools.discard.enabled
5134
const extractEnabled = config.tools.extract.enabled
5235

53-
// Use user-role prompts for reasoning models (second person),
54-
// assistant-role prompts for non-reasoning models (first person)
55-
const roleDir = state.isReasoningModel ? "user" : "assistant"
56-
5736
let promptName: string
5837
if (discardEnabled && extractEnabled) {
59-
promptName = `${roleDir}/system/system-prompt-both`
38+
promptName = "user/system/system-prompt-both"
6039
} else if (discardEnabled) {
61-
promptName = `${roleDir}/system/system-prompt-discard`
40+
promptName = "user/system/system-prompt-discard"
6241
} else if (extractEnabled) {
63-
promptName = `${roleDir}/system/system-prompt-extract`
42+
promptName = "user/system/system-prompt-extract"
6443
} else {
6544
return
6645
}

lib/messages/prune.ts

Lines changed: 20 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,35 @@ import type { SessionState, WithParts } from "../state"
22
import type { Logger } from "../logger"
33
import type { PluginConfig } from "../config"
44
import { loadPrompt } from "../prompt"
5-
import {
6-
extractParameterKey,
7-
buildToolIdList,
8-
createSyntheticUserMessage,
9-
createSyntheticAssistantMessage,
10-
} from "./utils"
11-
import { getLastAssistantMessage, getLastUserMessage, isMessageCompacted } from "../shared-utils"
5+
import { extractParameterKey, buildToolIdList, createSyntheticUserMessage } from "./utils"
6+
import { getLastUserMessage, isMessageCompacted } from "../shared-utils"
127

138
const PRUNED_TOOL_INPUT_REPLACEMENT =
149
"[content removed to save context, this is not what was written to the file, but a placeholder]"
1510
const PRUNED_TOOL_OUTPUT_REPLACEMENT =
1611
"[Output removed to save context - information superseded or no longer needed]"
1712
const PRUNED_TOOL_ERROR_INPUT_REPLACEMENT = "[input removed due to failed tool call]"
1813

19-
const getNudgeString = (config: PluginConfig, isReasoningModel: boolean): string => {
14+
const getNudgeString = (config: PluginConfig): string => {
2015
const discardEnabled = config.tools.discard.enabled
2116
const extractEnabled = config.tools.extract.enabled
22-
const roleDir = isReasoningModel ? "user" : "assistant"
2317

2418
if (discardEnabled && extractEnabled) {
25-
return loadPrompt(`${roleDir}/nudge/nudge-both`)
19+
return loadPrompt(`user/nudge/nudge-both`)
2620
} else if (discardEnabled) {
27-
return loadPrompt(`${roleDir}/nudge/nudge-discard`)
21+
return loadPrompt(`user/nudge/nudge-discard`)
2822
} else if (extractEnabled) {
29-
return loadPrompt(`${roleDir}/nudge/nudge-extract`)
23+
return loadPrompt(`user/nudge/nudge-extract`)
3024
}
3125
return ""
3226
}
3327

34-
const wrapPrunableToolsUser = (content: string): string => `<prunable-tools>
28+
const wrapPrunableTools = (content: string): string => `<prunable-tools>
3529
The following tools have been invoked and are available for pruning. This list does not mandate immediate action. Consider your current goals and the resources you need before discarding valuable tool inputs or outputs. Consolidate your prunes for efficiency; it is rarely worth pruning a single tiny tool output. Keep the context free of noise.
3630
${content}
3731
</prunable-tools>`
3832

39-
const wrapPrunableToolsAssistant = (content: string): string => `<prunable-tools>
40-
I have the following tool outputs available for pruning. I should consider my current goals and the resources I need before discarding valuable inputs or outputs. I should consolidate prunes for efficiency; it is rarely worth pruning a single tiny tool output.
41-
${content}
42-
</prunable-tools>`
43-
44-
const getCooldownMessage = (config: PluginConfig, isReasoningModel: boolean): string => {
33+
const getCooldownMessage = (config: PluginConfig): string => {
4534
const discardEnabled = config.tools.discard.enabled
4635
const extractEnabled = config.tools.extract.enabled
4736

@@ -54,11 +43,9 @@ const getCooldownMessage = (config: PluginConfig, isReasoningModel: boolean): st
5443
toolName = "extract tool"
5544
}
5645

57-
const message = isReasoningModel
58-
? `Context management was just performed. Do not use the ${toolName} again. A fresh list will be available after your next tool use.`
59-
: `I just performed context management. I will not use the ${toolName} again until after my next tool use, when a fresh list will be available.`
60-
61-
return `<prunable-tools>\n${message}\n</prunable-tools>`
46+
return `<prunable-tools>
47+
Context management was just performed. Do not use the ${toolName} again. A fresh list will be available after your next tool use.
48+
</prunable-tools>`
6249
}
6350

6451
const buildPrunableToolsList = (
@@ -74,10 +61,12 @@ const buildPrunableToolsList = (
7461
if (state.prune.toolIds.includes(toolCallId)) {
7562
return
7663
}
64+
7765
const allProtectedTools = config.tools.settings.protectedTools
7866
if (allProtectedTools.includes(toolParameterEntry.tool)) {
7967
return
8068
}
69+
8170
const numericId = toolIdList.indexOf(toolCallId)
8271
if (numericId === -1) {
8372
logger.warn(`Tool in cache but not in toolIdList - possible stale entry`, {
@@ -100,8 +89,7 @@ const buildPrunableToolsList = (
10089
return ""
10190
}
10291

103-
const wrapFn = state.isReasoningModel ? wrapPrunableToolsUser : wrapPrunableToolsAssistant
104-
return wrapFn(lines.join("\n"))
92+
return wrapPrunableTools(lines.join("\n"))
10593
}
10694

10795
export const insertPruneToolContext = (
@@ -114,14 +102,11 @@ export const insertPruneToolContext = (
114102
return
115103
}
116104

117-
// For reasoning models, inject into user role; for non-reasoning, inject into assistant role
118-
const isReasoningModel = state.isReasoningModel
119-
120105
let prunableToolsContent: string
121106

122107
if (state.lastToolPrune) {
123108
logger.debug("Last tool was prune - injecting cooldown message")
124-
prunableToolsContent = getCooldownMessage(config, isReasoningModel)
109+
prunableToolsContent = getCooldownMessage(config)
125110
} else {
126111
const prunableToolsList = buildPrunableToolsList(state, config, logger, messages)
127112
if (!prunableToolsList) {
@@ -136,25 +121,17 @@ export const insertPruneToolContext = (
136121
state.nudgeCounter >= config.tools.settings.nudgeFrequency
137122
) {
138123
logger.info("Inserting prune nudge message")
139-
nudgeString = "\n" + getNudgeString(config, isReasoningModel)
124+
nudgeString = "\n" + getNudgeString(config)
140125
}
141126

142127
prunableToolsContent = prunableToolsList + nudgeString
143128
}
144129

145-
if (isReasoningModel) {
146-
const lastUserMessage = getLastUserMessage(messages)
147-
if (!lastUserMessage) {
148-
return
149-
}
150-
messages.push(createSyntheticUserMessage(lastUserMessage, prunableToolsContent))
151-
} else {
152-
const lastAssistantMessage = getLastAssistantMessage(messages)
153-
if (!lastAssistantMessage) {
154-
return
155-
}
156-
messages.push(createSyntheticAssistantMessage(lastAssistantMessage, prunableToolsContent))
130+
const lastUserMessage = getLastUserMessage(messages)
131+
if (!lastUserMessage) {
132+
return
157133
}
134+
messages.push(createSyntheticUserMessage(lastUserMessage, prunableToolsContent))
158135
}
159136

160137
export const prune = (

lib/messages/utils.ts

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Logger } from "../logger"
22
import { isMessageCompacted } from "../shared-utils"
33
import type { SessionState, WithParts } from "../state"
4-
import type { AssistantMessage, UserMessage } from "@opencode-ai/sdk"
4+
import type { UserMessage } from "@opencode-ai/sdk"
55

66
const SYNTHETIC_MESSAGE_ID = "msg_01234567890123456789012345"
77
const SYNTHETIC_PART_ID = "prt_01234567890123456789012345"
@@ -32,37 +32,6 @@ export const createSyntheticUserMessage = (baseMessage: WithParts, content: stri
3232
}
3333
}
3434

35-
export const createSyntheticAssistantMessage = (
36-
baseMessage: WithParts,
37-
content: string,
38-
): WithParts => {
39-
const assistantInfo = baseMessage.info as AssistantMessage
40-
return {
41-
info: {
42-
id: SYNTHETIC_MESSAGE_ID,
43-
sessionID: assistantInfo.sessionID,
44-
role: "assistant",
45-
parentID: assistantInfo.parentID,
46-
modelID: assistantInfo.modelID,
47-
providerID: assistantInfo.providerID,
48-
time: { created: Date.now() },
49-
tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
50-
cost: 0,
51-
path: assistantInfo.path,
52-
mode: assistantInfo.mode,
53-
},
54-
parts: [
55-
{
56-
id: SYNTHETIC_PART_ID,
57-
sessionID: assistantInfo.sessionID,
58-
messageID: SYNTHETIC_MESSAGE_ID,
59-
type: "text",
60-
text: content,
61-
},
62-
],
63-
}
64-
}
65-
6635
/**
6736
* Extracts a human-readable key from tool metadata for display purposes.
6837
*/

lib/prompts/assistant/nudge/nudge-both.txt

Lines changed: 0 additions & 10 deletions
This file was deleted.

lib/prompts/assistant/nudge/nudge-discard.txt

Lines changed: 0 additions & 9 deletions
This file was deleted.

lib/prompts/assistant/nudge/nudge-extract.txt

Lines changed: 0 additions & 9 deletions
This file was deleted.

lib/prompts/assistant/system/system-prompt-both.txt

Lines changed: 0 additions & 44 deletions
This file was deleted.

lib/prompts/assistant/system/system-prompt-discard.txt

Lines changed: 0 additions & 36 deletions
This file was deleted.

0 commit comments

Comments
 (0)