open-plan-annotator 0.2.14 → 0.2.16
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.
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"name": "open-plan-annotator",
|
|
13
13
|
"source": "./",
|
|
14
14
|
"description": "Interactive plan annotation UI: review, strikethrough, and comment on Claude's plans before approving. Fully local, no external services.",
|
|
15
|
-
"version": "0.2.
|
|
15
|
+
"version": "0.2.16",
|
|
16
16
|
"author": {
|
|
17
17
|
"name": "ndom91"
|
|
18
18
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "open-plan-annotator",
|
|
3
3
|
"description": "Interactive plan annotation UI: review, strikethrough, and comment on Claude's plans before approving. Fully local, no external services.",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.16",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "ndom91"
|
|
7
7
|
},
|
package/opencode/bridge.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
1
|
+
import { execFileSync, spawn } from "node:child_process";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { existsSync, statSync } from "node:fs";
|
|
4
|
-
import { dirname } from "node:path";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const PKG_ROOT = fileURLToPath(new URL("..", import.meta.url));
|
|
8
|
+
const LOCAL_BINARY_PATH = join(PKG_ROOT, "bin", "open-plan-annotator-binary");
|
|
9
|
+
const INSTALL_SCRIPT = join(PKG_ROOT, "install.cjs");
|
|
10
|
+
|
|
11
|
+
/** Resolved path to the binary (may differ from LOCAL_BINARY_PATH if found on PATH). */
|
|
12
|
+
let BINARY_PATH = LOCAL_BINARY_PATH;
|
|
8
13
|
|
|
9
14
|
/**
|
|
10
15
|
* @typedef {{
|
|
@@ -97,10 +102,77 @@ function validateHookOutput(value) {
|
|
|
97
102
|
throw new Error("unsupported decision payload");
|
|
98
103
|
}
|
|
99
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Check if `open-plan-annotator` is available on PATH.
|
|
107
|
+
* The CLI wrapper handles binary discovery/download and stdin/stdout
|
|
108
|
+
* forwarding, so we can spawn it directly as a fallback when the local
|
|
109
|
+
* binary isn't available (e.g. OpenCode loads the plugin from its own
|
|
110
|
+
* node_modules but the binary only exists in a global pnpm install).
|
|
111
|
+
* @returns {string | undefined}
|
|
112
|
+
*/
|
|
113
|
+
function findWrapperOnPath() {
|
|
114
|
+
const cmd = process.platform === "win32" ? "where" : "which";
|
|
115
|
+
try {
|
|
116
|
+
const result = execFileSync(cmd, ["open-plan-annotator"], {
|
|
117
|
+
encoding: "utf-8",
|
|
118
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
119
|
+
}).trim().split("\n")[0];
|
|
120
|
+
return result || undefined;
|
|
121
|
+
} catch {
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Ensure the compiled binary exists, downloading if necessary. */
|
|
127
|
+
function ensureBinary() {
|
|
128
|
+
if (existsSync(LOCAL_BINARY_PATH)) {
|
|
129
|
+
BINARY_PATH = LOCAL_BINARY_PATH;
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Try to find node on PATH for running the install script
|
|
134
|
+
try {
|
|
135
|
+
execFileSync(process.execPath, [INSTALL_SCRIPT], {
|
|
136
|
+
cwd: PKG_ROOT,
|
|
137
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
138
|
+
});
|
|
139
|
+
} catch {
|
|
140
|
+
// Retry with "node" explicitly in case process.execPath is bun
|
|
141
|
+
try {
|
|
142
|
+
execFileSync("node", [INSTALL_SCRIPT], {
|
|
143
|
+
cwd: PKG_ROOT,
|
|
144
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
145
|
+
});
|
|
146
|
+
} catch {
|
|
147
|
+
// ignore — we'll check below
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (existsSync(LOCAL_BINARY_PATH)) {
|
|
152
|
+
BINARY_PATH = LOCAL_BINARY_PATH;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Fallback: use the CLI wrapper from PATH (e.g. global pnpm install).
|
|
157
|
+
// The wrapper handles binary discovery/download and stdio forwarding.
|
|
158
|
+
const wrapperPath = findWrapperOnPath();
|
|
159
|
+
if (wrapperPath) {
|
|
160
|
+
BINARY_PATH = wrapperPath;
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
throw new Error(
|
|
165
|
+
`open-plan-annotator: binary not found at ${LOCAL_BINARY_PATH}. ` +
|
|
166
|
+
`Try running: node ${INSTALL_SCRIPT}`,
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
100
170
|
/**
|
|
101
171
|
* @param {{ plan: string, sessionId?: string, cwd?: string }} options
|
|
102
172
|
*/
|
|
103
173
|
export async function runPlanReview(options) {
|
|
174
|
+
ensureBinary();
|
|
175
|
+
|
|
104
176
|
const payload = buildHookPayload(options);
|
|
105
177
|
|
|
106
178
|
const result = await new Promise((resolve, reject) => {
|
|
@@ -112,11 +184,12 @@ export async function runPlanReview(options) {
|
|
|
112
184
|
cwd = dirname(cwd);
|
|
113
185
|
}
|
|
114
186
|
} catch {
|
|
115
|
-
|
|
116
|
-
cwd = dirname(WRAPPER_PATH);
|
|
187
|
+
cwd = PKG_ROOT;
|
|
117
188
|
}
|
|
118
189
|
|
|
119
|
-
|
|
190
|
+
// Spawn the compiled binary directly (skip the Node wrapper).
|
|
191
|
+
// This avoids issues with bun vs node runtime differences.
|
|
192
|
+
const child = spawn(BINARY_PATH, [], {
|
|
120
193
|
cwd,
|
|
121
194
|
stdio: ["pipe", "pipe", "pipe"],
|
|
122
195
|
env: process.env,
|
|
@@ -177,4 +250,4 @@ export async function runPlanReview(options) {
|
|
|
177
250
|
approved: false,
|
|
178
251
|
feedback: decision.message,
|
|
179
252
|
};
|
|
180
|
-
}
|
|
253
|
+
}
|