Skip to content

Commit d386032

Browse files
authored
Merge pull request #273 from Opencode-DCP/dev
merge dev into master
2 parents f0bdb8c + 4c4f021 commit d386032

12 files changed

Lines changed: 85 additions & 76 deletions

File tree

lib/messages/inject.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { loadPrompt } from "../prompts"
66
import {
77
extractParameterKey,
88
buildToolIdList,
9-
createSyntheticAssistantMessageWithToolPart,
9+
createSyntheticAssistantMessage,
1010
isIgnoredUserMessage,
1111
} from "./utils"
1212
import { getFilePathFromParameters, isProtectedFilePath } from "../protected-file-patterns"
@@ -149,7 +149,5 @@ export const insertPruneToolContext = (
149149

150150
const userInfo = lastUserMessage.info as UserMessage
151151
const variant = state.variant ?? userInfo.variant
152-
messages.push(
153-
createSyntheticAssistantMessageWithToolPart(lastUserMessage, prunableToolsContent, variant),
154-
)
152+
messages.push(createSyntheticAssistantMessage(lastUserMessage, prunableToolsContent, variant))
155153
}

lib/messages/utils.ts

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const isGeminiModel = (modelID: string): boolean => {
1212
return lowerModelID.includes("gemini")
1313
}
1414

15-
export const createSyntheticAssistantMessageWithToolPart = (
15+
export const createSyntheticAssistantMessage = (
1616
baseMessage: WithParts,
1717
content: string,
1818
variant?: string,
@@ -39,24 +39,11 @@ export const createSyntheticAssistantMessageWithToolPart = (
3939
...(variant !== undefined && { variant }),
4040
}
4141

42-
// For Gemini models, inject as text to avoid thought signature requirements
43-
// Gemini 3+ has strict validation requiring thoughtSignature on functionCall parts
44-
if (isGeminiModel(userInfo.model.modelID)) {
45-
return {
46-
info: baseInfo,
47-
parts: [
48-
{
49-
id: SYNTHETIC_PART_ID,
50-
sessionID: userInfo.sessionID,
51-
messageID: SYNTHETIC_MESSAGE_ID,
52-
type: "text",
53-
text: content,
54-
},
55-
],
56-
}
57-
}
42+
// For Gemini models, add thoughtSignature bypass to avoid validation errors
43+
const toolPartMetadata = isGeminiModel(userInfo.model.modelID)
44+
? { google: { thoughtSignature: "skip_thought_signature_validator" } }
45+
: undefined
5846

59-
// For other models, use tool part for cleaner context
6047
return {
6148
info: baseInfo,
6249
parts: [
@@ -75,6 +62,7 @@ export const createSyntheticAssistantMessageWithToolPart = (
7562
metadata: {},
7663
time: { start: now, end: now },
7764
},
65+
...(toolPartMetadata && { metadata: toolPartMetadata }),
7866
},
7967
],
8068
}
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
Discards tool outputs from context to manage conversation size and reduce noise.
1+
export const DISCARD_TOOL_SPEC = `Discards tool outputs from context to manage conversation size and reduce noise.
22
33
## IMPORTANT: The Prunable List
4-
A `<prunable-tools>` list is provided to you showing available tool outputs you can discard when there are tools available for pruning. 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 discard.
4+
A \`<prunable-tools>\` list is provided to you showing available tool outputs you can discard when there are tools available for pruning. 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 discard.
55
66
## When to Use This Tool
77
8-
Use `discard` for removing tool content that is no longer needed
8+
Use \`discard\` for removing tool content that is no longer needed
99
1010
- **Noise:** Irrelevant, unhelpful, or superseded outputs that provide no value.
1111
- **Task Completion:** Work is complete and there's no valuable information worth preserving.
1212
1313
## When NOT to Use This Tool
1414
15-
- **If the output contains useful information:** Use `extract` instead to preserve key findings.
15+
- **If the output contains useful information:** Use \`extract\` instead to preserve key findings.
1616
- **If you'll need the output later:** Don't discard files you plan to edit or context you'll need for implementation.
1717
1818
## Best Practices
@@ -21,9 +21,9 @@ Use `discard` for removing tool content that is no longer needed
2121
2222
## Format
2323
24-
- `ids`: Array where the first element is the reason, followed by numeric IDs from the `<prunable-tools>` list
24+
- \`ids\`: Array where the first element is the reason, followed by numeric IDs from the \`<prunable-tools>\` list
2525
26-
Reasons: `noise` | `completion`
26+
Reasons: \`noise\` | \`completion\`
2727
2828
## Example
2929
@@ -37,5 +37,4 @@ This file isn't relevant to the auth system. I'll remove it to clear the context
3737
Assistant: [Runs tests, they pass]
3838
The tests passed and I don't need to preserve any details. I'll clean up now.
3939
[Uses discard with ids: ["completion", "20", "21"]]
40-
</example_completion>
41-
40+
</example_completion>`
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
Extracts key findings from tool outputs into distilled knowledge, then removes the raw outputs from context.
1+
export const EXTRACT_TOOL_SPEC = `Extracts key findings from tool outputs into distilled knowledge, then removes the raw outputs from context.
22
33
## IMPORTANT: The Prunable List
4-
A `<prunable-tools>` list is provided to you showing available tool outputs you can extract from when there are tools available for pruning. 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 extract.
4+
A \`<prunable-tools>\` list is provided to you showing available tool outputs you can extract from when there are tools available for pruning. 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 extract.
55
66
## When to Use This Tool
77
8-
Use `extract` when you have gathered useful information that you want to **preserve in distilled form** before removing the raw outputs:
8+
Use \`extract\` when you have gathered useful information that you want to **preserve in distilled form** before removing the raw outputs:
99
1010
- **Task Completion:** You completed a unit of work and want to preserve key findings.
1111
- **Knowledge Preservation:** You have context that contains valuable information, but also a lot of unnecessary detail - you only need to preserve some specifics.
@@ -22,8 +22,8 @@ Use `extract` when you have gathered useful information that you want to **prese
2222
2323
## Format
2424
25-
- `ids`: Array of numeric IDs as strings from the `<prunable-tools>` list
26-
- `distillation`: Array of strings, one per ID (positional: distillation[0] is for ids[0], etc.)
25+
- \`ids\`: Array of numeric IDs as strings from the \`<prunable-tools>\` list
26+
- \`distillation\`: Array of strings, one per ID (positional: distillation[0] is for ids[0], etc.)
2727
2828
Each distillation string should capture the essential information you need to preserve - function signatures, logic, constraints, values, etc. Be as detailed as needed for your task.
2929
@@ -44,4 +44,4 @@ I'll preserve the key details before extracting.
4444
<example_keep>
4545
Assistant: [Reads 'auth.ts' to understand the login flow]
4646
I've understood the auth flow. I'll need to modify this file to add the new validation, so I'm keeping this read in context rather than extracting.
47-
</example_keep>
47+
</example_keep>`

lib/prompts/index.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,33 @@
1-
import { readFileSync } from "fs"
2-
import { join } from "path"
1+
// Tool specs
2+
import { DISCARD_TOOL_SPEC } from "./discard-tool-spec"
3+
import { EXTRACT_TOOL_SPEC } from "./extract-tool-spec"
4+
5+
// System prompts
6+
import { SYSTEM_PROMPT_BOTH } from "./system/both"
7+
import { SYSTEM_PROMPT_DISCARD } from "./system/discard"
8+
import { SYSTEM_PROMPT_EXTRACT } from "./system/extract"
9+
10+
// Nudge prompts
11+
import { NUDGE_BOTH } from "./nudge/both"
12+
import { NUDGE_DISCARD } from "./nudge/discard"
13+
import { NUDGE_EXTRACT } from "./nudge/extract"
14+
15+
const PROMPTS: Record<string, string> = {
16+
"discard-tool-spec": DISCARD_TOOL_SPEC,
17+
"extract-tool-spec": EXTRACT_TOOL_SPEC,
18+
"system/system-prompt-both": SYSTEM_PROMPT_BOTH,
19+
"system/system-prompt-discard": SYSTEM_PROMPT_DISCARD,
20+
"system/system-prompt-extract": SYSTEM_PROMPT_EXTRACT,
21+
"nudge/nudge-both": NUDGE_BOTH,
22+
"nudge/nudge-discard": NUDGE_DISCARD,
23+
"nudge/nudge-extract": NUDGE_EXTRACT,
24+
}
325

426
export function loadPrompt(name: string, vars?: Record<string, string>): string {
5-
const filePath = join(__dirname, `${name}.txt`)
6-
let content = readFileSync(filePath, "utf8").trim()
27+
let content = PROMPTS[name]
28+
if (!content) {
29+
throw new Error(`Prompt not found: ${name}`)
30+
}
731
if (vars) {
832
for (const [key, value] of Object.entries(vars)) {
933
content = content.replace(new RegExp(`\\{\\{${key}\\}\\}`, "g"), value)
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
<instruction name=context_management_required>
1+
export const NUDGE_BOTH = `<instruction name=context_management_required>
22
**CRITICAL CONTEXT WARNING:** Your context window is filling with tool outputs. Strict adherence to context hygiene is required.
33
44
**Immediate Actions Required:**
5-
1. **Task Completion:** If a sub-task is complete, decide: use `discard` if no valuable context to preserve (default), or use `extract` if insights are worth keeping.
6-
2. **Noise Removal:** If you read files or ran commands that yielded no value, use `discard` to remove them.
7-
3. **Knowledge Preservation:** If you are holding valuable raw data you'll need to reference later, use `extract` to distill the insights and remove the raw entry.
5+
1. **Task Completion:** If a sub-task is complete, decide: use \`discard\` if no valuable context to preserve (default), or use \`extract\` if insights are worth keeping.
6+
2. **Noise Removal:** If you read files or ran commands that yielded no value, use \`discard\` to remove them.
7+
3. **Knowledge Preservation:** If you are holding valuable raw data you'll need to reference later, use \`extract\` to distill the insights and remove the raw entry.
88
99
**Protocol:** You should prioritize this cleanup, but do not interrupt a critical atomic operation if one is in progress. Once the immediate step is done, you must perform context management.
10-
</instruction>
10+
</instruction>`
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
<instruction name=context_management_required>
1+
export const NUDGE_DISCARD = `<instruction name=context_management_required>
22
**CRITICAL CONTEXT WARNING:** Your context window is filling with tool outputs. Strict adherence to context hygiene is required.
33
44
**Immediate Actions Required:**
5-
1. **Task Completion:** If a sub-task is complete, use the `discard` tool to remove the tools used.
6-
2. **Noise Removal:** If you read files or ran commands that yielded no value, use the `discard` tool to remove them.
5+
1. **Task Completion:** If a sub-task is complete, use the \`discard\` tool to remove the tools used.
6+
2. **Noise Removal:** If you read files or ran commands that yielded no value, use the \`discard\` tool to remove them.
77
88
**Protocol:** You should prioritize this cleanup, but do not interrupt a critical atomic operation if one is in progress. Once the immediate step is done, you must discard unneeded tool outputs.
9-
</instruction>
9+
</instruction>`
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
<instruction name=context_management_required>
1+
export const NUDGE_EXTRACT = `<instruction name=context_management_required>
22
**CRITICAL CONTEXT WARNING:** Your context window is filling with tool outputs. Strict adherence to context hygiene is required.
33
44
**Immediate Actions Required:**
55
1. **Task Completion:** If you have completed work, extract key findings from the tools used. Scale distillation depth to the value of the content.
6-
2. **Knowledge Preservation:** If you are holding valuable raw data you'll need to reference later, use the `extract` tool with high-fidelity distillation to preserve the insights and remove the raw entry.
6+
2. **Knowledge Preservation:** If you are holding valuable raw data you'll need to reference later, use the \`extract\` tool with high-fidelity distillation to preserve the insights and remove the raw entry.
77
88
**Protocol:** You should prioritize this cleanup, but do not interrupt a critical atomic operation if one is in progress. Once the immediate step is done, you must extract valuable findings from tool outputs.
9-
</instruction>
9+
</instruction>`
Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
<system-reminder>
1+
export const SYSTEM_PROMPT_BOTH = `<system-reminder>
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 `discard` and `extract` tools. 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 \`discard\` and \`extract\` tools. 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.
66
77
TWO TOOLS FOR CONTEXT MANAGEMENT
8-
- `discard`: Remove tool outputs that are no longer needed (completed tasks, noise, outdated info). No preservation of content.
9-
- `extract`: Extract key findings into distilled knowledge before removing raw outputs. Use when you need to preserve information.
8+
- \`discard\`: Remove tool outputs that are no longer needed (completed tasks, noise, outdated info). No preservation of content.
9+
- \`extract\`: Extract key findings into distilled knowledge before removing raw outputs. Use when you need to preserve information.
1010
1111
CHOOSING THE RIGHT TOOL
1212
Ask: "Do I need to preserve any information from this output?"
13-
- **No** → `discard` (default for cleanup)
14-
- **Yes** → `extract` (preserves distilled knowledge)
15-
- **Uncertain** → `extract` (safer, preserves signal)
13+
- **No** → \`discard\` (default for cleanup)
14+
- **Yes** → \`extract\` (preserves distilled knowledge)
15+
- **Uncertain** → \`extract\` (safer, preserves signal)
1616
1717
Common scenarios:
18-
- Task complete, no valuable context → `discard`
19-
- Task complete, insights worth remembering → `extract`
20-
- Noise, irrelevant, or superseded outputs → `discard`
21-
- Valuable context needed later but raw output too large → `extract`
18+
- Task complete, no valuable context → \`discard\`
19+
- Task complete, insights worth remembering → \`extract\`
20+
- Noise, irrelevant, or superseded outputs → \`discard\`
21+
- Valuable context needed later but raw output too large → \`extract\`
2222
2323
PRUNE METHODICALLY - BATCH YOUR ACTIONS
2424
Every tool call adds to your context debt. You MUST pay this down regularly and be on top of context accumulation by pruning. Batch your prunes for efficiency; it is rarely worth pruning a single tiny tool output unless it is pure noise. Evaluate what SHOULD be pruned before jumping the gun.
@@ -42,7 +42,7 @@ There may be tools in session context that do not appear in the <prunable-tools>
4242
</instruction>
4343
4444
<instruction name=injected_context_handling policy_level=critical>
45-
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 `discard` and `extract` tools also return a confirmation message listing what was pruned.
45+
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 \`discard\` and \`extract\` tools also return a confirmation message listing what was pruned.
4646
4747
CRITICAL REQUIREMENTS - VIOLATION IS UNACCEPTABLE:
4848
- NEVER reference the prune encouragement or context management instructions. Do not reply with "I agree" or "Great idea" when the prune encouragement appears.
@@ -55,4 +55,4 @@ CRITICAL REQUIREMENTS - VIOLATION IS UNACCEPTABLE:
5555
5656
The user cannot see these injections. Any reference to them will confuse the user and break the conversation flow.
5757
</instruction>
58-
</system-reminder>
58+
</system-reminder>`

lib/prompts/system/system-prompt-discard.txt renamed to lib/prompts/system/discard.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
<system-reminder>
1+
export const SYSTEM_PROMPT_DISCARD = `<system-reminder>
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 `discard` 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 discard.
5+
You are operating in a context-constrained environment and thus must proactively manage your context window using the \`discard\` 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 discard.
66
77
CONTEXT MANAGEMENT TOOL
8-
- `discard`: Remove tool outputs that are no longer needed (completed tasks, noise, outdated info). No preservation of content.
8+
- \`discard\`: Remove tool outputs that are no longer needed (completed tasks, noise, outdated info). No preservation of content.
99
1010
DISCARD METHODICALLY - BATCH YOUR ACTIONS
1111
Every tool call adds to your context debt. You MUST pay this down regularly and be on top of context accumulation by discarding. Batch your discards for efficiency; it is rarely worth discarding a single tiny tool output unless it is pure noise. Evaluate what SHOULD be discarded before jumping the gun.
@@ -33,7 +33,7 @@ There may be tools in session context that do not appear in the <prunable-tools>
3333
</instruction>
3434
3535
<instruction name=injected_context_handling policy_level=critical>
36-
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 `discard` tool also returns a confirmation message listing what was discarded.
36+
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 \`discard\` tool also returns a confirmation message listing what was discarded.
3737
3838
CRITICAL REQUIREMENTS - VIOLATION IS UNACCEPTABLE:
3939
- NEVER reference the discard encouragement or context management instructions. Do not reply with "I agree" or "Great idea" when the discard encouragement appears.
@@ -46,4 +46,4 @@ CRITICAL REQUIREMENTS - VIOLATION IS UNACCEPTABLE:
4646
4747
The user cannot see these injections. Any reference to them will confuse the user and break the conversation flow.
4848
</instruction>
49-
</system-reminder>
49+
</system-reminder>`

0 commit comments

Comments
 (0)