@north-light/crouter 0.3.312 → 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 +13 -1
- 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 +16 -3
- 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 +51 -8
- 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 +2 -1
- package/dist/core/__tests__/on-read-dedup-resume.test.js +2 -1
- package/dist/core/__tests__/on-read-nested-store.test.js +2 -1
- 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 +4 -1
- 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 +2 -1
- 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 +18 -4
- 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/config.d.ts +17 -12
- package/dist/core/config.js +106 -155
- 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 +3 -2
- 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/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/placement.js +2 -2
- package/dist/core/runtime/recycle.js +8 -2
- package/dist/core/runtime/reset.js +22 -6
- package/dist/core/runtime/revive.js +226 -218
- package/dist/core/runtime/spawn.js +14 -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 +39 -15
- 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 +4 -1
- 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 +27 -41
- 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 -151
- 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.js +7 -13
- 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/index.d.ts +2 -1
- 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,427 +1,17 @@
|
|
|
1
|
-
import { envNodeId } from '../../shared/env.js';
|
|
2
|
-
import { isRecord } from '../../shared/predicates.js';
|
|
3
|
-
import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
import { jobDir } from '../canvas/paths.js';
|
|
6
|
-
import { errorClassFromFault, } from '../fault-classifier.js';
|
|
7
|
-
import { emitEvent } from '../events/emit.js';
|
|
8
|
-
import { operationIdContext, validateOperationId } from '../events/operation-id.js';
|
|
9
1
|
export const FAULT_QUIET_MS = 5 * 60_000;
|
|
10
|
-
|
|
11
|
-
function faultPath(nodeId) {
|
|
12
|
-
return join(jobDir(nodeId), 'fault');
|
|
13
|
-
}
|
|
14
|
-
function providerRetryPath(nodeId) {
|
|
15
|
-
return join(jobDir(nodeId), 'provider-retry');
|
|
16
|
-
}
|
|
17
|
-
function canonicalSessionFile(sessionFile) {
|
|
18
|
-
try {
|
|
19
|
-
return realpathSync(sessionFile);
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
return sessionFile;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
function clampMessage(message) {
|
|
26
|
-
return message.slice(0, MESSAGE_CAP);
|
|
27
|
-
}
|
|
28
|
-
function faultPriority(fault) {
|
|
29
|
-
if (fault.link === 'pi→provider' && fault.retry.disposition === 'auto' && fault.retry.by === 'daemon')
|
|
30
|
-
return 3;
|
|
31
|
-
if (fault.retry.disposition === 'fatal')
|
|
32
|
-
return 2;
|
|
33
|
-
return 1;
|
|
34
|
-
}
|
|
35
|
-
const faultLinks = ['pi→provider', 'viewer↔broker', 'relay↔broker', 'viewer↔crtrd', 'broker↔crtrd', 'daemon→node', 'crtr→pi'];
|
|
36
|
-
const faultKinds = ['rate-limit', 'overloaded', 'connection', 'auth', 'protocol', 'context-overflow', 'other', 'wedged', 'model-not-found'];
|
|
37
|
-
function parseProviderError(value) {
|
|
38
|
-
if (!isRecord(value) || typeof value.provider !== 'string' || value.provider === '' || typeof value.model !== 'string' || value.model === '')
|
|
39
|
-
return undefined;
|
|
40
|
-
const status = typeof value.status === 'number' && Number.isFinite(value.status) ? value.status : undefined;
|
|
41
|
-
const code = typeof value.code === 'string' || typeof value.code === 'number' ? value.code : undefined;
|
|
42
|
-
const errno = typeof value.errno === 'string' ? value.errno : undefined;
|
|
43
|
-
const body = typeof value.body === 'string' ? value.body : undefined;
|
|
44
|
-
const causes = Array.isArray(value.causes)
|
|
45
|
-
? value.causes.flatMap((item) => {
|
|
46
|
-
if (!isRecord(item))
|
|
47
|
-
return [];
|
|
48
|
-
const cause = {
|
|
49
|
-
...(typeof item.message === 'string' ? { message: item.message } : {}),
|
|
50
|
-
...(typeof item.status === 'number' && Number.isFinite(item.status) ? { status: item.status } : {}),
|
|
51
|
-
...(typeof item.code === 'string' || typeof item.code === 'number' ? { code: item.code } : {}),
|
|
52
|
-
...(typeof item.errno === 'string' ? { errno: item.errno } : {}),
|
|
53
|
-
...(typeof item.body === 'string' ? { body: item.body } : {}),
|
|
54
|
-
};
|
|
55
|
-
return Object.keys(cause).length === 0 ? [] : [cause];
|
|
56
|
-
})
|
|
57
|
-
: undefined;
|
|
58
|
-
return {
|
|
59
|
-
provider: value.provider,
|
|
60
|
-
model: value.model,
|
|
61
|
-
...(status === undefined ? {} : { status }),
|
|
62
|
-
...(code === undefined ? {} : { code }),
|
|
63
|
-
...(errno === undefined ? {} : { errno }),
|
|
64
|
-
...(body === undefined ? {} : { body }),
|
|
65
|
-
...(causes === undefined || causes.length === 0 ? {} : { causes }),
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
function parseFault(raw) {
|
|
69
|
-
try {
|
|
70
|
-
const parsed = JSON.parse(raw);
|
|
71
|
-
if (!faultLinks.includes(parsed.link))
|
|
72
|
-
return null;
|
|
73
|
-
if (typeof parsed.op !== 'string' || parsed.op === '')
|
|
74
|
-
return null;
|
|
75
|
-
if (!faultKinds.includes(parsed.kind))
|
|
76
|
-
return null;
|
|
77
|
-
if (typeof parsed.message !== 'string' || typeof parsed.since !== 'string')
|
|
78
|
-
return null;
|
|
79
|
-
const operationId = validateOperationId(parsed.operation_id);
|
|
80
|
-
const retryRaw = parsed.retry;
|
|
81
|
-
if (retryRaw === undefined)
|
|
82
|
-
return null;
|
|
83
|
-
if (retryRaw.disposition !== 'auto' && retryRaw.disposition !== 'manual' && retryRaw.disposition !== 'fatal')
|
|
84
|
-
return null;
|
|
85
|
-
if (retryRaw.by !== undefined && retryRaw.by !== 'sdk' && retryRaw.by !== 'daemon' && retryRaw.by !== 'client')
|
|
86
|
-
return null;
|
|
87
|
-
if (retryRaw.attempt !== undefined && typeof retryRaw.attempt !== 'number')
|
|
88
|
-
return null;
|
|
89
|
-
if (retryRaw.max !== undefined && typeof retryRaw.max !== 'number')
|
|
90
|
-
return null;
|
|
91
|
-
if (retryRaw.nextAt !== undefined && typeof retryRaw.nextAt !== 'string')
|
|
92
|
-
return null;
|
|
93
|
-
if (parsed.anchorEntryId !== undefined && (typeof parsed.anchorEntryId !== 'string' || parsed.anchorEntryId === ''))
|
|
94
|
-
return null;
|
|
95
|
-
const providerError = parsed.providerError === undefined ? undefined : parseProviderError(parsed.providerError);
|
|
96
|
-
if (parsed.providerError !== undefined && providerError === undefined)
|
|
97
|
-
return null;
|
|
98
|
-
return {
|
|
99
|
-
link: parsed.link,
|
|
100
|
-
op: parsed.op,
|
|
101
|
-
kind: parsed.kind,
|
|
102
|
-
retry: {
|
|
103
|
-
disposition: retryRaw.disposition,
|
|
104
|
-
...(retryRaw.by === undefined ? {} : { by: retryRaw.by }),
|
|
105
|
-
...(retryRaw.attempt === undefined ? {} : { attempt: retryRaw.attempt }),
|
|
106
|
-
...(retryRaw.max === undefined ? {} : { max: retryRaw.max }),
|
|
107
|
-
...(retryRaw.nextAt === undefined ? {} : { nextAt: retryRaw.nextAt }),
|
|
108
|
-
},
|
|
109
|
-
message: parsed.message,
|
|
110
|
-
since: parsed.since,
|
|
111
|
-
operation_id: operationId,
|
|
112
|
-
...(parsed.anchorEntryId === undefined ? {} : { anchorEntryId: parsed.anchorEntryId }),
|
|
113
|
-
...(providerError === undefined ? {} : { providerError }),
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
function currentFault(nodeId) {
|
|
121
|
-
try {
|
|
122
|
-
return parseFault(readFileSync(faultPath(nodeId), 'utf8'));
|
|
123
|
-
}
|
|
124
|
-
catch {
|
|
125
|
-
return null;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
function currentProviderRetryEpisode(nodeId) {
|
|
129
|
-
try {
|
|
130
|
-
const parsed = JSON.parse(readFileSync(providerRetryPath(nodeId), 'utf8'));
|
|
131
|
-
if (parsed.state !== 'pending' && parsed.state !== 'admitted' && parsed.state !== 'invalidated')
|
|
132
|
-
return null;
|
|
133
|
-
if (typeof parsed.sessionFile !== 'string' || parsed.sessionFile === '')
|
|
134
|
-
return null;
|
|
135
|
-
if (parsed.anchorEntryId !== null && typeof parsed.anchorEntryId !== 'string')
|
|
136
|
-
return null;
|
|
137
|
-
const fault = parseFault(JSON.stringify(parsed.fault));
|
|
138
|
-
if (fault === null ||
|
|
139
|
-
fault.link !== 'pi→provider' ||
|
|
140
|
-
fault.retry.disposition !== 'auto' ||
|
|
141
|
-
fault.retry.by !== 'daemon' ||
|
|
142
|
-
(fault.anchorEntryId ?? null) !== parsed.anchorEntryId)
|
|
143
|
-
return null;
|
|
144
|
-
return { state: parsed.state, sessionFile: canonicalSessionFile(parsed.sessionFile), anchorEntryId: parsed.anchorEntryId, fault };
|
|
145
|
-
}
|
|
146
|
-
catch {
|
|
147
|
-
return null;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
function writeFault(nodeId, fault) {
|
|
151
|
-
try {
|
|
152
|
-
mkdirSync(jobDir(nodeId), { recursive: true });
|
|
153
|
-
writeFileSync(faultPath(nodeId), JSON.stringify(fault));
|
|
154
|
-
return true;
|
|
155
|
-
}
|
|
156
|
-
catch {
|
|
157
|
-
return false;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
function writeProviderRetryEpisode(nodeId, episode) {
|
|
161
|
-
try {
|
|
162
|
-
mkdirSync(jobDir(nodeId), { recursive: true });
|
|
163
|
-
writeFileSync(providerRetryPath(nodeId), JSON.stringify(episode));
|
|
164
|
-
return true;
|
|
165
|
-
}
|
|
166
|
-
catch {
|
|
167
|
-
return false;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
function resolvedMarker(nodeId, fault) {
|
|
171
|
-
const current = currentFault(nodeId);
|
|
172
|
-
if (current === null)
|
|
173
|
-
return fault;
|
|
174
|
-
if (current.link === fault.link && current.kind === fault.kind) {
|
|
175
|
-
const retry = { ...current.retry, ...fault.retry };
|
|
176
|
-
if (fault.retry.disposition === 'fatal' && !('nextAt' in fault.retry)) {
|
|
177
|
-
delete retry.nextAt;
|
|
178
|
-
}
|
|
179
|
-
return { ...fault, since: current.since, anchorEntryId: current.anchorEntryId ?? fault.anchorEntryId, retry };
|
|
180
|
-
}
|
|
181
|
-
return faultPriority(current) > faultPriority(fault) ? null : fault;
|
|
182
|
-
}
|
|
183
|
-
function updateMarker(nodeId, fault) {
|
|
184
|
-
const resolved = resolvedMarker(nodeId, fault);
|
|
185
|
-
return resolved !== null && writeFault(nodeId, resolved) ? resolved : null;
|
|
186
|
-
}
|
|
187
|
-
function resolveOperationId(explicit) {
|
|
188
|
-
if (explicit !== undefined)
|
|
189
|
-
return validateOperationId(explicit);
|
|
190
|
-
const current = operationIdContext.current();
|
|
191
|
-
if (current !== undefined)
|
|
192
|
-
return current;
|
|
193
|
-
return operationIdContext.fresh((operationId) => operationId);
|
|
194
|
-
}
|
|
195
|
-
function storedFault(input) {
|
|
196
|
-
return {
|
|
197
|
-
link: input.link,
|
|
198
|
-
op: input.op,
|
|
199
|
-
kind: input.kind,
|
|
200
|
-
retry: input.retry,
|
|
201
|
-
message: clampMessage(input.message),
|
|
202
|
-
since: input.since ?? new Date().toISOString(),
|
|
203
|
-
operation_id: resolveOperationId(input.operation_id),
|
|
204
|
-
...(typeof input.anchorEntryId === 'string' && input.anchorEntryId !== '' ? { anchorEntryId: input.anchorEntryId } : {}),
|
|
205
|
-
...(input.providerError === undefined ? {} : { providerError: input.providerError }),
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
function emitRecordedFault(nodeId, fault) {
|
|
209
|
-
emitEvent({
|
|
210
|
-
level: fault.retry.disposition === 'fatal' ? 'error' : 'warn',
|
|
211
|
-
event: 'fault.recorded',
|
|
212
|
-
operation_id: fault.operation_id,
|
|
213
|
-
node_id: nodeId,
|
|
214
|
-
error_class: errorClassFromFault(fault),
|
|
215
|
-
fields: {
|
|
216
|
-
link: fault.link,
|
|
217
|
-
op: fault.op,
|
|
218
|
-
kind: fault.kind,
|
|
219
|
-
retry: fault.retry,
|
|
220
|
-
message: fault.message,
|
|
221
|
-
...(fault.anchorEntryId === undefined ? {} : { anchor_entry_id: fault.anchorEntryId }),
|
|
222
|
-
...(fault.providerError === undefined ? {} : { provider_error: fault.providerError }),
|
|
223
|
-
},
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
export function recordFault(nodeId, input) {
|
|
227
|
-
const fault = storedFault(input);
|
|
228
|
-
emitRecordedFault(nodeId, fault);
|
|
229
|
-
updateMarker(nodeId, fault);
|
|
230
|
-
}
|
|
231
|
-
/** Atomically establishes the crash-recovery authority before publishing its
|
|
232
|
-
* ordinary marker, so a broker death can never leave only a retryable fault. */
|
|
233
|
-
export function recordPendingProviderRetryFault(nodeId, sessionFile, input) {
|
|
234
|
-
const fault = storedFault(input);
|
|
235
|
-
emitRecordedFault(nodeId, fault);
|
|
236
|
-
const marker = resolvedMarker(nodeId, fault);
|
|
237
|
-
if (marker === null)
|
|
238
|
-
return null;
|
|
239
|
-
if (!writeProviderRetryEpisode(nodeId, {
|
|
240
|
-
state: 'pending',
|
|
241
|
-
sessionFile: canonicalSessionFile(sessionFile),
|
|
242
|
-
anchorEntryId: marker.anchorEntryId ?? null,
|
|
243
|
-
fault: marker,
|
|
244
|
-
}))
|
|
245
|
-
return null;
|
|
246
|
-
return writeFault(nodeId, marker) ? marker : null;
|
|
247
|
-
}
|
|
248
|
-
export function recordFaultForCurrentNode(input) {
|
|
249
|
-
const nodeId = envNodeId();
|
|
250
|
-
if (nodeId === undefined || nodeId.trim() === '')
|
|
251
|
-
return false;
|
|
252
|
-
if (!existsSync(jobDir(nodeId)))
|
|
253
|
-
return false;
|
|
254
|
-
try {
|
|
255
|
-
recordFault(nodeId, input);
|
|
256
|
-
return true;
|
|
257
|
-
}
|
|
258
|
-
catch {
|
|
259
|
-
return false;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
export function clearFault(nodeId, opts) {
|
|
263
|
-
try {
|
|
264
|
-
const current = currentFault(nodeId);
|
|
265
|
-
if (current === null)
|
|
266
|
-
return false;
|
|
267
|
-
if (opts?.link !== undefined && current.link !== opts.link)
|
|
268
|
-
return false;
|
|
269
|
-
rmSync(faultPath(nodeId));
|
|
270
|
-
const episode = currentProviderRetryEpisode(nodeId);
|
|
271
|
-
// turn_end precedes agent_settled. An admitted retry keeps its durable
|
|
272
|
-
// coordinate while the broker classifies an error settlement; an invalidated
|
|
273
|
-
// coordinate also remains durable so replacement startup cannot replay it.
|
|
274
|
-
if (opts?.preserveProviderRetryEpisode !== true &&
|
|
275
|
-
episode?.fault.since === current.since &&
|
|
276
|
-
episode.state === 'pending')
|
|
277
|
-
rmSync(providerRetryPath(nodeId), { force: true });
|
|
278
|
-
const operationId = resolveOperationId();
|
|
279
|
-
emitEvent({
|
|
280
|
-
level: 'info',
|
|
281
|
-
event: 'fault.cleared',
|
|
282
|
-
operation_id: operationId,
|
|
283
|
-
node_id: nodeId,
|
|
284
|
-
error_class: errorClassFromFault(current),
|
|
285
|
-
fields: {
|
|
286
|
-
cleared_fault_operation_id: current.operation_id,
|
|
287
|
-
link: current.link,
|
|
288
|
-
op: current.op,
|
|
289
|
-
kind: current.kind,
|
|
290
|
-
retry: current.retry,
|
|
291
|
-
message: current.message,
|
|
292
|
-
since: current.since,
|
|
293
|
-
...(current.anchorEntryId === undefined ? {} : { anchor_entry_id: current.anchorEntryId }),
|
|
294
|
-
},
|
|
295
|
-
});
|
|
296
|
-
return true;
|
|
297
|
-
}
|
|
298
|
-
catch {
|
|
299
|
-
return false;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
export function clearFaultForCurrentNode(opts) {
|
|
303
|
-
const nodeId = envNodeId();
|
|
304
|
-
if (nodeId === undefined || nodeId.trim() === '')
|
|
305
|
-
return false;
|
|
306
|
-
if (!existsSync(jobDir(nodeId)))
|
|
307
|
-
return false;
|
|
308
|
-
return clearFault(nodeId, opts);
|
|
309
|
-
}
|
|
310
|
-
export function readFault(nodeId) {
|
|
311
|
-
return currentFault(nodeId);
|
|
312
|
-
}
|
|
313
|
-
export function readProviderRetryEpisode(nodeId) {
|
|
314
|
-
return currentProviderRetryEpisode(nodeId);
|
|
315
|
-
}
|
|
316
|
-
/** Persist a newly scheduled provider retry before its broker-local timer is armed. */
|
|
317
|
-
export function recordPendingProviderRetryEpisode(nodeId, episode) {
|
|
318
|
-
return writeProviderRetryEpisode(nodeId, { ...episode, sessionFile: canonicalSessionFile(episode.sessionFile), state: 'pending' });
|
|
319
|
-
}
|
|
320
|
-
/** Admission is irreversible EXCEPT through a proven no-progress rollback: a
|
|
321
|
-
* broker startup that finds no assistant content or tool activity past the
|
|
322
|
-
* episode's anchor may reopen it via `reopenProviderRetryEpisode` below. Short
|
|
323
|
-
* of that proof, an admitted episode is never replayed. */
|
|
324
|
-
export function admitProviderRetryEpisode(nodeId, sessionFile, fault) {
|
|
325
|
-
const current = currentProviderRetryEpisode(nodeId);
|
|
326
|
-
if (current === null ||
|
|
327
|
-
current.state !== 'pending' ||
|
|
328
|
-
current.sessionFile !== canonicalSessionFile(sessionFile) ||
|
|
329
|
-
current.fault.since !== fault.since ||
|
|
330
|
-
current.anchorEntryId !== (fault.anchorEntryId ?? null))
|
|
331
|
-
return false;
|
|
332
|
-
return writeProviderRetryEpisode(nodeId, {
|
|
333
|
-
state: 'admitted',
|
|
334
|
-
sessionFile: current.sessionFile,
|
|
335
|
-
anchorEntryId: current.anchorEntryId,
|
|
336
|
-
fault,
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
/** Reopens an `admitted` episode to `pending` so a surviving broker startup can
|
|
340
|
-
* re-drive it exactly like a never-admitted one. Callable only under the same
|
|
341
|
-
* no-progress proof `recoverOnStartup` establishes — the branch segment from
|
|
342
|
-
* `anchorEntryId` to the current leaf carries no assistant content and no tool
|
|
343
|
-
* activity. Guarded by the same transcript-identity coordinate `admitProviderRetryEpisode`
|
|
344
|
-
* uses, so a foreign or already-invalidated episode is never reopened. */
|
|
345
|
-
export function reopenProviderRetryEpisode(nodeId, sessionFile) {
|
|
346
|
-
const current = currentProviderRetryEpisode(nodeId);
|
|
347
|
-
if (current === null || current.state !== 'admitted' || current.sessionFile !== canonicalSessionFile(sessionFile))
|
|
348
|
-
return false;
|
|
349
|
-
return writeProviderRetryEpisode(nodeId, { ...current, state: 'pending' });
|
|
350
|
-
}
|
|
351
|
-
/** A replacement explicitly invalidates its old transcript's retry episode. */
|
|
352
|
-
export function invalidateProviderRetryEpisode(nodeId, sessionFile) {
|
|
353
|
-
const current = currentProviderRetryEpisode(nodeId);
|
|
354
|
-
if (current === null || current.sessionFile !== canonicalSessionFile(sessionFile) || current.state === 'invalidated')
|
|
355
|
-
return false;
|
|
356
|
-
return writeProviderRetryEpisode(nodeId, { ...current, state: 'invalidated' });
|
|
357
|
-
}
|
|
358
|
-
export function clearProviderRetryEpisode(nodeId) {
|
|
359
|
-
try {
|
|
360
|
-
rmSync(providerRetryPath(nodeId), { force: true });
|
|
361
|
-
}
|
|
362
|
-
catch {
|
|
363
|
-
/* best-effort */
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
export async function readFaultAsync(nodeId) {
|
|
367
|
-
return readFault(nodeId);
|
|
368
|
-
}
|
|
369
|
-
/** Snapshot fault state immediately before a broker launch begins, returning a
|
|
370
|
-
* reader that is only trustworthy for a fault recorded by THIS attempt.
|
|
371
|
-
*
|
|
372
|
-
* `clearFault` can silently fail to remove a prior marker (its own removal
|
|
373
|
-
* errors are swallowed, and its result goes unchecked by callers), so rather
|
|
374
|
-
* than assume that call succeeded, this independently CONFIRMS no fault is
|
|
375
|
-
* present at the moment of launch. Other processes (a viewer, a relay) can
|
|
376
|
-
* still write THEIR OWN fault links after this snapshot, but `explanation()`
|
|
377
|
-
* only ever accepts a fatal `crtr→pi` launch fault — the one shape only a
|
|
378
|
-
* newly launched broker itself writes (`resolveLaunchModel` in `broker.ts`) —
|
|
379
|
-
* so no ACCEPTED fault can exist before this snapshot without also surviving
|
|
380
|
-
* a failed clear, which the snapshot already catches. When a stale fault
|
|
381
|
-
* survives the clear, `explanation()` fails closed (returns null) rather than
|
|
382
|
-
* risk surfacing an old, unrelated cause as if it were fresh.
|
|
383
|
-
*
|
|
384
|
-
* Call this the instant before the launch call it is guarding, so the window
|
|
385
|
-
* in which an unrelated write could occur stays as small as possible. */
|
|
386
|
-
export function beginBootFaultAttempt(nodeId) {
|
|
387
|
-
const preLaunchClear = readFault(nodeId) === null;
|
|
388
|
-
return {
|
|
389
|
-
explanation() {
|
|
390
|
-
if (!preLaunchClear)
|
|
391
|
-
return null;
|
|
392
|
-
const fault = readFault(nodeId);
|
|
393
|
-
if (fault === null)
|
|
394
|
-
return null;
|
|
395
|
-
if (fault.link !== 'crtr\u2192pi' || fault.retry.disposition !== 'fatal')
|
|
396
|
-
return null;
|
|
397
|
-
const op = fault.op.trim();
|
|
398
|
-
const message = fault.message.trim();
|
|
399
|
-
if (op === '' || message === '')
|
|
400
|
-
return null;
|
|
401
|
-
return `${op}: ${message}`;
|
|
402
|
-
},
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
/** True when a raw engine error says pi could not resolve a credential for the model's
|
|
406
|
-
* provider at all. pi raises `Provider is not configured: <id>` whenever auth resolution
|
|
407
|
-
* yields nothing, and `Credential store read/modify failed for <id>` when the store itself
|
|
408
|
-
* errored — for crouter's managed providers both mean "the pool did not hand over a usable
|
|
409
|
-
* credential just now", which is frequently transient (a refresh in flight, a momentary read
|
|
410
|
-
* failure) and never something the agent can fix from inside its own turn. Classified as a
|
|
411
|
-
* plain `other` fault it is FATAL, so the node parks and every wake re-fails on the same
|
|
412
|
-
* provider; the broker instead substitutes an authenticated provider and re-drives. */
|
|
2
|
+
/** True when Pi could not resolve credentials for a provider. */
|
|
413
3
|
export function isProviderUnconfiguredError(message) {
|
|
414
|
-
const
|
|
415
|
-
if (/provider is not configured\b/i.test(
|
|
4
|
+
const value = message ?? '';
|
|
5
|
+
if (/provider is not configured\b/i.test(value))
|
|
416
6
|
return true;
|
|
417
|
-
return /credential store (?:read|modify) failed\b/i.test(
|
|
7
|
+
return /credential store (?:read|modify) failed\b/i.test(value);
|
|
418
8
|
}
|
|
419
|
-
/** True when a
|
|
9
|
+
/** True when a provider reports that a requested model is unavailable. */
|
|
420
10
|
export function isModelNotFoundError(message) {
|
|
421
|
-
const
|
|
422
|
-
if (/not_found_error/i.test(
|
|
11
|
+
const value = message ?? '';
|
|
12
|
+
if (/not_found_error/i.test(value))
|
|
423
13
|
return true;
|
|
424
|
-
if (/model[^.]{0,40}(not\s*found|does not exist|is not available|unavailable)|(no such|unknown) model/i.test(
|
|
14
|
+
if (/model[^.]{0,40}(not\s*found|does not exist|is not available|unavailable)|(no such|unknown) model/i.test(value))
|
|
425
15
|
return true;
|
|
426
|
-
return /\b404\b/.test(
|
|
16
|
+
return /\b404\b/.test(value) && /not\s*found|not available|does not exist/i.test(value);
|
|
427
17
|
}
|
|
@@ -32,17 +32,14 @@ export declare function hasRetainedReports(nodeId: string): boolean;
|
|
|
32
32
|
export interface ReviveBearings {
|
|
33
33
|
/** The one-shot yield note left by the prior self, pending boot confirmation. */
|
|
34
34
|
yieldMsg: string | null;
|
|
35
|
-
/** Coalesced
|
|
36
|
-
* cursor now records the last physically covered entry. */
|
|
35
|
+
/** Coalesced wake mail, held by the execution until the turn settles. */
|
|
37
36
|
unreadDigest: string | null;
|
|
38
37
|
/** Persona-transition framing to surface when the node's role changed while
|
|
39
38
|
* it was away. The drift remains pending until context-intro completes. */
|
|
40
39
|
driftGuidance: string | null;
|
|
41
40
|
}
|
|
42
|
-
/**
|
|
43
|
-
|
|
44
|
-
* Revive paths call it once, then pass the result to the pure kickoff builder. */
|
|
45
|
-
export declare function drainBearings(meta: NodeMeta): ReviveBearings;
|
|
41
|
+
/** Claim wake mail for this launch without acknowledging it before a turn. */
|
|
42
|
+
export declare function drainBearings(meta: NodeMeta, executionId: string): ReviveBearings;
|
|
46
43
|
/** Assemble the auto-injected first message for a FRESH revive of `meta` from its
|
|
47
44
|
* already-drained `bearings` (see drainBearings) plus pure on-disk reads of the
|
|
48
45
|
* node's goal, roadmap, and context dir, framed so the revived node can rebuild
|
|
@@ -25,7 +25,8 @@ import { activeBackgroundBashJobs, bashJobCommandLine, formatBashElapsed } from
|
|
|
25
25
|
import { readRoadmap, roadmapPath } from './roadmap.js';
|
|
26
26
|
import { buildWakeBearings } from './bearings.js';
|
|
27
27
|
import { personaDrift } from './persona.js';
|
|
28
|
-
import {
|
|
28
|
+
import { coalesce, nodeMailEntry } from '../feed/inbox.js';
|
|
29
|
+
import { claimKickoffMail } from '../canvas/deliveries.js';
|
|
29
30
|
import { formatCard } from '../../shared/generated-context.js';
|
|
30
31
|
/** The runtime-restart continuation exactly as delivered. `revive.ts` injects
|
|
31
32
|
* it as the prompt of a strict resume that follows a cleanly aborted turn. */
|
|
@@ -105,20 +106,14 @@ export function hasRetainedReports(nodeId) {
|
|
|
105
106
|
const dir = reportsDir(nodeId);
|
|
106
107
|
return existsSync(dir) && readdirSync(dir).some((file) => file.endsWith('.md'));
|
|
107
108
|
}
|
|
108
|
-
/**
|
|
109
|
-
|
|
110
|
-
* Revive paths call it once, then pass the result to the pure kickoff builder. */
|
|
111
|
-
export function drainBearings(meta) {
|
|
109
|
+
/** Claim wake mail for this launch without acknowledging it before a turn. */
|
|
110
|
+
export function drainBearings(meta, executionId) {
|
|
112
111
|
const nodeId = meta.node_id;
|
|
113
112
|
// The note stays on disk until session_start confirms this launch.
|
|
114
113
|
const yieldMsg = readYieldMessage(nodeId);
|
|
115
|
-
|
|
116
|
-
// record its final entry so only later physical entries remain unread.
|
|
117
|
-
const cursorEntryId = readCursor(nodeId);
|
|
118
|
-
const entries = readInboxSince(nodeId, cursorEntryId);
|
|
114
|
+
const entries = claimKickoffMail(nodeId, executionId).map(nodeMailEntry);
|
|
119
115
|
let unreadDigest = null;
|
|
120
116
|
if (entries.length > 0) {
|
|
121
|
-
writeCursor(nodeId, entries.at(-1).entry_id);
|
|
122
117
|
// The launch argv carries one message. Keep coalescing card-free runs, but
|
|
123
118
|
// start a new batch at each entry with cards. A batch's cards are therefore
|
|
124
119
|
// directly ahead of its coalesced text, so they cannot leap an earlier body.
|
|
@@ -144,8 +139,8 @@ export function drainBearings(meta) {
|
|
|
144
139
|
return { yieldMsg, unreadDigest, driftGuidance };
|
|
145
140
|
}
|
|
146
141
|
// Fresh-revive catch-up bug: on a refresh-yield (resume:false) the old
|
|
147
|
-
// conversation is gone AND
|
|
148
|
-
//
|
|
142
|
+
// conversation is gone AND earlier deliveries are already acknowledged,
|
|
143
|
+
// so the revived node loses sight of reports its
|
|
149
144
|
// subscriptions pushed BEFORE the yield. The bodies are never lost — they persist
|
|
150
145
|
// at reports/<ts>-<kind>.md forever — but a fresh revive needs a bounded index
|
|
151
146
|
// that says history exists and how to expand it, not every path preloaded.
|
|
@@ -181,7 +176,7 @@ function reportHistorySources(nodeId) {
|
|
|
181
176
|
}
|
|
182
177
|
/** Render the <feed> block PURELY: the live "awaiting" roster (a read), the
|
|
183
178
|
* already-drained unread digest (from drainBearings), and a progressive index
|
|
184
|
-
* to on-disk report history. No
|
|
179
|
+
* to on-disk report history. No delivery mutation. */
|
|
185
180
|
function feedBlock(nodeId, unreadDigest) {
|
|
186
181
|
// Awaiting = active subscriptions whose publisher is still live (active|idle).
|
|
187
182
|
const awaiting = subscriptionsOf(nodeId)
|
|
@@ -206,18 +201,17 @@ function feedBlock(nodeId, unreadDigest) {
|
|
|
206
201
|
lines.push('Awaiting 0 nodes.');
|
|
207
202
|
lines.push('', unreadDigest ?? '(no unread reports)');
|
|
208
203
|
}
|
|
209
|
-
//
|
|
210
|
-
//
|
|
211
|
-
// pre-yield, so preserve the breadcrumb without preloading every old report.
|
|
204
|
+
// Include a bounded history index because acknowledged reports are absent
|
|
205
|
+
// from the unread digest after a refresh.
|
|
212
206
|
const history = reportHistorySources(nodeId);
|
|
213
207
|
if (history.length > 0) {
|
|
214
208
|
const visible = history.slice(0, REPORT_HISTORY_SOURCE_CAP);
|
|
215
209
|
const hidden = history.length - visible.length;
|
|
216
210
|
const total = history.reduce((sum, h) => sum + h.count, 0);
|
|
217
|
-
lines.push('', `Report history on disk (collapsed): ${total} report${total === 1 ? '' : 's'} across ${history.length} subscribed node${history.length === 1 ? '' : 's'}. This is a catch-up index for reports
|
|
211
|
+
lines.push('', `Report history on disk (collapsed): ${total} report${total === 1 ? '' : 's'} across ${history.length} subscribed node${history.length === 1 ? '' : 's'}. This is a catch-up index for earlier reports; read only what matters.`, ...visible.map((h) => {
|
|
218
212
|
const ref = `${h.nodeId}:reports/${h.latest}`;
|
|
219
213
|
return ` - ${h.name} (${h.nodeId}): ${h.count} report${h.count === 1 ? '' : 's'}; latest ${reportKind(h.latest)}: ${ref}`;
|
|
220
|
-
}), ...(hidden > 0 ? [` - … ${hidden} more subscribed node${hidden === 1 ? '' : 's'} with reports hidden`] : []), 'Expand: `crtr canvas history read <ref>` for one listed report; `crtr node inspect artifacts <node-id> --type report` for that node\'s full report list; `crtr node inspect artifacts <node-id> --type inbox` for
|
|
214
|
+
}), ...(hidden > 0 ? [` - … ${hidden} more subscribed node${hidden === 1 ? '' : 's'} with reports hidden`] : []), 'Expand: `crtr canvas history read <ref>` for one listed report; `crtr node inspect artifacts <node-id> --type report` for that node\'s full report list; `crtr node inspect artifacts <node-id> --type inbox` for retained inbox history including full message bodies.');
|
|
221
215
|
}
|
|
222
216
|
return `<feed>\n${lines.join('\n')}\n</feed>`;
|
|
223
217
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// The launch spec — how a node becomes (or comes back as) a running pi process.
|
|
2
2
|
//
|
|
3
3
|
// pi-only. No claude branch — we are a super-opinionated system. A node's
|
|
4
|
-
// LaunchSpec (
|
|
4
|
+
// LaunchSpec (stored with the node in SQL) is the canonical recipe the daemon
|
|
5
5
|
// replays to revive it faithfully: `--session <path>` (the saved conversation's
|
|
6
6
|
// absolute .jsonl) to wake a done/idle node — a refresh-yield reuses the SAME
|
|
7
7
|
// path plus `--crtr-new-cycle`, resetting the session tree's leaf and rooting a
|
|
@@ -31,7 +31,9 @@
|
|
|
31
31
|
// unknown-node/illegal-move/already-finalized-cancel branching — stays here;
|
|
32
32
|
// only the raw conditional UPDATE lives in canvas.ts, keeping every `.prepare(`
|
|
33
33
|
// inside `core/canvas/`).
|
|
34
|
-
import { getNode, cancelCronsOnWake,
|
|
34
|
+
import { getNode, cancelCronsOnWake, transitionStatusIntent } from '../canvas/index.js';
|
|
35
|
+
import { readExternalActionDelivery } from '../canvas/deliveries.js';
|
|
36
|
+
import { composeNodeOutcomeDocument } from './outcome-document.js';
|
|
35
37
|
const ANY = '*';
|
|
36
38
|
const TERMINAL_REASONS = {
|
|
37
39
|
finish: 'finished',
|
|
@@ -95,6 +97,37 @@ function detailJson(detail) {
|
|
|
95
97
|
return serialized;
|
|
96
98
|
return JSON.stringify({ schema: 'crtr.node-outcome-detail/v1', truncated: true, ...(message === undefined ? {} : { message }) });
|
|
97
99
|
}
|
|
100
|
+
function armedOutcomeAction(nodeId) {
|
|
101
|
+
const delivery = readExternalActionDelivery(`node-outcome:${nodeId}`);
|
|
102
|
+
if (delivery === null || delivery.state !== 'armed')
|
|
103
|
+
return null;
|
|
104
|
+
const adapter = delivery.adapter;
|
|
105
|
+
if (adapter?.adapter !== 'subprocess' || !Array.isArray(adapter.argv) || !adapter.argv.every((entry) => typeof entry === 'string') || typeof adapter.cwd !== 'string') {
|
|
106
|
+
throw new Error(`outcome delivery ${delivery.deliveryId} has an invalid subprocess adapter`);
|
|
107
|
+
}
|
|
108
|
+
return { name: delivery.destinationId, payload: adapter.payload ?? null };
|
|
109
|
+
}
|
|
110
|
+
function nodeAtOutcome(node, reason) {
|
|
111
|
+
let status;
|
|
112
|
+
let intent;
|
|
113
|
+
if (reason === 'finished' || reason === 'declined') {
|
|
114
|
+
status = 'done';
|
|
115
|
+
intent = 'done';
|
|
116
|
+
}
|
|
117
|
+
else if (reason === 'parked') {
|
|
118
|
+
status = 'done';
|
|
119
|
+
intent = 'parked';
|
|
120
|
+
}
|
|
121
|
+
else if (reason === 'closed' || reason === 'retired' || reason === 'stranded' || reason === 'deadline_exceeded') {
|
|
122
|
+
status = 'canceled';
|
|
123
|
+
intent = null;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
status = 'dead';
|
|
127
|
+
intent = null;
|
|
128
|
+
}
|
|
129
|
+
return { ...node, status, intent, terminal_reason: reason };
|
|
130
|
+
}
|
|
98
131
|
/** Enact a lifecycle event on a node: validate the from-status against the
|
|
99
132
|
* table, then write status+intent in ONE atomic statement (so they can never
|
|
100
133
|
* disagree). Returns the hydrated node view after the write.
|
|
@@ -121,13 +154,13 @@ export function transition(nodeId, event, opts) {
|
|
|
121
154
|
const outcomeDetailJson = detailJson(opts?.outcome?.detail);
|
|
122
155
|
let documentJson;
|
|
123
156
|
if (recordsOutcome && current !== null && current.outcome_at === null) {
|
|
124
|
-
const
|
|
125
|
-
if (
|
|
126
|
-
documentJson =
|
|
127
|
-
|
|
157
|
+
const action = armedOutcomeAction(nodeId);
|
|
158
|
+
if (action !== null) {
|
|
159
|
+
documentJson = JSON.stringify(composeNodeOutcomeDocument({
|
|
160
|
+
node: nodeAtOutcome(current, outcomeReason),
|
|
128
161
|
outcome: { kind: 'failure', reason: outcomeReason, at: outcomeAt, revision: (current.outcome_revision ?? 0) + 1, detailJson: outcomeDetailJson },
|
|
129
|
-
action
|
|
130
|
-
});
|
|
162
|
+
action,
|
|
163
|
+
}));
|
|
131
164
|
}
|
|
132
165
|
}
|
|
133
166
|
// A committed canonical result is protected from a concurrent close.
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
// tmux half, the bindings owner, and tmux chrome.
|
|
25
25
|
import { envNodeId } from '../../shared/env.js';
|
|
26
26
|
import { getNode, fullName, deleteNode, listNodes, subscribersOf, openFocusRow, closeFocusRow, getFocusByNode, getFocusByPane, getFocusById, listFocuses as listFocusRows, } from '../canvas/index.js';
|
|
27
|
-
import { nodeHasAssistantMessage
|
|
27
|
+
import { nodeHasAssistantMessage } from '../canvas/render-source.js';
|
|
28
28
|
import { headlessBrokerHost } from './host.js';
|
|
29
29
|
import { fanDoctrineWake } from './close.js';
|
|
30
30
|
import { paneExists, paneLocation, closePane, currentTmux, switchClient, selectWindow, selectLayout, selectPane, getPaneOption, setPaneOption, respawnPaneSync, windowOfPane, renameWindow, } from './tmux-driver.js';
|
|
@@ -331,7 +331,7 @@ function isEmptyNode(nodeId) {
|
|
|
331
331
|
const m = getNode(nodeId);
|
|
332
332
|
if (m === null)
|
|
333
333
|
return false;
|
|
334
|
-
if (
|
|
334
|
+
if (m.streaming === true)
|
|
335
335
|
return false;
|
|
336
336
|
return !nodeHasAssistantMessage(m.pi_session_file);
|
|
337
337
|
}
|