rovecode 0.3.3 → 0.4.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +512 -0
- package/README.md +33 -48
- package/bin/rovecode.js +24 -0
- package/dist/cli/app-dybnr56b.js +2 -0
- package/dist/cli/ask-user-p8hq4xgj.js +2 -0
- package/dist/cli/auth-login-ewpgw5sm.js +2 -0
- package/dist/cli/auth-m8p9grty.js +2 -0
- package/dist/cli/bench-xv3ypwev.js +9 -0
- package/dist/cli/catalog-737wb2s0.js +2 -0
- package/dist/cli/cli-arhg40m0.js +2 -0
- package/dist/cli/client-cf2pxx8q.js +2 -0
- package/dist/cli/commands-3p7e4xxs.js +2 -0
- package/dist/cli/connect-3q93d7cb.js +2 -0
- package/dist/cli/context-cmd-eqxmxhzq.js +2 -0
- package/dist/cli/context-report-hbw9zfes.js +2 -0
- package/dist/cli/count-remote-mby98cd0.js +2 -0
- package/dist/cli/design-122y0axd.js +2 -0
- package/dist/cli/dispatch-b4egzvvh.js +2 -0
- package/dist/cli/doctor-x4jkv72e.js +3 -0
- package/dist/cli/executor-ftvg6tsy.js +2 -0
- package/dist/cli/export-pdgdhkch.js +2 -0
- package/dist/cli/files-cez9a96p.js +2 -0
- package/dist/cli/gauntlet-r3xxaszc.js +2 -0
- package/dist/cli/gauntlet-runner-r515m7kk.js +10 -0
- package/dist/cli/gauntlet-wave3-bnkjk2v2.js +5 -0
- package/dist/cli/gauntlet-wave4-acs9s60q.js +14 -0
- package/dist/cli/hashline-ewg5hbe3.js +2 -0
- package/dist/cli/http-n0kehsk8.js +5 -0
- package/dist/cli/index-z5qt1s76.js +2 -0
- package/dist/cli/install-80mp63kx.js +2 -0
- package/dist/cli/loop-12twjcat.js +2 -0
- package/dist/cli/main-01pv9206.js +4 -0
- package/dist/cli/main-0jys2ccn.js +3 -0
- package/dist/cli/main-1ztz6fkj.js +10 -0
- package/dist/cli/main-23q7cmww.js +9 -0
- package/dist/cli/main-2rzbexn2.js +3 -0
- package/dist/cli/main-2wyax8k9.js +9 -0
- package/dist/cli/main-2yeveeve.js +6 -0
- package/dist/cli/main-2z3dek0b.js +3 -0
- package/dist/cli/main-2zgsknth.js +3 -0
- package/dist/cli/main-45ejth3a.js +4 -0
- package/dist/cli/main-45rn3trk.js +22 -0
- package/dist/cli/main-4p4e2w7x.js +4 -0
- package/dist/cli/main-4y0tnfpa.js +16 -0
- package/dist/cli/main-5py0rkmc.js +4 -0
- package/dist/cli/main-6dtqmbt6.js +7 -0
- package/dist/cli/main-6h9x282m.js +4 -0
- package/dist/cli/main-6vjeds42.js +3 -0
- package/dist/cli/main-78gq4bt9.js +6 -0
- package/dist/cli/main-7jd5vh3x.js +4 -0
- package/dist/cli/main-7kt6r53y.js +4 -0
- package/dist/cli/main-8c1tbazx.js +58 -0
- package/dist/cli/main-9a9rnh47.js +19 -0
- package/dist/cli/main-9ht36z12.js +3 -0
- package/dist/cli/main-a2yfvcy9.js +7 -0
- package/dist/cli/main-a3f51n0x.js +5 -0
- package/dist/cli/main-b8zq261k.js +3 -0
- package/dist/cli/main-bxtvnf6d.js +13 -0
- package/dist/cli/main-edxc3yzt.js +4 -0
- package/dist/cli/main-evgz4mp5.js +21 -0
- package/dist/cli/main-f33fc5je.js +9 -0
- package/dist/cli/main-fvnpq46y.js +12 -0
- package/dist/cli/main-gbbty4d4.js +3 -0
- package/dist/cli/main-gth53dnt.js +25 -0
- package/dist/cli/main-hqbz10aw.js +9 -0
- package/dist/cli/main-hrrvcfan.js +38 -0
- package/dist/cli/main-hzwtsb2m.js +5 -0
- package/dist/cli/main-j7ttv0sd.js +34 -0
- package/dist/cli/main-jak598k9.js +5 -0
- package/dist/cli/main-kba6zeyd.js +6 -0
- package/dist/cli/main-kwwsz6rq.js +3 -0
- package/dist/cli/main-m8vm17zq.js +3 -0
- package/dist/cli/main-mg4f96e1.js +3 -0
- package/dist/cli/main-mg9b20ac.js +18 -0
- package/dist/cli/main-mgb9ccnx.js +3 -0
- package/dist/cli/main-mjt2p7aj.js +3 -0
- package/dist/cli/main-n6qrdbmy.js +3 -0
- package/dist/cli/main-na7wse0x.js +5 -0
- package/dist/cli/main-nqveez48.js +4 -0
- package/dist/cli/main-ntqef02r.js +10 -0
- package/dist/cli/main-nvc3yjay.js +136 -0
- package/dist/cli/main-p0cfn6nr.js +16 -0
- package/dist/cli/main-qj2djy17.js +19 -0
- package/dist/cli/main-qsevpgsv.js +3 -0
- package/dist/cli/main-qvarybsp.js +3 -0
- package/dist/cli/main-rebtt91r.js +5 -0
- package/dist/cli/main-rpg7h8mb.js +3 -0
- package/dist/cli/main-rsy72qmw.js +15 -0
- package/dist/cli/main-rvetps99.js +18 -0
- package/dist/cli/main-s4bb0jav.js +3 -0
- package/dist/cli/main-s9v8k74e.js +3 -0
- package/dist/cli/main-tjvwmscs.js +3 -0
- package/dist/cli/main-tkgarpjj.js +4 -0
- package/dist/cli/main-v8y60bb2.js +3 -0
- package/dist/cli/main-vhrrq337.js +3 -0
- package/dist/cli/main-vp2dfb7s.js +4 -0
- package/dist/cli/main-vqbr22sz.js +8 -0
- package/dist/cli/main-vxnwe5xx.js +18 -0
- package/dist/cli/main-wgph00xf.js +5 -0
- package/dist/cli/main-wk2csfnj.js +5 -0
- package/dist/cli/main-wm997zjx.js +3 -0
- package/dist/cli/main-wpkyraxh.js +3 -0
- package/dist/cli/main-wqt32p5x.js +4 -0
- package/dist/cli/main-x9ct6y1a.js +3 -0
- package/dist/cli/main-xfekqh9m.js +7 -0
- package/dist/cli/main-xt9zc3n6.js +7 -0
- package/dist/cli/main-xx2z3zh5.js +4 -0
- package/dist/cli/main-y5c82rxr.js +3 -0
- package/dist/cli/main-yrjt2sqt.js +14 -0
- package/dist/cli/main-ys6zj3yr.js +3 -0
- package/dist/cli/main-ywbxshqc.js +8 -0
- package/dist/cli/main-z13755t8.js +25 -0
- package/dist/cli/main-zc7pyrbj.js +4 -0
- package/dist/cli/main.js +279 -0
- package/dist/cli/market-cmd-bm5xvn9f.js +5 -0
- package/dist/cli/mcp-login-bthtfpt7.js +2 -0
- package/dist/cli/mcp-market-cmd-mbeshfyd.js +2 -0
- package/dist/cli/notify-54v5z9dz.js +2 -0
- package/dist/cli/oauth-g5gme95c.js +2 -0
- package/dist/cli/output-satndjap.js +16 -0
- package/dist/cli/profiles-sfhpbq3m.js +2 -0
- package/dist/cli/provider-config-hv3xtdt4.js +2 -0
- package/dist/cli/provider-kwzq6g84.js +2 -0
- package/dist/cli/registry-fh0hdnyn.js +2 -0
- package/dist/cli/registry-y1y8e94r.js +2 -0
- package/dist/cli/repl-t4z03mqq.js +11 -0
- package/dist/cli/resume-fqt4chg8.js +2 -0
- package/dist/cli/run-flags-rysbag9t.js +2 -0
- package/dist/cli/runtime-j19fjbsa.js +2 -0
- package/dist/cli/sandbox-config-g4qxd7y5.js +2 -0
- package/dist/cli/server-r0b6bksk.js +5 -0
- package/dist/cli/session-arg-txmn5g4x.js +2 -0
- package/dist/cli/session-ed250d9j.js +2 -0
- package/dist/cli/sessions-cmd-adw7svfn.js +7 -0
- package/dist/cli/settings-y9rzcqx8.js +2 -0
- package/dist/cli/setup-jmbr11j0.js +2 -0
- package/dist/cli/sextant-smoke-tcth0vea.js +5 -0
- package/dist/cli/skills-cmd-zbdy99v6.js +2 -0
- package/dist/cli/smoke-1bg937kx.js +8 -0
- package/dist/cli/start-chat-p01cdks3.js +12 -0
- package/dist/cli/stream-4wmyaypz.js +2 -0
- package/dist/cli/task-eg4s093s.js +2 -0
- package/dist/cli/tasks-12v9rr9k.js +2 -0
- package/dist/cli/thinking-a5ngvqyh.js +2 -0
- package/dist/cli/todo-1wxpcecx.js +2 -0
- package/dist/cli/tools-2ftsya7w.js +2 -0
- package/dist/cli/tools-x1tj4fxm.js +2 -0
- package/dist/cli/trust-cmd-hccxehzb.js +2 -0
- package/dist/cli/update-check-ygt3vd7m.js +2 -0
- package/dist/cli/update-cmd-v23qhr8c.js +2 -0
- package/dist/cli/voice-g1gtck92.js +2 -0
- package/dist/cli/webfetch-0nnrjgb5.js +2 -0
- package/dist/cli/websearch-f0vr2p7d.js +2 -0
- package/dist/cli/workspace-9rq1w4ta.js +2 -0
- package/dist/lib/index.js +62 -0
- package/dist/lib/models-index.json +1 -0
- package/dist/lib/plugins.js +6 -0
- package/dist/lib/providers.js +17 -0
- package/dist/lib/public-api.js +20 -0
- package/dist/rovecode.exe +4 -0
- package/package.json +83 -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/sextant/overlays.ts
DELETED
|
@@ -1,456 +0,0 @@
|
|
|
1
|
-
/** Sextant overlays (port #43): prompt parsing, the suggestion box, the command palette and the
|
|
2
|
-
* help card. Ported from the user's own sextant v0.4.0 prototype — src/commands.js:8-29
|
|
3
|
-
* (parseInput, mentionAt), :51-59 (resolveFile), src/engine.js:125-137 (fuzzy) and
|
|
4
|
-
* src/app.js:940-1029 (SLASH table, fileOptions, suggestions, drawSuggest), :1075-1089 (drawHelp),
|
|
5
|
-
* :1097-1156 (palette groups/open/close/draw), :1564-1574 (onPaletteKey).
|
|
6
|
-
* Dropped: intent matching, the mock shell table (`!cmd` is plain text for onSubmit), /spawn
|
|
7
|
-
* /crew /undo /permissions /mode /changes /pet /tasks-as-scenarios. Renderer-local commands
|
|
8
|
-
* (/help card, /theme, /open, /diff, /focus, /agents) are listed in LOCAL_COMMANDS and run by
|
|
9
|
-
* local-commands.ts; every other slash line (built-ins + custom, from `s.commands` = setCommands)
|
|
10
|
-
* is handed to onSubmit by keys.ts. `suggestions` caps its rows at MAX_SUGGESTIONS in one place;
|
|
11
|
-
* the drawers never write the state (a paint is not an event).
|
|
12
|
-
* Pure: no Date.now(), no timers, no process access. Palette actions are strings (contract
|
|
13
|
-
* PaletteState.items): a slash line, or `theme:<name>` `mode:<CodeMode>` `focus:<Focus>`
|
|
14
|
-
* `open:<path>` — keys.ts runs them. `fuzzy` is a parameter everywhere (default = the ported
|
|
15
|
-
* scorer) so #40's engine.fuzzy can be plugged in without a hard import. */
|
|
16
|
-
|
|
17
|
-
import type { HitZone } from "./keys.ts";
|
|
18
|
-
import {
|
|
19
|
-
ATTR, THEME_ORDER, type CodeMode, type KeyEvent, type Layout, type PaletteState, type Rect,
|
|
20
|
-
type ScreenLike, type SextantState, type Style, type Theme, type ThemeName,
|
|
21
|
-
} from "./types.ts";
|
|
22
|
-
import { markNoticesRead } from "./model.ts";
|
|
23
|
-
import { MENTION_RE } from "./mentions.ts";
|
|
24
|
-
|
|
25
|
-
// ------------------------------------------------------------------ parsing (commands.js)
|
|
26
|
-
|
|
27
|
-
export type Fuzzy = (q: string, s: string) => { score: number; idx: number[] } | null;
|
|
28
|
-
|
|
29
|
-
/** engine.js:125-137 — subsequence match; +3 for a consecutive hit, +2 at a word/path start */
|
|
30
|
-
export const fuzzy: Fuzzy = (q, s) => {
|
|
31
|
-
q = q.toLowerCase(); s = s.toLowerCase();
|
|
32
|
-
let qi = 0, score = 0, last = -2;
|
|
33
|
-
const idx: number[] = [];
|
|
34
|
-
for (let i = 0; i < s.length && qi < q.length; i++) {
|
|
35
|
-
if (s[i] === q[qi]) {
|
|
36
|
-
idx.push(i);
|
|
37
|
-
score += (last === i - 1 ? 3 : 1) + (i === 0 || s[i - 1] === " " || s[i - 1] === "/" ? 2 : 0);
|
|
38
|
-
last = i; qi++;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return qi === q.length ? { score, idx } : null;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export interface ParsedInput {
|
|
45
|
-
kind: "slash" | "shell" | "text";
|
|
46
|
-
/** slash: the command name (may be ""); shell: the command after `!` */
|
|
47
|
-
cmd?: string;
|
|
48
|
-
/** slash only: undefined = no space typed yet, "" = space typed and nothing after */
|
|
49
|
-
arg?: string;
|
|
50
|
-
mentions: string[];
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** commands.js:8-21 — classify one prompt line (an empty line is `text` with no mentions) */
|
|
54
|
-
export function parseInput(text: string): ParsedInput {
|
|
55
|
-
const t = text.trim();
|
|
56
|
-
if (t[0] === "/") {
|
|
57
|
-
const m = /^\/(\S*)(\s+(.*))?$/s.exec(text.trimStart());
|
|
58
|
-
return { kind: "slash", cmd: m?.[1] ?? "", arg: m?.[2] === undefined ? undefined : (m[3] ?? "").trim(), mentions: [] };
|
|
59
|
-
}
|
|
60
|
-
// `!cmd` runs a shell command (tui/shell-cmd.ts). Narrow on purpose: the bang must be followed by something that
|
|
61
|
-
// is neither whitespace nor another bang, so `!`, `! x` and `!!x` stay plain text for the model. Until the
|
|
62
|
-
// consumer existed this returned "shell" for a lone `!` too — harmless only for as long as nothing ran it.
|
|
63
|
-
if (t[0] === "!" && t.length > 1 && t[1] !== "!" && !/\s/.test(t[1]!)) return { kind: "shell", cmd: t.slice(1).trim(), mentions: [] };
|
|
64
|
-
return { kind: "text", mentions: [...t.matchAll(MENTION_RE)].map((m) => m[1]!) }; // one regex for both surfaces (mentions.ts)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** commands.js:24-29 — the @mention token under the cursor */
|
|
68
|
-
export function mentionAt(text: string, cur: number): { start: number; query: string } | null {
|
|
69
|
-
const m = /(?:^|\s)@([\w./-]*)$/.exec(text.slice(0, cur));
|
|
70
|
-
return m ? { start: cur - m[1]!.length - 1, query: m[1]! } : null;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/** commands.js:51-59 — exact path, then a unique basename, then the best fuzzy hit */
|
|
74
|
-
export function resolveFile(query: string, paths: readonly string[], fz: Fuzzy = fuzzy): string | null {
|
|
75
|
-
if (!query) return null;
|
|
76
|
-
const q = query.replace(/^@/, "");
|
|
77
|
-
if (paths.includes(q)) return q;
|
|
78
|
-
const byBase = paths.filter((p) => p.endsWith("/" + q) || p.split("/").pop() === q);
|
|
79
|
-
if (byBase.length === 1) return byBase[0]!;
|
|
80
|
-
return rank(q, paths, fz)[0] ?? null;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** fuzzy-ranked copy of `items` (stable: equal scores keep their order); all items when q is empty */
|
|
84
|
-
function rank<T>(q: string, items: readonly T[], fz: Fuzzy, key: (t: T) => string = String): T[] {
|
|
85
|
-
if (!q) return [...items];
|
|
86
|
-
return items.map((it) => ({ it, m: fz(q, key(it)) })).filter((x) => x.m).sort((a, b) => b.m!.score - a.m!.score).map((x) => x.it);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// ------------------------------------------------------------------ commands
|
|
90
|
-
|
|
91
|
-
export interface CommandInfo { name: string; description: string; arg?: string; local?: boolean; choices?: readonly string[] | (() => readonly string[]); choicesThen?: "submit" | "complete" }
|
|
92
|
-
/** the argument set of an app command right now: a list as given, a function read at suggestion time */
|
|
93
|
-
export const choicesOf = (c: { choices?: readonly string[] | (() => readonly string[]) }): readonly string[] =>
|
|
94
|
-
typeof c.choices === "function" ? c.choices() : c.choices ?? [];
|
|
95
|
-
interface Option { label: string; hint: string }
|
|
96
|
-
|
|
97
|
-
/** app.js:940-965 SLASH minus the mock rows; `options` feeds the argument suggestions */
|
|
98
|
-
export const LOCAL_COMMANDS: readonly (CommandInfo & { options?: (s: SextantState, q: string, fz: Fuzzy) => Option[] })[] = [
|
|
99
|
-
{ name: "help", description: "commands + keys card", local: true },
|
|
100
|
-
{ name: "theme", description: "switch palette", arg: "night·ember·contrast", local: true,
|
|
101
|
-
options: (_s, q, fz) => rank(q, THEME_ORDER, fz).map((t) => ({ label: t, hint: THEME_HINT[t] })) },
|
|
102
|
-
{ name: "open", description: "open a file in the code view", arg: "path", local: true,
|
|
103
|
-
options: (s, q, fz) => fileOptions(s, q, s.files.paths, fz) },
|
|
104
|
-
{ name: "diff", description: "diff of a file (or the current one)", arg: "path?", local: true,
|
|
105
|
-
options: (s, q, fz) => { const changed = s.files.paths.filter((p) => s.files.statuses.has(p)); return fileOptions(s, q, changed.length ? changed : s.files.paths, fz); } },
|
|
106
|
-
{ name: "focus", description: "move keyboard focus", arg: "messages·code·files", local: true,
|
|
107
|
-
options: (_s, q, fz) => rank(q, ["messages", "code", "files"], fz).map((f) => ({ label: f, hint: "" })) },
|
|
108
|
-
{ name: "agents", description: "the crew board (code panel ∷)", local: true },
|
|
109
|
-
{ name: "notices", description: "notification history (⌃b)", local: true },
|
|
110
|
-
{ name: "market", description: "install MCP servers, skills, plugins (⌃m)", local: true },
|
|
111
|
-
{ name: "context", description: "what is in the window right now, item by item (⌃g)", local: true },
|
|
112
|
-
];
|
|
113
|
-
|
|
114
|
-
const THEME_HINT: Record<ThemeName, string> = { night: "night + mint", ember: "ink + ember", contrast: "pure contrast" };
|
|
115
|
-
/** kbd hints for palette view rows and the help card */
|
|
116
|
-
const MODE_KBD: Partial<Record<CodeMode, string>> = { code: "⌃s", diff: "⌃d", run: "⌃r", agents: "⌃a" };
|
|
117
|
-
|
|
118
|
-
/** the prompt's command table: renderer-local rows first, then setCommands (built-ins + custom) */
|
|
119
|
-
export function allCommands(s: SextantState): CommandInfo[] {
|
|
120
|
-
const local = new Set(LOCAL_COMMANDS.map((c) => c.name));
|
|
121
|
-
return [...LOCAL_COMMANDS.map(({ name, description, arg, local: l }) => ({ name, description, arg, local: l })),
|
|
122
|
-
// an app command with a fixed argument set shows it the way a local one does ("auto·off·low·medium·high")
|
|
123
|
-
// a fixed set reads like a local command's ("auto·off·low·medium·high"); a live one is named, not listed
|
|
124
|
-
...s.commands.filter((c) => !local.has(c.name)).map((c) => {
|
|
125
|
-
if (!c.choices) return { name: c.name, description: c.description };
|
|
126
|
-
const arg = typeof c.choices === "function" ? "provider/model" : c.choices.join("·");
|
|
127
|
-
return { name: c.name, description: c.description, arg, choices: c.choices, ...(c.choicesThen ? { choicesThen: c.choicesThen } : {}) };
|
|
128
|
-
})];
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/** app.js:966-970 — top 6 fuzzy-ranked files with their git status as the hint */
|
|
132
|
-
export function fileOptions(s: SextantState, q: string, pool: readonly string[], fz: Fuzzy = fuzzy): Option[] {
|
|
133
|
-
return rank(q, pool, fz).slice(0, 6).map((p) => ({ label: p, hint: s.files.statuses.get(p) ?? "" }));
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// ------------------------------------------------------------------ suggestions (app.js:973-1003)
|
|
137
|
-
|
|
138
|
-
export interface Suggestion {
|
|
139
|
-
kind: "slash" | "arg" | "mention";
|
|
140
|
-
label: string;
|
|
141
|
-
hint: string;
|
|
142
|
-
/** argument placeholder shown dim after a slash command */
|
|
143
|
-
arg?: string;
|
|
144
|
-
/** what Tab does: the completed prompt text and cursor */
|
|
145
|
-
apply: { text: string; cur: number };
|
|
146
|
-
/** what Enter does after applying: "submit" the completed line, or only "complete" it
|
|
147
|
-
* (a mention, or a command that still needs its argument) */
|
|
148
|
-
enter: "submit" | "complete";
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/** rows the box can show — keys.ts wraps ↑↓ over exactly these, so the cap lives here alone.
|
|
152
|
-
* Raised from 8 when /market made the local list eight long: at 8 a bare `/` showed nothing BUT the
|
|
153
|
-
* renderer-local commands, and the app's own (/exit, /model, /effort…) fell off the box entirely. */
|
|
154
|
-
export const MAX_SUGGESTIONS = 10;
|
|
155
|
-
|
|
156
|
-
/** the dropdown above the prompt, at most MAX_SUGGESTIONS rows; [] when nothing applies
|
|
157
|
-
* (overlays, cards, empty or free text) */
|
|
158
|
-
export function suggestions(s: SextantState, files: readonly string[], fz: Fuzzy = fuzzy): Suggestion[] {
|
|
159
|
-
return suggestionRows(s, files, fz).slice(0, MAX_SUGGESTIONS);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function suggestionRows(s: SextantState, files: readonly string[], fz: Fuzzy): Suggestion[] {
|
|
163
|
-
if (s.palette || s.help || s.card) return [];
|
|
164
|
-
const text = s.input.text;
|
|
165
|
-
if (!text.trim()) return [];
|
|
166
|
-
const men = mentionAt(text, s.input.cur);
|
|
167
|
-
if (men) {
|
|
168
|
-
return fileOptions(s, men.query, files, fz).map((o) => ({
|
|
169
|
-
kind: "mention", label: o.label, hint: o.hint, enter: "complete",
|
|
170
|
-
apply: { text: text.slice(0, men.start) + "@" + o.label + " " + text.slice(s.input.cur), cur: men.start + o.label.length + 2 },
|
|
171
|
-
}));
|
|
172
|
-
}
|
|
173
|
-
const p = parseInput(text);
|
|
174
|
-
if (p.kind !== "slash") return [];
|
|
175
|
-
if (p.arg === undefined) {
|
|
176
|
-
return rank(p.cmd ?? "", allCommands(s), fz, (c) => c.name).map((c) => {
|
|
177
|
-
const needsArg = c.arg !== undefined && !c.arg.endsWith("?");
|
|
178
|
-
const t = "/" + c.name + (c.arg ? " " : "");
|
|
179
|
-
return { kind: "slash", label: "/" + c.name, hint: c.description, arg: c.arg, apply: { text: t, cur: t.length }, enter: needsArg ? "complete" : "submit" };
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
const c = LOCAL_COMMANDS.find((x) => x.name === p.cmd);
|
|
183
|
-
if (c?.options) {
|
|
184
|
-
return c.options(s, p.arg, fz).map((o) => {
|
|
185
|
-
const t = "/" + c.name + " " + o.label;
|
|
186
|
-
return { kind: "arg", label: o.label, hint: o.hint, apply: { text: t, cur: t.length }, enter: "submit" };
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
// an app command with a fixed argument set (/effort auto|off|low|medium|high): the same rows, ranked by what is typed
|
|
190
|
-
const app = allCommands(s).find((x) => x.name === p.cmd && x.choices);
|
|
191
|
-
const values = app ? choicesOf(app) : [];
|
|
192
|
-
if (!app || !values.length) return [];
|
|
193
|
-
// a subcommand-style set ("complete") leaves the prompt open with a trailing space for the next word
|
|
194
|
-
const complete = app.choicesThen === "complete";
|
|
195
|
-
return rank(p.arg, values, fz).map((label) => {
|
|
196
|
-
const t = "/" + app.name + " " + label + (complete ? " " : "");
|
|
197
|
-
return { kind: "arg", label, hint: "", apply: { text: t, cur: t.length }, enter: complete ? "complete" : "submit" };
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const st = (fg: number, bg = -1, a = 0): Style => ({ fg, bg, a });
|
|
202
|
-
const ENTER: KeyEvent = { type: "key", name: "enter" };
|
|
203
|
-
|
|
204
|
-
/** app.js:1004-1023 — the box sits just above the prompt line inside the messages panel `rect`;
|
|
205
|
-
* `sugs` is the `suggestions()` list (already capped); a row click selects it and replays Enter
|
|
206
|
-
* (HitZone.key). Painting never writes the state: the highlight is clamped locally. */
|
|
207
|
-
export function drawSuggest(scr: ScreenLike, rect: Rect, s: SextantState, sugs: readonly Suggestion[], C: Theme, hits?: HitZone[]): void {
|
|
208
|
-
if (!sugs.length || s.input.sgSel < 0) return;
|
|
209
|
-
const selected = Math.min(s.input.sgSel, sugs.length - 1);
|
|
210
|
-
const kind = sugs[0]!.kind, cmd = parseInput(s.input.text).cmd;
|
|
211
|
-
const title = kind === "mention" ? "mention a file" : kind === "slash" ? "commands"
|
|
212
|
-
: `/${cmd} · ${allCommands(s).find((c) => c.name === cmd)?.arg ?? ""}`;
|
|
213
|
-
const w = Math.min(rect.w - 4, 76), x = rect.x + 2, h = sugs.length + 3, y0 = Math.max(rect.y + 1, rect.y + rect.h - 3 - h);
|
|
214
|
-
scr.box(x, y0, w, h, st(C.rule2), C.bg2);
|
|
215
|
-
scr.text(x + 2, y0 + 1, [[title, st(C.dim, C.bg2)]]);
|
|
216
|
-
const help = kind === "mention" ? "tab insert" : "tab complete ⏎ run";
|
|
217
|
-
scr.put(x + w - 2 - help.length, y0 + 1, help, st(C.dim, C.bg2));
|
|
218
|
-
sugs.forEach((it, i) => {
|
|
219
|
-
const y = y0 + 2 + i, sel = i === selected;
|
|
220
|
-
const segs: [string, Style][] = [[sel ? "▸ " : " ", st(C.accent, C.bg2)], [it.label, st(sel ? C.fg : C.fg2, C.bg2, sel ? ATTR.BOLD : 0)]];
|
|
221
|
-
if (it.arg) segs.push([" " + it.arg, st(C.dim, C.bg2)]);
|
|
222
|
-
scr.text(x + 2, y, segs, w - 4);
|
|
223
|
-
if (it.hint) { const hw = Math.min(it.hint.length, 34); scr.clip(x + w - 2 - hw, y, it.hint, st(C.muted, C.bg2), hw); }
|
|
224
|
-
hits?.push({ rect: { x, y, w, h: 1 }, onClick: () => { s.input.sgSel = i; }, key: ENTER });
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// ------------------------------------------------------------------ palette (app.js:1097-1156)
|
|
229
|
-
|
|
230
|
-
const GROUPS = ["commands", "theme", "view", "open"];
|
|
231
|
-
type PaletteItem = PaletteState["items"][number];
|
|
232
|
-
|
|
233
|
-
/** groups: commands (local + setCommands), theme, view (code modes + focus), open (every file) */
|
|
234
|
-
export function paletteItems(s: SextantState): PaletteItem[] {
|
|
235
|
-
const items: PaletteItem[] = allCommands(s).map((c) => ({ label: "/" + c.name, group: "commands", action: "/" + c.name }));
|
|
236
|
-
for (const t of THEME_ORDER) items.push({ label: `theme ${t}`, group: "theme", action: `theme:${t}` });
|
|
237
|
-
const views: [string, CodeMode][] = [["code view", "code"], ["diff view", "diff"], ["run output", "run"], ["agents board", "agents"]];
|
|
238
|
-
for (const [label, mode] of views) items.push({ label, group: "view", action: `mode:${mode}` });
|
|
239
|
-
for (const f of ["messages", "code", "files"]) items.push({ label: `focus ${f}`, group: "view", action: `focus:${f}` });
|
|
240
|
-
for (const p of s.files.paths) items.push({ label: p, group: "open", action: `open:${p}` });
|
|
241
|
-
return items;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/** The overlays that can be on screen, and the one rule about them: at most one at a time.
|
|
245
|
-
*
|
|
246
|
-
* Nothing enforced that before — help, the palette and the market each wrote their own field, so ⌃m with
|
|
247
|
-
* the help card up left BOTH set and help painted over a market nobody could reach. The fix is one
|
|
248
|
-
* transition instead of three closers: every opener calls `openOverlay` first, and an opener that forgets
|
|
249
|
-
* is caught by the invariant test rather than by a reader six months later.
|
|
250
|
-
*
|
|
251
|
-
* ADDING A FIFTH: add its field to `closeOthers` below and its name here. That is the whole contract —
|
|
252
|
-
* do not write closing lines into your own opener, or the next one will forget one of them. */
|
|
253
|
-
export type OverlayKind = "palette" | "market" | "help" | "context" | "wizard";
|
|
254
|
-
|
|
255
|
-
/** close every overlay except `keep` (pass null to close them all). The single place that knows the set. */
|
|
256
|
-
export function openOverlay(s: SextantState, keep: OverlayKind | null): void {
|
|
257
|
-
if (keep !== "palette") s.palette = null;
|
|
258
|
-
if (keep !== "market") s.market = null;
|
|
259
|
-
if (keep !== "help") s.help = false;
|
|
260
|
-
if (keep !== "context") s.context = null;
|
|
261
|
-
if (keep !== "wizard") s.wizard = null;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/** which overlays are currently set — the invariant test asserts this is never longer than one */
|
|
265
|
-
export function openOverlays(s: SextantState): OverlayKind[] {
|
|
266
|
-
const out: OverlayKind[] = [];
|
|
267
|
-
if (s.palette) out.push("palette");
|
|
268
|
-
if (s.market) out.push("market");
|
|
269
|
-
if (s.help) out.push("help");
|
|
270
|
-
if (s.context) out.push("context");
|
|
271
|
-
if (s.wizard) out.push("wizard");
|
|
272
|
-
return out;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/** the help card, through the one transition (local-commands /help and anything else that opens it) */
|
|
276
|
-
export function openHelp(s: SextantState): void {
|
|
277
|
-
openOverlay(s, "help");
|
|
278
|
-
s.help = true;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
export function openPalette(s: SextantState, items: PaletteItem[] = paletteItems(s), title?: string): void {
|
|
282
|
-
openOverlay(s, "palette");
|
|
283
|
-
s.palette = { query: "", sel: 0, items, ...(title !== undefined ? { title } : {}) };
|
|
284
|
-
}
|
|
285
|
-
export function closePalette(s: SextantState): void { s.palette = null; }
|
|
286
|
-
|
|
287
|
-
/** The notification history (⌃b, /notices): the palette box titled "notifications", newest first,
|
|
288
|
-
* one row per Notice with its clock as the hint. Read-only rows — Enter just closes (the "noop:"
|
|
289
|
-
* action is ignored by runAction). Opening marks everything read, which clears the frame badge.
|
|
290
|
-
* Reuses the palette rather than adding a fourth overlay: same box, same keys, nothing new to learn. */
|
|
291
|
-
export function openNotices(s: SextantState, now: number = Date.now()): void {
|
|
292
|
-
const items = [...s.notices].reverse().map((n) => ({
|
|
293
|
-
label: `${n.tone === "error" ? "✗" : n.tone === "warn" ? "◆" : "·"} ${n.text}`,
|
|
294
|
-
group: "notices",
|
|
295
|
-
action: "noop:",
|
|
296
|
-
hint: agoLabel(now - n.at),
|
|
297
|
-
}));
|
|
298
|
-
markNoticesRead(s);
|
|
299
|
-
openPalette(s, items.length ? items : [{ label: "no notifications yet", group: "notices", action: "noop:", hint: "" }], "notifications");
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/** "just now" · "12s" · "3m" · "2h" — the age of a notice, coarse on purpose */
|
|
303
|
-
export function agoLabel(ms: number): string {
|
|
304
|
-
const sec = Math.max(0, Math.round(ms / 1000));
|
|
305
|
-
if (sec < 5) return "just now";
|
|
306
|
-
if (sec < 60) return `${sec}s`;
|
|
307
|
-
if (sec < 3600) return `${Math.round(sec / 60)}m`;
|
|
308
|
-
return `${Math.round(sec / 3600)}h`;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/** the rows the query leaves: no query = everything with `open` capped at 6; otherwise fuzzy
|
|
312
|
-
* hits, best first inside each group, groups in their fixed order (app.js:1112-1118) */
|
|
313
|
-
export function paletteVisible(p: PaletteState, fz: Fuzzy = fuzzy): PaletteItem[] {
|
|
314
|
-
const q = p.query.trim();
|
|
315
|
-
if (!q) { let open = 0; return p.items.filter((it) => it.group !== "open" || open++ < 6); }
|
|
316
|
-
return rank(q, p.items, fz, (it) => it.label).sort((a, b) => GROUPS.indexOf(a.group) - GROUPS.indexOf(b.group));
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/** right-aligned hint: command description, theme label, key chord, or git status */
|
|
320
|
-
export function paletteHint(s: SextantState, it: PaletteItem): string {
|
|
321
|
-
if (it.hint !== undefined) return it.hint; // an explicit hint wins, as PaletteState says it does
|
|
322
|
-
if (it.action.startsWith("/")) return allCommands(s).find((c) => "/" + c.name === it.action)?.description ?? "";
|
|
323
|
-
const i = it.action.indexOf(":"), kind = it.action.slice(0, i), rest = it.action.slice(i + 1);
|
|
324
|
-
switch (kind) {
|
|
325
|
-
case "theme": return THEME_HINT[rest as ThemeName] ?? "";
|
|
326
|
-
case "mode": return MODE_KBD[rest as CodeMode] ?? "";
|
|
327
|
-
case "focus": return rest === "files" ? "⌃e" : "";
|
|
328
|
-
case "open": return s.files.statuses.get(rest) ?? "";
|
|
329
|
-
default: return "";
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/** app.js:1122-1156 — returns the cursor cell (after the query). Hits: full-screen close, the box
|
|
334
|
-
* (swallows), each row (select + Enter). */
|
|
335
|
-
export function drawPalette(scr: ScreenLike, L: Layout, C: Theme, s: SextantState, fz: Fuzzy = fuzzy, hits?: HitZone[]): { x: number; y: number } | null {
|
|
336
|
-
const P = s.palette;
|
|
337
|
-
if (!P) return null;
|
|
338
|
-
hits?.push({ rect: { x: 0, y: 0, w: L.w, h: L.h }, onClick: () => closePalette(s) });
|
|
339
|
-
const vis = paletteVisible(P, fz);
|
|
340
|
-
P.sel = Math.max(0, Math.min(P.sel, vis.length - 1));
|
|
341
|
-
const list: ({ type: "group"; name: string } | { type: "item"; it: PaletteItem; idx: number })[] = [];
|
|
342
|
-
let g = "";
|
|
343
|
-
vis.forEach((it, idx) => { if (it.group !== g) { g = it.group; list.push({ type: "group", name: g }); } list.push({ type: "item", it, idx }); });
|
|
344
|
-
const pw = Math.min(72, L.w - 10), px = Math.floor((L.w - pw) / 2);
|
|
345
|
-
const maxList = Math.max(3, Math.min(list.length || 1, Math.floor(L.h / 2)));
|
|
346
|
-
const ph = maxList + 5, py = Math.max(2, Math.floor(L.h * 0.14));
|
|
347
|
-
scr.box(px, py, pw, ph, st(C.accent), C.bg2);
|
|
348
|
-
// the box says what it is. A picker's title comes from the caller, so it is CLIPPED to the box —
|
|
349
|
-
// leaving room for the corner and the `esc` label — rather than trusted to fit (an unclipped
|
|
350
|
-
// sentence ran past the right border and over the panel behind it).
|
|
351
|
-
const boxTitle = ` ${P.title ?? "commands"} `;
|
|
352
|
-
scr.clip(px + 2, py, boxTitle, st(C.accent, -1, ATTR.BOLD), Math.max(0, pw - 4));
|
|
353
|
-
hits?.push({ rect: { x: px, y: py, w: pw, h: ph }, onClick: () => {} });
|
|
354
|
-
scr.put(px + 2, py + 1, "▌", st(C.accent, C.bg2));
|
|
355
|
-
if (P.query) scr.put(px + 4, py + 1, P.query, st(C.fg, C.bg2, ATTR.BOLD), pw - 12);
|
|
356
|
-
else scr.put(px + 4, py + 1, P.title === undefined ? "commands, themes, views, files…" : "type to filter…", st(C.dim, C.bg2), pw - 12);
|
|
357
|
-
scr.put(px + pw - 6, py + 1, "esc", st(C.dim, C.bg2));
|
|
358
|
-
scr.hline(px + 1, py + 2, pw - 2, st(C.rule2, C.bg2), "╌");
|
|
359
|
-
const selRow = list.findIndex((r) => r.type === "item" && r.idx === P.sel);
|
|
360
|
-
const off = selRow >= maxList - 1 ? selRow - maxList + 2 : 0;
|
|
361
|
-
if (!list.length) scr.put(px + 4, py + 3, "no matches", st(C.muted, C.bg2));
|
|
362
|
-
for (let i = 0; i < maxList; i++) {
|
|
363
|
-
const r = list[off + i];
|
|
364
|
-
if (!r) break;
|
|
365
|
-
const y = py + 3 + i;
|
|
366
|
-
if (r.type === "group") { scr.put(px + 4, y, r.name, st(C.dim, C.bg2), pw - 6); continue; } // clipped: a group name is data too
|
|
367
|
-
const sel = r.idx === P.sel;
|
|
368
|
-
scr.text(px + 2, y, [[sel ? "▸ " : " ", st(C.accent, C.bg2)], [r.it.label, st(sel ? C.fg : C.fg2, C.bg2, sel ? ATTR.BOLD : 0)]], pw - 30);
|
|
369
|
-
const hint = paletteHint(s, r.it);
|
|
370
|
-
if (hint) scr.clip(px + pw - 3 - Math.min(hint.length, 24), y, hint, st(C.muted, C.bg2), 24);
|
|
371
|
-
hits?.push({ rect: { x: px, y, w: pw, h: 1 }, onClick: () => { P.sel = r.idx; }, key: ENTER });
|
|
372
|
-
}
|
|
373
|
-
return { x: px + 4 + P.query.length, y: py + 1 };
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
/** app.js:1564-1574 minus ⌃c (keys.ts handles it before delegating): Esc/⌃k/⌃p close, ↑↓ wrap,
|
|
377
|
-
* Enter closes then runs the selected action through `run`, backspace/typing edit the query */
|
|
378
|
-
export function onPaletteKey(s: SextantState, ev: KeyEvent, run: (action: string) => void, fz: Fuzzy = fuzzy): void {
|
|
379
|
-
const P = s.palette;
|
|
380
|
-
if (!P) return;
|
|
381
|
-
const { name, ctrl, alt, ch } = ev;
|
|
382
|
-
if (name === "escape" || (ctrl && (name === "k" || name === "p"))) { closePalette(s); return; }
|
|
383
|
-
const vis = paletteVisible(P, fz), n = Math.max(1, vis.length);
|
|
384
|
-
if (name === "up") { P.sel = (P.sel - 1 + n) % n; return; }
|
|
385
|
-
if (name === "down") { P.sel = (P.sel + 1) % n; return; }
|
|
386
|
-
if (name === "enter") { const it = vis[P.sel]; closePalette(s); if (it) run(it.action); return; }
|
|
387
|
-
if (name === "backspace") { P.query = [...P.query].slice(0, -1).join(""); P.sel = 0; return; } // by code point (😀 is one)
|
|
388
|
-
const c = name === "space" ? " " : ch;
|
|
389
|
-
if (c && !ctrl && !alt) { P.query += c; P.sel = 0; }
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
// ------------------------------------------------------------------ help card (app.js:1075-1089)
|
|
393
|
-
|
|
394
|
-
/** the README keys table with rovecode names */
|
|
395
|
-
export const HELP_KEYS: readonly (readonly [string, string])[] = [
|
|
396
|
-
["⏎", "send · confirm a card · run the suggestion"],
|
|
397
|
-
["tab ⇧tab", "complete a suggestion · cycle focus"],
|
|
398
|
-
["esc esc", "stop the run (the first esc warns)"],
|
|
399
|
-
["⌃c", "quit (interrupts a run first)"],
|
|
400
|
-
["⌃k ⌃p", "command palette"],
|
|
401
|
-
["⌃s ⌃d ⌃r", "code · diff · run view"],
|
|
402
|
-
["⌃a", "agents board"],
|
|
403
|
-
["⌃e", "files panel"],
|
|
404
|
-
["⌃o", "next tab (narrow terminal)"],
|
|
405
|
-
["⌃b", "notifications"],
|
|
406
|
-
["⌃m", "market (install servers, skills, plugins)"],
|
|
407
|
-
["⌃g", "context (what is in the window, and how far our count is from the provider’s)"],
|
|
408
|
-
["⌥d", "market: the selected item's documentation"],
|
|
409
|
-
["⌃v", "paste image · drop a file to attach"],
|
|
410
|
-
["⌃t", "next theme"],
|
|
411
|
-
["⌃n", "new session (/new)"],
|
|
412
|
-
["⌃u", "clear the prompt line"],
|
|
413
|
-
["↑↓ ←→", "files: pick · fold — code: scroll · mode — prompt: history"],
|
|
414
|
-
["⌃← ⌃→", "prompt: jump by word"],
|
|
415
|
-
["home end", "prompt: line start · end (end re-sticks the tail)"],
|
|
416
|
-
["pgup pgdn", "scroll messages · end sticks to the tail"],
|
|
417
|
-
["mouse", "click · wheel · drag a scrollbar"],
|
|
418
|
-
["@file", "mention a file (picker)"],
|
|
419
|
-
];
|
|
420
|
-
|
|
421
|
-
/** [name, description, arg] per command: local rows first, then setCommands */
|
|
422
|
-
export function helpRows(s: SextantState): [string, string, string][] {
|
|
423
|
-
return allCommands(s).map((c) => ["/" + c.name, c.description, c.arg ?? ""]);
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
/** centered card; the command column is cut to the height with an "… N more" row; any click closes */
|
|
427
|
-
export function drawHelp(scr: ScreenLike, L: Layout, C: Theme, s: SextantState, hits?: HitZone[]): void {
|
|
428
|
-
const rows = helpRows(s);
|
|
429
|
-
const w = Math.min(L.w - 8, 112), wide = w >= 110;
|
|
430
|
-
const maxRows = Math.max(1, L.h - 8);
|
|
431
|
-
const shown = rows.length > maxRows ? [...rows.slice(0, maxRows - 1), ["…", `${rows.length - maxRows + 1} more · /help lists all`, ""] as [string, string, string]] : rows;
|
|
432
|
-
// the KEYS column is capped by the same rule as the commands column. It used not to be, because it was
|
|
433
|
-
// shorter than every terminal anyone tried — and then the box height took the max of the two, so adding
|
|
434
|
-
// one chord pushed the bottom border past the frame on a 30-row terminal. A list that grows is a list
|
|
435
|
-
// that has to be cut somewhere.
|
|
436
|
-
const keys: (readonly [string, string])[] = HELP_KEYS.length > maxRows
|
|
437
|
-
? [...HELP_KEYS.slice(0, maxRows - 1), ["…", `${HELP_KEYS.length - maxRows + 1} more`] as [string, string]]
|
|
438
|
-
: [...HELP_KEYS];
|
|
439
|
-
const h = Math.max(shown.length, keys.length) + 6, x = Math.floor((L.w - w) / 2), y = Math.max(1, Math.floor((L.h - h) / 2));
|
|
440
|
-
scr.box(x, y, w, h, st(C.accent), C.bg2);
|
|
441
|
-
scr.text(x + 2, y, [[" help ", st(C.accent, -1, ATTR.BOLD)]]);
|
|
442
|
-
scr.put(x + w - 14, y, " esc closes ", st(C.dim));
|
|
443
|
-
const kx = wide ? x + 70 : x + 50;
|
|
444
|
-
scr.put(x + 3, y + 2, "commands", st(C.muted, C.bg2)); scr.put(kx, y + 2, "keys", st(C.muted, C.bg2));
|
|
445
|
-
shown.forEach(([name, desc, arg], i) => {
|
|
446
|
-
const yy = y + 3 + i;
|
|
447
|
-
scr.put(x + 3, yy, name, st(C.accent, C.bg2), 13); scr.put(x + 17, yy, desc, st(C.fg2, C.bg2), wide ? 28 : 30);
|
|
448
|
-
if (wide && arg) scr.put(x + 46, yy, arg, st(C.dim, C.bg2), 22);
|
|
449
|
-
});
|
|
450
|
-
keys.forEach(([a, b], i) => {
|
|
451
|
-
const yy = y + 3 + i;
|
|
452
|
-
scr.put(kx, yy, a, st(C.fg, C.bg2, ATTR.BOLD), 10); scr.put(kx + 11, yy, b, st(C.fg2, C.bg2), w - (kx - x) - 13);
|
|
453
|
-
});
|
|
454
|
-
scr.put(x + 3, y + h - 2, "plain text and !commands reach the agent as typed · @file attaches the file as a read (400 lines, 8 files)", st(C.dim, C.bg2), w - 6);
|
|
455
|
-
hits?.push({ rect: { x: 0, y: 0, w: L.w, h: L.h }, onClick: () => { s.help = false; } });
|
|
456
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/** Click zones for the panels' own rows — today the files tree.
|
|
2
|
-
*
|
|
3
|
-
* The files panel drew a cursor row and answered to ↑↓ ←→ Enter, and a click anywhere in it merely
|
|
4
|
-
* moved focus there (keys.ts onMouse's fallback), so "click the file to open it" — the one thing
|
|
5
|
-
* everyone tries first — did nothing. Same shape of gap as the card (card-hits.ts): the painter knew
|
|
6
|
-
* where every row was and told nobody.
|
|
7
|
-
*
|
|
8
|
-
* Geometry mirrors drawFiles exactly: rows start at the panel's inner top, one per line, the first
|
|
9
|
-
* visible row is `files.scroll`. Computed AFTER the frame is painted (drawFiles clamps scroll and the
|
|
10
|
-
* cursor while painting), so the zones describe what is actually on screen this frame.
|
|
11
|
-
*
|
|
12
|
-
* A click selects the row AND replays Enter: a directory toggles its fold, a file opens in the code
|
|
13
|
-
* panel — the same two things Enter already does on the cursor row (keys.ts onEnter), so clicking
|
|
14
|
-
* cannot do anything the keyboard could not. */
|
|
15
|
-
|
|
16
|
-
import { inner } from "./draw-util.ts";
|
|
17
|
-
import type { Rect, SextantState, TreeRow } from "./types.ts";
|
|
18
|
-
|
|
19
|
-
export interface RowHit {
|
|
20
|
-
rect: Rect;
|
|
21
|
-
/** the row's index into the flattened tree (files.cursor takes this value) */
|
|
22
|
-
index: number;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** One zone per visible tree row, or [] when the files panel is hidden or empty. `rows` is the
|
|
26
|
-
* flattened tree as drawn this frame (frame loop: treeRows(s)). */
|
|
27
|
-
export function fileRowHits(files: Rect | null, s: SextantState, rows: readonly TreeRow[]): RowHit[] {
|
|
28
|
-
if (files === null || rows.length === 0) return [];
|
|
29
|
-
const B = inner(files);
|
|
30
|
-
if (B.w <= 0 || B.h <= 0) return [];
|
|
31
|
-
const out: RowHit[] = [];
|
|
32
|
-
for (let i = 0; i < B.h; i++) {
|
|
33
|
-
const index = s.files.scroll + i;
|
|
34
|
-
if (index >= rows.length) break;
|
|
35
|
-
out.push({ rect: { x: B.x, y: B.y + i, w: B.w, h: 1 }, index });
|
|
36
|
-
}
|
|
37
|
-
return out;
|
|
38
|
-
}
|