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/tui/attach.ts
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
/** Port #34 TUI wiring for image input: `/attach` stages image parts for the next user message,
|
|
2
|
-
* user turns echo (and replay) with image chips, and the stage survives a session switch.
|
|
3
|
-
*
|
|
4
|
-
* The stage is the SessionStore's own (stageAttachments / stagedAttachments): the store folds it
|
|
5
|
-
* into the NEXT role:"user" entry that lands in append() — the run's goal message when idle
|
|
6
|
-
* (loop.ts userMsg), the queued steer when the loop drains it mid-run (loop.ts steering drain) —
|
|
7
|
-
* so the ONE agentLoop (ADR-003) needs no attach change and the TUI keeps no second copy of the
|
|
8
|
-
* list. Consequences, documented rather than hidden:
|
|
9
|
-
* - a steer queued BEFORE /attach is the next user entry and takes the images instead; if the
|
|
10
|
-
* run ends before any steer is drained, the images ride on the next run's goal message and the
|
|
11
|
-
* steer text follows it in the same request — nothing is ever dropped;
|
|
12
|
-
* - /sessions, /resume and a root /rewind replace the store INSTANCE: switchSession carries the
|
|
13
|
-
* stage across with a visible note (carryOverAttachments); same-store /new and /rewind move
|
|
14
|
-
* only the leaf, so the stage stays put;
|
|
15
|
-
* - no image-only messages: the editor drops empty input (pi-renderer.ts onSubmit), so text is
|
|
16
|
-
* required and every attach note says so — no "(see attached image)" text is invented on the
|
|
17
|
-
* user's behalf.
|
|
18
|
-
* Vision check at attach time (catalog.supportsImages on the current mode's model): false → warn
|
|
19
|
-
* (wire-messages.ts will send a text placeholder), undefined → info (unknown model: sent as-is,
|
|
20
|
-
* the provider may reject). Paths resolve against the runtime cwd; the loader sniffs magic bytes
|
|
21
|
-
* (core/images.ts), never the extension. */
|
|
22
|
-
|
|
23
|
-
import { resolve } from "node:path";
|
|
24
|
-
import { checkImageCount, describeImage, imageChip, imageFromBytes, loadImageAttachment, MAX_IMAGES_PER_MESSAGE } from "../core/images.ts";
|
|
25
|
-
import { clipboardImageName, readClipboardImage } from "./clipboard-image.ts";
|
|
26
|
-
import type { SessionStore } from "../core/session.ts";
|
|
27
|
-
import type { ImagePart, MessagePart } from "../core/types.ts";
|
|
28
|
-
import { supportsImages } from "../providers/catalog.ts";
|
|
29
|
-
import type { Renderer, SlashCommand } from "./renderer.ts";
|
|
30
|
-
|
|
31
|
-
/** The TUI_COMMANDS entry (/help, palette, custom-command reserved names). */
|
|
32
|
-
export const ATTACH_COMMAND: SlashCommand = {
|
|
33
|
-
name: "attach",
|
|
34
|
-
description: "Attach an image to your next message (text required): /attach <path> · /attach = list · /attach clear · or drag an image file onto the terminal",
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export interface AttachCtx {
|
|
38
|
-
renderer: Renderer;
|
|
39
|
-
/** runtime cwd — relative paths resolve against it */
|
|
40
|
-
cwd: string;
|
|
41
|
-
/** the ACTIVE store, read live (/sessions and a root /rewind swap it) */
|
|
42
|
-
store(): SessionStore;
|
|
43
|
-
/** the current mode's model — the vision check */
|
|
44
|
-
modelRef(): { provider: string; model: string };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const plural = (n: number): string => `${n} image${n === 1 ? "" : "s"}`;
|
|
48
|
-
|
|
49
|
-
/** `/attach <path>` stages one image · `/attach` lists the stage · `/attach clear` empties it.
|
|
50
|
-
* Never throws: a bad file, an oversize image or the 9th image is a note, nothing staged. */
|
|
51
|
-
export function cmdAttach(ctx: AttachCtx, arg: string): void {
|
|
52
|
-
const { renderer } = ctx;
|
|
53
|
-
const store = ctx.store();
|
|
54
|
-
const staged = store.stagedAttachments;
|
|
55
|
-
if (arg === "") {
|
|
56
|
-
renderer.addSystemNote(staged.length === 0
|
|
57
|
-
? "no images attached — /attach <path>"
|
|
58
|
-
: `attached (${staged.length}/${MAX_IMAGES_PER_MESSAGE}):\n${staged.map((p, i) => `${i + 1}. ${describeImage(p)}`).join("\n")}`);
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
if (arg === "clear") {
|
|
62
|
-
store.stageAttachments([]);
|
|
63
|
-
renderer.addSystemNote(staged.length === 0 ? "no images attached" : `attachments cleared (${plural(staged.length)} removed)`);
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
const path = arg.replace(/^(["'])(.*)\1$/, "$2"); // a quoted path keeps its spaces
|
|
67
|
-
const loaded = loadImageAttachment(resolve(ctx.cwd, path));
|
|
68
|
-
if ("error" in loaded) { renderer.addSystemNote(loaded.error, "error"); return; }
|
|
69
|
-
const over = checkImageCount(staged.length + 1);
|
|
70
|
-
if (over !== undefined) { renderer.addSystemNote(over, "error"); return; }
|
|
71
|
-
store.stageAttachments([...staged, loaded]); // replaces the stage; folds into the next user entry
|
|
72
|
-
renderer.addSystemNote(`attached ${describeImage(loaded)} (${staged.length + 1}/${MAX_IMAGES_PER_MESSAGE}) — type your message and press Enter to send it`);
|
|
73
|
-
const ref = ctx.modelRef();
|
|
74
|
-
const vision = supportsImages(ref);
|
|
75
|
-
if (vision === false) renderer.addSystemNote(`model ${ref.provider}/${ref.model} has no image input — it will be sent as a text placeholder`, "warn");
|
|
76
|
-
else if (vision === undefined) renderer.addSystemNote(`unknown model ${ref.provider}/${ref.model}; image sent as-is (provider may reject)`);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** `/paste` — the clipboard image as an attachment (⌃v in the sextant surface lands here). */
|
|
80
|
-
export const PASTE_COMMAND: SlashCommand = {
|
|
81
|
-
name: "paste",
|
|
82
|
-
description: "attach the image on the clipboard (⌃v)",
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
/** Stage the image currently on the system clipboard. Berkay: "gorsel gonderebilme olayini yapalim" —
|
|
86
|
-
* /attach <path> existed, but the thing everyone tries first is copying a screenshot and pressing ⌃v,
|
|
87
|
-
* and a terminal delivers only TEXT pastes, so that did nothing. tui/clipboard-image.ts asks the OS.
|
|
88
|
-
* Same rules as /attach: magic-byte sniff, size cap, the 8-image cap, the vision note; never throws.
|
|
89
|
-
* `read` is injectable (tests never touch a real clipboard). */
|
|
90
|
-
export function cmdPasteImage(ctx: AttachCtx, read: () => Uint8Array | null = () => readClipboardImage(), name = clipboardImageName()): void {
|
|
91
|
-
const { renderer } = ctx;
|
|
92
|
-
const bytes = read();
|
|
93
|
-
if (bytes === null) { renderer.addSystemNote("no image on the clipboard — copy a screenshot or picture first, or /attach <path>"); return; }
|
|
94
|
-
const loaded = imageFromBytes(bytes, { name });
|
|
95
|
-
if ("error" in loaded) { renderer.addSystemNote(loaded.error, "error"); return; }
|
|
96
|
-
const store = ctx.store();
|
|
97
|
-
const staged = store.stagedAttachments;
|
|
98
|
-
const over = checkImageCount(staged.length + 1);
|
|
99
|
-
if (over !== undefined) { renderer.addSystemNote(over, "error"); return; }
|
|
100
|
-
store.stageAttachments([...staged, loaded]);
|
|
101
|
-
renderer.addSystemNote(`attached ${describeImage(loaded)} from the clipboard (${staged.length + 1}/${MAX_IMAGES_PER_MESSAGE}) — type your message and press Enter to send it`);
|
|
102
|
-
const ref = ctx.modelRef();
|
|
103
|
-
const vision = supportsImages(ref);
|
|
104
|
-
if (vision === false) renderer.addSystemNote(`model ${ref.provider}/${ref.model} has no image input — it will be sent as a text placeholder`, "warn");
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/** Transcript line for a user turn: the text, then one chip per image on a second line; an
|
|
108
|
-
* image-only turn is just its chips; "" when there is nothing to show. Used by the submit echo
|
|
109
|
-
* (with the stage about to fold) and by replay (with the persisted parts). */
|
|
110
|
-
export function userTurnLine(text: string, parts: readonly MessagePart[]): string {
|
|
111
|
-
const chips = parts.filter((p): p is ImagePart => p.kind === "image").map(imageChip).join(" ");
|
|
112
|
-
return text && chips ? `${text}\n${chips}` : text || chips;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/** Suffix for the busy-submit note: what the queued steer will carry when the loop drains it. */
|
|
116
|
-
export function queuedAttachNote(store: SessionStore): string {
|
|
117
|
-
const n = store.stagedAttachments.length;
|
|
118
|
-
return n === 0 ? "" : ` — ${plural(n)} attached to your queued message`;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/** After a store swap (/sessions, /resume, root /rewind): re-stage the images the OLD instance held
|
|
122
|
-
* on the new one and say so — the switch must never lose them silently. */
|
|
123
|
-
export function carryOverAttachments(ctx: AttachCtx, pending: readonly ImagePart[]): void {
|
|
124
|
-
if (pending.length === 0) return;
|
|
125
|
-
ctx.store().stageAttachments(pending);
|
|
126
|
-
ctx.renderer.addSystemNote(`${plural(pending.length)} still attached — carried over to this session, rides on your next message`);
|
|
127
|
-
}
|
package/src/tui/boot-notes.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/** Boot-note extraction port: everything runTui says before the first prompt, in its original order.
|
|
2
|
-
* Adapted from aion's boot-notes.ts, retaining rovecode's voice and runtime channels. Memory migration,
|
|
3
|
-
* trust, workspace-root and agent-definition notes already ride plugins.onWarning: do not emit them twice.
|
|
4
|
-
* No boot work or update fetch here; only the renderer and the runtime's buffered/live note listeners. */
|
|
5
|
-
import type { Runtime } from "../cli/runtime.ts";
|
|
6
|
-
import { resumedLine, welcomeCard } from "../core/voice.ts";
|
|
7
|
-
import { summarizePlugins } from "../plugins/index.ts";
|
|
8
|
-
import type { Renderer } from "./renderer.ts";
|
|
9
|
-
|
|
10
|
-
export interface BootNotesCtx {
|
|
11
|
-
renderer: Pick<Renderer, "addSystemNote">;
|
|
12
|
-
rt: Pick<Runtime, "cwd" | "stream" | "noProviderReason" | "skillStore" | "mcp" | "providers" | "hooks" | "plugins" | "onRouterNote">;
|
|
13
|
-
yolo: boolean;
|
|
14
|
-
modelRef: { provider: string; model: string };
|
|
15
|
-
mode: "plan" | "act";
|
|
16
|
-
version: string;
|
|
17
|
-
width: number;
|
|
18
|
-
/** Undefined on a fresh boot; the active store's id on a resumed boot. */
|
|
19
|
-
sessionId: string | undefined;
|
|
20
|
-
bootWarn: string | undefined;
|
|
21
|
-
commandWarnings: readonly string[];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function emitBootNotes({ renderer, rt, yolo, modelRef, mode, version, width, sessionId, bootWarn, commandWarnings }: BootNotesCtx): void {
|
|
25
|
-
const connected = rt.stream && rt.noProviderReason() === null ? modelRef : null;
|
|
26
|
-
if (sessionId !== undefined) renderer.addSystemNote(resumedLine(sessionId, rt.cwd, yolo));
|
|
27
|
-
else {
|
|
28
|
-
// Count only what this runtime accepted, not untrusted/unfilled MCP entries or inactive plugins.
|
|
29
|
-
const loaded = { skills: rt.skillStore.list().length, plugins: rt.plugins.found.filter((p) => p.status === "active").length, mcp: rt.mcp?.serverNames().length ?? 0 };
|
|
30
|
-
renderer.addSystemNote(welcomeCard({ connected, cwd: rt.cwd, yolo, mode, version, loaded, width }));
|
|
31
|
-
}
|
|
32
|
-
if (bootWarn) renderer.addSystemNote(bootWarn); // a fact, not a fault (the original info tone)
|
|
33
|
-
for (const w of commandWarnings) renderer.addSystemNote(w, "warn");
|
|
34
|
-
for (const w of rt.providers.warnings()) renderer.addSystemNote(`providers: ${w}`, "warn");
|
|
35
|
-
rt.hooks.onWarning((w) => renderer.addSystemNote(`hooks: ${w}`, "warn"));
|
|
36
|
-
rt.plugins.onWarning((w) => renderer.addSystemNote(w, "warn"));
|
|
37
|
-
const pluginLine = summarizePlugins(rt.plugins.found);
|
|
38
|
-
if (pluginLine !== null) renderer.addSystemNote(pluginLine);
|
|
39
|
-
// Retry notices arrive during backoff; the run's final drain then has nothing left to print.
|
|
40
|
-
rt.onRouterNote((n) => renderer.addSystemNote(n, "warn"));
|
|
41
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/** Built-in prompt commands (port #53): slash commands whose whole effect is a prompt the ONE agent
|
|
2
|
-
* loop runs — today `/init`, which asks the agent to analyse the repo and write (or improve)
|
|
3
|
-
* AGENTS.md. They expand exactly where custom commands do: the TUI submits the rendered prompt as a
|
|
4
|
-
* plain user turn (context-cmds.ts) and `rovecode run "/init"` renders it headlessly through
|
|
5
|
-
* commands.ts expandSlashPrompt, which consults this table BEFORE the custom-command files (a
|
|
6
|
-
* built-in beats a same-named custom command, as in the TUI). No renderer, store or loop import
|
|
7
|
-
* here — both the TUI and the headless path can depend on this module without a cycle.
|
|
8
|
-
*
|
|
9
|
-
* Pattern reference only, no code ported: gemini-cli @ 0bd1d43 packages/cli/src/ui/commands/
|
|
10
|
-
* initCommand.ts (the command checks whether the context file exists in the target dir and turns
|
|
11
|
-
* into a submitted prompt, :33-49) and packages/core/src/commands/init.ts performInit (:9-57 — a
|
|
12
|
-
* guided analysis prompt: explore, read the README, pick up to ~10 key files, identify the project
|
|
13
|
-
* type, then write the file). Deviation: gemini refuses when its file already exists ("No changes
|
|
14
|
-
* were made", :10-17); rovecode asks for targeted improvements instead, and the write itself goes
|
|
15
|
-
* through the ordinary edit/write approval seam — the command never touches the file. */
|
|
16
|
-
|
|
17
|
-
import { existsSync } from "node:fs";
|
|
18
|
-
import { join } from "node:path";
|
|
19
|
-
|
|
20
|
-
/** The file the agent writes — the project-context file cli/boot-context.ts harvests (port #8). */
|
|
21
|
-
export const INIT_TARGET = "AGENTS.md";
|
|
22
|
-
|
|
23
|
-
/** `/init` — the analysis prompt; the variant depends on whether `<cwd>/AGENTS.md` exists. */
|
|
24
|
-
export function initPrompt(cwd: string): string {
|
|
25
|
-
const exists = existsSync(join(cwd, INIT_TARGET));
|
|
26
|
-
const head = exists
|
|
27
|
-
? `${INIT_TARGET} already exists in this project. Analyse the repository, read the current ${INIT_TARGET}, and propose TARGETED improvements to it: fix what is stale or wrong, add what a future agent session would need and cannot infer quickly, remove nothing that is still true. Apply the changes with the edit tool (small anchored edits, never a wholesale rewrite) and finish with a short list of what changed and why.`
|
|
28
|
-
: `Analyse this repository and write an ${INIT_TARGET} file at the project root: the instructional context a future agent session reads first.`;
|
|
29
|
-
return `${head}
|
|
30
|
-
|
|
31
|
-
Analysis:
|
|
32
|
-
1. List the top-level files and directories for an overview. Read the README (README.md or similar) first if there is one.
|
|
33
|
-
2. Read the files that matter most, up to about ten, letting each discovery guide the next: build/package manifests (package.json, pyproject.toml, Cargo.toml, go.mod, Makefile, …), the main entry points, existing agent or contributor guides (AGENTS.md, CLAUDE.md, CONTRIBUTING.md), CI config.
|
|
34
|
-
3. Decide whether this is a code project or something else (documentation, notes, data).
|
|
35
|
-
|
|
36
|
-
${INIT_TARGET} content — concise, factual, only what you verified in the files:
|
|
37
|
-
- Project overview: purpose, main technologies, architecture in a few sentences.
|
|
38
|
-
- Build, run and test: the exact commands, inferred from the manifests and scripts you read; mark anything you could not confirm with a TODO instead of guessing.
|
|
39
|
-
- Conventions: code style, testing practice, layout rules, review or contribution rules the files reveal.
|
|
40
|
-
- For a non-code directory: what it holds, the key files and how the contents are meant to be used.
|
|
41
|
-
|
|
42
|
-
${exists ? `Edit ${INIT_TARGET} in place; do not create a second file.` : `Write the complete file with the write tool as well-formatted Markdown; do not touch other files.`} Keep it under about 150 lines.`;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** Built-in prompt commands by name → their renderer. `arg` is the remainder of the line (unused by
|
|
46
|
-
* /init, which takes no arguments — kept in the signature so a later built-in can accept some). */
|
|
47
|
-
export const BUILTIN_PROMPTS: Readonly<Record<string, (cwd: string, arg: string) => string>> = {
|
|
48
|
-
init: (cwd) => initPrompt(cwd),
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
/** `"/name args"` → the rendered built-in prompt, or undefined when the line names no built-in
|
|
52
|
-
* prompt command (a custom command, another built-in, plain text). Case-insensitive like custom
|
|
53
|
-
* command names. */
|
|
54
|
-
export function expandBuiltinSlash(prompt: string, cwd: string): string | undefined {
|
|
55
|
-
const m = /^\/(\S+)(?:\s+([\s\S]*))?$/.exec(prompt.trim());
|
|
56
|
-
if (!m) return undefined;
|
|
57
|
-
const render = Object.hasOwn(BUILTIN_PROMPTS, m[1]!.toLowerCase()) ? BUILTIN_PROMPTS[m[1]!.toLowerCase()] : undefined;
|
|
58
|
-
return render ? render(cwd, (m[2] ?? "").trim()) : undefined;
|
|
59
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/** TUI surface for shadow-git checkpoints (port #11, cline): /checkpoints lists the
|
|
2
|
-
* session's snapshots in a pickOne overlay; /restore <ref> [files|conversation|both]
|
|
3
|
-
* replays cline's three restore modes. Conversation/both restores branch the session
|
|
4
|
-
* tree to the checkpoint's recorded entryId (port #2 leaf machinery) — the CALLER
|
|
5
|
-
* owns the store, so branching + replay run through the injected ctx. */
|
|
6
|
-
|
|
7
|
-
import type { RestoreMode } from "../coding/checkpoints.ts";
|
|
8
|
-
import type { Checkpoints } from "../coding/checkpoints.ts";
|
|
9
|
-
import type { Renderer } from "./renderer.ts";
|
|
10
|
-
|
|
11
|
-
export interface CheckpointCmdCtx {
|
|
12
|
-
renderer: Renderer;
|
|
13
|
-
busy(): boolean;
|
|
14
|
-
/** active session id (checkpoints are per-session) */
|
|
15
|
-
sessionId(): string;
|
|
16
|
-
checkpointsFor(sessionId: string): Promise<Checkpoints | null>;
|
|
17
|
-
/** branch the ACTIVE session store to entryId; false when the entry is unknown */
|
|
18
|
-
branchTo(entryId: string): boolean;
|
|
19
|
-
/** re-render transcript + usage after a conversation restore */
|
|
20
|
-
replayAndRefresh(): void;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const MODES: readonly RestoreMode[] = ["files", "conversation", "both"];
|
|
24
|
-
|
|
25
|
-
/** /checkpoints — list snapshots newest-first in the overlay; picking one prefills nothing
|
|
26
|
-
* and just prints the /restore hint (restore is deliberately an explicit second step). */
|
|
27
|
-
export async function cmdCheckpoints(ctx: CheckpointCmdCtx): Promise<void> {
|
|
28
|
-
if (ctx.busy()) { ctx.renderer.addSystemNote("finish or interrupt the run first (Esc)", "warn"); return; }
|
|
29
|
-
const cp = await ctx.checkpointsFor(ctx.sessionId());
|
|
30
|
-
if (!cp) { ctx.renderer.addSystemNote("checkpoints unavailable (git missing or ROVECODE_NO_CHECKPOINTS=1)", "warn"); return; }
|
|
31
|
-
const log = cp.list();
|
|
32
|
-
if (log.length === 0) { ctx.renderer.addSystemNote("no checkpoints yet — snapshots land after each mutating tool call"); return; }
|
|
33
|
-
const items = [...log].reverse().slice(0, 20).map((c, i) => ({
|
|
34
|
-
value: c.hash,
|
|
35
|
-
label: `#${log.length - i} ${c.label} · ${c.hash.slice(0, 8)}`,
|
|
36
|
-
description: `${new Date(c.createdAt).toLocaleString()}${c.entryId ? " · conversation anchor" : ""}`,
|
|
37
|
-
}));
|
|
38
|
-
const picked = await ctx.renderer.pickOne(items, "checkpoints (Enter = show restore hint, Esc = close)");
|
|
39
|
-
ctx.replayAndRefresh(); // clear the overlay title note
|
|
40
|
-
if (picked) ctx.renderer.addSystemNote(`restore with: /restore ${picked.slice(0, 8)} [files|conversation|both]`);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** /restore <hash-prefix> [mode] — files (workspace only), conversation (session branch
|
|
44
|
-
* only), or both. Cline's three modes, checkpoint-restore semantics. */
|
|
45
|
-
export async function cmdRestore(ctx: CheckpointCmdCtx, arg: string): Promise<void> {
|
|
46
|
-
if (ctx.busy()) { ctx.renderer.addSystemNote("finish or interrupt the run first (Esc)", "warn"); return; }
|
|
47
|
-
const [ref, modeArg] = arg.split(/\s+/);
|
|
48
|
-
if (!ref) { ctx.renderer.addSystemNote("usage: /restore <checkpoint> [files|conversation|both] — list with /checkpoints", "warn"); return; }
|
|
49
|
-
const mode = (modeArg || "files") as RestoreMode;
|
|
50
|
-
if (!MODES.includes(mode)) { ctx.renderer.addSystemNote(`unknown restore mode "${modeArg}" (files|conversation|both)`, "warn"); return; }
|
|
51
|
-
const cp = await ctx.checkpointsFor(ctx.sessionId());
|
|
52
|
-
if (!cp) { ctx.renderer.addSystemNote("checkpoints unavailable (git missing or ROVECODE_NO_CHECKPOINTS=1)", "warn"); return; }
|
|
53
|
-
// dedupe candidates BY HASH (identical content re-snapshotted shares one): counting
|
|
54
|
-
// entries made even the full 40-char hash "match 2 checkpoints" forever. Latest entry
|
|
55
|
-
// per hash wins, mirroring the module's own pick.
|
|
56
|
-
const match = [...new Map(cp.list().filter((c) => c.hash.startsWith(ref)).map((c) => [c.hash, c])).values()];
|
|
57
|
-
if (match.length !== 1) {
|
|
58
|
-
ctx.renderer.addSystemNote(match.length === 0 ? `no checkpoint matching "${ref}"` : `"${ref}" matches ${match.length} checkpoints — be more specific`, "warn");
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
const res = await cp.restore(match[0]!.hash, mode);
|
|
62
|
-
if (!res.ok) { ctx.renderer.addSystemNote(`restore failed: ${res.error}`, "error"); return; }
|
|
63
|
-
let convNote = "";
|
|
64
|
-
if (mode === "conversation" || mode === "both") {
|
|
65
|
-
if (res.entryId && ctx.branchTo(res.entryId)) { ctx.replayAndRefresh(); convNote = " · conversation branched to the checkpoint's turn"; }
|
|
66
|
-
else convNote = " · conversation anchor unavailable in this session tree (files unaffected by that)";
|
|
67
|
-
}
|
|
68
|
-
const fileNote = mode === "conversation" ? "" : "workspace rolled back";
|
|
69
|
-
ctx.renderer.addSystemNote(`restored ${res.checkpoint.hash.slice(0, 8)} (${mode}) — ${fileNote}${convNote}; snapshots keep history`);
|
|
70
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
/** Read an IMAGE from the system clipboard (⌃v / `/paste`).
|
|
2
|
-
*
|
|
3
|
-
* A terminal only ever hands a program TEXT from the clipboard (bracketed paste). When the clipboard
|
|
4
|
-
* holds an image — a screenshot, a copied picture — the terminal sends nothing useful, and users who
|
|
5
|
-
* press ⌃v expecting the image to land (every chat app taught them that) get silence. So the surface
|
|
6
|
-
* asks the OS itself, through the one tool each platform has for it, and converts to PNG:
|
|
7
|
-
* win32 PowerShell + System.Windows.Forms.Clipboard.GetImage() → PNG → base64 on stdout
|
|
8
|
-
* darwin osascript `the clipboard as «class PNGf»` → hex («data PNGf…»)
|
|
9
|
-
* linux wl-paste -t image/png, else xclip -selection clipboard -t image/png -o
|
|
10
|
-
*
|
|
11
|
-
* The command runner is injected so tests never touch a real clipboard; every failure (no image on
|
|
12
|
-
* the clipboard, tool missing, odd output) is `null`, never a throw — the caller says "no image on the
|
|
13
|
-
* clipboard" and moves on. Nothing here writes a file: the bytes go straight to core/images.ts
|
|
14
|
-
* imageFromBytes, which sniffs the magic bytes and enforces the size cap like any other attachment. */
|
|
15
|
-
|
|
16
|
-
import { spawnSync } from "node:child_process";
|
|
17
|
-
|
|
18
|
-
export interface ClipboardRunner {
|
|
19
|
-
/** run a command, return stdout decoded as `encoding` (utf8 for text tools, latin1 when the tool
|
|
20
|
-
* prints raw image bytes — utf8 decoding would corrupt them), or null when it failed / is missing */
|
|
21
|
-
(cmd: string, args: readonly string[], encoding?: "utf8" | "latin1"): string | null;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const TIMEOUT_MS = 5_000;
|
|
25
|
-
const MAX_OUT = 64 * 1024 * 1024; // a 5 MiB image is ~7 MiB of base64; leave room, never unbounded
|
|
26
|
-
|
|
27
|
-
/** child_process.spawnSync under the contract above: non-zero exit, signal, timeout or ENOENT → null */
|
|
28
|
-
export const spawnRunner: ClipboardRunner = (cmd, args, encoding = "utf8") => {
|
|
29
|
-
try {
|
|
30
|
-
const r = spawnSync(cmd, args, { encoding, timeout: TIMEOUT_MS, maxBuffer: MAX_OUT, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] });
|
|
31
|
-
if (r.error || r.status !== 0 || r.signal) return null;
|
|
32
|
-
return r.stdout;
|
|
33
|
-
} catch { return null; }
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
/** PowerShell: the image as PNG base64, or nothing when the clipboard holds no image */
|
|
37
|
-
const PS_SCRIPT = [
|
|
38
|
-
"Add-Type -AssemblyName System.Windows.Forms,System.Drawing",
|
|
39
|
-
"$i = [System.Windows.Forms.Clipboard]::GetImage()",
|
|
40
|
-
"if ($i -eq $null) { exit 3 }",
|
|
41
|
-
"$ms = New-Object System.IO.MemoryStream",
|
|
42
|
-
"$i.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)",
|
|
43
|
-
"[Console]::Out.Write([Convert]::ToBase64String($ms.ToArray()))",
|
|
44
|
-
].join("; ");
|
|
45
|
-
|
|
46
|
-
function fromBase64(s: string | null): Uint8Array | null {
|
|
47
|
-
const t = s?.trim() ?? "";
|
|
48
|
-
if (t.length < 16 || !/^[A-Za-z0-9+/=\r\n]+$/.test(t)) return null;
|
|
49
|
-
try { return new Uint8Array(Buffer.from(t.replace(/\s+/g, ""), "base64")); } catch { return null; }
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/** osascript prints `«data PNGf89504E47…»`; take the hex between the marker and the closing » */
|
|
53
|
-
function fromAppleScriptHex(s: string | null): Uint8Array | null {
|
|
54
|
-
const m = /«data PNGf([0-9A-Fa-f]+)»/.exec(s ?? "");
|
|
55
|
-
if (!m || m[1]!.length < 32 || m[1]!.length % 2 !== 0) return null;
|
|
56
|
-
return new Uint8Array(Buffer.from(m[1]!, "hex"));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/** The clipboard image as raw bytes (PNG on win32/darwin, whatever the tool yields on linux — the
|
|
60
|
-
* magic-byte sniff downstream decides), or null when there is none. `platform` defaults to the process's. */
|
|
61
|
-
export function readClipboardImage(run: ClipboardRunner = spawnRunner, platform: NodeJS.Platform = process.platform): Uint8Array | null {
|
|
62
|
-
if (platform === "win32") {
|
|
63
|
-
return fromBase64(run("powershell", ["-NoProfile", "-NonInteractive", "-STA", "-Command", PS_SCRIPT]));
|
|
64
|
-
}
|
|
65
|
-
if (platform === "darwin") {
|
|
66
|
-
return fromAppleScriptHex(run("osascript", ["-e", "the clipboard as «class PNGf»"]));
|
|
67
|
-
}
|
|
68
|
-
// linux and the rest: wayland first, then X11; both print the raw PNG, which the runner returns as a
|
|
69
|
-
// utf8 string — decode it back to bytes with latin1 so no byte is altered
|
|
70
|
-
for (const [cmd, args] of [["wl-paste", ["-t", "image/png"]], ["xclip", ["-selection", "clipboard", "-t", "image/png", "-o"]]] as const) {
|
|
71
|
-
const out = run(cmd, args, "latin1");
|
|
72
|
-
if (out !== null && out.length > 8) return new Uint8Array(Buffer.from(out, "latin1"));
|
|
73
|
-
}
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/** what a pasted image is called in the transcript chip and the sidecar name: clipboard-HHMMSS.png */
|
|
78
|
-
export function clipboardImageName(now: Date = new Date()): string {
|
|
79
|
-
const p = (n: number): string => String(n).padStart(2, "0");
|
|
80
|
-
return `clipboard-${p(now.getHours())}${p(now.getMinutes())}${p(now.getSeconds())}.png`;
|
|
81
|
-
}
|
package/src/tui/clipboard.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/** System clipboard writer for `/copy` (port #53). ONE candidate chain per platform family, tried in
|
|
2
|
-
* order until one succeeds; the process spawner is injectable so tests pin the order with a fake and
|
|
3
|
-
* the only real-process test is the Windows round-trip (clipboard.test.ts, skipped elsewhere).
|
|
4
|
-
* win32 powershell — `Set-Clipboard` fed the text on stdin, decoded as UTF-8 explicitly
|
|
5
|
-
* ([Console]::InputEncoding, else the OEM code page garbles non-ASCII; verified: a string
|
|
6
|
-
* with accents, an em dash, a check mark and CJK reads back byte-identical via
|
|
7
|
-
* `Get-Clipboard -Raw`). clip.exe is NOT in the chain: its stdin decoding is code-page
|
|
8
|
-
* dependent and was not proven.
|
|
9
|
-
* everything pbcopy (macOS) → wl-copy (Wayland) → xclip -selection clipboard → xsel --clipboard --input
|
|
10
|
-
* else — one chain for every non-Windows platform: a tool the host lacks fails to spawn
|
|
11
|
-
* (ENOENT) and the chain simply moves on, so macOS stops at pbcopy and Linux skips it
|
|
12
|
-
* A missing binary, a non-zero exit and a spawn error all mean "next candidate"; when the chain is
|
|
13
|
-
* exhausted the result says which tools were tried. Never throws.
|
|
14
|
-
*
|
|
15
|
-
* Pattern reference only, no code ported: gemini-cli @ 0bd1d43 packages/cli/src/ui/commands/
|
|
16
|
-
* copyCommand.ts (the last model message's text parts joined, "no output" / "no text" notes, :24-68).
|
|
17
|
-
* gemini hands the write to the `clipboardy` package behind an OSC-52 attempt
|
|
18
|
-
* (ui/utils/commandUtils.ts:256-283); the explicit tool chain, the stdin-fed PowerShell form and the
|
|
19
|
-
* injectable spawner are rovecode's. */
|
|
20
|
-
|
|
21
|
-
export interface SpawnOutcome { ok: boolean; detail?: string }
|
|
22
|
-
|
|
23
|
-
/** Run `argv` with `input` on stdin; resolve ok on exit 0. Rejections are treated as failures. */
|
|
24
|
-
export type ClipboardSpawn = (argv: readonly string[], input: string) => Promise<SpawnOutcome>;
|
|
25
|
-
|
|
26
|
-
export interface ClipboardOptions {
|
|
27
|
-
platform?: NodeJS.Platform;
|
|
28
|
-
spawn?: ClipboardSpawn;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export type ClipboardResult =
|
|
32
|
-
| { ok: true; tool: string }
|
|
33
|
-
| { ok: false; tried: string[]; detail?: string };
|
|
34
|
-
|
|
35
|
-
/** Windows: read ALL of stdin as UTF-8 (the default console input encoding is the OEM code page)
|
|
36
|
-
* and hand it to Set-Clipboard verbatim — no trailing newline added, no line splitting. */
|
|
37
|
-
export const WIN_SET_CLIPBOARD = "[Console]::InputEncoding=[Text.Encoding]::UTF8; $t=[Console]::In.ReadToEnd(); Set-Clipboard -Value $t";
|
|
38
|
-
|
|
39
|
-
/** The candidates for a platform, in the order they are tried (header): PowerShell alone on Windows,
|
|
40
|
-
* the pbcopy → wl-copy → xclip → xsel chain everywhere else. */
|
|
41
|
-
export function clipboardChain(platform: NodeJS.Platform): readonly (readonly string[])[] {
|
|
42
|
-
if (platform === "win32") return [["powershell", "-NoProfile", "-NonInteractive", "-Command", WIN_SET_CLIPBOARD]];
|
|
43
|
-
return [["pbcopy"], ["wl-copy"], ["xclip", "-selection", "clipboard"], ["xsel", "--clipboard", "--input"]];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** Default spawner: Bun.spawn with the text piped to stdin. A missing binary throws synchronously
|
|
47
|
-
* (ENOENT) — caught here and reported as a failed candidate, like a non-zero exit. */
|
|
48
|
-
export const bunClipboardSpawn: ClipboardSpawn = async (argv, input) => {
|
|
49
|
-
try {
|
|
50
|
-
const proc = Bun.spawn([...argv], { stdin: "pipe", stdout: "ignore", stderr: "pipe" });
|
|
51
|
-
proc.stdin.write(input);
|
|
52
|
-
await proc.stdin.end();
|
|
53
|
-
const code = await proc.exited;
|
|
54
|
-
if (code === 0) return { ok: true };
|
|
55
|
-
const err = (await new Response(proc.stderr).text()).trim().split("\n")[0] ?? "";
|
|
56
|
-
return { ok: false, detail: `exit ${code}${err ? `: ${err.slice(0, 120)}` : ""}` };
|
|
57
|
-
} catch (e) {
|
|
58
|
-
return { ok: false, detail: e instanceof Error ? e.message : String(e) };
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
/** Copy `text` to the system clipboard through the platform's chain. Empty text is refused up
|
|
63
|
-
* front (nothing is spawned): a blank clipboard write is never what /copy meant. */
|
|
64
|
-
export async function copyToClipboard(text: string, opts: ClipboardOptions = {}): Promise<ClipboardResult> {
|
|
65
|
-
const spawn = opts.spawn ?? bunClipboardSpawn;
|
|
66
|
-
const tried: string[] = [];
|
|
67
|
-
if (text.length === 0) return { ok: false, tried, detail: "nothing to copy (empty text)" };
|
|
68
|
-
let detail: string | undefined;
|
|
69
|
-
for (const argv of clipboardChain(opts.platform ?? process.platform)) {
|
|
70
|
-
const tool = argv[0]!;
|
|
71
|
-
tried.push(tool);
|
|
72
|
-
let out: SpawnOutcome;
|
|
73
|
-
try { out = await spawn(argv, text); } catch (e) { out = { ok: false, detail: e instanceof Error ? e.message : String(e) }; }
|
|
74
|
-
if (out.ok) return { ok: true, tool };
|
|
75
|
-
detail = out.detail;
|
|
76
|
-
}
|
|
77
|
-
return { ok: false, tried, ...(detail !== undefined ? { detail } : {}) };
|
|
78
|
-
}
|