diff --git a/packages/opencode/src/session/compaction.ts b/packages/opencode/src/session/compaction.ts index 3e4c8020dee..549769a1c24 100644 --- a/packages/opencode/src/session/compaction.ts +++ b/packages/opencode/src/session/compaction.ts @@ -126,12 +126,15 @@ export namespace SessionCompaction { model, abort: input.abort, }) - // Allow plugins to inject context for compaction + // Allow plugins to inject context or replace compaction prompt const compacting = await Plugin.trigger( "experimental.session.compacting", { sessionID: input.sessionID }, - { context: [] }, + { context: [], prompt: undefined }, ) + const defaultPrompt = + "Provide a detailed prompt for continuing our conversation above. Focus on information that would be helpful for continuing the conversation, including what we did, what we're doing, which files we're working on, and what we're going to do next considering new session will not have access to our conversation." + const promptText = compacting.prompt ?? [defaultPrompt, ...compacting.context].join("\n\n") const result = await processor.process({ user: userMessage, agent, @@ -146,10 +149,7 @@ export namespace SessionCompaction { content: [ { type: "text", - text: [ - "Provide a detailed prompt for continuing our conversation above. Focus on information that would be helpful for continuing the conversation, including what we did, what we're doing, which files we're working on, and what we're going to do next considering new session will not have access to our conversation.", - ...compacting.context, - ].join("\n\n"), + text: promptText, }, ], }, diff --git a/packages/plugin/src/index.ts b/packages/plugin/src/index.ts index 487e6ed3ee2..fbc0e710c83 100644 --- a/packages/plugin/src/index.ts +++ b/packages/plugin/src/index.ts @@ -192,10 +192,16 @@ export interface Hooks { }, ) => Promise /** - * Called before session compaction starts. Allows plugins to append - * additional context to the compaction prompt. + * Called before session compaction starts. Allows plugins to customize + * the compaction prompt. + * + * - `context`: Additional context strings appended to the default prompt + * - `prompt`: If set, replaces the default compaction prompt entirely */ - "experimental.session.compacting"?: (input: { sessionID: string }, output: { context: string[] }) => Promise + "experimental.session.compacting"?: ( + input: { sessionID: string }, + output: { context: string[]; prompt?: string }, + ) => Promise "experimental.text.complete"?: ( input: { sessionID: string; messageID: string; partID: string }, output: { text: string }, diff --git a/packages/web/src/content/docs/plugins.mdx b/packages/web/src/content/docs/plugins.mdx index 6982b4c932f..6be545482c1 100644 --- a/packages/web/src/content/docs/plugins.mdx +++ b/packages/web/src/content/docs/plugins.mdx @@ -233,3 +233,30 @@ Include any state that should persist across compaction: ``` The `experimental.session.compacting` hook fires before the LLM generates a continuation summary. Use it to inject domain-specific context that the default compaction prompt would miss. + +You can also replace the compaction prompt entirely by setting `output.prompt`: + +```ts title=".opencode/plugin/custom-compaction.ts" +import type { Plugin } from "@opencode-ai/plugin" + +export const CustomCompactionPlugin: Plugin = async (ctx) => { + return { + "experimental.session.compacting": async (input, output) => { + // Replace the entire compaction prompt + output.prompt = ` +You are generating a continuation prompt for a multi-agent swarm session. + +Summarize: +1. The current task and its status +2. Which files are being modified and by whom +3. Any blockers or dependencies between agents +4. The next steps to complete the work + +Format as a structured prompt that a new agent can use to resume work. +` + }, + } +} +``` + +When `output.prompt` is set, it completely replaces the default compaction prompt. The `output.context` array is ignored in this case.