Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 2 additions & 38 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { Plugin } from "@opencode-ai/plugin"
import { getConfig } from "./lib/config"
import { Logger } from "./lib/logger"
import { loadPrompt } from "./lib/prompts"
import { createSessionState } from "./lib/state"
import { createDiscardTool, createExtractTool } from "./lib/strategies"
import { createChatMessageTransformHandler } from "./lib/hooks"
import { createChatMessageTransformHandler, createSystemPromptHandler } from "./lib/hooks"

const plugin: Plugin = (async (ctx) => {
const config = getConfig(ctx)
Expand All @@ -13,11 +12,6 @@ const plugin: Plugin = (async (ctx) => {
return {}
}

// Suppress AI SDK warnings
if (typeof globalThis !== "undefined") {
;(globalThis as any).AI_SDK_LOG_WARNINGS = false
}

const logger = new Logger(config.debug)
const state = createSessionState()

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

return {
"experimental.chat.system.transform": async (
_input: unknown,
output: { system: string[] },
) => {
const systemText = output.system.join("\n")
const internalAgentSignatures = [
"You are a title generator",
"You are a helpful AI assistant tasked with summarizing conversations",
"Summarize what was done in this conversation",
]
if (internalAgentSignatures.some((sig) => systemText.includes(sig))) {
logger.info("Skipping DCP system prompt injection for internal agent")
return
}
"experimental.chat.system.transform": createSystemPromptHandler(state, logger, config),

const discardEnabled = config.tools.discard.enabled
const extractEnabled = config.tools.extract.enabled

let promptName: string
if (discardEnabled && extractEnabled) {
promptName = "user/system/system-prompt-both"
} else if (discardEnabled) {
promptName = "user/system/system-prompt-discard"
} else if (extractEnabled) {
promptName = "user/system/system-prompt-extract"
} else {
return
}

const syntheticPrompt = loadPrompt(promptName)
output.system.push(syntheticPrompt)
},
"experimental.chat.messages.transform": createChatMessageTransformHandler(
ctx.client,
state,
Expand Down
42 changes: 42 additions & 0 deletions lib/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,48 @@ import { syncToolCache } from "./state/tool-cache"
import { deduplicate, supersedeWrites, purgeErrors } from "./strategies"
import { prune, insertPruneToolContext } from "./messages"
import { checkSession } from "./state"
import { loadPrompt } from "./prompts"

const INTERNAL_AGENT_SIGNATURES = [
"You are a title generator",
"You are a helpful AI assistant tasked with summarizing conversations",
"Summarize what was done in this conversation",
]

export function createSystemPromptHandler(
state: SessionState,
logger: Logger,
config: PluginConfig,
) {
return async (_input: unknown, output: { system: string[] }) => {
if (state.isSubAgent) {
return
}

const systemText = output.system.join("\n")
if (INTERNAL_AGENT_SIGNATURES.some((sig) => systemText.includes(sig))) {
logger.info("Skipping DCP system prompt injection for internal agent")
return
}

const discardEnabled = config.tools.discard.enabled
const extractEnabled = config.tools.extract.enabled

let promptName: string
if (discardEnabled && extractEnabled) {
promptName = "user/system/system-prompt-both"
} else if (discardEnabled) {
promptName = "user/system/system-prompt-discard"
} else if (extractEnabled) {
promptName = "user/system/system-prompt-extract"
} else {
return
}

const syntheticPrompt = loadPrompt(promptName)
output.system.push(syntheticPrompt)
}
}

export function createChatMessageTransformHandler(
client: any,
Expand Down