rovecode 0.3.3 → 0.4.0-beta.3
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/CHANGELOG.md +527 -0
- package/README.md +46 -48
- package/bin/rovecode.js +24 -0
- package/dist/cli/app-j6gn14w3.js +2 -0
- package/dist/cli/ask-user-cwstt8fz.js +2 -0
- package/dist/cli/auth-login-9bbp9915.js +2 -0
- package/dist/cli/auth-m8p9grty.js +2 -0
- package/dist/cli/bench-16zqdms5.js +9 -0
- package/dist/cli/catalog-1xchffa4.js +2 -0
- package/dist/cli/cli-1n1zb64f.js +2 -0
- package/dist/cli/client-2t9gjkck.js +2 -0
- package/dist/cli/commands-exafvm2b.js +2 -0
- package/dist/cli/connect-6zde0kn3.js +2 -0
- package/dist/cli/context-cmd-5t43wgqt.js +2 -0
- package/dist/cli/context-report-kt01pw8y.js +2 -0
- package/dist/cli/count-remote-ap7x3vh6.js +2 -0
- package/dist/cli/design-ne5zszyh.js +2 -0
- package/dist/cli/dispatch-2r5myxye.js +2 -0
- package/dist/cli/doctor-ws4fh4tn.js +3 -0
- package/dist/cli/executor-bdrjn634.js +2 -0
- package/dist/cli/export-1mxb9g5p.js +2 -0
- package/dist/cli/files-g104xghh.js +2 -0
- package/dist/cli/gauntlet-07xrjpj7.js +2 -0
- package/dist/cli/gauntlet-runner-xvy64436.js +10 -0
- package/dist/cli/gauntlet-wave3-jm91yt5w.js +5 -0
- package/dist/cli/gauntlet-wave4-r13py7p1.js +14 -0
- package/dist/cli/hashline-znvrat11.js +2 -0
- package/dist/cli/http-xafw6fsh.js +143 -0
- package/dist/cli/index-1sgjm25y.js +2 -0
- package/dist/cli/init-g2m0tn4m.js +51 -0
- package/dist/cli/install-avaqjjqq.js +2 -0
- package/dist/cli/loop-mmpfft01.js +2 -0
- package/dist/cli/main-0904f6ps.js +5 -0
- package/dist/cli/main-0ab9fc26.js +9 -0
- package/dist/cli/main-0jys2ccn.js +3 -0
- package/dist/cli/main-0mtcdbs7.js +3 -0
- package/dist/cli/main-0z1w2zsg.js +3 -0
- package/dist/cli/main-1dchs7xv.js +18 -0
- package/dist/cli/main-1ereejm1.js +3 -0
- package/dist/cli/main-1k1kw6b5.js +3 -0
- package/dist/cli/main-27y4sm2k.js +38 -0
- package/dist/cli/main-2wwjex5j.js +58 -0
- package/dist/cli/main-2yeveeve.js +6 -0
- package/dist/cli/main-2yfck9b5.js +3 -0
- package/dist/cli/main-2zmzgkwh.js +3 -0
- package/dist/cli/main-351pz3z7.js +7 -0
- package/dist/cli/main-3gjqfh7a.js +6 -0
- package/dist/cli/main-3nf3kgve.js +3 -0
- package/dist/cli/main-3pjrb2hd.js +3 -0
- package/dist/cli/main-3rxcvgna.js +19 -0
- package/dist/cli/main-4b3jgy66.js +19 -0
- package/dist/cli/main-4wndhjdc.js +7 -0
- package/dist/cli/main-4xcmvxnk.js +3 -0
- package/dist/cli/main-5tbz0wbz.js +4 -0
- package/dist/cli/main-5ywnwthm.js +3 -0
- package/dist/cli/main-6b62vkz0.js +14 -0
- package/dist/cli/main-6dnk69vp.js +3 -0
- package/dist/cli/main-6genrmhs.js +136 -0
- package/dist/cli/main-73g7eff4.js +15 -0
- package/dist/cli/main-7c5thhjd.js +5 -0
- package/dist/cli/main-7rn6bqje.js +3 -0
- package/dist/cli/main-80haw7qk.js +4 -0
- package/dist/cli/main-875s60s2.js +4 -0
- package/dist/cli/main-8kjxbpw4.js +8 -0
- package/dist/cli/main-90ds1z4e.js +10 -0
- package/dist/cli/main-9etavkew.js +3 -0
- package/dist/cli/main-a9njrkk1.js +3 -0
- package/dist/cli/main-aecrjq2d.js +12 -0
- package/dist/cli/main-ck9asesq.js +9 -0
- package/dist/cli/main-cta9racd.js +4 -0
- package/dist/cli/main-ddv7j2ag.js +3 -0
- package/dist/cli/main-dfreez27.js +10 -0
- package/dist/cli/main-f7rw7des.js +3 -0
- package/dist/cli/main-ggcn7rd7.js +5 -0
- package/dist/cli/main-gzkmycnv.js +3 -0
- package/dist/cli/main-hq51jg8v.js +18 -0
- package/dist/cli/main-jft389w9.js +8 -0
- package/dist/cli/main-k1eqkg83.js +3 -0
- package/dist/cli/main-k2y8a2aw.js +9 -0
- package/dist/cli/main-kcpbykxz.js +4 -0
- package/dist/cli/main-kd488vje.js +22 -0
- package/dist/cli/main-kh32yvgk.js +5 -0
- package/dist/cli/main-kqxnqjnv.js +25 -0
- package/dist/cli/main-kyn0xnsg.js +3 -0
- package/dist/cli/main-m1kk6fp5.js +21 -0
- package/dist/cli/main-mv40pcr2.js +4 -0
- package/dist/cli/main-n0t3973w.js +3 -0
- package/dist/cli/main-nqveez48.js +4 -0
- package/dist/cli/main-pknhvrmj.js +3 -0
- package/dist/cli/main-pn1w7a7j.js +3 -0
- package/dist/cli/main-prxxs70n.js +4 -0
- package/dist/cli/main-q3vsesf9.js +3 -0
- package/dist/cli/main-qsevpgsv.js +3 -0
- package/dist/cli/main-rdgdw24b.js +25 -0
- package/dist/cli/main-rfth4tbm.js +16 -0
- package/dist/cli/main-rg0wn0xf.js +5 -0
- package/dist/cli/main-sdmxhtv8.js +4 -0
- package/dist/cli/main-skbp13js.js +18 -0
- package/dist/cli/main-t4xnd213.js +7 -0
- package/dist/cli/main-vqak588n.js +4 -0
- package/dist/cli/main-w2n1303f.js +9 -0
- package/dist/cli/main-wbrdspr2.js +5 -0
- package/dist/cli/main-wsrg79c1.js +7 -0
- package/dist/cli/main-x4r0fne4.js +5 -0
- package/dist/cli/main-xea2f3tn.js +6 -0
- package/dist/cli/main-xg704a3c.js +3 -0
- package/dist/cli/main-xvnrabfp.js +16 -0
- package/dist/cli/main-xy53xf0r.js +4 -0
- package/dist/cli/main-y1fqy60y.js +3 -0
- package/dist/cli/main-yn8cd281.js +34 -0
- package/dist/cli/main-yr0ksc0h.js +4 -0
- package/dist/cli/main-z2ex2vyf.js +4 -0
- package/dist/cli/main-z3aayzvq.js +3 -0
- package/dist/cli/main-zaqh35jg.js +3 -0
- package/dist/cli/main-zc2e8e46.js +4 -0
- package/dist/cli/main-zzrfw6cf.js +13 -0
- package/dist/cli/main.js +280 -0
- package/dist/cli/market-cmd-e14kmx9n.js +5 -0
- package/dist/cli/mcp-login-wq7ktdek.js +2 -0
- package/dist/cli/mcp-market-cmd-9mg3jecy.js +2 -0
- package/dist/cli/notify-b7qc0cjb.js +2 -0
- package/dist/cli/oauth-z8whcgfx.js +2 -0
- package/dist/cli/output-b3ewj3ps.js +16 -0
- package/dist/cli/profiles-6mr5he5e.js +2 -0
- package/dist/cli/provider-config-g7j42q8x.js +2 -0
- package/dist/cli/provider-jr1y8vvm.js +2 -0
- package/dist/cli/registry-s8yk86g0.js +2 -0
- package/dist/cli/registry-t6p8d4mn.js +2 -0
- package/dist/cli/repl-bajwe1mh.js +11 -0
- package/dist/cli/resume-rwn9nz7y.js +2 -0
- package/dist/cli/run-flags-nah7ndpt.js +2 -0
- package/dist/cli/runtime-n7gafzhb.js +2 -0
- package/dist/cli/sandbox-config-emdy18x4.js +2 -0
- package/dist/cli/server-b0nvs2bn.js +5 -0
- package/dist/cli/session-arg-y75wd4kj.js +2 -0
- package/dist/cli/session-j62evmjq.js +2 -0
- package/dist/cli/sessions-cmd-tsnwz0ns.js +7 -0
- package/dist/cli/settings-df10wfez.js +2 -0
- package/dist/cli/setup-jzvv72fg.js +2 -0
- package/dist/cli/sextant-smoke-37m81ke6.js +5 -0
- package/dist/cli/skills-cmd-gjxnxnhx.js +2 -0
- package/dist/cli/smoke-p7748apt.js +8 -0
- package/dist/cli/start-chat-s4st3mm0.js +12 -0
- package/dist/cli/stream-gmeyewds.js +2 -0
- package/dist/cli/task-gh0kkp3n.js +2 -0
- package/dist/cli/tasks-z1kfpe8e.js +2 -0
- package/dist/cli/thinking-0eqkrz6t.js +2 -0
- package/dist/cli/todo-5brcrt9m.js +2 -0
- package/dist/cli/tools-7pzm0vj9.js +2 -0
- package/dist/cli/tools-s635p6s8.js +2 -0
- package/dist/cli/trust-cmd-cjav8zgm.js +2 -0
- package/dist/cli/update-check-pt31bm2f.js +2 -0
- package/dist/cli/update-cmd-tk131s9t.js +2 -0
- package/dist/cli/voice-56nabd8d.js +2 -0
- package/dist/cli/webfetch-xd8q596m.js +2 -0
- package/dist/cli/websearch-5hkf98k1.js +2 -0
- package/dist/cli/workflow-cmd-cy3cvzjp.js +4 -0
- package/dist/cli/workspace-q10g5z3e.js +2 -0
- package/dist/lib/index.js +62 -0
- package/dist/lib/models-index.json +1 -0
- package/dist/lib/plugins.js +55 -0
- package/dist/lib/providers.js +17 -0
- package/dist/lib/public-api.js +20 -0
- package/dist/lib/sdk.js +360 -0
- package/package.json +84 -72
- package/bin/rovecode.ts +0 -21
- package/src/acp/server.ts +0 -374
- package/src/cli/auth-login.ts +0 -122
- package/src/cli/connect.ts +0 -244
- package/src/cli/context-cmd.ts +0 -199
- package/src/cli/dispatch.ts +0 -82
- package/src/cli/doctor.ts +0 -362
- package/src/cli/export.ts +0 -276
- package/src/cli/help.ts +0 -293
- package/src/cli/is-tui-invocation.ts +0 -8
- package/src/cli/main.ts +0 -583
- package/src/cli/market-cmd.ts +0 -658
- package/src/cli/mcp-login.ts +0 -141
- package/src/cli/mcp-market-cmd.ts +0 -302
- package/src/cli/output.ts +0 -382
- package/src/cli/repl.ts +0 -250
- package/src/cli/repomap-root.ts +0 -14
- package/src/cli/resume.ts +0 -57
- package/src/cli/run-flags.ts +0 -43
- package/src/cli/run-limits.ts +0 -78
- package/src/cli/runtime.ts +0 -931
- package/src/cli/session-arg.ts +0 -30
- package/src/cli/sessions-cmd.ts +0 -145
- package/src/cli/setup.ts +0 -153
- package/src/cli/skills-cmd.ts +0 -194
- package/src/cli/start-chat.ts +0 -65
- package/src/cli/trust-cmd.ts +0 -52
- package/src/coding/bash.ts +0 -148
- package/src/coding/checkpoints.ts +0 -327
- package/src/coding/diff.ts +0 -138
- package/src/coding/files.ts +0 -341
- package/src/coding/hashline.ts +0 -274
- package/src/coding/lsp-gate.ts +0 -254
- package/src/coding/lsp-servers.ts +0 -147
- package/src/coding/lsp.ts +0 -283
- package/src/coding/repomap-cache.ts +0 -99
- package/src/coding/repomap-files.ts +0 -192
- package/src/coding/repomap.ts +0 -481
- package/src/core/agents.ts +0 -255
- package/src/core/compaction.ts +0 -259
- package/src/core/config.ts +0 -289
- package/src/core/context-report.ts +0 -228
- package/src/core/context.ts +0 -60
- package/src/core/count-remote.ts +0 -107
- package/src/core/execpolicy-rules.ts +0 -196
- package/src/core/execpolicy.ts +0 -385
- package/src/core/executor.ts +0 -454
- package/src/core/guardrails.ts +0 -400
- package/src/core/hooks.ts +0 -411
- package/src/core/images.ts +0 -230
- package/src/core/intro.ts +0 -266
- package/src/core/loop.ts +0 -567
- package/src/core/modes.ts +0 -372
- package/src/core/orchestrator.ts +0 -245
- package/src/core/proc-group.ts +0 -48
- package/src/core/project-trust.ts +0 -98
- package/src/core/reflection.ts +0 -165
- package/src/core/sandbox-config.ts +0 -186
- package/src/core/session-id.ts +0 -24
- package/src/core/session-images.ts +0 -73
- package/src/core/session-ops.ts +0 -183
- package/src/core/session-text.ts +0 -29
- package/src/core/session.ts +0 -469
- package/src/core/settings.ts +0 -170
- package/src/core/tasks.ts +0 -646
- package/src/core/token-scale.ts +0 -108
- package/src/core/tools.ts +0 -309
- package/src/core/trust.ts +0 -104
- package/src/core/types.ts +0 -330
- package/src/core/update-check.ts +0 -171
- package/src/core/usage.ts +0 -204
- package/src/core/validate.ts +0 -121
- package/src/core/verify-gate.ts +0 -159
- package/src/core/verify.ts +0 -236
- package/src/core/voice.ts +0 -158
- package/src/core/win-job.ts +0 -183
- package/src/core/workspace.ts +0 -184
- package/src/design/audit.ts +0 -797
- package/src/design/direction.ts +0 -190
- package/src/design/rules.ts +0 -157
- package/src/eval/bench.ts +0 -150
- package/src/eval/gauntlet-runner.ts +0 -215
- package/src/eval/gauntlet-support.ts +0 -84
- package/src/eval/gauntlet-wave3.ts +0 -269
- package/src/eval/gauntlet-wave4.ts +0 -217
- package/src/eval/gauntlet.ts +0 -253
- package/src/index.ts +0 -17
- package/src/lanes/agy.ts +0 -95
- package/src/lanes/approval.ts +0 -24
- package/src/lanes/claude.ts +0 -129
- package/src/lanes/codex.ts +0 -127
- package/src/lanes/events.ts +0 -130
- package/src/lanes/job.ts +0 -142
- package/src/lanes/opencode.ts +0 -122
- package/src/lanes/process.ts +0 -184
- package/src/lanes/progress.ts +0 -183
- package/src/lanes/registry.ts +0 -178
- package/src/lanes/runner.ts +0 -124
- package/src/lanes/types.ts +0 -112
- package/src/market/catalogs/mcp-docs.json +0 -111
- package/src/market/catalogs/plugins.json +0 -111
- package/src/market/catalogs/skills.json +0 -478
- package/src/market/clone.ts +0 -72
- package/src/market/context-cost.ts +0 -121
- package/src/market/digest.ts +0 -106
- package/src/market/index.ts +0 -22
- package/src/market/install.ts +0 -578
- package/src/market/manifest.ts +0 -187
- package/src/market/prereq.ts +0 -145
- package/src/market/registry.ts +0 -363
- package/src/market/resolve.ts +0 -111
- package/src/market/types.ts +0 -236
- package/src/market/validate.ts +0 -227
- package/src/mcp/client.ts +0 -449
- package/src/mcp/config.ts +0 -252
- package/src/mcp/local-package.ts +0 -211
- package/src/mcp/market-catalog.ts +0 -84
- package/src/mcp/market-install.ts +0 -289
- package/src/mcp/market.ts +0 -362
- package/src/mcp/oauth.ts +0 -251
- package/src/mcp/prompts-resources.ts +0 -249
- package/src/mcp/shared.ts +0 -149
- package/src/mcp/status.ts +0 -67
- package/src/mcp/tools.ts +0 -275
- package/src/mcp/transport.ts +0 -122
- package/src/mcp/trust.ts +0 -25
- package/src/memory/blocks.ts +0 -278
- package/src/memory/recall.ts +0 -355
- package/src/memory/scope.ts +0 -182
- package/src/memory/store.ts +0 -105
- package/src/memory/tools.ts +0 -99
- package/src/plugins/cli.ts +0 -119
- package/src/plugins/discover.ts +0 -108
- package/src/plugins/index.ts +0 -50
- package/src/plugins/install.ts +0 -184
- package/src/plugins/load.ts +0 -124
- package/src/plugins/manifest.ts +0 -92
- package/src/plugins/state.ts +0 -83
- package/src/providers/auth.ts +0 -408
- package/src/providers/cache.ts +0 -223
- package/src/providers/catalog-local.ts +0 -160
- package/src/providers/catalog.ts +0 -421
- package/src/providers/middleware-context.ts +0 -86
- package/src/providers/middleware.ts +0 -373
- package/src/providers/model-list.ts +0 -23
- package/src/providers/oauth/common.ts +0 -105
- package/src/providers/oauth/device-code.ts +0 -107
- package/src/providers/oauth/github-copilot.ts +0 -146
- package/src/providers/oauth/loopback.ts +0 -158
- package/src/providers/oauth/openai.ts +0 -163
- package/src/providers/oauth/openrouter.ts +0 -89
- package/src/providers/oauth/pkce.ts +0 -45
- package/src/providers/oauth/registry.ts +0 -39
- package/src/providers/oauth/seam.ts +0 -89
- package/src/providers/profile-glm53.ts +0 -111
- package/src/providers/profile-sonnet5-persona.ts +0 -65
- package/src/providers/profile-sonnet5-voice.ts +0 -23
- package/src/providers/profiles.ts +0 -156
- package/src/providers/provider-config.ts +0 -311
- package/src/providers/registry.ts +0 -333
- package/src/providers/responses.ts +0 -209
- package/src/providers/retry.ts +0 -234
- package/src/providers/router.ts +0 -294
- package/src/providers/sse.ts +0 -26
- package/src/providers/stream-errors.ts +0 -117
- package/src/providers/stream.ts +0 -566
- package/src/providers/thinking.ts +0 -189
- package/src/providers/wire-messages.ts +0 -129
- package/src/providers/wire-responses.ts +0 -79
- package/src/providers/wire-select.ts +0 -53
- package/src/server/http.ts +0 -291
- package/src/server/openapi.ts +0 -246
- package/src/sextant/card-hits.ts +0 -102
- package/src/sextant/card-keys.ts +0 -55
- package/src/sextant/context-source.ts +0 -157
- package/src/sextant/crew-cards.ts +0 -350
- package/src/sextant/draw-agents.ts +0 -273
- package/src/sextant/draw-code.ts +0 -388
- package/src/sextant/draw-context.ts +0 -222
- package/src/sextant/draw-frame.ts +0 -164
- package/src/sextant/draw-market.ts +0 -573
- package/src/sextant/draw-messages.ts +0 -386
- package/src/sextant/draw-pet.ts +0 -230
- package/src/sextant/draw-plan.ts +0 -187
- package/src/sextant/draw-tabs.ts +0 -85
- package/src/sextant/draw-util.ts +0 -65
- package/src/sextant/draw-wizard.ts +0 -378
- package/src/sextant/engine.ts +0 -230
- package/src/sextant/frame-hits.ts +0 -25
- package/src/sextant/frame.ts +0 -101
- package/src/sextant/git-status.ts +0 -197
- package/src/sextant/grid.ts +0 -59
- package/src/sextant/input.ts +0 -119
- package/src/sextant/keys.ts +0 -521
- package/src/sextant/layout.ts +0 -86
- package/src/sextant/local-commands.ts +0 -169
- package/src/sextant/market-source.ts +0 -287
- package/src/sextant/mentions.ts +0 -200
- package/src/sextant/message-hits.ts +0 -26
- package/src/sextant/model.ts +0 -387
- package/src/sextant/overlays.ts +0 -456
- package/src/sextant/panel-hits.ts +0 -38
- package/src/sextant/pet.ts +0 -399
- package/src/sextant/screen.ts +0 -324
- package/src/sextant/scroll-hits.ts +0 -66
- package/src/sextant/scrollbar.ts +0 -82
- package/src/sextant/sextant-bridge.ts +0 -174
- package/src/sextant/sextant-cards.ts +0 -142
- package/src/sextant/sextant-diff-base.ts +0 -63
- package/src/sextant/sextant-files.ts +0 -154
- package/src/sextant/sextant-frame-loop.ts +0 -335
- package/src/sextant/sextant-renderer.ts +0 -574
- package/src/sextant/sextant-repo.ts +0 -140
- package/src/sextant/theme.ts +0 -66
- package/src/sextant/tool-rows.ts +0 -189
- package/src/sextant/types.ts +0 -493
- package/src/skills/index.ts +0 -387
- package/src/skills/pack.ts +0 -220
- package/src/skills/spec.ts +0 -162
- package/src/skills/tools.ts +0 -69
- package/src/skills/versioned.ts +0 -227
- package/src/telemetry/otel-export.ts +0 -122
- package/src/telemetry/otel-lanes.ts +0 -89
- package/src/telemetry/otel-logs.ts +0 -131
- package/src/telemetry/otel-metrics.ts +0 -136
- package/src/telemetry/otel.ts +0 -397
- package/src/telemetry/otlp.ts +0 -76
- package/src/tools/ask-user.ts +0 -156
- package/src/tools/bash-bg.ts +0 -94
- package/src/tools/bash-jobs.ts +0 -237
- package/src/tools/design.ts +0 -151
- package/src/tools/evalcell.ts +0 -338
- package/src/tools/html-text.ts +0 -139
- package/src/tools/provider.ts +0 -149
- package/src/tools/task.ts +0 -250
- package/src/tools/todo.ts +0 -320
- package/src/tools/webfetch.ts +0 -332
- package/src/tools/websearch.ts +0 -359
- package/src/tui/agents-cmd.ts +0 -41
- package/src/tui/app.ts +0 -749
- package/src/tui/attach.ts +0 -127
- package/src/tui/boot-notes.ts +0 -41
- package/src/tui/builtin-prompts.ts +0 -59
- package/src/tui/checkpoints-cmd.ts +0 -70
- package/src/tui/clipboard-image.ts +0 -81
- package/src/tui/clipboard.ts +0 -78
- package/src/tui/commands.ts +0 -283
- package/src/tui/config-view.ts +0 -53
- package/src/tui/context-cmds.ts +0 -282
- package/src/tui/cost.ts +0 -108
- package/src/tui/crash-guard.ts +0 -173
- package/src/tui/focus-terminal.ts +0 -34
- package/src/tui/git-cmds.ts +0 -273
- package/src/tui/git-plain.ts +0 -58
- package/src/tui/info-cmd.ts +0 -150
- package/src/tui/input-plain.ts +0 -76
- package/src/tui/mcp-cmd.ts +0 -128
- package/src/tui/memory-note.ts +0 -77
- package/src/tui/modes-cmd.ts +0 -45
- package/src/tui/notify-seq.ts +0 -100
- package/src/tui/notify.ts +0 -318
- package/src/tui/overlays.ts +0 -97
- package/src/tui/pi-renderer.ts +0 -428
- package/src/tui/providers-cmd.ts +0 -377
- package/src/tui/reasoning-view.ts +0 -56
- package/src/tui/renderer.ts +0 -128
- package/src/tui/replay-marker.ts +0 -29
- package/src/tui/session-cmd.ts +0 -148
- package/src/tui/session-manage.ts +0 -95
- package/src/tui/sextant-attach.ts +0 -102
- package/src/tui/sextant-io.ts +0 -202
- package/src/tui/sextant-smoke.ts +0 -110
- package/src/tui/shell-cmd.ts +0 -158
- package/src/tui/smoke.ts +0 -72
- package/src/tui/staged-terminal.ts +0 -50
- package/src/tui/startup.ts +0 -12
- package/src/tui/theme.ts +0 -59
- package/src/tui/todo-label.ts +0 -7
- package/src/tui/trust-card.ts +0 -107
- package/src/tui/tui-commands.ts +0 -87
- package/tsconfig.json +0 -30
- package/vendor/pi-tui/LICENSE +0 -21
- package/vendor/pi-tui/PATCHES.md +0 -12
- package/vendor/pi-tui/PROVENANCE.md +0 -12
- package/vendor/pi-tui/README.upstream.md +0 -854
- 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 +0 -158
- package/vendor/pi-tui/src/autocomplete.ts +0 -827
- package/vendor/pi-tui/src/components/alt-screen-flash.ts +0 -52
- package/vendor/pi-tui/src/components/box.ts +0 -138
- package/vendor/pi-tui/src/components/cancellable-loader.ts +0 -41
- package/vendor/pi-tui/src/components/editor.ts +0 -2364
- package/vendor/pi-tui/src/components/h-stack.ts +0 -45
- package/vendor/pi-tui/src/components/image.ts +0 -128
- package/vendor/pi-tui/src/components/input.ts +0 -448
- package/vendor/pi-tui/src/components/loader.ts +0 -93
- package/vendor/pi-tui/src/components/markdown.ts +0 -1016
- package/vendor/pi-tui/src/components/scroll-view.ts +0 -217
- package/vendor/pi-tui/src/components/select-list.ts +0 -230
- package/vendor/pi-tui/src/components/settings-list.ts +0 -277
- package/vendor/pi-tui/src/components/spacer.ts +0 -29
- package/vendor/pi-tui/src/components/stack.ts +0 -155
- package/vendor/pi-tui/src/components/text.ts +0 -108
- package/vendor/pi-tui/src/components/truncated-text.ts +0 -66
- package/vendor/pi-tui/src/components/v-stack.ts +0 -34
- package/vendor/pi-tui/src/editor-component.ts +0 -75
- package/vendor/pi-tui/src/fuzzy.ts +0 -138
- package/vendor/pi-tui/src/index.ts +0 -149
- package/vendor/pi-tui/src/keybindings.ts +0 -321
- package/vendor/pi-tui/src/keys.ts +0 -1402
- package/vendor/pi-tui/src/kill-ring.ts +0 -47
- package/vendor/pi-tui/src/latex.ts +0 -1381
- package/vendor/pi-tui/src/layout-node.ts +0 -52
- package/vendor/pi-tui/src/layout.ts +0 -411
- package/vendor/pi-tui/src/native-modifiers.ts +0 -60
- package/vendor/pi-tui/src/native-module-path.ts +0 -32
- package/vendor/pi-tui/src/stdin-buffer.ts +0 -445
- package/vendor/pi-tui/src/terminal-colors.ts +0 -74
- package/vendor/pi-tui/src/terminal-image.ts +0 -701
- package/vendor/pi-tui/src/terminal.ts +0 -554
- package/vendor/pi-tui/src/tui-alt-screen.ts +0 -1379
- package/vendor/pi-tui/src/tui-main-screen.ts +0 -655
- package/vendor/pi-tui/src/tui.ts +0 -1264
- package/vendor/pi-tui/src/undo-stack.ts +0 -29
- package/vendor/pi-tui/src/utils.ts +0 -1327
- package/vendor/pi-tui/src/word-navigation.ts +0 -118
- package/vendor/pi-tui/test/test-themes.ts +0 -39
- package/vendor/pi-tui/test/virtual-terminal.ts +0 -219
- /package/{src/providers → dist/cli}/models-index.json +0 -0
package/src/core/usage.ts
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
/** Token & cost accounting: o200k token counting, provider usage normalization, USD costing,
|
|
2
|
-
* and context-window health.
|
|
3
|
-
*
|
|
4
|
-
* Normalization convention (the part that makes cost math coherent across providers):
|
|
5
|
-
* `input` = tokens billed at the BASE input rate — i.e. excluding cache reads and cache writes.
|
|
6
|
-
* - Anthropic `/messages` usage already follows this convention: `input_tokens` excludes both
|
|
7
|
-
* `cache_read_input_tokens` (billed ~0.1x input) and `cache_creation_input_tokens` (~1.25x).
|
|
8
|
-
* - OpenAI `/chat/completions` does NOT: `prompt_tokens` INCLUDES
|
|
9
|
-
* `prompt_tokens_details.cached_tokens`, so we subtract the cached share (clamped at 0) or the
|
|
10
|
-
* cached tokens would be double-billed (once at the input rate, once at the cache-read rate).
|
|
11
|
-
* The cached-inclusive convention is detected by the PRESENCE of `prompt_tokens`, or of a
|
|
12
|
-
* *_details cached count when no Anthropic `cache_read_input_tokens` coexists — NOT by the
|
|
13
|
-
* absence of `input_tokens` (gateways like OpenRouter emit BOTH spellings in one payload, and
|
|
14
|
-
* keying on absence would skip the subtraction there and double-bill the cached share), and
|
|
15
|
-
* NOT by a bare *_details block (a payload that also carries `cache_read_input_tokens` has a
|
|
16
|
-
* cache-EXCLUSIVE base; subtracting again would double-subtract and clamp input to 0).
|
|
17
|
-
*
|
|
18
|
-
* tokenlens (v1.3.1) is used where it fits: `breakdownTokens` from tokenlens/helpers already
|
|
19
|
-
* recognizes both providers' field spellings (prompt_tokens/completion_tokens/
|
|
20
|
-
* prompt_tokens_details.cached_tokens as well as input_tokens/output_tokens/
|
|
21
|
-
* cache_read_input_tokens/cache_creation_input_tokens) and tolerates junk input. What it does
|
|
22
|
-
* NOT do is reconcile the OpenAI inclusive-input asymmetry above — that part is hand-mapped here.
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
import type { countTokens as CountTokensFn } from "gpt-tokenizer/encoding/o200k_base";
|
|
26
|
-
import { breakdownTokens } from "tokenlens/helpers";
|
|
27
|
-
|
|
28
|
-
// lazy loader — the o200k rank table is deferred until the first countTokens() call that needs it.
|
|
29
|
-
// Measured (scripts/probe-import.ts, 2026-09-06): loading it takes 385–520 ms and adds ~136 MB of
|
|
30
|
-
// resident memory, and 3.8 MB of the 8 MB CLI bundle is this table. So nothing on a session's boot
|
|
31
|
-
// path may call countTokens(): the sextant usage panel goes through countTokensIfLoaded() and the
|
|
32
|
-
// chars-based estimator instead (tui/cost.ts), and the table loads when a person asks for the exact
|
|
33
|
-
// figure — /cost, /context, `rovecode context`.
|
|
34
|
-
type GptTokenizerMod = { countTokens: typeof CountTokensFn };
|
|
35
|
-
let _gptMod: GptTokenizerMod | null = null;
|
|
36
|
-
function lazyTokenizer(): GptTokenizerMod {
|
|
37
|
-
if (_gptMod === null) {
|
|
38
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
39
|
-
_gptMod = require("gpt-tokenizer/encoding/o200k_base") as GptTokenizerMod;
|
|
40
|
-
}
|
|
41
|
-
return _gptMod;
|
|
42
|
-
}
|
|
43
|
-
/** the o200k table is resident (some caller already paid for it) */
|
|
44
|
-
export function tokenizerLoaded(): boolean { return _gptMod !== null; }
|
|
45
|
-
|
|
46
|
-
// ---------- pricing ----------
|
|
47
|
-
|
|
48
|
-
export interface PricingRow {
|
|
49
|
-
inputPerMTok?: number;
|
|
50
|
-
outputPerMTok?: number;
|
|
51
|
-
cacheReadPerMTok?: number;
|
|
52
|
-
cacheWritePerMTok?: number;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export interface NormalizedUsage {
|
|
56
|
-
/** tokens billed at the base input rate (cache reads/writes excluded) */
|
|
57
|
-
input: number;
|
|
58
|
-
output: number;
|
|
59
|
-
cacheRead: number;
|
|
60
|
-
cacheWrite: number;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// ---------- token counting ----------
|
|
64
|
-
|
|
65
|
-
/** Synchronous token count using gpt-tokenizer's o200k_base encoding.
|
|
66
|
-
* An ESTIMATE for non-OpenAI models (Anthropic's tokenizer is not public); good enough for
|
|
67
|
-
* context-budget arithmetic, not for billing reconciliation — use provider usage for that. */
|
|
68
|
-
export function countTokens(text: string): number {
|
|
69
|
-
if (text.length === 0) return 0; // a fresh session's empty transcript must not load a 136 MB table to learn it is empty
|
|
70
|
-
return lazyTokenizer().countTokens(text);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/** The exact o200k count when the table is already resident, else null — never loads it. For callers
|
|
74
|
-
* that run on a session's boot path or on every repaint and have a cheaper estimator to fall back on. */
|
|
75
|
-
export function countTokensIfLoaded(text: string): number | null {
|
|
76
|
-
if (text.length === 0) return 0;
|
|
77
|
-
return _gptMod === null ? null : _gptMod.countTokens(text);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// ---------- usage normalization ----------
|
|
81
|
-
|
|
82
|
-
/** Non-negative finite number, else 0. Keeps NaN/negatives out of cost arithmetic. */
|
|
83
|
-
function nz(v: unknown): number {
|
|
84
|
-
return typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function isRec(v: unknown): v is Record<string, unknown> {
|
|
88
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** cached_tokens read straight from prompt_tokens_details/input_tokens_details — tokenlens
|
|
92
|
-
* recognizes the former but not the Responses-API latter, so this is the fallback source. */
|
|
93
|
-
function detailsCachedTokens(raw: unknown): number {
|
|
94
|
-
if (!isRec(raw)) return 0;
|
|
95
|
-
for (const k of ["prompt_tokens_details", "input_tokens_details"]) {
|
|
96
|
-
const d = raw[k];
|
|
97
|
-
if (isRec(d)) return nz(d["cached_tokens"]);
|
|
98
|
-
}
|
|
99
|
-
return 0;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/** Normalize a raw provider usage payload (OpenAI or Anthropic wire shape) to a single
|
|
103
|
-
* cost-coherent structure. Unrecognized/malformed input normalizes to all zeros. */
|
|
104
|
-
export function normalizeUsage(raw: unknown): NormalizedUsage {
|
|
105
|
-
const b = breakdownTokens(raw as Parameters<typeof breakdownTokens>[0]);
|
|
106
|
-
const cacheRead = nz(b.cacheReads) || detailsCachedTokens(raw);
|
|
107
|
-
const cacheWrite = nz(b.cacheWrites);
|
|
108
|
-
let input = nz(b.input);
|
|
109
|
-
// OpenAI-style cache-INCLUSIVE base, i.e. the reported input still contains the cached share
|
|
110
|
-
// and it must be subtracted (clamped) so `input` means "billed at the base rate". Detected by
|
|
111
|
-
// PRESENCE of prompt_tokens — never by absence of input_tokens, which OpenRouter emits
|
|
112
|
-
// alongside prompt_tokens — or by a *_details cached count with NO cache_read_input_tokens
|
|
113
|
-
// beside it: that Anthropic spelling marks the base as already cache-EXCLUSIVE, so a payload
|
|
114
|
-
// carrying both (gateway mirroring the cached share into a details block) must not be
|
|
115
|
-
// subtracted a second time — that would clamp input to 0 and under-report /cost.
|
|
116
|
-
const cachedInclusive = isRec(raw) && (
|
|
117
|
-
typeof raw["prompt_tokens"] === "number"
|
|
118
|
-
|| (detailsCachedTokens(raw) > 0 && raw["cache_read_input_tokens"] === undefined)
|
|
119
|
-
);
|
|
120
|
-
if (cachedInclusive) input = Math.max(0, input - cacheRead);
|
|
121
|
-
return { input, output: nz(b.output), cacheRead, cacheWrite };
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// ---------- cost ----------
|
|
125
|
-
|
|
126
|
-
/** USD cost of a normalized usage under a pricing row (rates are $ per 1M tokens).
|
|
127
|
-
* Returns undefined when a rate needed for a NONZERO component is missing — an honest "unknown"
|
|
128
|
-
* beats silently under-billing (e.g. pricing cache reads at 0) or over-billing (at the full
|
|
129
|
-
* input rate). Zero components never require a rate; an all-zero usage costs 0. */
|
|
130
|
-
/** A prompt-size-dependent rate table, structurally what providers/catalog.ts `ratesFor()` returns.
|
|
131
|
-
* Declared here rather than imported so this module stays free of the catalog (and of its snapshot):
|
|
132
|
-
* a caller that knows the model builds the breakdown, this one only multiplies. */
|
|
133
|
-
export interface TieredRates {
|
|
134
|
-
/** prompt tokens billed at `base` */
|
|
135
|
-
promptBase: number;
|
|
136
|
-
/** prompt tokens billed at `above` */
|
|
137
|
-
promptAbove: number;
|
|
138
|
-
base: PricingRow;
|
|
139
|
-
above?: PricingRow;
|
|
140
|
-
/** the rates for everything that is not the prompt on this request — both vendors that tier also
|
|
141
|
-
* select the OUTPUT price by prompt size */
|
|
142
|
-
request: PricingRow;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/** USD for one turn under a tiered rate table. The prompt's three components (base input, cache reads,
|
|
146
|
-
* cache writes) are split in the same proportion as `promptBase`/`promptAbove`, which is exact for the
|
|
147
|
-
* two shapes that exist today — flat (everything base) and per-request (everything above) — and a
|
|
148
|
-
* documented approximation for a marginal tier, where no shipping provider states how a partly cached
|
|
149
|
-
* prompt divides across the threshold. Same honesty rule as costUsd: a missing rate for a nonzero
|
|
150
|
-
* component returns undefined rather than a wrong number. */
|
|
151
|
-
export function costUsdTiered(u: NormalizedUsage, r: TieredRates): number | undefined {
|
|
152
|
-
const promptTotal = r.promptBase + r.promptAbove;
|
|
153
|
-
const aboveShare = promptTotal > 0 ? r.promptAbove / promptTotal : 0;
|
|
154
|
-
const above = r.above ?? r.base;
|
|
155
|
-
const split = (count: number): readonly (readonly [number, PricingRow])[] =>
|
|
156
|
-
aboveShare <= 0 ? [[count, r.base]]
|
|
157
|
-
: aboveShare >= 1 ? [[count, above]]
|
|
158
|
-
: [[count * (1 - aboveShare), r.base], [count * aboveShare, above]];
|
|
159
|
-
|
|
160
|
-
let total = 0;
|
|
161
|
-
for (const [count, row] of [
|
|
162
|
-
...split(u.input).map(([c, p]) => [c, p.inputPerMTok] as const),
|
|
163
|
-
...split(u.cacheRead).map(([c, p]) => [c, p.cacheReadPerMTok] as const),
|
|
164
|
-
...split(u.cacheWrite).map(([c, p]) => [c, p.cacheWritePerMTok] as const),
|
|
165
|
-
[u.output, r.request.outputPerMTok] as const,
|
|
166
|
-
]) {
|
|
167
|
-
const c = nz(count);
|
|
168
|
-
if (c === 0) continue;
|
|
169
|
-
if (typeof row !== "number" || !Number.isFinite(row)) return undefined;
|
|
170
|
-
total += (c / 1_000_000) * row;
|
|
171
|
-
}
|
|
172
|
-
return total;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
export function costUsd(u: NormalizedUsage, p: PricingRow): number | undefined {
|
|
176
|
-
const parts: readonly (readonly [number, number | undefined])[] = [
|
|
177
|
-
[u.input, p.inputPerMTok],
|
|
178
|
-
[u.output, p.outputPerMTok],
|
|
179
|
-
[u.cacheRead, p.cacheReadPerMTok],
|
|
180
|
-
[u.cacheWrite, p.cacheWritePerMTok],
|
|
181
|
-
];
|
|
182
|
-
let total = 0;
|
|
183
|
-
for (const [count, rate] of parts) {
|
|
184
|
-
const c = nz(count);
|
|
185
|
-
if (c === 0) continue;
|
|
186
|
-
if (typeof rate !== "number" || !Number.isFinite(rate)) return undefined;
|
|
187
|
-
total += (c / 1_000_000) * rate;
|
|
188
|
-
}
|
|
189
|
-
return total;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// ---------- context health ----------
|
|
193
|
-
|
|
194
|
-
export const NEAR_LIMIT_FRACTION = 0.8;
|
|
195
|
-
|
|
196
|
-
/** Fraction of the context window consumed. `nearLimit` trips at ≥ 0.8 — the compaction signal.
|
|
197
|
-
* The fraction is deliberately NOT clamped above 1 (callers may want the overflow magnitude);
|
|
198
|
-
* negative/NaN usedTokens counts as 0. A degenerate window (≤ 0 or non-finite) reports full
|
|
199
|
-
* (fraction 1, nearLimit true): compacting on broken config beats silently overflowing. */
|
|
200
|
-
export function contextHealth(usedTokens: number, contextWindow: number): { fraction: number; nearLimit: boolean } {
|
|
201
|
-
if (!Number.isFinite(contextWindow) || contextWindow <= 0) return { fraction: 1, nearLimit: true };
|
|
202
|
-
const fraction = nz(usedTokens) / contextWindow;
|
|
203
|
-
return { fraction, nearLimit: fraction >= NEAR_LIMIT_FRACTION };
|
|
204
|
-
}
|
package/src/core/validate.ts
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
/** Tool argument validation — the "validate" that ADR-005 names first in
|
|
2
|
-
* `validate → revise → policy → approve → sandbox → execute` and that nothing actually did.
|
|
3
|
-
*
|
|
4
|
-
* Until this file existed, `call.args` went from the model straight into `execute`, where every tool
|
|
5
|
-
* casts it: `const a = args as { path: string; content: string }`. A cast is not a check. A model
|
|
6
|
-
* that sent `content` as an object got Node's own message back —
|
|
7
|
-
*
|
|
8
|
-
* Error: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView
|
|
9
|
-
*
|
|
10
|
-
* — which names no tool, no property, and no fix, so the model's next attempt is a guess. Worse are
|
|
11
|
-
* the cases that do not throw: a number where a string belongs stringifies somewhere downstream and
|
|
12
|
-
* the wrong thing happens quietly.
|
|
13
|
-
*
|
|
14
|
-
* This validates against the schema the tool already publishes (ToolSchema.args, the same object the
|
|
15
|
-
* provider is told about), so there is nothing new to maintain: a tool that documents its arguments
|
|
16
|
-
* is validated by that documentation. The message names the tool, the property, what was expected
|
|
17
|
-
* and what arrived — everything a model needs to fix the call on the next turn without a human.
|
|
18
|
-
*
|
|
19
|
-
* Deliberately a SUBSET of JSON Schema — type, required, enum, array item type, nested objects —
|
|
20
|
-
* because that is what the tool schemas in this repo use. An unknown keyword is ignored rather than
|
|
21
|
-
* rejected: a schema this validator does not fully understand must never make a working tool
|
|
22
|
-
* unusable. Unknown PROPERTIES are likewise allowed through: policy already re-aims resources from
|
|
23
|
-
* declared keys only (tools.ts describeResource), and a strict-mode rejection here would break every
|
|
24
|
-
* provider that decorates calls with its own metadata. */
|
|
25
|
-
|
|
26
|
-
export interface ValidationIssue {
|
|
27
|
-
/** dotted path from the argument root: "todos.3.status", "" for the root itself */
|
|
28
|
-
path: string;
|
|
29
|
-
message: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
interface Schema {
|
|
33
|
-
type?: unknown;
|
|
34
|
-
properties?: unknown;
|
|
35
|
-
required?: unknown;
|
|
36
|
-
enum?: unknown;
|
|
37
|
-
items?: unknown;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const isRec = (v: unknown): v is Record<string, unknown> => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
41
|
-
|
|
42
|
-
/** what a value IS, in the words the schema uses — so "expected string, got array" reads plainly */
|
|
43
|
-
export function jsonTypeOf(v: unknown): string {
|
|
44
|
-
if (v === null) return "null";
|
|
45
|
-
if (Array.isArray(v)) return "array";
|
|
46
|
-
const t = typeof v;
|
|
47
|
-
if (t === "number") return Number.isInteger(v) ? "integer" : "number";
|
|
48
|
-
return t === "object" || t === "boolean" || t === "string" ? t : t; // function/symbol/undefined pass through as themselves
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** JSON Schema's `type` accepts a string or a list of them */
|
|
52
|
-
function typeMatches(want: unknown, v: unknown): boolean {
|
|
53
|
-
if (Array.isArray(want)) return want.some((w) => typeMatches(w, v));
|
|
54
|
-
if (typeof want !== "string") return true; // no usable type keyword: nothing to check
|
|
55
|
-
const actual = jsonTypeOf(v);
|
|
56
|
-
if (want === "number") return actual === "number" || actual === "integer";
|
|
57
|
-
if (want === "integer") return actual === "integer";
|
|
58
|
-
if (want === "object") return isRec(v);
|
|
59
|
-
return actual === want;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function join(base: string, key: string | number): string {
|
|
63
|
-
return base === "" ? String(key) : `${base}.${key}`;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function check(schema: unknown, value: unknown, path: string, out: ValidationIssue[]): void {
|
|
67
|
-
if (!isRec(schema)) return;
|
|
68
|
-
const s = schema as Schema;
|
|
69
|
-
|
|
70
|
-
if (s.type !== undefined && !typeMatches(s.type, value)) {
|
|
71
|
-
const want = Array.isArray(s.type) ? s.type.join(" or ") : String(s.type);
|
|
72
|
-
out.push({ path, message: `expected ${want}, got ${jsonTypeOf(value)}` });
|
|
73
|
-
return; // one complaint per value: the nested checks below would only repeat it
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (Array.isArray(s.enum) && s.enum.length > 0 && !s.enum.includes(value as never)) {
|
|
77
|
-
out.push({ path, message: `expected one of ${s.enum.map((e) => JSON.stringify(e)).join(" | ")}, got ${JSON.stringify(value)}` });
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (Array.isArray(value) && s.items !== undefined) {
|
|
82
|
-
value.forEach((item, i) => check(s.items, item, join(path, i), out));
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (isRec(value)) {
|
|
87
|
-
if (Array.isArray(s.required)) {
|
|
88
|
-
for (const key of s.required) {
|
|
89
|
-
// present-but-undefined is missing: a provider that serializes an omitted argument as
|
|
90
|
-
// `{"path": undefined}` has not supplied it
|
|
91
|
-
if (typeof key === "string" && (!(key in value) || value[key] === undefined)) {
|
|
92
|
-
out.push({ path: join(path, key), message: "is required but was not provided" });
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (isRec(s.properties)) {
|
|
97
|
-
for (const [key, sub] of Object.entries(s.properties)) {
|
|
98
|
-
if (key in value && value[key] !== undefined) check(sub, value[key], join(path, key), out);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/** Every problem with these arguments, in schema order. Empty = usable. */
|
|
105
|
-
export function validateArgs(schema: unknown, args: unknown): ValidationIssue[] {
|
|
106
|
-
const out: ValidationIssue[] = [];
|
|
107
|
-
// a schema with no `type` still describes an object when it lists properties/required
|
|
108
|
-
const root = isRec(schema) && (schema as Schema).type === undefined && ((schema as Schema).properties !== undefined || (schema as Schema).required !== undefined)
|
|
109
|
-
? { ...(schema as Record<string, unknown>), type: "object" }
|
|
110
|
-
: schema;
|
|
111
|
-
check(root, args, "", out);
|
|
112
|
-
return out;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/** The line the model reads. Names the tool and each bad property; the model's next attempt is a
|
|
116
|
-
* correction, not a guess. Bounded: a list of 50 malformed todos must not become a 50-line error. */
|
|
117
|
-
export function formatIssues(tool: string, issues: readonly ValidationIssue[], max = 5): string {
|
|
118
|
-
const shown = issues.slice(0, max).map((i) => (i.path === "" ? i.message : `${i.path} ${i.message}`));
|
|
119
|
-
const more = issues.length > shown.length ? ` (+${issues.length - shown.length} more)` : "";
|
|
120
|
-
return `Invalid arguments for ${tool}: ${shown.join("; ")}${more}`;
|
|
121
|
-
}
|
package/src/core/verify-gate.ts
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
/** The verify gate: a run that changed files runs the project's own check before it is allowed to end "done".
|
|
2
|
-
*
|
|
3
|
-
* Why: "done" is the model's silence (loop.ts, the finish check). The finish check catches the model stopping
|
|
4
|
-
* right after a failure it could see. This catches the failure it could NOT see — the edit landed, the tests it
|
|
5
|
-
* never ran are red. The check's failing part goes back to the model ONCE, the same way the finish check's
|
|
6
|
-
* message does; then the run ends with working code or with an honest "check failed: …" on run_end.
|
|
7
|
-
*
|
|
8
|
-
* What is here: the runner (bounded by its own timeout, the run's abort, the executor's 10k clip), the
|
|
9
|
-
* failing-part extraction, the nudge text and the one-clause rendering. What is NOT here: deciding WHICH
|
|
10
|
-
* command runs. That is core/verify.ts (resolveVerify: configuration or an unambiguous script, never a guess),
|
|
11
|
-
* taken here as an injected function — this file never reads settings itself. No resolution = the gate does
|
|
12
|
-
* not run and run_end says "not verified: no check configured". Silence about an unverified change is the
|
|
13
|
-
* bug the finish check exists for; it is not reintroduced here.
|
|
14
|
-
*
|
|
15
|
-
* Blind spot, stated rather than hidden: the gate keys on RunOutstanding.writes (successful edit/write calls).
|
|
16
|
-
* A run that changed files only through `bash` (sed, git apply, a generator) has writes 0 and is not verified —
|
|
17
|
-
* and not reported either, because a bash call that changed nothing (ls, grep, cat) looks identical from here
|
|
18
|
-
* and "not verified" on every lookup would be the noise the finish check was careful to avoid. */
|
|
19
|
-
|
|
20
|
-
import type { RunOutstanding } from "./types.ts";
|
|
21
|
-
import { resolveVerify, recordVerifyTiming } from "./verify.ts";
|
|
22
|
-
|
|
23
|
-
/** what the resolver (core/verify.ts) answers, in the shape this file needs: the commands to run in order,
|
|
24
|
-
* uninterpreted (targeting — "typecheck plus the tests that import the changed files" — is the resolver's
|
|
25
|
-
* business, this runner never has to understand a command); what it saw and refused, each with its reason;
|
|
26
|
-
* and, when there is nothing to run, why. */
|
|
27
|
-
export interface VerifyResolution {
|
|
28
|
-
commands: string[];
|
|
29
|
-
refused?: string[];
|
|
30
|
-
/** where the commands came from ("settings", "inferred", "none") */
|
|
31
|
-
source?: string;
|
|
32
|
-
/** one sentence from the resolver: the file and key the answer came from, or why there is none */
|
|
33
|
-
reason?: string;
|
|
34
|
-
}
|
|
35
|
-
export type VerifyResolver = (cwd: string) => VerifyResolution | null;
|
|
36
|
-
|
|
37
|
-
/** the seam, one direction: this file asks core/verify.ts, never the other way round. `resolveVerify` reads
|
|
38
|
-
* settings and the project's manifests and decides; nothing here second-guesses it. */
|
|
39
|
-
export const resolveForGate: VerifyResolver = (cwd) => {
|
|
40
|
-
const plan = resolveVerify(cwd);
|
|
41
|
-
return { commands: plan.commands, refused: plan.refused, source: plan.source, reason: plan.reason };
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/** what one check cost, for the doctor row and the "on by default?" question (core/verify.ts timing file) */
|
|
45
|
-
export function noteVerifyCost(cwd: string, o: VerifyOutcome): void {
|
|
46
|
-
try { if (o.ran > 0) recordVerifyTiming(cwd, o.command, o.ms); } catch { /* a timing file that cannot be written is not the run's problem */ }
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface VerifyOutcome {
|
|
50
|
-
/** the command that decided the outcome: the failing one, or the last one when all passed */
|
|
51
|
-
command: string;
|
|
52
|
-
ok: boolean;
|
|
53
|
-
code: number;
|
|
54
|
-
timedOut: boolean;
|
|
55
|
-
ms: number;
|
|
56
|
-
/** the failing part of the output — never the whole log (failingPart); "" when ok */
|
|
57
|
-
failure: string;
|
|
58
|
-
/** how many of the resolved commands ran (a failure stops the list) */
|
|
59
|
-
ran: number;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** run one command through the same executor `bash` uses; injectable for tests */
|
|
63
|
-
export type Exec = (cmd: string, cwd: string, signal: AbortSignal) => Promise<{ code: number; text: string }>;
|
|
64
|
-
|
|
65
|
-
export const VERIFY_TIMEOUT_MS = 120_000;
|
|
66
|
-
export const FAILURE_CHARS = 3_000;
|
|
67
|
-
const TAIL_LINES = 40;
|
|
68
|
-
const EARLIER_LINES = 20;
|
|
69
|
-
|
|
70
|
-
const defaultExec: Exec = async (cmd, cwd, signal) => {
|
|
71
|
-
const { getExecutor } = await import("./executor.ts");
|
|
72
|
-
return getExecutor().run(cmd, cwd, signal);
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
/** The part of a check's output that says what failed: the last 40 lines (test runners summarize at the end),
|
|
76
|
-
* preceded by up to 20 earlier lines that name a failure, clipped from the FRONT to `cap` chars so the summary
|
|
77
|
-
* survives. Never the whole log — 4 000 lines of test output back to the model is the same as no information. */
|
|
78
|
-
export function failingPart(text: string, cap = FAILURE_CHARS): string {
|
|
79
|
-
const lines = text.replace(/\r\n?/g, "\n").split("\n");
|
|
80
|
-
while (lines.length > 0 && lines.at(-1)!.trim() === "") lines.pop();
|
|
81
|
-
const tailStart = Math.max(0, lines.length - TAIL_LINES);
|
|
82
|
-
const earlier = lines.slice(0, tailStart).filter((l) => /\b(fail|failed|failing|error|not ok|assert(ion)?|exception|panic)\b|✗|×|✘/i.test(l));
|
|
83
|
-
const picked = earlier.length > EARLIER_LINES ? [...earlier.slice(0, EARLIER_LINES), `… ${earlier.length - EARLIER_LINES} more lines naming a failure`] : earlier;
|
|
84
|
-
const parts = [...picked];
|
|
85
|
-
if (picked.length > 0 && tailStart > 0) parts.push("…");
|
|
86
|
-
parts.push(...lines.slice(tailStart));
|
|
87
|
-
let out = parts.join("\n");
|
|
88
|
-
if (out.length > cap) out = `[… ${out.length - cap} chars clipped]\n${out.slice(out.length - cap)}`;
|
|
89
|
-
return out;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/** Run the resolved commands in order, stopping at the first failure. Bounded by `timeoutMs` (its own clock,
|
|
93
|
-
* combined with the run's abort). A timeout or an abort ends the command through the executor's kill path and
|
|
94
|
-
* is reported as ok:false — a timed-out check is a failed check, not a passed one. An executor that cannot run
|
|
95
|
-
* at all (no rung configured, bash missing) is a failure with that message, never a throw. */
|
|
96
|
-
export async function runVerify(
|
|
97
|
-
res: VerifyResolution, cwd: string,
|
|
98
|
-
opts: { signal?: AbortSignal; timeoutMs?: number; exec?: Exec; clock?: () => number } = {},
|
|
99
|
-
): Promise<VerifyOutcome> {
|
|
100
|
-
const exec = opts.exec ?? defaultExec;
|
|
101
|
-
const clock = opts.clock ?? Date.now;
|
|
102
|
-
const timeoutMs = opts.timeoutMs ?? VERIFY_TIMEOUT_MS;
|
|
103
|
-
const started = clock();
|
|
104
|
-
let ran = 0;
|
|
105
|
-
let last = res.commands[0] ?? "";
|
|
106
|
-
for (const command of res.commands) {
|
|
107
|
-
last = command;
|
|
108
|
-
const ac = new AbortController();
|
|
109
|
-
let timedOut = false;
|
|
110
|
-
const onAbort = () => ac.abort();
|
|
111
|
-
if (opts.signal?.aborted) ac.abort(); else opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
112
|
-
const timer = setTimeout(() => { timedOut = true; ac.abort(); }, timeoutMs);
|
|
113
|
-
let r: { code: number; text: string };
|
|
114
|
-
try { r = await exec(command, cwd, ac.signal); }
|
|
115
|
-
catch (e) { r = { code: -1, text: `could not run the check: ${e instanceof Error ? e.message : String(e)}` }; }
|
|
116
|
-
finally { clearTimeout(timer); opts.signal?.removeEventListener("abort", onAbort); }
|
|
117
|
-
ran++;
|
|
118
|
-
if (timedOut) return { command, ok: false, code: r.code, timedOut: true, ms: clock() - started, failure: failingPart(r.text), ran };
|
|
119
|
-
if (r.code !== 0 || opts.signal?.aborted) return { command, ok: false, code: r.code, timedOut: false, ms: clock() - started, failure: failingPart(r.text), ran };
|
|
120
|
-
}
|
|
121
|
-
return { command: last, ok: true, code: 0, timedOut: false, ms: clock() - started, failure: "", ran };
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/** The one continuation turn after a failed check. A harness message, not the user's; both answers — fix it, or
|
|
125
|
-
* say plainly why it cannot be made to pass — are acceptable, and the next silence ends the run either way. */
|
|
126
|
-
export function verifyNudgeText(o: VerifyOutcome, timeoutMs = VERIFY_TIMEOUT_MS): string {
|
|
127
|
-
const head = o.timedOut
|
|
128
|
-
? `The project's check did not finish within ${Math.round(timeoutMs / 1000)}s and was stopped: \`${o.command}\``
|
|
129
|
-
: `The project's check failed (exit ${o.code}) after your changes: \`${o.command}\``;
|
|
130
|
-
return [
|
|
131
|
-
"<verify-check>",
|
|
132
|
-
"You stopped, but the work does not pass — this is a check by the harness, not a message from the user.",
|
|
133
|
-
head,
|
|
134
|
-
o.failure.trim() === "" ? "(the check produced no output)" : "Failing part of its output:\n" + o.failure,
|
|
135
|
-
"Fix what your changes broke and run the check yourself, or say plainly why it cannot be made to pass. This check runs once per run; your next reply ends it either way.",
|
|
136
|
-
"</verify-check>",
|
|
137
|
-
].join("\n");
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/** one clause for the surfaces ("done · check failed (bun test): 2 tests failed") */
|
|
141
|
-
export function verifyClause(v: NonNullable<RunOutstanding["verify"]>): string {
|
|
142
|
-
const refused = v.refused && v.refused.length > 0 ? ` · ${v.refused.length} check${v.refused.length === 1 ? "" : "s"} refused (${v.refused.join("; ")})` : "";
|
|
143
|
-
// a configured check can be a whole shell line; the clause names it, the transcript carries it
|
|
144
|
-
const cmd = "command" in v ? (v.command.length > 60 ? `${v.command.slice(0, 59)}…` : v.command) : "";
|
|
145
|
-
switch (v.state) {
|
|
146
|
-
case "unconfigured": return `not verified: ${v.reason ?? "no check configured"}${refused}`;
|
|
147
|
-
case "passed": return `check passed (${cmd})${refused}`;
|
|
148
|
-
case "timeout": return `check timed out after ${v.seconds}s (${cmd})${refused}`;
|
|
149
|
-
case "failed": return `check failed (${cmd}): ${(v.failure.split("\n").filter((l) => l.trim() !== "").at(-1) ?? "").slice(0, 120)}${refused}`;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/** first line for the surfaces while it runs / when it ends (the RunEvent "verify" detail) */
|
|
154
|
-
export function verifyDetail(o: VerifyOutcome): string {
|
|
155
|
-
if (o.ok) return `passed in ${(o.ms / 1000).toFixed(1)}s`;
|
|
156
|
-
if (o.timedOut) return `timed out after ${(o.ms / 1000).toFixed(0)}s`;
|
|
157
|
-
const lastLine = o.failure.split("\n").filter((l) => l.trim() !== "").at(-1) ?? "";
|
|
158
|
-
return `exit ${o.code}${lastLine ? ` — ${lastLine.slice(0, 120)}` : ""}`;
|
|
159
|
-
}
|