@north-light/cli 0.3.530 → 0.3.531
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 +3 -3
- 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 +1 -1
- 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 +7 -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 +6 -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
package/dist/core/worktree.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
var
|
|
1
|
+
var Z=Object.defineProperty;var o=(e,r)=>Z(e,"name",{value:r,configurable:!0});import{existsSync as k,mkdirSync as P,readFileSync as ee,realpathSync as H,rmSync as te,writeFileSync as re}from"node:fs";import{createHash as ne}from"node:crypto";import{dirname as oe,isAbsolute as ae,join as se,relative as ie,resolve as N,sep as ce}from"node:path";import{gitAsync as he,gitSync as i}from"./git.js";import{crtrHome as C}from"./canvas/paths.js";import{closeWorktreeAndRepoint as ue,getNode as v,recordLandIntent as le}from"./canvas/index.js";import{CONFIG_FILE as de,CRTR_DIR_NAME as O,STATE_FILE as fe}from"../types.js";import{withExclusiveDirectoryLock as pe,withExclusiveDirectoryLockAsync as me}from"./exclusive-lock.js";import{parseStatusPorcelain as be,planLandIntoCheckout as ke,refDeleteTransactionStdin as _e}from"./worktree-landing.js";import{shellQuote as w}from"../shared/shell-quote.js";class f extends Error{static{o(this,"WorktreeError")}code;next;detail;constructor(r,t,n,a){super(t),this.name="WorktreeError",this.code=r,this.next=n,this.detail=a}}function _(e,r,t,n){const a=i(r,e);if(a.status!==0){const s=(a.stderr.trim()||a.stdout.trim()).trim();throw new f(t,`git ${r.join(" ")} failed`,n,s)}return a.stdout.trim()}o(_,"runGit");function F(){return`${C()}/worktrees`}o(F,"managedWorktreesRoot");function ge(e){return`${F()}/${e}`}o(ge,"managedWorktreePath");function Xe(e){return e?.managed_worktree?.state==="open"}o(Xe,"hasOpenManagedWorktree");async function x(e){const t=(await v(e))?.managed_worktree;return t?.state==="open"?t:null}o(x,"openManagedWorktreeForNode");function we(e){const r=i(["rev-parse","--show-toplevel"],e);if(r.status!==0){const t=(r.stderr.trim()||r.stdout.trim()).trim();throw new f("not_git_repo",`cwd ${e} is not a git repository`,"Pass --cwd <real repo> pointing inside a git repository.",t)}return r.stdout.trim()}o(we,"repoRootFor");function ye(e){const r=ie(E(F()),E(e));return r!==""&&r!==".."&&!r.startsWith(`..${ce}`)&&!ae(r)}o(ye,"isManagedWorktreeBase");function $e(e,r){const t=`refs/heads/${r}`,n=i(["show-ref","--verify","--quiet",t],e);if(n.status===0)return!0;if(n.status===1&&n.executionFailed!==!0)return!1;const a=n.stderr.trim()||"<empty>",s=n.processError===void 0?"":`
|
|
2
2
|
process error: ${n.processError}`;throw new f("recorded_branch_inspection_failed",`could not inspect recorded branch '${r}' (git show-ref exited with status ${n.status})`,"Inspect the repository and its Git metadata, then retry.",`status: ${n.status}
|
|
3
|
-
stderr: ${
|
|
3
|
+
stderr: ${a}${s}`)}o($e,"recordedBranchExists");function A(e,r){const t=`refs/heads/${r}`,n=i(["show-ref","--verify","--quiet",t],e);if(n.status===1&&n.executionFailed!==!0)throw new f("missing_base_branch",`managed worktree base '${r}' does not name an existing local branch`,"The base must be a local branch that landing can fast-forward \u2014 freshen your local branch from origin first (rebase-not-merge), then base on it.");if(n.status!==0){const a=n.stderr.trim()||"<empty>",s=n.processError===void 0?"":`
|
|
4
4
|
process error: ${n.processError}`;throw new f("base_branch_inspection_failed",`could not inspect local base branch '${r}' (git show-ref exited with status ${n.status})`,"Inspect the repository and its Git metadata, then retry.",`status: ${n.status}
|
|
5
|
-
stderr: ${
|
|
6
|
-
`))if(n.startsWith("worktree "))t=n.slice(9).trim();else if(n===`branch refs/heads/${r}`)return t;return null}
|
|
7
|
-
`))if(s.startsWith("worktree "))
|
|
5
|
+
stderr: ${a}${s}`)}return _(e,["rev-parse","--verify",t],"base_branch_resolve_failed","Inspect the local base branch, then retry.")}o(A,"resolveLandableBase");function ve(e,r){const t=_(e,["worktree","list","--porcelain"],"worktree_list_failed","Inspect the repository worktrees manually, then retry.");return I(t,r)}o(ve,"checkoutPathForBranch");function I(e,r){let t=null;for(const n of e.split(`
|
|
6
|
+
`))if(n.startsWith("worktree "))t=n.slice(9).trim();else if(n===`branch refs/heads/${r}`)return t;return null}o(I,"checkoutPathForBranchInList");function xe(e,r){return e===r||E(e)===E(r)}o(xe,"samePath");function E(e){try{return H.native(e)}catch{return N(e)}}o(E,"canonicalPath");const q=3e4;function G(e){const r=`${C()}/worktree-locks`;return P(r,{recursive:!0}),`${r}/${ne("sha256").update(e).digest("hex")}`}o(G,"worktreeLockPathForCommonDir");function S(e){const r=_(e,["rev-parse","--git-common-dir"],"git_common_dir_failed","Inspect the repository git metadata, then retry.");return H(N(e,r))}o(S,"commonGitDir");function B(e,r){const t=S(e);return pe(G(t),r,{timeoutMs:q,timeoutError:o(()=>new f("worktree_lock_timeout",`timed out waiting to create a managed worktree in ${t}`,"Wait for the other managed-worktree operation to finish, then retry."),"timeoutError")})}o(B,"withRepositoryWorktreeLock");async function j(e,r){const t=S(e);return me(G(t),r,{timeoutMs:q,timeoutError:o(()=>new f("worktree_lock_timeout",`timed out waiting to create a managed worktree in ${t}`,"Wait for the other managed-worktree operation to finish, then retry."),"timeoutError")})}o(j,"withRepositoryWorktreeLockAsync");function D(e,r,t){const n=i(["worktree","list","--porcelain"],e);if(n.status!==0)return null;let a=null;for(const s of n.stdout.split(`
|
|
7
|
+
`))if(s.startsWith("worktree "))a=s.slice(9).trim();else if(a!==null&&xe(a,r)&&s===`branch refs/heads/${t}`)return!0;return!1}o(D,"registeredWorktree");function Ee(e,r,t){const n=[],a=`refs/heads/${r}`,s=i(["rev-parse","--verify","--quiet",a],e);s.status===0&&n.push({ref:a,sha:s.stdout.trim()});const u=i(["rev-parse","--symbolic-full-name","--verify",`${r}@{upstream}`],e),h=u.status===0&&u.stdout.trim().startsWith("refs/")?u.stdout.trim():`refs/remotes/origin/${r}`,m=i(["rev-parse","--verify","--quiet",h],e);if(m.status===0&&n.push({ref:h,sha:m.stdout.trim()}),n.length===0)return null;for(const d of n)if(i(["merge-base","--is-ancestor",t,d.sha],e).status===0)return{containingRef:d.ref,containingSha:d.sha};for(const d of n){const l=i(["cherry",d.sha,t],e);if(l.status!==0)continue;if(l.stdout.split(`
|
|
8
8
|
`).map(c=>c.trim()).filter(c=>c!=="").every(c=>c.startsWith("-")))return{containingRef:d.ref,containingSha:d.sha}}for(const d of n){const l=i(["rev-parse","--verify",`${d.sha}^{tree}`],e);if(l.status!==0)continue;const b=i(["merge-tree","--write-tree",d.sha,t],e);if(b.status===0&&b.stdout.split(`
|
|
9
|
-
`)[0]?.trim()===l.stdout.trim())return{containingRef:d.ref,containingSha:d.sha}}return null}
|
|
10
|
-
`).map(h=>h.trim())),
|
|
9
|
+
`)[0]?.trim()===l.stdout.trim())return{containingRef:d.ref,containingSha:d.sha}}return null}o(Ee,"proveBranchContained");function K(e,r){const t=i(["rev-parse","--verify",`refs/heads/${e.branch}`],e.repo_root);if(t.status!==0||t.stdout.trim()!==e.base_sha)return;const n=D(e.repo_root,e.path,e.branch);if(n!==null){if(n){if(i(["worktree","remove","--force",e.path],e.repo_root).status!==0||D(e.repo_root,e.path,e.branch)!==!1)return}else if(r&&k(e.path))try{te(e.path,{recursive:!0,force:!0})}catch{return}try{i(["update-ref","-d",`refs/heads/${e.branch}`,e.base_sha],e.repo_root)}catch{}}}o(K,"rollbackManagedWorktreeLocked");function ze(e){B(e.repo_root,()=>K(e,!1))}o(ze,"rollbackManagedWorktree");const Se="# crtr: exclude crtr's own untracked project-scope bookkeeping (auto-added at managed-worktree creation)",De=[`/${O}/${de}`,`/${O}/${fe}`];function We(e){try{const r=se(S(e),"info","exclude");P(oe(r),{recursive:!0});let t="";try{t=ee(r,"utf8")}catch{}const n=new Set(t.split(`
|
|
10
|
+
`).map(h=>h.trim())),a=De.filter(h=>!n.has(h));if(a.length===0)return;const u=(t.length>0&&!t.endsWith(`
|
|
11
11
|
`)?`
|
|
12
|
-
`:"")+
|
|
13
|
-
`+
|
|
12
|
+
`:"")+Se+`
|
|
13
|
+
`+a.join(`
|
|
14
14
|
`)+`
|
|
15
|
-
`;
|
|
16
|
-
`).map(g=>g.trim()).filter(g=>g!==""),h=
|
|
17
|
-
${$}`}}a(Ae,"landIntoBaseCheckout");function K(e,r){const t=i(["rev-parse","--verify","--quiet","refs/stash"],e);t.status===0&&t.stdout.trim()===r&&i(["stash","drop"],e)}a(K,"dropStashIfStillTip");function T(e){const r=`git -C ${w(e.repo_root)} worktree remove ${w(e.path)}`;return{worktree_removed:!1,worktree_remove_error:`cleanup pending: the caller checkout at ${e.path} remains intact. After its node exits, run \`${r}\` after confirming it is safe to delete.`,branch_deleted:!1,branch_delete_error:`cleanup pending: local branch ${e.branch} remains checked out at ${e.path}; delete it only after that checkout is removed and its landed commit is still contained in ${e.base_ref}.`}}a(T,"deferredCleanupResult");function Re(e,r,t){if(D(r.repo_root,r.path,t)!==!0)throw new f("wrong_branch",`managed worktree's recorded branch ${r.branch} no longer exists, and its checkout at ${r.path} is not registered to ${t} either`,`Inspect ${r.path} and its git worktree registration, then ask the user with \`crtr human send\` if you are unsure how to proceed.`);const n=_(r.path,["rev-parse","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.");if(ve(r.path,r.base_ref,n)===null)throw new f("branch_moved_unlanded",`managed worktree's recorded branch ${r.branch} no longer exists; its checkout is now on ${t} at ${n}, which carries content local base branch '${r.base_ref}' does not yet contain`,`Land or push ${t} through its own workflow (merge its PR, or fast-forward '${r.base_ref}' to include it) before closing, or ask the user with \`crtr human send\` if you are unsure how ${t} should be delivered.`);const s=R(r.repo_root),u=D(r.repo_root,r.path,t)===!0,h=B(r.path)===t,m=_(r.path,["rev-parse","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.")===n;if(!u||!h||!m)throw new f("wrong_branch",`managed worktree at ${r.path} changed while closing`,`Inspect ${r.path}, then rerun \`crtr node worktree close\`.`);const d={observed_branch:t,observed_sha:n,common_dir:s,authorized:new Date().toISOString()};y(e,{...r,disposal:d},"pending");const l=`git -C ${w(r.repo_root)} worktree remove ${w(r.path)}`;return{node_id:e,branch:t,worktree_path:r.path,landed_sha:n,worktree_removed:!1,worktree_remove_error:`cleanup pending: the caller checkout at ${r.path} remains intact. After its node exits, run \`${l}\` after confirming it is safe to delete.`,branch_deleted:!1,branch_delete_error:`${t} is not a crtr-managed branch and will never be deleted automatically; it is preserved once the checkout above is removed.`}}a(Re,"closeBranchMovedWorktree");function Me(e,r){const t=v(e)?.managed_worktree;if(t==null)return{message:`node ${e} has no managed worktree`,next:`Nothing to ${r} for this node.`};if(t.state==="abandoned"){const n=t.abandoned?.branch??t.branch;return{message:`node ${e}'s managed worktree was already abandoned`,next:`Nothing to ${r} for this node; its work was retained on branch ${n}.`}}return t.state==="closed"?t.cleanup==="complete"?{message:`node ${e}'s managed worktree is already closed and its cleanup is complete`,next:`Nothing to ${r} for this node.`}:{message:`node ${e}'s managed worktree is already closed; this is not lost ownership \u2014 its checkout at ${t.path} is scheduled for automatic cleanup once that is safe`,next:`Nothing to ${r} for this node. The daemon sweep finishes removing ${t.path} on its own; inspect it directly only if it still needs manual attention.`}:{message:`node ${e} has no open managed worktree`,next:`Nothing to ${r} for this node.`}}a(Me,"noManagedWorktreeMessage");function U(e){if(v(e)===null)throw new f("unknown_node",`unknown node: ${e}`,"Run this from a live node, or pass a real node id once that command supports it.");const t=x(e);if(t===null){const{message:c,next:p}=Me(e,"close");throw new f("no_managed_worktree",c,p)}if(!k(t.path)){const c=P(t);if(c===null)throw new f("worktree_missing",`managed worktree path is missing: ${t.path}`,X(t));if(z(e,t,c)===null)throw new f("worktree_missing",`managed worktree path is missing: ${t.path}`,X(t));return{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:c.branchSha??t.base_sha,worktree_removed:!0,branch_deleted:!0}}if(M(t.path))throw new f("rebase_in_progress","this managed worktree is mid-rebase",`Resolve conflicts in ${t.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`.`);if(De(t.path)!=="")throw new f("dirty_worktree","managed worktree has uncommitted changes",`Commit the work in ${t.path} (or ask the user with \`crtr human send\` if you do not know whether to keep it), then rerun \`crtr node worktree close\`.`);const o=B(t.path);if(o!==t.branch){const c=o==="HEAD"?"detached HEAD":o,p=_e(t.path,t.branch);if(p||o==="HEAD")throw new f("wrong_branch",`managed worktree is not on its recorded branch (expected ${t.branch}, found ${c})`,p?`Check out ${t.branch} in ${t.path} before closing, or ask the user with \`crtr human send\` if you are unsure why it changed, then rerun \`crtr node worktree close\`.`:`The recorded branch ${t.branch} no longer exists, and ${t.path} is in detached HEAD, so there is no branch to preserve. Check out or create a branch there before closing, or ask the user with \`crtr human send\` if you are unsure how to proceed.`);return Re(e,t,o)}let s;try{s=A(t.path,t.base_ref)}catch(c){const p=_(t.path,["rev-parse","HEAD"],"landed_sha_failed","Inspect the worktree checkout manually, then rerun `crtr node worktree close`.");if(!(c instanceof f)||c.code!=="missing_base_branch"||p!==t.base_sha)throw c;return y(e,t,"pending"),{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:t.base_sha,...T(t)}}const u=i(["rebase",s],t.path);if(u.status!==0){const c=(u.stderr.trim()||u.stdout.trim()).trim();throw new f("rebase_failed",`rebase onto local base branch '${t.base_ref}' did not complete`,`Resolve conflicts in ${t.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`. If the blocker is not mechanical, ask the user with \`crtr human send\`.`,c)}const h=_(t.path,["rev-parse","HEAD"],"landed_sha_failed","Inspect the worktree checkout manually, then rerun `crtr node worktree close`."),m=a((c,p,$)=>(We(e,c),new f("land_base_failed",c,p,$)),"blocked"),d=i(["merge-base","--is-ancestor",s,h],t.path);if(d.status!==0)throw m(`rebased worktree is not a fast-forward of local base branch '${t.base_ref}'`,"Ask the user with `crtr human send` how to land this managed worktree.",(d.stderr.trim()||d.stdout.trim()).trim());const l=ge(t.path,t.base_ref);if(l!==null){const c=i(["rev-parse","HEAD"],l),p=c.stdout.trim();if(c.status!==0||p!==s){const $=c.status!==0?(c.stderr.trim()||p).trim():`expected ${s}, found ${p}`;throw m(`local base branch '${t.base_ref}' changed while this worktree was closing`,`Reconcile the base checkout at ${l}, then rerun \`crtr node worktree close\`. If you are unsure, ask the user with \`crtr human send\`.`,$)}}let b;if(l!==null){const c=Ae(l,t.branch,s,h);if(!c.ok)throw m(`could not fast-forward local base branch '${t.base_ref}' to this worktree`,`Local base branch '${t.base_ref}' is checked out at ${l} in a state that blocks a fast-forward. Reconcile it there, then rerun \`crtr node worktree close\`. If you are unsure, ask the user with \`crtr human send\`.`,c.detail);b=c.stash}else{const c=i(["update-ref",`refs/heads/${t.base_ref}`,h,s],t.path);if(c.status!==0)throw m(`could not fast-forward local base branch '${t.base_ref}' to this worktree`,"Ask the user with `crtr human send` how to land this managed worktree.",(c.stderr.trim()||c.stdout.trim()).trim())}return y(e,t,"pending"),{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:h,...T(t),...b===void 0?{}:{base_checkout_stash:b}}}a(U,"closeManagedWorktreeLocked");function ze(e){const r=x(e);return r===null?U(e):E(k(r.path)?r.path:r.repo_root,()=>U(e))}a(ze,"closeManagedWorktree");function Te(e,r,t,n){const o=pe(e.branch,r,t,n),s=i(["update-ref","--stdin"],e.repo_root,o),u=s.status===0;if(u)return{branchDeleted:u};const h=(s.stderr.trim()||s.stdout.trim()).trim();return{branchDeleted:u,branchDeleteError:`local branch ${e.branch} could not be deleted automatically (${h}); run \`git -C ${w(e.repo_root)} branch -D ${w(e.branch)}\` after confirming it is merged.`}}a(Te,"bestEffortDeleteBranchWithContainmentProof");function P(e){if(e.state!=="open"||k(e.path))return null;const r=`refs/heads/${e.branch}`,t=i(["show-ref","--verify","--quiet",r],e.repo_root);if(t.status===1)return{branchSha:null};if(t.status!==0)return null;const n=i(["rev-parse","--verify",r],e.repo_root);if(n.status!==0)return null;const o=n.stdout.trim(),s=i(["worktree","list","--porcelain"],e.repo_root);if(s.status!==0||q(s.stdout,e.branch)!==null)return null;const u=[],h=`refs/heads/${e.base_ref}`,m=i(["show-ref","--verify","--quiet",h],e.repo_root);if(m.status===0){const l=i(["rev-parse","--verify",h],e.repo_root);if(l.status!==0)return null;u.push({ref:h,sha:l.stdout.trim()})}else if(m.status!==1)return null;const d=i(["rev-parse","--symbolic-full-name","--verify",`${e.base_ref}@{upstream}`],e.repo_root);if(d.status===0){const l=d.stdout.trim(),b=i(["rev-parse","--verify",l],e.repo_root);l.startsWith("refs/")&&b.status===0&&u.push({ref:l,sha:b.stdout.trim()})}else{const l=`refs/remotes/origin/${e.base_ref}`,b=i(["show-ref","--verify","--quiet",l],e.repo_root);if(b.status===0){const c=i(["rev-parse","--verify",l],e.repo_root);c.status===0&&u.push({ref:l,sha:c.stdout.trim()})}else if(b.status!==1)return null}for(const l of u)if(i(["merge-base","--is-ancestor",o,l.sha],e.repo_root).status===0)return{branchSha:o,containingRef:l.ref,containingSha:l.sha};return null}a(P,"proveAbsentPathManagedWorktree");function X(e){return`The recorded checkout path is gone, but crtr cannot prove ${e.branch} is already delivered. Push or land ${e.branch}, then rerun \`crtr push final\`; if you cannot establish what happened to the branch, ask the user with \`crtr human send\`.`}a(X,"missingWorktreeRecoveryHint");function L(e){if(e.state!=="open"||!k(e.path)||M(e.path))return null;const r=i(["rev-parse","--abbrev-ref","HEAD"],e.path);if(r.status!==0||r.stdout.trim()!==e.branch)return null;const t=i(["status","--porcelain"],e.path);if(t.status!==0||t.stdout.trim()!=="")return null;const n=i(["rev-parse","HEAD"],e.path);if(n.status!==0)return null;const o=n.stdout.trim();let s;try{s=A(e.path,e.base_ref)}catch(h){if(h instanceof f&&h.code==="missing_base_branch"&&o===e.base_sha)return{branchSha:o,baseSha:e.base_sha};throw h}return i(["merge-base","--is-ancestor",o,s],e.path).status!==0?null:{branchSha:o,baseSha:s}}a(L,"proveCleanEmptyManagedWorktree");function z(e,r,t){if(k(r.path))return null;if(t.branchSha===null)return y(e,r,"complete"),{node_id:e,branch:r.branch,worktree_path:r.path,worktree_removed:!0,branch_deleted:!0};if(t.containingRef===void 0||t.containingSha===void 0)return null;const{branchDeleted:n}=Te(r,t.branchSha,t.containingRef,t.containingSha);return n?(y(e,r,"complete"),{node_id:e,branch:r.branch,worktree_path:r.path,worktree_removed:!0,branch_deleted:!0}):null}a(z,"autoDropAbsentPathManagedWorktreeLocked");function Pe(e,r,t){const n=L(r);return n===null||n.branchSha!==t.branchSha?null:(y(e,r,"pending"),{node_id:e,branch:r.branch,worktree_path:r.path,...T(r)})}a(Pe,"autoDropCleanManagedWorktreeLocked");function Q(e){if(e.state!=="open"||!k(e.path)||M(e.path))return null;const r=i(["status","--porcelain"],e.path);if(r.status!==0||r.stdout.trim()!=="")return null;const t=i(["rev-parse","HEAD"],e.path);return t.status===0?t.stdout.trim():null}a(Q,"cleanCurrentCheckoutTip");async function Qe(e){const r=Q(e);if(r===null)return!1;const t=process.env.GIT_SSH_COMMAND??process.env.GIT_SSH??"ssh",n=await ae(["ls-remote","--exit-code","--heads","origin"],e.path,void 0,{timeoutMs:1e4,env:{...process.env,GIT_TERMINAL_PROMPT:"0",GIT_SSH_COMMAND:`${t} -o BatchMode=yes`}});return n.status!==0||!n.stdout.split(`
|
|
18
|
-
`).some(s=>{const[u,h]=s.split(" ",2);return u===r&&h?.startsWith("refs/heads/")===!0})?!1:
|
|
15
|
+
`;re(r,t+u)}catch{}}o(We,"seedManagedWorktreeExclude");function Qe(e,r,t="main"){const n=we(e);if(ye(n))throw new f("managed_worktree_base",`cwd ${n} is a managed worktree and cannot be used as a managed worktree base`,"Pass `--cwd` pointing at the repository\u2019s primary checkout and keep `--worktree` set to the desired existing local base branch, including the parent branch.");return B(n,()=>{const a=A(n,t),s=ge(r),u=`crtr/${r}`;if(k(s))throw new f("worktree_path_exists",`managed worktree path already exists: ${s}`,"Remove the stale path or choose a fresh node id.");if(i(["show-ref","--verify","--quiet",`refs/heads/${u}`],n).status===0)throw new f("worktree_branch_exists",`managed worktree branch already exists: ${u}`,"Remove the stale branch or choose a fresh node id.");const h={state:"open",path:s,branch:u,repo_root:n,base_ref:t,base_sha:a,created:new Date().toISOString()};_(n,["branch",u,a],"worktree_branch_create_failed","Inspect the git error, fix the repository/worktree state, then retry spawning with --worktree.");try{return _(n,["worktree","add",s,u],"worktree_add_failed","Inspect the git error, fix the repository/worktree state, then retry spawning with --worktree."),We(n),h}catch(m){throw K(h,!0),m}})}o(Qe,"createManagedWorktree");function Ae(e){return _(e,["status","--porcelain"],"status_failed","Inspect the worktree manually, then retry.")}o(Ae,"statusPorcelain");function U(e){return _(e,["rev-parse","--abbrev-ref","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.")}o(U,"currentBranch");function X(e,r){return _(e,["rev-parse","--git-path",r],"git_path_failed","Inspect the worktree manually, then retry.")}o(X,"gitPath");function R(e){return k(X(e,"rebase-merge"))||k(X(e,"rebase-apply"))}o(R,"isRebaseInProgress");async function $(e,r,t="pending"){const n=await v(e);await ue(e,{cwd:r.repo_root,cleanup:t,closedAt:new Date().toISOString(),unbindSession:n?.pi_session_id!=null||n?.pi_session_file!=null})}o($,"persistClosedWorktreeState");async function Re(e,r){const t=(await v(e))?.managed_worktree;t==null||t.state!=="open"||await le(e,{at:new Date().toISOString(),blocked:r})}o(Re,"recordBlockedLandIntent");function Me(e,r,t,n){const a=i(["status","--porcelain"],e);if(a.status!==0)return{ok:!1,detail:(a.stderr.trim()||a.stdout.trim()).trim()};const s=i(["diff","--name-only",t,n],e);if(s.status!==0)return{ok:!1,detail:(s.stderr.trim()||s.stdout.trim()).trim()};const u=s.stdout.split(`
|
|
16
|
+
`).map(g=>g.trim()).filter(g=>g!==""),h=ke(be(a.stdout),u);if(h.kind==="refuse")return{ok:!1,detail:`untracked files in ${e} would be overwritten by the incoming commits: ${h.collisions.join(", ")}`};const m=o(()=>{const g=i(["merge","--ff-only",n],e);return g.status===0?{ok:!0}:{ok:!1,detail:(g.stderr.trim()||g.stdout.trim()).trim()}},"merge");if(h.kind==="direct")return m();const d=i(["rev-parse","--verify","--quiet","refs/stash"],e),l=d.status===0?d.stdout.trim():null,b=i(["stash","push","--message",`crtr landing ${r}`],e);if(b.status!==0)return{ok:!1,detail:(b.stderr.trim()||b.stdout.trim()).trim()};const c=i(["rev-parse","--verify","--quiet","refs/stash"],e),p=c.status===0?c.stdout.trim():null;if(p===null||p===l)return m();const y=`local changes from ${e} are retained in stash ${p}; recover them with \`git -C ${w(e)} stash apply ${p}\` and resolve any conflict.`,W=m();return W.ok?i(["stash","apply",p],e).status===0?(z(e,p),{ok:!0}):(i(["reset","--hard",n],e),{ok:!0,stash:`the shared base checkout was reset to landed commit ${n} because local changes conflicted with it. ${y}`}):i(["stash","apply",p],e).status===0?(z(e,p),W):{ok:!1,detail:`${W.detail}
|
|
17
|
+
${y}`}}o(Me,"landIntoBaseCheckout");function z(e,r){const t=i(["rev-parse","--verify","--quiet","refs/stash"],e);t.status===0&&t.stdout.trim()===r&&i(["stash","drop"],e)}o(z,"dropStashIfStillTip");function M(e){const r=`git -C ${w(e.repo_root)} worktree remove ${w(e.path)}`;return{worktree_removed:!1,worktree_remove_error:`cleanup pending: the caller checkout at ${e.path} remains intact. After its node exits, run \`${r}\` after confirming it is safe to delete.`,branch_deleted:!1,branch_delete_error:`cleanup pending: local branch ${e.branch} remains checked out at ${e.path}; delete it only after that checkout is removed and its landed commit is still contained in ${e.base_ref}.`}}o(M,"deferredCleanupResult");async function Le(e,r,t){if(D(r.repo_root,r.path,t)!==!0)throw new f("wrong_branch",`managed worktree's recorded branch ${r.branch} no longer exists, and its checkout at ${r.path} is not registered to ${t} either`,`Inspect ${r.path} and its git worktree registration, then ask the user with \`crtr human send\` if you are unsure how to proceed.`);const n=_(r.path,["rev-parse","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.");if(Ee(r.path,r.base_ref,n)===null)throw new f("branch_moved_unlanded",`managed worktree's recorded branch ${r.branch} no longer exists; its checkout is now on ${t} at ${n}, which carries content local base branch '${r.base_ref}' does not yet contain`,`Land or push ${t} through its own workflow (merge its PR, or fast-forward '${r.base_ref}' to include it) before closing, or ask the user with \`crtr human send\` if you are unsure how ${t} should be delivered.`);const s=S(r.repo_root),u=D(r.repo_root,r.path,t)===!0,h=U(r.path)===t,m=_(r.path,["rev-parse","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.")===n;if(!u||!h||!m)throw new f("wrong_branch",`managed worktree at ${r.path} changed while closing`,`Inspect ${r.path}, then rerun \`crtr node worktree close\`.`);const d={observed_branch:t,observed_sha:n,common_dir:s,authorized:new Date().toISOString()};await $(e,{...r,disposal:d},"pending");const l=`git -C ${w(r.repo_root)} worktree remove ${w(r.path)}`;return{node_id:e,branch:t,worktree_path:r.path,landed_sha:n,worktree_removed:!1,worktree_remove_error:`cleanup pending: the caller checkout at ${r.path} remains intact. After its node exits, run \`${l}\` after confirming it is safe to delete.`,branch_deleted:!1,branch_delete_error:`${t} is not a crtr-managed branch and will never be deleted automatically; it is preserved once the checkout above is removed.`}}o(Le,"closeBranchMovedWorktree");async function Te(e,r){const t=(await v(e))?.managed_worktree;if(t==null)return{message:`node ${e} has no managed worktree`,next:`Nothing to ${r} for this node.`};if(t.state==="abandoned"){const n=t.abandoned?.branch??t.branch;return{message:`node ${e}'s managed worktree was already abandoned`,next:`Nothing to ${r} for this node; its work was retained on branch ${n}.`}}return t.state==="closed"?t.cleanup==="complete"?{message:`node ${e}'s managed worktree is already closed and its cleanup is complete`,next:`Nothing to ${r} for this node.`}:{message:`node ${e}'s managed worktree is already closed; this is not lost ownership \u2014 its checkout at ${t.path} is scheduled for automatic cleanup once that is safe`,next:`Nothing to ${r} for this node. The daemon sweep finishes removing ${t.path} on its own; inspect it directly only if it still needs manual attention.`}:{message:`node ${e} has no open managed worktree`,next:`Nothing to ${r} for this node.`}}o(Te,"noManagedWorktreeMessage");async function Q(e){if(await v(e)===null)throw new f("unknown_node",`unknown node: ${e}`,"Run this from a live node, or pass a real node id once that command supports it.");const t=await x(e);if(t===null){const{message:c,next:p}=await Te(e,"close");throw new f("no_managed_worktree",c,p)}if(!k(t.path)){const c=L(t);if(c===null)throw new f("worktree_missing",`managed worktree path is missing: ${t.path}`,J(t));if(await V(e,t,c)===null)throw new f("worktree_missing",`managed worktree path is missing: ${t.path}`,J(t));return{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:c.branchSha??t.base_sha,worktree_removed:!0,branch_deleted:!0}}if(R(t.path))throw new f("rebase_in_progress","this managed worktree is mid-rebase",`Resolve conflicts in ${t.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`.`);if(Ae(t.path)!=="")throw new f("dirty_worktree","managed worktree has uncommitted changes",`Commit the work in ${t.path} (or ask the user with \`crtr human send\` if you do not know whether to keep it), then rerun \`crtr node worktree close\`.`);const a=U(t.path);if(a!==t.branch){const c=a==="HEAD"?"detached HEAD":a,p=$e(t.path,t.branch);if(p||a==="HEAD")throw new f("wrong_branch",`managed worktree is not on its recorded branch (expected ${t.branch}, found ${c})`,p?`Check out ${t.branch} in ${t.path} before closing, or ask the user with \`crtr human send\` if you are unsure why it changed, then rerun \`crtr node worktree close\`.`:`The recorded branch ${t.branch} no longer exists, and ${t.path} is in detached HEAD, so there is no branch to preserve. Check out or create a branch there before closing, or ask the user with \`crtr human send\` if you are unsure how to proceed.`);return await Le(e,t,a)}let s;try{s=A(t.path,t.base_ref)}catch(c){const p=_(t.path,["rev-parse","HEAD"],"landed_sha_failed","Inspect the worktree checkout manually, then rerun `crtr node worktree close`.");if(!(c instanceof f)||c.code!=="missing_base_branch"||p!==t.base_sha)throw c;return await $(e,t,"pending"),{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:t.base_sha,...M(t)}}const u=i(["rebase",s],t.path);if(u.status!==0){const c=(u.stderr.trim()||u.stdout.trim()).trim();throw new f("rebase_failed",`rebase onto local base branch '${t.base_ref}' did not complete`,`Resolve conflicts in ${t.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`. If the blocker is not mechanical, ask the user with \`crtr human send\`.`,c)}const h=_(t.path,["rev-parse","HEAD"],"landed_sha_failed","Inspect the worktree checkout manually, then rerun `crtr node worktree close`."),m=o(async(c,p,y)=>(await Re(e,c),new f("land_base_failed",c,p,y)),"blocked"),d=i(["merge-base","--is-ancestor",s,h],t.path);if(d.status!==0)throw await m(`rebased worktree is not a fast-forward of local base branch '${t.base_ref}'`,"Ask the user with `crtr human send` how to land this managed worktree.",(d.stderr.trim()||d.stdout.trim()).trim());const l=ve(t.path,t.base_ref);if(l!==null){const c=i(["rev-parse","HEAD"],l),p=c.stdout.trim();if(c.status!==0||p!==s){const y=c.status!==0?(c.stderr.trim()||p).trim():`expected ${s}, found ${p}`;throw await m(`local base branch '${t.base_ref}' changed while this worktree was closing`,`Reconcile the base checkout at ${l}, then rerun \`crtr node worktree close\`. If you are unsure, ask the user with \`crtr human send\`.`,y)}}let b;if(l!==null){const c=Me(l,t.branch,s,h);if(!c.ok)throw await m(`could not fast-forward local base branch '${t.base_ref}' to this worktree`,`Local base branch '${t.base_ref}' is checked out at ${l} in a state that blocks a fast-forward. Reconcile it there, then rerun \`crtr node worktree close\`. If you are unsure, ask the user with \`crtr human send\`.`,c.detail);b=c.stash}else{const c=i(["update-ref",`refs/heads/${t.base_ref}`,h,s],t.path);if(c.status!==0)throw await m(`could not fast-forward local base branch '${t.base_ref}' to this worktree`,"Ask the user with `crtr human send` how to land this managed worktree.",(c.stderr.trim()||c.stdout.trim()).trim())}return await $(e,t,"pending"),{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:h,...M(t),...b===void 0?{}:{base_checkout_stash:b}}}o(Q,"closeManagedWorktreeLocked");async function Je(e){const r=await x(e);return r===null?await Q(e):await j(k(r.path)?r.path:r.repo_root,async()=>await Q(e))}o(Je,"closeManagedWorktree");function Pe(e,r,t,n){const a=_e(e.branch,r,t,n),s=i(["update-ref","--stdin"],e.repo_root,a),u=s.status===0;if(u)return{branchDeleted:u};const h=(s.stderr.trim()||s.stdout.trim()).trim();return{branchDeleted:u,branchDeleteError:`local branch ${e.branch} could not be deleted automatically (${h}); run \`git -C ${w(e.repo_root)} branch -D ${w(e.branch)}\` after confirming it is merged.`}}o(Pe,"bestEffortDeleteBranchWithContainmentProof");function L(e){if(e.state!=="open"||k(e.path))return null;const r=`refs/heads/${e.branch}`,t=i(["show-ref","--verify","--quiet",r],e.repo_root);if(t.status===1)return{branchSha:null};if(t.status!==0)return null;const n=i(["rev-parse","--verify",r],e.repo_root);if(n.status!==0)return null;const a=n.stdout.trim(),s=i(["worktree","list","--porcelain"],e.repo_root);if(s.status!==0||I(s.stdout,e.branch)!==null)return null;const u=[],h=`refs/heads/${e.base_ref}`,m=i(["show-ref","--verify","--quiet",h],e.repo_root);if(m.status===0){const l=i(["rev-parse","--verify",h],e.repo_root);if(l.status!==0)return null;u.push({ref:h,sha:l.stdout.trim()})}else if(m.status!==1)return null;const d=i(["rev-parse","--symbolic-full-name","--verify",`${e.base_ref}@{upstream}`],e.repo_root);if(d.status===0){const l=d.stdout.trim(),b=i(["rev-parse","--verify",l],e.repo_root);l.startsWith("refs/")&&b.status===0&&u.push({ref:l,sha:b.stdout.trim()})}else{const l=`refs/remotes/origin/${e.base_ref}`,b=i(["show-ref","--verify","--quiet",l],e.repo_root);if(b.status===0){const c=i(["rev-parse","--verify",l],e.repo_root);c.status===0&&u.push({ref:l,sha:c.stdout.trim()})}else if(b.status!==1)return null}for(const l of u)if(i(["merge-base","--is-ancestor",a,l.sha],e.repo_root).status===0)return{branchSha:a,containingRef:l.ref,containingSha:l.sha};return null}o(L,"proveAbsentPathManagedWorktree");function J(e){return`The recorded checkout path is gone, but crtr cannot prove ${e.branch} is already delivered. Push or land ${e.branch}, then rerun \`crtr push final\`; if you cannot establish what happened to the branch, ask the user with \`crtr human send\`.`}o(J,"missingWorktreeRecoveryHint");function T(e){if(e.state!=="open"||!k(e.path)||R(e.path))return null;const r=i(["rev-parse","--abbrev-ref","HEAD"],e.path);if(r.status!==0||r.stdout.trim()!==e.branch)return null;const t=i(["status","--porcelain"],e.path);if(t.status!==0||t.stdout.trim()!=="")return null;const n=i(["rev-parse","HEAD"],e.path);if(n.status!==0)return null;const a=n.stdout.trim();let s;try{s=A(e.path,e.base_ref)}catch(h){if(h instanceof f&&h.code==="missing_base_branch"&&a===e.base_sha)return{branchSha:a,baseSha:e.base_sha};throw h}return i(["merge-base","--is-ancestor",a,s],e.path).status!==0?null:{branchSha:a,baseSha:s}}o(T,"proveCleanEmptyManagedWorktree");async function V(e,r,t){if(k(r.path))return null;if(t.branchSha===null)return await $(e,r,"complete"),{node_id:e,branch:r.branch,worktree_path:r.path,worktree_removed:!0,branch_deleted:!0};if(t.containingRef===void 0||t.containingSha===void 0)return null;const{branchDeleted:n}=Pe(r,t.branchSha,t.containingRef,t.containingSha);return n?(await $(e,r,"complete"),{node_id:e,branch:r.branch,worktree_path:r.path,worktree_removed:!0,branch_deleted:!0}):null}o(V,"autoDropAbsentPathManagedWorktreeLocked");async function He(e,r,t){const n=T(r);return n===null||n.branchSha!==t.branchSha?null:(await $(e,r,"pending"),{node_id:e,branch:r.branch,worktree_path:r.path,...M(r)})}o(He,"autoDropCleanManagedWorktreeLocked");function Y(e){if(e.state!=="open"||!k(e.path)||R(e.path))return null;const r=i(["status","--porcelain"],e.path);if(r.status!==0||r.stdout.trim()!=="")return null;const t=i(["rev-parse","HEAD"],e.path);return t.status===0?t.stdout.trim():null}o(Y,"cleanCurrentCheckoutTip");async function Ve(e){const r=Y(e);if(r===null)return!1;const t=process.env.GIT_SSH_COMMAND??process.env.GIT_SSH??"ssh",n=await he(["ls-remote","--exit-code","--heads","origin"],e.path,void 0,{timeoutMs:1e4,env:{...process.env,GIT_TERMINAL_PROMPT:"0",GIT_SSH_COMMAND:`${t} -o BatchMode=yes`}});return n.status!==0||!n.stdout.split(`
|
|
18
|
+
`).some(s=>{const[u,h]=s.split(" ",2);return u===r&&h?.startsWith("refs/heads/")===!0})?!1:Y(e)===r}o(Ve,"branchIsPushedAtCurrentTip");async function Ye(e){const r=await x(e);if(r===null)return null;const t=!k(r.path);return(t?L(r)===null:T(r)===null)?null:await j(t?r.repo_root:r.path,async()=>{const n=await x(e);if(n===null)return null;if(!k(n.path)){const s=L(n);return s===null?null:await V(e,n,s)}const a=T(n);return a===null?null:await He(e,n,a)})}o(Ye,"autoDropCleanManagedWorktree");export{q as WORKTREE_LOCK_WAIT_MS,f as WorktreeError,Ye as autoDropCleanManagedWorktree,He as autoDropCleanManagedWorktreeLocked,Ve as branchIsPushedAtCurrentTip,I as checkoutPathForBranchInList,Je as closeManagedWorktree,Qe as createManagedWorktree,Xe as hasOpenManagedWorktree,ye as isManagedWorktreeBase,R as isRebaseInProgress,ge as managedWorktreePath,F as managedWorktreesRoot,J as missingWorktreeRecoveryHint,x as openManagedWorktreeForNode,$ as persistClosedWorktreeState,T as proveCleanEmptyManagedWorktree,ze as rollbackManagedWorktree,xe as samePath,G as worktreeLockPathForCommonDir};
|
|
@@ -29,9 +29,9 @@ export interface ComputeInput {
|
|
|
29
29
|
agents: AgentInput[];
|
|
30
30
|
scan: (input: ScanInput) => Promise<ScanResult>;
|
|
31
31
|
/** Throws when the memory-read log cannot be read. */
|
|
32
|
-
memory: (fromIso: string, toIso: string) => {
|
|
32
|
+
memory: (fromIso: string, toIso: string) => Promise<{
|
|
33
33
|
rows: MemoryReadInput[];
|
|
34
34
|
startedAt: string | null;
|
|
35
|
-
}
|
|
35
|
+
}>;
|
|
36
36
|
}
|
|
37
37
|
export declare function computeAnalytics(input: ComputeInput): Promise<AnalyticsDTO>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var L=Object.defineProperty;var u=(o,_)=>L(o,"name",{value:_,configurable:!0});const oe=36e5,Q={"24h":864e5,"7d":6048e5};function b(o,_){return o[Math.max(0,Math.ceil(_/100*o.length)-1)]}u(b,"rank");function P(o){const _=[...o].sort((g,h)=>g-h);return{count:_.length,p10_ms:b(_,10),median_ms:b(_,50),p90_ms:b(_,90),max_ms:_[_.length-1]}}u(P,"stats");const C=u(o=>o.input+o.output+o.cache_read+o.cache_write,"tokensOf"),X=u(o=>o.input+o.cache_read+o.cache_write,"contextOf"),y=u(o=>`${o.provider}\0${o.model}`,"modelKey");function v(o,_,g){const h=o.get(_);h?h.push(g):o.set(_,[g])}u(v,"push");const W=u(o=>o instanceof Error?o.message:String(o),"reason");function Y(o){const _=new Map(o.map(i=>[i.node_id,i])),g=new Map,h=u((i,w)=>{const p=g.get(i.node_id);if(p)return p;const l=i.parent===null?void 0:_.get(i.parent);let f;const r={a:i,createdMs:Date.parse(i.created),finMs:i.finalized_at===null?null:Date.parse(i.finalized_at)};if(!l||w.has(l.node_id)){if(l)throw new Error(`parent cycle through node ${i.node_id}`);f={...r,graph:i.node_id,parent:null,depth:0}}else{w.add(i.node_id);const t=h(l,w);f={...r,graph:t.graph,parent:l.node_id,depth:t.depth+1}}return g.set(i.node_id,f),f},"place");for(const i of o)h(i,new Set);return g}u(Y,"placeAgents");async function ae(o){const _=o.asOfMs,g=_-Q[o.window],h=u(e=>e!==null&&e>=g&&e<_,"inW"),i=Y(o.agents),w=u(e=>i.get(e.graph),"rootOf"),p=u(e=>w(e).a.cwd,"projectOf"),l=new Map;for(const e of i.values()){const a=p(e);v(l,a,e)}let f=null,r="";try{const e=[...l.keys()],a=await Promise.all(e.map(m=>o.scan({nodes:l.get(m).map(S=>({node_id:S.a.node_id,created:S.a.created,transcripts:S.a.transcripts})),windowStartMs:g,asOfMs:_})));f=new Map(e.map((m,S)=>[m,a[S]]))}catch(e){r=`transcript scan failed: ${W(e)}`}const t=new Map;for(const e of f?.values()??[])for(const a of e.responses)v(t,a.node_id,a);const c=u(e=>(t.get(e)??[]).reduce((a,m)=>a+m.cost,0),"priceOf"),s=u(e=>(t.get(e)??[]).reduce((a,m)=>a+C(m),0),"tokensOfAgent"),n=new Map;for(const e of f?.values()??[]){for(const a of e.responses)v(n,a.node_id,a.at_ms);for(const a of e.unknown_at)v(n,a.node_id,a.at_ms)}const d=u(e=>(n.get(e)?.length??0)>0,"isActive"),k=new Map,A=new Set;for(const e of i.values()){if(!d(e.a.node_id))continue;const a=p(e);A.add(a),k.set(a,(k.get(a)??0)+c(e.a.node_id))}const T=[...A].map(e=>({cwd:e,api_price_estimate:k.get(e)??0})).sort((e,a)=>a.api_price_estimate-e.api_price_estimate||e.cwd.localeCompare(a.cwd)),M=[...i.values()].filter(e=>o.project===null||p(e)===o.project),F=new Set(M.map(e=>e.a.node_id)),j=u(e=>e.parent!==null&&h(e.createdMs),"spawned"),z=u(e=>h(e.finMs),"finished"),D=new Set,I=new Set,R=u((e,a)=>{for(let m=e;m&&!a.has(m.a.node_id);m=m.parent===null?void 0:i.get(m.parent))a.add(m.a.node_id)},"climb");for(const e of M)d(e.a.node_id)&&R(e,D),(d(e.a.node_id)||j(e)||z(e))&&R(e,I);const N=M.filter(e=>I.has(e.a.node_id)).map(e=>({node_id:e.a.node_id,name:e.a.name,kind:e.a.kind,graph_id:e.graph,in_graph_detail:D.has(e.a.node_id),parent:e.parent,depth:e.depth,created:e.a.created,finalized_at:e.a.finalized_at,lifecycle:e.a.lifecycle,active:d(e.a.node_id),spawned_in_window:j(e),finished_in_window:z(e),agent_time_ms:e.finMs===null?null:e.finMs-e.createdMs,api_price_estimate:c(e.a.node_id),tokens:s(e.a.node_id),responses:n.get(e.a.node_id)?.length??0,response_times_ms:[...n.get(e.a.node_id)??[]].sort((a,m)=>a-m),final_report_ref:e.a.final_report?`${e.a.node_id}:reports/${e.a.final_report}`:null})).sort((e,a)=>e.created.localeCompare(a.created)||e.node_id.localeCompare(a.node_id)),V=M.reduce((e,a)=>e===null||a.a.created<e?a.a.created:e,null),q=M.flatMap(e=>(n.get(e.a.node_id)??[]).map(a=>({node_id:e.a.node_id,at_ms:a}))),x=M.filter(e=>d(e.a.node_id)).length;let H=null,U=null;if(f){const e=[...f.entries()].filter(([a])=>o.project===null||a===o.project).map(([,a])=>a);H={total:e.reduce((a,m)=>a+m.transcripts.total,0),read:e.reduce((a,m)=>a+m.transcripts.read,0),unreadable:e.flatMap(a=>a.transcripts.unreadable)},U=e.reduce((a,m)=>a+m.unknown,0)}const O=u(()=>({ok:!1,reason:r}),"fail"),B=f?{ok:!0,value:Z(M,i,d,c,s,j)}:O(),G=f?{ok:!0,value:ee(M,z,q,o.window,_)}:O(),J=f?{ok:!0,value:te(M,t)}:O();let $,K=null;try{const e=o.memory(new Date(g).toISOString(),new Date(_).toISOString());K=e.startedAt;const a=e.rows.filter(m=>F.has(m.node_id));$=f?{ok:!0,value:{read:E(a.filter(m=>m.type==="read"),i,x,d),loaded:E(a.filter(m=>m.type==="loaded"),i,x,d)}}:O()}catch(e){$={ok:!1,reason:`memory-read log unavailable: ${W(e)}`}}return{as_of:new Date(_).toISOString(),window_start:new Date(g).toISOString(),window:o.window,project:o.project,projects:T,transcripts:H,unknown_responses:U,oldest_agent_created:V,memory_log_started_at:K,agents:N,graphs:B,time:G,usage:J,memory:$}}u(ae,"computeAnalytics");function Z(o,_,g,h,i,w){const p=new Map,l=new Map;for(const n of o){if(w(n)&&l.set(n.graph,(l.get(n.graph)??new Set).add(n.a.kind)),!g(n.a.node_id))continue;let d=p.get(n.graph);if(!d){const k=_.get(n.graph).a;d={graph_id:n.graph,name:k.title||k.name,root_deleted:k.parent!==null,cwd:k.cwd,root_kind:k.kind,root_lifecycle:k.lifecycle,root_created:k.created,active_agents:0,depth:0,api_price_estimate:0,tokens:0,spawned_kinds:[]},p.set(n.graph,d)}d.active_agents++,d.depth=Math.max(d.depth,n.depth),d.api_price_estimate+=h(n.a.node_id),d.tokens+=i(n.a.node_id)}for(const n of p.values())n.spawned_kinds=[...l.get(n.graph_id)??[]].sort();const f=[...p.values()].sort((n,d)=>d.api_price_estimate-n.api_price_estimate||n.graph_id.localeCompare(d.graph_id)),r=u(n=>n<=1?0:n<=5?1:n<=10?2:n<=20?3:4,"bucket"),t=[0,0,0,0,0];for(const n of f)t[r(n.active_agents)]++;const c=new Map;for(const n of o)w(n)&&c.set(n.a.kind,(c.get(n.a.kind)??0)+1);const s=["1","2\u20135","6\u201310","11\u201320","21+"];return{count:f.length,spawned:[...c.values()].reduce((n,d)=>n+d,0),deepest:f.reduce((n,d)=>Math.max(n,d.depth),0),graphs:f,size_buckets:s.map((n,d)=>({label:n,graphs:t[d]})),spawned_by_kind:[...c].map(([n,d])=>({kind:n,agents:d})).sort((n,d)=>d.agents-n.agents||n.kind.localeCompare(d.kind))}}u(Z,"graphsMeasure");function ee(o,_,g,h,i){const w=o.filter(_),p=new Map;for(const s of w)v(p,s.a.kind,s.finMs-s.createdMs);const l=h==="24h"?36e5:24*36e5,f=h==="24h"?24:7,r=i-f*l,t=Array.from({length:f},()=>new Set);for(const s of g)t[Math.floor((s.at_ms-r)/l)].add(s.node_id);const c=t.map((s,n)=>({start:new Date(r+n*l).toISOString(),agents:s.size}));return{all:w.length===0?null:P(w.map(s=>s.finMs-s.createdMs)),by_kind:[...p].map(([s,n])=>({kind:s,...P(n)})).sort((s,n)=>n.count-s.count||s.kind.localeCompare(n.kind)),activity:{bucket_ms:l,buckets:c,max:c.reduce((s,n)=>Math.max(s,n.agents),0)}}}u(ee,"timeMeasure");function te(o,_){const g=new Map,h=new Map,i=[];let w=0,p=0;for(const r of o)for(const t of _.get(r.a.node_id)??[]){const c=y(t);let s=g.get(c);s||(s={row:{provider:t.provider,model:t.model,responses:0,api_price_estimate:0,tokens:0,tokens_by_type:{cache_read:0,cache_write:0,input:0,output:0},cache_read_share:0,context:{median:0,p90:0,max:0,buckets:[0,0,0,0,0]}},contexts:[]},g.set(c,s));const n=X(t);s.row.responses++,s.row.api_price_estimate+=t.cost,s.row.tokens+=C(t),s.row.tokens_by_type.cache_read+=t.cache_read,s.row.tokens_by_type.cache_write+=t.cache_write,s.row.tokens_by_type.input+=t.input,s.row.tokens_by_type.output+=t.output,s.row.context.buckets[Math.min(4,Math.floor(n/5e4))]++,s.contexts.push(n),i.push(n),w+=t.cost,p+=C(t);const d=h.get(r.a.kind)??{price:0,tokens:0,byModel:new Map};d.price+=t.cost,d.tokens+=C(t),d.byModel.set(c,(d.byModel.get(c)??0)+1),h.set(r.a.kind,d)}const l=[...g.values()].map(({row:r,contexts:t})=>{const c=t.sort((n,d)=>n-d),s=r.tokens_by_type.input+r.tokens_by_type.cache_read+r.tokens_by_type.cache_write;return r.cache_read_share=s===0?0:r.tokens_by_type.cache_read/s,r.context.median=b(c,50),r.context.p90=b(c,90),r.context.max=c[c.length-1],r}),f=u(r=>{const[t,c]=r.split("\0");return{provider:t,model:c}},"keyOf");return i.sort((r,t)=>r-t),{api_price_estimate:w,tokens:p,median_context:i.length===0?null:b(i,50),models:l.sort((r,t)=>t.api_price_estimate-r.api_price_estimate||y(r).localeCompare(y(t))),legend:[...l].sort((r,t)=>t.responses-r.responses||t.api_price_estimate-r.api_price_estimate||y(r).localeCompare(y(t))).slice(0,4).map(r=>({provider:r.provider,model:r.model})),kinds:[...h].map(([r,t])=>({kind:r,api_price_estimate:t.price,tokens:t.tokens,responses_by_model:[...t.byModel].map(([c,s])=>({...f(c),responses:s})).sort((c,s)=>s.responses-c.responses||y(c).localeCompare(y(s)))})).sort((r,t)=>t.api_price_estimate-r.api_price_estimate||r.kind.localeCompare(t.kind))}}u(te,"usageMeasure");function E(o,_,g,h){const i=new Map;for(const p of o){const l=`${p.name}\0${p.scope}`;v(i,l,p)}const w=[...i.values()].map(p=>{const l=new Map;for(const t of p){const c=l.get(t.node_id);c?(c.reads++,t.at<c.first_at&&(c.first_at=t.at)):l.set(t.node_id,{reads:1,first_at:t.at})}const f=[...l].map(([t,c])=>{const s=_.get(t);return{node_id:t,kind:s.a.kind,name:s.a.name,graph_id:s.graph,reads:c.reads,first_at:c.first_at}}).sort((t,c)=>c.reads-t.reads||t.first_at.localeCompare(c.first_at)||t.node_id.localeCompare(c.node_id)),r=new Map;for(const t of f)r.set(t.kind,(r.get(t.kind)??0)+1);return{name:p[0].name,scope:p[0].scope,reads:p.length,agents:f.length,graphs:new Set(f.map(t=>t.graph_id)).size,readers_by_kind:[...r].map(([t,c])=>({kind:t,agents:c})).sort((t,c)=>c.agents-t.agents||t.kind.localeCompare(c.kind)),readers:f}}).sort((p,l)=>l.reads-p.reads||l.agents-p.agents||p.name.localeCompare(l.name)||p.scope.localeCompare(l.scope));return{entries:o.length,documents:w.length,agents_with_entry:new Set(o.filter(p=>h(p.node_id)).map(p=>p.node_id)).size,active_agents:g,rows:w}}u(E,"memoryView");export{Q as WINDOW_MS,ae as computeAnalytics};
|
|
1
|
+
var L=Object.defineProperty;var u=(o,_)=>L(o,"name",{value:_,configurable:!0});const oe=36e5,Q={"24h":864e5,"7d":6048e5};function b(o,_){return o[Math.max(0,Math.ceil(_/100*o.length)-1)]}u(b,"rank");function P(o){const _=[...o].sort((g,h)=>g-h);return{count:_.length,p10_ms:b(_,10),median_ms:b(_,50),p90_ms:b(_,90),max_ms:_[_.length-1]}}u(P,"stats");const C=u(o=>o.input+o.output+o.cache_read+o.cache_write,"tokensOf"),X=u(o=>o.input+o.cache_read+o.cache_write,"contextOf"),y=u(o=>`${o.provider}\0${o.model}`,"modelKey");function v(o,_,g){const h=o.get(_);h?h.push(g):o.set(_,[g])}u(v,"push");const W=u(o=>o instanceof Error?o.message:String(o),"reason");function Y(o){const _=new Map(o.map(i=>[i.node_id,i])),g=new Map,h=u((i,w)=>{const p=g.get(i.node_id);if(p)return p;const l=i.parent===null?void 0:_.get(i.parent);let f;const r={a:i,createdMs:Date.parse(i.created),finMs:i.finalized_at===null?null:Date.parse(i.finalized_at)};if(!l||w.has(l.node_id)){if(l)throw new Error(`parent cycle through node ${i.node_id}`);f={...r,graph:i.node_id,parent:null,depth:0}}else{w.add(i.node_id);const t=h(l,w);f={...r,graph:t.graph,parent:l.node_id,depth:t.depth+1}}return g.set(i.node_id,f),f},"place");for(const i of o)h(i,new Set);return g}u(Y,"placeAgents");async function ae(o){const _=o.asOfMs,g=_-Q[o.window],h=u(e=>e!==null&&e>=g&&e<_,"inW"),i=Y(o.agents),w=u(e=>i.get(e.graph),"rootOf"),p=u(e=>w(e).a.cwd,"projectOf"),l=new Map;for(const e of i.values()){const a=p(e);v(l,a,e)}let f=null,r="";try{const e=[...l.keys()],a=await Promise.all(e.map(m=>o.scan({nodes:l.get(m).map(S=>({node_id:S.a.node_id,created:S.a.created,transcripts:S.a.transcripts})),windowStartMs:g,asOfMs:_})));f=new Map(e.map((m,S)=>[m,a[S]]))}catch(e){r=`transcript scan failed: ${W(e)}`}const t=new Map;for(const e of f?.values()??[])for(const a of e.responses)v(t,a.node_id,a);const c=u(e=>(t.get(e)??[]).reduce((a,m)=>a+m.cost,0),"priceOf"),s=u(e=>(t.get(e)??[]).reduce((a,m)=>a+C(m),0),"tokensOfAgent"),n=new Map;for(const e of f?.values()??[]){for(const a of e.responses)v(n,a.node_id,a.at_ms);for(const a of e.unknown_at)v(n,a.node_id,a.at_ms)}const d=u(e=>(n.get(e)?.length??0)>0,"isActive"),k=new Map,A=new Set;for(const e of i.values()){if(!d(e.a.node_id))continue;const a=p(e);A.add(a),k.set(a,(k.get(a)??0)+c(e.a.node_id))}const T=[...A].map(e=>({cwd:e,api_price_estimate:k.get(e)??0})).sort((e,a)=>a.api_price_estimate-e.api_price_estimate||e.cwd.localeCompare(a.cwd)),M=[...i.values()].filter(e=>o.project===null||p(e)===o.project),F=new Set(M.map(e=>e.a.node_id)),j=u(e=>e.parent!==null&&h(e.createdMs),"spawned"),z=u(e=>h(e.finMs),"finished"),D=new Set,I=new Set,R=u((e,a)=>{for(let m=e;m&&!a.has(m.a.node_id);m=m.parent===null?void 0:i.get(m.parent))a.add(m.a.node_id)},"climb");for(const e of M)d(e.a.node_id)&&R(e,D),(d(e.a.node_id)||j(e)||z(e))&&R(e,I);const N=M.filter(e=>I.has(e.a.node_id)).map(e=>({node_id:e.a.node_id,name:e.a.name,kind:e.a.kind,graph_id:e.graph,in_graph_detail:D.has(e.a.node_id),parent:e.parent,depth:e.depth,created:e.a.created,finalized_at:e.a.finalized_at,lifecycle:e.a.lifecycle,active:d(e.a.node_id),spawned_in_window:j(e),finished_in_window:z(e),agent_time_ms:e.finMs===null?null:e.finMs-e.createdMs,api_price_estimate:c(e.a.node_id),tokens:s(e.a.node_id),responses:n.get(e.a.node_id)?.length??0,response_times_ms:[...n.get(e.a.node_id)??[]].sort((a,m)=>a-m),final_report_ref:e.a.final_report?`${e.a.node_id}:reports/${e.a.final_report}`:null})).sort((e,a)=>e.created.localeCompare(a.created)||e.node_id.localeCompare(a.node_id)),V=M.reduce((e,a)=>e===null||a.a.created<e?a.a.created:e,null),q=M.flatMap(e=>(n.get(e.a.node_id)??[]).map(a=>({node_id:e.a.node_id,at_ms:a}))),x=M.filter(e=>d(e.a.node_id)).length;let H=null,U=null;if(f){const e=[...f.entries()].filter(([a])=>o.project===null||a===o.project).map(([,a])=>a);H={total:e.reduce((a,m)=>a+m.transcripts.total,0),read:e.reduce((a,m)=>a+m.transcripts.read,0),unreadable:e.flatMap(a=>a.transcripts.unreadable)},U=e.reduce((a,m)=>a+m.unknown,0)}const O=u(()=>({ok:!1,reason:r}),"fail"),B=f?{ok:!0,value:Z(M,i,d,c,s,j)}:O(),G=f?{ok:!0,value:ee(M,z,q,o.window,_)}:O(),J=f?{ok:!0,value:te(M,t)}:O();let $,K=null;try{const e=await o.memory(new Date(g).toISOString(),new Date(_).toISOString());K=e.startedAt;const a=e.rows.filter(m=>F.has(m.node_id));$=f?{ok:!0,value:{read:E(a.filter(m=>m.type==="read"),i,x,d),loaded:E(a.filter(m=>m.type==="loaded"),i,x,d)}}:O()}catch(e){$={ok:!1,reason:`memory-read log unavailable: ${W(e)}`}}return{as_of:new Date(_).toISOString(),window_start:new Date(g).toISOString(),window:o.window,project:o.project,projects:T,transcripts:H,unknown_responses:U,oldest_agent_created:V,memory_log_started_at:K,agents:N,graphs:B,time:G,usage:J,memory:$}}u(ae,"computeAnalytics");function Z(o,_,g,h,i,w){const p=new Map,l=new Map;for(const n of o){if(w(n)&&l.set(n.graph,(l.get(n.graph)??new Set).add(n.a.kind)),!g(n.a.node_id))continue;let d=p.get(n.graph);if(!d){const k=_.get(n.graph).a;d={graph_id:n.graph,name:k.title||k.name,root_deleted:k.parent!==null,cwd:k.cwd,root_kind:k.kind,root_lifecycle:k.lifecycle,root_created:k.created,active_agents:0,depth:0,api_price_estimate:0,tokens:0,spawned_kinds:[]},p.set(n.graph,d)}d.active_agents++,d.depth=Math.max(d.depth,n.depth),d.api_price_estimate+=h(n.a.node_id),d.tokens+=i(n.a.node_id)}for(const n of p.values())n.spawned_kinds=[...l.get(n.graph_id)??[]].sort();const f=[...p.values()].sort((n,d)=>d.api_price_estimate-n.api_price_estimate||n.graph_id.localeCompare(d.graph_id)),r=u(n=>n<=1?0:n<=5?1:n<=10?2:n<=20?3:4,"bucket"),t=[0,0,0,0,0];for(const n of f)t[r(n.active_agents)]++;const c=new Map;for(const n of o)w(n)&&c.set(n.a.kind,(c.get(n.a.kind)??0)+1);const s=["1","2\u20135","6\u201310","11\u201320","21+"];return{count:f.length,spawned:[...c.values()].reduce((n,d)=>n+d,0),deepest:f.reduce((n,d)=>Math.max(n,d.depth),0),graphs:f,size_buckets:s.map((n,d)=>({label:n,graphs:t[d]})),spawned_by_kind:[...c].map(([n,d])=>({kind:n,agents:d})).sort((n,d)=>d.agents-n.agents||n.kind.localeCompare(d.kind))}}u(Z,"graphsMeasure");function ee(o,_,g,h,i){const w=o.filter(_),p=new Map;for(const s of w)v(p,s.a.kind,s.finMs-s.createdMs);const l=h==="24h"?36e5:24*36e5,f=h==="24h"?24:7,r=i-f*l,t=Array.from({length:f},()=>new Set);for(const s of g)t[Math.floor((s.at_ms-r)/l)].add(s.node_id);const c=t.map((s,n)=>({start:new Date(r+n*l).toISOString(),agents:s.size}));return{all:w.length===0?null:P(w.map(s=>s.finMs-s.createdMs)),by_kind:[...p].map(([s,n])=>({kind:s,...P(n)})).sort((s,n)=>n.count-s.count||s.kind.localeCompare(n.kind)),activity:{bucket_ms:l,buckets:c,max:c.reduce((s,n)=>Math.max(s,n.agents),0)}}}u(ee,"timeMeasure");function te(o,_){const g=new Map,h=new Map,i=[];let w=0,p=0;for(const r of o)for(const t of _.get(r.a.node_id)??[]){const c=y(t);let s=g.get(c);s||(s={row:{provider:t.provider,model:t.model,responses:0,api_price_estimate:0,tokens:0,tokens_by_type:{cache_read:0,cache_write:0,input:0,output:0},cache_read_share:0,context:{median:0,p90:0,max:0,buckets:[0,0,0,0,0]}},contexts:[]},g.set(c,s));const n=X(t);s.row.responses++,s.row.api_price_estimate+=t.cost,s.row.tokens+=C(t),s.row.tokens_by_type.cache_read+=t.cache_read,s.row.tokens_by_type.cache_write+=t.cache_write,s.row.tokens_by_type.input+=t.input,s.row.tokens_by_type.output+=t.output,s.row.context.buckets[Math.min(4,Math.floor(n/5e4))]++,s.contexts.push(n),i.push(n),w+=t.cost,p+=C(t);const d=h.get(r.a.kind)??{price:0,tokens:0,byModel:new Map};d.price+=t.cost,d.tokens+=C(t),d.byModel.set(c,(d.byModel.get(c)??0)+1),h.set(r.a.kind,d)}const l=[...g.values()].map(({row:r,contexts:t})=>{const c=t.sort((n,d)=>n-d),s=r.tokens_by_type.input+r.tokens_by_type.cache_read+r.tokens_by_type.cache_write;return r.cache_read_share=s===0?0:r.tokens_by_type.cache_read/s,r.context.median=b(c,50),r.context.p90=b(c,90),r.context.max=c[c.length-1],r}),f=u(r=>{const[t,c]=r.split("\0");return{provider:t,model:c}},"keyOf");return i.sort((r,t)=>r-t),{api_price_estimate:w,tokens:p,median_context:i.length===0?null:b(i,50),models:l.sort((r,t)=>t.api_price_estimate-r.api_price_estimate||y(r).localeCompare(y(t))),legend:[...l].sort((r,t)=>t.responses-r.responses||t.api_price_estimate-r.api_price_estimate||y(r).localeCompare(y(t))).slice(0,4).map(r=>({provider:r.provider,model:r.model})),kinds:[...h].map(([r,t])=>({kind:r,api_price_estimate:t.price,tokens:t.tokens,responses_by_model:[...t.byModel].map(([c,s])=>({...f(c),responses:s})).sort((c,s)=>s.responses-c.responses||y(c).localeCompare(y(s)))})).sort((r,t)=>t.api_price_estimate-r.api_price_estimate||r.kind.localeCompare(t.kind))}}u(te,"usageMeasure");function E(o,_,g,h){const i=new Map;for(const p of o){const l=`${p.name}\0${p.scope}`;v(i,l,p)}const w=[...i.values()].map(p=>{const l=new Map;for(const t of p){const c=l.get(t.node_id);c?(c.reads++,t.at<c.first_at&&(c.first_at=t.at)):l.set(t.node_id,{reads:1,first_at:t.at})}const f=[...l].map(([t,c])=>{const s=_.get(t);return{node_id:t,kind:s.a.kind,name:s.a.name,graph_id:s.graph,reads:c.reads,first_at:c.first_at}}).sort((t,c)=>c.reads-t.reads||t.first_at.localeCompare(c.first_at)||t.node_id.localeCompare(c.node_id)),r=new Map;for(const t of f)r.set(t.kind,(r.get(t.kind)??0)+1);return{name:p[0].name,scope:p[0].scope,reads:p.length,agents:f.length,graphs:new Set(f.map(t=>t.graph_id)).size,readers_by_kind:[...r].map(([t,c])=>({kind:t,agents:c})).sort((t,c)=>c.agents-t.agents||t.kind.localeCompare(c.kind)),readers:f}}).sort((p,l)=>l.reads-p.reads||l.agents-p.agents||p.name.localeCompare(l.name)||p.scope.localeCompare(l.scope));return{entries:o.length,documents:w.length,agents_with_entry:new Set(o.filter(p=>h(p.node_id)).map(p=>p.node_id)).size,active_agents:g,rows:w}}u(E,"memoryView");export{Q as WINDOW_MS,ae as computeAnalytics};
|
|
@@ -10,13 +10,13 @@ export declare const RUN_STREAM_IDLE_MS = 60000;
|
|
|
10
10
|
export interface RunStreamOptions {
|
|
11
11
|
idleMs?: number;
|
|
12
12
|
idleCheckMs?: number;
|
|
13
|
-
isRunning?: (runId: string) => boolean
|
|
13
|
+
isRunning?: (runId: string) => Promise<boolean>;
|
|
14
14
|
}
|
|
15
15
|
export declare function streamRunEvents(req: IncomingMessage, res: ServerResponse, id: string, principal: AppPrincipal | RequestPrincipal, after: number, requestId: string, framing: 'sse' | 'ndjson', options?: RunStreamOptions): Promise<void>;
|
|
16
|
-
export declare function createAppListener(config: NonNullable<ScopeConfig['runtime']>, grantsReady: () => boolean
|
|
16
|
+
export declare function createAppListener(config: NonNullable<ScopeConfig['runtime']>, grantsReady: () => Promise<boolean>, syncGrants: GrantSync, listenerOptions?: {
|
|
17
17
|
deferHead?: DeferHeadOptions;
|
|
18
18
|
stream?: RunStreamOptions;
|
|
19
|
-
}): {
|
|
19
|
+
}): Promise<{
|
|
20
20
|
ready: Promise<void>;
|
|
21
21
|
close: () => Promise<void>;
|
|
22
|
-
}
|
|
22
|
+
}>;
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
var
|
|
2
|
-
data: ${JSON.stringify(D(u,o,
|
|
1
|
+
var F=Object.defineProperty;var i=(e,r)=>F(e,"name",{value:r,configurable:!0});import{randomUUID as Y}from"node:crypto";import{createServer as q}from"node:http";import{Router as L}from"./router.js";import{toErrorBody as Q}from"./map.js";import{objectRoutes as W}from"./handlers/objects.js";import{customObjectRoutes as K}from"./handlers/custom-objects.js";import{docRoutes as Z}from"./handlers/docs.js";import{OPERATIONS as ee}from"./operations.js";import{runtimeReadiness as te}from"../readiness.js";import{errorCodes as U}from"../../api/error-codes.js";import{MINIMUM_RUNTIME_VERSION_HEADER as ne,RUNTIME_VERSION_HEADER as re,minimumRuntimeRefusal as ae}from"../../api/runtime-version.js";import{CONTRACT_HEADER as oe,CONTRACT_LEVEL as V,REQUIRED_CONTRACT_HEADER as ie,contractRefusal as se}from"../../api/contract.js";import{crtrVersion as j}from"../../shared/crtr-version.js";import{AppPrincipalResolver as ue}from"./principal.js";import{isDaemonRoute as de,runtimeOwner as ce,servePeer as X}from"../peer/ingress.js";import{applySyncNotice as le}from"./sync-notice.js";import{ownMachineId as fe}from"../../core/peer/directory.js";import{handleRunOperation as me,integer as pe}from"./handlers/runs.js";import{llmCallerOf as he,parseLlmRequest as we,runLlm as ye}from"../../core/llm/run.js";import{parseUsageMonth as _e,usageFor as ve}from"../../core/usage/ledger.js";import{capFields as ge}from"./handlers/llm.js";import{CONTROL_BODY_MAX_BYTES as Re,MODEL_CONTEXT_BODY_MAX_BYTES as Oe}from"../../core/llm/body-limits.js";import{RunError as f,runIsRunning as Ee}from"../../core/runs/operations.js";import{requireRun as x}from"./router.js";import{deferHead as be}from"./deferred-head.js";import{readRunEvents as $,registerGrantStream as Se,subscribeRunEvents as Te}from"../../core/runs/events.js";import{activeGrant as z,payerOfGrant as Ae}from"../../core/grants/mirror.js";async function Ne(e){if(await Ae(e)==="app")throw new f(401,"grant_revoked","this app-paid grant is no longer active");return null}i(Ne,"appPaidGone");import{releaseGrantWaiters as Ce}from"../../core/grants/watch.js";import{emitEvent as Ie}from"../../core/events/emit.js";import{runNotices as Pe}from"../run-notices.js";import{handleVendorSignIn as ke,isVendorSignInPath as He}from"./vendor-signin.js";import{listAppProfiles as Me}from"./handlers/app-profiles.js";import{handleTransferDownload as De,handleTransferOperation as je,TRANSFER_OPERATIONS as xe}from"./handlers/transfer.js";import{handleQuestionOperation as Be,QUESTION_OPERATIONS as Je}from"./handlers/questions.js";import{vendorStatus as Le}from"./handlers/vendor-status.js";import{handleMemoryOperation as Ue,MEMORY_OPERATIONS as Ve}from"./handlers/memory.js";import{abortOnClose as Xe,callerFromApp as $e,handleProviderOperation as ze,PROVIDER_OPERATIONS as Ge,providerFailure as Fe}from"./handlers/providers.js";function Ye(e){return Object.prototype.hasOwnProperty.call(U,e)?U[e]:void 0}i(Ye,"fixedRow");function qe(e){const r=Ye(e);return r?r.type:e==="stream_gap"||e==="provider_error"||e==="runtime_version_unsupported"?"invalid_request_error":"server_error"}i(qe,"errorType");function Qe(e){if(!e||typeof e!="object"||Array.isArray(e)||!("rate_limit"in e))return e;const{rate_limit:r,...o}=e;return o}i(Qe,"appDetails");function D(e,r,o){const m=Qe(e.details);return{error:{code:e.code,message:e.message,...m===void 0?{}:{details:m},type:qe(e.code),...e.param?{param:e.param}:{},origin:"runtime",retryable:e.retryable||e.code==="stream_dropped",request_id:r,...o?{run_id:o}:{},...e.scope?{scope:e.scope}:{},...e.code==="unauthorized"?{user_action:"reconnect"}:{},...ge(e),...e.code==="all_routes_exhausted"?{retry_after_s:e.details.retry_after_s}:{}}}}i(D,"envelope");function We(e,r,o,m){const u=r instanceof f?r:new f(500,"server_failure","runtime request failed");if(r instanceof f||console.error("[app-listener]",r),e.headersSent&&!String(e.getHeader("Content-Type")??"").startsWith("text/event-stream")){e.destroy();return}if(e.headersSent){e.end(`event: error
|
|
2
|
+
data: ${JSON.stringify(D(u,o,m))}
|
|
3
3
|
|
|
4
|
-
`);return}e.writeHead(u.status,{"Content-Type":"application/json; charset=utf-8","Request-Id":o,"X-Content-Type-Options":"nosniff",...u.code==="all_routes_exhausted"?{"Retry-After":String(u.details.retry_after_s)}:{}}),e.end(JSON.stringify(D(u,o,
|
|
4
|
+
`);return}e.writeHead(u.status,{"Content-Type":"application/json; charset=utf-8","Request-Id":o,"X-Content-Type-Options":"nosniff",...u.code==="all_routes_exhausted"?{"Retry-After":String(u.details.retry_after_s)}:{}}),e.end(JSON.stringify(D(u,o,m)))}i(We,"fail");function G(e){return Array.isArray(e)?e[0]:e}i(G,"headerValue");function O(e,r,o){e.writeHead(r,{"Content-Type":"application/json; charset=utf-8"}),e.end(JSON.stringify(o))}i(O,"json");async function I(e,r=Re){const o=[];let m=0;for await(const u of e){if(m+=u.length,m>r)throw new f(400,"invalid_request","request body too large");o.push(u)}if(m)try{return JSON.parse(Buffer.concat(o).toString("utf8"))}catch{throw new f(400,"invalid_request","invalid JSON body")}}i(I,"bodyOf");function Ke(e,r){const o=e.headers["last-event-id"]??r.get("after");if(Array.isArray(o))throw new f(400,"invalid_request","invalid cursor","after");return pe(o??null,"after",0,Number.MAX_SAFE_INTEGER,0)}i(Ke,"cursor");function Ze(e){return`id: ${e.sequence_number}
|
|
5
5
|
event: ${e.type}
|
|
6
6
|
data: ${JSON.stringify(e)}
|
|
7
7
|
|
|
8
|
-
`}
|
|
8
|
+
`}i(Ze,"frame");const et=6e4;async function tt(e,r,o,m,u,w,b,N={}){await x(m,o);let v=await $(o,u);if(u>v.latest_sequence)throw new f(400,"invalid_request","cursor is beyond the run","after");if(u<v.latest_sequence&&(v.earliest_sequence===null||u<v.earliest_sequence-1))throw new f(409,"stream_gap","events have expired",void 0,{earliest_sequence:v.earliest_sequence,latest_sequence:v.latest_sequence});if(r.destroyed||e.destroyed)return r.destroy(),Promise.resolve();r.writeHead(200,{"Content-Type":b==="sse"?"text/event-stream":"application/x-ndjson","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),b==="sse"?r.write(`: connected
|
|
9
9
|
|
|
10
|
-
`):r.flushHeaders();let
|
|
11
|
-
data: ${JSON.stringify(D(
|
|
10
|
+
`):r.flushHeaders();let y=u;const B=await Pe().streamOpened(o);let n=!1,t=!1,h=!1,S;const C=new Promise(d=>{S=d}),_=i(()=>{n||(n=!0,B(y).catch(d=>console.error("[app-listener]",d)),clearInterval(c),clearInterval(A),P(),H(),r.off("close",_),r.off("drain",p),r.end(),S())},"end"),p=i(()=>{h=!1,a()},"onDrain"),R=i(d=>{n||r.write(b==="sse"?`event: error
|
|
11
|
+
data: ${JSON.stringify(D(d,w,o))}
|
|
12
12
|
|
|
13
|
-
`:`${JSON.stringify({type:"error",...D(
|
|
14
|
-
`),_()},"error"),a=
|
|
15
|
-
`),
|
|
13
|
+
`:`${JSON.stringify({type:"error",...D(d,w,o)})}
|
|
14
|
+
`),_()},"error"),a=i(async()=>{if(!(n||t)){t=!0;try{if(!await T()){k();return}if(await x(m,o),v=await $(o,y),v.backlog_count>1e3||v.backlog_bytes>32*1024*1024){R(new f(503,"stream_dropped","stream reader fell behind",void 0,{last_sequence:y}));return}for(const d of v.events){if(h)break;h=!r.write(b==="sse"?Ze(d):`${JSON.stringify(d)}
|
|
15
|
+
`),y=d.sequence_number}}catch(d){R(d instanceof f?d:new f(500,"server_failure","stream failed"))}finally{t=!1}}},"flush"),k=i(()=>R(new f(401,"grant_revoked","grant is not active")),"revoked"),T=i(async()=>"class"in m||await z(m.grant)!==null,"grantActive"),P=await Te(o,a),H="class"in m?()=>{}:Se(m.grant,k),c=setInterval(()=>{!n&&!h&&b==="sse"&&r.write(`: keepalive
|
|
16
16
|
|
|
17
|
-
`)},15e3),M=
|
|
17
|
+
`)},15e3),M=N.idleMs??et,s=N.isRunning??Ee;let g=Date.now(),l=y;const E=i(async()=>{if(n||b!=="sse")return;const d=Date.now();let J=!0;try{J=await s(o)}catch{}if(!n){if(J||y!==l){g=d,l=y;return}d-g<M||h||(r.write(`event: idle
|
|
18
18
|
data: {}
|
|
19
19
|
|
|
20
|
-
`),_())},A.idleCheckMs??1e3);return
|
|
20
|
+
`),_())}},"checkIdle"),A=setInterval(()=>{E().catch(d=>Ie({level:"error",event:"api.run_stream.idle_check_failed",error:d}))},N.idleCheckMs??1e3);return A.unref(),r.on("drain",p),r.on("close",_),await a(),C}i(tt,"streamRunEvents");async function Lt(e,r,o,m={}){const u=e.listener;if(!e.issuer||!e.audience||!u?.address||!Number.isInteger(u.port)||u.port<1||u.port>65535)throw new Error("runtime issuer, audience and listener address/port are required");if(["0.0.0.0","::","[::]"].includes(u.address))throw new Error("runtime listener must bind a specific address");const w=new ue(e.issuer,e.audience,o,e.jwksUrl),b=new L,N=new Map;for(const n of ee.filter(t=>t.stage!==void 0)){const t=i(()=>({status:500}),"handler");b.register({method:n.method,pattern:n.path,handler:t}),N.set(t,n)}const v=new L().registerAll(W).registerAll(K).registerAll(Z),y=q((n,t)=>{(async()=>{be(n,t,m.deferHead);const h=Y();t.setHeader("Request-Id",h),t.setHeader(re,j()),t.setHeader(oe,V);let S;try{const C=G(n.headers[ne.toLowerCase()]),_=ae(C,j())??se(G(n.headers[ie.toLowerCase()]),V,{legacyMinimum:C,runtimeVersion:j()});if(_!==null)throw _.status===400?new f(400,_.code,_.message,_.param):new f(426,_.code,_.message,void 0,_.details);const p=new URL(n.url??"/","http://runtime.local");if(He(p.pathname)){await ke(n,t,p,w);return}const R=b.match(n.method??"GET",p.pathname),a=R?N.get(R.handler):void 0,k=a?.name==="runtime.sync-notice"||a?.name==="runtime.vendor-status";let T,P;if(!k&&n.headers.authorization!==void 0)try{T=await w.verifyCall(n.headers.authorization)}catch(s){P=s}const H={issuer:e.issuer,jwks:w.jwks,audience:i(async()=>e.audience,"audience"),owner:ce,self:fe,syncGrants:o,ready:i(async()=>w.isReady()&&await r(),"ready")};if(T?.chain[0]?.sub.startsWith("runtime:")){await X(n,t,H,T);return}if(T===void 0&&a===void 0&&await de(n.method??"GET",p.pathname)){await X(n,t,H,{status:401,code:"unauthorized",message:P===void 0?"a machine token is required":"invalid machine token"});return}if(a?.name==="ready"){const s=await r(),g=await te({jwksReady:w.isReady(),grantsReady:i(()=>s,"grantsReady")});O(t,g.ready?200:503,g);return}if((n.method!=="GET"||p.pathname!=="/v1/health")&&(!w.isReady()||!await r()))throw new f(503,"runtime_starting","runtime_starting");if(!R||!a)throw new f(404,"not_found","unknown operation");if(S=R.params.run_id,a.name==="health"){O(t,200,{status:"ok",api_version:"2026-09-23"});return}if(a.name==="runtime.sync-notice"){await le(await w.verifySyncNotice(n.headers.authorization),o,h),t.writeHead(204),t.end();return}if(a.name==="runtime.vendor-status"){await w.verifyDirectoryRead(n.headers.authorization,"vendor_status"),O(t,200,Le());return}if(T===void 0)throw P??new f(401,"unauthorized","a directory access token is required");const c=await w.resolveVerified(T,a.scope);if(t.setHeader("Request-Id",h),S&&await x(c,S,["run.message","run.interrupt","run.cancel","run.rename","run.delete"].includes(a.name),a.name==="run.delete"),a.stage==="objects"){const s=v.match(a.method,p.pathname);if(!s)throw new f(404,"not_found","unknown operation");const g={method:a.method,path:p.pathname,params:s.params,query:p.searchParams,body:await I(n,s.maxBodyBytes),ceiling:c.resolved,principal:{class:"app",app:c.grantee,scopes:c.resolved},req:n,res:t};let l;try{l=await s.handler(g)}catch(E){const{status:A,body:d}=Q(E);throw A>=500&&console.error("[app-listener]",E),new f(A,d.error.code,d.error.message,void 0,d.error.details)}if(t.headersSent)return;if(l.rawBody!==void 0||l.status===204||l.body===void 0){t.writeHead(l.status,l.headers??{}),t.end(l.rawBody);return}t.writeHead(l.status,{"Content-Type":"application/json; charset=utf-8",...l.headers??{}}),t.end(JSON.stringify(l.body));return}if(a.stream==="bytes"){await De(n,t,c,p.searchParams);return}if(a.stream){await tt(n,t,S,c,Ke(n,p.searchParams),h,"sse",m.stream);return}if(a.name==="llm"){const s=we(await I(n,Oe)),g=new AbortController,l=i(()=>g.abort(),"abort");t.on("close",l);try{const E=await ye(s,g.signal,s.stream?A=>{t.headersSent||t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),t.write(`data: ${JSON.stringify(A)}
|
|
21
21
|
|
|
22
|
-
`)}:void 0,void 0,{grantee:
|
|
22
|
+
`)}:void 0,void 0,{grantee:c.grantee,spend_cap:c.spend_cap},he(await z(c.grant)??await Ne(c.grant)));s.stream?(t.headersSent||t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),t.end(`data: [DONE]
|
|
23
23
|
|
|
24
|
-
`)):O(t,200,
|
|
24
|
+
`)):O(t,200,E.completion)}finally{t.off("close",l)}return}if(a.name==="usage.get"){O(t,200,await ve(c.grantee,c.spend_cap,_e(p.searchParams.get("month"))));return}if(a.name==="profile.list"){O(t,200,Me(c));return}if(Je.has(a.name)){const s=await Be(a.name,c,R.params.question_id,a.method==="POST"?await I(n):void 0);O(t,s.status,s.body);return}if(Ge.has(a.name)){const{signal:s,release:g}=Xe(t);try{const l=await ze(a.name,$e(c),{params:R.params,body:a.method==="POST"?await I(n):void 0,query:p.searchParams},{requestId:h,signal:s});O(t,l.status,l.body)}catch(l){const E=Fe(l,h,!0);t.writeHead(E.status,{"Content-Type":"application/json; charset=utf-8","X-Content-Type-Options":"nosniff",...E.headers}),t.end(JSON.stringify(E.body))}finally{g()}return}if(Ve.has(a.name)){const s=await Ue(a.name,{class:"app",app:c.grantee,scopes:c.resolved},p.searchParams);O(t,s.status,s.body);return}if(xe.has(a.name)){const s=await je(a,c,R.params,p.searchParams,await I(n));O(t,s.status,s.body);return}const M=await me(a,c,S,p.searchParams,await I(n),n.headers["idempotency-key"]);O(t,M.status,M.body)}catch(C){We(t,C,h,S)}})()});return{ready:new Promise((n,t)=>{y.once("error",t),y.listen(u.port,u.address,()=>{y.off("error",t),n()})}),close:i(async()=>{w.close(),Ce(),y.closeAllConnections(),await new Promise((n,t)=>y.close(h=>h?t(h):n()))},"close")}}i(Lt,"createAppListener");export{et as RUN_STREAM_IDLE_MS,Lt as createAppListener,Ke as cursor,tt as streamRunEvents};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
1
|
+
var N=Object.defineProperty;var c=(t,e)=>N(t,"name",{value:e,configurable:!0});import{WebSocketServer as O}from"ws";import{isSafeNodeId as E}from"../../core/canvas/paths.js";import{getNode as S}from"../../core/canvas/index.js";import{BROKER_READ_CAPS as P,CLIENT_READ_CAPS as D,FrameDecoder as F,FrameOverflowError as U}from"../../core/runtime/broker-protocol.js";import{emitEvent as V}from"../../core/events/emit.js";import{classify as k}from"../../core/fault-classifier.js";import{clearFault as v,markNodeRead as L,recordFault as w}from"../../core/canvas/recovery.js";import{decideAttachRevive as H}from"../../core/runtime/revive.js";import{connectViewSocket as M,probeViewSocket as W,waitForBrokerViewSocket as J}from"../../core/runtime/view-socket.js";import{isBeneathRefusal as j}from"../../core/spaces/open-beneath.js";import{attachViewer as A,detachViewer as q,presentViewer as z}from"./viewer-presence.js";const K=new O({noServer:!0,maxPayload:P.maxLineBytes}),Q=25e3,G=6e4;function X(t,e=Q,n=G){let a=!0,o=!1,i=Date.now();const f=c(()=>{a=!0},"acknowledge"),y=c(()=>{o||(o=!0,clearInterval(d),t.off("pong",f))},"stop");t.on("pong",f);const d=setInterval(()=>{if(Date.now()-i>n){a=!0;return}if(!a){y(),t.terminate();return}a=!1;try{t.ping()}catch{y(),t.terminate()}},e);return d.unref(),{stop:y,noteActivity:c(()=>{i=Date.now()},"noteActivity")}}c(X,"startRemoteAttachHeartbeat");function b(t){const e=Buffer.from(t,"utf8");return e.byteLength<=123?t:e.subarray(0,123).toString("utf8")}c(b,"clampReason");function u(t,e,n,a,o){const i=JSON.stringify({error:{code:a,message:o,origin:"runtime"}}),f=`HTTP/1.1 ${e} ${n}\r
|
|
2
2
|
content-type: application/json; charset=utf-8\r
|
|
3
|
-
content-length: ${Buffer.byteLength(
|
|
3
|
+
content-length: ${Buffer.byteLength(i)}\r
|
|
4
4
|
connection: close\r
|
|
5
5
|
\r
|
|
6
|
-
`+
|
|
7
|
-
`)?
|
|
8
|
-
`;try{
|
|
6
|
+
`+i;try{t.end(f)}catch{try{t.destroy()}catch{}}}c(u,"refuseUpgrade");function Y(t){if(new URL(t.url??"/","http://127.0.0.1").searchParams.get("revive")==="0")return!0;const n=t.headers["x-crtr-attach-revive"];return(Array.isArray(n)?n[0]:n)==="0"}c(Y,"reviveOptedOut");function Z(t){return new URL(t.url??"/","http://127.0.0.1").searchParams.get("wakeParked")==="1"}c(Z,"wakeParkedRequested");function R(t){return t===1e3||t===1001||t===1005}c(R,"isCleanViewerClose");function m(t,e,n){n.catch(a=>V({level:"error",event:e,node_id:t,error:a}))}c(m,"detach");async function I(t,e){if(!E(e)){try{t.close(1008,b(`invalid node id: ${e}`))}catch{}return}if(await S(e)===null){try{t.close(1011,b(`no node ${e}`))}catch{}return}await v(e,{link:"viewer\u2194crtrd"});const n=M(e),a=new F(D);let o=!1,i=!1,f,y=!1,d=!1,g=!1;n.on("connect",()=>{y=!0,!o&&g&&A(e,t),m(e,"daemon.bridge.connect_failed",v(e,{link:"relay\u2194broker"}))});const h=c((r,l)=>{if(!o){if(o=!0,q(e,t),f?.stop(),!n.destroyed)try{n.destroy()}catch{}try{t.close(r,b(l))}catch{}}},"teardown");f=X(t);const $=c(async r=>{f?.noteActivity();let l;try{l=a.push(r)}catch(s){const p=s instanceof U?`broker sent an oversized frame (${s.message})`:`failed to decode a broker frame for ${e}`;h(1009,p);return}for(const s of l)if(t.readyState===t.OPEN&&(t.send(JSON.stringify(s)),g&&s?.type==="welcome"&&z(e,t)))try{await L(e)}catch{}},"onData");n.on("data",r=>m(e,"daemon.bridge.data_failed",$(r)));const C=c(async r=>{const l=k("relay\u2194broker",r);await w(e,{link:"relay\u2194broker",op:"bridge socket",kind:l.kind,retry:{disposition:"manual"},message:r.message});const s=r.code==="ECONNREFUSED"||r.code==="ENOENT"?`no running broker for ${e}`:`view socket error for ${e}: ${r.message}`;h(1011,s)},"onSocketError");n.on("error",r=>m(e,"daemon.bridge.socket_error_failed",C(r)));const T=c(async r=>{o||r||(await v(e,{link:"relay\u2194broker"}),h(1e3,"broker socket closed"))},"onSocketClose");n.on("close",r=>m(e,"daemon.bridge.socket_close_failed",T(r)));const x=c(async(r,l)=>{const s=l.toString("utf8");if(o){R(r)&&await v(e,{link:"viewer\u2194crtrd"});return}if(R(r))await v(e,{link:"viewer\u2194crtrd"});else if(!i){i=!0;const p=k("viewer\u2194crtrd",{code:r,reason:s});await w(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:p.kind,retry:{disposition:"auto"},message:s||`remote attach closed (${r})`})}h(r,s||`remote attach closed (${r})`)},"onWsClose");t.on("close",(r,l)=>m(e,"daemon.bridge.ws_close_failed",x(r,l)));const B=c(async()=>{if(!i){i=!0;const r=k("viewer\u2194crtrd",{code:1006,reason:"remote attach websocket error"});await w(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:r.kind,retry:{disposition:"auto"},message:"remote attach websocket error"})}h(1011,"remote attach websocket error")},"onWsError");t.on("error",()=>m(e,"daemon.bridge.ws_error_failed",B())),t.on("message",r=>{if(o||n.destroyed)return;f?.noteActivity();const s=(Array.isArray(r)?Buffer.concat(r):Buffer.isBuffer(r)?r:Buffer.from(new Uint8Array(r))).toString("utf8");if(!d)try{const _=JSON.parse(s);_?.type==="hello"&&(d=!0,g=_.attends!==!1,g&&y&&A(e,t))}catch{}const p=s.endsWith(`
|
|
7
|
+
`)?s:s+`
|
|
8
|
+
`;try{n.write(p)}catch{}})}c(I,"bridgeConnection");async function me(t,e,n,a){e.on("error",()=>{});try{if(!E(a)){u(e,400,"Bad Request","invalid_node_id",`invalid node id: ${a}`);return}if(await S(a)===null){u(e,404,"Not Found","node_not_found",`no node ${a}`);return}if(Y(t)){if(!await W(a,250)){u(e,409,"Conflict","node_dormant",`node ${a} is dormant and revive was opted out (?revive=0)`);return}}else{let o;try{const i=await H(a,{resume:!0,capacity:"refuse"},Z(t));if(i.parked){u(e,409,"Conflict","node_dormant",`node ${a} is parked; attach with ?wakeParked=1 to wake it`);return}o=i.result.launch?.exited}catch(i){const f=i instanceof Error?i.message:String(i);u(e,409,"Conflict","attach_revive_failed",`attach revive failed: ${f}`);return}if(!await J(a,o)){u(e,409,"Conflict","broker_not_ready",`broker view socket for ${a} did not become listenable after revive`);return}}if(e.destroyed)return;K.handleUpgrade(t,e,n,o=>m(a,"daemon.bridge.connection_failed",I(o,a)))}catch(o){const i=o instanceof Error?o.message:String(o);if(j(o)){u(e,400,"Bad Request","invalid_request",i);return}u(e,500,"Internal Server Error","internal",`attach upgrade failed: ${i}`)}}c(me,"handleAttachUpgrade");export{Q as REMOTE_ATTACH_HEARTBEAT_MS,G as REMOTE_ATTACH_QUIET_MS,me as handleAttachUpgrade,R as isCleanViewerClose,u as refuseUpgrade,X as startRemoteAttachHeartbeat};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
var
|
|
1
|
+
var D=Object.defineProperty;var h=(n,a)=>D(n,"name",{value:a,configurable:!0});import{createHash as A,timingSafeEqual as U}from"node:crypto";import{createServer as W}from"node:http";import{readFileSync as z}from"node:fs";import{join as E,extname as B}from"node:path";import{fileURLToPath as G}from"node:url";import{withCanvasWrite as b}from"../../core/canvas/db.js";import{ApiError as I}from"../../api/errors.js";import{bodyOf as C}from"../../core/graph/bodies.js";import{canChange as H,isShipped as F}from"../../core/graph/access.js";import{documentRecord as x,editDocument as J,heads as O,withCurrentNames as k}from"../../core/graph/documents.js";import{getById as N}from"../../core/graph/objects.js";import{subscribeDocumentEvents as M}from"../../core/graph/events.js";import{emitEvent as V}from"../../core/events/emit.js";import{checkoutsForCwd as X}from"../../core/graph/repo-sync/repos.js";import{canonicalName as Z,repoChange as K,syncChanged as Q}from"./handlers/docs.js";import{escapeHtml as S}from"./vendor-signin.js";import{readerFor as $,resolveRef as Y}from"./reader.js";import{mergeDocumentLines as q}from"./document-merge.js";import{crtrVersion as ee}from"../../shared/crtr-version.js";const te="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'",T={class:"person"},y=encodeURIComponent(ee()),j=G(new URL("../../../dist/",import.meta.url));function m(n,a,t,i){n.writeHead(a,{"Content-Type":"application/json; charset=utf-8"}),n.end(JSON.stringify({error:{code:t,message:i}}))}h(m,"error");function P(n,a){const t=h(i=>A("sha256").update(i).digest(),"digest");return U(t(n),t(a))}h(P,"sameSecret");function ne(n,a){for(const t of(n??"").split(";")){const i=t.indexOf("=");if(i!==-1&&t.slice(0,i).trim()===a)return t.slice(i+1).trim()}}h(ne,"cookieValue");function R(n,a,t){n.writeHead(a,{"Content-Type":"application/json; charset=utf-8"}),n.end(JSON.stringify(t))}h(R,"json");async function L(n){return await b(async a=>{const t=await N(a,n.id);if(!t||t.deleted_at||t.type!=="document")return null;const i=await $(a,{principal:T}),l=await x(a,t),o=await O(a,t),e=await Z(a,t),u=o.length===1&&await H(a,i,t);return{id:t.id,name:e,revision:l.revision,heads_key:l.heads_key,body:o.length===1?await k(a,t,C(o[0].body_hash,l.source_path)):"",editable:u,...u?{}:{readonly_reason:o.length!==1?`has ${o.length} heads and needs a merge`:await F(a,t)?"shipped by a plugin":"you cannot change this document"}}})}h(L,"snapshot");async function p(n){return await b(async a=>{const t=await $(a,{principal:T});try{const i=await Y(a,t,n);return"deleted"in i||"remote"in i||i.type!=="document"?null:i}catch(i){if(i instanceof I&&i.code==="not_found")return null;throw i}})}h(p,"resolveDocument");async function oe(n){const a=[];let t=0;for await(const i of n){if(t+=i.length,t>2e6)throw new Error("request body exceeds 2 MB");a.push(i)}return JSON.parse(Buffer.concat(a).toString("utf8"))}h(oe,"requestBody");async function ae(n){const a=await b(async t=>{const i=await $(t,{principal:T}),l=await N(t,n.id);if(!l||l.type!=="document"||l.deleted_at)return{status:404,value:{error:{code:"not_found",message:"document not found"}}};const o=await x(t,l),e=await O(t,l);if(e.length!==1||!await H(t,i,l))return{status:403,value:{error:{code:"forbidden",message:"document is read-only"}}};const u=await k(t,l,C(e[0].body_hash,o.source_path)),c=await t.prepareUncached("SELECT body_hash FROM revisions WHERE document = ? AND rev_id = ?").get(l.rowid,n.base_heads_key);if(!c||await k(t,l,C(c.body_hash,o.source_path))!==n.base_body)return{status:409,value:{saved:!1,conflict:{revision:o.revision,heads_key:o.heads_key,current_body:u,your_body:n.body}}};const r=n.base_heads_key!==o.heads_key,s=r?q(n.base_body,n.body,u):n.body;if(s===null)return{status:409,value:{saved:!1,conflict:{revision:o.revision,heads_key:o.heads_key,current_body:u,your_body:n.body}}};const d=await J(t,i,l,{body:s},n.rationale?.trim()||"edited by the person in the browser",o.heads_key,{},async w=>await X(t,w));return"stale"in d?{status:409,value:{saved:!1,conflict:{revision:d.stale.revision,heads_key:d.stale.heads_key,current_body:u,your_body:n.body}}}:{status:200,value:{saved:!0,revision:d.revision,heads_key:d.heads_key,body:s,merged:r},change:await K(t,i,[l])}});return a.change&&await Q(a.change),a}h(ae,"save");let v="the document listener has not started";function $e(){return v}h($e,"documentListenerUnavailable");function Te(n,a){const t=`crtr_doc_${n}`,i=W((o,e)=>{(async()=>{e.setHeader("Content-Security-Policy",te),e.setHeader("X-Content-Type-Options","nosniff");const u=[`127.0.0.1:${n}`,`localhost:${n}`];if(typeof o.headers.host!="string"||!u.includes(o.headers.host))return m(e,403,"forbidden","invalid Host");if(o.method==="POST"){if(!u.some(r=>o.headers.origin===`http://${r}`))return m(e,403,"forbidden","invalid Origin");if(o.headers["content-type"]!=="application/json")return m(e,415,"unsupported_media_type","Content-Type must be application/json")}const c=new URL(o.url??"/",`http://127.0.0.1:${n}`);if(!c.pathname.startsWith("/assets/")){const r=o.method==="GET"&&c.pathname.startsWith("/r/")?c.searchParams.get("t"):null;if(r!==null&&P(r,a))return c.searchParams.delete("t"),e.writeHead(303,{Location:`${c.pathname}${c.search}`,"Set-Cookie":`${t}=${a}; HttpOnly; SameSite=Strict; Path=/`,"Cache-Control":"no-store"}),e.end();const s=ne(o.headers.cookie,t);if(r!==null||s===void 0||!P(s,a))return c.pathname.startsWith("/r/")?(e.writeHead(401,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end('<!doctype html><html><head><meta charset="utf-8"><title>Not authorized</title><link rel="icon" href="data:,"></head><body style="font-family:system-ui,sans-serif;max-width:40rem;margin:4rem auto;padding:0 1rem"><h1>Not authorized</h1><p>Open this document from its link in the attach viewer.</p></body></html>')):m(e,401,"unauthorized","open the document link from the attach viewer")}if(o.method==="GET"&&c.pathname.startsWith("/r/")){let r;try{r=decodeURIComponent(c.pathname.slice(3))}catch{return m(e,400,"invalid_request","ref is not valid percent-encoding")}const s=await p(r);return s?(e.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end(`<!doctype html><html><head><meta charset="utf-8"><title>${S(s.name)}</title><link rel="icon" href="data:,"><link rel="stylesheet" href="/assets/${y}/editor.css"></head><body><div id="app" data-ref="${S(r)}"></div><script type="module" src="/assets/${y}/editor.js"><\/script></body></html>`)):(e.writeHead(404,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end(`<!doctype html><html><head><meta charset="utf-8"><title>Document not found</title><link rel="icon" href="data:,"></head><body style="font-family:system-ui,sans-serif;max-width:40rem;margin:4rem auto;padding:0 1rem"><h1>Document not found</h1><p>No document you can read is named <code>${S(r)}</code>.</p></body></html>`))}if(o.method==="GET"&&c.pathname==="/api/doc"){const r=c.searchParams.get("ref"),s=r?await p(r):null,d=s&&await L(s);return d?R(e,200,{...d,ref:r}):m(e,404,"not_found","document not found")}if(o.method==="POST"&&c.pathname==="/api/save"){const r=await oe(o);if(!r||typeof r!="object"||Array.isArray(r))return m(e,400,"invalid_request","invalid save body");const s=r;if(typeof s.id!="string"||typeof s.base_heads_key!="string"||typeof s.base_body!="string"||typeof s.body!="string"||s.rationale!==void 0&&typeof s.rationale!="string")return m(e,400,"invalid_request","invalid save body");const d=await ae(s);return R(e,d.status,d.value)}if(o.method==="GET"&&c.pathname==="/api/events"){const r=c.searchParams.get("id");if(!r||!await p(r))return m(e,404,"not_found","document not found");e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-store",Connection:"keep-alive"}),e.write(`: connected
|
|
2
2
|
|
|
3
|
-
`);const
|
|
3
|
+
`);const s=h(async _=>{if(_==="deleted"){e.write(`event: deleted
|
|
4
4
|
data: {}
|
|
5
5
|
|
|
6
|
-
`),e.end();return}const
|
|
7
|
-
data: ${JSON.stringify({revision:
|
|
6
|
+
`),e.end();return}const f=await p(r),g=f&&await L(f);g&&e.write(`event: edited
|
|
7
|
+
data: ${JSON.stringify({revision:g.revision,heads_key:g.heads_key})}
|
|
8
8
|
|
|
9
|
-
`)}),
|
|
9
|
+
`)},"notify"),d=await M(r,_=>{s(_).catch(f=>{V({level:"error",event:"daemon.document_events.notify_failed",error:f}),e.end()})}),w=setInterval(()=>e.write(`: keepalive
|
|
10
10
|
|
|
11
|
-
`),3e4);e.on("close",()=>{clearInterval(
|
|
11
|
+
`),3e4);e.on("close",()=>{clearInterval(w),d()});return}if(o.method==="GET"&&c.pathname.startsWith(`/assets/${y}/`)){const r=c.pathname.slice(`/assets/${y}/`.length);if(!/^[a-zA-Z0-9_.-]+$/.test(r))return m(e,404,"not_found","asset not found");const s=r==="mermaid.js"?E(j,"clients/attach/assets/mermaid.min.js"):E(j,"doc-editor",r);try{const d=z(s);return e.writeHead(200,{"Content-Type":B(r)===".css"?"text/css; charset=utf-8":"text/javascript; charset=utf-8","Cache-Control":"public, max-age=31536000, immutable"}),e.end(d)}catch(d){if(d.code==="ENOENT")return m(e,404,"not_found","asset not found");throw d}}return m(e,404,"not_found","route not found")})().catch(u=>{e.headersSent?e.destroy():m(e,500,"server_failure",u instanceof Error?u.message:String(u))})});return{ready:new Promise((o,e)=>{i.once("error",u=>{v=`the document listener could not bind 127.0.0.1:${n}: ${u.message}`,e(u)}),i.listen(n,"127.0.0.1",()=>{i.removeAllListeners("error"),v=void 0,o()})}),close:h(()=>new Promise(o=>{v="the document listener is closed",i.closeAllConnections(),i.close(()=>o())}),"close")}}h(Te,"createDocumentListener");export{Te as createDocumentListener,$e as documentListenerUnavailable};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var u=Object.defineProperty;var o=(e,a)=>u(e,"name",{value:a,configurable:!0});import{listNodes as _}from"../../../core/canvas/canvas.js";import{openDb as l}from"../../../core/canvas/db.js";import{listMemoryReads as h,memoryReadsStartedAt as g}from"../../../core/canvas/memory-reads.js";import{usage as n}from"../../../core/errors.js";import{computeAnalytics as b,WINDOW_MS as R}from"../../analytics/compute.js";import{scanResponses as O}from"../../analytics/scan.js";import{canReadNode as S}from"../router.js";import{filterAsync as E}from"../../../core/async-array.js";const A=new Set(["as_of","window","project"]);async function M(e){for(const[t]of e.query)if(!A.has(t))throw n(`unknown analytics query parameter: ${t}`);const a=e.query.get("as_of")??"",s=Date.parse(a);if(!Number.isFinite(s))throw n(`as_of must be an ISO 8601 time, got "${a}"`);const r=e.query.get("window")??"";if(!Object.hasOwn(R,r))throw n(`window must be 24h or 7d, got "${r}"`);const d=e.query.get("project");if(d==="")throw n("project must be a non-empty directory path when given");const i=new Map,m=await(await l()).prepare("SELECT node_id, transcript_path FROM sessions WHERE transcript_path IS NOT NULL").all();for(const t of m)i.set(t.node_id,(i.get(t.node_id)??new Set).add(t.transcript_path));const w=new Map((await(await l()).prepare("SELECT node_id, title FROM node_rows WHERE title IS NOT NULL").all()).map(t=>[t.node_id,t.title])),c=e.principal,f=(await E(await _(),async t=>t.kind!=="human"&&(c.class==="person"||await S(c,t.grantee??"app:terminal",t.node_id)))).map(t=>({node_id:t.node_id,name:t.name,title:w.get(t.node_id)??null,kind:t.kind,parent:t.parent??null,cwd:t.cwd,created:t.created,finalized_at:t.finalized_at??null,final_report:t.final_report??null,lifecycle:t.lifecycle,transcripts:[...i.get(t.node_id)??[]]})),p=new AbortController;return e.res.once("close",()=>p.abort()),{status:200,body:await b({asOfMs:s,window:r,project:d??null,agents:f,scan:o(t=>O(t,p.signal),"scan"),memory:o(async(t,y)=>({rows:await h(t,y),startedAt:await g()}),"memory")})}}o(M,"handleAnalytics");const D=[{method:"GET",pattern:"/v1/canvas/analytics",handler:M}];export{D as analyticsRoutes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var c=Object.defineProperty;var i=(t,e)=>c(t,"name",{value:e,configurable:!0});import{getNode as m}from"../../../core/canvas/canvas.js";import{decideAttachRevive as k}from"../../../core/runtime/revive.js";import{viewSocketPath as l}from"../../../core/canvas/paths.js";import{waitForBrokerViewSocket as v}from"../../../core/runtime/placement-tmux.js";import{notFound as
|
|
1
|
+
var c=Object.defineProperty;var i=(t,e)=>c(t,"name",{value:e,configurable:!0});import{getNode as m}from"../../../core/canvas/canvas.js";import{decideAttachRevive as k}from"../../../core/runtime/revive.js";import{viewSocketPath as l}from"../../../core/canvas/paths.js";import{waitForBrokerViewSocket as v}from"../../../core/runtime/placement-tmux.js";import{notFound as w,usage as n}from"../../../core/errors.js";import{ownerOnly as p}from"../router.js";function h(t){if(t==null)return{resume:!0,revive:!0,wakeParked:!0};if(typeof t!="object")throw n("attach body must be a JSON object { resume?, revive?, wakeParked? }");const e=t.resume,r=t.revive,o=t.wakeParked;if(e!==void 0&&typeof e!="boolean")throw n("resume must be a boolean");if(r!==void 0&&typeof r!="boolean")throw n("revive must be a boolean");if(o!==void 0&&typeof o!="boolean")throw n("wakeParked must be a boolean");return{resume:e??!0,revive:r??!0,wakeParked:o??!0}}i(h,"parseAttachBody");async function b(t){const e=t.params.id;if(await m(e)===null)throw w(`unknown node: ${e}`,{received:e});const{resume:r,revive:o,wakeParked:f}=h(t.body);let u=!1,d=!1,s=!1;if(o){const a=await k(e,{resume:r,capacity:"refuse"},f);s=a.parked,a.parked||(u=a.result.launch!==void 0,d=a.result.resumed,await v(e))}return{status:200,body:{node_id:e,socket_path:l(e),revived:u,resumed:d,parked:s}}}i(b,"handleAttach");const F=p([{method:"POST",pattern:"/v1/nodes/:id/attach",handler:b}]);export{F as attachRoutes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var B=Object.defineProperty;var h=(
|
|
1
|
+
var B=Object.defineProperty;var h=(t,o)=>B(t,"name",{value:o,configurable:!0});import{killBashJobObject as E,recordBashJobObject as J}from"../../../core/spaces/stop.js";import{readerFor as P}from"../reader.js";import{join as $}from"node:path";import{createFileBeneath as w,existsBeneath as m,unlinkBeneath as A}from"../../../core/spaces/open-beneath.js";import{launchAppProcess as q,appProcessSandboxed as O}from"../../../core/spaces/process.js";import{BASH_JOB_SUPERVISOR_SCRIPT as N}from"../../../core/bash-job-supervisor.js";import{resolveAdmittedHostCommand as L}from"../../../core/runtime/spawn-env.js";import{requireCurrentExecution as _}from"./broker-recovery.js";import{isSafeNodeId as T}from"../../../core/canvas/paths.js";import{contextDir as v}from"../../../core/canvas/node-agent-paths.js";import{getNode as j}from"../../../core/canvas/canvas.js";import{isBrokerLive as D}from"../../../core/runtime/model-swap.js";import{assertNotFinalized as R}from"../../../core/runtime/reopen.js";import{reviveNode as C}from"../../../core/runtime/revive.js";import{activeBackgroundBashJobs as z,bashJobPaths as k,isBashJobProcessGroupAlive as F,readJobPgid as M,readJobPgidIdentity as G,isSafeBashJobId as I,readBashNiceness as H,stopBackgroundBashJob as Z}from"../../../core/bash-jobs.js";import{ApiError as i}from"../../../api/index.js";import{notFound as U}from"../../../core/errors.js";import{freshChildNodeExecPath as V}from"../../../core/runtime/branded-host.js";async function f(t){const o=t.params.id;if(o===void 0||!T(o))throw new i(400,"invalid_node_id",`invalid node id: ${JSON.stringify(o)}`);if(await j(o)===null)throw U(`unknown node: ${o}`,{received:o});const d=t.params.jobId;if(d!==void 0){if(!I(d))throw new i(400,"invalid_job_id",`invalid background job id: ${JSON.stringify(d)}`);return{nodeId:o,jobId:d,dir:await v(o)}}return{nodeId:o,dir:await v(o)}}h(f,"requireTarget");async function X(t){const{nodeId:o,dir:e}=await f(t);if(t.principal.class!=="broker"||t.principal.node!==o)throw new i(403,"permission_error","only this node\u2019s broker may start a job");const d=t.body;if(!d||typeof d!="object"||Array.isArray(d))throw new i(400,"invalid_request","job.start requires a JSON body");const a=d;await _(o,a.expected_execution_id);const r=a.job_id,s=a.cwd,p=a.env;if(typeof r!="string"||!I(r)||typeof s!="string"||!p||typeof p!="object"||Array.isArray(p)||Object.entries(p).some(([c,b])=>!/^[A-Za-z_][A-Za-z0-9_]*$/.test(c)||typeof b!="string"))throw new i(400,"invalid_request","invalid job id, cwd or environment");if(!O())throw new i(400,"invalid_request","job.start is only used with the root launcher");const n=k(e,r);if(!(m(n.root,n.jobRun)||m(n.root,n.jobBg))||![n.cmdSh,n.jobLog].every(c=>m(n.root,c)))throw new i(404,"job_not_found","job was not prepared by this node");const g=$(n.dir,"job.starting");try{w(n.root,g,"")}catch(c){throw c.code==="EEXIST"?new i(409,"job_already_started","job was already started"):c}let l;try{const c=p,b=L("bash",c,s),y=await j(o),S=await V();return l=await q({nodeId:o,app:y.grantee??"app:terminal",isolated:y.isolated,cwd:s,env:c,capture:!1,command:[b,"-c",N,"--",n.cmdSh,n.jobLog,n.jobExit,n.jobRun,n.jobDone,b,String(H(e)),S]}),w(n.root,n.jobPgid,String(l.pid),384),w(n.root,n.jobPgidIdentity,`launcher:${l.pid}`,384),{status:201,body:{pid:l.pid}}}catch(c){if(l!==void 0)try{await l.stop()}catch(b){throw new AggregateError([c,b],`job ${r} launched but could not be recorded or stopped`)}try{A(n.root,g)}catch(b){if(b.code!=="ENOENT")throw b}throw c}}h(X,"handleStart");async function x(t){const{nodeId:o,dir:e}=await f(t),d=Date.now();return{status:200,body:z(e).map(r=>{const s=M(e,r.jobId)??null;return{job_id:r.jobId,command:r.command,purpose:r.purpose,started_at:new Date(r.startedAtMs).toISOString(),elapsed_ms:Math.max(0,d-r.startedAtMs),pgid:s,pgid_alive:s!==null&&F(s,G(e,r.jobId))}})}}h(x,"handleList");async function K(t){const{nodeId:o,jobId:e,dir:d}=await f(t);if(e===void 0)throw new i(400,"invalid_request","a job id is required");const a=t.query.get("foreground")==="1";if(a){if(t.principal.class!=="broker"||t.principal.node!==o)throw new i(403,"permission_error","only this node\u2019s broker may abort its foreground job");await _(o,t.body?.expected_execution_id)}const r=await Z(d,e,a,o);if(r.kind==="missing")throw new i(404,"job_not_found",`no background job ${e} for ${o}`);if(r.kind==="retired")throw new i(404,"job_not_found",`background job ${e} for ${o} is no longer running`,{log_path:r.logPath});if(r.kind==="not-stoppable")throw new i(409,"job_not_stoppable",`job ${e} recorded no trusted process identity`,{log_path:r.logPath});if(a)return{status:200,body:{node_id:o,job_id:e,signaled:r.signaled}};await R(o),await E(e,async n=>{const u=await P(n,t);return u.class==="person"?u.person:u.class==="app"?u.app:u.node});const s=await j(o);if(s!==null&&!D(s))try{await C(o,{resume:!0,capacity:"freeze"})}catch{}return{status:200,body:{node_id:o,job_id:e,signaled:r.signaled}}}h(K,"handleStop");async function Q(t){const{nodeId:o,jobId:e,dir:d}=await f(t);if(e===void 0)throw new i(400,"invalid_request","a job id is required");if(t.principal.class!=="broker"||t.principal.node!==o)throw new i(403,"permission_error","only this node\u2019s broker may record its job");const a=t.body,r=k(d,e);if(typeof a?.command!="string"||a.job_dir!==r.dir||a.log_path!==r.jobLog)throw new i(400,"invalid_request",`job.background requires command, job_dir ${r.dir} and log_path ${r.jobLog}`);if(!m(r.root,r.jobBg))throw new i(404,"job_not_found",`job ${e} of ${o} is not backgrounded`);const s=a.command;return{status:201,body:{id:(await J(o,e,{command:s,jobDir:r.dir,logPath:r.jobLog})).id}}}h(Q,"handleBackground");const jo=[{method:"POST",pattern:"/v1/nodes/:id/jobs/:jobId/background",handler:Q},{method:"POST",pattern:"/v1/nodes/:id/jobs/start",handler:X},{method:"GET",pattern:"/v1/nodes/:id/jobs",handler:x},{method:"DELETE",pattern:"/v1/nodes/:id/jobs/:jobId",handler:K}];export{jo as bashJobRoutes};
|