@plannotator/opencode 0.3.1 → 0.5.0-beta.1

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.
Files changed (3) hide show
  1. package/index.ts +16 -68
  2. package/package.json +1 -1
  3. package/plannotator.html +63 -57
package/index.ts CHANGED
@@ -5,81 +5,23 @@
5
5
  * When the agent calls submit_plan, the Plannotator UI opens for the user to
6
6
  * annotate, approve, or request changes to the plan.
7
7
  *
8
+ * Environment variables:
9
+ * PLANNOTATOR_REMOTE - Set to "1" or "true" for remote mode (devcontainer, SSH)
10
+ * PLANNOTATOR_PORT - Fixed port to use (default: random locally, 19432 for remote)
11
+ *
8
12
  * @packageDocumentation
9
13
  */
10
14
 
11
15
  import { type Plugin, tool } from "@opencode-ai/plugin";
12
- import { $ } from "bun";
16
+ import {
17
+ startPlannotatorServer,
18
+ handleServerReady,
19
+ } from "@plannotator/server";
13
20
 
14
21
  // @ts-ignore - Bun import attribute for text
15
22
  import indexHtml from "./plannotator.html" with { type: "text" };
16
23
  const htmlContent = indexHtml as unknown as string;
17
24
 
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 });
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
25
  export const PlannotatorPlugin: Plugin = async (ctx) => {
84
26
  return {
85
27
  "experimental.chat.system.transform": async (_input, output) => {
@@ -114,8 +56,14 @@ Do NOT proceed with implementation until your plan is approved.
114
56
  },
115
57
 
116
58
  async execute(args, _context) {
117
- const server = await startPlannotatorServer(args.plan);
118
- await openBrowser(server.url);
59
+ const server = await startPlannotatorServer({
60
+ plan: args.plan,
61
+ origin: "opencode",
62
+ htmlContent,
63
+ onReady: (url, isRemote, port) => {
64
+ handleServerReady(url, isRemote, port);
65
+ },
66
+ });
119
67
 
120
68
  const result = await server.waitForDecision();
121
69
  await Bun.sleep(1500);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plannotator/opencode",
3
- "version": "0.3.1",
3
+ "version": "0.5.0-beta.1",
4
4
  "description": "Plannotator plugin for OpenCode - interactive plan review with visual annotation",
5
5
  "author": "backnotprop",
6
6
  "license": "BSL-1.1",