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.
- package/.agents/skills/opencode-qa/SKILL.md +1 -0
- package/.agents/skills/opencode-qa/scripts/lib/common.sh +39 -1
- package/.agents/skills/opencode-qa/scripts/lib/fake-openai-branches.mjs +39 -0
- package/.agents/skills/opencode-qa/scripts/lib/fake-openai-events.mjs +106 -0
- package/.agents/skills/opencode-qa/scripts/lib/fake-openai-server.mjs +117 -0
- package/.agents/skills/opencode-qa/scripts/serve-wake-split-probe.sh +716 -0
- package/.agents/skills/tech-debt-audit/SKILL.md +277 -0
- package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/execution-plan.md +1 -1
- package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/execution-plan.md +1 -1
- package/bin/platform.js +5 -0
- package/bin/platform.test.ts +56 -0
- package/dist/agents/atlas/agent.d.ts +4 -3
- package/dist/agents/gpt-apply-patch-guard.d.ts +2 -2
- package/dist/agents/hephaestus/agent.d.ts +5 -0
- package/dist/agents/hephaestus/index.d.ts +1 -1
- package/dist/agents/metis.d.ts +1 -0
- package/dist/agents/prometheus/system-prompt.d.ts +1 -1
- package/dist/agents/sisyphus/kimi-k2-7.d.ts +17 -0
- package/dist/agents/sisyphus-junior/agent.d.ts +1 -1
- package/dist/agents/sisyphus-junior/kimi-k2-7.d.ts +11 -0
- package/dist/agents/types.d.ts +2 -2
- package/dist/cli/doctor/checks/codex-components.d.ts +13 -0
- package/dist/cli/doctor/checks/tui-plugin-config.d.ts +1 -0
- package/dist/cli/doctor/constants.d.ts +1 -1
- package/dist/cli/index.js +32329 -31437
- package/dist/cli/install-codex/codex-cleanup.d.ts +4 -0
- package/dist/cli/install-codex/install-codex-test-fixtures.d.ts +34 -0
- package/dist/cli/install-codex/link-cached-plugin-agents.d.ts +4 -0
- package/dist/cli/model-fallback.d.ts +1 -0
- package/dist/cli/provider-availability.d.ts +2 -0
- package/dist/cli-node/index.js +32329 -31437
- package/dist/config/schema/agent-overrides.d.ts +80 -16
- package/dist/config/schema/experimental.d.ts +1 -1
- package/dist/config/schema/hooks.d.ts +0 -1
- package/dist/config/schema/internal/permission.d.ts +5 -1
- package/dist/config/schema/oh-my-opencode-config.d.ts +76 -16
- package/dist/create-hooks.d.ts +0 -1
- package/dist/features/background-agent/index.d.ts +1 -1
- package/dist/features/background-agent/manager.d.ts +6 -0
- package/dist/features/background-agent/types.d.ts +2 -0
- package/dist/features/claude-code-plugin-loader/types.d.ts +3 -0
- package/dist/features/claude-code-session-state/state.d.ts +1 -0
- package/dist/features/skill-mcp-manager/manager.d.ts +11 -7
- package/dist/features/team-mode/team-mailbox/pending-delivery-recovery.d.ts +31 -0
- package/dist/features/team-mode/team-runtime/delete-team.d.ts +2 -1
- package/dist/features/team-mode/tools/lifecycle-inline-spec.d.ts +2 -2
- package/dist/features/tmux-subagent/stale-tmux-resource-sweeper.d.ts +12 -0
- package/dist/features/tool-metadata-store/store.d.ts +5 -0
- package/dist/hooks/anthropic-context-window-limit-recovery/storage/constants.d.ts +3 -0
- package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/messages-reader.d.ts +1 -1
- package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/part-content.d.ts +1 -1
- package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/parts-reader.d.ts +1 -1
- package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery/storage}/types.d.ts +0 -13
- package/dist/hooks/auto-update-checker/checker/bundled-version.d.ts +1 -0
- package/dist/hooks/auto-update-checker/checker.d.ts +1 -0
- package/dist/hooks/auto-update-checker/constants.d.ts +3 -3
- package/dist/hooks/auto-update-checker/hook.d.ts +2 -1
- package/dist/hooks/claude-code-hooks/types.d.ts +4 -0
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/team-session-events/team-idle-wake-hint.d.ts +5 -0
- package/dist/index.js +6061 -3714
- package/dist/oh-my-opencode.schema.json +123 -18
- package/dist/plugin/build-team-idle-wake-hint-client.d.ts +2 -0
- package/dist/plugin/event-session-lifecycle.d.ts +0 -3
- package/dist/plugin/hooks/create-continuation-hooks.d.ts +0 -6
- package/dist/plugin/hooks/create-core-hooks.d.ts +0 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +1 -2
- package/dist/shared/command-executor/execute-hook-command.d.ts +7 -0
- package/dist/shared/internal-initiator-marker.d.ts +7 -0
- package/dist/shared/live-server-route.d.ts +24 -0
- package/dist/shared/plugin-identity.d.ts +2 -2
- package/dist/shared/prompt-async-gate/prompt-message-state.d.ts +1 -0
- package/dist/shared/tmux/tmux-utils/server-health.d.ts +2 -1
- package/dist/shared/tmux/tmux-utils/stale-attach-pane-sweep.d.ts +16 -0
- package/dist/shared/tmux/tmux-utils.d.ts +1 -0
- package/dist/testing/create-plugin-module.d.ts +4 -0
- package/dist/tools/background-task/clients.d.ts +2 -0
- package/dist/tools/background-task/full-session-format.d.ts +1 -0
- package/dist/tools/background-task/types.d.ts +1 -0
- package/dist/tools/delegate-task/sync-prompt-sender.d.ts +1 -1
- package/dist/tools/delegate-task/sync-session-lifecycle.d.ts +2 -1
- package/dist/tools/look-at/look-at-input-preparer.d.ts +6 -2
- package/dist/tools/look-at/look-at-prompt.d.ts +2 -1
- package/dist/tools/look-at/look-at-session-runner.d.ts +3 -4
- package/dist/tools/look-at/types.d.ts +2 -0
- package/dist/tools/session-manager/types.d.ts +1 -0
- package/dist/tools/skill-mcp/types.d.ts +1 -0
- package/package.json +14 -13
- package/packages/ast-grep-mcp/dist/cli.js +50 -17
- package/packages/lsp-daemon/dist/cli.js +8 -5
- package/packages/lsp-daemon/dist/index.js +8 -5
- package/packages/lsp-tools-mcp/dist/lsp/connection.js +1 -1
- package/packages/lsp-tools-mcp/dist/lsp/server-definitions.js +2 -2
- package/packages/lsp-tools-mcp/dist/lsp/transport.d.ts +10 -1
- package/packages/lsp-tools-mcp/dist/lsp/transport.js +6 -3
- package/packages/omo-codex/lazycodex-repository/.github/workflows/pr-source-guidance.yml +11 -12
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +2583 -0
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +17 -0
- package/packages/omo-codex/plugin/components/bootstrap/manifests/ast-grep.json +22 -0
- package/packages/omo-codex/plugin/components/bootstrap/manifests/node.json +10 -0
- package/packages/omo-codex/plugin/components/bootstrap/package.json +20 -0
- package/packages/omo-codex/plugin/components/bootstrap/scripts/bootstrap.ps1 +310 -0
- package/packages/omo-codex/plugin/components/bootstrap/scripts/build.mjs +35 -0
- package/packages/omo-codex/plugin/components/bootstrap/scripts/generate-manifests.mjs +115 -0
- package/packages/omo-codex/plugin/components/bootstrap/src/cli.ts +153 -0
- package/packages/omo-codex/plugin/components/bootstrap/src/download.ts +212 -0
- package/packages/omo-codex/plugin/components/bootstrap/src/environment.ts +286 -0
- package/packages/omo-codex/plugin/components/bootstrap/src/hook.ts +108 -0
- package/packages/omo-codex/plugin/components/bootstrap/src/provision.ts +243 -0
- package/packages/omo-codex/plugin/components/bootstrap/src/setup.ts +294 -0
- package/packages/omo-codex/plugin/components/bootstrap/src/worker.ts +279 -0
- package/packages/omo-codex/plugin/components/bootstrap/test/download.test.ts +295 -0
- package/packages/omo-codex/plugin/components/bootstrap/test/environment.test.ts +375 -0
- package/packages/omo-codex/plugin/components/bootstrap/test/provision.test.ts +464 -0
- package/packages/omo-codex/plugin/components/bootstrap/tsconfig.json +25 -0
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +4 -4
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/dist/codex-hook-cli.js +6 -10
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +4 -4
- package/packages/omo-codex/plugin/components/lsp/scripts/build-lsp-tools.test.mjs +8 -3
- package/packages/omo-codex/plugin/components/lsp/src/codex-hook-cli.ts +5 -8
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook-cli.test.ts +24 -1
- package/packages/omo-codex/plugin/components/rules/bundled-rules/windows-git-bash.md +3 -1
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +4 -4
- package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +35 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +4 -4
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +4 -4
- package/packages/omo-codex/plugin/components/ultrawork/biome.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +155 -99
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +4 -4
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +19 -51
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +46 -51
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +19 -0
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +0 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +9 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +18 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +1 -3
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +6 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +19 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-commands.test.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-complete-goals.test.ts +26 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-json-errors.test.ts +89 -0
- package/packages/omo-codex/plugin/hooks/hooks.json +27 -16
- package/packages/omo-codex/plugin/package-lock.json +193 -193
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/auto-update-state.d.mts +20 -0
- package/packages/omo-codex/plugin/scripts/auto-update.mjs +28 -8
- package/packages/omo-codex/plugin/scripts/build-components.mjs +36 -5
- package/packages/omo-codex/plugin/scripts/install-flow.mjs +43 -0
- package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/SKILL.md +79 -28
- package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/agents/openai.yaml +2 -2
- package/packages/omo-codex/plugin/skills/lcx-report-bug/SKILL.md +7 -6
- package/packages/omo-codex/plugin/skills/lcx-report-bug/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +19 -51
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +46 -51
- package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -0
- package/packages/omo-codex/plugin/test/auto-update.test.mjs +145 -0
- package/packages/omo-codex/plugin/test/bootstrap-binlinks.test.mjs +250 -0
- package/packages/omo-codex/plugin/test/bootstrap-hooks.test.mjs +166 -0
- package/packages/omo-codex/plugin/test/bootstrap-orchestration.test.mjs +371 -0
- package/packages/omo-codex/plugin/test/bootstrap-ps-guard.test.mjs +134 -0
- package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +249 -0
- package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +10 -1
- package/packages/omo-codex/plugin/test/ulw-plan-skill.test.mjs +46 -0
- package/packages/omo-codex/scripts/atomic-write.test.mjs +82 -0
- package/packages/omo-codex/scripts/install/agents.d.mts +18 -0
- package/packages/omo-codex/scripts/install/agents.mjs +78 -5
- package/packages/omo-codex/scripts/install/atomic-write.mjs +59 -0
- package/packages/omo-codex/scripts/install/bin-dir.d.mts +7 -0
- package/packages/omo-codex/scripts/install/bin-links.d.mts +18 -0
- package/packages/omo-codex/scripts/install/config.d.mts +35 -0
- package/packages/omo-codex/scripts/install/config.mjs +13 -3
- package/packages/omo-codex/scripts/install/git-bash-mcp-env.d.mts +5 -0
- package/packages/omo-codex/scripts/install/git-bash.d.mts +23 -0
- package/packages/omo-codex/scripts/install/hook-trust.d.mts +10 -0
- package/packages/omo-codex/scripts/install-agent-links.test.mjs +41 -0
- package/packages/omo-codex/scripts/install-local.mjs +3 -2
- package/packages/shared-skills/skills/lcx-contribute-bug-fix/SKILL.md +79 -28
- package/packages/shared-skills/skills/lcx-contribute-bug-fix/agents/openai.yaml +2 -2
- package/packages/shared-skills/skills/lcx-report-bug/SKILL.md +7 -6
- package/packages/shared-skills/skills/lcx-report-bug/agents/openai.yaml +1 -1
- package/dist/hooks/session-recovery/constants.d.ts +0 -4
- package/dist/hooks/session-recovery/detect-error-type.d.ts +0 -4
- package/dist/hooks/session-recovery/error-recovery.d.ts +0 -4
- package/dist/hooks/session-recovery/hook-types.d.ts +0 -22
- package/dist/hooks/session-recovery/hook.d.ts +0 -4
- package/dist/hooks/session-recovery/index.d.ts +0 -5
- package/dist/hooks/session-recovery/interrupted-idle-message-fetch-timeout.d.ts +0 -7
- package/dist/hooks/session-recovery/interrupted-tool-results.d.ts +0 -3
- package/dist/hooks/session-recovery/message-state.d.ts +0 -4
- package/dist/hooks/session-recovery/recover-thinking-block-order.d.ts +0 -5
- package/dist/hooks/session-recovery/recover-thinking-disabled-violation.d.ts +0 -5
- package/dist/hooks/session-recovery/recover-tool-result-missing.d.ts +0 -10
- package/dist/hooks/session-recovery/recover-unavailable-tool.d.ts +0 -5
- package/dist/hooks/session-recovery/resume.d.ts +0 -7
- package/dist/hooks/session-recovery/storage/latest-assistant-message.d.ts +0 -5
- package/dist/hooks/session-recovery/storage/orphan-thinking-search.d.ts +0 -2
- package/dist/hooks/session-recovery/storage/thinking-block-search.d.ts +0 -2
- package/dist/hooks/session-recovery/storage/thinking-prepend.d.ts +0 -33
- package/dist/hooks/session-recovery/storage/thinking-strip.d.ts +0 -11
- package/dist/hooks/session-recovery/storage.d.ts +0 -20
- package/dist/plugin/event-session-recovery.d.ts +0 -9
- package/dist/plugin/user-abort-interrupted-recovery-guard.d.ts +0 -6
- /package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/empty-messages.d.ts +0 -0
- /package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/empty-text.d.ts +0 -0
- /package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/message-dir.d.ts +0 -0
- /package/dist/hooks/{session-recovery → anthropic-context-window-limit-recovery}/storage/part-id.d.ts +0 -0
- /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,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));
|