@north-light/crouter 0.3.173 → 0.3.174
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/bin/runtime-selector.mjs +8 -1
- package/dist/api/__tests__/{client.test.js → serial/client.test.js} +2 -135
- package/dist/api/client.d.ts +12 -21
- package/dist/api/client.js +22 -31
- package/dist/api/dto/broker-ops.d.ts +158 -0
- package/dist/api/dto/broker-ops.js +6 -0
- package/dist/api/dto/crons.d.ts +6 -0
- package/dist/api/dto/human.d.ts +7 -1
- package/dist/api/dto/inbox.d.ts +1 -71
- package/dist/api/dto/inbox.js +1 -9
- package/dist/api/dto/nodes.d.ts +6 -7
- package/dist/api/dto/reviews.d.ts +1 -11
- package/dist/api/routes.d.ts +7 -4
- package/dist/api/routes.js +8 -5
- package/dist/build-root.js +3 -3
- package/dist/builtin-memory/04-base-worker.md +1 -4
- package/dist/builtin-memory/05-kinds/advisor/00-base.md +1 -5
- package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +2 -7
- package/dist/builtin-memory/05-kinds/design/00-base.md +1 -6
- package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -6
- package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -4
- package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +1 -2
- package/dist/builtin-memory/05-kinds/general/00-base.md +1 -3
- package/dist/builtin-memory/05-kinds/plan/00-base.md +1 -6
- package/dist/builtin-memory/05-kinds/plan/reviewers/00-base.md +1 -2
- package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +1 -3
- package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +1 -3
- package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +1 -3
- package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +1 -3
- package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +1 -4
- package/dist/builtin-memory/05-kinds/review/companion/00-base.md +2 -3
- package/dist/builtin-memory/05-kinds/spec/00-base.md +1 -2
- package/dist/builtin-memory/advisor/council.md +1 -6
- package/dist/builtin-memory/design.md +2 -7
- package/dist/builtin-memory/development.md +9 -14
- package/dist/builtin-memory/internal/marketplaces.md +2 -6
- package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
- package/dist/builtin-memory/internal/plugins.md +2 -8
- package/dist/builtin-memory/internal/storage-tiers.md +1 -2
- package/dist/builtin-memory/testing.md +41 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/{provider-rotation.test.ts → serial/provider-rotation.test.ts} +27 -179
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +5 -15
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/index.ts +1 -28
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +43 -88
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +7 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +9 -1
- package/dist/cli.js +2 -2
- package/dist/clients/attach/__tests__/attach-remote-readonly.test.js +37 -131
- package/dist/clients/attach/__tests__/chat-view-snapshot-ordering.test.js +71 -152
- package/dist/clients/attach/__tests__/context-message.test.js +16 -174
- package/dist/clients/attach/__tests__/crtr-output.test.js +36 -2069
- package/dist/clients/attach/__tests__/diagram.test.js +2 -2
- package/dist/clients/attach/__tests__/edit-diff.test.js +0 -4
- package/dist/clients/attach/__tests__/file-review-focus.test.js +2 -1
- package/dist/clients/attach/__tests__/group-activity.test.js +40 -229
- package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.js +26 -76
- package/dist/clients/attach/__tests__/prompt-preview.test.js +4 -70
- package/dist/clients/attach/__tests__/ref-autocomplete.test.js +11 -125
- package/dist/clients/attach/__tests__/titled-editor-preview.test.js +14 -205
- package/dist/clients/attach/command.d.ts +2 -1
- package/dist/clients/attach/command.js +81 -76
- package/dist/clients/attach/input/capabilities.d.ts +27 -0
- package/dist/clients/attach/input/capabilities.js +96 -0
- package/dist/clients/attach/input/controller.d.ts +20 -182
- package/dist/clients/attach/input/controller.js +128 -537
- package/dist/clients/attach/input/overlay-owner.d.ts +41 -0
- package/dist/clients/attach/input/overlay-owner.js +199 -0
- package/dist/clients/attach/overlays/file-review.d.ts +0 -4
- package/dist/clients/attach/overlays/file-review.js +13 -5
- package/dist/clients/attach/overlays/graph.js +2 -10
- package/dist/clients/attach/render/chat-view.d.ts +4 -3
- package/dist/clients/attach/render/chat-view.js +39 -33
- package/dist/clients/attach/render/group-activity.d.ts +1 -0
- package/dist/clients/attach/render/group-activity.js +20 -13
- package/dist/clients/attach/render/group-recap.js +12 -3
- package/dist/clients/attach/session/connection.js +9 -15
- package/dist/clients/attach/session/editor-inventory.d.ts +6 -5
- package/dist/clients/attach/session/editor-inventory.js +7 -8
- package/dist/clients/attach/session/file-links.d.ts +13 -0
- package/dist/clients/attach/session/file-links.js +107 -0
- package/dist/clients/attach/session/frame.d.ts +3 -0
- package/dist/clients/attach/session/frame.js +10 -1
- package/dist/clients/attach/session/frames.js +2 -3
- package/dist/clients/attach/session/input-wiring.d.ts +4 -1
- package/dist/clients/attach/session/input-wiring.js +15 -14
- package/dist/clients/attach/session/mouse.d.ts +6 -1
- package/dist/clients/attach/session/mouse.js +8 -5
- package/dist/clients/attach/session/profile-files.js +18 -12
- package/dist/clients/attach/session/reconnect.js +1 -1
- package/dist/clients/attach/session/state-sync.js +1 -2
- package/dist/clients/attach/session/surface-host.d.ts +3 -2
- package/dist/clients/attach/session/surface-host.js +4 -4
- package/dist/clients/attach/slash/dispatch.d.ts +8 -31
- package/dist/clients/attach/slash/dispatch.js +34 -81
- package/dist/clients/attach/viewer.js +820 -860
- package/dist/clients/conversation/projection.d.ts +79 -0
- package/dist/clients/conversation/projection.js +341 -0
- package/dist/clients/inbox/__tests__/serial/inbox-controller.test.js +159 -0
- package/dist/clients/inbox/__tests__/serial/mount-panel.test.js +151 -0
- package/dist/clients/inbox/controller.d.ts +0 -4
- package/dist/clients/inbox/controller.js +0 -2
- package/dist/clients/inbox/review/__tests__/review-core.test.js +4 -293
- package/dist/clients/inbox/review/__tests__/teardown-notice.test.js +100 -0
- package/dist/clients/inbox/review/comments-client.d.ts +3 -2
- package/dist/clients/inbox/review/comments-client.js +12 -12
- package/dist/clients/inbox/review/companion-pane.d.ts +30 -0
- package/dist/clients/inbox/review/companion-pane.js +86 -0
- package/dist/clients/inbox/review/document-surface.d.ts +182 -0
- package/dist/clients/inbox/review/{document-region.js → document-surface.js} +252 -48
- package/dist/clients/inbox/review/frame.js +5 -4
- package/dist/clients/inbox/review/launch.d.ts +8 -8
- package/dist/clients/inbox/review/launch.js +52 -92
- package/dist/clients/inbox/review/nvim.d.ts +2 -0
- package/dist/clients/inbox/review/nvim.js +14 -12
- package/dist/clients/inbox/review/review-client.d.ts +12 -8
- package/dist/clients/inbox/review/review-client.js +46 -35
- package/dist/clients/inbox/review-adapter.d.ts +3 -10
- package/dist/clients/inbox/review-adapter.js +27 -19
- package/dist/clients/inbox/surface.d.ts +0 -4
- package/dist/clients/inbox/surface.js +0 -2
- package/dist/clients/surfaces/host.d.ts +11 -3
- package/dist/commands/__tests__/api-client-cold-start-diagnostic.test.js +7 -34
- package/dist/commands/__tests__/human.test.js +11 -322
- package/dist/commands/api-client.d.ts +5 -5
- package/dist/commands/api-client.js +6 -85
- package/dist/commands/canvas-browse.js +3 -29
- package/dist/commands/canvas-config.js +1 -1
- package/dist/commands/canvas-use.js +3 -3
- package/dist/commands/canvas.js +1 -1
- package/dist/commands/cron.js +5 -1
- package/dist/commands/human/queue.d.ts +0 -4
- package/dist/commands/human/queue.js +7 -40
- package/dist/commands/memory/list.d.ts +14 -0
- package/dist/commands/memory/list.js +35 -31
- package/dist/commands/memory/read.d.ts +7 -0
- package/dist/commands/memory/read.js +14 -8
- package/dist/commands/node/bash.d.ts +1 -0
- package/dist/commands/node/bash.js +198 -0
- package/dist/commands/node/create.d.ts +23 -0
- package/dist/commands/node/create.js +207 -0
- package/dist/commands/node/inspect.d.ts +2 -0
- package/dist/commands/node/inspect.js +302 -0
- package/dist/commands/node/lifecycle.d.ts +4 -0
- package/dist/commands/node/lifecycle.js +415 -0
- package/dist/commands/node/message.d.ts +1 -0
- package/dist/commands/node/message.js +164 -0
- package/dist/commands/node/pyramid.d.ts +2 -0
- package/dist/commands/node/pyramid.js +79 -0
- package/dist/commands/node/subscription.d.ts +1 -0
- package/dist/commands/node/subscription.js +82 -0
- package/dist/commands/node/wait.d.ts +1 -0
- package/dist/commands/node/wait.js +159 -0
- package/dist/commands/node-lifecycle-revive.js +10 -57
- package/dist/commands/node.d.ts +0 -42
- package/dist/commands/node.js +11 -2065
- package/dist/commands/search.js +1 -1
- package/dist/commands/surface/node/cycle.d.ts +1 -0
- package/dist/commands/surface/node/cycle.js +83 -0
- package/dist/commands/surface/node/focus.d.ts +1 -0
- package/dist/commands/surface/node/focus.js +67 -0
- package/dist/commands/surface/node/id.d.ts +1 -0
- package/dist/commands/surface/node/id.js +38 -0
- package/dist/commands/surface/node/pin.d.ts +1 -0
- package/dist/commands/surface/node/pin.js +42 -0
- package/dist/commands/surface/node/placement.d.ts +46 -0
- package/dist/commands/surface/node/placement.js +124 -0
- package/dist/commands/surface-node.js +4 -1
- package/dist/commands/surface-reload.js +1 -2
- package/dist/commands/surface-tmux-spread.js +1 -1
- package/dist/commands/surface.js +5 -20
- package/dist/commands/sys/__tests__/setup-core.test.js +18 -271
- package/dist/commands/sys/config.js +6 -6
- package/dist/commands/sys/logs.js +1 -1
- package/dist/commands/sys/panels/broker-limits-panel.d.ts +17 -0
- package/dist/commands/sys/panels/broker-limits-panel.js +104 -0
- package/dist/commands/sys/panels/dependencies-panel.d.ts +14 -0
- package/dist/commands/sys/panels/dependencies-panel.js +80 -0
- package/dist/commands/sys/panels/keybindings-panel.d.ts +56 -0
- package/dist/commands/sys/panels/keybindings-panel.js +703 -0
- package/dist/commands/sys/panels/keys-panel.d.ts +16 -0
- package/dist/commands/sys/panels/keys-panel.js +60 -0
- package/dist/commands/sys/panels/models-panel.d.ts +77 -0
- package/dist/commands/sys/panels/models-panel.js +647 -0
- package/dist/commands/sys/panels/panel.d.ts +45 -0
- package/dist/commands/sys/panels/panel.js +137 -0
- package/dist/commands/sys/panels/plugins-panel.d.ts +16 -0
- package/dist/commands/sys/panels/plugins-panel.js +80 -0
- package/dist/commands/sys/panels/prefs-panel.d.ts +21 -0
- package/dist/commands/sys/panels/prefs-panel.js +85 -0
- package/dist/commands/sys/panels/provider-panel.d.ts +62 -0
- package/dist/commands/sys/panels/provider-panel.js +538 -0
- package/dist/commands/sys/settings-shell.d.ts +55 -0
- package/dist/commands/sys/settings-shell.js +400 -0
- package/dist/commands/sys/settings.d.ts +2 -0
- package/dist/commands/sys/settings.js +31 -0
- package/dist/commands/sys/setup-core.d.ts +3 -33
- package/dist/commands/sys/setup-core.js +27 -78
- package/dist/commands/sys/setup-settings-runner.d.ts +24 -0
- package/dist/commands/sys/setup-settings-runner.js +63 -0
- package/dist/commands/sys/setup-wizard.d.ts +26 -125
- package/dist/commands/sys/setup-wizard.js +209 -2473
- package/dist/commands/sys/setup.js +5 -7
- package/dist/commands/sys.js +3 -2
- package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +50 -0
- package/dist/core/__tests__/broker-launch-candidates.test.js +20 -9
- package/dist/core/__tests__/broker-preflight.test.js +1 -1
- package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +108 -27
- package/dist/core/__tests__/canvas-inbox-watcher.test.js +14 -0
- package/dist/core/__tests__/canvas.test.js +2 -36
- package/dist/core/__tests__/close.test.js +14 -3
- package/dist/core/__tests__/context-intro.test.js +32 -143
- package/dist/core/__tests__/cron-broker-capacity.test.js +22 -3
- package/dist/core/__tests__/daemon-boot.test.js +2 -20
- package/dist/core/__tests__/daemon-wedge.test.js +1 -1
- package/dist/core/__tests__/dead-node-policy-table.test.js +1 -18
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +1 -1
- package/dist/core/__tests__/fixtures/fake-engine.js +2 -2
- package/dist/core/__tests__/fixtures/fake-pi-host.js +2 -2
- package/dist/core/__tests__/focuses.test.js +4 -98
- package/dist/core/__tests__/helpers/broker-clients.d.ts +0 -3
- package/dist/core/__tests__/helpers/broker-clients.js +0 -14
- package/dist/core/__tests__/helpers/harness.d.ts +0 -8
- package/dist/core/__tests__/helpers/harness.js +7 -87
- package/dist/core/__tests__/helpers/viewer-panes.js +1 -1
- package/dist/core/__tests__/inline-memory-refs.test.js +5 -134
- package/dist/core/__tests__/kickoff.test.js +1 -1
- package/dist/core/__tests__/memory-resolver-precedence.test.js +29 -1
- package/dist/core/__tests__/migration.test.js +35 -48
- package/dist/core/__tests__/on-read-dedup-resume.test.js +22 -12
- package/dist/core/__tests__/passive-subscription.test.js +26 -49
- package/dist/core/__tests__/preview-registry-sync.test.js +1 -2
- package/dist/core/__tests__/prune.test.js +94 -1
- package/dist/core/__tests__/review-model-floor.test.js +0 -32
- package/dist/core/__tests__/seam/broker-attach-multiclient.test.js +255 -0
- package/dist/core/__tests__/{full → seam}/broker-attach-stream.test.js +39 -7
- package/dist/core/__tests__/{full → seam}/broker-crash-teardown.test.js +30 -29
- package/dist/core/__tests__/{full → seam}/broker-pane-resolution.test.js +54 -5
- package/dist/core/__tests__/{full → seam}/broker-provider-retry.test.js +134 -82
- package/dist/core/__tests__/{full → seam}/broker-whip-interrupt.test.js +15 -4
- package/dist/core/__tests__/{full/idle-release-settlement.test.js → seam/dormancy-release.test.js} +69 -17
- package/dist/core/__tests__/{full/yield-message-transaction.test.js → seam/yield-refresh-transaction.test.js} +31 -9
- package/dist/core/__tests__/secrets.test.js +1 -7
- package/dist/core/__tests__/{broker-fork-seam.test.js → serial/broker-fork-seam.test.js} +58 -7
- package/dist/core/__tests__/{broker-sdk-wiring.test.js → serial/broker-sdk-wiring.test.js} +18 -162
- package/dist/core/__tests__/{broker-snapshot-history.test.js → serial/broker-snapshot-history.test.js} +9 -9
- package/dist/core/__tests__/{command-plugins.test.js → serial/command-plugins.test.js} +105 -15
- package/dist/core/__tests__/{deferred-no-wake.test.js → serial/deferred-no-wake.test.js} +23 -20
- package/dist/core/__tests__/{flagship-lifecycle.test.js → serial/flagship-lifecycle.test.js} +7 -7
- package/dist/core/__tests__/{host-teardown-process-group.test.js → serial/host-teardown-process-group.test.js} +6 -6
- package/dist/core/__tests__/{human-deliver-e2e.test.js → serial/human-deliver-e2e.test.js} +12 -12
- package/dist/core/__tests__/{live-mutation.test.js → serial/live-mutation.test.js} +5 -5
- package/dist/core/__tests__/{refresh-stall-recycle.test.js → serial/refresh-stall-recycle.test.js} +5 -14
- package/dist/core/__tests__/{revive.test.js → serial/revive.test.js} +15 -100
- package/dist/core/__tests__/{spawn-root.test.js → serial/spawn-root.test.js} +32 -15
- package/dist/core/__tests__/serial/subscription-delivery.test.js +126 -0
- package/dist/core/__tests__/serial/tmux-surface.test.js +256 -0
- package/dist/core/__tests__/{worktree.test.js → serial/worktree.test.js} +15 -15
- package/dist/core/__tests__/session-model.test.js +0 -18
- package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +9 -0
- package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +50 -0
- package/dist/core/broker-client/__tests__/transport-relay.test.js +15 -16
- package/dist/core/broker-client/__tests__/transport-socket.test.js +28 -0
- package/dist/core/broker-client/client.d.ts +2 -2
- package/dist/core/broker-client/client.js +4 -7
- package/dist/core/broker-client/transport-relay.d.ts +13 -19
- package/dist/core/broker-client/transport-relay.js +19 -34
- package/dist/core/broker-client/transport-socket.d.ts +2 -2
- package/dist/core/broker-client/transport-socket.js +9 -2
- package/dist/core/broker-client/transport.d.ts +7 -3
- package/dist/core/broker-client/transport.js +4 -4
- package/dist/core/canvas/__tests__/attention.test.js +1 -18
- package/dist/core/canvas/__tests__/remote-canvas-source.test.js +7 -64
- package/dist/core/canvas/__tests__/remote-transport.test.js +2 -3
- package/dist/core/canvas/__tests__/render-remote.test.js +7 -52
- package/dist/core/canvas/browse/app.d.ts +2 -17
- package/dist/core/canvas/browse/app.js +16 -88
- package/dist/core/canvas/browse/model.d.ts +0 -4
- package/dist/core/canvas/browse/model.js +1 -12
- package/dist/core/canvas/browse/render.js +6 -3
- package/dist/core/canvas/crons.d.ts +8 -5
- package/dist/core/canvas/crons.js +7 -6
- package/dist/core/canvas/extensions.d.ts +7 -3
- package/dist/core/canvas/extensions.js +16 -4
- package/dist/core/canvas/nav-model.d.ts +0 -4
- package/dist/core/canvas/nav-model.js +2 -14
- package/dist/core/canvas/node-order.d.ts +3 -0
- package/dist/core/canvas/node-order.js +12 -0
- package/dist/core/canvas/remote-canvas-source.d.ts +3 -6
- package/dist/core/canvas/remote-canvas-source.js +8 -15
- package/dist/core/command.js +11 -4
- package/dist/core/config.js +3 -1
- package/dist/core/events/envelope.js +1 -1
- package/dist/core/events/read.js +7 -21
- package/dist/core/events/source.d.ts +0 -2
- package/dist/core/events/source.js +0 -16
- package/dist/core/events/types.d.ts +1 -1
- package/dist/core/fault-classifier.d.ts +1 -1
- package/dist/core/feed/passive.d.ts +0 -11
- package/dist/core/feed/passive.js +1 -62
- package/dist/core/human/__tests__/{inbox-core.test.js → serial/inbox-core.test.js} +6 -6
- package/dist/core/keybindings/__tests__/resolve.test.js +1 -96
- package/dist/core/keybindings/background-bash.js +3 -4
- package/dist/core/keybindings/catalog.js +1 -1
- package/dist/core/memory/inline-ref-grammar.js +3 -3
- package/dist/core/memory-resolver.d.ts +11 -25
- package/dist/core/memory-resolver.js +51 -33
- package/dist/core/model-routes.d.ts +15 -0
- package/dist/core/model-routes.js +12 -0
- package/dist/core/pool-credential-store.js +1 -1
- package/dist/core/preview-registry.js +8 -9
- package/dist/core/profiles/__tests__/root-profile.test.js +4 -14
- package/dist/core/review/realize.d.ts +0 -13
- package/dist/core/review/realize.js +0 -40
- package/dist/core/review/types.d.ts +1 -1
- package/dist/core/runtime/__tests__/engine-route.test.js +2 -2
- package/dist/core/runtime/bearings.js +1 -11
- package/dist/core/runtime/broker/client-registry.d.ts +33 -0
- package/dist/core/runtime/broker/client-registry.js +164 -0
- package/dist/core/runtime/broker/daemon-ops.d.ts +19 -0
- package/dist/core/runtime/broker/daemon-ops.js +49 -0
- package/dist/core/runtime/broker/event-projection.d.ts +42 -0
- package/dist/core/runtime/broker/event-projection.js +178 -0
- package/dist/core/runtime/broker/fault-retry.d.ts +39 -0
- package/dist/core/runtime/broker/fault-retry.js +277 -0
- package/dist/core/runtime/broker/frame-dispatch.d.ts +238 -0
- package/dist/core/runtime/broker/frame-dispatch.js +1537 -0
- package/dist/core/runtime/broker/inbox.d.ts +22 -0
- package/dist/core/runtime/broker/inbox.js +167 -0
- package/dist/core/runtime/broker/passive.d.ts +16 -0
- package/dist/core/runtime/broker/passive.js +44 -0
- package/dist/core/runtime/broker/read-ops.d.ts +23 -0
- package/dist/core/runtime/broker/read-ops.js +150 -0
- package/dist/core/runtime/broker/rebind.d.ts +74 -0
- package/dist/core/runtime/broker/rebind.js +211 -0
- package/dist/core/runtime/broker/tool-groups.d.ts +39 -0
- package/dist/core/runtime/broker/tool-groups.js +244 -0
- package/dist/core/runtime/broker-extension-render.d.ts +11 -0
- package/dist/core/runtime/broker-extension-render.js +181 -0
- package/dist/core/runtime/broker-persona-guidance.d.ts +13 -0
- package/dist/core/runtime/broker-persona-guidance.js +58 -0
- package/dist/core/runtime/broker-protocol.d.ts +1 -1
- package/dist/core/runtime/broker-protocol.js +1 -1
- package/dist/core/runtime/broker.d.ts +5 -196
- package/dist/core/runtime/broker.js +276 -3059
- package/dist/core/runtime/canvas-extensions.js +11 -2
- package/dist/core/runtime/fault.js +1 -1
- package/dist/core/runtime/model-selection.d.ts +9 -0
- package/dist/core/runtime/model-selection.js +12 -0
- package/dist/core/runtime/model-swap.d.ts +3 -3
- package/dist/core/runtime/model-swap.js +33 -25
- package/dist/core/runtime/placement-tmux.d.ts +3 -14
- package/dist/core/runtime/placement-tmux.js +11 -80
- package/dist/core/runtime/placement.d.ts +4 -2
- package/dist/core/runtime/placement.js +7 -12
- package/dist/core/runtime/promote.d.ts +14 -1
- package/dist/core/runtime/promote.js +1 -1
- package/dist/core/runtime/reset.d.ts +1 -1
- package/dist/core/runtime/roadmap.js +1 -1
- package/dist/core/runtime/spawn.d.ts +8 -0
- package/dist/core/runtime/spawn.js +36 -6
- package/dist/core/runtime/stop-guard.d.ts +4 -3
- package/dist/core/runtime/stop-guard.js +36 -18
- package/dist/core/runtime/stop-signals.d.ts +4 -1
- package/dist/core/runtime/stream-watchdog.js +4 -5
- package/dist/core/runtime/structured-output.d.ts +15 -2
- package/dist/core/runtime/structured-output.js +35 -12
- package/dist/core/runtime/tmux-bindings.d.ts +25 -0
- package/dist/core/runtime/tmux-bindings.js +682 -0
- package/dist/core/runtime/tmux-chrome.d.ts +2 -1
- package/dist/core/runtime/tmux-chrome.js +3 -2
- package/dist/core/runtime/{tmux.d.ts → tmux-driver.d.ts} +18 -26
- package/dist/core/runtime/tmux-driver.js +598 -0
- package/dist/core/runtime/view-socket.d.ts +14 -0
- package/dist/core/runtime/view-socket.js +83 -0
- package/dist/core/session-model/session-state.d.ts +1 -2
- package/dist/core/session-model/session-state.js +5 -8
- package/dist/core/spawn.d.ts +1 -1
- package/dist/core/spawn.js +2 -2
- package/dist/core/substrate/gate.d.ts +1 -1
- package/dist/core/substrate/on-read-pure.d.ts +7 -0
- package/dist/core/substrate/on-read-pure.js +272 -0
- package/dist/core/termrender/termrender.js +32 -2
- package/dist/core/user-settings.d.ts +23 -1
- package/dist/core/user-settings.js +18 -1
- package/dist/daemon/api/__tests__/node-model-validation.test.js +134 -0
- package/dist/daemon/api/__tests__/review-terminal-conflict.test.js +98 -0
- package/dist/daemon/api/__tests__/{full → seam}/api-server.test.js +6 -48
- package/dist/daemon/api/__tests__/{full → seam}/b10-attach-modelauth.test.js +17 -44
- package/dist/daemon/api/__tests__/{full/push-parity.test.js → seam/leaf-api-parity.test.js} +61 -42
- package/dist/daemon/api/bridge.js +40 -81
- package/dist/daemon/api/handlers/broker-ops.d.ts +2 -0
- package/dist/daemon/api/handlers/broker-ops.js +383 -0
- package/dist/daemon/api/handlers/crons.js +9 -4
- package/dist/daemon/api/handlers/files.js +6 -7
- package/dist/daemon/api/handlers/inbox.js +2 -340
- package/dist/daemon/api/handlers/nodes.d.ts +10 -1
- package/dist/daemon/api/handlers/nodes.js +74 -39
- package/dist/daemon/api/handlers/review-comments.js +5 -1
- package/dist/daemon/api/handlers/reviews.js +0 -19
- package/dist/daemon/api/map.js +25 -4
- package/dist/daemon/api/router.js +2 -3
- package/dist/daemon/api/server.js +5 -7
- package/dist/daemon/cron-run.d.ts +4 -0
- package/dist/daemon/cron-run.js +30 -13
- package/dist/daemon/crtrd.d.ts +3 -58
- package/dist/daemon/crtrd.js +28 -1244
- package/dist/daemon/manage.js +0 -1
- package/dist/daemon/reconcilers/broker-supervision.d.ts +50 -0
- package/dist/daemon/reconcilers/broker-supervision.js +549 -0
- package/dist/daemon/reconcilers/cron-lane.d.ts +10 -0
- package/dist/daemon/reconcilers/cron-lane.js +32 -0
- package/dist/daemon/reconcilers/dormant-inbox.d.ts +18 -0
- package/dist/daemon/reconcilers/dormant-inbox.js +143 -0
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +22 -0
- package/dist/daemon/reconcilers/storage-maintenance.js +213 -0
- package/dist/daemon/review/finish.js +2 -5
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +34 -53
- package/dist/pi-extensions/__tests__/canvas-recap.test.js +16 -113
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +72 -99
- package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +29 -12
- package/dist/pi-extensions/broker-local.d.ts +20 -0
- package/dist/pi-extensions/broker-local.js +89 -0
- package/dist/pi-extensions/canvas-context-intro.d.ts +3 -3
- package/dist/pi-extensions/canvas-context-intro.js +22 -11
- package/dist/pi-extensions/canvas-doc-substrate.js +17 -34
- package/dist/pi-extensions/canvas-goal-capture.js +7 -12
- package/dist/pi-extensions/canvas-inbox-watcher.js +124 -139
- package/dist/pi-extensions/canvas-passive-context.d.ts +3 -3
- package/dist/pi-extensions/canvas-passive-context.js +22 -18
- package/dist/pi-extensions/canvas-recap.d.ts +2 -2
- package/dist/pi-extensions/canvas-recap.js +48 -21
- package/dist/pi-extensions/canvas-review-boundary.js +10 -4
- package/dist/pi-extensions/canvas-stophook.d.ts +0 -5
- package/dist/pi-extensions/canvas-stophook.js +149 -431
- package/dist/pi-extensions/canvas-structured-output.js +52 -30
- package/dist/pi-extensions/envelope-merge.d.ts +13 -0
- package/dist/pi-extensions/envelope-merge.js +29 -0
- package/dist/shared/working-activity.d.ts +3 -2
- package/dist/shared/working-activity.js +3 -2
- package/dist/types.d.ts +6 -5
- package/dist/types.js +2 -2
- package/docs/compat/hearth-crtr-v1.md +4 -12
- package/docs/compat/hearth-crtr-v2.md +3 -11
- package/docs/compat/hearth-crtr-v3.md +4 -12
- package/docs/compat/hearth-crtr-v4.md +3 -11
- package/docs/compat/hearth-crtr-v5.md +3 -11
- package/docs/public-api.md +3 -7
- package/package.json +7 -49
- package/runtime.lock.json +2766 -14533
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/claude-plugin-commands.test.ts +0 -49
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/memory-slash-commands.test.ts +0 -194
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/statusline.test.ts +0 -68
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/test.ts +0 -119
- package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +0 -439
- package/dist/clients/attach/__tests__/attach-keybindings.test.js +0 -170
- package/dist/clients/attach/__tests__/crtr-output-coverage.test.js +0 -57
- package/dist/clients/attach/__tests__/editor-frame-title.test.js +0 -19
- package/dist/clients/attach/__tests__/input-controller-extension-command.test.js +0 -32
- package/dist/clients/attach/__tests__/markdown-headings.test.js +0 -35
- package/dist/clients/attach/__tests__/session-identity-refresh.test.js +0 -32
- package/dist/clients/conversation/conversation.d.ts +0 -65
- package/dist/clients/conversation/conversation.js +0 -318
- package/dist/clients/conversation/frames.d.ts +0 -30
- package/dist/clients/conversation/frames.js +0 -52
- package/dist/clients/conversation/region.d.ts +0 -51
- package/dist/clients/conversation/region.js +0 -265
- package/dist/clients/inbox/__tests__/inbox-controller.test.js +0 -247
- package/dist/clients/inbox/__tests__/mount-panel.test.js +0 -776
- package/dist/clients/inbox/review/__tests__/remap.test.js +0 -196
- package/dist/clients/inbox/review/columns.d.ts +0 -22
- package/dist/clients/inbox/review/columns.js +0 -40
- package/dist/clients/inbox/review/composition.d.ts +0 -60
- package/dist/clients/inbox/review/composition.js +0 -278
- package/dist/clients/inbox/review/document-region.d.ts +0 -120
- package/dist/clients/surfaces/region.d.ts +0 -16
- package/dist/clients/web/__tests__/push-engine.test.js +0 -158
- package/dist/clients/web/__tests__/push-registry.test.d.ts +0 -1
- package/dist/clients/web/__tests__/push-registry.test.js +0 -177
- package/dist/clients/web/dev-server.d.ts +0 -7
- package/dist/clients/web/dev-server.js +0 -46
- package/dist/clients/web/events.d.ts +0 -19
- package/dist/clients/web/events.js +0 -163
- package/dist/clients/web/push-engine.d.ts +0 -44
- package/dist/clients/web/push-engine.js +0 -125
- package/dist/clients/web/push-registry.d.ts +0 -85
- package/dist/clients/web/push-registry.js +0 -373
- package/dist/clients/web/server.d.ts +0 -19
- package/dist/clients/web/server.js +0 -661
- package/dist/clients/web/web-client/shared/protocol.d.ts +0 -214
- package/dist/clients/web/web-client/shared/protocol.js +0 -8
- package/dist/clients/web/web-cmd.d.ts +0 -2
- package/dist/clients/web/web-cmd.js +0 -141
- package/dist/commands/__tests__/api-canvas-source.test.d.ts +0 -1
- package/dist/commands/__tests__/api-canvas-source.test.js +0 -37
- package/dist/commands/__tests__/canvas-config.test.d.ts +0 -1
- package/dist/commands/__tests__/canvas-config.test.js +0 -107
- package/dist/commands/__tests__/node-no-kickoff-flag.test.d.ts +0 -1
- package/dist/commands/__tests__/node-no-kickoff-flag.test.js +0 -73
- package/dist/commands/__tests__/node-worktree-flag.test.d.ts +0 -1
- package/dist/commands/__tests__/node-worktree-flag.test.js +0 -49
- package/dist/commands/__tests__/search-contents.test.d.ts +0 -1
- package/dist/commands/__tests__/search-contents.test.js +0 -52
- package/dist/commands/memory/__tests__/lint.test.d.ts +0 -1
- package/dist/commands/memory/__tests__/lint.test.js +0 -15
- package/dist/commands/sys/__tests__/config-broker-thresholds.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/config-broker-thresholds.test.js +0 -95
- package/dist/commands/sys/__tests__/config-keybindings.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/config-keybindings.test.js +0 -55
- package/dist/commands/sys/__tests__/helpers/setup-runtime.d.ts +0 -5
- package/dist/commands/sys/__tests__/helpers/setup-runtime.js +0 -19
- package/dist/commands/sys/__tests__/setup-front-door.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/setup-front-door.test.js +0 -102
- package/dist/commands/sys/__tests__/setup-models.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/setup-models.test.js +0 -205
- package/dist/commands/sys/__tests__/setup-providers-viewport.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/setup-providers-viewport.test.js +0 -155
- package/dist/commands/sys/__tests__/sync-deps.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/sync-deps.test.js +0 -179
- package/dist/commands/sys/__tests__/sync-import.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/sync-import.test.js +0 -315
- package/dist/core/__tests__/base-worker-prompt.test.d.ts +0 -1
- package/dist/core/__tests__/base-worker-prompt.test.js +0 -57
- package/dist/core/__tests__/command-plugins-surfaces.test.d.ts +0 -1
- package/dist/core/__tests__/command-plugins-surfaces.test.js +0 -359
- package/dist/core/__tests__/connection-reconnect-resume.test.d.ts +0 -1
- package/dist/core/__tests__/connection-reconnect-resume.test.js +0 -36
- package/dist/core/__tests__/finalization-migration.test.d.ts +0 -1
- package/dist/core/__tests__/finalization-migration.test.js +0 -38
- package/dist/core/__tests__/fixtures/extra-extension.d.ts +0 -1
- package/dist/core/__tests__/fixtures/extra-extension.js +0 -3
- package/dist/core/__tests__/fixtures/spawn-proof-target.test.d.ts +0 -1
- package/dist/core/__tests__/fixtures/spawn-proof-target.test.js +0 -15
- package/dist/core/__tests__/fork.test.d.ts +0 -1
- package/dist/core/__tests__/fork.test.js +0 -108
- package/dist/core/__tests__/full/broker-attach-limits.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-attach-limits.test.js +0 -147
- package/dist/core/__tests__/full/broker-deliver-ack.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-deliver-ack.test.js +0 -73
- package/dist/core/__tests__/full/broker-dialogs.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-dialogs.test.js +0 -180
- package/dist/core/__tests__/full/broker-display-snapshot.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-display-snapshot.test.js +0 -75
- package/dist/core/__tests__/full/broker-dormant-wake.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-dormant-wake.test.js +0 -130
- package/dist/core/__tests__/full/broker-model-changed-broadcast.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-model-changed-broadcast.test.js +0 -57
- package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.js +0 -80
- package/dist/core/__tests__/full/cascade-close.test.d.ts +0 -1
- package/dist/core/__tests__/full/cascade-close.test.js +0 -240
- package/dist/core/__tests__/full/detach-focus.test.d.ts +0 -1
- package/dist/core/__tests__/full/detach-focus.test.js +0 -126
- package/dist/core/__tests__/full/idle-release-settlement.test.d.ts +0 -1
- package/dist/core/__tests__/full/issue-146-yield-spawn-focus.test.d.ts +0 -1
- package/dist/core/__tests__/full/issue-146-yield-spawn-focus.test.js +0 -107
- package/dist/core/__tests__/full/park-clock-release.test.d.ts +0 -1
- package/dist/core/__tests__/full/park-clock-release.test.js +0 -56
- package/dist/core/__tests__/full/yield-message-transaction.test.d.ts +0 -1
- package/dist/core/__tests__/memory-index-render.test.d.ts +0 -1
- package/dist/core/__tests__/memory-index-render.test.js +0 -60
- package/dist/core/__tests__/model-routes.test.d.ts +0 -1
- package/dist/core/__tests__/model-routes.test.js +0 -41
- package/dist/core/__tests__/on-read-identity.test.d.ts +0 -1
- package/dist/core/__tests__/on-read-identity.test.js +0 -61
- package/dist/core/__tests__/phase4-review-migration.test.d.ts +0 -1
- package/dist/core/__tests__/phase4-review-migration.test.js +0 -100
- package/dist/core/__tests__/prune-to-limit.test.d.ts +0 -1
- package/dist/core/__tests__/prune-to-limit.test.js +0 -126
- package/dist/core/__tests__/reset.test.d.ts +0 -1
- package/dist/core/__tests__/reset.test.js +0 -69
- package/dist/core/__tests__/spawn-no-kickoff.test.d.ts +0 -1
- package/dist/core/__tests__/spawn-no-kickoff.test.js +0 -115
- package/dist/core/__tests__/steer-note.test.d.ts +0 -1
- package/dist/core/__tests__/steer-note.test.js +0 -41
- package/dist/core/__tests__/subcommand-tier.test.d.ts +0 -1
- package/dist/core/__tests__/subcommand-tier.test.js +0 -99
- package/dist/core/__tests__/subscription-delivery.test.js +0 -211
- package/dist/core/__tests__/test-runner-cheap-sharding.test.d.ts +0 -1
- package/dist/core/__tests__/test-runner-cheap-sharding.test.js +0 -97
- package/dist/core/__tests__/tmux-surface.test.js +0 -484
- package/dist/core/__tests__/wake-bearings.test.d.ts +0 -1
- package/dist/core/__tests__/wake-bearings.test.js +0 -102
- package/dist/core/canvas/__tests__/remote-event-stream.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/remote-event-stream.test.js +0 -146
- package/dist/core/canvas/__tests__/source-resolve.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/source-resolve.test.js +0 -77
- package/dist/core/canvas/browse/__tests__/model.test.d.ts +0 -1
- package/dist/core/canvas/browse/__tests__/model.test.js +0 -290
- package/dist/core/canvas/browse/__tests__/rebuild-coalescer.test.d.ts +0 -1
- package/dist/core/canvas/browse/__tests__/rebuild-coalescer.test.js +0 -134
- package/dist/core/canvas/browse/__tests__/render.test.d.ts +0 -1
- package/dist/core/canvas/browse/__tests__/render.test.js +0 -111
- package/dist/core/canvas/browse/rebuild-coalescer.d.ts +0 -7
- package/dist/core/canvas/browse/rebuild-coalescer.js +0 -61
- package/dist/core/canvas/remote-event-stream.d.ts +0 -24
- package/dist/core/canvas/remote-event-stream.js +0 -94
- package/dist/core/feed/__tests__/coalesce-human.test.d.ts +0 -1
- package/dist/core/feed/__tests__/coalesce-human.test.js +0 -36
- package/dist/core/feed/__tests__/empty-node-guard.test.d.ts +0 -1
- package/dist/core/feed/__tests__/empty-node-guard.test.js +0 -45
- package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.d.ts +0 -1
- package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.js +0 -84
- package/dist/core/human/__tests__/visible-paths.test.d.ts +0 -1
- package/dist/core/human/__tests__/visible-paths.test.js +0 -28
- package/dist/core/keybindings/__tests__/inbox-affordance.test.d.ts +0 -1
- package/dist/core/keybindings/__tests__/inbox-affordance.test.js +0 -38
- package/dist/core/review/__tests__/project.test.d.ts +0 -1
- package/dist/core/review/__tests__/project.test.js +0 -71
- package/dist/core/runtime/__tests__/command-expansion.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/command-expansion.test.js +0 -25
- package/dist/core/runtime/__tests__/session-visibility.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/session-visibility.test.js +0 -119
- package/dist/core/runtime/__tests__/spawn-at-given-id.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/spawn-at-given-id.test.js +0 -34
- package/dist/core/runtime/tmux.js +0 -1314
- package/dist/daemon/api/__tests__/full/push-parity.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/full/worktree-parity.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/full/worktree-parity.test.js +0 -160
- package/dist/daemon/api/__tests__/inbox.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/inbox.test.js +0 -489
- package/dist/web-client/apple-touch-icon.png +0 -0
- package/dist/web-client/assets/fragment-mono-latin-400-normal-BYwT3kSJ.woff +0 -0
- package/dist/web-client/assets/fragment-mono-latin-400-normal-yxdJ5AmL.woff2 +0 -0
- package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-BbKYyvR9.woff2 +0 -0
- package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-CT4YFKeK.woff +0 -0
- package/dist/web-client/assets/index-CCPaLeW7.css +0 -2
- package/dist/web-client/assets/index-kyOWsnZK.js +0 -86
- package/dist/web-client/assets/martian-mono-cyrillic-wght-normal-B84CD5C_.woff2 +0 -0
- package/dist/web-client/assets/martian-mono-latin-ext-wght-normal-DlL6xMw5.woff2 +0 -0
- package/dist/web-client/assets/martian-mono-latin-wght-normal-5W32yIyr.woff2 +0 -0
- package/dist/web-client/assets/workbox-window.prod.es5-Bd17z0YL.js +0 -2
- package/dist/web-client/icon-192.png +0 -0
- package/dist/web-client/icon-512.png +0 -0
- package/dist/web-client/icon-maskable-512.png +0 -0
- package/dist/web-client/index.html +0 -17
- package/dist/web-client/manifest.webmanifest +0 -1
- package/dist/web-client/sw.js +0 -1
- /package/dist/api/__tests__/{client.test.d.ts → serial/client.test.d.ts} +0 -0
- /package/dist/clients/inbox/__tests__/{inbox-controller.test.d.ts → serial/inbox-controller.test.d.ts} +0 -0
- /package/dist/clients/inbox/__tests__/{mount-panel.test.d.ts → serial/mount-panel.test.d.ts} +0 -0
- /package/dist/clients/{attach/__tests__/attach-chrome-remote.test.d.ts → inbox/review/__tests__/teardown-notice.test.d.ts} +0 -0
- /package/dist/{clients/attach/__tests__/attach-keybindings.test.d.ts → core/__tests__/broker-extension-canvas-db-boundary.test.d.ts} +0 -0
- /package/dist/{clients/attach/__tests__/crtr-output-coverage.test.d.ts → core/__tests__/seam/broker-attach-multiclient.test.d.ts} +0 -0
- /package/dist/core/__tests__/{full → seam}/broker-attach-stream.test.d.ts +0 -0
- /package/dist/core/__tests__/{full → seam}/broker-crash-teardown.test.d.ts +0 -0
- /package/dist/core/__tests__/{full → seam}/broker-pane-resolution.test.d.ts +0 -0
- /package/dist/core/__tests__/{full → seam}/broker-provider-retry.test.d.ts +0 -0
- /package/dist/core/__tests__/{full → seam}/broker-whip-interrupt.test.d.ts +0 -0
- /package/dist/{clients/attach/__tests__/editor-frame-title.test.d.ts → core/__tests__/seam/dormancy-release.test.d.ts} +0 -0
- /package/dist/{clients/attach/__tests__/input-controller-extension-command.test.d.ts → core/__tests__/seam/yield-refresh-transaction.test.d.ts} +0 -0
- /package/dist/core/__tests__/{broker-fork-seam.test.d.ts → serial/broker-fork-seam.test.d.ts} +0 -0
- /package/dist/core/__tests__/{broker-sdk-wiring.test.d.ts → serial/broker-sdk-wiring.test.d.ts} +0 -0
- /package/dist/core/__tests__/{broker-snapshot-history.test.d.ts → serial/broker-snapshot-history.test.d.ts} +0 -0
- /package/dist/core/__tests__/{command-plugins.test.d.ts → serial/command-plugins.test.d.ts} +0 -0
- /package/dist/core/__tests__/{deferred-no-wake.test.d.ts → serial/deferred-no-wake.test.d.ts} +0 -0
- /package/dist/core/__tests__/{flagship-lifecycle.test.d.ts → serial/flagship-lifecycle.test.d.ts} +0 -0
- /package/dist/core/__tests__/{host-teardown-process-group.test.d.ts → serial/host-teardown-process-group.test.d.ts} +0 -0
- /package/dist/core/__tests__/{human-deliver-e2e.test.d.ts → serial/human-deliver-e2e.test.d.ts} +0 -0
- /package/dist/core/__tests__/{live-mutation.test.d.ts → serial/live-mutation.test.d.ts} +0 -0
- /package/dist/core/__tests__/{refresh-stall-recycle.test.d.ts → serial/refresh-stall-recycle.test.d.ts} +0 -0
- /package/dist/core/__tests__/{revive.test.d.ts → serial/revive.test.d.ts} +0 -0
- /package/dist/core/__tests__/{spawn-root.test.d.ts → serial/spawn-root.test.d.ts} +0 -0
- /package/dist/core/__tests__/{subscription-delivery.test.d.ts → serial/subscription-delivery.test.d.ts} +0 -0
- /package/dist/core/__tests__/{tmux-surface.test.d.ts → serial/tmux-surface.test.d.ts} +0 -0
- /package/dist/core/__tests__/{worktree.test.d.ts → serial/worktree.test.d.ts} +0 -0
- /package/dist/{clients/attach/__tests__/markdown-headings.test.d.ts → core/__tests__/watchdog-abort-arms-retry.test.d.ts} +0 -0
- /package/dist/{clients/attach/__tests__/session-identity-refresh.test.d.ts → core/broker-client/__tests__/transport-socket.test.d.ts} +0 -0
- /package/dist/core/human/__tests__/{inbox-core.test.d.ts → serial/inbox-core.test.d.ts} +0 -0
- /package/dist/{clients/inbox/review/__tests__/remap.test.d.ts → daemon/api/__tests__/node-model-validation.test.d.ts} +0 -0
- /package/dist/{clients/surfaces/region.js → daemon/api/__tests__/review-terminal-conflict.test.d.ts} +0 -0
- /package/dist/daemon/api/__tests__/{full → seam}/api-server.test.d.ts +0 -0
- /package/dist/daemon/api/__tests__/{full → seam}/b10-attach-modelauth.test.d.ts +0 -0
- /package/dist/{clients/web/__tests__/push-engine.test.d.ts → daemon/api/__tests__/seam/leaf-api-parity.test.d.ts} +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { AgentSessionEvent } from '@earendil-works/pi-coding-agent';
|
|
2
|
+
import type { Message, ToolResultMessage } from '@earendil-works/pi-ai';
|
|
3
|
+
import type { BrokerSnapshot } from '../../core/runtime/broker-protocol.js';
|
|
4
|
+
import { type ToolGroupSummary } from '../../shared/tool-groups.js';
|
|
5
|
+
/** A persisted pi message or a crouter custom message carried on the broker wire. */
|
|
6
|
+
export type AnyMessage = Message | ({
|
|
7
|
+
role: string;
|
|
8
|
+
} & Record<string, unknown>);
|
|
9
|
+
export interface ConvState {
|
|
10
|
+
/** The full ordered transcript (snapshot history + streamed messages). */
|
|
11
|
+
messages: AnyMessage[];
|
|
12
|
+
/** Index of the assistant message currently streaming, or null. */
|
|
13
|
+
streamingIndex: number | null;
|
|
14
|
+
/** toolCallIds whose `tool_execution_*` is in flight (for an "executing…" badge). */
|
|
15
|
+
executingToolIds: ReadonlySet<string>;
|
|
16
|
+
/** Latest streaming/final result carried by tool_execution_* before the persisted toolResult message lands. */
|
|
17
|
+
partialToolResults: ReadonlyMap<string, ToolResultMessage>;
|
|
18
|
+
/** True between `agent_start` and `agent_end` (drives prompt-vs-steer + Stop). */
|
|
19
|
+
isStreaming: boolean;
|
|
20
|
+
/** A transient activity label (working / compacting / retrying), or null. */
|
|
21
|
+
activity: string | null;
|
|
22
|
+
/** Broker-selected normal label restored after temporary compaction/retry activity. */
|
|
23
|
+
workingActivity: string;
|
|
24
|
+
/** Texts still waiting to run — a writable view's steer/follow-up sent mid-turn
|
|
25
|
+
* (pi's `_steeringMessages` + `_followUpMessages`), authoritative from the
|
|
26
|
+
* engine's `queue_update` event. Drained (and removed here) the moment each
|
|
27
|
+
* one starts as a real `message_start`, so a queued row and the eventual
|
|
28
|
+
* transcript message never both show. */
|
|
29
|
+
queued: readonly string[];
|
|
30
|
+
/** Plain-text presentation recaps, keyed by the group's first tool-call id. */
|
|
31
|
+
toolGroupSummaries: Readonly<Record<string, string>>;
|
|
32
|
+
/** Canonical broker-owned completed tool-group summaries, keyed by the group's first tool-call id. */
|
|
33
|
+
toolGroupSummaryDetails: Readonly<Record<string, ToolGroupSummary>>;
|
|
34
|
+
}
|
|
35
|
+
export declare function initialConvState(): ConvState;
|
|
36
|
+
/** Rebuild the ephemeral reconciliation fields from a persisted transcript cache. */
|
|
37
|
+
export declare function restoreConvState(entry: {
|
|
38
|
+
messages: AnyMessage[];
|
|
39
|
+
isStreaming: boolean;
|
|
40
|
+
activity: string | null;
|
|
41
|
+
toolGroupSummaries: unknown;
|
|
42
|
+
}): ConvState;
|
|
43
|
+
/** Seed state from the broker's catch-up snapshot.
|
|
44
|
+
*
|
|
45
|
+
* `welcome.snapshot` is the PERSISTED history (`snapshotMessages()` in the
|
|
46
|
+
* broker), not the live in-memory array. During an active turn — after
|
|
47
|
+
* `message_start`, before `message_end` — the in-flight assistant message may
|
|
48
|
+
* not be persisted yet, so a mid-stream `welcome` can report
|
|
49
|
+
* `state.isStreaming: true` with no trailing assistant in the snapshot.
|
|
50
|
+
* Wholesale-replacing in that case (as we always did) drops the in-flight
|
|
51
|
+
* turn: `streamingIndex` resets to null and the next `message_update`/
|
|
52
|
+
* `message_end` has nothing to land on (see `reduce`).
|
|
53
|
+
*
|
|
54
|
+
* So: idle snapshots replace wholesale exactly as before. Streaming snapshots
|
|
55
|
+
* reconcile — if the persisted history already ends in an assistant, adopt
|
|
56
|
+
* it as the streaming target; otherwise adopt the caller-supplied `previous`
|
|
57
|
+
* state's in-flight assistant (a cache-first render or an earlier live
|
|
58
|
+
* session) if one exists, or synthesize an empty placeholder. Either way the
|
|
59
|
+
* first `message_update` REPLACES that message wholesale, so no duplicate or
|
|
60
|
+
* dropped turn results. */
|
|
61
|
+
export declare function applySnapshot(snapshot: BrokerSnapshot, previous?: ConvState): ConvState;
|
|
62
|
+
/** Apply the broker's random choice for the newly received user message. */
|
|
63
|
+
export declare function applyWorkingActivity(state: ConvState, activity: string): ConvState;
|
|
64
|
+
/** Apply one broker-published structured summary without touching transcript ordering. */
|
|
65
|
+
export declare function applyToolGroupSummary(state: ConvState, key: string, summary: ToolGroupSummary): ConvState;
|
|
66
|
+
export declare function bashStart(state: ConvState, command: string, excludeFromContext?: boolean): ConvState;
|
|
67
|
+
export declare function bashOutput(state: ConvState, chunk: string): ConvState;
|
|
68
|
+
export declare function bashEnd(state: ConvState, result: {
|
|
69
|
+
exitCode: number | undefined;
|
|
70
|
+
cancelled: boolean;
|
|
71
|
+
truncated: boolean;
|
|
72
|
+
fullOutputPath?: string;
|
|
73
|
+
}): ConvState;
|
|
74
|
+
/** Apply one broker→client AGENT event (an `AgentSessionEvent`) to the transcript.
|
|
75
|
+
* Broker control frames (welcome/model_changed/error/…) are handled by the hook,
|
|
76
|
+
* NOT here — only pi agent events reach this function. Returns a NEW state object
|
|
77
|
+
* (with fresh `messages`/`executingToolIds` only when they actually change) so
|
|
78
|
+
* React re-renders correctly. */
|
|
79
|
+
export declare function reduce(state: ConvState, event: AgentSessionEvent): ConvState;
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
// projection.ts — the surface-neutral reducer that turns a broker snapshot and
|
|
2
|
+
// its live frames into one ordered transcript model. Renderers retain their own
|
|
3
|
+
// folding and presentation; this module owns only wire-state reconciliation.
|
|
4
|
+
import { isInboxDigest } from '../../shared/generated-context.js';
|
|
5
|
+
import { normalizeToolGroupSummary, normalizeToolGroupSummaryRecord } from '../../shared/tool-groups.js';
|
|
6
|
+
import { DEFAULT_WORKING_ACTIVITY } from '../../shared/working-activity.js';
|
|
7
|
+
export function initialConvState() {
|
|
8
|
+
return {
|
|
9
|
+
messages: [],
|
|
10
|
+
streamingIndex: null,
|
|
11
|
+
executingToolIds: new Set(),
|
|
12
|
+
partialToolResults: new Map(),
|
|
13
|
+
isStreaming: false,
|
|
14
|
+
activity: null,
|
|
15
|
+
workingActivity: DEFAULT_WORKING_ACTIVITY,
|
|
16
|
+
queued: [],
|
|
17
|
+
toolGroupSummaries: {},
|
|
18
|
+
toolGroupSummaryDetails: {},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** Rebuild the ephemeral reconciliation fields from a persisted transcript cache. */
|
|
22
|
+
export function restoreConvState(entry) {
|
|
23
|
+
const lastIndex = entry.messages.length - 1;
|
|
24
|
+
return {
|
|
25
|
+
...initialConvState(),
|
|
26
|
+
messages: entry.messages,
|
|
27
|
+
streamingIndex: entry.isStreaming && lastIndex >= 0 ? lastIndex : null,
|
|
28
|
+
isStreaming: entry.isStreaming,
|
|
29
|
+
activity: entry.activity,
|
|
30
|
+
workingActivity: entry.isStreaming && entry.activity !== null ? entry.activity : DEFAULT_WORKING_ACTIVITY,
|
|
31
|
+
toolGroupSummaries: textToolGroupSummaries(entry.toolGroupSummaries),
|
|
32
|
+
toolGroupSummaryDetails: normalizeToolGroupSummaryRecord(entry.toolGroupSummaries),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Plain text of a user message (string content or concatenated text blocks),
|
|
36
|
+
* for inbox-digest detection. */
|
|
37
|
+
function userMessageText(m) {
|
|
38
|
+
const content = m.content;
|
|
39
|
+
if (typeof content === 'string')
|
|
40
|
+
return content;
|
|
41
|
+
if (Array.isArray(content)) {
|
|
42
|
+
return content
|
|
43
|
+
.filter((b) => !!b && b.type === 'text')
|
|
44
|
+
.map((b) => (typeof b.text === 'string' ? b.text : ''))
|
|
45
|
+
.join('');
|
|
46
|
+
}
|
|
47
|
+
return '';
|
|
48
|
+
}
|
|
49
|
+
/** Tag a `role:'user'` message as inbox-origin when its text matches the
|
|
50
|
+
* canvas-inbox-watcher coalesce digest; other messages pass through unchanged.
|
|
51
|
+
* The broker relays pi AgentMessages verbatim and never carries `origin` on the
|
|
52
|
+
* wire, so this is the sole writer of `origin:'inbox'` — recognized from the
|
|
53
|
+
* digest text. (Idempotent: a message already tagged is left as-is.) */
|
|
54
|
+
function tagInboxOrigin(m) {
|
|
55
|
+
if (roleOf(m) !== 'user')
|
|
56
|
+
return m;
|
|
57
|
+
if (m.origin)
|
|
58
|
+
return m;
|
|
59
|
+
if (!isInboxDigest(userMessageText(m)))
|
|
60
|
+
return m;
|
|
61
|
+
return { ...m, origin: 'inbox' };
|
|
62
|
+
}
|
|
63
|
+
/** An empty assistant message shaped so the next `message_update`/`message_end`
|
|
64
|
+
* (which replace, not append — see `reduce`'s `message_update` case) has a
|
|
65
|
+
* slot to land on. */
|
|
66
|
+
function placeholderAssistant() {
|
|
67
|
+
return { role: 'assistant', content: [] };
|
|
68
|
+
}
|
|
69
|
+
/** Seed state from the broker's catch-up snapshot.
|
|
70
|
+
*
|
|
71
|
+
* `welcome.snapshot` is the PERSISTED history (`snapshotMessages()` in the
|
|
72
|
+
* broker), not the live in-memory array. During an active turn — after
|
|
73
|
+
* `message_start`, before `message_end` — the in-flight assistant message may
|
|
74
|
+
* not be persisted yet, so a mid-stream `welcome` can report
|
|
75
|
+
* `state.isStreaming: true` with no trailing assistant in the snapshot.
|
|
76
|
+
* Wholesale-replacing in that case (as we always did) drops the in-flight
|
|
77
|
+
* turn: `streamingIndex` resets to null and the next `message_update`/
|
|
78
|
+
* `message_end` has nothing to land on (see `reduce`).
|
|
79
|
+
*
|
|
80
|
+
* So: idle snapshots replace wholesale exactly as before. Streaming snapshots
|
|
81
|
+
* reconcile — if the persisted history already ends in an assistant, adopt
|
|
82
|
+
* it as the streaming target; otherwise adopt the caller-supplied `previous`
|
|
83
|
+
* state's in-flight assistant (a cache-first render or an earlier live
|
|
84
|
+
* session) if one exists, or synthesize an empty placeholder. Either way the
|
|
85
|
+
* first `message_update` REPLACES that message wholesale, so no duplicate or
|
|
86
|
+
* dropped turn results. */
|
|
87
|
+
export function applySnapshot(snapshot, previous) {
|
|
88
|
+
const messages = snapshot.messages.map(tagInboxOrigin);
|
|
89
|
+
const toolGroupSummaryDetails = snapshotToolGroupSummaries(snapshot);
|
|
90
|
+
const toolGroupSummaries = summaryTexts(toolGroupSummaryDetails);
|
|
91
|
+
const isStreaming = snapshot.state?.isStreaming === true;
|
|
92
|
+
const workingActivity = snapshotWorkingActivity(snapshot);
|
|
93
|
+
if (!isStreaming) {
|
|
94
|
+
return {
|
|
95
|
+
messages,
|
|
96
|
+
streamingIndex: null,
|
|
97
|
+
executingToolIds: new Set(),
|
|
98
|
+
partialToolResults: new Map(),
|
|
99
|
+
isStreaming: false,
|
|
100
|
+
activity: null,
|
|
101
|
+
workingActivity,
|
|
102
|
+
queued: [],
|
|
103
|
+
toolGroupSummaries,
|
|
104
|
+
toolGroupSummaryDetails,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const lastIdx = messages.length - 1;
|
|
108
|
+
if (lastIdx >= 0 && roleOf(messages[lastIdx]) === 'assistant') {
|
|
109
|
+
// The in-flight assistant is already in the persisted snapshot — adopt it.
|
|
110
|
+
return {
|
|
111
|
+
messages,
|
|
112
|
+
streamingIndex: lastIdx,
|
|
113
|
+
executingToolIds: new Set(),
|
|
114
|
+
partialToolResults: new Map(),
|
|
115
|
+
isStreaming: true,
|
|
116
|
+
activity: workingActivity,
|
|
117
|
+
workingActivity,
|
|
118
|
+
queued: [],
|
|
119
|
+
toolGroupSummaries,
|
|
120
|
+
toolGroupSummaryDetails,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
// Not persisted yet — adopt the previous in-flight assistant if one was
|
|
124
|
+
// already rendered, else synthesize a placeholder.
|
|
125
|
+
const cachedAssistant = previous && previous.streamingIndex !== null ? previous.messages[previous.streamingIndex] : undefined;
|
|
126
|
+
const inFlightAssistant = cachedAssistant && roleOf(cachedAssistant) === 'assistant' ? cachedAssistant : placeholderAssistant();
|
|
127
|
+
const withInFlight = [...messages, inFlightAssistant];
|
|
128
|
+
return {
|
|
129
|
+
messages: withInFlight,
|
|
130
|
+
streamingIndex: withInFlight.length - 1,
|
|
131
|
+
executingToolIds: new Set(),
|
|
132
|
+
partialToolResults: new Map(),
|
|
133
|
+
isStreaming: true,
|
|
134
|
+
activity: workingActivity,
|
|
135
|
+
workingActivity,
|
|
136
|
+
queued: [],
|
|
137
|
+
toolGroupSummaries,
|
|
138
|
+
toolGroupSummaryDetails,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function snapshotWorkingActivity(snapshot) {
|
|
142
|
+
const activity = snapshot.workingActivity;
|
|
143
|
+
return typeof activity === 'string' && activity.trim() !== '' ? activity : DEFAULT_WORKING_ACTIVITY;
|
|
144
|
+
}
|
|
145
|
+
/** Apply the broker's random choice for the newly received user message. */
|
|
146
|
+
export function applyWorkingActivity(state, activity) {
|
|
147
|
+
const next = activity.trim() === '' ? DEFAULT_WORKING_ACTIVITY : activity;
|
|
148
|
+
return state.workingActivity === next ? state : { ...state, workingActivity: next };
|
|
149
|
+
}
|
|
150
|
+
/** Snapshot additions are optional across broker generations. Invalid entries
|
|
151
|
+
* are absent rather than adapted, so every surface receives the canonical
|
|
152
|
+
* structured summary or no summary at all. */
|
|
153
|
+
function snapshotToolGroupSummaries(snapshot) {
|
|
154
|
+
return normalizeToolGroupSummaryRecord(snapshot.toolGroupSummaries);
|
|
155
|
+
}
|
|
156
|
+
/** The web's compact recap is a presentation derived from canonical broker data. */
|
|
157
|
+
function summaryTexts(summaries) {
|
|
158
|
+
return Object.fromEntries(Object.entries(summaries).map(([key, summary]) => [key, summary.bullets.join(' · ')]));
|
|
159
|
+
}
|
|
160
|
+
/** Legacy browser-cache entries retain their prior presentation strings; live
|
|
161
|
+
* snapshots and frames always rebuild these from the structured source. */
|
|
162
|
+
function textToolGroupSummaries(value) {
|
|
163
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
164
|
+
return {};
|
|
165
|
+
return Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === 'string'));
|
|
166
|
+
}
|
|
167
|
+
/** Apply one broker-published structured summary without touching transcript ordering. */
|
|
168
|
+
export function applyToolGroupSummary(state, key, summary) {
|
|
169
|
+
const normalized = key.trim() === '' ? null : normalizeToolGroupSummary(summary);
|
|
170
|
+
if (normalized === null)
|
|
171
|
+
return state;
|
|
172
|
+
return {
|
|
173
|
+
...state,
|
|
174
|
+
toolGroupSummaries: { ...state.toolGroupSummaries, [key]: normalized.bullets.join(' · ') },
|
|
175
|
+
toolGroupSummaryDetails: { ...state.toolGroupSummaryDetails, [key]: normalized },
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function roleOf(m) {
|
|
179
|
+
return m.role ?? '';
|
|
180
|
+
}
|
|
181
|
+
// ---------------------------------------------------------------------------
|
|
182
|
+
// `!` bash execution (broker bash_start/bash_output/bash_end frames). These are
|
|
183
|
+
// broker control frames, NOT AgentSessionEvents, so the hook routes them here
|
|
184
|
+
// explicitly. They build a synthetic `bashExecution` message in the transcript
|
|
185
|
+
// that mirrors the one pi persists to context — rendered by MessageView.
|
|
186
|
+
// ---------------------------------------------------------------------------
|
|
187
|
+
/** Index of the most recent bashExecution message (the active `!` run), or null. */
|
|
188
|
+
function lastBashIndex(state) {
|
|
189
|
+
for (let i = state.messages.length - 1; i >= 0; i--) {
|
|
190
|
+
if (roleOf(state.messages[i]) === 'bashExecution')
|
|
191
|
+
return i;
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
export function bashStart(state, command, excludeFromContext) {
|
|
196
|
+
const msg = {
|
|
197
|
+
role: 'bashExecution',
|
|
198
|
+
command,
|
|
199
|
+
output: '',
|
|
200
|
+
exitCode: undefined,
|
|
201
|
+
cancelled: false,
|
|
202
|
+
truncated: false,
|
|
203
|
+
excludeFromContext,
|
|
204
|
+
timestamp: Date.now(),
|
|
205
|
+
};
|
|
206
|
+
return { ...state, messages: [...state.messages, msg] };
|
|
207
|
+
}
|
|
208
|
+
export function bashOutput(state, chunk) {
|
|
209
|
+
const idx = lastBashIndex(state);
|
|
210
|
+
if (idx === null)
|
|
211
|
+
return state;
|
|
212
|
+
const messages = [...state.messages];
|
|
213
|
+
const m = messages[idx];
|
|
214
|
+
messages[idx] = { ...m, output: `${m.output ?? ''}${chunk}` };
|
|
215
|
+
return { ...state, messages };
|
|
216
|
+
}
|
|
217
|
+
export function bashEnd(state, result) {
|
|
218
|
+
const idx = lastBashIndex(state);
|
|
219
|
+
if (idx === null)
|
|
220
|
+
return state;
|
|
221
|
+
const messages = [...state.messages];
|
|
222
|
+
const m = messages[idx];
|
|
223
|
+
messages[idx] = {
|
|
224
|
+
...m,
|
|
225
|
+
exitCode: result.exitCode,
|
|
226
|
+
cancelled: result.cancelled,
|
|
227
|
+
truncated: result.truncated,
|
|
228
|
+
fullOutputPath: result.fullOutputPath,
|
|
229
|
+
};
|
|
230
|
+
return { ...state, messages };
|
|
231
|
+
}
|
|
232
|
+
/** Apply one broker→client AGENT event (an `AgentSessionEvent`) to the transcript.
|
|
233
|
+
* Broker control frames (welcome/model_changed/error/…) are handled by the hook,
|
|
234
|
+
* NOT here — only pi agent events reach this function. Returns a NEW state object
|
|
235
|
+
* (with fresh `messages`/`executingToolIds` only when they actually change) so
|
|
236
|
+
* React re-renders correctly. */
|
|
237
|
+
export function reduce(state, event) {
|
|
238
|
+
switch (event.type) {
|
|
239
|
+
case 'agent_start':
|
|
240
|
+
return { ...state, isStreaming: true, activity: state.workingActivity };
|
|
241
|
+
case 'agent_end':
|
|
242
|
+
case 'agent_settled':
|
|
243
|
+
return {
|
|
244
|
+
...state,
|
|
245
|
+
isStreaming: false,
|
|
246
|
+
activity: null,
|
|
247
|
+
streamingIndex: null,
|
|
248
|
+
executingToolIds: state.executingToolIds.size ? new Set() : state.executingToolIds,
|
|
249
|
+
};
|
|
250
|
+
case 'message_start': {
|
|
251
|
+
// User messages arrive complete on message_start (no streaming deltas), so
|
|
252
|
+
// tagging here is sufficient — update/end only mutate the assistant message.
|
|
253
|
+
const tagged = tagInboxOrigin(event.message);
|
|
254
|
+
const messages = [...state.messages, tagged];
|
|
255
|
+
const isAssistant = roleOf(tagged) === 'assistant';
|
|
256
|
+
let partialToolResults = state.partialToolResults;
|
|
257
|
+
if (roleOf(tagged) === 'toolResult') {
|
|
258
|
+
const id = tagged.toolCallId;
|
|
259
|
+
if (typeof id === 'string' && partialToolResults.has(id)) {
|
|
260
|
+
const next = new Map(partialToolResults);
|
|
261
|
+
next.delete(id);
|
|
262
|
+
partialToolResults = next;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
...state,
|
|
267
|
+
messages,
|
|
268
|
+
partialToolResults,
|
|
269
|
+
streamingIndex: isAssistant ? messages.length - 1 : state.streamingIndex,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
case 'message_update': {
|
|
273
|
+
// Only assistant messages stream. Replace the in-progress message with the
|
|
274
|
+
// event's full `message`. If we attached mid-stream (no message_start seen),
|
|
275
|
+
// adopt the last message when it is the assistant being streamed.
|
|
276
|
+
let idx = state.streamingIndex;
|
|
277
|
+
if (idx === null) {
|
|
278
|
+
const last = state.messages.length - 1;
|
|
279
|
+
if (last >= 0 && roleOf(state.messages[last]) === 'assistant')
|
|
280
|
+
idx = last;
|
|
281
|
+
}
|
|
282
|
+
if (idx === null)
|
|
283
|
+
return state;
|
|
284
|
+
const messages = [...state.messages];
|
|
285
|
+
messages[idx] = event.message;
|
|
286
|
+
return { ...state, messages, streamingIndex: idx };
|
|
287
|
+
}
|
|
288
|
+
case 'message_end': {
|
|
289
|
+
if (state.streamingIndex === null)
|
|
290
|
+
return state;
|
|
291
|
+
const messages = [...state.messages];
|
|
292
|
+
messages[state.streamingIndex] = event.message;
|
|
293
|
+
return { ...state, messages, streamingIndex: null };
|
|
294
|
+
}
|
|
295
|
+
case 'tool_execution_start': {
|
|
296
|
+
const next = new Set(state.executingToolIds);
|
|
297
|
+
next.add(event.toolCallId);
|
|
298
|
+
return { ...state, executingToolIds: next };
|
|
299
|
+
}
|
|
300
|
+
case 'tool_execution_update': {
|
|
301
|
+
const next = new Map(state.partialToolResults);
|
|
302
|
+
next.set(event.toolCallId, toolResultFromExecution(event.toolCallId, event.toolName, event.partialResult, false));
|
|
303
|
+
return { ...state, partialToolResults: next };
|
|
304
|
+
}
|
|
305
|
+
case 'tool_execution_end': {
|
|
306
|
+
const nextExecuting = new Set(state.executingToolIds);
|
|
307
|
+
nextExecuting.delete(event.toolCallId);
|
|
308
|
+
const nextResults = new Map(state.partialToolResults);
|
|
309
|
+
nextResults.set(event.toolCallId, toolResultFromExecution(event.toolCallId, event.toolName, event.result, event.isError));
|
|
310
|
+
return { ...state, executingToolIds: nextExecuting, partialToolResults: nextResults };
|
|
311
|
+
}
|
|
312
|
+
case 'compaction_start':
|
|
313
|
+
return { ...state, activity: 'Compacting context…' };
|
|
314
|
+
case 'compaction_end':
|
|
315
|
+
return { ...state, activity: state.isStreaming ? state.workingActivity : null };
|
|
316
|
+
case 'auto_retry_start':
|
|
317
|
+
return {
|
|
318
|
+
...state,
|
|
319
|
+
activity: `Retrying (${event.attempt}/${event.maxAttempts}) in ${Math.ceil(event.delayMs / 1000)}s…`,
|
|
320
|
+
};
|
|
321
|
+
case 'auto_retry_end':
|
|
322
|
+
return { ...state, activity: state.isStreaming ? state.workingActivity : null };
|
|
323
|
+
case 'queue_update':
|
|
324
|
+
return { ...state, queued: [...event.steering, ...event.followUp] };
|
|
325
|
+
// turn_* / session_info_changed / thinking_level_changed — no transcript
|
|
326
|
+
// mutation in v1 (footer-only or covered by adjacent message events).
|
|
327
|
+
default:
|
|
328
|
+
return state;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function toolResultFromExecution(toolCallId, toolName, result, isError) {
|
|
332
|
+
const fields = typeof result === 'object' && result !== null ? result : {};
|
|
333
|
+
return {
|
|
334
|
+
role: 'toolResult',
|
|
335
|
+
toolCallId,
|
|
336
|
+
toolName,
|
|
337
|
+
...fields,
|
|
338
|
+
content: Array.isArray(fields.content) ? fields.content : [],
|
|
339
|
+
isError,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { createServer } from 'node:http';
|
|
3
|
+
import { existsSync, mkdtempSync, realpathSync, rmSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { claimExists } from '#core/human/claim';
|
|
7
|
+
import { ticketDir } from '#core/human/root';
|
|
8
|
+
import { cancelTicket, submitDeck, takeoverAndCompleteDeck } from '#core/human/tickets';
|
|
9
|
+
import { InboxController } from '../../controller.js';
|
|
10
|
+
const key = (part = {}) => ({ ctrl: false, meta: false, upArrow: false, downArrow: false, leftArrow: false, rightArrow: false, wordLeft: false, wordRight: false, home: false, end: false, pageUp: false, pageDown: false, del: false, return: false, newline: false, escape: false, tab: false, backspace: false, ...part });
|
|
11
|
+
function fakeHost() {
|
|
12
|
+
let closed = false;
|
|
13
|
+
const cleanup = [];
|
|
14
|
+
const handle = {
|
|
15
|
+
close() {
|
|
16
|
+
if (closed)
|
|
17
|
+
return;
|
|
18
|
+
closed = true;
|
|
19
|
+
for (const fn of cleanup)
|
|
20
|
+
void fn();
|
|
21
|
+
cleanup.length = 0;
|
|
22
|
+
},
|
|
23
|
+
invalidate() { },
|
|
24
|
+
onClose(fn) {
|
|
25
|
+
if (!closed)
|
|
26
|
+
cleanup.push(fn);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
capabilities: { remote: false, canFocusNode: false, selfPane: undefined },
|
|
31
|
+
mount() { return handle; },
|
|
32
|
+
notice() { },
|
|
33
|
+
suspendForChild() { return () => { }; },
|
|
34
|
+
focusNode: async () => false,
|
|
35
|
+
pickReviewFile: async () => null,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const makeController = (options) => new InboxController({ host: fakeHost(), onDirty: () => { }, onClosed: () => { }, ...options });
|
|
39
|
+
const tick = () => new Promise((resolve) => setImmediate(resolve));
|
|
40
|
+
function select(controller, dir) {
|
|
41
|
+
const count = controller.snapshot().items.length;
|
|
42
|
+
const matches = () => {
|
|
43
|
+
const selected = controller.snapshot().selectedDir;
|
|
44
|
+
return selected !== undefined && realpathSync(selected) === realpathSync(dir);
|
|
45
|
+
};
|
|
46
|
+
for (let i = 0; i < count && !matches(); i++)
|
|
47
|
+
controller.handleKey('j', key());
|
|
48
|
+
assert.ok(matches(), `expected ${dir} to be selectable`);
|
|
49
|
+
}
|
|
50
|
+
async function waitFor(predicate, message) {
|
|
51
|
+
const deadline = Date.now() + 1_000;
|
|
52
|
+
while (!predicate()) {
|
|
53
|
+
if (Date.now() >= deadline)
|
|
54
|
+
throw new Error(message);
|
|
55
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// The controller answers a ticket by crossing the daemon `/resolve` seam. This
|
|
59
|
+
// fake daemon plays back each failure the seam can return so the controller's
|
|
60
|
+
// unmount-or-retry decision is exercised against a real socket.
|
|
61
|
+
let mode = 'success';
|
|
62
|
+
async function startDaemon() {
|
|
63
|
+
const server = createServer(async (req, res) => {
|
|
64
|
+
if (!req.url?.endsWith('/resolve')) {
|
|
65
|
+
res.statusCode = 404;
|
|
66
|
+
res.end(JSON.stringify({ error: { code: 'not_found', message: 'not found' } }));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (mode === 'unreachable') {
|
|
70
|
+
res.statusCode = 503;
|
|
71
|
+
res.end(JSON.stringify({ error: { code: 'daemon_unavailable', message: 'offline' } }));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const body = await new Promise((resolve) => {
|
|
75
|
+
let text = '';
|
|
76
|
+
req.on('data', (chunk) => { text += chunk; });
|
|
77
|
+
req.on('end', () => resolve(text));
|
|
78
|
+
});
|
|
79
|
+
const nodeId = req.url.split('/').at(-2);
|
|
80
|
+
if (mode === 'already_resolved') {
|
|
81
|
+
res.statusCode = 409;
|
|
82
|
+
res.end(JSON.stringify({ error: { code: 'ticket_already_resolved', message: 'ticket already resolved' } }));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const request = JSON.parse(body);
|
|
86
|
+
if (request.responses === undefined)
|
|
87
|
+
throw new Error('expected a deck resolution');
|
|
88
|
+
takeoverAndCompleteDeck(ticketDir(nodeId), request.responses, { host: 'daemon', pid: 1 });
|
|
89
|
+
if (mode === 'delivery_failed') {
|
|
90
|
+
res.statusCode = 500;
|
|
91
|
+
res.end(JSON.stringify({ error: { code: 'delivery_failed', message: 'final report delivery failed' } }));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
res.end(JSON.stringify({ delivered: true, kind: 'deck' }));
|
|
95
|
+
});
|
|
96
|
+
await new Promise((resolve) => server.listen(join(process.env['CRTR_HOME'], 'crtrd.sock'), resolve));
|
|
97
|
+
return server;
|
|
98
|
+
}
|
|
99
|
+
const temp = mkdtempSync(join(tmpdir(), 'crtr-inbox-controller-'));
|
|
100
|
+
process.env['CRTR_HOME'] = temp;
|
|
101
|
+
const server = await startDaemon();
|
|
102
|
+
const deck = (id) => ({ title: id, source: { blockedSince: new Date().toISOString(), sessionName: 'Release planning', nodeId: 'node-private-123' }, interactions: [{ id: 'answer', title: 'Answer', subtitle: 'Answer requires your attention.', options: [{ id: 'yes', label: 'Yes', shortcut: 'y' }] }] });
|
|
103
|
+
try {
|
|
104
|
+
const first = submitDeck({ dir: ticketDir('first'), deck: deck('first') });
|
|
105
|
+
const active = makeController({ cols: 100, rows: 24 });
|
|
106
|
+
active.activate();
|
|
107
|
+
active.handleKey('y', key());
|
|
108
|
+
await waitFor(() => existsSync(join(first.dir, 'response.json')), 'a deck resolution crosses the controller daemon seam');
|
|
109
|
+
await waitFor(() => active.snapshot().screen === 'list', 'a successful daemon resolution unmounts the ticket');
|
|
110
|
+
active.close();
|
|
111
|
+
// A ticket arriving mid-edit must not move selection or clobber the freetext
|
|
112
|
+
// the user is part way through typing.
|
|
113
|
+
const editing = submitDeck({ dir: ticketDir('editing'), deck: { title: 'Editing', interactions: [{ id: 'note', title: 'Notes', subtitle: 'Notes require your attention.', options: [], allowFreetext: true }] } });
|
|
114
|
+
const editingController = makeController({ cols: 100, rows: 24 });
|
|
115
|
+
select(editingController, editing.dir);
|
|
116
|
+
editingController.activate();
|
|
117
|
+
editingController.handleKey('r', key());
|
|
118
|
+
for (const char of 'draft')
|
|
119
|
+
editingController.handleKey(char, key());
|
|
120
|
+
submitDeck({ dir: ticketDir('arrival'), deck: deck('arrival') });
|
|
121
|
+
editingController.rescan();
|
|
122
|
+
assert.equal(realpathSync(editingController.snapshot().selectedDir), realpathSync(editing.dir), 'arrival does not steal active selection');
|
|
123
|
+
assert.equal(editingController.snapshot().inputBuffer, 'draft', 'arrival does not alter freetext input');
|
|
124
|
+
editingController.close();
|
|
125
|
+
cancelTicket(editing.dir, { reason: 'done editing' });
|
|
126
|
+
const already = submitDeck({ dir: ticketDir('already'), deck: deck('already') });
|
|
127
|
+
const alreadyController = makeController({ cols: 100, rows: 24 });
|
|
128
|
+
alreadyController.activate();
|
|
129
|
+
cancelTicket(already.dir, { reason: 'resolved elsewhere' });
|
|
130
|
+
mode = 'already_resolved';
|
|
131
|
+
alreadyController.handleKey('y', key());
|
|
132
|
+
await waitFor(() => alreadyController.snapshot().screen === 'list', 'already_resolved unmounts instead of offering a stale resubmit');
|
|
133
|
+
assert.equal(claimExists(already.dir), true, 'already_resolved retains the daemon-taken claim');
|
|
134
|
+
alreadyController.close();
|
|
135
|
+
const delivery = submitDeck({ dir: ticketDir('delivery'), deck: deck('delivery') });
|
|
136
|
+
mode = 'delivery_failed';
|
|
137
|
+
const deliveryController = makeController({ cols: 100, rows: 24 });
|
|
138
|
+
deliveryController.activate();
|
|
139
|
+
deliveryController.handleKey('y', key());
|
|
140
|
+
await waitFor(() => deliveryController.snapshot().screen === 'list', 'delivery_failed unmounts because the canonical answer is already recorded');
|
|
141
|
+
assert.equal(existsSync(join(delivery.dir, 'response.json')), true, 'delivery_failed still leaves the canonical response on disk');
|
|
142
|
+
deliveryController.close();
|
|
143
|
+
const retry = submitDeck({ dir: ticketDir('retry'), deck: deck('retry') });
|
|
144
|
+
mode = 'unreachable';
|
|
145
|
+
const retryController = makeController({ cols: 100, rows: 24 });
|
|
146
|
+
retryController.activate();
|
|
147
|
+
retryController.handleKey('y', key());
|
|
148
|
+
await tick();
|
|
149
|
+
assert.equal(retryController.snapshot().screen, 'detail', 'unreachable keeps the mounted answer available for retry');
|
|
150
|
+
assert.equal(existsSync(join(retry.dir, 'response.json')), false, 'unreachable does not manufacture a local completion');
|
|
151
|
+
retryController.close();
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
server.closeAllConnections();
|
|
155
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
156
|
+
rmSync(temp, { recursive: true, force: true });
|
|
157
|
+
delete process.env['CRTR_HOME'];
|
|
158
|
+
}
|
|
159
|
+
console.log('inbox controller tests passed');
|