lazycodex-ai 5.1.62 → 5.1.63
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/cli/index.js +1598 -284
- package/dist/cli/service-auth/closed-device-login.fixture.d.ts +1 -0
- package/dist/cli/service-auth/credential-lock.d.ts +8 -2
- package/dist/cli/service-auth/keychain-helper/access.d.ts +27 -0
- package/dist/cli/service-auth/keychain-helper/approval-cache.d.ts +51 -0
- package/dist/cli/service-auth/keychain-helper/client.d.ts +68 -0
- package/dist/cli/service-auth/keychain-helper/creator-handoff.d.ts +31 -0
- package/dist/cli/service-auth/keychain-helper/darwin-backend.d.ts +75 -0
- package/dist/cli/service-auth/keychain-helper/darwin-read.d.ts +46 -0
- package/dist/cli/service-auth/keychain-helper/darwin-store.d.ts +28 -0
- package/dist/cli/service-auth/keychain-helper/fake-keychain.test-support.d.ts +85 -0
- package/dist/cli/service-auth/keychain-helper/location.d.ts +28 -0
- package/dist/cli/service-auth/keychain-helper/migration.d.ts +20 -0
- package/dist/cli/service-auth/keychain-helper/owner-marker.d.ts +7 -0
- package/dist/cli/service-auth/keychain-helper/pin.d.ts +20 -0
- package/dist/cli/service-auth/keychain-helper/process-copy.test-support.d.ts +3 -0
- package/dist/cli/service-auth/keychain-helper/process-state.d.ts +19 -0
- package/dist/cli/service-auth/keychain-helper/prompt-lock.d.ts +14 -0
- package/dist/cli/service-auth/keychain-helper/recovery.d.ts +34 -0
- package/dist/cli/service-auth/keychain-helper/runtime-capabilities.d.ts +13 -0
- package/dist/cli/service-auth/keychain-helper/secrets-gate.d.ts +4 -0
- package/dist/cli/service-auth/keychain-helper/signature.d.ts +17 -0
- package/dist/cli/service-auth/keychain-helper/store-binding.d.ts +46 -0
- package/dist/cli/service-auth/keystore.d.ts +18 -3
- package/dist/cli/service-auth/session.d.ts +2 -2
- package/dist/cli-node/index.js +1598 -284
- package/package.json +1 -1
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +2 -0
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/directive.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +10 -10
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +12 -12
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +6 -3
- package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +2 -2
- package/packages/omo-codex/plugin/skills/ast-grep/README.md +4 -4
- package/packages/omo-codex/plugin/skills/ast-grep/SKILL.md +10 -8
- package/packages/omo-codex/plugin/skills/ast-grep/references/cli.md +4 -3
- package/packages/omo-codex/plugin/skills/ast-grep/references/patterns.md +5 -5
- package/packages/omo-codex/plugin/skills/ast-grep/references/pitfalls.md +3 -3
- package/packages/omo-codex/plugin/skills/ast-grep/references/recipes.md +6 -4
- package/packages/omo-codex/plugin/skills/ast-grep/references/yaml-rules.md +3 -3
- package/packages/omo-codex/plugin/skills/ast-grep/scripts/ast_grep_helper.py +3 -3
- package/packages/omo-codex/plugin/skills/browser/SKILL.md +2 -3
- package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +2 -1
- package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +8 -6
- package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +9 -5
- package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +3 -3
- package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +19 -4
- package/packages/omo-codex/plugin/skills/debugging/SKILL.md +5 -5
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +2 -2
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/06-fix.md +2 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/09-cleanup.md +2 -2
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/partial-runtime-evidence.md +1 -1
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/bundled-js-binary.md +1 -1
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +1 -1
- package/packages/omo-codex/plugin/skills/debugging/references/tools/browser-qa.md +1 -2
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/frontend/references/design/design-system-architecture.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/perfection/README.md +0 -1
- package/packages/omo-codex/plugin/skills/frontend/references/perfection/react-perf-tooling.md +27 -8
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/lighthouse-audit.py +0 -1
- package/packages/omo-codex/plugin/skills/git-master/SKILL.md +12 -2
- package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/lsp-setup/SKILL.md +24 -15
- package/packages/omo-codex/plugin/skills/lsp-setup/references/bash/README.md +3 -3
- package/packages/omo-codex/plugin/skills/lsp-setup/references/c-cpp/README.md +2 -2
- package/packages/omo-codex/plugin/skills/lsp-setup/references/csharp/README.md +2 -2
- package/packages/omo-codex/plugin/skills/lsp-setup/references/dart/README.md +2 -2
- package/packages/omo-codex/plugin/skills/lsp-setup/references/elixir/README.md +2 -2
- package/packages/omo-codex/plugin/skills/lsp-setup/references/go/README.md +2 -2
- package/packages/omo-codex/plugin/skills/lsp-setup/references/haskell/README.md +2 -2
- package/packages/omo-codex/plugin/skills/lsp-setup/references/java/README.md +3 -3
- package/packages/omo-codex/plugin/skills/lsp-setup/references/julia/README.md +3 -3
- package/packages/omo-codex/plugin/skills/lsp-setup/references/kotlin/README.md +4 -4
- package/packages/omo-codex/plugin/skills/lsp-setup/references/lua/README.md +2 -2
- package/packages/omo-codex/plugin/skills/lsp-setup/references/php/README.md +3 -3
- package/packages/omo-codex/plugin/skills/lsp-setup/references/python/README.md +13 -12
- package/packages/omo-codex/plugin/skills/lsp-setup/references/ruby/README.md +2 -2
- package/packages/omo-codex/plugin/skills/lsp-setup/references/rust/README.md +2 -2
- package/packages/omo-codex/plugin/skills/lsp-setup/references/swift/README.md +4 -4
- package/packages/omo-codex/plugin/skills/lsp-setup/references/terraform/README.md +2 -2
- package/packages/omo-codex/plugin/skills/lsp-setup/references/typescript/README.md +3 -3
- package/packages/omo-codex/plugin/skills/lsp-setup/references/yaml/README.md +2 -2
- package/packages/omo-codex/plugin/skills/lsp-setup/references/zig/README.md +2 -2
- package/packages/omo-codex/plugin/skills/lsp-setup/scripts/detect-lsp.ts +1 -1
- package/packages/omo-codex/plugin/skills/lsp-setup/scripts/lsp-server-table.ts +3 -2
- package/packages/omo-codex/plugin/skills/programming/SKILL.md +5 -5
- package/packages/omo-codex/plugin/skills/programming/references/code-smells.md +2 -2
- package/packages/omo-codex/plugin/skills/programming/references/go/README.md +3 -3
- package/packages/omo-codex/plugin/skills/programming/references/python/README.md +8 -8
- package/packages/omo-codex/plugin/skills/programming/references/python/data-processing.md +9 -9
- package/packages/omo-codex/plugin/skills/programming/references/rust-ub/README.md +3 -3
- package/packages/omo-codex/plugin/skills/programming/references/typescript/README.md +5 -5
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/new-project.ts +1 -1
- package/packages/omo-codex/plugin/skills/refactor/SKILL.md +35 -35
- package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +6 -6
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +10 -7
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +4 -4
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/README.md +2 -2
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/career.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/web.md +4 -4
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +2 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +16 -17
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/fallback.md +10 -6
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/jina.md +12 -12
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/naver.md +3 -3
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/playwright.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/rss.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/tls-impersonate.md +12 -7
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +2 -0
- package/packages/omo-codex/plugin/skills/ulw-execute/SKILL.md +9 -6
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +10 -10
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/references/deliverable-phase.md +5 -5
- package/packages/omo-codex/plugin/skills/ulw-research/references/report-visualization.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/references/research-collection.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/references/unit-rules.md +2 -2
- package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +1 -1
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +5 -5
- package/packages/omo-codex/plugin/skills/visual-qa/references/browser-setup.md +4 -2
- package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +2 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +7 -3
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
- package/packages/prompts-core/prompts/ultrawork/codex.md +2 -0
- package/packages/shared-skills/skills/ast-grep/AGENTS.md +2 -2
- package/packages/shared-skills/skills/ast-grep/README.md +4 -4
- package/packages/shared-skills/skills/ast-grep/SKILL.md +10 -8
- package/packages/shared-skills/skills/ast-grep/references/cli.md +4 -3
- package/packages/shared-skills/skills/ast-grep/references/patterns.md +5 -5
- package/packages/shared-skills/skills/ast-grep/references/pitfalls.md +3 -3
- package/packages/shared-skills/skills/ast-grep/references/recipes.md +6 -4
- package/packages/shared-skills/skills/ast-grep/references/yaml-rules.md +3 -3
- package/packages/shared-skills/skills/ast-grep/scripts/ast_grep_helper.py +3 -3
- package/packages/shared-skills/skills/browser/SKILL.md +2 -3
- package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +2 -1
- package/packages/shared-skills/skills/data-scientist/SKILL.md +8 -6
- package/packages/shared-skills/skills/data-scientist/references/placement.md +9 -5
- package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +3 -3
- package/packages/shared-skills/skills/data-scientist/references/visualization.md +19 -4
- package/packages/shared-skills/skills/debugging/SKILL.md +5 -5
- package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +2 -2
- package/packages/shared-skills/skills/debugging/references/methodology/06-fix.md +2 -0
- package/packages/shared-skills/skills/debugging/references/methodology/09-cleanup.md +2 -2
- package/packages/shared-skills/skills/debugging/references/methodology/partial-runtime-evidence.md +1 -1
- package/packages/shared-skills/skills/debugging/references/runtimes/bundled-js-binary.md +1 -1
- package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +1 -1
- package/packages/shared-skills/skills/debugging/references/tools/browser-qa.md +1 -2
- package/packages/shared-skills/skills/frontend/SKILL.md +2 -2
- package/packages/shared-skills/skills/frontend/references/design/design-system-architecture.md +1 -1
- package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +1 -1
- package/packages/shared-skills/skills/frontend/references/perfection/README.md +0 -1
- package/packages/shared-skills/skills/frontend/references/perfection/react-perf-tooling.md +27 -8
- package/packages/shared-skills/skills/frontend/scripts/perfection/lighthouse-audit.py +0 -1
- package/packages/shared-skills/skills/git-master/SKILL.md +12 -2
- package/packages/shared-skills/skills/init-deep/SKILL.md +1 -1
- package/packages/shared-skills/skills/lsp-setup/SKILL.md +24 -15
- package/packages/shared-skills/skills/lsp-setup/references/bash/README.md +3 -3
- package/packages/shared-skills/skills/lsp-setup/references/c-cpp/README.md +2 -2
- package/packages/shared-skills/skills/lsp-setup/references/csharp/README.md +2 -2
- package/packages/shared-skills/skills/lsp-setup/references/dart/README.md +2 -2
- package/packages/shared-skills/skills/lsp-setup/references/elixir/README.md +2 -2
- package/packages/shared-skills/skills/lsp-setup/references/go/README.md +2 -2
- package/packages/shared-skills/skills/lsp-setup/references/haskell/README.md +2 -2
- package/packages/shared-skills/skills/lsp-setup/references/java/README.md +3 -3
- package/packages/shared-skills/skills/lsp-setup/references/julia/README.md +3 -3
- package/packages/shared-skills/skills/lsp-setup/references/kotlin/README.md +4 -4
- package/packages/shared-skills/skills/lsp-setup/references/lua/README.md +2 -2
- package/packages/shared-skills/skills/lsp-setup/references/php/README.md +3 -3
- package/packages/shared-skills/skills/lsp-setup/references/python/README.md +13 -12
- package/packages/shared-skills/skills/lsp-setup/references/ruby/README.md +2 -2
- package/packages/shared-skills/skills/lsp-setup/references/rust/README.md +2 -2
- package/packages/shared-skills/skills/lsp-setup/references/swift/README.md +4 -4
- package/packages/shared-skills/skills/lsp-setup/references/terraform/README.md +2 -2
- package/packages/shared-skills/skills/lsp-setup/references/typescript/README.md +3 -3
- package/packages/shared-skills/skills/lsp-setup/references/yaml/README.md +2 -2
- package/packages/shared-skills/skills/lsp-setup/references/zig/README.md +2 -2
- package/packages/shared-skills/skills/lsp-setup/scripts/detect-lsp.ts +1 -1
- package/packages/shared-skills/skills/lsp-setup/scripts/lsp-server-table.ts +3 -2
- package/packages/shared-skills/skills/programming/SKILL.md +5 -5
- package/packages/shared-skills/skills/programming/references/code-smells.md +2 -2
- package/packages/shared-skills/skills/programming/references/go/README.md +3 -3
- package/packages/shared-skills/skills/programming/references/python/README.md +8 -8
- package/packages/shared-skills/skills/programming/references/python/data-processing.md +9 -9
- package/packages/shared-skills/skills/programming/references/rust-ub/README.md +3 -3
- package/packages/shared-skills/skills/programming/references/typescript/README.md +5 -5
- package/packages/shared-skills/skills/programming/scripts/typescript/new-project.ts +1 -1
- package/packages/shared-skills/skills/refactor/SKILL.md +35 -35
- package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +6 -6
- package/packages/shared-skills/skills/review-work/SKILL.md +2 -2
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +10 -7
- package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +4 -4
- package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/README.md +2 -2
- package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/career.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/web.md +4 -4
- package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +2 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +16 -17
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/fallback.md +10 -6
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/jina.md +12 -12
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/naver.md +3 -3
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/playwright.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/rss.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/tls-impersonate.md +12 -7
- package/packages/shared-skills/skills/ulw-execute/SKILL.md +9 -6
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +2 -2
- package/packages/shared-skills/skills/ulw-research/SKILL.md +3 -3
- package/packages/shared-skills/skills/ulw-research/references/deliverable-phase.md +5 -5
- package/packages/shared-skills/skills/ulw-research/references/report-visualization.md +2 -2
- package/packages/shared-skills/skills/ulw-research/references/research-collection.md +2 -2
- package/packages/shared-skills/skills/ulw-research/references/unit-rules.md +2 -2
- package/packages/shared-skills/skills/visual-qa/AGENTS.md +1 -1
- package/packages/shared-skills/skills/visual-qa/SKILL.md +5 -5
- package/packages/shared-skills/skills/visual-qa/references/browser-setup.md +4 -2
package/dist/cli-node/index.js
CHANGED
|
@@ -2133,7 +2133,7 @@ var package_default;
|
|
|
2133
2133
|
var init_package = __esm(() => {
|
|
2134
2134
|
package_default = {
|
|
2135
2135
|
name: "oh-my-opencode",
|
|
2136
|
-
version: "5.1.
|
|
2136
|
+
version: "5.1.63",
|
|
2137
2137
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
2138
2138
|
main: "./dist/index.js",
|
|
2139
2139
|
types: "dist/index.d.ts",
|
|
@@ -2385,18 +2385,18 @@ var init_package = __esm(() => {
|
|
|
2385
2385
|
typescript: "^7.0.2"
|
|
2386
2386
|
},
|
|
2387
2387
|
optionalDependencies: {
|
|
2388
|
-
"oh-my-opencode-darwin-arm64": "5.1.
|
|
2389
|
-
"oh-my-opencode-darwin-x64": "5.1.
|
|
2390
|
-
"oh-my-opencode-darwin-x64-baseline": "5.1.
|
|
2391
|
-
"oh-my-opencode-linux-arm64": "5.1.
|
|
2392
|
-
"oh-my-opencode-linux-arm64-musl": "5.1.
|
|
2393
|
-
"oh-my-opencode-linux-x64": "5.1.
|
|
2394
|
-
"oh-my-opencode-linux-x64-baseline": "5.1.
|
|
2395
|
-
"oh-my-opencode-linux-x64-musl": "5.1.
|
|
2396
|
-
"oh-my-opencode-linux-x64-musl-baseline": "5.1.
|
|
2397
|
-
"oh-my-opencode-windows-arm64": "5.1.
|
|
2398
|
-
"oh-my-opencode-windows-x64": "5.1.
|
|
2399
|
-
"oh-my-opencode-windows-x64-baseline": "5.1.
|
|
2388
|
+
"oh-my-opencode-darwin-arm64": "5.1.63",
|
|
2389
|
+
"oh-my-opencode-darwin-x64": "5.1.63",
|
|
2390
|
+
"oh-my-opencode-darwin-x64-baseline": "5.1.63",
|
|
2391
|
+
"oh-my-opencode-linux-arm64": "5.1.63",
|
|
2392
|
+
"oh-my-opencode-linux-arm64-musl": "5.1.63",
|
|
2393
|
+
"oh-my-opencode-linux-x64": "5.1.63",
|
|
2394
|
+
"oh-my-opencode-linux-x64-baseline": "5.1.63",
|
|
2395
|
+
"oh-my-opencode-linux-x64-musl": "5.1.63",
|
|
2396
|
+
"oh-my-opencode-linux-x64-musl-baseline": "5.1.63",
|
|
2397
|
+
"oh-my-opencode-windows-arm64": "5.1.63",
|
|
2398
|
+
"oh-my-opencode-windows-x64": "5.1.63",
|
|
2399
|
+
"oh-my-opencode-windows-x64-baseline": "5.1.63"
|
|
2400
2400
|
},
|
|
2401
2401
|
overrides: {
|
|
2402
2402
|
hono: "^4.13.8",
|
|
@@ -7340,7 +7340,34 @@ var init_which = __esm(() => {
|
|
|
7340
7340
|
});
|
|
7341
7341
|
|
|
7342
7342
|
// packages/utils/src/runtime/file.ts
|
|
7343
|
-
|
|
7343
|
+
import { access, readFile, unlink, writeFile } from "node:fs/promises";
|
|
7344
|
+
function createNodeFile(path) {
|
|
7345
|
+
return {
|
|
7346
|
+
text() {
|
|
7347
|
+
return readFile(path, "utf8");
|
|
7348
|
+
},
|
|
7349
|
+
async arrayBuffer() {
|
|
7350
|
+
const buffer = await readFile(path);
|
|
7351
|
+
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
7352
|
+
},
|
|
7353
|
+
exists() {
|
|
7354
|
+
return access(path).then(() => true, () => false);
|
|
7355
|
+
},
|
|
7356
|
+
delete() {
|
|
7357
|
+
return unlink(path);
|
|
7358
|
+
}
|
|
7359
|
+
};
|
|
7360
|
+
}
|
|
7361
|
+
function bunFile(path) {
|
|
7362
|
+
const bun = runtime3.Bun;
|
|
7363
|
+
if (bun)
|
|
7364
|
+
return bun.file(path);
|
|
7365
|
+
return createNodeFile(path);
|
|
7366
|
+
}
|
|
7367
|
+
var runtime3;
|
|
7368
|
+
var init_file = __esm(() => {
|
|
7369
|
+
runtime3 = globalThis;
|
|
7370
|
+
});
|
|
7344
7371
|
|
|
7345
7372
|
// packages/utils/src/runtime/git-bash.ts
|
|
7346
7373
|
import { execFileSync } from "node:child_process";
|
|
@@ -12284,7 +12311,9 @@ var init_zip_extractor = __esm(() => {
|
|
|
12284
12311
|
});
|
|
12285
12312
|
|
|
12286
12313
|
// packages/omo-opencode/src/shared/bun-file-shim.ts
|
|
12287
|
-
var init_bun_file_shim = () => {
|
|
12314
|
+
var init_bun_file_shim = __esm(() => {
|
|
12315
|
+
init_runtime();
|
|
12316
|
+
});
|
|
12288
12317
|
|
|
12289
12318
|
// packages/omo-opencode/src/shared/binary-downloader.ts
|
|
12290
12319
|
import { chmodSync, existsSync as existsSync9, mkdirSync as mkdirSync4, unlinkSync as unlinkSync3 } from "node:fs";
|
|
@@ -92789,7 +92818,7 @@ var package_default2;
|
|
|
92789
92818
|
var init_package2 = __esm(() => {
|
|
92790
92819
|
package_default2 = {
|
|
92791
92820
|
name: "@oh-my-opencode/omo-codex",
|
|
92792
|
-
version: "5.1.
|
|
92821
|
+
version: "5.1.63",
|
|
92793
92822
|
type: "module",
|
|
92794
92823
|
private: true,
|
|
92795
92824
|
description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
|
|
@@ -93405,7 +93434,7 @@ var init_check_for_update = __esm(() => {
|
|
|
93405
93434
|
});
|
|
93406
93435
|
|
|
93407
93436
|
// packages/omo-opencode/src/hooks/auto-update-checker/checker/sync-package-json.ts
|
|
93408
|
-
import * as
|
|
93437
|
+
import * as crypto2 from "node:crypto";
|
|
93409
93438
|
import * as fs8 from "node:fs";
|
|
93410
93439
|
import * as path11 from "node:path";
|
|
93411
93440
|
function safeUnlink(filePath) {
|
|
@@ -93429,7 +93458,7 @@ function getPackageNameFromIntent(pluginInfo) {
|
|
|
93429
93458
|
return ACCEPTED_PACKAGE_NAMES2.find((packageName) => pluginInfo.entry === packageName || pluginInfo.entry.startsWith(`${packageName}@`)) ?? PACKAGE_NAME3;
|
|
93430
93459
|
}
|
|
93431
93460
|
function writeCachePackageJson(cachePackageJsonPath, pkgJson) {
|
|
93432
|
-
const tmpPath = `${cachePackageJsonPath}.${
|
|
93461
|
+
const tmpPath = `${cachePackageJsonPath}.${crypto2.randomUUID()}`;
|
|
93433
93462
|
try {
|
|
93434
93463
|
fs8.mkdirSync(path11.dirname(cachePackageJsonPath), { recursive: true });
|
|
93435
93464
|
fs8.writeFileSync(tmpPath, JSON.stringify(pkgJson, null, 2));
|
|
@@ -94350,7 +94379,7 @@ import { existsSync as existsSync27 } from "node:fs";
|
|
|
94350
94379
|
import { homedir as homedir7 } from "node:os";
|
|
94351
94380
|
|
|
94352
94381
|
// packages/omo-codex/src/install/codex-cache-bins.ts
|
|
94353
|
-
import { chmod, lstat as lstat4, mkdir, readFile as
|
|
94382
|
+
import { chmod, lstat as lstat4, mkdir, readFile as readFile4, readdir as readdir2, readlink as readlink3, rm as rm3, stat as stat2, symlink, writeFile as writeFile2 } from "node:fs/promises";
|
|
94354
94383
|
import { basename as basename4, isAbsolute as isAbsolute2, join as join26, relative, resolve as resolve6, sep } from "node:path";
|
|
94355
94384
|
|
|
94356
94385
|
// packages/omo-codex/src/install/codex-cache-command-shim.ts
|
|
@@ -94394,7 +94423,7 @@ function windowsCommandShim(targetPath) {
|
|
|
94394
94423
|
}
|
|
94395
94424
|
|
|
94396
94425
|
// packages/omo-codex/src/install/codex-cache-dangling-bins.ts
|
|
94397
|
-
import { lstat as lstat2, readFile, readdir, readlink, rm, stat } from "node:fs/promises";
|
|
94426
|
+
import { lstat as lstat2, readFile as readFile2, readdir, readlink, rm, stat } from "node:fs/promises";
|
|
94398
94427
|
import { dirname as dirname10, isAbsolute, join as join23, resolve as resolve5 } from "node:path";
|
|
94399
94428
|
|
|
94400
94429
|
// packages/omo-codex/src/install/codex-cache-fs.ts
|
|
@@ -94456,7 +94485,7 @@ async function removeDanglingGeneratedCommandShim(linkPath) {
|
|
|
94456
94485
|
const linkStat = await lstat2(linkPath);
|
|
94457
94486
|
if (!linkStat.isFile())
|
|
94458
94487
|
return;
|
|
94459
|
-
const content = await
|
|
94488
|
+
const content = await readFile2(linkPath, "utf8");
|
|
94460
94489
|
if (!content.includes(COMMAND_SHIM_MARKER))
|
|
94461
94490
|
return;
|
|
94462
94491
|
const target = extractCommandShimTarget(content);
|
|
@@ -94504,7 +94533,7 @@ function hasOmoCodexPluginPrefix(parts, endExclusive) {
|
|
|
94504
94533
|
}
|
|
94505
94534
|
|
|
94506
94535
|
// packages/omo-codex/src/install/codex-cache-legacy-bins.ts
|
|
94507
|
-
import { lstat as lstat3, readFile as
|
|
94536
|
+
import { lstat as lstat3, readFile as readFile3, readlink as readlink2, rm as rm2 } from "node:fs/promises";
|
|
94508
94537
|
import { join as join24 } from "node:path";
|
|
94509
94538
|
var LEGACY_CODEX_COMPONENT_BINS = [
|
|
94510
94539
|
{ name: "omo", component: "ulw-loop" },
|
|
@@ -94539,7 +94568,7 @@ async function removeLegacyCodexComponentBin(linkPath, component, platform) {
|
|
|
94539
94568
|
}
|
|
94540
94569
|
if (!stat.isFile())
|
|
94541
94570
|
return;
|
|
94542
|
-
const content = await
|
|
94571
|
+
const content = await readFile3(linkPath, "utf8");
|
|
94543
94572
|
if (content.includes(COMMAND_SHIM_MARKER))
|
|
94544
94573
|
await rm2(linkPath, { force: true });
|
|
94545
94574
|
} catch (error) {
|
|
@@ -94776,7 +94805,7 @@ async function collectPackageBins(directory, root, links) {
|
|
|
94776
94805
|
}
|
|
94777
94806
|
}
|
|
94778
94807
|
async function appendPackageBinLinks(packageJsonPath, packageRoot, root, links) {
|
|
94779
|
-
const packageJson = JSON.parse(await
|
|
94808
|
+
const packageJson = JSON.parse(await readFile4(packageJsonPath, "utf8"));
|
|
94780
94809
|
if (!isPlainRecord4(packageJson))
|
|
94781
94810
|
return;
|
|
94782
94811
|
const packageName = packageJson.name;
|
|
@@ -94828,13 +94857,13 @@ async function replaceSymlink(linkPath, targetPath) {
|
|
|
94828
94857
|
async function replaceCommandShim(linkPath, targetPath) {
|
|
94829
94858
|
if (await existingNonShim(linkPath))
|
|
94830
94859
|
throw new Error(`${linkPath} already exists and is not a command shim`);
|
|
94831
|
-
await
|
|
94860
|
+
await writeFile2(linkPath, windowsCommandShim(targetPath));
|
|
94832
94861
|
}
|
|
94833
94862
|
async function replaceRuntimeWrapper(linkPath, content) {
|
|
94834
94863
|
if (await existingNonRuntimeWrapper(linkPath))
|
|
94835
94864
|
throw new Error(`${linkPath} already exists and is not a generated OMO runtime wrapper`);
|
|
94836
94865
|
await rm3(linkPath, { force: true });
|
|
94837
|
-
await
|
|
94866
|
+
await writeFile2(linkPath, content);
|
|
94838
94867
|
}
|
|
94839
94868
|
async function removeGeneratedRuntimeWrapper(path) {
|
|
94840
94869
|
try {
|
|
@@ -94852,7 +94881,7 @@ async function removeGeneratedRuntimeWrapper(path) {
|
|
|
94852
94881
|
}
|
|
94853
94882
|
async function readGeneratedWrapperContent(path) {
|
|
94854
94883
|
try {
|
|
94855
|
-
return await
|
|
94884
|
+
return await readFile4(path, "utf8");
|
|
94856
94885
|
} catch (error) {
|
|
94857
94886
|
if (isNodeErrorWithCode(error) && (error.code === "ENOENT" || error.code === "EISDIR"))
|
|
94858
94887
|
return "";
|
|
@@ -94866,7 +94895,7 @@ async function existingNonRuntimeWrapper(path) {
|
|
|
94866
94895
|
return false;
|
|
94867
94896
|
if (!stat.isFile())
|
|
94868
94897
|
return true;
|
|
94869
|
-
const content = await
|
|
94898
|
+
const content = await readFile4(path, "utf8");
|
|
94870
94899
|
return !content.includes(RUNTIME_WRAPPER_MARKER);
|
|
94871
94900
|
} catch (error) {
|
|
94872
94901
|
if (isNodeErrorWithCode(error) && error.code === "ENOENT")
|
|
@@ -94879,7 +94908,7 @@ async function existingNonShim(path) {
|
|
|
94879
94908
|
const stat = await lstat4(path);
|
|
94880
94909
|
if (!stat.isFile())
|
|
94881
94910
|
return true;
|
|
94882
|
-
const content = await
|
|
94911
|
+
const content = await readFile4(path, "utf8");
|
|
94883
94912
|
if (content.includes(COMMAND_SHIM_MARKER))
|
|
94884
94913
|
return false;
|
|
94885
94914
|
throw new Error(`${path} already exists and is not a generated command shim`);
|
|
@@ -94903,11 +94932,11 @@ async function existingNonSymlink(path) {
|
|
|
94903
94932
|
}
|
|
94904
94933
|
}
|
|
94905
94934
|
// packages/omo-codex/src/install/codex-cache-install.ts
|
|
94906
|
-
import { cp as cp3, mkdir as mkdir3, readFile as
|
|
94935
|
+
import { cp as cp3, mkdir as mkdir3, readFile as readFile9, readdir as readdir5, rename as rename2, rm as rm5 } from "node:fs/promises";
|
|
94907
94936
|
import { basename as basename5, dirname as dirname13, join as join33, sep as sep6 } from "node:path";
|
|
94908
94937
|
|
|
94909
94938
|
// packages/omo-codex/src/install/codex-cache-bundled-mcps.ts
|
|
94910
|
-
import { cp, mkdir as mkdir2, readFile as
|
|
94939
|
+
import { cp, mkdir as mkdir2, readFile as readFile5, stat as stat3 } from "node:fs/promises";
|
|
94911
94940
|
import { dirname as dirname11, join as join27, resolve as resolve7 } from "node:path";
|
|
94912
94941
|
var BUNDLED_MCP_RUNTIMES = [
|
|
94913
94942
|
{
|
|
@@ -94949,7 +94978,7 @@ async function copyBundledMcpRuntimeDist(pluginRoot, sourceRoot, runtime) {
|
|
|
94949
94978
|
async function readSourceMcpArgs(path) {
|
|
94950
94979
|
let parsed;
|
|
94951
94980
|
try {
|
|
94952
|
-
parsed = JSON.parse(await
|
|
94981
|
+
parsed = JSON.parse(await readFile5(path, "utf8"));
|
|
94953
94982
|
} catch (error) {
|
|
94954
94983
|
if (error instanceof Error)
|
|
94955
94984
|
return new Set;
|
|
@@ -94980,7 +95009,7 @@ async function isDirectory(path) {
|
|
|
94980
95009
|
|
|
94981
95010
|
// packages/omo-codex/src/install/codex-cache-local-dependencies.ts
|
|
94982
95011
|
import { realpathSync as realpathSync7 } from "node:fs";
|
|
94983
|
-
import { readFile as
|
|
95012
|
+
import { readFile as readFile6, readdir as readdir3, writeFile as writeFile3 } from "node:fs/promises";
|
|
94984
95013
|
import { dirname as dirname12, isAbsolute as isAbsolute4, join as join29, relative as relative3, resolve as resolve9, sep as sep2 } from "node:path";
|
|
94985
95014
|
|
|
94986
95015
|
// packages/omo-codex/src/install/codex-cache-paths.ts
|
|
@@ -95046,7 +95075,7 @@ async function rewriteCachedPackageLocalFileDependencies(pluginRoot, sourceRoot)
|
|
|
95046
95075
|
const packageLock = await readPackageLock(pluginRoot);
|
|
95047
95076
|
let rewroteAnyPackageJson = false;
|
|
95048
95077
|
for (const packageJsonPath of packageJsonPaths) {
|
|
95049
|
-
const raw = await
|
|
95078
|
+
const raw = await readFile6(packageJsonPath, "utf8");
|
|
95050
95079
|
const parsed = JSON.parse(raw);
|
|
95051
95080
|
if (!isPlainRecord4(parsed))
|
|
95052
95081
|
continue;
|
|
@@ -95081,20 +95110,20 @@ async function rewriteCachedPackageLocalFileDependencies(pluginRoot, sourceRoot)
|
|
|
95081
95110
|
}
|
|
95082
95111
|
}
|
|
95083
95112
|
if (changed) {
|
|
95084
|
-
await
|
|
95113
|
+
await writeFile3(packageJsonPath, `${JSON.stringify(parsed, null, "\t")}
|
|
95085
95114
|
`);
|
|
95086
95115
|
rewroteAnyPackageJson = true;
|
|
95087
95116
|
}
|
|
95088
95117
|
}
|
|
95089
95118
|
if (packageLock.changed)
|
|
95090
|
-
await
|
|
95119
|
+
await writeFile3(packageLock.path, `${JSON.stringify(packageLock.value, null, "\t")}
|
|
95091
95120
|
`);
|
|
95092
95121
|
return rewroteAnyPackageJson;
|
|
95093
95122
|
}
|
|
95094
95123
|
async function readPackageLock(pluginRoot) {
|
|
95095
95124
|
const path = join29(pluginRoot, "package-lock.json");
|
|
95096
95125
|
try {
|
|
95097
|
-
const parsed = JSON.parse(await
|
|
95126
|
+
const parsed = JSON.parse(await readFile6(path, "utf8"));
|
|
95098
95127
|
return { path, value: isPlainRecord4(parsed) ? parsed : null, changed: false };
|
|
95099
95128
|
} catch (error) {
|
|
95100
95129
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -95168,14 +95197,14 @@ async function collectPackageJsonPaths(directory, root, paths) {
|
|
|
95168
95197
|
}
|
|
95169
95198
|
|
|
95170
95199
|
// packages/omo-codex/src/install/codex-cache-mcp-manifest.ts
|
|
95171
|
-
import { readFile as
|
|
95200
|
+
import { readFile as readFile7, writeFile as writeFile4 } from "node:fs/promises";
|
|
95172
95201
|
import { join as join30, sep as sep3 } from "node:path";
|
|
95173
95202
|
var CONTEXT7_API_KEY_ENV = "CONTEXT7_API_KEY";
|
|
95174
95203
|
async function rewriteCachedMcpManifest(pluginRoot, sourceRoot = pluginRoot) {
|
|
95175
95204
|
const manifestPath = join30(pluginRoot, ".mcp.json");
|
|
95176
95205
|
if (!await fileExistsStrict(manifestPath))
|
|
95177
95206
|
return;
|
|
95178
|
-
const raw = await
|
|
95207
|
+
const raw = await readFile7(manifestPath, "utf8");
|
|
95179
95208
|
const parsed = JSON.parse(raw);
|
|
95180
95209
|
if (!isPlainRecord4(parsed) || !isPlainRecord4(parsed.mcpServers))
|
|
95181
95210
|
return;
|
|
@@ -95209,7 +95238,7 @@ async function rewriteCachedMcpManifest(pluginRoot, sourceRoot = pluginRoot) {
|
|
|
95209
95238
|
}
|
|
95210
95239
|
}
|
|
95211
95240
|
if (changed)
|
|
95212
|
-
await
|
|
95241
|
+
await writeFile4(manifestPath, `${JSON.stringify(parsed, null, "\t")}
|
|
95213
95242
|
`);
|
|
95214
95243
|
}
|
|
95215
95244
|
function sanitizeContext7Auth(server) {
|
|
@@ -95268,7 +95297,7 @@ async function rewriteCachedManifestRoot(pluginRoot, fromRoot, toRoot) {
|
|
|
95268
95297
|
const manifestPath = join30(pluginRoot, ".mcp.json");
|
|
95269
95298
|
if (!await fileExistsStrict(manifestPath))
|
|
95270
95299
|
return;
|
|
95271
|
-
const raw = await
|
|
95300
|
+
const raw = await readFile7(manifestPath, "utf8");
|
|
95272
95301
|
const parsed = JSON.parse(raw);
|
|
95273
95302
|
if (!isPlainRecord4(parsed) || !isPlainRecord4(parsed.mcpServers))
|
|
95274
95303
|
return;
|
|
@@ -95295,7 +95324,7 @@ async function rewriteCachedManifestRoot(pluginRoot, fromRoot, toRoot) {
|
|
|
95295
95324
|
}
|
|
95296
95325
|
}
|
|
95297
95326
|
if (changed)
|
|
95298
|
-
await
|
|
95327
|
+
await writeFile4(manifestPath, `${JSON.stringify(parsed, null, "\t")}
|
|
95299
95328
|
`);
|
|
95300
95329
|
}
|
|
95301
95330
|
|
|
@@ -95357,7 +95386,7 @@ async function unsupportedEntries(root, directory) {
|
|
|
95357
95386
|
}
|
|
95358
95387
|
|
|
95359
95388
|
// packages/omo-codex/src/install/codex-hook-targets.ts
|
|
95360
|
-
import { readFile as
|
|
95389
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
95361
95390
|
import { join as join32, sep as sep5 } from "node:path";
|
|
95362
95391
|
var PLUGIN_ROOT_TARGET_PATTERN = /\$\{PLUGIN_ROOT\}[\\/]+([^"']+)/g;
|
|
95363
95392
|
async function findMissingHookCommandTargets(pluginRoot) {
|
|
@@ -95365,7 +95394,7 @@ async function findMissingHookCommandTargets(pluginRoot) {
|
|
|
95365
95394
|
for (const manifestPath of await hookManifestPaths(pluginRoot)) {
|
|
95366
95395
|
if (!await fileExistsStrict(manifestPath))
|
|
95367
95396
|
continue;
|
|
95368
|
-
const parsed = JSON.parse(await
|
|
95397
|
+
const parsed = JSON.parse(await readFile8(manifestPath, "utf8"));
|
|
95369
95398
|
collectCommands(parsed, commands);
|
|
95370
95399
|
}
|
|
95371
95400
|
const missing = [];
|
|
@@ -95389,7 +95418,7 @@ async function hookManifestPaths(pluginRoot) {
|
|
|
95389
95418
|
const pluginManifestPath = join32(pluginRoot, ".codex-plugin", "plugin.json");
|
|
95390
95419
|
if (!await fileExistsStrict(pluginManifestPath))
|
|
95391
95420
|
return [join32(pluginRoot, "hooks", "hooks.json")];
|
|
95392
|
-
const parsed = JSON.parse(await
|
|
95421
|
+
const parsed = JSON.parse(await readFile8(pluginManifestPath, "utf8"));
|
|
95393
95422
|
if (!isPlainRecord4(parsed))
|
|
95394
95423
|
return [];
|
|
95395
95424
|
if (typeof parsed.hooks === "string" && parsed.hooks.trim() !== "") {
|
|
@@ -95476,7 +95505,7 @@ async function maybeRunNpmInstall(cwd, runCommand, env, args = ["install"]) {
|
|
|
95476
95505
|
async function maybeRunNpmBuild(cwd, runCommand, env) {
|
|
95477
95506
|
if (!await fileExistsStrict(join33(cwd, "package.json")))
|
|
95478
95507
|
return;
|
|
95479
|
-
const packageJson = JSON.parse(await
|
|
95508
|
+
const packageJson = JSON.parse(await readFile9(join33(cwd, "package.json"), "utf8"));
|
|
95480
95509
|
if (!isPlainRecord4(packageJson))
|
|
95481
95510
|
return;
|
|
95482
95511
|
const scripts = packageJson.scripts;
|
|
@@ -95487,7 +95516,7 @@ async function maybeRunNpmBuild(cwd, runCommand, env) {
|
|
|
95487
95516
|
async function maybeRunNpmSyncSkills(cwd, runCommand, env) {
|
|
95488
95517
|
if (!await fileExistsStrict(join33(cwd, "package.json")))
|
|
95489
95518
|
return;
|
|
95490
|
-
const packageJson = JSON.parse(await
|
|
95519
|
+
const packageJson = JSON.parse(await readFile9(join33(cwd, "package.json"), "utf8"));
|
|
95491
95520
|
if (!isPlainRecord4(packageJson))
|
|
95492
95521
|
return;
|
|
95493
95522
|
const scripts = packageJson.scripts;
|
|
@@ -95550,7 +95579,7 @@ var removedSparkshellPromptSurfaceFiles = new Set(["directive.md", "plugin.json"
|
|
|
95550
95579
|
var removedSparkshellTextFilePattern = /\.(?:json|md|toml|ya?ml)$/i;
|
|
95551
95580
|
async function assertNoRemovedSparkshellPromptReferences(pluginRoot) {
|
|
95552
95581
|
for (const filePath of await listRemovedSparkshellPromptSurfaceFiles(pluginRoot, "")) {
|
|
95553
|
-
const content = await
|
|
95582
|
+
const content = await readFile9(join33(pluginRoot, filePath), "utf8");
|
|
95554
95583
|
if (!removedSparkshellReferencePattern.test(content))
|
|
95555
95584
|
continue;
|
|
95556
95585
|
throw new Error(`removed sparkshell reference found in Codex plugin prompt surface: ${filePath}`);
|
|
@@ -95699,7 +95728,7 @@ async function isBrokenCacheSymlink(path) {
|
|
|
95699
95728
|
}
|
|
95700
95729
|
}
|
|
95701
95730
|
// packages/omo-codex/src/install/codex-cached-marketplace-manifest.ts
|
|
95702
|
-
import { mkdir as mkdir4, rename as rename3, rm as rm7, stat as stat5, writeFile as
|
|
95731
|
+
import { mkdir as mkdir4, rename as rename3, rm as rm7, stat as stat5, writeFile as writeFile5 } from "node:fs/promises";
|
|
95703
95732
|
import { join as join35 } from "node:path";
|
|
95704
95733
|
async function writeCachedMarketplaceManifest(input) {
|
|
95705
95734
|
const marketplaceDir = join35(input.marketplaceRoot, ".agents", "plugins");
|
|
@@ -95712,7 +95741,7 @@ async function writeCachedMarketplaceManifest(input) {
|
|
|
95712
95741
|
const manifestPath = join35(marketplaceDir, "marketplace.json");
|
|
95713
95742
|
const tempPath = join35(marketplaceDir, `.marketplace.json.tmp-${process.pid}-${Date.now()}`);
|
|
95714
95743
|
try {
|
|
95715
|
-
await
|
|
95744
|
+
await writeFile5(tempPath, `${JSON.stringify({
|
|
95716
95745
|
name: input.marketplaceName,
|
|
95717
95746
|
plugins: input.plugins.map((plugin) => ({
|
|
95718
95747
|
name: plugin.name,
|
|
@@ -95738,7 +95767,7 @@ async function isDirectory2(path) {
|
|
|
95738
95767
|
|
|
95739
95768
|
// packages/omo-codex/src/install/codex-package-layout.ts
|
|
95740
95769
|
import { existsSync as existsSync24 } from "node:fs";
|
|
95741
|
-
import { readFile as
|
|
95770
|
+
import { readFile as readFile10 } from "node:fs/promises";
|
|
95742
95771
|
import { join as join36 } from "node:path";
|
|
95743
95772
|
var PACKAGED_CODEX_INSTALLER_NAMES = new Set([
|
|
95744
95773
|
"@code-yeongyu/lazycodex",
|
|
@@ -95754,14 +95783,14 @@ async function shouldBuildSourcePackages(repoRoot) {
|
|
|
95754
95783
|
const packageJsonPath = join36(repoRoot, "package.json");
|
|
95755
95784
|
if (!existsSync24(packageJsonPath))
|
|
95756
95785
|
return true;
|
|
95757
|
-
const packageJson = JSON.parse(await
|
|
95786
|
+
const packageJson = JSON.parse(await readFile10(packageJsonPath, "utf8"));
|
|
95758
95787
|
if (!isPlainRecord4(packageJson) || typeof packageJson.name !== "string")
|
|
95759
95788
|
return true;
|
|
95760
95789
|
return !PACKAGED_CODEX_INSTALLER_NAMES.has(packageJson.name);
|
|
95761
95790
|
}
|
|
95762
95791
|
|
|
95763
95792
|
// packages/omo-codex/src/install/codex-config-toml.ts
|
|
95764
|
-
import { mkdir as mkdir5, readFile as
|
|
95793
|
+
import { mkdir as mkdir5, readFile as readFile12 } from "node:fs/promises";
|
|
95765
95794
|
import { dirname as dirname16 } from "node:path";
|
|
95766
95795
|
|
|
95767
95796
|
// packages/omo-codex/src/install/toml-section-editor.ts
|
|
@@ -96358,18 +96387,18 @@ function tomlKeySegment(value) {
|
|
|
96358
96387
|
}
|
|
96359
96388
|
|
|
96360
96389
|
// packages/omo-codex/src/install/codex-config-atomic-write.ts
|
|
96361
|
-
import { lstat as lstat7, readlink as readlink4, realpath, rename as rename4, unlink, writeFile as
|
|
96390
|
+
import { lstat as lstat7, readlink as readlink4, realpath, rename as rename4, unlink as unlink2, writeFile as writeFile6 } from "node:fs/promises";
|
|
96362
96391
|
import { basename as basename6, dirname as dirname14, isAbsolute as isAbsolute5, join as join37, resolve as resolve10 } from "node:path";
|
|
96363
96392
|
var RENAME_RETRY_DELAYS_MS = [10, 25, 50];
|
|
96364
96393
|
var RETRIABLE_RENAME_CODES = new Set(["EPERM", "EBUSY"]);
|
|
96365
96394
|
async function writeFileAtomic(targetPath, data) {
|
|
96366
96395
|
const writeTarget = await resolveSymlinkTarget(targetPath);
|
|
96367
96396
|
const temporaryPath = join37(dirname14(writeTarget), `.tmp-${basename6(writeTarget)}-${process.pid}-${Date.now()}`);
|
|
96368
|
-
await
|
|
96397
|
+
await writeFile6(temporaryPath, data);
|
|
96369
96398
|
try {
|
|
96370
96399
|
await renameWithRetry(temporaryPath, writeTarget);
|
|
96371
96400
|
} catch (error) {
|
|
96372
|
-
await
|
|
96401
|
+
await unlink2(temporaryPath).catch((unlinkError) => {
|
|
96373
96402
|
if (unlinkError instanceof Error)
|
|
96374
96403
|
return;
|
|
96375
96404
|
return;
|
|
@@ -96864,7 +96893,7 @@ function isRootSetting(line, key) {
|
|
|
96864
96893
|
|
|
96865
96894
|
// packages/omo-codex/src/install/codex-model-catalog.ts
|
|
96866
96895
|
init_latest_models();
|
|
96867
|
-
import { readFile as
|
|
96896
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
96868
96897
|
import { join as join38 } from "node:path";
|
|
96869
96898
|
var FALLBACK_CODEX_MODEL_CATALOG = {
|
|
96870
96899
|
current: {
|
|
@@ -96898,7 +96927,7 @@ var FALLBACK_CODEX_MODEL_CATALOG = {
|
|
|
96898
96927
|
async function readCodexModelCatalog(codexPackageRoot) {
|
|
96899
96928
|
const catalogPath = join38(codexPackageRoot, "plugin", "model-catalog.json");
|
|
96900
96929
|
try {
|
|
96901
|
-
const parsed = JSON.parse(await
|
|
96930
|
+
const parsed = JSON.parse(await readFile11(catalogPath, "utf8"));
|
|
96902
96931
|
return parseCodexModelCatalog(parsed) ?? FALLBACK_CODEX_MODEL_CATALOG;
|
|
96903
96932
|
} catch (error) {
|
|
96904
96933
|
if (error instanceof Error)
|
|
@@ -97123,7 +97152,7 @@ async function updateCodexConfig(input) {
|
|
|
97123
97152
|
await mkdir5(dirname16(input.configPath), { recursive: true });
|
|
97124
97153
|
let config;
|
|
97125
97154
|
try {
|
|
97126
|
-
config = await
|
|
97155
|
+
config = await readFile12(input.configPath, "utf8");
|
|
97127
97156
|
} catch (error) {
|
|
97128
97157
|
if (!isMissingFileError(error))
|
|
97129
97158
|
throw error;
|
|
@@ -97171,7 +97200,7 @@ function isMissingFileError(error) {
|
|
|
97171
97200
|
|
|
97172
97201
|
// packages/omo-codex/src/install/codex-hook-trust.ts
|
|
97173
97202
|
import { createHash as createHash3 } from "node:crypto";
|
|
97174
|
-
import { readFile as
|
|
97203
|
+
import { readFile as readFile13 } from "node:fs/promises";
|
|
97175
97204
|
import { join as join40 } from "node:path";
|
|
97176
97205
|
var EVENT_LABELS = new Map([
|
|
97177
97206
|
["PreToolUse", "pre_tool_use"],
|
|
@@ -97189,7 +97218,7 @@ async function trustedHookStatesForPlugin(input) {
|
|
|
97189
97218
|
const manifestPath = join40(input.pluginRoot, ".codex-plugin", "plugin.json");
|
|
97190
97219
|
if (!await exists(manifestPath))
|
|
97191
97220
|
return [];
|
|
97192
|
-
const manifest = JSON.parse(await
|
|
97221
|
+
const manifest = JSON.parse(await readFile13(manifestPath, "utf8"));
|
|
97193
97222
|
if (!isPlainRecord4(manifest))
|
|
97194
97223
|
return [];
|
|
97195
97224
|
const states = [];
|
|
@@ -97197,7 +97226,7 @@ async function trustedHookStatesForPlugin(input) {
|
|
|
97197
97226
|
const hooksPath = join40(input.pluginRoot, hookPath);
|
|
97198
97227
|
if (!await exists(hooksPath))
|
|
97199
97228
|
continue;
|
|
97200
|
-
const parsed = JSON.parse(await
|
|
97229
|
+
const parsed = JSON.parse(await readFile13(hooksPath, "utf8"));
|
|
97201
97230
|
if (!isPlainRecord4(parsed) || !isPlainRecord4(parsed.hooks))
|
|
97202
97231
|
continue;
|
|
97203
97232
|
states.push(...trustedHookStatesForHooksFile({
|
|
@@ -97280,7 +97309,7 @@ function stripDotSlash2(value) {
|
|
|
97280
97309
|
}
|
|
97281
97310
|
async function exists(path) {
|
|
97282
97311
|
try {
|
|
97283
|
-
await
|
|
97312
|
+
await readFile13(path, "utf8");
|
|
97284
97313
|
return true;
|
|
97285
97314
|
} catch (error) {
|
|
97286
97315
|
if (error instanceof Error)
|
|
@@ -97380,7 +97409,7 @@ function recordAt2(value, key) {
|
|
|
97380
97409
|
}
|
|
97381
97410
|
|
|
97382
97411
|
// packages/omo-codex/src/install/codex-marketplace-snapshot.ts
|
|
97383
|
-
import { cp as cp4, mkdir as mkdir6, rename as rename5, rm as rm8, writeFile as
|
|
97412
|
+
import { cp as cp4, mkdir as mkdir6, rename as rename5, rm as rm8, writeFile as writeFile7 } from "node:fs/promises";
|
|
97384
97413
|
import { join as join41, sep as sep7 } from "node:path";
|
|
97385
97414
|
var INSTALLED_MARKETPLACES_DIR = ".tmp/marketplaces";
|
|
97386
97415
|
async function writeInstalledMarketplaceSnapshot(input) {
|
|
@@ -97400,7 +97429,7 @@ async function writeMarketplaceManifest(marketplaceRoot, marketplace) {
|
|
|
97400
97429
|
const manifestDir = join41(marketplaceRoot, ".agents", "plugins");
|
|
97401
97430
|
await mkdir6(manifestDir, { recursive: true });
|
|
97402
97431
|
const tempPath = join41(manifestDir, `.marketplace-${process.pid}-${Date.now()}.json.tmp`);
|
|
97403
|
-
await
|
|
97432
|
+
await writeFile7(tempPath, `${JSON.stringify(marketplace, null, "\t")}
|
|
97404
97433
|
`);
|
|
97405
97434
|
await rename5(tempPath, join41(manifestDir, "marketplace.json"));
|
|
97406
97435
|
}
|
|
@@ -97429,15 +97458,15 @@ function shouldCopyMarketplaceSourcePath(path, root) {
|
|
|
97429
97458
|
}
|
|
97430
97459
|
|
|
97431
97460
|
// packages/omo-codex/src/install/link-cached-plugin-agents.ts
|
|
97432
|
-
import { copyFile, lstat as lstat11, mkdir as mkdir7, readdir as readdir8, readFile as
|
|
97461
|
+
import { copyFile, lstat as lstat11, mkdir as mkdir7, readdir as readdir8, readFile as readFile18, rm as rm12, writeFile as writeFile10 } from "node:fs/promises";
|
|
97433
97462
|
import { basename as basename7, join as join46 } from "node:path";
|
|
97434
97463
|
|
|
97435
97464
|
// packages/omo-codex/src/install/agent-model-overrides.ts
|
|
97436
|
-
import { readFile as
|
|
97465
|
+
import { readFile as readFile15, rm as rm9, writeFile as writeFile9 } from "node:fs/promises";
|
|
97437
97466
|
import { join as join43 } from "node:path";
|
|
97438
97467
|
|
|
97439
97468
|
// packages/omo-codex/src/install/preserved-agent-settings.ts
|
|
97440
|
-
import { lstat as lstat8, readFile as
|
|
97469
|
+
import { lstat as lstat8, readFile as readFile14, readdir as readdir7, writeFile as writeFile8 } from "node:fs/promises";
|
|
97441
97470
|
import { join as join42 } from "node:path";
|
|
97442
97471
|
|
|
97443
97472
|
// packages/omo-codex/src/install/managed-agent-reasoning-defaults.ts
|
|
@@ -97672,7 +97701,7 @@ async function capturePreservedAgentServiceTier(input) {
|
|
|
97672
97701
|
async function restorePreservedReasoning(input) {
|
|
97673
97702
|
if (input.value === undefined)
|
|
97674
97703
|
return;
|
|
97675
|
-
const content = await
|
|
97704
|
+
const content = await readFile14(input.target, "utf8");
|
|
97676
97705
|
const bundledEffort = extractReasoningEffort(content);
|
|
97677
97706
|
const effort = resolveManagedAgentReasoning({
|
|
97678
97707
|
agentName: input.agentName,
|
|
@@ -97685,33 +97714,33 @@ async function restorePreservedReasoning(input) {
|
|
|
97685
97714
|
const replacement = replaceTopLevelStringSetting(content, "model_reasoning_effort", effort, { insertIfMissing: false });
|
|
97686
97715
|
if (!replacement.replaced)
|
|
97687
97716
|
return;
|
|
97688
|
-
await
|
|
97717
|
+
await writeFile8(input.linkPath, replacement.content);
|
|
97689
97718
|
}
|
|
97690
97719
|
async function restorePreservedServiceTier(input) {
|
|
97691
97720
|
if (!input.preserved)
|
|
97692
97721
|
return;
|
|
97693
|
-
const content = await
|
|
97722
|
+
const content = await readFile14(input.linkPath, "utf8");
|
|
97694
97723
|
if (extractServiceTier(content) === input.value)
|
|
97695
97724
|
return;
|
|
97696
97725
|
const replacement = replaceTopLevelStringSetting(content, "service_tier", input.value, { insertIfMissing: true });
|
|
97697
97726
|
if (!replacement.replaced)
|
|
97698
97727
|
return;
|
|
97699
|
-
await
|
|
97728
|
+
await writeFile8(input.linkPath, replacement.content);
|
|
97700
97729
|
}
|
|
97701
97730
|
async function restorePreservedModel(input) {
|
|
97702
97731
|
if (input.value === null)
|
|
97703
97732
|
return;
|
|
97704
|
-
const content = await
|
|
97733
|
+
const content = await readFile14(input.linkPath, "utf8");
|
|
97705
97734
|
if (extractModel(content) === input.value)
|
|
97706
97735
|
return;
|
|
97707
97736
|
const replacement = replaceTopLevelStringSetting(content, "model", input.value, { insertIfMissing: true });
|
|
97708
97737
|
if (!replacement.replaced)
|
|
97709
97738
|
return;
|
|
97710
|
-
await
|
|
97739
|
+
await writeFile8(input.linkPath, replacement.content);
|
|
97711
97740
|
}
|
|
97712
97741
|
async function readTextIfExists(path) {
|
|
97713
97742
|
try {
|
|
97714
|
-
return await
|
|
97743
|
+
return await readFile14(path, "utf8");
|
|
97715
97744
|
} catch (error) {
|
|
97716
97745
|
if (nodeErrorCode(error) === "ENOENT")
|
|
97717
97746
|
return null;
|
|
@@ -97833,13 +97862,13 @@ async function writeAgentModelReceipts(codexHome, receipts) {
|
|
|
97833
97862
|
await rm9(path, { force: true });
|
|
97834
97863
|
return;
|
|
97835
97864
|
}
|
|
97836
|
-
await
|
|
97865
|
+
await writeFile9(path, `${JSON.stringify(Object.fromEntries(receipts), null, "\t")}
|
|
97837
97866
|
`);
|
|
97838
97867
|
}
|
|
97839
97868
|
async function applyAgentOverride(input) {
|
|
97840
97869
|
if (input.override === undefined)
|
|
97841
97870
|
return;
|
|
97842
|
-
let content = await
|
|
97871
|
+
let content = await readFile15(input.linkPath, "utf8");
|
|
97843
97872
|
if (input.override.model !== undefined) {
|
|
97844
97873
|
content = replaceTopLevelStringSetting(content, "model", input.override.model, { insertIfMissing: true }).content;
|
|
97845
97874
|
}
|
|
@@ -97848,7 +97877,7 @@ async function applyAgentOverride(input) {
|
|
|
97848
97877
|
insertIfMissing: true
|
|
97849
97878
|
}).content;
|
|
97850
97879
|
}
|
|
97851
|
-
await
|
|
97880
|
+
await writeFile9(input.linkPath, content);
|
|
97852
97881
|
}
|
|
97853
97882
|
function receiptPath(codexHome) {
|
|
97854
97883
|
return join43(codexHome, "agents", RECEIPT_FILE);
|
|
@@ -97883,7 +97912,7 @@ function handEditedAgentModel(installedModel, receipt) {
|
|
|
97883
97912
|
}
|
|
97884
97913
|
|
|
97885
97914
|
// packages/omo-codex/src/install/retired-managed-agent-purge.ts
|
|
97886
|
-
import { lstat as lstat9, readFile as
|
|
97915
|
+
import { lstat as lstat9, readFile as readFile16, rm as rm10 } from "node:fs/promises";
|
|
97887
97916
|
import { join as join44 } from "node:path";
|
|
97888
97917
|
var RETIRED_MANAGED_AGENT_FILES = [
|
|
97889
97918
|
{
|
|
@@ -97917,7 +97946,7 @@ function hasRequiredMarkers(content, markers) {
|
|
|
97917
97946
|
}
|
|
97918
97947
|
async function readTextIfExists2(path) {
|
|
97919
97948
|
try {
|
|
97920
|
-
return await
|
|
97949
|
+
return await readFile16(path, "utf8");
|
|
97921
97950
|
} catch (error) {
|
|
97922
97951
|
if (nodeErrorCode2(error) === "ENOENT")
|
|
97923
97952
|
return null;
|
|
@@ -97942,7 +97971,7 @@ function nodeErrorCode2(error) {
|
|
|
97942
97971
|
|
|
97943
97972
|
// packages/omo-codex/src/install/default-agent-role.ts
|
|
97944
97973
|
import { createHash as createHash4 } from "node:crypto";
|
|
97945
|
-
import { lstat as lstat10, readFile as
|
|
97974
|
+
import { lstat as lstat10, readFile as readFile17, rm as rm11 } from "node:fs/promises";
|
|
97946
97975
|
import { join as join45 } from "node:path";
|
|
97947
97976
|
var REGISTRATION = { name: "default", configFile: "./agents/default.toml" };
|
|
97948
97977
|
async function installDefaultAgentRole(input) {
|
|
@@ -97979,7 +98008,7 @@ async function installDefaultAgentRole(input) {
|
|
|
97979
98008
|
if (foreign || existing !== null && !owned) {
|
|
97980
98009
|
throw new Error("Preserved user-owned agents.default / agents/default.toml. Move it aside to install the LazyCodex fallback, or set [codex].agents.default.disable = true in omo.jsonc. Explicit LazyCodex roles remain required.");
|
|
97981
98010
|
}
|
|
97982
|
-
const worker = await
|
|
98011
|
+
const worker = await readFile17(input.worker.path, "utf8");
|
|
97983
98012
|
const content = worker.replace(/^name\s*=\s*["']lazycodex-worker-medium["']\s*$/m, 'name = "default"');
|
|
97984
98013
|
if (content === worker)
|
|
97985
98014
|
throw new Error("Cannot derive default: medium worker has no matching internal name");
|
|
@@ -97989,7 +98018,7 @@ async function installDefaultAgentRole(input) {
|
|
|
97989
98018
|
}
|
|
97990
98019
|
async function readIfPresent(path) {
|
|
97991
98020
|
try {
|
|
97992
|
-
return await
|
|
98021
|
+
return await readFile17(path, "utf8");
|
|
97993
98022
|
} catch (error) {
|
|
97994
98023
|
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
97995
98024
|
return null;
|
|
@@ -98050,7 +98079,7 @@ async function syncAgentFile(input) {
|
|
|
98050
98079
|
value: input.preservedServiceTier?.get(input.agentName) ?? null
|
|
98051
98080
|
});
|
|
98052
98081
|
await applyAgentOverride({ linkPath: input.linkPath, override });
|
|
98053
|
-
const model = override?.model ?? extractModel(await
|
|
98082
|
+
const model = override?.model ?? extractModel(await readFile18(input.agentPath, "utf8"));
|
|
98054
98083
|
return {
|
|
98055
98084
|
...model === null ? {} : { model },
|
|
98056
98085
|
...override?.reasoningEffort === undefined ? {} : { reasoningEffort: override.reasoningEffort }
|
|
@@ -98094,7 +98123,7 @@ async function prepareReplacement(linkPath) {
|
|
|
98094
98123
|
async function writeManifest(pluginRoot, agentPaths) {
|
|
98095
98124
|
const manifestPath = join46(pluginRoot, MANIFEST_FILE);
|
|
98096
98125
|
const payload = { agents: [...agentPaths].sort() };
|
|
98097
|
-
await
|
|
98126
|
+
await writeFile10(manifestPath, `${JSON.stringify(payload, null, "\t")}
|
|
98098
98127
|
`);
|
|
98099
98128
|
}
|
|
98100
98129
|
function agentNameFromToml2(fileName) {
|
|
@@ -98163,12 +98192,12 @@ function agentNameFromToml3(fileName) {
|
|
|
98163
98192
|
}
|
|
98164
98193
|
|
|
98165
98194
|
// packages/omo-codex/src/install/codex-marketplace.ts
|
|
98166
|
-
import { readFile as
|
|
98195
|
+
import { readFile as readFile19 } from "node:fs/promises";
|
|
98167
98196
|
import { join as join47 } from "node:path";
|
|
98168
98197
|
var DEFAULT_MARKETPLACE_PATH = "packages/omo-codex/marketplace.json";
|
|
98169
98198
|
async function readMarketplace(repoRoot, options) {
|
|
98170
98199
|
const marketplacePath = options?.marketplacePath ?? join47(repoRoot, DEFAULT_MARKETPLACE_PATH);
|
|
98171
|
-
const raw = await
|
|
98200
|
+
const raw = await readFile19(marketplacePath, "utf8");
|
|
98172
98201
|
const parsed = JSON.parse(raw);
|
|
98173
98202
|
if (!isPlainRecord4(parsed))
|
|
98174
98203
|
throw new Error("marketplace.json must be an object");
|
|
@@ -98189,7 +98218,7 @@ function resolvePluginSource(repoRoot, plugin, options) {
|
|
|
98189
98218
|
return join47(repoRoot, ...relativePath.split(/[\\/]/));
|
|
98190
98219
|
}
|
|
98191
98220
|
async function readPluginManifest(pluginRoot) {
|
|
98192
|
-
const raw = await
|
|
98221
|
+
const raw = await readFile19(join47(pluginRoot, ".codex-plugin", "plugin.json"), "utf8");
|
|
98193
98222
|
const parsed = JSON.parse(raw);
|
|
98194
98223
|
if (!isPlainRecord4(parsed))
|
|
98195
98224
|
throw new Error(`${pluginRoot} plugin.json must be an object`);
|
|
@@ -98270,11 +98299,11 @@ function validateLocalSourcePath(path) {
|
|
|
98270
98299
|
}
|
|
98271
98300
|
|
|
98272
98301
|
// packages/omo-codex/src/install/lazycodex-version-stamp.ts
|
|
98273
|
-
import { readdir as readdir9, readFile as
|
|
98302
|
+
import { readdir as readdir9, readFile as readFile20, writeFile as writeFile11 } from "node:fs/promises";
|
|
98274
98303
|
import { join as join48 } from "node:path";
|
|
98275
98304
|
async function readDistributionManifest(repoRoot) {
|
|
98276
98305
|
try {
|
|
98277
|
-
const parsed = JSON.parse(await
|
|
98306
|
+
const parsed = JSON.parse(await readFile20(join48(repoRoot, "package.json"), "utf8"));
|
|
98278
98307
|
if (!isPlainRecord4(parsed) || typeof parsed.version !== "string" || parsed.version.trim().length === 0)
|
|
98279
98308
|
return;
|
|
98280
98309
|
return {
|
|
@@ -98310,7 +98339,7 @@ async function stampLazyCodexPluginVersion(input) {
|
|
|
98310
98339
|
async function writeLazyCodexInstallSnapshot(input) {
|
|
98311
98340
|
if (input.distributionManifest === undefined)
|
|
98312
98341
|
return;
|
|
98313
|
-
await
|
|
98342
|
+
await writeFile11(join48(input.pluginRoot, "lazycodex-install.json"), `${JSON.stringify({
|
|
98314
98343
|
packageName: input.distributionManifest.name,
|
|
98315
98344
|
version: input.distributionManifest.version
|
|
98316
98345
|
}, null, "\t")}
|
|
@@ -98318,11 +98347,11 @@ async function writeLazyCodexInstallSnapshot(input) {
|
|
|
98318
98347
|
}
|
|
98319
98348
|
async function stampJsonVersion(path, version) {
|
|
98320
98349
|
try {
|
|
98321
|
-
const parsed = JSON.parse(await
|
|
98350
|
+
const parsed = JSON.parse(await readFile20(path, "utf8"));
|
|
98322
98351
|
if (!isPlainRecord4(parsed))
|
|
98323
98352
|
return;
|
|
98324
98353
|
parsed.version = version;
|
|
98325
|
-
await
|
|
98354
|
+
await writeFile11(path, `${JSON.stringify(parsed, null, "\t")}
|
|
98326
98355
|
`);
|
|
98327
98356
|
} catch (error) {
|
|
98328
98357
|
if (error instanceof Error)
|
|
@@ -98332,7 +98361,7 @@ async function stampJsonVersion(path, version) {
|
|
|
98332
98361
|
}
|
|
98333
98362
|
async function readPluginHookPaths(manifestPath) {
|
|
98334
98363
|
try {
|
|
98335
|
-
const parsed = JSON.parse(await
|
|
98364
|
+
const parsed = JSON.parse(await readFile20(manifestPath, "utf8"));
|
|
98336
98365
|
if (!isPlainRecord4(parsed))
|
|
98337
98366
|
return [];
|
|
98338
98367
|
if (typeof parsed.hooks === "string" && parsed.hooks.trim().length > 0)
|
|
@@ -98352,11 +98381,11 @@ function stripDotSlash3(path) {
|
|
|
98352
98381
|
}
|
|
98353
98382
|
async function stampHookStatusMessages(path, version) {
|
|
98354
98383
|
try {
|
|
98355
|
-
const parsed = JSON.parse(await
|
|
98384
|
+
const parsed = JSON.parse(await readFile20(path, "utf8"));
|
|
98356
98385
|
if (!isPlainRecord4(parsed))
|
|
98357
98386
|
return;
|
|
98358
98387
|
stampHookGroups(parsed.hooks, version);
|
|
98359
|
-
await
|
|
98388
|
+
await writeFile11(path, `${JSON.stringify(parsed, null, "\t")}
|
|
98360
98389
|
`);
|
|
98361
98390
|
} catch (error) {
|
|
98362
98391
|
if (error instanceof Error)
|
|
@@ -98433,7 +98462,7 @@ var defaultRunCommand = async (command, args, options) => {
|
|
|
98433
98462
|
};
|
|
98434
98463
|
|
|
98435
98464
|
// packages/omo-codex/src/install/codex-project-local-cleanup.ts
|
|
98436
|
-
import { copyFile as copyFile2, lstat as lstat12, readFile as
|
|
98465
|
+
import { copyFile as copyFile2, lstat as lstat12, readFile as readFile21, writeFile as writeFile12 } from "node:fs/promises";
|
|
98437
98466
|
import { dirname as dirname17, join as join49, resolve as resolve11 } from "node:path";
|
|
98438
98467
|
var LEGACY_AGENT_CONFLICT_KEYS = ["max_threads"];
|
|
98439
98468
|
var PROJECT_LOCAL_ARTIFACT_PATHS = [
|
|
@@ -98453,7 +98482,7 @@ async function repairNearestProjectLocalCodexArtifacts(input) {
|
|
|
98453
98482
|
const artifacts = await collectProjectLocalArtifacts(project.artifactRoots);
|
|
98454
98483
|
const configs = [];
|
|
98455
98484
|
for (const configPath of project.configPaths) {
|
|
98456
|
-
const original = await
|
|
98485
|
+
const original = await readFile21(configPath, "utf8");
|
|
98457
98486
|
const repair = repairProjectLocalCodexConfigText(original);
|
|
98458
98487
|
if (!repair.changed) {
|
|
98459
98488
|
configs.push({
|
|
@@ -98466,7 +98495,7 @@ async function repairNearestProjectLocalCodexArtifacts(input) {
|
|
|
98466
98495
|
}
|
|
98467
98496
|
const backupPath = `${configPath}.backup-${formatBackupTimestamp(input.now?.() ?? new Date)}`;
|
|
98468
98497
|
await copyFile2(configPath, backupPath);
|
|
98469
|
-
await
|
|
98498
|
+
await writeFile12(configPath, `${repair.config.trimEnd()}
|
|
98470
98499
|
`);
|
|
98471
98500
|
configs.push({
|
|
98472
98501
|
projectRoot: project.projectRoot,
|
|
@@ -98663,13 +98692,13 @@ function formatUnknownError(error) {
|
|
|
98663
98692
|
|
|
98664
98693
|
// packages/omo-codex/src/install/lsp-daemon-reaper.ts
|
|
98665
98694
|
import { createHash as createHash5 } from "node:crypto";
|
|
98666
|
-
import { lstat as lstat13, readFile as
|
|
98695
|
+
import { lstat as lstat13, readFile as readFile23, readdir as readdir11, rm as rm13 } from "node:fs/promises";
|
|
98667
98696
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
98668
98697
|
import { join as join50, posix as posix6 } from "node:path";
|
|
98669
98698
|
|
|
98670
98699
|
// packages/omo-codex/src/install/lsp-daemon-reaper-attestation.ts
|
|
98671
98700
|
import { execFile } from "node:child_process";
|
|
98672
|
-
import { readFile as
|
|
98701
|
+
import { readFile as readFile22, readdir as readdir10, readlink as readlink5 } from "node:fs/promises";
|
|
98673
98702
|
import { connect } from "node:net";
|
|
98674
98703
|
import { basename as basename8 } from "node:path";
|
|
98675
98704
|
var PROBE_TIMEOUT_MS = 500;
|
|
@@ -98711,7 +98740,7 @@ async function attestLegacyDaemonOwnership(input, deps = {}) {
|
|
|
98711
98740
|
return false;
|
|
98712
98741
|
}
|
|
98713
98742
|
async function attestLinuxOwnership(input, deps) {
|
|
98714
|
-
const readFileImpl = deps.readFile ??
|
|
98743
|
+
const readFileImpl = deps.readFile ?? readFile22;
|
|
98715
98744
|
const readDirImpl = deps.readDir ?? readdir10;
|
|
98716
98745
|
const readLinkImpl = deps.readLink ?? readlink5;
|
|
98717
98746
|
const procNetUnix = await readText(readFileImpl, "/proc/net/unix");
|
|
@@ -98936,7 +98965,7 @@ async function readRegularTrimmedFile(path) {
|
|
|
98936
98965
|
return null;
|
|
98937
98966
|
if (!stats.isFile())
|
|
98938
98967
|
return "non_regular";
|
|
98939
|
-
const content = (await
|
|
98968
|
+
const content = (await readFile23(path, "utf8")).trim();
|
|
98940
98969
|
return content.length > 0 ? content : null;
|
|
98941
98970
|
}
|
|
98942
98971
|
function shortDigest(value) {
|
|
@@ -98997,11 +99026,11 @@ function resolveCodexInstallerBinDir(input) {
|
|
|
98997
99026
|
}
|
|
98998
99027
|
|
|
98999
99028
|
// packages/omo-codex/src/install/codex-installed-bin-dir.ts
|
|
99000
|
-
import { readFile as
|
|
99029
|
+
import { readFile as readFile24, readdir as readdir12, writeFile as writeFile13 } from "node:fs/promises";
|
|
99001
99030
|
import { join as join52 } from "node:path";
|
|
99002
99031
|
var INSTALLED_BIN_DIR_MANIFEST = ".installed-bin-dir.json";
|
|
99003
99032
|
async function writeInstalledCodexBinDir(input) {
|
|
99004
|
-
await
|
|
99033
|
+
await writeFile13(join52(input.pluginRoot, INSTALLED_BIN_DIR_MANIFEST), `${JSON.stringify({ binDir: input.binDir }, null, 2)}
|
|
99005
99034
|
`);
|
|
99006
99035
|
}
|
|
99007
99036
|
async function readInstalledCodexBinDir(codexHome) {
|
|
@@ -99027,7 +99056,7 @@ async function installedBinDirManifestPaths(codexHome) {
|
|
|
99027
99056
|
return paths;
|
|
99028
99057
|
}
|
|
99029
99058
|
async function readBinDirFromManifest(manifestPath) {
|
|
99030
|
-
const raw = await
|
|
99059
|
+
const raw = await readFile24(manifestPath, "utf8").catch(() => null);
|
|
99031
99060
|
if (raw === null)
|
|
99032
99061
|
return null;
|
|
99033
99062
|
let parsed;
|
|
@@ -99045,7 +99074,7 @@ async function readBinDirFromManifest(manifestPath) {
|
|
|
99045
99074
|
}
|
|
99046
99075
|
|
|
99047
99076
|
// packages/omo-codex/src/install/codex-git-bash-hooks.ts
|
|
99048
|
-
import { readFile as
|
|
99077
|
+
import { readFile as readFile25, writeFile as writeFile14 } from "node:fs/promises";
|
|
99049
99078
|
import { join as join53 } from "node:path";
|
|
99050
99079
|
var WINDOWS_ONLY_GIT_BASH_HOOKS = new Set([
|
|
99051
99080
|
"./hooks/pre-tool-use-recommending-git-bash-mcp.json",
|
|
@@ -99055,13 +99084,13 @@ async function removeGitBashHooksOffWindows(input) {
|
|
|
99055
99084
|
if (input.platform === "win32")
|
|
99056
99085
|
return;
|
|
99057
99086
|
const manifestPath = join53(input.pluginRoot, ".codex-plugin", "plugin.json");
|
|
99058
|
-
const parsed = JSON.parse(await
|
|
99087
|
+
const parsed = JSON.parse(await readFile25(manifestPath, "utf8"));
|
|
99059
99088
|
if (!isPlainRecord4(parsed) || !Array.isArray(parsed.hooks))
|
|
99060
99089
|
return;
|
|
99061
99090
|
const hooks = parsed.hooks.filter((hook) => typeof hook !== "string" || !WINDOWS_ONLY_GIT_BASH_HOOKS.has(hook));
|
|
99062
99091
|
if (hooks.length === parsed.hooks.length)
|
|
99063
99092
|
return;
|
|
99064
|
-
await
|
|
99093
|
+
await writeFile14(manifestPath, `${JSON.stringify({ ...parsed, hooks }, null, "\t")}
|
|
99065
99094
|
`);
|
|
99066
99095
|
}
|
|
99067
99096
|
|
|
@@ -99432,12 +99461,12 @@ function defaultRunCommand2(command, args) {
|
|
|
99432
99461
|
});
|
|
99433
99462
|
}
|
|
99434
99463
|
// packages/omo-codex/src/install/codex-cleanup.ts
|
|
99435
|
-
import { lstat as lstat16, readFile as
|
|
99464
|
+
import { lstat as lstat16, readFile as readFile28, readdir as readdir14, rm as rm15, rmdir } from "node:fs/promises";
|
|
99436
99465
|
import { homedir as homedir9 } from "node:os";
|
|
99437
99466
|
import { isAbsolute as isAbsolute11, join as join62, relative as relative7, resolve as resolve16 } from "node:path";
|
|
99438
99467
|
|
|
99439
99468
|
// packages/omo-codex/src/install/codex-cleanup-bins.ts
|
|
99440
|
-
import { lstat as lstat14, readFile as
|
|
99469
|
+
import { lstat as lstat14, readFile as readFile26, readdir as readdir13, readlink as readlink6, rm as rm14 } from "node:fs/promises";
|
|
99441
99470
|
import { dirname as dirname20, isAbsolute as isAbsolute9, join as join60, resolve as resolve14 } from "node:path";
|
|
99442
99471
|
var ROOT_RUNTIME_BIN_NAME = "omo";
|
|
99443
99472
|
var MANAGED_CODEX_BIN_NAMES = new Set([
|
|
@@ -99499,12 +99528,12 @@ async function isManagedCodexBin(linkPath, platform, binName) {
|
|
|
99499
99528
|
}
|
|
99500
99529
|
if (!entryStat.isFile())
|
|
99501
99530
|
return false;
|
|
99502
|
-
const content = await
|
|
99531
|
+
const content = await readFile26(linkPath, "utf8");
|
|
99503
99532
|
return content.includes(RUNTIME_WRAPPER_MARKER) || content.includes(COMMAND_SHIM_MARKER);
|
|
99504
99533
|
}
|
|
99505
99534
|
|
|
99506
99535
|
// packages/omo-codex/src/install/codex-cleanup-config.ts
|
|
99507
|
-
import { lstat as lstat15, mkdir as mkdir8, readFile as
|
|
99536
|
+
import { lstat as lstat15, mkdir as mkdir8, readFile as readFile27, writeFile as writeFile15 } from "node:fs/promises";
|
|
99508
99537
|
import { dirname as dirname21 } from "node:path";
|
|
99509
99538
|
var MANAGED_MARKETPLACES = ["sisyphuslabs", "lazycodex", "code-yeongyu-codex-plugins"];
|
|
99510
99539
|
var LEGACY_MANAGED_CODEX_AGENT_NAMES_TO_PURGE2 = ["codex-ultrawork-reviewer"];
|
|
@@ -99537,14 +99566,14 @@ function cleanupCodexLightConfigText(config) {
|
|
|
99537
99566
|
async function cleanupCodexConfig(configPath, now) {
|
|
99538
99567
|
if (!await configExists(configPath))
|
|
99539
99568
|
return { changed: false };
|
|
99540
|
-
const original = await
|
|
99569
|
+
const original = await readFile27(configPath, "utf8");
|
|
99541
99570
|
const next = cleanupCodexLightConfigText(original);
|
|
99542
99571
|
if (next === original)
|
|
99543
99572
|
return { changed: false };
|
|
99544
99573
|
const backupPath = `${configPath}.backup-${formatBackupTimestamp2(now?.() ?? new Date)}`;
|
|
99545
99574
|
await mkdir8(dirname21(configPath), { recursive: true });
|
|
99546
|
-
await
|
|
99547
|
-
await
|
|
99575
|
+
await writeFile15(backupPath, original);
|
|
99576
|
+
await writeFile15(configPath, `${next.trimEnd()}
|
|
99548
99577
|
`);
|
|
99549
99578
|
return { changed: true, backupPath };
|
|
99550
99579
|
}
|
|
@@ -99821,13 +99850,13 @@ async function collectInstalledAgentPaths(codexHome, configPath) {
|
|
|
99821
99850
|
async function readManagedAgentPathsFromConfig(codexHome, configPath) {
|
|
99822
99851
|
if (!await exists6(configPath))
|
|
99823
99852
|
return [];
|
|
99824
|
-
const config = await
|
|
99853
|
+
const config = await readFile28(configPath, "utf8");
|
|
99825
99854
|
return MANAGED_CODEX_AGENT_NAMES2.filter((agentName) => config.includes(`config_file = ${JSON.stringify(`./agents/${agentName}.toml`)}`)).map((agentName) => join62(codexHome, "agents", `${agentName}.toml`));
|
|
99826
99855
|
}
|
|
99827
99856
|
async function readInstalledAgentManifest(manifestPath) {
|
|
99828
99857
|
if (!await exists6(manifestPath))
|
|
99829
99858
|
return [];
|
|
99830
|
-
const parsed = JSON.parse(await
|
|
99859
|
+
const parsed = JSON.parse(await readFile28(manifestPath, "utf8"));
|
|
99831
99860
|
if (!isPlainRecord4(parsed) || !Array.isArray(parsed.agents))
|
|
99832
99861
|
return [];
|
|
99833
99862
|
return parsed.agents.filter((path) => typeof path === "string");
|
|
@@ -100019,7 +100048,7 @@ node "%~dp0omo" %*\r
|
|
|
100019
100048
|
// packages/omo-senpi/src/install/plugin-artifacts.ts
|
|
100020
100049
|
import { createHash as createHash7 } from "node:crypto";
|
|
100021
100050
|
import { constants as constants9 } from "node:fs";
|
|
100022
|
-
import { access as
|
|
100051
|
+
import { access as access3, readFile as readFile30, stat as stat6 } from "node:fs/promises";
|
|
100023
100052
|
import { dirname as dirname25, join as join66 } from "node:path";
|
|
100024
100053
|
|
|
100025
100054
|
// packages/memory-core/src/personas/manifest.ts
|
|
@@ -100038,7 +100067,7 @@ var PERSONA_ASSET_FILES = [
|
|
|
100038
100067
|
|
|
100039
100068
|
// packages/omo-senpi/src/install/senpi-settings.ts
|
|
100040
100069
|
import { constants as constants8 } from "node:fs";
|
|
100041
|
-
import { access, copyFile as copyFile3, mkdir as mkdir9, readFile as
|
|
100070
|
+
import { access as access2, copyFile as copyFile3, mkdir as mkdir9, readFile as readFile29, rename as rename6, writeFile as writeFile16 } from "node:fs/promises";
|
|
100042
100071
|
import { basename as basename10, dirname as dirname24, join as join65, resolve as resolve19 } from "node:path";
|
|
100043
100072
|
var OMO_SENPI_PACKAGE_NAME = "@code-yeongyu/omo-senpi";
|
|
100044
100073
|
var GENERATED_PLUGIN_BASENAME = /^omo-senpi-cli-plugin-[A-Za-z0-9]{6}$/;
|
|
@@ -100049,7 +100078,7 @@ var LEGACY_BUILTIN_SHADOW_PACKAGES = [
|
|
|
100049
100078
|
async function readSettings(settingsPath) {
|
|
100050
100079
|
let raw;
|
|
100051
100080
|
try {
|
|
100052
|
-
raw = await
|
|
100081
|
+
raw = await readFile29(settingsPath, "utf8");
|
|
100053
100082
|
} catch (error) {
|
|
100054
100083
|
if (isErrno(error, "ENOENT"))
|
|
100055
100084
|
return {};
|
|
@@ -100096,11 +100125,11 @@ async function writeSettingsAtomically(settingsPath, settings) {
|
|
|
100096
100125
|
if (await fileExists(settingsPath)) {
|
|
100097
100126
|
await copyFile3(settingsPath, backupPath);
|
|
100098
100127
|
} else {
|
|
100099
|
-
await
|
|
100128
|
+
await writeFile16(backupPath, `{}
|
|
100100
100129
|
`, "utf8");
|
|
100101
100130
|
}
|
|
100102
100131
|
const tempPath = `${settingsPath}.${process.pid}.${Date.now()}.tmp`;
|
|
100103
|
-
await
|
|
100132
|
+
await writeFile16(tempPath, `${JSON.stringify(settings, null, 2)}
|
|
100104
100133
|
`, "utf8");
|
|
100105
100134
|
await rename6(tempPath, settingsPath);
|
|
100106
100135
|
return backupPath;
|
|
@@ -100123,7 +100152,7 @@ function isRecord15(value) {
|
|
|
100123
100152
|
async function readPackageName(packagePath) {
|
|
100124
100153
|
let raw;
|
|
100125
100154
|
try {
|
|
100126
|
-
raw = await
|
|
100155
|
+
raw = await readFile29(join65(packagePath, "package.json"), "utf8");
|
|
100127
100156
|
} catch (error) {
|
|
100128
100157
|
if (isErrno(error, "ENOENT") || isErrno(error, "ENOTDIR"))
|
|
100129
100158
|
return;
|
|
@@ -100141,7 +100170,7 @@ async function readPackageName(packagePath) {
|
|
|
100141
100170
|
}
|
|
100142
100171
|
async function fileExists(path) {
|
|
100143
100172
|
try {
|
|
100144
|
-
await
|
|
100173
|
+
await access2(path, constants8.F_OK);
|
|
100145
100174
|
return true;
|
|
100146
100175
|
} catch (error) {
|
|
100147
100176
|
if (isErrno(error, "ENOENT"))
|
|
@@ -100204,6 +100233,7 @@ var REQUIRED_PLUGIN_ARTIFACTS = [
|
|
|
100204
100233
|
join66("skills", "visual-qa", "SKILL.md"),
|
|
100205
100234
|
join66("skills-conditional", "x-search", "SKILL.md"),
|
|
100206
100235
|
join66("runtime", "agent-toolkit-sdk", "sdk.js"),
|
|
100236
|
+
join66("runtime", "bunshin-ts", "sdk.js"),
|
|
100207
100237
|
join66("runtime", "thread-sdk", "sdk.js"),
|
|
100208
100238
|
join66("runtime", "ast-grep-mcp", "cli.js"),
|
|
100209
100239
|
join66("runtime", "lsp-daemon", "dist", "cli.js"),
|
|
@@ -100246,7 +100276,7 @@ async function verifyAstGrepRuntimeIntegrity(pluginPath, platform) {
|
|
|
100246
100276
|
runtimeStat = await stat6(runtimeEntry);
|
|
100247
100277
|
if (!runtimeStat.isFile())
|
|
100248
100278
|
throw new Error("runtime is not a file");
|
|
100249
|
-
await
|
|
100279
|
+
await access3(runtimeEntry, constants9.R_OK | constants9.X_OK);
|
|
100250
100280
|
} catch (error) {
|
|
100251
100281
|
throw astGrepIntegrityError(runtimeEntry, `runtime is unreadable or non-executable: ${messageOf(error)}`);
|
|
100252
100282
|
}
|
|
@@ -100255,7 +100285,7 @@ async function verifyAstGrepRuntimeIntegrity(pluginPath, platform) {
|
|
|
100255
100285
|
}
|
|
100256
100286
|
let manifest;
|
|
100257
100287
|
try {
|
|
100258
|
-
manifest = JSON.parse(await
|
|
100288
|
+
manifest = JSON.parse(await readFile30(manifestPath, "utf8"));
|
|
100259
100289
|
} catch (error) {
|
|
100260
100290
|
throw astGrepIntegrityError(runtimeEntry, `manifest is unreadable or invalid JSON: ${messageOf(error)}`);
|
|
100261
100291
|
}
|
|
@@ -100264,7 +100294,7 @@ async function verifyAstGrepRuntimeIntegrity(pluginPath, platform) {
|
|
|
100264
100294
|
}
|
|
100265
100295
|
let actualSha256;
|
|
100266
100296
|
try {
|
|
100267
|
-
actualSha256 = createHash7("sha256").update(await
|
|
100297
|
+
actualSha256 = createHash7("sha256").update(await readFile30(runtimeEntry)).digest("hex");
|
|
100268
100298
|
} catch (error) {
|
|
100269
100299
|
throw astGrepIntegrityError(runtimeEntry, `runtime hash could not be computed: ${messageOf(error)}`);
|
|
100270
100300
|
}
|
|
@@ -100289,7 +100319,7 @@ function messageOf(error) {
|
|
|
100289
100319
|
}
|
|
100290
100320
|
async function fileExists2(path) {
|
|
100291
100321
|
try {
|
|
100292
|
-
await
|
|
100322
|
+
await access3(path, constants9.F_OK);
|
|
100293
100323
|
return true;
|
|
100294
100324
|
} catch (error) {
|
|
100295
100325
|
if (isErrno2(error, "ENOENT"))
|
|
@@ -107982,7 +108012,7 @@ function getSuggestedInstallTag(currentVersion) {
|
|
|
107982
108012
|
// packages/omo-opencode/src/cli/doctor/checks/system.ts
|
|
107983
108013
|
init_jsonc_parser2();
|
|
107984
108014
|
init_plugin_identity();
|
|
107985
|
-
var
|
|
108015
|
+
var runtime5 = globalThis;
|
|
107986
108016
|
var defaultDeps5 = {
|
|
107987
108017
|
findOpenCodeBinary,
|
|
107988
108018
|
getOpenCodeVersion: getOpenCodeVersion3,
|
|
@@ -108043,7 +108073,7 @@ async function gatherSystemInfo(deps = defaultDeps5) {
|
|
|
108043
108073
|
opencodePath: binaryInfo?.path ?? null,
|
|
108044
108074
|
pluginVersion,
|
|
108045
108075
|
loadedVersion: loadedInfo.loadedVersion,
|
|
108046
|
-
bunVersion:
|
|
108076
|
+
bunVersion: runtime5.Bun?.version ?? "unavailable",
|
|
108047
108077
|
configPath: pluginInfo.configPath,
|
|
108048
108078
|
configValid: isConfigValid(pluginInfo.configPath, deps),
|
|
108049
108079
|
isLocalDev: pluginInfo.isLocalDev
|
|
@@ -109522,7 +109552,7 @@ async function pathExists2(dir) {
|
|
|
109522
109552
|
// packages/omo-opencode/src/cli/doctor/checks/codex.ts
|
|
109523
109553
|
init_src();
|
|
109524
109554
|
import { existsSync as existsSync61 } from "node:fs";
|
|
109525
|
-
import { lstat as lstat17, readdir as readdir15, readFile as
|
|
109555
|
+
import { lstat as lstat17, readdir as readdir15, readFile as readFile31 } from "node:fs/promises";
|
|
109526
109556
|
import { homedir as homedir26 } from "node:os";
|
|
109527
109557
|
import { basename as basename13, join as join99, resolve as resolve27 } from "node:path";
|
|
109528
109558
|
// packages/omo-opencode/package.json
|
|
@@ -109747,7 +109777,7 @@ async function readCodexConfigSummary(configPath) {
|
|
|
109747
109777
|
companionLifecycleHookStateEvents: []
|
|
109748
109778
|
};
|
|
109749
109779
|
}
|
|
109750
|
-
const content = await
|
|
109780
|
+
const content = await readFile31(configPath, "utf8");
|
|
109751
109781
|
return {
|
|
109752
109782
|
exists: true,
|
|
109753
109783
|
marketplaceConfigured: content.includes("[marketplaces.sisyphuslabs]"),
|
|
@@ -109775,7 +109805,7 @@ async function readLinkedAgents(codexHome) {
|
|
|
109775
109805
|
}
|
|
109776
109806
|
async function readJson(path) {
|
|
109777
109807
|
try {
|
|
109778
|
-
const parsed = JSON.parse(await
|
|
109808
|
+
const parsed = JSON.parse(await readFile31(path, "utf8"));
|
|
109779
109809
|
return isPlainRecord(parsed) ? parsed : null;
|
|
109780
109810
|
} catch (error) {
|
|
109781
109811
|
if (error instanceof Error)
|
|
@@ -109899,7 +109929,7 @@ function resolveLatestVersion(input) {
|
|
|
109899
109929
|
|
|
109900
109930
|
// packages/omo-opencode/src/cli/doctor/checks/codex-components.ts
|
|
109901
109931
|
init_src();
|
|
109902
|
-
import { readdir as readdir16, readFile as
|
|
109932
|
+
import { readdir as readdir16, readFile as readFile32, stat as stat7 } from "node:fs/promises";
|
|
109903
109933
|
import { homedir as homedir27 } from "node:os";
|
|
109904
109934
|
import { dirname as dirname40, isAbsolute as isAbsolute15, join as join100, relative as relative10, resolve as resolve28, sep as sep11 } from "node:path";
|
|
109905
109935
|
var CODEX_COMPONENTS_CHECK_ID = "codex-components";
|
|
@@ -110152,7 +110182,7 @@ function degradedDetailLines(entries) {
|
|
|
110152
110182
|
}
|
|
110153
110183
|
async function readJson2(path) {
|
|
110154
110184
|
try {
|
|
110155
|
-
const parsed = JSON.parse(await
|
|
110185
|
+
const parsed = JSON.parse(await readFile32(path, "utf8"));
|
|
110156
110186
|
return isRecord18(parsed) ? parsed : null;
|
|
110157
110187
|
} catch (error) {
|
|
110158
110188
|
if (error instanceof Error)
|
|
@@ -110180,7 +110210,7 @@ function isRecord18(value) {
|
|
|
110180
110210
|
|
|
110181
110211
|
// packages/omo-opencode/src/cli/doctor/checks/codex-runtime-wrapper.ts
|
|
110182
110212
|
import { existsSync as existsSync62 } from "node:fs";
|
|
110183
|
-
import { readFile as
|
|
110213
|
+
import { readFile as readFile33 } from "node:fs/promises";
|
|
110184
110214
|
import { homedir as homedir28 } from "node:os";
|
|
110185
110215
|
import { join as join101, resolve as resolve29 } from "node:path";
|
|
110186
110216
|
var RUNTIME_WRAPPER_MARKER2 = "OMO_GENERATED_RUNTIME_WRAPPER";
|
|
@@ -110225,7 +110255,7 @@ async function checkCodexRuntimeWrapper(deps = {}) {
|
|
|
110225
110255
|
}
|
|
110226
110256
|
async function readRuntimeWrapper(path) {
|
|
110227
110257
|
try {
|
|
110228
|
-
return await
|
|
110258
|
+
return await readFile33(path, "utf8");
|
|
110229
110259
|
} catch (error) {
|
|
110230
110260
|
if (error instanceof Error)
|
|
110231
110261
|
return null;
|
|
@@ -112149,6 +112179,73 @@ async function loadDeviceKeyring(store) {
|
|
|
112149
112179
|
import { execFile as execFile5 } from "node:child_process";
|
|
112150
112180
|
import { homedir as homedir30 } from "node:os";
|
|
112151
112181
|
import { join as join105 } from "node:path";
|
|
112182
|
+
|
|
112183
|
+
// packages/omo-opencode/src/shared/bun-ffi-shim.ts
|
|
112184
|
+
async function loadBunFfi() {
|
|
112185
|
+
return import("bun:ffi");
|
|
112186
|
+
}
|
|
112187
|
+
|
|
112188
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/process-state.ts
|
|
112189
|
+
var KEY = Symbol.for("omo.keychain-helper.process.v1");
|
|
112190
|
+
function keychainProcessState() {
|
|
112191
|
+
const holder = globalThis;
|
|
112192
|
+
holder[KEY] ??= {
|
|
112193
|
+
secretsQueue: Promise.resolve(),
|
|
112194
|
+
interactionSwitch: undefined,
|
|
112195
|
+
approvalCache: undefined,
|
|
112196
|
+
entryCandidates: [],
|
|
112197
|
+
helperAccess: undefined,
|
|
112198
|
+
heldPromptLocks: new Set,
|
|
112199
|
+
handOff: undefined
|
|
112200
|
+
};
|
|
112201
|
+
return holder[KEY];
|
|
112202
|
+
}
|
|
112203
|
+
|
|
112204
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/secrets-gate.ts
|
|
112205
|
+
async function loadInteractionSwitch() {
|
|
112206
|
+
const state = keychainProcessState();
|
|
112207
|
+
if (state.interactionSwitch !== undefined)
|
|
112208
|
+
return state.interactionSwitch;
|
|
112209
|
+
if (process.platform !== "darwin")
|
|
112210
|
+
return state.interactionSwitch = null;
|
|
112211
|
+
try {
|
|
112212
|
+
const { dlopen, FFIType } = await loadBunFfi();
|
|
112213
|
+
const security = dlopen("/System/Library/Frameworks/Security.framework/Security", {
|
|
112214
|
+
SecKeychainSetUserInteractionAllowed: { args: [FFIType.u8], returns: FFIType.i32 }
|
|
112215
|
+
});
|
|
112216
|
+
state.interactionSwitch = (allowed) => {
|
|
112217
|
+
security.symbols.SecKeychainSetUserInteractionAllowed(allowed ? 1 : 0);
|
|
112218
|
+
};
|
|
112219
|
+
} catch {
|
|
112220
|
+
state.interactionSwitch = null;
|
|
112221
|
+
}
|
|
112222
|
+
return state.interactionSwitch;
|
|
112223
|
+
}
|
|
112224
|
+
function gatedSecrets(run) {
|
|
112225
|
+
const state = keychainProcessState();
|
|
112226
|
+
const next = state.secretsQueue.then(run, run);
|
|
112227
|
+
state.secretsQueue = next.then(() => {
|
|
112228
|
+
return;
|
|
112229
|
+
}, () => {
|
|
112230
|
+
return;
|
|
112231
|
+
});
|
|
112232
|
+
return next;
|
|
112233
|
+
}
|
|
112234
|
+
function silentSecrets(run) {
|
|
112235
|
+
return gatedSecrets(async () => {
|
|
112236
|
+
const setInteraction = await loadInteractionSwitch();
|
|
112237
|
+
if (setInteraction === null)
|
|
112238
|
+
throw new Error("Keychain interaction cannot be switched off on this host.");
|
|
112239
|
+
setInteraction(false);
|
|
112240
|
+
try {
|
|
112241
|
+
return await run();
|
|
112242
|
+
} finally {
|
|
112243
|
+
setInteraction(true);
|
|
112244
|
+
}
|
|
112245
|
+
});
|
|
112246
|
+
}
|
|
112247
|
+
|
|
112248
|
+
// packages/omo-opencode/src/cli/account-keys/keystore.ts
|
|
112152
112249
|
var DEFAULT_SERVICE = "omo-cli";
|
|
112153
112250
|
function defaultRun(argv, input) {
|
|
112154
112251
|
const [file, ...args] = argv;
|
|
@@ -112172,7 +112269,7 @@ function createOsKeyStore(name, platform = process.platform, run = defaultRun, s
|
|
|
112172
112269
|
const resolved = secrets === undefined ? run === defaultRun && typeof Bun !== "undefined" ? Bun.secrets : null : secrets;
|
|
112173
112270
|
switch (platform) {
|
|
112174
112271
|
case "darwin":
|
|
112175
|
-
return resolved !== null ? createBunSecretsKeyStore(name, resolved) : createMacOsKeychainKeyStore(name, run);
|
|
112272
|
+
return resolved !== null ? createBunSecretsKeyStore(name, gateRealSecrets(resolved)) : createMacOsKeychainKeyStore(name, run);
|
|
112176
112273
|
case "linux":
|
|
112177
112274
|
return resolved !== null ? createBunSecretsKeyStore(name, resolved) : createLibsecretKeyStore(name, run);
|
|
112178
112275
|
case "win32":
|
|
@@ -112191,6 +112288,10 @@ async function guarded(run, fail, argv, input) {
|
|
|
112191
112288
|
throw fail();
|
|
112192
112289
|
}
|
|
112193
112290
|
}
|
|
112291
|
+
var gateRealSecrets = (secrets) => typeof Bun !== "undefined" && secrets === Bun.secrets ? {
|
|
112292
|
+
get: (key) => gatedSecrets(() => secrets.get(key)),
|
|
112293
|
+
set: (entry) => gatedSecrets(() => secrets.set(entry))
|
|
112294
|
+
} : secrets;
|
|
112194
112295
|
function createBunSecretsKeyStore(name, secrets) {
|
|
112195
112296
|
const key = { service: DEFAULT_SERVICE, name };
|
|
112196
112297
|
const unavailable = () => new Error("omo account keys: cannot access the OS credential store. Unlock the login keychain (macOS), the Secret Service keyring (Linux), or DPAPI (Windows), then try again. " + "Private keys are only ever stored through the OS credential facility.");
|
|
@@ -112728,64 +112829,705 @@ async function loginDevice(session, options) {
|
|
|
112728
112829
|
}
|
|
112729
112830
|
|
|
112730
112831
|
// packages/omo-opencode/src/cli/service-auth/keystore.ts
|
|
112731
|
-
import { createHash as createHash12, randomUUID as
|
|
112732
|
-
import { basename as
|
|
112832
|
+
import { createHash as createHash12, randomUUID as randomUUID8 } from "node:crypto";
|
|
112833
|
+
import { basename as basename17 } from "node:path";
|
|
112733
112834
|
|
|
112734
|
-
// packages/omo-opencode/src/cli/service-auth/
|
|
112735
|
-
import {
|
|
112736
|
-
|
|
112737
|
-
|
|
112738
|
-
|
|
112739
|
-
|
|
112740
|
-
|
|
112741
|
-
|
|
112742
|
-
|
|
112835
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/darwin-backend.ts
|
|
112836
|
+
import { homedir as homedir31 } from "node:os";
|
|
112837
|
+
import { join as join109 } from "node:path";
|
|
112838
|
+
|
|
112839
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/client.ts
|
|
112840
|
+
init_zod();
|
|
112841
|
+
init_bun_spawn_shim();
|
|
112842
|
+
var MUTATING = new Set(["write", "stage", "retire", "promote", "remove"]);
|
|
112843
|
+
var helperReplySchema = object({
|
|
112844
|
+
owned: boolean2(),
|
|
112845
|
+
value: string2(),
|
|
112846
|
+
marker: boolean2(),
|
|
112847
|
+
cdat: number2(),
|
|
112848
|
+
mdat: number2(),
|
|
112849
|
+
partition: _enum(["ours", "other", "none", "unknown"]),
|
|
112850
|
+
present: object({ staging: boolean2(), old: boolean2(), oldSlots: array(number2().int().min(0).max(7)).optional() }).strict(),
|
|
112851
|
+
missing: boolean2(),
|
|
112852
|
+
recover: boolean2(),
|
|
112853
|
+
ok: boolean2(),
|
|
112854
|
+
created: boolean2(),
|
|
112855
|
+
skipped: boolean2(),
|
|
112856
|
+
slot: number2().int().min(0).max(7),
|
|
112857
|
+
error: _enum(["locked", "store", "not-owned", "exists", "missing", "denied", "refused"]),
|
|
112858
|
+
reason: string2(),
|
|
112859
|
+
status: number2()
|
|
112860
|
+
}).partial().strict();
|
|
112861
|
+
|
|
112862
|
+
class HelperProtocolError extends Error {
|
|
112863
|
+
}
|
|
112864
|
+
async function firstLine(stream) {
|
|
112865
|
+
const reader = stream.getReader();
|
|
112866
|
+
const decoder = new TextDecoder;
|
|
112867
|
+
let text = "";
|
|
112868
|
+
for (;; ) {
|
|
112869
|
+
const newline = text.indexOf(`
|
|
112870
|
+
`);
|
|
112871
|
+
if (newline !== -1)
|
|
112872
|
+
return text.slice(0, newline);
|
|
112873
|
+
const chunk = await reader.read();
|
|
112874
|
+
if (chunk.done)
|
|
112875
|
+
return null;
|
|
112876
|
+
text += decoder.decode(chunk.value, { stream: true });
|
|
112877
|
+
}
|
|
112878
|
+
}
|
|
112879
|
+
function isFlushable(stream) {
|
|
112880
|
+
return typeof stream.flush === "function";
|
|
112881
|
+
}
|
|
112882
|
+
var spawnDetachedHelper = (path) => {
|
|
112883
|
+
const child = spawn([path], {
|
|
112884
|
+
stdin: "pipe",
|
|
112885
|
+
stdout: "pipe",
|
|
112886
|
+
stderr: "ignore",
|
|
112887
|
+
detached: true,
|
|
112888
|
+
env: process.env.HOME === undefined ? {} : { HOME: process.env.HOME }
|
|
112889
|
+
});
|
|
112890
|
+
const pid = child.pid;
|
|
112891
|
+
if (pid === undefined)
|
|
112892
|
+
throw new HelperProtocolError("The keychain helper did not start.");
|
|
112893
|
+
const stdin = child.stdin;
|
|
112894
|
+
return {
|
|
112895
|
+
pid,
|
|
112896
|
+
send: (line) => {
|
|
112897
|
+
stdin.write(line);
|
|
112898
|
+
if (isFlushable(stdin))
|
|
112899
|
+
stdin.flush();
|
|
112900
|
+
},
|
|
112901
|
+
reply: firstLine(child.stdout),
|
|
112902
|
+
close: () => {
|
|
112903
|
+
stdin.end();
|
|
112904
|
+
}
|
|
112905
|
+
};
|
|
112743
112906
|
};
|
|
112744
|
-
|
|
112745
|
-
const
|
|
112746
|
-
|
|
112747
|
-
|
|
112748
|
-
|
|
112749
|
-
|
|
112750
|
-
|
|
112751
|
-
|
|
112752
|
-
|
|
112753
|
-
|
|
112754
|
-
|
|
112755
|
-
|
|
112756
|
-
|
|
112757
|
-
|
|
112758
|
-
|
|
112759
|
-
|
|
112760
|
-
|
|
112761
|
-
|
|
112762
|
-
|
|
112763
|
-
|
|
112907
|
+
async function callHelper(path, call, options = {}) {
|
|
112908
|
+
const mutates = MUTATING.has(call.verb);
|
|
112909
|
+
if (mutates && options.lease === undefined)
|
|
112910
|
+
throw new HelperProtocolError(`The ${call.verb} helper call needs the session lock.`);
|
|
112911
|
+
const helper = (options.spawn ?? spawnDetachedHelper)(path);
|
|
112912
|
+
let handedOver = false;
|
|
112913
|
+
try {
|
|
112914
|
+
if (mutates && options.lease !== undefined) {
|
|
112915
|
+
await options.lease.handOver(helper.pid);
|
|
112916
|
+
handedOver = true;
|
|
112917
|
+
}
|
|
112918
|
+
helper.send(`${JSON.stringify({ v: 1, verb: call.verb, account: call.account, ...call.value === undefined ? {} : { value: call.value } })}
|
|
112919
|
+
`);
|
|
112920
|
+
const line = await helper.reply;
|
|
112921
|
+
if (handedOver && options.lease !== undefined) {
|
|
112922
|
+
handedOver = false;
|
|
112923
|
+
await options.lease.restore();
|
|
112924
|
+
}
|
|
112925
|
+
if (line === null)
|
|
112926
|
+
throw new HelperProtocolError(`The keychain helper exited without answering ${call.verb}.`);
|
|
112927
|
+
let json;
|
|
112928
|
+
try {
|
|
112929
|
+
json = JSON.parse(line);
|
|
112930
|
+
} catch {
|
|
112931
|
+
throw new HelperProtocolError(`The keychain helper sent a ${call.verb} reply that is not JSON.`);
|
|
112932
|
+
}
|
|
112933
|
+
const parsed = helperReplySchema.safeParse(json);
|
|
112934
|
+
if (!parsed.success)
|
|
112935
|
+
throw new HelperProtocolError(`The keychain helper sent an unexpected ${call.verb} reply.`);
|
|
112936
|
+
return parsed.data;
|
|
112937
|
+
} catch (error) {
|
|
112938
|
+
if (handedOver && options.lease !== undefined) {
|
|
112939
|
+
try {
|
|
112940
|
+
await options.lease.restore();
|
|
112941
|
+
} catch (restoreError) {
|
|
112942
|
+
throw new AggregateError([error, restoreError], `The ${call.verb} helper call failed and the session lock could not be restored.`);
|
|
112943
|
+
}
|
|
112944
|
+
}
|
|
112945
|
+
throw error;
|
|
112946
|
+
} finally {
|
|
112947
|
+
helper.close();
|
|
112948
|
+
}
|
|
112949
|
+
}
|
|
112950
|
+
|
|
112951
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/location.ts
|
|
112952
|
+
import { dirname as dirname42, join as join106, posix as posix13 } from "node:path";
|
|
112953
|
+
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
112954
|
+
function bundleCandidates(moduleUrl) {
|
|
112955
|
+
const root = dirname42(dirname42(dirname42(fileURLToPath8(moduleUrl))));
|
|
112956
|
+
return [join106(root, "bin", "darwin", "omo-keychain"), join106(root, "omo-keychain")];
|
|
112957
|
+
}
|
|
112958
|
+
function machineCandidates(home, arch = process.arch) {
|
|
112959
|
+
const runtimeArch = arch === "arm64" ? "arm64" : "x64";
|
|
112960
|
+
return [
|
|
112961
|
+
`/Applications/OmO.app/Contents/Resources/omo-runtime/darwin-${runtimeArch}/omo-keychain`,
|
|
112962
|
+
posix13.join(home, "Applications", "OmO.app", "Contents", "Resources", "omo-runtime", `darwin-${runtimeArch}`, "omo-keychain"),
|
|
112963
|
+
posix13.join(home, ".bun", "install", "global", "node_modules", "omo-ai", "bin", "darwin", "omo-keychain")
|
|
112964
|
+
];
|
|
112965
|
+
}
|
|
112966
|
+
async function locateHelper(candidates, verify) {
|
|
112967
|
+
const rejected = [];
|
|
112968
|
+
for (const path of candidates) {
|
|
112969
|
+
const verdict = await verify(path);
|
|
112970
|
+
if (verdict === "valid")
|
|
112971
|
+
return { kind: "found", path };
|
|
112972
|
+
if (verdict === "invalid")
|
|
112973
|
+
rejected.push(path);
|
|
112974
|
+
}
|
|
112975
|
+
return rejected.length === 0 ? { kind: "missing" } : { kind: "invalid", rejected };
|
|
112976
|
+
}
|
|
112977
|
+
|
|
112978
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/pin.ts
|
|
112979
|
+
import { readdirSync as readdirSync14, rmSync as rmSync9 } from "node:fs";
|
|
112980
|
+
import { chmod as chmod2, copyFile as copyFile4, constants as constants13, mkdtemp as mkdtemp2, rm as rm16, stat as stat8 } from "node:fs/promises";
|
|
112981
|
+
import { tmpdir as tmpdir6 } from "node:os";
|
|
112982
|
+
import { basename as basename15, join as join107 } from "node:path";
|
|
112983
|
+
var DIR_PREFIX = "omo-keychain-";
|
|
112984
|
+
var OWNED_DIR = new RegExp(`^${DIR_PREFIX}(\\d+)-`);
|
|
112985
|
+
var isAlive = (pid) => {
|
|
112986
|
+
try {
|
|
112987
|
+
process.kill(pid, 0);
|
|
112988
|
+
return true;
|
|
112989
|
+
} catch (error) {
|
|
112990
|
+
return !(error instanceof Error && ("code" in error) && error.code === "ESRCH");
|
|
112991
|
+
}
|
|
112992
|
+
};
|
|
112993
|
+
function sweepDeadPinDirs(root = tmpdir6()) {
|
|
112994
|
+
const removed = [];
|
|
112995
|
+
let entries;
|
|
112996
|
+
try {
|
|
112997
|
+
entries = readdirSync14(root);
|
|
112998
|
+
} catch {
|
|
112999
|
+
return removed;
|
|
113000
|
+
}
|
|
113001
|
+
for (const entry of entries) {
|
|
113002
|
+
const owner = OWNED_DIR.exec(entry)?.[1];
|
|
113003
|
+
if (owner === undefined || Number(owner) === process.pid || isAlive(Number(owner)))
|
|
113004
|
+
continue;
|
|
113005
|
+
try {
|
|
113006
|
+
rmSync9(join107(root, entry), { recursive: true, force: true });
|
|
113007
|
+
} catch {
|
|
113008
|
+
continue;
|
|
113009
|
+
}
|
|
113010
|
+
removed.push(entry);
|
|
113011
|
+
}
|
|
113012
|
+
return removed;
|
|
113013
|
+
}
|
|
113014
|
+
var processDir;
|
|
113015
|
+
async function processPinDir() {
|
|
113016
|
+
if (processDir !== undefined)
|
|
113017
|
+
return processDir;
|
|
113018
|
+
sweepDeadPinDirs();
|
|
113019
|
+
const dir = await mkdtemp2(join107(tmpdir6(), `${DIR_PREFIX}${process.pid}-`));
|
|
113020
|
+
process.once("exit", () => rmSync9(dir, { recursive: true, force: true }));
|
|
113021
|
+
processDir = dir;
|
|
113022
|
+
return dir;
|
|
113023
|
+
}
|
|
113024
|
+
var pinned = new Map;
|
|
113025
|
+
async function sourceIdentity(source) {
|
|
113026
|
+
const info = await stat8(source);
|
|
113027
|
+
return `${source}\x00${info.dev}\x00${info.ino}\x00${info.size}\x00${info.mtimeMs}\x00${info.ctimeMs}`;
|
|
113028
|
+
}
|
|
113029
|
+
async function copyAndVerify(source, verify, dir) {
|
|
113030
|
+
const target = join107(dir, `${crypto.randomUUID()}-${basename15(source)}`);
|
|
113031
|
+
try {
|
|
113032
|
+
await copyFile4(source, target, constants13.COPYFILE_EXCL);
|
|
113033
|
+
await chmod2(target, 320);
|
|
113034
|
+
} catch (error) {
|
|
113035
|
+
await rm16(target, { force: true });
|
|
113036
|
+
return { kind: "unavailable", reason: error instanceof Error ? error.message : String(error) };
|
|
113037
|
+
}
|
|
113038
|
+
let verdict;
|
|
113039
|
+
try {
|
|
113040
|
+
verdict = await verify(target);
|
|
113041
|
+
} catch (error) {
|
|
113042
|
+
await rm16(target, { force: true });
|
|
113043
|
+
return { kind: "unavailable", reason: error instanceof Error ? error.message : String(error) };
|
|
113044
|
+
}
|
|
113045
|
+
if (verdict === "valid")
|
|
113046
|
+
return { kind: "pinned", path: target };
|
|
113047
|
+
await rm16(target, { force: true });
|
|
113048
|
+
return { kind: "invalid" };
|
|
113049
|
+
}
|
|
113050
|
+
async function pinVerifiedCopy(source, verify, dir) {
|
|
113051
|
+
let identity;
|
|
113052
|
+
try {
|
|
113053
|
+
identity = `${dir ?? ""}\x00${await sourceIdentity(source)}`;
|
|
113054
|
+
} catch (error) {
|
|
113055
|
+
return { kind: "unavailable", reason: error instanceof Error ? error.message : String(error) };
|
|
113056
|
+
}
|
|
113057
|
+
const known = pinned.get(identity);
|
|
113058
|
+
if (known !== undefined) {
|
|
113059
|
+
const result = await known;
|
|
113060
|
+
if (result.kind !== "pinned")
|
|
113061
|
+
return result;
|
|
113062
|
+
let verdict;
|
|
113063
|
+
try {
|
|
113064
|
+
verdict = await verify(result.path);
|
|
113065
|
+
} catch (error) {
|
|
113066
|
+
pinned.delete(identity);
|
|
113067
|
+
await rm16(result.path, { force: true });
|
|
113068
|
+
return { kind: "unavailable", reason: error instanceof Error ? error.message : String(error) };
|
|
113069
|
+
}
|
|
113070
|
+
if (verdict === "valid")
|
|
113071
|
+
return result;
|
|
113072
|
+
}
|
|
113073
|
+
const created = Promise.resolve(dir ?? processPinDir()).then((target) => copyAndVerify(source, verify, target), (error) => ({ kind: "unavailable", reason: error instanceof Error ? error.message : String(error) }));
|
|
113074
|
+
pinned.set(identity, created);
|
|
113075
|
+
const result = await created;
|
|
113076
|
+
if (result.kind !== "pinned")
|
|
113077
|
+
pinned.delete(identity);
|
|
113078
|
+
return result;
|
|
113079
|
+
}
|
|
113080
|
+
|
|
113081
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/signature.ts
|
|
113082
|
+
import { stat as stat9 } from "node:fs/promises";
|
|
113083
|
+
init_bun_spawn_shim();
|
|
113084
|
+
var KEYCHAIN_HELPER_REQUIREMENT = 'identifier "com.mengmota.omo-keychain-helper" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] ' + 'and certificate leaf[field.1.2.840.113635.100.6.1.13] and certificate leaf[subject.OU] = "523JNR86LZ"';
|
|
113085
|
+
var STRICT_ALL_ARCHITECTURES = 1 << 4 | 1 << 0;
|
|
113086
|
+
var UTF8 = 134217984;
|
|
113087
|
+
var security;
|
|
113088
|
+
async function loadSecurity() {
|
|
113089
|
+
if (security !== undefined)
|
|
113090
|
+
return security;
|
|
113091
|
+
try {
|
|
113092
|
+
const { dlopen, FFIType, ptr } = await loadBunFfi();
|
|
113093
|
+
const cf = dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", {
|
|
113094
|
+
CFStringCreateWithCString: { args: [FFIType.u64, FFIType.ptr, FFIType.u32], returns: FFIType.u64 },
|
|
113095
|
+
CFURLCreateFromFileSystemRepresentation: { args: [FFIType.u64, FFIType.ptr, FFIType.i64, FFIType.bool], returns: FFIType.u64 },
|
|
113096
|
+
CFRelease: { args: [FFIType.u64], returns: FFIType.void }
|
|
113097
|
+
});
|
|
113098
|
+
const sec = dlopen("/System/Library/Frameworks/Security.framework/Security", {
|
|
113099
|
+
SecStaticCodeCreateWithPath: { args: [FFIType.u64, FFIType.u32, FFIType.ptr], returns: FFIType.i32 },
|
|
113100
|
+
SecRequirementCreateWithString: { args: [FFIType.u64, FFIType.u32, FFIType.ptr], returns: FFIType.i32 },
|
|
113101
|
+
SecStaticCodeCheckValidityWithErrors: { args: [FFIType.u64, FFIType.u32, FFIType.u64, FFIType.u64], returns: FFIType.i32 }
|
|
113102
|
+
});
|
|
113103
|
+
const cString = (text) => Buffer.from(`${text}\x00`, "utf8");
|
|
113104
|
+
security = {
|
|
113105
|
+
check(path, requirement) {
|
|
113106
|
+
const pathBytes = Buffer.from(path, "utf8");
|
|
113107
|
+
const url = BigInt(cf.symbols.CFURLCreateFromFileSystemRepresentation(0n, ptr(pathBytes), pathBytes.length, false));
|
|
113108
|
+
const text = BigInt(cf.symbols.CFStringCreateWithCString(0n, ptr(cString(requirement)), UTF8));
|
|
113109
|
+
const codeOut = new BigUint64Array(1);
|
|
113110
|
+
const requirementOut = new BigUint64Array(1);
|
|
113111
|
+
try {
|
|
113112
|
+
if (url === 0n || text === 0n)
|
|
113113
|
+
return false;
|
|
113114
|
+
if (sec.symbols.SecStaticCodeCreateWithPath(url, 0, ptr(codeOut)) !== 0)
|
|
113115
|
+
return false;
|
|
113116
|
+
if (sec.symbols.SecRequirementCreateWithString(text, 0, ptr(requirementOut)) !== 0)
|
|
113117
|
+
return false;
|
|
113118
|
+
const code = codeOut[0] ?? 0n;
|
|
113119
|
+
const designated = requirementOut[0] ?? 0n;
|
|
113120
|
+
return sec.symbols.SecStaticCodeCheckValidityWithErrors(code, STRICT_ALL_ARCHITECTURES, designated, 0n) === 0;
|
|
113121
|
+
} finally {
|
|
113122
|
+
for (const ref of [url, text, codeOut[0] ?? 0n, requirementOut[0] ?? 0n])
|
|
113123
|
+
if (ref !== 0n)
|
|
113124
|
+
cf.symbols.CFRelease(ref);
|
|
113125
|
+
}
|
|
113126
|
+
}
|
|
113127
|
+
};
|
|
113128
|
+
} catch {
|
|
113129
|
+
security = null;
|
|
113130
|
+
}
|
|
113131
|
+
return security;
|
|
113132
|
+
}
|
|
113133
|
+
async function verifyWithCodesign(path, requirement) {
|
|
113134
|
+
const child = spawn(["/usr/bin/codesign", "--verify", "--strict", `-R=${requirement}`, path], {
|
|
113135
|
+
stdout: "ignore",
|
|
113136
|
+
stderr: "ignore",
|
|
113137
|
+
env: {}
|
|
112764
113138
|
});
|
|
112765
|
-
child.
|
|
112766
|
-
|
|
112767
|
-
|
|
113139
|
+
return await child.exited === 0;
|
|
113140
|
+
}
|
|
113141
|
+
var verifyWithSecurityFramework = async (path, requirement) => {
|
|
113142
|
+
const loaded = await loadSecurity();
|
|
113143
|
+
return loaded === null ? verifyWithCodesign(path, requirement) : loaded.check(path, requirement);
|
|
113144
|
+
};
|
|
113145
|
+
async function fileIdentity(path) {
|
|
113146
|
+
try {
|
|
113147
|
+
const info = await stat9(path);
|
|
113148
|
+
if (!info.isFile())
|
|
113149
|
+
return null;
|
|
113150
|
+
return `${path}\x00${info.dev}\x00${info.ino}\x00${info.size}\x00${info.mtimeMs}\x00${info.ctimeMs}`;
|
|
113151
|
+
} catch {
|
|
113152
|
+
return null;
|
|
113153
|
+
}
|
|
113154
|
+
}
|
|
113155
|
+
function createSignatureChecker(check = verifyWithSecurityFramework, requirement = KEYCHAIN_HELPER_REQUIREMENT) {
|
|
113156
|
+
const verdicts = new Map;
|
|
113157
|
+
const checker = async (path) => {
|
|
113158
|
+
const before = await fileIdentity(path);
|
|
113159
|
+
if (before === null)
|
|
113160
|
+
return "missing";
|
|
113161
|
+
const known = verdicts.get(before);
|
|
113162
|
+
if (known !== undefined)
|
|
113163
|
+
return known;
|
|
113164
|
+
const passed = await check(path, requirement);
|
|
113165
|
+
if (await fileIdentity(path) !== before)
|
|
113166
|
+
return "invalid";
|
|
113167
|
+
const verdict = passed ? "valid" : "invalid";
|
|
113168
|
+
verdicts.set(before, verdict);
|
|
113169
|
+
return verdict;
|
|
113170
|
+
};
|
|
113171
|
+
return checker;
|
|
113172
|
+
}
|
|
113173
|
+
var processChecker;
|
|
113174
|
+
var processSignatureChecker = () => processChecker ??= createSignatureChecker();
|
|
113175
|
+
|
|
113176
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/access.ts
|
|
113177
|
+
async function resolveHelperAccess(candidates, options = {}) {
|
|
113178
|
+
const verify = options.verify ?? processSignatureChecker();
|
|
113179
|
+
let source;
|
|
113180
|
+
let pin;
|
|
113181
|
+
try {
|
|
113182
|
+
const location = await locateHelper(candidates, verify);
|
|
113183
|
+
if (location.kind !== "found")
|
|
113184
|
+
return location;
|
|
113185
|
+
source = location.path;
|
|
113186
|
+
pin = await (options.pin ?? pinVerifiedCopy)(source, verify);
|
|
113187
|
+
} catch (error) {
|
|
113188
|
+
return { kind: "unavailable", reason: error instanceof Error ? error.message : String(error) };
|
|
113189
|
+
}
|
|
113190
|
+
if (pin.kind === "invalid")
|
|
113191
|
+
return { kind: "invalid", rejected: [source] };
|
|
113192
|
+
if (pin.kind === "unavailable")
|
|
113193
|
+
return { kind: "unavailable", reason: pin.reason };
|
|
113194
|
+
const pinned = pin.path;
|
|
113195
|
+
const spawn = options.spawn ?? spawnDetachedHelper;
|
|
113196
|
+
return {
|
|
113197
|
+
kind: "ready",
|
|
113198
|
+
path: pinned,
|
|
113199
|
+
call: async (call, lease) => {
|
|
113200
|
+
const verdict = await verify(pinned).catch((error) => {
|
|
113201
|
+
throw new HelperProtocolError(`OmO's keychain helper could not be checked before it ran: ${error instanceof Error ? error.message : String(error)}`);
|
|
113202
|
+
});
|
|
113203
|
+
if (verdict !== "valid")
|
|
113204
|
+
throw new HelperProtocolError("OmO's keychain helper changed on disk and failed its signature check; it was not run.");
|
|
113205
|
+
return callHelper(pinned, call, { spawn, ...lease === undefined ? {} : { lease } });
|
|
113206
|
+
}
|
|
113207
|
+
};
|
|
113208
|
+
}
|
|
113209
|
+
|
|
113210
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/approval-cache.ts
|
|
113211
|
+
var systemClock = { nowSeconds: () => Date.now() / 1000, sleepMs: (ms) => new Promise((resolve) => setTimeout(resolve, ms)) };
|
|
113212
|
+
function isEntryValid(entry, current, nowSeconds) {
|
|
113213
|
+
if (nowSeconds < entry.readStartedAt)
|
|
113214
|
+
return false;
|
|
113215
|
+
return current.cdat === entry.cdat && current.mdat === entry.mdat && Math.floor(current.mdat) < Math.floor(entry.readStartedAt);
|
|
113216
|
+
}
|
|
113217
|
+
function createApprovalCache(clock = systemClock) {
|
|
113218
|
+
let entry = null;
|
|
113219
|
+
let deniedForBackground = false;
|
|
113220
|
+
let pending = null;
|
|
113221
|
+
return {
|
|
113222
|
+
consume(current) {
|
|
113223
|
+
if (entry === null)
|
|
113224
|
+
return null;
|
|
113225
|
+
if (!isEntryValid(entry, current, clock.nowSeconds())) {
|
|
113226
|
+
entry = null;
|
|
113227
|
+
return null;
|
|
113228
|
+
}
|
|
113229
|
+
return entry.value;
|
|
113230
|
+
},
|
|
113231
|
+
deniedForBackground: () => deniedForBackground,
|
|
113232
|
+
inFlight: () => pending,
|
|
113233
|
+
approve(run) {
|
|
113234
|
+
if (pending !== null)
|
|
113235
|
+
return pending;
|
|
113236
|
+
const readStartedAt = clock.nowSeconds();
|
|
113237
|
+
const started = run().then((answer) => {
|
|
113238
|
+
if (answer.kind === "approved") {
|
|
113239
|
+
entry = { value: answer.value, ...answer.attributes, readStartedAt };
|
|
113240
|
+
deniedForBackground = false;
|
|
113241
|
+
} else if (answer.kind === "denied")
|
|
113242
|
+
deniedForBackground = true;
|
|
113243
|
+
return answer;
|
|
113244
|
+
});
|
|
113245
|
+
const settled = () => {
|
|
113246
|
+
if (pending === started)
|
|
113247
|
+
pending = null;
|
|
113248
|
+
};
|
|
113249
|
+
started.then(settled, settled);
|
|
113250
|
+
pending = started;
|
|
113251
|
+
return started;
|
|
113252
|
+
},
|
|
113253
|
+
async afterOwnWrite(value, readAttributes) {
|
|
113254
|
+
if (entry === null)
|
|
113255
|
+
return;
|
|
113256
|
+
const written = await readAttributes();
|
|
113257
|
+
if (written === null) {
|
|
113258
|
+
entry = null;
|
|
113259
|
+
return;
|
|
113260
|
+
}
|
|
113261
|
+
while (Math.floor(clock.nowSeconds()) <= Math.floor(written.mdat)) {
|
|
113262
|
+
await clock.sleepMs(Math.max(1, Math.ceil((Math.floor(written.mdat) + 1 - clock.nowSeconds()) * 1000)));
|
|
113263
|
+
}
|
|
113264
|
+
const readStartedAt = clock.nowSeconds();
|
|
113265
|
+
const fresh = await readAttributes();
|
|
113266
|
+
entry = fresh === null ? null : { value, ...fresh, readStartedAt };
|
|
113267
|
+
},
|
|
113268
|
+
drop() {
|
|
113269
|
+
entry = null;
|
|
113270
|
+
}
|
|
113271
|
+
};
|
|
113272
|
+
}
|
|
113273
|
+
var processApprovalCache = () => {
|
|
113274
|
+
const state = keychainProcessState();
|
|
113275
|
+
state.approvalCache ??= createApprovalCache();
|
|
113276
|
+
return state.approvalCache;
|
|
113277
|
+
};
|
|
113278
|
+
|
|
113279
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/darwin-read.ts
|
|
113280
|
+
var ROW_8B_DEFAULT = "re-login";
|
|
113281
|
+
|
|
113282
|
+
class HelperReadError extends Error {
|
|
113283
|
+
failure;
|
|
113284
|
+
constructor(failure, message) {
|
|
113285
|
+
super(message);
|
|
113286
|
+
this.failure = failure;
|
|
113287
|
+
}
|
|
113288
|
+
}
|
|
113289
|
+
function failure2(reply) {
|
|
113290
|
+
if (reply.error === "locked")
|
|
113291
|
+
return new HelperReadError("locked", "The keychain is locked.");
|
|
113292
|
+
return new HelperReadError("store", `The keychain helper answered ${reply.error ?? "unexpectedly"}.`);
|
|
113293
|
+
}
|
|
113294
|
+
async function approveOnce(deps) {
|
|
113295
|
+
const running = deps.cache.inFlight();
|
|
113296
|
+
if (running !== null)
|
|
113297
|
+
return running;
|
|
113298
|
+
const release = await deps.takePromptLock();
|
|
113299
|
+
if (release === null)
|
|
113300
|
+
throw new HelperReadError("pending", "Another omo process is waiting for your keychain approval.");
|
|
113301
|
+
try {
|
|
113302
|
+
return await deps.cache.approve(async () => {
|
|
113303
|
+
const reply = await deps.access.call({ verb: "approve", account: deps.account });
|
|
113304
|
+
if (reply.missing === true)
|
|
113305
|
+
return { kind: "missing" };
|
|
113306
|
+
if (reply.error === "denied")
|
|
113307
|
+
return { kind: "denied" };
|
|
113308
|
+
if (reply.error !== undefined || reply.value === undefined || reply.cdat === undefined || reply.mdat === undefined)
|
|
113309
|
+
throw failure2(reply);
|
|
113310
|
+
return { kind: "approved", value: reply.value, attributes: { cdat: reply.cdat, mdat: reply.mdat } };
|
|
113311
|
+
});
|
|
113312
|
+
} finally {
|
|
113313
|
+
await release();
|
|
113314
|
+
}
|
|
113315
|
+
}
|
|
113316
|
+
async function readThroughHelper(deps, allowPrompt) {
|
|
113317
|
+
const reply = await deps.access.call({ verb: "read", account: deps.account });
|
|
113318
|
+
if (reply.error !== undefined)
|
|
113319
|
+
throw failure2(reply);
|
|
113320
|
+
if (reply.missing === true)
|
|
113321
|
+
return { kind: "missing", reply };
|
|
113322
|
+
if (reply.owned === true && reply.value !== undefined)
|
|
113323
|
+
return { kind: "value", value: reply.value, source: reply.marker === true || reply.recover === true ? "owned" : "owned-unmarked", reply };
|
|
113324
|
+
const own = await deps.ownSilentGet().catch(() => {
|
|
113325
|
+
return;
|
|
112768
113326
|
});
|
|
112769
|
-
|
|
112770
|
-
|
|
112771
|
-
|
|
113327
|
+
if (typeof own === "string")
|
|
113328
|
+
return { kind: "value", value: own, source: "own-identity", reply };
|
|
113329
|
+
if (reply.cdat === undefined || reply.mdat === undefined)
|
|
113330
|
+
throw failure2(reply);
|
|
113331
|
+
const cached = deps.cache.consume({ cdat: reply.cdat, mdat: reply.mdat });
|
|
113332
|
+
if (cached !== null)
|
|
113333
|
+
return { kind: "value", value: cached, source: "approved", reply };
|
|
113334
|
+
const reloginInstead = reply.partition !== "ours" && reply.partition !== "none" && (deps.row8b ?? ROW_8B_DEFAULT) === "re-login";
|
|
113335
|
+
if (!allowPrompt) {
|
|
113336
|
+
if (reloginInstead)
|
|
113337
|
+
return { kind: "missing", reply };
|
|
113338
|
+
throw new HelperReadError("pending", "The keychain needs your approval; run an omo command in a terminal.");
|
|
113339
|
+
}
|
|
113340
|
+
if (deps.background && deps.cache.deniedForBackground())
|
|
113341
|
+
throw new HelperReadError("pending", "Keychain access was denied; run an omo command in a terminal to approve it.");
|
|
113342
|
+
if (reloginInstead)
|
|
113343
|
+
return { kind: "missing", reply };
|
|
113344
|
+
if (deps.noDialog === true)
|
|
113345
|
+
throw new HelperReadError("pending", "The keychain hand-off cannot show a dialog.");
|
|
113346
|
+
if (deps.handOff !== undefined && await deps.handOff()) {
|
|
113347
|
+
const after = await deps.access.call({ verb: "read", account: deps.account });
|
|
113348
|
+
if (after.owned === true && after.value !== undefined)
|
|
113349
|
+
return { kind: "value", value: after.value, source: "owned", reply: after };
|
|
113350
|
+
}
|
|
113351
|
+
const answer = await approveOnce(deps);
|
|
113352
|
+
if (answer.kind === "approved")
|
|
113353
|
+
return { kind: "value", value: answer.value, source: "approved", reply };
|
|
113354
|
+
if (answer.kind === "missing")
|
|
113355
|
+
return { kind: "missing", reply };
|
|
113356
|
+
throw new HelperReadError("denied", "Keychain access was denied.");
|
|
113357
|
+
}
|
|
113358
|
+
|
|
113359
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/recovery.ts
|
|
113360
|
+
var OLD_SLOT_COUNT = 8;
|
|
113361
|
+
var oldSlotName = (account, slot) => slot === 0 ? `${account}.old` : `${account}.old.${slot}`;
|
|
113362
|
+
function recoveryPlan(names) {
|
|
113363
|
+
if (!names.original && names.staging)
|
|
113364
|
+
return names.old ? ["promote", "delete-old"] : ["promote"];
|
|
113365
|
+
if (!names.original && names.old)
|
|
113366
|
+
return ["delete-old"];
|
|
113367
|
+
if (names.original && names.staging)
|
|
113368
|
+
return names.old ? ["remove-staging", "delete-old"] : ["remove-staging"];
|
|
113369
|
+
if (names.original && names.old)
|
|
113370
|
+
return ["delete-old"];
|
|
113371
|
+
return [];
|
|
113372
|
+
}
|
|
113373
|
+
function oldSlotsOf(reply) {
|
|
113374
|
+
return reply.present?.oldSlots ?? (reply.present?.old === true ? [0] : []);
|
|
113375
|
+
}
|
|
113376
|
+
function namesFromRead(reply) {
|
|
113377
|
+
const original = reply.owned === false || reply.owned === true && reply.recover !== true;
|
|
113378
|
+
return { original, staging: reply.present?.staging === true, old: reply.present?.old === true, oldSlots: oldSlotsOf(reply) };
|
|
113379
|
+
}
|
|
113380
|
+
async function deleteOld(name, helper, deleteOwn) {
|
|
113381
|
+
const removed = await helper({ verb: "remove", account: name }).catch(() => null);
|
|
113382
|
+
if (removed?.ok === true)
|
|
113383
|
+
return true;
|
|
113384
|
+
return deleteOwn(name).catch(() => false);
|
|
113385
|
+
}
|
|
113386
|
+
async function deleteOldSlots(account, slots, helper, deleteOwn) {
|
|
113387
|
+
let cleared = true;
|
|
113388
|
+
for (const slot of slots)
|
|
113389
|
+
if (!await deleteOld(oldSlotName(account, slot), helper, deleteOwn))
|
|
113390
|
+
cleared = false;
|
|
113391
|
+
return cleared;
|
|
113392
|
+
}
|
|
113393
|
+
async function runRecovery(account, names, helper, deleteOwnOld) {
|
|
113394
|
+
const applied = [];
|
|
113395
|
+
for (const step of recoveryPlan(names)) {
|
|
113396
|
+
const ok = step === "promote" ? (await helper({ verb: "promote", account })).ok === true : step === "remove-staging" ? (await helper({ verb: "remove", account: `${account}.staging` })).ok === true : await deleteOldSlots(account, names.oldSlots, helper, deleteOwnOld);
|
|
113397
|
+
if (!ok && step !== "delete-old")
|
|
113398
|
+
return { applied, failed: step };
|
|
113399
|
+
if (ok)
|
|
113400
|
+
applied.push(step);
|
|
113401
|
+
}
|
|
113402
|
+
return { applied, failed: null };
|
|
113403
|
+
}
|
|
113404
|
+
|
|
113405
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/migration.ts
|
|
113406
|
+
var MIGRATABLE = new Set(["own-identity", "owned-unmarked", "approved"]);
|
|
113407
|
+
async function migrate(account, value, source, helper, deleteOwnOld) {
|
|
113408
|
+
if (!MIGRATABLE.has(source))
|
|
113409
|
+
return { kind: "skipped", reason: "not-migratable" };
|
|
113410
|
+
if ((await helper({ verb: "stage", account, value })).ok !== true)
|
|
113411
|
+
return { kind: "failed", step: "stage" };
|
|
113412
|
+
const retired = await helper({ verb: "retire", account });
|
|
113413
|
+
if (retired.error === "exists" && retired.reason === "old-slots-full" || retired.ok === true && retired.skipped === true) {
|
|
113414
|
+
await helper({ verb: "remove", account: `${account}.staging` });
|
|
113415
|
+
return { kind: "skipped", reason: "old-slots-full" };
|
|
113416
|
+
}
|
|
113417
|
+
if (retired.ok !== true)
|
|
113418
|
+
return { kind: "failed", step: "retire" };
|
|
113419
|
+
const slot = retired.slot ?? 0;
|
|
113420
|
+
if ((await helper({ verb: "promote", account })).ok !== true)
|
|
113421
|
+
return { kind: "failed", step: "promote" };
|
|
113422
|
+
return { kind: "migrated", oldDeleted: await deleteOld(oldSlotName(account, slot), helper, deleteOwnOld) };
|
|
113423
|
+
}
|
|
113424
|
+
|
|
113425
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/darwin-store.ts
|
|
113426
|
+
class HelperOldSlotsFull extends Error {
|
|
113427
|
+
}
|
|
113428
|
+
var ALL_OLD_SLOTS = Array.from({ length: OLD_SLOT_COUNT }, (_, slot) => slot);
|
|
113429
|
+
var OLD_SLOTS_FULL_MESSAGE = 'The macOS keychain holds 8 earlier OmO sign-ins that cannot be removed automatically. Open Keychain Access, delete the items whose account name ends in ".old" or ".old.1" to ".old.7" for OmO, then sign in again.';
|
|
113430
|
+
var failed = (reply, verb) => new HelperReadError(reply.error === "locked" ? "locked" : "store", `The keychain helper could not ${verb} the sign-in (${reply.error ?? "no answer"}).`);
|
|
113431
|
+
function lockedDarwinStore(deps, lease) {
|
|
113432
|
+
const helper = (call) => deps.access.call(call, lease);
|
|
113433
|
+
const deleteOwnOld = (name) => deps.ownDelete(name);
|
|
113434
|
+
let lastRead = null;
|
|
113435
|
+
const read = async () => {
|
|
113436
|
+
const result = await readThroughHelper(deps, false);
|
|
113437
|
+
lastRead = result.kind === "value" ? result : null;
|
|
113438
|
+
return result.kind === "value" ? result.value : null;
|
|
113439
|
+
};
|
|
113440
|
+
return {
|
|
113441
|
+
async recover() {
|
|
113442
|
+
const reply = await deps.access.call({ verb: "read", account: deps.account });
|
|
113443
|
+
if (reply.error === undefined)
|
|
113444
|
+
await runRecovery(deps.account, namesFromRead(reply), helper, deleteOwnOld);
|
|
113445
|
+
},
|
|
113446
|
+
read,
|
|
113447
|
+
async settle() {
|
|
113448
|
+
if (lastRead === null)
|
|
113449
|
+
return;
|
|
113450
|
+
const outcome = await migrate(deps.account, lastRead.value, lastRead.source, helper, deleteOwnOld);
|
|
113451
|
+
if (outcome.kind === "skipped" && outcome.reason === "old-slots-full")
|
|
113452
|
+
deps.notice(`omo: ${OLD_SLOTS_FULL_MESSAGE}`);
|
|
113453
|
+
if (outcome.kind === "failed")
|
|
113454
|
+
deps.notice(`omo: the macOS keychain item could not be moved to OmO's keychain helper (${outcome.step}); it keeps working as before.`);
|
|
113455
|
+
},
|
|
113456
|
+
async write(value, intent, beforeRetire) {
|
|
113457
|
+
const state = await deps.access.call({ verb: "read", account: deps.account });
|
|
113458
|
+
if (state.error !== undefined)
|
|
113459
|
+
throw failed(state, "check");
|
|
113460
|
+
if (state.owned === false) {
|
|
113461
|
+
const approved = state.cdat !== undefined && state.mdat !== undefined && deps.cache.consume({ cdat: state.cdat, mdat: state.mdat }) !== null;
|
|
113462
|
+
const readable = lastRead !== null || approved || await deps.ownSilentGet().catch(() => {
|
|
113463
|
+
return;
|
|
113464
|
+
}) !== undefined;
|
|
113465
|
+
if (readable || intent !== "fresh-sign-in") {
|
|
113466
|
+
await deps.ownOverwrite(value);
|
|
113467
|
+
if (lastRead?.source === "approved")
|
|
113468
|
+
await deps.cache.afterOwnWrite(value, async () => {
|
|
113469
|
+
const after = await deps.access.call({ verb: "read", account: deps.account });
|
|
113470
|
+
return after.cdat === undefined || after.mdat === undefined ? null : { cdat: after.cdat, mdat: after.mdat };
|
|
113471
|
+
});
|
|
113472
|
+
return;
|
|
113473
|
+
}
|
|
113474
|
+
await beforeRetire?.();
|
|
113475
|
+
const retired = await helper({ verb: "retire", account: deps.account });
|
|
113476
|
+
if (retired.reason === "old-slots-full" || retired.ok === true && retired.skipped === true)
|
|
113477
|
+
throw new HelperOldSlotsFull(OLD_SLOTS_FULL_MESSAGE);
|
|
113478
|
+
if (retired.ok !== true)
|
|
113479
|
+
throw failed(retired, "replace");
|
|
113480
|
+
}
|
|
113481
|
+
const written = await helper({ verb: "write", account: deps.account, value });
|
|
113482
|
+
if (written.ok !== true)
|
|
113483
|
+
throw failed(written, "save");
|
|
113484
|
+
lastRead = { kind: "value", value, source: "owned", reply: written };
|
|
113485
|
+
},
|
|
113486
|
+
async clear() {
|
|
113487
|
+
const removed = await helper({ verb: "remove", account: deps.account });
|
|
113488
|
+
if (removed.error === "not-owned")
|
|
113489
|
+
await deps.ownDelete(deps.account);
|
|
113490
|
+
else if (removed.ok !== true)
|
|
113491
|
+
throw failed(removed, "remove");
|
|
113492
|
+
await helper({ verb: "remove", account: `${deps.account}.staging` });
|
|
113493
|
+
const present = await helper({ verb: "read", account: deps.account });
|
|
113494
|
+
const slots = present.error === undefined ? oldSlotsOf(present) : ALL_OLD_SLOTS;
|
|
113495
|
+
await deleteOldSlots(deps.account, slots, helper, deleteOwnOld);
|
|
113496
|
+
lastRead = null;
|
|
113497
|
+
}
|
|
113498
|
+
};
|
|
113499
|
+
}
|
|
113500
|
+
|
|
113501
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/owner-marker.ts
|
|
113502
|
+
init_bun_spawn_shim();
|
|
113503
|
+
var MARKER_LINE = /^\s*"gena"<blob>="omo-owner\/1"\s*$/m;
|
|
113504
|
+
var ITEM_NOT_FOUND = 44;
|
|
113505
|
+
var probeOwnerMarker = async (service, account, keychain) => {
|
|
113506
|
+
const args = ["find-generic-password", "-s", service, "-a", account, ...keychain === undefined ? [] : [keychain]];
|
|
113507
|
+
const child = spawn(["/usr/bin/security", ...args], {
|
|
113508
|
+
stdout: "pipe",
|
|
113509
|
+
stderr: "ignore",
|
|
113510
|
+
env: process.env.HOME === undefined ? {} : { HOME: process.env.HOME }
|
|
112772
113511
|
});
|
|
112773
|
-
|
|
113512
|
+
const [stdout, code] = await Promise.all([new Response(child.stdout).text(), child.exited]);
|
|
113513
|
+
if (code === ITEM_NOT_FOUND)
|
|
113514
|
+
return "absent";
|
|
113515
|
+
if (code !== 0)
|
|
113516
|
+
return "unknown";
|
|
113517
|
+
return MARKER_LINE.test(stdout) ? "helper-owned" : "other";
|
|
113518
|
+
};
|
|
112774
113519
|
|
|
112775
|
-
// packages/omo-opencode/src/cli/service-auth/
|
|
112776
|
-
import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
|
|
112777
|
-
import { createHash as createHash11 } from "node:crypto";
|
|
113520
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/prompt-lock.ts
|
|
112778
113521
|
import { mkdir as mkdir11 } from "node:fs/promises";
|
|
112779
|
-
import {
|
|
112780
|
-
import { join as join106 } from "node:path";
|
|
113522
|
+
import { dirname as dirname45 } from "node:path";
|
|
112781
113523
|
|
|
112782
113524
|
// packages/team-core/src/team-state-store/lock-publish.ts
|
|
112783
|
-
import { access as
|
|
112784
|
-
import { dirname as
|
|
113525
|
+
import { access as access5, open as open3, unlink as unlink4 } from "node:fs/promises";
|
|
113526
|
+
import { dirname as dirname43 } from "node:path";
|
|
112785
113527
|
|
|
112786
113528
|
// packages/team-core/src/team-state-store/lock-record.ts
|
|
112787
113529
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
112788
|
-
import { readFile as
|
|
113530
|
+
import { readFile as readFile35, stat as stat11 } from "node:fs/promises";
|
|
112789
113531
|
|
|
112790
113532
|
// packages/memory-core/src/locks/process-identity.ts
|
|
112791
113533
|
import { execFile as execFile7 } from "node:child_process";
|
|
@@ -112883,23 +113625,23 @@ function rename8(from, to, admit) {
|
|
|
112883
113625
|
}
|
|
112884
113626
|
var sync = resilientNamespace(fsSync, "sync");
|
|
112885
113627
|
var {
|
|
112886
|
-
access:
|
|
112887
|
-
chmod:
|
|
112888
|
-
copyFile:
|
|
113628
|
+
access: access4,
|
|
113629
|
+
chmod: chmod3,
|
|
113630
|
+
copyFile: copyFile5,
|
|
112889
113631
|
cp: cp5,
|
|
112890
113632
|
link,
|
|
112891
113633
|
lstat: lstat18,
|
|
112892
113634
|
mkdir: mkdir10,
|
|
112893
|
-
mkdtemp:
|
|
112894
|
-
readFile:
|
|
113635
|
+
mkdtemp: mkdtemp3,
|
|
113636
|
+
readFile: readFile34,
|
|
112895
113637
|
readdir: readdir17,
|
|
112896
113638
|
readlink: readlink7,
|
|
112897
113639
|
realpath: realpath2,
|
|
112898
|
-
rm:
|
|
113640
|
+
rm: rm17,
|
|
112899
113641
|
rmdir: rmdir2,
|
|
112900
|
-
stat:
|
|
113642
|
+
stat: stat10,
|
|
112901
113643
|
statfs,
|
|
112902
|
-
unlink:
|
|
113644
|
+
unlink: unlink3
|
|
112903
113645
|
} = promises;
|
|
112904
113646
|
var {
|
|
112905
113647
|
accessSync: accessSync5,
|
|
@@ -112909,7 +113651,7 @@ var {
|
|
|
112909
113651
|
lstatSync: lstatSync5,
|
|
112910
113652
|
mkdirSync: mkdirSync19,
|
|
112911
113653
|
readFileSync: readFileSync44,
|
|
112912
|
-
readdirSync:
|
|
113654
|
+
readdirSync: readdirSync15,
|
|
112913
113655
|
realpathSync: realpathSync13,
|
|
112914
113656
|
statSync: statSync8,
|
|
112915
113657
|
unlinkSync: unlinkSync10,
|
|
@@ -113022,7 +113764,7 @@ async function execFileText(command, args) {
|
|
|
113022
113764
|
}
|
|
113023
113765
|
async function readLinuxStartIdentity(pid) {
|
|
113024
113766
|
try {
|
|
113025
|
-
const stat = await
|
|
113767
|
+
const stat = await readFile34(`/proc/${pid}/stat`, "utf8");
|
|
113026
113768
|
const commandEnd = stat.lastIndexOf(")");
|
|
113027
113769
|
if (commandEnd < 0)
|
|
113028
113770
|
return null;
|
|
@@ -113261,14 +114003,17 @@ async function isWorkerLockReleased(incarnation, record) {
|
|
|
113261
114003
|
// packages/team-core/src/team-state-store/lock-record.ts
|
|
113262
114004
|
async function buildLockRecord(ownerTag) {
|
|
113263
114005
|
await registerLockWorker();
|
|
113264
|
-
const processStart = await
|
|
114006
|
+
const processStart = await lockProcessStartLine(process.pid);
|
|
113265
114007
|
return `${ownerTag} ${randomUUID6()}
|
|
113266
114008
|
${process.pid}
|
|
113267
114009
|
${Date.now()}
|
|
113268
114010
|
${lockOwnerInstanceId}
|
|
113269
|
-
${processStart
|
|
114011
|
+
${processStart}
|
|
113270
114012
|
`;
|
|
113271
114013
|
}
|
|
114014
|
+
async function lockProcessStartLine(pid) {
|
|
114015
|
+
return await getProcessStartIdentity(pid) ?? "unavailable";
|
|
114016
|
+
}
|
|
113272
114017
|
function errorCode2(error) {
|
|
113273
114018
|
if (!(error instanceof Error) || !("code" in error))
|
|
113274
114019
|
return null;
|
|
@@ -113297,8 +114042,8 @@ function parseLockOwner(content) {
|
|
|
113297
114042
|
}
|
|
113298
114043
|
async function readLockRecord(lockPath) {
|
|
113299
114044
|
try {
|
|
113300
|
-
const content = await
|
|
113301
|
-
const { mtimeMs } = await
|
|
114045
|
+
const content = await readFile35(lockPath, "utf8");
|
|
114046
|
+
const { mtimeMs } = await stat11(lockPath);
|
|
113302
114047
|
return { content, modifiedAtEpochMs: mtimeMs };
|
|
113303
114048
|
} catch (error) {
|
|
113304
114049
|
if (!(error instanceof Error))
|
|
@@ -113329,7 +114074,7 @@ async function isLockRecordStale(record, staleAfterMs) {
|
|
|
113329
114074
|
|
|
113330
114075
|
// packages/team-core/src/team-state-store/lock-publish.ts
|
|
113331
114076
|
async function pathMayExist(path, deps = {}) {
|
|
113332
|
-
const accessPath = deps.access ??
|
|
114077
|
+
const accessPath = deps.access ?? access5;
|
|
113333
114078
|
try {
|
|
113334
114079
|
await accessPath(path);
|
|
113335
114080
|
return true;
|
|
@@ -113346,7 +114091,7 @@ async function assertRetryableLockOpenError(lockPath, error, deps) {
|
|
|
113346
114091
|
if (code === "EPERM") {
|
|
113347
114092
|
if (await pathMayExist(lockPath, deps))
|
|
113348
114093
|
return;
|
|
113349
|
-
if ((deps?.platform ?? process.platform) === "win32" && await pathMayExist(
|
|
114094
|
+
if ((deps?.platform ?? process.platform) === "win32" && await pathMayExist(dirname43(lockPath), deps))
|
|
113350
114095
|
return;
|
|
113351
114096
|
}
|
|
113352
114097
|
throw error;
|
|
@@ -113366,7 +114111,7 @@ async function publishLockRecord(lockPath, record) {
|
|
|
113366
114111
|
} catch (error) {
|
|
113367
114112
|
markLockRecordReleased(record);
|
|
113368
114113
|
await fileHandle.close();
|
|
113369
|
-
await
|
|
114114
|
+
await unlink4(lockPath).catch(() => {
|
|
113370
114115
|
return;
|
|
113371
114116
|
});
|
|
113372
114117
|
throw error;
|
|
@@ -113375,9 +114120,14 @@ async function publishLockRecord(lockPath, record) {
|
|
|
113375
114120
|
return true;
|
|
113376
114121
|
}
|
|
113377
114122
|
|
|
114123
|
+
// packages/team-core/src/team-state-store/lock-lease.ts
|
|
114124
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
114125
|
+
import { open as open4, readdir as readdir18, readFile as readFile36, rename as rename9, rm as rm18 } from "node:fs/promises";
|
|
114126
|
+
import { basename as basename16, dirname as dirname44, join as join108 } from "node:path";
|
|
114127
|
+
|
|
113378
114128
|
// packages/team-core/src/team-state-store/lock-reclaim.ts
|
|
113379
114129
|
import { createHash as createHash10 } from "node:crypto";
|
|
113380
|
-
import { unlink as
|
|
114130
|
+
import { unlink as unlink5 } from "node:fs/promises";
|
|
113381
114131
|
var RECLAIM_UNLINK_ATTEMPTS = 3;
|
|
113382
114132
|
var RECLAIM_UNLINK_RETRY_MS = 25;
|
|
113383
114133
|
function delay2(ms) {
|
|
@@ -113390,7 +114140,7 @@ function reclaimGuardPath(lockPath, record) {
|
|
|
113390
114140
|
}
|
|
113391
114141
|
async function unlinkWithRetry(path, deps) {
|
|
113392
114142
|
const wait = deps.delay ?? delay2;
|
|
113393
|
-
const unlinkFile = deps.unlink ??
|
|
114143
|
+
const unlinkFile = deps.unlink ?? unlink5;
|
|
113394
114144
|
for (let attempt = 1;; attempt += 1) {
|
|
113395
114145
|
try {
|
|
113396
114146
|
await unlinkFile(path);
|
|
@@ -113408,6 +114158,19 @@ async function unlinkWithRetry(path, deps) {
|
|
|
113408
114158
|
}
|
|
113409
114159
|
}
|
|
113410
114160
|
async function removeLockRecordIfUnchanged(lockPath, expectedRecord, staleAfterMs, deps = {}) {
|
|
114161
|
+
return withRecordGuard(lockPath, expectedRecord, staleAfterMs, deps, async () => {
|
|
114162
|
+
const current = await readLockRecord(lockPath);
|
|
114163
|
+
if (current === null)
|
|
114164
|
+
return "absent";
|
|
114165
|
+
if (current.content !== expectedRecord || !await isLockRecordStale(current, staleAfterMs))
|
|
114166
|
+
return "changed";
|
|
114167
|
+
const unlinked = await unlinkWithRetry(lockPath, deps);
|
|
114168
|
+
if (unlinked !== "stuck")
|
|
114169
|
+
forgetLockRecord(expectedRecord);
|
|
114170
|
+
return unlinked === "absent" ? "absent" : unlinked;
|
|
114171
|
+
});
|
|
114172
|
+
}
|
|
114173
|
+
async function withRecordGuard(lockPath, expectedRecord, staleAfterMs, deps, act) {
|
|
113411
114174
|
const guardPath = reclaimGuardPath(lockPath, expectedRecord);
|
|
113412
114175
|
const guardRecord = await buildLockRecord("lock-reclaim");
|
|
113413
114176
|
if (!await publishLockRecord(guardPath, guardRecord)) {
|
|
@@ -113418,15 +114181,7 @@ async function removeLockRecordIfUnchanged(lockPath, expectedRecord, staleAfterM
|
|
|
113418
114181
|
return "busy";
|
|
113419
114182
|
}
|
|
113420
114183
|
try {
|
|
113421
|
-
|
|
113422
|
-
if (current === null)
|
|
113423
|
-
return "absent";
|
|
113424
|
-
if (current.content !== expectedRecord || !await isLockRecordStale(current, staleAfterMs))
|
|
113425
|
-
return "changed";
|
|
113426
|
-
const unlinked = await unlinkWithRetry(lockPath, deps);
|
|
113427
|
-
if (unlinked !== "stuck")
|
|
113428
|
-
forgetLockRecord(expectedRecord);
|
|
113429
|
-
return unlinked === "absent" ? "absent" : unlinked;
|
|
114184
|
+
return await act();
|
|
113430
114185
|
} finally {
|
|
113431
114186
|
markLockRecordReleased(guardRecord);
|
|
113432
114187
|
if (await unlinkWithRetry(guardPath, deps) !== "stuck")
|
|
@@ -113434,6 +114189,97 @@ async function removeLockRecordIfUnchanged(lockPath, expectedRecord, staleAfterM
|
|
|
113434
114189
|
}
|
|
113435
114190
|
}
|
|
113436
114191
|
|
|
114192
|
+
// packages/team-core/src/team-state-store/lock-lease.ts
|
|
114193
|
+
class LockLeaseLostError extends Error {
|
|
114194
|
+
constructor(lockPath) {
|
|
114195
|
+
super(`The lock at ${lockPath} changed while it was handed over; the critical section was aborted.`);
|
|
114196
|
+
this.name = "LockLeaseLostError";
|
|
114197
|
+
}
|
|
114198
|
+
}
|
|
114199
|
+
var leaseTempPrefix = (lockPath) => `.${basename16(lockPath)}.`;
|
|
114200
|
+
var LEASE_TEMP_SUFFIX = ".lease";
|
|
114201
|
+
var UUID2 = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
|
|
114202
|
+
var escapeRegExp2 = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
114203
|
+
var leaseTempPattern = (lockPath) => new RegExp(`^\\.${escapeRegExp2(basename16(lockPath))}\\.${UUID2}\\.lease$`);
|
|
114204
|
+
async function replaceRecord(lockPath, content) {
|
|
114205
|
+
const temporary = join108(dirname44(lockPath), `${leaseTempPrefix(lockPath)}${randomUUID7()}${LEASE_TEMP_SUFFIX}`);
|
|
114206
|
+
try {
|
|
114207
|
+
const handle = await open4(temporary, "wx", 384);
|
|
114208
|
+
try {
|
|
114209
|
+
await handle.writeFile(content);
|
|
114210
|
+
} finally {
|
|
114211
|
+
await handle.close();
|
|
114212
|
+
}
|
|
114213
|
+
await rename9(temporary, lockPath);
|
|
114214
|
+
} catch (error) {
|
|
114215
|
+
await rm18(temporary, { force: true });
|
|
114216
|
+
throw error;
|
|
114217
|
+
}
|
|
114218
|
+
}
|
|
114219
|
+
async function removeLeftoverTemps(lockPath) {
|
|
114220
|
+
const pattern = leaseTempPattern(lockPath);
|
|
114221
|
+
let entries;
|
|
114222
|
+
try {
|
|
114223
|
+
entries = await readdir18(dirname44(lockPath));
|
|
114224
|
+
} catch (error) {
|
|
114225
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
114226
|
+
return;
|
|
114227
|
+
throw error;
|
|
114228
|
+
}
|
|
114229
|
+
for (const entry of entries) {
|
|
114230
|
+
if (pattern.test(entry))
|
|
114231
|
+
await rm18(join108(dirname44(lockPath), entry), { force: true });
|
|
114232
|
+
}
|
|
114233
|
+
}
|
|
114234
|
+
async function currentRecord(lockPath) {
|
|
114235
|
+
try {
|
|
114236
|
+
return await readFile36(lockPath, "utf8");
|
|
114237
|
+
} catch (error) {
|
|
114238
|
+
if (error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR"))
|
|
114239
|
+
return null;
|
|
114240
|
+
throw error;
|
|
114241
|
+
}
|
|
114242
|
+
}
|
|
114243
|
+
function createLockLease(lockPath, ownerRecord, ownerTag, options = {}) {
|
|
114244
|
+
const staleAfterMs = options.staleAfterMs ?? Number.POSITIVE_INFINITY;
|
|
114245
|
+
let handedTo = null;
|
|
114246
|
+
return {
|
|
114247
|
+
async handOver(pid) {
|
|
114248
|
+
if (handedTo !== null)
|
|
114249
|
+
throw new Error("The lock is already handed over; restore it first.");
|
|
114250
|
+
if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid)
|
|
114251
|
+
throw new Error(`Cannot hand the lock to pid ${pid}.`);
|
|
114252
|
+
if (await currentRecord(lockPath) !== ownerRecord)
|
|
114253
|
+
throw new LockLeaseLostError(lockPath);
|
|
114254
|
+
await removeLeftoverTemps(lockPath);
|
|
114255
|
+
const processStart = await lockProcessStartLine(pid);
|
|
114256
|
+
const record = `${ownerTag} ${randomUUID7()}
|
|
114257
|
+
${pid}
|
|
114258
|
+
${Date.now()}
|
|
114259
|
+
${randomUUID7()}
|
|
114260
|
+
${processStart}
|
|
114261
|
+
`;
|
|
114262
|
+
await replaceRecord(lockPath, record);
|
|
114263
|
+
handedTo = record;
|
|
114264
|
+
},
|
|
114265
|
+
async restore() {
|
|
114266
|
+
if (handedTo === null)
|
|
114267
|
+
throw new Error("The lock is not handed over.");
|
|
114268
|
+
const expected = handedTo;
|
|
114269
|
+
handedTo = null;
|
|
114270
|
+
const outcome = await withRecordGuard(lockPath, expected, staleAfterMs, {}, async () => {
|
|
114271
|
+
if (await currentRecord(lockPath) !== expected)
|
|
114272
|
+
return "lost";
|
|
114273
|
+
await options.beforeRestoreRename?.();
|
|
114274
|
+
await replaceRecord(lockPath, ownerRecord);
|
|
114275
|
+
return "restored";
|
|
114276
|
+
});
|
|
114277
|
+
if (outcome !== "restored")
|
|
114278
|
+
throw new LockLeaseLostError(lockPath);
|
|
114279
|
+
}
|
|
114280
|
+
};
|
|
114281
|
+
}
|
|
114282
|
+
|
|
113437
114283
|
// packages/team-core/src/team-state-store/locks.ts
|
|
113438
114284
|
var LOCK_RETRY_MS = 50;
|
|
113439
114285
|
var LOCK_WAIT_TIMEOUT_MS = 15000;
|
|
@@ -113463,7 +114309,7 @@ async function withLock(lockPath, fn, opts) {
|
|
|
113463
114309
|
const ownerTag = opts?.ownerTag ?? "owner";
|
|
113464
114310
|
const record = await acquireLock(lockPath, ownerTag, staleAfterMs);
|
|
113465
114311
|
try {
|
|
113466
|
-
return await fn();
|
|
114312
|
+
return await fn(createLockLease(lockPath, record, ownerTag, { staleAfterMs }));
|
|
113467
114313
|
} finally {
|
|
113468
114314
|
markLockRecordReleased(record);
|
|
113469
114315
|
const outcome = await removeLockRecordIfUnchanged(lockPath, record, staleAfterMs);
|
|
@@ -113480,20 +114326,382 @@ async function reapStaleLock(lockPath, staleAfterMs = DEFAULT_STALE_AFTER_MS, de
|
|
|
113480
114326
|
return await removeLockRecordIfUnchanged(lockPath, observed.content, staleAfterMs, deps);
|
|
113481
114327
|
}
|
|
113482
114328
|
|
|
114329
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/prompt-lock.ts
|
|
114330
|
+
function promptLockAt(path, hooks = {}) {
|
|
114331
|
+
return async () => {
|
|
114332
|
+
const held = keychainProcessState().heldPromptLocks;
|
|
114333
|
+
if (held.has(path))
|
|
114334
|
+
return null;
|
|
114335
|
+
held.add(path);
|
|
114336
|
+
let granted = false;
|
|
114337
|
+
try {
|
|
114338
|
+
await mkdir11(dirname45(path), { recursive: true, mode: 448 });
|
|
114339
|
+
await hooks.beforePublish?.();
|
|
114340
|
+
for (let attempt = 0;attempt < 2; attempt++) {
|
|
114341
|
+
const record = await buildLockRecord("keychain-prompt");
|
|
114342
|
+
if (await publishLockRecord(path, record)) {
|
|
114343
|
+
granted = true;
|
|
114344
|
+
return async () => {
|
|
114345
|
+
markLockRecordReleased(record);
|
|
114346
|
+
try {
|
|
114347
|
+
await (hooks.removeRecord ?? ((target, owned) => removeLockRecordIfUnchanged(target, owned, Number.POSITIVE_INFINITY)))(path, record);
|
|
114348
|
+
} finally {
|
|
114349
|
+
held.delete(path);
|
|
114350
|
+
}
|
|
114351
|
+
};
|
|
114352
|
+
}
|
|
114353
|
+
if (await reapStaleLock(path, Number.POSITIVE_INFINITY) !== "removed")
|
|
114354
|
+
return null;
|
|
114355
|
+
}
|
|
114356
|
+
return null;
|
|
114357
|
+
} finally {
|
|
114358
|
+
if (!granted)
|
|
114359
|
+
held.delete(path);
|
|
114360
|
+
}
|
|
114361
|
+
};
|
|
114362
|
+
}
|
|
114363
|
+
|
|
114364
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/darwin-backend.ts
|
|
114365
|
+
var ROW_9B_DEFAULT = "reinstall-notice";
|
|
114366
|
+
var helperAccess = () => sharedHelperAccess(() => {
|
|
114367
|
+
const { entryCandidates } = keychainProcessState();
|
|
114368
|
+
return resolveHelperAccess([...entryCandidates, ...bundleCandidates(import.meta.url), ...machineCandidates(homedir31())]);
|
|
114369
|
+
});
|
|
114370
|
+
function sharedHelperAccess(resolve) {
|
|
114371
|
+
const state = keychainProcessState();
|
|
114372
|
+
if (state.helperAccess !== undefined)
|
|
114373
|
+
return state.helperAccess;
|
|
114374
|
+
const started = resolve();
|
|
114375
|
+
state.helperAccess = started;
|
|
114376
|
+
started.then((access) => {
|
|
114377
|
+
if (access.kind === "unavailable" && state.helperAccess === started)
|
|
114378
|
+
state.helperAccess = undefined;
|
|
114379
|
+
}, () => {
|
|
114380
|
+
if (state.helperAccess === started)
|
|
114381
|
+
state.helperAccess = undefined;
|
|
114382
|
+
});
|
|
114383
|
+
return started;
|
|
114384
|
+
}
|
|
114385
|
+
|
|
114386
|
+
class HelperMissingForOwnedItem extends Error {
|
|
114387
|
+
}
|
|
114388
|
+
function asKeystoreError(error, pending) {
|
|
114389
|
+
if (!(error instanceof HelperReadError))
|
|
114390
|
+
return error;
|
|
114391
|
+
if (error.failure === "pending")
|
|
114392
|
+
return pending(error.message);
|
|
114393
|
+
if (error.failure === "locked")
|
|
114394
|
+
return Object.assign(new Error(error.message), { code: "-25308" });
|
|
114395
|
+
return error;
|
|
114396
|
+
}
|
|
114397
|
+
function createDarwinBackend(options) {
|
|
114398
|
+
const silently = options.silently ?? silentSecrets;
|
|
114399
|
+
const key = { service: options.service, name: options.account };
|
|
114400
|
+
const deps = {
|
|
114401
|
+
account: options.account,
|
|
114402
|
+
access: options.access,
|
|
114403
|
+
cache: options.cache ?? processApprovalCache(),
|
|
114404
|
+
background: options.background,
|
|
114405
|
+
takePromptLock: promptLockAt(join109(options.home ?? homedir31(), ".omo", "session-locks", `${options.account}.keychain-prompt`)),
|
|
114406
|
+
ownSilentGet: () => silently(() => options.secrets.get(key)),
|
|
114407
|
+
ownOverwrite: (value) => silently(() => options.secrets.set({ ...key, value })),
|
|
114408
|
+
ownDelete: (name) => name === options.account ? gatedSecrets(() => options.secrets.delete({ ...key, name })) : silently(() => options.secrets.delete({ ...key, name })),
|
|
114409
|
+
notice: options.notice,
|
|
114410
|
+
...options.row8b === undefined ? {} : { row8b: options.row8b },
|
|
114411
|
+
...options.handOff === undefined ? {} : { handOff: options.handOff },
|
|
114412
|
+
noDialog: options.noDialog === true
|
|
114413
|
+
};
|
|
114414
|
+
let unowned = false;
|
|
114415
|
+
return {
|
|
114416
|
+
read: async () => {
|
|
114417
|
+
const result = await readThroughHelper(deps, true);
|
|
114418
|
+
unowned = result.kind === "value" && result.source !== "owned";
|
|
114419
|
+
return result.kind === "value" ? result.value : null;
|
|
114420
|
+
},
|
|
114421
|
+
underLock: (lease) => lockedDarwinStore(deps, lease),
|
|
114422
|
+
migrationPending: () => unowned
|
|
114423
|
+
};
|
|
114424
|
+
}
|
|
114425
|
+
async function guardHelperlessRead(service, account, choice = ROW_9B_DEFAULT, probe = probeOwnerMarker) {
|
|
114426
|
+
if (choice === "dialog")
|
|
114427
|
+
return;
|
|
114428
|
+
if (await probe(service, account) === "helper-owned")
|
|
114429
|
+
throw new HelperMissingForOwnedItem("OmO's keychain helper is missing or damaged on this Mac. Reinstall omo, then try again.");
|
|
114430
|
+
}
|
|
114431
|
+
|
|
114432
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/store-binding.ts
|
|
114433
|
+
import { homedir as homedir32 } from "node:os";
|
|
114434
|
+
|
|
114435
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/creator-handoff.ts
|
|
114436
|
+
init_bun_file_shim();
|
|
114437
|
+
init_bun_spawn_shim();
|
|
114438
|
+
import { dirname as dirname47, posix as posix14 } from "node:path";
|
|
114439
|
+
|
|
114440
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/runtime-capabilities.ts
|
|
114441
|
+
init_zod();
|
|
114442
|
+
import { readFile as readFile37 } from "node:fs/promises";
|
|
114443
|
+
import { dirname as dirname46, join as join110 } from "node:path";
|
|
114444
|
+
var RUNTIME_CAPABILITIES_FILE = "omo-runtime-capabilities.json";
|
|
114445
|
+
var RUNTIME_CAPABILITIES = { keychainHandoff: 1 };
|
|
114446
|
+
var capabilitiesSchema = object({ keychainHandoff: number2().int() }).passthrough();
|
|
114447
|
+
async function runtimeDeclaresKeychainHandoff(runtime) {
|
|
114448
|
+
const text = await readFile37(join110(dirname46(runtime), RUNTIME_CAPABILITIES_FILE), "utf8").catch(() => null);
|
|
114449
|
+
if (text === null)
|
|
114450
|
+
return false;
|
|
114451
|
+
try {
|
|
114452
|
+
const parsed = capabilitiesSchema.safeParse(JSON.parse(text));
|
|
114453
|
+
return parsed.success && parsed.data.keychainHandoff >= RUNTIME_CAPABILITIES.keychainHandoff;
|
|
114454
|
+
} catch {
|
|
114455
|
+
return false;
|
|
114456
|
+
}
|
|
114457
|
+
}
|
|
114458
|
+
|
|
114459
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/creator-handoff.ts
|
|
114460
|
+
var DEVELOPER_ID_TEAM = 'anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] and certificate leaf[field.1.2.840.113635.100.6.1.13] and certificate leaf[subject.OU] = "523JNR86LZ"';
|
|
114461
|
+
var DESKTOP_RUNTIME_REQUIREMENT = `identifier "com.mengmota.omo-desktop-runtime" and ${DEVELOPER_ID_TEAM}`;
|
|
114462
|
+
var DESKTOP_APP_REQUIREMENT = DEVELOPER_ID_TEAM;
|
|
114463
|
+
var HANDOFF_ENV = "OMO_KEYCHAIN_HANDOFF";
|
|
114464
|
+
var HANDOFF_DEADLINE_MS = 45000;
|
|
114465
|
+
function desktopRuntimeCandidates(home, arch = process.arch) {
|
|
114466
|
+
const runtimeArch = arch === "arm64" ? "arm64" : "x64";
|
|
114467
|
+
return ["/Applications/OmO.app", posix14.join(home, "Applications", "OmO.app")].map((app) => ({
|
|
114468
|
+
app,
|
|
114469
|
+
runtime: posix14.join(app, "Contents", "Resources", "omo-runtime", `darwin-${runtimeArch}`, "omo")
|
|
114470
|
+
}));
|
|
114471
|
+
}
|
|
114472
|
+
var verifyBundle = async (app, requirement) => {
|
|
114473
|
+
const child = spawn(["/usr/bin/codesign", "--verify", "--deep", "--strict", `-R=${requirement}`, app], {
|
|
114474
|
+
stdin: "ignore",
|
|
114475
|
+
stdout: "ignore",
|
|
114476
|
+
stderr: "ignore"
|
|
114477
|
+
});
|
|
114478
|
+
return await child.exited === 0;
|
|
114479
|
+
};
|
|
114480
|
+
var runBounded = async (path, args, env, deadlineMs) => {
|
|
114481
|
+
const child = spawn([path, ...args], { cwd: dirname47(path), stdin: "ignore", stdout: "ignore", stderr: "ignore", env });
|
|
114482
|
+
let killed = false;
|
|
114483
|
+
const timer = setTimeout(() => {
|
|
114484
|
+
killed = true;
|
|
114485
|
+
child.kill("SIGKILL");
|
|
114486
|
+
}, deadlineMs);
|
|
114487
|
+
try {
|
|
114488
|
+
const code = await child.exited;
|
|
114489
|
+
return killed ? null : code;
|
|
114490
|
+
} finally {
|
|
114491
|
+
clearTimeout(timer);
|
|
114492
|
+
}
|
|
114493
|
+
};
|
|
114494
|
+
function createCreatorHandOff(options) {
|
|
114495
|
+
return async () => {
|
|
114496
|
+
const env = options.env ?? process.env;
|
|
114497
|
+
if (env[HANDOFF_ENV] === "1")
|
|
114498
|
+
return false;
|
|
114499
|
+
const checkRuntime = options.checkRuntime ?? verifyWithSecurityFramework;
|
|
114500
|
+
const checkBundle = options.checkBundle ?? verifyBundle;
|
|
114501
|
+
const declaresHandOff = options.declaresHandOff ?? runtimeDeclaresKeychainHandoff;
|
|
114502
|
+
const self = options.selfPath ?? process.execPath;
|
|
114503
|
+
for (const { app, runtime } of options.candidates) {
|
|
114504
|
+
if (runtime === self || !await bunFile(runtime).exists())
|
|
114505
|
+
continue;
|
|
114506
|
+
const verified = await Promise.resolve().then(async () => await checkBundle(app, DESKTOP_APP_REQUIREMENT) && await checkRuntime(runtime, DESKTOP_RUNTIME_REQUIREMENT) && await declaresHandOff(runtime)).catch(() => false);
|
|
114507
|
+
if (!verified)
|
|
114508
|
+
continue;
|
|
114509
|
+
const childEnv = { [HANDOFF_ENV]: "1" };
|
|
114510
|
+
if (env.HOME !== undefined)
|
|
114511
|
+
childEnv.HOME = env.HOME;
|
|
114512
|
+
const origin = options.origin ?? env.OMO_SERVICE_API_URL;
|
|
114513
|
+
if (origin !== undefined)
|
|
114514
|
+
childEnv.OMO_SERVICE_API_URL = origin;
|
|
114515
|
+
try {
|
|
114516
|
+
return await (options.run ?? runBounded)(runtime, ["account", "token"], childEnv, HANDOFF_DEADLINE_MS) === 0;
|
|
114517
|
+
} catch {
|
|
114518
|
+
return false;
|
|
114519
|
+
}
|
|
114520
|
+
}
|
|
114521
|
+
return false;
|
|
114522
|
+
};
|
|
114523
|
+
}
|
|
114524
|
+
|
|
114525
|
+
// packages/omo-opencode/src/cli/service-auth/keychain-helper/store-binding.ts
|
|
114526
|
+
var readers = new Map;
|
|
114527
|
+
var INJECTED_SECRETS = Symbol.for("omo.test.injectedSecrets");
|
|
114528
|
+
var isInjectedSecrets = (api) => api[INJECTED_SECRETS] === true;
|
|
114529
|
+
var backends = new Map;
|
|
114530
|
+
function processHandOff(origin) {
|
|
114531
|
+
return () => {
|
|
114532
|
+
const state = keychainProcessState();
|
|
114533
|
+
state.handOff ??= createCreatorHandOff({ candidates: desktopRuntimeCandidates(homedir32()), origin })();
|
|
114534
|
+
return state.handOff;
|
|
114535
|
+
};
|
|
114536
|
+
}
|
|
114537
|
+
function bindKeychainHelper(input) {
|
|
114538
|
+
const { secrets: real, key, options } = input;
|
|
114539
|
+
const eligible = input.platform === "darwin" && input.namespace === "omo-cli" && (options !== undefined || typeof Bun !== "undefined" && real === Bun.secrets && !isInjectedSecrets(real));
|
|
114540
|
+
const secrets = !eligible ? real : {
|
|
114541
|
+
get: (entry) => gatedSecrets(() => real.get(entry)),
|
|
114542
|
+
set: (entry) => gatedSecrets(() => real.set(entry)),
|
|
114543
|
+
delete: (entry) => gatedSecrets(() => real.delete(entry))
|
|
114544
|
+
};
|
|
114545
|
+
const cacheKey = `${key.service}
|
|
114546
|
+
${key.name}
|
|
114547
|
+
${input.background ? "bounded" : "interactive"}`;
|
|
114548
|
+
let own;
|
|
114549
|
+
const backend = () => {
|
|
114550
|
+
if (!eligible)
|
|
114551
|
+
return Promise.resolve(null);
|
|
114552
|
+
const known = options === undefined ? backends.get(cacheKey) : own;
|
|
114553
|
+
if (known !== undefined)
|
|
114554
|
+
return known;
|
|
114555
|
+
const created = (options?.access ?? helperAccess)().then((access) => access.kind !== "ready" ? null : createDarwinBackend({
|
|
114556
|
+
access,
|
|
114557
|
+
secrets: real,
|
|
114558
|
+
service: key.service,
|
|
114559
|
+
account: key.name,
|
|
114560
|
+
background: input.background,
|
|
114561
|
+
noDialog: options?.noDialog ?? process.env[HANDOFF_ENV] === "1",
|
|
114562
|
+
notice: input.notice,
|
|
114563
|
+
...options?.home === undefined ? {} : { home: options.home },
|
|
114564
|
+
...options?.row8b === undefined ? {} : { row8b: options.row8b },
|
|
114565
|
+
...options?.silently === undefined ? {} : { silently: options.silently },
|
|
114566
|
+
...options?.cache === undefined ? {} : { cache: options.cache },
|
|
114567
|
+
handOff: options === undefined ? processHandOff(input.origin) : options.handOff ?? (async () => false)
|
|
114568
|
+
}));
|
|
114569
|
+
if (options === undefined) {
|
|
114570
|
+
backends.set(cacheKey, created);
|
|
114571
|
+
created.then((found) => {
|
|
114572
|
+
if (found === null && backends.get(cacheKey) === created)
|
|
114573
|
+
backends.delete(cacheKey);
|
|
114574
|
+
});
|
|
114575
|
+
} else
|
|
114576
|
+
own = created;
|
|
114577
|
+
return created;
|
|
114578
|
+
};
|
|
114579
|
+
const reader = (helper) => {
|
|
114580
|
+
const known = readers.get(helper);
|
|
114581
|
+
if (known !== undefined)
|
|
114582
|
+
return known;
|
|
114583
|
+
const refuse = async () => {
|
|
114584
|
+
throw new Error("OmO's keychain helper changes the sign-in only under the session lock.");
|
|
114585
|
+
};
|
|
114586
|
+
const created = {
|
|
114587
|
+
get: async () => {
|
|
114588
|
+
try {
|
|
114589
|
+
return await helper.read();
|
|
114590
|
+
} catch (error) {
|
|
114591
|
+
throw asKeystoreError(error, (message) => input.pending(`${message} Credentials are never saved to a file.`));
|
|
114592
|
+
}
|
|
114593
|
+
},
|
|
114594
|
+
set: refuse,
|
|
114595
|
+
delete: refuse
|
|
114596
|
+
};
|
|
114597
|
+
readers.set(helper, created);
|
|
114598
|
+
return created;
|
|
114599
|
+
};
|
|
114600
|
+
return {
|
|
114601
|
+
secrets,
|
|
114602
|
+
eligible,
|
|
114603
|
+
backend,
|
|
114604
|
+
reader,
|
|
114605
|
+
isHelperReader: (api) => [...readers.values()].includes(api),
|
|
114606
|
+
guardHelperless: async () => {
|
|
114607
|
+
if (!eligible)
|
|
114608
|
+
return;
|
|
114609
|
+
if ((options?.noDialog ?? process.env[HANDOFF_ENV] === "1") === true)
|
|
114610
|
+
throw input.pending("The keychain hand-off cannot show a dialog.");
|
|
114611
|
+
await guardHelperlessRead(key.service, key.name, options?.row9b, options?.ownerMarker);
|
|
114612
|
+
}
|
|
114613
|
+
};
|
|
114614
|
+
}
|
|
114615
|
+
function lockedStoreView(helper, lease, codec, mapError, done) {
|
|
114616
|
+
const locked = helper.underLock(lease);
|
|
114617
|
+
const run = async (step) => {
|
|
114618
|
+
try {
|
|
114619
|
+
return await step();
|
|
114620
|
+
} catch (error) {
|
|
114621
|
+
throw mapError(error);
|
|
114622
|
+
} finally {
|
|
114623
|
+
done();
|
|
114624
|
+
}
|
|
114625
|
+
};
|
|
114626
|
+
return {
|
|
114627
|
+
read: () => run(async () => {
|
|
114628
|
+
const text = await locked.read();
|
|
114629
|
+
return text === null ? null : codec.parse(text);
|
|
114630
|
+
}),
|
|
114631
|
+
write: (value, intent = "update", beforeRetire) => run(async () => {
|
|
114632
|
+
const next = codec.amend === undefined ? value : codec.amend(await locked.read(), value);
|
|
114633
|
+
await locked.write(codec.serialize(next), intent, beforeRetire);
|
|
114634
|
+
}),
|
|
114635
|
+
clear: () => run(() => locked.clear()),
|
|
114636
|
+
recover: () => run(() => locked.recover()),
|
|
114637
|
+
settle: () => run(() => locked.settle())
|
|
114638
|
+
};
|
|
114639
|
+
}
|
|
114640
|
+
|
|
114641
|
+
// packages/omo-opencode/src/cli/service-auth/secret-service-lock.ts
|
|
114642
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
114643
|
+
var DEFAULT_COLLECTION = "/org/freedesktop/secrets/aliases/default";
|
|
114644
|
+
var PROBE_TIMEOUT_MS2 = 1e4;
|
|
114645
|
+
var parseLockedReply = (stdout) => {
|
|
114646
|
+
const match = /<\s*(true|false)\s*>/.exec(stdout);
|
|
114647
|
+
if (match === null)
|
|
114648
|
+
return null;
|
|
114649
|
+
return match[1] === "true" ? "locked" : "unlocked";
|
|
114650
|
+
};
|
|
114651
|
+
var probeSecretServiceLock = () => new Promise((resolve) => {
|
|
114652
|
+
const child = spawn5("gdbus", [
|
|
114653
|
+
"call",
|
|
114654
|
+
"--session",
|
|
114655
|
+
"--dest",
|
|
114656
|
+
"org.freedesktop.secrets",
|
|
114657
|
+
"--object-path",
|
|
114658
|
+
DEFAULT_COLLECTION,
|
|
114659
|
+
"--method",
|
|
114660
|
+
"org.freedesktop.DBus.Properties.Get",
|
|
114661
|
+
"org.freedesktop.Secret.Collection",
|
|
114662
|
+
"Locked"
|
|
114663
|
+
], { stdio: ["ignore", "pipe", "ignore"] });
|
|
114664
|
+
let stdout = "";
|
|
114665
|
+
const timer = setTimeout(() => {
|
|
114666
|
+
child.kill();
|
|
114667
|
+
resolve("unknown");
|
|
114668
|
+
}, PROBE_TIMEOUT_MS2);
|
|
114669
|
+
child.stdout.on("data", (chunk) => {
|
|
114670
|
+
stdout += chunk.toString();
|
|
114671
|
+
});
|
|
114672
|
+
child.on("error", () => {
|
|
114673
|
+
clearTimeout(timer);
|
|
114674
|
+
resolve("unknown");
|
|
114675
|
+
});
|
|
114676
|
+
child.on("close", (code) => {
|
|
114677
|
+
clearTimeout(timer);
|
|
114678
|
+
resolve(code === 0 ? parseLockedReply(stdout) ?? "absent" : "absent");
|
|
114679
|
+
});
|
|
114680
|
+
});
|
|
114681
|
+
|
|
113483
114682
|
// packages/omo-opencode/src/cli/service-auth/credential-lock.ts
|
|
114683
|
+
import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
|
|
114684
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
114685
|
+
import { mkdir as mkdir12 } from "node:fs/promises";
|
|
114686
|
+
import { homedir as homedir33 } from "node:os";
|
|
114687
|
+
import { join as join112 } from "node:path";
|
|
113484
114688
|
var held = new AsyncLocalStorage3;
|
|
113485
|
-
function credentialLockPaths(api, home =
|
|
114689
|
+
function credentialLockPaths(api, home = homedir33()) {
|
|
113486
114690
|
const id = createHash11("sha256").update(serviceOrigin(api)).digest("hex");
|
|
113487
|
-
const directory =
|
|
113488
|
-
return { directory, lock:
|
|
114691
|
+
const directory = join112(home, ".omo", "session-locks");
|
|
114692
|
+
return { directory, lock: join112(directory, `${id}.lock`), desktopRecord: join112(directory, `${id}.desktop-generation.json`) };
|
|
114693
|
+
}
|
|
114694
|
+
function heldCredentialLease(api, home = homedir33()) {
|
|
114695
|
+
return held.getStore()?.get(credentialLockPaths(api, home).lock);
|
|
113489
114696
|
}
|
|
113490
|
-
async function withCredentialLock(api, action, home =
|
|
114697
|
+
async function withCredentialLock(api, action, home = homedir33(), ownerTag = "cli-session") {
|
|
113491
114698
|
const { directory, lock } = credentialLockPaths(api, home);
|
|
113492
114699
|
const owned = held.getStore();
|
|
113493
|
-
|
|
113494
|
-
|
|
113495
|
-
|
|
113496
|
-
|
|
114700
|
+
const outer = owned?.get(lock);
|
|
114701
|
+
if (outer !== undefined)
|
|
114702
|
+
return action(outer);
|
|
114703
|
+
await mkdir12(directory, { recursive: true, mode: 448 });
|
|
114704
|
+
return withLock(lock, (lease) => held.run(new Map([...owned ?? [], [lock, lease]]), () => action(lease)), {
|
|
113497
114705
|
ownerTag,
|
|
113498
114706
|
staleAfterMs: Number.POSITIVE_INFINITY
|
|
113499
114707
|
});
|
|
@@ -113545,17 +114753,51 @@ function createCredentialStore(api, options = {}) {
|
|
|
113545
114753
|
return {
|
|
113546
114754
|
...value,
|
|
113547
114755
|
...accountId === undefined ? {} : { accountId },
|
|
113548
|
-
credentialGeneration: sameIdentity ? current?.credentialGeneration ??
|
|
114756
|
+
credentialGeneration: sameIdentity ? current?.credentialGeneration ?? randomUUID8() : randomUUID8()
|
|
113549
114757
|
};
|
|
113550
|
-
});
|
|
114758
|
+
}, options.keychainHelper);
|
|
114759
|
+
const sections = new WeakMap;
|
|
114760
|
+
const underLock = (lease) => {
|
|
114761
|
+
const known = sections.get(lease);
|
|
114762
|
+
if (known !== undefined)
|
|
114763
|
+
return known;
|
|
114764
|
+
const view = (async () => {
|
|
114765
|
+
const opened = await store.underLock?.(lease) ?? null;
|
|
114766
|
+
await opened?.recover();
|
|
114767
|
+
return opened;
|
|
114768
|
+
})();
|
|
114769
|
+
sections.set(lease, view);
|
|
114770
|
+
return view;
|
|
114771
|
+
};
|
|
114772
|
+
const held = async () => {
|
|
114773
|
+
const lease = heldCredentialLease(api, options.home);
|
|
114774
|
+
return lease === undefined ? null : underLock(lease);
|
|
114775
|
+
};
|
|
114776
|
+
const locked = async (helper, plain) => {
|
|
114777
|
+
if (heldCredentialLease(api, options.home) === undefined)
|
|
114778
|
+
await store.prepare?.();
|
|
114779
|
+
await withCredentialLock(api, async (lease) => {
|
|
114780
|
+
const view = await underLock(lease);
|
|
114781
|
+
await (view === null ? plain() : helper(view));
|
|
114782
|
+
}, options.home);
|
|
114783
|
+
};
|
|
113551
114784
|
return {
|
|
113552
|
-
read:
|
|
113553
|
-
|
|
113554
|
-
|
|
113555
|
-
|
|
114785
|
+
read: async () => {
|
|
114786
|
+
const view = await held();
|
|
114787
|
+
return view === null ? store.read() : view.read();
|
|
114788
|
+
},
|
|
114789
|
+
readAuthoritative: async () => {
|
|
114790
|
+
const view = await held();
|
|
114791
|
+
return view === null ? store.readAuthoritative() : view.read();
|
|
114792
|
+
},
|
|
114793
|
+
write: (value, intent, beforeRetire) => locked((view) => view.write(value, intent, beforeRetire), () => store.write(value)),
|
|
114794
|
+
clear: () => locked((view) => view.clear(), store.clear),
|
|
114795
|
+
...store.prepare === undefined ? {} : { prepare: store.prepare },
|
|
114796
|
+
underLock,
|
|
114797
|
+
...store.migrationPending === undefined ? {} : { migrationPending: store.migrationPending }
|
|
113556
114798
|
};
|
|
113557
114799
|
}
|
|
113558
|
-
function createSealedStore(api, namespace, schema, secrets = typeof Bun === "undefined" ? null : Bun.secrets, platform = process.platform, lockProbe = probeSecretServiceLock, notice = stderrNoticeOncePerProcess, wait = SESSION_READ_WAIT, amendWrite) {
|
|
114800
|
+
function createSealedStore(api, namespace, schema, secrets = typeof Bun === "undefined" ? null : Bun.secrets, platform = process.platform, lockProbe = probeSecretServiceLock, notice = stderrNoticeOncePerProcess, wait = SESSION_READ_WAIT, amendWrite, keychainHelper) {
|
|
113559
114801
|
if (!secrets)
|
|
113560
114802
|
throw new SignInError("OmO sign-in needs Bun 1.4 or newer with OS credential storage. No file fallback is available.");
|
|
113561
114803
|
const platformName = platform === "darwin" ? "macOS Keychain" : platform === "linux" ? "Linux Secret Service (libsecret and an unlocked keyring)" : platform === "win32" ? "Windows Credential Manager" : null;
|
|
@@ -113564,6 +114806,18 @@ function createSealedStore(api, namespace, schema, secrets = typeof Bun === "und
|
|
|
113564
114806
|
const key = { service: namespace, name: credentialId(api) };
|
|
113565
114807
|
const slot = `${key.service}
|
|
113566
114808
|
${key.name}`;
|
|
114809
|
+
const helper = bindKeychainHelper({
|
|
114810
|
+
platform,
|
|
114811
|
+
namespace,
|
|
114812
|
+
secrets,
|
|
114813
|
+
key,
|
|
114814
|
+
background: wait.kind === "bounded",
|
|
114815
|
+
origin: api,
|
|
114816
|
+
notice,
|
|
114817
|
+
pending: (message) => new KeychainApprovalPendingError(message),
|
|
114818
|
+
...keychainHelper === undefined ? {} : { options: keychainHelper }
|
|
114819
|
+
});
|
|
114820
|
+
secrets = helper.secrets;
|
|
113567
114821
|
const readsOf = (api) => {
|
|
113568
114822
|
const known = processReads.get(api);
|
|
113569
114823
|
if (known !== undefined)
|
|
@@ -113589,17 +114843,19 @@ ${key.name}`;
|
|
|
113589
114843
|
reads.set(slot, read);
|
|
113590
114844
|
return read;
|
|
113591
114845
|
};
|
|
113592
|
-
const waiting = platform === "darwin" ? `macOS Keychain is waiting for your approval: answer the "${
|
|
114846
|
+
const waiting = platform === "darwin" ? `macOS Keychain is waiting for your approval: answer the "${basename17(process.execPath)} wants to access key ${namespace}" dialog ("Always Allow" stops it asking again)` : `${platformName} has not answered; it may be waiting for your approval or an unlock in a system dialog`;
|
|
114847
|
+
const helperWaiting = `macOS Keychain is waiting for your approval: answer the "OmO's keychain helper wants to access key ${namespace}" dialog`;
|
|
113593
114848
|
const answered = async (api, fresh = false) => {
|
|
114849
|
+
const waitingFor = helper.isHelperReader(api) ? helperWaiting : waiting;
|
|
113594
114850
|
const read = fresh ? Promise.resolve().then(() => api.get(key)) : sharedRead(api);
|
|
113595
114851
|
let timer;
|
|
113596
114852
|
try {
|
|
113597
114853
|
if (wait.kind === "interactive") {
|
|
113598
|
-
timer = setTimeout(() => wait.notice(`omo: ${
|
|
114854
|
+
timer = setTimeout(() => wait.notice(`omo: ${waitingFor}.`), wait.noticeAfterMs);
|
|
113599
114855
|
return await read;
|
|
113600
114856
|
}
|
|
113601
114857
|
const expired = new Promise((_, reject) => {
|
|
113602
|
-
timer = setTimeout(() => reject(new KeychainApprovalPendingError(`${
|
|
114858
|
+
timer = setTimeout(() => reject(new KeychainApprovalPendingError(`${waitingFor}, then try again. Credentials are never saved to a file.`)), wait.deadlineMs);
|
|
113603
114859
|
});
|
|
113604
114860
|
return await Promise.race([read, expired]);
|
|
113605
114861
|
} finally {
|
|
@@ -113624,41 +114880,76 @@ ${key.name}`;
|
|
|
113624
114880
|
notice("omo: could not check whether the keyring is locked (gdbus or the Secret Service did not answer); using libsecret directly.");
|
|
113625
114881
|
}
|
|
113626
114882
|
};
|
|
113627
|
-
const
|
|
114883
|
+
const parseStored = (value) => {
|
|
114884
|
+
try {
|
|
114885
|
+
return schema.parse(JSON.parse(value));
|
|
114886
|
+
} catch {
|
|
114887
|
+
throw new InvalidCredentialState(signInRoute() === "cli" ? "Stored sign-in data is invalid. Run omo account forget, then omo login." : "The OmO sign-in saved on this computer can't be read. Run omo account forget to remove it, then sign in again in the desktop app.");
|
|
114888
|
+
}
|
|
114889
|
+
};
|
|
114890
|
+
const previousOf = (raw) => {
|
|
114891
|
+
if (raw === null)
|
|
114892
|
+
return null;
|
|
114893
|
+
try {
|
|
114894
|
+
return schema.parse(JSON.parse(raw));
|
|
114895
|
+
} catch {
|
|
114896
|
+
return null;
|
|
114897
|
+
}
|
|
114898
|
+
};
|
|
114899
|
+
const rawRead = async (fresh) => {
|
|
113628
114900
|
await assertUsable();
|
|
113629
|
-
|
|
114901
|
+
const backend = await helper.backend();
|
|
113630
114902
|
try {
|
|
113631
|
-
|
|
114903
|
+
if (backend === null)
|
|
114904
|
+
await helper.guardHelperless();
|
|
114905
|
+
return await answered(backend === null ? secrets : helper.reader(backend), fresh);
|
|
113632
114906
|
} catch (error) {
|
|
113633
114907
|
if (error instanceof KeychainApprovalPendingError)
|
|
113634
114908
|
throw error;
|
|
114909
|
+
if (error instanceof HelperMissingForOwnedItem)
|
|
114910
|
+
throw new CredentialStoreError(error.message);
|
|
113635
114911
|
throw unavailable(error);
|
|
113636
114912
|
}
|
|
113637
|
-
|
|
113638
|
-
|
|
113639
|
-
|
|
113640
|
-
|
|
113641
|
-
|
|
113642
|
-
|
|
113643
|
-
|
|
114913
|
+
};
|
|
114914
|
+
const parsedRead = async (fresh) => {
|
|
114915
|
+
const value = await rawRead(fresh);
|
|
114916
|
+
return value === null ? null : parseStored(value);
|
|
114917
|
+
};
|
|
114918
|
+
const lockedFailure = (error) => {
|
|
114919
|
+
const mapped = asKeystoreError(error, (message) => new KeychainApprovalPendingError(message));
|
|
114920
|
+
if (error instanceof HelperOldSlotsFull)
|
|
114921
|
+
return new CredentialStoreError(error.message);
|
|
114922
|
+
if (mapped instanceof KeychainApprovalPendingError || mapped instanceof SignInError)
|
|
114923
|
+
return mapped;
|
|
114924
|
+
if (mapped instanceof Error && mapped.name === "LockLeaseLostError")
|
|
114925
|
+
return mapped;
|
|
114926
|
+
return unavailable(mapped);
|
|
113644
114927
|
};
|
|
113645
114928
|
return {
|
|
113646
114929
|
read: () => parsedRead(false),
|
|
113647
114930
|
readAuthoritative: () => parsedRead(true),
|
|
114931
|
+
async prepare() {
|
|
114932
|
+
if (await helper.backend() !== null)
|
|
114933
|
+
await rawRead(false);
|
|
114934
|
+
},
|
|
114935
|
+
async underLock(lease) {
|
|
114936
|
+
const backend = await helper.backend();
|
|
114937
|
+
if (backend === null)
|
|
114938
|
+
return null;
|
|
114939
|
+
const codec = {
|
|
114940
|
+
parse: parseStored,
|
|
114941
|
+
serialize: (value) => JSON.stringify(schema.parse(value)),
|
|
114942
|
+
...amendWrite === undefined ? {} : { amend: (raw, next) => amendWrite(previousOf(raw), next) }
|
|
114943
|
+
};
|
|
114944
|
+
return lockedStoreView(backend, lease, codec, lockedFailure, () => forget(helper.reader(backend)));
|
|
114945
|
+
},
|
|
114946
|
+
migrationPending: async () => (await helper.backend())?.migrationPending() ?? false,
|
|
113648
114947
|
async write(value) {
|
|
113649
114948
|
await assertUsable();
|
|
114949
|
+
if (await helper.backend() !== null)
|
|
114950
|
+
throw new Error("OmO's keychain helper writes only under the session lock.");
|
|
113650
114951
|
try {
|
|
113651
|
-
|
|
113652
|
-
if (amendWrite !== undefined) {
|
|
113653
|
-
const raw = await answered(secrets, true);
|
|
113654
|
-
let previous = null;
|
|
113655
|
-
if (raw !== null) {
|
|
113656
|
-
try {
|
|
113657
|
-
previous = schema.parse(JSON.parse(raw));
|
|
113658
|
-
} catch {}
|
|
113659
|
-
}
|
|
113660
|
-
next = amendWrite(previous, value);
|
|
113661
|
-
}
|
|
114952
|
+
const next = amendWrite === undefined ? value : amendWrite(previousOf(await answered(secrets, true)), value);
|
|
113662
114953
|
await secrets.set({ ...key, value: JSON.stringify(schema.parse(next)) });
|
|
113663
114954
|
} catch (error) {
|
|
113664
114955
|
throw unavailable(error);
|
|
@@ -113667,6 +114958,8 @@ ${key.name}`;
|
|
|
113667
114958
|
},
|
|
113668
114959
|
async clear() {
|
|
113669
114960
|
await assertUsable();
|
|
114961
|
+
if (await helper.backend() !== null)
|
|
114962
|
+
throw new Error("OmO's keychain helper deletes only under the session lock.");
|
|
113670
114963
|
try {
|
|
113671
114964
|
await secrets.delete(key);
|
|
113672
114965
|
} catch (error) {
|
|
@@ -113778,14 +115071,14 @@ async function loginLoopback(session, options) {
|
|
|
113778
115071
|
|
|
113779
115072
|
// packages/memory-core/src/sync/device-retire.ts
|
|
113780
115073
|
import { createHash as createHash14, randomBytes as randomBytes6 } from "node:crypto";
|
|
113781
|
-
import { join as
|
|
115074
|
+
import { join as join115 } from "node:path";
|
|
113782
115075
|
|
|
113783
115076
|
// packages/memory-core/src/identity/layout.ts
|
|
113784
|
-
import { homedir as
|
|
113785
|
-
import { join as
|
|
115077
|
+
import { homedir as homedir34 } from "node:os";
|
|
115078
|
+
import { join as join113, resolve as resolve31 } from "node:path";
|
|
113786
115079
|
var MEMORY_ROOT_ENV_VAR = "OMO_MEMORY_HOME";
|
|
113787
115080
|
function defaultMemoryRoot() {
|
|
113788
|
-
return
|
|
115081
|
+
return join113(homedir34(), ".omo", "memory");
|
|
113789
115082
|
}
|
|
113790
115083
|
function resolveMemoryRoot(env, cwd) {
|
|
113791
115084
|
const override = env[MEMORY_ROOT_ENV_VAR];
|
|
@@ -113795,13 +115088,13 @@ function resolveMemoryRoot(env, cwd) {
|
|
|
113795
115088
|
return resolve31(cwd, override);
|
|
113796
115089
|
}
|
|
113797
115090
|
// packages/memory-core/src/sync/pin-dir.ts
|
|
113798
|
-
import { join as
|
|
113799
|
-
var syncPinDir = (memoryRoot) =>
|
|
115091
|
+
import { join as join114 } from "node:path";
|
|
115092
|
+
var syncPinDir = (memoryRoot) => join114(memoryRoot, "sync-device");
|
|
113800
115093
|
|
|
113801
115094
|
// packages/memory-core/src/sync/device-retire.ts
|
|
113802
|
-
var trustAnchorRoot = (pinDir) =>
|
|
115095
|
+
var trustAnchorRoot = (pinDir) => join115(pinDir, "trust-anchor");
|
|
113803
115096
|
var trustAnchorKey = (account) => createHash14("sha256").update(account, "utf8").digest("base64url");
|
|
113804
|
-
var trustAnchorDir = (pinDir, account) =>
|
|
115097
|
+
var trustAnchorDir = (pinDir, account) => join115(trustAnchorRoot(pinDir), trustAnchorKey(account));
|
|
113805
115098
|
var hasLiveTrustAnchor = async (pinDir) => {
|
|
113806
115099
|
try {
|
|
113807
115100
|
return (await readdir17(trustAnchorRoot(pinDir))).some((name) => !name.includes(".retired-"));
|
|
@@ -113822,16 +115115,16 @@ var retireSyncDevice = async (input) => {
|
|
|
113822
115115
|
};
|
|
113823
115116
|
|
|
113824
115117
|
// packages/omo-opencode/src/cli/service-auth/session.ts
|
|
113825
|
-
import { homedir as
|
|
115118
|
+
import { homedir as homedir35 } from "node:os";
|
|
113826
115119
|
|
|
113827
115120
|
// packages/omo-opencode/src/cli/service-auth/signed-out-marker.ts
|
|
113828
115121
|
init_zod();
|
|
113829
|
-
import { mkdir as
|
|
113830
|
-
import { dirname as
|
|
115122
|
+
import { mkdir as mkdir13, readFile as readFile38, rename as rename10, rm as rm19, writeFile as writeFile18 } from "node:fs/promises";
|
|
115123
|
+
import { dirname as dirname48, join as join116 } from "node:path";
|
|
113831
115124
|
var markerSchema = object({ device: string2().nullable(), at: string2() });
|
|
113832
|
-
var signedOutMarkerPath = (home, credential) =>
|
|
115125
|
+
var signedOutMarkerPath = (home, credential) => join116(home, ".omo", "account-state", `${credential}.signed-out.json`);
|
|
113833
115126
|
async function readSignedOutMarker(path) {
|
|
113834
|
-
const text = await
|
|
115127
|
+
const text = await readFile38(path, "utf8").catch(() => null);
|
|
113835
115128
|
if (text === null)
|
|
113836
115129
|
return null;
|
|
113837
115130
|
let value;
|
|
@@ -113844,12 +115137,12 @@ async function readSignedOutMarker(path) {
|
|
|
113844
115137
|
return parsed.success ? parsed.data : null;
|
|
113845
115138
|
}
|
|
113846
115139
|
async function writeSignedOutMarker(path, device) {
|
|
113847
|
-
await
|
|
115140
|
+
await mkdir13(dirname48(path), { recursive: true, mode: 448 });
|
|
113848
115141
|
const staging = `${path}.${process.pid}.tmp`;
|
|
113849
|
-
await
|
|
113850
|
-
await
|
|
115142
|
+
await writeFile18(staging, JSON.stringify({ device, at: new Date().toISOString() }), { mode: 384 });
|
|
115143
|
+
await rename10(staging, path);
|
|
113851
115144
|
}
|
|
113852
|
-
var clearSignedOutMarker = (path) =>
|
|
115145
|
+
var clearSignedOutMarker = (path) => rm19(path, { force: true });
|
|
113853
115146
|
|
|
113854
115147
|
// packages/omo-opencode/src/cli/service-auth/session.ts
|
|
113855
115148
|
class SessionEnded extends SignInError {
|
|
@@ -113873,12 +115166,14 @@ function createSession(options) {
|
|
|
113873
115166
|
const api = serviceOrigin(options.api);
|
|
113874
115167
|
const now = options.now ?? Date.now;
|
|
113875
115168
|
const { store, signal, beforeKeysDiscarded } = options;
|
|
113876
|
-
const markerPath = signedOutMarkerPath(options.home ??
|
|
115169
|
+
const markerPath = signedOutMarkerPath(options.home ?? homedir35(), credentialId(api));
|
|
113877
115170
|
async function locked(action) {
|
|
113878
115171
|
signal?.throwIfAborted();
|
|
113879
|
-
|
|
115172
|
+
if (heldCredentialLease(api, options.home) === undefined)
|
|
115173
|
+
await store.prepare?.();
|
|
115174
|
+
return withCredentialLock(api, async (lease) => {
|
|
113880
115175
|
signal?.throwIfAborted();
|
|
113881
|
-
return action();
|
|
115176
|
+
return action(await store.underLock?.(lease) ?? null);
|
|
113882
115177
|
}, options.home);
|
|
113883
115178
|
}
|
|
113884
115179
|
const request = (path, init) => requestApi(api, path, init, signal);
|
|
@@ -113915,9 +115210,12 @@ function createSession(options) {
|
|
|
113915
115210
|
}
|
|
113916
115211
|
}
|
|
113917
115212
|
async function snapshot() {
|
|
113918
|
-
return locked(async () => {
|
|
115213
|
+
return locked(async (view) => {
|
|
113919
115214
|
const current = await store.read();
|
|
113920
|
-
|
|
115215
|
+
if (current === null)
|
|
115216
|
+
return null;
|
|
115217
|
+
await view?.settle();
|
|
115218
|
+
return refreshed(current);
|
|
113921
115219
|
});
|
|
113922
115220
|
}
|
|
113923
115221
|
return {
|
|
@@ -113940,7 +115238,7 @@ function createSession(options) {
|
|
|
113940
115238
|
}
|
|
113941
115239
|
if (stored !== null && stored.device.id !== value.device.id)
|
|
113942
115240
|
await beforeKeysDiscarded(discardedOf(stored, "replaced"));
|
|
113943
|
-
await store.write(value);
|
|
115241
|
+
await store.write(value, "fresh-sign-in", () => beforeKeysDiscarded({ kind: "unreadable" }));
|
|
113944
115242
|
await clearSignedOutMarker(markerPath);
|
|
113945
115243
|
});
|
|
113946
115244
|
},
|
|
@@ -114001,14 +115299,15 @@ function createSession(options) {
|
|
|
114001
115299
|
signal?.throwIfAborted();
|
|
114002
115300
|
const snapshot = await store.read();
|
|
114003
115301
|
signal?.throwIfAborted();
|
|
114004
|
-
if (snapshot !== null && snapshot.refreshState !== "uncertain" && snapshot.refreshAttempt === undefined && Date.parse(snapshot.accessTokenExpiresAt) > now() + 30000 && (expect === undefined || expect(snapshot)))
|
|
115302
|
+
if (snapshot !== null && snapshot.refreshState !== "uncertain" && snapshot.refreshAttempt === undefined && Date.parse(snapshot.accessTokenExpiresAt) > now() + 30000 && (expect === undefined || expect(snapshot)) && !await store.migrationPending?.())
|
|
114005
115303
|
return snapshot.accessToken;
|
|
114006
|
-
return locked(async () => {
|
|
115304
|
+
return locked(async (view) => {
|
|
114007
115305
|
const current = await store.readAuthoritative();
|
|
114008
115306
|
if (current === null)
|
|
114009
115307
|
throw new SignInError(`Not signed in. ${signInHint("first")}`);
|
|
114010
115308
|
if (expect !== undefined && !expect(current))
|
|
114011
115309
|
throw new CredentialIdentityChanged;
|
|
115310
|
+
await view?.settle();
|
|
114012
115311
|
return (await refreshed(current)).accessToken;
|
|
114013
115312
|
});
|
|
114014
115313
|
},
|
|
@@ -114156,6 +115455,10 @@ function refuseClosedServiceAuth() {
|
|
|
114156
115455
|
}
|
|
114157
115456
|
function configureClosedServiceAuthCommands(program) {
|
|
114158
115457
|
for (const name of SERVICE_AUTH_COMMANDS) {
|
|
115458
|
+
if (name === "login") {
|
|
115459
|
+
configureClosedDeviceLogin(program);
|
|
115460
|
+
continue;
|
|
115461
|
+
}
|
|
114159
115462
|
const command = program.command(name, { hidden: true }).helpOption(false).allowUnknownOption().allowExcessArguments().action(() => {
|
|
114160
115463
|
console.error(SERVICE_ACCOUNTS_CLOSED_MESSAGE);
|
|
114161
115464
|
process.exitCode = 1;
|
|
@@ -114163,6 +115466,17 @@ function configureClosedServiceAuthCommands(program) {
|
|
|
114163
115466
|
command.help = refuseClosedServiceAuth;
|
|
114164
115467
|
}
|
|
114165
115468
|
}
|
|
115469
|
+
function configureClosedDeviceLogin(program) {
|
|
115470
|
+
const command = program.command("login", { hidden: true }).helpOption(false).allowUnknownOption().allowExcessArguments().option("--device").option("--no-browser").option("--api <url>").action((options) => {
|
|
115471
|
+
if (options.device !== true && options.browser !== false || command.args.length > 0) {
|
|
115472
|
+
console.error(SERVICE_ACCOUNTS_CLOSED_MESSAGE);
|
|
115473
|
+
process.exitCode = 1;
|
|
115474
|
+
return;
|
|
115475
|
+
}
|
|
115476
|
+
return run2("login", { ...options, device: true });
|
|
115477
|
+
});
|
|
115478
|
+
command.help = refuseClosedServiceAuth;
|
|
115479
|
+
}
|
|
114166
115480
|
function configureServiceAuthCommands(program, open = serviceAccountsOpen()) {
|
|
114167
115481
|
if (!open) {
|
|
114168
115482
|
configureClosedServiceAuthCommands(program);
|
|
@@ -114364,11 +115678,11 @@ async function boulder(options) {
|
|
|
114364
115678
|
// packages/omo-opencode/src/cli/codex-ulw-loop.ts
|
|
114365
115679
|
import { spawn as spawn6 } from "node:child_process";
|
|
114366
115680
|
import { existsSync as existsSync67, readFileSync as readFileSync45, realpathSync as realpathSync14 } from "node:fs";
|
|
114367
|
-
import { homedir as
|
|
115681
|
+
import { homedir as homedir36 } from "node:os";
|
|
114368
115682
|
var ULW_LOOP_DELEGATION_SENTINEL = "OMO_ULW_LOOP_DELEGATED";
|
|
114369
115683
|
function resolveCodexUlwLoopCommand(input = {}) {
|
|
114370
115684
|
const env = input.env ?? process.env;
|
|
114371
|
-
const homeDir = input.homeDir ??
|
|
115685
|
+
const homeDir = input.homeDir ?? homedir36();
|
|
114372
115686
|
const localComponentBin = resolveLocalUlwLoopBin(env, homeDir);
|
|
114373
115687
|
if (localComponentBin !== null)
|
|
114374
115688
|
return { executable: localComponentBin, argsPrefix: [] };
|
|
@@ -114611,7 +115925,7 @@ function linkedWorktrees(records) {
|
|
|
114611
115925
|
}
|
|
114612
115926
|
// packages/omo-opencode/src/cli/worktree-sweep/sweep.ts
|
|
114613
115927
|
import { existsSync as existsSync68 } from "node:fs";
|
|
114614
|
-
import { stat as
|
|
115928
|
+
import { stat as stat12 } from "node:fs/promises";
|
|
114615
115929
|
import os7 from "node:os";
|
|
114616
115930
|
import { normalize as normalize2 } from "node:path";
|
|
114617
115931
|
|
|
@@ -114694,7 +116008,7 @@ async function isOlderThan(worktreePath, days, now) {
|
|
|
114694
116008
|
if (days <= 0)
|
|
114695
116009
|
return false;
|
|
114696
116010
|
try {
|
|
114697
|
-
const stats = await
|
|
116011
|
+
const stats = await stat12(worktreePath);
|
|
114698
116012
|
return now - stats.mtimeMs > days * DAY_MS;
|
|
114699
116013
|
} catch {
|
|
114700
116014
|
return false;
|
|
@@ -114859,7 +116173,7 @@ prunes.
|
|
|
114859
116173
|
|
|
114860
116174
|
// packages/omo-opencode/src/cli/config-migrate.ts
|
|
114861
116175
|
init_startup_migration();
|
|
114862
|
-
import { posix as
|
|
116176
|
+
import { posix as posix15 } from "node:path";
|
|
114863
116177
|
function reports(result) {
|
|
114864
116178
|
return result.results.map((entry) => ({
|
|
114865
116179
|
diagnostics: entry.diagnostics,
|
|
@@ -114893,7 +116207,7 @@ function runConfigMigrate(options = {}) {
|
|
|
114893
116207
|
dryRun: options.dryRun ?? false,
|
|
114894
116208
|
environment,
|
|
114895
116209
|
...homeDir === undefined ? {} : { env: { HOME: homeDir }, homeDir },
|
|
114896
|
-
pathOperations:
|
|
116210
|
+
pathOperations: posix15
|
|
114897
116211
|
});
|
|
114898
116212
|
const report = reports(result);
|
|
114899
116213
|
const response = {
|