@north-light/cli 0.3.530 → 0.3.532
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/clients/attach/session/connection.js +1 -1
- package/dist/clients/attach/session/reconnect.js +1 -1
- package/dist/clients/attach/viewer.js +508 -508
- package/dist/core/async-array.d.ts +7 -0
- package/dist/core/async-array.js +1 -0
- package/dist/core/audit.d.ts +1 -1
- package/dist/core/audit.js +2 -2
- package/dist/core/canvas/attention.d.ts +4 -4
- package/dist/core/canvas/attention.js +1 -1
- package/dist/core/canvas/boot.d.ts +4 -4
- package/dist/core/canvas/boot.js +1 -1
- package/dist/core/canvas/canvas.d.ts +59 -59
- package/dist/core/canvas/canvas.js +19 -19
- package/dist/core/canvas/context-strip.js +2 -2
- package/dist/core/canvas/crons.d.ts +27 -27
- package/dist/core/canvas/crons.js +11 -11
- package/dist/core/canvas/daemon-actions.d.ts +10 -10
- package/dist/core/canvas/daemon-actions.js +8 -8
- package/dist/core/canvas/daemon-owner.d.ts +3 -3
- package/dist/core/canvas/daemon-owner.js +2 -2
- package/dist/core/canvas/db.d.ts +19 -30
- package/dist/core/canvas/db.js +3 -2
- package/dist/core/canvas/deliveries.d.ts +16 -16
- package/dist/core/canvas/deliveries.js +24 -24
- package/dist/core/canvas/executions.d.ts +8 -8
- package/dist/core/canvas/executions.js +1 -1
- package/dist/core/canvas/focuses.d.ts +8 -8
- package/dist/core/canvas/focuses.js +1 -1
- package/dist/core/canvas/history.d.ts +3 -3
- package/dist/core/canvas/history.js +9 -9
- package/dist/core/canvas/install-id.d.ts +1 -1
- package/dist/core/canvas/install-id.js +1 -1
- package/dist/core/canvas/managed-worktree-sweep-candidates.d.ts +1 -1
- package/dist/core/canvas/managed-worktree-sweep-candidates.js +2 -2
- package/dist/core/canvas/memory-reads.d.ts +6 -6
- package/dist/core/canvas/memory-reads.js +1 -1
- package/dist/core/canvas/nav-model.d.ts +13 -13
- package/dist/core/canvas/nav-model.js +1 -1
- package/dist/core/canvas/node-agent-paths.d.ts +6 -6
- package/dist/core/canvas/node-agent-paths.js +1 -1
- package/dist/core/canvas/node-tokens.d.ts +7 -7
- package/dist/core/canvas/node-tokens.js +3 -3
- package/dist/core/canvas/outcome-actions.d.ts +5 -5
- package/dist/core/canvas/outcome-actions.js +3 -3
- package/dist/core/canvas/recovery.d.ts +26 -26
- package/dist/core/canvas/recovery.js +2 -2
- package/dist/core/canvas/render-source.d.ts +1 -1
- package/dist/core/canvas/render-source.js +1 -1
- package/dist/core/canvas/sessions.d.ts +10 -10
- package/dist/core/canvas/sessions.js +4 -4
- package/dist/core/canvas/source.js +1 -1
- package/dist/core/canvas/structured-requests.d.ts +15 -15
- package/dist/core/canvas/structured-requests.js +5 -5
- package/dist/core/canvas/tree.d.ts +9 -9
- package/dist/core/canvas/tree.js +5 -5
- package/dist/core/canvas/waits.d.ts +13 -13
- package/dist/core/canvas/waits.js +6 -6
- package/dist/core/canvas/worktrees.d.ts +15 -15
- package/dist/core/canvas/worktrees.js +1 -1
- package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
- package/dist/core/conversation-store/file-store.d.ts +7 -7
- package/dist/core/conversation-store/file-store.js +9 -9
- package/dist/core/conversation-store/index.d.ts +16 -14
- package/dist/core/conversation-store/index.js +1 -1
- package/dist/core/conversation-store/listener.js +5 -5
- package/dist/core/conversation-store/patch.d.ts +3 -1
- package/dist/core/conversation-store/patch.js +1 -1
- package/dist/core/feed/feed.js +3 -3
- package/dist/core/feed/inbox.d.ts +2 -2
- package/dist/core/feed/inbox.js +1 -1
- package/dist/core/feed/messages.d.ts +11 -12
- package/dist/core/feed/messages.js +5 -5
- package/dist/core/feed/reports.d.ts +4 -4
- package/dist/core/feed/reports.js +2 -2
- package/dist/core/grants/cover.d.ts +1 -1
- package/dist/core/grants/cover.js +1 -1
- package/dist/core/grants/local.d.ts +1 -1
- package/dist/core/grants/local.js +1 -1
- package/dist/core/grants/mirror.d.ts +19 -19
- package/dist/core/grants/mirror.js +2 -2
- package/dist/core/grants/on-sync.d.ts +1 -1
- package/dist/core/grants/on-sync.js +1 -1
- package/dist/core/grants/remove.js +1 -1
- package/dist/core/grants/sync.js +1 -1
- package/dist/core/graph/access.d.ts +17 -17
- package/dist/core/graph/access.js +3 -3
- package/dist/core/graph/custom.d.ts +16 -16
- package/dist/core/graph/custom.js +9 -9
- package/dist/core/graph/deletion.d.ts +3 -7
- package/dist/core/graph/deletion.js +4 -4
- package/dist/core/graph/documents.d.ts +24 -27
- package/dist/core/graph/documents.js +7 -7
- package/dist/core/graph/edges.d.ts +13 -13
- package/dist/core/graph/edges.js +1 -1
- package/dist/core/graph/events.d.ts +7 -9
- package/dist/core/graph/events.js +8 -8
- package/dist/core/graph/exposures.d.ts +6 -6
- package/dist/core/graph/exposures.js +4 -4
- package/dist/core/graph/jobs.d.ts +6 -8
- package/dist/core/graph/jobs.js +2 -2
- package/dist/core/graph/kinds/action.js +1 -1
- package/dist/core/graph/kinds/custom.js +2 -2
- package/dist/core/graph/kinds/document.d.ts +1 -0
- package/dist/core/graph/kinds/document.js +4 -4
- package/dist/core/graph/kinds/dto.d.ts +2 -2
- package/dist/core/graph/kinds/dto.js +1 -1
- package/dist/core/graph/kinds/job.js +2 -2
- package/dist/core/graph/kinds/kind.d.ts +6 -8
- package/dist/core/graph/kinds/kind.js +1 -1
- package/dist/core/graph/kinds/node.js +5 -5
- package/dist/core/graph/kinds/owner.js +2 -2
- package/dist/core/graph/kinds/registry.d.ts +6 -9
- package/dist/core/graph/kinds/registry.js +1 -1
- package/dist/core/graph/names.d.ts +6 -6
- package/dist/core/graph/names.js +3 -3
- package/dist/core/graph/object-waits.d.ts +4 -7
- package/dist/core/graph/object-waits.js +1 -1
- package/dist/core/graph/objects.d.ts +14 -14
- package/dist/core/graph/objects.js +9 -9
- package/dist/core/graph/package-docs.d.ts +2 -7
- package/dist/core/graph/package-docs.js +5 -5
- package/dist/core/graph/package-kinds.d.ts +2 -5
- package/dist/core/graph/package-kinds.js +1 -1
- package/dist/core/graph/package-reconcile.d.ts +2 -5
- package/dist/core/graph/package-reconcile.js +1 -1
- package/dist/core/graph/reader.d.ts +18 -18
- package/dist/core/graph/reader.js +3 -3
- package/dist/core/graph/receivers.d.ts +4 -4
- package/dist/core/graph/receivers.js +5 -5
- package/dist/core/graph/repo-sync/exchange.d.ts +3 -7
- package/dist/core/graph/repo-sync/exchange.js +2 -2
- package/dist/core/graph/repo-sync/repos.d.ts +7 -5
- package/dist/core/graph/repo-sync/repos.js +3 -3
- package/dist/core/graph/repo-sync/sync.d.ts +3 -6
- package/dist/core/graph/repo-sync/sync.js +2 -2
- package/dist/core/graph/rules.d.ts +5 -5
- package/dist/core/graph/rules.js +3 -3
- package/dist/core/graph/spaces/app.js +1 -1
- package/dist/core/graph/spaces/index.d.ts +4 -5
- package/dist/core/graph/spaces/index.js +1 -1
- package/dist/core/graph/spaces/own-memory.d.ts +4 -4
- package/dist/core/graph/spaces/own-memory.js +1 -1
- package/dist/core/graph/spaces/person.js +3 -3
- package/dist/core/graph/spaces/repo.d.ts +1 -1
- package/dist/core/graph/spaces/repo.js +1 -1
- package/dist/core/graph/watches.d.ts +15 -15
- package/dist/core/graph/watches.js +10 -10
- package/dist/core/human/feedback-companion.d.ts +2 -2
- package/dist/core/human/feedback-companion.js +1 -1
- package/dist/core/human/feedback.d.ts +3 -3
- package/dist/core/human/feedback.js +1 -1
- package/dist/core/human/requests.d.ts +34 -33
- package/dist/core/human/requests.js +20 -20
- package/dist/core/human/scan.d.ts +2 -2
- package/dist/core/human/scan.js +1 -1
- package/dist/core/human/tickets.d.ts +9 -9
- package/dist/core/human/tickets.js +1 -1
- package/dist/core/llm/app-rungs.d.ts +1 -1
- package/dist/core/llm/app-rungs.js +1 -1
- package/dist/core/llm/run.js +2 -2
- package/dist/core/peer/directory.d.ts +1 -1
- package/dist/core/peer/directory.js +1 -1
- package/dist/core/peer/envelope.d.ts +3 -3
- package/dist/core/peer/envelope.js +1 -1
- package/dist/core/peer/home.d.ts +13 -7
- package/dist/core/peer/home.js +2 -2
- package/dist/core/peer/ingest.d.ts +6 -6
- package/dist/core/peer/ingest.js +1 -1
- package/dist/core/peer/outbox-store.d.ts +14 -14
- package/dist/core/peer/outbox-store.js +5 -5
- package/dist/core/peer/receiver.d.ts +2 -2
- package/dist/core/peer/receiver.js +1 -1
- package/dist/core/peer/stubs.d.ts +10 -10
- package/dist/core/peer/stubs.js +1 -1
- package/dist/core/providers/approval.d.ts +2 -2
- package/dist/core/providers/approval.js +2 -2
- package/dist/core/providers/audit.d.ts +3 -3
- package/dist/core/providers/audit.js +2 -2
- package/dist/core/providers/bundles.js +2 -2
- package/dist/core/providers/call.d.ts +2 -2
- package/dist/core/providers/call.js +1 -1
- package/dist/core/providers/files.d.ts +1 -1
- package/dist/core/providers/files.js +1 -1
- package/dist/core/providers/mint.js +1 -1
- package/dist/core/providers/receipts.d.ts +1 -1
- package/dist/core/providers/receipts.js +2 -2
- package/dist/core/review/birth.js +1 -1
- package/dist/core/review/comments.d.ts +19 -19
- package/dist/core/review/comments.js +5 -5
- package/dist/core/review/companion.d.ts +1 -1
- package/dist/core/review/companion.js +1 -1
- package/dist/core/review/document.d.ts +3 -3
- package/dist/core/review/document.js +2 -2
- package/dist/core/review/fork.js +2 -2
- package/dist/core/review/realize.js +1 -1
- package/dist/core/review/remap.d.ts +2 -2
- package/dist/core/review/remap.js +4 -4
- package/dist/core/review/stage.d.ts +1 -1
- package/dist/core/review/stage.js +1 -1
- package/dist/core/review/store.d.ts +21 -21
- package/dist/core/review/store.js +1 -1
- package/dist/core/runs/activity.d.ts +1 -1
- package/dist/core/runs/activity.js +5 -5
- package/dist/core/runs/confinement.d.ts +7 -7
- package/dist/core/runs/confinement.js +2 -2
- package/dist/core/runs/events.d.ts +12 -12
- package/dist/core/runs/events.js +4 -4
- package/dist/core/runs/operations.d.ts +11 -11
- package/dist/core/runs/operations.js +5 -5
- package/dist/core/runs/questions.d.ts +10 -10
- package/dist/core/runs/questions.js +3 -3
- package/dist/core/runtime/auth-reload.js +1 -1
- package/dist/core/runtime/bearings.d.ts +5 -5
- package/dist/core/runtime/bearings.js +6 -6
- package/dist/core/runtime/broker-inventory.js +1 -1
- package/dist/core/runtime/broker-request.js +1 -1
- package/dist/core/runtime/broker.js +1 -1
- package/dist/core/runtime/close.d.ts +3 -3
- package/dist/core/runtime/close.js +1 -1
- package/dist/core/runtime/deliver-live.js +1 -1
- package/dist/core/runtime/fleet.d.ts +2 -2
- package/dist/core/runtime/host.d.ts +3 -3
- package/dist/core/runtime/host.js +3 -3
- package/dist/core/runtime/kickoff.d.ts +12 -12
- package/dist/core/runtime/kickoff.js +17 -17
- package/dist/core/runtime/launch-target.d.ts +1 -1
- package/dist/core/runtime/launch-target.js +1 -1
- package/dist/core/runtime/ledger.d.ts +3 -3
- package/dist/core/runtime/ledger.js +3 -3
- package/dist/core/runtime/lifecycle.d.ts +1 -1
- package/dist/core/runtime/lifecycle.js +2 -2
- package/dist/core/runtime/memory-admission.js +1 -1
- package/dist/core/runtime/model-swap.d.ts +2 -2
- package/dist/core/runtime/model-swap.js +1 -1
- package/dist/core/runtime/node-read.d.ts +1 -1
- package/dist/core/runtime/node-read.js +2 -2
- package/dist/core/runtime/nodes.d.ts +6 -6
- package/dist/core/runtime/nodes.js +1 -1
- package/dist/core/runtime/outcome-document.d.ts +1 -1
- package/dist/core/runtime/outcome-document.js +1 -1
- package/dist/core/runtime/persona.d.ts +3 -3
- package/dist/core/runtime/persona.js +2 -2
- package/dist/core/runtime/placement.d.ts +11 -11
- package/dist/core/runtime/placement.js +1 -1
- package/dist/core/runtime/promote.d.ts +3 -3
- package/dist/core/runtime/promote.js +1 -1
- package/dist/core/runtime/recycle.js +1 -1
- package/dist/core/runtime/reopen.d.ts +5 -5
- package/dist/core/runtime/reopen.js +1 -1
- package/dist/core/runtime/reset.d.ts +4 -4
- package/dist/core/runtime/reset.js +1 -1
- package/dist/core/runtime/revive-all.d.ts +2 -2
- package/dist/core/runtime/revive-all.js +1 -1
- package/dist/core/runtime/revive.d.ts +4 -4
- package/dist/core/runtime/revive.js +2 -2
- package/dist/core/runtime/roadmap.d.ts +6 -6
- package/dist/core/runtime/roadmap.js +5 -5
- package/dist/core/runtime/session-branch.d.ts +1 -1
- package/dist/core/runtime/session-branch.js +1 -1
- package/dist/core/runtime/session-list-cache.js +1 -1
- package/dist/core/runtime/situational-live.js +1 -1
- package/dist/core/runtime/spawn.d.ts +2 -2
- package/dist/core/runtime/spawn.js +2 -2
- package/dist/core/runtime/stop-guard.d.ts +2 -2
- package/dist/core/runtime/stop-guard.js +3 -3
- package/dist/core/runtime/warm-pool.d.ts +2 -2
- package/dist/core/runtime/warm-pool.js +1 -1
- package/dist/core/spaces/mounts.d.ts +2 -2
- package/dist/core/spaces/mounts.js +1 -1
- package/dist/core/spaces/permissions.d.ts +1 -1
- package/dist/core/spaces/permissions.js +1 -1
- package/dist/core/spaces/process.d.ts +1 -1
- package/dist/core/spaces/process.js +1 -1
- package/dist/core/spaces/space.js +1 -1
- package/dist/core/spaces/stop.d.ts +3 -3
- package/dist/core/spaces/stop.js +2 -2
- package/dist/core/spaces/users.d.ts +6 -6
- package/dist/core/spaces/users.js +1 -1
- package/dist/core/storage/attachments.d.ts +2 -2
- package/dist/core/storage/attachments.js +1 -1
- package/dist/core/storage/shares.d.ts +2 -2
- package/dist/core/storage/shares.js +1 -1
- package/dist/core/storage/tables.d.ts +21 -21
- package/dist/core/storage/tables.js +3 -3
- package/dist/core/substrate/delivery/corpus.d.ts +5 -8
- package/dist/core/substrate/delivery/corpus.js +3 -3
- package/dist/core/substrate/delivery/deliver.d.ts +10 -15
- package/dist/core/substrate/delivery/deliver.js +3 -3
- package/dist/core/substrate/delivery/plan.d.ts +2 -12
- package/dist/core/substrate/delivery/plan.js +3 -3
- package/dist/core/substrate/delivery/render-boot.d.ts +4 -4
- package/dist/core/substrate/delivery/render-boot.js +18 -18
- package/dist/core/substrate/delivery/render-event.d.ts +7 -14
- package/dist/core/substrate/delivery/render-event.js +4 -4
- package/dist/core/substrate/subject.d.ts +2 -2
- package/dist/core/substrate/subject.js +1 -1
- package/dist/core/usage/ledger.d.ts +6 -6
- package/dist/core/usage/ledger.js +4 -4
- package/dist/core/worktree-close.js +4 -4
- package/dist/core/worktree-mutation-async.js +7 -7
- package/dist/core/worktree-quarantine.js +1 -1
- package/dist/core/worktree-sweep.d.ts +1 -1
- package/dist/core/worktree-sweep.js +6 -6
- package/dist/core/worktree.d.ts +5 -5
- package/dist/core/worktree.js +13 -13
- package/dist/daemon/analytics/compute.d.ts +2 -2
- package/dist/daemon/analytics/compute.js +1 -1
- package/dist/daemon/api/app-listener.d.ts +4 -4
- package/dist/daemon/api/app-listener.js +13 -13
- package/dist/daemon/api/bridge.js +5 -5
- package/dist/daemon/api/document-listener.js +6 -6
- package/dist/daemon/api/handlers/analytics.js +1 -1
- package/dist/daemon/api/handlers/attach.js +1 -1
- package/dist/daemon/api/handlers/bash-jobs.js +1 -1
- package/dist/daemon/api/handlers/bash.js +1 -1
- package/dist/daemon/api/handlers/broker-ops.d.ts +1 -1
- package/dist/daemon/api/handlers/broker-ops.js +1 -1
- package/dist/daemon/api/handlers/broker-recovery.d.ts +1 -1
- package/dist/daemon/api/handlers/broker-recovery.js +1 -1
- package/dist/daemon/api/handlers/broker-signals.d.ts +2 -2
- package/dist/daemon/api/handlers/broker-signals.js +2 -2
- package/dist/daemon/api/handlers/canvas.d.ts +1 -1
- package/dist/daemon/api/handlers/canvas.js +4 -4
- package/dist/daemon/api/handlers/chat-inventory.js +1 -1
- package/dist/daemon/api/handlers/crons.js +1 -1
- package/dist/daemon/api/handlers/custom-objects.d.ts +4 -4
- package/dist/daemon/api/handlers/custom-objects.js +3 -3
- package/dist/daemon/api/handlers/delivery-retry.js +1 -1
- package/dist/daemon/api/handlers/delivery.js +1 -1
- package/dist/daemon/api/handlers/docs.d.ts +4 -4
- package/dist/daemon/api/handlers/docs.js +1 -1
- package/dist/daemon/api/handlers/feedback-comments.js +3 -3
- package/dist/daemon/api/handlers/files.js +1 -1
- package/dist/daemon/api/handlers/focus.js +1 -1
- package/dist/daemon/api/handlers/health.js +3 -3
- package/dist/daemon/api/handlers/hook-exec.js +1 -1
- package/dist/daemon/api/handlers/human-requests.js +1 -1
- package/dist/daemon/api/handlers/inbox-page.d.ts +1 -1
- package/dist/daemon/api/handlers/inbox-page.js +1 -1
- package/dist/daemon/api/handlers/inbox.d.ts +1 -1
- package/dist/daemon/api/handlers/inbox.js +1 -1
- package/dist/daemon/api/handlers/llm.d.ts +1 -1
- package/dist/daemon/api/handlers/llm.js +3 -3
- package/dist/daemon/api/handlers/memory-reads.js +1 -1
- package/dist/daemon/api/handlers/memory.d.ts +5 -5
- package/dist/daemon/api/handlers/memory.js +5 -5
- package/dist/daemon/api/handlers/messages.js +2 -2
- package/dist/daemon/api/handlers/node-events.d.ts +2 -2
- package/dist/daemon/api/handlers/node-events.js +3 -3
- package/dist/daemon/api/handlers/node-outcomes.js +1 -1
- package/dist/daemon/api/handlers/node-records.js +2 -2
- package/dist/daemon/api/handlers/nodes.d.ts +1 -1
- package/dist/daemon/api/handlers/nodes.js +1 -1
- package/dist/daemon/api/handlers/objects.js +3 -3
- package/dist/daemon/api/handlers/package-docs.js +1 -1
- package/dist/daemon/api/handlers/plugin-app-token.d.ts +1 -1
- package/dist/daemon/api/handlers/plugin-app-token.js +1 -1
- package/dist/daemon/api/handlers/profiles.d.ts +3 -3
- package/dist/daemon/api/handlers/profiles.js +1 -1
- package/dist/daemon/api/handlers/providers.d.ts +1 -1
- package/dist/daemon/api/handlers/providers.js +1 -1
- package/dist/daemon/api/handlers/questions.js +1 -1
- package/dist/daemon/api/handlers/reports.d.ts +1 -1
- package/dist/daemon/api/handlers/reports.js +5 -5
- package/dist/daemon/api/handlers/review-comments.js +1 -1
- package/dist/daemon/api/handlers/reviews.js +1 -1
- package/dist/daemon/api/handlers/runs.js +1 -1
- package/dist/daemon/api/handlers/structured-requests.js +1 -1
- package/dist/daemon/api/handlers/subscriptions.js +1 -1
- package/dist/daemon/api/handlers/transfer.js +1 -1
- package/dist/daemon/api/map.d.ts +3 -3
- package/dist/daemon/api/map.js +1 -1
- package/dist/daemon/api/principal.d.ts +1 -1
- package/dist/daemon/api/principal.js +1 -1
- package/dist/daemon/api/reader.d.ts +5 -5
- package/dist/daemon/api/reader.js +1 -1
- package/dist/daemon/api/router.d.ts +5 -5
- package/dist/daemon/api/router.js +1 -1
- package/dist/daemon/api/server.js +1 -1
- package/dist/daemon/broker-signals/bus.d.ts +1 -1
- package/dist/daemon/broker-signals/bus.js +1 -1
- package/dist/daemon/companion-retire.js +1 -1
- package/dist/daemon/cron/armed-context.d.ts +2 -2
- package/dist/daemon/cron/armed-context.js +1 -1
- package/dist/daemon/cron/authority.d.ts +2 -2
- package/dist/daemon/cron/authority.js +1 -1
- package/dist/daemon/cron/disposition.js +1 -1
- package/dist/daemon/cron/ended.d.ts +1 -1
- package/dist/daemon/cron/ended.js +2 -2
- package/dist/daemon/cron/escalation.js +3 -3
- package/dist/daemon/cron/folders.d.ts +1 -1
- package/dist/daemon/cron/folders.js +1 -1
- package/dist/daemon/cron/held.d.ts +1 -1
- package/dist/daemon/cron/held.js +1 -1
- package/dist/daemon/cron/lease-recovery.d.ts +1 -1
- package/dist/daemon/cron/lease-recovery.js +1 -1
- package/dist/daemon/cron/passes.d.ts +2 -2
- package/dist/daemon/cron/passes.js +1 -1
- package/dist/daemon/cron/run-socket.d.ts +1 -1
- package/dist/daemon/cron/run-socket.js +1 -1
- package/dist/daemon/cron/settle.js +1 -1
- package/dist/daemon/cron/sinks.d.ts +1 -1
- package/dist/daemon/cron/sinks.js +2 -2
- package/dist/daemon/cron-run.d.ts +12 -3
- package/dist/daemon/cron-run.js +2 -2
- package/dist/daemon/crtrd.js +6 -6
- package/dist/daemon/delivery/run-delivery.js +1 -1
- package/dist/daemon/due-sources.d.ts +3 -3
- package/dist/daemon/due-sources.js +1 -1
- package/dist/daemon/due.d.ts +3 -3
- package/dist/daemon/due.js +7 -7
- package/dist/daemon/fleet.d.ts +2 -2
- package/dist/daemon/fleet.js +11 -11
- package/dist/daemon/human/finish.js +3 -3
- package/dist/daemon/human/settle.d.ts +1 -1
- package/dist/daemon/human/settle.js +1 -1
- package/dist/daemon/human/sweep.js +1 -1
- package/dist/daemon/joined-owner.d.ts +2 -2
- package/dist/daemon/joined-owner.js +1 -1
- package/dist/daemon/messaging/node-message.js +1 -1
- package/dist/daemon/park-activity.d.ts +2 -2
- package/dist/daemon/park-activity.js +1 -1
- package/dist/daemon/peer/authority.js +1 -1
- package/dist/daemon/peer/forward.d.ts +13 -6
- package/dist/daemon/peer/forward.js +1 -1
- package/dist/daemon/peer/handlers.js +1 -1
- package/dist/daemon/peer/ingress.d.ts +4 -4
- package/dist/daemon/peer/ingress.js +1 -1
- package/dist/daemon/peer/outbox.d.ts +2 -2
- package/dist/daemon/peer/outbox.js +1 -1
- package/dist/daemon/peer/relay-service.js +1 -1
- package/dist/daemon/plugin-objects/read-leaf.d.ts +2 -2
- package/dist/daemon/plugin-objects/read-leaf.js +2 -2
- package/dist/daemon/profile-delete.js +1 -1
- package/dist/daemon/readiness.d.ts +2 -2
- package/dist/daemon/readiness.js +1 -1
- package/dist/daemon/reconcilers/action-lane.d.ts +1 -1
- package/dist/daemon/reconcilers/action-lane.js +1 -1
- package/dist/daemon/reconcilers/bash-deadline.js +2 -2
- package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
- package/dist/daemon/reconcilers/broker-supervision.js +4 -4
- package/dist/daemon/reconcilers/controller-death.d.ts +1 -1
- package/dist/daemon/reconcilers/controller-death.js +1 -1
- package/dist/daemon/reconcilers/cron-lane.d.ts +1 -1
- package/dist/daemon/reconcilers/cron-lane.js +1 -1
- package/dist/daemon/reconcilers/delivery-lane.d.ts +1 -1
- package/dist/daemon/reconcilers/delivery-lane.js +2 -2
- package/dist/daemon/reconcilers/fault-retry-backstop.d.ts +3 -3
- package/dist/daemon/reconcilers/fault-retry-backstop.js +1 -1
- package/dist/daemon/reconcilers/grove-instance-sweep.d.ts +2 -2
- package/dist/daemon/reconcilers/grove-instance-sweep.js +1 -1
- package/dist/daemon/reconcilers/live-obligation.d.ts +6 -6
- package/dist/daemon/reconcilers/live-obligation.js +1 -1
- package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -1
- package/dist/daemon/reconcilers/node-deadline.d.ts +1 -1
- package/dist/daemon/reconcilers/node-deadline.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.d.ts +3 -3
- package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/terminating.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/wants-execution.d.ts +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -1
- package/dist/daemon/reconcilers/pending-review-submit.d.ts +1 -1
- package/dist/daemon/reconcilers/pending-review-submit.js +1 -1
- package/dist/daemon/reconcilers/storage-due-work.js +1 -1
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +1 -1
- package/dist/daemon/reconcilers/storage-maintenance.js +2 -2
- package/dist/daemon/reconcilers/structured-request-lane.d.ts +1 -1
- package/dist/daemon/reconcilers/structured-request-lane.js +1 -1
- package/dist/daemon/review/comment-notify.js +2 -2
- package/dist/daemon/review/companion.d.ts +3 -3
- package/dist/daemon/review/companion.js +1 -1
- package/dist/daemon/review/finish.js +1 -1
- package/dist/daemon/review/sweep.js +1 -1
- package/dist/daemon/run-notices.d.ts +4 -4
- package/dist/daemon/run-notices.js +1 -1
- package/dist/daemon/runs/append-section.d.ts +2 -2
- package/dist/daemon/runs/append-section.js +2 -2
- package/dist/daemon/runs/observer.d.ts +2 -2
- package/dist/daemon/runs/observer.js +2 -2
- package/dist/daemon/structured-requests/boot.d.ts +1 -1
- package/dist/daemon/structured-requests/boot.js +1 -1
- package/dist/daemon/structured-requests/effects.js +1 -1
- package/dist/daemon/structured-requests/sidecar.d.ts +1 -1
- package/dist/daemon/structured-requests/sidecar.js +1 -1
- package/dist/migrations/004-canvas-documents/apply.d.ts +3 -3
- package/dist/migrations/004-canvas-documents/apply.js +1 -1
- package/dist/migrations/004-canvas-documents/index.d.ts +2 -2
- package/dist/migrations/004-canvas-documents/index.js +2 -2
- package/dist/migrations/activation.js +2 -2
- package/docs/public-api.md +11 -0
- package/package.json +3 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +12 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var $=Object.defineProperty;var i=(n,e)=>$(n,"name",{value:e,configurable:!0});import{ApiError as m}from"../../api/errors.js";import{openDb as g}from"../../core/canvas/db.js";import{getById as j,nodeObject as A}from"../../core/graph/objects.js";import{envelopeFor as D}from"../../core/peer/envelope.js";import{isUnreachable as w}from"../../core/peer/client.js";import{machineReach as E}from"../../core/peer/directory.js";import{defaultHomeDeps as O,homeOf as S,peersToAsk as F,relocate as N}from"../../core/peer/home.js";import{ensureStub as y,rehomeStub as q,stubOf as C}from"../../core/peer/stubs.js";import{peerCall as M}from"../../core/peer/client.js";const T={...O,call:i((n,e,o,t)=>M(n,e,{...o===void 0?{}:{envelope:o},...t===void 0?{}:{signal:t}}),"call"),envelope:i(async n=>await D(n),"envelope"),label:i(async n=>{try{const e=await E(n);return{id:n,name:e?.name??n}}catch{return{id:n,name:n}}},"label")},_={current:T},v=i(n=>n.class==="person"||n.class==="broker"||n.class==="cron","originates"),k=i(n=>{const e=n?.error;return typeof e=="object"&&e!==null&&typeof e.code=="string"?e.code:null},"errorCode");function K(n,e){const o=e?.error;return new m(n,o?.code??"error",o?.message??`the home machine answered ${n}`,o?.details)}i(K,"relayError");function L(n,e){return new m(503,"runtime_unreachable",`No machine of yours answers for ${n} (unreachable: ${e.join(", ")}).`,{id:n,unreachable:e})}i(L,"unknownError");const Q=i((n,e)=>n!==null&&typeof n=="object"&&!Array.isArray(n)?{...n,machine:e}:n,"withMachine");async function X(n,e,o){const t=_.current,a=await g(),c=await j(a,e),u=c===null?null:await C(a,c),p=n.principal;if(!v(p)){if(u!==null)throw new m(404,"not_here",`${e} is not homed on this machine (it is a stub of ${u.home_machine})`,{id:e,home_machine:u.home_machine});return{kind:"local"}}if(c!==null&&u===null)return{kind:"local"};const h={...t,call:i((r,d)=>t.call(r,d),"call")};let l=await S(a,e,{hint:n.query.get("machine"),deps:h});for(let r=0;r<2;r++){if(l.where==="nowhere"||l.where==="here"){if(u!==null)throw new m(404,"not_found",`${e} is no longer on any machine of yours`,{id:e});return{kind:"local"}}if(l.where==="unknown")return{kind:"unknown",unreachable:l.unreachable};const d=l.machine,s=await t.call(d,o,await t.envelope(p)),b=await t.label(d);if(w(s))return{kind:"unknown",unreachable:[`${b.name} (${s.unreachable.reason})`]};const x=l.source!=="locate";if(s.status===404&&r===0&&(k(s.body)==="not_here"||x&&k(s.body)==="not_found")){const f=await N(a,e,d,h);if(f.where==="machine"){l=f;continue}if(f.where==="unknown")return{kind:"unknown",unreachable:f.unreachable};if(k(s.body)==="not_found")return{kind:"remote",status:s.status,body:s.body,machine:b};if(u!==null)throw new m(404,"not_found",`${e} is no longer on any machine of yours`,{id:e});return{kind:"local"}}return{kind:"remote",status:s.status,body:s.body,machine:b}}return{kind:"unknown",unreachable:[]}}i(X,"forwardVerb");async function Y(n,e,o){const t=_.current,a=n.principal;if(!v(a))return{kind:"local"};const c=await F(t);if("where"in c)return{kind:"unknown",unreachable:c.unreachable};if(c.length===0)return{kind:"local"};const u=await t.envelope(a),p=await Promise.all(c.map(async r=>({m:r,out:await t.call(r.machine_id,o,u)}))),h=p.find(r=>!w(r.out)&&r.out.status<400);if(h){const r=e.method==="GET"?h.out:await t.call(h.m.machine_id,e,u),d=await t.label(h.m.machine_id);return w(r)?{kind:"unknown",unreachable:[`${d.name} (${r.unreachable.reason})`]}:{kind:"remote",status:r.status,body:r.body,machine:d}}const l=p.filter(r=>w(r.out)||r.out.status!==404).map(r=>r.m.name||r.m.machine_id);return l.length>0?{kind:"unknown",unreachable:l}:{kind:"local"}}i(Y,"forwardNamed");function W(n){if(n.actor.kind==="person")return{sub:n.sub,act:{sub:n.via}};const{app:e,node:o,node_scopes:t,place:a}=n.actor;return{sub:n.sub,act:{sub:n.via,act:{sub:e,node:o,node_scopes:t,place:a}}}}i(W,"envelopeOfForwarded");function Z(n){const e={};for(const[o,t]of n.query)o!=="machine"&&(e[o]=t);return e}i(Z,"queryWithoutMachine");async function nn(n,e){const o=e.principal;return o.class!=="forwarded"||o.actor.kind!=="app"||o.actor.node===null?null:await y(n,o.actor.node,"node",o.via,W(o))}i(nn,"callerStub");async function en(n,e){return e.principal.class==="broker"?await A(n,e.principal.node):null}i(en,"callerNode");async function on(n,e,o,t,a){await q(n,e,t);const c=a?.owner,u=c&&c.type==="app"?{id:"",type:"app",scheme:"app",external_id:c.external_id??(c.handle.startsWith("app:")?c.handle:`app:${c.handle}`),handle:c.handle}:null;return await y(n,e,o,t,void 0,a===void 0?void 0:{id:e,type:o,kind:a.kind??null,name:a.name??e,...a.preview===void 0?{}:{preview:a.preview},owner:u,...a.kind_decl===void 0?{}:{kind_decl:a.kind_decl},...a.privacy===void 0?{}:{privacy:a.privacy}})}i(on,"remoteStub");export{en as callerNode,nn as callerStub,T as defaultForwardDeps,W as envelopeOfForwarded,Y as forwardNamed,X as forwardVerb,_ as forwarding,v as originates,Z as queryWithoutMachine,K as relayError,on as remoteStub,L as unknownError,Q as withMachine};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var u=Object.defineProperty;var
|
|
1
|
+
var u=Object.defineProperty;var s=(e,t)=>u(e,"name",{value:t,configurable:!0});import{ApiError as c}from"../../api/errors.js";import{withCanvasWrite as l}from"../../core/canvas/db.js";import{getById as y}from"../../core/graph/objects.js";import{stubOf as d}from"../../core/peer/stubs.js";import{ackFor as w,claimFor as v,ingestPeerEvents as f,MAX_EVENTS_PER_CALL as p}from"../../core/peer/ingest.js";function m(e){if(e.principal.class!=="machine")throw new c(403,"permission_error","peer routes are for a machine");return e.principal.via}s(m,"via");const a=s(e=>e!==null&&typeof e=="object"&&!Array.isArray(e)?e:{},"fields"),o=s(e=>typeof e=="string"&&e!=="","text");function h(e){const t=a(e),r=a(t.object);return o(t.key)&&o(t.message_id)&&o(t.event)&&typeof t.level=="number"&&o(r.id)&&o(r.type)&&typeof r.name=="string"&&(t.actor===null||o(a(t.actor).id)&&o(a(t.actor).type))&&a(t.attrs)===t.attrs}s(h,"validEvent");const b=s(async e=>{const t=m(e),r=a(e.body).events;if(!Array.isArray(r))throw new c(400,"invalid_request","events must be an array");if(r.length>p)throw new c(400,"invalid_request",`at most ${p} events per call`);const n=r.findIndex(i=>!h(i));if(n>=0)throw new c(400,"invalid_request",`events[${n}] is not a well-formed event`);return{status:200,body:await l(async i=>await f(i,t,r))}},"peerEvents"),_=s(async e=>{const t=m(e),r=a(e.body).limit;return{status:200,body:{rows:await l(async i=>await v(i,t,typeof r=="number"?r:50))}}},"peerClaim"),k=s(async e=>{const t=m(e),r=a(e.body).acks;if(!Array.isArray(r)||r.some(n=>!o(a(n).key)||!o(a(n).claim_token)))throw new c(400,"invalid_request","acks must be an array of {key, claim_token}");return{status:200,body:{acked:await l(async n=>await w(n,t,r))}}},"peerAck"),A=s(async e=>{m(e);const t=a(e.body).id;if(!o(t))throw new c(400,"invalid_request","id must be a non-empty string");return await l(async r=>{const n=await y(r,t);if(n===null)return{status:200,body:{answer:"no"}};const i=await d(r,n);return{status:200,body:i===null?{answer:"here"}:{answer:"moved",machine:i.home_machine}}})},"peerLocate"),T=[{method:"POST",pattern:"/v1/peer/events",handler:b},{method:"POST",pattern:"/v1/peer/outbox/claim",handler:_},{method:"POST",pattern:"/v1/peer/outbox/ack",handler:k},{method:"POST",pattern:"/v1/peer/locate",handler:A}];export{k as peerAck,_ as peerClaim,b as peerEvents,A as peerLocate,T as peerRoutes};
|
|
@@ -8,9 +8,9 @@ export interface PeerIngressContext {
|
|
|
8
8
|
/** Its key set (the app listener's cache, or the laptop's own). */
|
|
9
9
|
jwks: JwksCache;
|
|
10
10
|
/** The audience peer call tokens must carry: `machineUrl()` on the laptop, `runtime.audience` on the hosted runtime. Null before it is known: every request is refused 503. */
|
|
11
|
-
audience(): string | null
|
|
11
|
+
audience(): Promise<string | null>;
|
|
12
12
|
/** The account owner (`user:<id>`) this runtime belongs to. Null when it has none: no relation reaches the machine and every request is refused 403. */
|
|
13
|
-
owner(): string | null
|
|
13
|
+
owner(): Promise<string | null>;
|
|
14
14
|
/** This machine's id (`runtime:<id>`). */
|
|
15
15
|
self(): string;
|
|
16
16
|
/** Pulls the directory's grants when a token's app link is ahead of the mirror. Absent: a mirror behind a token's `rev` answers 503. */
|
|
@@ -18,13 +18,13 @@ export interface PeerIngressContext {
|
|
|
18
18
|
/** The router that serves the request; defaults to the daemon's own (`buildRouter(() => null)`), built on first use. */
|
|
19
19
|
router?: () => Router | Promise<Router>;
|
|
20
20
|
/** False while the JWKS or grants are not loaded: every request is refused 503 (audited). Defaults to ready. */
|
|
21
|
-
ready?: () => boolean
|
|
21
|
+
ready?: () => Promise<boolean>;
|
|
22
22
|
}
|
|
23
23
|
/** Whether the daemon's own route table serves this request: the routes `servePeer` hands to its router (`peer.*` and every daemon route a forwarded call reaches). */
|
|
24
24
|
export declare function isDaemonRoute(method: string, pathname: string): Promise<boolean>;
|
|
25
25
|
/** The account owner this runtime belongs to: the owner a successful `crtr sys join` recorded (a laptop), else — on a hosted runtime, which is
|
|
26
26
|
* provisioned without join — the one `sub` its mirrored grants all carry. Null when neither names exactly one owner. Never throws. */
|
|
27
|
-
export declare function runtimeOwner(): string | null
|
|
27
|
+
export declare function runtimeOwner(): Promise<string | null>;
|
|
28
28
|
/** A bearer the caller already tried to verify and that failed: `servePeer` answers it as its own refusal (and audits it). */
|
|
29
29
|
export interface PeerRefusal {
|
|
30
30
|
status: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var H=Object.defineProperty;var
|
|
1
|
+
var H=Object.defineProperty;var a=(e,t)=>H(e,"name",{value:t,configurable:!0});import{randomUUID as j}from"node:crypto";import{verifyCallToken as z}from"@north-light/identity";import{ENVELOPE_HEADER as I}from"../../core/peer/envelope.js";import{mirrorGrantLink as L,peerAuthority as U}from"./authority.js";import{peerVersionRefusal as q,PEER_VERSION_HEADER as D}from"../../core/peer/version.js";import{auditOutcome as v,writePeerAudit as G}from"../../core/audit.js";import{emitEvent as C}from"../../core/events/emit.js";import{joinedOwner as P}from"../../core/directory/join.js";import{allGrants as N}from"../../core/grants/mirror.js";import{errorCodes as T}from"../../api/error-codes.js";let O;function S(){return O??=import("../api/server.js").then(e=>e.buildRouter(()=>null)),O}a(S,"defaultRouter");async function x(e,t){return(await S()).match(e.toUpperCase(),t)!==null}a(x,"isDaemonRoute");function V(e,t,r,o,i,m){if(e.headersSent){e.destroy();return}const l=T[r];e.writeHead(t,{"content-type":"application/json; charset=utf-8","Request-Id":i,"X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify({error:{code:r,message:o,origin:"runtime",...m===void 0?{}:{details:m},...l?{type:l.type}:{},request_id:i}}))}a(V,"refuse");const _=a((e,t)=>{const r=e.headers[t.toLowerCase()];return Array.isArray(r)?r[0]:r},"header");async function ee(){try{const e=P();if(e!==null)return e;const t=new Set((await N()).map(r=>r.sub));return t.size===1?[...t][0]:null}catch{return null}}a(ee,"runtimeOwner");async function te(e,t,r,o){const i=t.getHeader("Request-Id")?.toString()??j();t.setHeader("Request-Id",i);const m=_(e,I),l=new URL(e.url??"/","http://peer.local"),E=(e.method??"GET").toUpperCase();let d={class:m===void 0?"machine":"forwarded",grantee:null,sub:null,via:"unauthenticated",operation:`${E} ${l.pathname}`,node_id:null},R=!1;const b=a(async(n,c={})=>{if(!R){R=!0;try{await G({request_id:i,resource:l.pathname,...d,...c,outcome:n})}catch(u){C({level:"error",event:"daemon.peer.audit_failed",error:u instanceof Error?u:new Error(String(u)),fields:{request_id:i}})}}},"record"),s=a(async(n,c,u,f)=>{await b(v(n)),V(t,n,c,u,i,f)},"deny");try{if(r.ready&&!await r.ready()){await s(503,"runtime_starting","runtime_starting");return}let n;if(o!==void 0&&!("chain"in o)){await s(o.status,o.code,o.message);return}if(o!==void 0)n=o;else{const y=await r.audience();if(y===null){await s(503,"runtime_starting","this machine does not yet know its own address");return}const g=_(e,"authorization");if(!g?.startsWith("Bearer ")||g.length<=7){await s(401,"unauthorized","a machine token is required");return}try{n=await z({token:g.slice(7),jwks:r.jwks,issuer:r.issuer,audience:y})}catch{await s(401,"unauthorized","invalid machine token");return}}d={...d,grantee:n.sub,sub:n.sub,via:n.chain[0]?.sub??"unauthenticated"};const c=await(r.router??S)(),u=c.match(E,l.pathname);d={...d,operation:u?.operation.name??d.operation,node_id:u?.params.id??null};const f=await r.owner(),p=await U(n,m,{self:r.self,relation:a(y=>f!==null&&y===f?"owner":null,"relation"),grantLink:L(r.syncGrants??(async()=>{}))});if("status"in p){await s(p.status,p.code,p.message);return}const w=q(_(e,D));if(w!==null){await s(426,w.code,w.message,w.details);return}const{principal:h}=p,k=h.class==="forwarded"&&h.actor.kind==="app"?h.actor:null,A={grantee:k?.app??n.sub,node_id:k?.node??d.node_id};t.once("close",()=>{b(t.writableFinished?v(t.statusCode):"aborted",A)}),await c.handle(e,t,null,h)}catch(n){C({level:"error",event:"daemon.peer.ingress_failed",error:n instanceof Error?n:new Error(String(n)),fields:{request_id:i}}),await s(500,"server_failure","peer request failed")}}a(te,"servePeer");export{x as isDaemonRoute,ee as runtimeOwner,te as servePeer};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type CanvasDb } from '../../core/canvas/db.js';
|
|
2
2
|
import { type PeerRequest, type PeerResult } from '../../core/peer/client.js';
|
|
3
3
|
import { type Machine } from '../../core/peer/directory.js';
|
|
4
4
|
export declare const STABLE_BACKOFF_MS: {
|
|
@@ -9,7 +9,7 @@ export declare const STABLE_BACKOFF_MS: {
|
|
|
9
9
|
export declare const RELAY_RETRY_WINDOW_MS: number;
|
|
10
10
|
export declare const PULL_INTERVAL_MS: number;
|
|
11
11
|
export interface OutboxDeps {
|
|
12
|
-
db():
|
|
12
|
+
db(): Promise<CanvasDb>;
|
|
13
13
|
call(machineId: string, request: PeerRequest): Promise<PeerResult>;
|
|
14
14
|
reach(machineId: string): Promise<Machine | null>;
|
|
15
15
|
machines(): Promise<Machine[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var C=Object.defineProperty;var l=(
|
|
1
|
+
var C=Object.defineProperty;var l=(a,f)=>C(a,"name",{value:f,configurable:!0});import{openDb as I,withCanvasWrite as j}from"../../core/canvas/db.js";import{emitEvent as B}from"../../core/events/emit.js";import{isUnreachable as O,peerCall as D}from"../../core/peer/client.js";import{listMachines as U,machineReach as F,normalizeMachineId as g,ownMachineId as N}from"../../core/peer/directory.js";import{relayConnected as W}from"../../core/peer/events.js";import{ingestPeerEvents as q,isCatalogLag as S}from"../../core/peer/ingest.js";import{CATALOG_LAG_RETRY_MS as G,dueRows as X,expireOld as Y,markDone as z,markExpired as E,markRetry as A,markWaiting as L,onPeerEnqueued as H,pendingFor as J,pruneOutbox as K,OUTBOX_MAX_AGE_MS as V}from"../../core/peer/outbox-store.js";const T={first:1e3,max:10*6e4},P=5*6e4,$=5*6e4,R=50,Q=20,Z={db:I,call:l((a,f)=>D(a,f),"call"),reach:F,machines:U,self:N,now:Date.now},M=l(a=>Math.min(T.first*2**Math.max(0,a-1),T.max),"stableBackoffMs");function ee(a){const f=new Set;async function u(c,o,i){const t=await a.db(),n=a.now(),s=await a.call(c,{method:"POST",path:"/v1/peer/events",body:{events:o.map(e=>JSON.parse(e.payload_json))}}),d=l(async(e,x=o)=>{for(const m of x){const h=m.attempts+1,_=m.first_failed_at??n;i&&e?await L(t,m.id,h):i?n-_>=P?await L(t,m.id,h):await A(t,m.id,h,n+Math.min(M(h),P-(n-_)),_):n-_>=V?await E(t,m.id):await A(t,m.id,h,n+M(h),_)}},"fail");if(O(s)){await d(s.unreachable.reason==="machine_offline");return}const r=s.body;if(s.status!==200||r===null||!Array.isArray(r.accepted)){await d(!1);return}const p=new Set(r.accepted),k=new Map((Array.isArray(r.rejected)?r.rejected:[]).map(e=>[e.key,e.code??""])),y=[];for(const e of o)p.has(e.idempotency_key)?await z(t,e.id):k.has(e.idempotency_key)?S(k.get(e.idempotency_key))&&n-e.created_at<G?y.push(e):await E(t,e.id):await A(t,e.id,e.attempts+1,n+M(e.attempts+1),e.first_failed_at??n);await d(!1,y)}l(u,"sendBatch");async function b(c){const o=c.filter(i=>!f.has(i.id));for(const i of o)f.add(i.id);try{const i=new Map;for(const t of o)i.set(t.peer,[...i.get(t.peer)??[],t]);await Promise.all([...i].map(async([t,n])=>{const d=(await a.reach(t).catch(()=>null))?.reach.kind==="relay";for(let r=0;r<n.length;r+=R)await u(t,n.slice(r,r+R),d)}))}finally{for(const i of o)f.delete(i.id)}}l(b,"pushRows");let w=0;return{async run(){const c=await a.db(),o=a.now();o-w>=60*6e4&&(w=o,await Y(c,o),await K(c,o)),await b(await X(c,o))},flush:l(async c=>b(await J(await a.db(),c,a.now())),"flush"),async pull(){const c=a.self(),o=(await a.machines()).filter(t=>g(t.machine_id)!==c&&t.kind!=="device"&&t.reach.kind==="stable");let i=0;for(const t of o){const n=g(t.machine_id);for(let s=0;s<Q;s++){const d=await a.call(n,{method:"POST",path:"/v1/peer/outbox/claim",body:{limit:100}}),r=!O(d)&&d.status===200?d.body?.rows:void 0;if(!Array.isArray(r)||r.length===0)break;const p=await j(async e=>await q(e,n,r.map(x=>x.payload)));i+=p.accepted.length;const k=new Set([...p.accepted,...p.rejected.filter(e=>!S(e.code)).map(e=>e.key)]),y=r.filter(e=>k.has(e.key)).map(e=>({key:e.key,claim_token:e.claim_token}));if(y.length>0&&await a.call(n,{method:"POST",path:"/v1/peer/outbox/ack",body:{acks:y}}),r.length<100)break}}return i}}}l(ee,"createOutboxLane");function le(a){if(!a.joined)return()=>{};const f=a.deps??Z,u=ee(f),b=l(n=>s=>{B({level:"warn",event:`daemon.peer.${n}_failed`,error:s})},"quiet"),w=l((n,s)=>a.register(n().then(()=>{},b(s))),"guarded"),v=H(n=>w(()=>u.flush(n),"outbox_flush")),c=setInterval(()=>w(()=>u.run(),"outbox_run"),a.tickMs??5e3);c.unref();const o=l(()=>w(async()=>{(await f.machines()).find(s=>g(s.machine_id)===f.self())?.reach.kind==="relay"&&await u.pull()},"outbox_pull"),"pull"),i=W.on(o),t=setInterval(o,$);return t.unref(),o(),()=>{v(),i(),clearInterval(c),clearInterval(t)}}l(le,"startPeerOutbox");export{$ as PULL_INTERVAL_MS,P as RELAY_RETRY_WINDOW_MS,T as STABLE_BACKOFF_MS,ee as createOutboxLane,Z as liveOutboxDeps,M as stableBackoffMs,le as startPeerOutbox};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var U=Object.defineProperty;var
|
|
1
|
+
var U=Object.defineProperty;var a=(e,c)=>U(e,"name",{value:c,configurable:!0});import{JwksCache as E}from"@north-light/identity";import{randomUUID as N}from"node:crypto";import{readConfig as k}from"../../core/config.js";import{hasSyncedGrants as O}from"../../core/grants/mirror.js";import{emitEvent as _}from"../../core/events/emit.js";import{directoryIssuer as b,machineUrl as j,ownMachineId as R}from"../../core/peer/directory.js";import{RunError as m}from"../../core/runs/operations.js";import{createResumeDetector as G}from"../resume-detector.js";import{applySyncNotice as H,NoticeLedger as M}from"../api/sync-notice.js";import{runtimeOwner as J,servePeer as T}from"./ingress.js";import{startLocalIngress as D}from"./local-ingress.js";import{startRelayClient as L}from"./relay-client.js";const $="/v1/runtime/sync-notice",z=5e3;async function A(e,c,f){if(e.headersSent){e.destroy();return}e.writeHead(c,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify(f))}a(A,"answerJson");function ae(e){const c=e.unsandboxed??(()=>k("user").runtime?.unsandboxed===!0),f=e.issuer??b;let s;const S=new M;async function d(){const t=s;s=void 0,t!==void 0&&(clearInterval(t.resume),await t.client.stop(),await t.ingress.close())}a(d,"stopStarted");async function C(t,r){const i=new E(r,fetch,e.jwksUrl?e.jwksUrl():k("user").runtime?.jwksUrl),u={issuer:r,jwks:i,audience:j,owner:J,self:R,ready:a(async()=>await O(r.replace(/\/$/,"")),"ready"),syncGrants:e.syncGrants,...e.ingress},w=await D(a(async(o,l)=>{const x=(o.url??"").split("?",1)[0];if(o.method==="POST"&&x===$){o.resume();try{const n=await u.audience();if(n===null||u.ready&&!await u.ready())throw new m(503,"runtime_starting","runtime_starting");await H(await S.accept(o.headers.authorization,i,r,n),e.syncGrants,N()),l.writeHead(204),l.end()}catch(n){const I=n instanceof m?n.status:500;await A(l,I,{error:{code:n instanceof m?n.code:"server_failure",message:n instanceof m?n.message:"sync notice failed"}})}return}await T(o,l,u)},"serve"),e.socketPath);let y;try{y=L({issuer:r,relayOrigin:t,socketPath:w.socketPath,...e.client})}catch(o){throw await w.close(),o}const P=G(),v=setInterval(()=>{P.check()&&(_({level:"info",event:"daemon.peer.relay_resume"}),y.reconnectNow())},e.resumeCheckMs??z);v.unref(),s={relay:t,ingress:w,client:y,resume:v,jwks:i},_({level:"info",event:"daemon.peer.relay_started",fields:{relay:t}})}a(C,"begin");let h=Promise.resolve(),p=!1;const g=a(t=>{const r=h.then(t);return h=r.catch(()=>{}),r},"serial");return{observe(t){return g(async()=>{if(p)return;const r=f();if(t===null)return;if(t.reach?.kind!=="relay"||!c()||r===null){await d();return}const i=t.reach.relay.replace(/\/$/,"");s?.relay!==i&&(await d(),await C(i,r))})},running:a(()=>s!==void 0,"running"),stop(){return p=!0,g(d)}}}a(ae,"createPeerRelay");export{z as RESUME_CHECK_MS,$ as SYNC_NOTICE_PATH,ae as createPeerRelay};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { DatabaseSync } from 'node:sqlite';
|
|
2
1
|
import type { ObjectRow } from '../../core/graph/types.js';
|
|
3
2
|
import type { RequestPrincipal } from '../api/router.js';
|
|
3
|
+
import type { CanvasDb } from '../../core/canvas/db.js';
|
|
4
4
|
export declare const READ_LEAF_DEADLINE_MS = 15000;
|
|
5
5
|
export interface ReadDelegation {
|
|
6
6
|
plugin: string;
|
|
@@ -15,6 +15,6 @@ export type ReadLeafResult = {
|
|
|
15
15
|
};
|
|
16
16
|
/** The delegation for a custom object, or null when its kind has no read leaf or no installed plugin declares it any more (`declared=0`: an inert
|
|
17
17
|
* kind shows the last announcement). Sync: runs inside the first read transaction. */
|
|
18
|
-
export declare function readDelegationFor(db:
|
|
18
|
+
export declare function readDelegationFor(db: CanvasDb, object: ObjectRow): Promise<ReadDelegation | null>;
|
|
19
19
|
/** Run the declared read leaf as `principal`. Never throws. */
|
|
20
20
|
export declare function runReadLeaf(d: ReadDelegation, principal: RequestPrincipal, deadlineMs?: number): Promise<ReadLeafResult>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var f=Object.defineProperty;var l=(n,o)=>f(n,"name",{value:o,configurable:!0});import{randomUUID as g}from"node:crypto";import{
|
|
2
|
-
LEFT JOIN identities i ON i.object = k.owner WHERE k.name = ?`).get(o.type);if(a===void 0||a.read_json===null||a.declared===0||a.scheme!=="app"||a.external_id===null||!a.external_id.startsWith("app:"))return null;const e=JSON.parse(a.read_json).command;return{plugin:a.external_id.slice(4),command:e,id:o.id,name:o.name}}l(
|
|
1
|
+
var f=Object.defineProperty;var l=(n,o)=>f(n,"name",{value:o,configurable:!0});import{randomUUID as g}from"node:crypto";import{listInstalledPlugins as h}from"../../core/resolver.js";import{validatePluginCommands as v}from"../../core/command-plugins/discovery.js";import{executeExternalLeafAsync as b}from"../../core/command-plugins/transport/exec-invoke-async.js";import{invokeHttpLeaf as E}from"../../core/command-plugins/transport/http-invoke.js";import{sha256Hex as w,signedHeaderDigest as k}from"../../core/command-plugins/transport/sign.js";import{pluginAppEnv as x}from"../../core/plugin-app.js";import{callProvider as _}from"../../core/providers/call.js";import{callerFromRequest as y}from"../api/handlers/providers.js";import{signCallHeaders as L}from"../api/handlers/plugin-app-token.js";const P=15e3;async function O(n,o){const a=await n.prepare(`SELECT k.read_json, k.declared, i.scheme, i.external_id FROM object_kinds k
|
|
2
|
+
LEFT JOIN identities i ON i.object = k.owner WHERE k.name = ?`).get(o.type);if(a===void 0||a.read_json===null||a.declared===0||a.scheme!=="app"||a.external_id===null||!a.external_id.startsWith("app:"))return null;const e=JSON.parse(a.read_json).command;return{plugin:a.external_id.slice(4),command:e,id:o.id,name:o.name}}l(O,"readDelegationFor");async function q(n,o,a=P){try{const e=h("user").find(r=>r.name===n.plugin);if(e===void 0||!e.enabled)return{unavailable:`plugin ${n.plugin} is not installed`};const u={id:n.id,name:n.name};let d;if(e.manifest.provider?.id===e.name){const r=AbortSignal.timeout(a),t=_(await y(o),{provider:e.name,tool:n.command.join(" "),arguments:u},{requestId:g(),signal:r});t.catch(()=>{}),d=(await Promise.race([t,new Promise((p,i)=>{r.addEventListener("abort",()=>i(new Error(`provider read leaf gave no answer within ${a} ms`)),{once:!0})})])).body}else{const r=v(e),t=r.transport;let i=r.manifest?.roots.find(m=>m.name===e.name);for(const m of n.command)i=i?.kind==="branch"?i.children.find(s=>s?.name===m):void 0;if(i?.kind!=="leaf"||t?.kind!=="exec"&&t?.kind!=="http")return{unavailable:`plugin ${n.plugin} has no read leaf ${n.command.join(" ")}`};if(t.kind==="http"){const m=i;d=await E({registration:{name:e.name,endpoint:t.endpoint,...t.authEnv!==void 0?{authEnv:t.authEnv}:{}},...r.manifest?.baseUrl!==void 0?{baseUrl:r.manifest.baseUrl}:{},timeouts:{...r.manifest?.timeouts,requestMs:a},params:m.params,rest:m.rest,output:m.output,commandPath:[e.name,...n.command]},u,void 0,{callHeaders:l(async s=>(await L(e.name,o,{method:s.method,url:s.url.href,body_sha256:w(s.body),...k(s.headers)})).headers,"callHeaders")})}else{if(t.executable===void 0)return{unavailable:`plugin ${n.plugin} has no read leaf ${n.command.join(" ")}`};d=await b({plugin:e,executable:t.executable,commandPath:[e.name,...n.command],output:i.output},u,{deadlineMs:a,cwd:e.root,env:{...process.env,...x(e.name)??{}}})}}const c=d?.markdown;return typeof c=="string"?{markdown:c}:{unavailable:"read leaf returned no markdown"}}catch(e){return{unavailable:e instanceof Error?e.message:String(e)}}}l(q,"runReadLeaf");export{P as READ_LEAF_DEADLINE_MS,O as readDelegationFor,q as runReadLeaf};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var q=Object.defineProperty;var d=(e,
|
|
1
|
+
var q=Object.defineProperty;var d=(e,t)=>q(e,"name",{value:t,configurable:!0});import{existsSync as w,readFileSync as E,readdirSync as g,rmSync as p}from"node:fs";import{join as u}from"node:path";import{cronIdsForProfileDeletion as R,cronIdsForProfileDetach as C,deleteCronsForProfile as T,deleteNodes as O,getNode as m,getRow as W,globalizeCronsForProfile as A,listNodesByProfile as M,nodesRoot as B,reviewDir as $}from"../core/canvas/index.js";import{withCanvasWrite as v}from"../core/canvas/db.js";import{deleteProfileWithOwned as _}from"../core/graph/deletion.js";import{usage as f}from"../core/errors.js";import{emitEvent as z}from"../core/events/emit.js";import{clearDefaultProfileId as k,defaultProfileDirs as L}from"../core/profiles/default-binding.js";import{reserveProfileDeletion as J}from"../core/profiles/deletion-reservation.js";import{deleteProfile as D,loadProfileManifest as G}from"../core/profiles/manifest.js";import{deleteReviewsByOriginNodes as H,reviewIdsByOriginNodes as K}from"../core/review/store.js";import{boundFleet as U}from"../core/runtime/fleet.js";import{headlessBrokerHost as b}from"../core/runtime/host.js";import{transition as Q}from"../core/runtime/lifecycle.js";import{tearDownNode as V}from"../core/runtime/placement.js";import{reshapeNode as X}from"../core/runtime/promote.js";import{reviveNode as Y}from"../core/runtime/revive.js";import{filterAsync as Z,flatMapAsync as ee}from"../core/async-array.js";const P=1e3,N=new Set(["page.json","page.tsx","page.html","page.js","review.json","response.json","progress.json","claim.json","reply-route.json","feedback-comments.json","feedback.json",".ticket-lock"]),h=new Map;function te(e){if(typeof e!="object"||e===null||Array.isArray(e))throw f("profile deletion requires a JSON request body",{error:"force_required",message:"profile deletion requires --force",next:"Re-run `crtr profile delete <profile> --force` after reviewing its effects."});return e}d(te,"requestObject");function re(e){const t=te(e);if(t.force!==!0)throw f("profile deletion requires --force",{error:"force_required",message:"profile deletion requires --force",next:"Re-run `crtr profile delete <profile> --force` after reviewing its effects."});if(t.detach!==void 0&&typeof t.detach!="boolean")throw f("detach must be a boolean",{error:"invalid_detach",message:"detach must be a boolean",next:"Use --detach as a presence-only flag, or omit it."});const r=t.caller_node_id;if(r!=null&&(typeof r!="string"||r===""))throw f("caller_node_id must be a nonempty string or null");return{force:!0,...t.detach===!0?{detach:!0}:{},...r===void 0?{}:{caller_node_id:r}}}d(re,"validateRequest");function j(e){if(!w(e))return null;try{const t=JSON.parse(E(e,"utf8"));return typeof t.source?.nodeId=="string"&&t.source.nodeId!==""?t.source.nodeId:null}catch{return null}}d(j,"manifestSourceNodeId");async function oe(e){const t=new Set(e),r=B();if(t.size===0||!w(r))return[];const o=[];for(const n of g(r,{withFileTypes:!0})){if(!n.isDirectory())continue;const s=u(r,n.name);[j(u(s,"page.json")),j(u(s,"review.json"))].some(a=>a!==null&&t.has(a))&&o.push({dir:s,wholeDirectory:t.has(n.name)||await W(n.name)===null})}return o.sort((n,s)=>n.dir.localeCompare(s.dir))}d(oe,"ticketCleanupForNodes");function ne(e){if(N.has(e))return!0;for(const t of N)if(e.startsWith(`${t}.`)&&(e.endsWith(".tmp")||e.endsWith(".lock")))return!0;return!1}d(ne,"isTicketOwnedResidue");function ie(e){let t=0;for(const r of e)if(w(r.dir)){if(r.wholeDirectory){p(r.dir,{recursive:!0,force:!0}),t+=1;continue}for(const o of g(r.dir,{withFileTypes:!0}))ne(o.name)&&p(u(r.dir,o.name),{recursive:!0,force:!0});t+=1}return t}d(ie,"cleanTickets");function S(e){const t=e.filter(o=>o.managed_worktree?.state==="open").map(o=>({node_id:o.node_id,path:o.managed_worktree.path}));if(t.length===0)return null;const r=`profile deletion is blocked by ${t.length} open managed worktree${t.length===1?"":"s"}`;return f(r,{error:"open_managed_worktree",message:r,nodes:t,next:`Close ${t.map(({node_id:o})=>o).join(", ")} with \`crtr node worktree close <node>\`, then retry.`})}d(S,"openWorktreeError");async function se(e,t){const r=await M(e.profileId),o=S(r);if(o!==null)throw o;const n=r.map(({node_id:c})=>c),s=t.detach===!0?"detached":"deleted";return{entry:e,mode:s,nodes:r,nodeIds:n,tickets:s==="deleted"?await oe(n):[],cronIds:s==="deleted"?await R(e.profileId,n):await C(e.profileId),reviewIds:s==="deleted"?await K(n):[],defaultDirs:L(e.profileId)}}d(se,"prepareDeletion");async function x(e){const t=await ee(e.nodeIds,async o=>{const n=await m(o);return n===null?[]:[n]}),r=S(t);if(r!==null)throw r}d(x,"assertDeletionPlanPreconditions");function y(e){return{profile_id:e.entry.profileId,name:e.entry.manifest.name,mode:e.mode,nodes:e.nodeIds.length,crons:e.cronIds.length,tickets:e.tickets.length,reviews:e.reviewIds.length,default_pins:e.defaultDirs.length}}d(y,"resultForPlan");async function de(e){await x(e);const t=await Z(e.nodeIds,async i=>await m(i)!==null),r=U(),o=t.flatMap(i=>{const l=r.get(i);return l===void 0?[]:[{nodeId:i,exited:l.handle.exited}]}),n=[];for(const{nodeId:i}of o){const l=await m(i);(l?.status==="active"||l?.status==="idle")&&(await Q(i,"release"),n.push(i)),b.teardown(i)}await Promise.all(o.map(({exited:i})=>i));const s=[];for(const i of t)await m(i)!==null&&(await X(i,{profileId:null}),s.push(i));const c=await A(e.entry.profileId),a=k(e.entry.profileId);await v(async i=>await _(i,e.entry.profileId)),D(e.entry.profileId);const I=new Set(s);for(const i of n)I.has(i)&&await Y(i,{resume:!0,recovery:!0,capacity:"freeze"});return{...y(e),nodes:s.length,crons:c.length,default_pins:a.length}}d(de,"detachProfile");async function ce(e){await x(e);const t=await T(e.entry.profileId,e.nodeIds);for(const c of e.nodeIds)b.teardown(c),await V(c);const r=await H(e.nodeIds);for(const c of r)p($(c),{recursive:!0,force:!0});const o=ie(e.tickets),n=await O(e.nodeIds),s=k(e.entry.profileId);return await v(async c=>await _(c,e.entry.profileId)),D(e.entry.profileId),{...y(e),nodes:n.length,crons:t.length,tickets:o,reviews:r.length,default_pins:s.length}}d(ce,"hardDeleteProfile");async function F(e){return e.mode==="detached"?de(e):await ce(e)}d(F,"executePlan");function ae(e,t){const r={...y(e),accepted:!0,grace_ms:P};return h.set(e.entry.profileId,{result:r}),setTimeout(()=>{(async()=>{try{await F(e)}catch(o){z({level:"error",event:"profile.delete.deferred_failed",error:o instanceof Error?o:new Error(String(o)),fields:{profile_id:e.entry.profileId,mode:e.mode}})}finally{h.delete(e.entry.profileId),t()}})()},P),r}d(ae,"scheduleSelfDeletion");async function xe(e,t){const r=re(t),o=G(e),n=h.get(o.profileId);if(n!==void 0)return{status:202,body:n.result};const s=J(o.profileId);let c=!1;try{const a=await se(o,r);if(r.caller_node_id!=null&&a.nodeIds.includes(r.caller_node_id)){const i=ae(a,s);return c=!0,{status:202,body:i}}return{status:200,body:await F(a)}}finally{c||s()}}d(xe,"requestProfileDeletion");export{xe as requestProfileDeletion};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { ReadyDTO } from '../api/dto/health.js';
|
|
2
2
|
/** True on a joined runtime whose issuer snapshot has never committed (a committed empty snapshot counts as committed). */
|
|
3
|
-
export declare function grantSnapshotMissing(): boolean
|
|
3
|
+
export declare function grantSnapshotMissing(): Promise<boolean>;
|
|
4
4
|
export interface ReadinessInputs {
|
|
5
5
|
/** App listener only: the JWKS mirror has loaded. */
|
|
6
6
|
jwksReady?: boolean;
|
|
7
7
|
/** App listener only: its injected grant-snapshot test, used in place of the mirror read. */
|
|
8
8
|
grantsReady?: () => boolean;
|
|
9
9
|
}
|
|
10
|
-
export declare function runtimeReadiness(inputs?: ReadinessInputs): ReadyDTO
|
|
10
|
+
export declare function runtimeReadiness(inputs?: ReadinessInputs): Promise<ReadyDTO>;
|
package/dist/daemon/readiness.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var a=Object.defineProperty;var
|
|
1
|
+
var a=Object.defineProperty;var e=(s,n)=>a(s,"name",{value:n,configurable:!0});import{readConfig as o}from"../core/config.js";import{grantsSource as i,hasSyncedGrants as r}from"../core/grants/mirror.js";import{boundDaemonControl as u}from"./control.js";function t(){const s=o("user").runtime?.issuer;return s?s.replace(/\/$/,""):null}e(t,"joinedIssuer");async function g(){const s=t();return s!==null&&!await r(s)}e(g,"grantSnapshotMissing");async function l(){const s=t();return s===null?await i()==="local":await r(s)}e(l,"grantsInstalled");async function p(s={}){const n=u()?.startupBlock()??null;return n!==null?{ready:!1,reason:"startup_pending",message:`daemon startup is ${n.phase}`}:s.jwksReady===!1?{ready:!1,reason:"jwks_pending",message:"the directory key set has not loaded"}:s.grantsReady?.()??await l()?{ready:!0}:t()===null?{ready:!1,reason:"grant_snapshot_missing",message:"the local grant is not installed yet"}:{ready:!1,reason:"grant_snapshot_missing",message:"the first grant snapshot from the directory has not committed"}}e(p,"runtimeReadiness");export{g as grantSnapshotMissing,p as runtimeReadiness};
|
|
@@ -4,5 +4,5 @@ export interface ActionLaneContext {
|
|
|
4
4
|
}
|
|
5
5
|
/** The daemon lane for one-shot obligations with no publishing object: cron spawn/human sinks and human completion actions. */
|
|
6
6
|
export declare class ActionLaneReconciler {
|
|
7
|
-
run(now: number, ctx: ActionLaneContext): void
|
|
7
|
+
run(now: number, ctx: ActionLaneContext): Promise<void>;
|
|
8
8
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var p=Object.defineProperty;var
|
|
1
|
+
var p=Object.defineProperty;var o=(n,t)=>p(n,"name",{value:t,configurable:!0});import{rmSync as h}from"node:fs";import{claimDaemonAction as g,dueDaemonActions as w,settleDaemonAction as y}from"../../core/canvas/daemon-actions.js";import{getNode as _}from"../../core/canvas/canvas.js";import{emitEvent as l}from"../../core/events/emit.js";import{operationIdContext as c}from"../../core/events/operation-id.js";import{createPageRequest as I,getRequest as f}from"../../core/human/requests.js";import{synthesizedPageDocument as v,writeSynthesizedPage as k}from"../../core/human/page-synth.js";import{preparePage as $}from"../../core/human/page-authoring.js";import{resolvePageComponents as b}from"../../core/config.js";import{spawnChild as q}from"../../core/runtime/spawn.js";import{runDelivery as D}from"../delivery/run-delivery.js";import{deliveryDaemonInstanceId as m}from"./delivery-lane.js";import{cronBirthPlacement as P}from"../cron/armed-context.js";import{checkCronBirth as N}from"../cron/authority.js";async function s(n,t,e){await y(n.actionId,n.attempts,t,e,Date.now())}o(s,"settle");async function u(n,t,e){await s(n,t,{state:"permanent_failed",failure:{kind:"spawn_error",message:e}})}o(u,"failed");async function S(n,t,e){const i=await _(e.nodeId);if(i!==null){if(i.frozen_at!==null||i.pi_session_id!==null||i.status==="idle"||i.status==="done"||i.status==="canceled"){await s(n,t,{state:"acknowledged"});return}await u(n,t,i.status==="dead"?`cron spawn ${e.nodeId} recorded a failed birth`:`cron spawn ${e.nodeId} found an incomplete birth`);return}const r=e.principal;if(r===void 0){c.fresh(()=>l({level:"warn",event:"cron.birth.refused",node_id:e.nodeId,fields:{cron_id:e.cronId??null,action_id:n.actionId,reason:"grant_missing",stage:"delivery"}})),await s(n,t,{state:"permanent_failed",failure:{kind:"grant_refused",message:"grant_missing: the queued birth carries no cron principal"}});return}const a=await N(r);if(!a.allowed){c.fresh(()=>l({level:"warn",event:"cron.birth.refused",node_id:e.nodeId,fields:{cron_id:r.cron_id,action_id:n.actionId,grant_id:r.grant_id,reason:a.reason,stage:"delivery"}})),await s(n,t,{state:"permanent_failed",failure:{kind:"grant_refused",message:`${a.reason}: ${a.message}`}});return}try{await q({nodeId:e.nodeId,kind:e.kind,cwd:e.cwd,prompt:e.prompt,...await P(r,e.nodeId),readiness:"launch",profile:e.profile,isolated:e.isolated===!0,wakeOrigin:e.wakeOrigin}),await s(n,t,{state:"acknowledged"})}catch(d){await u(n,t,`cron spawn ${e.nodeId} failed: ${d instanceof Error?d.message:String(d)}`),c.fresh(()=>l({level:"error",event:"delivery.cron_spawn_failed",node_id:e.nodeId,error:d,fields:{action_id:n.actionId}}))}}o(S,"deliverSpawn");function z(n,t){const e=k(v(n.title,n.summary,t,!1));try{return $({sourceFile:e.path,source:{sessionName:n.sessionName,...n.profileName===null?{}:{profileName:n.profileName}},productKinds:b(),delivery:{placement:"inline",inbox:!0,reply:!1}})}finally{h(e.dir,{recursive:!0,force:!0})}}o(z,"preparedCronPage");async function A(n,t,e){if(await f(e.requestId)!==null){await s(n,t,{state:"acknowledged"});return}const i=n.body,r=typeof i?.stdout=="string"?i.stdout:null;if(r===null){await u(n,t,`cron human ${e.requestId} has no frozen stdout`);return}try{await I({request_id:e.requestId,prepared:z(e,r)}),await s(n,t,{state:"acknowledged"})}catch(a){await u(n,t,`cron human ${e.requestId} failed: ${a instanceof Error?a.message:String(a)}`)}}o(A,"deliverHuman");async function C(n,t){const e=n.adapter;if(n.body===null){await u(n,t,`daemon action ${n.actionId} has no body`);return}if(e.adapter==="subprocess"){let i=e.node_id;if(i===void 0){const r=n.idempotencyKey;if(!r.startsWith("human-action:"))throw new Error(`daemon action ${n.actionId} has no originating app`);const a=await f(r.slice(13));if(!a)throw new Error(`daemon action ${n.actionId} has no originating human request`);i=a.requester_node_id}await D({argv:e.argv,cwd:e.cwd,document:n.body,attempt:n.attempts,nodeId:i,...e.app?{app:e.app}:{}},async r=>await s(n,t,r));return}if(e.adapter==="cron_spawn"){await S(n,t,e);return}if(e.adapter==="cron_human"){await A(n,t,e);return}await u(n,t,`daemon action ${n.actionId} has unknown adapter ${String(e.adapter)}`)}o(C,"deliverAction");class T{static{o(this,"ActionLaneReconciler")}async run(t,e){if(!e.lifecycle.acceptsDetachedWork())return;let i;try{i=await w(t)}catch(r){c.fresh(()=>l({level:"error",event:"daemon_action.scan_failed",error:r}));return}for(const r of i)try{const a=await g(r.actionId,t,m);if(a===null)continue;e.lifecycle.registerDetached(C(a,m).catch(d=>{c.fresh(()=>l({level:"error",event:"daemon_action.failed",error:d,fields:{action_id:a.actionId}}))}))}catch(a){c.fresh(()=>l({level:"error",event:"daemon_action.claim_failed",error:a,fields:{action_id:r.actionId}}))}}}export{T as ActionLaneReconciler};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
2
|
-
WHERE j.status = 'running' AND o.deleted_at IS NULL`).all();for(const{object:
|
|
1
|
+
var h=Object.defineProperty;var f=(l,t)=>h(l,"name",{value:t,configurable:!0});import{existsSync as n,readFileSync as m,readdirSync as u,statSync as j}from"node:fs";import{join as b}from"node:path";import{bashJobPaths as _,bashJobsDir as y,expiredAutoBackgroundBashJobs as w,stopBackgroundBashJob as S}from"../../core/bash-jobs.js";import{killBashJobObject as x,recordBashJobObject as N}from"../../core/spaces/stop.js";import{withCanvasWrite as p}from"../../core/canvas/db.js";import{finishJob as E}from"../../core/graph/jobs.js";import{getById as v,getByRowid as A}from"../../core/graph/objects.js";import{isSafeNodeId as c}from"../../core/canvas/paths.js";import{contextDir as g}from"../../core/canvas/node-agent-paths.js";import{emitEvent as s}from"../../core/events/emit.js";import{operationIdContext as d}from"../../core/events/operation-id.js";import{isProfilePaused as B}from"../../core/profiles/manifest.js";import{filterAsync as J}from"../../core/async-array.js";const D=5*1e3;class H{static{f(this,"BashDeadlineReconciler")}lastScanAt=Number.NEGATIVE_INFINITY;startedAt=Date.now();async run(t,a){if(await this.publishExits(),!(t-this.lastScanAt<D)){this.lastScanAt=t;for(const e of a.rows){if(e.status==="dead"||B(e.profile_id))continue;const r=await g(e.node_id);let i;try{await this.adoptUnrecorded(e.node_id,r),i=w(r,t)}catch(o){d.fresh(()=>{s({level:"error",event:"bash_deadline.scan_failed",...c(e.node_id)?{node_id:e.node_id}:{},error:o})});continue}for(const o of i)await this.cancel(e.node_id,r,o.jobId)}}}async publishExits(){try{await p(async t=>{const a=await t.prepare(`SELECT j.object, j.job_dir FROM jobs j JOIN objects o ON o.rowid = j.object
|
|
2
|
+
WHERE j.status = 'running' AND o.deleted_at IS NULL`).all();for(const{object:e,job_dir:r}of a){const i=b(r,"job.exit");if(!n(i)||n(b(r,"job.stop")))continue;const o=Number(m(i,"utf8").trim());Number.isSafeInteger(o)&&await E(t,await A(t,e),{exitCode:o})}})}catch(t){d.fresh(()=>s({level:"error",event:"bash_completion.delivery_failed",error:t}))}}async adoptUnrecorded(t,a){let e;try{e=u(y(a))}catch{return}const r=await p(async i=>await J(e,async o=>await v(i,o)===null));for(const i of r){const o=_(a,i);!n(o.jobBg)||!n(o.cmdSh)||n(o.jobExit)&&j(o.jobExit).mtimeMs<this.startedAt||await N(t,i,{command:m(o.cmdSh,"utf8"),jobDir:o.dir,logPath:o.jobLog})}}async cancel(t,a,e){(await S(a,e,!1,t)).kind==="stopped"&&await d.fresh(async()=>{try{s({level:"info",event:"bash_deadline.canceled",...c(t)?{node_id:t}:{},fields:{job_id:e}}),await x(e,async()=>null,"deadline")}catch(i){s({level:"error",event:"bash_deadline.notice_failed",...c(t)?{node_id:t}:{},error:i,fields:{job_id:e}})}})}}export{H as BashDeadlineReconciler};
|
|
@@ -97,6 +97,6 @@ export declare class BrokerSupervisionReconciler {
|
|
|
97
97
|
* leaves the fault either fully announced or fully unannounced. The daemon registers this as the announcer
|
|
98
98
|
* every clear of an unannounced fatal fault runs first with `settle` false: a clear ends the fault on purpose
|
|
99
99
|
* (a revive, a completed turn), so it announces but does not end the node. */
|
|
100
|
-
handleFatalFault(id: string, settle?: boolean): void
|
|
100
|
+
handleFatalFault(id: string, settle?: boolean): Promise<void>;
|
|
101
101
|
}
|
|
102
102
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var Y=Object.defineProperty;var p=(s,e)=>Y(s,"name",{value:e,configurable:!0});import{existsSync as H}from"node:fs";import{LAUNCHER_SOCKET as K}from"../../launcher/spec.js";import{launcherRequest as V}from"../../launcher/client.js";import{execFile as z}from"node:child_process";import{promisify as j}from"node:util";import{getNode as T,isWarmSpare as J,subscribersOf as Q}from"../../core/canvas/index.js";import{isSafeNodeId as c}from"../../core/canvas/paths.js";import{contextDir as X}from"../../core/canvas/node-agent-paths.js";import{fullName as C}from"../../core/canvas/labels.js";import{recordedPidLiveness as D}from"../../core/canvas/pid.js";import{transition as Z}from"../../core/runtime/lifecycle.js";import{hasAdmittedTurn as ee,listUnnotifiedFatalFaultNodes as te,markFaultNotified as ne,readFault as O,readLiveTurn as E,recordFault as re}from"../../core/canvas/recovery.js";import{errorClassFromFault as ie}from"../../core/fault-classifier.js";import{nextFaultRetry as ae}from"../../core/runtime/fault-recovery.js";import{publishNotice as R}from"../../core/runtime/close.js";import{openDb as G,withCanvasWrite as se}from"../../core/canvas/db.js";import{getById as oe}from"../../core/graph/objects.js";import{watcherIdsOf as le}from"../../core/graph/watches.js";import{headlessBrokerHost as S}from"../../core/runtime/host.js";import{emitEvent as u}from"../../core/events/emit.js";import{operationIdContext as F}from"../../core/events/operation-id.js";import{hasUnseenWakeMail as de,resetStaleExecutionMail as ce}from"../../core/canvas/deliveries.js";import{activeBackgroundBashJobs as ue}from"../../core/bash-jobs.js";import{focusOf as fe}from"../../core/runtime/placement.js";import{hasAttachedBrokerViewers as pe}from"../api/viewer-presence.js";import{deliverLive as me}from"../../core/runtime/interactive-deliver.js";import{BrokerUnreachableError as he}from"../../core/runtime/broker-request.js";import{formatCard as _e,PARK_SUMMARY_PROMPT as ge}from"../../shared/generated-context.js";import{brokerThresholdsForDaemon as
|
|
2
|
-
`)){const i=r.trim();if(i==="")continue;const n=i.split(/\s+/);if(n.length<3)continue;const l=Number(n[0]),o=Number(n[1]),a=Number(n[2]);if(!Number.isFinite(l)||!Number.isFinite(o)||!Number.isFinite(a))continue;e.set(l,a);const m=t.get(o);m===void 0?t.set(o,[l]):m.push(l)}return{byPid:e,childrenOf:t}}p(q,"parsePsTree");function Le(s,e){const{byPid:t,childrenOf:r}=q(s);if(!t.has(e))return null;let i=0;const n=[e],l=new Set;for(;n.length>0;){const o=n.pop();if(l.has(o))continue;l.add(o),i+=t.get(o)??0;const a=r.get(o);a!==void 0&&n.push(...a)}return i}p(Le,"sumTreeCpu");function We(s,e){const{byPid:t,childrenOf:r}=q(s);return t.has(e)?(r.get(e)??[]).length>0:null}p(We,"treeHasDescendants");class Pt{static{p(this,"BrokerSupervisionReconciler")}yieldStalls=new Map;wedgeNotifiedAt=new Map;unattendedSince=new Map;sampleTree;signal;lastOverCapWarnAt=Number.NEGATIVE_INFINITY;constructor(e={}){this.sampleTree=e.readTreeSample??(t=>this.readTreeSample(t)),this.signal=e.signal??((t,r)=>{if(process.platform==="linux"&&H(K)){if(r!=="SIGTERM"&&r!=="SIGKILL")throw new Error(`unsupported launcher signal ${r}`);return V({operation:"stop",pid:t,signal:r}).then(()=>{})}process.kill(t,r)})}async runFleetPreamble(e){return
|
|
3
|
-
`).map(async h=>{if(h!=="")try{await A("tmux",["display-message","-C","-d","10000","-c",h,m],{encoding:"utf8",timeout:2e3})}catch{try{await A("tmux",["display-message","-c",h,m],{encoding:"utf8",timeout:2e3})}catch(_){u({level:"error",event:"broker.capacity.tmux_display_failed",error:_,fields:{client:h}})}}}))}catch(d){u({level:"error",event:"broker.capacity.tmux_list_clients_failed",error:d})}}async handleYieldStall(e,t,r,i){const n=e.node_id,l=L(t.pid,e.pi_pid_identity);if(e.intent!=="refresh"||x(e)!==null||l===null){l!==null&&this.yieldStalls.delete(l);return}let o=this.yieldStalls.get(l);if(o===void 0){o={since:i},this.yieldStalls.set(l,o);return}if(Re(!0,e.intent,!1,i-o.since)!=="kill")return;const a=T(n);if(!(r.get(n)!==t||a?.pi_pid!==t.pid||a.pi_pid_identity!==e.pi_pid_identity||D(t.pid,e.pi_pid_identity)!=="alive"))if(o.termedAt===void 0){if(!await this.signalYieldStall(n,t.pid,"SIGTERM"))return;o.termedAt=i,u({level:"warn",event:"broker.yield_stall.sigterm",...c(n)?{node_id:n}:{},fields:{...c(n)?{}:{affected_node_id:n},pid:t.pid,elapsed_ms:i-o.since,grace_ms:W}})}else i-o.termedAt>=B&&await this.signalYieldStall(n,t.pid,"SIGKILL")&&u({level:"warn",event:"broker.yield_stall.sigkill",...c(n)?{node_id:n}:{},fields:{...c(n)?{}:{affected_node_id:n},pid:t.pid,elapsed_ms:i-o.termedAt,grace_ms:B,stall_elapsed_ms:i-o.since}})}async signalYieldStall(e,t,r){try{return await this.signal(t,r),!0}catch(i){return u({level:"error",event:"broker.yield_stall.signal_failed",...c(e)?{node_id:e}:{},error:i,fields:{...c(e)?{}:{affected_node_id:e},pid:t,signal:r}}),!1}}async readTreeSample(e){try{const{stdout:t}=await A("ps",["-ax","-o","pid=,ppid=,pcpu="],{encoding:"utf8",timeout:2e3});if(typeof t!="string")return null;const r=Le(t,e),i=We(t,e);return r===null||i===null?null:{cpuPercent:r,hasDescendants:i}}catch{return null}}async handleWedgeDetection(e,t,r,i){const n=e.node_id,l=L(t.pid,e.pi_pid_identity),o=x(e);if(o===null||l===null){l!==null&&this.wedgeNotifiedAt.delete(l);return}const a=i-o,m=a>=I?await this.sampleTree(t.pid):null,d=T(n),h=d===null?null:x(d);if(r.get(n)!==t||d===null||d.pi_pid!==t.pid||d.pi_pid_identity!==e.pi_pid_identity||h!==o)return;const _=m?.cpuPercent??null,$=m?.hasDescendants??null;if(Ge({busy:!0,quietForMs:a,cpuPercent:_,hasDescendants:$})!=="wedged"||this.wedgeNotifiedAt.get(l)===o)return;this.wedgeNotifiedAt.set(l,o);const
|
|
4
|
-
`)[0]??"").slice(0,200),a=r.providerError,m=a===void 0?"":` Provider: ${a.provider}/${a.model}.`+(a.status===void 0?"":` HTTP status: ${a.status}.`)+(a.errno===void 0?"":` Errno: ${a.errno}.`)+(a.code===void 0?"":` Code: ${a.code}.`)+(a.body===void 0?"":` Body: ${a.body.slice(0,200)}.`)+(a.ratelimit===void 0?"":` Rate limit: ${a.ratelimit.scope??"account"}${a.ratelimit.claim===void 0?"":` (${a.ratelimit.claim})`}${a.ratelimit.model===void 0?"":` on ${a.ratelimit.model}`}.`),d=r.kind==="context-overflow",h=De(i,typeof a?.code=="string"?a.code:void 0),_=d||h,$=d?`exceeded its model context window and is now dead. Shrink the task or loaded context, or choose a larger-context model before spawning it again. Error: ${o}`:`got a non-retryable ${r.kind} error and will NOT recover on its own; `+(h?"its terminal run has failed. ":"it stays alive, and waking it clears the fault as soon as one turn completes \u2014 a wake that hits the same cause fails again. "+(l?"Its provider credential is dead \u2014 re-authenticate (`/login`, or re-auth crtr); it recovers on its next wake once the auth reloads. ":""))+`Error: ${o}.${m}`,
|
|
1
|
+
var Y=Object.defineProperty;var p=(s,e)=>Y(s,"name",{value:e,configurable:!0});import{existsSync as H}from"node:fs";import{LAUNCHER_SOCKET as K}from"../../launcher/spec.js";import{launcherRequest as V}from"../../launcher/client.js";import{execFile as z}from"node:child_process";import{promisify as j}from"node:util";import{getNode as T,isWarmSpare as J,subscribersOf as Q}from"../../core/canvas/index.js";import{isSafeNodeId as c}from"../../core/canvas/paths.js";import{contextDir as X}from"../../core/canvas/node-agent-paths.js";import{fullName as C}from"../../core/canvas/labels.js";import{recordedPidLiveness as D}from"../../core/canvas/pid.js";import{transition as Z}from"../../core/runtime/lifecycle.js";import{hasAdmittedTurn as ee,listUnnotifiedFatalFaultNodes as te,markFaultNotified as ne,readFault as O,readLiveTurn as E,recordFault as re}from"../../core/canvas/recovery.js";import{errorClassFromFault as ie}from"../../core/fault-classifier.js";import{nextFaultRetry as ae}from"../../core/runtime/fault-recovery.js";import{publishNotice as R}from"../../core/runtime/close.js";import{openDb as G,withCanvasWrite as se}from"../../core/canvas/db.js";import{getById as oe}from"../../core/graph/objects.js";import{watcherIdsOf as le}from"../../core/graph/watches.js";import{headlessBrokerHost as S}from"../../core/runtime/host.js";import{emitEvent as u}from"../../core/events/emit.js";import{operationIdContext as F}from"../../core/events/operation-id.js";import{hasUnseenWakeMail as de,resetStaleExecutionMail as ce}from"../../core/canvas/deliveries.js";import{activeBackgroundBashJobs as ue}from"../../core/bash-jobs.js";import{focusOf as fe}from"../../core/runtime/placement.js";import{hasAttachedBrokerViewers as pe}from"../api/viewer-presence.js";import{deliverLive as me}from"../../core/runtime/interactive-deliver.js";import{BrokerUnreachableError as he}from"../../core/runtime/broker-request.js";import{formatCard as _e,PARK_SUMMARY_PROMPT as ge}from"../../shared/generated-context.js";import{brokerThresholdsForDaemon as ve}from"../../core/runtime/fleet.js";import{readConfig as we}from"../../core/config.js";import{beginPendingPark as ke,consumePendingPark as N,pendingParkIds as ye,pendingParkStartedAt as be}from"../park-pending.js";import{shouldParkAfterSummary as Se}from"../park-activity.js";import{applyParkEvent as P,parkEvent as Ne}from"./live-obligation.js";import{readGoal as Pe}from"../../core/runtime/kickoff.js";import{memoryDeniedRecently as $e}from"../../core/runtime/memory-admission.js";import{envNoDaemonAutostart as Te,envTestUnattendedParkMs as Ae,parkSummaryGraceMs as Me,envUnattendedParkMs as Ee}from"../../shared/env.js";const A=j(z);async function Fe(s){return!await ee(s)&&((await Pe(s))?.trim()??"")!==""}p(Fe,"awaitsBirthTurn");async function xe(s){return(await E(s))?.busy===!0}p(xe,"liveBusy");async function Nt(s){const e=(await E(s))?.progressAt;if(e==null)return null;const t=Date.parse(e);return Number.isNaN(t)?null:t}p(Nt,"liveTurnProgressMs");function L(s,e){return e===null?null:`${s}:${e}`}p(L,"incarnationOf");async function x(s){const e=await E(s.node_id),t=e?.busy===!0&&e.progressAt!==null?Date.parse(e.progressAt):Number.NaN,r=s.launched_at===null||s.launched_at===void 0?Number.NaN:Date.parse(s.launched_at);return!Number.isFinite(t)||!Number.isFinite(r)||t<r?null:t}p(x,"busySinceForIncarnation");const W=3*6e4,B=2e4,I=20*6e4,Ie=2,Ce=5*6e4;function De(s,e){return s===null||s.parent!=null?!1:s.lifecycle==="terminal"?!0:e==="cap_exhausted"&&s.run_id===s.node_id}p(De,"settlesOnFatalProviderFault");function Oe(){const s=Ee();if(s!==void 0)return s;const e=we("user").lifecycle.unattendedParkMs;return Te()?Ae()??e:e}p(Oe,"unattendedParkMsForDaemon");function U(){return Me()}p(U,"parkSummaryGraceMsForDaemon");function Re(s,e,t,r){return s!==!0||e!=="refresh"||t?"leave":r===null||r<W?"pending":"kill"}p(Re,"yieldStallVerdict");function Ge(s){return!s.busy||s.quietForMs===null||s.quietForMs<I?"leave":s.cpuPercent===null||s.hasDescendants!==!1&&s.cpuPercent>Ie?"pending":"wedged"}p(Ge,"wedgeVerdict");function q(s){const e=new Map,t=new Map;for(const r of s.split(`
|
|
2
|
+
`)){const i=r.trim();if(i==="")continue;const n=i.split(/\s+/);if(n.length<3)continue;const l=Number(n[0]),o=Number(n[1]),a=Number(n[2]);if(!Number.isFinite(l)||!Number.isFinite(o)||!Number.isFinite(a))continue;e.set(l,a);const m=t.get(o);m===void 0?t.set(o,[l]):m.push(l)}return{byPid:e,childrenOf:t}}p(q,"parsePsTree");function Le(s,e){const{byPid:t,childrenOf:r}=q(s);if(!t.has(e))return null;let i=0;const n=[e],l=new Set;for(;n.length>0;){const o=n.pop();if(l.has(o))continue;l.add(o),i+=t.get(o)??0;const a=r.get(o);a!==void 0&&n.push(...a)}return i}p(Le,"sumTreeCpu");function We(s,e){const{byPid:t,childrenOf:r}=q(s);return t.has(e)?(r.get(e)??[]).length>0:null}p(We,"treeHasDescendants");class Pt{static{p(this,"BrokerSupervisionReconciler")}yieldStalls=new Map;wedgeNotifiedAt=new Map;unattendedSince=new Map;sampleTree;signal;lastOverCapWarnAt=Number.NEGATIVE_INFINITY;constructor(e={}){this.sampleTree=e.readTreeSample??(t=>this.readTreeSample(t)),this.signal=e.signal??((t,r)=>{if(process.platform==="linux"&&H(K)){if(r!=="SIGTERM"&&r!=="SIGKILL")throw new Error(`unsupported launcher signal ${r}`);return V({operation:"stop",pid:t,signal:r}).then(()=>{})}process.kill(t,r)})}async runFleetPreamble(e){return ve()}warnIfSaturated(e){if(e.fleet.size()<e.thresholds.warning||!e.lifecycle.acceptsDetachedWork())return;const t=F.fresh(()=>this.warnOverCapInTmux(e.fleet.size(),e.thresholds,e.frozen));e.lifecycle.registerDetached(t)}async run(e,t){const r=Oe();for(const i of await te())await F.fresh(async()=>{try{await this.handleFatalFault(i)}catch(n){u({level:"error",event:"broker.supervision.failed",...c(i)?{node_id:i}:{fields:{affected_node_id:i}},error:n})}});for(const i of t.rows){const n=i.node_id,l=t.fleet.get(n);if(l===void 0||i.status!=="active"&&i.status!=="idle"){this.unattendedSince.delete(n);continue}await F.fresh(async()=>{try{await this.handleYieldStall(i,l,t.fleet,e),await this.handleWedgeDetection(i,l,t.fleet,e),await this.handleUnattendedParking(n,await T(n),l.pid,e,t,r)}catch(o){this.unattendedSince.delete(n),u({level:"error",event:"broker.supervision.failed",...c(n)?{node_id:n}:{fields:{affected_node_id:n}},error:o})}})}for(const i of this.unattendedSince.keys())t.fleet.has(i)||this.unattendedSince.delete(i);for(const i of ye())t.fleet.has(i)||N(i);await ce(e)}async parkResetCondition(e,t,r,i){if(t.pi_session_id==null||t.pi_pid!==r||t.status==="done"||t.status==="canceled"||t.status==="dead"||t.intent!==null||ue(await X(e)).length>0||await fe(e)!==null||pe(e))return!0;const n=await O(e);return n!==null&&n.retry.disposition==="auto"&&n.retry.by==="daemon"&&(n.kind==="connection"||n.kind==="rate-limit"||n.kind==="overloaded")&&(n.retry.nextAt!==void 0||ae(n,i)!==null)?!0:await de(e)}async handleUnattendedParking(e,t,r,i,n,l){if(await J(e)){this.unattendedSince.delete(e),N(e);return}if(t===null){this.unattendedSince.delete(e),N(e);return}const o=await this.parkResetCondition(e,t,r,i),a=be(e);if(a!==void 0){if(i-a<U())return;const _=N(e);if(_===void 0||(this.unattendedSince.delete(e),!await Se(e,t,_)))return;u({level:"warn",event:"broker.park.summary_expired",...c(e)?{node_id:e}:{},fields:{...c(e)?{}:{affected_node_id:e},grace_ms:U()}}),await P(e,"park"),S.teardown(e);return}if(o||await xe(e)||await Fe(e)){this.unattendedSince.delete(e);return}const m=this.unattendedSince.get(e);if(m===void 0){this.unattendedSince.set(e,i);return}const d=await Ne(e,t.lifecycle),h=d!=="cancel"&&$e(t.grantee??"app:terminal",i)?0:l;if(!(i-m<h)){if(this.unattendedSince.delete(e),d==="release"){await P(e,d),S.teardown(e);return}if(d==="cancel"){await P(e,d),S.teardown(e);return}if(t.grantee!==void 0&&t.grantee!=="app:terminal"){await P(e,"park"),S.teardown(e);return}n.lifecycle.acceptsDetachedWork()&&(ke(e,i),n.lifecycle.registerDetached(this.requestParkSummary(e)))}}async requestParkSummary(e){try{const t=await me(e,_e("park",{},ge),{origin:{type:"runtime",kind:"park"}});u({level:"info",event:"broker.park.summary_requested",...c(e)?{node_id:e}:{},fields:{...c(e)?{}:{affected_node_id:e},route:t}})}catch(t){if(N(e)===void 0)return;if(t instanceof he){await P(e,"park"),S.teardown(e);return}u({level:"error",event:"broker.park.summary_failed",...c(e)?{node_id:e}:{fields:{affected_node_id:e}},error:t})}}async warnOverCapInTmux(e,t,r){const i=Date.now();if(i-this.lastOverCapWarnAt<Ce)return;this.lastOverCapWarnAt=i;const{warning:n,automaticReviveCap:l}=t,o=r.stalled+r.waitingOnMail;u({level:"warn",event:"broker.capacity.warning",fields:{live_count:e,warning_threshold:n,hard_cap:l,frozen_stalled:r.stalled,frozen_waiting_on_mail:r.waitingOnMail}});const a=o===0?"":` \u2014 ${o} frozen (${r.stalled} stalled, ${r.waitingOnMail} waiting on mail)`,m=`\u26A0 crtrd: ${e} live brokers (warning ${n}; hard cap ${l})${a} \u2014 possible broker leak. ps -ax | grep broker-cli.js`;try{const d=await A("tmux",["list-clients","-F","#{client_name}"],{encoding:"utf8",timeout:2e3});if(typeof d.stdout!="string")return;await Promise.allSettled(d.stdout.split(`
|
|
3
|
+
`).map(async h=>{if(h!=="")try{await A("tmux",["display-message","-C","-d","10000","-c",h,m],{encoding:"utf8",timeout:2e3})}catch{try{await A("tmux",["display-message","-c",h,m],{encoding:"utf8",timeout:2e3})}catch(_){u({level:"error",event:"broker.capacity.tmux_display_failed",error:_,fields:{client:h}})}}}))}catch(d){u({level:"error",event:"broker.capacity.tmux_list_clients_failed",error:d})}}async handleYieldStall(e,t,r,i){const n=e.node_id,l=L(t.pid,e.pi_pid_identity);if(e.intent!=="refresh"||await x(e)!==null||l===null){l!==null&&this.yieldStalls.delete(l);return}let o=this.yieldStalls.get(l);if(o===void 0){o={since:i},this.yieldStalls.set(l,o);return}if(Re(!0,e.intent,!1,i-o.since)!=="kill")return;const a=await T(n);if(!(r.get(n)!==t||a?.pi_pid!==t.pid||a.pi_pid_identity!==e.pi_pid_identity||D(t.pid,e.pi_pid_identity)!=="alive"))if(o.termedAt===void 0){if(!await this.signalYieldStall(n,t.pid,"SIGTERM"))return;o.termedAt=i,u({level:"warn",event:"broker.yield_stall.sigterm",...c(n)?{node_id:n}:{},fields:{...c(n)?{}:{affected_node_id:n},pid:t.pid,elapsed_ms:i-o.since,grace_ms:W}})}else i-o.termedAt>=B&&await this.signalYieldStall(n,t.pid,"SIGKILL")&&u({level:"warn",event:"broker.yield_stall.sigkill",...c(n)?{node_id:n}:{},fields:{...c(n)?{}:{affected_node_id:n},pid:t.pid,elapsed_ms:i-o.termedAt,grace_ms:B,stall_elapsed_ms:i-o.since}})}async signalYieldStall(e,t,r){try{return await this.signal(t,r),!0}catch(i){return u({level:"error",event:"broker.yield_stall.signal_failed",...c(e)?{node_id:e}:{},error:i,fields:{...c(e)?{}:{affected_node_id:e},pid:t,signal:r}}),!1}}async readTreeSample(e){try{const{stdout:t}=await A("ps",["-ax","-o","pid=,ppid=,pcpu="],{encoding:"utf8",timeout:2e3});if(typeof t!="string")return null;const r=Le(t,e),i=We(t,e);return r===null||i===null?null:{cpuPercent:r,hasDescendants:i}}catch{return null}}async handleWedgeDetection(e,t,r,i){const n=e.node_id,l=L(t.pid,e.pi_pid_identity),o=await x(e);if(o===null||l===null){l!==null&&this.wedgeNotifiedAt.delete(l);return}const a=i-o,m=a>=I?await this.sampleTree(t.pid):null,d=await T(n),h=d===null?null:await x(d);if(r.get(n)!==t||d===null||d.pi_pid!==t.pid||d.pi_pid_identity!==e.pi_pid_identity||h!==o)return;const _=m?.cpuPercent??null,$=m?.hasDescendants??null;if(Ge({busy:!0,quietForMs:a,cpuPercent:_,hasDescendants:$})!=="wedged"||this.wedgeNotifiedAt.get(l)===o)return;this.wedgeNotifiedAt.set(l,o);const w=C(d),g=Math.round((a??I)/6e4),k=$??!0,v=!k&&D(t.pid,e.pi_pid_identity)!=="alive"?"pid_identity_unproven":null;let f=!1,y=!1,b;if(k)b=`Child wedged \u2014 ${w} (${n}) is alive and mid-turn but has shown NO engine progress for ${g}+ minutes and its process is near-idle. It will NOT recover on its own \u2014 read \`crtr canvas read wedged-child-on-runaway-bash\` and kill the runaway SUBPROCESS (not this node) so its turn can resume with no lost context.`;else if(v!==null)b=`Child wedged \u2014 ${w} (${n}) is alive and mid-turn but has shown NO engine progress for ${g}+ minutes and it has no subprocess to kill (the engine itself stalled). The daemon did not SIGTERM the broker because its PID identity cannot be confirmed alive.`;else{f=!0;try{await this.signal(t.pid,"SIGTERM"),y=!0,b=`Child wedged \u2014 ${w} (${n}) is alive and mid-turn but has shown NO engine progress for ${g}+ minutes and it has no subprocess to kill (the engine itself stalled). The daemon sent SIGTERM to the broker and will resume a cleanly aborted session with a continuation, or start a recovery cycle if the abort cannot settle.`}catch(M){u({level:"error",event:"broker.wedge.signal_failed",...c(n)?{node_id:n}:{},error:M,fields:{...c(n)?{}:{affected_node_id:n},pid:t.pid,signal:"SIGTERM"}}),b=`Child wedged \u2014 ${w} (${n}) is alive and mid-turn but has shown NO engine progress for ${g}+ minutes and it has no subprocess to kill (the engine itself stalled). The daemon attempted SIGTERM to the broker, but the signal call failed.`}}u({level:"error",event:"broker.wedge.detected",...c(n)?{node_id:n}:{},fields:{...c(n)?{}:{affected_node_id:n},pid:t.pid,quiet_ms:a,cpu_percent:_,has_descendants:k,kick_attempted:f,kicked:y,...v===null?{}:{kick_suppression_reason:v}}});try{await re(n,{link:"daemon\u2192node",op:"engine wedge",kind:"wedged",retry:{disposition:"manual"},message:b})}catch(M){u({level:"error",event:"broker.wedge.fault_record_failed",...c(n)?{node_id:n}:{fields:{affected_node_id:n}},error:M})}await R(n,"notice.crash",b,{reason:"child-wedged",child:n,quiet_ms:a,cpu_percent:_,kick_attempted:f,kicked:y,...v===null?{}:{kick_suppression_reason:v}})}async handleFatalFault(e,t=!0){const r=await O(e);if(r===null||r.retry.disposition!=="fatal"||r.link!=="pi\u2192provider"||r.notifiedSince===r.since)return;const i=await T(e),n=i!==null?C(i):e,l=r.kind==="auth",o=(r.message.split(`
|
|
4
|
+
`)[0]??"").slice(0,200),a=r.providerError,m=a===void 0?"":` Provider: ${a.provider}/${a.model}.`+(a.status===void 0?"":` HTTP status: ${a.status}.`)+(a.errno===void 0?"":` Errno: ${a.errno}.`)+(a.code===void 0?"":` Code: ${a.code}.`)+(a.body===void 0?"":` Body: ${a.body.slice(0,200)}.`)+(a.ratelimit===void 0?"":` Rate limit: ${a.ratelimit.scope??"account"}${a.ratelimit.claim===void 0?"":` (${a.ratelimit.claim})`}${a.ratelimit.model===void 0?"":` on ${a.ratelimit.model}`}.`),d=r.kind==="context-overflow",h=De(i,typeof a?.code=="string"?a.code:void 0),_=d||h,$=d?`exceeded its model context window and is now dead. Shrink the task or loaded context, or choose a larger-context model before spawning it again. Error: ${o}`:`got a non-retryable ${r.kind} error and will NOT recover on its own; `+(h?"its terminal run has failed. ":"it stays alive, and waking it clears the fault as soon as one turn completes \u2014 a wake that hits the same cause fails again. "+(l?"Its provider credential is dead \u2014 re-authenticate (`/login`, or re-auth crtr); it recovers on its next wake once the auth reloads. ":""))+`Error: ${o}.${m}`,w=d?"failed":"hit a fatal provider fault",g=new Set((await Q(e)).map(f=>f.node_id)),k=await le(await G(),await oe(await G(),e)),v=[{relation:"Child",recipients:k.filter(f=>g.has(f))},{relation:"Watched node",recipients:k.filter(f=>!g.has(f))}];u({level:"error",event:"fault.fatal.fanout",...c(e)?{node_id:e}:{},fields:{...c(e)?{}:{affected_node_id:e},kind:r.kind,link:r.link,terminal_overflow:d,terminal_provider_fault:h}}),await se(async()=>{for(const{relation:f,recipients:y}of v)y.length!==0&&await R(e,"notice.crash",`${f} ${w} \u2014 ${n} (${e}) ${$}`,{reason:d?"child-context-overflow":"child-fault-fatal",child:e,kind:r.kind,message:o,...a===void 0?{}:{provider_error:a}},"normal",null,y);await ne(r.faultId),t&&_&&await Z(e,"crash",{reason:d?"context_overflow":a?.code==="cap_exhausted"?"cap_exhausted":"provider_fatal",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",message:r.message,fault_kind:r.kind,error_class:ie(r).class}}})}),t&&_&&S.teardown(e).then(f=>{f.confirmed||u({level:"error",event:"fault.fatal.teardown_failed",node_id:e,error:f.error??new Error("Broker teardown not confirmed")})},f=>u({level:"error",event:"fault.fatal.teardown_failed",node_id:e,error:f}))}}export{Pt as BrokerSupervisionReconciler,Ie as WEDGE_CPU_MAX_PERCENT,I as WEDGE_QUIET_MS,W as YIELD_STALL_GRACE_MS,U as parkSummaryGraceMsForDaemon,De as settlesOnFatalProviderFault,Le as sumTreeCpu,We as treeHasDescendants,Oe as unattendedParkMsForDaemon,Ge as wedgeVerdict,Re as yieldStallVerdict};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var i=Object.defineProperty;var e=(r,o)=>i(r,"name",{value:o,configurable:!0});import{liveControllerWaits as n}from"../../core/canvas/waits.js";import{operationIdContext as l}from"../../core/events/operation-id.js";import{enqueueControllerDeathNotice as c}from"../../core/feed/messages.js";class p{static{e(this,"ControllerDeathReconciler")}async run(o,a){for(const t of await n())await l.fresh(async()=>{await c(t.nodeId,t.controllerId)})}}export{p as ControllerDeathReconciler};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var l=Object.defineProperty;var t=(i,r)=>l(i,"name",{value:r,configurable:!0});import{emitEvent as o}from"../../core/events/emit.js";import{operationIdContext as c}from"../../core/events/operation-id.js";import{sweepOrphanCronFolders as n}from"../cron/folders.js";import{reapRebuiltCronExecutions as s}from"../cron/run-socket.js";import{recoverStaleCronLeases as f,runDueCrons as p}from"../cron-run.js";class w{static{t(this,"CronLaneReconciler")}lastFolderSweep=0;async run(r,a){await c.fresh(async()=>{try{await f(r,{register:t(e=>a.lifecycle.registerDetached(e),"register")})}catch(e){o({level:"error",event:"cron.lease_recovery.failed",error:e})}});try{await s()}catch(e){o({level:"error",event:"cron.execution.reap_failed",error:e})}if(r-this.lastFolderSweep>=6e4){this.lastFolderSweep=r;try{await n()}catch(e){o({level:"error",event:"cron.folder.sweep_failed",error:e})}}if(a.lifecycle.acceptsDetachedWork())try{await p(r,{register:t(e=>a.lifecycle.registerDetached(e),"register")})}catch(e){o({level:"error",event:"cron.run.failed",error:e})}}}export{w as CronLaneReconciler};
|
|
@@ -5,5 +5,5 @@ export interface DeliveryLaneContext {
|
|
|
5
5
|
}
|
|
6
6
|
/** Due push receivers only. Queue rows have no next_attempt_at and never enter this lane. */
|
|
7
7
|
export declare class DeliveryLaneReconciler {
|
|
8
|
-
run(now: number, ctx: DeliveryLaneContext): void
|
|
8
|
+
run(now: number, ctx: DeliveryLaneContext): Promise<void>;
|
|
9
9
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
1
|
+
var g=Object.defineProperty;var c=(e,t)=>g(e,"name",{value:t,configurable:!0});import{randomUUID as D}from"node:crypto";import{claimPushDelivery as h,duePushDeliveries as j,messageBodyForDelivery as N,pushDeliveryClaimIsCurrent as O,settleDelivery as d}from"../../core/canvas/deliveries.js";import{deliveryBackoffMs as f}from"../../core/canvas/delivery-contract.js";import{openDb as p}from"../../core/canvas/db.js";import{pushLineFor as u}from"../../core/graph/custom.js";import{postReceiverUrl as b}from"../../core/graph/receiver-url.js";import{emitEvent as l}from"../../core/events/emit.js";import{operationIdContext as m}from"../../core/events/operation-id.js";import{runDelivery as w,DELIVERY_TIMEOUT_MS as E}from"../delivery/run-delivery.js";const v=D();async function o(e,t,a){await d(e.deliveryId,e.attempts,t,{state:"permanent_failed",failure:{kind:"spawn_error",message:a}},Date.now())}c(o,"failed");async function T(e,t){const a=await(await p()).prepare(`SELECT o.type, o.name, c.receiver_json, c.payload_json, m.object_id, i.external_id AS app,
|
|
2
2
|
d.message_id, owner.type AS owner_type, parent.external_id AS parent_app
|
|
3
3
|
FROM deliveries d JOIN objects o ON o.id = d.destination_id
|
|
4
4
|
JOIN custom_objects c ON c.object = o.rowid JOIN messages m ON m.message_id = d.message_id
|
|
5
5
|
LEFT JOIN objects owner ON owner.rowid = o.owner
|
|
6
6
|
LEFT JOIN identities i ON i.object = o.owner AND i.scheme = 'app'
|
|
7
7
|
LEFT JOIN identities parent ON parent.object = owner.owner AND parent.scheme = 'app'
|
|
8
|
-
WHERE d.delivery_id = ?`).get(e.deliveryId);if(!
|
|
8
|
+
WHERE d.delivery_id = ?`).get(e.deliveryId);if(!a||!a.receiver_json){await o(e,t,`delivery ${e.deliveryId} has no supported receiver`);return}const i=JSON.parse(a.receiver_json);if(!await O(e,t)){await d(e.deliveryId,e.attempts,t,{state:"acknowledged"},Date.now());return}if(typeof i=="object"&&typeof i.url=="string"&&a.type!=="action"){const n=await u(await p(),e.deliveryId);if(!n){await o(e,t,`delivery ${e.deliveryId} has no event document`);return}try{const r=await b(i.url,JSON.stringify(n),{"Content-Type":"application/json","X-Crtr-Delivery":e.deliveryId,"X-Crtr-Event":a.message_id},E);r>=200&&r<300?await d(e.deliveryId,e.attempts,t,{state:"acknowledged"},Date.now()):r>=300&&r<400?await o(e,t,`url receiver returned HTTP ${r}; redirects are not followed \u2014 register the final URL`):r>=400&&r<500&&r!==408&&r!==429?await o(e,t,`url receiver returned HTTP ${r}`):await d(e.deliveryId,e.attempts,t,{state:"pending",nextAttemptAt:Date.now()+f(e.attempts),failure:{kind:"spawn_error",message:`url receiver returned HTTP ${r}`}},Date.now())}catch(r){await d(e.deliveryId,e.attempts,t,{state:"pending",nextAttemptAt:Date.now()+f(e.attempts),failure:{kind:"spawn_error",message:String(r)}},Date.now())}return}if(typeof i!="object"||!Array.isArray(i.argv)||typeof i.cwd!="string"){await o(e,t,`delivery ${e.deliveryId} has an invalid argv receiver`);return}if(a.type==="action"){if(typeof i.name!="string"||!a.object_id){await o(e,t,`delivery ${e.deliveryId} has an invalid argv receiver`);return}const n=await N(e.deliveryId);if(n===null){await o(e,t,`delivery ${e.deliveryId} has no message body`);return}const{push:r,...y}=n,I={...y,action:{name:i.name,payload:a.payload_json===null?null:JSON.parse(a.payload_json)}};await w({argv:i.argv,cwd:i.cwd,document:I,attempt:e.attempts,nodeId:a.object_id,...a.app?{app:a.app}:{}},async _=>{await d(e.deliveryId,e.attempts,t,_,Date.now())});return}const s=await u(await p(),e.deliveryId);if(!s){await o(e,t,`delivery ${e.deliveryId} has no event document`);return}await w({argv:i.argv,cwd:i.cwd,document:s,attempt:e.attempts,app:a.app??a.parent_app??"app:terminal",custom:{deliveryId:e.deliveryId,messageId:a.message_id}},async n=>{await d(e.deliveryId,e.attempts,t,n,Date.now())})}c(T,"deliverExternal");class P{static{c(this,"DeliveryLaneReconciler")}async run(t,a){if(!a.lifecycle.acceptsDetachedWork())return;let i;try{i=await j(t)}catch(s){m.fresh(()=>l({level:"error",event:"delivery.scan_failed",error:s}));return}for(const s of i)try{const n=await h(s.deliveryId,t,v);if(n===null)continue;a.lifecycle.registerDetached(T(n,v).catch(r=>{m.fresh(()=>l({level:"error",event:"delivery.failed",error:r,fields:{delivery_id:n.deliveryId}}))}))}catch(n){m.fresh(()=>l({level:"error",event:"delivery.claim_failed",error:n,fields:{delivery_id:s.deliveryId}}))}}}export{P as DeliveryLaneReconciler,v as deliveryDaemonInstanceId};
|
|
@@ -19,9 +19,9 @@ export interface FaultRetryBackstopContext {
|
|
|
19
19
|
export interface FaultRetryBackstopDeps {
|
|
20
20
|
probeOnline?: () => Promise<boolean>;
|
|
21
21
|
/** Signal a node's broker; false when it holds no open signal stream. */
|
|
22
|
-
nudge?: (nodeId: string) => boolean
|
|
23
|
-
list?: () => PendingProviderRetry[]
|
|
24
|
-
busy?: (nodeId: string) => boolean
|
|
22
|
+
nudge?: (nodeId: string) => Promise<boolean>;
|
|
23
|
+
list?: () => Promise<PendingProviderRetry[]>;
|
|
24
|
+
busy?: (nodeId: string) => Promise<boolean>;
|
|
25
25
|
}
|
|
26
26
|
/** When the broker's timer should have fired: the recorded next attempt, else
|
|
27
27
|
* the policy delay after the fault was last (re)recorded as pending. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var A=Object.defineProperty;var
|
|
1
|
+
var A=Object.defineProperty;var o=(a,t)=>A(a,"name",{value:t,configurable:!0});import{filterAsync as g}from"../../core/async-array.js";import{listPendingProviderRetries as y,readLiveTurn as _}from"../../core/canvas/recovery.js";import{probeOnline as I}from"../../core/runtime/connectivity.js";import{nextFaultRetry as b}from"../../core/runtime/fault-recovery.js";import{emitEvent as f}from"../../core/events/emit.js";import{operationIdContext as p}from"../../core/events/operation-id.js";import{isSafeNodeId as R}from"../../core/canvas/paths.js";import{brokerSignalStreams as v}from"../api/handlers/broker-signals.js";const h=2*6e4,S=15e3;function m(a){const{fault:t}=a;if(t.retry.nextAt!==void 0){const i=Date.parse(t.retry.nextAt);return Number.isFinite(i)?i:null}const n=Date.parse(a.updatedAt),s=b(t,n);return Number.isFinite(n)&&s!==null?n+s.delayMs:null}o(m,"dueAtMs");class D{static{o(this,"FaultRetryBackstopReconciler")}deps;lastScanAt=Number.NEGATIVE_INFINITY;scanning=null;nudgedAt=new Map;constructor(t={}){this.deps=t}run(t,n){if(this.scanning!==null)return this.scanning;if(!n.lifecycle.acceptsDetachedWork()||t-this.lastScanAt<S)return Promise.resolve();this.lastScanAt=t;const s=this.scan(t,n).catch(i=>{p.fresh(()=>{f({level:"warn",event:"fault_retry_backstop.scan_failed",error:i})})}).finally(()=>{this.scanning=null});return this.scanning=s,n.lifecycle.registerDetached(s),s}async scan(t,n){const s=await(this.deps.list??y)(),i=new Set(s.map(e=>e.fault.faultId));for(const e of this.nudgedAt.keys())i.has(e)||this.nudgedAt.delete(e);const d=this.deps.busy??(async e=>(await _(e))?.busy===!0),u=await g(s,async e=>{if(!n.fleet.has(e.nodeId)||await d(e.nodeId))return!1;const r=m(e);if(r===null||t<r+h)return!1;const l=this.nudgedAt.get(e.fault.faultId);return l===void 0||t-l>=h});if(u.length===0)return;let c;for(const e of u){if(e.fault.kind==="connection"&&(c??=await(this.deps.probeOnline??(()=>I()))(),!c)||!n.fleet.has(e.nodeId)||await d(e.nodeId))continue;this.nudgedAt.set(e.fault.faultId,t);const r=await(this.deps.nudge??(async l=>await v.nudgeFaultRetry(l)))(e.nodeId);p.fresh(()=>{f({level:"info",event:"fault_retry_backstop.nudged",...R(e.nodeId)?{node_id:e.nodeId}:{},fields:{kind:e.fault.kind,since:e.fault.since,delivered:r,overdue_ms:t-(m(e)??t)}})})}}}export{S as FAULT_RETRY_SCAN_INTERVAL_MS,h as FAULT_RETRY_STALE_GRACE_MS,D as FaultRetryBackstopReconciler,m as dueAtMs};
|