@plannotator/opencode 0.27.6 → 0.27.7

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/dist/embedded.js CHANGED
@@ -73591,6 +73591,36 @@ var init_claude_agent_sdk = __esm(() => {
73591
73591
  registerProviderFactory(PROVIDER_NAME, async (config) => new ClaudeAgentSDKProvider(config));
73592
73592
  });
73593
73593
 
73594
+ // ../../packages/ai/providers/child-io.ts
73595
+ function toChildError(err) {
73596
+ return err instanceof Error ? err : new Error(String(err));
73597
+ }
73598
+ function guardChildStreams(proc, label, onFailure) {
73599
+ const report = (stream) => (err) => {
73600
+ onFailure(new Error(`${label} ${stream} failed: ${toChildError(err).message}`));
73601
+ };
73602
+ proc.on("error", report("process"));
73603
+ proc.stdin?.on("error", report("stdin"));
73604
+ proc.stdout?.on("error", report("stdout"));
73605
+ proc.stderr?.on("error", report("stderr"));
73606
+ }
73607
+ function writeChildLine(proc, line, label, onAsyncFailure) {
73608
+ const stdin = proc?.stdin;
73609
+ if (!stdin || stdin.destroyed || stdin.writableEnded) {
73610
+ return new Error(`${label} stdin is closed`);
73611
+ }
73612
+ try {
73613
+ stdin.write(line, (err) => {
73614
+ if (err) {
73615
+ onAsyncFailure(new Error(`${label} stdin write failed: ${toChildError(err).message}`));
73616
+ }
73617
+ });
73618
+ } catch (err) {
73619
+ return new Error(`${label} stdin write failed: ${toChildError(err).message}`);
73620
+ }
73621
+ return null;
73622
+ }
73623
+
73594
73624
  // ../../packages/ai/providers/codex-app-server.ts
73595
73625
  var exports_codex_app_server = {};
73596
73626
  __export(exports_codex_app_server, {
@@ -73772,6 +73802,7 @@ class CodexAppServerProcess {
73772
73802
  throw error;
73773
73803
  }
73774
73804
  this.proc = proc;
73805
+ guardChildStreams(proc, CODEX_PROCESS_LABEL, (error) => this.failProcess(error));
73775
73806
  proc.once("exit", () => {
73776
73807
  this.handleProcessEnd(new Error("Codex app-server exited unexpectedly"));
73777
73808
  });
@@ -73807,6 +73838,17 @@ class CodexAppServerProcess {
73807
73838
  }
73808
73839
  this.send({ method: "initialized", params: {} });
73809
73840
  }
73841
+ failProcess(error) {
73842
+ const proc = this.proc;
73843
+ this.startPromise = null;
73844
+ this.handleProcessEnd(error);
73845
+ if (proc) {
73846
+ try {
73847
+ if (!killWindowsProcessTree(proc.pid))
73848
+ proc.kill();
73849
+ } catch {}
73850
+ }
73851
+ }
73810
73852
  handleProcessEnd(error) {
73811
73853
  if (!this.proc && this.pendingRequests.size === 0)
73812
73854
  return;
@@ -73870,10 +73912,10 @@ class CodexAppServerProcess {
73870
73912
  }
73871
73913
  }
73872
73914
  send(message) {
73873
- if (!this.proc?.stdin || this.proc.stdin.destroyed)
73874
- return;
73875
- this.proc.stdin.write(`${JSON.stringify(message)}
73876
- `);
73915
+ const error = writeChildLine(this.proc, `${JSON.stringify(message)}
73916
+ `, CODEX_PROCESS_LABEL, (err) => this.failProcess(err));
73917
+ if (error)
73918
+ this.failProcess(error);
73877
73919
  }
73878
73920
  sendAndWait(message, timeoutMs = RPC_TIMEOUT_MS) {
73879
73921
  const id = ++this.nextId;
@@ -74028,7 +74070,7 @@ class CodexAppServerProvider {
74028
74070
  this.sessions.clear();
74029
74071
  }
74030
74072
  }
74031
- var PROVIDER_NAME2 = "codex-sdk", DEFAULT_MODEL2 = "gpt-5.6-sol", CLIENT_NAME = "plannotator", IDLE_TIMEOUT_MS, RPC_TIMEOUT_MS = 30000, MODEL_DISCOVERY_TIMEOUT_MS = 6000, CMD_APPROVAL_METHOD = "item/commandExecution/requestApproval", FILE_APPROVAL_METHOD = "item/fileChange/requestApproval", PERMISSIONS_APPROVAL_METHOD = "item/permissions/requestApproval", REASONING_EFFORT_LABELS, CodexAppServerSession;
74073
+ var PROVIDER_NAME2 = "codex-sdk", CODEX_PROCESS_LABEL = "Codex app-server", DEFAULT_MODEL2 = "gpt-5.6-sol", CLIENT_NAME = "plannotator", IDLE_TIMEOUT_MS, RPC_TIMEOUT_MS = 30000, MODEL_DISCOVERY_TIMEOUT_MS = 6000, CMD_APPROVAL_METHOD = "item/commandExecution/requestApproval", FILE_APPROVAL_METHOD = "item/fileChange/requestApproval", PERMISSIONS_APPROVAL_METHOD = "item/permissions/requestApproval", REASONING_EFFORT_LABELS, CodexAppServerSession;
74032
74074
  var init_codex_app_server = __esm(() => {
74033
74075
  init_base_session();
74034
74076
  init_context();
@@ -74391,7 +74433,7 @@ class PiProcess {
74391
74433
  cwd,
74392
74434
  stdin: "pipe",
74393
74435
  stdout: "pipe",
74394
- stderr: "pipe"
74436
+ stderr: "ignore"
74395
74437
  });
74396
74438
  } catch (err) {
74397
74439
  const error = err instanceof Error ? err : new Error(String(err));
@@ -74404,6 +74446,16 @@ class PiProcess {
74404
74446
  this.handleProcessEnd(new Error("Pi process exited unexpectedly"));
74405
74447
  });
74406
74448
  }
74449
+ failProcess(error) {
74450
+ const proc = this.proc;
74451
+ this.handleProcessEnd(error);
74452
+ if (proc) {
74453
+ try {
74454
+ if (!killWindowsProcessTree(proc.pid))
74455
+ proc.kill();
74456
+ } catch {}
74457
+ }
74458
+ }
74407
74459
  handleProcessEnd(error) {
74408
74460
  if (!this.proc && this.pendingRequests.size === 0)
74409
74461
  return;
@@ -74461,12 +74513,24 @@ class PiProcess {
74461
74513
  }
74462
74514
  }
74463
74515
  send(command) {
74464
- if (!this.proc?.stdin || typeof this.proc.stdin === "number")
74516
+ const stdin = this.proc?.stdin;
74517
+ if (!stdin || typeof stdin === "number") {
74518
+ this.failProcess(new Error("Pi process stdin is closed"));
74465
74519
  return;
74466
- const sink = this.proc.stdin;
74467
- sink.write(`${JSON.stringify(command)}
74520
+ }
74521
+ const sink = stdin;
74522
+ try {
74523
+ sink.write(`${JSON.stringify(command)}
74468
74524
  `);
74469
- sink.flush();
74525
+ const flushed = sink.flush();
74526
+ if (flushed && typeof flushed.then === "function") {
74527
+ flushed.catch((err) => {
74528
+ this.failProcess(new Error(`Pi process stdin write failed: ${err instanceof Error ? err.message : String(err)}`));
74529
+ });
74530
+ }
74531
+ } catch (err) {
74532
+ this.failProcess(new Error(`Pi process stdin write failed: ${err instanceof Error ? err.message : String(err)}`));
74533
+ }
74470
74534
  }
74471
74535
  sendAndWait(command) {
74472
74536
  const id = `req_${++this.nextId}`;
@@ -77947,6 +78011,8 @@ function jjCompareTargetRevset(target) {
77947
78011
  if (remoteBookmark) {
77948
78012
  return `remote_bookmarks(exact:${quoteJjString(remoteBookmark.name)}, exact:${quoteJjString(remoteBookmark.remote)})`;
77949
78013
  }
78014
+ if (JJ_FULL_COMMIT_ID.test(target))
78015
+ return target;
77950
78016
  const localBookmark = parseJjBookmarkName(target);
77951
78017
  return localBookmark ? `bookmarks(exact:${quoteJjString(localBookmark)})` : target;
77952
78018
  }
@@ -79113,11 +79179,12 @@ function isBinaryPatchFile(patch, filePath) {
79113
79179
  }
79114
79180
  return false;
79115
79181
  }
79116
- var JJ_TRUNK_REVSET = "trunk()", MAX_REVIEW_FILE_CONTENT_BYTES, MAX_UNTRACKED_DIFF_CONCURRENCY = 4, MAX_UNTRACKED_FINGERPRINT_CONTENT_BYTES, RECENT_COMMIT_LIMIT_DEFAULT = 20, COMMIT_FIELD_SEP = "\x1F", NULL_OBJECT_ID, BOUNDED_DIFF_GIT_CONFIG, WORKTREE_SUB_TYPES, BARE_HEX_SHA_RE, MAX_UNTRACKED_FINGERPRINT_FILES = 20, UNTRACKED_STATUS_OUTPUT_CAP, collapsedUntrackedCwds;
79182
+ var JJ_TRUNK_REVSET = "trunk()", MAX_REVIEW_FILE_CONTENT_BYTES, MAX_UNTRACKED_DIFF_CONCURRENCY = 4, MAX_UNTRACKED_FINGERPRINT_CONTENT_BYTES, JJ_FULL_COMMIT_ID, RECENT_COMMIT_LIMIT_DEFAULT = 20, COMMIT_FIELD_SEP = "\x1F", NULL_OBJECT_ID, BOUNDED_DIFF_GIT_CONFIG, WORKTREE_SUB_TYPES, BARE_HEX_SHA_RE, MAX_UNTRACKED_FINGERPRINT_FILES = 20, UNTRACKED_STATUS_OUTPUT_CAP, collapsedUntrackedCwds;
79117
79183
  var init_review_core = __esm(() => {
79118
79184
  init_diff_paths2();
79119
79185
  MAX_REVIEW_FILE_CONTENT_BYTES = 5 * 1024 * 1024;
79120
79186
  MAX_UNTRACKED_FINGERPRINT_CONTENT_BYTES = 1024 * 1024;
79187
+ JJ_FULL_COMMIT_ID = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/;
79121
79188
  NULL_OBJECT_ID = /^0+$/;
79122
79189
  BOUNDED_DIFF_GIT_CONFIG = {
79123
79190
  "core.bigFileThreshold": String(MAX_REVIEW_FILE_CONTENT_BYTES)
@@ -79372,13 +79439,27 @@ async function selectDefaultJjCompareTarget(runtime, cwd) {
79372
79439
  "log",
79373
79440
  "--no-graph",
79374
79441
  "-r",
79375
- JJ_TRUNK_REVSET,
79442
+ JJ_LINE_BASE_REVSET,
79376
79443
  "-T",
79377
- "json(bookmarks)"
79444
+ 'json(bookmarks) ++ "\\t" ++ commit_id ++ "\\n"'
79378
79445
  ], { cwd });
79379
79446
  if (result.exitCode !== 0)
79380
79447
  return JJ_TRUNK_REVSET;
79381
- return parseJjResolvedBookmarks(result.stdout)[0] ?? JJ_TRUNK_REVSET;
79448
+ const [record] = splitJjTemplateRecords(result.stdout);
79449
+ if (!record)
79450
+ return JJ_TRUNK_REVSET;
79451
+ const fields = splitJjTemplateFields(record);
79452
+ const bookmark = parseJjResolvedBookmarks(fields?.[0] ?? record).find((name) => !isGeneratedPushBookmark(name));
79453
+ if (bookmark)
79454
+ return bookmark;
79455
+ const commitId = fields?.[1]?.trim();
79456
+ if (commitId && !JJ_ROOT_COMMIT_ID.test(commitId))
79457
+ return commitId;
79458
+ return JJ_TRUNK_REVSET;
79459
+ }
79460
+ function isGeneratedPushBookmark(target) {
79461
+ const name = parseRemoteBookmark(target)?.name ?? target;
79462
+ return name.startsWith(JJ_GENERATED_PUSH_BOOKMARK_PREFIX);
79382
79463
  }
79383
79464
  function parseJjResolvedBookmarks(value) {
79384
79465
  try {
@@ -79545,9 +79626,11 @@ function firstErrorLine(stderr) {
79545
79626
  return;
79546
79627
  return line.length > 200 ? line.slice(0, 200) + "..." : line;
79547
79628
  }
79629
+ var JJ_LINE_BASE_REVSET = "latest(fork_point(roots(reachable(@, mutable()))-), 1)", JJ_GENERATED_PUSH_BOOKMARK_PREFIX = "push-", JJ_ROOT_COMMIT_ID;
79548
79630
  var init_jj_core = __esm(() => {
79549
79631
  init_review_core();
79550
79632
  init_review_core();
79633
+ JJ_ROOT_COMMIT_ID = /^0+$/;
79551
79634
  });
79552
79635
 
79553
79636
  // ../../packages/shared/gitbutler-core.ts
@@ -83693,9 +83776,9 @@ function parseCallDiffWorkerResult(value) {
83693
83776
  if (!isRecord2(value.result) || !Array.isArray(value.result.trees)) {
83694
83777
  throw new Error("CallDiff worker response is missing its diff trees.");
83695
83778
  }
83696
- if (value.result.trees.length > MAX_TREES) {
83697
- throw new Error("CallDiff result exceeded Plannotator's tree limits.");
83698
- }
83779
+ const totalTreeCount = value.result.trees.length;
83780
+ const truncatedTrees = totalTreeCount > MAX_TREES;
83781
+ const boundedTreeCandidates = truncatedTrees ? value.result.trees.slice(0, MAX_TREES) : value.result.trees;
83699
83782
  let nodeCount = 0;
83700
83783
  const parseNode = (candidate, depth) => {
83701
83784
  if (!isRecord2(candidate) || depth > MAX_TREE_DEPTH || ++nodeCount > MAX_NODES) {
@@ -83727,7 +83810,7 @@ function parseCallDiffWorkerResult(value) {
83727
83810
  };
83728
83811
  };
83729
83812
  const raw2 = boundedRaw(value.result.ascii);
83730
- const trees = value.result.trees.map((candidate) => {
83813
+ const trees = boundedTreeCandidates.map((candidate) => {
83731
83814
  if (!isRecord2(candidate))
83732
83815
  throw new Error("CallDiff worker returned an invalid tree.");
83733
83816
  const entry = boundedString(candidate.entry, "tree entry");
@@ -83759,6 +83842,12 @@ function parseCallDiffWorkerResult(value) {
83759
83842
  });
83760
83843
  }
83761
83844
  }
83845
+ if (truncatedTrees) {
83846
+ diagnostics.push({
83847
+ level: "warning",
83848
+ message: `Showing the first ${MAX_TREES.toLocaleString("en-US")} of ${totalTreeCount.toLocaleString("en-US")} call trees; the rest were truncated to bound the result.`
83849
+ });
83850
+ }
83762
83851
  return {
83763
83852
  version: boundedString(value.version, "version", 100),
83764
83853
  from: boundedString(value.result.from, "from snapshot"),
@@ -83825,7 +83914,7 @@ function indexCallFlowImpacts(trees) {
83825
83914
  }
83826
83915
  };
83827
83916
  }
83828
- var MAX_TREES = 100, MAX_NODES = 5000, MAX_TREE_DEPTH = 32, MAX_DIAGNOSTICS = 100, MAX_TEXT_LENGTH = 2000, MAX_RAW_LENGTH;
83917
+ var MAX_TREES = 2000, MAX_NODES = 5000, MAX_TREE_DEPTH = 32, MAX_DIAGNOSTICS = 100, MAX_TEXT_LENGTH = 2000, MAX_RAW_LENGTH;
83829
83918
  var init_call_flow_types = __esm(() => {
83830
83919
  MAX_RAW_LENGTH = 1024 * 1024;
83831
83920
  });
package/dist/index.js CHANGED
@@ -12940,7 +12940,8 @@ var PLAN_TOOL_NAMES = {
12940
12940
  "copilot-cli": "exit_plan_mode",
12941
12941
  pi: "plannotator_submit_plan",
12942
12942
  codex: "ExitPlanMode",
12943
- "gemini-cli": "exit_plan_mode"
12943
+ "gemini-cli": "exit_plan_mode",
12944
+ "oh-my-pi": "ExitPlanMode"
12944
12945
  };
12945
12946
  function getPlanToolName(runtime) {
12946
12947
  return runtime && PLAN_TOOL_NAMES[runtime] || "ExitPlanMode";
package/dist/server.js CHANGED
@@ -433,7 +433,8 @@ var PLAN_TOOL_NAMES = {
433
433
  "copilot-cli": "exit_plan_mode",
434
434
  pi: "plannotator_submit_plan",
435
435
  codex: "ExitPlanMode",
436
- "gemini-cli": "exit_plan_mode"
436
+ "gemini-cli": "exit_plan_mode",
437
+ "oh-my-pi": "ExitPlanMode"
437
438
  };
438
439
  function getPlanToolName(runtime) {
439
440
  return runtime && PLAN_TOOL_NAMES[runtime] || "ExitPlanMode";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plannotator/opencode",
3
- "version": "0.27.6",
3
+ "version": "0.27.7",
4
4
  "type": "module",
5
5
  "description": "Plannotator plugin for OpenCode - interactive plan review with visual annotation",
6
6
  "author": "backnotprop",
@@ -27,22 +27,25 @@
27
27
  "exports": {
28
28
  ".": "./dist/server.js"
29
29
  },
30
+ "//files": "skills/ is generated by build:skill from apps/skills/core/plannotator and is gitignored, so the shipped copy cannot drift from the single source.",
30
31
  "files": [
31
32
  "dist",
32
33
  "commands",
34
+ "skills",
33
35
  "README.md",
34
36
  "plannotator.html",
35
37
  "review-editor.html"
36
38
  ],
37
39
  "scripts": {
38
- "build": "mkdir -p dist && cp ../hook/dist/index.html ./plannotator.html && cp ../review/dist/index.html ./review-editor.html && bun build embedded.ts --outfile dist/embedded.js --target bun --external @opencode-ai/plugin && bun build index.ts --outfile dist/index.js --target node && bun build server.ts --outfile dist/server.js --target node --external @opencode-ai/plugin",
40
+ "build": "bun run build:skill && mkdir -p dist && cp ../hook/dist/index.html ./plannotator.html && cp ../review/dist/index.html ./review-editor.html && bun build embedded.ts --outfile dist/embedded.js --target bun --external @opencode-ai/plugin && bun build index.ts --outfile dist/index.js --target node && bun build server.ts --outfile dist/server.js --target node --external @opencode-ai/plugin",
41
+ "build:skill": "rm -rf skills && mkdir -p skills && cp -R ../skills/core/plannotator skills/plannotator",
39
42
  "smoke:v2": "bun fixtures/v2-installed-smoke.ts",
40
- "postinstall": "mkdir -p ${XDG_CONFIG_HOME:-$HOME/.config}/opencode/commands && cp ./commands/*.md ${XDG_CONFIG_HOME:-$HOME/.config}/opencode/commands/ 2>/dev/null || true",
43
+ "postinstall": "mkdir -p ${XDG_CONFIG_HOME:-$HOME/.config}/opencode/commands && cp ./commands/*.md ${XDG_CONFIG_HOME:-$HOME/.config}/opencode/commands/ 2>/dev/null || true; mkdir -p ${XDG_CONFIG_HOME:-$HOME/.config}/opencode/skills/plannotator && cp ./skills/plannotator/SKILL.md ${XDG_CONFIG_HOME:-$HOME/.config}/opencode/skills/plannotator/ 2>/dev/null || true",
41
44
  "prepublishOnly": "bun run build"
42
45
  },
43
46
  "devDependencies": {
44
47
  "@opencode-ai/plugin": "0.0.0-next-16775",
45
- "@plannotator/server": "0.27.3",
48
+ "@plannotator/server": "0.27.6",
46
49
  "@plannotator/shared": "0.0.1"
47
50
  },
48
51
  "engines": {