@north-light/crouter 0.3.170 → 0.3.172
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/dist/api/client.d.ts +37 -11
- package/dist/api/client.js +84 -15
- package/dist/api/dto/human.d.ts +53 -39
- package/dist/api/dto/human.js +2 -3
- package/dist/api/dto/inbox.d.ts +0 -1
- package/dist/api/dto/nodes.d.ts +12 -0
- package/dist/api/dto/review-comments.d.ts +137 -0
- package/dist/api/dto/review-comments.js +5 -0
- package/dist/api/dto/reviews.d.ts +109 -0
- package/dist/api/dto/reviews.js +5 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +2 -0
- package/dist/api/routes.d.ts +17 -4
- package/dist/api/routes.js +21 -5
- package/dist/build-root.d.ts +1 -16
- package/dist/build-root.js +1 -25
- package/dist/builtin-memory/00-runtime-base.md +7 -5
- package/dist/builtin-memory/04-base-worker.md +1 -1
- package/dist/builtin-memory/04-orchestration-kernel.md +7 -7
- package/dist/builtin-memory/05-kinds/design/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +1 -1
- package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/plan/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +1 -1
- package/dist/builtin-memory/05-kinds/review/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/review/companion/00-base.md +20 -0
- package/dist/builtin-memory/05-kinds/spec/00-base.md +3 -7
- package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +3 -3
- package/dist/builtin-memory/05-kinds/spec/requirements.md +3 -3
- package/dist/builtin-memory/design.md +2 -2
- package/dist/builtin-memory/insights/capture.md +50 -0
- package/dist/builtin-memory/insights/init.md +45 -0
- package/dist/builtin-memory/insights/listen.md +9 -0
- package/dist/builtin-memory/internal/agent-shaping.md +2 -2
- package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
- package/dist/builtin-memory/internal/plugins.md +12 -11
- package/dist/builtin-memory/internal/storage-tiers.md +2 -2
- package/dist/builtin-memory/{planning.md → plan/roadmap.md} +3 -3
- package/dist/builtin-memory/plan.md +19 -0
- package/dist/builtin-memory/spec/guide.md +38 -0
- package/dist/builtin-memory/spec/requirements.md +31 -0
- package/dist/builtin-memory/spec/roadmap.md +35 -0
- package/dist/builtin-memory/spec.md +10 -86
- package/dist/builtin-pi-packages/pi-crtr-extensions/README.md +3 -4
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/provider-rotation.test.ts +49 -5
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +56 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +920 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +221 -156
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +4 -5
- package/dist/cli.js +2 -6
- package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +7 -35
- package/dist/clients/attach/__tests__/attach-keybindings.test.js +32 -16
- package/dist/clients/attach/__tests__/context-message.test.js +142 -6
- package/dist/clients/attach/__tests__/crtr-output.test.js +29 -45
- package/dist/clients/attach/__tests__/diagram.test.js +1 -1
- package/dist/clients/attach/__tests__/file-review-focus.test.js +48 -0
- package/dist/clients/attach/__tests__/group-activity.test.js +266 -0
- package/dist/clients/attach/__tests__/input-controller-extension-command.test.js +32 -0
- package/dist/clients/attach/__tests__/session-identity-refresh.test.js +32 -0
- package/dist/clients/attach/__tests__/titled-editor-preview.test.js +1 -2
- package/dist/clients/attach/chrome/header.d.ts +10 -0
- package/dist/clients/attach/chrome/header.js +30 -0
- package/dist/clients/attach/chrome/recap.d.ts +7 -0
- package/dist/clients/attach/chrome/recap.js +19 -0
- package/dist/clients/attach/chrome/status-line.d.ts +3 -0
- package/dist/clients/attach/chrome/status-line.js +5 -0
- package/dist/clients/attach/chrome/widgets.js +11 -21
- package/dist/clients/attach/command.js +11 -7
- package/dist/clients/attach/config.d.ts +4 -0
- package/dist/clients/attach/config.js +3 -0
- package/dist/clients/attach/input/controller.d.ts +19 -0
- package/dist/clients/attach/input/controller.js +62 -28
- package/dist/clients/attach/input/titled-editor.d.ts +0 -4
- package/dist/clients/attach/input/titled-editor.js +2 -10
- package/dist/clients/attach/overlays/file-review.d.ts +9 -5
- package/dist/clients/attach/overlays/file-review.js +9 -70
- package/dist/clients/attach/overlays/help.d.ts +33 -0
- package/dist/clients/attach/overlays/help.js +204 -0
- package/dist/clients/attach/render/activity-slot.d.ts +4 -0
- package/dist/clients/attach/render/activity-slot.js +13 -0
- package/dist/clients/attach/render/chat-view.d.ts +117 -12
- package/dist/clients/attach/render/chat-view.js +604 -135
- package/dist/clients/attach/render/context-message.d.ts +2 -1
- package/dist/clients/attach/render/context-message.js +17 -13
- package/dist/clients/attach/render/crtr-output.js +1 -3
- package/dist/clients/attach/render/diagram.js +2 -2
- package/dist/clients/attach/render/edit-diff.d.ts +4 -1
- package/dist/clients/attach/render/edit-diff.js +7 -11
- package/dist/clients/attach/render/group-activity.d.ts +32 -0
- package/dist/clients/attach/render/group-activity.js +206 -0
- package/dist/clients/attach/render/group-recap.d.ts +10 -0
- package/dist/clients/attach/render/group-recap.js +93 -0
- package/dist/clients/attach/render/html-markdown.d.ts +17 -0
- package/dist/clients/attach/render/html-markdown.js +228 -0
- package/dist/clients/attach/render/measured-container.d.ts +96 -0
- package/dist/clients/attach/render/measured-container.js +322 -0
- package/dist/clients/attach/render/scroll-animation.d.ts +8 -0
- package/dist/clients/attach/render/scroll-animation.js +80 -0
- package/dist/clients/attach/render/tool-calls.js +6 -6
- package/dist/clients/attach/render/transcript-copy.d.ts +9 -0
- package/dist/clients/attach/render/transcript-copy.js +81 -0
- package/dist/clients/attach/render/viewport.d.ts +29 -0
- package/dist/clients/attach/render/viewport.js +159 -0
- package/dist/clients/attach/session/bindings.d.ts +10 -7
- package/dist/clients/attach/session/bindings.js +23 -8
- package/dist/clients/attach/session/connection.js +4 -5
- package/dist/clients/attach/session/context.d.ts +6 -4
- package/dist/clients/attach/session/frame.d.ts +34 -0
- package/dist/clients/attach/session/frame.js +176 -0
- package/dist/clients/attach/session/frames.d.ts +4 -1
- package/dist/clients/attach/session/frames.js +14 -1
- package/dist/clients/attach/session/identity.js +4 -3
- package/dist/clients/attach/session/input-wiring.d.ts +14 -4
- package/dist/clients/attach/session/input-wiring.js +15 -13
- package/dist/clients/attach/session/invariant.d.ts +9 -0
- package/dist/clients/attach/session/invariant.js +15 -0
- package/dist/clients/attach/session/keys.d.ts +10 -2
- package/dist/clients/attach/session/keys.js +13 -5
- package/dist/clients/attach/session/layout.d.ts +10 -8
- package/dist/clients/attach/session/layout.js +33 -34
- package/dist/clients/attach/session/mouse.d.ts +18 -0
- package/dist/clients/attach/session/mouse.js +64 -0
- package/dist/clients/attach/session/pane-tag.d.ts +3 -0
- package/dist/clients/attach/session/pane-tag.js +51 -8
- package/dist/clients/attach/session/reconnect.d.ts +3 -0
- package/dist/clients/attach/session/reconnect.js +42 -5
- package/dist/clients/attach/session/surface-frame.d.ts +20 -0
- package/dist/clients/attach/session/surface-frame.js +73 -0
- package/dist/clients/attach/session/surface-host.d.ts +64 -0
- package/dist/clients/attach/session/surface-host.js +255 -0
- package/dist/clients/attach/session/whip.d.ts +17 -0
- package/dist/clients/attach/session/whip.js +334 -0
- package/dist/clients/attach/slash/dispatch.d.ts +13 -1
- package/dist/clients/attach/slash/dispatch.js +51 -29
- package/dist/clients/attach/viewer.js +907 -819
- package/dist/clients/conversation/conversation.d.ts +65 -0
- package/dist/clients/conversation/conversation.js +318 -0
- package/dist/clients/conversation/frames.d.ts +30 -0
- package/dist/clients/conversation/frames.js +52 -0
- package/dist/clients/conversation/region.d.ts +51 -0
- package/dist/clients/conversation/region.js +265 -0
- package/dist/clients/conversation/submit.d.ts +38 -0
- package/dist/clients/conversation/submit.js +51 -0
- package/dist/clients/inbox/__tests__/inbox-controller.test.js +247 -0
- package/dist/clients/inbox/__tests__/mount-panel.test.js +776 -0
- package/dist/clients/inbox/controller.d.ts +79 -0
- package/dist/clients/inbox/controller.js +448 -0
- package/dist/clients/inbox/deck-adapter.d.ts +29 -0
- package/dist/clients/inbox/deck-adapter.js +62 -0
- package/dist/clients/inbox/layout.d.ts +8 -0
- package/dist/clients/inbox/layout.js +9 -0
- package/dist/clients/inbox/resolve.d.ts +10 -0
- package/dist/clients/inbox/resolve.js +34 -0
- package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.js +29 -0
- package/dist/clients/inbox/review/__tests__/remap.test.js +196 -0
- package/dist/clients/inbox/review/__tests__/review-core.test.js +341 -0
- package/dist/clients/inbox/review/anchors.d.ts +41 -0
- package/dist/clients/inbox/review/anchors.js +89 -0
- package/dist/clients/inbox/review/columns.d.ts +22 -0
- package/dist/clients/inbox/review/columns.js +40 -0
- package/dist/clients/inbox/review/comments-client.d.ts +66 -0
- package/dist/clients/inbox/review/comments-client.js +98 -0
- package/dist/clients/inbox/review/composition.d.ts +60 -0
- package/dist/clients/inbox/review/composition.js +278 -0
- package/dist/clients/inbox/review/document-region.d.ts +120 -0
- package/dist/clients/inbox/review/document-region.js +902 -0
- package/dist/clients/inbox/review/frame.d.ts +45 -0
- package/dist/clients/inbox/review/frame.js +215 -0
- package/dist/clients/inbox/review/keys.d.ts +67 -0
- package/dist/clients/inbox/review/keys.js +130 -0
- package/dist/clients/inbox/review/launch.d.ts +10 -0
- package/dist/clients/inbox/review/launch.js +129 -0
- package/dist/clients/inbox/review/live-source.d.ts +24 -0
- package/dist/clients/inbox/review/live-source.js +160 -0
- package/dist/clients/inbox/review/nvim.d.ts +13 -0
- package/dist/clients/inbox/review/nvim.js +42 -0
- package/dist/clients/inbox/review/remap.d.ts +51 -0
- package/dist/clients/inbox/review/remap.js +157 -0
- package/dist/clients/inbox/review/review-client.d.ts +30 -0
- package/dist/clients/inbox/review/review-client.js +107 -0
- package/dist/clients/inbox/review/roundtrip.d.ts +5 -0
- package/dist/clients/inbox/review/roundtrip.js +36 -0
- package/dist/clients/inbox/review/state.d.ts +143 -0
- package/dist/clients/inbox/review/state.js +282 -0
- package/dist/clients/inbox/review-adapter.d.ts +29 -0
- package/dist/clients/inbox/review-adapter.js +92 -0
- package/dist/clients/inbox/review-visibility.d.ts +5 -0
- package/dist/clients/inbox/review-visibility.js +19 -0
- package/dist/clients/inbox/surface.d.ts +19 -0
- package/dist/clients/inbox/surface.js +128 -0
- package/dist/clients/inbox/tui/ansi.d.ts +66 -0
- package/dist/clients/inbox/tui/ansi.js +317 -0
- package/dist/clients/inbox/tui/clipboard.d.ts +2 -0
- package/dist/clients/inbox/tui/clipboard.js +26 -0
- package/dist/clients/inbox/tui/input.d.ts +7 -0
- package/dist/clients/inbox/tui/input.js +653 -0
- package/dist/clients/inbox/tui/keys.d.ts +28 -0
- package/dist/clients/inbox/tui/keys.js +111 -0
- package/dist/clients/inbox/tui/panel.d.ts +2 -0
- package/dist/clients/inbox/tui/panel.js +217 -0
- package/dist/clients/inbox/tui/render.d.ts +37 -0
- package/dist/clients/inbox/tui/render.js +476 -0
- package/dist/clients/inbox/tui/types.d.ts +57 -0
- package/dist/clients/inbox/tui/types.js +1 -0
- package/dist/clients/inbox/tui.d.ts +6 -0
- package/dist/clients/inbox/tui.js +74 -0
- package/dist/clients/surfaces/host.d.ts +66 -0
- package/dist/clients/surfaces/host.js +1 -0
- package/dist/clients/surfaces/region.d.ts +16 -0
- package/dist/clients/surfaces/region.js +1 -0
- package/dist/clients/web/__tests__/push-engine.test.js +14 -158
- package/dist/clients/web/dev-server.d.ts +3 -3
- package/dist/clients/web/dev-server.js +9 -23
- package/dist/clients/web/events.js +4 -6
- package/dist/clients/web/push-engine.d.ts +2 -66
- package/dist/clients/web/push-engine.js +30 -161
- package/dist/clients/web/push-registry.d.ts +0 -4
- package/dist/clients/web/push-registry.js +2 -7
- package/dist/clients/web/server.js +3 -35
- package/dist/clients/web/web-client/shared/protocol.d.ts +0 -108
- package/dist/clients/web/web-cmd.js +2 -2
- package/dist/commands/__tests__/human.test.js +27 -15
- package/dist/commands/api-client.js +3 -3
- package/dist/commands/canvas-browse.js +1 -1
- package/dist/commands/canvas-issue.js +1 -1
- package/dist/commands/canvas-use.js +1 -1
- package/dist/commands/human/doc.d.ts +2 -0
- package/dist/commands/human/doc.js +98 -0
- package/dist/commands/human/inbox.d.ts +2 -0
- package/dist/commands/human/inbox.js +101 -0
- package/dist/commands/human/prompts.d.ts +2 -3
- package/dist/commands/human/prompts.js +27 -180
- package/dist/commands/human/queue.d.ts +1 -5
- package/dist/commands/human/queue.js +54 -216
- package/dist/commands/human/review.d.ts +2 -0
- package/dist/commands/human/review.js +298 -0
- package/dist/commands/human/shared.d.ts +2 -69
- package/dist/commands/human/shared.js +1 -181
- package/dist/commands/human.js +15 -20
- package/dist/commands/memory/__tests__/lint.test.d.ts +1 -0
- package/dist/commands/memory/__tests__/lint.test.js +15 -0
- package/dist/commands/memory/delete.js +2 -2
- package/dist/commands/memory/lint.d.ts +1 -0
- package/dist/commands/memory/lint.js +21 -3
- package/dist/commands/memory/read.js +4 -4
- package/dist/commands/node.js +8 -7
- package/dist/commands/pkg/plugin-manage.js +143 -68
- package/dist/commands/surface-inspect.js +2 -2
- package/dist/commands/surface.js +6 -12
- package/dist/commands/sys/__tests__/setup-core.test.js +9 -5
- package/dist/commands/sys/__tests__/setup-front-door.test.js +7 -42
- package/dist/commands/sys/config.js +29 -3
- package/dist/commands/sys/feedback.js +1 -1
- package/dist/commands/sys/setup-core.d.ts +12 -11
- package/dist/commands/sys/setup-core.js +55 -46
- package/dist/commands/sys/setup-wizard.d.ts +4 -1
- package/dist/commands/sys/setup-wizard.js +50 -9
- package/dist/commands/sys/sync-deps.js +1 -1
- package/dist/commands/sys.js +4 -6
- package/dist/core/__tests__/broker-sdk-wiring.test.js +6 -1
- package/dist/core/__tests__/broker-snapshot-history.test.js +9 -1
- package/dist/core/__tests__/dead-node-policy-table.test.js +3 -4
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +8 -5
- package/dist/core/__tests__/fixtures/fake-engine.js +28 -2
- package/dist/core/__tests__/full/broker-provider-retry.test.js +87 -2
- package/dist/core/__tests__/full/broker-whip-interrupt.test.d.ts +1 -0
- package/dist/core/__tests__/full/broker-whip-interrupt.test.js +39 -0
- package/dist/core/__tests__/full/detach-focus.test.js +1 -1
- package/dist/core/__tests__/human-deliver-e2e.test.js +64 -64
- package/dist/core/__tests__/human-deliver.test.js +71 -345
- package/dist/core/__tests__/inline-memory-refs.test.js +2 -12
- package/dist/core/__tests__/memory-resolver-precedence.test.js +12 -15
- package/dist/core/__tests__/migration.test.js +10 -0
- package/dist/core/__tests__/model-pin-durability.test.js +14 -0
- package/dist/core/__tests__/phase4-review-migration.test.d.ts +1 -0
- package/dist/core/__tests__/phase4-review-migration.test.js +100 -0
- package/dist/core/__tests__/phase4-review-store.test.d.ts +1 -0
- package/dist/core/__tests__/phase4-review-store.test.js +143 -0
- package/dist/core/__tests__/remote-canvas-target.test.js +2 -2
- package/dist/core/__tests__/revive.test.js +22 -53
- package/dist/core/__tests__/session-cycles.test.js +48 -18
- package/dist/core/__tests__/spawn-no-kickoff.test.js +8 -12
- package/dist/core/__tests__/stop-guard.test.js +16 -1
- package/dist/core/__tests__/tmux-surface.test.js +21 -25
- package/dist/core/asset-root.d.ts +7 -0
- package/dist/core/asset-root.js +18 -0
- package/dist/core/broker-client/client.d.ts +0 -7
- package/dist/core/broker-client/client.js +4 -10
- package/dist/core/broker-client/transport-relay.d.ts +3 -4
- package/dist/core/broker-client/transport-relay.js +3 -4
- package/dist/core/canvas/__tests__/attention.test.js +1 -1
- package/dist/core/canvas/__tests__/remote-canvas-source.test.js +1 -1
- package/dist/core/canvas/__tests__/remote-transport.test.d.ts +1 -0
- package/dist/core/{view/__tests__/transport-remote.test.js → canvas/__tests__/remote-transport.test.js} +2 -2
- package/dist/core/canvas/__tests__/render-remote.test.js +1 -1
- package/dist/core/canvas/attention.js +4 -4
- package/dist/core/canvas/canvas.d.ts +6 -11
- package/dist/core/canvas/canvas.js +11 -33
- package/dist/core/canvas/db.js +207 -38
- package/dist/core/canvas/extensions.d.ts +1 -1
- package/dist/core/canvas/extensions.js +8 -1
- package/dist/core/canvas/index.d.ts +0 -1
- package/dist/core/canvas/index.js +0 -1
- package/dist/core/canvas/nav-model.d.ts +1 -1
- package/dist/core/canvas/nav-model.js +1 -1
- package/dist/core/canvas/paths.d.ts +5 -0
- package/dist/core/canvas/paths.js +16 -0
- package/dist/core/canvas/remote-canvas-source.js +2 -2
- package/dist/core/canvas/remote-transport.d.ts +7 -0
- package/dist/core/{view/transport-remote.js → canvas/remote-transport.js} +3 -4
- package/dist/core/canvas/source.js +1 -1
- package/dist/core/canvas/status-glyph.js +4 -12
- package/dist/core/canvas/types.d.ts +10 -35
- package/dist/core/clipboard-text.d.ts +8 -0
- package/dist/core/clipboard-text.js +18 -0
- package/dist/core/command-manifests/registry.d.ts +1 -3
- package/dist/core/command-plugins/bundle.d.ts +29 -0
- package/dist/core/command-plugins/bundle.js +198 -0
- package/dist/core/command-plugins/discovery.d.ts +0 -8
- package/dist/core/command-plugins/discovery.js +2 -39
- package/dist/core/command-plugins/transport/http-fetch.d.ts +4 -30
- package/dist/core/command-plugins/transport/http-fetch.js +17 -95
- package/dist/core/command.d.ts +1 -13
- package/dist/core/command.js +1 -16
- package/dist/core/config.d.ts +4 -0
- package/dist/core/config.js +28 -3
- package/dist/core/document-lines.d.ts +4 -0
- package/dist/core/document-lines.js +6 -0
- package/dist/core/feed/feed.d.ts +2 -0
- package/dist/core/feed/feed.js +11 -7
- package/dist/core/human/__tests__/inbox-cancel-worker.d.ts +1 -0
- package/dist/core/human/__tests__/inbox-cancel-worker.js +7 -0
- package/dist/core/human/__tests__/inbox-claim-worker.d.ts +1 -0
- package/dist/core/human/__tests__/inbox-claim-worker.js +17 -0
- package/dist/core/human/__tests__/inbox-core.test.d.ts +1 -0
- package/dist/core/human/__tests__/inbox-core.test.js +144 -0
- package/dist/core/human/__tests__/inbox-stale-claim-worker.d.ts +1 -0
- package/dist/core/human/__tests__/inbox-stale-claim-worker.js +8 -0
- package/dist/core/human/__tests__/visible-paths.test.d.ts +1 -0
- package/dist/{clients/attach → core/human}/__tests__/visible-paths.test.js +9 -0
- package/dist/core/human/claim.d.ts +23 -0
- package/dist/core/human/claim.js +67 -0
- package/dist/core/human/convention.d.ts +30 -0
- package/dist/core/human/convention.js +202 -0
- package/dist/core/human/deck-factories.d.ts +8 -0
- package/dist/core/human/deck-factories.js +15 -0
- package/dist/core/human/deck-schema.d.ts +70 -0
- package/dist/core/human/deck-schema.js +92 -0
- package/dist/core/human/root.d.ts +7 -0
- package/dist/core/human/root.js +37 -0
- package/dist/core/human/scan.d.ts +3 -0
- package/dist/core/human/scan.js +76 -0
- package/dist/core/human/summary.d.ts +8 -0
- package/dist/core/human/summary.js +44 -0
- package/dist/core/human/tickets.d.ts +49 -0
- package/dist/core/human/tickets.js +190 -0
- package/dist/core/human/types.d.ts +136 -0
- package/dist/core/human/types.js +5 -0
- package/dist/{clients/attach → core/human}/visible-paths.d.ts +1 -1
- package/dist/{clients/attach → core/human}/visible-paths.js +3 -2
- package/dist/core/inspector/chrome.d.ts +6 -0
- package/dist/core/inspector/chrome.js +14 -0
- package/dist/core/inspector/contract.d.ts +105 -0
- package/dist/core/inspector/contract.js +1 -0
- package/dist/core/inspector/core.d.ts +4 -5
- package/dist/core/inspector/core.js +3 -5
- package/dist/core/inspector/host.d.ts +46 -0
- package/dist/core/{tui → inspector}/host.js +42 -208
- package/dist/core/inspector/text.d.ts +2 -2
- package/dist/core/inspector/transport.d.ts +6 -0
- package/dist/core/inspector/transport.js +36 -0
- package/dist/core/inspector/tui.d.ts +2 -2
- package/dist/core/inspector/tui.js +15 -15
- package/dist/core/keybindings/__tests__/inbox-affordance.test.js +11 -11
- package/dist/core/keybindings/__tests__/resolve.test.js +10 -19
- package/dist/core/keybindings/attach-control.d.ts +9 -3
- package/dist/core/keybindings/attach-control.js +3 -1
- package/dist/core/keybindings/catalog.d.ts +6 -5
- package/dist/core/keybindings/catalog.js +61 -133
- package/dist/core/keybindings/inbox.d.ts +5 -6
- package/dist/core/keybindings/inbox.js +9 -10
- package/dist/core/keybindings/index.d.ts +3 -3
- package/dist/core/keybindings/index.js +3 -3
- package/dist/core/keybindings/persistence.d.ts +5 -1
- package/dist/core/keybindings/persistence.js +24 -6
- package/dist/core/keybindings/resolve.d.ts +6 -0
- package/dist/core/keybindings/resolve.js +10 -3
- package/dist/core/memory/inline-ref-grammar.js +2 -3
- package/dist/core/memory-resolver.d.ts +27 -29
- package/dist/core/memory-resolver.js +45 -39
- package/dist/core/model-routes.d.ts +33 -0
- package/dist/core/model-routes.js +42 -3
- package/dist/core/preview-registry.js +17 -55
- package/dist/core/profiles/select.js +3 -3
- package/dist/core/{view/remote-canvas-target.d.ts → remote-canvas-target.d.ts} +2 -2
- package/dist/core/{view/remote-canvas-target.js → remote-canvas-target.js} +4 -4
- package/dist/core/review/__tests__/capture-origin.test.d.ts +1 -0
- package/dist/core/review/__tests__/capture-origin.test.js +139 -0
- package/dist/core/review/__tests__/comments.test.d.ts +1 -0
- package/dist/core/review/__tests__/comments.test.js +98 -0
- package/dist/core/review/__tests__/project.test.d.ts +1 -0
- package/dist/core/review/__tests__/project.test.js +71 -0
- package/dist/core/review/__tests__/remap.test.d.ts +1 -0
- package/dist/core/review/__tests__/remap.test.js +159 -0
- package/dist/core/review/__tests__/stage-identity.test.d.ts +1 -0
- package/dist/core/review/__tests__/stage-identity.test.js +140 -0
- package/dist/core/review/birth.d.ts +7 -0
- package/dist/core/review/birth.js +23 -0
- package/dist/core/review/comments.d.ts +69 -0
- package/dist/core/review/comments.js +295 -0
- package/dist/core/review/companion.d.ts +35 -0
- package/dist/core/review/companion.js +205 -0
- package/dist/core/review/document.d.ts +27 -0
- package/dist/core/review/document.js +138 -0
- package/dist/core/review/project.d.ts +13 -0
- package/dist/core/review/project.js +58 -0
- package/dist/core/review/realize.d.ts +19 -0
- package/dist/core/review/realize.js +217 -0
- package/dist/core/review/remap.d.ts +24 -0
- package/dist/core/review/remap.js +156 -0
- package/dist/core/review/signal.d.ts +5 -0
- package/dist/core/review/signal.js +31 -0
- package/dist/core/review/stage.d.ts +26 -0
- package/dist/core/review/stage.js +184 -0
- package/dist/core/review/store.d.ts +46 -0
- package/dist/core/review/store.js +163 -0
- package/dist/core/review/ticket-filter.d.ts +17 -0
- package/dist/core/review/ticket-filter.js +32 -0
- package/dist/core/review/types.d.ts +130 -0
- package/dist/core/review/types.js +23 -0
- package/dist/core/runtime/__tests__/session-visibility.test.d.ts +1 -0
- package/dist/core/runtime/__tests__/session-visibility.test.js +119 -0
- package/dist/core/runtime/bearings.d.ts +5 -17
- package/dist/core/runtime/bearings.js +88 -71
- package/dist/core/runtime/broker-protocol.d.ts +31 -8
- package/dist/core/runtime/broker.d.ts +15 -1
- package/dist/core/runtime/broker.js +573 -141
- package/dist/core/runtime/canvas-extensions.d.ts +4 -5
- package/dist/core/runtime/canvas-extensions.js +5 -5
- package/dist/core/runtime/front-door.js +4 -4
- package/dist/core/runtime/headless-pi.d.ts +24 -0
- package/dist/core/runtime/headless-pi.js +152 -0
- package/dist/core/runtime/kickoff.d.ts +1 -5
- package/dist/core/runtime/kickoff.js +1 -5
- package/dist/core/runtime/model-registry.d.ts +3 -0
- package/dist/core/runtime/model-registry.js +13 -0
- package/dist/core/runtime/naming-persist.d.ts +4 -0
- package/dist/core/runtime/naming-persist.js +27 -1
- package/dist/core/runtime/naming.d.ts +17 -12
- package/dist/core/runtime/naming.js +91 -140
- package/dist/core/runtime/node-read.js +19 -10
- package/dist/core/runtime/nodes.d.ts +9 -14
- package/dist/core/runtime/nodes.js +3 -53
- package/dist/core/runtime/package-health.d.ts +6 -21
- package/dist/core/runtime/package-health.js +12 -123
- package/dist/core/runtime/placement-tmux.d.ts +2 -1
- package/dist/core/runtime/placement-tmux.js +6 -4
- package/dist/core/runtime/placement.d.ts +1 -0
- package/dist/core/runtime/placement.js +4 -8
- package/dist/core/runtime/promote.js +3 -0
- package/dist/core/runtime/recap.d.ts +2 -7
- package/dist/core/runtime/recap.js +35 -69
- package/dist/core/runtime/revive.js +34 -77
- package/dist/core/runtime/session-cycles.d.ts +4 -0
- package/dist/core/runtime/session-cycles.js +14 -1
- package/dist/core/runtime/session-visibility.d.ts +37 -0
- package/dist/core/runtime/session-visibility.js +83 -0
- package/dist/core/runtime/spawn.js +10 -22
- package/dist/core/runtime/stop-guard.d.ts +1 -1
- package/dist/core/runtime/stop-guard.js +18 -13
- package/dist/core/runtime/surface-bg.js +1 -1
- package/dist/core/runtime/tmux-chrome.d.ts +1 -1
- package/dist/core/runtime/tmux-chrome.js +1 -1
- package/dist/core/runtime/tmux.d.ts +35 -7
- package/dist/core/runtime/tmux.js +439 -62
- package/dist/core/runtime/tool-group-summary.d.ts +19 -0
- package/dist/core/runtime/tool-group-summary.js +88 -0
- package/dist/core/scope.d.ts +2 -7
- package/dist/core/scope.js +9 -35
- package/dist/core/substrate/schema.d.ts +2 -2
- package/dist/core/termrender/code-doc.d.ts +12 -0
- package/dist/core/termrender/code-doc.js +92 -0
- package/dist/core/termrender/display.d.ts +12 -0
- package/dist/core/termrender/display.js +19 -0
- package/dist/core/termrender/termrender.d.ts +73 -0
- package/dist/core/termrender/termrender.js +795 -0
- package/dist/core/termrender/version.d.ts +1 -0
- package/dist/core/termrender/version.js +1 -0
- package/dist/core/tui/terminal.js +1 -2
- package/dist/core/user-settings.d.ts +71 -3
- package/dist/core/user-settings.js +83 -1
- package/dist/daemon/api/__tests__/inbox.test.js +44 -133
- package/dist/daemon/api/handlers/human.d.ts +0 -10
- package/dist/daemon/api/handlers/human.js +104 -702
- package/dist/daemon/api/handlers/inbox.js +113 -142
- package/dist/daemon/api/handlers/review-comments.d.ts +2 -0
- package/dist/daemon/api/handlers/review-comments.js +500 -0
- package/dist/daemon/api/handlers/reviews.d.ts +2 -0
- package/dist/daemon/api/handlers/reviews.js +287 -0
- package/dist/daemon/api/map.d.ts +22 -7
- package/dist/daemon/api/map.js +159 -11
- package/dist/daemon/api/server.js +4 -0
- package/dist/daemon/cron-run.js +6 -9
- package/dist/daemon/crtrd.js +17 -33
- package/dist/daemon/fleet.d.ts +1 -8
- package/dist/daemon/fleet.js +4 -30
- package/dist/daemon/human/finish.d.ts +14 -0
- package/dist/daemon/human/finish.js +115 -0
- package/dist/daemon/human/sweep.d.ts +6 -0
- package/dist/daemon/human/sweep.js +49 -0
- package/dist/daemon/messaging/node-message.d.ts +18 -0
- package/dist/daemon/messaging/node-message.js +70 -0
- package/dist/daemon/review/comment-notify.d.ts +26 -0
- package/dist/daemon/review/comment-notify.js +107 -0
- package/dist/daemon/review/deliver.d.ts +7 -0
- package/dist/daemon/review/deliver.js +56 -0
- package/dist/daemon/review/finish.d.ts +22 -0
- package/dist/daemon/review/finish.js +254 -0
- package/dist/daemon/review/sweep.d.ts +11 -0
- package/dist/daemon/review/sweep.js +120 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -2
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +42 -64
- package/dist/pi-extensions/__tests__/canvas-recap.test.d.ts +1 -0
- package/dist/pi-extensions/__tests__/canvas-recap.test.js +159 -0
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +16 -38
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.d.ts +1 -0
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +63 -0
- package/dist/pi-extensions/canvas-context-intro.d.ts +8 -11
- package/dist/pi-extensions/canvas-context-intro.js +50 -104
- package/dist/pi-extensions/canvas-recap.d.ts +15 -2
- package/dist/pi-extensions/canvas-recap.js +192 -69
- package/dist/pi-extensions/canvas-review-boundary.d.ts +59 -0
- package/dist/pi-extensions/canvas-review-boundary.js +81 -0
- package/dist/pi-extensions/canvas-stophook.d.ts +3 -3
- package/dist/pi-extensions/canvas-stophook.js +78 -128
- package/dist/pi-extensions/canvas-structured-output.js +52 -8
- package/dist/shared/generated-context.d.ts +29 -4
- package/dist/shared/generated-context.js +122 -7
- package/dist/shared/tool-groups.d.ts +23 -0
- package/dist/shared/tool-groups.js +60 -0
- package/dist/shared/working-activity.d.ts +8 -0
- package/dist/shared/working-activity.js +26 -0
- package/dist/types.d.ts +36 -2
- package/dist/types.js +51 -0
- package/dist/web-client/assets/index-CCPaLeW7.css +2 -0
- package/dist/web-client/assets/index-kyOWsnZK.js +86 -0
- package/dist/web-client/index.html +2 -2
- package/dist/web-client/sw.js +1 -1
- package/docs/compat/hearth-crtr-v4.md +2 -2
- package/docs/compat/hearth-crtr-v5.md +4 -2
- package/docs/public-api.md +3 -3
- package/package.json +21 -14
- package/runtime.lock.json +4661 -1453
- package/scripts/postinstall.mjs +15 -2
- package/dist/builtin-pi-packages/pi-mode-switch/README.md +0 -36
- package/dist/builtin-pi-packages/pi-mode-switch/bin/mode +0 -36
- package/dist/builtin-pi-packages/pi-mode-switch/extensions/index.ts +0 -449
- package/dist/builtin-pi-packages/pi-mode-switch/package.json +0 -14
- package/dist/builtin-pi-packages/pi-mode-switch/tsconfig.json +0 -9
- package/dist/builtin-views/_lib/states.mjs +0 -161
- package/dist/builtin-views/canvas/core.mjs +0 -657
- package/dist/builtin-views/canvas/text.mjs +0 -58
- package/dist/builtin-views/canvas/tui.mjs +0 -168
- package/dist/builtin-views/canvas/web.jsx +0 -121
- package/dist/builtin-views/chat/core.mjs +0 -684
- package/dist/builtin-views/chat/text.mjs +0 -101
- package/dist/builtin-views/chat/tui.mjs +0 -360
- package/dist/builtin-views/chat/web.jsx +0 -362
- package/dist/builtin-views/git-pr/core.mjs +0 -673
- package/dist/builtin-views/git-pr/text.mjs +0 -84
- package/dist/builtin-views/git-pr/tui.mjs +0 -301
- package/dist/builtin-views/git-pr/web.jsx +0 -216
- package/dist/builtin-views/inbox/_lib/render.mjs +0 -175
- package/dist/builtin-views/inbox/core.mjs +0 -1273
- package/dist/builtin-views/inbox/text.mjs +0 -73
- package/dist/builtin-views/inbox/tui.mjs +0 -314
- package/dist/builtin-views/inbox/web.jsx +0 -188
- package/dist/builtin-views/linkedin/core.mjs +0 -906
- package/dist/builtin-views/linkedin/text.mjs +0 -69
- package/dist/builtin-views/linkedin/tui.mjs +0 -413
- package/dist/builtin-views/linkedin/web.jsx +0 -206
- package/dist/builtin-views/prompt-review/core.mjs +0 -735
- package/dist/builtin-views/prompt-review/text.mjs +0 -15
- package/dist/builtin-views/prompt-review/tui.mjs +0 -196
- package/dist/builtin-views/prompt-review/web.jsx +0 -484
- package/dist/builtin-views/workspace-sidebar/__tests__/core.test.js +0 -50
- package/dist/builtin-views/workspace-sidebar/__tests__/core.test.ts +0 -53
- package/dist/builtin-views/workspace-sidebar/core.mjs +0 -670
- package/dist/builtin-views/workspace-sidebar/text.mjs +0 -53
- package/dist/builtin-views/workspace-sidebar/tui.mjs +0 -141
- package/dist/builtin-views/workspace-sidebar/web.jsx +0 -109
- package/dist/clients/attach/session/mode.d.ts +0 -25
- package/dist/clients/attach/session/mode.js +0 -97
- package/dist/commands/sys/promptstudio.d.ts +0 -2
- package/dist/commands/sys/promptstudio.js +0 -65
- package/dist/commands/view-cycle.d.ts +0 -2
- package/dist/commands/view-cycle.js +0 -130
- package/dist/commands/view-list.d.ts +0 -2
- package/dist/commands/view-list.js +0 -66
- package/dist/commands/view-new.d.ts +0 -2
- package/dist/commands/view-new.js +0 -74
- package/dist/commands/view-pick.d.ts +0 -6
- package/dist/commands/view-pick.js +0 -129
- package/dist/commands/view-run.d.ts +0 -2
- package/dist/commands/view-run.js +0 -214
- package/dist/commands/view.d.ts +0 -2
- package/dist/commands/view.js +0 -31
- package/dist/commands/workspace.d.ts +0 -2
- package/dist/commands/workspace.js +0 -165
- package/dist/core/__tests__/chat-view-reconnect.test.js +0 -105
- package/dist/core/__tests__/full/consult-startup-failure.test.js +0 -124
- package/dist/core/canvas/__tests__/human-work-outbox.test.js +0 -123
- package/dist/core/canvas/human-work-outbox.d.ts +0 -73
- package/dist/core/canvas/human-work-outbox.js +0 -261
- package/dist/core/command-plugins/store.d.ts +0 -16
- package/dist/core/command-plugins/store.js +0 -64
- package/dist/core/keybindings/__tests__/bespoke-consumers.test.js +0 -40
- package/dist/core/runtime/fault-recovery-nudge.d.ts +0 -3
- package/dist/core/runtime/fault-recovery-nudge.js +0 -3
- package/dist/core/tui/__tests__/host-keybindings.test.js +0 -113
- package/dist/core/tui/host.d.ts +0 -66
- package/dist/core/view/__tests__/transport-cache.test.js +0 -62
- package/dist/core/view/bridge.d.ts +0 -10
- package/dist/core/view/bridge.js +0 -31
- package/dist/core/view/chrome.d.ts +0 -9
- package/dist/core/view/chrome.js +0 -22
- package/dist/core/view/contract.d.ts +0 -205
- package/dist/core/view/contract.js +0 -23
- package/dist/core/view/loader.d.ts +0 -31
- package/dist/core/view/loader.js +0 -188
- package/dist/core/view/stream-local.d.ts +0 -3
- package/dist/core/view/stream-local.js +0 -231
- package/dist/core/view/transport-cache.d.ts +0 -8
- package/dist/core/view/transport-cache.js +0 -38
- package/dist/core/view/transport-local.d.ts +0 -7
- package/dist/core/view/transport-local.js +0 -83
- package/dist/core/view/transport-remote.d.ts +0 -2
- package/dist/core/view/transport.d.ts +0 -10
- package/dist/core/view/transport.js +0 -15
- package/dist/pi-extensions/naming-tool.d.ts +0 -24
- package/dist/pi-extensions/naming-tool.js +0 -67
- package/dist/prompts/view.d.ts +0 -7
- package/dist/prompts/view.js +0 -172
- package/dist/web/ViewChrome.d.ts +0 -7
- package/dist/web/ViewChrome.js +0 -28
- package/dist/web/ViewPane.d.ts +0 -39
- package/dist/web/ViewPane.js +0 -48
- package/dist/web/index.d.ts +0 -8
- package/dist/web/index.js +0 -22
- package/dist/web/runtime.d.ts +0 -39
- package/dist/web/runtime.js +0 -232
- package/dist/web/states.d.ts +0 -24
- package/dist/web/states.js +0 -24
- package/dist/web/transport-http.d.ts +0 -5
- package/dist/web/transport-http.js +0 -34
- package/dist/web/transport-stream.d.ts +0 -3
- package/dist/web/transport-stream.js +0 -204
- package/dist/web-client/assets/index-U_NZ66VE.js +0 -79
- package/dist/web-client/assets/index-aaeu4adv.css +0 -2
- /package/dist/{builtin-views/workspace-sidebar/__tests__/core.test.d.ts → clients/attach/__tests__/file-review-focus.test.d.ts} +0 -0
- /package/dist/clients/attach/__tests__/{visible-paths.test.d.ts → group-activity.test.d.ts} +0 -0
- /package/dist/{core/__tests__/chat-view-reconnect.test.d.ts → clients/attach/__tests__/input-controller-extension-command.test.d.ts} +0 -0
- /package/dist/{core/__tests__/full/consult-startup-failure.test.d.ts → clients/attach/__tests__/session-identity-refresh.test.d.ts} +0 -0
- /package/dist/{core/canvas/__tests__/human-work-outbox.test.d.ts → clients/inbox/__tests__/inbox-controller.test.d.ts} +0 -0
- /package/dist/{core/keybindings/__tests__/bespoke-consumers.test.d.ts → clients/inbox/__tests__/mount-panel.test.d.ts} +0 -0
- /package/dist/{core/tui/__tests__/host-keybindings.test.d.ts → clients/inbox/review/__tests__/editor-roundtrip.test.d.ts} +0 -0
- /package/dist/{core/view/__tests__/transport-cache.test.d.ts → clients/inbox/review/__tests__/remap.test.d.ts} +0 -0
- /package/dist/{core/view/__tests__/transport-remote.test.d.ts → clients/inbox/review/__tests__/review-core.test.d.ts} +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { RenderedDoc } from '../../../core/termrender/termrender.js';
|
|
2
|
+
import type { ReviewState } from './state.js';
|
|
3
|
+
/** Width prose is rendered at for a given terminal width: 2-col left
|
|
4
|
+
* margin + 2-col gutter before the content, capped for readability. */
|
|
5
|
+
export declare function renderWidthForCols(cols: number): number;
|
|
6
|
+
/** The body rectangle a rendered row is painted into: the terminal minus the
|
|
7
|
+
* 4-col gutter prefix. Diagram blocks render at this width (no prose cap),
|
|
8
|
+
* and every emitted body row is contained within it. */
|
|
9
|
+
export declare function contentWidthForCols(cols: number): number;
|
|
10
|
+
/** Body width left after an optional line-number gutter. */
|
|
11
|
+
export declare function bodyWidth(cols: number, gutterW?: number): number;
|
|
12
|
+
/** The mapped render this surface paints: prose at the readability cap,
|
|
13
|
+
* diagrams at the full body width. */
|
|
14
|
+
export declare function renderReviewDoc(content: string, cols: number): RenderedDoc;
|
|
15
|
+
/** Widest painted row, in display cells, for a body window. */
|
|
16
|
+
export declare function widestVisibleRow(doc: RenderedDoc, scroll: number, bodyHeight: number): number;
|
|
17
|
+
/** How far the body can pan right, given what is currently on screen. Zero
|
|
18
|
+
* when nothing visible overflows — which is also what makes h/l contextual:
|
|
19
|
+
* the keys only pan while an overflowing row is in view. */
|
|
20
|
+
export declare function maxHScroll(state: ReviewState, doc: RenderedDoc, cols: number, rows: number, gutterW?: number): number;
|
|
21
|
+
/** Pan the body horizontally, clamped to what is currently reachable. The
|
|
22
|
+
* stored offset is only ever clamped against the live window, so vertical
|
|
23
|
+
* scrolling and resize can never leave it pointing past the content. */
|
|
24
|
+
export declare function panBy(state: ReviewState, delta: number, doc: RenderedDoc, cols: number, rows: number, gutterW?: number): ReviewState;
|
|
25
|
+
/** Cells one h/l press pans by — a chunk large enough to cross a diagram in a
|
|
26
|
+
* few presses, small enough to keep orientation. */
|
|
27
|
+
export declare const PAN_STEP = 8;
|
|
28
|
+
/** Reserved (non-body) rows for each mode's fixed header/footer chrome. Kept in
|
|
29
|
+
* sync with renderReviewFrame so scroll math can clamp before a repaint — the
|
|
30
|
+
* compose case counts the same hard-wrapped input lines the frame renders. */
|
|
31
|
+
export declare function reservedRows(state: ReviewState, cols: number): number;
|
|
32
|
+
export declare function renderReviewFrame(state: ReviewState, fileLabel: string, doc: RenderedDoc, cols: number, rows: number, opts?: {
|
|
33
|
+
lineNumbers?: boolean;
|
|
34
|
+
notice?: string;
|
|
35
|
+
}): string[];
|
|
36
|
+
export interface ReviewSurfaceKind {
|
|
37
|
+
/** `markdown` renders the file AS a document; `code` renders it as a
|
|
38
|
+
* syntax-highlighted source panel with a line-number gutter. */
|
|
39
|
+
doc: 'markdown' | 'code';
|
|
40
|
+
/** Fence language for `doc: 'code'` (see `fenceLanguageFor`). */
|
|
41
|
+
language?: string;
|
|
42
|
+
}
|
|
43
|
+
/** How a reviewed file is presented: markdown renders as a document, anything
|
|
44
|
+
* else as a syntax-highlighted source panel. */
|
|
45
|
+
export declare function docSurface(absFile: string): ReviewSurfaceKind;
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import stringWidth from 'string-width';
|
|
2
|
+
import { renderMarkdownBlockAware } from '../../../core/termrender/termrender.js';
|
|
3
|
+
import { fenceLanguageFor, isMarkdownFile } from '../../../core/termrender/code-doc.js';
|
|
4
|
+
import { renderInputBuffer } from '../tui/render.js';
|
|
5
|
+
import { BOLD, CYAN, DIM, ESC, RESET, YELLOW, centerHorizontal, clipLine, hline, panLine, sanitize, truncate, visibleWidth } from '../tui/ansi.js';
|
|
6
|
+
import { commentedUnitSet, selectedUnitBounds } from './state.js';
|
|
7
|
+
// ── Rendering (pure) ─────────────────────────────────────────────────────────
|
|
8
|
+
/** Width prose is rendered at for a given terminal width: 2-col left
|
|
9
|
+
* margin + 2-col gutter before the content, capped for readability. */
|
|
10
|
+
export function renderWidthForCols(cols) {
|
|
11
|
+
return Math.min(Math.max(20, cols - 6), 120);
|
|
12
|
+
}
|
|
13
|
+
/** The body rectangle a rendered row is painted into: the terminal minus the
|
|
14
|
+
* 4-col gutter prefix. Diagram blocks render at this width (no prose cap),
|
|
15
|
+
* and every emitted body row is contained within it. */
|
|
16
|
+
export function contentWidthForCols(cols) {
|
|
17
|
+
return Math.max(20, cols - 4);
|
|
18
|
+
}
|
|
19
|
+
/** Body width left after an optional line-number gutter. */
|
|
20
|
+
export function bodyWidth(cols, gutterW = 0) {
|
|
21
|
+
return Math.max(1, contentWidthForCols(cols) - (gutterW > 0 ? gutterW + 1 : 0));
|
|
22
|
+
}
|
|
23
|
+
/** The mapped render this surface paints: prose at the readability cap,
|
|
24
|
+
* diagrams at the full body width. */
|
|
25
|
+
export function renderReviewDoc(content, cols) {
|
|
26
|
+
return renderMarkdownBlockAware(content, renderWidthForCols(cols), contentWidthForCols(cols));
|
|
27
|
+
}
|
|
28
|
+
/** Body rows as they are actually painted. Vertical-scroll indicators replace
|
|
29
|
+
* their endpoint rows, so content behind one cannot advertise or claim h/l. */
|
|
30
|
+
function paintedBodyRows(doc, scroll, bodyHeight) {
|
|
31
|
+
const rows = [];
|
|
32
|
+
for (let i = 0; i < bodyHeight; i++) {
|
|
33
|
+
const abs = scroll + i;
|
|
34
|
+
rows.push(abs < doc.lines.length ? { abs, line: doc.lines[abs] } : { abs: null, line: '' });
|
|
35
|
+
}
|
|
36
|
+
if (scroll > 0 && rows.length > 0)
|
|
37
|
+
rows[0] = { abs: null, line: ` ${DIM}↑ ${scroll} more above${RESET}` };
|
|
38
|
+
const remaining = doc.lines.length - (scroll + bodyHeight);
|
|
39
|
+
if (remaining > 0 && rows.length > 0)
|
|
40
|
+
rows[rows.length - 1] = { abs: null, line: ` ${DIM}↓ ${remaining} more below${RESET}` };
|
|
41
|
+
return rows;
|
|
42
|
+
}
|
|
43
|
+
/** Widest painted row, in display cells, for a body window. */
|
|
44
|
+
export function widestVisibleRow(doc, scroll, bodyHeight) {
|
|
45
|
+
let widest = 0;
|
|
46
|
+
for (const row of paintedBodyRows(doc, scroll, bodyHeight))
|
|
47
|
+
widest = Math.max(widest, visibleWidth(row.line));
|
|
48
|
+
return widest;
|
|
49
|
+
}
|
|
50
|
+
/** How far the body can pan right, given what is currently on screen. Zero
|
|
51
|
+
* when nothing visible overflows — which is also what makes h/l contextual:
|
|
52
|
+
* the keys only pan while an overflowing row is in view. */
|
|
53
|
+
export function maxHScroll(state, doc, cols, rows, gutterW = 0) {
|
|
54
|
+
const bodyHeight = Math.max(1, rows - reservedRows(state, cols));
|
|
55
|
+
const maxScroll = Math.max(0, doc.lines.length - bodyHeight);
|
|
56
|
+
const scroll = Math.max(0, Math.min(state.scroll, maxScroll));
|
|
57
|
+
return Math.max(0, widestVisibleRow(doc, scroll, bodyHeight) - bodyWidth(cols, gutterW));
|
|
58
|
+
}
|
|
59
|
+
/** Pan the body horizontally, clamped to what is currently reachable. The
|
|
60
|
+
* stored offset is only ever clamped against the live window, so vertical
|
|
61
|
+
* scrolling and resize can never leave it pointing past the content. */
|
|
62
|
+
export function panBy(state, delta, doc, cols, rows, gutterW = 0) {
|
|
63
|
+
const max = maxHScroll(state, doc, cols, rows, gutterW);
|
|
64
|
+
const next = Math.max(0, Math.min(state.hscroll + delta, max));
|
|
65
|
+
return next === state.hscroll ? state : { ...state, hscroll: next };
|
|
66
|
+
}
|
|
67
|
+
/** Cells one h/l press pans by — a chunk large enough to cross a diagram in a
|
|
68
|
+
* few presses, small enough to keep orientation. */
|
|
69
|
+
export const PAN_STEP = 8;
|
|
70
|
+
// Single-hue anchor tint (a dark neutral step below the CYAN gutter bar).
|
|
71
|
+
// termrender's only reset is `\x1b[0m`, so re-arming the background after each
|
|
72
|
+
// reset keeps the tint alive across inner styling. Heading rows carry their
|
|
73
|
+
// own background and won't show the tint — the gutter bar still marks them.
|
|
74
|
+
const TINT_BG = `${ESC}48;5;236m`;
|
|
75
|
+
function tintRow(row, width) {
|
|
76
|
+
const pad = Math.max(0, width - stringWidth(sanitize(row)));
|
|
77
|
+
return TINT_BG + row.replaceAll(RESET, RESET + TINT_BG) + ' '.repeat(pad) + RESET;
|
|
78
|
+
}
|
|
79
|
+
/** Reserved (non-body) rows for each mode's fixed header/footer chrome. Kept in
|
|
80
|
+
* sync with renderReviewFrame so scroll math can clamp before a repaint — the
|
|
81
|
+
* compose case counts the same hard-wrapped input lines the frame renders. */
|
|
82
|
+
export function reservedRows(state, cols) {
|
|
83
|
+
const header = 3; // blank, title, divider
|
|
84
|
+
if (state.mode === 'view')
|
|
85
|
+
return header + 1;
|
|
86
|
+
if (state.mode === 'compose') {
|
|
87
|
+
const c = state.compose;
|
|
88
|
+
const maxW = Math.min(Math.max(20, cols - 4), 120);
|
|
89
|
+
const bufLines = c ? renderInputBuffer(c.buffer, c.cursor, Math.max(10, maxW - 2)).length : 1;
|
|
90
|
+
return header + 3 + bufLines;
|
|
91
|
+
}
|
|
92
|
+
if (state.mode === 'list')
|
|
93
|
+
return header + Math.max(1, state.comments.length) + 2;
|
|
94
|
+
return header + 9; // help
|
|
95
|
+
}
|
|
96
|
+
export function renderReviewFrame(state, fileLabel, doc, cols, rows, opts) {
|
|
97
|
+
const maxW = Math.min(Math.max(20, cols - 4), 120);
|
|
98
|
+
const docW = renderWidthForCols(cols);
|
|
99
|
+
const header = [
|
|
100
|
+
'',
|
|
101
|
+
` ${BOLD}${CYAN}Review — ${fileLabel}${RESET} ${DIM}${state.comments.length} comment${state.comments.length === 1 ? '' : 's'}${RESET}`,
|
|
102
|
+
` ${DIM}${hline(maxW)}${RESET}`,
|
|
103
|
+
];
|
|
104
|
+
const footer = [];
|
|
105
|
+
if (state.mode === 'compose' && state.compose) {
|
|
106
|
+
const c = state.compose;
|
|
107
|
+
const label = c.anchor.line === c.anchor.endLine ? `L${c.anchor.line}` : `L${c.anchor.line}-${c.anchor.endLine}`;
|
|
108
|
+
footer.push(` ${YELLOW}${c.editingId !== null ? 'Edit comment' : 'Comment'} on ${label}:${RESET}`);
|
|
109
|
+
for (const l of renderInputBuffer(c.buffer, c.cursor, Math.max(10, maxW - 2)))
|
|
110
|
+
footer.push(` ${l}`);
|
|
111
|
+
footer.push('');
|
|
112
|
+
footer.push(` ${DIM}enter${RESET} save ${DIM}^J/⌥⏎${RESET} newline ${DIM}esc${RESET} cancel`);
|
|
113
|
+
}
|
|
114
|
+
else if (state.mode === 'list') {
|
|
115
|
+
if (state.comments.length === 0) {
|
|
116
|
+
footer.push(` ${DIM}(no comments yet — space c to add one)${RESET}`);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
state.comments.forEach((c, i) => {
|
|
120
|
+
const loc = c.line === c.endLine ? `L${c.line}` : `L${c.line}-${c.endLine}`;
|
|
121
|
+
const cursor = i === state.listIndex ? `${CYAN}▸${RESET}` : ' ';
|
|
122
|
+
const text = truncate(c.comment.replace(/\n/g, ' / '), Math.max(10, maxW - 14));
|
|
123
|
+
footer.push(` ${cursor} ${DIM}[${loc}]${RESET} ${text}`);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
footer.push('');
|
|
127
|
+
footer.push(` ${DIM}j/k${RESET} move ${DIM}enter/e${RESET} edit ${DIM}d${RESET} delete ${DIM}q/esc${RESET} close`);
|
|
128
|
+
}
|
|
129
|
+
else if (state.mode === 'help') {
|
|
130
|
+
footer.push(' Keys:');
|
|
131
|
+
footer.push(` ${DIM}j/k${RESET} move anchor ${DIM}shift-j/k${RESET} extend selection`);
|
|
132
|
+
footer.push(` ${DIM}u/d${RESET} scroll document ${DIM}h/l${RESET} pan visible wide diagrams`);
|
|
133
|
+
footer.push(` ${DIM}space c${RESET} compose comment ${DIM}space l${RESET} list comments`);
|
|
134
|
+
footer.push(` ${DIM}space u${RESET} undo last comment ${DIM}space e${RESET} edit in $EDITOR`);
|
|
135
|
+
footer.push(` ${DIM}space s${RESET} submit review`);
|
|
136
|
+
footer.push(` ${DIM}?${RESET} toggle this help ${DIM}esc${RESET} close/cancel`);
|
|
137
|
+
footer.push('');
|
|
138
|
+
footer.push(` ${DIM}esc / ?${RESET} close`);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
footer.push(` ${DIM}j/k${RESET} · ${DIM}shift-j/k${RESET} · ${DIM}u/d${RESET} · ${DIM}space c${RESET} · ${DIM}space l${RESET} · ` +
|
|
142
|
+
`${DIM}space u${RESET} · ${DIM}space e${RESET} · ${DIM}space s${RESET} submit · ${DIM}?${RESET} · ${DIM}esc${RESET}`);
|
|
143
|
+
}
|
|
144
|
+
if (opts?.notice !== undefined && footer.length > 0) {
|
|
145
|
+
footer[footer.length - 1] = ` ${YELLOW}${opts.notice}${RESET}`;
|
|
146
|
+
}
|
|
147
|
+
const reserved = header.length + footer.length;
|
|
148
|
+
const bodyHeight = Math.max(1, rows - reserved);
|
|
149
|
+
const maxScroll = Math.max(0, doc.lines.length - bodyHeight);
|
|
150
|
+
const scroll = Math.max(0, Math.min(state.scroll, maxScroll));
|
|
151
|
+
const gutterW = opts?.lineNumbers === true ? String(doc.lines.length).length : 0;
|
|
152
|
+
const contentW = bodyWidth(cols, gutterW);
|
|
153
|
+
// Effective pan: the stored offset, clamped to what this window can reach.
|
|
154
|
+
// Scrolling into narrow content parks the diagram offset rather than losing
|
|
155
|
+
// it, so scrolling back restores the same horizontal position.
|
|
156
|
+
const widest = widestVisibleRow(doc, scroll, bodyHeight);
|
|
157
|
+
const overflow = Math.max(0, widest - contentW);
|
|
158
|
+
const hscroll = Math.max(0, Math.min(state.hscroll, overflow));
|
|
159
|
+
const { lo, hi } = selectedUnitBounds(state);
|
|
160
|
+
const commented = commentedUnitSet(state);
|
|
161
|
+
const body = [];
|
|
162
|
+
for (const source of paintedBodyRows(doc, scroll, bodyHeight)) {
|
|
163
|
+
if (source.abs === null) {
|
|
164
|
+
// Indicator/fill rows reserve the same 4-col marker prefix and gutter a
|
|
165
|
+
// source row does, so the content column never shifts while scrolling.
|
|
166
|
+
body.push(` ${' '.repeat(gutterW > 0 ? gutterW + 1 : 0)}${source.line}`);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
// Every body row is windowed into the body rectangle: a diagram wider than
|
|
170
|
+
// the pane pans instead of spilling past the right edge.
|
|
171
|
+
const row = panLine(source.line, hscroll, contentW);
|
|
172
|
+
const u = state.rowUnits[source.abs] ?? null;
|
|
173
|
+
// A row with no span is chrome (the code panel's border), not a source
|
|
174
|
+
// line — it gets blank gutter width rather than an invented line number.
|
|
175
|
+
const gutterLine = doc.spans[source.abs]?.[0];
|
|
176
|
+
const gutter = gutterW > 0
|
|
177
|
+
? (gutterLine === undefined ? ' '.repeat(gutterW + 1) : `${DIM}${String(gutterLine).padStart(gutterW)}${RESET} `)
|
|
178
|
+
: '';
|
|
179
|
+
// Tint the prose column at minimum, and a wide row across what it occupies.
|
|
180
|
+
const tintW = Math.min(contentW, Math.max(docW, visibleWidth(row)));
|
|
181
|
+
if (u !== null && u >= lo && u <= hi)
|
|
182
|
+
body.push(` ${CYAN}▌${RESET} ${gutter}${tintRow(row, tintW)}`);
|
|
183
|
+
else if (u !== null && commented.has(u))
|
|
184
|
+
body.push(` ${YELLOW}▎${RESET} ${gutter}${row}`);
|
|
185
|
+
else
|
|
186
|
+
body.push(` ${gutter}${row}`);
|
|
187
|
+
}
|
|
188
|
+
while (body.length < bodyHeight)
|
|
189
|
+
body.push('');
|
|
190
|
+
// Keep the header, footer, and readable body rows in one stable centered
|
|
191
|
+
// column. A full-width diagram drops only its own row padding, so it can use
|
|
192
|
+
// the pane without shifting the surrounding review as it scrolls into view.
|
|
193
|
+
const readableFrameW = Math.min(cols, Math.max(maxW + 2, docW + 4 + (gutterW > 0 ? gutterW + 1 : 0)));
|
|
194
|
+
const centeredBody = body.map((line) => {
|
|
195
|
+
const frameW = visibleWidth(line) > readableFrameW ? cols : readableFrameW;
|
|
196
|
+
return centerHorizontal([line], cols, frameW)[0] ?? '';
|
|
197
|
+
});
|
|
198
|
+
const lines = [
|
|
199
|
+
...centerHorizontal(header, cols, readableFrameW),
|
|
200
|
+
...centeredBody,
|
|
201
|
+
...centerHorizontal(footer, cols, readableFrameW),
|
|
202
|
+
];
|
|
203
|
+
while (lines.length < rows)
|
|
204
|
+
lines.push('');
|
|
205
|
+
// The frame is contained by construction: no row may exceed the terminal, or
|
|
206
|
+
// it wraps and breaks the differ's one-line-per-row model.
|
|
207
|
+
return lines.slice(0, rows).map((line) => clipLine(line, cols));
|
|
208
|
+
}
|
|
209
|
+
/** How a reviewed file is presented: markdown renders as a document, anything
|
|
210
|
+
* else as a syntax-highlighted source panel. */
|
|
211
|
+
export function docSurface(absFile) {
|
|
212
|
+
return isMarkdownFile(absFile)
|
|
213
|
+
? { doc: 'markdown' }
|
|
214
|
+
: { doc: 'code', language: fenceLanguageFor(absFile) };
|
|
215
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/** A semantic keypress for the review surface. Textual commands retain their
|
|
2
|
+
* text because their meaning is mode-dependent: `j` navigates in view/list
|
|
3
|
+
* mode and inserts in compose mode, for example. */
|
|
4
|
+
export type ReviewKey = {
|
|
5
|
+
type: 'moveUnit';
|
|
6
|
+
delta: -1 | 1;
|
|
7
|
+
text: 'j' | 'k';
|
|
8
|
+
} | {
|
|
9
|
+
type: 'extendUnit';
|
|
10
|
+
delta: -1 | 1;
|
|
11
|
+
text: 'J' | 'K';
|
|
12
|
+
} | {
|
|
13
|
+
type: 'scrollPage';
|
|
14
|
+
delta: -1 | 1;
|
|
15
|
+
text?: 'u' | 'd';
|
|
16
|
+
} | {
|
|
17
|
+
type: 'pan';
|
|
18
|
+
delta: -1 | 1;
|
|
19
|
+
text?: 'h' | 'l';
|
|
20
|
+
} | {
|
|
21
|
+
type: 'leader';
|
|
22
|
+
text: ' ';
|
|
23
|
+
} | {
|
|
24
|
+
type: 'help';
|
|
25
|
+
text: '?';
|
|
26
|
+
} | {
|
|
27
|
+
type: 'listEdit';
|
|
28
|
+
text: 'e';
|
|
29
|
+
} | {
|
|
30
|
+
type: 'cancel';
|
|
31
|
+
text?: 'q';
|
|
32
|
+
} | {
|
|
33
|
+
type: 'confirm';
|
|
34
|
+
} | {
|
|
35
|
+
type: 'tab';
|
|
36
|
+
reverse: boolean;
|
|
37
|
+
} | {
|
|
38
|
+
type: 'composeNewline';
|
|
39
|
+
} | {
|
|
40
|
+
type: 'composeBackspace';
|
|
41
|
+
} | {
|
|
42
|
+
type: 'composeWordBackspace';
|
|
43
|
+
} | {
|
|
44
|
+
type: 'composeDelete';
|
|
45
|
+
} | {
|
|
46
|
+
type: 'composeHome';
|
|
47
|
+
} | {
|
|
48
|
+
type: 'composeEnd';
|
|
49
|
+
} | {
|
|
50
|
+
type: 'composeMove';
|
|
51
|
+
direction: 'wordLeft' | 'wordRight';
|
|
52
|
+
} | {
|
|
53
|
+
type: 'arrow';
|
|
54
|
+
direction: 'left' | 'right' | 'up' | 'down';
|
|
55
|
+
} | {
|
|
56
|
+
type: 'printable';
|
|
57
|
+
text: string;
|
|
58
|
+
} | {
|
|
59
|
+
type: 'paste';
|
|
60
|
+
text: string;
|
|
61
|
+
};
|
|
62
|
+
/** Return text that compose mode inserts. Semantic textual commands deliberately
|
|
63
|
+
* retain their payload so compose can preserve the old branch order. */
|
|
64
|
+
export declare function reviewKeyText(key: ReviewKey): string | undefined;
|
|
65
|
+
/** Match one complete pi-tui input chunk. pi-tui owns ESC/meta disambiguation;
|
|
66
|
+
* this function has neither terminal state nor a fallback raw-sequence parser. */
|
|
67
|
+
export declare function matchReviewKey(data: string): ReviewKey | null;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Key, decodeKittyPrintable, matchesKey, parseKey } from '@earendil-works/pi-tui';
|
|
2
|
+
/** pi-tui parses legacy ESC+lowercase as Alt+letter, but does not normalize
|
|
3
|
+
* the shifted uppercase form. Convert that complete two-byte form to the
|
|
4
|
+
* equivalent CSI-u key so all semantic matching stays in pi-tui. */
|
|
5
|
+
function normalizeLegacyShiftedMeta(data) {
|
|
6
|
+
if (data.length !== 2 || data[0] !== '\x1b' || !/[A-Z]/.test(data[1]))
|
|
7
|
+
return data;
|
|
8
|
+
return `\x1b[${data.charCodeAt(1)};4u`;
|
|
9
|
+
}
|
|
10
|
+
/** Return text that compose mode inserts. Semantic textual commands deliberately
|
|
11
|
+
* retain their payload so compose can preserve the old branch order. */
|
|
12
|
+
export function reviewKeyText(key) {
|
|
13
|
+
switch (key.type) {
|
|
14
|
+
case 'moveUnit':
|
|
15
|
+
case 'extendUnit':
|
|
16
|
+
case 'leader':
|
|
17
|
+
case 'help':
|
|
18
|
+
case 'listEdit':
|
|
19
|
+
case 'printable':
|
|
20
|
+
case 'paste':
|
|
21
|
+
return key.text;
|
|
22
|
+
case 'scrollPage':
|
|
23
|
+
case 'pan':
|
|
24
|
+
case 'cancel':
|
|
25
|
+
return key.text;
|
|
26
|
+
default:
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Match one complete pi-tui input chunk. pi-tui owns ESC/meta disambiguation;
|
|
31
|
+
* this function has neither terminal state nor a fallback raw-sequence parser. */
|
|
32
|
+
export function matchReviewKey(data) {
|
|
33
|
+
const normalized = normalizeLegacyShiftedMeta(data);
|
|
34
|
+
// Compose-only chords precede their unmodified forms. The surface applies
|
|
35
|
+
// these only while composing, preserving the terminal-review mode ladder.
|
|
36
|
+
if (matchesKey(normalized, Key.ctrl('j')) || matchesKey(normalized, Key.alt('enter')))
|
|
37
|
+
return { type: 'composeNewline' };
|
|
38
|
+
if (matchesKey(normalized, Key.alt('backspace')) || matchesKey(normalized, Key.ctrl('w')))
|
|
39
|
+
return { type: 'composeWordBackspace' };
|
|
40
|
+
if (matchesKey(normalized, Key.backspace))
|
|
41
|
+
return { type: 'composeBackspace' };
|
|
42
|
+
if (matchesKey(normalized, Key.delete))
|
|
43
|
+
return { type: 'composeDelete' };
|
|
44
|
+
if (matchesKey(normalized, Key.alt('left')) || matchesKey(normalized, Key.ctrl('left')) || matchesKey(normalized, Key.super('left')) || matchesKey(normalized, Key.alt('b'))) {
|
|
45
|
+
return { type: 'composeMove', direction: 'wordLeft' };
|
|
46
|
+
}
|
|
47
|
+
if (matchesKey(normalized, Key.alt('right')) || matchesKey(normalized, Key.ctrl('right')) || matchesKey(normalized, Key.super('right')) || matchesKey(normalized, Key.alt('f'))) {
|
|
48
|
+
return { type: 'composeMove', direction: 'wordRight' };
|
|
49
|
+
}
|
|
50
|
+
if (matchesKey(normalized, Key.home) || matchesKey(normalized, Key.ctrl('a')))
|
|
51
|
+
return { type: 'composeHome' };
|
|
52
|
+
if (matchesKey(normalized, Key.end) || matchesKey(normalized, Key.ctrl('e')))
|
|
53
|
+
return { type: 'composeEnd' };
|
|
54
|
+
if (matchesKey(normalized, Key.shift('tab')))
|
|
55
|
+
return { type: 'tab', reverse: true };
|
|
56
|
+
if (matchesKey(normalized, Key.tab))
|
|
57
|
+
return { type: 'tab', reverse: false };
|
|
58
|
+
if (matchesKey(normalized, Key.enter))
|
|
59
|
+
return { type: 'confirm' };
|
|
60
|
+
if (matchesKey(normalized, Key.escape))
|
|
61
|
+
return { type: 'cancel' };
|
|
62
|
+
// Arrow keys remain distinct because each mode gives them its own meaning.
|
|
63
|
+
if (matchesKey(normalized, Key.up))
|
|
64
|
+
return { type: 'arrow', direction: 'up' };
|
|
65
|
+
if (matchesKey(normalized, Key.down))
|
|
66
|
+
return { type: 'arrow', direction: 'down' };
|
|
67
|
+
if (matchesKey(normalized, Key.left))
|
|
68
|
+
return { type: 'arrow', direction: 'left' };
|
|
69
|
+
if (matchesKey(normalized, Key.right))
|
|
70
|
+
return { type: 'arrow', direction: 'right' };
|
|
71
|
+
if (matchesKey(normalized, Key.pageUp))
|
|
72
|
+
return { type: 'scrollPage', delta: -1 };
|
|
73
|
+
if (matchesKey(normalized, Key.pageDown))
|
|
74
|
+
return { type: 'scrollPage', delta: 1 };
|
|
75
|
+
if (matchesKey(normalized, Key.shift('j')))
|
|
76
|
+
return { type: 'extendUnit', delta: 1, text: 'J' };
|
|
77
|
+
if (matchesKey(normalized, Key.shift('k')))
|
|
78
|
+
return { type: 'extendUnit', delta: -1, text: 'K' };
|
|
79
|
+
if (matchesKey(normalized, 'j'))
|
|
80
|
+
return { type: 'moveUnit', delta: 1, text: 'j' };
|
|
81
|
+
if (matchesKey(normalized, 'k'))
|
|
82
|
+
return { type: 'moveUnit', delta: -1, text: 'k' };
|
|
83
|
+
if (matchesKey(normalized, 'u'))
|
|
84
|
+
return { type: 'scrollPage', delta: -1, text: 'u' };
|
|
85
|
+
if (matchesKey(normalized, 'd'))
|
|
86
|
+
return { type: 'scrollPage', delta: 1, text: 'd' };
|
|
87
|
+
if (matchesKey(normalized, 'h'))
|
|
88
|
+
return { type: 'pan', delta: -1, text: 'h' };
|
|
89
|
+
if (matchesKey(normalized, 'l'))
|
|
90
|
+
return { type: 'pan', delta: 1, text: 'l' };
|
|
91
|
+
if (matchesKey(normalized, Key.space))
|
|
92
|
+
return { type: 'leader', text: ' ' };
|
|
93
|
+
if (matchesKey(normalized, Key.question))
|
|
94
|
+
return { type: 'help', text: '?' };
|
|
95
|
+
if (matchesKey(normalized, 'e'))
|
|
96
|
+
return { type: 'listEdit', text: 'e' };
|
|
97
|
+
if (matchesKey(normalized, 'q'))
|
|
98
|
+
return { type: 'cancel', text: 'q' };
|
|
99
|
+
const parsed = parseKey(normalized);
|
|
100
|
+
const text = printableText(data, parsed);
|
|
101
|
+
// Kitty reports question mark as Shift+Slash, so the unmodified-key matcher
|
|
102
|
+
// above cannot recognize it. Keep its text for compose through reviewKeyText.
|
|
103
|
+
if (text === '?')
|
|
104
|
+
return { type: 'help', text };
|
|
105
|
+
if (text !== undefined)
|
|
106
|
+
return { type: 'printable', text };
|
|
107
|
+
// A recognized but unhandled modified key (notably Alt+I) is not text or a
|
|
108
|
+
// paste. Its viewer-level owner may already have consumed it.
|
|
109
|
+
if (parsed !== undefined)
|
|
110
|
+
return null;
|
|
111
|
+
if ([...data].length > 1)
|
|
112
|
+
return { type: 'paste', text: data };
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
function printableText(data, parsed) {
|
|
116
|
+
const kitty = decodeKittyPrintable(data);
|
|
117
|
+
if (kitty !== undefined && isPrintable(kitty))
|
|
118
|
+
return kitty;
|
|
119
|
+
if (parsed !== undefined) {
|
|
120
|
+
const shifted = parsed.startsWith('shift+');
|
|
121
|
+
const candidate = shifted ? parsed.slice('shift+'.length) : parsed;
|
|
122
|
+
if ([...candidate].length === 1 && isPrintable(candidate)) {
|
|
123
|
+
return shifted && /^[a-z]$/.test(candidate) ? candidate.toUpperCase() : candidate;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return [...data].length === 1 && isPrintable(data) ? data : undefined;
|
|
127
|
+
}
|
|
128
|
+
function isPrintable(text) {
|
|
129
|
+
return !/\p{C}/u.test(text);
|
|
130
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TUI } from '@earendil-works/pi-tui';
|
|
2
|
+
import type { CanvasSource } from '../../../core/canvas/source.js';
|
|
3
|
+
import type { SurfaceHost } from '../../surfaces/host.js';
|
|
4
|
+
export interface ComposedReviewOptions {
|
|
5
|
+
reviewId: string;
|
|
6
|
+
tui: TUI;
|
|
7
|
+
canvasSource: CanvasSource;
|
|
8
|
+
}
|
|
9
|
+
/** Mount the canonical live-document and companion-conversation review. */
|
|
10
|
+
export declare function openComposedReview(host: SurfaceHost, opts: ComposedReviewOptions): Promise<void>;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { ApiError } from '../../../api/errors.js';
|
|
2
|
+
import { CompanionRegion } from '../../conversation/region.js';
|
|
3
|
+
import { createCommentAuthority } from './comments-client.js';
|
|
4
|
+
import { ReviewCompositionComponent } from './composition.js';
|
|
5
|
+
import { DocumentRegion } from './document-region.js';
|
|
6
|
+
import { openLiveSource } from './live-source.js';
|
|
7
|
+
import { createReviewClient, ReviewTerminalError } from './review-client.js';
|
|
8
|
+
/** Mount the canonical live-document and companion-conversation review. */
|
|
9
|
+
export async function openComposedReview(host, opts) {
|
|
10
|
+
if (host.capabilities.remote) {
|
|
11
|
+
host.notice('The composed review is unavailable in a remote attach — the file and companion live on the host.');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const reviewClient = createReviewClient();
|
|
15
|
+
let opened;
|
|
16
|
+
try {
|
|
17
|
+
opened = await reviewClient.open(opts.reviewId);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
host.notice(error instanceof ReviewTerminalError
|
|
21
|
+
? terminalRefusalNotice(error)
|
|
22
|
+
: `couldn't open review: ${describeError(error)}`);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
let source;
|
|
26
|
+
try {
|
|
27
|
+
source = openLiveSource(opened.file);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
host.notice(`couldn't open ${opened.file}: ${describeError(error)}`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const comments = createCommentAuthority(opened.reviewId);
|
|
34
|
+
let handle;
|
|
35
|
+
let composition;
|
|
36
|
+
let submitting = false;
|
|
37
|
+
const documentRegion = new DocumentRegion({
|
|
38
|
+
reviewId: opened.reviewId,
|
|
39
|
+
absFile: opened.file,
|
|
40
|
+
cwd: opened.cwd,
|
|
41
|
+
source,
|
|
42
|
+
comments,
|
|
43
|
+
services: {
|
|
44
|
+
notice: (text) => host.notice(text),
|
|
45
|
+
suspendForChild: () => {
|
|
46
|
+
const resumeHost = host.suspendForChild();
|
|
47
|
+
const resumeComposition = composition?.suspendForChild() ?? (() => { });
|
|
48
|
+
let resumed = false;
|
|
49
|
+
return () => {
|
|
50
|
+
if (resumed)
|
|
51
|
+
return;
|
|
52
|
+
resumed = true;
|
|
53
|
+
resumeComposition();
|
|
54
|
+
resumeHost();
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
requestClose: () => handle?.close(),
|
|
58
|
+
submit: () => { void submit(); },
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
const companionRegion = new CompanionRegion({
|
|
62
|
+
companionNodeId: opened.companionNodeId,
|
|
63
|
+
tui: opts.tui,
|
|
64
|
+
canvasSource: opts.canvasSource,
|
|
65
|
+
reopenDormantCompanion: async () => {
|
|
66
|
+
await reviewClient.open(opened.reviewId);
|
|
67
|
+
},
|
|
68
|
+
onRequestClose: () => handle?.close(),
|
|
69
|
+
});
|
|
70
|
+
await documentRegion.open();
|
|
71
|
+
composition = new ReviewCompositionComponent({
|
|
72
|
+
document: documentRegion,
|
|
73
|
+
companion: companionRegion,
|
|
74
|
+
notice: (text) => host.notice(text),
|
|
75
|
+
onRequestClose: () => { },
|
|
76
|
+
});
|
|
77
|
+
handle = host.mount(composition);
|
|
78
|
+
composition.setHandle(handle);
|
|
79
|
+
void companionRegion.open();
|
|
80
|
+
async function submit() {
|
|
81
|
+
if (submitting)
|
|
82
|
+
return;
|
|
83
|
+
submitting = true;
|
|
84
|
+
try {
|
|
85
|
+
const result = await reviewClient.submit(opened.reviewId);
|
|
86
|
+
host.notice(approvalNotice(result));
|
|
87
|
+
handle?.close();
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
const conflict = terminalConflictNotice(error);
|
|
91
|
+
if (conflict !== undefined) {
|
|
92
|
+
host.notice(conflict);
|
|
93
|
+
handle?.close();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
submitting = false;
|
|
97
|
+
host.notice(`couldn't submit review: ${describeError(error)}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function terminalRefusalNotice(error) {
|
|
102
|
+
if (error.state === 'approved')
|
|
103
|
+
return `This review was already approved. Result: ${error.resultPath ?? 'unknown'}`;
|
|
104
|
+
return error.reason === undefined || error.reason === '' ? 'This review was canceled.' : `This review was canceled: ${error.reason}`;
|
|
105
|
+
}
|
|
106
|
+
function approvalNotice(result) {
|
|
107
|
+
return result.changed
|
|
108
|
+
? `Approved — the document changed during review. Result: ${result.resultPath}`
|
|
109
|
+
: `Approved — the document was not modified. Result: ${result.resultPath}`;
|
|
110
|
+
}
|
|
111
|
+
function terminalConflictNotice(error) {
|
|
112
|
+
if (!(error instanceof ApiError) || error.status !== 409 || error.code !== 'review_terminal_conflict')
|
|
113
|
+
return undefined;
|
|
114
|
+
const review = error.details?.review;
|
|
115
|
+
if (review === undefined)
|
|
116
|
+
return undefined;
|
|
117
|
+
if (review.state === 'approved')
|
|
118
|
+
return review.result_path === undefined
|
|
119
|
+
? 'This review was already approved by someone else.'
|
|
120
|
+
: `This review was already approved by someone else. Result: ${review.result_path}`;
|
|
121
|
+
if (review.state === 'canceled')
|
|
122
|
+
return review.cancel_reason === undefined || review.cancel_reason === ''
|
|
123
|
+
? 'This review was canceled before this submission landed.'
|
|
124
|
+
: `This review was canceled before this submission landed: ${review.cancel_reason}`;
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
function describeError(error) {
|
|
128
|
+
return error instanceof Error ? error.message : String(error);
|
|
129
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** The trailing delay used to collapse an editor's write/rename burst. */
|
|
2
|
+
export declare const COALESCE_MS = 120;
|
|
3
|
+
export type StaleReason = 'missing' | 'unreadable' | 'too-large' | 'binary';
|
|
4
|
+
export interface SourceSnapshot {
|
|
5
|
+
text: string;
|
|
6
|
+
lines: string[];
|
|
7
|
+
revision: number;
|
|
8
|
+
status: 'live' | 'stale';
|
|
9
|
+
staleReason?: StaleReason;
|
|
10
|
+
sha256: string;
|
|
11
|
+
loadedAt: string;
|
|
12
|
+
}
|
|
13
|
+
export interface LiveSource {
|
|
14
|
+
current(): SourceSnapshot;
|
|
15
|
+
/** The text captured when the surface opened. */
|
|
16
|
+
openText(): string;
|
|
17
|
+
/** Fires only when text changes or the live/stale status flips. */
|
|
18
|
+
onChange(fn: (next: SourceSnapshot, previous: SourceSnapshot) => void): void;
|
|
19
|
+
/** Read immediately, bypassing the directory watcher and coalescing timer. */
|
|
20
|
+
refreshNow(): void;
|
|
21
|
+
close(): void;
|
|
22
|
+
}
|
|
23
|
+
/** Watch the containing directory so atomic replacement of the file remains live. */
|
|
24
|
+
export declare function openLiveSource(absFile: string): LiveSource;
|