diff --git a/index.ts b/index.ts index 13df1b0..28b4a6c 100644 --- a/index.ts +++ b/index.ts @@ -68,6 +68,21 @@ const plugin: Plugin = (async (ctx) => { logger, config, ), + "chat.message": async ( + input: { + sessionID: string + agent?: string + model?: { providerID: string; modelID: string } + messageID?: string + variant?: string + }, + _output: any, + ) => { + // Cache variant from real user messages (not synthetic) + // This avoids scanning all messages to find variant + state.variant = input.variant + logger.debug("Cached variant from chat.message hook", { variant: input.variant }) + }, tool: { ...(config.tools.discard.enabled && { discard: createDiscardTool({ diff --git a/lib/messages/inject.ts b/lib/messages/inject.ts index debfd83..11153b7 100644 --- a/lib/messages/inject.ts +++ b/lib/messages/inject.ts @@ -1,6 +1,7 @@ import type { SessionState, WithParts } from "../state" import type { Logger } from "../logger" import type { PluginConfig } from "../config" +import type { UserMessage } from "@opencode-ai/sdk/v2" import { loadPrompt } from "../prompts" import { extractParameterKey, buildToolIdList, createSyntheticUserMessage } from "./utils" import { getLastUserMessage } from "../shared-utils" @@ -125,5 +126,6 @@ export const insertPruneToolContext = ( if (!lastUserMessage) { return } - messages.push(createSyntheticUserMessage(lastUserMessage, prunableToolsContent)) + const variant = state.variant ?? (lastUserMessage.info as UserMessage).variant + messages.push(createSyntheticUserMessage(lastUserMessage, prunableToolsContent, variant)) } diff --git a/lib/messages/utils.ts b/lib/messages/utils.ts index 88dd75a..0338d86 100644 --- a/lib/messages/utils.ts +++ b/lib/messages/utils.ts @@ -1,14 +1,17 @@ import { Logger } from "../logger" import { isMessageCompacted } from "../shared-utils" import type { SessionState, WithParts } from "../state" -import type { UserMessage } from "@opencode-ai/sdk" +import type { UserMessage } from "@opencode-ai/sdk/v2" const SYNTHETIC_MESSAGE_ID = "msg_01234567890123456789012345" const SYNTHETIC_PART_ID = "prt_01234567890123456789012345" -export const createSyntheticUserMessage = (baseMessage: WithParts, content: string): WithParts => { +export const createSyntheticUserMessage = ( + baseMessage: WithParts, + content: string, + variant?: string, +): WithParts => { const userInfo = baseMessage.info as UserMessage - const variant = (userInfo as any).variant return { info: { id: SYNTHETIC_MESSAGE_ID, diff --git a/lib/state/state.ts b/lib/state/state.ts index 05ebc0c..a85d61e 100644 --- a/lib/state/state.ts +++ b/lib/state/state.ts @@ -56,6 +56,7 @@ export function createSessionState(): SessionState { lastToolPrune: false, lastCompaction: 0, currentTurn: 0, + variant: undefined, } } @@ -75,6 +76,7 @@ export function resetSessionState(state: SessionState): void { state.lastToolPrune = false state.lastCompaction = 0 state.currentTurn = 0 + state.variant = undefined } export async function ensureSessionInitialized( diff --git a/lib/state/types.ts b/lib/state/types.ts index f9dfd7a..9d72e19 100644 --- a/lib/state/types.ts +++ b/lib/state/types.ts @@ -1,4 +1,4 @@ -import { Message, Part } from "@opencode-ai/sdk" +import { Message, Part } from "@opencode-ai/sdk/v2" export interface WithParts { info: Message @@ -35,4 +35,5 @@ export interface SessionState { lastToolPrune: boolean lastCompaction: number currentTurn: number + variant: string | undefined } diff --git a/lib/strategies/tools.ts b/lib/strategies/tools.ts index 370c5d1..6ca7d59 100644 --- a/lib/strategies/tools.ts +++ b/lib/strategies/tools.ts @@ -58,7 +58,7 @@ async function executePruneOperation( await ensureSessionInitialized(ctx.client, state, sessionId, logger, messages) - const currentParams = getCurrentParams(messages, logger) + const currentParams = getCurrentParams(state, messages, logger) const toolIdList: string[] = buildToolIdList(state, messages, logger) // Validate that all numeric IDs are within bounds diff --git a/lib/strategies/utils.ts b/lib/strategies/utils.ts index 5f141ca..c75081f 100644 --- a/lib/strategies/utils.ts +++ b/lib/strategies/utils.ts @@ -1,27 +1,36 @@ import { SessionState, WithParts } from "../state" -import { UserMessage } from "@opencode-ai/sdk" +import { UserMessage } from "@opencode-ai/sdk/v2" import { Logger } from "../logger" import { encode } from "gpt-tokenizer" import { getLastUserMessage, isMessageCompacted } from "../shared-utils" export function getCurrentParams( + state: SessionState, messages: WithParts[], logger: Logger, ): { providerId: string | undefined modelId: string | undefined agent: string | undefined + variant: string | undefined } { const userMsg = getLastUserMessage(messages) if (!userMsg) { logger.debug("No user message found when determining current params") - return { providerId: undefined, modelId: undefined, agent: undefined } + return { + providerId: undefined, + modelId: undefined, + agent: undefined, + variant: state.variant, + } } - const agent: string = (userMsg.info as UserMessage).agent - const providerId: string | undefined = (userMsg.info as UserMessage).model.providerID - const modelId: string | undefined = (userMsg.info as UserMessage).model.modelID + const userInfo = userMsg.info as UserMessage + const agent: string = userInfo.agent + const providerId: string | undefined = userInfo.model.providerID + const modelId: string | undefined = userInfo.model.modelID + const variant: string | undefined = state.variant ?? userInfo.variant - return { providerId, modelId, agent } + return { providerId, modelId, agent, variant } } /** diff --git a/lib/ui/notification.ts b/lib/ui/notification.ts index 159246c..81bba14 100644 --- a/lib/ui/notification.ts +++ b/lib/ui/notification.ts @@ -99,6 +99,7 @@ export async function sendIgnoredMessage( logger: Logger, ): Promise { const agent = params.agent || undefined + const variant = params.variant || undefined const model = params.providerId && params.modelId ? { @@ -116,6 +117,7 @@ export async function sendIgnoredMessage( noReply: true, agent: agent, model: model, + variant: variant, parts: [ { type: "text", diff --git a/package-lock.json b/package-lock.json index 50e3705..20fae79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.1.3", "license": "MIT", "dependencies": { - "@opencode-ai/sdk": "latest", + "@opencode-ai/sdk": "^1.1.3", "gpt-tokenizer": "^3.4.0", "jsonc-parser": "^3.3.1", "zod": "^4.1.13" @@ -477,6 +477,12 @@ "zod": "4.1.8" } }, + "node_modules/@opencode-ai/plugin/node_modules/@opencode-ai/sdk": { + "version": "1.0.143", + "resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.0.143.tgz", + "integrity": "sha512-dtmkBfJ7IIAHzL6KCzAlwc9GybfJONVeCsF6ePYySpkuhslDbRkZBJYb5vqGd1H5zdsgjc6JjuvmOf0rPWUL6A==", + "dev": true + }, "node_modules/@opencode-ai/plugin/node_modules/zod": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.8.tgz", @@ -488,9 +494,10 @@ } }, "node_modules/@opencode-ai/sdk": { - "version": "1.0.143", - "resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.0.143.tgz", - "integrity": "sha512-dtmkBfJ7IIAHzL6KCzAlwc9GybfJONVeCsF6ePYySpkuhslDbRkZBJYb5vqGd1H5zdsgjc6JjuvmOf0rPWUL6A==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.1.3.tgz", + "integrity": "sha512-P4ERbfuT7CilZYyB1l6J/DM6KD0i5V15O+xvsjUitxSS3S2Gr0YsA4bmXU+EsBQGHryUHc81bhJF49a8wSU+tw==", + "license": "MIT" }, "node_modules/@types/node": { "version": "24.10.1", diff --git a/package.json b/package.json index 1f8714b..a1d02ae 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@opencode-ai/plugin": ">=0.13.7" }, "dependencies": { - "@opencode-ai/sdk": "latest", + "@opencode-ai/sdk": "^1.1.3", "gpt-tokenizer": "^3.4.0", "jsonc-parser": "^3.3.1", "zod": "^4.1.13"