omo-ai 0.0.0-beta.0 → 5.0.0-0.beta.2
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/bin/lib/child-process.js +18 -0
- package/bin/lib/doctor.js +87 -0
- package/bin/lib/launcher.js +69 -0
- package/bin/lib/package-paths.js +39 -0
- package/bin/lib/provider-map.json +55 -0
- package/bin/lib/setup-detect.js +167 -0
- package/bin/lib/setup-import.js +231 -0
- package/bin/lib/setup-models.js +26 -0
- package/bin/lib/setup-report.js +28 -0
- package/bin/omo-agent-toolkit.js +14 -0
- package/bin/omo.js +11 -0
- package/package.json +20 -5
- package/plugin/LICENSE +22 -0
- package/plugin/NOTICE +5 -0
- package/plugin/README.md +59 -0
- package/plugin/extensions/omo-member.js +76 -0
- package/plugin/extensions/omo.js +2263 -0
- package/plugin/extensions/reflection-persona.md +206 -0
- package/plugin/package.json +31 -0
- package/plugin/runtime/agent-toolkit/cli.js +14 -0
- package/plugin/runtime/agent-toolkit/directive.md +471 -0
- package/plugin/runtime/agent-toolkit/omo-agent-toolkit +2 -0
- package/plugin/runtime/agent-toolkit/omo-agent-toolkit.cmd +2 -0
- package/plugin/runtime/agent-toolkit/ulw-loop/cli.js +3455 -0
- package/plugin/runtime/ast-grep-mcp/cli.js +2424 -0
- package/plugin/runtime/ast-grep-mcp/manifest.json +5 -0
- package/plugin/runtime/lsp-daemon/dist/.omo-runtime-manifest.json +155 -0
- package/plugin/runtime/lsp-daemon/dist/cli.d.ts +2 -0
- package/plugin/runtime/lsp-daemon/dist/cli.js +6756 -0
- package/plugin/runtime/lsp-daemon/dist/client.d.ts +105 -0
- package/plugin/runtime/lsp-daemon/dist/client.js +6097 -0
- package/plugin/runtime/lsp-daemon/dist/daemon-client.d.ts +14 -0
- package/plugin/runtime/lsp-daemon/dist/daemon-client.js +189 -0
- package/plugin/runtime/lsp-daemon/dist/daemon-failure-result.d.ts +3 -0
- package/plugin/runtime/lsp-daemon/dist/daemon-failure-result.js +38 -0
- package/plugin/runtime/lsp-daemon/dist/daemon-request-error.d.ts +14 -0
- package/plugin/runtime/lsp-daemon/dist/daemon-request-error.js +26 -0
- package/plugin/runtime/lsp-daemon/dist/daemon-server.d.ts +13 -0
- package/plugin/runtime/lsp-daemon/dist/daemon-server.js +135 -0
- package/plugin/runtime/lsp-daemon/dist/ensure-daemon.d.ts +25 -0
- package/plugin/runtime/lsp-daemon/dist/ensure-daemon.js +200 -0
- package/plugin/runtime/lsp-daemon/dist/index.d.ts +5 -0
- package/plugin/runtime/lsp-daemon/dist/index.js +6182 -0
- package/plugin/runtime/lsp-daemon/dist/ipc-protocol.d.ts +46 -0
- package/plugin/runtime/lsp-daemon/dist/ipc-protocol.js +187 -0
- package/plugin/runtime/lsp-daemon/dist/lock.d.ts +7 -0
- package/plugin/runtime/lsp-daemon/dist/lock.js +71 -0
- package/plugin/runtime/lsp-daemon/dist/ownership.d.ts +49 -0
- package/plugin/runtime/lsp-daemon/dist/ownership.js +168 -0
- package/plugin/runtime/lsp-daemon/dist/package.json +6 -0
- package/plugin/runtime/lsp-daemon/dist/paths.d.ts +36 -0
- package/plugin/runtime/lsp-daemon/dist/paths.js +93 -0
- package/plugin/runtime/lsp-daemon/dist/proxy.d.ts +18 -0
- package/plugin/runtime/lsp-daemon/dist/proxy.js +146 -0
- package/plugin/runtime/lsp-daemon/dist/request-routing.d.ts +14 -0
- package/plugin/runtime/lsp-daemon/dist/request-routing.js +91 -0
- package/plugin/runtime/lsp-daemon/dist/run-daemon.d.ts +1 -0
- package/plugin/runtime/lsp-daemon/dist/run-daemon.js +18 -0
- package/plugin/runtime/lsp-daemon/dist/runtime-contract.d.ts +21 -0
- package/plugin/runtime/lsp-daemon/dist/runtime-contract.js +58 -0
- package/plugin/runtime/lsp-daemon/dist/socket-jsonrpc.d.ts +5 -0
- package/plugin/runtime/lsp-daemon/dist/socket-jsonrpc.js +30 -0
- package/plugin/runtime/lsp-daemon/dist/version-reap.d.ts +26 -0
- package/plugin/runtime/lsp-daemon/dist/version-reap.js +182 -0
- package/plugin/scripts/install.mjs +360 -0
- package/plugin/skills/ast-grep/LICENSE +21 -0
- package/plugin/skills/ast-grep/README.md +136 -0
- package/plugin/skills/ast-grep/SKILL.md +272 -0
- package/plugin/skills/ast-grep/SOURCE +1 -0
- package/plugin/skills/ast-grep/install.ps1 +235 -0
- package/plugin/skills/ast-grep/install.sh +286 -0
- package/plugin/skills/ast-grep/references/cli.md +231 -0
- package/plugin/skills/ast-grep/references/install.md +166 -0
- package/plugin/skills/ast-grep/references/patterns.md +147 -0
- package/plugin/skills/ast-grep/references/pitfalls.md +303 -0
- package/plugin/skills/ast-grep/references/recipes.md +402 -0
- package/plugin/skills/ast-grep/references/sgconfig.md +248 -0
- package/plugin/skills/ast-grep/references/yaml-rules.md +509 -0
- package/plugin/skills/ast-grep/scripts/ast_grep_helper.py +748 -0
- package/plugin/skills/ast-grep/tests/smoke.ps1 +123 -0
- package/plugin/skills/ast-grep/tests/smoke.sh +212 -0
- package/plugin/skills/coding-agent-sessions/SKILL.md +132 -0
- package/plugin/skills/coding-agent-sessions/references/all-platforms.md +75 -0
- package/plugin/skills/coding-agent-sessions/references/claude.md +32 -0
- package/plugin/skills/coding-agent-sessions/references/codex.md +30 -0
- package/plugin/skills/coding-agent-sessions/references/opencode.md +43 -0
- package/plugin/skills/coding-agent-sessions/references/senpi.md +27 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/__init__.py +1 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/aside_scanner.py +140 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/claude.py +66 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/cli.py +283 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/codex.py +105 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/file_scanners.py +275 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/jsonio.py +55 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/kiro_scanner.py +91 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/opencode.py +289 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +104 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/sqlite_optional_scanners.py +203 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/sqlite_scanners.py +177 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/timeparse.py +51 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/transcript.py +149 -0
- package/plugin/skills/coding-agent-sessions/scripts/agent_sessions/types.py +57 -0
- package/plugin/skills/coding-agent-sessions/scripts/find-agent-sessions.py +19 -0
- package/plugin/skills/data-scientist/SKILL.md +243 -0
- package/plugin/skills/data-scientist/references/common-scenarios.md +176 -0
- package/plugin/skills/data-scientist/references/execution-templates.md +197 -0
- package/plugin/skills/data-scientist/references/integration-patterns.md +153 -0
- package/plugin/skills/data-scientist/references/performance-benchmarks.md +37 -0
- package/plugin/skills/data-scientist/references/uv-setup.md +78 -0
- package/plugin/skills/data-scientist/scripts/quick-query.py +111 -0
- package/plugin/skills/data-scientist/scripts/setup-uv.ps1 +53 -0
- package/plugin/skills/data-scientist/scripts/setup-uv.sh +60 -0
- package/plugin/skills/debugging/SKILL.md +117 -0
- package/plugin/skills/debugging/references/methodology/00-setup.md +108 -0
- package/plugin/skills/debugging/references/methodology/02-investigate.md +146 -0
- package/plugin/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
- package/plugin/skills/debugging/references/methodology/04-oracle-triple.md +152 -0
- package/plugin/skills/debugging/references/methodology/05-escalate.md +69 -0
- package/plugin/skills/debugging/references/methodology/06-fix.md +122 -0
- package/plugin/skills/debugging/references/methodology/08-qa.md +94 -0
- package/plugin/skills/debugging/references/methodology/09-cleanup.md +164 -0
- package/plugin/skills/debugging/references/methodology/partial-runtime-evidence.md +245 -0
- package/plugin/skills/debugging/references/runtimes/bundled-js-binary.md +415 -0
- package/plugin/skills/debugging/references/runtimes/go.md +252 -0
- package/plugin/skills/debugging/references/runtimes/native-binary.md +484 -0
- package/plugin/skills/debugging/references/runtimes/node.md +260 -0
- package/plugin/skills/debugging/references/runtimes/python.md +248 -0
- package/plugin/skills/debugging/references/runtimes/rust.md +234 -0
- package/plugin/skills/debugging/references/tools/ghidra.md +212 -0
- package/plugin/skills/debugging/references/tools/playwright-cli.md +194 -0
- package/plugin/skills/debugging/references/tools/pwndbg.md +263 -0
- package/plugin/skills/debugging/references/tools/pwntools.md +265 -0
- package/plugin/skills/frontend/ATTRIBUTION.md +225 -0
- package/plugin/skills/frontend/LICENSE-Apache-2.0.txt +201 -0
- package/plugin/skills/frontend/SKILL.md +147 -0
- package/plugin/skills/frontend/references/design/README.md +253 -0
- package/plugin/skills/frontend/references/design/_INDEX.md +204 -0
- package/plugin/skills/frontend/references/design/airbnb.md +393 -0
- package/plugin/skills/frontend/references/design/airtable.md +92 -0
- package/plugin/skills/frontend/references/design/apple.md +250 -0
- package/plugin/skills/frontend/references/design/aside.md +209 -0
- package/plugin/skills/frontend/references/design/binance.md +348 -0
- package/plugin/skills/frontend/references/design/bmw.md +183 -0
- package/plugin/skills/frontend/references/design/brutalist-skill.md +92 -0
- package/plugin/skills/frontend/references/design/bugatti.md +271 -0
- package/plugin/skills/frontend/references/design/cal.md +262 -0
- package/plugin/skills/frontend/references/design/claude.md +315 -0
- package/plugin/skills/frontend/references/design/clay.md +307 -0
- package/plugin/skills/frontend/references/design/clickhouse.md +284 -0
- package/plugin/skills/frontend/references/design/clone-from-url.md +65 -0
- package/plugin/skills/frontend/references/design/cohere.md +269 -0
- package/plugin/skills/frontend/references/design/coinbase.md +132 -0
- package/plugin/skills/frontend/references/design/composio.md +310 -0
- package/plugin/skills/frontend/references/design/cursor.md +312 -0
- package/plugin/skills/frontend/references/design/design-system-architecture.md +244 -0
- package/plugin/skills/frontend/references/design/elevenlabs.md +268 -0
- package/plugin/skills/frontend/references/design/expo.md +284 -0
- package/plugin/skills/frontend/references/design/ferrari.md +317 -0
- package/plugin/skills/frontend/references/design/figma.md +223 -0
- package/plugin/skills/frontend/references/design/framer.md +249 -0
- package/plugin/skills/frontend/references/design/gpt-tasteskill.md +74 -0
- package/plugin/skills/frontend/references/design/hashicorp.md +281 -0
- package/plugin/skills/frontend/references/design/ibm.md +335 -0
- package/plugin/skills/frontend/references/design/image-to-code-skill.md +1228 -0
- package/plugin/skills/frontend/references/design/imagegen-brandkit.md +798 -0
- package/plugin/skills/frontend/references/design/imagegen-frontend-mobile.md +1465 -0
- package/plugin/skills/frontend/references/design/imagegen-frontend-web.md +987 -0
- package/plugin/skills/frontend/references/design/interaction-skill.md +144 -0
- package/plugin/skills/frontend/references/design/intercom.md +149 -0
- package/plugin/skills/frontend/references/design/kraken.md +128 -0
- package/plugin/skills/frontend/references/design/lamborghini.md +291 -0
- package/plugin/skills/frontend/references/design/layout-skill.md +107 -0
- package/plugin/skills/frontend/references/design/lazyweb.md +77 -0
- package/plugin/skills/frontend/references/design/linear.app.md +370 -0
- package/plugin/skills/frontend/references/design/lovable.md +301 -0
- package/plugin/skills/frontend/references/design/mastercard.md +368 -0
- package/plugin/skills/frontend/references/design/meta.md +369 -0
- package/plugin/skills/frontend/references/design/minimalist-skill.md +85 -0
- package/plugin/skills/frontend/references/design/minimax.md +260 -0
- package/plugin/skills/frontend/references/design/mintlify.md +329 -0
- package/plugin/skills/frontend/references/design/miro.md +111 -0
- package/plugin/skills/frontend/references/design/mistral.ai.md +264 -0
- package/plugin/skills/frontend/references/design/mongodb.md +269 -0
- package/plugin/skills/frontend/references/design/nike.md +366 -0
- package/plugin/skills/frontend/references/design/notion.md +312 -0
- package/plugin/skills/frontend/references/design/nvidia.md +296 -0
- package/plugin/skills/frontend/references/design/ollama.md +270 -0
- package/plugin/skills/frontend/references/design/opencode.ai.md +284 -0
- package/plugin/skills/frontend/references/design/output-skill.md +49 -0
- package/plugin/skills/frontend/references/design/pinterest.md +233 -0
- package/plugin/skills/frontend/references/design/playstation.md +367 -0
- package/plugin/skills/frontend/references/design/posthog.md +259 -0
- package/plugin/skills/frontend/references/design/raycast.md +271 -0
- package/plugin/skills/frontend/references/design/react-dev-tooling-skill.md +230 -0
- package/plugin/skills/frontend/references/design/redesign-skill.md +178 -0
- package/plugin/skills/frontend/references/design/renault.md +314 -0
- package/plugin/skills/frontend/references/design/replicate.md +264 -0
- package/plugin/skills/frontend/references/design/resend.md +306 -0
- package/plugin/skills/frontend/references/design/revolut.md +188 -0
- package/plugin/skills/frontend/references/design/runwayml.md +247 -0
- package/plugin/skills/frontend/references/design/sanity.md +360 -0
- package/plugin/skills/frontend/references/design/sentry.md +265 -0
- package/plugin/skills/frontend/references/design/shopify.md +353 -0
- package/plugin/skills/frontend/references/design/soft-skill.md +98 -0
- package/plugin/skills/frontend/references/design/spacex.md +197 -0
- package/plugin/skills/frontend/references/design/spotify.md +249 -0
- package/plugin/skills/frontend/references/design/starbucks.md +583 -0
- package/plugin/skills/frontend/references/design/stitch-design-example.md +121 -0
- package/plugin/skills/frontend/references/design/stitch-skill.md +184 -0
- package/plugin/skills/frontend/references/design/stripe.md +325 -0
- package/plugin/skills/frontend/references/design/supabase.md +258 -0
- package/plugin/skills/frontend/references/design/superhuman.md +255 -0
- package/plugin/skills/frontend/references/design/taste-skill.md +1206 -0
- package/plugin/skills/frontend/references/design/tesla.md +289 -0
- package/plugin/skills/frontend/references/design/theverge.md +342 -0
- package/plugin/skills/frontend/references/design/together.ai.md +266 -0
- package/plugin/skills/frontend/references/design/uber.md +298 -0
- package/plugin/skills/frontend/references/design/vercel.md +313 -0
- package/plugin/skills/frontend/references/design/vodafone.md +426 -0
- package/plugin/skills/frontend/references/design/voltagent.md +326 -0
- package/plugin/skills/frontend/references/design/warp.md +256 -0
- package/plugin/skills/frontend/references/design/webflow.md +95 -0
- package/plugin/skills/frontend/references/design/wired.md +281 -0
- package/plugin/skills/frontend/references/design/wise.md +176 -0
- package/plugin/skills/frontend/references/design/x.ai.md +260 -0
- package/plugin/skills/frontend/references/design/zapier.md +331 -0
- package/plugin/skills/frontend/references/designpowers/EVIDENCE.md +97 -0
- package/plugin/skills/frontend/references/designpowers/README.md +48 -0
- package/plugin/skills/frontend/references/designpowers/UPSTREAM.md +80 -0
- package/plugin/skills/frontend/references/designpowers/lane-a-direction.md +64 -0
- package/plugin/skills/frontend/references/designpowers/lane-b-execution.md +65 -0
- package/plugin/skills/frontend/references/designpowers/lane-c-review.md +65 -0
- package/plugin/skills/frontend/references/designpowers/lane-d-memory.md +83 -0
- package/plugin/skills/frontend/references/designpowers/orchestration.md +80 -0
- package/plugin/skills/frontend/references/designpowers/routing.md +79 -0
- package/plugin/skills/frontend/references/designpowers/vendor/LICENSE +21 -0
- package/plugin/skills/frontend/references/designpowers/vendor/agents/accessibility-reviewer.md +83 -0
- package/plugin/skills/frontend/references/designpowers/vendor/agents/content-writer.md +132 -0
- package/plugin/skills/frontend/references/designpowers/vendor/agents/design-builder.md +109 -0
- package/plugin/skills/frontend/references/designpowers/vendor/agents/design-critic.md +89 -0
- package/plugin/skills/frontend/references/designpowers/vendor/agents/design-lead.md +113 -0
- package/plugin/skills/frontend/references/designpowers/vendor/agents/design-scout.md +78 -0
- package/plugin/skills/frontend/references/designpowers/vendor/agents/design-strategist.md +121 -0
- package/plugin/skills/frontend/references/designpowers/vendor/agents/heuristic-evaluator.md +268 -0
- package/plugin/skills/frontend/references/designpowers/vendor/agents/inspiration-scout.md +107 -0
- package/plugin/skills/frontend/references/designpowers/vendor/agents/motion-designer.md +120 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/accessible-content/reference.md +101 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/adaptive-interfaces/reference.md +109 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/cognitive-accessibility/reference.md +107 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/design-debate/reference.md +199 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/design-debt-tracker/reference.md +174 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/design-handoff/reference.md +125 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/design-md/reference.md +106 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/design-retrospective/reference.md +266 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/design-review/reference.md +123 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/design-system-alignment/reference.md +120 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/designpowers-critique/reference.md +164 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/heuristic-evaluation/reference.md +85 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/inclusive-personas/reference.md +98 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/inspiration-scouting/reference.md +165 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/interaction-design/reference.md +122 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/motion-choreography/reference.md +81 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/research-planning/reference.md +96 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/responsive-patterns/reference.md +77 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/synthetic-user-testing/reference.md +192 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/taste-feedback/reference.md +165 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/taste-report/reference.md +78 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/token-architecture/reference.md +75 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/ui-composition/reference.md +117 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/usability-testing/reference.md +78 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/verification-before-shipping/reference.md +125 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/voice-and-tone/reference.md +79 -0
- package/plugin/skills/frontend/references/designpowers/vendor/skills/writing-design-plans/reference.md +119 -0
- package/plugin/skills/frontend/references/perfection/README.md +160 -0
- package/plugin/skills/frontend/references/perfection/react-perf-tooling.md +127 -0
- package/plugin/skills/frontend/references/ui-ux-db/README.md +658 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/charts.csv +26 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/colors.csv +162 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/icons.csv +106 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/landing.csv +35 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/products.csv +162 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/react-performance.csv +45 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/stacks/astro.csv +54 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/stacks/flutter.csv +53 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/stacks/html-tailwind.csv +56 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/stacks/jetpack-compose.csv +53 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/stacks/nextjs.csv +53 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/stacks/nuxt-ui.csv +51 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/stacks/nuxtjs.csv +59 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/stacks/react-native.csv +52 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/stacks/react.csv +54 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/stacks/shadcn.csv +61 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/stacks/svelte.csv +54 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/stacks/swiftui.csv +51 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/stacks/vue.csv +50 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/styles.csv +85 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/typography.csv +74 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/ui-reasoning.csv +162 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/ux-guidelines.csv +100 -0
- package/plugin/skills/frontend/references/ui-ux-db/data/web-interface.csv +31 -0
- package/plugin/skills/frontend/references/ui-ux-db/scripts/core.py +262 -0
- package/plugin/skills/frontend/references/ui-ux-db/scripts/design_system.py +1148 -0
- package/plugin/skills/frontend/references/ui-ux-db/scripts/search.py +114 -0
- package/plugin/skills/frontend/scripts/perfection/lighthouse-audit.py +201 -0
- package/plugin/skills/git-master/SKILL.md +104 -0
- package/plugin/skills/give-me-tips/SKILL.md +102 -0
- package/plugin/skills/hyperplan/SKILL.md +460 -0
- package/plugin/skills/init-deep/SKILL.md +304 -0
- package/plugin/skills/lsp-setup/SKILL.md +139 -0
- package/plugin/skills/lsp-setup/references/bash/README.md +60 -0
- package/plugin/skills/lsp-setup/references/c-cpp/README.md +61 -0
- package/plugin/skills/lsp-setup/references/csharp/README.md +71 -0
- package/plugin/skills/lsp-setup/references/dart/README.md +48 -0
- package/plugin/skills/lsp-setup/references/elixir/README.md +51 -0
- package/plugin/skills/lsp-setup/references/go/README.md +57 -0
- package/plugin/skills/lsp-setup/references/haskell/README.md +57 -0
- package/plugin/skills/lsp-setup/references/java/README.md +57 -0
- package/plugin/skills/lsp-setup/references/julia/README.md +60 -0
- package/plugin/skills/lsp-setup/references/kotlin/README.md +59 -0
- package/plugin/skills/lsp-setup/references/lua/README.md +66 -0
- package/plugin/skills/lsp-setup/references/php/README.md +62 -0
- package/plugin/skills/lsp-setup/references/python/README.md +71 -0
- package/plugin/skills/lsp-setup/references/ruby/README.md +53 -0
- package/plugin/skills/lsp-setup/references/rust/README.md +59 -0
- package/plugin/skills/lsp-setup/references/swift/README.md +51 -0
- package/plugin/skills/lsp-setup/references/terraform/README.md +62 -0
- package/plugin/skills/lsp-setup/references/typescript/README.md +77 -0
- package/plugin/skills/lsp-setup/references/yaml/README.md +70 -0
- package/plugin/skills/lsp-setup/references/zig/README.md +49 -0
- package/plugin/skills/lsp-setup/scripts/detect-lsp.ts +210 -0
- package/plugin/skills/lsp-setup/scripts/lsp-server-table.ts +177 -0
- package/plugin/skills/lsp-setup/scripts/tsconfig.json +17 -0
- package/plugin/skills/lsp-setup/scripts/verify-lsp.ts +147 -0
- package/plugin/skills/programming/SKILL.md +397 -0
- package/plugin/skills/programming/references/code-smells.md +390 -0
- package/plugin/skills/programming/references/go/README.md +90 -0
- package/plugin/skills/programming/references/go/backend-stack.md +641 -0
- package/plugin/skills/programming/references/go/bootstrap.md +328 -0
- package/plugin/skills/programming/references/go/bubbletea-v2.md +360 -0
- package/plugin/skills/programming/references/go/cobra-stack.md +468 -0
- package/plugin/skills/programming/references/go/concurrency.md +362 -0
- package/plugin/skills/programming/references/go/data-modeling.md +329 -0
- package/plugin/skills/programming/references/go/error-handling.md +359 -0
- package/plugin/skills/programming/references/go/golangci-strict.md +236 -0
- package/plugin/skills/programming/references/go/grpc-connect.md +375 -0
- package/plugin/skills/programming/references/go/libraries.md +337 -0
- package/plugin/skills/programming/references/go/one-liners.md +202 -0
- package/plugin/skills/programming/references/go/sqlc-pgx.md +471 -0
- package/plugin/skills/programming/references/go/testing.md +467 -0
- package/plugin/skills/programming/references/go/type-patterns.md +298 -0
- package/plugin/skills/programming/references/logging.md +96 -0
- package/plugin/skills/programming/references/python/README.md +314 -0
- package/plugin/skills/programming/references/python/async-anyio.md +442 -0
- package/plugin/skills/programming/references/python/data-modeling.md +233 -0
- package/plugin/skills/programming/references/python/data-processing.md +133 -0
- package/plugin/skills/programming/references/python/error-handling.md +218 -0
- package/plugin/skills/programming/references/python/fastapi-stack.md +299 -0
- package/plugin/skills/programming/references/python/httpx2-optimization.md +354 -0
- package/plugin/skills/programming/references/python/libraries.md +307 -0
- package/plugin/skills/programming/references/python/one-liners.md +260 -0
- package/plugin/skills/programming/references/python/orjson-stack.md +378 -0
- package/plugin/skills/programming/references/python/pydantic-ai.md +285 -0
- package/plugin/skills/programming/references/python/pyproject-strict.md +232 -0
- package/plugin/skills/programming/references/python/textual-tui.md +195 -0
- package/plugin/skills/programming/references/python/type-patterns.md +176 -0
- package/plugin/skills/programming/references/rust/README.md +317 -0
- package/plugin/skills/programming/references/rust/async-tokio.md +299 -0
- package/plugin/skills/programming/references/rust/axum-stack.md +467 -0
- package/plugin/skills/programming/references/rust/cargo-strict.md +317 -0
- package/plugin/skills/programming/references/rust/clap-stack.md +409 -0
- package/plugin/skills/programming/references/rust/concurrency.md +375 -0
- package/plugin/skills/programming/references/rust/libraries.md +439 -0
- package/plugin/skills/programming/references/rust/one-liners.md +291 -0
- package/plugin/skills/programming/references/rust/proptest-insta.md +429 -0
- package/plugin/skills/programming/references/rust/type-state.md +354 -0
- package/plugin/skills/programming/references/rust/unsafe-discipline.md +250 -0
- package/plugin/skills/programming/references/rust/zero-cost-safety.md +527 -0
- package/plugin/skills/programming/references/rust-ub/README.md +304 -0
- package/plugin/skills/programming/references/rust-ub/miri-sanitizers-loom.md +411 -0
- package/plugin/skills/programming/references/rust-ub/ub-taxonomy.md +269 -0
- package/plugin/skills/programming/references/typescript/README.md +195 -0
- package/plugin/skills/programming/references/typescript/backend-hono.md +672 -0
- package/plugin/skills/programming/references/typescript/bootstrap.md +199 -0
- package/plugin/skills/programming/references/typescript/data-modeling.md +202 -0
- package/plugin/skills/programming/references/typescript/error-handling.md +169 -0
- package/plugin/skills/programming/references/typescript/tsconfig-strict.md +152 -0
- package/plugin/skills/programming/references/typescript/type-patterns.md +196 -0
- package/plugin/skills/programming/scripts/go/check-no-excuse-rules.sh +173 -0
- package/plugin/skills/programming/scripts/go/new-project.py +138 -0
- package/plugin/skills/programming/scripts/go/templates/.editorconfig +13 -0
- package/plugin/skills/programming/scripts/go/templates/.golangci.yml +95 -0
- package/plugin/skills/programming/scripts/go/templates/AGENTS.md.tmpl +24 -0
- package/plugin/skills/programming/scripts/go/templates/README.md.tmpl +12 -0
- package/plugin/skills/programming/scripts/go/templates/Taskfile.yml +40 -0
- package/plugin/skills/programming/scripts/go/templates/ci.yml +37 -0
- package/plugin/skills/programming/scripts/go/templates/config.go +24 -0
- package/plugin/skills/programming/scripts/go/templates/gitignore +15 -0
- package/plugin/skills/programming/scripts/go/templates/main.go.tmpl +22 -0
- package/plugin/skills/programming/scripts/go/templates/run.go +15 -0
- package/plugin/skills/programming/scripts/python/check-no-excuse-rules.py +687 -0
- package/plugin/skills/programming/scripts/python/new-project.py +172 -0
- package/plugin/skills/programming/scripts/python/new-script.py +116 -0
- package/plugin/skills/programming/scripts/rust/check-no-excuse-rules.py +296 -0
- package/plugin/skills/programming/scripts/rust/check-no-excuse-rules.sh +158 -0
- package/plugin/skills/programming/scripts/rust/new-project.py +175 -0
- package/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +346 -0
- package/plugin/skills/programming/scripts/typescript/new-project.ts +177 -0
- package/plugin/skills/refactor/SKILL.md +770 -0
- package/plugin/skills/remove-ai-slops/SKILL.md +352 -0
- package/plugin/skills/review-work/SKILL.md +564 -0
- package/plugin/skills/start-work/SKILL.md +232 -0
- package/plugin/skills/ultimate-browsing/ATTRIBUTION.md +105 -0
- package/plugin/skills/ultimate-browsing/SKILL.md +140 -0
- package/plugin/skills/ultimate-browsing/engine/__init__.py +24 -0
- package/plugin/skills/ultimate-browsing/engine/__main__.py +113 -0
- package/plugin/skills/ultimate-browsing/engine/bias_check.py +185 -0
- package/plugin/skills/ultimate-browsing/engine/curl_probe.py +91 -0
- package/plugin/skills/ultimate-browsing/engine/executor.py +192 -0
- package/plugin/skills/ultimate-browsing/engine/fetch_chain.py +306 -0
- package/plugin/skills/ultimate-browsing/engine/referers.py +15 -0
- package/plugin/skills/ultimate-browsing/engine/result_schema.py +54 -0
- package/plugin/skills/ultimate-browsing/engine/summary.py +37 -0
- package/plugin/skills/ultimate-browsing/engine/surrogate.py +214 -0
- package/plugin/skills/ultimate-browsing/engine/surrogates.yaml +60 -0
- package/plugin/skills/ultimate-browsing/engine/templates/package.json +11 -0
- package/plugin/skills/ultimate-browsing/engine/templates/playwright_mobile_chrome.js +129 -0
- package/plugin/skills/ultimate-browsing/engine/templates/playwright_real_chrome.js +167 -0
- package/plugin/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +7 -0
- package/plugin/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +19 -0
- package/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +1 -0
- package/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +1128 -0
- package/plugin/skills/ultimate-browsing/engine/tests/test_fetch_chain.py +77 -0
- package/plugin/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +282 -0
- package/plugin/skills/ultimate-browsing/engine/tests/test_surrogate.py +252 -0
- package/plugin/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +78 -0
- package/plugin/skills/ultimate-browsing/engine/url_transforms.py +98 -0
- package/plugin/skills/ultimate-browsing/engine/validators.py +262 -0
- package/plugin/skills/ultimate-browsing/engine/waf_detector.py +214 -0
- package/plugin/skills/ultimate-browsing/engine/waf_profiles.yaml +167 -0
- package/plugin/skills/ultimate-browsing/references/agent-reach/README.md +78 -0
- package/plugin/skills/ultimate-browsing/references/agent-reach/career.md +29 -0
- package/plugin/skills/ultimate-browsing/references/agent-reach/dev.md +61 -0
- package/plugin/skills/ultimate-browsing/references/agent-reach/search.md +33 -0
- package/plugin/skills/ultimate-browsing/references/agent-reach/social.md +207 -0
- package/plugin/skills/ultimate-browsing/references/agent-reach/video.md +115 -0
- package/plugin/skills/ultimate-browsing/references/agent-reach/web.md +76 -0
- package/plugin/skills/ultimate-browsing/references/chrome-stealth.md +122 -0
- package/plugin/skills/ultimate-browsing/references/insane-search/README.md +318 -0
- package/plugin/skills/ultimate-browsing/references/insane-search/cache-archive.md +84 -0
- package/plugin/skills/ultimate-browsing/references/insane-search/fallback.md +159 -0
- package/plugin/skills/ultimate-browsing/references/insane-search/jina.md +135 -0
- package/plugin/skills/ultimate-browsing/references/insane-search/json-api.md +133 -0
- package/plugin/skills/ultimate-browsing/references/insane-search/media.md +123 -0
- package/plugin/skills/ultimate-browsing/references/insane-search/metadata.md +116 -0
- package/plugin/skills/ultimate-browsing/references/insane-search/naver.md +107 -0
- package/plugin/skills/ultimate-browsing/references/insane-search/playwright.md +142 -0
- package/plugin/skills/ultimate-browsing/references/insane-search/public-api.md +119 -0
- package/plugin/skills/ultimate-browsing/references/insane-search/rss.md +123 -0
- package/plugin/skills/ultimate-browsing/references/insane-search/tls-impersonate.md +186 -0
- package/plugin/skills/ultimate-browsing/references/insane-search/twitter.md +104 -0
- package/plugin/skills/ultimate-browsing/scripts/cookie_crypto.py +75 -0
- package/plugin/skills/ultimate-browsing/scripts/cookie_domains.py +38 -0
- package/plugin/skills/ultimate-browsing/scripts/cookie_paths.py +112 -0
- package/plugin/skills/ultimate-browsing/scripts/extract_cookies.py +280 -0
- package/plugin/skills/ultrawork/SKILL.md +544 -0
- package/plugin/skills/ulw-loop/SKILL.md +66 -0
- package/plugin/skills/ulw-loop/references/full-workflow.md +249 -0
- package/plugin/skills/ulw-plan/SKILL.md +135 -0
- package/plugin/skills/ulw-plan/references/full-workflow.md +247 -0
- package/plugin/skills/ulw-plan/references/intent-clear.md +44 -0
- package/plugin/skills/ulw-plan/references/intent-unclear.md +44 -0
- package/plugin/skills/ulw-plan/scripts/scaffold-plan.mjs +328 -0
- package/plugin/skills/ulw-research/ATTRIBUTION.md +61 -0
- package/plugin/skills/ulw-research/SKILL.md +407 -0
- package/plugin/skills/ulw-research/references/latex-report.md +176 -0
- package/plugin/skills/visual-qa/SKILL.md +349 -0
- package/plugin/skills/visual-qa/references/agent-browser-setup.md +45 -0
- package/plugin/skills/visual-qa/scripts/ansi.ts +17 -0
- package/plugin/skills/visual-qa/scripts/cli.ts +82 -0
- package/plugin/skills/visual-qa/scripts/east-asian-width.ts +72 -0
- package/plugin/skills/visual-qa/scripts/image-diff.ts +109 -0
- package/plugin/skills/visual-qa/scripts/png-crc.ts +27 -0
- package/plugin/skills/visual-qa/scripts/png-decode.ts +206 -0
- package/plugin/skills/visual-qa/scripts/png-synth.ts +57 -0
- package/plugin/skills/visual-qa/scripts/tui-grid.ts +88 -0
- package/plugin/skills/visual-qa/scripts/types.ts +54 -0
- package/plugin/skills/visual-qa/scripts/visual-qa.mjs +530 -0
- package/index.js +0 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process"
|
|
2
|
+
|
|
3
|
+
export function propagateResult(result) {
|
|
4
|
+
if (result.error) throw result.error
|
|
5
|
+
if (result.signal) {
|
|
6
|
+
process.kill(process.pid, result.signal)
|
|
7
|
+
return
|
|
8
|
+
}
|
|
9
|
+
process.exitCode = result.status ?? 1
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function spawnNode(scriptPath, args, options = {}) {
|
|
13
|
+
const result = spawnSync(process.execPath, [scriptPath, ...args], {
|
|
14
|
+
stdio: "inherit",
|
|
15
|
+
...options,
|
|
16
|
+
})
|
|
17
|
+
propagateResult(result)
|
|
18
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs"
|
|
2
|
+
import { homedir } from "node:os"
|
|
3
|
+
import { join } from "node:path"
|
|
4
|
+
import { packageManifest, packageRoot, readJson, resolveSenpi } from "./package-paths.js"
|
|
5
|
+
import { needsSetupSuggestion } from "./setup-detect.js"
|
|
6
|
+
|
|
7
|
+
const artifacts = [
|
|
8
|
+
["plugin manifest", "plugin/package.json"],
|
|
9
|
+
["extension", "plugin/extensions/omo.js"],
|
|
10
|
+
["lsp-daemon runtime", "plugin/runtime/lsp-daemon/dist/cli.js"],
|
|
11
|
+
["agent-toolkit runtime", "plugin/runtime/agent-toolkit/cli.js"],
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
function pass(message) {
|
|
15
|
+
console.log(`PASS ${message}`)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function fail(message) {
|
|
19
|
+
console.log(`FAIL ${message}`)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function warnForSettings() {
|
|
23
|
+
const agentDir = process.env.SENPI_CODING_AGENT_DIR || join(homedir(), ".senpi", "agent")
|
|
24
|
+
const settingsPath = join(agentDir, "settings.json")
|
|
25
|
+
if (!existsSync(settingsPath)) return
|
|
26
|
+
|
|
27
|
+
let settings
|
|
28
|
+
try {
|
|
29
|
+
settings = JSON.parse(readFileSync(settingsPath, "utf8"))
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.log(`WARN could not parse ${settingsPath}: ${error.message}`)
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const packages = Array.isArray(settings?.packages) ? settings.packages : []
|
|
36
|
+
const duplicate = packages.some((entry) => {
|
|
37
|
+
if (typeof entry === "string") return entry === "@code-yeongyu/omo-senpi"
|
|
38
|
+
return entry !== null && typeof entry === "object" && entry.source === "@code-yeongyu/omo-senpi"
|
|
39
|
+
})
|
|
40
|
+
if (duplicate) {
|
|
41
|
+
console.log("WARN duplicate @code-yeongyu/omo-senpi package entry; remove it from the packages array because omo loads the packaged extension")
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function runDoctor(inventory) {
|
|
46
|
+
let failed = false
|
|
47
|
+
for (const [label, artifact] of artifacts) {
|
|
48
|
+
const path = join(packageRoot, artifact)
|
|
49
|
+
if (existsSync(path)) pass(`${label}: ${artifact}`)
|
|
50
|
+
else {
|
|
51
|
+
// Report the declared posix-style artifact path so diagnostics read identically on every platform;
|
|
52
|
+
// deriving it back from the joined path yields backslashes on Windows.
|
|
53
|
+
fail(`${label}: missing ${artifact}`)
|
|
54
|
+
failed = true
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let senpi
|
|
59
|
+
try {
|
|
60
|
+
senpi = resolveSenpi()
|
|
61
|
+
pass(`senpi CLI: ${senpi.cliPath}`)
|
|
62
|
+
} catch (error) {
|
|
63
|
+
fail(`senpi CLI: ${error.message}`)
|
|
64
|
+
failed = true
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (senpi) {
|
|
68
|
+
try {
|
|
69
|
+
const expected = packageManifest().dependencies["@code-yeongyu/senpi"]
|
|
70
|
+
const installed = readJson(join(senpi.packageRoot, "package.json")).version
|
|
71
|
+
if (installed === expected) pass(`senpi version ${installed}`)
|
|
72
|
+
else {
|
|
73
|
+
fail(`senpi version: expected ${expected}, found ${installed}`)
|
|
74
|
+
failed = true
|
|
75
|
+
}
|
|
76
|
+
} catch (error) {
|
|
77
|
+
fail(`senpi version: ${error.message}`)
|
|
78
|
+
failed = true
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
warnForSettings()
|
|
83
|
+
if (needsSetupSuggestion(inventory)) {
|
|
84
|
+
console.log("INFO senpi has no credentials; run omo setup to review sibling stores")
|
|
85
|
+
}
|
|
86
|
+
process.exitCode = failed ? 1 : 0
|
|
87
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { existsSync } from "node:fs"
|
|
2
|
+
import { delimiter, join } from "node:path"
|
|
3
|
+
import { spawnNode } from "./child-process.js"
|
|
4
|
+
import { runDoctor } from "./doctor.js"
|
|
5
|
+
import { nearestNodeBin, packageManifest, packageRoot, resolveSenpi } from "./package-paths.js"
|
|
6
|
+
import { detectHarnesses, needsSetupSuggestion } from "./setup-detect.js"
|
|
7
|
+
import { printSetupReport } from "./setup-report.js"
|
|
8
|
+
|
|
9
|
+
const earlyCommands = new Set(["install", "remove", "list", "config", "auth", "app-server"])
|
|
10
|
+
|
|
11
|
+
function senpiEnvironment(senpiRoot) {
|
|
12
|
+
const env = { ...process.env }
|
|
13
|
+
delete env.OMO_BIN
|
|
14
|
+
delete env.SENPI_BIN
|
|
15
|
+
env.OMO_AGENT_TOOLKIT_BIN = join(packageRoot, "bin", "omo-agent-toolkit.js")
|
|
16
|
+
|
|
17
|
+
const binDir = nearestNodeBin(senpiRoot)
|
|
18
|
+
if (binDir) {
|
|
19
|
+
env.PATH = env.PATH ? `${binDir}${delimiter}${env.PATH}` : binDir
|
|
20
|
+
const shim = join(binDir, process.platform === "win32" ? "senpi.cmd" : "senpi")
|
|
21
|
+
if (existsSync(shim)) env.SENPI_BIN = shim
|
|
22
|
+
}
|
|
23
|
+
return env
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function spawnSenpi(args, withExtension) {
|
|
27
|
+
const senpi = resolveSenpi()
|
|
28
|
+
const finalArgs = withExtension
|
|
29
|
+
? ["--extension", join(packageRoot, "plugin"), ...args]
|
|
30
|
+
: args
|
|
31
|
+
spawnNode(senpi.cliPath, finalArgs, { env: senpiEnvironment(senpi.packageRoot) })
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function isInteractiveDefault(args) {
|
|
35
|
+
return process.stderr.isTTY === true && !args.includes("-p") && !args.includes("--print")
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function runLauncher(args = process.argv.slice(2)) {
|
|
39
|
+
const command = args[0]
|
|
40
|
+
if (command === "ulw-loop") {
|
|
41
|
+
spawnNode(join(packageRoot, "plugin", "runtime", "agent-toolkit", "ulw-loop", "cli.js"), args.slice(1))
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
if (command === "doctor") {
|
|
45
|
+
runDoctor(await detectHarnesses())
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
if (command === "setup") {
|
|
49
|
+
printSetupReport(await detectHarnesses())
|
|
50
|
+
process.exitCode = 0
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
if (command === "update" && args.length === 1) {
|
|
54
|
+
console.log("omo is updated via npm: npm i -g omo-ai@beta")
|
|
55
|
+
process.exitCode = 0
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
if (earlyCommands.has(command) || command === "update") {
|
|
59
|
+
spawnSenpi(args, false)
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
if (isInteractiveDefault(args)) {
|
|
63
|
+
console.error(`omo (omo-ai beta ${packageManifest().version})`)
|
|
64
|
+
if (process.stdout.isTTY === true && needsSetupSuggestion(await detectHarnesses())) {
|
|
65
|
+
console.error("omo: sibling credentials detected; run `omo setup` to review them")
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
spawnSenpi(args, true)
|
|
69
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs"
|
|
2
|
+
import { dirname, join, parse } from "node:path"
|
|
3
|
+
import { fileURLToPath } from "node:url"
|
|
4
|
+
|
|
5
|
+
export const packageRoot = fileURLToPath(new URL("../..", import.meta.url))
|
|
6
|
+
|
|
7
|
+
export function readJson(path) {
|
|
8
|
+
return JSON.parse(readFileSync(path, "utf8"))
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function packageManifest() {
|
|
12
|
+
return readJson(join(packageRoot, "package.json"))
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function resolveSenpi() {
|
|
16
|
+
let indexPath
|
|
17
|
+
try {
|
|
18
|
+
indexPath = fileURLToPath(import.meta.resolve("@code-yeongyu/senpi"))
|
|
19
|
+
} catch (error) {
|
|
20
|
+
throw new Error(`could not resolve @code-yeongyu/senpi; reinstall with: npm i -g omo-ai@beta (${error.message})`)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const cliPath = join(dirname(indexPath), "cli.js")
|
|
24
|
+
if (!existsSync(cliPath)) {
|
|
25
|
+
throw new Error(`senpi CLI is missing at ${cliPath}; reinstall with: npm i -g omo-ai@beta`)
|
|
26
|
+
}
|
|
27
|
+
return { cliPath, packageRoot: dirname(dirname(indexPath)) }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function nearestNodeBin(startPath) {
|
|
31
|
+
let current = startPath
|
|
32
|
+
const root = parse(current).root
|
|
33
|
+
while (true) {
|
|
34
|
+
const candidate = join(current, "node_modules", ".bin")
|
|
35
|
+
if (existsSync(candidate)) return candidate
|
|
36
|
+
if (current === root) return undefined
|
|
37
|
+
current = dirname(current)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "Derived from @code-yeongyu/senpi 2026.8.9-2. Re-derive builtin provider ids and mappings whenever that pin changes.",
|
|
3
|
+
"builtinProviderIds": [
|
|
4
|
+
"alibaba-token-plan",
|
|
5
|
+
"amazon-bedrock",
|
|
6
|
+
"ant-ling",
|
|
7
|
+
"anthropic",
|
|
8
|
+
"azure-openai-responses",
|
|
9
|
+
"cerebras",
|
|
10
|
+
"cloudflare-ai-gateway",
|
|
11
|
+
"cloudflare-workers-ai",
|
|
12
|
+
"deepseek",
|
|
13
|
+
"fireworks",
|
|
14
|
+
"github-copilot",
|
|
15
|
+
"google",
|
|
16
|
+
"google-vertex",
|
|
17
|
+
"groq",
|
|
18
|
+
"huggingface",
|
|
19
|
+
"kimi-coding",
|
|
20
|
+
"minimax",
|
|
21
|
+
"minimax-cn",
|
|
22
|
+
"mistral",
|
|
23
|
+
"moonshotai",
|
|
24
|
+
"moonshotai-cn",
|
|
25
|
+
"nvidia",
|
|
26
|
+
"ollama",
|
|
27
|
+
"openai",
|
|
28
|
+
"openai-codex",
|
|
29
|
+
"openrouter",
|
|
30
|
+
"qwen-token-plan",
|
|
31
|
+
"qwen-token-plan-cn",
|
|
32
|
+
"radius",
|
|
33
|
+
"together",
|
|
34
|
+
"vercel-ai-gateway",
|
|
35
|
+
"xai",
|
|
36
|
+
"xiaomi",
|
|
37
|
+
"xiaomi-token-plan-ams",
|
|
38
|
+
"xiaomi-token-plan-cn",
|
|
39
|
+
"xiaomi-token-plan-sgp",
|
|
40
|
+
"zai",
|
|
41
|
+
"zai-coding-cn"
|
|
42
|
+
],
|
|
43
|
+
"excludedHostedGatewayIds": [
|
|
44
|
+
"opencode",
|
|
45
|
+
"opencode-go",
|
|
46
|
+
"zai-coding-plan"
|
|
47
|
+
],
|
|
48
|
+
"providers": {
|
|
49
|
+
"anthropic-api": "anthropic",
|
|
50
|
+
"azure": "azure-openai-responses",
|
|
51
|
+
"kimi-for-coding": "kimi-coding",
|
|
52
|
+
"moonshot": "moonshotai",
|
|
53
|
+
"zhipuai": "zai"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs"
|
|
2
|
+
import { homedir } from "node:os"
|
|
3
|
+
import { join } from "node:path"
|
|
4
|
+
|
|
5
|
+
export const KNOWN_AUTH_SCHEMA_VERSIONS = new Set([4, 7])
|
|
6
|
+
|
|
7
|
+
function sorted(values) {
|
|
8
|
+
return [...new Set(values)].sort()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function harness(id, installed, providers = [], credentialTypes = [], modelHint = "none") {
|
|
12
|
+
return {
|
|
13
|
+
id,
|
|
14
|
+
installed,
|
|
15
|
+
providers: sorted(providers),
|
|
16
|
+
credentialTypes: sorted(credentialTypes),
|
|
17
|
+
entryCount: providers.length,
|
|
18
|
+
importableCount: 0,
|
|
19
|
+
modelHint,
|
|
20
|
+
notices: [],
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function readAuthJson(id, path) {
|
|
25
|
+
if (!existsSync(path)) return harness(id, false)
|
|
26
|
+
const result = harness(id, true)
|
|
27
|
+
try {
|
|
28
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"))
|
|
29
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
30
|
+
throw new Error("expected an object")
|
|
31
|
+
}
|
|
32
|
+
for (const [provider, entry] of Object.entries(parsed)) {
|
|
33
|
+
result.providers.push(provider)
|
|
34
|
+
const type = entry !== null && typeof entry === "object" && typeof entry.type === "string"
|
|
35
|
+
? entry.type
|
|
36
|
+
: "unknown"
|
|
37
|
+
result.credentialTypes.push(type)
|
|
38
|
+
if (id === "opencode" && type === "api") result.importableCount += 1
|
|
39
|
+
}
|
|
40
|
+
result.providers = sorted(result.providers)
|
|
41
|
+
result.credentialTypes = sorted(result.credentialTypes)
|
|
42
|
+
result.entryCount = result.providers.length
|
|
43
|
+
} catch (error) {
|
|
44
|
+
result.notices.push(`could not parse auth.json: ${error.message}`)
|
|
45
|
+
}
|
|
46
|
+
return result
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function readSenpiModels(path, result) {
|
|
50
|
+
if (!existsSync(path)) return
|
|
51
|
+
try {
|
|
52
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"))
|
|
53
|
+
const providers = parsed?.providers
|
|
54
|
+
if (providers !== null && typeof providers === "object" && !Array.isArray(providers)) {
|
|
55
|
+
const ids = sorted(Object.keys(providers))
|
|
56
|
+
result.modelHint = ids.length > 0 ? `providers: ${ids.join(", ")}` : "providers: none"
|
|
57
|
+
}
|
|
58
|
+
} catch (error) {
|
|
59
|
+
result.notices.push(`could not parse models.json: ${error.message}`)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function readGajaeModels(path) {
|
|
64
|
+
if (!existsSync(path)) return "none"
|
|
65
|
+
try {
|
|
66
|
+
const lines = readFileSync(path, "utf8").split(/\r?\n/)
|
|
67
|
+
const enabledModels = []
|
|
68
|
+
const modelRoles = []
|
|
69
|
+
let section
|
|
70
|
+
for (const line of lines) {
|
|
71
|
+
if (/^enabledModels\s*:/.test(line)) {
|
|
72
|
+
section = "enabledModels"
|
|
73
|
+
continue
|
|
74
|
+
}
|
|
75
|
+
if (/^modelRoles\s*:/.test(line)) {
|
|
76
|
+
section = "modelRoles"
|
|
77
|
+
continue
|
|
78
|
+
}
|
|
79
|
+
if (/^[^\s#][^:]*\s*:/.test(line)) {
|
|
80
|
+
section = undefined
|
|
81
|
+
continue
|
|
82
|
+
}
|
|
83
|
+
if (section === "enabledModels") {
|
|
84
|
+
const match = line.match(/^\s+-\s+(.+?)\s*$/)
|
|
85
|
+
if (match) enabledModels.push(match[1].replace(/^['"]|['"]$/g, ""))
|
|
86
|
+
} else if (section === "modelRoles") {
|
|
87
|
+
const match = line.match(/^\s+([^#][^:]*?)\s*:/)
|
|
88
|
+
if (match) modelRoles.push(match[1].trim())
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const hints = []
|
|
92
|
+
if (enabledModels.length > 0) hints.push(`enabledModels: ${sorted(enabledModels).join(", ")}`)
|
|
93
|
+
if (modelRoles.length > 0) hints.push(`modelRoles: ${sorted(modelRoles).join(", ")}`)
|
|
94
|
+
return hints.length > 0 ? hints.join("; ") : "none"
|
|
95
|
+
} catch {
|
|
96
|
+
return "none"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function inspectSqlite(id, path, DatabaseSync, modelHint) {
|
|
101
|
+
const result = harness(id, existsSync(path), [], [], modelHint)
|
|
102
|
+
if (!result.installed) return result
|
|
103
|
+
let database
|
|
104
|
+
try {
|
|
105
|
+
database = new DatabaseSync(path, { readOnly: true })
|
|
106
|
+
const schema = database.prepare("SELECT version FROM auth_schema_version").get()
|
|
107
|
+
const version = schema?.version
|
|
108
|
+
if (!KNOWN_AUTH_SCHEMA_VERSIONS.has(version)) {
|
|
109
|
+
result.notices.push(`auth schema version ${String(version)} is unknown; credentials not inspected`)
|
|
110
|
+
return result
|
|
111
|
+
}
|
|
112
|
+
const rows = database.prepare(
|
|
113
|
+
"SELECT provider, credential_type, disabled_cause FROM auth_credentials",
|
|
114
|
+
).all()
|
|
115
|
+
result.providers = sorted(rows.map((row) => row.provider))
|
|
116
|
+
result.credentialTypes = sorted(rows.map((row) => row.credential_type))
|
|
117
|
+
result.entryCount = rows.length
|
|
118
|
+
result.importableCount = rows.filter((row) =>
|
|
119
|
+
row.disabled_cause === null && row.credential_type === "api_key",
|
|
120
|
+
).length
|
|
121
|
+
} catch (error) {
|
|
122
|
+
result.notices.push(`could not inspect agent.db: ${error.message}`)
|
|
123
|
+
} finally {
|
|
124
|
+
database?.close()
|
|
125
|
+
}
|
|
126
|
+
return result
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export async function detectHarnesses(options = {}) {
|
|
130
|
+
const home = options.home ?? homedir()
|
|
131
|
+
const env = options.env ?? process.env
|
|
132
|
+
const agentDir = env.SENPI_CODING_AGENT_DIR || join(home, ".senpi", "agent")
|
|
133
|
+
const dataHome = env.XDG_DATA_HOME || join(home, ".local", "share")
|
|
134
|
+
const senpi = readAuthJson("senpi", join(agentDir, "auth.json"))
|
|
135
|
+
readSenpiModels(join(agentDir, "models.json"), senpi)
|
|
136
|
+
const opencode = readAuthJson("opencode", join(dataHome, "opencode", "auth.json"))
|
|
137
|
+
const ompPath = join(home, ".omp", "agent", "agent.db")
|
|
138
|
+
const gjcPath = join(home, ".gjc", "agent", "agent.db")
|
|
139
|
+
const ompModels = existsSync(join(home, ".omp", "agent", "models.db")) ? "models.db: yes" : "models.db: no"
|
|
140
|
+
const gjcModels = readGajaeModels(join(home, ".gjc", "agent", "config.yml"))
|
|
141
|
+
let DatabaseSync
|
|
142
|
+
try {
|
|
143
|
+
const sqlite = await (options.loadSqlite ?? (() => import("node:sqlite")))()
|
|
144
|
+
DatabaseSync = sqlite.DatabaseSync
|
|
145
|
+
} catch {
|
|
146
|
+
const omp = harness("oh-my-pi", existsSync(ompPath), [], [], ompModels)
|
|
147
|
+
const gjc = harness("gajae-code", existsSync(gjcPath), [], [], gjcModels)
|
|
148
|
+
for (const item of [omp, gjc]) {
|
|
149
|
+
if (item.installed) item.notices.push("node:sqlite unavailable; file presence only")
|
|
150
|
+
}
|
|
151
|
+
return { harnesses: [senpi, opencode, omp, gjc] }
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
harnesses: [
|
|
155
|
+
senpi,
|
|
156
|
+
opencode,
|
|
157
|
+
inspectSqlite("oh-my-pi", ompPath, DatabaseSync, ompModels),
|
|
158
|
+
inspectSqlite("gajae-code", gjcPath, DatabaseSync, gjcModels),
|
|
159
|
+
],
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function needsSetupSuggestion(inventory) {
|
|
164
|
+
const senpi = inventory.harnesses.find((item) => item.id === "senpi")
|
|
165
|
+
const siblingInstalled = inventory.harnesses.some((item) => item.id !== "senpi" && item.installed)
|
|
166
|
+
return (senpi?.entryCount ?? 0) === 0 && siblingInstalled
|
|
167
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import {
|
|
2
|
+
chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync,
|
|
3
|
+
} from "node:fs"
|
|
4
|
+
import { homedir } from "node:os"
|
|
5
|
+
import { dirname, join } from "node:path"
|
|
6
|
+
import { createInterface } from "node:readline/promises"
|
|
7
|
+
import { detectHarnesses } from "./setup-detect.js"
|
|
8
|
+
import { printModelReport } from "./setup-models.js"
|
|
9
|
+
import { printSetupReport } from "./setup-report.js"
|
|
10
|
+
|
|
11
|
+
export const API_KEY_TYPE_ACCEPTLIST = new Set(["api_key"])
|
|
12
|
+
const SQLITE_STORES = [
|
|
13
|
+
["oh-my-pi", ".omp", 7],
|
|
14
|
+
["gajae-code", ".gjc", 4],
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
function sorted(values) {
|
|
18
|
+
return [...new Set(values)].sort()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function readProviderMap() {
|
|
22
|
+
return JSON.parse(readFileSync(new URL("./provider-map.json", import.meta.url), "utf8"))
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function targetProvider(provider, providerMap) {
|
|
26
|
+
if (providerMap.excludedHostedGatewayIds.includes(provider)) return undefined
|
|
27
|
+
if (providerMap.builtinProviderIds.includes(provider)) return provider
|
|
28
|
+
return providerMap.providers[provider]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function candidate(provider, key, source, providerMap) {
|
|
32
|
+
const target = targetProvider(provider, providerMap)
|
|
33
|
+
return target ? { provider: target, key, source } : { provider, source, unmapped: true }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function readOpencode(path, providerMap, plan) {
|
|
37
|
+
if (!existsSync(path)) return
|
|
38
|
+
try {
|
|
39
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"))
|
|
40
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return
|
|
41
|
+
for (const [provider, entry] of Object.entries(parsed)) {
|
|
42
|
+
if (entry === null || typeof entry !== "object") continue
|
|
43
|
+
if (entry.type === "oauth") {
|
|
44
|
+
plan.oauth.push(provider)
|
|
45
|
+
} else if (entry.type === "api" && typeof entry.key === "string") {
|
|
46
|
+
plan.candidates.push(candidate(provider, entry.key, "opencode", providerMap))
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
plan.notices.push(`WARN opencode: could not parse auth.json: ${error.message}`)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function readSqliteStore(id, path, expectedVersion, DatabaseSync, providerMap, plan) {
|
|
55
|
+
if (!existsSync(path)) return
|
|
56
|
+
let database
|
|
57
|
+
try {
|
|
58
|
+
database = new DatabaseSync(path, { readOnly: true })
|
|
59
|
+
const version = database.prepare("SELECT version FROM auth_schema_version").get()?.version
|
|
60
|
+
if (version !== expectedVersion) {
|
|
61
|
+
plan.notices.push(`NOTICE ${id}: auth schema version ${String(version)} is unknown; credentials not imported`)
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
const rows = database.prepare(
|
|
65
|
+
"SELECT provider, credential_type, data FROM auth_credentials WHERE disabled_cause IS NULL ORDER BY id ASC",
|
|
66
|
+
).all()
|
|
67
|
+
for (const row of rows) {
|
|
68
|
+
if (row.credential_type === "oauth") {
|
|
69
|
+
plan.oauth.push(row.provider)
|
|
70
|
+
continue
|
|
71
|
+
}
|
|
72
|
+
if (!API_KEY_TYPE_ACCEPTLIST.has(row.credential_type)) continue
|
|
73
|
+
try {
|
|
74
|
+
const data = JSON.parse(row.data)
|
|
75
|
+
if (typeof data?.key === "string") {
|
|
76
|
+
plan.candidates.push(candidate(row.provider, data.key, id, providerMap))
|
|
77
|
+
}
|
|
78
|
+
} catch {
|
|
79
|
+
plan.notices.push(`WARN ${id}: ignored malformed ${row.credential_type} row for ${row.provider}`)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} catch (error) {
|
|
83
|
+
plan.notices.push(`WARN ${id}: could not inspect agent.db: ${error.message}`)
|
|
84
|
+
} finally {
|
|
85
|
+
database?.close()
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function buildPlan(options) {
|
|
90
|
+
const home = options.home ?? homedir()
|
|
91
|
+
const env = options.env ?? process.env
|
|
92
|
+
const dataHome = env.XDG_DATA_HOME || join(home, ".local", "share")
|
|
93
|
+
const providerMap = readProviderMap()
|
|
94
|
+
const plan = { candidates: [], oauth: [], notices: [] }
|
|
95
|
+
readOpencode(join(dataHome, "opencode", "auth.json"), providerMap, plan)
|
|
96
|
+
try {
|
|
97
|
+
const { DatabaseSync } = await (options.loadSqlite ?? (() => import("node:sqlite")))()
|
|
98
|
+
for (const [id, directory, version] of SQLITE_STORES) {
|
|
99
|
+
readSqliteStore(id, join(home, directory, "agent", "agent.db"), version, DatabaseSync, providerMap, plan)
|
|
100
|
+
}
|
|
101
|
+
} catch {
|
|
102
|
+
plan.notices.push("NOTICE setup: node:sqlite unavailable; database credentials not imported")
|
|
103
|
+
}
|
|
104
|
+
return plan
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function readTarget(path) {
|
|
108
|
+
if (!existsSync(path)) return { entries: {}, bytes: undefined }
|
|
109
|
+
const bytes = readFileSync(path, "utf8")
|
|
110
|
+
try {
|
|
111
|
+
const entries = JSON.parse(bytes)
|
|
112
|
+
if (entries === null || typeof entries !== "object" || Array.isArray(entries)) throw new Error("expected object")
|
|
113
|
+
return { entries, bytes }
|
|
114
|
+
} catch {
|
|
115
|
+
return { malformed: true, bytes }
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function classify(plan, existing) {
|
|
120
|
+
const additions = []
|
|
121
|
+
const skippedExisting = []
|
|
122
|
+
const skippedUnmapped = []
|
|
123
|
+
const reserved = new Set(Object.keys(existing))
|
|
124
|
+
for (const item of plan.candidates) {
|
|
125
|
+
if (item.unmapped) {
|
|
126
|
+
skippedUnmapped.push(item.provider)
|
|
127
|
+
} else if (reserved.has(item.provider)) {
|
|
128
|
+
skippedExisting.push(item.provider)
|
|
129
|
+
} else {
|
|
130
|
+
reserved.add(item.provider)
|
|
131
|
+
additions.push(item)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
additions,
|
|
136
|
+
skippedExisting: sorted(skippedExisting),
|
|
137
|
+
skippedOauth: sorted(plan.oauth),
|
|
138
|
+
skippedUnmapped: sorted(skippedUnmapped),
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function list(label, ids) {
|
|
143
|
+
return `${label}: ${ids.length > 0 ? ids.join(", ") : "none"}`
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function printPlan(result, dryRun) {
|
|
147
|
+
if (dryRun) process.stdout.write("DRY RUN: no files will be written\n")
|
|
148
|
+
process.stdout.write(`${[
|
|
149
|
+
list("planned-add", result.additions.map((item) => item.provider)),
|
|
150
|
+
list("skipped-existing", result.skippedExisting),
|
|
151
|
+
list("skipped-oauth", result.skippedOauth),
|
|
152
|
+
list("skipped-unmapped", result.skippedUnmapped),
|
|
153
|
+
].join("\n")}\n`)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function printCounts(result) {
|
|
157
|
+
process.stdout.write([
|
|
158
|
+
`imported: ${result.additions.length}`,
|
|
159
|
+
`skipped-existing: ${result.skippedExisting.length}`,
|
|
160
|
+
`skipped-oauth: ${result.skippedOauth.length}`,
|
|
161
|
+
`skipped-unmapped: ${result.skippedUnmapped.length}`,
|
|
162
|
+
"Use `omo auth` to sign in to OAuth providers.",
|
|
163
|
+
].join("\n") + "\n")
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function timestamp() {
|
|
167
|
+
return new Date().toISOString().replace(/[-:]/g, "")
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function writeTarget(path, current, additions) {
|
|
171
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 })
|
|
172
|
+
if (current.bytes !== undefined) copyFileSync(path, `${path}.bak-${timestamp()}`)
|
|
173
|
+
const next = { ...current.entries }
|
|
174
|
+
for (const item of additions) next[item.provider] = { type: "api_key", key: item.key }
|
|
175
|
+
const temporary = `${path}.tmp-${process.pid}`
|
|
176
|
+
try {
|
|
177
|
+
writeFileSync(temporary, JSON.stringify(next, null, 2), { encoding: "utf8", mode: 0o600 })
|
|
178
|
+
chmodSync(temporary, 0o600)
|
|
179
|
+
renameSync(temporary, path)
|
|
180
|
+
chmodSync(path, 0o600)
|
|
181
|
+
} finally {
|
|
182
|
+
if (existsSync(temporary)) unlinkSync(temporary)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function consent(result, target, options) {
|
|
187
|
+
if (options.yes) return true
|
|
188
|
+
if (options.stdin?.isTTY !== true || options.stdout?.isTTY !== true) {
|
|
189
|
+
process.stdout.write("Non-interactive setup did not import credentials. Re-run with `omo setup --yes`.\n")
|
|
190
|
+
return false
|
|
191
|
+
}
|
|
192
|
+
process.stdout.write(`Import API credentials for ${result.additions.map((item) => item.provider).join(", ")} into ${target}? [y/N] `)
|
|
193
|
+
const readline = createInterface({ input: options.stdin, output: options.stdout })
|
|
194
|
+
try {
|
|
195
|
+
return (await readline.question("")).trim().toLowerCase() === "y"
|
|
196
|
+
} finally {
|
|
197
|
+
readline.close()
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export async function runSetup(args = process.argv.slice(2), options = {}) {
|
|
202
|
+
const home = options.home ?? homedir()
|
|
203
|
+
const env = options.env ?? process.env
|
|
204
|
+
const agentDir = env.SENPI_CODING_AGENT_DIR || join(home, ".senpi", "agent")
|
|
205
|
+
const target = join(agentDir, "auth.json")
|
|
206
|
+
const runtime = { stdin: process.stdin, stdout: process.stdout, ...options, home, env }
|
|
207
|
+
const inventory = await detectHarnesses(runtime)
|
|
208
|
+
printSetupReport(inventory)
|
|
209
|
+
printModelReport(inventory)
|
|
210
|
+
const plan = await buildPlan(runtime)
|
|
211
|
+
for (const notice of plan.notices) process.stdout.write(`${notice}\n`)
|
|
212
|
+
const current = readTarget(target)
|
|
213
|
+
if (current.malformed) {
|
|
214
|
+
process.stdout.write("WARN senpi: malformed auth.json; credentials were not imported\n")
|
|
215
|
+
return
|
|
216
|
+
}
|
|
217
|
+
const result = classify(plan, current.entries)
|
|
218
|
+
const dryRun = args.includes("--dry-run")
|
|
219
|
+
printPlan(result, dryRun)
|
|
220
|
+
if (dryRun) return
|
|
221
|
+
if (result.additions.length === 0) {
|
|
222
|
+
printCounts(result)
|
|
223
|
+
return
|
|
224
|
+
}
|
|
225
|
+
if (!await consent(result, target, { ...runtime, yes: args.includes("--yes") })) {
|
|
226
|
+
if (runtime.stdin.isTTY === true) process.stdout.write("Import cancelled\n")
|
|
227
|
+
return
|
|
228
|
+
}
|
|
229
|
+
writeTarget(target, current, result.additions)
|
|
230
|
+
printCounts(result)
|
|
231
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
function values(items) {
|
|
2
|
+
return items.length > 0 ? items.join(", ") : "none"
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function formatModelReport(inventory) {
|
|
6
|
+
const lines = ["", "MODEL AVAILABILITY"]
|
|
7
|
+
for (const harness of inventory.harnesses) {
|
|
8
|
+
lines.push(`${harness.id}: providers ${values(harness.providers)}; models ${harness.modelHint}`)
|
|
9
|
+
}
|
|
10
|
+
lines.push(
|
|
11
|
+
"Model-to-agent guidance: docs/guide/agent-model-matching.md",
|
|
12
|
+
"Ready-to-paste omo.json models catalog template:",
|
|
13
|
+
JSON.stringify({
|
|
14
|
+
models: {
|
|
15
|
+
primary: { model: "<provider>/<model-id>", reasoning: "<off|low|medium|high|max>" },
|
|
16
|
+
"custom-endpoint": { model: "<custom-baseUrl-provider>/<model-id>" },
|
|
17
|
+
},
|
|
18
|
+
}, null, 2),
|
|
19
|
+
"For custom endpoints, define the provider baseUrl in senpi models.json, then use that provider id above.",
|
|
20
|
+
)
|
|
21
|
+
return `${lines.join("\n")}\n`
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function printModelReport(inventory) {
|
|
25
|
+
process.stdout.write(formatModelReport(inventory))
|
|
26
|
+
}
|