open-plan-annotator 1.0.20 → 1.1.0

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.
@@ -5,7 +5,7 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "Interactive plan annotation plugin for Claude Code",
8
- "version": "1.0.20"
8
+ "version": "1.1.0"
9
9
  },
10
10
  "plugins": [
11
11
  {
@@ -13,11 +13,11 @@
13
13
  "source": {
14
14
  "npm": {
15
15
  "package": "open-plan-annotator",
16
- "version": "1.0.20"
16
+ "version": "1.1.0"
17
17
  }
18
18
  },
19
19
  "description": "Interactive plan annotation UI: review, strikethrough, and comment on Claude's plans before approving. Fully local, no external services.",
20
- "version": "1.0.20",
20
+ "version": "1.1.0",
21
21
  "author": {
22
22
  "name": "ndom91"
23
23
  },
@@ -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": "1.0.20",
4
+ "version": "1.1.0",
5
5
  "author": {
6
6
  "name": "ndom91"
7
7
  },
@@ -6,6 +6,7 @@ import path from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import { buildCliHelpText, buildUnknownCommandPrefix } from "../shared/cliHelp.mjs";
8
8
  import { resolveCliMode } from "../shared/cliMode.mjs";
9
+ import { detectPackageManager } from "../shared/packageManager.mjs";
9
10
  import { resolveRuntimeBinary } from "../shared/runtimeResolver.mjs";
10
11
  import { buildUpdateInstructions } from "../shared/updateHints.mjs";
11
12
 
@@ -50,19 +51,10 @@ if (cliMode === "hook") {
50
51
  }
51
52
 
52
53
  if (cliMode === "update") {
53
- console.log(buildUpdateInstructions({ host: process.env.OPEN_PLAN_HOST, packageManager: detectPackageManager() }));
54
+ console.log(buildUpdateInstructions({ host: process.env.OPEN_PLAN_HOST, packageManager: detectPackageManager({ installPath: fileURLToPath(import.meta.url) }) }));
54
55
  process.exit(0);
55
56
  }
56
57
 
57
- // Detect package manager so the binary can suggest the right update command
58
- function detectPackageManager() {
59
- const ua = process.env.npm_config_user_agent || "";
60
- if (ua.startsWith("pnpm")) return "pnpm";
61
- if (ua.startsWith("yarn")) return "yarn";
62
- if (ua.startsWith("bun")) return "bun";
63
- return "npm";
64
- }
65
-
66
58
  let runtime;
67
59
  try {
68
60
  runtime = resolveRuntimeBinary({ parentUrl: import.meta.url });
@@ -77,7 +69,7 @@ const child = spawn(runtime.binaryPath, process.argv.slice(2), {
77
69
  env: {
78
70
  ...process.env,
79
71
  OPEN_PLAN_HOST: process.env.OPEN_PLAN_HOST || "claude-code",
80
- OPEN_PLAN_PKG_MANAGER: detectPackageManager(),
72
+ OPEN_PLAN_PKG_MANAGER: detectPackageManager({ installPath: fileURLToPath(import.meta.url) }),
81
73
  },
82
74
  });
83
75
 
@@ -136,7 +128,7 @@ function printDoctor() {
136
128
  `platform: ${platformKey}`,
137
129
  `runtime package: ${runtime.packageName}`,
138
130
  `runtime path: ${runtime.binaryPath}`,
139
- `update: ${buildUpdateInstructions({ host: process.env.OPEN_PLAN_HOST, packageManager: detectPackageManager() })}`,
131
+ `update: ${buildUpdateInstructions({ host: process.env.OPEN_PLAN_HOST, packageManager: detectPackageManager({ installPath: fileURLToPath(import.meta.url) }) })}`,
140
132
  ].join("\n"));
141
133
  } catch (error) {
142
134
  console.log([
@@ -144,7 +136,7 @@ function printDoctor() {
144
136
  `platform: ${platformKey}`,
145
137
  `runtime: missing`,
146
138
  `error: ${error instanceof Error ? error.message : String(error)}`,
147
- `update: ${buildUpdateInstructions({ host: process.env.OPEN_PLAN_HOST, packageManager: detectPackageManager() })}`,
139
+ `update: ${buildUpdateInstructions({ host: process.env.OPEN_PLAN_HOST, packageManager: detectPackageManager({ installPath: fileURLToPath(import.meta.url) }) })}`,
148
140
  ].join("\n"));
149
141
  }
150
142
  }
@@ -3,6 +3,7 @@ import { randomUUID } from "node:crypto";
3
3
  import { existsSync, statSync } from "node:fs";
4
4
  import { dirname } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
+ import { detectPackageManager } from "../shared/packageManager.mjs";
6
7
  import { resolveRuntimeBinary } from "../shared/runtimeResolver.mjs";
7
8
 
8
9
  const PKG_ROOT = fileURLToPath(new URL("..", import.meta.url));
@@ -98,14 +99,6 @@ function validateHookOutput(value) {
98
99
  throw new Error("unsupported decision payload");
99
100
  }
100
101
 
101
- function detectPackageManager() {
102
- const ua = process.env.npm_config_user_agent || "";
103
- if (ua.startsWith("pnpm")) return "pnpm";
104
- if (ua.startsWith("yarn")) return "yarn";
105
- if (ua.startsWith("bun")) return "bun";
106
- return "npm";
107
- }
108
-
109
102
  /**
110
103
  * @param {{ plan: string, sessionId?: string, cwd?: string }} options
111
104
  */
@@ -134,7 +127,8 @@ export async function runPlanReview(options) {
134
127
  env: {
135
128
  ...process.env,
136
129
  OPEN_PLAN_HOST: "opencode",
137
- OPEN_PLAN_PKG_MANAGER: process.env.OPEN_PLAN_PKG_MANAGER || detectPackageManager(),
130
+ OPEN_PLAN_PKG_MANAGER:
131
+ process.env.OPEN_PLAN_PKG_MANAGER || detectPackageManager({ installPath: fileURLToPath(import.meta.url) }),
138
132
  },
139
133
  detached: true,
140
134
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-plan-annotator",
3
- "version": "1.0.20",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "description": "Fully local plugin for interactive plan annotation from your Agentic assistants",
6
6
  "author": "ndom91",
@@ -61,9 +61,9 @@
61
61
  "@opencode-ai/plugin": "^1.2.14"
62
62
  },
63
63
  "optionalDependencies": {
64
- "@open-plan-annotator/runtime-darwin-arm64": "1.0.20",
65
- "@open-plan-annotator/runtime-darwin-x64": "1.0.20",
66
- "@open-plan-annotator/runtime-linux-arm64": "1.0.20",
67
- "@open-plan-annotator/runtime-linux-x64": "1.0.20"
64
+ "@open-plan-annotator/runtime-darwin-arm64": "1.1.0",
65
+ "@open-plan-annotator/runtime-darwin-x64": "1.1.0",
66
+ "@open-plan-annotator/runtime-linux-arm64": "1.1.0",
67
+ "@open-plan-annotator/runtime-linux-x64": "1.1.0"
68
68
  }
69
69
  }
@@ -0,0 +1,39 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+
4
+ function detectFromValue(value) {
5
+ if (!value) return undefined;
6
+ const normalized = value.toLowerCase();
7
+ if (normalized.includes("pnpm")) return "pnpm";
8
+ if (normalized.includes("yarn")) return "yarn";
9
+ if (normalized.includes("bun")) return "bun";
10
+ if (normalized.includes("npm")) return "npm";
11
+ return undefined;
12
+ }
13
+
14
+ export function detectPackageManager(options = {}) {
15
+ const env = options.env ?? process.env;
16
+ const installPath = options.installPath;
17
+
18
+ const explicit = detectFromValue(env.OPEN_PLAN_PKG_MANAGER);
19
+ if (explicit) return explicit;
20
+
21
+ const userAgent = env.npm_config_user_agent;
22
+ if (typeof userAgent === "string") {
23
+ const name = userAgent.split("/")[0];
24
+ const detected = detectFromValue(name);
25
+ if (detected) return detected;
26
+ }
27
+
28
+ const packageManager = detectFromValue(env.npm_package_manager);
29
+ if (packageManager) return packageManager;
30
+
31
+ const execPath = detectFromValue(env.npm_execpath);
32
+ if (execPath) return execPath;
33
+
34
+ const resolvedInstallPath = installPath ?? fileURLToPath(import.meta.url);
35
+ const pathHint = detectFromValue(path.normalize(resolvedInstallPath));
36
+ if (pathHint) return pathHint;
37
+
38
+ return "npm";
39
+ }
@@ -0,0 +1,33 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { detectPackageManager } from "./packageManager.mjs";
3
+
4
+ describe("detectPackageManager", () => {
5
+ test("prefers explicit OPEN_PLAN_PKG_MANAGER", () => {
6
+ expect(detectPackageManager({ env: { OPEN_PLAN_PKG_MANAGER: "pnpm" } })).toBe("pnpm");
7
+ });
8
+
9
+ test("detects package manager from npm user agent", () => {
10
+ expect(detectPackageManager({ env: { npm_config_user_agent: "pnpm/10.0.0 node/v22.0.0" } })).toBe("pnpm");
11
+ });
12
+
13
+ test("detects package manager from npm execpath", () => {
14
+ expect(detectPackageManager({ env: { npm_execpath: "/usr/local/lib/node_modules/pnpm/bin/pnpm.cjs" } })).toBe(
15
+ "pnpm",
16
+ );
17
+ });
18
+
19
+ test("detects package manager from install path hints", () => {
20
+ expect(
21
+ detectPackageManager({
22
+ env: {},
23
+ installPath: "/Users/test/Library/pnpm/global/5/node_modules/open-plan-annotator/bin/open-plan-annotator.mjs",
24
+ }),
25
+ ).toBe("pnpm");
26
+ });
27
+
28
+ test("falls back to npm", () => {
29
+ expect(detectPackageManager({ env: {}, installPath: "/tmp/open-plan-annotator/bin/open-plan-annotator.mjs" })).toBe(
30
+ "npm",
31
+ );
32
+ });
33
+ });