oh-my-opencode 4.9.1 → 4.10.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.
Files changed (220) hide show
  1. package/.agents/skills/opencode-qa/SKILL.md +1 -0
  2. package/.agents/skills/opencode-qa/scripts/lib/common.sh +39 -1
  3. package/.agents/skills/opencode-qa/scripts/lib/fake-openai-branches.mjs +39 -0
  4. package/.agents/skills/opencode-qa/scripts/lib/fake-openai-events.mjs +106 -0
  5. package/.agents/skills/opencode-qa/scripts/lib/fake-openai-server.mjs +117 -0
  6. package/.agents/skills/opencode-qa/scripts/serve-wake-split-probe.sh +716 -0
  7. package/.agents/skills/tech-debt-audit/SKILL.md +277 -0
  8. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/execution-plan.md +1 -1
  9. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/execution-plan.md +1 -1
  10. package/bin/platform.js +5 -0
  11. package/bin/platform.test.ts +56 -0
  12. package/dist/agents/atlas/agent.d.ts +4 -3
  13. package/dist/agents/gpt-apply-patch-guard.d.ts +2 -2
  14. package/dist/agents/hephaestus/agent.d.ts +5 -0
  15. package/dist/agents/hephaestus/index.d.ts +1 -1
  16. package/dist/agents/metis.d.ts +1 -0
  17. package/dist/agents/prometheus/system-prompt.d.ts +1 -1
  18. package/dist/agents/sisyphus/kimi-k2-7.d.ts +17 -0
  19. package/dist/agents/sisyphus-junior/agent.d.ts +1 -1
  20. package/dist/agents/sisyphus-junior/kimi-k2-7.d.ts +11 -0
  21. package/dist/agents/types.d.ts +2 -2
  22. package/dist/cli/doctor/checks/codex-components.d.ts +13 -0
  23. package/dist/cli/doctor/checks/tui-plugin-config.d.ts +1 -0
  24. package/dist/cli/doctor/constants.d.ts +1 -1
  25. package/dist/cli/index.js +32329 -31437
  26. package/dist/cli/install-codex/codex-cleanup.d.ts +4 -0
  27. package/dist/cli/install-codex/install-codex-test-fixtures.d.ts +34 -0
  28. package/dist/cli/install-codex/link-cached-plugin-agents.d.ts +4 -0
  29. package/dist/cli/model-fallback.d.ts +1 -0
  30. package/dist/cli/provider-availability.d.ts +2 -0
  31. package/dist/cli-node/index.js +32329 -31437
  32. package/dist/config/schema/agent-overrides.d.ts +80 -16
  33. package/dist/config/schema/experimental.d.ts +1 -1
  34. package/dist/config/schema/hooks.d.ts +0 -1
  35. package/dist/config/schema/internal/permission.d.ts +5 -1
  36. package/dist/config/schema/oh-my-opencode-config.d.ts +76 -16
  37. package/dist/create-hooks.d.ts +0 -1
  38. package/dist/features/background-agent/index.d.ts +1 -1
  39. package/dist/features/background-agent/manager.d.ts +6 -0
  40. package/dist/features/background-agent/types.d.ts +2 -0
  41. package/dist/features/claude-code-plugin-loader/types.d.ts +3 -0
  42. package/dist/features/claude-code-session-state/state.d.ts +1 -0
  43. package/dist/features/skill-mcp-manager/manager.d.ts +11 -7
  44. package/dist/features/team-mode/team-mailbox/pending-delivery-recovery.d.ts +31 -0
  45. package/dist/features/team-mode/team-runtime/delete-team.d.ts +2 -1
  46. package/dist/features/team-mode/tools/lifecycle-inline-spec.d.ts +2 -2
  47. package/dist/features/tmux-subagent/stale-tmux-resource-sweeper.d.ts +12 -0
  48. package/dist/features/tool-metadata-store/store.d.ts +5 -0
  49. package/dist/hooks/anthropic-context-window-limit-recovery/storage/constants.d.ts +3 -0
  50. package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/messages-reader.d.ts +1 -1
  51. package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/part-content.d.ts +1 -1
  52. package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/parts-reader.d.ts +1 -1
  53. package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery/storage}/types.d.ts +0 -13
  54. package/dist/hooks/auto-update-checker/checker/bundled-version.d.ts +1 -0
  55. package/dist/hooks/auto-update-checker/checker.d.ts +1 -0
  56. package/dist/hooks/auto-update-checker/constants.d.ts +3 -3
  57. package/dist/hooks/auto-update-checker/hook.d.ts +2 -1
  58. package/dist/hooks/claude-code-hooks/types.d.ts +4 -0
  59. package/dist/hooks/index.d.ts +0 -1
  60. package/dist/hooks/team-session-events/team-idle-wake-hint.d.ts +5 -0
  61. package/dist/index.js +6061 -3714
  62. package/dist/oh-my-opencode.schema.json +123 -18
  63. package/dist/plugin/build-team-idle-wake-hint-client.d.ts +2 -0
  64. package/dist/plugin/event-session-lifecycle.d.ts +0 -3
  65. package/dist/plugin/hooks/create-continuation-hooks.d.ts +0 -6
  66. package/dist/plugin/hooks/create-core-hooks.d.ts +0 -1
  67. package/dist/plugin/hooks/create-session-hooks.d.ts +1 -2
  68. package/dist/shared/command-executor/execute-hook-command.d.ts +7 -0
  69. package/dist/shared/internal-initiator-marker.d.ts +7 -0
  70. package/dist/shared/live-server-route.d.ts +24 -0
  71. package/dist/shared/plugin-identity.d.ts +2 -2
  72. package/dist/shared/prompt-async-gate/prompt-message-state.d.ts +1 -0
  73. package/dist/shared/tmux/tmux-utils/server-health.d.ts +2 -1
  74. package/dist/shared/tmux/tmux-utils/stale-attach-pane-sweep.d.ts +16 -0
  75. package/dist/shared/tmux/tmux-utils.d.ts +1 -0
  76. package/dist/testing/create-plugin-module.d.ts +4 -0
  77. package/dist/tools/background-task/clients.d.ts +2 -0
  78. package/dist/tools/background-task/full-session-format.d.ts +1 -0
  79. package/dist/tools/background-task/types.d.ts +1 -0
  80. package/dist/tools/delegate-task/sync-prompt-sender.d.ts +1 -1
  81. package/dist/tools/delegate-task/sync-session-lifecycle.d.ts +2 -1
  82. package/dist/tools/look-at/look-at-input-preparer.d.ts +6 -2
  83. package/dist/tools/look-at/look-at-prompt.d.ts +2 -1
  84. package/dist/tools/look-at/look-at-session-runner.d.ts +3 -4
  85. package/dist/tools/look-at/types.d.ts +2 -0
  86. package/dist/tools/session-manager/types.d.ts +1 -0
  87. package/dist/tools/skill-mcp/types.d.ts +1 -0
  88. package/package.json +14 -13
  89. package/packages/ast-grep-mcp/dist/cli.js +50 -17
  90. package/packages/lsp-daemon/dist/cli.js +8 -5
  91. package/packages/lsp-daemon/dist/index.js +8 -5
  92. package/packages/lsp-tools-mcp/dist/lsp/connection.js +1 -1
  93. package/packages/lsp-tools-mcp/dist/lsp/server-definitions.js +2 -2
  94. package/packages/lsp-tools-mcp/dist/lsp/transport.d.ts +10 -1
  95. package/packages/lsp-tools-mcp/dist/lsp/transport.js +6 -3
  96. package/packages/omo-codex/lazycodex-repository/.github/workflows/pr-source-guidance.yml +11 -12
  97. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  98. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +2583 -0
  99. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +17 -0
  100. package/packages/omo-codex/plugin/components/bootstrap/manifests/ast-grep.json +22 -0
  101. package/packages/omo-codex/plugin/components/bootstrap/manifests/node.json +10 -0
  102. package/packages/omo-codex/plugin/components/bootstrap/package.json +20 -0
  103. package/packages/omo-codex/plugin/components/bootstrap/scripts/bootstrap.ps1 +310 -0
  104. package/packages/omo-codex/plugin/components/bootstrap/scripts/build.mjs +35 -0
  105. package/packages/omo-codex/plugin/components/bootstrap/scripts/generate-manifests.mjs +115 -0
  106. package/packages/omo-codex/plugin/components/bootstrap/src/cli.ts +153 -0
  107. package/packages/omo-codex/plugin/components/bootstrap/src/download.ts +212 -0
  108. package/packages/omo-codex/plugin/components/bootstrap/src/environment.ts +286 -0
  109. package/packages/omo-codex/plugin/components/bootstrap/src/hook.ts +108 -0
  110. package/packages/omo-codex/plugin/components/bootstrap/src/provision.ts +243 -0
  111. package/packages/omo-codex/plugin/components/bootstrap/src/setup.ts +294 -0
  112. package/packages/omo-codex/plugin/components/bootstrap/src/worker.ts +279 -0
  113. package/packages/omo-codex/plugin/components/bootstrap/test/download.test.ts +295 -0
  114. package/packages/omo-codex/plugin/components/bootstrap/test/environment.test.ts +375 -0
  115. package/packages/omo-codex/plugin/components/bootstrap/test/provision.test.ts +464 -0
  116. package/packages/omo-codex/plugin/components/bootstrap/tsconfig.json +25 -0
  117. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  118. package/packages/omo-codex/plugin/components/comment-checker/package.json +4 -4
  119. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  120. package/packages/omo-codex/plugin/components/git-bash/package.json +2 -2
  121. package/packages/omo-codex/plugin/components/lsp/dist/codex-hook-cli.js +6 -10
  122. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  123. package/packages/omo-codex/plugin/components/lsp/package.json +4 -4
  124. package/packages/omo-codex/plugin/components/lsp/scripts/build-lsp-tools.test.mjs +8 -3
  125. package/packages/omo-codex/plugin/components/lsp/src/codex-hook-cli.ts +5 -8
  126. package/packages/omo-codex/plugin/components/lsp/test/codex-hook-cli.test.ts +24 -1
  127. package/packages/omo-codex/plugin/components/rules/bundled-rules/windows-git-bash.md +3 -1
  128. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  129. package/packages/omo-codex/plugin/components/rules/package.json +4 -4
  130. package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +35 -1
  131. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  132. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +4 -4
  133. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  134. package/packages/omo-codex/plugin/components/telemetry/package.json +4 -4
  135. package/packages/omo-codex/plugin/components/ultrawork/biome.json +1 -1
  136. package/packages/omo-codex/plugin/components/ultrawork/directive.md +155 -99
  137. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  138. package/packages/omo-codex/plugin/components/ultrawork/package.json +4 -4
  139. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +19 -51
  140. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +46 -51
  141. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +19 -0
  142. package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +0 -1
  143. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +9 -1
  144. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -0
  145. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +18 -0
  146. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +1 -3
  147. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +2 -2
  148. package/packages/omo-codex/plugin/components/ulw-loop/package.json +4 -4
  149. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +6 -2
  150. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +19 -0
  151. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +1 -1
  152. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-commands.test.ts +6 -0
  153. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-complete-goals.test.ts +26 -1
  154. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-json-errors.test.ts +89 -0
  155. package/packages/omo-codex/plugin/hooks/hooks.json +27 -16
  156. package/packages/omo-codex/plugin/package-lock.json +193 -193
  157. package/packages/omo-codex/plugin/package.json +1 -1
  158. package/packages/omo-codex/plugin/scripts/auto-update-state.d.mts +20 -0
  159. package/packages/omo-codex/plugin/scripts/auto-update.mjs +28 -8
  160. package/packages/omo-codex/plugin/scripts/build-components.mjs +36 -5
  161. package/packages/omo-codex/plugin/scripts/install-flow.mjs +43 -0
  162. package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/SKILL.md +79 -28
  163. package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/agents/openai.yaml +2 -2
  164. package/packages/omo-codex/plugin/skills/lcx-report-bug/SKILL.md +7 -6
  165. package/packages/omo-codex/plugin/skills/lcx-report-bug/agents/openai.yaml +1 -1
  166. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +19 -51
  167. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +46 -51
  168. package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -0
  169. package/packages/omo-codex/plugin/test/auto-update.test.mjs +145 -0
  170. package/packages/omo-codex/plugin/test/bootstrap-binlinks.test.mjs +250 -0
  171. package/packages/omo-codex/plugin/test/bootstrap-hooks.test.mjs +166 -0
  172. package/packages/omo-codex/plugin/test/bootstrap-orchestration.test.mjs +371 -0
  173. package/packages/omo-codex/plugin/test/bootstrap-ps-guard.test.mjs +134 -0
  174. package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +249 -0
  175. package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +10 -1
  176. package/packages/omo-codex/plugin/test/ulw-plan-skill.test.mjs +46 -0
  177. package/packages/omo-codex/scripts/atomic-write.test.mjs +82 -0
  178. package/packages/omo-codex/scripts/install/agents.d.mts +18 -0
  179. package/packages/omo-codex/scripts/install/agents.mjs +78 -5
  180. package/packages/omo-codex/scripts/install/atomic-write.mjs +59 -0
  181. package/packages/omo-codex/scripts/install/bin-dir.d.mts +7 -0
  182. package/packages/omo-codex/scripts/install/bin-links.d.mts +18 -0
  183. package/packages/omo-codex/scripts/install/config.d.mts +35 -0
  184. package/packages/omo-codex/scripts/install/config.mjs +13 -3
  185. package/packages/omo-codex/scripts/install/git-bash-mcp-env.d.mts +5 -0
  186. package/packages/omo-codex/scripts/install/git-bash.d.mts +23 -0
  187. package/packages/omo-codex/scripts/install/hook-trust.d.mts +10 -0
  188. package/packages/omo-codex/scripts/install-agent-links.test.mjs +41 -0
  189. package/packages/omo-codex/scripts/install-local.mjs +3 -2
  190. package/packages/shared-skills/skills/lcx-contribute-bug-fix/SKILL.md +79 -28
  191. package/packages/shared-skills/skills/lcx-contribute-bug-fix/agents/openai.yaml +2 -2
  192. package/packages/shared-skills/skills/lcx-report-bug/SKILL.md +7 -6
  193. package/packages/shared-skills/skills/lcx-report-bug/agents/openai.yaml +1 -1
  194. package/dist/hooks/session-recovery/constants.d.ts +0 -4
  195. package/dist/hooks/session-recovery/detect-error-type.d.ts +0 -4
  196. package/dist/hooks/session-recovery/error-recovery.d.ts +0 -4
  197. package/dist/hooks/session-recovery/hook-types.d.ts +0 -22
  198. package/dist/hooks/session-recovery/hook.d.ts +0 -4
  199. package/dist/hooks/session-recovery/index.d.ts +0 -5
  200. package/dist/hooks/session-recovery/interrupted-idle-message-fetch-timeout.d.ts +0 -7
  201. package/dist/hooks/session-recovery/interrupted-tool-results.d.ts +0 -3
  202. package/dist/hooks/session-recovery/message-state.d.ts +0 -4
  203. package/dist/hooks/session-recovery/recover-thinking-block-order.d.ts +0 -5
  204. package/dist/hooks/session-recovery/recover-thinking-disabled-violation.d.ts +0 -5
  205. package/dist/hooks/session-recovery/recover-tool-result-missing.d.ts +0 -10
  206. package/dist/hooks/session-recovery/recover-unavailable-tool.d.ts +0 -5
  207. package/dist/hooks/session-recovery/resume.d.ts +0 -7
  208. package/dist/hooks/session-recovery/storage/latest-assistant-message.d.ts +0 -5
  209. package/dist/hooks/session-recovery/storage/orphan-thinking-search.d.ts +0 -2
  210. package/dist/hooks/session-recovery/storage/thinking-block-search.d.ts +0 -2
  211. package/dist/hooks/session-recovery/storage/thinking-prepend.d.ts +0 -33
  212. package/dist/hooks/session-recovery/storage/thinking-strip.d.ts +0 -11
  213. package/dist/hooks/session-recovery/storage.d.ts +0 -20
  214. package/dist/plugin/event-session-recovery.d.ts +0 -9
  215. package/dist/plugin/user-abort-interrupted-recovery-guard.d.ts +0 -6
  216. /package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/empty-messages.d.ts +0 -0
  217. /package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/empty-text.d.ts +0 -0
  218. /package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/message-dir.d.ts +0 -0
  219. /package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/part-id.d.ts +0 -0
  220. /package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/text-part-injector.d.ts +0 -0
@@ -0,0 +1,17 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "node \"${PLUGIN_ROOT}/components/bootstrap/dist/cli.js\" hook session-start",
9
+ "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\bootstrap.ps1\"",
10
+ "timeout": 30,
11
+ "statusMessage": "LazyCodex(4.10.0): Checking Bootstrap Provisioning"
12
+ }
13
+ ]
14
+ }
15
+ ]
16
+ }
17
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "ast-grep",
3
+ "platforms": {
4
+ "darwin-arm64": {
5
+ "sha256": "12a870c414c90208f338649b0b53d9659b724b680edaf9da9c151275dad3e41a",
6
+ "url": "https://github.com/ast-grep/ast-grep/releases/download/0.42.3/app-aarch64-apple-darwin.zip"
7
+ },
8
+ "darwin-x64": {
9
+ "sha256": "af5a04a43c062974634296f692ab93c03755e5b6f33e70e226a434cde1355a1f",
10
+ "url": "https://github.com/ast-grep/ast-grep/releases/download/0.42.3/app-x86_64-apple-darwin.zip"
11
+ },
12
+ "linux-x64": {
13
+ "sha256": "4191ac4247d183c502778e740a68b7cf45fe477b6423c43b8b8d6e732ba3b333",
14
+ "url": "https://github.com/ast-grep/ast-grep/releases/download/0.42.3/app-x86_64-unknown-linux-gnu.zip"
15
+ },
16
+ "win32-x64": {
17
+ "sha256": "98acb57edae7a9f9e68657c2cc03ce25b7144bae69621fe7cf2d0492807cb623",
18
+ "url": "https://github.com/ast-grep/ast-grep/releases/download/0.42.3/app-x86_64-pc-windows-msvc.zip"
19
+ }
20
+ },
21
+ "version": "0.42.3"
22
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "node",
3
+ "platforms": {
4
+ "win32-x64": {
5
+ "sha256": "edaca9bd58ec8e92037dac4e877d52f6b8f430b81c18b57e264b4e2fb111cd56",
6
+ "url": "https://nodejs.org/dist/v24.16.0/node-v24.16.0-win-x64.zip"
7
+ }
8
+ },
9
+ "version": "24.16.0"
10
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@sisyphuslabs/codex-bootstrap",
3
+ "version": "4.10.0",
4
+ "description": "Codex SessionStart bootstrap component that provisions LazyCodex runtime dependencies from a detached worker.",
5
+ "type": "module",
6
+ "private": true,
7
+ "files": [
8
+ "dist",
9
+ "hooks",
10
+ "scripts",
11
+ "manifests"
12
+ ],
13
+ "scripts": {
14
+ "build": "node scripts/build.mjs",
15
+ "test": "bun test test/*.test.ts"
16
+ },
17
+ "engines": {
18
+ "node": ">=20.0.0"
19
+ }
20
+ }
@@ -0,0 +1,310 @@
1
+ # LazyCodex bootstrap SessionStart hook for native Windows (Windows PowerShell 5.1).
2
+ # Codex runs hooks through %COMSPEC%, so node may be absent from PATH entirely;
3
+ # this script provisions it silently: node on PATH -> common install dirs ->
4
+ # winget OpenJS.NodeJS.LTS -> portable ZIP pinned by manifests/node.json
5
+ # (sha256-verified, extracted under <codexHome>\runtime\node, USER PATH append).
6
+ # Git Bash is prepared best-effort on the provisioning path, then the script
7
+ # delegates to the bundled node hook. It always exits 0: provisioning failures
8
+ # are logged to $env:PLUGIN_DATA\bootstrap\ps-bootstrap.log, never block a session.
9
+
10
+ $ErrorActionPreference = "Continue"
11
+ [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
12
+
13
+ $script:LogPath = $null
14
+ $script:DoctorHint = "npx lazycodex-ai doctor"
15
+ $script:NonGitBashLauncherDirSegments = @("\windows\system32\", "\microsoft\windowsapps\")
16
+
17
+ function Initialize-BootstrapLog {
18
+ if ([string]::IsNullOrWhiteSpace($env:PLUGIN_DATA)) { return }
19
+ try {
20
+ $logDirectory = Join-Path $env:PLUGIN_DATA "bootstrap"
21
+ if (-not (Test-Path -LiteralPath $logDirectory)) {
22
+ New-Item -ItemType Directory -Path $logDirectory -Force | Out-Null
23
+ }
24
+ $script:LogPath = Join-Path $logDirectory "ps-bootstrap.log"
25
+ } catch {
26
+ $script:LogPath = $null
27
+ }
28
+ }
29
+
30
+ function Write-BootstrapLog {
31
+ param([string]$Message)
32
+ if ($null -eq $script:LogPath) { return }
33
+ try {
34
+ $stamp = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
35
+ Add-Content -LiteralPath $script:LogPath -Value ($stamp + " " + $Message) -Encoding ASCII
36
+ } catch { }
37
+ }
38
+
39
+ function Resolve-CodexHome {
40
+ if (-not [string]::IsNullOrWhiteSpace($env:CODEX_HOME)) { return $env:CODEX_HOME.Trim() }
41
+ if (-not [string]::IsNullOrWhiteSpace($env:PLUGIN_ROOT)) {
42
+ $current = $env:PLUGIN_ROOT
43
+ for ($level = 0; $level -lt 6; $level += 1) {
44
+ $parent = Split-Path -Path $current -Parent
45
+ if ([string]::IsNullOrEmpty($parent) -or ($parent -eq $current)) { break }
46
+ $current = $parent
47
+ if (Test-Path -LiteralPath (Join-Path $current "config.toml") -PathType Leaf) { return $current }
48
+ }
49
+ }
50
+ return (Join-Path $env:USERPROFILE ".codex")
51
+ }
52
+
53
+ function Get-NodeManifest {
54
+ $manifestPath = Join-Path $env:PLUGIN_ROOT "components\bootstrap\manifests\node.json"
55
+ if (-not (Test-Path -LiteralPath $manifestPath -PathType Leaf)) {
56
+ Write-BootstrapLog ("degraded component=node reason=manifest-missing path=" + $manifestPath + " hint=" + $script:DoctorHint)
57
+ return $null
58
+ }
59
+ try {
60
+ return (Get-Content -LiteralPath $manifestPath -Raw | ConvertFrom-Json)
61
+ } catch {
62
+ Write-BootstrapLog ("degraded component=node reason=manifest-unparsable path=" + $manifestPath + " hint=" + $script:DoctorHint)
63
+ return $null
64
+ }
65
+ }
66
+
67
+ function Get-PortableNodeDirectory {
68
+ param([string]$CodexHome, $Manifest)
69
+ $runtimeRoot = Join-Path $CodexHome "runtime\node"
70
+ return (Join-Path $runtimeRoot ("node-v" + $Manifest.version + "-win-x64"))
71
+ }
72
+
73
+ function Resolve-NodeCommand {
74
+ param([string]$CodexHome, $Manifest)
75
+ $onPath = Get-Command node -CommandType Application -ErrorAction SilentlyContinue
76
+ if ($null -ne $onPath) {
77
+ return (@($onPath)[0]).Source
78
+ }
79
+ $candidateDirectories = @()
80
+ if (-not [string]::IsNullOrWhiteSpace($env:ProgramFiles)) {
81
+ $candidateDirectories += (Join-Path $env:ProgramFiles "nodejs")
82
+ }
83
+ if (-not [string]::IsNullOrWhiteSpace($env:LOCALAPPDATA)) {
84
+ $candidateDirectories += (Join-Path $env:LOCALAPPDATA "Programs\nodejs")
85
+ }
86
+ if ($null -ne $Manifest) {
87
+ $candidateDirectories += (Get-PortableNodeDirectory -CodexHome $CodexHome -Manifest $Manifest)
88
+ }
89
+ foreach ($directory in $candidateDirectories) {
90
+ $candidate = Join-Path $directory "node.exe"
91
+ if (Test-Path -LiteralPath $candidate -PathType Leaf) { return $candidate }
92
+ }
93
+ return $null
94
+ }
95
+
96
+ function Install-NodeWithWinget {
97
+ $winget = Get-Command winget -ErrorAction SilentlyContinue
98
+ if ($null -eq $winget) {
99
+ Write-BootstrapLog "winget unavailable; skipping winget node install"
100
+ return
101
+ }
102
+ Write-BootstrapLog "installing node via: winget install OpenJS.NodeJS.LTS --silent"
103
+ try {
104
+ & winget install OpenJS.NodeJS.LTS --silent --accept-package-agreements --accept-source-agreements | Out-Null
105
+ Write-BootstrapLog ("winget node install finished with exit code " + $LASTEXITCODE)
106
+ } catch {
107
+ Write-BootstrapLog ("winget node install failed: " + $_.Exception.Message)
108
+ }
109
+ }
110
+
111
+ function Add-UserPathEntry {
112
+ param([string]$Directory)
113
+ $normalizedTarget = $Directory.TrimEnd("\")
114
+ $currentPath = [Environment]::GetEnvironmentVariable("Path", "User")
115
+ if ($null -eq $currentPath) { $currentPath = "" }
116
+ foreach ($entry in $currentPath.Split(";")) {
117
+ if ($entry.Trim().TrimEnd("\") -eq $normalizedTarget) {
118
+ Write-BootstrapLog ("user PATH already contains " + $Directory + "; leaving it unchanged")
119
+ return
120
+ }
121
+ }
122
+ if ($currentPath.Trim().Length -eq 0) {
123
+ $updatedPath = $Directory
124
+ } else {
125
+ $updatedPath = $currentPath.TrimEnd(";") + ";" + $Directory
126
+ }
127
+ [Environment]::SetEnvironmentVariable("Path", $updatedPath, "User")
128
+ Write-BootstrapLog ("appended " + $Directory + " to the USER PATH; restart Codex so new sessions can see node")
129
+ }
130
+
131
+ function Install-PortableNode {
132
+ param([string]$CodexHome, $Manifest)
133
+ if ($null -eq $Manifest) { return $null }
134
+ $platformEntry = $Manifest.platforms."win32-x64"
135
+ if ($null -eq $platformEntry) {
136
+ Write-BootstrapLog ("degraded component=node reason=manifest-missing-win32-x64 hint=" + $script:DoctorHint)
137
+ return $null
138
+ }
139
+ $zipPath = Join-Path $env:TEMP ("lazycodex-node-v" + $Manifest.version + "-win-x64.zip")
140
+ Write-BootstrapLog ("downloading portable node from " + $platformEntry.url)
141
+ try {
142
+ Invoke-WebRequest -Uri $platformEntry.url -OutFile $zipPath -UseBasicParsing
143
+ } catch {
144
+ Write-BootstrapLog ("degraded component=node reason=download-failed url=" + $platformEntry.url + " error=" + $_.Exception.Message + " hint=" + $script:DoctorHint)
145
+ return $null
146
+ }
147
+ $expectedHash = ([string]$platformEntry.sha256).ToLowerInvariant()
148
+ $actualHash = (Get-FileHash -LiteralPath $zipPath -Algorithm SHA256).Hash.ToLowerInvariant()
149
+ if ($actualHash -ne $expectedHash) {
150
+ Remove-Item -LiteralPath $zipPath -Force -ErrorAction SilentlyContinue
151
+ Write-BootstrapLog ("degraded component=node reason=sha256-mismatch expected=" + $expectedHash + " actual=" + $actualHash + " hint=" + $script:DoctorHint)
152
+ return $null
153
+ }
154
+ $runtimeRoot = Join-Path $CodexHome "runtime\node"
155
+ try {
156
+ if (-not (Test-Path -LiteralPath $runtimeRoot)) {
157
+ New-Item -ItemType Directory -Path $runtimeRoot -Force | Out-Null
158
+ }
159
+ Expand-Archive -LiteralPath $zipPath -DestinationPath $runtimeRoot -Force
160
+ } catch {
161
+ Write-BootstrapLog ("degraded component=node reason=extract-failed error=" + $_.Exception.Message + " hint=" + $script:DoctorHint)
162
+ return $null
163
+ } finally {
164
+ Remove-Item -LiteralPath $zipPath -Force -ErrorAction SilentlyContinue
165
+ }
166
+ $nodeDirectory = Get-PortableNodeDirectory -CodexHome $CodexHome -Manifest $Manifest
167
+ $nodeExe = Join-Path $nodeDirectory "node.exe"
168
+ if (-not (Test-Path -LiteralPath $nodeExe -PathType Leaf)) {
169
+ Write-BootstrapLog ("degraded component=node reason=extracted-layout-unexpected expected=" + $nodeExe + " hint=" + $script:DoctorHint)
170
+ return $null
171
+ }
172
+ Write-BootstrapLog ("portable node provisioned at " + $nodeExe)
173
+ Add-UserPathEntry -Directory $nodeDirectory
174
+ return $nodeExe
175
+ }
176
+
177
+ function Test-KnownNonGitBashLauncher {
178
+ param([string]$CandidatePath)
179
+ $normalized = $CandidatePath.Replace("/", "\").ToLowerInvariant()
180
+ foreach ($segment in $script:NonGitBashLauncherDirSegments) {
181
+ if ($normalized.Contains($segment)) { return $true }
182
+ }
183
+ return $false
184
+ }
185
+
186
+ function Resolve-GitBash {
187
+ if (-not [string]::IsNullOrWhiteSpace($env:OMO_CODEX_GIT_BASH_PATH)) {
188
+ $envCandidate = $env:OMO_CODEX_GIT_BASH_PATH.Trim()
189
+ if ($envCandidate.ToLowerInvariant().EndsWith("bash.exe") -and (Test-Path -LiteralPath $envCandidate -PathType Leaf)) {
190
+ return @{ Path = $envCandidate; Source = "env" }
191
+ }
192
+ return $null
193
+ }
194
+ $programFilesCandidates = @()
195
+ if (-not [string]::IsNullOrWhiteSpace($env:ProgramFiles)) {
196
+ $programFilesCandidates += (Join-Path $env:ProgramFiles "Git\bin\bash.exe")
197
+ }
198
+ $programFilesX86 = ${env:ProgramFiles(x86)}
199
+ if (-not [string]::IsNullOrWhiteSpace($programFilesX86)) {
200
+ $programFilesCandidates += (Join-Path $programFilesX86 "Git\bin\bash.exe")
201
+ }
202
+ foreach ($candidate in $programFilesCandidates) {
203
+ if (Test-Path -LiteralPath $candidate -PathType Leaf) {
204
+ return @{ Path = $candidate; Source = "program-files" }
205
+ }
206
+ }
207
+ $whereOutput = @()
208
+ try { $whereOutput = & where.exe bash 2>$null } catch { $whereOutput = @() }
209
+ foreach ($rawLine in @($whereOutput)) {
210
+ if ($null -eq $rawLine) { continue }
211
+ $candidate = ([string]$rawLine).Trim()
212
+ if ($candidate.Length -eq 0) { continue }
213
+ if (Test-KnownNonGitBashLauncher -CandidatePath $candidate) { continue }
214
+ if ($candidate.ToLowerInvariant().EndsWith("bash.exe") -and (Test-Path -LiteralPath $candidate -PathType Leaf)) {
215
+ return @{ Path = $candidate; Source = "path" }
216
+ }
217
+ }
218
+ return $null
219
+ }
220
+
221
+ function Initialize-GitBash {
222
+ $resolution = Resolve-GitBash
223
+ if (($null -eq $resolution) -and ($env:OMO_CODEX_SKIP_GIT_BASH_AUTO_INSTALL -ne "1")) {
224
+ $winget = Get-Command winget -ErrorAction SilentlyContinue
225
+ if ($null -ne $winget) {
226
+ Write-BootstrapLog "installing git bash via: winget install --id Git.Git -e --source winget"
227
+ try {
228
+ & winget install --id Git.Git -e --source winget | Out-Null
229
+ Write-BootstrapLog ("winget git install finished with exit code " + $LASTEXITCODE)
230
+ } catch {
231
+ Write-BootstrapLog ("winget git install failed: " + $_.Exception.Message)
232
+ }
233
+ $resolution = Resolve-GitBash
234
+ } else {
235
+ Write-BootstrapLog "winget unavailable; skipping git bash install"
236
+ }
237
+ }
238
+ if ($null -eq $resolution) {
239
+ Write-BootstrapLog ("degraded component=git_bash reason=not-found install=winget install --id Git.Git -e --source winget hint=" + $script:DoctorHint)
240
+ return
241
+ }
242
+ Write-BootstrapLog ("git bash resolved at " + $resolution.Path + " source=" + $resolution.Source)
243
+ if ($resolution.Source -eq "path") {
244
+ $persisted = [Environment]::GetEnvironmentVariable("OMO_CODEX_GIT_BASH_PATH", "User")
245
+ if ([string]::IsNullOrWhiteSpace($persisted)) {
246
+ [Environment]::SetEnvironmentVariable("OMO_CODEX_GIT_BASH_PATH", $resolution.Path, "User")
247
+ Write-BootstrapLog ("persisted OMO_CODEX_GIT_BASH_PATH=" + $resolution.Path + " in the USER environment; restart Codex to pick it up")
248
+ }
249
+ }
250
+ }
251
+
252
+ function Invoke-NodeHookDelegate {
253
+ param([string]$NodeExe)
254
+ $hookCli = Join-Path $env:PLUGIN_ROOT "components\bootstrap\dist\cli.js"
255
+ if (-not (Test-Path -LiteralPath $hookCli -PathType Leaf)) {
256
+ Write-BootstrapLog ("degraded component=bootstrap reason=hook-cli-missing path=" + $hookCli + " hint=" + $script:DoctorHint)
257
+ return
258
+ }
259
+ Write-BootstrapLog ("delegating to node hook: " + $NodeExe + " " + $hookCli + " hook session-start")
260
+ & $NodeExe $hookCli hook session-start
261
+ Write-BootstrapLog ("node hook exited with code " + $LASTEXITCODE)
262
+ }
263
+
264
+ function Write-ProvisioningIncompleteNotice {
265
+ $notice = "LazyCodex bootstrap: Node.js is not available yet. Install Node LTS (winget install OpenJS.NodeJS.LTS), then restart Codex. Diagnose with: " + $script:DoctorHint
266
+ $payload = @{
267
+ hookSpecificOutput = @{
268
+ hookEventName = "SessionStart"
269
+ additionalContext = $notice
270
+ }
271
+ }
272
+ Write-Output (ConvertTo-Json -InputObject $payload -Compress -Depth 4)
273
+ }
274
+
275
+ function Invoke-Bootstrap {
276
+ Initialize-BootstrapLog
277
+ Write-BootstrapLog "bootstrap.ps1 session-start begin"
278
+ if ([string]::IsNullOrWhiteSpace($env:PLUGIN_ROOT)) {
279
+ Write-BootstrapLog "PLUGIN_ROOT missing; skipping bootstrap"
280
+ return
281
+ }
282
+ $codexHome = Resolve-CodexHome
283
+ Write-BootstrapLog ("codex home resolved to " + $codexHome)
284
+ $manifest = Get-NodeManifest
285
+ $nodeExe = Resolve-NodeCommand -CodexHome $codexHome -Manifest $manifest
286
+ if ($null -ne $nodeExe) {
287
+ Write-BootstrapLog ("node already available at " + $nodeExe)
288
+ Invoke-NodeHookDelegate -NodeExe $nodeExe
289
+ return
290
+ }
291
+ Install-NodeWithWinget
292
+ $nodeExe = Resolve-NodeCommand -CodexHome $codexHome -Manifest $manifest
293
+ if ($null -eq $nodeExe) {
294
+ $nodeExe = Install-PortableNode -CodexHome $codexHome -Manifest $manifest
295
+ }
296
+ Initialize-GitBash
297
+ if ($null -eq $nodeExe) {
298
+ Write-BootstrapLog ("degraded component=node reason=unresolved hint=" + $script:DoctorHint)
299
+ Write-ProvisioningIncompleteNotice
300
+ return
301
+ }
302
+ Invoke-NodeHookDelegate -NodeExe $nodeExe
303
+ }
304
+
305
+ try {
306
+ Invoke-Bootstrap
307
+ } catch {
308
+ try { Write-BootstrapLog ("unhandled bootstrap error: " + $_.Exception.Message) } catch { }
309
+ }
310
+ exit 0
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from "node:child_process";
3
+ import { existsSync, statSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ const componentRoot = dirname(dirname(fileURLToPath(import.meta.url)));
8
+ const bundlePath = join(componentRoot, "dist", "cli.js");
9
+
10
+ const result = spawnSync(
11
+ "bun",
12
+ ["x", "esbuild", "src/cli.ts", "--bundle", "--platform=node", "--format=esm", "--outfile=dist/cli.js"],
13
+ {
14
+ cwd: componentRoot,
15
+ shell: process.platform === "win32",
16
+ stdio: "inherit",
17
+ },
18
+ );
19
+
20
+ if (result.error === undefined && result.status === 0) {
21
+ process.exit(0);
22
+ }
23
+
24
+ if (hasBundledDist()) {
25
+ console.log("Using bundled bootstrap dist");
26
+ process.exit(0);
27
+ }
28
+
29
+ console.error(`Bootstrap bundle failed and no bundled dist exists at ${bundlePath}.`);
30
+ console.error("Install Bun (used via `bun x esbuild`) or ship a prebuilt dist/cli.js.");
31
+ process.exit(result.status === null || result.status === undefined || result.status === 0 ? 1 : result.status);
32
+
33
+ function hasBundledDist() {
34
+ return existsSync(bundlePath) && statSync(bundlePath).size > 0;
35
+ }
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+ // Regenerates the committed, reviewed manifests at ../manifests/{ast-grep,node}.json.
3
+ // This script is the ONLY network-touching code in the bootstrap component; runtime
4
+ // downloads consume the pinned values, and unit tests inject fetch (never the network).
5
+ //
6
+ // Re-run procedure (after an @ast-grep/cli bump in packages/ast-grep-mcp/package.json,
7
+ // or to move the pinned Node.js LTS):
8
+ // 1. bun install (so node_modules/@ast-grep/cli matches the lockfile resolution)
9
+ // 2. node packages/omo-codex/plugin/components/bootstrap/scripts/generate-manifests.mjs
10
+ // [--ast-grep-version <x.y.z>] [--node-version <x.y.z>]
11
+ // 3. Review the manifest diff and commit it. Manifests are NEVER generated at build
12
+ // time; builds must stay offline and deterministic.
13
+ //
14
+ // Sources:
15
+ // - sg: https://github.com/ast-grep/ast-grep/releases (assets downloaded + hashed
16
+ // here because the release publishes no checksum files)
17
+ // - node: https://nodejs.org/dist (SHASUMS256.txt per release; win32-x64 zip only)
18
+ import { createHash } from "node:crypto";
19
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
20
+ import { dirname, join, resolve } from "node:path";
21
+ import { fileURLToPath } from "node:url";
22
+
23
+ const scriptDirectory = dirname(fileURLToPath(import.meta.url));
24
+ const componentRoot = dirname(scriptDirectory);
25
+ const repoRoot = resolve(componentRoot, "..", "..", "..", "..", "..");
26
+ const manifestsDirectory = join(componentRoot, "manifests");
27
+
28
+ const SG_PLATFORM_ASSETS = {
29
+ "darwin-arm64": "app-aarch64-apple-darwin.zip",
30
+ "darwin-x64": "app-x86_64-apple-darwin.zip",
31
+ "linux-x64": "app-x86_64-unknown-linux-gnu.zip",
32
+ "win32-x64": "app-x86_64-pc-windows-msvc.zip",
33
+ };
34
+
35
+ function parseArgs(argv) {
36
+ const flags = {};
37
+ for (let index = 0; index < argv.length; index += 1) {
38
+ if (argv[index] === "--ast-grep-version") flags.astGrepVersion = argv[(index += 1)];
39
+ else if (argv[index] === "--node-version") flags.nodeVersion = argv[(index += 1)];
40
+ else throw new Error(`unknown argument: ${argv[index]}`);
41
+ }
42
+ return flags;
43
+ }
44
+
45
+ async function fetchOk(url, accept) {
46
+ const headers = { "user-agent": "lazycodex-generate-manifests" };
47
+ if (accept) headers.accept = accept;
48
+ if (process.env.GITHUB_TOKEN && url.startsWith("https://api.github.com/")) {
49
+ headers.authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
50
+ }
51
+ const response = await fetch(url, { headers });
52
+ if (!response.ok) throw new Error(`GET ${url} -> HTTP ${response.status}`);
53
+ return response;
54
+ }
55
+
56
+ async function resolveInstalledAstGrepVersion() {
57
+ const declared = JSON.parse(await readFile(join(repoRoot, "packages", "ast-grep-mcp", "package.json"), "utf8"))
58
+ .dependencies["@ast-grep/cli"];
59
+ const installedPackageJsonPath = join(repoRoot, "node_modules", "@ast-grep", "cli", "package.json");
60
+ const installed = JSON.parse(await readFile(installedPackageJsonPath, "utf8")).version;
61
+ console.log(`ast-grep: declared ${declared} in packages/ast-grep-mcp, locked install ${installed}`);
62
+ return installed;
63
+ }
64
+
65
+ async function generateAstGrepManifest(version) {
66
+ const release = await (
67
+ await fetchOk(`https://api.github.com/repos/ast-grep/ast-grep/releases/tags/${version}`, "application/vnd.github+json")
68
+ ).json();
69
+ const assetNames = new Set(release.assets.map((asset) => asset.name));
70
+ const platforms = {};
71
+ for (const [platformKey, assetName] of Object.entries(SG_PLATFORM_ASSETS)) {
72
+ if (!assetNames.has(assetName)) {
73
+ throw new Error(`release ${version} has no asset named ${assetName} (have: ${[...assetNames].join(", ")})`);
74
+ }
75
+ const url = `https://github.com/ast-grep/ast-grep/releases/download/${version}/${assetName}`;
76
+ const bytes = Buffer.from(await (await fetchOk(url)).arrayBuffer());
77
+ const sha256 = createHash("sha256").update(bytes).digest("hex");
78
+ platforms[platformKey] = { sha256, url };
79
+ console.log(`ast-grep ${platformKey}: ${assetName} ${bytes.length} bytes sha256=${sha256}`);
80
+ }
81
+ return { name: "ast-grep", platforms, version };
82
+ }
83
+
84
+ async function resolveLatestNodeLtsVersion() {
85
+ const releases = await (await fetchOk("https://nodejs.org/dist/index.json")).json();
86
+ const latestLts = releases.find((release) => release.lts !== false);
87
+ if (latestLts === undefined) throw new Error("nodejs.org/dist/index.json contains no LTS release");
88
+ console.log(`node: latest LTS ${latestLts.version} (${latestLts.lts})`);
89
+ return latestLts.version.replace(/^v/, "");
90
+ }
91
+
92
+ async function generateNodeManifest(version) {
93
+ const zipName = `node-v${version}-win-x64.zip`;
94
+ const shasums = await (await fetchOk(`https://nodejs.org/dist/v${version}/SHASUMS256.txt`)).text();
95
+ const line = shasums.split("\n").find((candidate) => candidate.trim().endsWith(` ${zipName}`) || candidate.trim().endsWith(` ${zipName}`));
96
+ if (line === undefined) throw new Error(`SHASUMS256.txt for v${version} has no entry for ${zipName}`);
97
+ const sha256 = line.trim().split(/\s+/)[0];
98
+ if (!/^[a-f0-9]{64}$/.test(sha256)) throw new Error(`invalid sha256 parsed for ${zipName}: ${sha256}`);
99
+ const url = `https://nodejs.org/dist/v${version}/${zipName}`;
100
+ console.log(`node win32-x64: ${zipName} sha256=${sha256}`);
101
+ return { name: "node", platforms: { "win32-x64": { sha256, url } }, version };
102
+ }
103
+
104
+ async function writeManifest(fileName, manifest) {
105
+ const path = join(manifestsDirectory, fileName);
106
+ await mkdir(manifestsDirectory, { recursive: true });
107
+ await writeFile(path, `${JSON.stringify(manifest, null, "\t")}\n`, "utf8");
108
+ console.log(`wrote ${path}`);
109
+ }
110
+
111
+ const flags = parseArgs(process.argv.slice(2));
112
+ const astGrepVersion = flags.astGrepVersion ?? (await resolveInstalledAstGrepVersion());
113
+ const nodeVersion = flags.nodeVersion ?? (await resolveLatestNodeLtsVersion());
114
+ await writeManifest("ast-grep.json", await generateAstGrepManifest(astGrepVersion));
115
+ await writeManifest("node.json", await generateNodeManifest(nodeVersion));