@north-light/crouter 0.3.311 → 0.3.313
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.d.ts +27 -30
- package/dist/api/client.js +80 -67
- package/dist/api/dto/broker-ops.d.ts +10 -20
- package/dist/api/dto/canvas.d.ts +1 -10
- package/dist/api/dto/health.d.ts +113 -0
- package/dist/api/dto/human-requests.d.ts +14 -3
- package/dist/api/dto/human.d.ts +2 -48
- package/dist/api/dto/human.js +3 -2
- package/dist/api/dto/inbox.d.ts +14 -0
- package/dist/api/dto/mail.d.ts +43 -0
- package/dist/api/dto/nodes.d.ts +11 -8
- package/dist/api/dto/recovery.d.ts +96 -0
- package/dist/api/dto/reviews.d.ts +2 -2
- package/dist/api/routes.d.ts +9 -6
- package/dist/api/routes.js +11 -11
- package/dist/build-root.d.ts +4 -0
- package/dist/build-root.js +11 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/integration/provider-rotation.test.ts +35 -47
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +1 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +12 -5
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +12 -5
- package/dist/cli.js +10 -1
- package/dist/clients/__tests__/helpers/human-daemon.d.ts +11 -0
- package/dist/clients/__tests__/helpers/human-daemon.js +60 -0
- package/dist/clients/attach/chrome/canvas-panels.js +1 -1
- package/dist/clients/attach/chrome/inbox-strip.d.ts +3 -3
- package/dist/clients/attach/chrome/inbox-strip.js +17 -9
- package/dist/clients/attach/chrome/ticket-panel.d.ts +2 -2
- package/dist/clients/attach/chrome/ticket-panel.js +77 -46
- package/dist/clients/attach/overlays/graph.js +6 -9
- package/dist/clients/attach/render/chat-view.d.ts +5 -4
- package/dist/clients/attach/render/chat-view.js +22 -13
- package/dist/clients/attach/render/page-block.d.ts +11 -7
- package/dist/clients/attach/render/page-block.js +64 -55
- package/dist/clients/attach/viewer.js +746 -735
- package/dist/clients/inbox/__tests__/integration/inbox-controller.test.js +56 -56
- package/dist/clients/inbox/__tests__/integration/stale-row-activation.test.js +45 -32
- package/dist/clients/inbox/controller.d.ts +42 -14
- package/dist/clients/inbox/controller.js +240 -124
- package/dist/clients/inbox/dto-adapt.d.ts +28 -0
- package/dist/clients/inbox/dto-adapt.js +93 -0
- package/dist/clients/inbox/page-adapter.d.ts +5 -4
- package/dist/clients/inbox/page-adapter.js +12 -12
- package/dist/clients/inbox/resolve.d.ts +10 -5
- package/dist/clients/inbox/resolve.js +13 -12
- package/dist/clients/inbox/review/review-client.d.ts +0 -1
- package/dist/clients/inbox/review/review-client.js +0 -4
- package/dist/clients/inbox/review-adapter.d.ts +2 -1
- package/dist/clients/inbox/review-adapter.js +3 -5
- package/dist/clients/inbox/surface.d.ts +2 -2
- package/dist/clients/inbox/surface.js +19 -8
- package/dist/clients/inbox/tui.d.ts +3 -3
- package/dist/commands/__tests__/human.test.js +31 -15
- package/dist/commands/__tests__/integration/dashboard-snapshot.test.js +36 -11
- package/dist/commands/{sys/__tests__ → __tests__/integration}/migrate.test.js +142 -36
- package/dist/commands/__tests__/revive-now-gate.test.js +2 -0
- package/dist/commands/api-client.d.ts +5 -4
- package/dist/commands/api-client.js +13 -7
- package/dist/commands/canvas-history/shared.js +1 -1
- package/dist/commands/canvas-history.js +1 -1
- package/dist/commands/canvas-roster.js +1 -1
- package/dist/commands/canvas.js +1 -2
- package/dist/commands/human/feedback.js +20 -17
- package/dist/commands/human/prompts.js +45 -36
- package/dist/commands/human/queue.js +73 -123
- package/dist/commands/human/review.js +6 -16
- package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +2 -0
- package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.js +2 -0
- package/dist/commands/memory/__tests__/repository-root-lint.test.js +2 -0
- package/dist/commands/node-inspect-artifacts.js +1 -1
- package/dist/commands/node-lifecycle-revive.d.ts +2 -2
- package/dist/commands/node-lifecycle-revive.js +9 -19
- package/dist/commands/pkg/plugin-manage.js +0 -1
- package/dist/commands/profile/show.js +4 -12
- package/dist/commands/surface-tmux-spread.js +1 -5
- package/dist/commands/sys/__tests__/config-model-ladders.test.js +23 -30
- package/dist/commands/sys/__tests__/sync-project-guidance.test.js +37 -11
- package/dist/commands/sys/branch.d.ts +2 -0
- package/dist/commands/sys/branch.js +19 -0
- package/dist/commands/sys/config.js +106 -33
- package/dist/commands/sys/daemon.d.ts +2 -0
- package/dist/commands/sys/daemon.js +130 -7
- package/dist/commands/sys/doctor.js +5 -15
- package/dist/commands/sys/migrate.js +21 -92
- package/dist/commands/sys/setup-settings-runner.js +4 -2
- package/dist/commands/sys.js +2 -15
- package/dist/core/__tests__/boot-fault-attempt.test.js +23 -1
- package/dist/core/__tests__/boot.test.js +32 -25
- package/dist/core/__tests__/broker-launch-candidates.test.js +49 -0
- package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +149 -176
- package/dist/core/__tests__/canvas-inbox-watcher-naming.test.js +59 -10
- package/dist/core/__tests__/canvas-inbox-watcher.test.js +76 -20
- package/dist/core/__tests__/canvas.test.js +18 -47
- package/dist/core/__tests__/child-death-wake.test.js +29 -7
- package/dist/core/__tests__/cli-help-contract.test.js +2 -0
- package/dist/core/__tests__/close.test.js +29 -10
- package/dist/core/__tests__/collectible.test.js +2 -1
- package/dist/core/__tests__/config-change-delta.test.js +2 -0
- package/dist/core/__tests__/context-intro.test.js +17 -5
- package/dist/core/__tests__/cron-armed-context-failure.test.js +17 -12
- package/dist/core/__tests__/cron-held-settlement.test.js +21 -3
- package/dist/core/__tests__/cron-node-sink-parked-root.test.js +29 -10
- package/dist/core/__tests__/cron-self-cancel-delivery.test.js +14 -2
- package/dist/core/__tests__/cron-timeout-descendants.test.js +13 -1
- package/dist/core/__tests__/daemon-boot.test.js +51 -14
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +1 -1
- package/dist/core/__tests__/fixtures/fake-engine.js +8 -3
- package/dist/core/__tests__/focuses.test.js +10 -5
- package/dist/core/__tests__/helpers/harness.js +50 -18
- package/dist/core/__tests__/history-inbox.test.js +12 -16
- package/dist/core/__tests__/human-action-delivery.test.js +48 -28
- package/dist/core/__tests__/human-actions.test.js +7 -3
- package/dist/core/__tests__/inline-memory-refs.test.js +7 -2
- package/dist/core/__tests__/integration/broker-fork-seam.test.js +37 -10
- package/dist/core/__tests__/integration/broker-sdk-wiring.test.js +42 -0
- package/dist/core/__tests__/integration/broker-snapshot-history.test.js +42 -29
- package/dist/core/__tests__/integration/broker-wedge-supervision.test.js +36 -35
- package/dist/core/__tests__/integration/command-plugins.test.js +15 -6
- package/dist/core/__tests__/integration/deferred-no-wake.test.js +113 -92
- package/dist/core/__tests__/integration/host-teardown-process-group.test.js +9 -5
- package/dist/core/__tests__/integration/lifecycle-hooks.test.js +312 -1
- package/dist/core/__tests__/integration/plugin-revalidate.test.js +4 -0
- package/dist/core/__tests__/integration/profile-pause.test.js +4 -4
- package/dist/core/__tests__/integration/refresh-stall-recycle.test.js +9 -12
- package/dist/core/__tests__/integration/revive.test.js +67 -21
- package/dist/core/__tests__/integration/spawn-root.test.js +62 -19
- package/dist/core/__tests__/integration/subscription-delivery.test.js +33 -21
- package/dist/core/__tests__/integration/worktree-land.test.js +5 -2
- package/dist/core/__tests__/integration/worktree-reap.test.js +15 -1
- package/dist/core/__tests__/kickoff.test.js +36 -39
- package/dist/core/__tests__/lifecycle-terminal-reasons.test.js +2 -1
- package/dist/core/__tests__/lifecycle.test.js +2 -1
- package/dist/core/__tests__/live-lifecycle-prompt.test.js +13 -1
- package/dist/core/__tests__/memory-resolver-precedence.test.js +2 -0
- package/dist/core/__tests__/migration.test.js +145 -31
- package/dist/core/__tests__/model-pin-durability.test.js +4 -1
- package/dist/core/__tests__/model-routes-config.test.js +13 -5
- package/dist/core/__tests__/node-outcome.test.js +93 -26
- package/dist/core/__tests__/on-read-crouter-home-fence.test.js +4 -3
- package/dist/core/__tests__/on-read-dedup-resume.test.js +8 -7
- package/dist/core/__tests__/on-read-nested-store.test.js +8 -7
- package/dist/core/__tests__/passive-subscription.test.js +50 -157
- package/dist/core/__tests__/plugin-kinds.test.js +6 -4
- package/dist/core/__tests__/plugin-link-symlinked-scope-root.test.js +6 -1
- package/dist/core/__tests__/plugin-page-components.test.js +6 -4
- package/dist/core/__tests__/preview-registry-sync.test.js +2 -0
- package/dist/core/__tests__/profile-project-memory-delivery.test.js +35 -32
- package/dist/core/__tests__/prune.test.js +11 -5
- package/dist/core/__tests__/push-final-guard.test.js +14 -7
- package/dist/core/__tests__/relaunch-root.test.js +30 -2
- package/dist/core/__tests__/remote-canvas-target.test.js +7 -1
- package/dist/core/__tests__/repository-root-identity.test.js +4 -0
- package/dist/core/__tests__/review-model-floor.test.js +6 -3
- package/dist/core/__tests__/revive-all.test.js +13 -3
- package/dist/core/__tests__/revive-capacity.test.js +26 -4
- package/dist/core/__tests__/revive-parked-fresh.test.js +31 -8
- package/dist/core/__tests__/seam/broker-attach-stream.test.js +1 -1
- package/dist/core/__tests__/seam/broker-cap-freeze.test.js +4 -3
- package/dist/core/__tests__/seam/broker-crash-teardown.test.js +11 -14
- package/dist/core/__tests__/seam/broker-provider-retry.test.js +85 -71
- package/dist/core/__tests__/seam/dormancy-release.test.js +33 -19
- package/dist/core/__tests__/seam/held-deferred-human-prompt.test.js +7 -5
- package/dist/core/__tests__/seam/inbox-reference-guidance.test.js +20 -6
- package/dist/core/__tests__/seam/node-outcome-delivery.test.js +27 -3
- package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +5 -4
- package/dist/core/__tests__/stop-guard.test.js +2 -1
- package/dist/core/__tests__/subscription-pool-credential-guard.test.js +4 -3
- package/dist/core/__tests__/warm-claim-preference-snapshot.test.js +19 -5
- package/dist/core/__tests__/yield-ensures-daemon.test.js +2 -1
- package/dist/core/bootstrap.js +2 -0
- package/dist/core/broker-client/__tests__/transport-socket.test.js +51 -6
- package/dist/core/broker-client/transport-socket.d.ts +1 -0
- package/dist/core/broker-client/transport-socket.js +13 -5
- package/dist/core/canvas/__tests__/attention.test.js +29 -35
- package/dist/core/canvas/__tests__/history-transcript.test.js +6 -6
- package/dist/core/canvas/__tests__/render-remote.test.js +25 -9
- package/dist/core/canvas/attention.d.ts +2 -5
- package/dist/core/canvas/attention.js +15 -64
- package/dist/core/canvas/boot.d.ts +6 -7
- package/dist/core/canvas/boot.js +5 -9
- package/dist/core/canvas/canvas.d.ts +13 -109
- package/dist/core/canvas/canvas.js +140 -401
- package/dist/core/canvas/crons.d.ts +2 -0
- package/dist/core/canvas/crons.js +16 -15
- package/dist/core/canvas/daemon-owner.js +10 -0
- package/dist/core/canvas/db.d.ts +2 -2
- package/dist/core/canvas/db.js +2 -18
- package/dist/core/canvas/deliveries.d.ts +104 -0
- package/dist/core/canvas/deliveries.js +354 -0
- package/dist/core/canvas/executions.d.ts +29 -0
- package/dist/core/canvas/executions.js +68 -0
- package/dist/core/canvas/history.js +35 -35
- package/dist/core/canvas/index.d.ts +3 -1
- package/dist/core/canvas/index.js +3 -1
- package/dist/core/canvas/migrations.js +20 -12
- package/dist/core/canvas/nav-model.js +1 -3
- package/dist/core/canvas/nav-render.d.ts +4 -4
- package/dist/core/canvas/nav-render.js +11 -21
- package/dist/core/canvas/node-sql-migration.d.ts +3 -0
- package/dist/core/canvas/node-sql-migration.js +261 -0
- package/dist/core/canvas/paths.d.ts +2 -16
- package/dist/core/canvas/paths.js +2 -31
- package/dist/core/canvas/recovery.d.ts +76 -0
- package/dist/core/canvas/recovery.js +588 -0
- package/dist/core/canvas/remote-canvas-source.js +4 -0
- package/dist/core/canvas/render-source.d.ts +16 -27
- package/dist/core/canvas/render-source.js +16 -45
- package/dist/core/canvas/sessions.d.ts +33 -0
- package/dist/core/canvas/sessions.js +78 -0
- package/dist/core/canvas/types.d.ts +33 -33
- package/dist/core/canvas/types.js +2 -5
- package/dist/core/canvas/waits.d.ts +18 -0
- package/dist/core/canvas/waits.js +70 -0
- package/dist/core/canvas/worktrees.d.ts +40 -0
- package/dist/core/canvas/worktrees.js +93 -0
- package/dist/core/command-hooks/artifact.d.ts +6 -0
- package/dist/core/command-hooks/artifact.js +22 -6
- package/dist/core/command-hooks/discovery.d.ts +2 -0
- package/dist/core/command-hooks/discovery.js +2 -0
- package/dist/core/command-hooks/lifecycle-catalog.d.ts +20 -2
- package/dist/core/command-hooks/lifecycle-catalog.js +7 -2
- package/dist/core/command-hooks/lifecycle-create.d.ts +4 -0
- package/dist/core/command-hooks/lifecycle-create.js +51 -0
- package/dist/core/command-hooks/schema.d.ts +2 -2
- package/dist/core/command-hooks/schema.js +5 -4
- package/dist/core/command-hooks/transport/exec-invoke.js +3 -1
- package/dist/core/command-hooks/transport/exec-lifecycle.d.ts +18 -8
- package/dist/core/command-hooks/transport/exec-lifecycle.js +89 -30
- package/dist/core/config.d.ts +17 -12
- package/dist/core/config.js +106 -155
- package/dist/core/errors.d.ts +1 -0
- package/dist/core/errors.js +4 -0
- package/dist/core/feed/__tests__/inbox-migrate.test.js +27 -31
- package/dist/core/feed/feed.d.ts +0 -6
- package/dist/core/feed/feed.js +68 -56
- package/dist/core/feed/inbox.d.ts +7 -81
- package/dist/core/feed/inbox.js +46 -378
- package/dist/core/feed/messages.d.ts +58 -0
- package/dist/core/feed/messages.js +217 -0
- package/dist/core/fs-utils.d.ts +4 -0
- package/dist/core/fs-utils.js +21 -1
- package/dist/core/human/answer.d.ts +1 -1
- package/dist/core/human/answer.js +1 -1
- package/dist/core/human/claim.d.ts +1 -1
- package/dist/core/human/claim.js +2 -4
- package/dist/core/human/component-docs.js +1 -1
- package/dist/core/human/feedback-companion.js +4 -3
- package/dist/core/human/feedback.d.ts +5 -8
- package/dist/core/human/feedback.js +57 -85
- package/dist/core/human/page-authoring.d.ts +30 -0
- package/dist/core/human/page-authoring.js +19 -0
- package/dist/core/human/requests.d.ts +136 -0
- package/dist/core/human/requests.js +515 -0
- package/dist/core/human/root.d.ts +0 -7
- package/dist/core/human/root.js +0 -17
- package/dist/core/human/scan.d.ts +2 -7
- package/dist/core/human/scan.js +48 -132
- package/dist/core/human/summary.d.ts +1 -1
- package/dist/core/human/summary.js +1 -1
- package/dist/core/human/tickets.d.ts +23 -83
- package/dist/core/human/tickets.js +92 -243
- package/dist/core/human/types.d.ts +5 -1
- package/dist/core/installed-plugins.js +8 -3
- package/dist/core/keybindings/__tests__/resolve.test.js +19 -17
- package/dist/core/locked-file.d.ts +6 -3
- package/dist/core/locked-file.js +36 -9
- package/dist/core/memory/extensions.js +2 -0
- package/dist/core/preview-registry.js +0 -1
- package/dist/core/profiles/__tests__/env-store.test.js +2 -0
- package/dist/core/profiles/default-binding.d.ts +0 -4
- package/dist/core/profiles/default-binding.js +12 -58
- package/dist/core/profiles/env-store.js +8 -3
- package/dist/core/profiles/manifest.d.ts +2 -37
- package/dist/core/profiles/manifest.js +35 -161
- package/dist/core/profiles/select.js +3 -0
- package/dist/core/review/__tests__/capture-origin.test.js +13 -2
- package/dist/core/review/__tests__/comments.test.js +28 -10
- package/dist/core/review/__tests__/remap.test.js +28 -10
- package/dist/core/review/__tests__/stage-identity.test.js +17 -7
- package/dist/core/review/birth.d.ts +1 -1
- package/dist/core/review/birth.js +34 -5
- package/dist/core/review/comments.js +1 -1
- package/dist/core/review/companion.d.ts +1 -1
- package/dist/core/review/companion.js +2 -2
- package/dist/core/review/document.js +1 -1
- package/dist/core/review/project.d.ts +5 -1
- package/dist/core/review/project.js +14 -36
- package/dist/core/review/realize.d.ts +3 -6
- package/dist/core/review/realize.js +51 -168
- package/dist/core/review/remap.js +1 -1
- package/dist/core/review/stage.d.ts +3 -2
- package/dist/core/review/stage.js +2 -3
- package/dist/core/review/store.d.ts +3 -21
- package/dist/core/review/store.js +140 -186
- package/dist/core/review/types.d.ts +0 -1
- package/dist/core/runtime/__tests__/install-id-cache-scoping.test.js +9 -5
- package/dist/core/runtime/__tests__/spawn-env.test.js +8 -9
- package/dist/core/runtime/broker/auth-reload.js +9 -10
- package/dist/core/runtime/broker/daemon-ops.d.ts +25 -8
- package/dist/core/runtime/broker/daemon-ops.js +42 -9
- package/dist/core/runtime/broker/extension-abort.d.ts +3 -0
- package/dist/core/runtime/broker/extension-abort.js +11 -0
- package/dist/core/runtime/broker/fault-retry.d.ts +15 -6
- package/dist/core/runtime/broker/fault-retry.js +142 -95
- package/dist/core/runtime/broker/inbox.d.ts +4 -32
- package/dist/core/runtime/broker/inbox.js +4 -92
- package/dist/core/runtime/broker/rebind.d.ts +1 -0
- package/dist/core/runtime/broker/rebind.js +21 -12
- package/dist/core/runtime/broker-persona-guidance.d.ts +1 -1
- package/dist/core/runtime/broker-persona-guidance.js +2 -13
- package/dist/core/runtime/broker.js +28 -22
- package/dist/core/runtime/close.d.ts +3 -9
- package/dist/core/runtime/close.js +16 -27
- package/dist/core/runtime/fault.d.ts +3 -93
- package/dist/core/runtime/fault.js +9 -419
- package/dist/core/runtime/kickoff.d.ts +3 -6
- package/dist/core/runtime/kickoff.js +12 -18
- package/dist/core/runtime/launch.js +1 -1
- package/dist/core/runtime/lifecycle.js +40 -7
- package/dist/core/runtime/nodes.d.ts +5 -1
- package/dist/core/runtime/nodes.js +26 -11
- package/dist/core/runtime/placement.js +2 -2
- package/dist/core/runtime/recycle.js +24 -14
- package/dist/core/runtime/reset.js +26 -7
- package/dist/core/runtime/revive.js +226 -217
- package/dist/core/runtime/spawn.d.ts +4 -1
- package/dist/core/runtime/spawn.js +43 -5
- package/dist/core/runtime/warm-pool.d.ts +2 -2
- package/dist/core/runtime/warm-pool.js +23 -3
- package/dist/core/scoped-state/db.d.ts +7 -0
- package/dist/core/scoped-state/db.js +92 -0
- package/dist/core/scoped-state/migrate.d.ts +11 -0
- package/dist/core/scoped-state/migrate.js +198 -0
- package/dist/core/scoped-state/paths.d.ts +9 -0
- package/dist/core/scoped-state/paths.js +27 -0
- package/dist/core/scoped-state/profiles.d.ts +12 -0
- package/dist/core/scoped-state/profiles.js +62 -0
- package/dist/core/scoped-state/providers.d.ts +16 -0
- package/dist/core/scoped-state/providers.js +8 -0
- package/dist/core/scoped-state/schema.d.ts +3 -0
- package/dist/core/scoped-state/schema.js +26 -0
- package/dist/core/scoped-state/settings.d.ts +28 -0
- package/dist/core/scoped-state/settings.js +82 -0
- package/dist/core/subscription-state.d.ts +29 -48
- package/dist/core/subscription-state.js +176 -712
- package/dist/core/worktree-close.js +4 -4
- package/dist/core/worktree-mutation-async.js +2 -2
- package/dist/core/worktree-sweep.js +11 -16
- package/dist/core/worktree.js +6 -12
- package/dist/daemon/__tests__/autostart-storm.test.js +1 -39
- package/dist/daemon/__tests__/helpers/source-daemon.d.ts +2 -2
- package/dist/daemon/__tests__/helpers/source-daemon.js +7 -6
- package/dist/daemon/__tests__/integration/migration-startup.test.js +59 -26
- package/dist/daemon/__tests__/node-deadline-lane.test.js +2 -1
- package/dist/daemon/__tests__/node-outcome-birth-invariants.test.js +41 -17
- package/dist/daemon/__tests__/node-outcome-delivery.test.js +39 -10
- package/dist/daemon/__tests__/reconciler-signature.test.js +2 -2
- package/dist/daemon/__tests__/subtree-filter-freshness.test.js +2 -2
- package/dist/daemon/api/__tests__/broker-settle-park.test.js +17 -12
- package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.js +27 -5
- package/dist/daemon/api/__tests__/model-config.test.js +8 -8
- package/dist/daemon/api/__tests__/node-create-description.test.js +22 -5
- package/dist/daemon/api/__tests__/node-model-validation.test.js +21 -1
- package/dist/daemon/api/__tests__/nodes-activity-query.test.js +10 -12
- package/dist/daemon/api/__tests__/profile-launch-gates.test.js +6 -3
- package/dist/daemon/api/__tests__/profile-metadata-route.test.js +4 -1
- package/dist/daemon/api/__tests__/reopen-delivery.test.js +26 -8
- package/dist/daemon/api/__tests__/seam/api-server.test.js +24 -32
- package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.js +4 -1
- package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +5 -4
- package/dist/daemon/api/__tests__/seam/profile-delete.test.js +29 -43
- package/dist/daemon/api/__tests__/submit-result.test.js +3 -2
- package/dist/daemon/api/bridge.js +1 -1
- package/dist/daemon/api/handlers/bash-jobs.js +6 -7
- package/dist/daemon/api/handlers/broker-ops.js +47 -84
- package/dist/daemon/api/handlers/broker-recovery.d.ts +4 -0
- package/dist/daemon/api/handlers/broker-recovery.js +251 -0
- package/dist/daemon/api/handlers/canvas.js +2 -44
- package/dist/daemon/api/handlers/daemon.js +41 -0
- package/dist/daemon/api/handlers/feedback-comments.js +2 -2
- package/dist/daemon/api/handlers/health.js +10 -5
- package/dist/daemon/api/handlers/human-requests.js +168 -188
- package/dist/daemon/api/handlers/human.js +3 -148
- package/dist/daemon/api/handlers/inbox-page.d.ts +4 -0
- package/dist/daemon/api/handlers/inbox-page.js +89 -0
- package/dist/daemon/api/handlers/inbox.js +21 -120
- package/dist/daemon/api/handlers/messages.d.ts +1 -0
- package/dist/daemon/api/handlers/messages.js +73 -15
- package/dist/daemon/api/handlers/node-outcomes.js +58 -13
- package/dist/daemon/api/handlers/nodes.d.ts +1 -0
- package/dist/daemon/api/handlers/nodes.js +41 -42
- package/dist/daemon/api/handlers/reviews.js +4 -29
- package/dist/daemon/api/map.d.ts +25 -3
- package/dist/daemon/api/map.js +84 -14
- package/dist/daemon/api/server.js +68 -9
- package/dist/daemon/control.d.ts +18 -0
- package/dist/daemon/cron/disposition.d.ts +2 -0
- package/dist/daemon/cron/disposition.js +8 -5
- package/dist/daemon/cron/settle.js +37 -13
- package/dist/daemon/cron/sinks.d.ts +18 -1
- package/dist/daemon/cron/sinks.js +47 -93
- package/dist/daemon/crtrd-cli.js +4 -19
- package/dist/daemon/crtrd.d.ts +2 -0
- package/dist/daemon/crtrd.js +206 -81
- package/dist/daemon/fleet.js +5 -6
- package/dist/daemon/human/finish.d.ts +12 -24
- package/dist/daemon/human/finish.js +88 -285
- package/dist/daemon/human/settle.d.ts +40 -0
- package/dist/daemon/human/settle.js +89 -0
- package/dist/daemon/human/sweep.d.ts +20 -5
- package/dist/daemon/human/sweep.js +56 -60
- package/dist/daemon/manage.d.ts +21 -16
- package/dist/daemon/manage.js +85 -51
- package/dist/daemon/messaging/node-message.d.ts +1 -1
- package/dist/daemon/messaging/node-message.js +9 -12
- package/dist/daemon/park-activity.js +3 -3
- package/dist/daemon/reconcilers/bash-deadline.js +6 -7
- package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
- package/dist/daemon/reconcilers/broker-supervision.js +41 -19
- package/dist/daemon/reconcilers/controller-death.js +6 -18
- package/dist/daemon/reconcilers/delivery-lane.d.ts +9 -0
- package/dist/daemon/reconcilers/delivery-lane.js +130 -0
- package/dist/daemon/reconcilers/live-obligation.js +3 -3
- package/dist/daemon/reconcilers/node-deadline.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +10 -12
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +5 -5
- package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -1
- package/dist/daemon/reconcilers/pending-review-submit.js +3 -3
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +2 -8
- package/dist/daemon/reconcilers/storage-maintenance.js +13 -43
- package/dist/daemon/review/companion.js +5 -11
- package/dist/daemon/review/deliver.d.ts +1 -5
- package/dist/daemon/review/deliver.js +3 -52
- package/dist/daemon/review/finish.d.ts +2 -27
- package/dist/daemon/review/finish.js +79 -263
- package/dist/daemon/review/sweep.d.ts +3 -10
- package/dist/daemon/review/sweep.js +13 -131
- package/dist/daemon/startup-policy.d.ts +0 -5
- package/dist/daemon/startup-policy.js +0 -5
- package/dist/hook-authoring.d.ts +28 -2
- package/dist/hook-authoring.js +53 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/migrations/__tests__/activation-concurrency.test.js +3 -2
- package/dist/migrations/__tests__/activation.test.js +9 -6
- package/dist/migrations/activation.d.ts +3 -2
- package/dist/migrations/activation.js +2 -4
- package/dist/migrations/corpus.d.ts +2 -5
- package/dist/migrations/corpus.js +9 -20
- package/dist/migrations/runner.d.ts +3 -1
- package/dist/migrations/runner.js +6 -2
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +21 -89
- package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.js +4 -2
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +51 -33
- package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +16 -2
- package/dist/pi-extensions/__tests__/pre-command-gate.test.js +13 -1
- package/dist/pi-extensions/canvas-inbox-watcher.js +98 -244
- package/dist/pi-extensions/canvas-passive-context.d.ts +4 -8
- package/dist/pi-extensions/canvas-passive-context.js +85 -37
- package/dist/pi-extensions/canvas-stophook.js +47 -31
- package/dist/shared/env.d.ts +1 -0
- package/dist/shared/env.js +3 -0
- package/package.json +1 -1
- package/runtime.lock.json +5 -5
- package/dist/clients/attach/__tests__/page-block.test.js +0 -54
- package/dist/clients/inbox/review-visibility.d.ts +0 -5
- package/dist/clients/inbox/review-visibility.js +0 -19
- package/dist/commands/canvas-rebuild-index.d.ts +0 -2
- package/dist/commands/canvas-rebuild-index.js +0 -46
- package/dist/core/__tests__/human-cancel-guard.test.js +0 -110
- package/dist/core/__tests__/human-deliver.test.d.ts +0 -1
- package/dist/core/__tests__/human-deliver.test.js +0 -256
- package/dist/core/__tests__/human-node-not-supervised.test.d.ts +0 -1
- package/dist/core/__tests__/human-node-not-supervised.test.js +0 -89
- package/dist/core/__tests__/integration/human-deliver-e2e.test.d.ts +0 -1
- package/dist/core/__tests__/integration/human-deliver-e2e.test.js +0 -131
- package/dist/core/__tests__/phase4-review-store.test.d.ts +0 -1
- package/dist/core/__tests__/phase4-review-store.test.js +0 -144
- package/dist/core/__tests__/watchdog-abort-arms-retry.test.d.ts +0 -1
- package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +0 -110
- package/dist/core/canvas/human-deliveries.d.ts +0 -39
- package/dist/core/canvas/human-deliveries.js +0 -75
- package/dist/core/canvas/node-outcome-deliveries.d.ts +0 -64
- package/dist/core/canvas/node-outcome-deliveries.js +0 -159
- package/dist/core/feed/passive.d.ts +0 -3
- package/dist/core/feed/passive.js +0 -53
- package/dist/core/human/__tests__/inbox-cancel-worker.d.ts +0 -1
- package/dist/core/human/__tests__/inbox-cancel-worker.js +0 -7
- package/dist/core/human/__tests__/inbox-claim-worker.d.ts +0 -1
- package/dist/core/human/__tests__/inbox-claim-worker.js +0 -17
- package/dist/core/human/__tests__/inbox-stale-claim-worker.d.ts +0 -1
- package/dist/core/human/__tests__/inbox-stale-claim-worker.js +0 -8
- package/dist/core/human/__tests__/integration/inbox-core.test.d.ts +0 -1
- package/dist/core/human/__tests__/integration/inbox-core.test.js +0 -145
- package/dist/core/human/__tests__/page-tickets.test.d.ts +0 -1
- package/dist/core/human/__tests__/page-tickets.test.js +0 -161
- package/dist/core/review/ticket-filter.d.ts +0 -17
- package/dist/core/review/ticket-filter.js +0 -21
- package/dist/core/runtime/broker/passive.d.ts +0 -17
- package/dist/core/runtime/broker/passive.js +0 -44
- package/dist/core/runtime/busy.d.ts +0 -46
- package/dist/core/runtime/busy.js +0 -150
- package/dist/daemon/__tests__/startup-block-marker.test.d.ts +0 -1
- package/dist/daemon/__tests__/startup-block-marker.test.js +0 -86
- package/dist/daemon/api/__tests__/review-terminal-conflict.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/review-terminal-conflict.test.js +0 -98
- package/dist/daemon/human/deliver-action.d.ts +0 -3
- package/dist/daemon/human/deliver-action.js +0 -9
- package/dist/daemon/node-outcome/deliver-outcome.d.ts +0 -3
- package/dist/daemon/node-outcome/deliver-outcome.js +0 -9
- package/dist/daemon/reconcilers/human-delivery-lane.d.ts +0 -10
- package/dist/daemon/reconcilers/human-delivery-lane.js +0 -41
- package/dist/daemon/reconcilers/node-outcome-delivery-lane.d.ts +0 -10
- package/dist/daemon/reconcilers/node-outcome-delivery-lane.js +0 -41
- package/dist/daemon/startup-block-marker.d.ts +0 -25
- package/dist/daemon/startup-block-marker.js +0 -99
- /package/dist/{clients/attach/__tests__/page-block.test.d.ts → api/dto/mail.js} +0 -0
- /package/dist/{commands/sys/__tests__/migrate.test.d.ts → api/dto/recovery.js} +0 -0
- /package/dist/{core/__tests__/human-cancel-guard.test.d.ts → commands/__tests__/integration/migrate.test.d.ts} +0 -0
|
@@ -1,27 +1,20 @@
|
|
|
1
|
-
// Durable programmatic human requests — crtrd `/v1/human/requests`. A request
|
|
2
|
-
// is an ordinary page ticket with an optional frozen completion action, so it
|
|
3
|
-
// is the same record the inbox lists, answers, and dismisses. Creation is the
|
|
4
|
-
// only surface that writes the action binding; every settlement path funnels
|
|
5
|
-
// through the shared first-writer-wins store.
|
|
6
|
-
import { randomBytes } from 'node:crypto';
|
|
7
1
|
import { statSync } from 'node:fs';
|
|
8
|
-
import {
|
|
2
|
+
import { isAbsolute } from 'node:path';
|
|
9
3
|
import { ApiError } from '../../../api/index.js';
|
|
10
|
-
import {
|
|
4
|
+
import { readExternalActionDelivery } from '../../../core/canvas/deliveries.js';
|
|
5
|
+
import { isSafeNodeId } from '../../../core/canvas/paths.js';
|
|
11
6
|
import { resolvePageComponents } from '../../../core/config.js';
|
|
12
7
|
import { resolveHumanAction } from '../../../core/human-actions.js';
|
|
13
|
-
import { HUMAN_ACTION_NAME_PATTERN
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import { preparePageSource, publishPage, readPageTicket, readTicketResult, validatePageTicketResponses, } from '../../../core/human/tickets.js';
|
|
8
|
+
import { HUMAN_ACTION_NAME_PATTERN } from '../../../core/human/action-binding.js';
|
|
9
|
+
import { createPageRequest, getRequest } from '../../../core/human/requests.js';
|
|
10
|
+
import { preparePageSource } from '../../../core/human/page-authoring.js';
|
|
11
|
+
import { publishPage, validatePageTicketResponses } from '../../../core/human/tickets.js';
|
|
18
12
|
import { cancelHumanTicket, resolvePageTicket } from '../../human/finish.js';
|
|
19
|
-
import {
|
|
13
|
+
import { inboxPageProjection } from './inbox-page.js';
|
|
20
14
|
const REASON_MAX = 1000;
|
|
21
15
|
const ACTOR_MAX = 200;
|
|
22
16
|
const DEFAULT_DELIVERY = { placement: 'inline', inbox: true, reply: false };
|
|
23
17
|
const SOURCE_FIELDS = ['sessionName', 'askedBy', 'emittedAt', 'profileName', 'nodeId'];
|
|
24
|
-
// Body validation
|
|
25
18
|
function isPlainObject(value) {
|
|
26
19
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
27
20
|
}
|
|
@@ -31,39 +24,39 @@ function requireNoExtraKeys(obj, allowed, where) {
|
|
|
31
24
|
throw new ApiError(400, 'invalid_request', `unexpected field in ${where}: ${key}`);
|
|
32
25
|
}
|
|
33
26
|
}
|
|
34
|
-
function invalid(message) {
|
|
35
|
-
return new ApiError(400, 'invalid_request', message);
|
|
36
|
-
}
|
|
27
|
+
function invalid(message) { return new ApiError(400, 'invalid_request', message); }
|
|
37
28
|
function validatePage(raw) {
|
|
38
29
|
if (!isPlainObject(raw))
|
|
39
30
|
throw invalid('`page` must be an object');
|
|
40
31
|
requireNoExtraKeys(raw, ['dialect', 'source'], '`page`');
|
|
41
|
-
|
|
42
|
-
if (dialect !== 'jsx' && dialect !== 'html')
|
|
32
|
+
if (raw['dialect'] !== 'jsx' && raw['dialect'] !== 'html')
|
|
43
33
|
throw invalid('`page.dialect` must be "jsx" or "html"');
|
|
44
|
-
|
|
45
|
-
if (typeof source !== 'string' || source.trim() === '')
|
|
34
|
+
if (typeof raw['source'] !== 'string' || raw['source'].trim() === '')
|
|
46
35
|
throw invalid('`page.source` must be the authored page text');
|
|
47
|
-
return { dialect, source };
|
|
36
|
+
return { dialect: raw['dialect'], source: raw['source'] };
|
|
37
|
+
}
|
|
38
|
+
function validatePlacement(raw, fallback) {
|
|
39
|
+
const placement = raw ?? fallback;
|
|
40
|
+
if (placement !== 'inline' && placement !== 'panel')
|
|
41
|
+
throw invalid('`delivery.placement` must be "inline" or "panel"');
|
|
42
|
+
return placement;
|
|
48
43
|
}
|
|
49
|
-
|
|
50
|
-
function validateCreateDelivery(raw) {
|
|
44
|
+
function validateCreateDelivery(raw, requesterNodeId) {
|
|
51
45
|
if (raw === undefined)
|
|
52
46
|
return DEFAULT_DELIVERY;
|
|
53
47
|
if (!isPlainObject(raw))
|
|
54
48
|
throw invalid('`delivery` must be an object');
|
|
55
49
|
requireNoExtraKeys(raw, ['placement', 'inbox', 'reply'], '`delivery`');
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
50
|
+
const inbox = raw['inbox'] ?? DEFAULT_DELIVERY.inbox;
|
|
51
|
+
const reply = raw['reply'] ?? DEFAULT_DELIVERY.reply;
|
|
52
|
+
if (typeof inbox !== 'boolean')
|
|
53
|
+
throw invalid('`delivery.inbox` must be boolean');
|
|
54
|
+
if (typeof reply !== 'boolean')
|
|
55
|
+
throw invalid('`delivery.reply` must be boolean');
|
|
56
|
+
if (reply && requesterNodeId === null)
|
|
57
|
+
throw invalid('`delivery.reply` requires `requester_node_id`');
|
|
58
|
+
return { placement: validatePlacement(raw['placement'], DEFAULT_DELIVERY.placement), inbox, reply };
|
|
64
59
|
}
|
|
65
|
-
/** Replace re-presents a pending page; where the ticket is routed is fixed at
|
|
66
|
-
* creation, so only placement is replaceable. */
|
|
67
60
|
function validateReplaceDelivery(raw, prior) {
|
|
68
61
|
if (raw === undefined)
|
|
69
62
|
return prior;
|
|
@@ -72,12 +65,6 @@ function validateReplaceDelivery(raw, prior) {
|
|
|
72
65
|
requireNoExtraKeys(raw, ['placement'], '`delivery`');
|
|
73
66
|
return { ...prior, placement: validatePlacement(raw['placement'], prior.placement) };
|
|
74
67
|
}
|
|
75
|
-
function validatePlacement(raw, fallback) {
|
|
76
|
-
const placement = raw ?? fallback;
|
|
77
|
-
if (placement !== 'inline' && placement !== 'panel')
|
|
78
|
-
throw invalid('`delivery.placement` must be "inline" or "panel"');
|
|
79
|
-
return placement;
|
|
80
|
-
}
|
|
81
68
|
function validateSource(raw) {
|
|
82
69
|
if (raw === undefined)
|
|
83
70
|
return undefined;
|
|
@@ -117,40 +104,43 @@ function validateActionSelection(raw) {
|
|
|
117
104
|
if (!isPlainObject(raw))
|
|
118
105
|
throw invalid('`action` must be an object');
|
|
119
106
|
requireNoExtraKeys(raw, ['name', 'payload'], '`action`');
|
|
120
|
-
|
|
121
|
-
if (typeof name !== 'string' || !HUMAN_ACTION_NAME_PATTERN.test(name)) {
|
|
107
|
+
if (typeof raw['name'] !== 'string' || !HUMAN_ACTION_NAME_PATTERN.test(raw['name']))
|
|
122
108
|
throw invalid('`action.name` must be a declared action name');
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
109
|
+
return { name: raw['name'], payload: raw['payload'] ?? null };
|
|
110
|
+
}
|
|
111
|
+
function validateRequesterNodeId(raw) {
|
|
112
|
+
if (raw === undefined || raw === null)
|
|
113
|
+
return null;
|
|
114
|
+
if (typeof raw !== 'string' || !isSafeNodeId(raw))
|
|
115
|
+
throw invalid('`requester_node_id` must be a safe node id or null');
|
|
116
|
+
return raw;
|
|
127
117
|
}
|
|
128
118
|
function validateCreateRequest(raw) {
|
|
129
119
|
if (!isPlainObject(raw))
|
|
130
120
|
throw invalid('request body is required');
|
|
131
|
-
requireNoExtraKeys(raw, ['page', 'delivery', 'source', 'creator_cwd', 'action'], 'the request body');
|
|
121
|
+
requireNoExtraKeys(raw, ['page', 'delivery', 'source', 'requester_node_id', 'creator_cwd', 'action'], 'the request body');
|
|
132
122
|
const source = validateSource(raw['source']);
|
|
123
|
+
const requesterNodeId = validateRequesterNodeId(raw['requester_node_id']);
|
|
133
124
|
const action = validateActionSelection(raw['action']);
|
|
134
125
|
return {
|
|
135
126
|
page: validatePage(raw['page']),
|
|
136
|
-
delivery: validateCreateDelivery(raw['delivery']),
|
|
127
|
+
delivery: validateCreateDelivery(raw['delivery'], requesterNodeId),
|
|
137
128
|
...(source === undefined ? {} : { source }),
|
|
129
|
+
requesterNodeId,
|
|
138
130
|
creatorCwd: validateCreatorCwd(raw['creator_cwd']),
|
|
139
131
|
...(action === undefined ? {} : { action }),
|
|
140
132
|
};
|
|
141
133
|
}
|
|
142
|
-
function validateReplaceRequest(raw,
|
|
134
|
+
function validateReplaceRequest(raw, prior) {
|
|
143
135
|
if (!isPlainObject(raw))
|
|
144
136
|
throw invalid('request body is required');
|
|
145
137
|
requireNoExtraKeys(raw, ['page', 'delivery'], 'the request body');
|
|
146
|
-
return { page: validatePage(raw['page']), delivery: validateReplaceDelivery(raw['delivery'],
|
|
138
|
+
return { page: validatePage(raw['page']), delivery: validateReplaceDelivery(raw['delivery'], prior) };
|
|
147
139
|
}
|
|
148
140
|
function optionalBoundedString(raw, field, max) {
|
|
149
141
|
if (raw === undefined)
|
|
150
142
|
return undefined;
|
|
151
|
-
if (typeof raw !== 'string')
|
|
152
|
-
throw invalid(`\`${field}\` must be a string`);
|
|
153
|
-
if (raw.trim() === '' || raw.length > max)
|
|
143
|
+
if (typeof raw !== 'string' || raw.trim() === '' || raw.length > max)
|
|
154
144
|
throw invalid(`\`${field}\` must be nonempty after trim and at most ${max} characters`);
|
|
155
145
|
return raw;
|
|
156
146
|
}
|
|
@@ -173,92 +163,111 @@ function validateSettleRequest(raw) {
|
|
|
173
163
|
const actor = optionalBoundedString(raw['actor'], 'actor', ACTOR_MAX);
|
|
174
164
|
return { ...(reason === undefined ? {} : { reason }), ...(actor === undefined ? {} : { actor }) };
|
|
175
165
|
}
|
|
176
|
-
function
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
166
|
+
function requestId(ctx) {
|
|
167
|
+
const id = ctx.params['request_id'];
|
|
168
|
+
if (typeof id !== 'string' || id === '')
|
|
169
|
+
throw invalid('request id is required');
|
|
170
|
+
return id;
|
|
171
|
+
}
|
|
172
|
+
function requirePageRequest(id) {
|
|
173
|
+
const request = getRequest(id);
|
|
174
|
+
if (request === null || request.kind !== 'page')
|
|
180
175
|
throw new ApiError(404, 'not_found', 'no request with that id');
|
|
181
|
-
|
|
176
|
+
return request;
|
|
177
|
+
}
|
|
178
|
+
function manifest(request) {
|
|
182
179
|
try {
|
|
183
|
-
|
|
180
|
+
const value = JSON.parse(request.specification_json);
|
|
181
|
+
if (!isPlainObject(value))
|
|
182
|
+
throw new Error('not an object');
|
|
183
|
+
return value;
|
|
184
184
|
}
|
|
185
185
|
catch {
|
|
186
|
-
throw new ApiError(500, 'internal', 'the request could not be read');
|
|
186
|
+
throw new ApiError(500, 'internal', 'the request specification could not be read');
|
|
187
187
|
}
|
|
188
|
-
return {
|
|
189
|
-
requestId,
|
|
190
|
-
ticketId: resolved.ticketId,
|
|
191
|
-
dir: resolved.dir,
|
|
192
|
-
manifest,
|
|
193
|
-
result: readTicketResult(resolved.dir),
|
|
194
|
-
binding: readTicketActionBinding(resolved.dir),
|
|
195
|
-
};
|
|
196
188
|
}
|
|
197
|
-
function
|
|
198
|
-
if (
|
|
189
|
+
function terminalResult(request) {
|
|
190
|
+
if (request.result_json === null)
|
|
191
|
+
return null;
|
|
192
|
+
try {
|
|
193
|
+
return JSON.parse(request.result_json);
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
throw new ApiError(500, 'internal', 'the request result could not be read');
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function frozenAction(request) {
|
|
200
|
+
if (request.action_json === null)
|
|
201
|
+
return null;
|
|
202
|
+
try {
|
|
203
|
+
const action = JSON.parse(request.action_json);
|
|
204
|
+
if (action.schema !== 'crtr.human-action-binding/v1' || typeof action.name !== 'string')
|
|
205
|
+
throw new Error('invalid action');
|
|
206
|
+
return action;
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
throw new ApiError(500, 'internal', 'the request action could not be read');
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function requestState(request) {
|
|
213
|
+
if (request.state !== 'settled')
|
|
199
214
|
return 'pending';
|
|
200
|
-
|
|
201
|
-
return completionEventFor(result);
|
|
202
|
-
return 'answered';
|
|
215
|
+
return request.outcome === 'answered' ? 'answered' : request.outcome === 'dismissed' ? 'dismissed' : 'canceled';
|
|
203
216
|
}
|
|
204
|
-
function deliveryDetail(
|
|
205
|
-
if (
|
|
217
|
+
function deliveryDetail(request) {
|
|
218
|
+
if (request.action_delivery_id === null)
|
|
206
219
|
return { state: 'none', attempt: 0 };
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if (
|
|
213
|
-
detail.
|
|
214
|
-
if (
|
|
215
|
-
detail.
|
|
216
|
-
if (
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
...(failure.exitCode === undefined ? {} : { exit_code: failure.exitCode }),
|
|
221
|
-
...(failure.signal === undefined ? {} : { signal: failure.signal }),
|
|
222
|
-
...(failure.message === undefined ? {} : { message: failure.message }),
|
|
223
|
-
...(failure.stderr === undefined ? {} : { stderr: failure.stderr }),
|
|
224
|
-
};
|
|
225
|
-
}
|
|
220
|
+
const delivery = readExternalActionDelivery(`human-action:${request.inbox_ticket_id}`);
|
|
221
|
+
if (delivery === null)
|
|
222
|
+
return { state: 'none', attempt: 0 };
|
|
223
|
+
const state = delivery.state === 'acknowledged' ? 'accepted' : delivery.state === 'permanent_failed' ? 'permanent_failed' : delivery.state === 'handed_off' ? 'running' : 'pending';
|
|
224
|
+
const detail = { state, attempt: delivery.attempts };
|
|
225
|
+
if (state === 'pending' && delivery.nextAttemptAt !== null)
|
|
226
|
+
detail.next_attempt_at = new Date(delivery.nextAttemptAt).toISOString();
|
|
227
|
+
if (delivery.acknowledgedAt !== null)
|
|
228
|
+
detail.accepted_at = new Date(delivery.acknowledgedAt).toISOString();
|
|
229
|
+
if (delivery.failedAt !== null)
|
|
230
|
+
detail.permanent_failed_at = new Date(delivery.failedAt).toISOString();
|
|
231
|
+
if (delivery.lastFailure !== null)
|
|
232
|
+
detail.last_failure = delivery.lastFailure;
|
|
226
233
|
return detail;
|
|
227
234
|
}
|
|
228
235
|
function requestToDTO(request) {
|
|
229
|
-
const
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
throw new ApiError(500, 'internal', 'the request carries no emitted time');
|
|
233
|
-
const state = requestState(result);
|
|
236
|
+
const page = manifest(request);
|
|
237
|
+
const result = terminalResult(request);
|
|
238
|
+
const state = requestState(request);
|
|
234
239
|
const dto = {
|
|
235
|
-
request_id: request.
|
|
240
|
+
request_id: request.request_id,
|
|
241
|
+
inbox_ticket_id: request.inbox_ticket_id,
|
|
242
|
+
request_dir: request.request_dir,
|
|
243
|
+
kind: request.kind,
|
|
236
244
|
state,
|
|
237
|
-
title:
|
|
238
|
-
source:
|
|
239
|
-
emitted_at: emittedAt,
|
|
245
|
+
title: request.title,
|
|
246
|
+
source: page.source ?? {},
|
|
247
|
+
emitted_at: page.source?.emittedAt ?? request.created_at,
|
|
240
248
|
};
|
|
241
|
-
if (
|
|
242
|
-
dto.subtitle =
|
|
249
|
+
if (request.subtitle !== null)
|
|
250
|
+
dto.subtitle = request.subtitle;
|
|
251
|
+
if (request.kind === 'page')
|
|
252
|
+
dto.page = inboxPageProjection(request);
|
|
243
253
|
if (result !== null) {
|
|
244
|
-
dto.settled_at =
|
|
245
|
-
|
|
246
|
-
if (state === 'answered' && result.kind === 'page')
|
|
254
|
+
dto.settled_at = request.settled_at ?? request.updated_at;
|
|
255
|
+
if (result.kind === 'page' && state === 'answered')
|
|
247
256
|
dto.responses = result.responses;
|
|
248
257
|
if (result.kind === 'canceled' && result.reason !== undefined)
|
|
249
258
|
dto.reason = result.reason;
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
259
|
+
if (result.kind === 'page' && result.actor !== undefined)
|
|
260
|
+
dto.actor = result.actor;
|
|
261
|
+
if (result.kind === 'canceled' && result.actor !== undefined)
|
|
262
|
+
dto.actor = result.actor;
|
|
253
263
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
dto.
|
|
264
|
+
const action = frozenAction(request);
|
|
265
|
+
if (action !== null) {
|
|
266
|
+
dto.action = { name: action.name, payload: action.payload };
|
|
267
|
+
dto.delivery = deliveryDetail(request);
|
|
257
268
|
}
|
|
258
269
|
return dto;
|
|
259
270
|
}
|
|
260
|
-
// POST /v1/human/requests — create
|
|
261
|
-
/** Authoring failure is the caller's malformed page, never a server fault. */
|
|
262
271
|
function prepareOrReject(dialect, document, source, delivery) {
|
|
263
272
|
try {
|
|
264
273
|
return preparePageSource({ dialect, document, source, delivery, productKinds: resolvePageComponents() });
|
|
@@ -269,9 +278,7 @@ function prepareOrReject(dialect, document, source, delivery) {
|
|
|
269
278
|
}
|
|
270
279
|
function handleCreate(ctx) {
|
|
271
280
|
const request = validateCreateRequest(ctx.body);
|
|
272
|
-
|
|
273
|
-
// inbox row for a human to answer.
|
|
274
|
-
let resolvedAction;
|
|
281
|
+
let actionJson;
|
|
275
282
|
if (request.action !== undefined) {
|
|
276
283
|
const resolution = resolveHumanAction(request.action.name, request.creatorCwd);
|
|
277
284
|
if ('kind' in resolution) {
|
|
@@ -280,120 +287,93 @@ function handleCreate(ctx) {
|
|
|
280
287
|
: `${resolution.name} is declared in ${resolution.configOrigin} but unusable: ${resolution.reason}`;
|
|
281
288
|
throw new ApiError(400, resolution.kind, detail);
|
|
282
289
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const dir = ticketDir(`page-${randomBytes(8).toString('hex')}`);
|
|
287
|
-
// The binding is written before the page exists, so a visible request is
|
|
288
|
-
// never momentarily unbound and `replace` can never reach the approved effect.
|
|
289
|
-
if (request.action !== undefined && resolvedAction !== undefined) {
|
|
290
|
-
publishTicketActionBinding(dir, {
|
|
291
|
-
schema: 'crtr.human-action-binding/v1',
|
|
292
|
-
name: request.action.name,
|
|
293
|
-
payload: request.action.payload,
|
|
294
|
-
creatorCwd: request.creatorCwd,
|
|
295
|
-
configOrigin: resolvedAction.configOrigin,
|
|
296
|
-
argv: resolvedAction.argv,
|
|
297
|
-
cwd: resolvedAction.cwd,
|
|
290
|
+
actionJson = JSON.stringify({
|
|
291
|
+
schema: 'crtr.human-action-binding/v1', name: request.action.name, payload: request.action.payload,
|
|
292
|
+
creatorCwd: request.creatorCwd, configOrigin: resolution.configOrigin, argv: resolution.argv, cwd: resolution.cwd,
|
|
298
293
|
});
|
|
299
294
|
}
|
|
300
|
-
const
|
|
295
|
+
const prepared = prepareOrReject(request.page.dialect, request.page.source, request.source, request.delivery);
|
|
296
|
+
const created = createPageRequest({
|
|
297
|
+
prepared,
|
|
298
|
+
requester_node_id: request.requesterNodeId,
|
|
299
|
+
...(actionJson === undefined ? {} : { action_json: actionJson }),
|
|
300
|
+
});
|
|
301
301
|
return {
|
|
302
302
|
status: 201,
|
|
303
|
-
body: {
|
|
304
|
-
request_id: opaqueInboxTicketId(basename(published.dir)),
|
|
305
|
-
state: 'pending',
|
|
306
|
-
...(request.action === undefined ? {} : { action: { name: request.action.name } }),
|
|
307
|
-
delivery_state: 'none',
|
|
308
|
-
},
|
|
303
|
+
body: { request_id: created.request_id, request_dir: created.request_dir, state: 'pending', ...(request.action === undefined ? {} : { action: { name: request.action.name } }), delivery_state: 'none' },
|
|
309
304
|
};
|
|
310
305
|
}
|
|
311
|
-
// GET /v1/human/requests/:request_id — read
|
|
312
306
|
function handleGet(ctx) {
|
|
313
|
-
return { status: 200, body: requestToDTO(
|
|
307
|
+
return { status: 200, body: requestToDTO(requirePageRequest(requestId(ctx))) };
|
|
314
308
|
}
|
|
315
|
-
// POST /v1/human/requests/:request_id/replace — revise the pending page
|
|
316
309
|
function handleReplace(ctx) {
|
|
317
|
-
const request =
|
|
318
|
-
if (request.
|
|
310
|
+
const request = requirePageRequest(requestId(ctx));
|
|
311
|
+
if (request.state === 'settled')
|
|
319
312
|
throw new ApiError(409, 'already_settled', 'the request already has a terminal result');
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
313
|
+
const page = manifest(request);
|
|
314
|
+
const body = validateReplaceRequest(ctx.body, page.delivery);
|
|
315
|
+
const prepared = prepareOrReject(body.page.dialect, body.page.source, page.source, body.delivery);
|
|
316
|
+
try {
|
|
317
|
+
publishPage(request.request_dir, prepared);
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
if (error instanceof Error && error.message === `page request is not open: ${request.request_id}`) {
|
|
321
|
+
throw new ApiError(409, 'already_settled', 'the request already has a terminal result');
|
|
322
|
+
}
|
|
323
|
+
throw error;
|
|
324
|
+
}
|
|
325
|
+
return { status: 200, body: requestToDTO(requirePageRequest(request.request_id)) };
|
|
326
326
|
}
|
|
327
|
-
// Settlement — respond, dismiss, cancel
|
|
328
|
-
/** The settlement funnels speak the inbox's error vocabulary; requests speak
|
|
329
|
-
* the wire contract's. This is the one translation. */
|
|
330
327
|
function settlementError(error) {
|
|
331
|
-
if (error instanceof ApiError)
|
|
332
|
-
if (error.code === 'ticket_already_resolved')
|
|
333
|
-
return new ApiError(409, 'already_settled', 'the request already has a terminal result');
|
|
334
|
-
if (error.code === 'page_has_no_response_lifecycle')
|
|
335
|
-
return new ApiError(409, 'not_settleable', 'this request carries no response lifecycle');
|
|
328
|
+
if (error instanceof ApiError)
|
|
336
329
|
return error;
|
|
337
|
-
|
|
338
|
-
|
|
330
|
+
if (error instanceof Error && error.message.includes('unknown page request'))
|
|
331
|
+
return new ApiError(404, 'not_found', 'no request with that id');
|
|
332
|
+
if (error instanceof Error && error.message === 'page_has_no_response_lifecycle')
|
|
339
333
|
return new ApiError(409, 'not_settleable', 'this request carries no response lifecycle');
|
|
340
|
-
}
|
|
341
334
|
return new ApiError(500, 'internal', 'the request could not be settled');
|
|
342
335
|
}
|
|
343
336
|
function requireSettleable(request) {
|
|
344
|
-
if (request.
|
|
337
|
+
if (request.state === 'settled')
|
|
345
338
|
throw new ApiError(409, 'already_settled', 'the request already has a terminal result');
|
|
346
|
-
if (
|
|
339
|
+
if (!request.settleable)
|
|
347
340
|
throw new ApiError(409, 'not_settleable', 'this request carries no response lifecycle');
|
|
348
|
-
}
|
|
349
341
|
}
|
|
350
342
|
async function handleRespond(ctx) {
|
|
351
|
-
const request =
|
|
343
|
+
const request = requirePageRequest(requestId(ctx));
|
|
352
344
|
const body = validateRespondRequest(ctx.body);
|
|
353
345
|
requireSettleable(request);
|
|
354
346
|
try {
|
|
355
|
-
validatePageTicketResponses(request.
|
|
347
|
+
validatePageTicketResponses(request.request_dir, body.responses);
|
|
356
348
|
}
|
|
357
349
|
catch (error) {
|
|
358
|
-
// `requireSettleable` already refused a page with no response lifecycle, so
|
|
359
|
-
// anything left here is the caller's response map.
|
|
360
350
|
throw invalid(error instanceof Error ? error.message : 'the response map is invalid');
|
|
361
351
|
}
|
|
362
|
-
let result;
|
|
363
352
|
try {
|
|
364
|
-
|
|
353
|
+
await resolvePageTicket(request.request_id, body.responses, body.actor === undefined ? {} : { actor: body.actor });
|
|
365
354
|
}
|
|
366
355
|
catch (error) {
|
|
367
356
|
throw settlementError(error);
|
|
368
357
|
}
|
|
369
|
-
return { status: 200, body: requestToDTO(
|
|
358
|
+
return { status: 200, body: requestToDTO(requirePageRequest(request.request_id)) };
|
|
370
359
|
}
|
|
371
360
|
async function settle(ctx, disposition) {
|
|
372
|
-
const request =
|
|
361
|
+
const request = requirePageRequest(requestId(ctx));
|
|
373
362
|
const body = validateSettleRequest(ctx.body);
|
|
374
363
|
requireSettleable(request);
|
|
375
|
-
let result;
|
|
376
364
|
try {
|
|
377
|
-
|
|
365
|
+
await cancelHumanTicket(request.request_id, { ...body, disposition });
|
|
378
366
|
}
|
|
379
367
|
catch (error) {
|
|
380
368
|
throw settlementError(error);
|
|
381
369
|
}
|
|
382
|
-
return { status: 200, body: requestToDTO(
|
|
383
|
-
}
|
|
384
|
-
/** The recipient surface deliberately closing the request without answering. */
|
|
385
|
-
function handleDismiss(ctx) {
|
|
386
|
-
return settle(ctx, 'dismissed');
|
|
387
|
-
}
|
|
388
|
-
/** The requester withdrawing its own request. */
|
|
389
|
-
function handleCancel(ctx) {
|
|
390
|
-
return settle(ctx, 'canceled');
|
|
370
|
+
return { status: 200, body: requestToDTO(requirePageRequest(request.request_id)) };
|
|
391
371
|
}
|
|
392
372
|
export const humanRequestRoutes = [
|
|
393
373
|
{ method: 'POST', pattern: '/v1/human/requests', handler: handleCreate },
|
|
394
374
|
{ method: 'GET', pattern: '/v1/human/requests/:request_id', handler: handleGet },
|
|
395
375
|
{ method: 'POST', pattern: '/v1/human/requests/:request_id/replace', handler: handleReplace },
|
|
396
376
|
{ method: 'POST', pattern: '/v1/human/requests/:request_id/respond', handler: handleRespond },
|
|
397
|
-
{ method: 'POST', pattern: '/v1/human/requests/:request_id/dismiss', handler:
|
|
398
|
-
{ method: 'POST', pattern: '/v1/human/requests/:request_id/cancel', handler:
|
|
377
|
+
{ method: 'POST', pattern: '/v1/human/requests/:request_id/dismiss', handler: (ctx) => settle(ctx, 'dismissed') },
|
|
378
|
+
{ method: 'POST', pattern: '/v1/human/requests/:request_id/cancel', handler: (ctx) => settle(ctx, 'canceled') },
|
|
399
379
|
];
|