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
5 changes: 5 additions & 0 deletions .changeset/empty-hoops-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"opencode-adaptive-thinking": patch
---

Preserve the active agent when synthetic prompts adjust reasoning effort and when temporary overrides reset after a session becomes idle. This prevents OpenCode from routing follow-up work to the default agent instead of the agent that initiated the change.
16 changes: 16 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,21 @@ describe("AdaptiveThinkingPlugin", () => {
expect(system[0]).toContain("set_reasoning_effort");
});

test("preserves the calling agent when setting reasoning effort", async () => {
const sessionID = "preserve-agent";
const { client, toolContext } = createClient(sessionID, [createMessage("medium")]);
toolContext.agent = "custom-worker";
const plugin = await AdaptiveThinkingPlugin({ client } as never);

await setReasoningEffort(plugin, { level: "high", persist: true }, toolContext);

expect(client.session.promptAsync).toHaveBeenCalledWith(
expect.objectContaining({
body: expect.objectContaining({ agent: "custom-worker", variant: "high" }),
}),
);
});

test("returns no hooks when disabled", async () => {
const { client } = createClient("disabled-plugin");
const plugin = await AdaptiveThinkingPlugin({ client } as never, { enabled: false });
Expand Down Expand Up @@ -298,6 +313,7 @@ describe("AdaptiveThinkingPlugin", () => {
const secondPrompt = promptCalls[1]?.[0];
expect(secondPrompt).toMatchObject({
body: {
agent: "agent",
variant: "medium",
parts: [{ ignored: true, synthetic: true }],
},
Expand Down
14 changes: 12 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type SessionState = {
currentVariant?: string;
persistedVariant?: string;
temporaryResetVariant?: string;
temporaryResetAgent?: string;
};

class SessionStateCache {
Expand Down Expand Up @@ -83,6 +84,7 @@ export const AdaptiveThinkingPlugin: Plugin = async ({ client }, options) => {
sessionID: string,
variant: string,
text: string,
agent: string,
ignored = true,
) => {
const body: PromptAsyncBody = {
Expand All @@ -95,6 +97,7 @@ export const AdaptiveThinkingPlugin: Plugin = async ({ client }, options) => {
ignored,
},
],
agent,
variant,
};

Expand Down Expand Up @@ -212,7 +215,7 @@ export const AdaptiveThinkingPlugin: Plugin = async ({ client }, options) => {
"Whether to persist the setting for this session, otherwise it will only apply for the remainder of the current turn",
),
},
execute: async ({ level, persist }, { sessionID }) => {
execute: async ({ level, persist }, { sessionID, agent }) => {
const validVariants = await resolveValidVariants(sessionID);
if (validVariants.length === 0) {
return "Failed to set reasoning effort: no valid reasoning effort levels are available for this session";
Expand All @@ -230,6 +233,7 @@ export const AdaptiveThinkingPlugin: Plugin = async ({ client }, options) => {
sessionID,
level,
`Reasoning effort set to ${level}`,
agent,
);
if (promptResponse.error) {
return `Failed to set reasoning effort: ${JSON.stringify(promptResponse.error.data)}`;
Expand All @@ -240,10 +244,13 @@ export const AdaptiveThinkingPlugin: Plugin = async ({ client }, options) => {
if (persist) {
entry.persistedVariant = level;
delete entry.temporaryResetVariant;
delete entry.temporaryResetAgent;
} else if (resetVariant && resetVariant !== level) {
entry.temporaryResetVariant = resetVariant;
entry.temporaryResetAgent = agent;
} else {
delete entry.temporaryResetVariant;
delete entry.temporaryResetAgent;
}
});

Expand All @@ -256,12 +263,14 @@ export const AdaptiveThinkingPlugin: Plugin = async ({ client }, options) => {
const sessionID = event.properties.sessionID;
const sessionState = state.get(sessionID);
const resetVariant = sessionState?.temporaryResetVariant;
if (!resetVariant) return;
const resetAgent = sessionState?.temporaryResetAgent;
if (!resetVariant || !resetAgent) return;

const promptResponse = await sendVariantPrompt(
sessionID,
resetVariant,
`Reasoning effort reset to ${resetVariant}.`,
resetAgent,
);
if (promptResponse.error) {
client.app.log({
Expand All @@ -277,6 +286,7 @@ export const AdaptiveThinkingPlugin: Plugin = async ({ client }, options) => {
state.update(sessionID, (entry) => {
entry.currentVariant = resetVariant;
delete entry.temporaryResetVariant;
delete entry.temporaryResetAgent;
});
return;
}
Expand Down