@north-light/crouter 0.3.233 → 0.3.235
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.js +16 -15
- package/dist/api/dto/nodes.d.ts +11 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/integration/provider-rotation.test.ts +1 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +14 -17
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/crtr-commands/index.ts +7 -11
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/index.ts +8 -8
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +10 -11
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/pi-shell-runner.ts +2 -2
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +3 -3
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +7 -7
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +8 -8
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +6 -6
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/sysprompt-window.ts +3 -3
- package/dist/builtin-pi-packages/pi-crtr-extensions/lib/subscription-state.ts +1 -1
- package/dist/clients/attach/chrome/ticket-panel.js +15 -2
- package/dist/clients/attach/overlays/graph.js +0 -3
- package/dist/clients/attach/overlays/mcp.js +1 -2
- package/dist/clients/attach/render/chat-view.js +0 -12
- package/dist/clients/attach/render/crtr-output.js +0 -2
- package/dist/clients/attach/render/tool-calls.js +0 -6
- package/dist/clients/attach/slash/dispatch.js +8 -11
- package/dist/clients/attach/viewer.js +535 -537
- package/dist/clients/conversation/projection.js +0 -2
- package/dist/clients/inbox/controller.js +22 -3
- package/dist/clients/inbox/review/companion-pane.js +0 -4
- package/dist/clients/inbox/review-adapter.js +0 -7
- package/dist/clients/inbox/tui/slots.d.ts +3 -3
- package/dist/clients/inbox/tui/types.d.ts +2 -2
- package/dist/commands/api-client.js +0 -8
- package/dist/commands/attention.js +1 -9
- package/dist/commands/canvas-browse.js +2 -1
- package/dist/commands/canvas-config.js +0 -10
- package/dist/commands/canvas-history.js +2 -1
- package/dist/commands/cron.js +10 -23
- package/dist/commands/dashboard.js +0 -2
- package/dist/commands/human/feedback.js +2 -1
- package/dist/commands/human/prompts.js +2 -5
- package/dist/commands/human/queue.js +2 -7
- package/dist/commands/human/request.js +0 -14
- package/dist/commands/human/review.js +2 -1
- package/dist/commands/human.js +1 -1
- package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +4 -4
- package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.d.ts +1 -0
- package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.js +96 -0
- package/dist/commands/memory/delete.js +1 -1
- package/dist/commands/memory/edit.js +6 -3
- package/dist/commands/memory/find.js +2 -2
- package/dist/commands/memory/lint.js +2 -1
- package/dist/commands/memory/list.d.ts +4 -0
- package/dist/commands/memory/list.js +20 -14
- package/dist/commands/memory/move.js +1 -1
- package/dist/commands/memory/read.d.ts +2 -7
- package/dist/commands/memory/read.js +5 -16
- package/dist/commands/memory/shared.d.ts +1 -0
- package/dist/commands/memory/shared.js +17 -8
- package/dist/commands/memory/write.js +8 -4
- package/dist/commands/node/bash.js +2 -1
- package/dist/commands/node/create.js +2 -1
- package/dist/commands/node/inspect.js +11 -10
- package/dist/commands/node/lifecycle.js +5 -13
- package/dist/commands/node/message.js +11 -6
- package/dist/commands/node/subscription.js +7 -2
- package/dist/commands/node/wait.js +9 -4
- package/dist/commands/node-context.js +2 -1
- package/dist/commands/node-lifecycle-revive.js +0 -2
- package/dist/commands/node-worktree.js +2 -1
- package/dist/commands/pkg/browse/actions.d.ts +1 -1
- package/dist/commands/pkg/browse/actions.js +4 -4
- package/dist/commands/pkg/browse/catalog.d.ts +1 -1
- package/dist/commands/pkg/browse/catalog.js +15 -15
- package/dist/commands/pkg/browse/command-view.d.ts +1 -1
- package/dist/commands/pkg/browse/command-view.js +3 -3
- package/dist/commands/pkg/browse/detail-panel.d.ts +1 -1
- package/dist/commands/pkg/browse/detail-panel.js +8 -8
- package/dist/commands/pkg/browse/doc-view.d.ts +1 -1
- package/dist/commands/pkg/browse/doc-view.js +3 -3
- package/dist/commands/pkg/browse/list-panel.d.ts +1 -1
- package/dist/commands/pkg/browse/list-panel.js +3 -3
- package/dist/commands/pkg/browse/model.d.ts +3 -3
- package/dist/commands/pkg/browse/shell.d.ts +2 -2
- package/dist/commands/pkg/browse/shell.js +13 -13
- package/dist/commands/pkg/plugin-manage.js +3 -2
- package/dist/commands/pkg/shared.js +0 -2
- package/dist/commands/pkg.js +1 -0
- package/dist/commands/profile/delete.js +2 -1
- package/dist/commands/profile/rename.js +1 -1
- package/dist/commands/push.js +2 -3
- package/dist/commands/revive.js +0 -2
- package/dist/commands/surface/node/placement.js +2 -1
- package/dist/commands/surface-edit.js +2 -1
- package/dist/commands/sys/config.js +1 -4
- package/dist/commands/sys/daemon.js +0 -10
- package/dist/commands/sys/doctor.js +3 -2
- package/dist/commands/sys/panels/broker-limits-panel.d.ts +2 -2
- package/dist/commands/sys/panels/broker-limits-panel.js +4 -4
- package/dist/commands/sys/panels/dependencies-panel.d.ts +2 -2
- package/dist/commands/sys/panels/dependencies-panel.js +2 -2
- package/dist/commands/sys/panels/keybindings-panel.d.ts +1 -1
- package/dist/commands/sys/panels/keybindings-panel.js +5 -5
- package/dist/commands/sys/panels/models-panel.d.ts +4 -4
- package/dist/commands/sys/panels/models-panel.js +11 -10
- package/dist/commands/sys/panels/plugins-panel.d.ts +2 -2
- package/dist/commands/sys/panels/plugins-panel.js +2 -2
- package/dist/commands/sys/panels/prefs-panel.d.ts +2 -2
- package/dist/commands/sys/panels/prefs-panel.js +4 -4
- package/dist/commands/sys/panels/profiles-panel.d.ts +1 -1
- package/dist/commands/sys/panels/profiles-panel.js +14 -13
- package/dist/commands/sys/panels/provider-panel.d.ts +3 -3
- package/dist/commands/sys/panels/provider-panel.js +8 -8
- package/dist/commands/sys/settings-shell.d.ts +3 -3
- package/dist/commands/sys/settings-shell.js +15 -15
- package/dist/commands/sys/setup-settings-runner.d.ts +3 -3
- package/dist/commands/sys/setup-settings-runner.js +5 -5
- package/dist/commands/sys/setup-wizard.d.ts +4 -4
- package/dist/commands/sys/setup-wizard.js +8 -8
- package/dist/commands/sys/support/prepare.js +4 -4
- package/dist/commands/sys/support/submit.js +2 -2
- package/dist/commands/sys/sync-deps.js +0 -2
- package/dist/commands/sys/sync-project-guidance.js +2 -1
- package/dist/commands/sys/sysprompt.js +2 -1
- package/dist/commands/sys.js +1 -0
- package/dist/core/__tests__/boot.test.js +0 -8
- package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +23 -1
- package/dist/core/__tests__/canvas-db-boundary.test.d.ts +1 -0
- package/dist/core/__tests__/canvas-db-boundary.test.js +46 -0
- package/dist/core/__tests__/canvas.test.js +1 -1
- package/dist/core/__tests__/child-death-wake.test.js +0 -2
- package/dist/core/__tests__/cli-help-contract.test.d.ts +1 -0
- package/dist/core/__tests__/cli-help-contract.test.js +150 -0
- package/dist/core/__tests__/cron-armed-context-failure.test.d.ts +1 -0
- package/dist/core/__tests__/cron-armed-context-failure.test.js +145 -0
- package/dist/core/__tests__/daemon-wedge.test.js +0 -4
- package/dist/core/__tests__/dead-node-policy-table.test.js +0 -4
- package/dist/core/__tests__/fixtures/fake-engine.js +4 -14
- package/dist/core/__tests__/fixtures/fake-pi-host.js +5 -5
- package/dist/core/__tests__/focuses.test.js +0 -6
- package/dist/core/__tests__/fs-utils.test.d.ts +1 -0
- package/dist/core/__tests__/fs-utils.test.js +50 -0
- package/dist/core/__tests__/helpers/harness.js +1 -1
- package/dist/core/__tests__/inline-memory-refs.test.js +0 -2
- package/dist/core/__tests__/integration/broker-fork-seam.test.js +0 -2
- package/dist/core/__tests__/integration/broker-sdk-wiring.test.js +3 -16
- package/dist/core/__tests__/integration/command-plugins.test.js +21 -24
- package/dist/core/__tests__/integration/deferred-no-wake.test.js +0 -6
- package/dist/core/__tests__/integration/flagship-lifecycle.test.js +0 -26
- package/dist/core/__tests__/integration/live-mutation-verbs.test.js +0 -4
- package/dist/core/__tests__/integration/live-mutation.test.js +1 -5
- package/dist/core/__tests__/integration/refresh-stall-recycle.test.js +1 -5
- package/dist/core/__tests__/integration/revive.test.js +0 -12
- package/dist/core/__tests__/integration/subscription-delivery.test.js +0 -6
- package/dist/core/__tests__/integration/tmux-surface.test.js +24 -8
- package/dist/core/__tests__/integration/worktree-reap.test.js +0 -6
- package/dist/core/__tests__/lifecycle.test.js +0 -18
- package/dist/core/__tests__/memory-resolver-precedence.test.js +1 -1
- package/dist/core/__tests__/migration.test.js +2 -2
- package/dist/core/__tests__/on-read-dedup-resume.test.js +3 -3
- package/dist/core/__tests__/pid-identity-match.test.js +1 -1
- package/dist/core/__tests__/plugin-kinds.test.js +1 -1
- package/dist/core/__tests__/plugin-page-components.test.js +1 -1
- package/dist/core/__tests__/preview-registry-sync.test.js +42 -1
- package/dist/core/__tests__/respawn-throttle.test.js +0 -4
- package/dist/core/__tests__/revive-all.test.js +5 -5
- package/dist/core/__tests__/revive-parked-fresh.test.js +62 -11
- package/dist/core/__tests__/seam/broker-attach-multiclient.test.js +0 -8
- package/dist/core/__tests__/seam/broker-attach-stream.test.js +0 -8
- package/dist/core/__tests__/seam/broker-crash-teardown.test.js +0 -2
- package/dist/core/__tests__/tmux-driver-boundary.test.d.ts +1 -0
- package/dist/core/__tests__/tmux-driver-boundary.test.js +50 -0
- package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +11 -6
- package/dist/core/activity-signal.d.ts +7 -0
- package/dist/core/activity-signal.js +38 -0
- package/dist/core/auto-update.js +2 -1
- package/dist/core/bootstrap.js +2 -1
- package/dist/core/canvas/__tests__/remote-canvas-source.test.js +1 -1
- package/dist/core/canvas/__tests__/remote-transport.test.js +1 -1
- package/dist/core/canvas/__tests__/render-remote.test.js +1 -1
- package/dist/core/canvas/browse/app.js +3 -2
- package/dist/core/canvas/browse/model.d.ts +1 -1
- package/dist/core/canvas/browse/model.js +0 -4
- package/dist/core/canvas/canvas.d.ts +22 -0
- package/dist/core/canvas/canvas.js +61 -19
- package/dist/core/canvas/crons.js +0 -6
- package/dist/core/canvas/db.d.ts +14 -20
- package/dist/core/canvas/db.js +30 -1332
- package/dist/core/canvas/focuses.js +0 -4
- package/dist/core/canvas/history.js +2 -1
- package/dist/core/canvas/meta-file.js +18 -27
- package/dist/core/canvas/migrations.d.ts +20 -0
- package/dist/core/canvas/migrations.js +1339 -0
- package/dist/core/canvas/nav-model.js +1 -11
- package/dist/core/canvas/nav-render.js +0 -8
- package/dist/core/canvas/remote-canvas-source.d.ts +8 -0
- package/dist/core/canvas/remote-canvas-source.js +9 -3
- package/dist/core/canvas/render-source.js +31 -13
- package/dist/core/command-manifests/manifest.js +0 -10
- package/dist/core/command-manifests/registry.d.ts +2 -0
- package/dist/core/command-manifests/schema.js +0 -4
- package/dist/core/command-plugins/compose.js +4 -2
- package/dist/core/command-plugins/discovery.d.ts +1 -0
- package/dist/core/command-plugins/discovery.js +1 -1
- package/dist/core/command-plugins/transport/http-invoke.js +0 -14
- package/dist/core/command.js +2 -6
- package/dist/core/config.js +2 -1
- package/dist/core/fault-classifier.js +8 -0
- package/dist/core/feed/inbox.d.ts +10 -0
- package/dist/core/feed/inbox.js +18 -12
- package/dist/core/fs-utils.d.ts +9 -2
- package/dist/core/fs-utils.js +7 -15
- package/dist/core/help.js +0 -8
- package/dist/core/host-exports/export.d.ts +2 -2
- package/dist/core/host-exports/export.js +9 -12
- package/dist/core/human/answer.d.ts +2 -2
- package/dist/core/human/convention.d.ts +2 -5
- package/dist/core/human/convention.js +3 -13
- package/dist/core/human/page-schema.d.ts +2 -2
- package/dist/core/human/page-schema.js +2 -2
- package/dist/core/human/root.js +6 -23
- package/dist/core/human/scan.js +24 -7
- package/dist/core/human/tickets.d.ts +4 -1
- package/dist/core/human/tickets.js +20 -6
- package/dist/core/io.js +0 -12
- package/dist/core/memory/identity.js +0 -4
- package/dist/core/memory/inline-ref-inventory.js +3 -2
- package/dist/core/memory/lint.js +3 -6
- package/dist/core/memory-resolver.d.ts +5 -0
- package/dist/core/memory-resolver.js +14 -12
- package/dist/core/pagination.d.ts +2 -0
- package/dist/core/pagination.js +2 -3
- package/dist/core/preview-registry.d.ts +14 -0
- package/dist/core/preview-registry.js +2 -4
- package/dist/core/preview-result-path.js +2 -1
- package/dist/core/profiles/manifest.d.ts +37 -5
- package/dist/core/profiles/manifest.js +44 -24
- package/dist/core/profiles/select.js +0 -4
- package/dist/core/review/signal.js +4 -23
- package/dist/core/review/ticket-filter.d.ts +3 -3
- package/dist/core/review/ticket-filter.js +4 -9
- package/dist/core/runtime/__tests__/engine-route.test.js +1 -1
- package/dist/core/runtime/__tests__/spawn-env.test.js +0 -8
- package/dist/core/runtime/bearings-render.d.ts +56 -0
- package/dist/core/runtime/bearings-render.js +241 -0
- package/dist/core/runtime/bearings.d.ts +2 -17
- package/dist/core/runtime/bearings.js +12 -198
- package/dist/core/runtime/broker/auth-reload.d.ts +39 -0
- package/dist/core/runtime/broker/auth-reload.js +149 -0
- package/dist/core/runtime/broker/engine-drive.d.ts +26 -0
- package/dist/core/runtime/broker/engine-drive.js +257 -0
- package/dist/core/runtime/broker/engine-routing.d.ts +143 -0
- package/dist/core/runtime/broker/engine-routing.js +211 -0
- package/dist/core/runtime/broker/event-projection.js +3 -2
- package/dist/core/runtime/broker/fault-retry.js +11 -4
- package/dist/core/runtime/broker/frame-client.d.ts +38 -0
- package/dist/core/runtime/broker/frame-client.js +129 -0
- package/dist/core/runtime/broker/frame-dispatch.d.ts +12 -189
- package/dist/core/runtime/broker/frame-dispatch.js +89 -1476
- package/dist/core/runtime/broker/frame-engine-control.d.ts +20 -0
- package/dist/core/runtime/broker/frame-engine-control.js +231 -0
- package/dist/core/runtime/broker/frame-memory-refs.d.ts +19 -0
- package/dist/core/runtime/broker/frame-memory-refs.js +41 -0
- package/dist/core/runtime/broker/frame-model-query.d.ts +13 -0
- package/dist/core/runtime/broker/frame-model-query.js +69 -0
- package/dist/core/runtime/broker/frame-read.d.ts +19 -0
- package/dist/core/runtime/broker/frame-read.js +116 -0
- package/dist/core/runtime/broker/frame-replies.d.ts +24 -0
- package/dist/core/runtime/broker/frame-replies.js +64 -0
- package/dist/core/runtime/broker/frame-session.d.ts +34 -0
- package/dist/core/runtime/broker/frame-session.js +203 -0
- package/dist/core/runtime/broker/rebind.js +50 -0
- package/dist/core/runtime/broker/turn-ignition.d.ts +42 -0
- package/dist/core/runtime/broker/turn-ignition.js +74 -0
- package/dist/core/runtime/broker-extension-render.js +9 -85
- package/dist/core/runtime/broker-protocol.js +0 -4
- package/dist/core/runtime/broker-sdk.js +2 -1
- package/dist/core/runtime/broker.d.ts +1 -1
- package/dist/core/runtime/broker.js +5 -23
- package/dist/core/runtime/fault.js +3 -2
- package/dist/core/runtime/headless-pi.js +3 -2
- package/dist/core/runtime/host.js +2 -3
- package/dist/core/runtime/kickoff.js +0 -4
- package/dist/core/runtime/launch-target.js +2 -1
- package/dist/core/runtime/launch.d.ts +2 -2
- package/dist/core/runtime/launch.js +20 -10
- package/dist/core/runtime/lifecycle.js +17 -26
- package/dist/core/runtime/managed-provider-cooling.d.ts +1 -1
- package/dist/core/runtime/naming.js +0 -2
- package/dist/core/runtime/nodes.js +2 -1
- package/dist/core/runtime/persona.js +0 -6
- package/dist/core/runtime/placement-tmux.js +2 -5
- package/dist/core/runtime/placement.js +4 -11
- package/dist/core/runtime/recap.js +4 -3
- package/dist/core/runtime/reopen.js +4 -7
- package/dist/core/runtime/reset.js +0 -4
- package/dist/core/runtime/resume-root.js +0 -2
- package/dist/core/runtime/revive.js +17 -13
- package/dist/core/runtime/session-list-cache.js +2 -2
- package/dist/core/runtime/shell-expansion.js +0 -2
- package/dist/core/runtime/spawn.js +0 -2
- package/dist/core/runtime/stop-guard.js +28 -16
- package/dist/core/runtime/stream-watchdog.d.ts +0 -1
- package/dist/core/runtime/stream-watchdog.js +13 -18
- package/dist/core/runtime/tmux-bindings.js +0 -2
- package/dist/core/runtime/tmux-driver.d.ts +12 -0
- package/dist/core/runtime/tmux-driver.js +18 -13
- package/dist/core/runtime/warm-pool.js +0 -4
- package/dist/core/scope.js +4 -3
- package/dist/core/spawn.js +2 -3
- package/dist/core/subscription-state.js +10 -17
- package/dist/core/substrate/__tests__/surface-match-pre-command.test.js +3 -3
- package/dist/core/substrate/frontmatter-validation.d.ts +1 -0
- package/dist/core/substrate/frontmatter-validation.js +1 -1
- package/dist/core/substrate/render.js +0 -12
- package/dist/core/substrate/schema.js +0 -12
- package/dist/core/substrate/surface-match.js +0 -2
- package/dist/core/termrender/display.js +2 -1
- package/dist/core/tui/page-host.d.ts +3 -3
- package/dist/core/tui/page-host.js +4 -4
- package/dist/core/tui/panel.js +3 -3
- package/dist/core/wake.js +0 -12
- package/dist/core/worktree.js +0 -2
- package/dist/daemon/__tests__/reconciler-signature.test.d.ts +1 -0
- package/dist/daemon/__tests__/reconciler-signature.test.js +36 -0
- package/dist/daemon/api/__tests__/error-seam.test.js +27 -0
- package/dist/daemon/api/__tests__/seam/api-server.test.js +2 -16
- package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.js +3 -11
- package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +0 -6
- package/dist/daemon/api/handlers/attach.js +2 -1
- package/dist/daemon/api/handlers/broker-ops.js +3 -6
- package/dist/daemon/api/handlers/canvas.js +12 -18
- package/dist/daemon/api/handlers/feedback-comments.js +0 -8
- package/dist/daemon/api/handlers/health.js +3 -2
- package/dist/daemon/api/handlers/human-requests.js +0 -10
- package/dist/daemon/api/handlers/human.js +1 -5
- package/dist/daemon/api/handlers/inbox.js +0 -18
- package/dist/daemon/api/handlers/memory.js +1 -1
- package/dist/daemon/api/handlers/messages.js +16 -20
- package/dist/daemon/api/handlers/nodes.js +23 -22
- package/dist/daemon/api/handlers/reports.js +1 -1
- package/dist/daemon/api/handlers/reviews.js +1 -6
- package/dist/daemon/api/handlers/worktree.js +6 -22
- package/dist/daemon/api/map.d.ts +4 -2
- package/dist/daemon/api/map.js +22 -8
- package/dist/daemon/api/router.js +0 -4
- package/dist/daemon/api/server.js +2 -5
- package/dist/daemon/boot-migrations.d.ts +14 -0
- package/dist/daemon/boot-migrations.js +31 -0
- package/dist/daemon/cron/armed-context.d.ts +21 -0
- package/dist/daemon/cron/armed-context.js +100 -0
- package/dist/daemon/cron/capture.d.ts +20 -0
- package/dist/daemon/cron/capture.js +45 -0
- package/dist/daemon/cron/disposition.d.ts +19 -0
- package/dist/daemon/cron/disposition.js +52 -0
- package/dist/daemon/cron/escalation.d.ts +12 -0
- package/dist/daemon/cron/escalation.js +124 -0
- package/dist/daemon/cron/held.d.ts +4 -0
- package/dist/daemon/cron/held.js +20 -0
- package/dist/daemon/cron/lease-recovery.d.ts +3 -0
- package/dist/daemon/cron/lease-recovery.js +119 -0
- package/dist/daemon/cron/live-runs.d.ts +11 -0
- package/dist/daemon/cron/live-runs.js +23 -0
- package/dist/daemon/cron/passes.d.ts +11 -0
- package/dist/daemon/cron/passes.js +78 -0
- package/dist/daemon/cron/settle.d.ts +28 -0
- package/dist/daemon/cron/settle.js +37 -0
- package/dist/daemon/cron/sinks.d.ts +2 -0
- package/dist/daemon/cron/sinks.js +100 -0
- package/dist/daemon/cron-run.d.ts +5 -41
- package/dist/daemon/cron-run.js +193 -882
- package/dist/daemon/crtrd-cli.js +2 -1
- package/dist/daemon/crtrd.js +22 -22
- package/dist/daemon/fleet.js +0 -4
- package/dist/daemon/human/deliver-action.js +2 -1
- package/dist/daemon/human/sweep.js +15 -4
- package/dist/daemon/manage.d.ts +2 -2
- package/dist/daemon/manage.js +4 -13
- package/dist/daemon/pidfile.js +2 -2
- package/dist/daemon/reconcilers/broker-supervision.js +27 -30
- package/dist/daemon/reconcilers/dormant-inbox.d.ts +1 -1
- package/dist/daemon/reconcilers/dormant-inbox.js +2 -1
- package/dist/daemon/reconcilers/live-obligation.js +2 -2
- package/dist/daemon/reconcilers/pending-review-submit.d.ts +1 -1
- package/dist/daemon/reconcilers/pending-review-submit.js +2 -1
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +2 -1
- package/dist/daemon/reconcilers/storage-maintenance.js +2 -1
- package/dist/daemon/review/companion.js +2 -2
- package/dist/daemon/review/sweep.js +8 -3
- package/dist/migrations/001-surfaces-frontmatter.js +0 -6
- package/dist/migrations/corpus.js +2 -5
- package/dist/migrations/registry.js +15 -2
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +0 -4
- package/dist/pi-extensions/broker-local.js +2 -1
- package/dist/pi-extensions/canvas-bash-valve.js +7 -20
- package/dist/pi-extensions/canvas-context-intro.js +2 -7
- package/dist/pi-extensions/canvas-doc-substrate.js +2 -3
- package/dist/pi-extensions/canvas-goal-capture.js +2 -1
- package/dist/pi-extensions/canvas-inbox-watcher.js +5 -12
- package/dist/pi-extensions/canvas-passive-context.js +2 -5
- package/dist/pi-extensions/canvas-preview-result.js +2 -1
- package/dist/pi-extensions/canvas-prompt-scrub.js +2 -1
- package/dist/pi-extensions/canvas-recap.js +3 -16
- package/dist/pi-extensions/canvas-review-boundary.js +2 -5
- package/dist/pi-extensions/canvas-stophook.js +2 -26
- package/dist/pi-extensions/canvas-structured-output.js +2 -1
- package/dist/pi-extensions/canvas-tool-guide.js +2 -1
- package/dist/shared/__tests__/env-boundary.test.d.ts +1 -0
- package/dist/shared/__tests__/env-boundary.test.js +93 -0
- package/dist/shared/env.d.ts +68 -0
- package/dist/shared/env.js +171 -0
- package/package.json +3 -1
- package/runtime.lock.json +2 -2
- package/dist/core/canvas/render.d.ts +0 -47
- package/dist/core/canvas/render.js +0 -245
|
@@ -11,13 +11,15 @@
|
|
|
11
11
|
// the sanctioned place for it.
|
|
12
12
|
import { existsSync, readdirSync } from 'node:fs';
|
|
13
13
|
import { join } from 'node:path';
|
|
14
|
-
import { listNodes,
|
|
15
|
-
import { getNode, pruneNodes, pruneToLimit, rebuildIndex, rosterEdges, rosterNodes, subscriptionsOf } from '../../../core/canvas/canvas.js';
|
|
14
|
+
import { getNode, listNodes, pruneNodes, pruneToLimit, rebuildIndex, rosterEdges, rosterNodes, subscriptionsOf } from '../../../core/canvas/canvas.js';
|
|
16
15
|
import { activeBackgroundBashJobs } from '../../../core/bash-jobs.js';
|
|
17
16
|
import { contextDir } from '../../../core/canvas/paths.js';
|
|
17
|
+
import { nowIso } from '../../../core/fs-utils.js';
|
|
18
18
|
import { isBrokerLive } from '../../../core/runtime/model-swap.js';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
19
|
+
import { dashboardRowsAllFromSource, enrichRowsFromSource } from '../../../core/canvas/render-source.js';
|
|
20
|
+
import { localCanvasSource } from '../../../core/canvas/source.js';
|
|
21
|
+
import { listFocuses } from '../../../core/canvas/focuses.js';
|
|
22
|
+
import { ticketCountsForNodes, ticketsAcrossCanvas } from '../../../core/canvas/attention.js';
|
|
21
23
|
import { buildCorpus, resolveRef, } from '../../../core/canvas/history.js';
|
|
22
24
|
import { nodeDir, nodesRoot } from '../../../core/canvas/paths.js';
|
|
23
25
|
import { reapEmptyNodes } from '../../../core/runtime/placement.js';
|
|
@@ -49,7 +51,6 @@ function handleAttentionCounts(ctx) {
|
|
|
49
51
|
const body = { counts: ticketCountsForNodes(rawIds) };
|
|
50
52
|
return { status: 200, body };
|
|
51
53
|
}
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
54
|
// history search / grep / read \u2014 the ranked corpus search, the required-
|
|
54
55
|
// pattern line-hit search, and ref resolution. Lifted verbatim from
|
|
55
56
|
// `commands/canvas-history/{search,grep,read}.ts`' run() bodies: the pure
|
|
@@ -57,7 +58,6 @@ function handleAttentionCounts(ctx) {
|
|
|
57
58
|
// now parses+validates flags and POSTs the normalized query). search and grep
|
|
58
59
|
// share the corpus builder and cursor helpers but are distinct wire contracts
|
|
59
60
|
// \u2014 no `--grep` flag survives on the search query.
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
61
|
function encodeCursor(offset) {
|
|
62
62
|
return Buffer.from(String(offset), 'utf8').toString('base64');
|
|
63
63
|
}
|
|
@@ -168,7 +168,7 @@ function handleHistorySearch(ctx) {
|
|
|
168
168
|
const limit = Math.min(100, Math.max(1, q.limit ?? 20));
|
|
169
169
|
const arts = buildCorpusFromQuery(q);
|
|
170
170
|
const offset = q.cursor !== undefined ? decodeCursor(q.cursor) : 0;
|
|
171
|
-
//
|
|
171
|
+
// ranked / browse mode
|
|
172
172
|
const terms = query.toLowerCase().split(/\s+/).filter((t) => t.length > 0);
|
|
173
173
|
let pool = arts;
|
|
174
174
|
let scored;
|
|
@@ -264,13 +264,13 @@ function handleHistoryRead(ctx) {
|
|
|
264
264
|
};
|
|
265
265
|
return { status: 200, body };
|
|
266
266
|
}
|
|
267
|
-
// ---------------------------------------------------------------------------
|
|
268
267
|
// snapshot \u2014 the enriched browser canvas roster + subscribes_to adjacency.
|
|
269
268
|
// Lifted from `commands/canvas-snapshot.ts` run() (dashboardRowsAll + enrichRows).
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
const rows =
|
|
273
|
-
|
|
269
|
+
async function handleSnapshot() {
|
|
270
|
+
const focusedNodeIds = new Set(listFocuses().map((f) => f.node_id));
|
|
271
|
+
const rows = await dashboardRowsAllFromSource(localCanvasSource, focusedNodeIds);
|
|
272
|
+
const asks = ticketCountsForNodes(rows.map((r) => r.node_id));
|
|
273
|
+
await enrichRowsFromSource(localCanvasSource, rows, asks);
|
|
274
274
|
const nodes = rows.map((row) => {
|
|
275
275
|
const meta = getNode(row.node_id);
|
|
276
276
|
const hostKind = meta?.host_kind ?? 'tmux';
|
|
@@ -308,13 +308,11 @@ function handleSnapshot() {
|
|
|
308
308
|
const body = { generated_at: nowIso(), nodes, subscriptions };
|
|
309
309
|
return { status: 200, body };
|
|
310
310
|
}
|
|
311
|
-
// ---------------------------------------------------------------------------
|
|
312
311
|
// roster - the lean, set-based topology read (daemon-starvation fix step 2).
|
|
313
312
|
// Exactly two indexed queries (rosterNodes() + rosterEdges()), no enrichRows,
|
|
314
313
|
// no per-row getNode/subscriptionsOf loop, no isStreaming/isPidAlive process
|
|
315
314
|
// probe. Single-flighted below so a burst of concurrent pollers (attach +
|
|
316
315
|
// browser, or several attach viewers) shares one DB pass instead of stacking N.
|
|
317
|
-
// ---------------------------------------------------------------------------
|
|
318
316
|
function buildRoster() {
|
|
319
317
|
const nodes = rosterNodes().map((row) => {
|
|
320
318
|
const hostKind = row.host_kind ?? 'tmux';
|
|
@@ -370,10 +368,8 @@ async function handleRoster() {
|
|
|
370
368
|
const body = await rosterCoalesced();
|
|
371
369
|
return { status: 200, body };
|
|
372
370
|
}
|
|
373
|
-
// ---------------------------------------------------------------------------
|
|
374
371
|
// prune \u2014 the three exclusive modes (COUNT > EMPTY > TTL sweep) + target-gone
|
|
375
372
|
// notification. Lifted from `commands/canvas-prune.ts` run().
|
|
376
|
-
// ---------------------------------------------------------------------------
|
|
377
373
|
/** Validate + narrow the prune body (all fields optional). */
|
|
378
374
|
function parsePruneBody(body) {
|
|
379
375
|
if (body === undefined || body === null)
|
|
@@ -436,10 +432,8 @@ function handlePrune(ctx) {
|
|
|
436
432
|
const body = { pruned, dry_run: dryRun, ttl_days: ttlDays };
|
|
437
433
|
return { status: 200, body };
|
|
438
434
|
}
|
|
439
|
-
// ---------------------------------------------------------------------------
|
|
440
435
|
// rebuild-index \u2014 re-derive rows from on-disk metas + the fail-loud guard.
|
|
441
436
|
// Lifted from `commands/canvas-rebuild-index.ts` (countOnDiskMetas + throw).
|
|
442
|
-
// ---------------------------------------------------------------------------
|
|
443
437
|
function countOnDiskMetas() {
|
|
444
438
|
const root = nodesRoot();
|
|
445
439
|
if (!existsSync(root))
|
|
@@ -18,9 +18,7 @@ import { requireTicketId, resolveTicket } from './inbox.js';
|
|
|
18
18
|
import { invalidRequest, objectBody, optionalString, requiredString } from './validate.js';
|
|
19
19
|
import { toPageFeedbackDTO, toPageFeedbackCommentDTO } from '../map.js';
|
|
20
20
|
const COMMENT_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
21
|
// Shared guards
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
22
|
/** Resolve a mutable page ticket: it must exist, be a page, and not have a
|
|
25
23
|
* terminal outcome. Passive pages never settle, so they stay commentable.
|
|
26
24
|
* A terminal ticket refuses every feedback action — settlement won. */
|
|
@@ -45,9 +43,7 @@ function requireCommentId(params) {
|
|
|
45
43
|
}
|
|
46
44
|
return commentId;
|
|
47
45
|
}
|
|
48
|
-
// ---------------------------------------------------------------------------
|
|
49
46
|
// Delivery — the person's turn in the companion conversation
|
|
50
|
-
// ---------------------------------------------------------------------------
|
|
51
47
|
/** The comment as the person's own words: the quoted page content and the
|
|
52
48
|
* note, nothing else. The companion's briefing rides its bearings and
|
|
53
49
|
* persona, never the human turn. */
|
|
@@ -79,9 +75,7 @@ async function deliverCommentTurn(args) {
|
|
|
79
75
|
return { target_node_id: target, status: 'failed', woke: false, error: error instanceof Error ? error.message : String(error) };
|
|
80
76
|
}
|
|
81
77
|
}
|
|
82
|
-
// ---------------------------------------------------------------------------
|
|
83
78
|
// POST /v1/human/inbox/:ticket_id/feedback-comments — create
|
|
84
|
-
// ---------------------------------------------------------------------------
|
|
85
79
|
function parseCreate(ctx) {
|
|
86
80
|
const violations = [];
|
|
87
81
|
const body = objectBody(ctx.body, ['quote', 'context', 'note'], violations);
|
|
@@ -154,9 +148,7 @@ async function handleCreate(ctx) {
|
|
|
154
148
|
};
|
|
155
149
|
return { status: 200, body };
|
|
156
150
|
}
|
|
157
|
-
// ---------------------------------------------------------------------------
|
|
158
151
|
// POST .../feedback-comments/:comment_id/resolve — the companion's report
|
|
159
|
-
// ---------------------------------------------------------------------------
|
|
160
152
|
function parseResolve(ctx) {
|
|
161
153
|
const violations = [];
|
|
162
154
|
const body = objectBody(ctx.body, ['node_id'], violations);
|
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
// Both run INSIDE crtrd, so `daemon_up` is trivially true and `daemon_pid` is
|
|
7
7
|
// this process. Store access is probed by a cheap `listNodes()` — a throw means
|
|
8
8
|
// the store is inaccessible.
|
|
9
|
-
import { listNodes } from '../../../
|
|
9
|
+
import { listNodes } from '../../../core/canvas/canvas.js';
|
|
10
10
|
import { apiSocketPath } from '../../../core/canvas/paths.js';
|
|
11
11
|
import { currentVersion } from '../../../core/self-update.js';
|
|
12
12
|
import { API_VERSION } from '../../../api/index.js';
|
|
13
13
|
import { DEFAULT_INTERVAL_MS } from '../../supervise-cadence.js';
|
|
14
|
+
import { envCrtrdTcp } from '../../../shared/env.js';
|
|
14
15
|
// The daemon's supervise-loop cadence, echoed as an informational field; the
|
|
15
16
|
// loop itself is unchanged (hard constraint). Derived from the single shared
|
|
16
17
|
// constant so it can never drift from crtrd's actual interval.
|
|
@@ -45,7 +46,7 @@ function handleStatus() {
|
|
|
45
46
|
// The store is unreachable — spec §8 store_unavailable.
|
|
46
47
|
throw { status: 503, code: 'store_unavailable', message: 'canvas store is inaccessible' };
|
|
47
48
|
}
|
|
48
|
-
const tcp =
|
|
49
|
+
const tcp = envCrtrdTcp();
|
|
49
50
|
const body = {
|
|
50
51
|
daemon_pid: process.pid,
|
|
51
52
|
tick_interval_ms: TICK_INTERVAL_MS,
|
|
@@ -21,9 +21,7 @@ const REASON_MAX = 1000;
|
|
|
21
21
|
const ACTOR_MAX = 200;
|
|
22
22
|
const DEFAULT_DELIVERY = { placement: 'inline', inbox: true, reply: false };
|
|
23
23
|
const SOURCE_FIELDS = ['sessionName', 'askedBy', 'emittedAt', 'profileName', 'nodeId'];
|
|
24
|
-
// ===========================================================================
|
|
25
24
|
// Body validation
|
|
26
|
-
// ===========================================================================
|
|
27
25
|
function isPlainObject(value) {
|
|
28
26
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
29
27
|
}
|
|
@@ -259,9 +257,7 @@ function requestToDTO(request) {
|
|
|
259
257
|
}
|
|
260
258
|
return dto;
|
|
261
259
|
}
|
|
262
|
-
// ===========================================================================
|
|
263
260
|
// POST /v1/human/requests — create
|
|
264
|
-
// ===========================================================================
|
|
265
261
|
/** Authoring failure is the caller's malformed page, never a server fault. */
|
|
266
262
|
function prepareOrReject(dialect, document, source, delivery) {
|
|
267
263
|
try {
|
|
@@ -312,15 +308,11 @@ function handleCreate(ctx) {
|
|
|
312
308
|
},
|
|
313
309
|
};
|
|
314
310
|
}
|
|
315
|
-
// ===========================================================================
|
|
316
311
|
// GET /v1/human/requests/:request_id — read
|
|
317
|
-
// ===========================================================================
|
|
318
312
|
function handleGet(ctx) {
|
|
319
313
|
return { status: 200, body: requestToDTO(resolveRequest(ctx)) };
|
|
320
314
|
}
|
|
321
|
-
// ===========================================================================
|
|
322
315
|
// POST /v1/human/requests/:request_id/replace — revise the pending page
|
|
323
|
-
// ===========================================================================
|
|
324
316
|
function handleReplace(ctx) {
|
|
325
317
|
const request = resolveRequest(ctx);
|
|
326
318
|
if (request.result !== null)
|
|
@@ -332,9 +324,7 @@ function handleReplace(ctx) {
|
|
|
332
324
|
publishPage(request.dir, prepared);
|
|
333
325
|
return { status: 200, body: requestToDTO({ ...request, manifest: prepared.manifest }) };
|
|
334
326
|
}
|
|
335
|
-
// ===========================================================================
|
|
336
327
|
// Settlement — respond, dismiss, cancel
|
|
337
|
-
// ===========================================================================
|
|
338
328
|
/** The settlement funnels speak the inbox's error vocabulary; requests speak
|
|
339
329
|
* the wire contract's. This is the one translation. */
|
|
340
330
|
function settlementError(error) {
|
|
@@ -19,9 +19,7 @@ function requireInteractionTicketId(ctx) {
|
|
|
19
19
|
}
|
|
20
20
|
return ticketId;
|
|
21
21
|
}
|
|
22
|
-
// ===========================================================================
|
|
23
22
|
// POST /v1/human/bridge — create a terminal bridge without a broker
|
|
24
|
-
// ===========================================================================
|
|
25
23
|
function handleCreateBridge(ctx) {
|
|
26
24
|
const req = ctx.body;
|
|
27
25
|
if (req === undefined || typeof req !== 'object') {
|
|
@@ -46,9 +44,7 @@ function handleCreateBridge(ctx) {
|
|
|
46
44
|
throw new ApiError(400, 'invalid_request', String(error));
|
|
47
45
|
}
|
|
48
46
|
}
|
|
49
|
-
// ===========================================================================
|
|
50
47
|
// POST /v1/human/tickets/:ticket_id/resolve and /cancel
|
|
51
|
-
// ===========================================================================
|
|
52
48
|
function reviewSubmitGuidance() {
|
|
53
49
|
return new ApiError(400, 'invalid_request', 'review approvals use POST /v1/human/reviews/:review_id/submit');
|
|
54
50
|
}
|
|
@@ -100,7 +96,7 @@ async function handleResolve(ctx) {
|
|
|
100
96
|
return { status: 200, body: { completed: true, reply_delivered: replyExpected, kind: 'page' } };
|
|
101
97
|
}
|
|
102
98
|
function hasPublishedTicket(dir) {
|
|
103
|
-
return existsSync(pageManifestPath(dir)) ||
|
|
99
|
+
return existsSync(pageManifestPath(dir)) || readTicketResult(dir) !== null;
|
|
104
100
|
}
|
|
105
101
|
async function handleCancel(ctx) {
|
|
106
102
|
const ticketId = requireInteractionTicketId(ctx);
|
|
@@ -18,9 +18,7 @@ import { filterTerminalReviewTickets } from '../../../core/review/ticket-filter.
|
|
|
18
18
|
const DEFAULT_CANCEL_REASON = 'Canceled from the inbox.';
|
|
19
19
|
const CANCEL_REASON_MAX = 1000;
|
|
20
20
|
const TICKET_ID_PATTERN = /^[a-f0-9]{64}$/;
|
|
21
|
-
// ===========================================================================
|
|
22
21
|
// Opaque ticket id resolution
|
|
23
|
-
// ===========================================================================
|
|
24
22
|
function ticketHash(canonicalRoot, ticketBasename) {
|
|
25
23
|
return createHash('sha256').update(`${canonicalRoot}\0${ticketBasename}`, 'utf8').digest('hex');
|
|
26
24
|
}
|
|
@@ -70,9 +68,7 @@ export function requireTicketId(params) {
|
|
|
70
68
|
}
|
|
71
69
|
return ticketId;
|
|
72
70
|
}
|
|
73
|
-
// ===========================================================================
|
|
74
71
|
// Projections — humanloop canonical shapes → wire DTOs
|
|
75
|
-
// ===========================================================================
|
|
76
72
|
function pageSlotToDTO(slot) {
|
|
77
73
|
const dto = {
|
|
78
74
|
kind: slot.kind,
|
|
@@ -166,9 +162,7 @@ const SLOT_VALIDATION_PATTERNS = [
|
|
|
166
162
|
function isSlotValidationError(err) {
|
|
167
163
|
return err instanceof Error && SLOT_VALIDATION_PATTERNS.some((pattern) => pattern.test(err.message));
|
|
168
164
|
}
|
|
169
|
-
// ===========================================================================
|
|
170
165
|
// GET /v1/human/inbox — enumerate
|
|
171
|
-
// ===========================================================================
|
|
172
166
|
/** The one page-summary projection: the pending list and the per-node history differ only in which tickets they walk. */
|
|
173
167
|
function pageSummaryToDTO(item, canonicalRoot) {
|
|
174
168
|
const dto = {
|
|
@@ -222,9 +216,7 @@ function handleList() {
|
|
|
222
216
|
});
|
|
223
217
|
return { status: 200, body: { tickets } };
|
|
224
218
|
}
|
|
225
|
-
// ===========================================================================
|
|
226
219
|
// GET /v1/human/inbox/history?node_id=<id> — page ticket history
|
|
227
|
-
// ===========================================================================
|
|
228
220
|
function handleHistory(ctx) {
|
|
229
221
|
// Home-wide when `node_id` is absent; an explicitly empty param is a caller bug.
|
|
230
222
|
const nodeId = ctx.query.get('node_id');
|
|
@@ -236,9 +228,7 @@ function handleHistory(ctx) {
|
|
|
236
228
|
const tickets = history.map((item) => pageSummaryToDTO(item, canonicalRoot));
|
|
237
229
|
return { status: 200, body: { tickets } };
|
|
238
230
|
}
|
|
239
|
-
// ===========================================================================
|
|
240
231
|
// GET /v1/human/inbox/:ticket_id — read a page ticket
|
|
241
|
-
// ===========================================================================
|
|
242
232
|
function handleGetPage(ctx) {
|
|
243
233
|
const ticketId = requireTicketId(ctx.params);
|
|
244
234
|
const resolved = resolveTicket(ticketId);
|
|
@@ -270,9 +260,7 @@ function handleGetPage(ctx) {
|
|
|
270
260
|
},
|
|
271
261
|
};
|
|
272
262
|
}
|
|
273
|
-
// ===========================================================================
|
|
274
263
|
// POST /v1/human/inbox/:ticket_id/respond — submit
|
|
275
|
-
// ===========================================================================
|
|
276
264
|
async function handleRespond(ctx) {
|
|
277
265
|
const ticketId = requireTicketId(ctx.params);
|
|
278
266
|
const request = validateRespondRequest(ctx.body);
|
|
@@ -317,9 +305,7 @@ async function handleRespond(ctx) {
|
|
|
317
305
|
throw new ApiError(500, 'internal', 'the ticket could not be finalized');
|
|
318
306
|
}
|
|
319
307
|
}
|
|
320
|
-
// ===========================================================================
|
|
321
308
|
// POST /v1/human/inbox/:ticket_id/progress — autosave
|
|
322
|
-
// ===========================================================================
|
|
323
309
|
function handleProgress(ctx) {
|
|
324
310
|
const ticketId = requireTicketId(ctx.params);
|
|
325
311
|
const request = validateProgressRequest(ctx.body);
|
|
@@ -346,9 +332,7 @@ function handleProgress(ctx) {
|
|
|
346
332
|
throw new ApiError(500, 'internal', 'progress could not be saved');
|
|
347
333
|
}
|
|
348
334
|
}
|
|
349
|
-
// ===========================================================================
|
|
350
335
|
// POST /v1/human/inbox/:ticket_id/cancel — cancel
|
|
351
|
-
// ===========================================================================
|
|
352
336
|
async function handleCancel(ctx) {
|
|
353
337
|
const ticketId = requireTicketId(ctx.params);
|
|
354
338
|
const request = validateCancelRequest(ctx.body);
|
|
@@ -378,9 +362,7 @@ async function handleCancel(ctx) {
|
|
|
378
362
|
throw new ApiError(500, 'internal', 'the ticket could not be canceled');
|
|
379
363
|
}
|
|
380
364
|
}
|
|
381
|
-
// ===========================================================================
|
|
382
365
|
// GET /v1/human/inbox/:ticket_id/response — published response
|
|
383
|
-
// ===========================================================================
|
|
384
366
|
function handleGetResponse(ctx) {
|
|
385
367
|
const ticketId = requireTicketId(ctx.params);
|
|
386
368
|
const resolved = resolveTicket(ticketId);
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// to different documents for two nodes (each has its own context store, project
|
|
9
9
|
// stack, and profile). Resolution therefore runs target-addressed —
|
|
10
10
|
// `resolveMemoryDocForTarget` with the node's cwd/profile/id off canvas.
|
|
11
|
-
import { getNode } from '../../../
|
|
11
|
+
import { getNode } from '../../../core/canvas/canvas.js';
|
|
12
12
|
import { notFound, usage } from '../../../core/errors.js';
|
|
13
13
|
import { resolveMemoryDocForTarget } from '../../../core/memory-resolver.js';
|
|
14
14
|
import { isDocLinkName } from '../../../core/memory/doc-link-grammar.js';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Message handler (spec §6.2). `POST /v1/nodes/{id}/messages` delivers an
|
|
2
2
|
// inbox message now (201) or fresh-revives with no inbox entry. `{id}` is the
|
|
3
3
|
// target node.
|
|
4
|
-
import { appendInbox,
|
|
4
|
+
import { appendInbox, cancelPendingHumanMessages } from '../../../core/feed/inbox.js';
|
|
5
|
+
import { reviveNode } from '../../../core/runtime/revive.js';
|
|
5
6
|
import { BrokerUnreachableError } from '../../../core/runtime/broker-request.js';
|
|
6
7
|
import { isBrokerLive } from '../../../core/runtime/model-swap.js';
|
|
7
8
|
import { deliverLive, interruptLive } from '../../../core/runtime/interactive-deliver.js';
|
|
8
|
-
import { cancelPendingHumanMessages } from '../../../core/feed/inbox.js';
|
|
9
9
|
import { isProfilePaused } from '../../../core/profiles/manifest.js';
|
|
10
|
-
import { withFreshTerminalGuard } from '../../../core/canvas/canvas.js';
|
|
10
|
+
import { getNode, withFreshTerminalGuard } from '../../../core/canvas/canvas.js';
|
|
11
11
|
import { assertNotFinalized, assertFinalizedForReopen, commitReopen, commitReopenResident, } from '../../../core/runtime/reopen.js';
|
|
12
12
|
import { writeOutputSchema } from '../../../core/runtime/structured-output.js';
|
|
13
13
|
import { appendSituationalContext, formatSituationalProse } from '../../../core/runtime/situational-context.js';
|
|
@@ -17,9 +17,7 @@ import { hasFreshGroundState } from '../../../core/runtime/revive.js';
|
|
|
17
17
|
import { notFound, usage } from '../../../core/errors.js';
|
|
18
18
|
import { InputError } from '../../../core/io.js';
|
|
19
19
|
import { ApiError } from '../../../api/index.js';
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
20
|
// POST /v1/nodes/{id}/messages
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
21
|
const TIERS = ['critical', 'urgent', 'normal', 'deferred'];
|
|
24
22
|
/** Validate + narrow one caller-supplied runtime card. A bare kind is crouter's
|
|
25
23
|
* own closed vocabulary, so a caller must namespace: no product can shadow a
|
|
@@ -209,7 +207,7 @@ async function handleMessage(ctx) {
|
|
|
209
207
|
const schema = req.output_schema !== undefined && req.output_schema.trim() !== ''
|
|
210
208
|
? parseSchema(req.output_schema)
|
|
211
209
|
: null;
|
|
212
|
-
//
|
|
210
|
+
// Fresh revive: no inbox entry, resume:false (spec §7.7).
|
|
213
211
|
// Mirrors the CLI's immediate --fresh: validate/clear the finalization latch
|
|
214
212
|
// (--reopen) and upsert the situational sidecar BEFORE the revive, so the
|
|
215
213
|
// fresh kickoff picks up the update. The goal/roadmap recoverable-state guard
|
|
@@ -311,18 +309,18 @@ async function handleMessage(ctx) {
|
|
|
311
309
|
// nothing will ever bring back on its own, and a deferred entry appended to it
|
|
312
310
|
// would wait forever. Reopen widens the WAKE-CAPABLE tiers to a finalized
|
|
313
311
|
// target; deferred stays rejected, and the rejection names those tiers.
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
312
|
+
const deliver = () => {
|
|
313
|
+
if (tier === 'deferred') {
|
|
314
|
+
const outcome = withFreshTerminalGuard(id, hasNoNaturalCycle, deliverImmediate);
|
|
315
|
+
if (outcome.kind === 'missing')
|
|
316
|
+
throw notFound(`unknown node: ${id}`, { received: id });
|
|
317
|
+
if (outcome.kind === 'terminal')
|
|
318
|
+
throw deferredNoNaturalCycle(id, outcome.status);
|
|
319
|
+
return outcome.result;
|
|
320
|
+
}
|
|
321
|
+
return deliverImmediate();
|
|
322
|
+
};
|
|
323
|
+
const entry = deliver();
|
|
326
324
|
// A wake-capable tier revives a dormant target so its inbox-watcher delivers
|
|
327
325
|
// this; deferred never wakes — it rides the target's next natural cycle.
|
|
328
326
|
let revived = false;
|
|
@@ -344,9 +342,7 @@ async function handleMessage(ctx) {
|
|
|
344
342
|
};
|
|
345
343
|
return { status: 201, body };
|
|
346
344
|
}
|
|
347
|
-
// ---------------------------------------------------------------------------
|
|
348
345
|
// POST /v1/nodes/{id}/interrupt
|
|
349
|
-
// ---------------------------------------------------------------------------
|
|
350
346
|
/** The human Esc, first-class. Cancel pending undelivered human sends FIRST,
|
|
351
347
|
* then abort the live turn — in that order, so a watcher injection racing
|
|
352
348
|
* between the two is caught by the abort right behind it. A dormant target is
|
|
@@ -6,12 +6,15 @@
|
|
|
6
6
|
// map.ts carries no projector — it is frozen under concurrency).
|
|
7
7
|
//
|
|
8
8
|
// `{id}` is the target node.
|
|
9
|
+
import { envProfileId } from '../../../shared/env.js';
|
|
9
10
|
import { readdirSync } from 'node:fs';
|
|
10
11
|
import { basename } from 'node:path';
|
|
11
|
-
import { appendSituationalContext,
|
|
12
|
-
import {
|
|
12
|
+
import { appendSituationalContext, formatSituationalProse } from '../../../core/runtime/situational-context.js';
|
|
13
|
+
import { closeNode } from '../../../core/runtime/close.js';
|
|
14
|
+
import { reviveNode } from '../../../core/runtime/revive.js';
|
|
15
|
+
import { nowIso } from '../../../core/fs-utils.js';
|
|
13
16
|
import { assertLaunchModelRegistered, forkNode, spawnChild } from '../../../core/runtime/spawn.js';
|
|
14
|
-
import { childrenOf, subscribersOf, subscriptionsOf, setMessageWait, updateNode } from '../../../core/canvas/canvas.js';
|
|
17
|
+
import { childrenOf, getNode, listNodes, subscribersOf, subscriptionsOf, setMessageWait, updateNode } from '../../../core/canvas/canvas.js';
|
|
15
18
|
import { subtreeIds } from '../../../core/canvas/nav-model.js';
|
|
16
19
|
import { ticketCountsForNodes } from '../../../core/canvas/attention.js';
|
|
17
20
|
import { contextDir, reportsDir } from '../../../core/canvas/paths.js';
|
|
@@ -29,6 +32,8 @@ import { renameWindow } from '../../../core/runtime/placement.js';
|
|
|
29
32
|
import { buildLaunchSpecAsync, isProviderPinnedModelToken, normalizeModel, readMergedLaunchConfigAsync } from '../../../core/runtime/launch.js';
|
|
30
33
|
import { modelRequestFromConfig } from '../../../core/model-routes.js';
|
|
31
34
|
import { BrokerUnreachableError } from '../../../core/runtime/broker-request.js';
|
|
35
|
+
import { readFault } from '../../../core/runtime/fault.js';
|
|
36
|
+
import { activeFaultForDisplay } from '../../../core/canvas/render-source.js';
|
|
32
37
|
import { isBrokerLive, persistDormantModel, setModelLive } from '../../../core/runtime/model-swap.js';
|
|
33
38
|
import { writeOutputSchema } from '../../../core/runtime/structured-output.js';
|
|
34
39
|
import { claimWarmNode, refillWarmPool, warmPoolEnabled } from '../../../core/runtime/warm-pool.js';
|
|
@@ -40,9 +45,7 @@ import { cronWakeOrigin } from '../../../core/runtime/bearings.js';
|
|
|
40
45
|
import { notFound, usage } from '../../../core/errors.js';
|
|
41
46
|
import { toCloseResultDTO, toNodeDetailDTO, toNodeSummaryDTO, toReviveResultDTO } from '../map.js';
|
|
42
47
|
import { ApiError } from '../../../api/index.js';
|
|
43
|
-
// ---------------------------------------------------------------------------
|
|
44
48
|
// Shared helpers
|
|
45
|
-
// ---------------------------------------------------------------------------
|
|
46
49
|
function requireMeta(id) {
|
|
47
50
|
const meta = getNode(id);
|
|
48
51
|
if (meta === null)
|
|
@@ -61,7 +64,17 @@ function edgesFor(id) {
|
|
|
61
64
|
}
|
|
62
65
|
/** Re-read a node fresh and project its detail DTO (post-action response). */
|
|
63
66
|
function detailOf(id) {
|
|
64
|
-
|
|
67
|
+
const meta = requireMeta(id);
|
|
68
|
+
const fault = activeFaultForDisplay(meta, readFault(id));
|
|
69
|
+
return {
|
|
70
|
+
...toNodeDetailDTO(meta, edgesFor(id)),
|
|
71
|
+
fault: fault === null ? null : {
|
|
72
|
+
link: fault.link,
|
|
73
|
+
kind: fault.kind,
|
|
74
|
+
retry: { disposition: fault.retry.disposition },
|
|
75
|
+
since: fault.since,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
65
78
|
}
|
|
66
79
|
/** Count context + report files under a node (the context-roster `files`). */
|
|
67
80
|
function countFiles(id) {
|
|
@@ -76,9 +89,7 @@ function countFiles(id) {
|
|
|
76
89
|
}
|
|
77
90
|
return n;
|
|
78
91
|
}
|
|
79
|
-
// ---------------------------------------------------------------------------
|
|
80
92
|
// POST /v1/nodes — create immediately (201)
|
|
81
|
-
// ---------------------------------------------------------------------------
|
|
82
93
|
/** Validate + narrow the create body (spec §6.2). */
|
|
83
94
|
function parseCreateBody(body) {
|
|
84
95
|
if (typeof body !== 'object' || body === null) {
|
|
@@ -192,7 +203,7 @@ export async function handleCreate(ctx, deps = {}) {
|
|
|
192
203
|
// buildRecipe already defaults `prompt` to ''. The CLI keeps every no_kickoff
|
|
193
204
|
// guards (root-only / no-prompt / no-orchestrator).
|
|
194
205
|
const parent = req.parent ?? undefined;
|
|
195
|
-
//
|
|
206
|
+
// Immediate spawn (201). A managed child needs a parent; a root does not.
|
|
196
207
|
if (parent == null && req.root !== true) {
|
|
197
208
|
throw usage('a node create requires a parent (or root: true for an independent root)');
|
|
198
209
|
}
|
|
@@ -233,9 +244,7 @@ export async function handleCreate(ctx, deps = {}) {
|
|
|
233
244
|
writeOutputSchema(result.node.node_id, 'terminal', schema);
|
|
234
245
|
return { status: 201, body: detailOf(result.node.node_id) };
|
|
235
246
|
}
|
|
236
|
-
// ---------------------------------------------------------------------------
|
|
237
247
|
// GET /v1/nodes — list (filters) ; GET /v1/nodes/{id} — detail
|
|
238
|
-
// ---------------------------------------------------------------------------
|
|
239
248
|
function singleQueryValue(ctx, name) {
|
|
240
249
|
const values = ctx.query.getAll(name);
|
|
241
250
|
if (values.length > 1)
|
|
@@ -343,9 +352,7 @@ function handleDetail(ctx) {
|
|
|
343
352
|
requireMeta(id);
|
|
344
353
|
return { status: 200, body: detailOf(id) };
|
|
345
354
|
}
|
|
346
|
-
// ---------------------------------------------------------------------------
|
|
347
355
|
// Read endpoints (snapshot / transcript / context / artifacts)
|
|
348
|
-
// ---------------------------------------------------------------------------
|
|
349
356
|
async function handleSnapshot(ctx) {
|
|
350
357
|
const id = ctx.params['id'];
|
|
351
358
|
requireMeta(id);
|
|
@@ -458,9 +465,7 @@ function handleArtifacts(ctx) {
|
|
|
458
465
|
const body = { node_id: id, artifacts };
|
|
459
466
|
return { status: 200, body };
|
|
460
467
|
}
|
|
461
|
-
// ---------------------------------------------------------------------------
|
|
462
468
|
// Lifecycle verbs
|
|
463
|
-
// ---------------------------------------------------------------------------
|
|
464
469
|
async function handleFork(ctx) {
|
|
465
470
|
const id = ctx.params['id'];
|
|
466
471
|
requireMeta(id);
|
|
@@ -601,9 +606,7 @@ function handleReviveAll() {
|
|
|
601
606
|
const body = { revived: [...result.revived], failed: [...result.failed] };
|
|
602
607
|
return { status: 200, body };
|
|
603
608
|
}
|
|
604
|
-
// ---------------------------------------------------------------------------
|
|
605
609
|
// PATCH /v1/nodes/{id}/config — model / situational-context (spec §6.2)
|
|
606
|
-
// ---------------------------------------------------------------------------
|
|
607
610
|
export async function handleConfig(ctx, deps = {}) {
|
|
608
611
|
const id = ctx.params['id'];
|
|
609
612
|
let meta = requireMeta(id);
|
|
@@ -646,7 +649,7 @@ export async function handleConfig(ctx, deps = {}) {
|
|
|
646
649
|
// Re-read so the launch-spec rebuild below sees the fresh model pin.
|
|
647
650
|
meta = requireMeta(id);
|
|
648
651
|
}
|
|
649
|
-
//
|
|
652
|
+
// kind / mode / lifecycle: reshape via canonical primitive (CLI parity).
|
|
650
653
|
if (patch.kind !== undefined || patch.mode !== undefined || patch.lifecycle !== undefined) {
|
|
651
654
|
if (patch.kind !== undefined)
|
|
652
655
|
await assertKindServer(patch.kind);
|
|
@@ -671,7 +674,7 @@ export async function handleConfig(ctx, deps = {}) {
|
|
|
671
674
|
...(patch.lifecycle !== undefined ? { lifecycle: newLifecycle } : {}),
|
|
672
675
|
}, beforePersist);
|
|
673
676
|
}
|
|
674
|
-
//
|
|
677
|
+
// name: rename the row and, when it has a live viewer window, that window.
|
|
675
678
|
if (patch.name !== undefined) {
|
|
676
679
|
meta = updateNode(id, { name: patch.name });
|
|
677
680
|
if (meta.window)
|
|
@@ -685,15 +688,13 @@ export async function handleConfig(ctx, deps = {}) {
|
|
|
685
688
|
* ambient configuration; prospective reads validate their resolved target. The
|
|
686
689
|
* read is subprocess-isolated — crtrd must never resolve config on its own loop. */
|
|
687
690
|
async function assertKindServer(kind) {
|
|
688
|
-
const kinds = Object.keys((await readMergedLaunchConfigAsync(process.cwd(),
|
|
691
|
+
const kinds = Object.keys((await readMergedLaunchConfigAsync(process.cwd(), envProfileId() || null)).kinds);
|
|
689
692
|
if (!kinds.includes(kind)) {
|
|
690
693
|
throw usage(`unknown kind: ${kind}`, { received: kind, next: `Valid kinds: ${kinds.sort().join(', ')}.` });
|
|
691
694
|
}
|
|
692
695
|
}
|
|
693
|
-
// ---------------------------------------------------------------------------
|
|
694
696
|
// Route table (revive-all registered before `:id` collisions are impossible —
|
|
695
697
|
// different methods — but ordered defensively).
|
|
696
|
-
// ---------------------------------------------------------------------------
|
|
697
698
|
export const nodeRoutes = [
|
|
698
699
|
{ method: 'POST', pattern: '/v1/nodes', handler: handleCreate },
|
|
699
700
|
{ method: 'GET', pattern: '/v1/nodes', handler: handleList },
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// `{id}` is the REPORTING node (client-side = CRTR_NODE_ID).
|
|
7
7
|
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
8
8
|
import { join } from 'node:path';
|
|
9
|
-
import { getNode } from '../../../
|
|
9
|
+
import { getNode } from '../../../core/canvas/canvas.js';
|
|
10
10
|
import { push, FinalizationError } from '../../../core/feed/feed.js';
|
|
11
11
|
import { autoDropCleanManagedWorktree, hasOpenManagedWorktree, missingWorktreeRecoveryHint } from '../../../core/worktree.js';
|
|
12
12
|
import { reportsDir } from '../../../core/canvas/paths.js';
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
// Canonical daemon-owned review lifecycle routes. Handlers validate the full
|
|
2
2
|
// wire request, delegate lifecycle work to review services, and project only
|
|
3
3
|
// committed daemon state.
|
|
4
|
-
import { existsSync } from 'node:fs';
|
|
5
|
-
import { ApiError } from '../../../api/index.js';
|
|
6
4
|
import { isSafeNodeId, reviewResultPath } from '../../../core/canvas/paths.js';
|
|
7
|
-
import { responsePath
|
|
5
|
+
import { responsePath } from '../../../core/human/convention.js';
|
|
8
6
|
import { ticketDir } from '../../../core/human/root.js';
|
|
9
7
|
import { createReview } from '../../../core/review/birth.js';
|
|
10
8
|
import { readAnchorBase, getReviewByBridge, listReviews, requireVisibleReview } from '../../../core/review/store.js';
|
|
@@ -168,9 +166,6 @@ function handleByBridge(ctx) {
|
|
|
168
166
|
const review = getReviewByBridge(bridgeNodeId);
|
|
169
167
|
if (review !== null)
|
|
170
168
|
return { status: 200, body: toReviewResponseDTO(review) };
|
|
171
|
-
if (existsSync(reviewPath(ticketDir(bridgeNodeId)))) {
|
|
172
|
-
throw new ApiError(409, 'review_predates_system', 'this review predates canonical review records; cancel it and re-file the review', { bridge_node_id: bridgeNodeId });
|
|
173
|
-
}
|
|
174
169
|
throw new ReviewOperationError('unknown_review', 'review was not found', { received: bridgeNodeId });
|
|
175
170
|
}
|
|
176
171
|
async function handleSubmit(ctx) {
|
|
@@ -8,32 +8,16 @@
|
|
|
8
8
|
//
|
|
9
9
|
// Error parity: `closeManagedWorktree` throws `WorktreeError` with a SPECIFIC
|
|
10
10
|
// code (`dirty_worktree`, `rebase_failed`, `unknown_node`, `no_managed_worktree`,
|
|
11
|
-
// …) plus a `next` remediation and an optional `detail`.
|
|
12
|
-
// `CrtrError`
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
import { closeManagedWorktree
|
|
16
|
-
import { CrtrError } from '../../../core/errors.js';
|
|
17
|
-
import { ExitCode } from '../../../types.js';
|
|
18
|
-
function worktreeErrorToCrtrError(err) {
|
|
19
|
-
const exitCode = err.code === 'unknown_node' ? ExitCode.NOT_FOUND : ExitCode.GENERAL;
|
|
20
|
-
const details = { next: err.next };
|
|
21
|
-
if (err.detail !== undefined)
|
|
22
|
-
details['received'] = err.detail;
|
|
23
|
-
return new CrtrError(err.code, err.message, exitCode, details);
|
|
24
|
-
}
|
|
11
|
+
// …) plus a `next` remediation and an optional `detail`. The error map projects
|
|
12
|
+
// all of that onto `CrtrError` for every route that can raise it — so the CLI
|
|
13
|
+
// leaf can reconstruct the original agent-facing contract instead of collapsing
|
|
14
|
+
// to a generic status code.
|
|
15
|
+
import { closeManagedWorktree } from '../../../core/worktree.js';
|
|
25
16
|
function handleWorktreeClose(ctx) {
|
|
26
17
|
const id = ctx.params['id'];
|
|
27
18
|
// No requireMeta: closeManagedWorktree already throws the precise
|
|
28
19
|
// `unknown_node` / `no_managed_worktree` WorktreeError for a bad id.
|
|
29
|
-
|
|
30
|
-
return { status: 200, body: closeManagedWorktree(id) };
|
|
31
|
-
}
|
|
32
|
-
catch (err) {
|
|
33
|
-
if (err instanceof WorktreeError)
|
|
34
|
-
throw worktreeErrorToCrtrError(err);
|
|
35
|
-
throw err;
|
|
36
|
-
}
|
|
20
|
+
return { status: 200, body: closeManagedWorktree(id) };
|
|
37
21
|
}
|
|
38
22
|
export const worktreeRoutes = [
|
|
39
23
|
{ method: 'POST', pattern: '/v1/nodes/:id/worktree/close', handler: handleWorktreeClose },
|