rovecode 0.4.0-beta.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -72
- package/THIRD_PARTY_NOTICES.md +0 -44
- package/bin/rovecode.ts +21 -0
- package/package.json +16 -38
- package/src/account/keys.ts +97 -0
- package/src/account/login.ts +158 -0
- package/src/account/provision.ts +47 -0
- package/src/account/store.ts +63 -0
- package/src/acp/server.ts +373 -0
- package/src/cli/account-cmd.ts +116 -0
- package/src/cli/connect.ts +244 -0
- package/src/cli/context-cmd.ts +199 -0
- package/src/cli/dispatch.ts +109 -0
- package/src/cli/doctor.ts +324 -0
- package/src/cli/export.ts +278 -0
- package/src/cli/help.ts +240 -0
- package/src/cli/is-tui-invocation.ts +8 -0
- package/src/cli/main.ts +599 -0
- package/src/cli/market-cmd.ts +658 -0
- package/src/cli/mcp-market-cmd.ts +299 -0
- package/src/cli/output.ts +382 -0
- package/src/cli/repl.ts +172 -0
- package/src/cli/resume.ts +32 -0
- package/src/cli/run-limits.ts +78 -0
- package/src/cli/runtime.ts +792 -0
- package/src/cli/setup.ts +187 -0
- package/src/cli/update-cmd.ts +78 -0
- package/src/cli/workflow-cmd.ts +100 -0
- package/src/coding/checkpoints.ts +270 -0
- package/src/coding/diff.ts +136 -0
- package/src/coding/files.ts +339 -0
- package/src/coding/hashline.ts +319 -0
- package/src/coding/lsp.ts +406 -0
- package/src/coding/repomap-cache.ts +99 -0
- package/src/coding/repomap-files.ts +110 -0
- package/src/coding/repomap.ts +392 -0
- package/src/core/compaction.ts +399 -0
- package/src/core/config.ts +289 -0
- package/src/core/context-report.ts +228 -0
- package/src/core/context.ts +60 -0
- package/src/core/count-remote.ts +107 -0
- package/src/core/execpolicy-rules.ts +196 -0
- package/src/core/execpolicy.ts +385 -0
- package/src/core/executor.ts +397 -0
- package/src/core/guardrails.ts +400 -0
- package/src/core/hooks.ts +398 -0
- package/src/core/images.ts +230 -0
- package/src/core/intro.ts +236 -0
- package/src/core/loop.ts +621 -0
- package/src/core/modes.ts +372 -0
- package/src/core/orchestrator.ts +207 -0
- package/src/core/reflection.ts +165 -0
- package/src/core/sandbox-config.ts +167 -0
- package/src/core/session-images.ts +73 -0
- package/src/core/session.ts +398 -0
- package/src/core/settings.ts +98 -0
- package/src/core/stuck-detector.ts +273 -0
- package/src/core/tasks.ts +374 -0
- package/src/core/token-scale.ts +108 -0
- package/src/core/tool-output-budget.ts +166 -0
- package/src/core/tools.ts +288 -0
- package/src/core/types.ts +330 -0
- package/src/core/update-check.ts +171 -0
- package/src/core/update.ts +158 -0
- package/src/core/usage.ts +204 -0
- package/src/core/validate.ts +121 -0
- package/src/core/verify-gate.ts +159 -0
- package/src/core/verify.ts +237 -0
- package/src/core/voice.ts +158 -0
- package/src/core/win-job.ts +183 -0
- package/src/design/audit.ts +797 -0
- package/src/design/direction.ts +190 -0
- package/src/design/rules.ts +157 -0
- package/src/eval/bench.ts +150 -0
- package/src/eval/gauntlet-runner.ts +218 -0
- package/src/eval/gauntlet.ts +226 -0
- package/src/eval/grader.ts +186 -0
- package/src/eval/record.ts +202 -0
- package/src/eval/redact.ts +141 -0
- package/src/eval/replay.ts +147 -0
- package/src/eval/trajectory.ts +373 -0
- package/src/index.ts +17 -0
- package/src/market/catalogs/mcp-docs.json +111 -0
- package/src/market/catalogs/plugins.json +111 -0
- package/src/market/catalogs/skills.json +478 -0
- package/src/market/clone.ts +72 -0
- package/src/market/context-cost.ts +121 -0
- package/src/market/digest.ts +106 -0
- package/src/market/index.ts +22 -0
- package/src/market/install.ts +578 -0
- package/src/market/manifest.ts +187 -0
- package/src/market/prereq.ts +145 -0
- package/src/market/registry.ts +363 -0
- package/src/market/resolve.ts +111 -0
- package/src/market/types.ts +236 -0
- package/src/market/validate.ts +227 -0
- package/src/mcp/client.ts +431 -0
- package/src/mcp/config.ts +239 -0
- package/src/mcp/local-package.ts +211 -0
- package/src/mcp/market-catalog.ts +84 -0
- package/src/mcp/market-install.ts +289 -0
- package/src/mcp/market.ts +0 -0
- package/src/mcp/tools.ts +131 -0
- package/src/mcp/trust.ts +49 -0
- package/src/memory/blocks.ts +175 -0
- package/src/memory/recall.ts +355 -0
- package/src/memory/store.ts +105 -0
- package/src/memory/tools.ts +99 -0
- package/src/plugins/cli.ts +123 -0
- package/src/plugins/discover.ts +108 -0
- package/src/plugins/index.ts +50 -0
- package/src/plugins/init.ts +140 -0
- package/src/plugins/install.ts +184 -0
- package/src/plugins/load.ts +149 -0
- package/src/plugins/manifest.ts +106 -0
- package/src/plugins/state.ts +83 -0
- package/src/providers/auth.ts +293 -0
- package/src/providers/cache.ts +223 -0
- package/src/providers/catalog-local.ts +160 -0
- package/src/providers/catalog.ts +408 -0
- package/src/providers/middleware-context.ts +86 -0
- package/src/providers/middleware.ts +373 -0
- package/src/providers/profile-glm53.ts +111 -0
- package/src/providers/profile-sonnet5-persona.ts +65 -0
- package/src/providers/profile-sonnet5-voice.ts +23 -0
- package/src/providers/profiles.ts +156 -0
- package/src/providers/provider-config.ts +311 -0
- package/src/providers/registry.ts +302 -0
- package/src/providers/response-validation.ts +80 -0
- package/src/providers/retry.ts +234 -0
- package/src/providers/router.ts +294 -0
- package/src/providers/sse.ts +26 -0
- package/src/providers/stream-errors.ts +117 -0
- package/src/providers/stream.ts +569 -0
- package/src/providers/thinking.ts +189 -0
- package/src/providers/wire-messages.ts +129 -0
- package/src/sdk/client.ts +225 -0
- package/src/sdk/index.ts +3 -0
- package/src/server/dashboard.ts +144 -0
- package/src/server/http.ts +343 -0
- package/src/server/openapi.ts +246 -0
- package/src/sextant/card-hits.ts +102 -0
- package/src/sextant/card-keys.ts +55 -0
- package/src/sextant/context-source.ts +157 -0
- package/src/sextant/draw-agents.ts +273 -0
- package/src/sextant/draw-code.ts +388 -0
- package/src/sextant/draw-context.ts +222 -0
- package/src/sextant/draw-frame.ts +164 -0
- package/src/sextant/draw-market.ts +573 -0
- package/src/sextant/draw-messages.ts +386 -0
- package/src/sextant/draw-pet.ts +230 -0
- package/src/sextant/draw-plan.ts +159 -0
- package/src/sextant/draw-tabs.ts +85 -0
- package/src/sextant/draw-util.ts +65 -0
- package/src/sextant/engine.ts +230 -0
- package/src/sextant/frame-hits.ts +25 -0
- package/src/sextant/frame.ts +101 -0
- package/src/sextant/git-status.ts +197 -0
- package/src/sextant/grid.ts +59 -0
- package/src/sextant/input.ts +119 -0
- package/src/sextant/keys.ts +488 -0
- package/src/sextant/layout.ts +86 -0
- package/src/sextant/local-commands.ts +156 -0
- package/src/sextant/market-source.ts +287 -0
- package/src/sextant/mentions.ts +141 -0
- package/src/sextant/message-hits.ts +26 -0
- package/src/sextant/model.ts +387 -0
- package/src/sextant/overlays.ts +451 -0
- package/src/sextant/panel-hits.ts +38 -0
- package/src/sextant/pet.ts +399 -0
- package/src/sextant/screen.ts +324 -0
- package/src/sextant/scroll-hits.ts +66 -0
- package/src/sextant/scrollbar.ts +82 -0
- package/src/sextant/selection.ts +123 -0
- package/src/sextant/sextant-bridge.ts +174 -0
- package/src/sextant/sextant-cards.ts +142 -0
- package/src/sextant/sextant-diff-base.ts +63 -0
- package/src/sextant/sextant-files.ts +154 -0
- package/src/sextant/sextant-frame-loop.ts +314 -0
- package/src/sextant/sextant-renderer.ts +478 -0
- package/src/sextant/sextant-repo.ts +131 -0
- package/src/sextant/theme.ts +66 -0
- package/src/sextant/tool-rows.ts +189 -0
- package/src/sextant/types.ts +473 -0
- package/src/skills/index.ts +306 -0
- package/src/skills/tools.ts +69 -0
- package/src/skills/versioned.ts +227 -0
- package/src/telemetry/otel.ts +353 -0
- package/src/telemetry/otlp.ts +68 -0
- package/src/tools/ask-user.ts +156 -0
- package/src/tools/design.ts +151 -0
- package/src/tools/evalcell.ts +338 -0
- package/src/tools/html-text.ts +139 -0
- package/src/tools/provider.ts +149 -0
- package/src/tools/task.ts +216 -0
- package/src/tools/todo.ts +320 -0
- package/src/tools/webfetch.ts +331 -0
- package/src/tui/app.ts +608 -0
- package/src/tui/attach.ts +127 -0
- package/src/tui/checkpoints-cmd.ts +70 -0
- package/src/tui/clipboard-image.ts +81 -0
- package/src/tui/commands.ts +277 -0
- package/src/tui/cost.ts +108 -0
- package/src/tui/info-cmd.ts +144 -0
- package/src/tui/mcp-cmd.ts +128 -0
- package/src/tui/modes-cmd.ts +45 -0
- package/src/tui/overlays.ts +97 -0
- package/src/tui/pi-renderer.ts +424 -0
- package/src/tui/providers-cmd.ts +366 -0
- package/src/tui/renderer.ts +101 -0
- package/src/tui/replay-marker.ts +29 -0
- package/src/tui/session-cmd.ts +146 -0
- package/src/tui/sextant-attach.ts +68 -0
- package/src/tui/sextant-io.ts +184 -0
- package/src/tui/sextant-smoke.ts +110 -0
- package/src/tui/smoke.ts +72 -0
- package/src/tui/theme.ts +59 -0
- package/src/tui/todo-label.ts +7 -0
- package/src/workflow/engine.ts +266 -0
- package/tsconfig.json +30 -0
- package/vendor/pi-tui/LICENSE +21 -0
- package/vendor/pi-tui/PATCHES.md +12 -0
- package/vendor/pi-tui/PROVENANCE.md +12 -0
- package/vendor/pi-tui/README.upstream.md +854 -0
- package/vendor/pi-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
- package/vendor/pi-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
- package/vendor/pi-tui/src/alt-screen-search.ts +158 -0
- package/vendor/pi-tui/src/autocomplete.ts +827 -0
- package/vendor/pi-tui/src/components/alt-screen-flash.ts +52 -0
- package/vendor/pi-tui/src/components/box.ts +138 -0
- package/vendor/pi-tui/src/components/cancellable-loader.ts +41 -0
- package/vendor/pi-tui/src/components/editor.ts +2364 -0
- package/vendor/pi-tui/src/components/h-stack.ts +45 -0
- package/vendor/pi-tui/src/components/image.ts +128 -0
- package/vendor/pi-tui/src/components/input.ts +448 -0
- package/vendor/pi-tui/src/components/loader.ts +93 -0
- package/vendor/pi-tui/src/components/markdown.ts +1016 -0
- package/vendor/pi-tui/src/components/scroll-view.ts +217 -0
- package/vendor/pi-tui/src/components/select-list.ts +230 -0
- package/vendor/pi-tui/src/components/settings-list.ts +277 -0
- package/vendor/pi-tui/src/components/spacer.ts +29 -0
- package/vendor/pi-tui/src/components/stack.ts +155 -0
- package/vendor/pi-tui/src/components/text.ts +108 -0
- package/vendor/pi-tui/src/components/truncated-text.ts +66 -0
- package/vendor/pi-tui/src/components/v-stack.ts +34 -0
- package/vendor/pi-tui/src/editor-component.ts +75 -0
- package/vendor/pi-tui/src/fuzzy.ts +138 -0
- package/vendor/pi-tui/src/index.ts +149 -0
- package/vendor/pi-tui/src/keybindings.ts +321 -0
- package/vendor/pi-tui/src/keys.ts +1402 -0
- package/vendor/pi-tui/src/kill-ring.ts +47 -0
- package/vendor/pi-tui/src/latex.ts +1381 -0
- package/vendor/pi-tui/src/layout-node.ts +52 -0
- package/vendor/pi-tui/src/layout.ts +411 -0
- package/vendor/pi-tui/src/native-modifiers.ts +60 -0
- package/vendor/pi-tui/src/native-module-path.ts +32 -0
- package/vendor/pi-tui/src/stdin-buffer.ts +445 -0
- package/vendor/pi-tui/src/terminal-colors.ts +74 -0
- package/vendor/pi-tui/src/terminal-image.ts +701 -0
- package/vendor/pi-tui/src/terminal.ts +554 -0
- package/vendor/pi-tui/src/tui-alt-screen.ts +1379 -0
- package/vendor/pi-tui/src/tui-main-screen.ts +655 -0
- package/vendor/pi-tui/src/tui.ts +1264 -0
- package/vendor/pi-tui/src/undo-stack.ts +29 -0
- package/vendor/pi-tui/src/utils.ts +1327 -0
- package/vendor/pi-tui/src/word-navigation.ts +118 -0
- package/vendor/pi-tui/test/test-themes.ts +39 -0
- package/vendor/pi-tui/test/virtual-terminal.ts +219 -0
- package/CHANGELOG.md +0 -527
- package/bin/rovecode.js +0 -24
- package/dist/cli/app-j6gn14w3.js +0 -2
- package/dist/cli/ask-user-cwstt8fz.js +0 -2
- package/dist/cli/auth-login-9bbp9915.js +0 -2
- package/dist/cli/auth-m8p9grty.js +0 -2
- package/dist/cli/bench-16zqdms5.js +0 -9
- package/dist/cli/catalog-1xchffa4.js +0 -2
- package/dist/cli/cli-1n1zb64f.js +0 -2
- package/dist/cli/client-2t9gjkck.js +0 -2
- package/dist/cli/commands-exafvm2b.js +0 -2
- package/dist/cli/connect-6zde0kn3.js +0 -2
- package/dist/cli/context-cmd-5t43wgqt.js +0 -2
- package/dist/cli/context-report-kt01pw8y.js +0 -2
- package/dist/cli/count-remote-ap7x3vh6.js +0 -2
- package/dist/cli/design-ne5zszyh.js +0 -2
- package/dist/cli/dispatch-2r5myxye.js +0 -2
- package/dist/cli/doctor-ws4fh4tn.js +0 -3
- package/dist/cli/executor-bdrjn634.js +0 -2
- package/dist/cli/export-1mxb9g5p.js +0 -2
- package/dist/cli/files-g104xghh.js +0 -2
- package/dist/cli/gauntlet-07xrjpj7.js +0 -2
- package/dist/cli/gauntlet-runner-xvy64436.js +0 -10
- package/dist/cli/gauntlet-wave3-jm91yt5w.js +0 -5
- package/dist/cli/gauntlet-wave4-r13py7p1.js +0 -14
- package/dist/cli/hashline-znvrat11.js +0 -2
- package/dist/cli/http-xafw6fsh.js +0 -143
- package/dist/cli/index-1sgjm25y.js +0 -2
- package/dist/cli/init-g2m0tn4m.js +0 -51
- package/dist/cli/install-avaqjjqq.js +0 -2
- package/dist/cli/loop-mmpfft01.js +0 -2
- package/dist/cli/main-0904f6ps.js +0 -5
- package/dist/cli/main-0ab9fc26.js +0 -9
- package/dist/cli/main-0jys2ccn.js +0 -3
- package/dist/cli/main-0mtcdbs7.js +0 -3
- package/dist/cli/main-0z1w2zsg.js +0 -3
- package/dist/cli/main-1dchs7xv.js +0 -18
- package/dist/cli/main-1ereejm1.js +0 -3
- package/dist/cli/main-1k1kw6b5.js +0 -3
- package/dist/cli/main-27y4sm2k.js +0 -38
- package/dist/cli/main-2wwjex5j.js +0 -58
- package/dist/cli/main-2yeveeve.js +0 -6
- package/dist/cli/main-2yfck9b5.js +0 -3
- package/dist/cli/main-2zmzgkwh.js +0 -3
- package/dist/cli/main-351pz3z7.js +0 -7
- package/dist/cli/main-3gjqfh7a.js +0 -6
- package/dist/cli/main-3nf3kgve.js +0 -3
- package/dist/cli/main-3pjrb2hd.js +0 -3
- package/dist/cli/main-3rxcvgna.js +0 -19
- package/dist/cli/main-4b3jgy66.js +0 -19
- package/dist/cli/main-4wndhjdc.js +0 -7
- package/dist/cli/main-4xcmvxnk.js +0 -3
- package/dist/cli/main-5tbz0wbz.js +0 -4
- package/dist/cli/main-5ywnwthm.js +0 -3
- package/dist/cli/main-6b62vkz0.js +0 -14
- package/dist/cli/main-6dnk69vp.js +0 -3
- package/dist/cli/main-6genrmhs.js +0 -136
- package/dist/cli/main-73g7eff4.js +0 -15
- package/dist/cli/main-7c5thhjd.js +0 -5
- package/dist/cli/main-7rn6bqje.js +0 -3
- package/dist/cli/main-80haw7qk.js +0 -4
- package/dist/cli/main-875s60s2.js +0 -4
- package/dist/cli/main-8kjxbpw4.js +0 -8
- package/dist/cli/main-90ds1z4e.js +0 -10
- package/dist/cli/main-9etavkew.js +0 -3
- package/dist/cli/main-a9njrkk1.js +0 -3
- package/dist/cli/main-aecrjq2d.js +0 -12
- package/dist/cli/main-ck9asesq.js +0 -9
- package/dist/cli/main-cta9racd.js +0 -4
- package/dist/cli/main-ddv7j2ag.js +0 -3
- package/dist/cli/main-dfreez27.js +0 -10
- package/dist/cli/main-f7rw7des.js +0 -3
- package/dist/cli/main-ggcn7rd7.js +0 -5
- package/dist/cli/main-gzkmycnv.js +0 -3
- package/dist/cli/main-hq51jg8v.js +0 -18
- package/dist/cli/main-jft389w9.js +0 -8
- package/dist/cli/main-k1eqkg83.js +0 -3
- package/dist/cli/main-k2y8a2aw.js +0 -9
- package/dist/cli/main-kcpbykxz.js +0 -4
- package/dist/cli/main-kd488vje.js +0 -22
- package/dist/cli/main-kh32yvgk.js +0 -5
- package/dist/cli/main-kqxnqjnv.js +0 -25
- package/dist/cli/main-kyn0xnsg.js +0 -3
- package/dist/cli/main-m1kk6fp5.js +0 -21
- package/dist/cli/main-mv40pcr2.js +0 -4
- package/dist/cli/main-n0t3973w.js +0 -3
- package/dist/cli/main-nqveez48.js +0 -4
- package/dist/cli/main-pknhvrmj.js +0 -3
- package/dist/cli/main-pn1w7a7j.js +0 -3
- package/dist/cli/main-prxxs70n.js +0 -4
- package/dist/cli/main-q3vsesf9.js +0 -3
- package/dist/cli/main-qsevpgsv.js +0 -3
- package/dist/cli/main-rdgdw24b.js +0 -25
- package/dist/cli/main-rfth4tbm.js +0 -16
- package/dist/cli/main-rg0wn0xf.js +0 -5
- package/dist/cli/main-sdmxhtv8.js +0 -4
- package/dist/cli/main-skbp13js.js +0 -18
- package/dist/cli/main-t4xnd213.js +0 -7
- package/dist/cli/main-vqak588n.js +0 -4
- package/dist/cli/main-w2n1303f.js +0 -9
- package/dist/cli/main-wbrdspr2.js +0 -5
- package/dist/cli/main-wsrg79c1.js +0 -7
- package/dist/cli/main-x4r0fne4.js +0 -5
- package/dist/cli/main-xea2f3tn.js +0 -6
- package/dist/cli/main-xg704a3c.js +0 -3
- package/dist/cli/main-xvnrabfp.js +0 -16
- package/dist/cli/main-xy53xf0r.js +0 -4
- package/dist/cli/main-y1fqy60y.js +0 -3
- package/dist/cli/main-yn8cd281.js +0 -34
- package/dist/cli/main-yr0ksc0h.js +0 -4
- package/dist/cli/main-z2ex2vyf.js +0 -4
- package/dist/cli/main-z3aayzvq.js +0 -3
- package/dist/cli/main-zaqh35jg.js +0 -3
- package/dist/cli/main-zc2e8e46.js +0 -4
- package/dist/cli/main-zzrfw6cf.js +0 -13
- package/dist/cli/main.js +0 -280
- package/dist/cli/market-cmd-e14kmx9n.js +0 -5
- package/dist/cli/mcp-login-wq7ktdek.js +0 -2
- package/dist/cli/mcp-market-cmd-9mg3jecy.js +0 -2
- package/dist/cli/notify-b7qc0cjb.js +0 -2
- package/dist/cli/oauth-z8whcgfx.js +0 -2
- package/dist/cli/output-b3ewj3ps.js +0 -16
- package/dist/cli/profiles-6mr5he5e.js +0 -2
- package/dist/cli/provider-config-g7j42q8x.js +0 -2
- package/dist/cli/provider-jr1y8vvm.js +0 -2
- package/dist/cli/registry-s8yk86g0.js +0 -2
- package/dist/cli/registry-t6p8d4mn.js +0 -2
- package/dist/cli/repl-bajwe1mh.js +0 -11
- package/dist/cli/resume-rwn9nz7y.js +0 -2
- package/dist/cli/run-flags-nah7ndpt.js +0 -2
- package/dist/cli/runtime-n7gafzhb.js +0 -2
- package/dist/cli/sandbox-config-emdy18x4.js +0 -2
- package/dist/cli/server-b0nvs2bn.js +0 -5
- package/dist/cli/session-arg-y75wd4kj.js +0 -2
- package/dist/cli/session-j62evmjq.js +0 -2
- package/dist/cli/sessions-cmd-tsnwz0ns.js +0 -7
- package/dist/cli/settings-df10wfez.js +0 -2
- package/dist/cli/setup-jzvv72fg.js +0 -2
- package/dist/cli/sextant-smoke-37m81ke6.js +0 -5
- package/dist/cli/skills-cmd-gjxnxnhx.js +0 -2
- package/dist/cli/smoke-p7748apt.js +0 -8
- package/dist/cli/start-chat-s4st3mm0.js +0 -12
- package/dist/cli/stream-gmeyewds.js +0 -2
- package/dist/cli/task-gh0kkp3n.js +0 -2
- package/dist/cli/tasks-z1kfpe8e.js +0 -2
- package/dist/cli/thinking-0eqkrz6t.js +0 -2
- package/dist/cli/todo-5brcrt9m.js +0 -2
- package/dist/cli/tools-7pzm0vj9.js +0 -2
- package/dist/cli/tools-s635p6s8.js +0 -2
- package/dist/cli/trust-cmd-cjav8zgm.js +0 -2
- package/dist/cli/update-check-pt31bm2f.js +0 -2
- package/dist/cli/update-cmd-tk131s9t.js +0 -2
- package/dist/cli/voice-56nabd8d.js +0 -2
- package/dist/cli/webfetch-xd8q596m.js +0 -2
- package/dist/cli/websearch-5hkf98k1.js +0 -2
- package/dist/cli/workflow-cmd-cy3cvzjp.js +0 -4
- package/dist/cli/workspace-q10g5z3e.js +0 -2
- package/dist/lib/index.js +0 -62
- package/dist/lib/models-index.json +0 -1
- package/dist/lib/plugins.js +0 -55
- package/dist/lib/providers.js +0 -17
- package/dist/lib/public-api.js +0 -20
- package/dist/lib/sdk.js +0 -360
- /package/{dist/cli → src/providers}/models-index.json +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** Cloning at a ref, and the one subtle decision in it.
|
|
2
|
+
*
|
|
3
|
+
* `--ref` takes a branch, a tag or a commit, and git needs a DIFFERENT command for the last one:
|
|
4
|
+
* `clone --depth 1 --branch <x>` works for a branch or a tag and fails for a bare commit, so a commit has
|
|
5
|
+
* to go through `init` + `fetch --depth 1 <url> <sha>` + `checkout FETCH_HEAD`.
|
|
6
|
+
*
|
|
7
|
+
* We do not decide which one `<x>` is by looking at it. `/^[0-9a-f]{7,40}$/` is a guess, and a wrong guess
|
|
8
|
+
* here installs the wrong tree silently: `abcdef` is a perfectly legal branch name, and a repository that
|
|
9
|
+
* has one would be pinned to a commit that merely shares the spelling. Git's answer is a fact, so we ask
|
|
10
|
+
* git: try the branch form, and use the commit form only when that fails.
|
|
11
|
+
*
|
|
12
|
+
* ORDER IS A DECISION, not a side effect. When a name is BOTH a branch and the short id of some commit,
|
|
13
|
+
* the branch wins, because someone typing `--ref` almost always means a name. That is why the branch form
|
|
14
|
+
* is tried first, and the manifest records `resolvedBy` so the question "was this a branch or a commit?"
|
|
15
|
+
* has an answer afterwards rather than a shrug.
|
|
16
|
+
*
|
|
17
|
+
* One deliberate refusal: fetching a bare SHA needs `uploadpack.allowReachableSHA1InWant` on the server,
|
|
18
|
+
* and plenty of hosts leave it off. When that is refused we STOP and say so. The alternative — quietly
|
|
19
|
+
* dropping `--depth` and cloning the entire history — turns a pin into a very long download the person
|
|
20
|
+
* did not ask for, and they would have no idea why. */
|
|
21
|
+
|
|
22
|
+
export type Spawn = (cmd: string[], cwd: string) => Promise<{ code: number; stderr: string }>;
|
|
23
|
+
|
|
24
|
+
export type ResolvedBy = "branch" | "commit" | "default";
|
|
25
|
+
|
|
26
|
+
export interface CloneResult {
|
|
27
|
+
ok: true;
|
|
28
|
+
/** which form of the command actually produced the tree */
|
|
29
|
+
resolvedBy: ResolvedBy;
|
|
30
|
+
}
|
|
31
|
+
export type CloneOutcome = CloneResult | { ok: false; error: string };
|
|
32
|
+
|
|
33
|
+
/** the last line of git's complaint, which is the part a person can act on */
|
|
34
|
+
const lastLine = (stderr: string): string => stderr.trim().split("\n").at(-1)?.trim() ?? "";
|
|
35
|
+
|
|
36
|
+
/** a server that will not serve a bare commit says so in one of a few ways; all of them mean the same
|
|
37
|
+
* thing to us, and none of them should be answered by fetching more */
|
|
38
|
+
function refusesBareSha(stderr: string): boolean {
|
|
39
|
+
return /allow.*sha1.*in.?want|not our ref|unadvertised object|Server does not allow request for unadvertised object/i.test(stderr);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Clone `url` into `dir` (which must exist and be empty), optionally at `ref`. */
|
|
43
|
+
/** `--` before every positional, on purpose. git parses options wherever it finds them, so a value that
|
|
44
|
+
* begins with a dash is read as an option no matter which slot it sits in: a ref or a URL spelled
|
|
45
|
+
* `--upload-pack=...` becomes an instruction rather than a name. Catalog data cannot reach here in that
|
|
46
|
+
* shape (`url()` filters it), but `market install <git-url>` and `--ref` come straight from a command
|
|
47
|
+
* line. The marker costs one argument and says "what follows is a value", which is the claim we mean. */
|
|
48
|
+
export async function cloneAtRef(spawn: Spawn, url: string, dir: string, ref?: string): Promise<CloneOutcome> {
|
|
49
|
+
if (ref === undefined || ref.trim() === "") {
|
|
50
|
+
const r = await spawn(["git", "clone", "--depth", "1", "--quiet", "--", url, "."], dir);
|
|
51
|
+
return r.code === 0 ? { ok: true, resolvedBy: "default" } : { ok: false, error: `git clone failed (exit ${r.code})${lastLine(r.stderr) ? `: ${lastLine(r.stderr)}` : ""}` };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 1. a branch or a tag — the common case, and the winner when a name is both
|
|
55
|
+
const branch = await spawn(["git", "clone", "--depth", "1", "--quiet", "--branch", ref, "--", url, "."], dir);
|
|
56
|
+
if (branch.code === 0) return { ok: true, resolvedBy: "branch" };
|
|
57
|
+
|
|
58
|
+
// 2. a commit. Not a fallback for "anything went wrong": if the failure was the network or auth, the
|
|
59
|
+
// fetch will fail the same way and we report THAT, not a misleading "no such ref".
|
|
60
|
+
const init = await spawn(["git", "init", "--quiet"], dir);
|
|
61
|
+
if (init.code !== 0) return { ok: false, error: `git init failed (exit ${init.code})${lastLine(init.stderr) ? `: ${lastLine(init.stderr)}` : ""}` };
|
|
62
|
+
const fetch = await spawn(["git", "fetch", "--depth", "1", "--quiet", "--", url, ref], dir);
|
|
63
|
+
if (fetch.code !== 0) {
|
|
64
|
+
if (refusesBareSha(fetch.stderr)) {
|
|
65
|
+
return { ok: false, error: `${url} will not serve the single commit ${ref} (the server has uploadpack.allowReachableSHA1InWant off) — give a branch or tag instead, or ask the host to enable it` };
|
|
66
|
+
}
|
|
67
|
+
return { ok: false, error: `"${ref}" is not a branch or tag there, and fetching it as a commit failed (exit ${fetch.code})${lastLine(fetch.stderr) ? `: ${lastLine(fetch.stderr)}` : ""}` };
|
|
68
|
+
}
|
|
69
|
+
const checkout = await spawn(["git", "checkout", "--quiet", "FETCH_HEAD"], dir);
|
|
70
|
+
if (checkout.code !== 0) return { ok: false, error: `fetched ${ref} but could not check it out (exit ${checkout.code})${lastLine(checkout.stderr) ? `: ${lastLine(checkout.stderr)}` : ""}` };
|
|
71
|
+
return { ok: true, resolvedBy: "commit" };
|
|
72
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/** What installing this item costs you in context, said before the yes.
|
|
2
|
+
*
|
|
3
|
+
* THE NUMBER IS TWO NUMBERS, and collapsing them would be the whole feature's undoing. rovecode's skills
|
|
4
|
+
* are progressive disclosure: `buildSkillsIndex` puts one line per skill in the system prompt — the name,
|
|
5
|
+
* the version and the clipped description — and the SKILL.md body enters context only when the model calls
|
|
6
|
+
* `skill_view`. Measured across the 19 skills that ship: the index line averages 79 tokens, the body
|
|
7
|
+
* averages 2,288. A single "costs ~2.3k tokens per turn" would be 29× the truth for a skill nobody opens,
|
|
8
|
+
* and a reader who checked once would never trust the line again.
|
|
9
|
+
*
|
|
10
|
+
* So: `perTurn` is what every request carries, `whenUsed` is what arrives if the model opens it.
|
|
11
|
+
*
|
|
12
|
+
* WHAT CANNOT BE KNOWN is said instead of guessed:
|
|
13
|
+
* - an MCP server publishes its tool schemas after it connects. Before that there is no number, and
|
|
14
|
+
* inventing one would spend this line's credibility on the day it shipped.
|
|
15
|
+
* - a plugin's entry module contributes tools whose schemas we would have to LOAD ITS CODE to read,
|
|
16
|
+
* which is exactly what a plan must not do. Its skills and commands directories are files, so those
|
|
17
|
+
* are measured.
|
|
18
|
+
*
|
|
19
|
+
* THE ESTIMATE IS SCALED, NOT CAVEATED. `countTokens` is gpt-tokenizer's o200k_base and Anthropic's
|
|
20
|
+
* tokenizer is not public, so for a Claude model the raw count is simply wrong — measured against
|
|
21
|
+
* Anthropic's own count_tokens endpoint over all 19 skill bodies that ship, it reads 1.41×–1.79× low
|
|
22
|
+
* (mean 1.59×). Rather than describe that in prose, the numbers are multiplied by `tokenScaleFor`, which
|
|
23
|
+
* holds a measured factor per model generation. An earlier draft of this file said "reads roughly a third
|
|
24
|
+
* low on Anthropic models"; that was already wrong for Claude 4.5, where the factor is 1.21×, and a
|
|
25
|
+
* sentence like it is wrong again every time a model ships.
|
|
26
|
+
*
|
|
27
|
+
* When no model is named the numbers are left unscaled and the line says so. When the provider's own
|
|
28
|
+
* tokenizer IS o200k — OpenAI — there is nothing to scale and the line says that instead. A model nobody
|
|
29
|
+
* has measured is never given a neighbour's factor.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import { tokenScaleFor, type TokenScale } from "../core/token-scale.ts";
|
|
33
|
+
import { countTokens } from "../core/usage.ts";
|
|
34
|
+
import { INDEX_PROMPT_LIMIT } from "../skills/tools.ts";
|
|
35
|
+
import type { MarketItem } from "./types.ts";
|
|
36
|
+
|
|
37
|
+
export interface ContextCost {
|
|
38
|
+
/** tokens added to EVERY request while this is installed */
|
|
39
|
+
perTurn: number;
|
|
40
|
+
/** tokens added only when the model opens it; absent when there is no such body */
|
|
41
|
+
whenUsed?: number;
|
|
42
|
+
/** the tokenizer the numbers came from — named because it is not the model's */
|
|
43
|
+
tokenizer: "o200k_base";
|
|
44
|
+
/** a part of the cost that cannot be known before installing, and why */
|
|
45
|
+
unknown?: string;
|
|
46
|
+
/** installing this would push the skill count past the index limit; see `INDEX_PROMPT_LIMIT` */
|
|
47
|
+
overIndexLimit?: boolean;
|
|
48
|
+
/** how wrong the estimate is for the model that will carry it, when a measurement exists for it */
|
|
49
|
+
scale?: TokenScale;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface ContextCostOptions {
|
|
53
|
+
/** how many skills are already installed, so the index-limit warning can be right */
|
|
54
|
+
installedSkills?: number;
|
|
55
|
+
/** the model that will actually carry this, so the estimate can be scaled by a MEASURED factor rather
|
|
56
|
+
* than described with a hand-written one. Omit it and the line says the number is unscaled. */
|
|
57
|
+
model?: { provider: string; model: string };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** The system-prompt line `buildSkillsIndex` renders, rebuilt from catalog fields so the count describes
|
|
61
|
+
* what would actually be in the prompt rather than an approximation of it (skills/tools.ts
|
|
62
|
+
* renderIndexLine). The description is already clipped to 60 characters by the skill reader. */
|
|
63
|
+
const indexLine = (item: MarketItem): string =>
|
|
64
|
+
`- ${item.id}${item.version ? ` (v${item.version})` : ""}: ${item.description}`;
|
|
65
|
+
|
|
66
|
+
export function contextCostOf(item: MarketItem, opts: ContextCostOptions = {}): ContextCost | undefined {
|
|
67
|
+
const install = item.install;
|
|
68
|
+
|
|
69
|
+
if (install.kind === "mcp") {
|
|
70
|
+
// Deliberately no numbers. A server's tools are whatever it reports on connect.
|
|
71
|
+
return { perTurn: 0, tokenizer: "o200k_base",
|
|
72
|
+
unknown: "an MCP server's tools are only known once it connects, so its context cost cannot be measured before you install it" };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (install.kind === "skill") {
|
|
76
|
+
const body = item.docs?.body;
|
|
77
|
+
const cost: ContextCost = { perTurn: countTokens(indexLine(item)), tokenizer: "o200k_base" };
|
|
78
|
+
if (opts.model !== undefined) cost.scale = tokenScaleFor(opts.model);
|
|
79
|
+
if (body !== undefined) cost.whenUsed = countTokens(body);
|
|
80
|
+
else cost.unknown = "the SKILL.md is not carried in the catalog, so only the index line can be measured here";
|
|
81
|
+
const installed = opts.installedSkills;
|
|
82
|
+
if (installed !== undefined && installed + 1 > INDEX_PROMPT_LIMIT) cost.overIndexLimit = true;
|
|
83
|
+
return cost;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// A plugin, and the answer is nothing measurable — for two separate reasons, both worth stating plainly
|
|
87
|
+
// rather than papering over with a number:
|
|
88
|
+
// its entry module registers tools whose schemas need the code LOADED to read, which a plan must not do;
|
|
89
|
+
// its commands and skills are files inside the repository, and the catalog carries the plugin's README,
|
|
90
|
+
// not those files — measuring them would mean cloning during a preview.
|
|
91
|
+
return { perTurn: 0, tokenizer: "o200k_base",
|
|
92
|
+
unknown: "a plugin's context cost cannot be measured from the catalog: its tools need the code loaded to read, and its commands and skills are files that are only fetched when you install it" };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const n = (t: number): string => (t >= 1000 ? `${(t / 1000).toFixed(1)}k` : String(t));
|
|
96
|
+
|
|
97
|
+
/** The plan's line(s). Returns [] when there is nothing worth saying. */
|
|
98
|
+
export function contextCostLines(c: ContextCost | undefined): string[] {
|
|
99
|
+
if (c === undefined) return [];
|
|
100
|
+
const lines: string[] = [];
|
|
101
|
+
|
|
102
|
+
if (c.perTurn > 0 || c.whenUsed !== undefined) {
|
|
103
|
+
// When a measurement exists for the model in play, the numbers are SCALED BY IT rather than described
|
|
104
|
+
// with a hand-written caveat. "Reads roughly a third low on Anthropic models" was wrong the moment
|
|
105
|
+
// token-scale.ts had two Anthropic generations in it: 1.59x on Claude 5 and 1.21x on 4.5. A sentence
|
|
106
|
+
// that has to be rewritten every time a model ships is a sentence that will be wrong between ships.
|
|
107
|
+
const k = c.scale?.measured === true ? c.scale.scale : 1;
|
|
108
|
+
const turn = `~${n(Math.round(c.perTurn * k))} tokens every turn`;
|
|
109
|
+
const used = c.whenUsed !== undefined ? `, ~${n(Math.round(c.whenUsed * k))} more when the model opens it` : "";
|
|
110
|
+
lines.push(`${turn}${used}`);
|
|
111
|
+
if (c.scale === undefined) lines.push(`counted with o200k_base, which is not every model's tokenizer — unscaled here because no model was named`);
|
|
112
|
+
else if (!c.scale.measured) lines.push(`counted with o200k_base — ${c.scale.note}`);
|
|
113
|
+
else if (k === 1) lines.push(`counted with o200k_base — ${c.scale.note}`);
|
|
114
|
+
else lines.push(`o200k_base scaled ${k}× for this model — ${c.scale.note}`);
|
|
115
|
+
}
|
|
116
|
+
if (c.overIndexLimit) {
|
|
117
|
+
lines.push(`past ${INDEX_PROMPT_LIMIT} skills the index leaves the prompt entirely and the model lists skills with a tool instead — this changes the cost of every skill you have, not just this one`);
|
|
118
|
+
}
|
|
119
|
+
if (c.unknown !== undefined) lines.push(c.unknown);
|
|
120
|
+
return lines;
|
|
121
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/** What landed on disk, as one number — so "has this changed since I installed it?" has an answer.
|
|
2
|
+
*
|
|
3
|
+
* `--ref` pins what we ASK for; a digest is what we GOT. The two answer different questions and the second
|
|
4
|
+
* is the one that survives: a commit id says the remote pointed there at fetch time, a digest says the
|
|
5
|
+
* bytes on this machine are still the bytes that arrived. Nobody in this space signs anything, so a
|
|
6
|
+
* recorded digest is the honest ceiling — it detects drift, it does not prove provenance, and the wording
|
|
7
|
+
* everywhere says the former.
|
|
8
|
+
*
|
|
9
|
+
* Over a FOLDER, the hash covers the relative path and the content of every file, in a sorted order, so it
|
|
10
|
+
* is stable across platforms and independent of the order a directory happens to list. `.git` is excluded:
|
|
11
|
+
* it is fetch bookkeeping, it differs between a clone and a copy of the same tree, and including it would
|
|
12
|
+
* make every digest disagree with itself for no reason a person could act on.
|
|
13
|
+
*
|
|
14
|
+
* Line endings are NOT normalised. A file that arrives with CRLF and later has LF is genuinely different
|
|
15
|
+
* content, and on a repository that has been through a Windows checkout that difference is exactly the
|
|
16
|
+
* kind of thing someone would want reported rather than hidden. */
|
|
17
|
+
|
|
18
|
+
import { createHash } from "node:crypto";
|
|
19
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
20
|
+
import { join, relative, sep } from "node:path";
|
|
21
|
+
|
|
22
|
+
export interface Digest {
|
|
23
|
+
algo: "sha256";
|
|
24
|
+
/** hex */
|
|
25
|
+
value: string;
|
|
26
|
+
/** how many files went into it — a cheap sanity check when two digests differ */
|
|
27
|
+
files: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Every file under `dir`, relative and slash-separated, sorted. Excludes `.git`. */
|
|
31
|
+
function walk(dir: string): string[] {
|
|
32
|
+
const out: string[] = [];
|
|
33
|
+
const stack = [dir];
|
|
34
|
+
while (stack.length > 0) {
|
|
35
|
+
const here = stack.pop()!;
|
|
36
|
+
let names: string[];
|
|
37
|
+
try { names = readdirSync(here); } catch { continue; }
|
|
38
|
+
for (const name of names) {
|
|
39
|
+
if (name === ".git") continue;
|
|
40
|
+
const full = join(here, name);
|
|
41
|
+
let st;
|
|
42
|
+
try { st = statSync(full); } catch { continue; }
|
|
43
|
+
// a symlink is never followed: install refuses them, and following one here would hash something
|
|
44
|
+
// outside the folder we claim to be describing
|
|
45
|
+
if (st.isDirectory()) { stack.push(full); continue; }
|
|
46
|
+
if (st.isFile()) out.push(relative(dir, full).split(sep).join("/"));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return out.sort();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** The digest of a file or a folder. Undefined when the path is not there — a missing thing has no
|
|
53
|
+
* digest, and pretending it has one of an empty folder would make "deleted" and "emptied" look alike. */
|
|
54
|
+
export function digestOf(path: string): Digest | undefined {
|
|
55
|
+
if (!existsSync(path)) return undefined;
|
|
56
|
+
const hash = createHash("sha256");
|
|
57
|
+
let files = 0;
|
|
58
|
+
try {
|
|
59
|
+
if (statSync(path).isFile()) {
|
|
60
|
+
hash.update(readFileSync(path));
|
|
61
|
+
files = 1;
|
|
62
|
+
} else {
|
|
63
|
+
for (const rel of walk(path)) {
|
|
64
|
+
// the PATH goes in too: moving a file's content to another name is a change
|
|
65
|
+
hash.update(rel);
|
|
66
|
+
hash.update("\0");
|
|
67
|
+
hash.update(readFileSync(join(path, rel)));
|
|
68
|
+
hash.update("\0");
|
|
69
|
+
files += 1;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} catch { return undefined; }
|
|
73
|
+
return { algo: "sha256", value: hash.digest("hex"), files };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type VerifyState =
|
|
77
|
+
/** the bytes are what they were */
|
|
78
|
+
| { state: "unchanged"; digest: Digest }
|
|
79
|
+
/** it is still installed, and it is not what it was */
|
|
80
|
+
| { state: "changed"; recorded: Digest; now: Digest }
|
|
81
|
+
/** it was installed and is no longer there */
|
|
82
|
+
| { state: "missing"; recorded: Digest }
|
|
83
|
+
/** there is nothing recorded to compare against; not a failure */
|
|
84
|
+
| { state: "unrecorded"; now?: Digest }
|
|
85
|
+
/** the kind carries no digest by design (an MCP entry is a line in a shared file) */
|
|
86
|
+
| { state: "not-applicable"; why: string };
|
|
87
|
+
|
|
88
|
+
/** Compare what is on disk with what was recorded. Pure over its inputs apart from reading the path. */
|
|
89
|
+
export function verifyDigest(recorded: Digest | undefined, path: string | undefined): VerifyState {
|
|
90
|
+
if (path === undefined) return { state: "not-applicable", why: "this kind of install has no folder of its own to hash" };
|
|
91
|
+
const now = digestOf(path);
|
|
92
|
+
if (recorded === undefined) return now === undefined ? { state: "unrecorded" } : { state: "unrecorded", now };
|
|
93
|
+
if (now === undefined) return { state: "missing", recorded };
|
|
94
|
+
return now.value === recorded.value ? { state: "unchanged", digest: now } : { state: "changed", recorded, now };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** One line for `market verify`, in the words the state deserves. */
|
|
98
|
+
export function verifyLine(id: string, v: VerifyState): string {
|
|
99
|
+
switch (v.state) {
|
|
100
|
+
case "unchanged": return `${id} unchanged (${v.digest.files} file${v.digest.files === 1 ? "" : "s"})`;
|
|
101
|
+
case "changed": return `${id} CHANGED since install — recorded ${v.recorded.value.slice(0, 12)} (${v.recorded.files} files), now ${v.now.value.slice(0, 12)} (${v.now.files} files)`;
|
|
102
|
+
case "missing": return `${id} gone from disk, but a record remains`;
|
|
103
|
+
case "unrecorded": return `${id} no digest recorded — installed before rovecode kept one, or by hand`;
|
|
104
|
+
case "not-applicable": return `${id} ${v.why}`;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** The market's public face. Every surface — the CLI, the sextant's /market, the site's build step —
|
|
2
|
+
* imports from here and from nowhere deeper, so the internals can move without touching them.
|
|
3
|
+
*
|
|
4
|
+
* Importing this module pulls in `registry.ts` and `install.ts`, which reach the MCP and plugin modules;
|
|
5
|
+
* it is NOT free, so keep it off the boot path (cli/main.ts loads `market-cmd.ts` with a dynamic import
|
|
6
|
+
* inside `case "market"`, and the TUI should reach it the same way, on first use). `types.ts` alone is
|
|
7
|
+
* free — import that directly when all you need is a shape. */
|
|
8
|
+
|
|
9
|
+
export type {
|
|
10
|
+
MarketKind, MarketSource, MarketScope, MarketEnv, InstallSpec, MarketItem,
|
|
11
|
+
InstalledState, MarketRow, SourceStatus, MarketResult, InstallPlanView, InstallOutcome, ItemDocs,
|
|
12
|
+
} from "./types.ts";
|
|
13
|
+
export { LIMITS, parseQualifiedId, qualify, itemLine } from "./types.ts";
|
|
14
|
+
|
|
15
|
+
export type { RegistryDeps } from "./registry.ts";
|
|
16
|
+
export { searchMarket, findItem, allItems, itemFromCatalog, itemFromMcp, CATALOG_FILES, CATALOG_DIR, MCP_DOCS_FILE } from "./registry.ts";
|
|
17
|
+
|
|
18
|
+
export type { Resolution } from "./resolve.ts";
|
|
19
|
+
export { resolveTarget, resolveDirect } from "./resolve.ts";
|
|
20
|
+
|
|
21
|
+
export type { PlanOptions, RunDeps } from "./install.ts";
|
|
22
|
+
export { planInstall, runInstall, installedState, withInstalled, removeItem, skillDir } from "./install.ts";
|