@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,22 +1,10 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// burst, and hands hidden context cards and visible deliveries to pi. A
|
|
5
|
-
// burst mixing a person's words with node reports splits into several visible
|
|
6
|
-
// deliveries, one per cycle. A send return is only a handoff. Exact cursor persistence at agent_settled is the
|
|
7
|
-
// durable boundary; an uncommitted process exit is recovered by rereading from
|
|
8
|
-
// the unchanged cursor.
|
|
9
|
-
//
|
|
10
|
-
// Context sends never trigger a turn: the visible human delivery is the sole
|
|
11
|
-
// trigger, so the agent cannot run on context alone before hearing the person.
|
|
12
|
-
// A context-only batch keeps its wake by triggering on its LAST card while idle,
|
|
13
|
-
// and rides the running turn while streaming. A deferred-only idle batch stays
|
|
14
|
-
// held until either durable mail wakes a turn or the broker prepends it to an
|
|
15
|
-
// already-admitted live human prompt; that bridge still commits only at
|
|
16
|
-
// agent_settled.
|
|
1
|
+
// Wake mail is claimed through the daemon and acknowledged by delivery identity
|
|
2
|
+
// only after Pi settles. Deferred mail rides a natural input; a refused turn
|
|
3
|
+
// releases its claims instead of acknowledging content the model never consumed.
|
|
17
4
|
import { envNodeId, envProfileId, envWatcherDebounceMs, envWatcherTickMs } from '../shared/env.js';
|
|
18
|
-
import { coalesceBrokerInbox, entryCards,
|
|
19
|
-
import {
|
|
5
|
+
import { coalesceBrokerInbox, entryCards, reportRefNodeId, } from '../core/runtime/broker/inbox.js';
|
|
6
|
+
import { acknowledgeBrokerMail, claimBrokerMail, brokerExtensionState } from '../core/runtime/broker/daemon-ops.js';
|
|
7
|
+
import { wasTurnRefused } from '../core/runtime/broker/extension-abort.js';
|
|
20
8
|
import { announceMessageOrigin } from '../core/runtime/stamp/channel.js';
|
|
21
9
|
import { captureGoalIfAbsent, generateAndCommitInitialName } from './broker-local.js';
|
|
22
10
|
import { emitEvent } from '../core/events/emit.js';
|
|
@@ -45,23 +33,11 @@ function currentNodeId() {
|
|
|
45
33
|
const nodeId = envNodeId();
|
|
46
34
|
return nodeId === undefined || nodeId.trim() === '' ? undefined : nodeId;
|
|
47
35
|
}
|
|
48
|
-
/**
|
|
49
|
-
* manifest file directly, so a live broker sees the flip on its next tick with
|
|
50
|
-
* no daemon round-trip. '' is the historical no-profile row. */
|
|
36
|
+
/** Profile pause is read fresh each poll from its owning scoped store. */
|
|
51
37
|
function profilePaused() {
|
|
52
38
|
const profileId = envProfileId();
|
|
53
39
|
return profileId !== undefined && profileId !== '' && isProfilePaused(profileId);
|
|
54
40
|
}
|
|
55
|
-
function isFilesystemError(error) {
|
|
56
|
-
if (typeof error !== 'object' || error === null)
|
|
57
|
-
return false;
|
|
58
|
-
try {
|
|
59
|
-
return typeof error.code === 'string';
|
|
60
|
-
}
|
|
61
|
-
catch {
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
41
|
function safeErrorClass(error) {
|
|
66
42
|
try {
|
|
67
43
|
return errorClassFromError(error);
|
|
@@ -75,7 +51,7 @@ function emitBestEffort(input) {
|
|
|
75
51
|
emitEvent(input);
|
|
76
52
|
}
|
|
77
53
|
catch {
|
|
78
|
-
//
|
|
54
|
+
// SQL delivery state remains authoritative if diagnostics fail.
|
|
79
55
|
}
|
|
80
56
|
}
|
|
81
57
|
function emitFreshBestEffort(input) {
|
|
@@ -207,8 +183,8 @@ class CanvasInboxWatcher {
|
|
|
207
183
|
lastCtx;
|
|
208
184
|
streaming = false;
|
|
209
185
|
nodeId;
|
|
210
|
-
|
|
211
|
-
|
|
186
|
+
claims = new Map();
|
|
187
|
+
tickInFlight;
|
|
212
188
|
buffer = [];
|
|
213
189
|
lastArrival = 0;
|
|
214
190
|
pendingHandoffs = [];
|
|
@@ -272,10 +248,10 @@ class CanvasInboxWatcher {
|
|
|
272
248
|
return;
|
|
273
249
|
try {
|
|
274
250
|
this.assertNodeOwnership(nodeId, 'settle');
|
|
275
|
-
|
|
276
|
-
//
|
|
277
|
-
|
|
278
|
-
|
|
251
|
+
await this.tickInFlight;
|
|
252
|
+
// Include kickoff claims even when the first turn settled before a poll.
|
|
253
|
+
if (!this.seeded)
|
|
254
|
+
await this.claimMail(nodeId);
|
|
279
255
|
const result = await this.settle(nodeId, ctx, false, true);
|
|
280
256
|
if (result === 'refresh_held')
|
|
281
257
|
this.dispose('refresh', false);
|
|
@@ -306,9 +282,7 @@ class CanvasInboxWatcher {
|
|
|
306
282
|
});
|
|
307
283
|
}
|
|
308
284
|
try {
|
|
309
|
-
//
|
|
310
|
-
// crtrd rejects a cursor commit for a refresh, preserving every handoff
|
|
311
|
-
// that may have reached this discarded conversation for the next broker.
|
|
285
|
+
// Refresh rejects receipts, preserving claims for the replacement broker.
|
|
312
286
|
await this.disposeAtSettlement(reason, this.lastCtx);
|
|
313
287
|
}
|
|
314
288
|
catch (error) {
|
|
@@ -338,11 +312,7 @@ class CanvasInboxWatcher {
|
|
|
338
312
|
this.reportNodesRefreshing = false;
|
|
339
313
|
}
|
|
340
314
|
}
|
|
341
|
-
/**
|
|
342
|
-
* The projection captured at session_start omits every node created since —
|
|
343
|
-
* each reply-bearing `crtr human send` bridge and each child this node spawns — so their
|
|
344
|
-
* reports would render as bare refs instead of inlined bodies. One refresh
|
|
345
|
-
* per unknown node id keeps a genuinely missing node from stalling delivery. */
|
|
315
|
+
/** Refresh once per unknown report sender, so new children can inline their reports. */
|
|
346
316
|
refreshForUnknownReportRefs() {
|
|
347
317
|
const unknown = [];
|
|
348
318
|
for (const entry of this.buffer) {
|
|
@@ -371,9 +341,7 @@ class CanvasInboxWatcher {
|
|
|
371
341
|
// the normal debounce owns delivery instead of waiting a full tick.
|
|
372
342
|
this.runTick('schedule');
|
|
373
343
|
}
|
|
374
|
-
/**
|
|
375
|
-
* The daemon decides whether a refresh preserves the cursor, and this method
|
|
376
|
-
* awaits that decision so a process exit never outruns an accepted commit. */
|
|
344
|
+
/** Await graceful-shutdown receipts before disposing their in-process state. */
|
|
377
345
|
async disposeAtSettlement(reason, ctx) {
|
|
378
346
|
const nodeId = currentNodeId();
|
|
379
347
|
if (nodeId === undefined) {
|
|
@@ -402,8 +370,7 @@ class CanvasInboxWatcher {
|
|
|
402
370
|
...this.pendingHandoffs.splice(0),
|
|
403
371
|
];
|
|
404
372
|
this.buffer.length = 0;
|
|
405
|
-
this.
|
|
406
|
-
this.durableCursor = undefined;
|
|
373
|
+
this.claims.clear();
|
|
407
374
|
this.reportNodes.clear();
|
|
408
375
|
this.reportNodesAsked.clear();
|
|
409
376
|
this.pendingCommit = undefined;
|
|
@@ -502,85 +469,66 @@ class CanvasInboxWatcher {
|
|
|
502
469
|
}
|
|
503
470
|
this.escapeFatal(fatal, 'schedule');
|
|
504
471
|
}
|
|
505
|
-
runTick(
|
|
506
|
-
if (!this.canMutate())
|
|
472
|
+
runTick(_fatalMode = 'throw') {
|
|
473
|
+
if (!this.canMutate() || this.tickInFlight !== undefined)
|
|
507
474
|
return;
|
|
508
|
-
|
|
509
|
-
this.
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
if (
|
|
513
|
-
this.
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
if (isFilesystemError(error))
|
|
517
|
-
return;
|
|
518
|
-
let fatal;
|
|
519
|
-
try {
|
|
520
|
-
this.raiseReadFatal('poll', error);
|
|
521
|
-
}
|
|
522
|
-
catch (tagged) {
|
|
523
|
-
fatal = tagged;
|
|
524
|
-
}
|
|
525
|
-
this.escapeFatal(fatal, fatalMode);
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
pollRead(read) {
|
|
529
|
-
try {
|
|
530
|
-
return { ok: true, value: read() };
|
|
531
|
-
}
|
|
532
|
-
catch (error) {
|
|
533
|
-
if (isFilesystemError(error))
|
|
534
|
-
return { ok: false };
|
|
535
|
-
this.raiseReadFatal('poll', error);
|
|
536
|
-
}
|
|
475
|
+
const attempt = this.tick().catch((error) => {
|
|
476
|
+
if (this.canMutate())
|
|
477
|
+
this.scheduleHandlerFatal(error, 'poll');
|
|
478
|
+
}).finally(() => {
|
|
479
|
+
if (this.tickInFlight === attempt)
|
|
480
|
+
this.tickInFlight = undefined;
|
|
481
|
+
});
|
|
482
|
+
this.tickInFlight = attempt;
|
|
537
483
|
}
|
|
538
|
-
|
|
484
|
+
async claimMail(nodeId) {
|
|
539
485
|
this.assertNodeOwnership(nodeId, 'poll');
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
if (
|
|
486
|
+
const result = await claimBrokerMail(nodeId, 'wake');
|
|
487
|
+
if (!this.canMutate())
|
|
488
|
+
return false;
|
|
489
|
+
if (result.action === 'hold')
|
|
544
490
|
return false;
|
|
545
491
|
this.nodeId = nodeId;
|
|
546
|
-
this.cursor = initial.value;
|
|
547
|
-
this.durableCursor = initial.value;
|
|
548
492
|
this.seeded = true;
|
|
493
|
+
const activeIds = new Set(result.deliveries.map((claim) => claim.entry.entry_id));
|
|
494
|
+
// A canceled buffered delivery disappears from the daemon's claim query.
|
|
495
|
+
const canceled = this.buffer.filter((entry) => !activeIds.has(entry.entry_id));
|
|
496
|
+
for (const entry of canceled)
|
|
497
|
+
this.claims.delete(entry.entry_id);
|
|
498
|
+
this.buffer.splice(0, this.buffer.length, ...this.buffer.filter((entry) => activeIds.has(entry.entry_id)));
|
|
499
|
+
for (const claim of result.deliveries) {
|
|
500
|
+
const id = claim.entry.entry_id;
|
|
501
|
+
if (this.claims.has(id))
|
|
502
|
+
continue;
|
|
503
|
+
this.claims.set(id, claim);
|
|
504
|
+
if (claim.handoff === 'inherited') {
|
|
505
|
+
operationIdContext.fresh((operationId) => {
|
|
506
|
+
this.pendingHandoffs.push({ ...deliveryFacts([claim.entry], 'visible'), operationId, settleAtAgentSettled: true });
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
this.buffer.push(claim.entry);
|
|
511
|
+
this.lastArrival = Date.now();
|
|
512
|
+
}
|
|
513
|
+
}
|
|
549
514
|
return true;
|
|
550
515
|
}
|
|
551
|
-
tick() {
|
|
516
|
+
async tick() {
|
|
552
517
|
const nodeId = currentNodeId();
|
|
553
|
-
if (nodeId === undefined
|
|
518
|
+
if (nodeId === undefined)
|
|
554
519
|
return;
|
|
555
520
|
if (this.pendingCommit !== undefined) {
|
|
556
|
-
this.
|
|
521
|
+
const result = await this.retryPendingCommit(nodeId);
|
|
522
|
+
if (result === 'refresh_held' && this.canMutate())
|
|
523
|
+
this.dispose('refresh', false);
|
|
557
524
|
return;
|
|
558
525
|
}
|
|
559
|
-
if (this.promptJoinInFlight)
|
|
560
|
-
return;
|
|
561
|
-
// A paused profile is inert: read nothing, send nothing, leave the cursor
|
|
562
|
-
// where it is, so every queued entry — critical included, since aborting the
|
|
563
|
-
// live turn is exactly the punch-through pause forbids — is still there to
|
|
564
|
-
// deliver on resume. Pause is not a kill: the turn already running finishes,
|
|
565
|
-
// and an in-flight handoff still commits above.
|
|
566
|
-
if (profilePaused())
|
|
526
|
+
if (this.promptJoinInFlight || profilePaused())
|
|
567
527
|
return;
|
|
568
|
-
if (this.
|
|
528
|
+
if (this.pendingHandoffs.length >= MAX_PENDING_HANDOFFS)
|
|
569
529
|
return;
|
|
570
|
-
if (this.
|
|
571
|
-
const plan = this.ordinaryPlan();
|
|
572
|
-
if (plan.sendCount > 0 && this.pendingHandoffs.length + plan.sendCount > MAX_PENDING_HANDOFFS)
|
|
573
|
-
return;
|
|
574
|
-
}
|
|
575
|
-
const read = this.pollRead(() => readBrokerInboxSince(nodeId, this.cursor));
|
|
576
|
-
if (!read.ok)
|
|
530
|
+
if (!await this.claimMail(nodeId))
|
|
577
531
|
return;
|
|
578
|
-
const newEntries = read.value;
|
|
579
|
-
if (newEntries.length > 0) {
|
|
580
|
-
this.cursor = newEntries.at(-1).entry_id;
|
|
581
|
-
this.buffer.push(...newEntries);
|
|
582
|
-
this.lastArrival = Date.now();
|
|
583
|
-
}
|
|
584
532
|
if (this.buffer.length > 0 && Date.now() - this.lastArrival >= this.cadence.debounceMs) {
|
|
585
533
|
if (this.refreshForUnknownReportRefs())
|
|
586
534
|
return;
|
|
@@ -588,16 +536,8 @@ class CanvasInboxWatcher {
|
|
|
588
536
|
}
|
|
589
537
|
}
|
|
590
538
|
missingChannelEntries(entries) {
|
|
591
|
-
//
|
|
592
|
-
|
|
593
|
-
// fresh each plan build: the cancel can land AFTER the entry was buffered.
|
|
594
|
-
// Skipped entries are never handed off; the durable cursor covers them
|
|
595
|
-
// positionally when a later entry settles (or they are re-filtered after a
|
|
596
|
-
// restart).
|
|
597
|
-
const canceled = this.nodeId === undefined ? undefined : readBrokerCanceledEntryIds(this.nodeId);
|
|
598
|
-
const live = canceled === undefined || canceled.size === 0
|
|
599
|
-
? entries
|
|
600
|
-
: entries.filter((entry) => !canceled.has(entry.entry_id));
|
|
539
|
+
// Each claim refresh removes canceled buffered entries before either channel sends.
|
|
540
|
+
const live = entries.filter((entry) => this.claims.has(entry.entry_id));
|
|
601
541
|
const hiddenCoverage = this.coveredEntryIds('hidden');
|
|
602
542
|
const visibleCoverage = this.coveredEntryIds('visible');
|
|
603
543
|
return {
|
|
@@ -863,10 +803,7 @@ class CanvasInboxWatcher {
|
|
|
863
803
|
this.requeueFromBatch(batch, execution.requeueEntryIds);
|
|
864
804
|
return 'attempted';
|
|
865
805
|
}
|
|
866
|
-
/**
|
|
867
|
-
* by the broker. Each rendered delivery is persisted before that prompt, but
|
|
868
|
-
* no cursor may advance until the prompt's agent_settled event proves the
|
|
869
|
-
* turn consumed it. */
|
|
806
|
+
/** Deferred mail joins an admitted human prompt but remains unacknowledged until settlement. */
|
|
870
807
|
async prependHeldDeferredInbox(session) {
|
|
871
808
|
if (!this.canMutate() || this.nodeId === undefined || profilePaused())
|
|
872
809
|
return;
|
|
@@ -950,15 +887,6 @@ class CanvasInboxWatcher {
|
|
|
950
887
|
}
|
|
951
888
|
return covered;
|
|
952
889
|
}
|
|
953
|
-
retryPendingCommitOnTick(nodeId) {
|
|
954
|
-
void this.retryPendingCommit(nodeId).then((result) => {
|
|
955
|
-
if (result === 'refresh_held' && this.canMutate())
|
|
956
|
-
this.dispose('refresh', false);
|
|
957
|
-
}).catch((error) => {
|
|
958
|
-
if (this.canMutate())
|
|
959
|
-
this.dispose('shutdown', false, undefined, { error, stage: 'settle' });
|
|
960
|
-
});
|
|
961
|
-
}
|
|
962
890
|
retryPendingCommit(nodeId) {
|
|
963
891
|
const pending = this.pendingCommit;
|
|
964
892
|
if (pending === undefined)
|
|
@@ -973,28 +901,40 @@ class CanvasInboxWatcher {
|
|
|
973
901
|
return attempt;
|
|
974
902
|
}
|
|
975
903
|
async attemptPendingCommit(nodeId, pending) {
|
|
904
|
+
let acknowledged = false;
|
|
976
905
|
try {
|
|
977
|
-
const directive = await
|
|
978
|
-
|
|
979
|
-
brokerPid: process.pid,
|
|
980
|
-
});
|
|
981
|
-
if (directive.action === 'hold_refresh')
|
|
906
|
+
const directive = await acknowledgeBrokerMail(nodeId, pending.receipts);
|
|
907
|
+
if (directive.action === 'hold')
|
|
982
908
|
return 'refresh_held';
|
|
909
|
+
for (const receipt of pending.receipts) {
|
|
910
|
+
const result = directive.results.find((result) => result.delivery_id === receipt.delivery_id);
|
|
911
|
+
if (result?.outcome !== receipt.disposition && result?.outcome !== 'stale')
|
|
912
|
+
throw new Error('daemon returned no terminal mail settlement outcome');
|
|
913
|
+
}
|
|
914
|
+
acknowledged = directive.results.every((result) => result.outcome === 'acknowledged');
|
|
983
915
|
}
|
|
984
916
|
catch (error) {
|
|
985
917
|
if (this.pendingCommit === pending) {
|
|
986
918
|
for (const handoff of pending.handoffs) {
|
|
987
|
-
emitDeliveryFailure(handoff.operationId, handoff, '
|
|
919
|
+
emitDeliveryFailure(handoff.operationId, handoff, 'receipt_commit', error);
|
|
988
920
|
}
|
|
989
921
|
}
|
|
990
922
|
return 'held';
|
|
991
923
|
}
|
|
992
924
|
if (this.pendingCommit !== pending)
|
|
993
925
|
return 'settled';
|
|
994
|
-
|
|
926
|
+
for (const id of pending.entryIds)
|
|
927
|
+
this.claims.delete(id);
|
|
928
|
+
if (pending.receipts.some((receipt) => receipt.disposition === 'released')) {
|
|
929
|
+
const released = new Set(pending.entryIds);
|
|
930
|
+
this.buffer.splice(0, this.buffer.length, ...this.buffer.filter((entry) => !released.has(entry.entry_id)));
|
|
931
|
+
}
|
|
995
932
|
this.pendingCommit = undefined;
|
|
996
|
-
|
|
997
|
-
|
|
933
|
+
const completed = this.detachPending((handoff) => handoff.entryIds.every((id) => !this.claims.has(id)));
|
|
934
|
+
for (const handoff of completed) {
|
|
935
|
+
if (acknowledged)
|
|
936
|
+
emitDeliveryCompleted(handoff);
|
|
937
|
+
}
|
|
998
938
|
return 'settled';
|
|
999
939
|
}
|
|
1000
940
|
async settle(nodeId, ctx, holdPendingMessages, atAgentSettled = false) {
|
|
@@ -1009,109 +949,23 @@ class CanvasInboxWatcher {
|
|
|
1009
949
|
}
|
|
1010
950
|
if (this.pendingCommit !== undefined)
|
|
1011
951
|
return this.retryPendingCommit(nodeId);
|
|
1012
|
-
|
|
952
|
+
const refused = wasTurnRefused();
|
|
953
|
+
const buffered = new Set(this.buffer.map((entry) => entry.entry_id));
|
|
954
|
+
const eligible = this.pendingHandoffs.filter((handoff) => atAgentSettled || handoff.settleAtAgentSettled !== true);
|
|
955
|
+
const handedOff = new Set(eligible.flatMap((handoff) => [...handoff.entryIds]));
|
|
956
|
+
const entryIds = [...this.claims.keys()].filter((id) => refused || (handedOff.has(id) && !buffered.has(id)));
|
|
957
|
+
if (entryIds.length === 0)
|
|
1013
958
|
return 'settled';
|
|
1014
|
-
const physical = this.readPhysicalSettlementState(nodeId);
|
|
1015
|
-
if (physical.durableIndex >= 0) {
|
|
1016
|
-
const alreadyDurable = this.detachPending((handoff) => physical.throughIndexes.get(handoff) <= physical.durableIndex);
|
|
1017
|
-
for (const handoff of alreadyDurable)
|
|
1018
|
-
emitDeliveryCompleted(handoff);
|
|
1019
|
-
}
|
|
1020
|
-
const agentSettledBlock = atAgentSettled
|
|
1021
|
-
? undefined
|
|
1022
|
-
: this.pendingHandoffs
|
|
1023
|
-
.filter((handoff) => handoff.settleAtAgentSettled === true)
|
|
1024
|
-
.map((handoff) => physical.throughIndexes.get(handoff))
|
|
1025
|
-
.reduce((first, index) => first === undefined ? index : Math.min(first, index), undefined);
|
|
1026
|
-
const eligible = this.pendingHandoffs.filter((handoff) => {
|
|
1027
|
-
const throughIndex = physical.throughIndexes.get(handoff);
|
|
1028
|
-
return (handoff.settleAtAgentSettled !== true || atAgentSettled)
|
|
1029
|
-
&& (physical.blockedIndex === undefined || throughIndex < physical.blockedIndex)
|
|
1030
|
-
&& (agentSettledBlock === undefined || throughIndex < agentSettledBlock);
|
|
1031
|
-
});
|
|
1032
|
-
if (eligible.length === 0)
|
|
1033
|
-
return 'settled';
|
|
1034
|
-
let target = eligible[0];
|
|
1035
|
-
for (const handoff of eligible.slice(1)) {
|
|
1036
|
-
if (physical.throughIndexes.get(handoff) > physical.throughIndexes.get(target))
|
|
1037
|
-
target = handoff;
|
|
1038
|
-
}
|
|
1039
|
-
const committing = new Set(eligible);
|
|
1040
959
|
this.pendingCommit = {
|
|
1041
|
-
handoffs:
|
|
1042
|
-
|
|
960
|
+
handoffs: eligible,
|
|
961
|
+
entryIds,
|
|
962
|
+
receipts: entryIds.map((id) => {
|
|
963
|
+
const claim = this.claims.get(id);
|
|
964
|
+
return { delivery_id: claim.delivery_id, attempts: claim.attempts, disposition: refused ? 'released' : 'acknowledged' };
|
|
965
|
+
}),
|
|
1043
966
|
};
|
|
1044
967
|
return this.retryPendingCommit(nodeId);
|
|
1045
968
|
}
|
|
1046
|
-
readPhysicalSettlementState(nodeId) {
|
|
1047
|
-
let entries;
|
|
1048
|
-
try {
|
|
1049
|
-
entries = readBrokerInboxSince(nodeId);
|
|
1050
|
-
}
|
|
1051
|
-
catch (error) {
|
|
1052
|
-
this.raiseReadFatal('settle', error);
|
|
1053
|
-
}
|
|
1054
|
-
try {
|
|
1055
|
-
const indexes = new Map();
|
|
1056
|
-
entries.forEach((entry, index) => indexes.set(entry.entry_id, index));
|
|
1057
|
-
const indexOf = (entryId, owner) => {
|
|
1058
|
-
const index = indexes.get(entryId);
|
|
1059
|
-
if (index === undefined)
|
|
1060
|
-
throw new Error(`${owner} entry_id is absent from the physical inbox: ${entryId}`);
|
|
1061
|
-
return index;
|
|
1062
|
-
};
|
|
1063
|
-
const durableIndex = this.durableCursor === undefined ? -1 : indexOf(this.durableCursor, 'durable cursor');
|
|
1064
|
-
const cursorIndex = this.cursor === undefined ? -1 : indexOf(this.cursor, 'read cursor');
|
|
1065
|
-
if (cursorIndex < durableIndex)
|
|
1066
|
-
throw new Error('read cursor precedes the durable cursor');
|
|
1067
|
-
let previousBufferIndex = -1;
|
|
1068
|
-
let blockedIndex;
|
|
1069
|
-
const bufferedIds = new Set();
|
|
1070
|
-
for (const entry of this.buffer) {
|
|
1071
|
-
if (bufferedIds.has(entry.entry_id))
|
|
1072
|
-
throw new Error(`buffer contains duplicate entry_id: ${entry.entry_id}`);
|
|
1073
|
-
bufferedIds.add(entry.entry_id);
|
|
1074
|
-
const index = indexOf(entry.entry_id, 'buffer');
|
|
1075
|
-
if (index <= previousBufferIndex)
|
|
1076
|
-
throw new Error('buffer is not in physical inbox order');
|
|
1077
|
-
if (index <= durableIndex)
|
|
1078
|
-
throw new Error('buffer contains an entry at or before the durable cursor');
|
|
1079
|
-
if (cursorIndex < index)
|
|
1080
|
-
throw new Error('buffer contains an entry beyond the read cursor');
|
|
1081
|
-
previousBufferIndex = index;
|
|
1082
|
-
blockedIndex = blockedIndex === undefined ? index : Math.min(blockedIndex, index);
|
|
1083
|
-
}
|
|
1084
|
-
const throughIndexes = new Map();
|
|
1085
|
-
for (const handoff of this.pendingHandoffs) {
|
|
1086
|
-
if (handoff.entryIds.length === 0)
|
|
1087
|
-
throw new Error('pending handoff has no entry_ids');
|
|
1088
|
-
if (handoff.entryIds.at(-1) !== handoff.throughEntryId) {
|
|
1089
|
-
throw new Error('pending handoff through_entry_id is not its physical-last attempted entry');
|
|
1090
|
-
}
|
|
1091
|
-
let previousIndex = -1;
|
|
1092
|
-
const handoffIds = new Set();
|
|
1093
|
-
for (const entryId of handoff.entryIds) {
|
|
1094
|
-
if (handoffIds.has(entryId))
|
|
1095
|
-
throw new Error(`pending handoff contains duplicate entry_id: ${entryId}`);
|
|
1096
|
-
handoffIds.add(entryId);
|
|
1097
|
-
const index = indexOf(entryId, 'pending handoff');
|
|
1098
|
-
if (index <= previousIndex)
|
|
1099
|
-
throw new Error('pending handoff entry_ids are not in physical inbox order');
|
|
1100
|
-
if (cursorIndex < index)
|
|
1101
|
-
throw new Error('pending handoff contains an entry beyond the read cursor');
|
|
1102
|
-
previousIndex = index;
|
|
1103
|
-
}
|
|
1104
|
-
const throughIndex = indexOf(handoff.throughEntryId, 'pending handoff through');
|
|
1105
|
-
if (throughIndex !== previousIndex)
|
|
1106
|
-
throw new Error('pending handoff through_entry_id is physically inconsistent');
|
|
1107
|
-
throughIndexes.set(handoff, throughIndex);
|
|
1108
|
-
}
|
|
1109
|
-
return { throughIndexes, durableIndex, blockedIndex };
|
|
1110
|
-
}
|
|
1111
|
-
catch (error) {
|
|
1112
|
-
this.raiseReadFatal('settle', error);
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
969
|
detachPending(predicate) {
|
|
1116
970
|
const removed = [];
|
|
1117
971
|
for (let index = this.pendingHandoffs.length - 1; index >= 0; index -= 1) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { MailEntryDTO } from '../api/dto/mail.js';
|
|
2
|
+
type BrokerPassiveEntry = MailEntryDTO;
|
|
2
3
|
interface InputEventLike {
|
|
3
4
|
type: 'input';
|
|
4
5
|
text: string;
|
|
@@ -15,7 +16,8 @@ type InputEventResultLike = {
|
|
|
15
16
|
action: 'handled';
|
|
16
17
|
};
|
|
17
18
|
interface PiLike {
|
|
18
|
-
on
|
|
19
|
+
on(event: 'input', handler: (event: InputEventLike, ctx: any) => InputEventResultLike | void | Promise<InputEventResultLike | void>): void;
|
|
20
|
+
on(event: 'agent_settled' | 'session_shutdown', handler: (event: any, ctx: any) => void | Promise<void>): void;
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
21
23
|
* Render drained passive entries (oldest first) into one XML pre-text block.
|
|
@@ -32,11 +34,5 @@ export declare function formatPassive(entries: BrokerPassiveEntry[], reportNodes
|
|
|
32
34
|
* becomes the body's first child instead.
|
|
33
35
|
*/
|
|
34
36
|
export declare function placeBacklog(text: string, preText: string): string;
|
|
35
|
-
/**
|
|
36
|
-
* Register the passive-context drain on `pi`.
|
|
37
|
-
*
|
|
38
|
-
* Returns immediately (inert) when CRTR_NODE_ID is absent. The `input` handler
|
|
39
|
-
* is the whole extension: drain on every message, prepend when non-empty.
|
|
40
|
-
*/
|
|
41
37
|
export declare function registerCanvasPassiveContext(pi: PiLike): void;
|
|
42
38
|
export default registerCanvasPassiveContext;
|
|
@@ -1,28 +1,11 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
// Loaded into every canvas node's pi process via the node's launch.extensions
|
|
4
|
-
// list. INERT when CRTR_NODE_ID is absent (plain pi session or legacy job agent).
|
|
5
|
-
//
|
|
6
|
-
// The passive-subscription drain. A PASSIVE subscription (active=false edge)
|
|
7
|
-
// never wakes its subscriber: `push` routes its pointers to passive.jsonl, which
|
|
8
|
-
// the inbox-watcher never polls. They simply accumulate. This extension is what
|
|
9
|
-
// finally surfaces them — the moment the node is MESSAGED.
|
|
10
|
-
//
|
|
11
|
-
// pi fires an `input` event for every user message (human-typed, an RPC, or an
|
|
12
|
-
// extension's sendUserMessage — including the inbox-watcher's own wake). On that
|
|
13
|
-
// event we DRAIN the node's passive accumulator and, when non-empty, prepend
|
|
14
|
-
// every entry as timestamped XML to the message text via the `transform` action.
|
|
15
|
-
// So the backlog rides in as pre-text on whatever message next engages the node,
|
|
16
|
-
// before the LLM sees it — and is cleared in the same step (drain = read+clear),
|
|
17
|
-
// so it surfaces exactly once.
|
|
18
|
-
//
|
|
19
|
-
// Plain TS-with-types — no imports from @earendil-works/* so this compiles inside
|
|
20
|
-
// crouter's own tsc build without a dep on the pi packages.
|
|
1
|
+
// Passive mail is claimed only on natural input and acknowledged after settlement.
|
|
2
|
+
// Formatting failures retain the SQL claim; refused turns release it for replay.
|
|
21
3
|
import { envNodeId } from '../shared/env.js';
|
|
22
4
|
import { existsSync, readFileSync } from 'node:fs';
|
|
23
|
-
import { brokerExtensionState } from '../core/runtime/broker/daemon-ops.js';
|
|
5
|
+
import { acknowledgeBrokerMail, claimBrokerMail, brokerExtensionState } from '../core/runtime/broker/daemon-ops.js';
|
|
6
|
+
import { wasTurnRefused } from '../core/runtime/broker/extension-abort.js';
|
|
7
|
+
import { emitEvent } from '../core/events/emit.js';
|
|
24
8
|
import { reportPathFromRef } from '../core/runtime/broker-extension-render.js';
|
|
25
|
-
import { drainBrokerPassive } from '../core/runtime/broker/passive.js';
|
|
26
9
|
import { parseCard } from '../shared/generated-context.js';
|
|
27
10
|
// Per-entry body cap so a single fat report can't blow the context budget. The
|
|
28
11
|
// full report stays on disk at `ref` if the agent needs more.
|
|
@@ -126,30 +109,95 @@ export function placeBacklog(text, preText) {
|
|
|
126
109
|
return `${text.slice(0, bodyStart)}${preText}\n${text.slice(bodyStart)}`;
|
|
127
110
|
}
|
|
128
111
|
// Extension
|
|
129
|
-
/**
|
|
130
|
-
* Register the passive-context drain on `pi`.
|
|
131
|
-
*
|
|
132
|
-
* Returns immediately (inert) when CRTR_NODE_ID is absent. The `input` handler
|
|
133
|
-
* is the whole extension: drain on every message, prepend when non-empty.
|
|
134
|
-
*/
|
|
135
112
|
export function registerCanvasPassiveContext(pi) {
|
|
113
|
+
const claims = new Map();
|
|
114
|
+
let pending;
|
|
115
|
+
let settlement;
|
|
116
|
+
function reportFailure(error) {
|
|
117
|
+
try {
|
|
118
|
+
emitEvent({ level: 'error', event: 'inbox.delivery.failed', outcome: 'failed', error, fields: { channel: 'passive' } });
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// SQL claims and pending receipts remain authoritative if diagnostics fail.
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async function settle(nodeId) {
|
|
125
|
+
if (settlement !== undefined)
|
|
126
|
+
return settlement;
|
|
127
|
+
if (pending === undefined) {
|
|
128
|
+
pending = [...claims.values()].filter((item) => item.injected).map(({ claim }) => ({
|
|
129
|
+
delivery_id: claim.delivery_id, attempts: claim.attempts,
|
|
130
|
+
disposition: wasTurnRefused() ? 'released' : 'acknowledged',
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
if (pending.length === 0) {
|
|
134
|
+
pending = undefined;
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
const receipts = pending;
|
|
138
|
+
const attempt = (async () => {
|
|
139
|
+
try {
|
|
140
|
+
const result = await acknowledgeBrokerMail(nodeId, receipts);
|
|
141
|
+
if (result.action === 'hold')
|
|
142
|
+
return false;
|
|
143
|
+
for (const receipt of receipts) {
|
|
144
|
+
const confirmed = result.results.find((result) => result.delivery_id === receipt.delivery_id);
|
|
145
|
+
if (confirmed?.outcome !== receipt.disposition && confirmed?.outcome !== 'stale')
|
|
146
|
+
throw new Error(`passive mail settlement has no terminal outcome: ${receipt.delivery_id}`);
|
|
147
|
+
}
|
|
148
|
+
for (const receipt of receipts)
|
|
149
|
+
claims.delete(receipt.delivery_id);
|
|
150
|
+
pending = undefined;
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
reportFailure(error);
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
})().finally(() => { if (settlement === attempt)
|
|
158
|
+
settlement = undefined; });
|
|
159
|
+
settlement = attempt;
|
|
160
|
+
return attempt;
|
|
161
|
+
}
|
|
136
162
|
pi.on('input', async (event) => {
|
|
163
|
+
const nodeId = envNodeId();
|
|
164
|
+
if (nodeId === undefined || nodeId.trim() === '')
|
|
165
|
+
return;
|
|
137
166
|
try {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
167
|
+
if (pending !== undefined && !await settle(nodeId))
|
|
168
|
+
return;
|
|
169
|
+
const result = await claimBrokerMail(nodeId, 'passive');
|
|
170
|
+
if (result.action === 'hold')
|
|
171
|
+
return;
|
|
172
|
+
for (const claim of result.deliveries) {
|
|
173
|
+
if (!claims.has(claim.delivery_id))
|
|
174
|
+
claims.set(claim.delivery_id, { claim, injected: false });
|
|
175
|
+
}
|
|
176
|
+
const unsent = [...claims.values()].filter((item) => !item.injected);
|
|
177
|
+
if (unsent.length === 0)
|
|
178
|
+
return;
|
|
144
179
|
const state = await brokerExtensionState(nodeId);
|
|
145
180
|
const reportNodes = new Map(state.report_nodes.map((node) => [node.node_id, node]));
|
|
146
|
-
const text = placeBacklog(event.text, formatPassive(
|
|
181
|
+
const text = placeBacklog(event.text, formatPassive(unsent.map(({ claim }) => claim.entry), reportNodes));
|
|
182
|
+
for (const item of unsent)
|
|
183
|
+
item.injected = true;
|
|
147
184
|
return { action: 'transform', text, images: event.images };
|
|
148
185
|
}
|
|
149
|
-
catch {
|
|
150
|
-
//
|
|
186
|
+
catch (error) {
|
|
187
|
+
// The original input proceeds; unformatted mail remains held and unacknowledged.
|
|
188
|
+
reportFailure(error);
|
|
151
189
|
return;
|
|
152
190
|
}
|
|
153
191
|
});
|
|
192
|
+
pi.on('agent_settled', async () => {
|
|
193
|
+
const nodeId = envNodeId();
|
|
194
|
+
if (nodeId !== undefined && nodeId !== '')
|
|
195
|
+
await settle(nodeId);
|
|
196
|
+
});
|
|
197
|
+
pi.on('session_shutdown', async (_event, ctx) => {
|
|
198
|
+
const nodeId = envNodeId();
|
|
199
|
+
if (nodeId !== undefined && nodeId !== '' && ctx?.hasPendingMessages?.() !== true)
|
|
200
|
+
await settle(nodeId);
|
|
201
|
+
});
|
|
154
202
|
}
|
|
155
203
|
export default registerCanvasPassiveContext;
|