diff --git a/apps/opencode-plugin/commands/plannotator-annotate.md b/apps/opencode-plugin/commands/plannotator-annotate.md index f2c7d2208..6a9c58fb2 100644 --- a/apps/opencode-plugin/commands/plannotator-annotate.md +++ b/apps/opencode-plugin/commands/plannotator-annotate.md @@ -1,6 +1,3 @@ --- description: Open interactive annotation UI for a markdown file, HTML file, or URL --- - -The Plannotator Annotate UI has been triggered. Opening the annotation UI... -Acknowledge "Opening annotation UI..." and wait for the user's feedback. diff --git a/apps/opencode-plugin/commands/plannotator-archive.md b/apps/opencode-plugin/commands/plannotator-archive.md index b9899be8a..2dfff75cc 100644 --- a/apps/opencode-plugin/commands/plannotator-archive.md +++ b/apps/opencode-plugin/commands/plannotator-archive.md @@ -1,6 +1,3 @@ --- description: Browse saved plan decisions in the archive --- - -The Plannotator Archive has been triggered. Opening the archive browser... -Acknowledge "Opening plan archive..." and wait for the user to finish browsing. diff --git a/apps/opencode-plugin/commands/plannotator-review.md b/apps/opencode-plugin/commands/plannotator-review.md index 172904be4..bd150d01d 100644 --- a/apps/opencode-plugin/commands/plannotator-review.md +++ b/apps/opencode-plugin/commands/plannotator-review.md @@ -1,6 +1,3 @@ --- description: Open interactive code review for current changes or a PR URL; pass --git to force Git in JJ workspaces --- - -The Plannotator Code Review has been triggered. Opening the review UI... -Acknowledge "Opening code review..." and wait for the user's feedback. diff --git a/apps/opencode-plugin/index.ts b/apps/opencode-plugin/index.ts index 5e576853a..b9ebb9fb8 100644 --- a/apps/opencode-plugin/index.ts +++ b/apps/opencode-plugin/index.ts @@ -383,11 +383,26 @@ The user will review your plan in a visual UI where they can annotate, approve, Do NOT proceed with implementation until your plan is approved.`); }, - // Intercept plannotator-last before the agent sees the command + // Intercept plannotator commands before the agent sees them. + // Clearing output.parts in place suppresses the .md body + appended + // args so the agent never receives the command — without this, OpenCode + // calls resolvePromptParts() on " ", which auto-attaches + // any file path it finds as a FilePart. On a large file that blows the + // context before the annotation UI even opens (#713). + // + // Must mutate in place (length = 0), not reassign (= []). The caller + // holds a reference to the parts array directly and ignores any new + // array assigned to output.parts. "command.execute.before": async (input, output) => { - if (input.command !== "plannotator-last") return; + const cmd = input.command; + if ( + cmd !== "plannotator-last" && + cmd !== "plannotator-annotate" && + cmd !== "plannotator-review" && + cmd !== "plannotator-archive" + ) return; - output.parts = []; + output.parts.length = 0; const deps: CommandDeps = { client: ctx.client, @@ -398,58 +413,35 @@ Do NOT proceed with implementation until your plan is approved.`); getPasteApiUrl, directory: ctx.directory, }; + // input.arguments is the raw tail string from OpenCode's command dispatcher — + // needed so --gate / --json reach the handlers' parseAnnotateArgs (#570). + const event = { + properties: { sessionID: input.sessionID, arguments: input.arguments }, + }; - const feedback = await handleAnnotateLastCommand( - // input.arguments is the raw tail string from OpenCode's command dispatcher — - // needed so --gate / --json reach handleAnnotateLastCommand's parseAnnotateArgs (#570). - { properties: { sessionID: input.sessionID, arguments: input.arguments } }, - deps - ); - - if (feedback) { - try { - await ctx.client.session.prompt({ - path: { id: input.sessionID }, - body: { - parts: [{ - type: "text", - text: getAnnotateMessageFeedbackPrompt("opencode", undefined, { feedback }), - }], - }, - }); - } catch { - // Session may not be available + if (cmd === "plannotator-last") { + const feedback = await handleAnnotateLastCommand(event, deps); + if (feedback) { + try { + await ctx.client.session.prompt({ + path: { id: input.sessionID }, + body: { + parts: [{ + type: "text", + text: getAnnotateMessageFeedbackPrompt("opencode", undefined, { feedback }), + }], + }, + }); + } catch { + // Session may not be available + } } + return; } - }, - - // Listen for slash commands (review + annotate) - event: async ({ event }) => { - const isCommandEvent = - event.type === "command.executed" || - event.type === "tui.command.execute"; - - if (!isCommandEvent) return; - - // @ts-ignore - Event structure varies - const commandName = event.properties?.name || event.command || event.payload?.name; - - const deps: CommandDeps = { - client: ctx.client, - htmlContent: getPlanHtml(), - reviewHtmlContent: getReviewHtml(), - getSharingEnabled, - getShareBaseUrl, - getPasteApiUrl, - directory: ctx.directory, - }; - if (commandName === "plannotator-review") - return handleReviewCommand(event, deps); - if (commandName === "plannotator-annotate") - return handleAnnotateCommand(event, deps); - if (commandName === "plannotator-archive") - return handleArchiveCommand(event, deps); + if (cmd === "plannotator-annotate") return handleAnnotateCommand(event, deps); + if (cmd === "plannotator-review") return handleReviewCommand(event, deps); + if (cmd === "plannotator-archive") return handleArchiveCommand(event, deps); }, };