From 0a1124ba5368e830969fc1a1f30f84265711b8cd Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 25 Mar 2026 17:09:09 -0700 Subject: [PATCH] fix(opencode): inject bootstrap as user message instead of system message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move bootstrap injection from experimental.chat.system.transform to experimental.chat.messages.transform, prepending to the first user message instead of adding a system message. This avoids two issues: - System messages repeated every turn inflate token usage (#750) - Multiple system messages break Qwen and other models (#894) Tested on OpenCode 1.3.2 with Claude Sonnet 4.5 — brainstorming skill fires correctly on "Let's make a React to do list" prompt. --- .opencode/plugins/superpowers.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/.opencode/plugins/superpowers.js b/.opencode/plugins/superpowers.js index 76b23577..48a2b72d 100644 --- a/.opencode/plugins/superpowers.js +++ b/.opencode/plugins/superpowers.js @@ -94,12 +94,19 @@ ${toolMapping} } }, - // Use system prompt transform to inject bootstrap (fixes #226 agent reset bug) - 'experimental.chat.system.transform': async (_input, output) => { + // Inject bootstrap into the first user message of each session. + // Using a user message instead of a system message avoids: + // 1. Token bloat from system messages repeated every turn (#750) + // 2. Multiple system messages breaking Qwen and other models (#894) + 'experimental.chat.messages.transform': async (_input, output) => { const bootstrap = getBootstrapContent(); - if (bootstrap) { - (output.system ||= []).push(bootstrap); - } + if (!bootstrap || !output.messages.length) return; + const firstUser = output.messages.find(m => m.info.role === 'user'); + if (!firstUser || !firstUser.parts.length) return; + // Only inject once + if (firstUser.parts.some(p => p.type === 'text' && p.text.includes('EXTREMELY_IMPORTANT'))) return; + const ref = firstUser.parts[0]; + firstUser.parts.unshift({ ...ref, type: 'text', text: bootstrap }); } }; };