@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,48 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { test } from 'node:test';
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
import { initTheme } from '@earendil-works/pi-coding-agent';
|
|
5
|
+
import { InputController } from '../input/controller.js';
|
|
6
|
+
initTheme(undefined, false);
|
|
7
|
+
function fakeEditor() {
|
|
8
|
+
const obj = {
|
|
9
|
+
onSubmit: undefined,
|
|
10
|
+
onEscape: undefined,
|
|
11
|
+
onPasteImage: undefined,
|
|
12
|
+
onAction: () => { },
|
|
13
|
+
getText: () => '',
|
|
14
|
+
setText: () => { },
|
|
15
|
+
addToHistory: () => { },
|
|
16
|
+
insertTextAtCursor: () => { },
|
|
17
|
+
};
|
|
18
|
+
return obj;
|
|
19
|
+
}
|
|
20
|
+
test('choosing a review file closes the inline picker before the review surface takes focus', () => {
|
|
21
|
+
const editor = fakeEditor();
|
|
22
|
+
let focused = null;
|
|
23
|
+
let mountedPicker;
|
|
24
|
+
const tui = {
|
|
25
|
+
requestRender: () => { },
|
|
26
|
+
setFocus: (component) => { focused = component; },
|
|
27
|
+
showOverlay: () => ({ hide: () => { } }),
|
|
28
|
+
start: () => { },
|
|
29
|
+
stop: () => { },
|
|
30
|
+
};
|
|
31
|
+
const reviewSurface = {
|
|
32
|
+
render: () => [],
|
|
33
|
+
invalidate: () => { },
|
|
34
|
+
handleInput: () => { },
|
|
35
|
+
};
|
|
36
|
+
const controller = new InputController(tui, editor, {}, {
|
|
37
|
+
onCommand: () => { },
|
|
38
|
+
onDialogResponse: () => { },
|
|
39
|
+
onMountPicker: (component) => { mountedPicker = component; },
|
|
40
|
+
onUnmountPicker: () => { },
|
|
41
|
+
});
|
|
42
|
+
controller.openFileReviewPicker([fileURLToPath(import.meta.url)], process.cwd(), () => {
|
|
43
|
+
tui.setFocus(reviewSurface);
|
|
44
|
+
});
|
|
45
|
+
assert.ok(mountedPicker?.handleInput);
|
|
46
|
+
mountedPicker.handleInput('\n');
|
|
47
|
+
assert.equal(focused, reviewSurface, 'picker close must not restore editor focus over the review surface');
|
|
48
|
+
});
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import test from 'node:test';
|
|
5
|
+
import { Container, TUI, getCapabilities, setCapabilities } from '@earendil-works/pi-tui';
|
|
6
|
+
import { initTheme } from '@earendil-works/pi-coding-agent';
|
|
7
|
+
import { AUTH_FAULT_RECOVERY_BODY, RUNTIME_RESTART_CONTINUATION, isRuntimeRestartContinuation } from '../../../shared/generated-context.js';
|
|
8
|
+
import { ChatView } from '../render/chat-view.js';
|
|
9
|
+
import { GroupActivityRecorder } from '../render/group-activity.js';
|
|
10
|
+
import { GroupRecapComponent } from '../render/group-recap.js';
|
|
11
|
+
import { TOOL_ICON } from '../../../core/preview-registry.js';
|
|
12
|
+
function memoryRead(name, pathStyle = 'section') {
|
|
13
|
+
const path = pathStyle === 'field'
|
|
14
|
+
? `- path: /tmp/memories/${name}.md`
|
|
15
|
+
: `**path:** /tmp/memories/${name}.md`;
|
|
16
|
+
return `- name: ${name}\n- kind: knowledge\n- scope: project\n${pathStyle === 'section' ? '\n' : ''}${path}`;
|
|
17
|
+
}
|
|
18
|
+
function fakeTerminal() {
|
|
19
|
+
return {
|
|
20
|
+
start() { }, stop() { }, async drainInput() { }, write() { },
|
|
21
|
+
get columns() { return 80; }, get rows() { return 24; }, get kittyProtocolActive() { return false; },
|
|
22
|
+
moveBy() { }, hideCursor() { }, showCursor() { }, clearLine() { }, clearFromCursor() { }, clearScreen() { }, setTitle() { }, setProgress() { },
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function snapshotWithContinuation(body) {
|
|
26
|
+
return {
|
|
27
|
+
messages: [
|
|
28
|
+
{ role: 'assistant', content: [{ type: 'toolCall', id: 'before', name: 'bash', arguments: { command: 'true' } }] },
|
|
29
|
+
{ role: 'toolResult', toolCallId: 'before', toolName: 'bash', content: [{ type: 'text', text: '' }], isError: false },
|
|
30
|
+
{ role: 'user', content: body },
|
|
31
|
+
{ role: 'assistant', content: [{ type: 'toolCall', id: 'after', name: 'bash', arguments: { command: 'true' } }] },
|
|
32
|
+
{ role: 'toolResult', toolCallId: 'after', toolName: 'bash', content: [{ type: 'text', text: '' }], isError: false },
|
|
33
|
+
],
|
|
34
|
+
stats: {},
|
|
35
|
+
state: { isStreaming: false },
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
initTheme(undefined, false);
|
|
39
|
+
test('group activity aggregates successful file changes and resolved memory reads', () => {
|
|
40
|
+
const cwd = '/tmp/activity';
|
|
41
|
+
const recorder = new GroupActivityRecorder(cwd);
|
|
42
|
+
recorder.noteCall('edit-1', 'edit', { path: 'same.ts' });
|
|
43
|
+
recorder.settle('edit-1', { details: { diff: '-1 old\n+1 new' } }, false);
|
|
44
|
+
recorder.noteCall('write', 'write', { path: 'other.ts', content: 'one\ntwo\n' });
|
|
45
|
+
recorder.settle('write', {}, false);
|
|
46
|
+
recorder.noteCall('edit-2', 'edit', { path: resolve(cwd, 'same.ts') });
|
|
47
|
+
recorder.settle('edit-2', { details: { diff: '+2 later' } }, false);
|
|
48
|
+
recorder.noteCall('home-edit', 'edit', { path: '~/same-home.ts' });
|
|
49
|
+
recorder.settle('home-edit', { details: { diff: '+1 home' } }, false);
|
|
50
|
+
recorder.noteCall('home-write', 'write', { path: resolve(homedir(), 'same-home.ts'), content: 'replacement' });
|
|
51
|
+
recorder.settle('home-write', {}, false);
|
|
52
|
+
recorder.noteCall('failed', 'edit', { path: 'failed.ts' });
|
|
53
|
+
recorder.settle('failed', { details: { diff: '+1 never' } }, true);
|
|
54
|
+
recorder.noteCall('memory', 'bash', { command: 'crtr memory read alpha && crtr memory read beta' });
|
|
55
|
+
recorder.settle('memory', { content: [{ type: 'text', text: `${memoryRead('alpha')}\n\n${memoryRead('beta', 'field')}` }] }, false);
|
|
56
|
+
recorder.noteCall('repeat', 'bash', { command: 'crtr memory read alpha' });
|
|
57
|
+
recorder.settle('repeat', { content: [{ type: 'text', text: memoryRead('alpha') }] }, false);
|
|
58
|
+
recorder.noteCall('not-a-read', 'bash', { command: 'crtr memory list' });
|
|
59
|
+
recorder.settle('not-a-read', { content: [{ type: 'text', text: memoryRead('ignored') }] }, false);
|
|
60
|
+
recorder.noteCall('quoted-not-a-read', 'bash', { command: 'echo "not a command; crtr memory read fabricated"' });
|
|
61
|
+
recorder.settle('quoted-not-a-read', { content: [{ type: 'text', text: memoryRead('fabricated') }] }, false);
|
|
62
|
+
const activity = recorder.activity();
|
|
63
|
+
assert.deepEqual(activity.memories, [
|
|
64
|
+
{ name: 'alpha', path: '/tmp/memories/alpha.md' },
|
|
65
|
+
{ name: 'beta', path: '/tmp/memories/beta.md' },
|
|
66
|
+
]);
|
|
67
|
+
assert.deepEqual(activity.files.map((file) => [file.kind, file.displayPath]), [
|
|
68
|
+
['edit', 'same.ts'],
|
|
69
|
+
['write', 'other.ts'],
|
|
70
|
+
['edit', '~/same-home.ts'],
|
|
71
|
+
['write', resolve(homedir(), 'same-home.ts')],
|
|
72
|
+
]);
|
|
73
|
+
assert.deepEqual(activity.files[0], {
|
|
74
|
+
key: resolve(cwd, 'same.ts'),
|
|
75
|
+
displayPath: 'same.ts',
|
|
76
|
+
kind: 'edit',
|
|
77
|
+
added: 2,
|
|
78
|
+
removed: 1,
|
|
79
|
+
hasKnownCounts: true,
|
|
80
|
+
countsIncomplete: false,
|
|
81
|
+
});
|
|
82
|
+
assert.deepEqual(activity.files[1], {
|
|
83
|
+
key: resolve(cwd, 'other.ts'),
|
|
84
|
+
displayPath: 'other.ts',
|
|
85
|
+
kind: 'write',
|
|
86
|
+
added: 2,
|
|
87
|
+
removed: 0,
|
|
88
|
+
hasKnownCounts: true,
|
|
89
|
+
countsIncomplete: false,
|
|
90
|
+
});
|
|
91
|
+
assert.equal(activity.files[2]?.added, 1, 'edits retain their own aggregate');
|
|
92
|
+
assert.equal(activity.files[3]?.added, 1, 'writes retain their own aggregate');
|
|
93
|
+
});
|
|
94
|
+
test('the detailed folded recap retains paths and counts without diff or payload bodies', () => {
|
|
95
|
+
const recorder = new GroupActivityRecorder('/tmp/activity');
|
|
96
|
+
recorder.noteCall('edit', 'edit', { path: 'overwritten.ts' });
|
|
97
|
+
const addedDiff = Array.from({ length: 11 }, (_, index) => `+${index + 1} sensitive-new-diff`).join('\n');
|
|
98
|
+
recorder.settle('edit', { details: { diff: `-1 sensitive-old-diff\n${addedDiff}` } }, false);
|
|
99
|
+
recorder.noteCall('write', 'write', {
|
|
100
|
+
path: 'overwritten.ts',
|
|
101
|
+
content: Array.from({ length: 8 }, () => 'sensitive-write-payload').join('\n'),
|
|
102
|
+
});
|
|
103
|
+
recorder.settle('write', {}, false);
|
|
104
|
+
recorder.noteCall('zero', 'edit', { path: 'overwritten.ts' });
|
|
105
|
+
recorder.settle('zero', { details: { diff: '' } }, false);
|
|
106
|
+
recorder.noteCall('unavailable', 'edit', { path: 'overwritten.ts' });
|
|
107
|
+
recorder.settle('unavailable', {}, false);
|
|
108
|
+
const tone = (key) => (text) => `[${key}]${text}`;
|
|
109
|
+
const palette = {
|
|
110
|
+
accent: tone('accent'), active: tone('active'), info: tone('info'), muted: tone('muted'),
|
|
111
|
+
faint: tone('faint'), border: tone('border'), surface: tone('surface'), bold: tone('bold'),
|
|
112
|
+
error: tone('error'), warning: tone('warning'), diffAdded: tone('diffAdded'), diffRemoved: tone('diffRemoved'),
|
|
113
|
+
bashMode: tone('bashMode'), bashModeAlt: tone('bashModeAlt'),
|
|
114
|
+
};
|
|
115
|
+
const recap = new GroupRecapComponent();
|
|
116
|
+
const originalCapabilities = getCapabilities();
|
|
117
|
+
let lines;
|
|
118
|
+
try {
|
|
119
|
+
setCapabilities({ ...originalCapabilities, hyperlinks: true });
|
|
120
|
+
recap.setRecap({ bullets: ['finished'], nodesSpawned: 1, filesEdited: 3 }, 2, {
|
|
121
|
+
memories: [
|
|
122
|
+
{ name: 'alpha', path: '/tmp/memories/alpha.md' },
|
|
123
|
+
{ name: 'beta', path: '/tmp/memories/beta.md' },
|
|
124
|
+
],
|
|
125
|
+
files: recorder.activity().files,
|
|
126
|
+
}, true, palette);
|
|
127
|
+
lines = recap.render(120);
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
setCapabilities(originalCapabilities);
|
|
131
|
+
}
|
|
132
|
+
const text = lines.join('\n');
|
|
133
|
+
assert.equal(lines[0], '');
|
|
134
|
+
assert.equal(lines.at(-1), '');
|
|
135
|
+
assert.match(text, /2 tool calls/, 'tool-call count remains visible in every recap mode');
|
|
136
|
+
assert.doesNotMatch(text, /✦/, 'the tool-call count has no decorative prefix');
|
|
137
|
+
assert.doesNotMatch(text, /files?\s+edited|memory\s+reads/, 'detailed recaps do not duplicate their itemized activity with count chrome');
|
|
138
|
+
assert.equal(lines.filter((line) => line.includes('[muted]alpha')).length, 1, 'each memory renders on one line');
|
|
139
|
+
assert.equal(lines.filter((line) => line.includes('[muted]beta')).length, 1, 'each memory renders on one line');
|
|
140
|
+
assert.match(text, /file:\/\/\/tmp\/memories\/alpha\.md/);
|
|
141
|
+
assert.match(text, /file:\/\/\/tmp\/memories\/beta\.md/);
|
|
142
|
+
assert.doesNotMatch(text, /alpha · beta/);
|
|
143
|
+
const fileLines = lines.filter((line) => line.includes('overwritten.ts'));
|
|
144
|
+
assert.equal(fileLines.length, 2, 'edits and writes remain independently visible');
|
|
145
|
+
const editLine = fileLines.find((line) => line.includes(`[warning]${TOOL_ICON.edit}`));
|
|
146
|
+
const writeLine = fileLines.find((line) => line.includes(`[warning]${TOOL_ICON.write}`));
|
|
147
|
+
assert.ok(editLine.indexOf(TOOL_ICON.edit) < editLine.indexOf('overwritten.ts'), 'the edit path stays inline with its glyph');
|
|
148
|
+
assert.ok(writeLine.indexOf(TOOL_ICON.write) < writeLine.indexOf('overwritten.ts'), 'the write path stays inline with its glyph');
|
|
149
|
+
assert.ok(editLine.endsWith('[diffAdded]+11 [diffRemoved]-1[muted] · counts incomplete'), 'edit counts stay with the edit');
|
|
150
|
+
assert.ok(writeLine.endsWith('[diffAdded]+8'), 'write counts stay with the write');
|
|
151
|
+
assert.equal(lines.filter((line) => line.includes('[diffAdded]')).length, 2, 'each action has one count row');
|
|
152
|
+
const toolCallIndex = lines.findIndex((line) => line.includes('2 tool calls'));
|
|
153
|
+
const bulletIndex = lines.findIndex((line) => line.includes('finished'));
|
|
154
|
+
assert.ok(lines.findIndex((line) => line.includes('[muted]alpha')) < toolCallIndex, 'memory reads precede the tool-call count');
|
|
155
|
+
assert.ok(lines.findIndex((line) => line.includes(`[warning]${TOOL_ICON.edit}`)) < toolCallIndex, 'file actions precede the tool-call count');
|
|
156
|
+
assert.ok(toolCallIndex < bulletIndex, 'the tool-call count precedes recap bullets');
|
|
157
|
+
assert.ok(!text.includes('sensitive-old-diff'));
|
|
158
|
+
assert.ok(!text.includes('sensitive-new-diff'));
|
|
159
|
+
assert.ok(!text.includes('sensitive-write-payload'));
|
|
160
|
+
});
|
|
161
|
+
async function summarizedGroup(messages, key) {
|
|
162
|
+
const view = new ChatView(new TUI(fakeTerminal()), new Container());
|
|
163
|
+
const internals = view;
|
|
164
|
+
internals.foldSettledTools = true;
|
|
165
|
+
internals.showGroupSummaries = true;
|
|
166
|
+
await view.applySnapshot({
|
|
167
|
+
messages,
|
|
168
|
+
stats: {},
|
|
169
|
+
state: { isStreaming: false },
|
|
170
|
+
toolGroupSummaries: {
|
|
171
|
+
[key]: { bullets: ['broker recap'], nodesSpawned: 0, filesEdited: 0 },
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
const group = internals.groups.find((candidate) => candidate.key === key);
|
|
175
|
+
assert.ok(group, `missing ${key} group`);
|
|
176
|
+
return {
|
|
177
|
+
group,
|
|
178
|
+
children: internals.historyContainer.children,
|
|
179
|
+
hidden: internals.historyContainer.hiddenChildren,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
test('broker summaries hide every settled call while aborted/error assistant endings remain visible boundaries', async () => {
|
|
183
|
+
const successful = await summarizedGroup([
|
|
184
|
+
{ role: 'assistant', content: [{ type: 'toolCall', id: 'successful', name: 'bash', arguments: { command: 'true' } }] },
|
|
185
|
+
{ role: 'toolResult', toolCallId: 'successful', toolName: 'bash', content: [{ type: 'text', text: 'ok' }], isError: false },
|
|
186
|
+
], 'successful');
|
|
187
|
+
assert.equal(successful.hidden.has(successful.group.recap), false, 'a settled successful group still folds to its recap');
|
|
188
|
+
assert.ok(successful.group.members.every((member) => successful.hidden.has(member)), 'successful group members hide behind the recap');
|
|
189
|
+
const mixed = await summarizedGroup([
|
|
190
|
+
{
|
|
191
|
+
role: 'assistant',
|
|
192
|
+
content: [
|
|
193
|
+
{ type: 'toolCall', id: 'mixed-success', name: 'bash', arguments: { command: 'true' } },
|
|
194
|
+
{ type: 'toolCall', id: 'mixed-failure', name: 'bash', arguments: { command: 'false' } },
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
{ role: 'toolResult', toolCallId: 'mixed-success', toolName: 'bash', content: [{ type: 'text', text: 'ok' }], isError: false },
|
|
198
|
+
{ role: 'toolResult', toolCallId: 'mixed-failure', toolName: 'bash', content: [{ type: 'text', text: 'failed' }], isError: true },
|
|
199
|
+
], 'mixed-success');
|
|
200
|
+
assert.equal(mixed.hidden.has(mixed.group.recap), false, 'a failed call does not suppress the valid group recap');
|
|
201
|
+
assert.ok(mixed.group.members.every((member) => mixed.hidden.has(member)), 'successful and failed calls all hide behind the recap');
|
|
202
|
+
for (const stopReason of ['aborted', 'error']) {
|
|
203
|
+
const key = `terminal-${stopReason}`;
|
|
204
|
+
const terminalMessage = stopReason === 'aborted'
|
|
205
|
+
? { role: 'assistant', content: [], stopReason }
|
|
206
|
+
: { role: 'assistant', content: [{ type: 'text', text: 'partial reply' }], stopReason, errorMessage: 'provider failed' };
|
|
207
|
+
const terminalMessages = [
|
|
208
|
+
{ role: 'assistant', content: [{ type: 'toolCall', id: key, name: 'bash', arguments: { command: 'true' } }] },
|
|
209
|
+
];
|
|
210
|
+
if (stopReason === 'error') {
|
|
211
|
+
terminalMessages.push({ role: 'toolResult', toolCallId: key, toolName: 'bash', content: [{ type: 'text', text: 'ok' }], isError: false });
|
|
212
|
+
}
|
|
213
|
+
terminalMessages.push(terminalMessage);
|
|
214
|
+
const terminal = await summarizedGroup(terminalMessages, key);
|
|
215
|
+
assert.equal(terminal.hidden.has(terminal.group.recap), false, `${stopReason} does not suppress the preceding valid recap`);
|
|
216
|
+
assert.ok(terminal.group.members.every((member) => terminal.hidden.has(member)), `${stopReason} leaves preceding tool rows folded`);
|
|
217
|
+
const visibleBoundary = terminal.children
|
|
218
|
+
.filter((component) => component !== terminal.group.recap && !terminal.hidden.has(component))
|
|
219
|
+
.flatMap((component) => component.render(80))
|
|
220
|
+
.join('\n');
|
|
221
|
+
assert.match(visibleBoundary, stopReason === 'aborted' ? /Operation aborted|Interrupted/ : /partial reply|provider failed/, `${stopReason} assistant ending remains visible outside the folded group`);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
test('streamed aborted/error endings stay visible while the preceding summarized tools remain folded', () => {
|
|
225
|
+
for (const stopReason of ['aborted', 'error']) {
|
|
226
|
+
const view = new ChatView(new TUI(fakeTerminal()), new Container());
|
|
227
|
+
const internals = view;
|
|
228
|
+
internals.foldSettledTools = true;
|
|
229
|
+
internals.showGroupSummaries = true;
|
|
230
|
+
const key = `live-${stopReason}`;
|
|
231
|
+
view.handleEvent({ type: 'message_start', message: { role: 'assistant', content: [] } });
|
|
232
|
+
view.handleEvent({ type: 'tool_execution_start', toolCallId: key, toolName: 'bash', args: { command: 'true' } });
|
|
233
|
+
if (stopReason === 'error') {
|
|
234
|
+
view.handleEvent({ type: 'tool_execution_end', toolCallId: key, result: { content: [{ type: 'text', text: 'ok' }] }, isError: false });
|
|
235
|
+
}
|
|
236
|
+
view.applyToolGroupSummary(key, { bullets: ['broker recap'], nodesSpawned: 0, filesEdited: 0 });
|
|
237
|
+
const group = internals.groups.find((candidate) => candidate.key === key);
|
|
238
|
+
assert.ok(group, `missing ${stopReason} live group`);
|
|
239
|
+
assert.equal(internals.historyContainer.hiddenChildren.has(group.recap), stopReason === 'aborted', 'only an in-flight call holds back an early recap');
|
|
240
|
+
const content = stopReason === 'aborted' ? [] : [{ type: 'text', text: 'partial reply' }];
|
|
241
|
+
if (content.length > 0) {
|
|
242
|
+
view.handleEvent({ type: 'message_update', message: { role: 'assistant', content } });
|
|
243
|
+
}
|
|
244
|
+
view.handleEvent({ type: 'message_end', message: { role: 'assistant', content, stopReason, errorMessage: 'provider failed' } });
|
|
245
|
+
view.applyToolGroupSummary(key, { bullets: ['broker recap'], nodesSpawned: 0, filesEdited: 0 });
|
|
246
|
+
assert.equal(internals.historyContainer.hiddenChildren.has(group.recap), false, `${stopReason} does not suppress the preceding streamed recap`);
|
|
247
|
+
assert.ok(group.members.every((member) => internals.historyContainer.hiddenChildren.has(member)), `${stopReason} leaves preceding streamed tool rows folded`);
|
|
248
|
+
const visibleBoundary = internals.historyContainer.children
|
|
249
|
+
.filter((component) => component !== group.recap && !internals.historyContainer.hiddenChildren.has(component))
|
|
250
|
+
.flatMap((component) => component.render(80))
|
|
251
|
+
.join('\n');
|
|
252
|
+
assert.match(visibleBoundary, stopReason === 'aborted' ? /Interrupted/ : /partial reply|provider failed/, `${stopReason} streamed assistant ending remains visible outside the folded group`);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
test('only the exact runtime-restart continuation closes an attach tool group', async () => {
|
|
256
|
+
assert.equal(isRuntimeRestartContinuation({ role: 'user', content: RUNTIME_RESTART_CONTINUATION }), true);
|
|
257
|
+
assert.equal(isRuntimeRestartContinuation({ role: 'user', content: AUTH_FAULT_RECOVERY_BODY }), false);
|
|
258
|
+
const runtimeView = new ChatView(new TUI(fakeTerminal()), new Container());
|
|
259
|
+
await runtimeView.applySnapshot(snapshotWithContinuation(RUNTIME_RESTART_CONTINUATION));
|
|
260
|
+
const runtimeGroups = runtimeView.groups;
|
|
261
|
+
assert.deepEqual(runtimeGroups.map((group) => group.key), ['before', 'after']);
|
|
262
|
+
const recoveryView = new ChatView(new TUI(fakeTerminal()), new Container());
|
|
263
|
+
await recoveryView.applySnapshot(snapshotWithContinuation(AUTH_FAULT_RECOVERY_BODY));
|
|
264
|
+
const recoveryGroups = recoveryView.groups;
|
|
265
|
+
assert.deepEqual(recoveryGroups.map((group) => group.key), ['before']);
|
|
266
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
import { InputController } from '../input/controller.js';
|
|
4
|
+
function controller(sent) {
|
|
5
|
+
const editor = {
|
|
6
|
+
onSubmit: undefined,
|
|
7
|
+
onEscape: undefined,
|
|
8
|
+
onPasteImage: undefined,
|
|
9
|
+
onPasteImagePath: undefined,
|
|
10
|
+
onAction: () => { },
|
|
11
|
+
addToHistory: () => { },
|
|
12
|
+
setText: () => { },
|
|
13
|
+
getText: () => '',
|
|
14
|
+
insertTextAtCursor: () => { },
|
|
15
|
+
};
|
|
16
|
+
const input = new InputController({}, editor, { matches: () => false }, { onCommand: (frame) => sent.push(frame), onDialogResponse: () => { } });
|
|
17
|
+
return {
|
|
18
|
+
submit: (text) => editor.onSubmit(text),
|
|
19
|
+
setStreaming: (streaming) => input.setState({ isStreaming: streaming }),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
test('an unrecognized slash command reaches the broker for extension dispatch', () => {
|
|
23
|
+
const sent = [];
|
|
24
|
+
const input = controller(sent);
|
|
25
|
+
input.submit('/recap');
|
|
26
|
+
input.setStreaming(true);
|
|
27
|
+
input.submit('/recap refresh');
|
|
28
|
+
assert.deepEqual(sent, [
|
|
29
|
+
{ type: 'prompt', text: '/recap' },
|
|
30
|
+
{ type: 'steer', text: '/recap refresh' },
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createFrameHandler } from '../session/frames.js';
|
|
4
|
+
test('a regenerated session title refreshes the cached canvas icon', () => {
|
|
5
|
+
let identityRefreshes = 0;
|
|
6
|
+
const noop = () => { };
|
|
7
|
+
const effects = {
|
|
8
|
+
foldState: noop,
|
|
9
|
+
chat: {
|
|
10
|
+
applySnapshot: noop,
|
|
11
|
+
handleEvent: noop,
|
|
12
|
+
setWorkingActivity: noop,
|
|
13
|
+
bashStart: noop,
|
|
14
|
+
bashOutput: noop,
|
|
15
|
+
bashEnd: noop,
|
|
16
|
+
applyToolGroupSummary: noop,
|
|
17
|
+
},
|
|
18
|
+
setNotice: noop,
|
|
19
|
+
renderFooter: noop,
|
|
20
|
+
setEditorText: noop,
|
|
21
|
+
attachDialog: noop,
|
|
22
|
+
dismissDialog: noop,
|
|
23
|
+
setCommands: noop,
|
|
24
|
+
resetMemoryRefs: noop,
|
|
25
|
+
refreshNodeIdentity: () => { identityRefreshes += 1; },
|
|
26
|
+
reloadBindings: noop,
|
|
27
|
+
modelThinkingLabel: () => undefined,
|
|
28
|
+
};
|
|
29
|
+
const handler = createFrameHandler({ socket: { send: noop } }, effects);
|
|
30
|
+
handler({ type: 'session_info_changed', name: '\uf14e compass-recap' });
|
|
31
|
+
assert.equal(identityRefreshes, 1);
|
|
32
|
+
});
|
|
@@ -134,13 +134,12 @@ test('cursor sweep across a resolved ref decorates outside the cursor cell and s
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
});
|
|
137
|
-
test('chrome (loaded-command disclosure, title/info border,
|
|
137
|
+
test('chrome (loaded-command disclosure, title/info border, context badge) never carries ref decoration', () => {
|
|
138
138
|
const editorA = makeEditor();
|
|
139
139
|
const editorB = makeEditor();
|
|
140
140
|
for (const editor of [editorA, editorB]) {
|
|
141
141
|
editor.title = 'session';
|
|
142
142
|
editor.info = 'cwd-info';
|
|
143
|
-
editor.mode = 'plan';
|
|
144
143
|
editor.contextBadge = 'node-1';
|
|
145
144
|
editor.loadedCommand = { name: 'dev', content: 'do the thing', inspectHint: 'ctrl+i' };
|
|
146
145
|
editor.setText('please use /dev to continue');
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Container } from '@earendil-works/pi-tui';
|
|
2
|
+
import type { SessionState } from '../../../core/session-model/session-state.js';
|
|
3
|
+
import type { AttachSession } from '../session/context.js';
|
|
4
|
+
export interface RecapHeader {
|
|
5
|
+
/** The component ViewerFrame renders as its header region. */
|
|
6
|
+
readonly component: Container;
|
|
7
|
+
/** Repaint from the live `crtr-recap` widget state. Empty widget → 0 rows. */
|
|
8
|
+
render(): void;
|
|
9
|
+
}
|
|
10
|
+
export declare function createRecapHeader(ctx: Pick<AttachSession, 'tui' | 'pal'>, state: () => SessionState): RecapHeader;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// chrome/header.ts — the pinned recap header above the transcript.
|
|
2
|
+
//
|
|
3
|
+
// Only the GOAL line of the broker's retained `crtr-recap` widget is painted
|
|
4
|
+
// here, label stripped, so it stays visible while the transcript scrolls. The
|
|
5
|
+
// state line rides the widget's own cockpit slot (chrome/widgets.ts).
|
|
6
|
+
import { Container, Text, wrapTextWithAnsi } from '@earendil-works/pi-tui';
|
|
7
|
+
import { DynamicBorder } from '@earendil-works/pi-coding-agent';
|
|
8
|
+
import { splitRecapLines } from './recap.js';
|
|
9
|
+
export function createRecapHeader(ctx, state) {
|
|
10
|
+
const { tui, pal } = ctx;
|
|
11
|
+
const component = new Container();
|
|
12
|
+
const render = () => {
|
|
13
|
+
component.clear();
|
|
14
|
+
const widget = state().display.widgets['crtr-recap'];
|
|
15
|
+
const goal = widget === undefined ? [] : splitRecapLines(widget.lines).goal;
|
|
16
|
+
if (goal.length > 0) {
|
|
17
|
+
const span = Math.max(1, (process.stdout.columns ?? 80) - 2);
|
|
18
|
+
for (const line of goal) {
|
|
19
|
+
// Styled BEFORE wrapping (wrapTextWithAnsi carries SGR state across
|
|
20
|
+
// wraps), so a wrapped continuation stays faint.
|
|
21
|
+
for (const wrapped of wrapTextWithAnsi(pal.faint(line), span)) {
|
|
22
|
+
component.addChild(new Text(wrapped, 1, 0));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
component.addChild(new DynamicBorder(pal.border));
|
|
26
|
+
}
|
|
27
|
+
tui.requestRender();
|
|
28
|
+
};
|
|
29
|
+
return { component, render };
|
|
30
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface RecapSplit {
|
|
2
|
+
/** `Goal:` lines, label stripped — the pinned header's content. */
|
|
3
|
+
goal: string[];
|
|
4
|
+
/** The remaining lines, `State:` label stripped — cockpit content. */
|
|
5
|
+
state: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function splitRecapLines(lines: readonly string[]): RecapSplit;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// chrome/recap.ts — how the broker's `crtr-recap` widget divides between the
|
|
2
|
+
// two chrome surfaces: the goal pins to the header above the transcript, and
|
|
3
|
+
// everything else (the state line) rides the widget's own cockpit slot above
|
|
4
|
+
// the editor. The `Goal:`/`State:` prefixes are the widget's transport format,
|
|
5
|
+
// not chrome — both surfaces strip them before painting.
|
|
6
|
+
export function splitRecapLines(lines) {
|
|
7
|
+
const goal = [];
|
|
8
|
+
const state = [];
|
|
9
|
+
for (const line of lines) {
|
|
10
|
+
const goalMatch = /^Goal:\s*/.exec(line);
|
|
11
|
+
if (goalMatch !== null) {
|
|
12
|
+
goal.push(line.slice(goalMatch[0].length));
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
const stateMatch = /^State:\s*/.exec(line);
|
|
16
|
+
state.push(stateMatch === null ? line : line.slice(stateMatch[0].length));
|
|
17
|
+
}
|
|
18
|
+
return { goal, state };
|
|
19
|
+
}
|
|
@@ -20,6 +20,9 @@ export interface StatusLineHooks {
|
|
|
20
20
|
* a LOCAL in-tmux attach: a remote attach's local inbox registry cannot open
|
|
21
21
|
* the remote canvas's filesystem tickets. */
|
|
22
22
|
inboxAffordance: boolean;
|
|
23
|
+
/** Whether mouse reporting is currently enabled. When false, displays a
|
|
24
|
+
* low-priority 'mouse off' indicator in the status bar. */
|
|
25
|
+
mouseEnabled: () => boolean;
|
|
23
26
|
}
|
|
24
27
|
export interface AttachStatusLine {
|
|
25
28
|
/** Repaint the bar from current state. */
|
|
@@ -76,6 +76,11 @@ export function createStatusLine(s, hooks) {
|
|
|
76
76
|
segs.push(pal.muted(`⚑ ${total} · ${inboxOpenHint(bindings)}`));
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
+
// Mouse reporting state: show "mouse off" when reporting is disabled, so
|
|
80
|
+
// users are aware that tmux drag-select and copy-mode mouse work again.
|
|
81
|
+
if (!hooks.mouseEnabled()) {
|
|
82
|
+
segs.push(pal.muted('mouse off'));
|
|
83
|
+
}
|
|
79
84
|
// Lowest-priority segment (R4): the Alt+C -> b hint, shown only once the
|
|
80
85
|
// oldest still-foreground bash job has crossed the threshold. Read straight
|
|
81
86
|
// off this node's job files rather than tracked from relayed tool-execution
|
|
@@ -3,36 +3,26 @@
|
|
|
3
3
|
// the editor. Both read the folded `SessionState` the orchestrator owns, so it
|
|
4
4
|
// arrives as a getter rather than a captured value.
|
|
5
5
|
import { Text, truncateToWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';
|
|
6
|
-
import {
|
|
6
|
+
import { splitRecapLines } from './recap.js';
|
|
7
7
|
export function createChromeWidgets(ctx, state) {
|
|
8
8
|
const { tui, pal } = ctx;
|
|
9
|
-
const {
|
|
10
|
-
/**
|
|
11
|
-
* Styled BEFORE wrapping (wrapTextWithAnsi carries SGR state across wraps),
|
|
12
|
-
* so a wrapped continuation stays faint. Unlabeled lines are all-faint. */
|
|
13
|
-
const styleRecapLine = (line) => {
|
|
14
|
-
const m = /^(Goal|State):\s*/.exec(line);
|
|
15
|
-
if (m === null)
|
|
16
|
-
return pal.faint(line);
|
|
17
|
-
return `${pal.bold(m[1] + ':')} ${pal.faint(line.slice(m[0].length))}`;
|
|
18
|
-
};
|
|
19
|
-
/** Paint serializable extension widgets into their fixed cockpit slots. The
|
|
20
|
-
* recap sits immediately above the editor border and uses the faint palette:
|
|
21
|
-
* persistent orientation, but visually a side note rather than primary UI. */
|
|
9
|
+
const { aboveWidgets, belowWidgets, queued } = ctx.containers;
|
|
10
|
+
/** Paint serializable extension widgets into their fixed cockpit slots. */
|
|
22
11
|
const renderExtensionWidgets = () => {
|
|
23
12
|
const session = state();
|
|
24
13
|
aboveWidgets.clear();
|
|
25
14
|
belowWidgets.clear();
|
|
26
|
-
// The
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
if (session.display.widgets['crtr-recap'] === undefined)
|
|
30
|
-
chrome.addChild(new DynamicBorder(pal.border));
|
|
15
|
+
// The recap widget is split: its goal line is painted by the pinned
|
|
16
|
+
// header, while its state line lands here in the widget's own cockpit
|
|
17
|
+
// slot, label stripped and faint.
|
|
31
18
|
const span = Math.max(1, (process.stdout.columns ?? 80) - 2);
|
|
32
19
|
for (const [key, widget] of Object.entries(session.display.widgets)) {
|
|
20
|
+
const recap = key === 'crtr-recap';
|
|
21
|
+
const lines = recap ? splitRecapLines(widget.lines).state : widget.lines;
|
|
33
22
|
const target = widget.placement === 'belowEditor' ? belowWidgets : aboveWidgets;
|
|
34
|
-
for (const line of
|
|
35
|
-
|
|
23
|
+
for (const line of lines) {
|
|
24
|
+
// Styled before wrapping so a wrapped continuation stays faint.
|
|
25
|
+
const styled = recap ? pal.faint(line) : line;
|
|
36
26
|
for (const wrapped of wrapTextWithAnsi(styled, span)) {
|
|
37
27
|
target.addChild(new Text(wrapped, 1, 0));
|
|
38
28
|
}
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
//
|
|
3
3
|
// This module holds only the command metadata (help schema, flags) and the
|
|
4
4
|
// thin `run` entry. It is deliberately kept OFF the heavy pi-coding-agent module
|
|
5
|
-
// graph so
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// imported inside `run`, so the bundle loads ONLY when a viewer actually opens.
|
|
5
|
+
// graph so registering the `surface` subtree costs a cheap command-framework
|
|
6
|
+
// load, not the ~363ms ESM load of the esbuild-bundled attach viewer (`viewer.ts`,
|
|
7
|
+
// which pulls pi-coding-agent's babel/highlight.js). The viewer runtime is
|
|
8
|
+
// dynamically imported inside `run`, so the bundle loads ONLY when a viewer
|
|
9
|
+
// actually opens.
|
|
11
10
|
import { defineBranch, defineLeaf } from '../../core/command.js';
|
|
12
11
|
import { mark } from '../../core/timing.js';
|
|
13
12
|
const attachToLeaf = defineLeaf({
|
|
@@ -74,7 +73,12 @@ const attachToLeaf = defineLeaf({
|
|
|
74
73
|
const { runAttach } = await import('./viewer.js');
|
|
75
74
|
mark('viewer.bundle_loaded');
|
|
76
75
|
await runAttach(nodeId, observer, canvasName);
|
|
77
|
-
|
|
76
|
+
// The session has sent its final broker frame and restored the terminal.
|
|
77
|
+
// Force this one-shot viewer process out now: pi's bundled UI dependencies
|
|
78
|
+
// can retain libuv handles after their visible work is finished. The exit
|
|
79
|
+
// handler registered by teardown still runs, so terminal restoration remains
|
|
80
|
+
// safe if the normal path raced a signal.
|
|
81
|
+
process.exit(0);
|
|
78
82
|
},
|
|
79
83
|
render: (result) => (result['note'] !== undefined ? String(result['note']) : ''),
|
|
80
84
|
});
|
|
@@ -63,6 +63,10 @@ export interface AttachPalette {
|
|
|
63
63
|
error: (s: string) => string;
|
|
64
64
|
/** Warning / transient notices. Same constraint as `error` → ANSI yellow. */
|
|
65
65
|
warning: (s: string) => string;
|
|
66
|
+
/** Added display-diff prefixes/line numbers. pi exposes no foreground role here. */
|
|
67
|
+
diffAdded: (s: string) => string;
|
|
68
|
+
/** Removed display-diff prefixes/line numbers. pi exposes no foreground role here. */
|
|
69
|
+
diffRemoved: (s: string) => string;
|
|
66
70
|
/** Editor border for a SINGLE-`!` bash command (output IS added to the agent's
|
|
67
71
|
* context). Dull/normal ANSI green — pi paints shell mode from its `bashMode`
|
|
68
72
|
* theme color (default `green`), which pi does NOT re-export through its public
|
|
@@ -207,6 +207,7 @@ const RED = (s) => `\x1b[31m${s}\x1b[39m`;
|
|
|
207
207
|
const YELLOW = (s) => `\x1b[33m${s}\x1b[39m`;
|
|
208
208
|
const GREEN = (s) => `\x1b[32m${s}\x1b[39m`;
|
|
209
209
|
const BRIGHT_GREEN = (s) => `\x1b[92m${s}\x1b[39m`;
|
|
210
|
+
const DIFF_REMOVED = (s) => `\x1b[91m${s}\x1b[39m`;
|
|
210
211
|
// Terminals do not support alpha. This neutral charcoal is the dark-theme
|
|
211
212
|
// equivalent of a low-opacity gray overlay, without borrowing the purple
|
|
212
213
|
// selection surface used by interactive chrome.
|
|
@@ -264,6 +265,8 @@ export function attachPalette() {
|
|
|
264
265
|
bold: md.bold,
|
|
265
266
|
error: RED,
|
|
266
267
|
warning: YELLOW,
|
|
268
|
+
diffAdded: GREEN,
|
|
269
|
+
diffRemoved: DIFF_REMOVED,
|
|
267
270
|
bashMode: GREEN,
|
|
268
271
|
bashModeAlt: BRIGHT_GREEN,
|
|
269
272
|
surface: (line) => `${bgOn}${line.replace(/\x1b\[0m/g, `\x1b[0m${bgOn}`)}\x1b[49m`,
|