@north-light/crouter 0.3.348 → 0.3.350
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/bin/crtr-launcher +4 -0
- package/bin/runtime-generation-manifest.mjs +12 -2
- package/dist/api/client.d.ts +50 -7
- package/dist/api/client.js +2 -2
- package/dist/api/command-manifest/schema.js +1 -1
- package/dist/api/dto/analytics.d.ts +184 -0
- package/dist/api/dto/analytics.js +0 -0
- package/dist/api/dto/broker-ops.d.ts +43 -1
- package/dist/api/dto/config.d.ts +11 -0
- package/dist/api/dto/grants.d.ts +14 -0
- package/dist/api/dto/grants.js +0 -0
- package/dist/api/dto/human-requests.d.ts +14 -0
- package/dist/api/dto/memory.d.ts +6 -0
- package/dist/api/dto/modelauth.d.ts +35 -0
- package/dist/api/dto/node-records.d.ts +35 -0
- package/dist/api/dto/node-records.js +0 -0
- package/dist/api/dto/nodes.d.ts +5 -0
- package/dist/api/dto/profiles.d.ts +38 -3
- package/dist/api/dto/worktree.d.ts +11 -0
- package/dist/api/errors.d.ts +23 -1
- package/dist/api/errors.js +1 -1
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +1 -1
- package/dist/api/node-transport.js +1 -1
- package/dist/api/routes.d.ts +22 -0
- package/dist/api/routes.js +1 -1
- package/dist/build-root.d.ts +6 -1
- package/dist/build-root.js +1 -1
- package/dist/builtin-memory/crouter-sdk/client.md +34 -0
- package/dist/builtin-memory/crouter-sdk/errors.md +2 -0
- package/dist/builtin-memory/crouter-sdk/memory.md +2 -2
- package/dist/builtin-memory/crouter-sdk/streaming.md +21 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +8 -4
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +39 -118
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +6 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +41 -27
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +52 -29
- package/dist/cli.js +9 -8
- package/dist/clients/attach/chrome/inbox-strip.js +1 -1
- package/dist/clients/attach/chrome/roster.js +1 -1
- package/dist/clients/attach/config.js +1 -1
- package/dist/clients/attach/overlays/auth.js +2 -2
- package/dist/clients/attach/overlays/graph.js +1 -1
- package/dist/clients/attach/render/tool-calls.js +3 -3
- package/dist/clients/attach/session/connection.js +1 -1
- package/dist/clients/attach/session/profile-files.js +1 -1
- package/dist/clients/attach/viewer.js +1569 -816
- package/dist/commands/api-client.js +3 -3
- package/dist/commands/broker-permissions.d.ts +2 -0
- package/dist/commands/broker-permissions.js +1 -0
- package/dist/commands/canvas-analytics/chart.d.ts +52 -0
- package/dist/commands/canvas-analytics/chart.js +1 -0
- package/dist/commands/canvas-analytics/drilldown.d.ts +34 -0
- package/dist/commands/canvas-analytics/drilldown.js +1 -0
- package/dist/commands/canvas-analytics/format.d.ts +29 -0
- package/dist/commands/canvas-analytics/format.js +1 -0
- package/dist/commands/canvas-analytics/graph-detail.d.ts +2 -0
- package/dist/commands/canvas-analytics/graph-detail.js +2 -0
- package/dist/commands/canvas-analytics/graphs.d.ts +9 -0
- package/dist/commands/canvas-analytics/graphs.js +1 -0
- package/dist/commands/canvas-analytics/memory.d.ts +2 -0
- package/dist/commands/canvas-analytics/memory.js +1 -0
- package/dist/commands/canvas-analytics/overview.d.ts +2 -0
- package/dist/commands/canvas-analytics/overview.js +1 -0
- package/dist/commands/canvas-analytics/shell.d.ts +60 -0
- package/dist/commands/canvas-analytics/shell.js +2 -0
- package/dist/commands/canvas-analytics/time.d.ts +2 -0
- package/dist/commands/canvas-analytics/time.js +1 -0
- package/dist/commands/canvas-analytics/usage.d.ts +2 -0
- package/dist/commands/canvas-analytics/usage.js +1 -0
- package/dist/commands/canvas-analytics/view.d.ts +85 -0
- package/dist/commands/canvas-analytics/view.js +1 -0
- package/dist/commands/canvas-analytics.d.ts +2 -0
- package/dist/commands/canvas-analytics.js +1 -0
- package/dist/commands/canvas-prune.js +1 -1
- package/dist/commands/canvas.js +1 -1
- package/dist/commands/cron.js +5 -5
- package/dist/commands/human/components.d.ts +2 -0
- package/dist/commands/human/components.js +2 -2
- package/dist/commands/human/prompts.js +1 -1
- package/dist/commands/human/queue.js +1 -1
- package/dist/commands/memory/client.d.ts +11 -0
- package/dist/commands/memory/client.js +1 -0
- package/dist/commands/memory/delete.js +1 -1
- package/dist/commands/memory/edit.js +3 -3
- package/dist/commands/memory/find.js +1 -1
- package/dist/commands/memory/history.js +4 -4
- package/dist/commands/memory/lint.js +1 -1
- package/dist/commands/memory/list.d.ts +0 -2
- package/dist/commands/memory/list.js +1 -1
- package/dist/commands/memory/move.js +1 -1
- package/dist/commands/memory/origin.js +1 -1
- package/dist/commands/memory/read.d.ts +0 -5
- package/dist/commands/memory/read.js +3 -3
- package/dist/commands/memory/shared.d.ts +0 -178
- package/dist/commands/memory/shared.js +1 -12
- package/dist/commands/memory/write.js +5 -5
- package/dist/commands/node/bash.js +5 -5
- package/dist/commands/node/create.d.ts +0 -17
- package/dist/commands/node/create.js +2 -3
- package/dist/commands/node/inspect.js +6 -6
- package/dist/commands/node/lifecycle.js +2 -2
- package/dist/commands/node-context.js +2 -2
- package/dist/commands/node-inspect-artifacts.js +6 -6
- package/dist/commands/pkg/browse/catalog.js +1 -1
- package/dist/commands/pkg/browse/model.d.ts +1 -1
- package/dist/commands/pkg/market-manage.js +1 -1
- package/dist/commands/pkg/plugin-manage.js +10 -10
- package/dist/commands/profile/daemon-profiles.d.ts +13 -0
- package/dist/commands/profile/daemon-profiles.js +4 -0
- package/dist/commands/profile/delete.js +1 -1
- package/dist/commands/profile/env.d.ts +6 -0
- package/dist/commands/profile/env.js +2 -2
- package/dist/commands/profile/kind.js +1 -2
- package/dist/commands/profile/list.js +1 -1
- package/dist/commands/profile/meta.js +1 -1
- package/dist/commands/profile/new.js +1 -1
- package/dist/commands/profile/pause.js +1 -1
- package/dist/commands/profile/project.js +1 -1
- package/dist/commands/profile/rename.js +1 -1
- package/dist/commands/profile/show.js +1 -1
- package/dist/commands/profile.js +1 -1
- package/dist/commands/push.js +3 -3
- package/dist/commands/surface-inspect.js +1 -1
- package/dist/commands/sys/branch.js +1 -1
- package/dist/commands/sys/config.js +1 -1
- package/dist/commands/sys/connect.js +3 -3
- package/dist/commands/sys/context/admin/actions.js +1 -1
- package/dist/commands/sys/context/admin/model.d.ts +1 -0
- package/dist/commands/sys/context/admin/model.js +1 -1
- package/dist/commands/sys/context/admin.js +1 -1
- package/dist/commands/sys/context/expose.js +2 -1
- package/dist/commands/sys/context/prompt-review.js +2 -2
- package/dist/commands/sys/context/resolve.js +7 -7
- package/dist/commands/sys/context/sysprompt.js +1 -1
- package/dist/commands/sys/join.d.ts +1 -0
- package/dist/commands/sys/join.js +1 -0
- package/dist/commands/sys/migrate.js +1 -1
- package/dist/commands/sys/panels/models-panel.js +1 -1
- package/dist/commands/sys/panels/profiles-panel.d.ts +0 -1
- package/dist/commands/sys/panels/profiles-panel.js +1 -1
- package/dist/commands/sys/provider-login.js +6 -6
- package/dist/commands/sys/setup-core.d.ts +1 -1
- package/dist/commands/sys/setup-core.js +6 -6
- package/dist/commands/sys/setup-settings-runner.js +1 -1
- package/dist/commands/sys/setup.js +1 -1
- package/dist/commands/sys/spaces.d.ts +1 -0
- package/dist/commands/sys/spaces.js +2 -0
- package/dist/commands/sys/sync-deps.js +2 -2
- package/dist/commands/sys/sync-project-guidance.js +4 -4
- package/dist/commands/sys/sync-skills.js +2 -2
- package/dist/commands/sys/worktrees.d.ts +1 -0
- package/dist/commands/sys/worktrees.js +1 -1
- package/dist/commands/sys.js +1 -1
- package/dist/core/auth-file.js +2 -2
- package/dist/core/bash-job-supervisor.d.ts +6 -0
- package/dist/core/bash-job-supervisor.js +4 -0
- package/dist/core/bash-jobs.d.ts +13 -6
- package/dist/core/bash-jobs.js +8 -7
- package/dist/core/broker-client/transport-relay.d.ts +6 -3
- package/dist/core/broker-client/transport-relay.js +1 -1
- package/dist/core/broker-client/transport-socket.d.ts +6 -1
- package/dist/core/broker-client/transport-socket.js +1 -1
- package/dist/core/canvas/canvas.d.ts +39 -18
- package/dist/core/canvas/canvas.js +21 -20
- package/dist/core/canvas/context-strip.d.ts +20 -0
- package/dist/core/canvas/context-strip.js +5 -0
- package/dist/core/canvas/crons.d.ts +12 -20
- package/dist/core/canvas/crons.js +15 -13
- package/dist/core/canvas/db.js +2 -2
- package/dist/core/canvas/deliveries.d.ts +4 -1
- package/dist/core/canvas/deliveries.js +1 -1
- package/dist/core/canvas/executions.js +1 -1
- package/dist/core/canvas/history.d.ts +2 -1
- package/dist/core/canvas/history.js +17 -18
- package/dist/core/canvas/memory-reads.d.ts +19 -0
- package/dist/core/canvas/memory-reads.js +1 -0
- package/dist/core/canvas/migrations.d.ts +0 -4
- package/dist/core/canvas/migrations.js +99 -32
- package/dist/core/canvas/nav-render.js +1 -1
- package/dist/core/canvas/node-agent-paths.d.ts +8 -0
- package/dist/core/canvas/node-agent-paths.js +1 -0
- package/dist/core/canvas/node-recap.d.ts +2 -2
- package/dist/core/canvas/node-recap.js +2 -2
- package/dist/core/canvas/node-tokens.d.ts +24 -0
- package/dist/core/canvas/node-tokens.js +5 -0
- package/dist/core/canvas/paths.d.ts +16 -19
- package/dist/core/canvas/paths.js +1 -1
- package/dist/core/canvas/render-source.d.ts +2 -2
- package/dist/core/canvas/render-source.js +6 -9
- package/dist/core/canvas/sessions.d.ts +18 -0
- package/dist/core/canvas/sessions.js +4 -1
- package/dist/core/canvas/types.d.ts +22 -6
- package/dist/core/command-hooks/compose.js +1 -1
- package/dist/core/command-hooks/discovery.d.ts +15 -1
- package/dist/core/command-hooks/discovery.js +1 -1
- package/dist/core/command-hooks/help.d.ts +2 -2
- package/dist/core/command-hooks/lifecycle-create.d.ts +1 -1
- package/dist/core/command-hooks/lifecycle-create.js +1 -1
- package/dist/core/command-hooks/transport/exec-invoke.d.ts +2 -0
- package/dist/core/command-hooks/transport/exec-invoke.js +1 -1
- package/dist/core/command-hooks/transport/exec-lifecycle.d.ts +1 -0
- package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
- package/dist/core/command-hooks/transport/plan.d.ts +3 -0
- package/dist/core/command-hooks/transport/plan.js +1 -0
- package/dist/core/command-plugins/discovery.js +1 -1
- package/dist/core/command-plugins/transport/http-invoke.js +2 -2
- package/dist/core/command.d.ts +6 -2
- package/dist/core/command.js +6 -6
- package/dist/core/config.d.ts +8 -5
- package/dist/core/config.js +1 -1
- package/dist/core/conversation-store/client-worker.d.ts +1 -0
- package/dist/core/conversation-store/client-worker.js +1 -0
- package/dist/core/conversation-store/client.d.ts +2 -0
- package/dist/core/conversation-store/client.js +2 -0
- package/dist/core/conversation-store/file-store.d.ts +37 -0
- package/dist/core/conversation-store/file-store.js +9 -0
- package/dist/core/conversation-store/index.d.ts +50 -0
- package/dist/core/conversation-store/index.js +1 -0
- package/dist/core/conversation-store/listener.d.ts +4 -0
- package/dist/core/conversation-store/listener.js +3 -0
- package/dist/core/conversation-store/patch.d.ts +1 -0
- package/dist/core/conversation-store/patch.js +1 -0
- package/dist/core/directory/join.d.ts +27 -0
- package/dist/core/directory/join.js +1 -0
- package/dist/core/disk-usage.d.ts +4 -0
- package/dist/core/disk-usage.js +1 -0
- package/dist/core/events/emit.d.ts +2 -0
- package/dist/core/events/emit.js +3 -1
- package/dist/core/feed/feed.js +4 -4
- package/dist/core/feed/messages.d.ts +3 -0
- package/dist/core/feed/messages.js +6 -6
- package/dist/core/fs-utils.d.ts +2 -0
- package/dist/core/fs-utils.js +3 -3
- package/dist/core/grants/local.d.ts +4 -0
- package/dist/core/grants/local.js +1 -0
- package/dist/core/grants/mirror.d.ts +44 -0
- package/dist/core/grants/mirror.js +4 -0
- package/dist/core/grants/on-sync.d.ts +22 -0
- package/dist/core/grants/on-sync.js +1 -0
- package/dist/core/grants/remove.d.ts +7 -0
- package/dist/core/grants/remove.js +1 -0
- package/dist/core/grants/sandboxes.d.ts +7 -0
- package/dist/core/grants/sandboxes.js +1 -0
- package/dist/core/grants/sync.d.ts +12 -0
- package/dist/core/grants/sync.js +1 -0
- package/dist/core/help/memory-extensions.d.ts +3 -0
- package/dist/core/help/memory-extensions.js +2 -0
- package/dist/core/help.d.ts +14 -0
- package/dist/core/help.js +7 -7
- package/dist/core/host-exports/builtins.js +3 -3
- package/dist/core/host-exports/export.js +3 -3
- package/dist/core/human/action-binding.d.ts +2 -0
- package/dist/core/human/action-binding.js +1 -1
- package/dist/core/human/feedback-companion.d.ts +0 -1
- package/dist/core/human/feedback-companion.js +1 -1
- package/dist/core/human/page-schema.d.ts +1 -1
- package/dist/core/inspector/core.d.ts +2 -0
- package/dist/core/inspector/core.js +1 -1
- package/dist/core/inspector/tui.js +2 -2
- package/dist/core/installed-plugins.js +1 -1
- package/dist/core/io.js +6 -6
- package/dist/core/keybindings/catalog.d.ts +1 -1
- package/dist/core/keybindings/catalog.js +1 -1
- package/dist/core/layout-migrate/index.d.ts +15 -0
- package/dist/core/layout-migrate/index.js +4 -0
- package/dist/core/layout-migrate/paths.d.ts +26 -0
- package/dist/core/layout-migrate/paths.js +1 -0
- package/dist/core/layout-migrate/stored-paths.d.ts +2 -0
- package/dist/core/layout-migrate/stored-paths.js +11 -0
- package/dist/core/layout-migrate/stores.d.ts +17 -0
- package/dist/core/layout-migrate/stores.js +4 -0
- package/dist/core/layout.d.ts +26 -0
- package/dist/core/layout.js +2 -0
- package/dist/core/llm/run.d.ts +60 -0
- package/dist/core/llm/run.js +4 -0
- package/dist/core/memory/cli-selector.d.ts +13 -0
- package/dist/core/memory/cli-selector.js +1 -0
- package/dist/core/memory/history.d.ts +5 -4
- package/dist/core/memory/history.js +6 -6
- package/dist/core/memory/inline-ref-inventory.d.ts +2 -1
- package/dist/core/memory/inline-ref-inventory.js +1 -1
- package/dist/core/memory/lint.js +2 -2
- package/dist/core/memory/mutation-domain.d.ts +2 -2
- package/dist/core/memory/mutation-domain.js +8 -7
- package/dist/core/memory/mutations.js +1 -1
- package/dist/core/memory/service.d.ts +5 -0
- package/dist/core/memory/service.js +2 -2
- package/dist/core/memory-resolver.d.ts +11 -7
- package/dist/core/memory-resolver.js +2 -2
- package/dist/core/model-auth/daemon-login.d.ts +13 -0
- package/dist/core/model-auth/daemon-login.js +1 -0
- package/dist/core/model-auth/flows.d.ts +45 -0
- package/dist/core/model-auth/flows.js +1 -0
- package/dist/core/model-auth/handoff-jti.d.ts +4 -0
- package/dist/core/model-auth/handoff-jti.js +1 -0
- package/dist/core/model-routes.js +1 -1
- package/dist/core/nested-stores.d.ts +2 -1
- package/dist/core/nested-stores.js +1 -2
- package/dist/core/preview-registry.js +2 -2
- package/dist/core/profiles/env-store.js +2 -2
- package/dist/core/profiles/manifest.d.ts +16 -5
- package/dist/core/profiles/manifest.js +1 -1
- package/dist/core/provider-management.js +1 -1
- package/dist/core/review/birth.js +1 -1
- package/dist/core/review/companion.d.ts +0 -2
- package/dist/core/review/companion.js +1 -1
- package/dist/core/review/fork.js +2 -2
- package/dist/core/review/realize.js +1 -1
- package/dist/core/review/stage.d.ts +1 -1
- package/dist/core/review/stage.js +1 -1
- package/dist/core/review/types.d.ts +1 -1
- package/dist/core/runs/events.d.ts +34 -0
- package/dist/core/runs/events.js +1 -0
- package/dist/core/runs/operations.d.ts +43 -0
- package/dist/core/runs/operations.js +12 -0
- package/dist/core/runtime/bearings-render.d.ts +2 -2
- package/dist/core/runtime/bearings-render.js +11 -11
- package/dist/core/runtime/bearings.js +2 -2
- package/dist/core/runtime/broker/cli-relay.d.ts +5 -0
- package/dist/core/runtime/broker/cli-relay.js +1 -0
- package/dist/core/runtime/broker/client-registry.d.ts +0 -5
- package/dist/core/runtime/broker/client-registry.js +1 -1
- package/dist/core/runtime/broker/daemon-ops.d.ts +28 -1
- package/dist/core/runtime/broker/daemon-ops.js +1 -1
- package/dist/core/runtime/broker/engine-drive.d.ts +0 -2
- package/dist/core/runtime/broker/engine-drive.js +1 -1
- package/dist/core/runtime/broker/fault-retry.d.ts +9 -0
- package/dist/core/runtime/broker/fault-retry.js +1 -1
- package/dist/core/runtime/broker/frame-dispatch.d.ts +5 -9
- package/dist/core/runtime/broker/frame-dispatch.js +1 -1
- package/dist/core/runtime/broker/frame-engine-control.d.ts +3 -2
- package/dist/core/runtime/broker/frame-engine-control.js +1 -1
- package/dist/core/runtime/broker/frame-memory-refs.d.ts +4 -3
- package/dist/core/runtime/broker/frame-memory-refs.js +1 -1
- package/dist/core/runtime/broker/frame-read.js +1 -1
- package/dist/core/runtime/broker/frame-session.js +1 -1
- package/dist/core/runtime/broker/held-deferred-inbox.d.ts +3 -1
- package/dist/core/runtime/broker/held-deferred-inbox.js +1 -1
- package/dist/core/runtime/broker/inbox.d.ts +1 -2
- package/dist/core/runtime/broker/inbox.js +7 -10
- package/dist/core/runtime/broker/model-adapter.d.ts +9 -0
- package/dist/core/runtime/broker/model-adapter.js +2 -0
- package/dist/core/runtime/broker/node-token.d.ts +3 -0
- package/dist/core/runtime/broker/node-token.js +1 -0
- package/dist/core/runtime/broker/read-ops.js +1 -1
- package/dist/core/runtime/broker/rebind.d.ts +2 -0
- package/dist/core/runtime/broker/rebind.js +1 -1
- package/dist/core/runtime/broker/tool-groups.js +1 -1
- package/dist/core/runtime/broker/turn-ignition.d.ts +3 -3
- package/dist/core/runtime/broker/turn-ignition.js +1 -1
- package/dist/core/runtime/broker-cli.js +3 -3
- package/dist/core/runtime/broker-extension-render.d.ts +2 -5
- package/dist/core/runtime/broker-extension-render.js +4 -4
- package/dist/core/runtime/broker-persona-guidance.js +3 -3
- package/dist/core/runtime/broker-protocol.d.ts +7 -8
- package/dist/core/runtime/broker.js +1 -1
- package/dist/core/runtime/canvas-extensions.d.ts +1 -0
- package/dist/core/runtime/canvas-extensions.js +1 -1
- package/dist/core/runtime/close.d.ts +9 -0
- package/dist/core/runtime/close.js +1 -1
- package/dist/core/runtime/deliver-live.js +1 -1
- package/dist/core/runtime/fleet.d.ts +1 -1
- package/dist/core/runtime/front-door-login.js +1 -1
- package/dist/core/runtime/front-door.js +2 -2
- package/dist/core/runtime/headless-pi.d.ts +1 -1
- package/dist/core/runtime/headless-pi.js +1 -1
- package/dist/core/runtime/host.d.ts +1 -1
- package/dist/core/runtime/host.js +3 -1
- package/dist/core/runtime/invocation.d.ts +3 -0
- package/dist/core/runtime/kickoff.d.ts +1 -0
- package/dist/core/runtime/kickoff.js +16 -16
- package/dist/core/runtime/launch-target.d.ts +1 -1
- package/dist/core/runtime/launch-target.js +1 -1
- package/dist/core/runtime/launch.d.ts +10 -35
- package/dist/core/runtime/launch.js +1 -1
- package/dist/core/runtime/lifecycle.js +2 -2
- package/dist/core/runtime/memory.d.ts +1 -1
- package/dist/core/runtime/memory.js +1 -1
- package/dist/core/runtime/model-registry.js +1 -1
- package/dist/core/runtime/model-swap.d.ts +17 -19
- package/dist/core/runtime/model-swap.js +1 -1
- package/dist/core/runtime/node-read.js +3 -2
- package/dist/core/runtime/nodes.d.ts +7 -0
- package/dist/core/runtime/nodes.js +1 -1
- package/dist/core/runtime/outcome-document.js +1 -1
- package/dist/core/runtime/package-health.js +2 -2
- package/dist/core/runtime/persona.js +2 -2
- package/dist/core/runtime/pi-vendored.js +1 -1
- package/dist/core/runtime/placement-tmux.d.ts +1 -1
- package/dist/core/runtime/placement-tmux.js +1 -1
- package/dist/core/runtime/placement.js +1 -1
- package/dist/core/runtime/promote.js +1 -1
- package/dist/core/runtime/provider-credential-gate.js +2 -2
- package/dist/core/runtime/recovery-hold.d.ts +2 -0
- package/dist/core/runtime/recovery-hold.js +1 -0
- package/dist/core/runtime/recycle.js +1 -1
- package/dist/core/runtime/reopen.js +1 -1
- package/dist/core/runtime/reset.js +1 -1
- package/dist/core/runtime/revive.d.ts +1 -1
- package/dist/core/runtime/revive.js +2 -3
- package/dist/core/runtime/roadmap.js +4 -4
- package/dist/core/runtime/run-command.d.ts +6 -0
- package/dist/core/runtime/run-command.js +1 -1
- package/dist/core/runtime/session-branch.d.ts +2 -8
- package/dist/core/runtime/session-branch.js +1 -1
- package/dist/core/runtime/session-list-cache.d.ts +6 -22
- package/dist/core/runtime/session-list-cache.js +1 -1
- package/dist/core/runtime/situational-context.js +2 -2
- package/dist/core/runtime/spawn-env.d.ts +6 -6
- package/dist/core/runtime/spawn-env.js +1 -1
- package/dist/core/runtime/spawn.d.ts +5 -0
- package/dist/core/runtime/spawn.js +2 -2
- package/dist/core/runtime/stop-guard.js +2 -2
- package/dist/core/runtime/stop-signals.d.ts +2 -2
- package/dist/core/runtime/stop-signals.js +1 -1
- package/dist/core/runtime/structured-output.d.ts +10 -4
- package/dist/core/runtime/structured-output.js +4 -4
- package/dist/core/runtime/tmux-bindings.js +3 -3
- package/dist/core/runtime/tmux-driver.d.ts +4 -0
- package/dist/core/runtime/tmux-driver.js +7 -7
- package/dist/core/runtime/view-socket.d.ts +9 -2
- package/dist/core/runtime/view-socket.js +1 -1
- package/dist/core/runtime/warm-pool.js +1 -1
- package/dist/core/scope.d.ts +3 -2
- package/dist/core/scope.js +1 -1
- package/dist/core/scoped-state/db.js +1 -1
- package/dist/core/scoped-state/migrate.js +3 -3
- package/dist/core/scoped-state/profiles.d.ts +2 -1
- package/dist/core/scoped-state/profiles.js +1 -1
- package/dist/core/scoped-state/schema.d.ts +2 -1
- package/dist/core/scoped-state/schema.js +4 -4
- package/dist/core/scopes.d.ts +2 -2
- package/dist/core/scopes.js +1 -1
- package/dist/core/secrets.d.ts +1 -0
- package/dist/core/secrets.js +2 -2
- package/dist/core/spaces/mounts.d.ts +32 -0
- package/dist/core/spaces/mounts.js +1 -0
- package/dist/core/spaces/open-beneath.d.ts +71 -0
- package/dist/core/spaces/open-beneath.js +1 -0
- package/dist/core/spaces/permissions.d.ts +46 -0
- package/dist/core/spaces/permissions.js +1 -0
- package/dist/core/spaces/process.d.ts +27 -0
- package/dist/core/spaces/process.js +1 -0
- package/dist/core/spaces/space.d.ts +8 -0
- package/dist/core/spaces/space.js +2 -0
- package/dist/core/spaces/stop.d.ts +8 -0
- package/dist/core/spaces/stop.js +2 -0
- package/dist/core/spaces/users.d.ts +19 -0
- package/dist/core/spaces/users.js +1 -0
- package/dist/core/subscription-state.d.ts +2 -0
- package/dist/core/subscription-state.js +3 -3
- package/dist/core/substrate/frontmatter-validation.js +1 -1
- package/dist/core/substrate/injected-store.d.ts +28 -3
- package/dist/core/substrate/injected-store.js +2 -1
- package/dist/core/substrate/listings.js +1 -1
- package/dist/core/substrate/memory-events.d.ts +6 -0
- package/dist/core/substrate/memory-events.js +1 -0
- package/dist/core/substrate/on-read-node.js +1 -1
- package/dist/core/substrate/on-read.d.ts +6 -6
- package/dist/core/substrate/on-read.js +5 -5
- package/dist/core/substrate/plan.js +1 -1
- package/dist/core/substrate/render-node.js +1 -1
- package/dist/core/substrate/render.d.ts +4 -3
- package/dist/core/substrate/render.js +38 -38
- package/dist/core/substrate/schema.d.ts +6 -0
- package/dist/core/substrate/schema.js +1 -1
- package/dist/core/tui/panel.js +1 -1
- package/dist/core/user-settings.d.ts +12 -0
- package/dist/core/user-settings.js +1 -1
- package/dist/core/worktree-mutation-async.js +5 -5
- package/dist/core/worktree-quarantine.js +1 -1
- package/dist/core/worktree-remove.d.ts +15 -0
- package/dist/core/worktree-remove.js +1 -0
- package/dist/core/worktree-sweep.js +6 -6
- package/dist/daemon/analytics/compute.d.ts +37 -0
- package/dist/daemon/analytics/compute.js +1 -0
- package/dist/daemon/analytics/scan-worker.d.ts +1 -0
- package/dist/daemon/analytics/scan-worker.js +2 -0
- package/dist/daemon/analytics/scan.d.ts +37 -0
- package/dist/daemon/analytics/scan.js +1 -0
- package/dist/daemon/api/app-listener.d.ts +11 -0
- package/dist/daemon/api/app-listener.js +21 -0
- package/dist/daemon/api/bridge.js +5 -5
- package/dist/daemon/api/handlers/analytics.d.ts +2 -0
- package/dist/daemon/api/handlers/analytics.js +1 -0
- package/dist/daemon/api/handlers/attach.js +1 -1
- package/dist/daemon/api/handlers/bash-jobs.js +2 -2
- package/dist/daemon/api/handlers/bash.js +1 -1
- package/dist/daemon/api/handlers/broker-ops.js +1 -1
- package/dist/daemon/api/handlers/canvas.d.ts +1 -1
- package/dist/daemon/api/handlers/canvas.js +6 -6
- package/dist/daemon/api/handlers/crons.js +1 -1
- package/dist/daemon/api/handlers/files.d.ts +1 -1
- package/dist/daemon/api/handlers/files.js +1 -1
- package/dist/daemon/api/handlers/health.js +2 -2
- package/dist/daemon/api/handlers/hook-exec.d.ts +2 -0
- package/dist/daemon/api/handlers/hook-exec.js +1 -0
- package/dist/daemon/api/handlers/human-requests.js +1 -1
- package/dist/daemon/api/handlers/inbox.js +1 -1
- package/dist/daemon/api/handlers/llm.d.ts +2 -0
- package/dist/daemon/api/handlers/llm.js +3 -0
- package/dist/daemon/api/handlers/memory-reads.d.ts +4 -0
- package/dist/daemon/api/handlers/memory-reads.js +1 -0
- package/dist/daemon/api/handlers/memory.js +5 -1
- package/dist/daemon/api/handlers/messages.js +2 -2
- package/dist/daemon/api/handlers/modelauth.js +1 -1
- package/dist/daemon/api/handlers/node-outcomes.js +1 -1
- package/dist/daemon/api/handlers/node-records.d.ts +2 -0
- package/dist/daemon/api/handlers/node-records.js +3 -0
- package/dist/daemon/api/handlers/nodes.d.ts +1 -1
- package/dist/daemon/api/handlers/nodes.js +1 -1
- package/dist/daemon/api/handlers/profiles.d.ts +4 -1
- package/dist/daemon/api/handlers/profiles.js +1 -1
- package/dist/daemon/api/handlers/reports.js +5 -3
- package/dist/daemon/api/handlers/reviews.d.ts +1 -1
- package/dist/daemon/api/handlers/reviews.js +1 -1
- package/dist/daemon/api/handlers/run-routes.d.ts +2 -0
- package/dist/daemon/api/handlers/run-routes.js +1 -0
- package/dist/daemon/api/handlers/runs.d.ts +9 -0
- package/dist/daemon/api/handlers/runs.js +1 -0
- package/dist/daemon/api/handlers/subscriptions.js +1 -1
- package/dist/daemon/api/handlers/worktree.js +1 -1
- package/dist/daemon/api/map.d.ts +10 -4
- package/dist/daemon/api/map.js +2 -2
- package/dist/daemon/api/operations.d.ts +18 -0
- package/dist/daemon/api/operations.js +1 -0
- package/dist/daemon/api/principal.d.ts +42 -0
- package/dist/daemon/api/principal.js +1 -0
- package/dist/daemon/api/router.d.ts +27 -3
- package/dist/daemon/api/router.js +1 -1
- package/dist/daemon/api/server.d.ts +4 -0
- package/dist/daemon/api/server.js +1 -1
- package/dist/daemon/api/vendor-signin.d.ts +7 -0
- package/dist/daemon/api/vendor-signin.js +77 -0
- package/dist/daemon/api/viewer-presence.d.ts +3 -0
- package/dist/daemon/api/viewer-presence.js +1 -0
- package/dist/daemon/cron/armed-context.d.ts +4 -0
- package/dist/daemon/cron/armed-context.js +1 -1
- package/dist/daemon/cron/escalation.js +3 -3
- package/dist/daemon/cron/lease-recovery.js +1 -1
- package/dist/daemon/cron/sinks.js +2 -2
- package/dist/daemon/cron-run.d.ts +5 -5
- package/dist/daemon/cron-run.js +1 -1
- package/dist/daemon/crtrd-cli.js +1 -1
- package/dist/daemon/crtrd.js +8 -7
- package/dist/daemon/delivery/run-delivery.d.ts +4 -0
- package/dist/daemon/delivery/run-delivery.js +1 -1
- package/dist/daemon/fleet.d.ts +1 -1
- package/dist/daemon/fleet.js +6 -6
- package/dist/daemon/http-dispatcher.d.ts +1 -0
- package/dist/daemon/http-dispatcher.js +1 -0
- package/dist/daemon/human/finish.js +7 -7
- package/dist/daemon/joined-owner.d.ts +5 -0
- package/dist/daemon/joined-owner.js +1 -0
- package/dist/daemon/manage.js +2 -2
- package/dist/daemon/messaging/node-message.js +1 -1
- package/dist/daemon/park-activity.js +1 -1
- package/dist/daemon/reconcilers/bash-deadline.js +1 -1
- package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
- package/dist/daemon/reconcilers/broker-supervision.js +4 -4
- package/dist/daemon/reconcilers/delivery-lane.js +1 -1
- package/dist/daemon/reconcilers/live-obligation.d.ts +7 -0
- package/dist/daemon/reconcilers/live-obligation.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +20 -1
- package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
- package/dist/daemon/runs/append-section.d.ts +6 -0
- package/dist/daemon/runs/append-section.js +2 -0
- package/dist/daemon/runs/observer.d.ts +5 -0
- package/dist/daemon/runs/observer.js +4 -0
- package/dist/launcher/bwrap.d.ts +4 -0
- package/dist/launcher/bwrap.js +2 -0
- package/dist/launcher/client.d.ts +2 -0
- package/dist/launcher/client.js +3 -0
- package/dist/launcher/main.d.ts +1 -0
- package/dist/launcher/main.js +3 -0
- package/dist/launcher/netrule.d.ts +1 -0
- package/dist/launcher/netrule.js +1 -0
- package/dist/launcher/seccomp.d.ts +1 -0
- package/dist/launcher/seccomp.js +1 -0
- package/dist/launcher/spec.d.ts +88 -0
- package/dist/launcher/spec.js +1 -0
- package/dist/launcher/users.d.ts +18 -0
- package/dist/launcher/users.js +7 -0
- package/dist/launcher/validate.d.ts +22 -0
- package/dist/launcher/validate.js +1 -0
- package/dist/migrations/corpus.js +3 -3
- package/dist/migrations/runner.js +1 -1
- package/dist/native/linux/addon.node +0 -0
- package/dist/native/linux.d.ts +29 -0
- package/dist/native/linux.js +1 -0
- package/dist/pi-extensions/broker-local.js +2 -2
- package/dist/pi-extensions/canvas-bash-valve.d.ts +1 -3
- package/dist/pi-extensions/canvas-bash-valve.js +4 -7
- package/dist/pi-extensions/canvas-context-intro.d.ts +1 -2
- package/dist/pi-extensions/canvas-context-intro.js +2 -2
- package/dist/pi-extensions/canvas-doc-substrate.js +6 -6
- package/dist/pi-extensions/canvas-inbox-watcher.d.ts +2 -1
- package/dist/pi-extensions/canvas-inbox-watcher.js +2 -1
- package/dist/pi-extensions/canvas-passive-context.d.ts +1 -1
- package/dist/pi-extensions/canvas-passive-context.js +11 -11
- package/dist/pi-extensions/canvas-recap.js +6 -6
- package/dist/pi-extensions/canvas-stophook.js +1 -1
- package/dist/pi-extensions/canvas-structured-output.js +4 -4
- package/dist/pi-extensions/canvas-tool-guide.js +1 -1
- package/dist/pi-extensions/system-prompt-entry.d.ts +15 -0
- package/dist/pi-extensions/system-prompt-entry.js +1 -0
- package/dist/shared/env.d.ts +5 -1
- package/dist/shared/env.js +1 -1
- package/dist/shared/strip-cd-prefix.d.ts +1 -0
- package/dist/shared/strip-cd-prefix.js +1 -0
- package/dist/types.d.ts +31 -15
- package/docs/cli/memory-and-preferences.md +3 -1
- package/docs/sdk/client.md +34 -0
- package/docs/sdk/errors.md +2 -0
- package/docs/sdk/memory.md +2 -2
- package/docs/sdk/streaming.md +21 -0
- package/package.json +19 -4
- package/packages/crouter-identity/dist/index.d.ts +54 -0
- package/packages/crouter-identity/dist/index.js +166 -0
- package/packages/crouter-identity/package.json +33 -0
- package/runtime.lock.json +44 -8
- package/scripts/build-native-linux.mjs +16 -0
- package/scripts/install-runtime.mjs +9 -7
- package/scripts/lib/isolation-env.mjs +42 -0
- package/scripts/runtime-smoke.mjs +49 -0
- package/src/native/linux/addon.c +249 -0
- package/dist/core/profiles/state-block.d.ts +0 -4
- package/dist/core/profiles/state-block.js +0 -3
- package/dist/core/runtime/broker/auth-reload.d.ts +0 -41
- package/dist/core/runtime/broker/auth-reload.js +0 -1
- package/dist/core/substrate/cli-context-delivery.d.ts +0 -22
- package/dist/core/substrate/cli-context-delivery.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
var L=Object.defineProperty;var s=(t,o)=>L(t,"name",{value:o,configurable:!0});import{createServer as O}from"node:http";import{chmodSync as J,existsSync as U,unlinkSync as P}from"node:fs";import{apiSocketPath as D}from"../../core/canvas/paths.js";import{readConfig as F}from"../../core/config.js";import{getApiToken as M,listScopedApiTokens as $}from"../../core/secrets.js";import{emitEvent as A}from"../../core/events/emit.js";import{envCrtrdTcp as W,envCrtrdToken as Y}from"../../shared/env.js";import{Router as N}from"./router.js";import{handleAttachUpgrade as Z,refuseUpgrade as b}from"./bridge.js";import{boundDaemonControl as K}from"../control.js";import{attachRoutes as Q}from"./handlers/attach.js";import{bashJobRoutes as V}from"./handlers/bash-jobs.js";import{bashRoutes as X}from"./handlers/bash.js";import{brokerOperationRoutes as H}from"./handlers/broker-ops.js";import{brokerRecoveryRoutes as I,nodeFaultRoutes as q}from"./handlers/broker-recovery.js";import{canvasRoutes as ee}from"./handlers/canvas.js";import{chatInventoryRoutes as re}from"./handlers/chat-inventory.js";import{daemonRoutes as te}from"./handlers/daemon.js";import{fileRoutes as oe}from"./handlers/files.js";import{focusRoutes as ne}from"./handlers/focus.js";import{healthRoutes as ie}from"./handlers/health.js";import{humanRequestRoutes as se}from"./handlers/human-requests.js";import{inboxRoutes as le}from"./handlers/inbox.js";import{feedbackCommentRoutes as ce}from"./handlers/feedback-comments.js";import{memoryRoutes as ae}from"./handlers/memory.js";import{brokerMailRoutes as _,messageRoutes as ue}from"./handlers/messages.js";import{modelAuthRoutes as de}from"./handlers/modelauth.js";import{modelConfigRoutes as me}from"./handlers/model-config.js";import{nodeRoutes as pe}from"./handlers/nodes.js";import{nodeOutcomeRoutes as fe}from"./handlers/node-outcomes.js";import{nodeEventRoutes as ge}from"./handlers/node-events.js";import{profileRoutes as he}from"./handlers/profiles.js";import{prospectiveChatInventoryRoutes as Ae}from"./handlers/prospective-chat-inventory.js";import{reportRoutes as Re}from"./handlers/reports.js";import{reviewCommentRoutes as ve}from"./handlers/review-comments.js";import{reviewRoutes as ye}from"./handlers/reviews.js";import{subscriptionRoutes as be}from"./handlers/subscriptions.js";import{cronRoutes as we}from"./handlers/crons.js";import{worktreeRoutes as Te}from"./handlers/worktree.js";function Se(t){return new N().registerAll(ie(t)).registerAll(te).registerAll(pe).registerAll(fe).registerAll(ge).registerAll(V).registerAll(X).registerAll(H).registerAll(I).registerAll(q).registerAll(Te).registerAll(_).registerAll(ue).registerAll(Re).registerAll(Q).registerAll(ee).registerAll(oe).registerAll(ae).registerAll(ne).registerAll(be).registerAll(we).registerAll(he).registerAll(de).registerAll(me).registerAll(ye).registerAll(ve).registerAll(le).registerAll(se).registerAll(re).registerAll(Ae).registerAll(ce)}s(Se,"buildRouter");function Ce(t,o){if(t.toUpperCase()!=="GET")return null;const i=o.split("/").filter(f=>f.length>0);if(i.length!==4||i[0]!=="v1"||i[1]!=="nodes"||i[3]!=="attach")return null;const u=i[2];return u===void 0||u===""?null:decodeURIComponent(u)}s(Ce,"attachNodeId");function ke(t){const o=t.trim();if(o==="")return null;const i=o.lastIndexOf(":");if(i<0)return null;const u=o.slice(0,i),f=o.slice(i+1),a=Number(f);return!Number.isInteger(a)||a<0||a>65535?null:{host:u===""?"0.0.0.0":u,port:a}}s(ke,"parseTcp");function Ee(t,o){return`${t.includes(":")?`[${t}]`:t}:${o}`}s(Ee,"formatTcpAddress");const w={code:"unauthorized",message:"missing or invalid bearer token"},x={code:"owner_only",message:"attach is owner-only; a scoped token does not reach it"};function Oe(t){const o=new Map;for(const i of $("user"))o.set(i.token,i.scopes);return o.set(t,null),o}s(Oe,"resolveBearers");function z(t,o){const i=t.headers.authorization;if(!(typeof i!="string"||!i.startsWith("Bearer ")))return o.get(i.slice(7))}s(z,"authorize");function Ue(t){t.writeHead(401,{"content-type":"application/json; charset=utf-8"}),t.end(JSON.stringify({error:w}))}s(Ue,"writeUnauthorized");function Pe(t,o){t.writeHead(503,{"content-type":"application/json; charset=utf-8"}),t.end(JSON.stringify({error:{code:"startup_blocked",message:o}}))}s(Pe,"writeStartupBlocked");function B(t){return new Promise(o=>{try{t.closeAllConnections()}catch{}t.close(()=>o())})}s(B,"closeServer");function Rr(t={}){let o=null;const i=Se(()=>o),u=new N().registerAll(H).registerAll(I).registerAll(_),f=s((e,r)=>{const c=K()?.startupBlock()??null;return c===null||e==="GET"&&(r==="/healthz"||r==="/v1/status")||e==="POST"&&(r==="/v1/daemon/migrate"||r==="/v1/daemon/admit")||c.phase==="recovering"&&u.match(e,r)!==null?null:c},"startupBlockFor"),a=D(),v=s((e,r,c)=>{const m=s(n=>{A({event:"api.request.failed",level:"error",error:n instanceof Error?n:new Error(String(n))});try{r.headersSent||r.writeHead(500,{"content-type":"application/json; charset=utf-8"}),r.end(JSON.stringify({error:{code:"internal",message:"internal error"}}))}catch{}},"internalFailure");let p;try{p=new URL(e.url??"/","http://127.0.0.1")}catch{try{r.writeHead(400,{"content-type":"application/json; charset=utf-8"}),r.end(JSON.stringify({error:{code:"invalid_request",message:"request URL is invalid"}}))}catch{}return}try{const n=f((e.method??"GET").toUpperCase(),p.pathname);if(n!==null){Pe(r,n.message);return}i.handle(e,r,c).catch(m)}catch(n){m(n)}},"onRequest"),y=s((e,r,c)=>{r.on("error",()=>{});try{const m=new URL(e.url??"/","http://127.0.0.1"),p=f((e.method??"GET").toUpperCase(),m.pathname);if(p!==null){b(r,503,"Service Unavailable","startup_blocked",p.message);return}const n=Ce(e.method??"GET",m.pathname);if(n===null){r.destroy();return}Z(e,r,c,n).catch(()=>{try{r.destroy()}catch{}})}catch{try{r.destroy()}catch{}}},"onUpgrade"),G=s(e=>{e.on("error",r=>{A({event:"api.server.failed",level:"error",error:r})})},"bindErrorHandler"),h=O((e,r)=>v(e,r,null));h.on("upgrade",y);let T=!1,S,C;const j=new Promise((e,r)=>{S=e,C=r});h.once("listening",()=>{T=!0,S()}),h.on("error",e=>{A({event:"api.server.failed",level:"error",error:e}),T||C(e)});try{U(a)&&P(a)}catch{}h.listen(a,()=>{try{J(a,384)}catch(e){A({event:"api.socket.chmod_failed",level:"error",error:e instanceof Error?e:new Error(String(e))})}});let d;const R=t.tcp??W()??F("user").api.tcp;if(R!==void 0&&R!==""){const e=ke(R);if(e===null)A({event:"api.tcp.invalid",level:"error",error:new Error(`invalid CRTRD_TCP/--tcp spec: ${R}`)});else{const r=t.token??Y()??M("user"),c=r===void 0?void 0:Oe(r),m=c===void 0?(n,l)=>v(n,l,null):(n,l)=>{if((n.method??"GET").toUpperCase()==="OPTIONS"){l.writeHead(204,{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Headers":"authorization, content-type","Access-Control-Allow-Methods":"GET, POST, PATCH, PUT, DELETE, OPTIONS","Access-Control-Max-Age":"600"}),l.end();return}const g=z(n,c);if(g===void 0){Ue(l);return}l.setHeader("Access-Control-Allow-Origin","*"),v(n,l,g)},p=c===void 0?y:(n,l,g)=>{const E=z(n,c);if(E===void 0){b(l,401,"Unauthorized",w.code,w.message);return}if(E!==null){b(l,403,"Forbidden",x.code,x.message);return}y(n,l,g)};d=O(m),d.on("upgrade",p),G(d),d.once("listening",()=>{const n=d?.address();if(n!==null&&typeof n=="object"){const{address:l,port:g}=n;o=Ee(l,g)}}),d.listen(e.port,e.host)}}let k=!1;return{ready:j,tcpAddress:s(()=>o,"tcpAddress"),close:s(async()=>{if(!k){k=!0,await Promise.all([B(h),d!==void 0?B(d):Promise.resolve()]);try{U(a)&&P(a)}catch{}}},"close")}}s(Rr,"createApiServer");export{Rr as createApiServer};
|
|
1
|
+
var D=Object.defineProperty;var l=(t,o)=>D(t,"name",{value:o,configurable:!0});import{createServer as H}from"node:http";import{chmodSync as Y,existsSync as C,unlinkSync as x}from"node:fs";import{apiSocketPath as Z}from"../../core/canvas/paths.js";import{resolveNodeToken as I}from"../../core/canvas/node-tokens.js";import{grantFor as K,hasSyncedGrants as Q}from"../../core/grants/mirror.js";import{readConfig as U}from"../../core/config.js";import{peerUid as V}from"../../native/linux.js";import{getApiToken as X,listScopedApiTokens as q}from"../../core/secrets.js";import{emitEvent as g}from"../../core/events/emit.js";import{envCrtrdTcp as ee,envCrtrdToken as re}from"../../shared/env.js";import{Router as B}from"./router.js";import{handleAttachUpgrade as te,refuseUpgrade as A}from"./bridge.js";import{boundDaemonControl as oe}from"../control.js";import{attachRoutes as ne}from"./handlers/attach.js";import{bashJobRoutes as ie}from"./handlers/bash-jobs.js";import{bashRoutes as se}from"./handlers/bash.js";import{hookExecRoutes as le}from"./handlers/hook-exec.js";import{brokerOperationRoutes as G}from"./handlers/broker-ops.js";import{brokerRecoveryRoutes as j,nodeFaultRoutes as ae}from"./handlers/broker-recovery.js";import{canvasRoutes as ce}from"./handlers/canvas.js";import{chatInventoryRoutes as ue}from"./handlers/chat-inventory.js";import{daemonRoutes as pe}from"./handlers/daemon.js";import{fileRoutes as de}from"./handlers/files.js";import{focusRoutes as me}from"./handlers/focus.js";import{analyticsRoutes as fe}from"./handlers/analytics.js";import{memoryReadsRoutes as ge}from"./handlers/memory-reads.js";import{healthRoutes as he}from"./handlers/health.js";import{humanRequestRoutes as Ae}from"./handlers/human-requests.js";import{inboxRoutes as Re}from"./handlers/inbox.js";import{feedbackCommentRoutes as ve}from"./handlers/feedback-comments.js";import{memoryRoutes as ye}from"./handlers/memory.js";import{brokerMailRoutes as $,messageRoutes as be}from"./handlers/messages.js";import{modelAuthRoutes as we}from"./handlers/modelauth.js";import{llmRoutes as Se}from"./handlers/llm.js";import{modelConfigRoutes as ke}from"./handlers/model-config.js";import{nodeRoutes as Te}from"./handlers/nodes.js";import{nodeRecordRoutes as Ee}from"./handlers/node-records.js";import{nodeOutcomeRoutes as Ce}from"./handlers/node-outcomes.js";import{nodeEventRoutes as Ue}from"./handlers/node-events.js";import{profileRoutes as Oe}from"./handlers/profiles.js";import{prospectiveChatInventoryRoutes as ze}from"./handlers/prospective-chat-inventory.js";import{reportRoutes as Pe}from"./handlers/reports.js";import{runRoutes as _e}from"./handlers/run-routes.js";import{reviewCommentRoutes as Ne}from"./handlers/review-comments.js";import{reviewRoutes as He}from"./handlers/reviews.js";import{subscriptionRoutes as xe}from"./handlers/subscriptions.js";import{cronRoutes as Ie}from"./handlers/crons.js";import{worktreeRoutes as Be}from"./handlers/worktree.js";function Ge(t){return new B().registerAll(he(t)).registerAll(pe).registerAll(Te).registerAll(Ee).registerAll(Ce).registerAll(Ue).registerAll(ie).registerAll(se).registerAll(le).registerAll(G).registerAll(j).registerAll(ae).registerAll(Be).registerAll($).registerAll(be).registerAll(Pe).registerAll(_e).registerAll(ne).registerAll(ce).registerAll(fe).registerAll(ge).registerAll(de).registerAll(ye).registerAll(me).registerAll(xe).registerAll(Ie).registerAll(Oe).registerAll(we).registerAll(Se).registerAll(ke).registerAll(He).registerAll(Ne).registerAll(Re).registerAll(Ae).registerAll(ue).registerAll(ze).registerAll(ve)}l(Ge,"buildRouter");function je(t,o){if(t.toUpperCase()!=="GET")return null;const s=o.split("/").filter(d=>d.length>0);if(s.length!==4||s[0]!=="v1"||s[1]!=="nodes"||s[3]!=="attach")return null;const p=s[2];return p===void 0||p===""?null:decodeURIComponent(p)}l(je,"attachNodeId");function $e(t){const o=t.trim();if(o==="")return null;const s=o.lastIndexOf(":");if(s<0)return null;const p=o.slice(0,s),d=o.slice(s+1),c=Number(d);return!Number.isInteger(c)||c<0||c>65535?null:{host:p===""?"0.0.0.0":p,port:c}}l($e,"parseTcp");function Fe(t,o){return`${t.includes(":")?`[${t}]`:t}:${o}`}l(Fe,"formatTcpAddress");const v={code:"unauthorized",message:"missing or invalid bearer token"},w={code:"owner_only",message:"attach is owner-only; a scoped token does not reach it"},S=new WeakMap;function Je(t){return S.get(t)}l(Je,"socketPrincipal");function F(t,o){const s=process.platform==="linux"?V(t.socket):null,p=t.headers.authorization;if(p===void 0)return s===null||o.has(s)?{class:"person"}:"unauthorized";if(typeof p!="string"||!p.startsWith("Bearer "))return"unauthorized";const d=I(p.slice(7));if(!d||s!==null&&s!==d.uid)return"unauthorized";const c=U("user").runtime?.issuer;if(c&&!Q(c.replace(/\/$/,"")))return"runtime_starting";const y=d.grant??K("app:terminal",d.sub)?.id??null;return{class:"broker",...d,grant:y}}l(F,"resolveSocketPrincipal");function Le(t){const o=new Map;for(const s of q("user"))o.set(s.token,{principal:{class:"app",app:s.grantee,scopes:s.scopes},ceiling:s.scopes});return o.set(t,{principal:{class:"person"},ceiling:null}),o}l(Le,"resolveBearers");function J(t,o){const s=t.headers.authorization;if(!(typeof s!="string"||!s.startsWith("Bearer ")))return o.get(s.slice(7))}l(J,"authorize");function k(t){t.writeHead(401,{"content-type":"application/json; charset=utf-8"}),t.end(JSON.stringify({error:v}))}l(k,"writeUnauthorized");function Me(t,o){t.writeHead(503,{"content-type":"application/json; charset=utf-8"}),t.end(JSON.stringify({error:{code:"startup_blocked",message:o}}))}l(Me,"writeStartupBlocked");function L(t){return new Promise(o=>{try{t.closeAllConnections()}catch{}t.close(()=>o())})}l(L,"closeServer");function Fr(t={}){let o=null;const s=Ge(()=>o),p=new B().registerAll(G).registerAll(j).registerAll($),d=l((e,r)=>{const n=oe()?.startupBlock()??null;return n===null||e==="GET"&&(r==="/healthz"||r==="/v1/status")||e==="POST"&&(r==="/v1/daemon/migrate"||r==="/v1/daemon/admit")||n.phase==="recovering"&&p.match(e,r)!==null?null:n},"startupBlockFor"),c=Z(),y=new Set([process.getuid?.()??0,...U("user").runtime?.person_uids??[]]),T=l((e,r,n)=>{const a=l(i=>{g({event:"api.request.failed",level:"error",error:i instanceof Error?i:new Error(String(i))});try{r.headersSent||r.writeHead(500,{"content-type":"application/json; charset=utf-8"}),r.end(JSON.stringify({error:{code:"internal",message:"internal error"}}))}catch{}},"internalFailure");let h;try{h=new URL(e.url??"/","http://127.0.0.1")}catch{try{r.writeHead(400,{"content-type":"application/json; charset=utf-8"}),r.end(JSON.stringify({error:{code:"invalid_request",message:"request URL is invalid"}}))}catch{}return}try{const i=d((e.method??"GET").toUpperCase(),h.pathname);if(i!==null){Me(r,i.message);return}s.handle(e,r,n,Je(e)??{class:"person"}).catch(a)}catch(i){a(i)}},"onRequest"),E=l((e,r,n)=>{r.on("error",()=>{});try{const a=new URL(e.url??"/","http://127.0.0.1"),h=d((e.method??"GET").toUpperCase(),a.pathname);if(h!==null){A(r,503,"Service Unavailable","startup_blocked",h.message);return}const i=je(e.method??"GET",a.pathname);if(i===null){r.destroy();return}te(e,r,n,i).catch(()=>{try{r.destroy()}catch{}})}catch{try{r.destroy()}catch{}}},"onUpgrade"),M=l(e=>{e.on("error",r=>{g({event:"api.server.failed",level:"error",error:r})})},"bindErrorHandler"),R=H((e,r)=>{try{const n=F(e,y);if(n==="unauthorized"){k(r);return}if(n==="runtime_starting"){r.writeHead(503,{"content-type":"application/json; charset=utf-8"}),r.end(JSON.stringify({error:{code:"runtime_starting",message:"grant sync is not ready",type:"server_error",origin:"runtime",retryable:!0}}));return}S.set(e,n),n.class==="broker"&&g({event:"api.request.principal",level:"info",node_id:n.node,fields:{principal:`${n.app} node:${n.node}`,method:e.method,path:e.url}}),T(e,r,null)}catch(n){g({event:"api.principal.failed",level:"error",error:n instanceof Error?n:new Error(String(n))}),k(r)}});R.on("upgrade",(e,r,n)=>{try{const a=F(e,y);if(a==="unauthorized"||a==="runtime_starting"){A(r,a==="unauthorized"?401:503,"Unauthorized",a,"socket principal unavailable");return}if(a.class!=="person"){A(r,403,"Forbidden",w.code,w.message);return}S.set(e,a),E(e,r,n)}catch(a){g({event:"api.principal.failed",level:"error",error:a instanceof Error?a:new Error(String(a))}),A(r,401,"Unauthorized",v.code,v.message)}});let O=!1,z,P;const W=new Promise((e,r)=>{z=e,P=r});R.once("listening",()=>{O=!0,z()}),R.on("error",e=>{g({event:"api.server.failed",level:"error",error:e}),O||P(e)});try{C(c)&&x(c)}catch{}R.listen(c,()=>{try{Y(c,process.platform==="linux"&&C("/run/crtr/launcher.sock")?438:384)}catch(e){g({event:"api.socket.chmod_failed",level:"error",error:e instanceof Error?e:new Error(String(e))})}});let f;const b=t.tcp??ee()??U("user").api.tcp;if(b!==void 0&&b!==""){const e=$e(b);if(e===null)g({event:"api.tcp.invalid",level:"error",error:new Error(`invalid CRTRD_TCP/--tcp spec: ${b}`)});else{const r=t.token??re()??X("user"),n=r===void 0?void 0:Le(r),a=n===void 0?(i,u)=>{const m=i.headers.authorization;if(typeof m=="string"&&m.startsWith("Bearer ")&&I(m.slice(7))){k(u);return}T(i,u,null)}:(i,u)=>{if((i.method??"GET").toUpperCase()==="OPTIONS"){u.writeHead(204,{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Headers":"authorization, content-type","Access-Control-Allow-Methods":"GET, POST, PATCH, PUT, DELETE, OPTIONS","Access-Control-Max-Age":"600"}),u.end();return}const m=J(i,n);if(m===void 0){k(u);return}S.set(i,m.principal),u.setHeader("Access-Control-Allow-Origin","*"),T(i,u,m.ceiling)},h=n===void 0?E:(i,u,m)=>{const N=J(i,n);if(N===void 0){A(u,401,"Unauthorized",v.code,v.message);return}if(N.ceiling!==null){A(u,403,"Forbidden",w.code,w.message);return}E(i,u,m)};f=H(a),f.on("upgrade",h),M(f),f.once("listening",()=>{const i=f?.address();if(i!==null&&typeof i=="object"){const{address:u,port:m}=i;o=Fe(u,m)}}),f.listen(e.port,e.host)}}let _=!1;return{ready:W,tcpAddress:l(()=>o,"tcpAddress"),close:l(async()=>{if(!_){_=!0,await Promise.all([L(R),f!==void 0?L(f):Promise.resolve()]);try{C(c)&&x(c)}catch{}}},"close")}}l(Fr,"createApiServer");export{Fr as createApiServer,Je as socketPrincipal};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import type { AppPrincipalResolver } from './principal.js';
|
|
3
|
+
export declare const VENDOR_SIGNIN_PATH = "/signin/vendor";
|
|
4
|
+
export declare function isVendorSignInPath(pathname: string): boolean;
|
|
5
|
+
/** Serve one `/signin/vendor*` request; errors propagate as RunErrors so the
|
|
6
|
+
* listener answers them with contract 2's envelope (RT-LLM-53). */
|
|
7
|
+
export declare function handleVendorSignIn(req: IncomingMessage, res: ServerResponse, url: URL, principal: AppPrincipalResolver): Promise<void>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
var k=Object.defineProperty;var a=(e,t)=>k(e,"name",{value:t,configurable:!0});import{randomBytes as P}from"node:crypto";import{joinedOwner as _}from"../../core/directory/join.js";import{consumeHandoffJti as E,handoffJtiConsumed as w}from"../../core/model-auth/handoff-jti.js";import{completeModelAuthFlow as $,modelAuthProvider as j,readModelAuthFlow as v,startModelAuthFlow as I,waitModelAuthFlow as O}from"../../core/model-auth/flows.js";import{RunError as s}from"../../core/runs/operations.js";const d="/signin/vendor",A=25e3,R="https://chatgpt.com/#settings/Security";function K(e){return e===d||e.startsWith(`${d}/`)}a(K,"isVendorSignInPath");function u(){return new s(401,"unauthorized","invalid vendor sign-in handoff")}a(u,"unauthorized");async function C(e,t){const n=await e.verifyHandoff(t);let o;try{o=_()}catch{o=null}if(n.sub!==o)throw u();return n}a(C,"verifyOwnerHandoff");function B(e){const t=e.headers.authorization;return t?.startsWith("Bearer ")&&t.length>7?t.slice(7):void 0}a(B,"bearer");function y(e,t){const n=e.getAll(t);return n.length===1?n[0]:void 0}a(y,"single");function N(e,t){const n=new URL(e);return n.searchParams.set("status",t),n.toString()}a(N,"returnUrl");function f(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}a(f,"escapeHtml");function l(e,t,n){e.writeHead(t,{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}),e.end(JSON.stringify(n))}a(l,"sendJson");async function U(e){const t=[];let n=0;for await(const r of e){if(n+=r.length,n>64*1024)throw new s(400,"invalid_request","request body too large");t.push(r)}let o;try{o=JSON.parse(Buffer.concat(t).toString("utf8"))}catch{throw new s(400,"invalid_request","invalid JSON body")}if(typeof o!="object"||o===null||Array.isArray(o))throw new s(400,"invalid_request","request body must be a JSON object");return o}a(U,"jsonBody");const G=`
|
|
2
|
+
body{font:16px/1.5 system-ui,-apple-system,sans-serif;max-width:34rem;margin:3rem auto;padding:0 1.25rem;color:#1a1a1a}
|
|
3
|
+
h1{font-size:1.4rem;margin:0 0 1rem}
|
|
4
|
+
.button{display:inline-block;background:#1a1a1a;color:#fff;border:0;border-radius:.5rem;padding:.8rem 1.4rem;font-size:1.05rem;text-decoration:none;cursor:pointer}
|
|
5
|
+
.code{font:600 2.2rem/1.2 ui-monospace,monospace;letter-spacing:.12em;margin:.5rem 0}
|
|
6
|
+
.note{background:#f4f4f5;border-radius:.5rem;padding:.8rem 1rem}
|
|
7
|
+
label{display:block;font-weight:600;margin:1.5rem 0 .4rem}
|
|
8
|
+
input[type=text]{width:100%;box-sizing:border-box;font:1rem ui-monospace,monospace;padding:.6rem;border:1px solid #bbb;border-radius:.4rem}
|
|
9
|
+
#error{color:#b00020}
|
|
10
|
+
[hidden]{display:none}
|
|
11
|
+
`,J=`
|
|
12
|
+
(function(){
|
|
13
|
+
var cfg=JSON.parse(document.getElementById('cfg').textContent);
|
|
14
|
+
history.replaceState(null,'',location.pathname);
|
|
15
|
+
var auth={'Authorization':'Bearer '+cfg.handoff};
|
|
16
|
+
function back(status){var u=new URL(cfg.returnTo);u.searchParams.set('status',status);location.assign(u.toString());}
|
|
17
|
+
function show(id){document.getElementById(id).hidden=false;}
|
|
18
|
+
var error=document.getElementById('error');
|
|
19
|
+
if(cfg.kind==='anthropic'){
|
|
20
|
+
var form=document.getElementById('paste');
|
|
21
|
+
form.addEventListener('submit',function(e){
|
|
22
|
+
e.preventDefault();
|
|
23
|
+
var button=form.querySelector('button');button.disabled=true;error.textContent='';
|
|
24
|
+
fetch(cfg.base,{method:'POST',headers:Object.assign({'Content-Type':'application/json'},auth),body:JSON.stringify({input:form.elements.code.value})})
|
|
25
|
+
.then(function(r){return r.json().then(function(b){return {ok:r.ok,s:r.status,b:b};});})
|
|
26
|
+
.then(function(x){
|
|
27
|
+
if(x.ok){back(x.b.status==='connected'?'connected':'failed');return;}
|
|
28
|
+
if(x.s===401||x.s===404){back('failed');return;}
|
|
29
|
+
error.textContent=(x.b&&x.b.error&&x.b.error.message)||'That code was not accepted.';button.disabled=false;
|
|
30
|
+
})
|
|
31
|
+
.catch(function(){error.textContent='Could not reach your runtime. Try again.';button.disabled=false;});
|
|
32
|
+
});
|
|
33
|
+
}else{
|
|
34
|
+
document.getElementById('copy').addEventListener('click',function(){navigator.clipboard&&navigator.clipboard.writeText(cfg.userCode);});
|
|
35
|
+
document.getElementById('renew').addEventListener('click',function(){back('failed');});
|
|
36
|
+
(function poll(){
|
|
37
|
+
fetch(cfg.base+'/wait',{headers:auth})
|
|
38
|
+
.then(function(r){if(r.status===401||r.status===404)return {status:'failed'};if(!r.ok)throw new Error(String(r.status));return r.json();})
|
|
39
|
+
.then(function(b){
|
|
40
|
+
if(b.status==='pending'){poll();return;}
|
|
41
|
+
if(b.status==='connected'){back('connected');return;}
|
|
42
|
+
if(b.status==='expired'){document.getElementById('device').hidden=true;show('expired');return;}
|
|
43
|
+
back('failed');
|
|
44
|
+
})
|
|
45
|
+
.catch(function(){setTimeout(poll,3000);});
|
|
46
|
+
})();
|
|
47
|
+
}
|
|
48
|
+
})();
|
|
49
|
+
`;function x(e){const t=JSON.stringify(e.config).replace(/</g,"\\u003c");return`<!doctype html>
|
|
50
|
+
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
51
|
+
<title>${f(e.title)}</title><style nonce="${e.nonce}">${G}</style></head>
|
|
52
|
+
<body>${e.body}
|
|
53
|
+
<script type="application/json" id="cfg">${t}<\/script>
|
|
54
|
+
<script nonce="${e.nonce}">${J}<\/script>
|
|
55
|
+
</body></html>`}a(x,"page");function L(e,t,n,o){return x({nonce:t,title:"Connect Claude",body:`<h1>Connect your Claude account</h1>
|
|
56
|
+
<p>Sign in to Claude in a new tab. When Claude shows you a code, copy it and paste it below.</p>
|
|
57
|
+
<p><a class="button" href="${f(e.url)}" target="_blank" rel="noopener noreferrer">Sign in at claude.ai</a></p>
|
|
58
|
+
<form id="paste" autocomplete="off">
|
|
59
|
+
<label for="code">Paste the code Claude shows</label>
|
|
60
|
+
<input type="text" id="code" name="code" required spellcheck="false">
|
|
61
|
+
<p><button class="button" type="submit">Connect</button></p>
|
|
62
|
+
<p id="error" role="alert"></p>
|
|
63
|
+
</form>`,config:{kind:"anthropic",base:`${d}/${encodeURIComponent(e.flow_id)}`,returnTo:n,handoff:o}})}a(L,"anthropicPage");function H(e,t,n,o){const r=e.user_code??"";return x({nonce:t,title:"Connect ChatGPT",body:`<h1>Connect your ChatGPT account</h1>
|
|
64
|
+
<p class="note">OpenAI refuses this sign-in unless <strong>device code authorization for Codex</strong> is turned on in your
|
|
65
|
+
<a href="${R}" target="_blank" rel="noopener noreferrer">ChatGPT Security Settings</a>. Turn it on first.</p>
|
|
66
|
+
<p>When OpenAI shows an account email, check it is the account you want to use: approving connects that account.</p>
|
|
67
|
+
<div id="device">
|
|
68
|
+
<p>Open <a href="${f(e.url)}" target="_blank" rel="noopener noreferrer">${f(e.url.replace(/^https:\/\//,""))}</a> and enter this code:</p>
|
|
69
|
+
<p class="code">${f(r)}</p>
|
|
70
|
+
<p><button class="button" type="button" id="copy">Copy code</button></p>
|
|
71
|
+
<p>The code expires in 15 minutes. This page moves on by itself once you approve.</p>
|
|
72
|
+
</div>
|
|
73
|
+
<div id="expired" hidden>
|
|
74
|
+
<p>The code expired before it was approved.</p>
|
|
75
|
+
<p><button class="button" type="button" id="renew">Get a new code</button></p>
|
|
76
|
+
</div>
|
|
77
|
+
<p id="error" role="alert"></p>`,config:{kind:"openai",base:`${d}/${encodeURIComponent(e.flow_id)}`,returnTo:n,handoff:o,userCode:r}})}a(H,"openaiPage");async function z(e,t,n,o){const r=y(n.searchParams,"handoff"),c=await C(o,r);if(w(c.jti))throw u();const i=y(n.searchParams,"return_to");let m;try{m=i===void 0?void 0:new URL(i).origin}catch{m=void 0}if(i===void 0||m!==new URL(o.issuer).origin)throw new s(400,"invalid_request","return_to must be an absolute URL on the directory origin","return_to");const p=y(n.searchParams,"vendor");if(p!=="anthropic"&&p!=="openai")throw new s(400,"invalid_request","vendor must be anthropic or openai","vendor");if(!E(c.jti,c.exp))throw u();let b;try{b=await I({provider:j(p),jti:c.jti})}catch(g){console.error("[vendor-signin] start failed:",g instanceof Error?g.message:g),t.writeHead(303,{Location:N(i,"failed"),"Cache-Control":"no-store","Referrer-Policy":"no-referrer"}),t.end();return}const h=P(16).toString("base64"),T=p==="anthropic"?L(b,h,i,r):H(b,h,i,r);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store","Referrer-Policy":"no-referrer","X-Content-Type-Options":"nosniff","Content-Security-Policy":`default-src 'none'; script-src 'nonce-${h}'; style-src 'nonce-${h}'; connect-src 'self'; form-action 'none'; base-uri 'none'; frame-ancestors 'none'`}),t.end(T)}a(z,"startPage");async function S(e,t,n){const o=await C(t,B(e)),r=v(n);if(!r){if(w(o.jti))return!1;throw u()}if(r.jti===void 0||r.jti!==o.jti)throw u();return!0}a(S,"followUpFlow");async function q(e,t,n,o){if(!await S(e,n,o)){l(t,200,{status:"failed"});return}const r=await U(e);try{await $(o,r.input),l(t,200,{status:"connected"})}catch(c){const i=v(o);if(i&&i.status!=="pending"){l(t,200,{status:"failed"});return}throw c}}a(q,"submitCode");async function F(e,t,n,o){if(!await S(e,n,o)){l(t,200,{status:"failed"});return}const r=new AbortController;t.once("close",()=>r.abort());const c=await O(o,A,r.signal);l(t,200,{status:c?.status??"failed"})}a(F,"waitFlow");async function Q(e,t,n,o){const r=e.method??"GET";if(n.pathname===d&&r==="GET"){await z(e,t,n,o);return}const c=n.pathname.slice(d.length+1).split("/");let i="";try{i=c[0]?decodeURIComponent(c[0]):""}catch{throw new s(404,"not_found","unknown operation")}if(i&&c.length===1&&r==="POST"){await q(e,t,o,i);return}if(i&&c.length===2&&c[1]==="wait"&&r==="GET"){await F(e,t,o,i);return}throw new s(404,"not_found","unknown operation")}a(Q,"handleVendorSignIn");export{d as VENDOR_SIGNIN_PATH,Q as handleVendorSignIn,K as isVendorSignInPath};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var r=Object.defineProperty;var c=(e,n)=>r(e,"name",{value:n,configurable:!0});const i=new Map;function s(e){return(i.get(e)?.size??0)>0}c(s,"hasAttachedBrokerViewers");function a(e,n){let t=i.get(e);t||(t=new Set,i.set(e,t)),t.add(n)}c(a,"attachViewer");function f(e,n){const t=i.get(e);t&&(t.delete(n),t.size===0&&i.delete(e))}c(f,"detachViewer");export{a as attachViewer,f as detachViewer,s as hasAttachedBrokerViewers};
|
|
@@ -7,6 +7,10 @@ import type { Cron } from '../../core/canvas/crons.js';
|
|
|
7
7
|
* purview silently replaced. That throws, and the run fails loudly once
|
|
8
8
|
* instead of running wrong on every tick. */
|
|
9
9
|
export declare function resolveLiveProfile(c: Cron): string | null;
|
|
10
|
+
/** The node a cron's birth is a child of: its live creator. With none, the
|
|
11
|
+
* birth is a parentless root, which is the person's (app:terminal); an app's
|
|
12
|
+
* cron has no node to take its grant from, so it cannot start one. */
|
|
13
|
+
export declare function cronBirthParent(c: Cron): string | null;
|
|
10
14
|
export declare function resolveLiveProfileOrRoot(c: Cron): string | null;
|
|
11
15
|
export declare function resolveLiveProfileName(c: Cron): string | undefined;
|
|
12
16
|
/** A stored context cannot be rebuilt; the run fails rather than running under a context nobody armed. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var p=Object.defineProperty;var o=(e,r)=>p(e,"name",{value:r,configurable:!0});import{envHomeOverride as h}from"../../shared/env.js";import{loadProfileManifest as v,lookupProfile as c}from"../../core/profiles/manifest.js";import{readProfileEnvVars as m}from"../../core/profiles/env-store.js";import{ADMITTED_HOST_PATH_ENV as u,buildOperationalEnvBase as _}from"../../core/runtime/spawn-env.js";import{getNode as R}from"../../core/canvas/canvas.js";function f(e){if(e.profile==null)return null;let r;try{r=c(e.profile)}catch{return null}if(r.kind==="resolved")return r.entry.profileId;if(r.kind==="absent")return null;throw new i(`the armed profile "${e.profile}" is still on this host but its manifest could not be read (${r.manifestPath}) \u2014 running as root would silently give this cron a different identity, env store, and purview. Repair the manifest, or re-arm the cron under a profile that resolves.`)}o(f,"resolveLiveProfile");function x(e){if(e.created_by!==null&&R(e.created_by)!==null)return e.created_by;if(e.grantee!=="app:terminal")throw new i(`cron ${e.cron_id} belongs to ${e.grantee} and its creator node is gone; only a node of that app can start its births`);return null}o(x,"cronBirthParent");function A(e){try{return f(e)}catch{return null}}o(A,"resolveLiveProfileOrRoot");function N(e){if(e.profile!=null)try{return v(e.profile).manifest.name}catch{return}}o(N,"resolveLiveProfileName");class i extends Error{static{o(this,"ArmedContextError")}constructor(r){super(r),this.name="ArmedContextError"}}function w(e){if(e==null)return{};let r;try{r=JSON.parse(e)}catch(t){throw new i(`the armed env snapshot is not valid JSON (${t.message}) \u2014 this cron's stored env_json is corrupt, so the run would silently drop every armed variable. Re-arm the cron with a valid --env.`)}if(typeof r!="object"||r===null||Array.isArray(r))throw new i("the armed env snapshot is not a JSON object \u2014 this cron's stored env_json is corrupt. Re-arm the cron with a valid --env.");const a={};for(const[t,n]of Object.entries(r)){if(typeof n!="string")throw new i(`the armed env snapshot's value for "${t}" is not a string \u2014 this cron's stored env_json is corrupt, so the run would silently drop that variable. Re-arm the cron with a valid --env.`);a[t]=n}return a}o(w,"parseArmedEnv");function P(e,r){const a=w(e.env_json),t=e.grantee==="app:terminal",n=t?f(e):null,d=_({targetCwd:e.cwd,targetProfileId:n,skipSpawnAllow:!t}),l={...d,...t?m(n):{},...a,...n!==null?{CRTR_PROFILE_ID:n}:{},CRTR_CRON_ID:e.cron_id,CRTR_CRON_NAME:e.name,CRTR_RUN_ID:r},s=h();return s!==void 0&&s!==""&&(l.CRTR_HOME=s),e.anchor_node!=null&&(l.CRTR_ANCHOR=e.anchor_node),l[u]=d[u],{profileId:n,env:l}}o(P,"buildArmedRunContext");export{i as ArmedContextError,P as buildArmedRunContext,x as cronBirthParent,f as resolveLiveProfile,N as resolveLiveProfileName,A as resolveLiveProfileOrRoot};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
2
|
-
`)[0]?.slice(0,120)??"";return`- ${n.started} \u2014 ${
|
|
3
|
-
`)}o(
|
|
1
|
+
var m=Object.defineProperty;var o=(e,r)=>m(e,"name",{value:r,configurable:!0});import{getNode as h}from"../../core/canvas/canvas.js";import{fullName as f}from"../../core/canvas/labels.js";import{listCronRuns as p,setCronState as $}from"../../core/canvas/crons.js";import{emitEvent as l}from"../../core/events/emit.js";import{spawnChild as y}from"../../core/runtime/spawn.js";import{cronWakeOrigin as _}from"../../core/runtime/bearings.js";import{cadenceDisplay as w}from"../../core/wake.js";import{cronBirthParent as b,resolveLiveProfileOrRoot as g}from"./armed-context.js";function v(e,r){return r!==null?r:e.timedOut?`run timed out after ${e.runTimeoutS}s (killed; recorded exit -1)`:e.processErrorMessage!==null?`run process error: ${e.processErrorMessage}`:`command exited ${e.exitCode??"(no exit observed)"}`}o(v,"failureSummary");function O(e,r,a){const t=e.created_by!=null?h(e.created_by):null,i=e.created_by==null?"created by: (no creating node recorded)":t!==null?`created by: node ${e.created_by} ("${f(t)}") \u2014 still on the canvas; consider telling it what happened`:`created by: node ${e.created_by} (now gone)`,u=e.recur!=null?`every ${w(e.recur)}`:`one-shot at ${e.fire_at}`,d=p(e.cron_id).slice(0,10).map(n=>{const c=n.exit_code===null?"no exit":`exit ${n.exit_code}`,s=(n.stderr_head??n.stdout_head??"").split(`
|
|
2
|
+
`)[0]?.slice(0,120)??"";return`- ${n.started} \u2014 ${c}, ${n.duration_ms}ms \u2014 ${n.delivered??""}${s!==""?` \u2014 ${s}`:""}`});return["A scheduled cron FAILED and has paused itself. You were spawned to deal with it.","",`- cron: "${e.name}" (${e.cron_id})`,`- schedule: ${u}${e.tz!=null?` (tz ${e.tz})`:""}`,`- context: cwd ${e.cwd}${e.profile!=null?`, profile ${e.profile}`:""}`,`- ${i}`,`- this failure: ${v(r,a)}`,"","## The command","","```bash",e.command,"```","","## This run","",`- exit: ${r.timedOut?"-1 (timeout)":String(r.exitCode)}`,`- stdout (head): ${r.stdoutHead===""?"(empty)":""}`,...r.stdoutHead!==""?["```",r.stdoutHead,"```"]:[],`- stderr (head): ${r.stderrHead===""?"(empty)":""}`,...r.stderrHead!==""?["```",r.stderrHead,"```"]:[],"","## Recent runs (most recent first, this failure not yet recorded)","",...d.length>0?d:["(no prior runs recorded)"],"","## Your mandate","","Diagnose why it failed and decide what to do:",`- Transient or fixable: fix the environment/command context, verify with \`crtr cron run ${e.cron_id}\` (fires now, out of band, shows you the result), then \`crtr cron resume ${e.cron_id}\` to re-arm it.`,`- Obsolete: \`crtr cron cancel ${e.cron_id}\`.`,"- The user's call (or the fix needs a change you cannot make): `crtr human send`.","","The cron stays paused until someone resumes it \u2014 nothing refires while you work."].join(`
|
|
3
|
+
`)}o(O,"buildEscalationKickoff");async function R(e,r,a){$(e.cron_id,"paused");try{const t=b(e),i=await y({kind:"general",cwd:e.cwd,prompt:O(e,r,a),...t!==null?{parent:t}:{root:!0,rootLifecycle:"terminal"},readiness:"launch",profile:g(e),wakeOrigin:_(e,"node_birth")});return l({level:"info",event:"cron.failure.escalated",fields:{cron_id:e.cron_id,name:e.name,escalation_node:i.node.node_id}}),`failure: cron paused, escalation node ${i.node.node_id} spawned`}catch(t){return l({level:"error",event:"cron.escalation.spawn_failed",error:t,fields:{cron_id:e.cron_id,name:e.name}}),`failure: cron paused; escalation spawn failed: ${t.message}`}}o(R,"escalateFailure");function z(e){return[`${e}.`,"This is a ONE-SHOT, so it has been PAUSED rather than released: its side effects may have completed in full,","and re-firing would enact them a second time. Determine whether the work actually landed, then either","`crtr cron run` it to redo it deliberately, or `crtr cron cancel` it."].join(" ")}o(z,"crashedOneShotSummary");export{z as crashedOneShotSummary,R as escalateFailure,v as failureSummary};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var v=Object.defineProperty;var d=(e,r)=>v(e,"name",{value:r,configurable:!0});import{randomUUID as m}from"node:crypto";import{setTimeout as S}from"node:timers/promises";import{CRON_DEATH_POLL_MS as w,CRON_KILL_GRACE_MS as A,EMPTY_STDOUT_SHA256 as f}from"./capture.js";import{cronDaemonInstanceId as C}from"./live-runs.js";import{crashedOneShotSummary as L,escalateFailure as H}from"./escalation.js";import{settleRun as h}from"./settle.js";import{runningCrons as M,stopLeasedCronRun as p,setCronState as g,verifyLeasedCronRun as l}from"../../core/canvas/crons.js";import{emitEvent as c}from"../../core/events/emit.js";const i=new Set;function K(e,r={}){for(const t of M()){if(t.run_lease_owner===C||i.has(t.cron_id))continue;if(t.run_pid===null||!l(t)){i.add(t.cron_id),D(t,e,r);continue}const o=t.run_started_at!=null?new Date(t.run_started_at).getTime():e;if(e-o<t.run_timeout_s*1e3)continue;const a={runId:m(),startedAtIso:t.run_started_at??new Date(e).toISOString(),exitCode:-1,timedOut:!0,runTimeoutS:t.run_timeout_s,processErrorMessage:null,stdoutHead:"",stdoutSha256:f,stderrHead:`run timed out after ${t.run_timeout_s}s (recovered stale lease from a prior daemon instance)`};i.add(t.cron_id);const n=(async()=>{await p(t),await y(t),await h(t,{outOfBand:!1,outcome:{kind:"disposed",ctx:a},record:{runId:a.runId,startedAtIso:a.startedAtIso,finishedAtMs:e,durationMs:e-o,exitCode:-1,stdoutHead:null,stderrHead:a.stderrHead},lease:{kind:"clear"}})})().finally(()=>i.delete(t.cron_id));r.register?.(n),n.catch(s=>{c({level:"error",event:"cron.stale_lease.settle_failed",error:s,fields:{cron_id:t.cron_id}})})}}d(K,"recoverStaleCronLeases");async function y(e){if(!await I(e)&&(await p(e,"SIGKILL"),!await I(e)))throw new Error(`cron ${e.cron_id} run ${e.run_pid} survived SIGKILL`)}d(y,"awaitLeasedRunDeath");async function I(e){const r=Date.now()+A;for(;Date.now()<r;){if(!l(e))return!0;await S(w)}return!l(e)}d(I,"pollLeasedRunGone");function D(e,r,t){const o=e.recur==null,a=e.run_started_at!=null?new Date(e.run_started_at).getTime():r,n=e.run_pid===null?"the daemon life that claimed this run ended before its launch pid was recorded \u2014 the command may have started and its outcome is unknown":"the daemon life that owned this run ended before it settled \u2014 the process is gone and its outcome was never observed",s={runId:m(),startedAtIso:e.run_started_at??new Date(r).toISOString(),exitCode:null,timedOut:!1,runTimeoutS:e.run_timeout_s,processErrorMessage:n,stdoutHead:"",stdoutSha256:f,stderrHead:`run outcome unobserved: ${n}`},_=(async()=>{let u=`crashed: ${n}${o?"":" \u2014 the next occurrence is unaffected"}`;o&&(g(e.cron_id,"paused"),u=e.on_output==="silent"?`crashed: ${n} \u2014 one-shot paused, not re-fired (silent: not escalated)`:`crashed one-shot: ${await H(e,s,L(n))}`),await h(e,{outOfBand:!1,outcome:{kind:"stated",delivered:u,paused:o},record:{runId:s.runId,startedAtIso:s.startedAtIso,finishedAtMs:r,durationMs:Math.max(0,r-a),exitCode:null,stdoutHead:null,stderrHead:s.stderrHead},lease:"release"}),c({level:"warn",event:"cron.run.unobserved",fields:{cron_id:e.cron_id,name:e.name,one_shot:o}})})().finally(()=>i.delete(e.cron_id));t.register?.(_),_.catch(u=>{c({level:"error",event:"cron.crashed_run.settle_failed",error:u,fields:{cron_id:e.cron_id}})})}d(D,"settleCrashedRun");export{K as recoverStaleCronLeases};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var m=Object.defineProperty;var
|
|
2
|
-
`);return{kind:"external",destinationId:"cron_spawn",adapter:{adapter:"cron_spawn",cronId:
|
|
1
|
+
var m=Object.defineProperty;var d=(n,o)=>m(n,"name",{value:o,configurable:!0});import{newNodeId as t}from"../../core/runtime/nodes.js";import{getNode as a}from"../../core/canvas/canvas.js";import{parseCronSink as s}from"../../core/canvas/crons.js";import{hasNoNaturalCycle as u}from"../../core/runtime/revive-all.js";import{isParked as p}from"../../core/runtime/lifecycle.js";import{cronWakeOrigin as f}from"../../core/runtime/bearings.js";import{cronBirthParent as k,resolveLiveProfile as c,resolveLiveProfileName as y}from"./armed-context.js";function g(n,o,i){const e=s(n.sink);if(e===null)return{kind:"none",delivered:"no sink armed \u2014 nothing delivered"};if(e.kind==="node"){const r=a(e.node);if(r===null)throw new Error(`node sink ${e.node} is gone`);if(u(r)&&!p(r))throw new Error(`node sink ${e.node} has no natural cycle ahead (done or finalized)`);return{kind:"node",destinationNodeId:e.node,senderNodeId:n.created_by!==null&&a(n.created_by)!==null?n.created_by:null,label:`\u23F0 cron ${n.name}`,stdout:i,urgency:n.tier}}if(e.kind==="spawn"){const r=k(n),l=[`Scheduled cron "${n.name}" (${n.cron_id}) fired and delivered its output to you as your kickoff.`,"","## Command output","",i].join(`
|
|
2
|
+
`);return{kind:"external",destinationId:"cron_spawn",adapter:{adapter:"cron_spawn",cronId:n.cron_id,nodeId:t(),kind:e.spawn,cwd:n.cwd,...r!==null?{parent:r,root:!1}:{parent:null,root:!0,rootLifecycle:"terminal"},profile:c(n),wakeOrigin:f(n,"node_birth"),prompt:l},bodyJson:{runId:o,stdout:i}}}return{kind:"external",destinationId:"cron_human",adapter:{adapter:"cron_human",cronId:n.cron_id,requestId:t(),title:`\u23F0 cron ${n.name}`,summary:`Scheduled cron "${n.name}" delivered output for your attention.`,sessionName:`cron ${n.name} (${n.cron_id})`,profileName:y(n)??null},bodyJson:{runId:o,stdout:i}}}d(g,"resolveCronSink");export{g as resolveCronSink};
|
|
@@ -6,9 +6,9 @@ export { type RunDueCronOptions } from './cron/passes.js';
|
|
|
6
6
|
export { recoverStaleCronLeases } from './cron/lease-recovery.js';
|
|
7
7
|
/** Kick off ONE cron run and return its settlement promise, resolving with
|
|
8
8
|
* the settled run record (null = the idle→running lease was lost, or the row
|
|
9
|
-
* was quarantined — nothing was recorded by THIS call). The
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* was quarantined — nothing was recorded by THIS call). The lease and
|
|
10
|
+
* recurrence advance happen synchronously before the asynchronous launcher
|
|
11
|
+
* request; the promise resolves only after the child has CLOSED and
|
|
12
12
|
* every durable transition — disposition/delivery, run record, lease
|
|
13
13
|
* release, one-shot consumption — is written.
|
|
14
14
|
*
|
|
@@ -20,8 +20,8 @@ export declare function executeCron(c: Cron, opts: {
|
|
|
20
20
|
outOfBand: boolean;
|
|
21
21
|
}): Promise<CronRunRecord | null>;
|
|
22
22
|
/** The daemon's cron pass: expire clock-bounded rows, apply overlap policies,
|
|
23
|
-
* then kick off every due active idle cron. Each
|
|
24
|
-
* but is NEVER awaited in the tick; returns one settlement promise per
|
|
23
|
+
* then kick off every due active idle cron. Each lease is claimed synchronously,
|
|
24
|
+
* but its launch is NEVER awaited in the tick; returns one settlement promise per
|
|
25
25
|
* admitted run.
|
|
26
26
|
*
|
|
27
27
|
* A run that launches or revives a node is admitted unconditionally: the
|
package/dist/daemon/cron-run.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var D=Object.defineProperty;var f=(e,t)=>D(e,"name",{value:t,configurable:!0});import{randomUUID as O}from"node:crypto";import{CRON_OUTPUT_HEAD_BYTES as h,EMPTY_STDOUT_SHA256 as x,formatCronOutputHead as I}from"./cron/capture.js";import{clearLiveRun as A,cronDaemonInstanceId as S,liveRunFor as R,registerLiveRun as T}from"./cron/live-runs.js";import{buildArmedRunContext as g}from"./cron/armed-context.js";import{decideHeldSettle as v,EXIT_HELD as M,HELD_DELIVERED as k}from"./cron/held.js";import{settleRun as w}from"./cron/settle.js";import{applyOverlapPolicies as B,expireDueCrons as L}from"./cron/passes.js";import{dueClockCrons as U,acquireCronRunLease as b,attachCronRunPid as y,advanceCron as P,setCronState as $}from"../core/canvas/crons.js";import{emitEvent as N}from"../core/events/emit.js";import{runAppCommand as Y}from"../core/runtime/run-command.js";import{nextSlotAfter as F}from"../core/wake.js";import{CRON_OUTPUT_HEAD_BYTES as ae}from"./cron/capture.js";import{cronDaemonInstanceId as ue,markSelfCanceledCronRun as le}from"./cron/live-runs.js";import{recoverStaleCronLeases as fe}from"./cron/lease-recovery.js";async function q(e,t){const{runId:s,outOfBand:r,startedAtIso:o,finishedAtMs:d,code:l,timedOut:i,processError:u}=t,p=!r&&!i&&u==null&&l===M&&!t.wasReplaced&&!t.wasSelfCanceled;let n,c;return t.wasReplaced?(n={kind:"stated",delivered:"replaced (overlap=replace)"},c="release"):p?(n={kind:"stated",delivered:k},c=v(e,o,d)??"release"):(n={kind:"disposed",ctx:{runId:s,startedAtIso:o,exitCode:i?-1:l,timedOut:i,runTimeoutS:e.run_timeout_s,processErrorMessage:u!=null?u.message:null,stdoutHead:t.stdoutHead,stdoutSha256:t.stdoutSha256,stderrHead:t.stderrHead},selfCanceled:t.wasSelfCanceled},c=r?"release":{kind:"clear"}),w(e,{outOfBand:r,outcome:n,record:{runId:s,startedAtIso:o,finishedAtMs:d,durationMs:d-t.startedAtMs,exitCode:i?-1:l,stdoutHead:t.stdoutHead===""?null:t.stdoutHead,stderrHead:u!=null?`run process error: ${u.message}`.slice(0,h):t.stderrHead===""?null:t.stderrHead},lease:c})}f(q,"settleClosedRun");function C(e,t,s,r){const o=Date.now(),d=`${s}: ${r.message}`.slice(0,h);return w(e,{outOfBand:t.outOfBand,outcome:{kind:"disposed",ctx:{runId:t.runId,startedAtIso:t.startedAtIso,exitCode:null,timedOut:!1,runTimeoutS:e.run_timeout_s,processErrorMessage:r.message,stdoutHead:"",stdoutSha256:x,stderrHead:d}},record:{runId:t.runId,startedAtIso:t.startedAtIso,finishedAtMs:o,durationMs:o-t.startedAtMs,exitCode:null,stdoutHead:null,stderrHead:d},lease:"release"})}f(C,"settleUnspawnedRun");function J(e,t){let s;try{s=F(e.recur,new Date(t))}catch(r){return N({level:"error",event:"cron.recur.unparseable",error:r,fields:{cron_id:e.cron_id,name:e.name,recur:e.recur}}),$(e.cron_id,"paused"),new Error(`unparseable recurrence ${JSON.stringify(e.recur)}: ${r.message} \u2014 this cron cannot be rescheduled until its recurrence is fixed (\`crtr cron cancel\` and re-arm it), so it has been paused.`)}return P(e.cron_id,s),null}f(J,"advanceRecurrence");function V(e,t){const{outOfBand:s}=t;return new Promise((r,o)=>{const d=O(),l=Date.now(),i=new Date(l).toISOString(),u={runId:d,outOfBand:s,startedAtIso:i,startedAtMs:l};if(!b(e.cron_id,S,i,s)){r(null);return}let p;try{if({env:p}=g(e,d),!s&&e.recur!=null){const n=J(e,l);if(n!==null)throw n}}catch(n){C(e,u,"run could not be armed",n).then(r,o);return}Y({command:e.command,cwd:e.cwd,env:p,app:e.grantee,...e.anchor_node===null?{}:{nodeId:e.anchor_node},timeoutMs:e.run_timeout_s*1e3,headBytes:h}).then(n=>{if(n.pid===null){n.completion.then(a=>{C(e,u,"run failed to spawn",a.processError??new Error("bash did not provide a process id")).then(r,o)},o);return}let c=!1;const _=f(()=>{n.completion.then(a=>{const m=R(e.cron_id),H=m!==void 0&&m.runId===d&&m.replaced,E=m!==void 0&&m.runId===d&&m.selfCanceled;if(A(e.cron_id,d),c){r(null);return}q(e,{runId:d,outOfBand:s,startedAtIso:i,startedAtMs:l,finishedAtMs:Date.now(),code:a.exitCode,timedOut:a.timedOut,processError:a.processError,stdoutHead:I(a.stdout,a.stdoutTruncated),stderrHead:I(a.stderr,a.stderrTruncated),stdoutSha256:a.stdoutSha256,wasReplaced:H,wasSelfCanceled:E}).then(r,o)},o)},"settleCommand");if(!y(e.cron_id,S,i,n.pid)){c=!0,n.terminate(),_();return}T(e.cron_id,{runId:d,replaced:!1,selfCanceled:!1,kill:n.terminate}),_()},n=>{C(e,u,"run failed to spawn",n).then(r,o)})})}f(V,"executeCron");function oe(e,t={}){const s=new Date(e).toISOString();L(s),B(e,s);const r=[];for(const o of U(s)){const d=V(o,{outOfBand:!1}).then(()=>{});r.push(d),t.register?.(d)}for(const o of r)o.catch(()=>{});return r}f(oe,"runDueCrons");export{ae as CRON_OUTPUT_HEAD_BYTES,ue as cronDaemonInstanceId,V as executeCron,le as markSelfCanceledCronRun,fe as recoverStaleCronLeases,oe as runDueCrons};
|
package/dist/daemon/crtrd-cli.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var i=Object.defineProperty;var n=(r,e)=>i(r,"name",{value:e,configurable:!0});import"../suppress-experimental-warnings.js";import{runDaemon as c}from"./crtrd.js";function
|
|
1
|
+
var i=Object.defineProperty;var n=(r,e)=>i(r,"name",{value:e,configurable:!0});import"../suppress-experimental-warnings.js";import{runDaemon as c}from"./crtrd.js";import{configureDaemonHttpDispatcher as o}from"./http-dispatcher.js";function a(r){for(let e=0;e<r.length;e++){const t=r[e];if(t==="--tcp")return r[e+1];if(t!==void 0&&t.startsWith("--tcp="))return t.slice(6)}}n(a,"parseTcpArg");function s(r){return r.includes("--prepare")}n(s,"parsePrepareArg"),o();const p=process.argv.slice(2);await c({tcp:a(p),prepare:s(p)});
|
package/dist/daemon/crtrd.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
var
|
|
2
|
-
`);
|
|
3
|
-
`)
|
|
1
|
+
var ve=Object.defineProperty;var a=(t,o)=>ve(t,"name",{value:o,configurable:!0});import{writeFileSync as ge,readFileSync as we,rmSync as ye,mkdirSync as V,existsSync as b,chmodSync as Se}from"node:fs";import{createServer as J}from"node:http";import{dirname as _e}from"node:path";import{envCrtrdTcp as be}from"../shared/env.js";import{serveCanvasConversationStore as ke}from"../core/canvas/sessions.js";import{pollRunObservers as Ee}from"./runs/observer.js";import{randomBytes as Pe}from"node:crypto";import{apiSocketPath as Ie,crtrHome as Te}from"../core/canvas/paths.js";import{activeAppUsers as Re}from"../core/spaces/users.js";import{ensureAppSpace as xe,ensureUserFiles as De}from"../core/spaces/space.js";import{LAUNCHER_SOCKET as E}from"../launcher/spec.js";import{launcherRequest as T}from"../launcher/client.js";import{initializeEmptyLayout as Ce,layoutNeedsMigration as Me,socketDir as Q}from"../core/layout.js";import{listNodeMemoryTargets as Y,listNodesForSupervision as Ae}from"../core/canvas/index.js";import{createApiServer as Le}from"./api/server.js";import{createAppListener as Ne}from"./api/app-listener.js";import{installLocalTerminalGrant as Ge}from"../core/grants/local.js";import{createGrantSync as $e,GRANT_SYNC_INTERVAL_S as Oe}from"../core/grants/sync.js";import{runRemovalCascades as Fe}from"../core/grants/remove.js";import{sweepSandboxes as je}from"../core/grants/on-sync.js";import{hasSyncedGrants as He}from"../core/grants/mirror.js";import{readConfig as ze}from"../core/config.js";import{reconcileUndeliveredTickets as Be}from"./human/sweep.js";import{resetHandedOffDeliveries as Ue}from"../core/canvas/deliveries.js";import{sweepReviews as qe}from"./review/sweep.js";import{pidfilePath as $}from"./pidfile.js";import{rendererWarning as We}from"../core/runtime/package-health.js";import{DEFAULT_INTERVAL_MS as Ke}from"./supervise-cadence.js";import{BrokerSupervisionReconciler as Ve}from"./reconcilers/broker-supervision.js";import{ControllerDeathReconciler as Je}from"./reconcilers/controller-death.js";import{NodeLifecycleReconciler as Qe}from"./reconcilers/node-lifecycle/tick.js";import{NodeDeadlineReconciler as Ye}from"./reconcilers/node-deadline.js";import{CronLaneReconciler as Xe}from"./reconcilers/cron-lane.js";import{DeliveryLaneReconciler as Ze}from"./reconcilers/delivery-lane.js";import{migrateLegacyExecutionIdentities as er}from"../core/canvas/executions.js";import{revokePriorEpochNodeTokens as rr}from"../core/canvas/node-tokens.js";import{PendingReviewSubmitReconciler as tr}from"./reconcilers/pending-review-submit.js";import{StorageMaintenanceReconciler as nr}from"./reconcilers/storage-maintenance.js";import{BashDeadlineReconciler as or}from"./reconcilers/bash-deadline.js";import{captureLivenessSnapshot as X,capturePidCommand as ir,captureTeardownSnapshot as Z,isPidAlive as ar,isAnyPidAlive as ee,killProcessTreePids as re}from"../core/canvas/pid.js";import{bindFleet as sr,boundFleet as cr}from"../core/runtime/fleet.js";import{bindDaemonControl as lr,clearDaemonControl as dr}from"./control.js";import{execDaemon as pr,spawnDaemon as mr}from"./manage.js";import{reconcileAndMigrateBoot as fr}from"../core/canvas/boot.js";import{resolveInstallId as ur}from"../core/canvas/install-id.js";import{setInstallId as hr}from"../core/runtime/nodes.js";import{claimDaemonOwnership as vr,releaseDaemonOwnership as te}from"../core/canvas/daemon-owner.js";import{migrate as gr,openDb as wr}from"../core/canvas/db.js";import{prewarmRecentRecipes as yr,reapStaleSpares as Sr}from"../core/runtime/warm-pool.js";import{DaemonFleet as _r}from"./fleet.js";import{BOOT_MIGRATIONS as br}from"./boot-migrations.js";import{applyJoinedOwner as kr}from"./joined-owner.js";import{emitEvent as h}from"../core/events/emit.js";import{operationIdContext as _}from"../core/events/operation-id.js";import{bindDaemonEventSource as Er}from"../core/events/source.js";import{activateOnDiskMigrations as Pr,MigrationBlockedError as Ir,runForcedOnDiskMigrations as Tr}from"../migrations/activation.js";import{convertLegacyProviderStore as Rr,convertLegacyScopedStore as xr}from"../core/scoped-state/migrate.js";import{userScopeRoot as Dr}from"../core/scope.js";import{secretsDir as Cr}from"../core/layout.js";function O(t,o){return t.includes(` --canvas-home ${o} `)}a(O,"brokerCommandDeclaresCanvasHome");function F(t){return/ --epoch (\S+) /.exec(t)?.[1]??null}a(F,"brokerCommandEpoch");const Mr=5e3,ne=150;async function Ar(t){const o=X();if(o===null)throw h({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness"}}),new Error("prior-epoch broker census could not capture the process table");const s=Te(),m=[];for(const[i,p]of o.processes){const g=p.command;if(p.zombie||!g.includes("broker-cli.js")||!O(g,s)||F(g)===t)continue;const y=g.trim().split(/\s+/).at(-1)??"";y===""||y.endsWith("broker-cli.js")||m.push({pid:i,nodeId:y})}let f=0;const n=[];for(const i of m){const p=ir(i.pid);if(p===null||!p.includes("broker-cli.js")||!O(p,s)||F(p)===t||p.trim().split(/\s+/).at(-1)!==i.nodeId)continue;const g=Z(i.pid,null);if(!g.reused){try{process.platform==="linux"&&b(E)?await T({operation:"stop",pid:i.pid}):process.kill(i.pid,"SIGTERM")}catch{continue}f++,n.push({pid:i.pid,snap:g})}}const w=Date.now()+Mr;for(;Date.now()<w&&n.some(i=>ee(i.snap.tree.length>0?i.snap.tree:[i.pid]));)await new Promise(i=>setTimeout(i,ne));let v=0;for(const i of n){const p=i.snap.tree.length>0?i.snap.tree:[i.pid];ee(p)&&(process.platform==="linux"&&b(E)?await T({operation:"stop",pid:i.pid}):re(p,"SIGKILL",i.snap.identities),v++)}v>0&&await new Promise(i=>setTimeout(i,ne));const c=X();if(c===null)throw h({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness",stage:"final"}}),new Error("prior-epoch broker census could not capture the final process table");const d=[];for(const[i,p]of c.processes){const g=p.command;p.zombie||!g.includes("broker-cli.js")||O(g,s)&&F(g)!==t&&d.push(i)}if(d.length>0)throw new Error(`prior-epoch broker census could not prove termination of pid(s): ${d.join(", ")}`);h({level:"info",event:"daemon.census.completed",fields:{prior_epoch_brokers:m.length,sigtermed:f,sigkilled:v}})}a(Ar,"reapPriorEpochBrokers");const Lr=5e3;async function Nr(t){const o=Array.from(t.entries());if(o.length===0)return;const s=o.map(([,n])=>({pid:n.pid,snap:Z(n.pid,null),exited:n.handle.exited}));for(const n of s)if(!n.snap.reused)try{process.platform==="linux"&&b(E)?await T({operation:"stop",pid:n.pid}):process.kill(n.pid,"SIGTERM")}catch{}const m=new Promise(n=>{setTimeout(n,Lr).unref()});await Promise.allSettled(s.map(n=>Promise.race([n.exited.then(()=>{}),m])));const f=[];for(const n of s)ar(n.pid)&&(process.platform==="linux"&&b(E)?await T({operation:"stop",pid:n.pid}):re(n.snap.tree.length>0?n.snap.tree:[n.pid],"SIGKILL",n.snap.identities),f.push(n));await Promise.all(f.map(n=>n.exited)),h({level:"info",event:"daemon.fleet_teardown.completed",fields:{brokers:s.length,sigkilled:f.length}})}a(Nr,"teardownFleet");function oe(){V(_e($()),{recursive:!0}),ge($(),String(process.pid),"utf8")}a(oe,"writePidfile");function ie(t){return typeof t=="object"&&t!==null&&t.code==="ENOENT"}a(ie,"isMissingPathError");function ae(t){const o=$();let s;try{s=we(o,"utf8")}catch(m){if(ie(m))return;throw m}if(s.trim()!==String(t))throw new Error(`daemon readiness mirror does not name this invocation (expected pid ${t})`);try{ye(o)}catch(m){if(ie(m))return;throw m}}a(ae,"removeOwnedPidfileMirror");const Gr={acceptsDetachedWork:a(()=>!0,"acceptsDetachedWork"),registerDetached:a(t=>{t.catch(()=>{})},"registerDetached")},j=new Ve,$r=new Je,Or=new Qe,Fr=new Ye,jr=new Xe,Hr=new Ze,zr=new tr,Br=new nr,Ur=new or;async function qr(t=Date.now(),o=Gr){const s=cr(),m=await j.runFleetPreamble(s);let f,n;try{const v=Ae();f=v.filter(c=>c.status==="active"||c.status==="idle"),n=v.filter(c=>c.status==="done"||c.status==="canceled"||c.status==="dead")}catch(v){h({level:"error",event:"canvas.node_list.failed",error:v});return}await j.run(t,{rows:f,fleet:s,lifecycle:o}),$r.run(t,{rows:f});const w=await Or.run(t,{rows:[...f,...n],fleet:s});Fr.run(t),jr.run(t,{lifecycle:o}),Hr.run(t,{lifecycle:o}),zr.run(t,{lifecycle:o}),Br.run(t,{lifecycle:o,fleet:s}),Ee(),await Ur.run(t,{rows:f}),j.warnIfSaturated({fleet:s,lifecycle:o,thresholds:m,frozen:w})}a(qr,"superviseTick");async function Wr(t){V(Q(),{recursive:!0,mode:493}),process.platform==="linux"&&Se(Q(),493);const o=Ie();if(b(o))throw new Error(`layout refusal cannot bind occupied socket: ${o}`);const s=J((c,d)=>{if(c.method==="GET"&&c.url==="/healthz"){d.writeHead(200,{"content-type":"application/json; charset=utf-8"}),d.end(JSON.stringify({ok:!1,daemon_up:!0,store_accessible:!1,brokers_reconciled:!1,startup_phase:"blocked",startup_blocked:"layout_migration_required"}));return}d.writeHead(503,{"content-type":"application/json; charset=utf-8"}),d.end(JSON.stringify({error:{code:"layout_migration_required",message:"run crtr sys migrate while the runtime is offline",type:"server_error",origin:"runtime",retryable:!1}}))});await new Promise((c,d)=>{s.once("error",d),s.listen(o,()=>{s.off("error",d),c()})});let m;const f=t.tcp??be();if(f){const c=/^(.*):(\d+)$/.exec(f);if(!c||Number(c[2])>65535)throw new Error(`invalid refusal TCP address: ${f}`);const d=J(s.listeners("request")[0]);await new Promise((i,p)=>{d.once("error",p),d.listen(Number(c[2]),c[1],()=>{d.off("error",p),i()})}),m=d}oe();let n;const w=a(()=>(n??=(async()=>{s.closeAllConnections(),m?.closeAllConnections(),await Promise.all([s,m].filter(c=>c!==void 0).map(c=>new Promise((d,i)=>c.close(p=>p?i(p):d())))),ae(process.pid),process.off("SIGINT",v),process.off("SIGTERM",v)})(),n),"cleanup"),v=a(()=>{w().then(()=>process.exit(0),c=>{process.stderr.write(`[crtrd] layout refusal cleanup failed: ${String(c)}
|
|
2
|
+
`),process.exit(1)})},"onSignal");return process.on("SIGINT",v),process.on("SIGTERM",v),w}a(Wr,"serveLayoutRefusal");async function Kr(t={}){if(Me())return Wr(t);Ce();const o=vr(Pe(16).toString("hex"));if(!o.claimed){if(o.reason==="incumbent_alive")process.stderr.write(`[crtrd] already running (pid ${o.incumbentPid??"?"})
|
|
3
|
+
`);else{const e=[o.incumbentPid!==void 0?`pid ${o.incumbentPid}`:void 0,o.verdict!==void 0?`verdict ${o.verdict}`:void 0].filter(l=>l!==void 0),r=e.length>0?` (${e.join(", ")})`:"";process.stderr.write(`[crtrd] claim lost: ${o.reason}${r}
|
|
4
|
+
`)}return async()=>{}}const s=o.claim;let m=null;try{await Ar(s.token),xr({kind:"user",root:Dr()}),await Rr(Cr()),gr(wr()),m=kr(),process.platform==="linux"&&b(E)&&await T({operation:"users.sync",users:Re()}),rr(s.token)}catch(e){try{const{released:r}=te(s);if(!r)throw new Error("daemon ownership claim was not released")}catch(r){throw new AggregateError([e,r],"daemon startup failed and cleanup also failed")}throw e}let f=!0,n,w=Promise.resolve(),v=!1,c,d;const i=new Set;let p=!1,g=!1,y,C,H=!1,M,R,x,A,u={phase:"initializing",message:"daemon startup is initializing its on-disk memory migration and normal services are unavailable",blockerPaths:[]},P="initial startup activation",se=null;function ce(){return u.phase==="ready"?null:{phase:u.phase,message:u.message,blockerPaths:u.blockerPaths}}a(ce,"startupBlock");function I(e){i.add(e),e.finally(()=>{i.delete(e)}).catch(()=>{})}a(I,"registerDetached");const le={acceptsDetachedWork:a(()=>f,"acceptsDetachedWork"),registerDetached:I};async function de(){try{f=!1,c!==void 0&&(clearInterval(c),c=void 0),x!==void 0&&(clearInterval(x),x=void 0);let e;do e=w,await e;while(e!==w);for(;i.size>0;)await Promise.allSettled([...i]);if(d!==void 0&&(await Nr(d),d.dispose()),C!==void 0&&!H&&(H=!0,await C.close()),R!==void 0){const r=R;R=void 0,await r.close()}if(M!==void 0){const r=M;M=void 0,await r.close()}if(p||(ae(process.pid),p=!0),p&&!g){const{released:r}=te(s);if(!r)throw new Error("daemon ownership claim was not released");g=!0}}finally{dr(),process.off("SIGINT",U),process.off("SIGTERM",q),process.off("exit",W)}}a(de,"cleanupAttempt");const L=1e3;let z=!1;function pe(){return z?{graceMs:L}:(z=!0,_.fresh(()=>{h({level:"info",event:"daemon.handover.armed",fields:{pid:process.pid,grace_ms:L}})}),setTimeout(()=>{me()},L),{graceMs:L})}a(pe,"requestHandover");async function me(){try{await k()}catch(e){const r=e instanceof Error?e.stack??e.message:String(e);process.stderr.write(`[crtrd] handover cleanup failed:
|
|
4
5
|
${r}
|
|
5
|
-
`),process.exit(1)}try{process.pid===1&&await
|
|
6
|
-
`),process.exit(1)}process.exit(0)}
|
|
7
|
-
${
|
|
8
|
-
`),process.exit(1)}}
|
|
6
|
+
`),process.exit(1)}try{process.platform==="linux"&&b(E)&&(await T({operation:"daemon.handover"}),process.exit(0)),process.pid===1&&await pr();const e=await mr();_.fresh(()=>{h({level:"info",event:"daemon.handover.completed",fields:{predecessor_pid:process.pid,successor_pid:e.pid??e.existing_pid??null,spawned:e.started}})})}catch(e){_.fresh(()=>{h({level:"error",event:"daemon.handover.successor_failed",error:e})});const r=e instanceof Error?e.message:String(e);process.stderr.write(`[crtrd] handover successor failed to start: ${r}
|
|
7
|
+
`),process.exit(1)}process.exit(0)}a(me,"performHandover");function k(){if(y!==void 0)return y;const e=de();return y=e,e.then(()=>{y===e&&(y=void 0)},()=>{y===e&&(y=void 0)}),e}a(k,"requestCleanup");async function B(e){try{await k(),process.exit(0)}catch(r){process.exitCode=1;const l=r instanceof Error?r.stack??`${r.name}: ${r.message}`:String(r);process.stderr.write(`[crtrd] ${e} cleanup failed:
|
|
8
|
+
${l}
|
|
9
|
+
`),process.exit(1)}}a(B,"handleSignal");function U(){B("SIGINT")}a(U,"onSigint");function q(){B("SIGTERM")}a(q,"onSigterm");function W(){k().catch(()=>{})}a(W,"onExit");function N(e){f&&(w=w.then(e).then(()=>{},r=>{_.fresh(()=>{h({level:"error",event:"daemon.lane_job.failed",error:r})})}))}a(N,"enqueue");function K(){!f||v||(v=!0,N(async()=>{if(v=!1,!!f)try{await qr(Date.now(),le)}catch(e){_.fresh(()=>{h({level:"error",event:"daemon.tick.failed",error:e})})}}))}a(K,"enqueueTick");let D=null;async function fe(){if(D!==null)throw{status:500,code:"admission_failed",message:`daemon admission previously failed: ${D instanceof Error?D.message:String(D)}`};if(u.phase==="ready")return{admitted:!1,already_admitted:!0,startup_phase:"ready"};if(u.phase!=="prepared"&&u.phase!=="recovering")throw{status:409,code:"not_prepared",message:u.message};const e=u.phase==="prepared";try{return await G(),u={phase:"ready",message:"",blockerPaths:[]},e?{admitted:!0,already_admitted:!1,startup_phase:"ready"}:{admitted:!1,already_admitted:!0,startup_phase:"ready"}}catch(r){throw D=r,{status:500,code:"admission_failed",message:`daemon admission failed: ${r instanceof Error?r.message:String(r)}`}}}a(fe,"admitStartup");async function ue(e){if(P!==null)throw{status:409,code:"migration_in_progress",message:`on-disk migration is already running (${P})`};P="repair";try{const r=await Tr({dryRun:e.dryRun,explicitDirs:e.dirs,nodes:Y()});if(e.dryRun||!r.finalVerificationSucceeded||u.phase!=="blocked")return{result:r,resumed:!1};if(t.prepare)return u={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]},{result:r,resumed:!1};try{return await G(),u={phase:"ready",message:"",blockerPaths:[]},{result:r,resumed:!0}}catch(l){const S=l instanceof Error?l.message:String(l);return setTimeout(()=>{k().catch(()=>{})},1e3),{result:r,resumed:!1,resumeError:S}}}finally{P=null}}a(ue,"repairMigrations");async function he(){n=t.intervalMs??Ke;const e=s.token;d=new _r({epoch:e,enqueue:N}),sr(d),u={phase:"recovering",message:"daemon startup recovery is running and normal services are unavailable",blockerPaths:[]},_.fresh(()=>{h({level:"info",event:"daemon.started",fields:{pid:process.pid,interval_ms:n}})});const r=ur();if(hr(r),_.fresh(()=>{h({level:"info",event:"daemon.install_id.resolved",fields:{install_id:r}})}),_.fresh(()=>{let l;try{l=We()}catch{return}l!==null&&h({level:"warn",event:"daemon.startup.warning",fields:{stage:"termrender",warning:l.slice(0,2048)}})}),await _.fresh(async()=>{await qe(),await Be(),Ue(Date.now())}),_.fresh(()=>{const{reconcile:l,migrated:S}=fr(er);l.changed&&h({level:"info",event:"daemon.boot_change.reconciled",fields:{cleared_count:l.cleared.length,same_boot_proven:l.sameBootProven}}),S.length>0&&h({level:"info",event:"daemon.pid_identity.migrated",fields:{migrated_count:S.length}})}),_.fresh(()=>{for(const l of br){const S=l.apply();S.changed&&h({level:"info",event:"daemon.boot_migration.applied",fields:{migration:l.id,...S.summary}})}}),A){const l=a(()=>{I(A().catch(()=>{}))},"refresh");I(Fe().catch(()=>{})),I(je().then(({completion:S})=>S).catch(S=>{h({level:"error",event:"daemon.grants.sweep_failed",error:S})})),l(),x=setInterval(l,Oe*1e3),x.unref()}N(()=>{Sr(),yr()}),c=setInterval(K,n),K()}a(he,"completeStartup");function G(){return se??=he().catch(e=>{throw u={phase:"initializing",message:"daemon startup recovery failed and normal services are unavailable",blockerPaths:[]},e})}a(G,"resumeStartup");try{process.on("SIGINT",U),process.on("SIGTERM",q),process.on("exit",W),Er(),m!==null&&h({level:"info",event:"daemon.joined_owner.applied",fields:{owner:m.owner,rows:m.rows}}),M=await ke();const e=s.token;lr({epoch:e,requestHandover:pe,registerDetached:I,startupBlock:ce,admitStartup:fe,repairMigrations:ue}),oe(),C=Le({tcp:t.tcp}),await C.ready;const r=ze("user").runtime;r?.issuer?A=$e(r.issuer,I):Ge(),r!==void 0&&(R=Ne(r,()=>He(r.issuer.replace(/\/$/,"")),A),await R.ready);try{await Pr({nodes:Y()})}catch(l){if(P=null,l instanceof Ir)return u={phase:"blocked",message:l.message,blockerPaths:l.blockerPaths},k;throw l}process.platform==="linux"&&b(E)&&(De(),await xe("app:terminal"));try{t.prepare?u={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]}:(await G(),u={phase:"ready",message:"",blockerPaths:[]})}finally{P=null}return k}catch(e){try{await k()}catch(r){throw new AggregateError([e,r],"daemon startup failed and cleanup also failed")}throw e}}a(Kr,"runDaemon");var en=Kr;export{O as brokerCommandDeclaresCanvasHome,F as brokerCommandEpoch,en as default,Kr as runDaemon,qr as superviseTick};
|
|
@@ -19,6 +19,10 @@ export interface DeliveryJob {
|
|
|
19
19
|
/** The stored document; its `delivery.attempt` is stamped per attempt. */
|
|
20
20
|
document: unknown;
|
|
21
21
|
attempt: number;
|
|
22
|
+
/** Originating node, or null for a request made outside a node. */
|
|
23
|
+
nodeId?: string | null;
|
|
24
|
+
/** Frozen originating app, used with its current grant after node deletion. */
|
|
25
|
+
app?: string;
|
|
22
26
|
}
|
|
23
27
|
/** Spawn and settle one already-claimed delivery. `settle` writes the outcome
|
|
24
28
|
* to whichever durable row owns this attempt. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var C=Object.defineProperty;var a=(e,t)=>C(e,"name",{value:t,configurable:!0});import{spawn as T}from"node:child_process";import{envHomeOverride as h}from"../../shared/env.js";import{deliveryBackoffMs as g}from"../../core/canvas/delivery-contract.js";import{killProcessGroup as y}from"../../core/canvas/pid.js";import{buildOperationalEnvBase as v}from"../../core/runtime/spawn-env.js";import{getNode as O}from"../../core/canvas/canvas.js";import{appProcessSandboxed as A,launchAppProcess as _}from"../../core/spaces/process.js";const E=12e4,S=2e3,w=4*1024;function x(e,t,r){return e.spawnError!==void 0?{state:"pending",nextAttemptAt:r+g(t),failure:m("spawn_error",{message:e.spawnError.message,stderr:e.stderr})}:e.timedOut?{state:"pending",nextAttemptAt:r+g(t),failure:m("timeout",{...e.signal===null?{}:{signal:e.signal},stderr:e.stderr})}:e.signal!==null?{state:"pending",nextAttemptAt:r+g(t),failure:m("signal",{signal:e.signal,stderr:e.stderr})}:e.exitCode===0?{state:"accepted"}:e.exitCode===78?{state:"permanent_failed",failure:m("exit",{exitCode:78,stderr:e.stderr})}:{state:"pending",nextAttemptAt:r+g(t),failure:m("exit",{exitCode:e.exitCode??void 0,stderr:e.stderr})}}a(x,"deliverySettlementForOutcome");function m(e,t){return{kind:e,...t}}a(m,"failure");function D(){let e=Buffer.alloc(0);return{take(t){e=t.length>=w?t.subarray(t.length-w):Buffer.concat([e,t]).subarray(Math.max(0,e.length+t.length-w))},decode(){return e.toString("utf8")}}}a(D,"stderrTailCapture");function L(e,t){const r=e,u=r.delivery;return JSON.stringify({...r,delivery:{...u,attempt:t}})}a(L,"documentForAttempt");function R(e){const t=v({targetCwd:e,targetProfileId:null}),r=h();return r!==void 0&&r!==""&&(t.CRTR_HOME=r),t}a(R,"deliveryEnv");async function V(e,t){const r=D();let u;try{u=L(e.document,e.attempt)}catch(d){t(x({exitCode:null,signal:null,timedOut:!1,spawnError:d,stderr:r.decode()},e.attempt,Date.now()));return}if(process.platform==="linux"){let d;try{if(!A())throw new Error("root launcher is required for delivery");const o=e.nodeId===null||e.nodeId===void 0?null:O(e.nodeId),f=e.app??o?.grantee??(e.nodeId==null?"app:terminal":void 0);if(!f)throw new Error(`delivery origin ${e.nodeId} was deleted without a stored app`);const l=await _({...o?{nodeId:e.nodeId}:{},app:f,command:e.argv,cwd:e.cwd,env:v({targetCwd:e.cwd,targetProfileId:null,skipSpawnAllow:!0}),stdin:u,stdoutBytes:0,stderrBytes:w,stderrTail:!0});let s,p=!1;try{s=setTimeout(()=>{p=!0,l.stop().catch(i=>{console.error(`delivery process ${l.pid} could not be stopped:`,i)})},E),s.unref?.();const c=await l.completion;d={exitCode:c.exitCode,signal:c.signal,timedOut:p,stderr:c.stderr}}finally{s!==void 0&&clearTimeout(s)}}catch(o){d={exitCode:null,signal:null,timedOut:!1,spawnError:o,stderr:""}}t(x(d,e.attempt,Date.now()));return}let n;try{n=T(e.argv[0],e.argv.slice(1),{cwd:e.cwd,env:R(e.cwd),detached:!0,stdio:["pipe","pipe","pipe"]})}catch(d){t(x({exitCode:null,signal:null,timedOut:!1,spawnError:d,stderr:r.decode()},e.attempt,Date.now()));return}await new Promise(d=>{let o=!1,f=!1,l,s;const p=a(i=>{o||(o=!0,s!==void 0&&clearTimeout(s),!i.timedOut&&l!==void 0&&clearTimeout(l),n.stdin?.destroy(),n.stdout?.destroy(),n.stderr?.destroy(),t(x(i,e.attempt,Date.now())),d())},"finish");n.stdout?.on("data",()=>{}),n.stderr?.on("data",i=>r.take(i)),n.stdin?.on("error",()=>{}),n.on("error",i=>{p({exitCode:null,signal:null,timedOut:!1,spawnError:i,stderr:r.decode()})}),n.on("exit",(i,I)=>{p({exitCode:i,signal:I,timedOut:f,stderr:r.decode()})});const c=a(()=>{n.pid!==void 0&&(y(n.pid),l=setTimeout(()=>y(n.pid,"SIGKILL"),S),l.unref?.())},"killWithEscalation");s=setTimeout(()=>{f=!0,c()},E),s.unref?.(),n.stdin?.end(u,"utf8")})}a(V,"runDelivery");export{w as DELIVERY_STDERR_TAIL_BYTES,E as DELIVERY_TIMEOUT_MS,x as deliverySettlementForOutcome,V as runDelivery};
|
package/dist/daemon/fleet.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ export declare class DaemonFleet implements FleetRegistry {
|
|
|
66
66
|
interruptForProfilePause(nodeId: string, pid?: number | undefined): void;
|
|
67
67
|
hasProfilePauseInterruption(nodeId: string): boolean;
|
|
68
68
|
forget(nodeId: string): void;
|
|
69
|
-
onChildExit(nodeId: string, status: FleetExitStatus): void;
|
|
69
|
+
onChildExit(nodeId: string, status: FleetExitStatus, executionId?: string): void;
|
|
70
70
|
deliverExit(nodeId: string, status: FleetExitStatus): void;
|
|
71
71
|
/** The node-lifecycle tick's enactment entry. */
|
|
72
72
|
applyDeadRowPolicy(nodeId: string): Promise<void>;
|
package/dist/daemon/fleet.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
var b=Object.defineProperty;var l=(
|
|
1
|
+
var b=Object.defineProperty;var l=(t,e)=>b(t,"name",{value:e,configurable:!0});import{getNode as p,getRow as g,subscribersOf as k}from"../core/canvas/index.js";import{revokeExitedNodeToken as $}from"../core/canvas/node-tokens.js";import{isProfilePaused as T}from"../core/profiles/manifest.js";import{fullName as v}from"../core/canvas/labels.js";import{isSafeNodeId as o}from"../core/canvas/paths.js";import{transition as _}from"../core/runtime/lifecycle.js";import{fanDoctrineWake as P}from"../core/runtime/close.js";import{readInterruptedTurn as E,readTransportPoisonVerdict as x}from"../core/canvas/recovery.js";import{hasPendingWake as N}from"./reconcilers/live-obligation.js";import{clearRespawnPolicy as h,deferRespawnWhileOffline as R,MAX_RESPAWN_ATTEMPTS as C,OFFLINE_RESPAWN_RETRY_MS as F,recordRespawnPolicy as S,respawnBackoffMs as M}from"./reconcilers/node-lifecycle/respawn-policy.js";import{probeOnline as O}from"../core/runtime/connectivity.js";import{reviveNode as A}from"../core/runtime/revive.js";import{pushUrgent as m}from"../core/feed/feed.js";import{emitEvent as c}from"../core/events/emit.js";import{brokerThresholdsForDaemon as z}from"../core/runtime/fleet.js";import{isRecoveryHeld as D}from"../core/runtime/recovery-hold.js";function w(t,e){const r=e===void 0?"The daemon did not observe an exit status.":`The observed exit status was code ${e.code??"null"}, signal ${e.signal??"null"}.`;return`\u26A0 Spawn failed \u2014 \`${t.name}\` (${t.kind}) never started.
|
|
2
2
|
|
|
3
3
|
Its pi vehicle exited before the session came up (no pi_session_id was ever recorded), so the node produced no output. ${r}
|
|
4
4
|
|
|
5
|
-
Inspect canonical event diagnostics with \`crtr sys logs --node ${
|
|
5
|
+
Inspect canonical event diagnostics with \`crtr sys logs --node ${t.node_id}\`.
|
|
6
6
|
|
|
7
|
-
If the work still needs doing, re-spawn it.`}l(w,"bootFailureBody");async function y(
|
|
7
|
+
If the work still needs doing, re-spawn it.`}l(w,"bootFailureBody");async function y(t,e){await m(t.node_id,w(t,e),{from:t.node_id})}l(y,"surfaceBootFailure");async function B(t){const e=x(t.node_id),r=e===null?"":`
|
|
8
8
|
|
|
9
|
-
Provider rotation observed ${e.consecutivePasses} consecutive route-queue passes with no HTTP response (tried ${e.routes.join(", ")}). Check network and provider transport before reviving.`,
|
|
9
|
+
Provider rotation observed ${e.consecutivePasses} consecutive route-queue passes with no HTTP response (tried ${e.routes.join(", ")}). Check network and provider transport before reviving.`,i=`\u26A0 Crash loop \u2014 \`${t.name}\` (${t.kind}) kept dying without settling a turn.
|
|
10
10
|
|
|
11
11
|
Its session started successfully, but six consecutive relaunches made no progress, so the daemon stopped retrying.`+r+`
|
|
12
12
|
|
|
13
|
-
Fix the crash cause, then revive the node if the work still needs doing.`;await
|
|
13
|
+
Fix the crash cause, then revive the node if the work still needs doing.`;await m(t.node_id,i,{from:t.node_id})}l(B,"surfaceCrashLoop");async function L(t,e){const r=e instanceof Error?e.message:String(e),i=`\u26A0 Recovery failed \u2014 \`${t.name}\` (${t.kind}) could not be relaunched.
|
|
14
14
|
|
|
15
15
|
The daemon refused this recovery before starting a broker: ${r}
|
|
16
16
|
|
|
17
|
-
The node is now dead. Fix the recorded launch configuration, then revive it if the work still needs doing.`;await
|
|
17
|
+
The node is now dead. Fix the recorded launch configuration, then revive it if the work still needs doing.`;await m(t.node_id,i,{from:t.node_id})}l(L,"surfaceRecoveryFailure");function W(t){return t?.cycle_pending!==!0}l(W,"retryResumeMode");function q(t,e,r=!0){return t===null||t.status==="done"||t.status==="canceled"||t.status==="dead"?"forget":t.intent==="refresh"?"respawn-fresh":t.intent==="idle-release"?"dormant":t.lifecycle==="resident"&&!e&&!r&&t.pi_session_id!=null?"release-idle":t.pi_session_id!=null?W(t)?"respawn-resume":"respawn-cycle":e||t.fork_from!=null?"respawn-fresh":"boot-failure"}l(q,"classifyDeadNode");const G=3e4;class ne{static{l(this,"DaemonFleet")}#n;#o;#i;#l;#e=new Map;#r=new Set;#s=new Set;#t=new Map;#c=Number.NEGATIVE_INFINITY;constructor(e){this.#n=e.epoch,this.#o=e.enqueue,this.#i=e.now??Date.now,this.#l=e.probeOnline??(()=>O())}epoch(){return this.#n}register(e,r){if(this.#e.has(e))throw new Error(`fleet: ${e} already has a live broker entry \u2014 refusing a second launch (programming error)`);if(r.pid===null)throw new Error(`fleet: refusing to register ${e} with no pid`);this.#r.delete(e),this.#t.delete(e),this.#e.set(e,{pid:r.pid,handle:r})}has(e){return this.#e.has(e)}isClaimed(e){return this.#e.has(e)||this.#r.has(e)}get(e){return this.#e.get(e)}size(){return this.#e.size}occupancy(){return this.#e.size+this.#r.size}reserveSlot(e){if(this.#r.has(e)||this.#e.has(e))return!0;const{automaticReviveCap:r}=z();if(this.occupancy()<r)return this.#r.add(e),!0;const i=this.#i();return i-this.#c>=G&&(this.#c=i,c({level:"warn",event:"broker.capacity.revive_deferred",fields:{live_count:this.occupancy(),hard_cap:r}})),!1}releaseReservation(e){this.#r.delete(e)}entries(){return this.#e.entries()}interruptForProfilePause(e,r=this.#e.get(e)?.pid){if(r!==void 0){this.#s.add(e);try{process.kill(r,"SIGTERM")}catch{}}}hasProfilePauseInterruption(e){return this.#s.has(e)}forget(e){this.#e.delete(e),this.#r.delete(e),this.#t.delete(e)}onChildExit(e,r,i){i&&$(i),this.#e.delete(e),this.#o(()=>{const s=p(e),a=s?.launched_at==null?Number.NaN:Date.parse(s.launched_at),n=Number.isFinite(a)?Math.max(0,this.#i()-a):null,d=s?.respawn_failures??0;s?.status==="done"||s?.status==="canceled"||s?.status==="dead"?this.#t.delete(e):this.#t.set(e,r),this.#u(e,r,n,d)})}deliverExit(e,r){this.onChildExit(e,r)}async applyDeadRowPolicy(e){const r=this.#t.get(e);try{await this.#f(e,r)}finally{this.#t.get(e)===r&&this.#t.delete(e)}}async terminalizeIfStillNonTerminal(e,r,i,s,a){const n=p(e);return n===null||n.status==="done"||n.status==="canceled"||n.status==="dead"?!1:(await this.#a(e,n,{event:r,reason:s,detail:a,wake:`Child crashed \u2014 ${v(n)} (${e}) could not be relaunched and is now dead. It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,surface:l(()=>L(n,i),"surface")}),!0)}dispose(){}#u(e,r,i,s){c({level:"info",event:"broker.exit.observed",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e},code:r.code,signal:r.signal,uptime_ms:i,consecutive_failures:s}})}async#f(e,r){return this.#h(e,r)}async#h(e,r){const i=p(e);if(i!==null&&T(i.profile_id))return h(e),"forget";if(this.#s.delete(e))return h(e),"forget";if(D(e))return"dormant";const s=E(e)?.interrupted===!0,a=q(i,s,N(e));switch(a){case"forget":h(e);break;case"dormant":h(e);break;case"release-idle":h(e),_(e,"release"),c({level:"info",event:"broker.recovery.released",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e}}});break;case"boot-failure":await this.#a(e,i,{event:"broker.boot.failed",reason:"boot_failed",detail:{schema:"crtr.node-outcome-detail/v1",message:w(i,r)},wake:`Child crashed \u2014 ${v(i)} (${e}) exited before its session ever came up and is now dead. It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,surface:l(()=>y(i,r),"surface")});break;case"respawn-fresh":case"respawn-cycle":case"respawn-resume":await this.#d(e,i,a,s);break}return a}async#d(e,r,i,s){const a=g(e);if(a===null)return;const n=a.respawn_failures??0;if(!await this.#l()){R(e,n,this.#i()),c({level:"info",event:"broker.respawn.offline_deferred",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e},action:i,retry_in_ms:F,consecutive_failures:n}});return}const d=a.respawn_not_before==null,f=d?S(a,this.#i()):{failures:n,notBefore:a.respawn_not_before,exhausted:n>=C};if(f.exhausted){const u=`Child crashed \u2014 ${v(r)} (${e}) kept dying without settling a turn (${f.failures} consecutive launches) and is now dead. It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`;await this.#a(e,r,{event:"broker.respawn.exhausted",reason:"crash_looped",detail:{schema:"crtr.node-outcome-detail/v1",message:u,respawn_failures:f.failures},wake:u,...r.pi_session_id!=null?{surface:l(()=>B(r),"surface")}:{}});return}if(d&&f.notBefore!==null){c({level:"info",event:"broker.respawn.deferred",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e},action:i,backoff_ms:M(f.failures),consecutive_failures:f.failures}});return}c({level:"info",event:"broker.respawn.started",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e},action:i,consecutive_failures:f.failures}});try{await A(e,{capacity:"freeze",resume:i==="respawn-resume",wakeReason:i==="respawn-resume"&&s?"runtime-restart-abort":void 0,recovery:!0})}catch(u){c({level:"error",event:"broker.respawn.failed",...o(e)?{node_id:e}:{},error:u,fields:{...o(e)?{}:{affected_node_id:e},action:i}}),await this.terminalizeIfStillNonTerminal(e,"broker.respawn.refused",u,"launch_failed",{schema:"crtr.node-outcome-detail/v1",message:u instanceof Error?u.message:String(u)})}}async#a(e,r,i){c({level:"error",event:i.event,...o(e)?{node_id:e}:{fields:{affected_node_id:e}}}),_(e,"crash",{reason:i.reason,outcome:{detail:i.detail}});try{await(i.surface??(()=>y(r)))()}catch(s){c({level:"error",event:"broker.boot_failure_surface.failed",...o(e)?{node_id:e}:{fields:{affected_node_id:e}},error:s})}P(e,k(e),i.wake,{reason:"child-crashed",child:e})}}export{ne as DaemonFleet,q as classifyDeadNode,W as retryResumeMode,y as surfaceBootFailure};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function configureDaemonHttpDispatcher(): void;
|