@north-light/crouter 0.3.233 → 0.3.234
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.js +16 -15
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/integration/provider-rotation.test.ts +1 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +14 -17
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/crtr-commands/index.ts +7 -11
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/index.ts +8 -8
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +10 -11
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/pi-shell-runner.ts +2 -2
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +3 -3
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +7 -7
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +8 -8
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +6 -6
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/sysprompt-window.ts +3 -3
- package/dist/builtin-pi-packages/pi-crtr-extensions/lib/subscription-state.ts +1 -1
- package/dist/clients/attach/chrome/ticket-panel.js +15 -2
- package/dist/clients/attach/overlays/graph.js +0 -3
- package/dist/clients/attach/overlays/mcp.js +1 -2
- package/dist/clients/attach/render/chat-view.js +0 -12
- package/dist/clients/attach/render/crtr-output.js +0 -2
- package/dist/clients/attach/render/tool-calls.js +0 -6
- package/dist/clients/attach/slash/dispatch.js +8 -11
- package/dist/clients/attach/viewer.js +532 -534
- package/dist/clients/conversation/projection.js +0 -2
- package/dist/clients/inbox/controller.js +22 -3
- package/dist/clients/inbox/review/companion-pane.js +0 -4
- package/dist/clients/inbox/review-adapter.js +0 -7
- package/dist/clients/inbox/tui/slots.d.ts +3 -3
- package/dist/clients/inbox/tui/types.d.ts +2 -2
- package/dist/commands/api-client.js +0 -8
- package/dist/commands/attention.js +0 -8
- package/dist/commands/canvas-browse.js +2 -1
- package/dist/commands/canvas-config.js +0 -10
- package/dist/commands/canvas-history.js +2 -1
- package/dist/commands/cron.js +5 -18
- package/dist/commands/dashboard.js +0 -2
- package/dist/commands/human/feedback.js +2 -1
- package/dist/commands/human/prompts.js +2 -5
- package/dist/commands/human/queue.js +2 -7
- package/dist/commands/human/request.js +0 -14
- package/dist/commands/human/review.js +2 -1
- package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +4 -4
- package/dist/commands/memory/find.js +2 -2
- package/dist/commands/memory/lint.js +2 -1
- package/dist/commands/memory/read.d.ts +2 -7
- package/dist/commands/memory/read.js +5 -16
- package/dist/commands/memory/shared.js +4 -7
- package/dist/commands/memory/write.js +4 -3
- package/dist/commands/node/bash.js +2 -1
- package/dist/commands/node/create.js +2 -1
- package/dist/commands/node/inspect.js +0 -6
- package/dist/commands/node/lifecycle.js +4 -13
- package/dist/commands/node/message.js +3 -2
- package/dist/commands/node/subscription.js +2 -1
- package/dist/commands/node/wait.js +4 -3
- package/dist/commands/node-context.js +2 -1
- package/dist/commands/node-lifecycle-revive.js +0 -2
- package/dist/commands/node-worktree.js +2 -1
- package/dist/commands/pkg/browse/actions.d.ts +1 -1
- package/dist/commands/pkg/browse/actions.js +4 -4
- package/dist/commands/pkg/browse/catalog.d.ts +1 -1
- package/dist/commands/pkg/browse/catalog.js +15 -15
- package/dist/commands/pkg/browse/command-view.d.ts +1 -1
- package/dist/commands/pkg/browse/command-view.js +3 -3
- package/dist/commands/pkg/browse/detail-panel.d.ts +1 -1
- package/dist/commands/pkg/browse/detail-panel.js +8 -8
- package/dist/commands/pkg/browse/doc-view.d.ts +1 -1
- package/dist/commands/pkg/browse/doc-view.js +3 -3
- package/dist/commands/pkg/browse/list-panel.d.ts +1 -1
- package/dist/commands/pkg/browse/list-panel.js +3 -3
- package/dist/commands/pkg/browse/model.d.ts +3 -3
- package/dist/commands/pkg/browse/shell.d.ts +2 -2
- package/dist/commands/pkg/browse/shell.js +13 -13
- package/dist/commands/pkg/plugin-manage.js +2 -1
- package/dist/commands/pkg/shared.js +0 -2
- package/dist/commands/profile/delete.js +2 -1
- package/dist/commands/push.js +2 -3
- package/dist/commands/revive.js +0 -2
- package/dist/commands/surface/node/placement.js +2 -1
- package/dist/commands/surface-edit.js +2 -1
- package/dist/commands/sys/config.js +0 -4
- package/dist/commands/sys/daemon.js +0 -10
- package/dist/commands/sys/doctor.js +3 -2
- package/dist/commands/sys/panels/broker-limits-panel.d.ts +2 -2
- package/dist/commands/sys/panels/broker-limits-panel.js +4 -4
- package/dist/commands/sys/panels/dependencies-panel.d.ts +2 -2
- package/dist/commands/sys/panels/dependencies-panel.js +2 -2
- package/dist/commands/sys/panels/keybindings-panel.d.ts +1 -1
- package/dist/commands/sys/panels/keybindings-panel.js +5 -5
- package/dist/commands/sys/panels/models-panel.d.ts +4 -4
- package/dist/commands/sys/panels/models-panel.js +11 -10
- package/dist/commands/sys/panels/plugins-panel.d.ts +2 -2
- package/dist/commands/sys/panels/plugins-panel.js +2 -2
- package/dist/commands/sys/panels/prefs-panel.d.ts +2 -2
- package/dist/commands/sys/panels/prefs-panel.js +4 -4
- package/dist/commands/sys/panels/profiles-panel.d.ts +1 -1
- package/dist/commands/sys/panels/profiles-panel.js +14 -13
- package/dist/commands/sys/panels/provider-panel.d.ts +3 -3
- package/dist/commands/sys/panels/provider-panel.js +8 -8
- package/dist/commands/sys/settings-shell.d.ts +3 -3
- package/dist/commands/sys/settings-shell.js +15 -15
- package/dist/commands/sys/setup-settings-runner.d.ts +3 -3
- package/dist/commands/sys/setup-settings-runner.js +5 -5
- package/dist/commands/sys/setup-wizard.d.ts +4 -4
- package/dist/commands/sys/setup-wizard.js +8 -8
- package/dist/commands/sys/support/prepare.js +4 -4
- package/dist/commands/sys/support/submit.js +2 -2
- package/dist/commands/sys/sync-deps.js +0 -2
- package/dist/commands/sys/sync-project-guidance.js +2 -1
- package/dist/commands/sys/sysprompt.js +2 -1
- package/dist/core/__tests__/boot.test.js +0 -8
- package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +23 -1
- package/dist/core/__tests__/canvas-db-boundary.test.d.ts +1 -0
- package/dist/core/__tests__/canvas-db-boundary.test.js +46 -0
- package/dist/core/__tests__/canvas.test.js +1 -1
- package/dist/core/__tests__/child-death-wake.test.js +0 -2
- package/dist/core/__tests__/cron-armed-context-failure.test.d.ts +1 -0
- package/dist/core/__tests__/cron-armed-context-failure.test.js +145 -0
- package/dist/core/__tests__/daemon-wedge.test.js +0 -4
- package/dist/core/__tests__/dead-node-policy-table.test.js +0 -4
- package/dist/core/__tests__/fixtures/fake-engine.js +4 -14
- package/dist/core/__tests__/fixtures/fake-pi-host.js +5 -5
- package/dist/core/__tests__/focuses.test.js +0 -6
- package/dist/core/__tests__/fs-utils.test.d.ts +1 -0
- package/dist/core/__tests__/fs-utils.test.js +50 -0
- package/dist/core/__tests__/helpers/harness.js +1 -1
- package/dist/core/__tests__/inline-memory-refs.test.js +0 -2
- package/dist/core/__tests__/integration/broker-fork-seam.test.js +0 -2
- package/dist/core/__tests__/integration/broker-sdk-wiring.test.js +3 -16
- package/dist/core/__tests__/integration/command-plugins.test.js +0 -24
- package/dist/core/__tests__/integration/deferred-no-wake.test.js +0 -6
- package/dist/core/__tests__/integration/flagship-lifecycle.test.js +0 -26
- package/dist/core/__tests__/integration/live-mutation-verbs.test.js +0 -4
- package/dist/core/__tests__/integration/live-mutation.test.js +1 -5
- package/dist/core/__tests__/integration/refresh-stall-recycle.test.js +1 -5
- package/dist/core/__tests__/integration/revive.test.js +0 -12
- package/dist/core/__tests__/integration/subscription-delivery.test.js +0 -6
- package/dist/core/__tests__/integration/tmux-surface.test.js +24 -8
- package/dist/core/__tests__/integration/worktree-reap.test.js +0 -6
- package/dist/core/__tests__/lifecycle.test.js +0 -18
- package/dist/core/__tests__/memory-resolver-precedence.test.js +1 -1
- package/dist/core/__tests__/migration.test.js +2 -2
- package/dist/core/__tests__/on-read-dedup-resume.test.js +3 -3
- package/dist/core/__tests__/pid-identity-match.test.js +1 -1
- package/dist/core/__tests__/plugin-kinds.test.js +1 -1
- package/dist/core/__tests__/plugin-page-components.test.js +1 -1
- package/dist/core/__tests__/preview-registry-sync.test.js +42 -1
- package/dist/core/__tests__/respawn-throttle.test.js +0 -4
- package/dist/core/__tests__/revive-all.test.js +5 -5
- package/dist/core/__tests__/revive-parked-fresh.test.js +62 -11
- package/dist/core/__tests__/seam/broker-attach-multiclient.test.js +0 -8
- package/dist/core/__tests__/seam/broker-attach-stream.test.js +0 -8
- package/dist/core/__tests__/seam/broker-crash-teardown.test.js +0 -2
- package/dist/core/__tests__/tmux-driver-boundary.test.d.ts +1 -0
- package/dist/core/__tests__/tmux-driver-boundary.test.js +50 -0
- package/dist/core/activity-signal.d.ts +7 -0
- package/dist/core/activity-signal.js +38 -0
- package/dist/core/auto-update.js +2 -1
- package/dist/core/bootstrap.js +2 -1
- package/dist/core/canvas/__tests__/remote-canvas-source.test.js +1 -1
- package/dist/core/canvas/__tests__/remote-transport.test.js +1 -1
- package/dist/core/canvas/__tests__/render-remote.test.js +1 -1
- package/dist/core/canvas/browse/app.js +3 -2
- package/dist/core/canvas/browse/model.d.ts +1 -1
- package/dist/core/canvas/browse/model.js +0 -4
- package/dist/core/canvas/canvas.d.ts +22 -0
- package/dist/core/canvas/canvas.js +50 -18
- package/dist/core/canvas/crons.js +0 -6
- package/dist/core/canvas/db.d.ts +14 -20
- package/dist/core/canvas/db.js +30 -1332
- package/dist/core/canvas/focuses.js +0 -4
- package/dist/core/canvas/history.js +2 -1
- package/dist/core/canvas/migrations.d.ts +20 -0
- package/dist/core/canvas/migrations.js +1339 -0
- package/dist/core/canvas/nav-model.js +1 -11
- package/dist/core/canvas/nav-render.js +0 -8
- package/dist/core/canvas/remote-canvas-source.js +0 -2
- package/dist/core/canvas/render-source.js +31 -13
- package/dist/core/command-manifests/manifest.js +0 -10
- package/dist/core/command-manifests/schema.js +0 -4
- package/dist/core/command-plugins/transport/http-invoke.js +0 -14
- package/dist/core/command.js +0 -4
- package/dist/core/config.js +2 -1
- package/dist/core/feed/inbox.d.ts +10 -0
- package/dist/core/feed/inbox.js +18 -12
- package/dist/core/fs-utils.d.ts +9 -2
- package/dist/core/fs-utils.js +7 -15
- package/dist/core/help.js +0 -8
- package/dist/core/host-exports/export.d.ts +2 -2
- package/dist/core/host-exports/export.js +9 -12
- package/dist/core/human/answer.d.ts +2 -2
- package/dist/core/human/convention.d.ts +2 -5
- package/dist/core/human/convention.js +3 -13
- package/dist/core/human/page-schema.d.ts +2 -2
- package/dist/core/human/page-schema.js +2 -2
- package/dist/core/human/root.js +6 -23
- package/dist/core/human/scan.js +24 -7
- package/dist/core/human/tickets.d.ts +4 -1
- package/dist/core/human/tickets.js +20 -6
- package/dist/core/io.js +0 -12
- package/dist/core/memory/identity.js +0 -4
- package/dist/core/memory/inline-ref-inventory.js +3 -2
- package/dist/core/memory/lint.js +3 -6
- package/dist/core/memory-resolver.d.ts +5 -0
- package/dist/core/memory-resolver.js +14 -12
- package/dist/core/pagination.js +0 -2
- package/dist/core/preview-registry.d.ts +14 -0
- package/dist/core/preview-registry.js +2 -4
- package/dist/core/preview-result-path.js +2 -1
- package/dist/core/profiles/manifest.d.ts +37 -5
- package/dist/core/profiles/manifest.js +44 -24
- package/dist/core/profiles/select.js +0 -4
- package/dist/core/review/signal.js +4 -23
- package/dist/core/review/ticket-filter.d.ts +3 -3
- package/dist/core/review/ticket-filter.js +4 -9
- package/dist/core/runtime/__tests__/engine-route.test.js +1 -1
- package/dist/core/runtime/__tests__/spawn-env.test.js +0 -8
- package/dist/core/runtime/bearings-render.d.ts +56 -0
- package/dist/core/runtime/bearings-render.js +241 -0
- package/dist/core/runtime/bearings.d.ts +2 -17
- package/dist/core/runtime/bearings.js +12 -198
- package/dist/core/runtime/broker/auth-reload.d.ts +39 -0
- package/dist/core/runtime/broker/auth-reload.js +149 -0
- package/dist/core/runtime/broker/engine-drive.d.ts +26 -0
- package/dist/core/runtime/broker/engine-drive.js +257 -0
- package/dist/core/runtime/broker/engine-routing.d.ts +143 -0
- package/dist/core/runtime/broker/engine-routing.js +211 -0
- package/dist/core/runtime/broker/event-projection.js +3 -2
- package/dist/core/runtime/broker/fault-retry.js +5 -4
- package/dist/core/runtime/broker/frame-client.d.ts +38 -0
- package/dist/core/runtime/broker/frame-client.js +129 -0
- package/dist/core/runtime/broker/frame-dispatch.d.ts +12 -189
- package/dist/core/runtime/broker/frame-dispatch.js +89 -1476
- package/dist/core/runtime/broker/frame-engine-control.d.ts +20 -0
- package/dist/core/runtime/broker/frame-engine-control.js +231 -0
- package/dist/core/runtime/broker/frame-memory-refs.d.ts +19 -0
- package/dist/core/runtime/broker/frame-memory-refs.js +41 -0
- package/dist/core/runtime/broker/frame-model-query.d.ts +13 -0
- package/dist/core/runtime/broker/frame-model-query.js +69 -0
- package/dist/core/runtime/broker/frame-read.d.ts +19 -0
- package/dist/core/runtime/broker/frame-read.js +116 -0
- package/dist/core/runtime/broker/frame-replies.d.ts +24 -0
- package/dist/core/runtime/broker/frame-replies.js +64 -0
- package/dist/core/runtime/broker/frame-session.d.ts +34 -0
- package/dist/core/runtime/broker/frame-session.js +203 -0
- package/dist/core/runtime/broker/turn-ignition.d.ts +42 -0
- package/dist/core/runtime/broker/turn-ignition.js +74 -0
- package/dist/core/runtime/broker-extension-render.js +9 -85
- package/dist/core/runtime/broker-protocol.js +0 -4
- package/dist/core/runtime/broker-sdk.js +2 -1
- package/dist/core/runtime/broker.d.ts +1 -1
- package/dist/core/runtime/broker.js +5 -23
- package/dist/core/runtime/fault.js +3 -2
- package/dist/core/runtime/headless-pi.js +3 -2
- package/dist/core/runtime/host.js +2 -3
- package/dist/core/runtime/kickoff.js +0 -4
- package/dist/core/runtime/launch-target.js +2 -1
- package/dist/core/runtime/launch.js +3 -6
- package/dist/core/runtime/lifecycle.js +17 -26
- package/dist/core/runtime/managed-provider-cooling.d.ts +1 -1
- package/dist/core/runtime/naming.js +0 -2
- package/dist/core/runtime/nodes.js +2 -1
- package/dist/core/runtime/persona.js +0 -6
- package/dist/core/runtime/placement-tmux.js +2 -5
- package/dist/core/runtime/placement.js +4 -11
- package/dist/core/runtime/recap.js +4 -3
- package/dist/core/runtime/reopen.js +4 -7
- package/dist/core/runtime/reset.js +0 -4
- package/dist/core/runtime/resume-root.js +0 -2
- package/dist/core/runtime/revive.js +17 -13
- package/dist/core/runtime/session-list-cache.js +2 -2
- package/dist/core/runtime/shell-expansion.js +0 -2
- package/dist/core/runtime/spawn.js +0 -2
- package/dist/core/runtime/stream-watchdog.d.ts +0 -1
- package/dist/core/runtime/stream-watchdog.js +13 -18
- package/dist/core/runtime/tmux-bindings.js +0 -2
- package/dist/core/runtime/tmux-driver.d.ts +12 -0
- package/dist/core/runtime/tmux-driver.js +18 -13
- package/dist/core/runtime/warm-pool.js +0 -4
- package/dist/core/scope.js +4 -3
- package/dist/core/spawn.js +2 -3
- package/dist/core/subscription-state.js +10 -17
- package/dist/core/substrate/__tests__/surface-match-pre-command.test.js +3 -3
- package/dist/core/substrate/render.js +0 -12
- package/dist/core/substrate/schema.js +0 -12
- package/dist/core/substrate/surface-match.js +0 -2
- package/dist/core/termrender/display.js +2 -1
- package/dist/core/tui/page-host.d.ts +3 -3
- package/dist/core/tui/page-host.js +4 -4
- package/dist/core/tui/panel.js +3 -3
- package/dist/core/wake.js +0 -12
- package/dist/core/worktree.js +0 -2
- package/dist/daemon/__tests__/reconciler-signature.test.d.ts +1 -0
- package/dist/daemon/__tests__/reconciler-signature.test.js +36 -0
- package/dist/daemon/api/__tests__/seam/api-server.test.js +2 -16
- package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.js +3 -11
- package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +0 -6
- package/dist/daemon/api/handlers/attach.js +2 -1
- package/dist/daemon/api/handlers/broker-ops.js +3 -6
- package/dist/daemon/api/handlers/canvas.js +12 -18
- package/dist/daemon/api/handlers/feedback-comments.js +0 -8
- package/dist/daemon/api/handlers/health.js +3 -2
- package/dist/daemon/api/handlers/human-requests.js +0 -10
- package/dist/daemon/api/handlers/human.js +1 -5
- package/dist/daemon/api/handlers/inbox.js +0 -18
- package/dist/daemon/api/handlers/memory.js +1 -1
- package/dist/daemon/api/handlers/messages.js +4 -8
- package/dist/daemon/api/handlers/nodes.js +10 -21
- package/dist/daemon/api/handlers/reports.js +1 -1
- package/dist/daemon/api/handlers/reviews.js +1 -6
- package/dist/daemon/api/map.js +0 -6
- package/dist/daemon/api/router.js +0 -4
- package/dist/daemon/api/server.js +2 -5
- package/dist/daemon/boot-migrations.d.ts +14 -0
- package/dist/daemon/boot-migrations.js +31 -0
- package/dist/daemon/cron/armed-context.d.ts +21 -0
- package/dist/daemon/cron/armed-context.js +100 -0
- package/dist/daemon/cron/capture.d.ts +20 -0
- package/dist/daemon/cron/capture.js +45 -0
- package/dist/daemon/cron/disposition.d.ts +19 -0
- package/dist/daemon/cron/disposition.js +52 -0
- package/dist/daemon/cron/escalation.d.ts +12 -0
- package/dist/daemon/cron/escalation.js +124 -0
- package/dist/daemon/cron/held.d.ts +4 -0
- package/dist/daemon/cron/held.js +20 -0
- package/dist/daemon/cron/lease-recovery.d.ts +3 -0
- package/dist/daemon/cron/lease-recovery.js +119 -0
- package/dist/daemon/cron/live-runs.d.ts +11 -0
- package/dist/daemon/cron/live-runs.js +23 -0
- package/dist/daemon/cron/passes.d.ts +11 -0
- package/dist/daemon/cron/passes.js +78 -0
- package/dist/daemon/cron/settle.d.ts +28 -0
- package/dist/daemon/cron/settle.js +37 -0
- package/dist/daemon/cron/sinks.d.ts +2 -0
- package/dist/daemon/cron/sinks.js +100 -0
- package/dist/daemon/cron-run.d.ts +5 -41
- package/dist/daemon/cron-run.js +193 -882
- package/dist/daemon/crtrd-cli.js +2 -1
- package/dist/daemon/crtrd.js +22 -22
- package/dist/daemon/fleet.js +0 -4
- package/dist/daemon/human/deliver-action.js +2 -1
- package/dist/daemon/human/sweep.js +15 -4
- package/dist/daemon/manage.d.ts +2 -2
- package/dist/daemon/manage.js +4 -13
- package/dist/daemon/pidfile.js +2 -2
- package/dist/daemon/reconcilers/broker-supervision.js +26 -29
- package/dist/daemon/reconcilers/dormant-inbox.d.ts +1 -1
- package/dist/daemon/reconcilers/dormant-inbox.js +2 -1
- package/dist/daemon/reconcilers/live-obligation.js +2 -2
- package/dist/daemon/reconcilers/pending-review-submit.d.ts +1 -1
- package/dist/daemon/reconcilers/pending-review-submit.js +2 -1
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +2 -1
- package/dist/daemon/reconcilers/storage-maintenance.js +2 -1
- package/dist/daemon/review/companion.js +2 -2
- package/dist/daemon/review/sweep.js +8 -3
- package/dist/migrations/001-surfaces-frontmatter.js +0 -6
- package/dist/migrations/corpus.js +2 -5
- package/dist/migrations/registry.js +15 -2
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +0 -4
- package/dist/pi-extensions/broker-local.js +2 -1
- package/dist/pi-extensions/canvas-bash-valve.js +3 -17
- package/dist/pi-extensions/canvas-context-intro.js +2 -7
- package/dist/pi-extensions/canvas-doc-substrate.js +2 -3
- package/dist/pi-extensions/canvas-goal-capture.js +2 -1
- package/dist/pi-extensions/canvas-inbox-watcher.js +5 -12
- package/dist/pi-extensions/canvas-passive-context.js +2 -5
- package/dist/pi-extensions/canvas-preview-result.js +2 -1
- package/dist/pi-extensions/canvas-prompt-scrub.js +2 -1
- package/dist/pi-extensions/canvas-recap.js +3 -16
- package/dist/pi-extensions/canvas-review-boundary.js +2 -5
- package/dist/pi-extensions/canvas-stophook.js +2 -26
- package/dist/pi-extensions/canvas-structured-output.js +2 -1
- package/dist/pi-extensions/canvas-tool-guide.js +2 -1
- package/dist/shared/__tests__/env-boundary.test.d.ts +1 -0
- package/dist/shared/__tests__/env-boundary.test.js +93 -0
- package/dist/shared/env.d.ts +68 -0
- package/dist/shared/env.js +171 -0
- package/package.json +3 -1
- package/runtime.lock.json +2 -2
- package/dist/core/canvas/render.d.ts +0 -47
- package/dist/core/canvas/render.js +0 -245
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// `FoldState`) so this layer owns no singletons and each consumer keeps its own
|
|
12
12
|
// state.
|
|
13
13
|
import { getNode, subscribersOf, subscriptionsOf } from './index.js';
|
|
14
|
-
import { activeFaultForDisplay } from './render.js';
|
|
14
|
+
import { activeFaultForDisplay } from './render-source.js';
|
|
15
15
|
import { readFault } from '../runtime/fault.js';
|
|
16
16
|
import { faultSummary } from './status-glyph.js';
|
|
17
17
|
import { statusRank } from './node-order.js';
|
|
@@ -19,7 +19,6 @@ import { nodeGlyph, navLabel, shortId, tokensCell, activityCell, cycleBadge, ask
|
|
|
19
19
|
// Re-export the pure render/telemetry half so existing nav-model importers
|
|
20
20
|
// (chrome/canvas-panels, overlays/graph, resume) keep resolving these here.
|
|
21
21
|
export { PI_MAX_WIDGET_LINES, VIEWPORT_FALLBACK_ROWS, ESC, RESET, BOLD, DIM, REVERSE, BG_ATTACHED, GREEN, RED, YELLOW, CYAN, GRAY, nodeGlyph, visibleWidth, truncate, fillWidth, fillBar, readTelemetry, fmtTokens, tokensCell, activityCell, cycleBadge, navLabel, shortId, askBadge, liveBelowBadge, isAttached, hasBrokerViewers, fetchAsksMap, graphWidgetBudget, GRAPH_HINT, } from './nav-render.js';
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
22
|
// Read primitives — UNCACHED, deliberately
|
|
24
23
|
//
|
|
25
24
|
// These once memoized into module-global Maps that a `beginFrame()` cleared at
|
|
@@ -36,7 +35,6 @@ export { PI_MAX_WIDGET_LINES, VIEWPORT_FALLBACK_ROWS, ESC, RESET, BOLD, DIM, REV
|
|
|
36
35
|
// goes straight to the canvas db. The only frame cache still in play is
|
|
37
36
|
// nav-render's telemetry memo, whose TUI callers clear it themselves via
|
|
38
37
|
// `beginFrameTelem()`.
|
|
39
|
-
// ---------------------------------------------------------------------------
|
|
40
38
|
/** subscriptionsOf (a node's reports); an unreadable row reads as no edges. */
|
|
41
39
|
function subsOf(id) {
|
|
42
40
|
try {
|
|
@@ -55,7 +53,6 @@ function mgrsOf(id) {
|
|
|
55
53
|
return [];
|
|
56
54
|
}
|
|
57
55
|
}
|
|
58
|
-
// ---------------------------------------------------------------------------
|
|
59
56
|
// Attachment — is a human currently WATCHING a node? A separate axis from
|
|
60
57
|
// running (status 'active' = the engine is live on its detached broker, watched
|
|
61
58
|
// or not). Two signals:
|
|
@@ -65,10 +62,7 @@ function mgrsOf(id) {
|
|
|
65
62
|
// web tabs) to job/attach.json on every viewer change
|
|
66
63
|
// (src/core/runtime/broker.ts). Trusted only while the node is
|
|
67
64
|
// 'active': a broker crash can leave a stale file.
|
|
68
|
-
// ---------------------------------------------------------------------------
|
|
69
|
-
// ---------------------------------------------------------------------------
|
|
70
65
|
// Graph queries (dependency-free, straight off the canvas db)
|
|
71
|
-
// ---------------------------------------------------------------------------
|
|
72
66
|
/** First manager (by created) — the UP step for the ancestry spine. */
|
|
73
67
|
export function managerOf(id) {
|
|
74
68
|
return mgrsOf(id)[0]?.node_id;
|
|
@@ -130,9 +124,7 @@ export function subtreeIds(root) {
|
|
|
130
124
|
}
|
|
131
125
|
return out;
|
|
132
126
|
}
|
|
133
|
-
// ---------------------------------------------------------------------------
|
|
134
127
|
// Shared cell builders
|
|
135
|
-
// ---------------------------------------------------------------------------
|
|
136
128
|
/** ⤳M direct-children badge — the single child-count signal, shown on any row
|
|
137
129
|
* with navigable children (folded or not). In GRAPH the ▸ caret separately marks
|
|
138
130
|
* a collapsed row, so this stays a pure count and never doubles as a fold badge. */
|
|
@@ -148,11 +140,9 @@ export function childBadge(node) {
|
|
|
148
140
|
export function sortedChildIds(id) {
|
|
149
141
|
return convoChildIds(id).sort((a, b) => statusRank(getNode(a)?.status) - statusRank(getNode(b)?.status));
|
|
150
142
|
}
|
|
151
|
-
// ---------------------------------------------------------------------------
|
|
152
143
|
// GRAPH model — flatten the local graph fold-aware. Rebuilt every render (cheap
|
|
153
144
|
// sqlite reads) so a finished child / new spawn shows live; the manual fold
|
|
154
145
|
// overrides and the cursor id are the only persisted state.
|
|
155
|
-
// ---------------------------------------------------------------------------
|
|
156
146
|
export function computeSubtreeActivity(root, self) {
|
|
157
147
|
const expand = new Set();
|
|
158
148
|
const activeBelow = new Map();
|
|
@@ -15,22 +15,18 @@ import { isBusy } from '../runtime/busy.js';
|
|
|
15
15
|
import { readFault } from '../runtime/fault.js';
|
|
16
16
|
import { activeFaultForDisplay } from './render-source.js';
|
|
17
17
|
import { resolveNodeVisual } from './status-glyph.js';
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
18
|
// Tuning constants
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
19
|
/** pi's InteractiveMode.MAX_WIDGET_LINES — the hard cap on lines in a string
|
|
22
20
|
* array widget; anything beyond it pi truncates with its own "... (widget
|
|
23
21
|
* truncated)". Our GRAPH viewport stays at/under this and scrolls internally. */
|
|
24
22
|
export const PI_MAX_WIDGET_LINES = 10;
|
|
25
23
|
export const VIEWPORT_FALLBACK_ROWS = 30;
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
24
|
// ANSI styling. pi renders embedded escapes in widget lines and measures width
|
|
28
25
|
// ANSI-aware, so raw escapes are safe and need no pi-tui dependency. The cursor
|
|
29
26
|
// (selected row) uses a theme-agnostic ATTRIBUTE (reverse), so it reads under
|
|
30
27
|
// NO_COLOR; the attached-row tint is a background COLOUR, while the overlay-
|
|
31
28
|
// aware glyph (●/○/✓/✗/⟳/⚠) carries the live signal independently, even where
|
|
32
29
|
// colour is stripped.
|
|
33
|
-
// ---------------------------------------------------------------------------
|
|
34
30
|
export const ESC = '\x1b[';
|
|
35
31
|
export const RESET = `${ESC}0m`;
|
|
36
32
|
export const BOLD = `${ESC}1m`;
|
|
@@ -129,14 +125,12 @@ export function fillBar(content, width, open) {
|
|
|
129
125
|
const pad = Math.max(0, width - visibleWidth(clipped));
|
|
130
126
|
return `${open}${reasserted}${' '.repeat(pad)}${RESET}`;
|
|
131
127
|
}
|
|
132
|
-
// ---------------------------------------------------------------------------
|
|
133
128
|
// Per-frame telemetry cache. Its callers are TUI render passes ONLY (the GRAPH
|
|
134
129
|
// overlay and the canvas panels), each of which calls beginFrameTelem() at the
|
|
135
130
|
// top of the pass, so token/activity cells read fresh once per frame instead of
|
|
136
131
|
// once per row and a stale entry can at worst be one frame old. Never memoize a
|
|
137
132
|
// canvas read for a caller that is not a render pass: crtrd lives for hours, and
|
|
138
133
|
// a memo it never clears is permanent, not per-frame.
|
|
139
|
-
// ---------------------------------------------------------------------------
|
|
140
134
|
const frameTelem = new Map();
|
|
141
135
|
/** Clear the per-frame telemetry cache. Every render pass calls this first, so
|
|
142
136
|
* one keystroke re-reads each node's telemetry exactly once. */
|
|
@@ -246,12 +240,10 @@ export function liveBelowBadge(node, activeBelow) {
|
|
|
246
240
|
const n = activeBelow.get(node.node_id) ?? 0;
|
|
247
241
|
return n > 0 ? ` ${GREEN}⇣${n}${RESET}` : '';
|
|
248
242
|
}
|
|
249
|
-
// ---------------------------------------------------------------------------
|
|
250
243
|
// Per-node ask counts — ONE shell-out per poll. `crtr canvas attention map`
|
|
251
244
|
// buckets a whole sub-DAG's pending asks by node in a single process, so the
|
|
252
245
|
// timer stays cheap (< 2 s) regardless of how many nodes are visible. --json
|
|
253
246
|
// gives a parseable {counts} blob (the default render is XML chrome).
|
|
254
|
-
// ---------------------------------------------------------------------------
|
|
255
247
|
export function fetchAsksMap(rootId) {
|
|
256
248
|
try {
|
|
257
249
|
const raw = execFileSync('crtr', ['canvas', 'attention', 'map', '--view', rootId, '--json'], {
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
// "every process is a /v1 client" architecture (which governs LOCAL access).
|
|
13
13
|
import { createRemoteExec } from './remote-transport.js';
|
|
14
14
|
const CACHE_TTL_MS = 1000;
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
15
|
// Remote JSON shape validation.
|
|
17
16
|
//
|
|
18
17
|
// `execJson<T>` parses stdout and casts it to T with NO structural check — a
|
|
@@ -21,7 +20,6 @@ const CACHE_TTL_MS = 1000;
|
|
|
21
20
|
// `ticketCountsForView` validate before caching/returning; on a shape mismatch
|
|
22
21
|
// they degrade exactly like the existing network-failure path (null/[]/{}),
|
|
23
22
|
// never a malformed object a caller might dereference.
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
23
|
function isPlainObject(x) {
|
|
26
24
|
return typeof x === 'object' && x !== null && !Array.isArray(x);
|
|
27
25
|
}
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
// Every `*FromSource` variant + the pure/disk helpers they share live here so a
|
|
4
4
|
// CLI process rendering the canvas through a `CanvasSource` (the API-backed
|
|
5
5
|
// `ApiCanvasSource`, or a `RemoteCanvasSource`) NEVER drags in `core/canvas/db.ts`
|
|
6
|
-
// (`openDb`) or the `core/canvas/canvas.ts` accessors.
|
|
7
|
-
// renderers (`renderTree`/`dashboardRows`/…)
|
|
8
|
-
//
|
|
9
|
-
//
|
|
6
|
+
// (`openDb`) or the `core/canvas/canvas.ts` accessors. This is the whole module now
|
|
7
|
+
// — the sync, db-backed renderers (`renderTree`/`dashboardRows`/…) that used to live
|
|
8
|
+
// in a separate `render.ts` re-export shim have been retired; their few real callers
|
|
9
|
+
// migrated onto these `*FromSource` variants directly.
|
|
10
10
|
//
|
|
11
11
|
// ALLOWED imports (verified openDb-free): node:fs/path, ./pid.js, ./labels.js,
|
|
12
12
|
// ./status-glyph.js, ../runtime/fault.js, ./paths.js, ./remote-canvas-source.js,
|
|
@@ -21,10 +21,8 @@ import { isPidAlive } from './pid.js';
|
|
|
21
21
|
import { resolveNodeVisual, faultSummary } from './status-glyph.js';
|
|
22
22
|
import { readFault } from '../runtime/fault.js';
|
|
23
23
|
import { parseCard } from '../../shared/generated-context.js';
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
24
|
// Active-fault overlay: stale daemon-owned provider faults are hidden once the
|
|
26
25
|
// broker pid is gone; manual/client faults stay visible until cleared.
|
|
27
|
-
// ---------------------------------------------------------------------------
|
|
28
26
|
export function activeFaultForDisplay(node, fault) {
|
|
29
27
|
if (fault === null)
|
|
30
28
|
return null;
|
|
@@ -52,7 +50,6 @@ export function fmtCtx(tokensIn) {
|
|
|
52
50
|
return '0k';
|
|
53
51
|
return `${Math.floor(tokensIn / 1000)}k`;
|
|
54
52
|
}
|
|
55
|
-
// ---------------------------------------------------------------------------
|
|
56
53
|
// Source-driven tree builder (openDb-free)
|
|
57
54
|
//
|
|
58
55
|
// Ticket counts are threaded in as a `Record<node_id, count>` fetched ONCE per
|
|
@@ -61,7 +58,6 @@ export function fmtCtx(tokensIn) {
|
|
|
61
58
|
// LOCAL disk reads (telemetry.json / fault.json), valid for a same-host source
|
|
62
59
|
// but meaningless for a truly remote canvas, so both are suppressed when the
|
|
63
60
|
// source is a `RemoteCanvasSource`.
|
|
64
|
-
// ---------------------------------------------------------------------------
|
|
65
61
|
async function nodeLineFromSource(source, nodeId, indent, connector, remote, tickets) {
|
|
66
62
|
const node = await source.getNode(nodeId);
|
|
67
63
|
if (node === null)
|
|
@@ -80,8 +76,15 @@ async function walkTreeFromSource(source, nodeId, indent, isLast, visited, out,
|
|
|
80
76
|
visited.add(nodeId);
|
|
81
77
|
const connector = isLast ? '└─ ' : '├─ ';
|
|
82
78
|
out.push(await nodeLineFromSource(source, nodeId, indent, connector, remote, tickets));
|
|
83
|
-
const children = await source.subscriptionsOf(nodeId).catch(() => []);
|
|
84
79
|
const childIndent = indent + (isLast ? ' ' : '│ ');
|
|
80
|
+
let children;
|
|
81
|
+
try {
|
|
82
|
+
children = await source.subscriptionsOf(nodeId);
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
out.push(`${childIndent}⚠ children unavailable: ${err instanceof Error ? err.message : String(err)}`);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
85
88
|
for (let i = 0; i < children.length; i++) {
|
|
86
89
|
const child = children[i];
|
|
87
90
|
const childIsLast = i === children.length - 1;
|
|
@@ -98,7 +101,15 @@ export async function renderTreeFromSource(source, rootId) {
|
|
|
98
101
|
const node = await source.getNode(rootId);
|
|
99
102
|
if (node === null)
|
|
100
103
|
return `? <missing node: ${rootId}>`;
|
|
101
|
-
|
|
104
|
+
let tickets;
|
|
105
|
+
let ticketsUnavailable = null;
|
|
106
|
+
try {
|
|
107
|
+
tickets = await source.ticketCountsForView(rootId);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
tickets = {};
|
|
111
|
+
ticketsUnavailable = err instanceof Error ? err.message : String(err);
|
|
112
|
+
}
|
|
102
113
|
const ctx = remote ? '0k' : fmtCtx(readNodeTelemetry(rootId).tokens_in);
|
|
103
114
|
const asks = tickets[rootId] ?? 0;
|
|
104
115
|
const askSuffix = asks > 0 ? ` ⚑${asks}` : '';
|
|
@@ -108,12 +119,21 @@ export async function renderTreeFromSource(source, rootId) {
|
|
|
108
119
|
const out = [];
|
|
109
120
|
out.push(`${glyph} ${fullName(node)} [${node.kind}/${node.mode}] ctx ${ctx}${askSuffix}${faultSuffix}`);
|
|
110
121
|
const visited = new Set([rootId]);
|
|
111
|
-
|
|
122
|
+
let children;
|
|
123
|
+
try {
|
|
124
|
+
children = await source.subscriptionsOf(rootId);
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
out.push(`⚠ children unavailable: ${err instanceof Error ? err.message : String(err)}`);
|
|
128
|
+
children = [];
|
|
129
|
+
}
|
|
112
130
|
for (let i = 0; i < children.length; i++) {
|
|
113
131
|
const child = children[i];
|
|
114
132
|
const isLast = i === children.length - 1;
|
|
115
133
|
await walkTreeFromSource(source, child.node_id, '', isLast, visited, out, remote, tickets);
|
|
116
134
|
}
|
|
135
|
+
if (ticketsUnavailable !== null)
|
|
136
|
+
out.push(`Tickets: unavailable (${ticketsUnavailable}).`);
|
|
117
137
|
return out.join('\n');
|
|
118
138
|
}
|
|
119
139
|
export async function renderForestFromSource(source) {
|
|
@@ -424,13 +444,11 @@ export async function dashboardRowsAllFromSource(source, localFocusedNodeIds = n
|
|
|
424
444
|
const focusedNodeIds = remote ? new Set() : localFocusedNodeIds;
|
|
425
445
|
return (await source.listNodes()).map((row) => dashboardRowFromNodeRow(row, focusedNodeIds, remote));
|
|
426
446
|
}
|
|
427
|
-
// ---------------------------------------------------------------------------
|
|
428
447
|
// Lazy enrichment (source-driven) — fold expensive per-node reads into rows on
|
|
429
448
|
// demand. Ask counts are supplied by the caller (`asks` — a pre-fetched
|
|
430
449
|
// `ticketCountsForView` map merged across the visible roots), NOT scanned here
|
|
431
450
|
// (`ticketCountsForNodes` reaches openDb). Telemetry (ctx tokens) + goal/session
|
|
432
451
|
// are LOCAL disk reads, suppressed for a `RemoteCanvasSource`.
|
|
433
|
-
// ---------------------------------------------------------------------------
|
|
434
452
|
export async function enrichRowsFromSource(source, rows, asks) {
|
|
435
453
|
const todo = rows.filter((r) => r.enriched !== true);
|
|
436
454
|
if (todo.length === 0)
|
|
@@ -9,9 +9,7 @@
|
|
|
9
9
|
// the raw manifest bytes passed in.
|
|
10
10
|
import { validateCommandNode } from './schema.js';
|
|
11
11
|
import { isRecord } from '../../shared/predicates.js';
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
12
|
// Validation helpers
|
|
14
|
-
// ---------------------------------------------------------------------------
|
|
15
13
|
const KEBAB = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
16
14
|
const REST_METHODS = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
|
|
17
15
|
function typeName(v) {
|
|
@@ -21,9 +19,7 @@ function typeName(v) {
|
|
|
21
19
|
return 'array';
|
|
22
20
|
return typeof v;
|
|
23
21
|
}
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
22
|
// Top-level manifest validation
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
23
|
/**
|
|
28
24
|
* Validates a HTTP-transport plugin manifest exactly per §4, performing strict atomic
|
|
29
25
|
* validation and order-independent forest materialization. Returns either a
|
|
@@ -130,9 +126,7 @@ export function validateCommandManifest(raw, options) {
|
|
|
130
126
|
// Any issue found -> zero contributions
|
|
131
127
|
return { issues };
|
|
132
128
|
}
|
|
133
|
-
// ---------------------------------------------------------------------------
|
|
134
129
|
// Timeouts validation
|
|
135
|
-
// ---------------------------------------------------------------------------
|
|
136
130
|
function validateTimeouts(raw, issue) {
|
|
137
131
|
if (!isRecord(raw)) {
|
|
138
132
|
issue('command_manifest_invalid', 'timeouts must be an object', typeName(raw), '{ connectMs?, requestMs?, streamIdleMs? }', 'Fix timeouts.', 'timeouts');
|
|
@@ -156,9 +150,7 @@ function validateTimeouts(raw, issue) {
|
|
|
156
150
|
}
|
|
157
151
|
return out;
|
|
158
152
|
}
|
|
159
|
-
// ---------------------------------------------------------------------------
|
|
160
153
|
// Help addenda validation
|
|
161
|
-
// ---------------------------------------------------------------------------
|
|
162
154
|
/** Validate the optional top-level `helpAddenda` map: core command path →
|
|
163
155
|
* addendum text rendered as an attributed block beneath that core command's
|
|
164
156
|
* help. When the caller supplies the core command path set, a key naming no
|
|
@@ -228,9 +220,7 @@ function validateMount(raw, index, transport, issue) {
|
|
|
228
220
|
const typedNode = node;
|
|
229
221
|
return { parent, node: typedNode };
|
|
230
222
|
}
|
|
231
|
-
// ---------------------------------------------------------------------------
|
|
232
223
|
// Forest materialization (order-independent)
|
|
233
|
-
// ---------------------------------------------------------------------------
|
|
234
224
|
/**
|
|
235
225
|
* Materializes a flat list of mounts into a forest of top-level branches,
|
|
236
226
|
* resolving nested mounts whose parent exists in a top-level inline tree regardless of order. Nested mounts that provide another nested mount's parent must appear first. Validates self-containment and no duplicates.
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// Unified command-manifest schema. Transport is the sole leaf-dialect discriminator.
|
|
2
2
|
import { isRecord } from '../../shared/predicates.js';
|
|
3
|
-
// ---------------------------------------------------------------------------
|
|
4
3
|
// Validation helpers
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
4
|
const TIERS = new Set(['normal', 'common', 'important']);
|
|
7
5
|
const FLAG_TYPES = new Set(['string', 'int', 'bool', 'path', 'enum']);
|
|
8
6
|
const KEBAB = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
@@ -471,9 +469,7 @@ function validateLeaf(raw, path, transport, issue) {
|
|
|
471
469
|
const rest = validateRestMapping(raw['rest'], path, params, issue);
|
|
472
470
|
return rest === null ? null : { ...base, rest };
|
|
473
471
|
}
|
|
474
|
-
// ---------------------------------------------------------------------------
|
|
475
472
|
// REST mapping validation (§4.4)
|
|
476
|
-
// ---------------------------------------------------------------------------
|
|
477
473
|
const REST_METHODS_SET = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
|
|
478
474
|
// RFC 7230 `token` grammar — the legal charset for an HTTP header field name.
|
|
479
475
|
const HTTP_TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
@@ -20,9 +20,7 @@ import { CrtrError } from '../../errors.js';
|
|
|
20
20
|
import { diag, recordPreviewError, recordPreviewJsonLine, writeStdout } from '../../io.js';
|
|
21
21
|
import { ExitCode } from '../../../types.js';
|
|
22
22
|
import { isRecord } from '../../../shared/predicates.js';
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
23
|
// Constants
|
|
25
|
-
// ---------------------------------------------------------------------------
|
|
26
24
|
const DEFAULT_CONNECT_MS = 10_000;
|
|
27
25
|
const DEFAULT_REQUEST_MS = 30_000;
|
|
28
26
|
const DEFAULT_STREAM_IDLE_MS = 60_000;
|
|
@@ -33,9 +31,7 @@ const RESERVED_CODES = new Set(['internal', 'unknown_path', 'command_collision',
|
|
|
33
31
|
/** Marker for the idle-timeout abort so the relay loop can distinguish it. */
|
|
34
32
|
class StreamIdleError extends Error {
|
|
35
33
|
}
|
|
36
|
-
// ---------------------------------------------------------------------------
|
|
37
34
|
// Public entry
|
|
38
|
-
// ---------------------------------------------------------------------------
|
|
39
35
|
/**
|
|
40
36
|
* Execute one HTTP-transport plugin leaf. Unary leaves return the validated response
|
|
41
37
|
* object (crtr's ordinary dispatcher renders it, or mirrors it under --json).
|
|
@@ -59,9 +55,7 @@ export async function invokeHttpLeaf(spec, input, context) {
|
|
|
59
55
|
return mapUnary2xx(spec, body);
|
|
60
56
|
throwNon2xx(spec, status, body); // always throws
|
|
61
57
|
}
|
|
62
|
-
// ---------------------------------------------------------------------------
|
|
63
58
|
// Request construction (§6.1) — pure, no network I/O
|
|
64
|
-
// ---------------------------------------------------------------------------
|
|
65
59
|
function buildRequestPlan(spec, input, context) {
|
|
66
60
|
const paramsByName = new Map();
|
|
67
61
|
for (const p of spec.params)
|
|
@@ -245,9 +239,7 @@ function encodePathSegmentValue(value) {
|
|
|
245
239
|
function paramKey(name) {
|
|
246
240
|
return name.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
247
241
|
}
|
|
248
|
-
// ---------------------------------------------------------------------------
|
|
249
242
|
// Unary lifecycle (§6.4) — connect + total clocks, buffered body
|
|
250
|
-
// ---------------------------------------------------------------------------
|
|
251
243
|
function requestUnary(spec, plan) {
|
|
252
244
|
const connectMs = spec.timeouts?.connectMs ?? DEFAULT_CONNECT_MS;
|
|
253
245
|
const requestMs = spec.timeouts?.requestMs ?? DEFAULT_REQUEST_MS;
|
|
@@ -335,9 +327,7 @@ function mapUnary2xx(spec, body) {
|
|
|
335
327
|
}
|
|
336
328
|
return parsed;
|
|
337
329
|
}
|
|
338
|
-
// ---------------------------------------------------------------------------
|
|
339
330
|
// Streaming lifecycle (§6.3) — connect + idle clocks, verbatim frame relay
|
|
340
|
-
// ---------------------------------------------------------------------------
|
|
341
331
|
async function requestStreaming(spec, plan) {
|
|
342
332
|
const connectMs = spec.timeouts?.connectMs ?? DEFAULT_CONNECT_MS;
|
|
343
333
|
const idleMs = spec.timeouts?.streamIdleMs ?? DEFAULT_STREAM_IDLE_MS;
|
|
@@ -461,9 +451,7 @@ async function requestStreaming(spec, plan) {
|
|
|
461
451
|
throw unreachable(spec, plan, detail);
|
|
462
452
|
}
|
|
463
453
|
}
|
|
464
|
-
// ---------------------------------------------------------------------------
|
|
465
454
|
// Error mapping (§6.5)
|
|
466
|
-
// ---------------------------------------------------------------------------
|
|
467
455
|
/** Extract a non-2xx error. A conforming nested `{ error: { code, message,
|
|
468
456
|
* field?, next? } }` with an acceptable snake_case, non-reserved code becomes a
|
|
469
457
|
* CrtrError carrying that code; a reserved/ill-formed code demotes to
|
|
@@ -526,9 +514,7 @@ function unreachable(spec, plan, detail) {
|
|
|
526
514
|
next: `Check connectivity to ${plan.url.host} and retry; run \`crtr pkg plugin update ${spec.registration.name}\` if the command surface changed.`,
|
|
527
515
|
});
|
|
528
516
|
}
|
|
529
|
-
// ---------------------------------------------------------------------------
|
|
530
517
|
// Small helpers
|
|
531
|
-
// ---------------------------------------------------------------------------
|
|
532
518
|
function label(spec) {
|
|
533
519
|
return `HTTP-transport plugin "${spec.registration.name}" command \`${spec.commandPath.join(' ')}\``;
|
|
534
520
|
}
|
package/dist/core/command.js
CHANGED
|
@@ -15,9 +15,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
15
15
|
import { constants as osConstants } from 'node:os';
|
|
16
16
|
import { isatty } from 'node:tty';
|
|
17
17
|
import { resolve } from 'node:path';
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
18
|
// Factory functions
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
19
|
function freezeCommandMetadata(value) {
|
|
22
20
|
if (value === null || typeof value !== 'object' || Object.isFrozen(value))
|
|
23
21
|
return value;
|
|
@@ -301,9 +299,7 @@ export function unknownPathError(node, path, bad) {
|
|
|
301
299
|
next: `Valid children: ${validStr}. Run \`${entryCmd}\` for the full list.`,
|
|
302
300
|
});
|
|
303
301
|
}
|
|
304
|
-
// ---------------------------------------------------------------------------
|
|
305
302
|
// Argv parser
|
|
306
|
-
// ---------------------------------------------------------------------------
|
|
307
303
|
function parseArgvError(code, message, received, field, next) {
|
|
308
304
|
return new CrtrError(code, message, ExitCode.USAGE, {
|
|
309
305
|
received,
|
package/dist/core/config.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { envProfileId } from '../shared/env.js';
|
|
1
2
|
import { dirname, join } from 'node:path';
|
|
2
3
|
import { isDeepStrictEqual } from 'node:util';
|
|
3
4
|
import { CONFIG_FILE, STATE_FILE, CONDENSED_HISTORY_MODES, MOUSE_MODE_DEFAULTS, WHIP_MESSAGE_MODES, DEFAULT_WHIP_MESSAGES, defaultScopeConfig, defaultScopeState, defaultModelLaddersConfig, defaultKindsConfig, defaultRemoteCanvasConfig } from '../types.js';
|
|
@@ -762,7 +763,7 @@ function readRawProjectScopeConfigs(targetCwd, targetProfileId) {
|
|
|
762
763
|
* the target node's) MUST pass the target's own cwd/profile explicitly, or
|
|
763
764
|
* `spawnEnv.allow` resolves from the wrong scope entirely (the C-1
|
|
764
765
|
* follow-up fix this parameterization exists for). */
|
|
765
|
-
export function readMergedLaunchConfig(targetCwd = process.cwd(), targetProfileId =
|
|
766
|
+
export function readMergedLaunchConfig(targetCwd = process.cwd(), targetProfileId = envProfileId() || null) {
|
|
766
767
|
const defaults = defaultScopeConfig();
|
|
767
768
|
const userRaw = readRawScopeConfig('user');
|
|
768
769
|
const profileRaw = readRawProfileConfig(targetProfileId);
|
|
@@ -76,6 +76,16 @@ export declare function cancelPendingEntries(nodeId: string, select: (entry: Inb
|
|
|
76
76
|
export declare function readCursor(nodeId: string): InboxEntryId | undefined;
|
|
77
77
|
/** Persist one validated exact cursor identity (atomic tmp+rename). */
|
|
78
78
|
export declare function writeCursor(nodeId: string, entryId: string): void;
|
|
79
|
+
/** Is there mail this node has not seen that would drive a turn? The one
|
|
80
|
+
* authority for "wake-worthy inbox state", read by the park clock, the
|
|
81
|
+
* settlement policy, the review-companion guard, and reviveNode's parked
|
|
82
|
+
* re-entry rule. Deferred entries are excluded everywhere for the same
|
|
83
|
+
* reason: a deferred entry rides the next natural cycle and never starts one.
|
|
84
|
+
* A cursor that no longer resolves against the physical inbox is a fault, not
|
|
85
|
+
* an answer — every caller's conservative reading of this predicate is `true`
|
|
86
|
+
* (do not park, do not shut down, do not resume quietly), so report it and
|
|
87
|
+
* return that. */
|
|
88
|
+
export declare function hasUnseenWakeMail(nodeId: string): boolean;
|
|
79
89
|
/** Clip a body to a bounded preview, reporting whether anything was dropped. */
|
|
80
90
|
export declare function clipBody(body: string): {
|
|
81
91
|
text: string;
|
package/dist/core/feed/inbox.js
CHANGED
|
@@ -44,15 +44,11 @@ export function finalizeInboxEntry(input) {
|
|
|
44
44
|
ts: new Date().toISOString(),
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
|
-
// ---------------------------------------------------------------------------
|
|
48
47
|
// Cursor sidecar path
|
|
49
|
-
// ---------------------------------------------------------------------------
|
|
50
48
|
function cursorPath(nodeId) {
|
|
51
49
|
return `${inboxPath(nodeId)}.cursor`;
|
|
52
50
|
}
|
|
53
|
-
// ---------------------------------------------------------------------------
|
|
54
51
|
// Append
|
|
55
|
-
// ---------------------------------------------------------------------------
|
|
56
52
|
/** Spill an oversized inline body to a durable file — the SAME atomic
|
|
57
53
|
* tmp+rename pattern a push report uses — and return its absolute path.
|
|
58
54
|
* Called only when the body would clip in the digest; short bodies never
|
|
@@ -151,9 +147,7 @@ export function appendControllerDeathNotice(nodeId, controller) {
|
|
|
151
147
|
throw error;
|
|
152
148
|
}
|
|
153
149
|
}
|
|
154
|
-
// ---------------------------------------------------------------------------
|
|
155
150
|
// Read
|
|
156
|
-
// ---------------------------------------------------------------------------
|
|
157
151
|
function readPhysicalInbox(nodeId) {
|
|
158
152
|
const p = inboxPath(nodeId);
|
|
159
153
|
if (!existsSync(p))
|
|
@@ -212,9 +206,7 @@ export function readInboxRange(nodeId, afterEntryId, throughEntryId) {
|
|
|
212
206
|
throw new Error(`inbox range is reversed: ${after} through ${through}`);
|
|
213
207
|
return entries.slice(afterIndex + 1, throughIndex + 1);
|
|
214
208
|
}
|
|
215
|
-
// ---------------------------------------------------------------------------
|
|
216
209
|
// Cancel set (interrupt-canceled entries)
|
|
217
|
-
// ---------------------------------------------------------------------------
|
|
218
210
|
function canceledPath(nodeId) {
|
|
219
211
|
return `${inboxPath(nodeId)}.canceled`;
|
|
220
212
|
}
|
|
@@ -267,9 +259,7 @@ export function cancelPendingEntries(nodeId, select) {
|
|
|
267
259
|
appendFileSync(canceledPath(nodeId), targets.join('\n') + '\n', { encoding: 'utf8', flag: 'a' });
|
|
268
260
|
return targets;
|
|
269
261
|
}
|
|
270
|
-
// ---------------------------------------------------------------------------
|
|
271
262
|
// Cursor persistence
|
|
272
|
-
// ---------------------------------------------------------------------------
|
|
273
263
|
/** Read and validate the persisted exact cursor identity. */
|
|
274
264
|
export function readCursor(nodeId) {
|
|
275
265
|
const p = cursorPath(nodeId);
|
|
@@ -291,9 +281,25 @@ export function writeCursor(nodeId, entryId) {
|
|
|
291
281
|
writeFileSync(tmp, value, 'utf8');
|
|
292
282
|
renameSync(tmp, p);
|
|
293
283
|
}
|
|
294
|
-
|
|
284
|
+
/** Is there mail this node has not seen that would drive a turn? The one
|
|
285
|
+
* authority for "wake-worthy inbox state", read by the park clock, the
|
|
286
|
+
* settlement policy, the review-companion guard, and reviveNode's parked
|
|
287
|
+
* re-entry rule. Deferred entries are excluded everywhere for the same
|
|
288
|
+
* reason: a deferred entry rides the next natural cycle and never starts one.
|
|
289
|
+
* A cursor that no longer resolves against the physical inbox is a fault, not
|
|
290
|
+
* an answer — every caller's conservative reading of this predicate is `true`
|
|
291
|
+
* (do not park, do not shut down, do not resume quietly), so report it and
|
|
292
|
+
* return that. */
|
|
293
|
+
export function hasUnseenWakeMail(nodeId) {
|
|
294
|
+
try {
|
|
295
|
+
return readInboxSince(nodeId, readCursor(nodeId)).some((entry) => entry.tier !== 'deferred');
|
|
296
|
+
}
|
|
297
|
+
catch (error) {
|
|
298
|
+
emitEvent({ level: 'warn', event: 'inbox.wake_scan.failed', node_id: nodeId, error });
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
295
302
|
// Coalesce
|
|
296
|
-
// ---------------------------------------------------------------------------
|
|
297
303
|
/** Bounds for inlining a message body's preview in the digest. */
|
|
298
304
|
const BODY_MAX_LINES = 12;
|
|
299
305
|
const BODY_MAX_CHARS = 1000;
|
package/dist/core/fs-utils.d.ts
CHANGED
|
@@ -5,8 +5,15 @@ export declare function realpathOrSelf(p: string): string;
|
|
|
5
5
|
export declare function expandTilde(p: string, homeDir?: string): string;
|
|
6
6
|
export declare function ensureDir(dir: string): void;
|
|
7
7
|
export declare function writeJson(path: string, data: unknown): void;
|
|
8
|
-
export
|
|
9
|
-
|
|
8
|
+
export interface AtomicWriteOptions {
|
|
9
|
+
/** Force this mode regardless of any existing file's mode. Omitted: preserve the existing file's mode, or default a new file to `0o600`. */
|
|
10
|
+
mode?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function atomicWriteJson(path: string, data: unknown, opts?: AtomicWriteOptions): void;
|
|
13
|
+
/** Replace one file's contents in a single rename, so a concurrent reader — the
|
|
14
|
+
* tmux inbox watcher, or crtrd serving a ticket read — sees either the old
|
|
15
|
+
* bytes or the new ones and never a truncated file mid-write. */
|
|
16
|
+
export declare function atomicWriteText(path: string, content: string | Uint8Array, opts?: AtomicWriteOptions): void;
|
|
10
17
|
export declare function readJson<T = unknown>(path: string): T;
|
|
11
18
|
export declare function readJsonIfExists<T = unknown>(path: string): T | null;
|
|
12
19
|
/** Missing or corrupt reads as absent, so a crash artifact never throws. */
|
package/dist/core/fs-utils.js
CHANGED
|
@@ -26,24 +26,16 @@ export function writeJson(path, data) {
|
|
|
26
26
|
ensureDir(dirname(path));
|
|
27
27
|
writeFileSync(path, JSON.stringify(data, null, 2) + '\n', 'utf8');
|
|
28
28
|
}
|
|
29
|
-
export function atomicWriteJson(path, data) {
|
|
30
|
-
|
|
31
|
-
const temp = `${path}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`;
|
|
32
|
-
const mode = existsSync(path) ? statSync(path).mode & 0o777 : 0o600;
|
|
33
|
-
try {
|
|
34
|
-
writeFileSync(temp, JSON.stringify(data, null, 2) + '\n', { encoding: 'utf8', mode });
|
|
35
|
-
chmodSync(temp, mode);
|
|
36
|
-
renameSync(temp, path);
|
|
37
|
-
}
|
|
38
|
-
finally {
|
|
39
|
-
if (existsSync(temp))
|
|
40
|
-
rmSync(temp, { force: true });
|
|
41
|
-
}
|
|
29
|
+
export function atomicWriteJson(path, data, opts) {
|
|
30
|
+
atomicWriteText(path, JSON.stringify(data, null, 2) + '\n', opts);
|
|
42
31
|
}
|
|
43
|
-
|
|
32
|
+
/** Replace one file's contents in a single rename, so a concurrent reader — the
|
|
33
|
+
* tmux inbox watcher, or crtrd serving a ticket read — sees either the old
|
|
34
|
+
* bytes or the new ones and never a truncated file mid-write. */
|
|
35
|
+
export function atomicWriteText(path, content, opts) {
|
|
44
36
|
ensureDir(dirname(path));
|
|
45
37
|
const temp = `${path}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`;
|
|
46
|
-
const mode = existsSync(path) ? statSync(path).mode & 0o777 : 0o600;
|
|
38
|
+
const mode = opts?.mode ?? (existsSync(path) ? statSync(path).mode & 0o777 : 0o600);
|
|
47
39
|
try {
|
|
48
40
|
writeFileSync(temp, content, { mode });
|
|
49
41
|
chmodSync(temp, mode);
|
package/dist/core/help.js
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
// Pure functions — no side effects, no commander, no process.exit.
|
|
3
3
|
// Rendering matches reference.md shapes exactly:
|
|
4
4
|
// root L11-32, branch L43-58, leaf L65-189.
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
5
|
// Internal helpers
|
|
7
|
-
// ---------------------------------------------------------------------------
|
|
8
6
|
/** Build a self-named runtime-state element: `<tag attr="v">body</tag>`. The
|
|
9
7
|
* subtree that owns the state authors it through this, so the tag name and any
|
|
10
8
|
* scalar metadata (e.g. a count) travel with the data and render identically
|
|
@@ -42,9 +40,7 @@ function maxLen(names) {
|
|
|
42
40
|
function pad(s, width) {
|
|
43
41
|
return s + ' '.repeat(Math.max(0, width - s.length));
|
|
44
42
|
}
|
|
45
|
-
// ---------------------------------------------------------------------------
|
|
46
43
|
// renderRoot
|
|
47
|
-
// ---------------------------------------------------------------------------
|
|
48
44
|
const IO_CONTRACT = 'I/O contract: flags and positional args on input; stdout is agent-ready markdown/XML you\n' +
|
|
49
45
|
'act on directly — read it as a continuation of your prompt, don\'t parse it as data.\n' +
|
|
50
46
|
'Exit 0 on success, non-zero on failure. Schemas appear at leaf -h; a leaf may route an uncommon flag to focused --flag -h guidance.';
|
|
@@ -132,9 +128,7 @@ export function renderRoot(h) {
|
|
|
132
128
|
lines.push(CAPABILITY_DISCOVERY);
|
|
133
129
|
return lines.join('\n');
|
|
134
130
|
}
|
|
135
|
-
// ---------------------------------------------------------------------------
|
|
136
131
|
// renderBranch
|
|
137
|
-
// ---------------------------------------------------------------------------
|
|
138
132
|
/** Escape a value for a rendered XML attribute. Output is light XML around
|
|
139
133
|
* markdown read as prose by a model, not parsed — so we only guard the
|
|
140
134
|
* double-quote that would visually break the attribute, swapping it for a
|
|
@@ -170,9 +164,7 @@ export function renderBranch(h) {
|
|
|
170
164
|
lines.push('</command>');
|
|
171
165
|
return lines.join('\n');
|
|
172
166
|
}
|
|
173
|
-
// ---------------------------------------------------------------------------
|
|
174
167
|
// renderLeafArgv
|
|
175
|
-
// ---------------------------------------------------------------------------
|
|
176
168
|
/** Build the display label for a param entry (left column). */
|
|
177
169
|
function paramLabel(p) {
|
|
178
170
|
if (p.kind === 'positional')
|
|
@@ -20,8 +20,8 @@ import type { RootDef } from '../command.js';
|
|
|
20
20
|
export declare function writeIfOurs(path: string, content: string, markerPrefix: string): void;
|
|
21
21
|
/** Render and write every built-in export artifact to every present host, while
|
|
22
22
|
* pruning legacy generated artifacts that should no longer be surfaced.
|
|
23
|
-
* Best-effort:
|
|
24
|
-
*
|
|
23
|
+
* Best-effort: reports errors without breaking an unrelated `crtr` command.
|
|
24
|
+
* Kill switch: `CRTR_NO_EXPORTS=1`. */
|
|
25
25
|
export declare function pruneLegacyExports(argv?: string[]): void;
|
|
26
26
|
/** Write every built-in export artifact to every present host. Split from the
|
|
27
27
|
* prune above because the prune must run BEFORE the front door boots (stale
|