@north-light/crouter 0.3.172 → 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} +106 -177
- 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 +55 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +60 -0
- 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,415 @@
|
|
|
1
|
+
// `crtr node` lifecycle and durable configuration commands.
|
|
2
|
+
import { defineBranch, defineLeaf } from '../../core/command.js';
|
|
3
|
+
import { InputError } from '../../core/io.js';
|
|
4
|
+
import { cliClient, getNodeOrNull, rethrowAsCliError } from '../api-client.js';
|
|
5
|
+
import { nodeReviveLeaf } from '../node-lifecycle-revive.js';
|
|
6
|
+
import { assertKind, kindsStateBlock } from './create.js';
|
|
7
|
+
import { closePane, paneExists, respawnPaneSync, viewerEnv, viewerPaneOf, nodeInPane } from '../surface/node/placement.js';
|
|
8
|
+
const nodeRecycle = defineLeaf({
|
|
9
|
+
name: 'recycle',
|
|
10
|
+
description: 'finish the agent in your pane + recycle it into a fresh root',
|
|
11
|
+
whenToUse: 'you are at an agent\'s pane and done with it: finish it cleanly and recycle the pane in one move — push its last message as a final report to everyone waiting on it, mark it done, then boot a fresh crtr root in the same pane to keep working. The human-driver way to end an agent and immediately start over in place. Use `node lifecycle demote` instead to put it on a finishing track IN PLACE (flip terminal, keep it running) without ending it now, `node lifecycle close` to tear a node and its subtree down WITHOUT finishing (no report, revivable), and `push final` when the agent should finish ITSELF from inside its own turn',
|
|
12
|
+
help: {
|
|
13
|
+
name: 'node lifecycle recycle',
|
|
14
|
+
summary: 'finish the agent in your current pane and recycle the pane — push its last message as a final report to everyone waiting on it, mark it done, then boot a fresh crtr root in the same pane',
|
|
15
|
+
params: [
|
|
16
|
+
{ kind: 'flag', name: 'node', type: 'string', required: false, constraint: 'Node to finish. Defaults to the node occupying --pane (or your current pane).' },
|
|
17
|
+
{ kind: 'flag', name: 'pane', type: 'string', required: false, constraint: 'tmux pane id to recycle. Defaults to $TMUX_PANE / your current pane. The Alt+C menu passes this for you.' },
|
|
18
|
+
],
|
|
19
|
+
output: [
|
|
20
|
+
{ name: 'recycled', type: 'boolean', required: true, constraint: 'True when the pane was recycled into a fresh root.' },
|
|
21
|
+
{ name: 'node_id', type: 'string', required: false, constraint: 'The finished node.' },
|
|
22
|
+
{ name: 'finalized', type: 'boolean', required: false, constraint: 'True when a final report was pushed to its subscribers.' },
|
|
23
|
+
{ name: 'delivered', type: 'number', required: false, constraint: 'How many subscribers/managers received the final report.' },
|
|
24
|
+
{ name: 'new_root', type: 'string', required: false, constraint: 'The fresh root node booted into the pane.' },
|
|
25
|
+
],
|
|
26
|
+
outputKind: 'object',
|
|
27
|
+
effects: ['Pushes a final report from the node (fans out to all subscribers) and marks it done.', 'Kills the agent\'s pi and respawns a fresh resident root in the same tmux pane.'],
|
|
28
|
+
},
|
|
29
|
+
run: async (input) => {
|
|
30
|
+
const pane = input['pane'] ?? process.env['TMUX_PANE'];
|
|
31
|
+
let id = input['node'];
|
|
32
|
+
if (id === undefined || id === '') {
|
|
33
|
+
// Derive the node from the pane: which node's window holds it?
|
|
34
|
+
id = nodeInPane(pane);
|
|
35
|
+
}
|
|
36
|
+
if (id === undefined || id === '') {
|
|
37
|
+
throw new InputError({ error: 'no_node', message: 'no node found in this pane to finish', next: 'Pass --node <id>, or run from inside the agent\'s pane.' });
|
|
38
|
+
}
|
|
39
|
+
const detail = await cliClient()
|
|
40
|
+
.getNode(id)
|
|
41
|
+
.catch((err) => rethrowAsCliError(err, 'List nodes with `crtr node inspect list`.'));
|
|
42
|
+
// The server finalizes the node + spawns a fresh root (pane-less); the local
|
|
43
|
+
// tail re-execs the caller's pane onto a fresh `crtr` root so the human keeps
|
|
44
|
+
// working in place.
|
|
45
|
+
const recycled = await cliClient().recycleNode(id).catch(rethrowAsCliError);
|
|
46
|
+
const newRoot = recycled.node_id;
|
|
47
|
+
let paneRecycled = false;
|
|
48
|
+
if (pane !== undefined && pane !== '') {
|
|
49
|
+
paneRecycled = respawnPaneSync({ pane, cwd: detail.cwd, env: viewerEnv(), command: 'crtr' });
|
|
50
|
+
}
|
|
51
|
+
return { recycled: paneRecycled, node_id: id, finalized: true, delivered: undefined, new_root: newRoot };
|
|
52
|
+
},
|
|
53
|
+
render: (r) => {
|
|
54
|
+
if (r['recycled'] !== true) {
|
|
55
|
+
// A broker recycle that finalized + spawned a fresh root but whose new
|
|
56
|
+
// broker never served its socket: the state DID change (node finished, root
|
|
57
|
+
// born), only the viewer re-attach failed — say so, don't call it a no-op.
|
|
58
|
+
if (r['finalized'] === true && r['new_root']) {
|
|
59
|
+
return `Finished ${r['node_id']} and spawned a fresh broker root (${r['new_root']}), but its viewer did not attach — the new broker did not come up. Re-focus the root to view it.`;
|
|
60
|
+
}
|
|
61
|
+
return `Recycle failed for ${r['node_id'] ?? '?'} — not in tmux, or no agent in this pane.`;
|
|
62
|
+
}
|
|
63
|
+
const lines = [`Recycled the pane — finished ${r['node_id']}.`, `- finalized: ${r['finalized']}`];
|
|
64
|
+
if (r['finalized'] === true)
|
|
65
|
+
lines.push(`- delivered: ${r['delivered']}`);
|
|
66
|
+
if (r['new_root'])
|
|
67
|
+
lines.push(`- new root: ${r['new_root']}`);
|
|
68
|
+
return lines.join('\n');
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// node lifecycle close — close a node + cascade-cancel its exclusive subtree (Alt+C → x)
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
const nodeClose = defineLeaf({
|
|
75
|
+
name: 'close',
|
|
76
|
+
description: 'close a node + cascade-cancel its exclusive subtree (revivable)',
|
|
77
|
+
whenToUse: 'you want to tear a node down WITHOUT finishing it, cascade-cancelling every descendant it exclusively owns: abandoning a line of work, killing a stuck or wrong-turn subtree, clearing a branch you no longer need. Windows die but nothing is deleted — each closed node keeps its pi session and can be revived later (`node lifecycle revive`). Use `node lifecycle recycle` instead to FINISH the agent in your pane with a final report, and `push final` when a worker should end its own work normally (Alt+C → x)',
|
|
78
|
+
help: {
|
|
79
|
+
name: 'node lifecycle close',
|
|
80
|
+
summary: 'close a node and cascade-cancel its subtree — kill its tmux window plus those of every descendant it EXCLUSIVELY owns (down the subscribes_to spine), mark them all canceled, and leave each a notice it reads on resume. A descendant still subscribed to by a manager outside the subtree is left running. Nothing is deleted: every closed node keeps its pi session and can be revived later (`crtr node lifecycle revive`)',
|
|
81
|
+
params: [
|
|
82
|
+
{ kind: 'flag', name: 'node', type: 'string', required: false, constraint: 'Node to close. Defaults to the node occupying --pane (or your current pane).' },
|
|
83
|
+
{ kind: 'flag', name: 'pane', type: 'string', required: false, constraint: 'tmux pane id whose node to close. Defaults to $TMUX_PANE / your current pane. The Alt+C menu passes this for you.' },
|
|
84
|
+
],
|
|
85
|
+
output: [
|
|
86
|
+
{ name: 'closed', type: 'boolean', required: true, constraint: 'True when the node (and its exclusive subtree) was closed.' },
|
|
87
|
+
{ name: 'node_id', type: 'string', required: false, constraint: 'The node that was closed — the cascade root.' },
|
|
88
|
+
{ name: 'count', type: 'number', required: false, constraint: 'How many nodes were closed (root + cascaded descendants).' },
|
|
89
|
+
{ name: 'closed_ids', type: 'string[]', required: false, constraint: 'All closed node ids, kill order (leaves first, root last).' },
|
|
90
|
+
{ name: 'spared', type: 'string[]', required: false, constraint: 'Descendants left alive because a manager outside the subtree still subscribes to them.' },
|
|
91
|
+
],
|
|
92
|
+
outputKind: 'object',
|
|
93
|
+
effects: [
|
|
94
|
+
'Marks the node and its exclusive descendants `canceled` and clears intent (the daemon never revives a canceled node).',
|
|
95
|
+
'Kills each closed node\'s tmux window; their pi sessions and canvas edges persist for a later revive.',
|
|
96
|
+
'Appends a cancellation notice to each closed node\'s inbox, surfaced on its next resume.',
|
|
97
|
+
],
|
|
98
|
+
},
|
|
99
|
+
run: async (input) => {
|
|
100
|
+
const pane = input['pane'] ?? process.env['TMUX_PANE'];
|
|
101
|
+
let id = input['node'];
|
|
102
|
+
if (id === undefined || id === '')
|
|
103
|
+
id = nodeInPane(pane);
|
|
104
|
+
if (id === undefined || id === '') {
|
|
105
|
+
throw new InputError({ error: 'no_node', message: 'no node found in this pane to close', next: 'Pass --node <id>, or run from inside the agent\'s pane.' });
|
|
106
|
+
}
|
|
107
|
+
const res = await cliClient()
|
|
108
|
+
.closeNode(id)
|
|
109
|
+
.catch((err) => rethrowAsCliError(err, 'List nodes with `crtr node inspect list`.'));
|
|
110
|
+
return { closed: true, node_id: res.root, count: res.closed.length, closed_ids: res.closed, spared: res.spared };
|
|
111
|
+
},
|
|
112
|
+
render: (r) => {
|
|
113
|
+
if (r['closed'] !== true)
|
|
114
|
+
return 'Close failed — no node found in this pane to close.';
|
|
115
|
+
const spared = r['spared']?.length ?? 0;
|
|
116
|
+
return `Closed ${r['node_id']} and its exclusive subtree — ${r['count']} node(s) closed${spared > 0 ? `, ${spared} spared (still managed from outside the subtree)` : ''}.`;
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
// node config — reconfigure a node's settings headlessly (model/lifecycle/kind/mode/name)
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
export const nodeConfig = defineLeaf({
|
|
123
|
+
name: 'config',
|
|
124
|
+
description: 'reconfigure a node\'s settings headlessly — model, lifecycle (terminal/resident), kind, mode, name',
|
|
125
|
+
whenToUse: 'you want to reconfigure a node\'s settings headlessly after spawn — swap its model/provider, flip it terminal↔resident (interactable), respecialize its kind, switch base↔orchestrator mode, or rename it — without opening its viewer. The durable attribute setter; reuses the same recipes a revive reads. Use `node promote` for the opinionated self-promotion path, and `node lifecycle` for teardown actions (recycle/close/demote).',
|
|
126
|
+
help: {
|
|
127
|
+
name: 'node config',
|
|
128
|
+
summary: 'reconfigure a node\'s settings headlessly — model, lifecycle, kind, mode, name',
|
|
129
|
+
params: [
|
|
130
|
+
{ kind: 'flag', name: 'node', type: 'string', required: false, constraint: 'Target node id. Defaults to the node in --pane, else CRTR_NODE_ID.' },
|
|
131
|
+
{ kind: 'flag', name: 'pane', type: 'string', required: false, constraint: 'tmux pane id to resolve the node from. Defaults to $TMUX_PANE.' },
|
|
132
|
+
{ kind: 'flag', name: 'model', type: 'string', required: false, constraint: 'Model spec: exact provider/id, capability tier (ultra|strong|medium|light), family alias (opus|sonnet|haiku), or a free-text substring when the broker is live. Dormant nodes require a provider/id, tier, or alias.' },
|
|
133
|
+
{ kind: 'flag', name: 'lifecycle', type: 'enum', choices: ['terminal', 'resident'], required: false, constraint: 'Set lifecycle headlessly without closing the viewer. terminal owes a final and reaps when done; resident stays interactable and wakes on inbox/human.' },
|
|
134
|
+
{ kind: 'flag', name: 'kind', type: 'string', required: false, constraint: 'Persona kind. The <kinds> list below names every top-level installable kind and when to use each; a sub-kind (e.g. plan/reviewers/security) is valid too by exact path but not listed here.' },
|
|
135
|
+
{ kind: 'flag', name: 'mode', type: 'enum', choices: ['base', 'orchestrator'], required: false, constraint: 'Set persona mode headlessly. base is hands-on; orchestrator holds a roadmap and delegates. orchestrator seeds a roadmap scaffold if absent.' },
|
|
136
|
+
{ kind: 'flag', name: 'name', type: 'string', required: false, constraint: 'Rename the node; if the node has a live window, also rename that viewer window.' },
|
|
137
|
+
],
|
|
138
|
+
output: [
|
|
139
|
+
{ name: 'node_id', type: 'string', required: true, constraint: 'The reconfigured node.' },
|
|
140
|
+
{ name: 'model', type: 'string', required: false, constraint: 'The resolved model, present only when --model changed it.' },
|
|
141
|
+
{ name: 'lifecycle', type: 'string', required: false, constraint: 'The new lifecycle, present only when --lifecycle changed it.' },
|
|
142
|
+
{ name: 'kind', type: 'string', required: false, constraint: 'The new kind, present only when --kind changed it.' },
|
|
143
|
+
{ name: 'mode', type: 'string', required: false, constraint: 'The new mode, present only when --mode changed it.' },
|
|
144
|
+
{ name: 'name', type: 'string', required: false, constraint: 'The new name, present only when --name changed it.' },
|
|
145
|
+
{ name: 'applied', type: 'string[]', required: false, constraint: 'The fields that changed, in application order.' },
|
|
146
|
+
],
|
|
147
|
+
outputKind: 'object',
|
|
148
|
+
effects: [
|
|
149
|
+
'Model change first: live broker switches over its socket; dormant node persists the durable recipe (model_override + launch.model).',
|
|
150
|
+
'Kind, mode, and lifecycle changes rebuild the launch spec from the fresh node meta; setting mode to orchestrator seeds a roadmap scaffold if absent.',
|
|
151
|
+
'Name changes update the row and, when the node already has a live window, rename that viewer window to the new full name.',
|
|
152
|
+
],
|
|
153
|
+
dynamicState: () => kindsStateBlock(),
|
|
154
|
+
},
|
|
155
|
+
run: async (input) => {
|
|
156
|
+
const pane = input['pane'] ?? process.env['TMUX_PANE'];
|
|
157
|
+
const nodeId = await resolveLifecycleNode(input, pane);
|
|
158
|
+
// Validate the model spec's SHAPE client-side (the server owns the
|
|
159
|
+
// live/dormant resolution branch); build the patch from the flags set. The
|
|
160
|
+
// kind is validated against the caller's installed personas here for the
|
|
161
|
+
// clean listing error, and re-validated server-side against the TARGET
|
|
162
|
+
// node's scope as a backstop.
|
|
163
|
+
const modelSpec = input['model']?.trim();
|
|
164
|
+
if (modelSpec === '') {
|
|
165
|
+
throw new InputError({ error: 'empty_spec', message: 'a model spec is required', field: 'model', next: 'Pass a `provider/id`, a tier (ultra|strong|medium|light), an alias (opus|sonnet|haiku), or a substring.' });
|
|
166
|
+
}
|
|
167
|
+
const kindSpec = input['kind']?.trim();
|
|
168
|
+
const lifecycleSpec = input['lifecycle']?.trim();
|
|
169
|
+
const modeSpec = input['mode']?.trim();
|
|
170
|
+
const nameSpec = input['name'];
|
|
171
|
+
if (kindSpec !== undefined)
|
|
172
|
+
assertKind(kindSpec);
|
|
173
|
+
if (lifecycleSpec !== undefined && lifecycleSpec.toLowerCase() !== 'terminal' && lifecycleSpec.toLowerCase() !== 'resident') {
|
|
174
|
+
throw new InputError({ error: 'bad_lifecycle', message: `invalid lifecycle: ${lifecycleSpec}`, field: 'lifecycle', next: 'Pass `terminal` or `resident`.' });
|
|
175
|
+
}
|
|
176
|
+
if (modeSpec !== undefined && modeSpec.toLowerCase() !== 'base' && modeSpec.toLowerCase() !== 'orchestrator') {
|
|
177
|
+
throw new InputError({ error: 'bad_mode', message: `invalid mode: ${modeSpec}`, field: 'mode', next: 'Pass `base` or `orchestrator`.' });
|
|
178
|
+
}
|
|
179
|
+
const applied = [];
|
|
180
|
+
const patch = {};
|
|
181
|
+
if (modelSpec !== undefined) {
|
|
182
|
+
patch.model = modelSpec;
|
|
183
|
+
applied.push('model');
|
|
184
|
+
}
|
|
185
|
+
if (kindSpec !== undefined) {
|
|
186
|
+
patch.kind = kindSpec;
|
|
187
|
+
applied.push('kind');
|
|
188
|
+
}
|
|
189
|
+
if (lifecycleSpec !== undefined) {
|
|
190
|
+
patch.lifecycle = lifecycleSpec.toLowerCase();
|
|
191
|
+
applied.push('lifecycle');
|
|
192
|
+
}
|
|
193
|
+
if (modeSpec !== undefined) {
|
|
194
|
+
patch.mode = modeSpec.toLowerCase();
|
|
195
|
+
applied.push('mode');
|
|
196
|
+
}
|
|
197
|
+
if (nameSpec !== undefined) {
|
|
198
|
+
patch.name = nameSpec;
|
|
199
|
+
applied.push('name');
|
|
200
|
+
}
|
|
201
|
+
if (applied.length === 0) {
|
|
202
|
+
throw new InputError({ error: 'no_change', message: 'no config changes requested', next: 'Pass at least one of --model, --lifecycle, --kind, --mode, --name.' });
|
|
203
|
+
}
|
|
204
|
+
const detail = await cliClient()
|
|
205
|
+
.patchConfig(nodeId, patch)
|
|
206
|
+
.catch((err) => rethrowAsCliError(err, 'List nodes with `crtr node inspect list`.'));
|
|
207
|
+
const result = { node_id: nodeId, applied };
|
|
208
|
+
if (applied.includes('model'))
|
|
209
|
+
result.model = detail.model_override ?? modelSpec;
|
|
210
|
+
if (applied.includes('lifecycle'))
|
|
211
|
+
result.lifecycle = detail.lifecycle;
|
|
212
|
+
if (applied.includes('kind'))
|
|
213
|
+
result.kind = detail.kind;
|
|
214
|
+
if (applied.includes('mode'))
|
|
215
|
+
result.mode = detail.mode;
|
|
216
|
+
if (applied.includes('name'))
|
|
217
|
+
result.name = detail.name;
|
|
218
|
+
return result;
|
|
219
|
+
},
|
|
220
|
+
render: (r) => {
|
|
221
|
+
const bits = [];
|
|
222
|
+
if (r['model'] !== undefined)
|
|
223
|
+
bits.push(`model=${r['model']}`);
|
|
224
|
+
if (r['lifecycle'] !== undefined)
|
|
225
|
+
bits.push(`lifecycle=${r['lifecycle']}`);
|
|
226
|
+
if (r['kind'] !== undefined)
|
|
227
|
+
bits.push(`kind=${r['kind']}`);
|
|
228
|
+
if (r['mode'] !== undefined)
|
|
229
|
+
bits.push(`mode=${r['mode']}`);
|
|
230
|
+
if (r['name'] !== undefined)
|
|
231
|
+
bits.push(`name=${r['name']}`);
|
|
232
|
+
return `Configured ${r['node_id']} — ${bits.join(', ')}`;
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
export const nodePromote = defineLeaf({
|
|
236
|
+
name: 'promote',
|
|
237
|
+
description: 'become an orchestrator of a chosen kind',
|
|
238
|
+
whenToUse: 'the remaining work contains independent units that can run in parallel, and the task is large enough that coordinating and integrating them will materially improve intelligence, productivity, or elapsed throughput. Become a long-lived, roadmap-holding orchestrator whose primary job is steering those children across refreshes (`node yield`). Keep sequential or tightly coupled work in base mode even when it spans phases or context windows; spawning one helper does not itself require promotion',
|
|
239
|
+
tier: 'important',
|
|
240
|
+
help: {
|
|
241
|
+
name: 'node promote',
|
|
242
|
+
summary: 'promote yourself to an orchestrator when worthwhile parallel delegation should make coordination your primary job; task duration, sequential phases, or one helper do not qualify. Mode only — lifecycle stays as-is unless you pass --resident',
|
|
243
|
+
params: [
|
|
244
|
+
{ kind: 'flag', name: 'kind', type: 'string', required: false, constraint: 'Specialize as this kind of orchestrator. The <kinds> list below names every top-level installable kind and when to use each; a sub-kind (e.g. plan/reviewers/security) is valid too by exact path but not listed here. For an exact composed persona list, use `crtr sys prompt-review --list --kind <kind>` with the target kind. Defaults to your current kind. Promoting from a generic kind? CHOOSE a concrete one — it sets the orchestrator persona you revive into.' },
|
|
245
|
+
{ kind: 'flag', name: 'resident', type: 'bool', required: false, constraint: 'ALSO flip lifecycle→resident: make the node interactable — it stays dormant, woken by inbox/human, and is never forced to submit a final. Omit to stay terminal/orchestrator (delegates + holds a roadmap, but still owes a final up the spine and reaps when done).' },
|
|
246
|
+
{ kind: 'flag', name: 'model', type: 'enum', choices: ['ultra', 'strong'], required: false, constraint: 'Change the model you run on, by capability tier: `ultra` (frontier — reserve for high-taste judgment or enormous work: speccing, planning something large, e2e-testing something hard to test) or `strong` (opus — regular dev work). Omit to keep your current model. An orchestrator steering work is never weaker than opus, so these are the only two choices; the change is durable across future revives.' },
|
|
247
|
+
{ kind: 'flag', name: 'node', type: 'string', required: false, constraint: 'Node to promote. Defaults to the caller (CRTR_NODE_ID).' },
|
|
248
|
+
],
|
|
249
|
+
output: [
|
|
250
|
+
{ name: 'node_id', type: 'string', required: true, constraint: 'The promoted node.' },
|
|
251
|
+
{ name: 'kind', type: 'string', required: true, constraint: 'The kind it now orchestrates as.' },
|
|
252
|
+
{ name: 'mode', type: 'string', required: true, constraint: 'Now "orchestrator".' },
|
|
253
|
+
{ name: 'model', type: 'string', required: false, constraint: 'The model tier it now runs on, present only when you changed it with --model.' },
|
|
254
|
+
{ name: 'lifecycle', type: 'string', required: true, constraint: '"resident" if you passed --resident, else unchanged (typically "terminal").' },
|
|
255
|
+
{ name: 'roadmap_written', type: 'boolean', required: true, constraint: 'True if a roadmap scaffold was seeded by this call.' },
|
|
256
|
+
{ name: 'roadmap_path', type: 'string', required: true, constraint: 'Absolute path to your roadmap doc (context/roadmap.md) — edit it to author your plan.' },
|
|
257
|
+
{ name: 'goal_path', type: 'string', required: true, constraint: 'Absolute path to your goal doc (context/initial-prompt.md) — the mandate you were spawned with.' },
|
|
258
|
+
],
|
|
259
|
+
dynamicState: () => kindsStateBlock(),
|
|
260
|
+
outputKind: 'object',
|
|
261
|
+
effects: ['Flips mode→orchestrator + kind→chosen (lifecycle unchanged unless --resident, which also flips lifecycle→resident); --model durably pins the model tier; rewrites the launch spec to that kind\'s orchestrator persona; seeds context/roadmap.md scaffold if absent.', 'Your new-role guidance is injected automatically at the turn boundary by the persona injector — the command no longer returns it.'],
|
|
262
|
+
},
|
|
263
|
+
run: async (input) => {
|
|
264
|
+
const id = input['node'] ?? process.env['CRTR_NODE_ID'];
|
|
265
|
+
if (id === undefined || id === '')
|
|
266
|
+
throw new InputError({ error: 'no_node', message: 'no node to promote (set CRTR_NODE_ID or pass --node)', next: 'Run from inside a node, or pass --node <id>.' });
|
|
267
|
+
const kind = input['kind'];
|
|
268
|
+
if (kind !== undefined)
|
|
269
|
+
assertKind(kind);
|
|
270
|
+
const model = input['model'];
|
|
271
|
+
const resident = input['resident'] === true;
|
|
272
|
+
const detail = await cliClient()
|
|
273
|
+
.promoteNode(id, { ...(kind !== undefined ? { kind } : {}), ...(resident ? { resident: true } : {}), ...(model !== undefined ? { model } : {}) })
|
|
274
|
+
.catch((err) => rethrowAsCliError(err));
|
|
275
|
+
return {
|
|
276
|
+
node_id: detail.node_id,
|
|
277
|
+
kind: detail.kind,
|
|
278
|
+
mode: detail.mode,
|
|
279
|
+
lifecycle: detail.lifecycle,
|
|
280
|
+
...(model !== undefined && detail.model_override != null ? { model: detail.model_override } : {}),
|
|
281
|
+
roadmap_written: detail.roadmap_written ?? false,
|
|
282
|
+
roadmap_path: detail.roadmap_path ?? '',
|
|
283
|
+
goal_path: detail.goal_path ?? '',
|
|
284
|
+
};
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
// The target resolver is shared by `node config` and `node lifecycle demote`;
|
|
288
|
+
// each command owns its direct config patch path.
|
|
289
|
+
/** Resolve the node a demote/config command acts on: explicit --node, else
|
|
290
|
+
* the node occupying --pane (the Alt+C menu passes #{pane_id}), else the caller
|
|
291
|
+
* (CRTR_NODE_ID). Throws a rendered error when none resolves or it is unknown. */
|
|
292
|
+
async function resolveLifecycleNode(input, pane) {
|
|
293
|
+
let id = input['node'];
|
|
294
|
+
if (id === undefined || id === '')
|
|
295
|
+
id = nodeInPane(pane);
|
|
296
|
+
if (id === undefined || id === '')
|
|
297
|
+
id = process.env['CRTR_NODE_ID'];
|
|
298
|
+
if (id === undefined || id === '')
|
|
299
|
+
throw new InputError({ error: 'no_node', message: 'no node (set CRTR_NODE_ID, pass --node, or run from the agent\'s pane)', next: 'Run from inside a node, pass --node <id>, or --pane <pane>.' });
|
|
300
|
+
const exists = await getNodeOrNull(id);
|
|
301
|
+
if (exists === null)
|
|
302
|
+
throw new InputError({ error: 'not_found', message: `no node: ${id}`, next: 'List nodes with `crtr node inspect list`.' });
|
|
303
|
+
return id;
|
|
304
|
+
}
|
|
305
|
+
// ---------------------------------------------------------------------------
|
|
306
|
+
// node lifecycle demote — flip a node to TERMINAL in place (the friendly half
|
|
307
|
+
// of the promote/demote pair; bound to Alt+C → d, and → D with --detach). It
|
|
308
|
+
// stays focused and running but now owes a final up the spine. `node config
|
|
309
|
+
// --lifecycle` remains the orthogonal low-level command (it also does resident).
|
|
310
|
+
// See vision F5.
|
|
311
|
+
// ---------------------------------------------------------------------------
|
|
312
|
+
const nodeDemote = defineLeaf({
|
|
313
|
+
name: 'demote',
|
|
314
|
+
description: 'demote a node to terminal in place; it stays focused and running but now owes a final; --detach also closes its viewer (broker keeps running off-screen)',
|
|
315
|
+
whenToUse: 'you are watching a resident/interactive node and want to put it on a finishing track WITHOUT disturbing it: flip it terminal IN PLACE — it keeps its viewer and your focus, keeps running, but now owes a final report up the spine and reaps when done. The friendly counterpart to `node promote`. You can also let go entirely and close its viewer so the agent finishes off-screen on its broker. Use `node lifecycle recycle` instead to FINISH it now and reboot a fresh root in its pane, and `node config --lifecycle` for the orthogonal low-level flip (incl. terminal→resident)',
|
|
316
|
+
help: {
|
|
317
|
+
name: 'node lifecycle demote',
|
|
318
|
+
summary: 'demote a node to terminal IN PLACE — it stays focused and running but now owes a final up the spine and reaps when done. Pairs with `node promote` (mode↑); `--detach` also closes its viewer (the broker engine keeps running off-screen)',
|
|
319
|
+
params: [
|
|
320
|
+
{ kind: 'flag', name: 'node', type: 'string', required: false, constraint: 'Node to demote. Defaults to the node in --pane, else the caller (CRTR_NODE_ID).' },
|
|
321
|
+
{ kind: 'flag', name: 'pane', type: 'string', required: false, constraint: 'tmux pane id whose node to demote, when --node is omitted. Defaults to $TMUX_PANE. The Alt+C menu passes this for you.' },
|
|
322
|
+
{ kind: 'flag', name: 'detach', type: 'bool', required: false, constraint: 'After flipping terminal, stop foregrounding the agent by closing its viewer pane. The broker engine keeps generating off-screen and — now terminal — pushes a final up the spine when done; a later `focus` reattaches a viewer. The Alt+C → D move.' },
|
|
323
|
+
],
|
|
324
|
+
output: [
|
|
325
|
+
{ name: 'node_id', type: 'string', required: true, constraint: 'The demoted node.' },
|
|
326
|
+
{ name: 'lifecycle', type: 'string', required: true, constraint: 'Always "terminal" after a demote.' },
|
|
327
|
+
{ name: 'detached', type: 'boolean', required: false, constraint: 'True when --detach closed the agent\'s viewer pane (broker keeps running).' },
|
|
328
|
+
],
|
|
329
|
+
outputKind: 'object',
|
|
330
|
+
effects: ['Flips the node\'s lifecycle→terminal and rebuilds its launch spec so a future revive boots terminal — it stays focused and running, now owing a final up the spine.', 'The persona injector delivers the transition guidance at the next turn boundary (or on the node\'s next revive if it is dormant).', 'With --detach: closes the agent\'s viewer pane WITHOUT touching the broker engine — it keeps generating off-screen, reconnectable by a later `focus`.'],
|
|
331
|
+
},
|
|
332
|
+
run: async (input) => {
|
|
333
|
+
const pane = input['pane'] ?? process.env['TMUX_PANE'];
|
|
334
|
+
const id = await resolveLifecycleNode(input, pane);
|
|
335
|
+
// The server owns the lifecycle flip + launch-spec rebuild. Keep the patch
|
|
336
|
+
// before pane close so a failed patch never strands a running viewer.
|
|
337
|
+
const detail = await cliClient()
|
|
338
|
+
.patchConfig(id, { lifecycle: 'terminal' })
|
|
339
|
+
.catch((err) => rethrowAsCliError(err));
|
|
340
|
+
let detached = false;
|
|
341
|
+
if (input['detach'] === true) {
|
|
342
|
+
const viewer = viewerPaneOf(id) ?? pane;
|
|
343
|
+
if (viewer !== undefined && viewer !== '' && paneExists(viewer))
|
|
344
|
+
detached = closePane(viewer);
|
|
345
|
+
}
|
|
346
|
+
return { node_id: detail.node_id, lifecycle: detail.lifecycle, detached };
|
|
347
|
+
},
|
|
348
|
+
render: (r) => `Demoted ${r['node_id']} — lifecycle now ${r['lifecycle']} (in place)${r['detached'] === true ? ', viewer closed (broker still running off-screen)' : ''}.`,
|
|
349
|
+
});
|
|
350
|
+
// ---------------------------------------------------------------------------
|
|
351
|
+
// node lifecycle — recycle, close, or demote a node
|
|
352
|
+
// ---------------------------------------------------------------------------
|
|
353
|
+
export const nodeLifecycle = defineBranch({
|
|
354
|
+
name: 'lifecycle',
|
|
355
|
+
description: 'lifecycle actions — recycle, close, demote, or revive a node',
|
|
356
|
+
whenToUse: 'you are ending, transitioning, or bringing back one node you can name: finish the agent in your pane and reboot a fresh root (`recycle`), tear a node + its exclusive subtree down without finishing (`close`), flip a node onto a finishing track in place (`demote`), or bring a dormant node back (`revive`). To merely SET the terminal/resident attribute headlessly use `node config --lifecycle`; to FINISH from inside a node\'s own turn use `crtr push final`; to mass-reconnect EVERY disconnected node at once use `canvas revive --all`.',
|
|
357
|
+
help: {
|
|
358
|
+
name: 'node lifecycle',
|
|
359
|
+
summary: 'end, transition, or revive a node — recycle the pane, close + cascade-cancel a subtree, demote to terminal in place, or revive a dormant node',
|
|
360
|
+
},
|
|
361
|
+
children: [nodeRecycle, nodeClose, nodeDemote, nodeReviveLeaf],
|
|
362
|
+
});
|
|
363
|
+
// ---------------------------------------------------------------------------
|
|
364
|
+
// node yield — refresh: discard context, revive fresh in the same mode against roadmap or goal
|
|
365
|
+
// ---------------------------------------------------------------------------
|
|
366
|
+
export const nodeYield = defineLeaf({
|
|
367
|
+
name: 'yield',
|
|
368
|
+
description: 'refresh your context, same mode, against your roadmap or goal',
|
|
369
|
+
whenToUse: 'your context is filling but the mandate remains; refresh in the same mode, or combine the refresh with promotion when meaningful independent work can run in parallel and coordinating it should become your primary job',
|
|
370
|
+
help: {
|
|
371
|
+
name: 'node yield',
|
|
372
|
+
summary: 'request a fresh context window against your roadmap or original goal; mode stays unchanged unless --promote is passed',
|
|
373
|
+
guide: 'Persist anything needed after refresh and send any pending human question before invoking; in-flight asks survive the refresh.',
|
|
374
|
+
params: [
|
|
375
|
+
{ kind: 'flag', name: 'promote', type: 'bool', required: false, constraint: 'Also become an orchestrator as you refresh. Pass only when (1) the remaining work contains independent units that can run in parallel and (2) the task is large enough that parallel execution will materially improve intelligence, productivity, or elapsed throughput after coordination and synthesis. Task length, context exhaustion, sequential phases, or one helper are not enough; keep hands-on work in base mode and yield again as needed. Promote when coordinating and integrating children becomes your primary job. Already an orchestrator? This is not an error: your mode stays orchestrator and a missing roadmap is seeded.' },
|
|
376
|
+
{ kind: 'flag', name: 'kind', type: 'string', required: false, constraint: 'Respecialize as you refresh. The <kinds> list below names every top-level available kind and when to choose it; a sub-kind (e.g. plan/reviewers/security) is valid too by exact path but not listed here. Defaults to your current kind. With --promote it sets the orchestrator kind you become; without --promote it changes the kind while preserving your current mode.' },
|
|
377
|
+
{ kind: 'flag', name: 'model', type: 'enum', choices: ['ultra', 'strong'], required: false, constraint: 'Change the model your fresh revive runs on, by capability tier: `ultra` (frontier — reserve for high-taste judgment or enormous work: speccing, planning something large, e2e-testing something hard to test) or `strong` (opus — regular dev work). Omit to keep your current model. A node steering work is never weaker than opus, so these are the only two choices; the change is durable across future revives.' },
|
|
378
|
+
// Deliberate fail-first contract (#395): builtin orchestration guidance shows bare
|
|
379
|
+
// `crtr node yield`; that invocation fails fast and surfaces yield's full help just in
|
|
380
|
+
// time, at the point of use. Keep the note required rather than pre-documenting stdin
|
|
381
|
+
// in kernel guidance.
|
|
382
|
+
{ kind: 'stdin', name: 'message', required: true, constraint: 'A note to your future self — what to do the moment you wake fresh. Surfaced as <yield-message> in the next revive. Pass as a positional or pipe via heredoc.' },
|
|
383
|
+
],
|
|
384
|
+
output: [
|
|
385
|
+
{ name: 'node_id', type: 'string', required: true, constraint: 'The yielding node.' },
|
|
386
|
+
{ name: 'promoted', type: 'boolean', required: true, constraint: 'True iff you passed --promote.' },
|
|
387
|
+
{ name: 'model', type: 'string', required: false, constraint: 'The model tier your fresh revive will run on, present only when you changed it with --model.' },
|
|
388
|
+
{ name: 'will_refresh', type: 'boolean', required: true, constraint: 'Always true: end your turn and you will revive fresh.' },
|
|
389
|
+
],
|
|
390
|
+
dynamicState: () => kindsStateBlock(),
|
|
391
|
+
outputKind: 'object',
|
|
392
|
+
effects: ['Sets intent=refresh; the stophook shuts the process down on next stop and the daemon revives it fresh.', '--kind and/or --model durably reshape the node (kind respecialization, model-tier pin) before the refresh-revive; --promote additionally flips mode→orchestrator and seeds a roadmap scaffold — mode is otherwise left exactly as it was.'],
|
|
393
|
+
},
|
|
394
|
+
run: async (input) => {
|
|
395
|
+
const id = process.env['CRTR_NODE_ID'];
|
|
396
|
+
if (id === undefined || id === '')
|
|
397
|
+
throw new InputError({ error: 'no_node', message: 'no node to yield (CRTR_NODE_ID unset)', next: 'Run from inside a node.' });
|
|
398
|
+
const kind = input['kind'];
|
|
399
|
+
if (kind !== undefined)
|
|
400
|
+
assertKind(kind);
|
|
401
|
+
const model = input['model'];
|
|
402
|
+
const doPromote = input['promote'] === true;
|
|
403
|
+
const message = typeof input['message'] === 'string' ? input['message'].trim() : '';
|
|
404
|
+
if (message === '') {
|
|
405
|
+
throw new InputError({ error: 'empty_message', message: 'a yield message is required (stdin or positional)', next: 'Pass a note to your future self as an argument or pipe it on stdin.' });
|
|
406
|
+
}
|
|
407
|
+
// The server writes the yield note + sets intent=refresh (handleYield);
|
|
408
|
+
// `promoted`/`will_refresh` are derived client-side (a yield always refreshes;
|
|
409
|
+
// promoted iff --promote was passed).
|
|
410
|
+
const detail = await cliClient()
|
|
411
|
+
.yieldNode(id, { note: message, ...(kind !== undefined ? { kind } : {}), ...(model !== undefined ? { model } : {}), ...(doPromote ? { promote: true } : {}) })
|
|
412
|
+
.catch((err) => rethrowAsCliError(err));
|
|
413
|
+
return { node_id: detail.node_id, promoted: doPromote, ...(model !== undefined && detail.model_override != null ? { model: detail.model_override } : {}), will_refresh: true };
|
|
414
|
+
},
|
|
415
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const nodeMessage: import("../../core/command.js").BranchDef;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// `crtr node message` — immediate inbox delivery and typed-output requests.
|
|
2
|
+
import { defineBranch, defineLeaf } from '../../core/command.js';
|
|
3
|
+
import { InputError } from '../../core/io.js';
|
|
4
|
+
import { parseOutputSchemaValue } from '../../core/runtime/structured-output.js';
|
|
5
|
+
import { cliClient, getNodeOrNull, rethrowAsCliError } from '../api-client.js';
|
|
6
|
+
function requireNonBlankDiscriminant(input, name) {
|
|
7
|
+
const value = input[name];
|
|
8
|
+
if (value !== undefined && (typeof value !== 'string' || value.trim() === '')) {
|
|
9
|
+
const flag = name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
|
|
10
|
+
throw new InputError({ error: 'empty_discriminant', message: `--${flag} must contain non-whitespace text`, received: typeof value === 'string' ? value : String(value), field: flag, next: `Pass a non-empty --${flag} value, or omit the flag.` });
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
async function resolveMsgTarget(input) {
|
|
14
|
+
const to = input['to']?.trim();
|
|
15
|
+
const self = input['self'] === true;
|
|
16
|
+
const hasTo = to !== undefined && to !== '';
|
|
17
|
+
if (hasTo === self) {
|
|
18
|
+
throw new InputError({
|
|
19
|
+
error: 'bad_target',
|
|
20
|
+
message: hasTo && self ? '--to and --self are mutually exclusive' : 'exactly one of --to or --self is required',
|
|
21
|
+
next: 'Pass --to <node-id> or --self.',
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
if (self) {
|
|
25
|
+
const id = process.env['CRTR_NODE_ID'];
|
|
26
|
+
if (id === undefined || id === '') {
|
|
27
|
+
throw new InputError({ error: 'no_node', message: 'no node to target with --self (CRTR_NODE_ID unset)', next: 'Run from inside a node, or pass --to <node-id>.' });
|
|
28
|
+
}
|
|
29
|
+
return { targetId: id, isSelf: true };
|
|
30
|
+
}
|
|
31
|
+
const exists = await getNodeOrNull(to);
|
|
32
|
+
if (exists === null) {
|
|
33
|
+
throw new InputError({ error: 'not_found', message: `no node: ${to}`, field: 'to', next: 'List nodes with `crtr node inspect list`.' });
|
|
34
|
+
}
|
|
35
|
+
return { targetId: to, isSelf: false };
|
|
36
|
+
}
|
|
37
|
+
function messageOutput() {
|
|
38
|
+
return [
|
|
39
|
+
{ name: 'target', type: 'string', required: true, constraint: 'self or the target node id.' },
|
|
40
|
+
{ name: 'delivered', type: 'boolean', required: false, constraint: 'True when an inbox message was delivered.' },
|
|
41
|
+
{ name: 'revived', type: 'boolean', required: false, constraint: 'True when the target was revived.' },
|
|
42
|
+
{ name: 'guidance', type: 'string', required: true, constraint: 'Immediate action confirmation.' },
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
function messageSendParams() {
|
|
46
|
+
return [
|
|
47
|
+
{ kind: 'stdin', name: 'body', required: false, constraint: 'Visible message body. Required unless --fresh, --output-schema, or --situational-context is supplied.' },
|
|
48
|
+
{ kind: 'flag', name: 'to', type: 'string', required: false, constraint: 'Target an existing node by id. Exactly one of --to or --self is required.' },
|
|
49
|
+
{ kind: 'flag', name: 'self', type: 'bool', required: false, constraint: 'Target the calling node. Exactly one of --to or --self is required.' },
|
|
50
|
+
{ kind: 'flag', name: 'tier', type: 'enum', choices: ['critical', 'urgent', 'normal', 'deferred'], required: false, default: 'normal', constraint: 'Delivery urgency. Deferred never wakes an idle node.' },
|
|
51
|
+
{ kind: 'flag', name: 'situational-context', type: 'string', required: false, constraint: 'Non-empty hidden ambient context delivered beside the message, or alone.' },
|
|
52
|
+
{ kind: 'flag', name: 'reopen', type: 'bool', required: false, hidden: true, constraint: 'Clear a finalized target latch before delivery or fresh revive.' },
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
function messageRequestParams() {
|
|
56
|
+
return [
|
|
57
|
+
{ kind: 'stdin', name: 'body', required: false, constraint: 'Visible message body. Required unless --fresh, --output-schema, or --situational-context is supplied.' },
|
|
58
|
+
{ kind: 'flag', name: 'to', type: 'string', required: false, constraint: 'Target an existing node by id. Exactly one of --to or --self is required.' },
|
|
59
|
+
{ kind: 'flag', name: 'self', type: 'bool', required: false, constraint: 'Target the calling node. Exactly one of --to or --self is required.' },
|
|
60
|
+
{ kind: 'flag', name: 'tier', type: 'enum', choices: ['critical', 'urgent', 'normal'], required: false, default: 'normal', constraint: 'Delivery urgency. Deferred never wakes an idle node.' },
|
|
61
|
+
{ kind: 'flag', name: 'output-schema', type: 'string', required: true, constraint: 'Path to a JSON Schema file, or inline JSON beginning with `{`. Grants a one-off submit tool.' },
|
|
62
|
+
{ kind: 'flag', name: 'situational-context', type: 'string', required: false, constraint: 'Non-empty hidden ambient context delivered beside the message, or alone.' },
|
|
63
|
+
{ kind: 'flag', name: 'reopen', type: 'bool', required: false, hidden: true, constraint: 'Clear a finalized target latch before delivery or fresh revive.' },
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
async function runMessageEngine(input) {
|
|
67
|
+
const situationalContextSupplied = input['situationalContext'] !== undefined;
|
|
68
|
+
const situationalContextRaw = input['situationalContext']?.trim();
|
|
69
|
+
if (situationalContextSupplied && situationalContextRaw === '') {
|
|
70
|
+
throw new InputError({ error: 'empty_situational_context', message: '--situational-context must contain non-whitespace text', field: 'situational-context', next: 'Pass non-whitespace text, or omit --situational-context.' });
|
|
71
|
+
}
|
|
72
|
+
const { targetId, isSelf } = await resolveMsgTarget(input);
|
|
73
|
+
const bodyRaw = input['body'];
|
|
74
|
+
const body = bodyRaw !== undefined ? bodyRaw.trim() : undefined;
|
|
75
|
+
const hasBody = body !== undefined && body !== '';
|
|
76
|
+
const tierRaw = input['tier'];
|
|
77
|
+
const hasTier = tierRaw !== undefined && tierRaw !== '';
|
|
78
|
+
const fresh = input['fresh'] === true;
|
|
79
|
+
const outputSchemaParsed = parseOutputSchemaValue(input['outputSchema']);
|
|
80
|
+
const outputSchema = outputSchemaParsed !== null ? JSON.stringify(outputSchemaParsed) : null;
|
|
81
|
+
const hasSituational = situationalContextRaw !== undefined && situationalContextRaw !== '';
|
|
82
|
+
const reopen = input['reopen'] === true;
|
|
83
|
+
if (fresh && (hasBody || hasTier || outputSchema !== null)) {
|
|
84
|
+
throw new InputError({ error: 'bad_fresh_combo', message: '--fresh cannot combine with a body, --tier, or --output-schema', next: 'Drop the conflicting input; --fresh is a revive, not a message.' });
|
|
85
|
+
}
|
|
86
|
+
if (outputSchema !== null && tierRaw === 'deferred') {
|
|
87
|
+
throw new InputError({ error: 'output_schema_deferred_tier', message: '--output-schema cannot combine with --tier deferred because the target must answer', field: 'tier', next: 'Use normal, urgent, or critical tier, or drop --output-schema.' });
|
|
88
|
+
}
|
|
89
|
+
const target = isSelf ? 'self' : targetId;
|
|
90
|
+
const senderFrom = process.env['CRTR_NODE_ID'];
|
|
91
|
+
const client = cliClient();
|
|
92
|
+
let result;
|
|
93
|
+
if (fresh) {
|
|
94
|
+
const res = await client.sendMessage(targetId, {
|
|
95
|
+
body: '',
|
|
96
|
+
fresh: true,
|
|
97
|
+
...(reopen ? { reopen: true } : {}),
|
|
98
|
+
...(hasSituational ? { situational_context: situationalContextRaw } : {}),
|
|
99
|
+
...(senderFrom !== undefined ? { from: senderFrom } : {}),
|
|
100
|
+
}).catch(rethrowAsCliError);
|
|
101
|
+
result = { target, revived: res.revived, guidance: `Fresh-revived ${isSelf ? 'yourself' : targetId} now.` };
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
if (!hasBody && !hasSituational && outputSchema === null) {
|
|
105
|
+
throw new InputError({ error: 'empty_body', message: 'a message body is required unless --output-schema or --situational-context is supplied', field: 'body', next: 'Pass the message on stdin, or supply one of the documented alternatives.' });
|
|
106
|
+
}
|
|
107
|
+
const tier = (hasTier ? tierRaw : 'normal');
|
|
108
|
+
const res = await client.sendMessage(targetId, {
|
|
109
|
+
body: body ?? '',
|
|
110
|
+
tier,
|
|
111
|
+
...(reopen ? { reopen: true } : {}),
|
|
112
|
+
...(hasSituational ? { situational_context: situationalContextRaw } : {}),
|
|
113
|
+
...(outputSchema !== null ? { output_schema: outputSchema } : {}),
|
|
114
|
+
...(senderFrom !== undefined ? { from: senderFrom } : {}),
|
|
115
|
+
}).catch(rethrowAsCliError);
|
|
116
|
+
const guidance = res.revived
|
|
117
|
+
? 'Delivered — the dormant target was revived to receive it.'
|
|
118
|
+
: tier === 'deferred'
|
|
119
|
+
? "Delivered — held for the target's next natural cycle; not revived."
|
|
120
|
+
: 'Delivered.';
|
|
121
|
+
result = { target, delivered: true, revived: res.revived, guidance };
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
const nodeMessageSend = defineLeaf({
|
|
126
|
+
name: 'send',
|
|
127
|
+
description: 'deliver an inbox message to an existing node immediately',
|
|
128
|
+
whenToUse: 'you need to steer or inform a node now without creating an ongoing subscription',
|
|
129
|
+
help: {
|
|
130
|
+
name: 'node message send',
|
|
131
|
+
summary: 'deliver an inbox message to an existing node immediately',
|
|
132
|
+
params: messageSendParams(),
|
|
133
|
+
output: messageOutput(),
|
|
134
|
+
outputKind: 'object',
|
|
135
|
+
effects: ['Appends one inbox entry. Critical, urgent, and normal delivery may revive a dormant target; deferred waits for its next natural cycle.'],
|
|
136
|
+
},
|
|
137
|
+
run: (input) => runMessageEngine(input),
|
|
138
|
+
render: (r) => String(r['guidance']),
|
|
139
|
+
});
|
|
140
|
+
const nodeMessageRequest = defineLeaf({
|
|
141
|
+
name: 'request',
|
|
142
|
+
description: 'deliver an immediate typed-output request to an existing node',
|
|
143
|
+
whenToUse: 'the target must answer once through a submit tool constrained by a JSON Schema',
|
|
144
|
+
help: {
|
|
145
|
+
name: 'node message request',
|
|
146
|
+
summary: 'deliver an immediate typed-output request to an existing node',
|
|
147
|
+
params: messageRequestParams(),
|
|
148
|
+
output: messageOutput(),
|
|
149
|
+
outputKind: 'object',
|
|
150
|
+
effects: ['Installs the one-off submit schema before appending the request.'],
|
|
151
|
+
},
|
|
152
|
+
run: (input) => {
|
|
153
|
+
requireNonBlankDiscriminant(input, 'outputSchema');
|
|
154
|
+
return runMessageEngine(input);
|
|
155
|
+
},
|
|
156
|
+
render: (r) => String(r['guidance']),
|
|
157
|
+
});
|
|
158
|
+
export const nodeMessage = defineBranch({
|
|
159
|
+
name: 'message',
|
|
160
|
+
description: 'deliver immediate inbox work to an existing node',
|
|
161
|
+
whenToUse: 'you need one immediate delivery: send ordinary information, or request one schema-constrained result',
|
|
162
|
+
help: { name: 'node message', summary: 'deliver now; choose ordinary delivery or a typed-output obligation' },
|
|
163
|
+
children: [nodeMessageSend, nodeMessageRequest],
|
|
164
|
+
});
|