@plannotator/opencode 0.4.0 → 0.5.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plannotator/opencode",
3
- "version": "0.4.0",
3
+ "version": "0.5.0-beta.2",
4
4
  "description": "Plannotator plugin for OpenCode - interactive plan review with visual annotation",
5
5
  "author": "backnotprop",
6
6
  "license": "BSL-1.1",
@@ -21,14 +21,13 @@
21
21
  "ai-agent",
22
22
  "coding-agent"
23
23
  ],
24
- "main": "index.ts",
24
+ "main": "dist/index.js",
25
25
  "files": [
26
- "index.ts",
27
- "plannotator.html",
26
+ "dist",
28
27
  "README.md"
29
28
  ],
30
29
  "scripts": {
31
- "build": "cp ../hook/dist/index.html ./plannotator.html",
30
+ "build": "cp ../hook/dist/index.html ./plannotator.html && bun build index.ts --outfile dist/index.js --target bun --external @opencode-ai/plugin",
32
31
  "prepublishOnly": "bun run build"
33
32
  },
34
33
  "dependencies": {
package/index.ts DELETED
@@ -1,157 +0,0 @@
1
- /**
2
- * Plannotator Plugin for OpenCode
3
- *
4
- * Provides a Claude Code-style planning experience with interactive plan review.
5
- * When the agent calls submit_plan, the Plannotator UI opens for the user to
6
- * annotate, approve, or request changes to the plan.
7
- *
8
- * @packageDocumentation
9
- */
10
-
11
- import { type Plugin, tool } from "@opencode-ai/plugin";
12
- import { $ } from "bun";
13
-
14
- // @ts-ignore - Bun import attribute for text
15
- import indexHtml from "./plannotator.html" with { type: "text" };
16
- const htmlContent = indexHtml as unknown as string;
17
-
18
- interface ServerResult {
19
- port: number;
20
- url: string;
21
- waitForDecision: () => Promise<{ approved: boolean; feedback?: string }>;
22
- stop: () => void;
23
- }
24
-
25
- async function startPlannotatorServer(planContent: string): Promise<ServerResult> {
26
- let resolveDecision: (result: { approved: boolean; feedback?: string }) => void;
27
- const decisionPromise = new Promise<{ approved: boolean; feedback?: string }>(
28
- (resolve) => { resolveDecision = resolve; }
29
- );
30
-
31
- const server = Bun.serve({
32
- port: 0,
33
- async fetch(req) {
34
- const url = new URL(req.url);
35
-
36
- if (url.pathname === "/api/plan") {
37
- return Response.json({ plan: planContent, origin: "opencode" });
38
- }
39
-
40
- if (url.pathname === "/api/approve" && req.method === "POST") {
41
- resolveDecision({ approved: true });
42
- return Response.json({ ok: true });
43
- }
44
-
45
- if (url.pathname === "/api/deny" && req.method === "POST") {
46
- try {
47
- const body = await req.json() as { feedback?: string };
48
- resolveDecision({ approved: false, feedback: body.feedback || "Plan rejected by user" });
49
- } catch {
50
- resolveDecision({ approved: false, feedback: "Plan rejected by user" });
51
- }
52
- return Response.json({ ok: true });
53
- }
54
-
55
- return new Response(htmlContent, {
56
- headers: { "Content-Type": "text/html" }
57
- });
58
- },
59
- });
60
-
61
- return {
62
- port: server.port!,
63
- url: `http://localhost:${server.port}`,
64
- waitForDecision: () => decisionPromise,
65
- stop: () => server.stop(),
66
- };
67
- }
68
-
69
- async function openBrowser(url: string): Promise<void> {
70
- try {
71
- if (process.platform === "win32") {
72
- await $`cmd /c start ${url}`.quiet();
73
- } else if (process.platform === "darwin") {
74
- await $`open ${url}`.quiet();
75
- } else {
76
- await $`xdg-open ${url}`.quiet();
77
- }
78
- } catch {
79
- // Silently fail - user can open manually if needed
80
- }
81
- }
82
-
83
- export const PlannotatorPlugin: Plugin = async (ctx) => {
84
- return {
85
- "experimental.chat.system.transform": async (_input, output) => {
86
- output.system.push(`
87
- ## Plan Submission
88
-
89
- When you have completed your plan, you MUST call the \`submit_plan\` tool to submit it for user review.
90
- The user will be able to:
91
- - Review your plan visually in a dedicated UI
92
- - Annotate specific sections with feedback
93
- - Approve the plan to proceed with implementation
94
- - Request changes with detailed feedback
95
-
96
- If your plan is rejected, you will receive the user's annotated feedback. Revise your plan
97
- based on their feedback and call submit_plan again.
98
-
99
- Do NOT proceed with implementation until your plan is approved.
100
- `);
101
- },
102
-
103
- tool: {
104
- submit_plan: tool({
105
- description:
106
- "Submit your completed plan for interactive user review. The user can annotate, approve, or request changes. Call this when you have finished creating your implementation plan.",
107
- args: {
108
- plan: tool.schema
109
- .string()
110
- .describe("The complete implementation plan in markdown format"),
111
- summary: tool.schema
112
- .string()
113
- .describe("A brief 1-2 sentence summary of what the plan accomplishes"),
114
- },
115
-
116
- async execute(args, _context) {
117
- const server = await startPlannotatorServer(args.plan);
118
- await openBrowser(server.url);
119
-
120
- const result = await server.waitForDecision();
121
- await Bun.sleep(1500);
122
- server.stop();
123
-
124
- if (result.approved) {
125
- try {
126
- await ctx.client.tui.executeCommand({
127
- body: { command: "agent_cycle" },
128
- });
129
- } catch {
130
- // Silently fail - agent switching is optional
131
- }
132
-
133
- return `Plan approved! Switching to build mode.
134
-
135
- Your plan has been approved by the user. You may now proceed with implementation.
136
-
137
- Plan Summary: ${args.summary}`;
138
- } else {
139
- return `Plan needs revision.
140
-
141
- The user has requested changes to your plan. Please review their feedback below and revise your plan accordingly.
142
-
143
- ## User Feedback
144
-
145
- ${result.feedback}
146
-
147
- ---
148
-
149
- Please revise your plan based on this feedback and call \`submit_plan\` again when ready.`;
150
- }
151
- },
152
- }),
153
- },
154
- };
155
- };
156
-
157
- export default PlannotatorPlugin;