Skip to content

Commit 0bdcb7f

Browse files
LHMQ878cursoragent
andcommitted
fix: detect internal agents from primary system prompt only
Bundled internal-agent system prompts in the same API call no longer cause DCP to skip nudge injection on main sessions. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 85b6f5c commit 0bdcb7f

2 files changed

Lines changed: 73 additions & 2 deletions

File tree

lib/hooks.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ const INTERNAL_AGENT_SIGNATURES = [
4646
"Summarize what was done in this conversation",
4747
]
4848

49+
function isInternalAgentCall(systemPrompts: string[]): boolean {
50+
const primaryPrompt = systemPrompts[0]
51+
if (typeof primaryPrompt !== "string" || primaryPrompt.length === 0) {
52+
return false
53+
}
54+
55+
return INTERNAL_AGENT_SIGNATURES.some((signature) => primaryPrompt.includes(signature))
56+
}
57+
4958
export function createSystemPromptHandler(
5059
state: SessionState,
5160
logger: Logger,
@@ -65,8 +74,7 @@ export function createSystemPromptHandler(
6574
return
6675
}
6776

68-
const systemText = output.system.join("\n")
69-
if (INTERNAL_AGENT_SIGNATURES.some((sig) => systemText.includes(sig))) {
77+
if (isInternalAgentCall(output.system)) {
7078
logger.info("Skipping DCP system prompt injection for internal agent")
7179
return
7280
}

tests/hooks-permission.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,69 @@ test("system prompt handler caches full model context for percentage thresholds"
114114
assert.equal(state.modelContextLimit, 200000)
115115
})
116116

117+
function buildPromptStore() {
118+
return {
119+
reload() {},
120+
getRuntimePrompts() {
121+
return {
122+
system: "DCP-RUNTIME-PROMPT",
123+
manualExtension: "",
124+
subagentExtension: "",
125+
}
126+
},
127+
} as any
128+
}
129+
130+
test("system prompt handler injects nudges for main session with bundled internal prompts", async () => {
131+
const state = createSessionState()
132+
const handler = createSystemPromptHandler(
133+
state,
134+
new Logger(false),
135+
buildConfig("allow"),
136+
buildPromptStore(),
137+
)
138+
const output = {
139+
system: [
140+
"You are the primary coding assistant for this repository.",
141+
"You are a title generator for short session names.",
142+
],
143+
}
144+
145+
await handler(
146+
{
147+
sessionID: "session-1",
148+
model: { limit: { context: 200000 } },
149+
} as any,
150+
output,
151+
)
152+
153+
assert.match(output.system[output.system.length - 1], /DCP-RUNTIME-PROMPT/)
154+
})
155+
156+
test("system prompt handler skips injection for internal agent calls", async () => {
157+
const state = createSessionState()
158+
const handler = createSystemPromptHandler(
159+
state,
160+
new Logger(false),
161+
buildConfig("allow"),
162+
buildPromptStore(),
163+
)
164+
const output = {
165+
system: ["You are a title generator. Return only a short title."],
166+
}
167+
168+
await handler(
169+
{
170+
sessionID: "session-1",
171+
model: { limit: { context: 200000 } },
172+
} as any,
173+
output,
174+
)
175+
176+
assert.equal(output.system.length, 1)
177+
assert.doesNotMatch(output.system[0], /DCP-RUNTIME-PROMPT/)
178+
})
179+
117180
test("chat message transform strips hallucinated tags even when compress is denied", async () => {
118181
const state = createSessionState()
119182
const logger = new Logger(false)

0 commit comments

Comments
 (0)