Skip to content

Commit d7ea156

Browse files
authored
Merge pull request #249 from Opencode-DCP/fix/skip-subagent-system-prompt-injection
fix: skip system prompt injection for subagent sessions
2 parents 4fe0a5c + 9204bd2 commit d7ea156

File tree

2 files changed

+44
-38
lines changed

2 files changed

+44
-38
lines changed

index.ts

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import type { Plugin } from "@opencode-ai/plugin"
22
import { getConfig } from "./lib/config"
33
import { Logger } from "./lib/logger"
4-
import { loadPrompt } from "./lib/prompts"
54
import { createSessionState } from "./lib/state"
65
import { createDiscardTool, createExtractTool } from "./lib/strategies"
7-
import { createChatMessageTransformHandler } from "./lib/hooks"
6+
import { createChatMessageTransformHandler, createSystemPromptHandler } from "./lib/hooks"
87

98
const plugin: Plugin = (async (ctx) => {
109
const config = getConfig(ctx)
@@ -13,11 +12,6 @@ const plugin: Plugin = (async (ctx) => {
1312
return {}
1413
}
1514

16-
// Suppress AI SDK warnings
17-
if (typeof globalThis !== "undefined") {
18-
;(globalThis as any).AI_SDK_LOG_WARNINGS = false
19-
}
20-
2115
const logger = new Logger(config.debug)
2216
const state = createSessionState()
2317

@@ -26,38 +20,8 @@ const plugin: Plugin = (async (ctx) => {
2620
})
2721

2822
return {
29-
"experimental.chat.system.transform": async (
30-
_input: unknown,
31-
output: { system: string[] },
32-
) => {
33-
const systemText = output.system.join("\n")
34-
const internalAgentSignatures = [
35-
"You are a title generator",
36-
"You are a helpful AI assistant tasked with summarizing conversations",
37-
"Summarize what was done in this conversation",
38-
]
39-
if (internalAgentSignatures.some((sig) => systemText.includes(sig))) {
40-
logger.info("Skipping DCP system prompt injection for internal agent")
41-
return
42-
}
23+
"experimental.chat.system.transform": createSystemPromptHandler(state, logger, config),
4324

44-
const discardEnabled = config.tools.discard.enabled
45-
const extractEnabled = config.tools.extract.enabled
46-
47-
let promptName: string
48-
if (discardEnabled && extractEnabled) {
49-
promptName = "user/system/system-prompt-both"
50-
} else if (discardEnabled) {
51-
promptName = "user/system/system-prompt-discard"
52-
} else if (extractEnabled) {
53-
promptName = "user/system/system-prompt-extract"
54-
} else {
55-
return
56-
}
57-
58-
const syntheticPrompt = loadPrompt(promptName)
59-
output.system.push(syntheticPrompt)
60-
},
6125
"experimental.chat.messages.transform": createChatMessageTransformHandler(
6226
ctx.client,
6327
state,

lib/hooks.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,48 @@ import { syncToolCache } from "./state/tool-cache"
55
import { deduplicate, supersedeWrites, purgeErrors } from "./strategies"
66
import { prune, insertPruneToolContext } from "./messages"
77
import { checkSession } from "./state"
8+
import { loadPrompt } from "./prompts"
9+
10+
const INTERNAL_AGENT_SIGNATURES = [
11+
"You are a title generator",
12+
"You are a helpful AI assistant tasked with summarizing conversations",
13+
"Summarize what was done in this conversation",
14+
]
15+
16+
export function createSystemPromptHandler(
17+
state: SessionState,
18+
logger: Logger,
19+
config: PluginConfig,
20+
) {
21+
return async (_input: unknown, output: { system: string[] }) => {
22+
if (state.isSubAgent) {
23+
return
24+
}
25+
26+
const systemText = output.system.join("\n")
27+
if (INTERNAL_AGENT_SIGNATURES.some((sig) => systemText.includes(sig))) {
28+
logger.info("Skipping DCP system prompt injection for internal agent")
29+
return
30+
}
31+
32+
const discardEnabled = config.tools.discard.enabled
33+
const extractEnabled = config.tools.extract.enabled
34+
35+
let promptName: string
36+
if (discardEnabled && extractEnabled) {
37+
promptName = "user/system/system-prompt-both"
38+
} else if (discardEnabled) {
39+
promptName = "user/system/system-prompt-discard"
40+
} else if (extractEnabled) {
41+
promptName = "user/system/system-prompt-extract"
42+
} else {
43+
return
44+
}
45+
46+
const syntheticPrompt = loadPrompt(promptName)
47+
output.system.push(syntheticPrompt)
48+
}
49+
}
850

951
export function createChatMessageTransformHandler(
1052
client: any,

0 commit comments

Comments
 (0)