@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
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
//
|
|
21
21
|
// Plain TS-with-types — no imports from @earendil-works/* so this compiles inside
|
|
22
22
|
// crouter's own tsc build without a dep on the pi packages.
|
|
23
|
+
import { envNodeId } from '../shared/env.js';
|
|
23
24
|
import { writeFileSync, mkdirSync, existsSync, readFileSync } from 'node:fs';
|
|
24
25
|
import { join } from 'node:path';
|
|
25
26
|
import { contextDir, jobDir } from '../core/canvas/paths.js';
|
|
@@ -79,9 +80,7 @@ function flushTelemetry(jobDirPath, tokensIn, tokensOut, model, contextTokens, a
|
|
|
79
80
|
/* telemetry is best-effort; never surface */
|
|
80
81
|
}
|
|
81
82
|
}
|
|
82
|
-
// ---------------------------------------------------------------------------
|
|
83
83
|
// Message-extraction helpers
|
|
84
|
-
// ---------------------------------------------------------------------------
|
|
85
84
|
/** Walk backwards through the agent_end messages array to find the last
|
|
86
85
|
* assistant turn. */
|
|
87
86
|
function lastAssistantMessage(messages) {
|
|
@@ -117,7 +116,6 @@ function currentReviewBoundaryIds(ctx) {
|
|
|
117
116
|
return [];
|
|
118
117
|
}
|
|
119
118
|
}
|
|
120
|
-
// ---------------------------------------------------------------------------
|
|
121
119
|
// Context-size steering bands — a single shared schedule of thresholds that
|
|
122
120
|
// ESCALATE in tone as input context grows. The first band is a gentle
|
|
123
121
|
// "consider it"; a later band turns firm. The schedule TIGHTENS as it climbs:
|
|
@@ -150,7 +148,6 @@ function currentReviewBoundaryIds(ctx) {
|
|
|
150
148
|
// worthwhile parallel work. Only a terminal node is ever told `push final` (a
|
|
151
149
|
// resident finishes by yielding or being closed); only an orchestrator already
|
|
152
150
|
// HAS a roadmap to checkpoint before it yields.
|
|
153
|
-
// ---------------------------------------------------------------------------
|
|
154
151
|
const STEER_STEP = 10_000;
|
|
155
152
|
// Shared escalation schedule (both lifecycles). Tightens as it climbs:
|
|
156
153
|
// 130k, 150k, 170k, 185k, 200k, then every 10k (210k, 220k, …).
|
|
@@ -233,9 +230,7 @@ export function steerNote(at, lifecycle, mode) {
|
|
|
233
230
|
}
|
|
234
231
|
return `Context ~${k}k — this is getting long. Wrap up now before this context overflows: \`crtr push final\` if you're close, otherwise \`crtr node yield\` immediately to continue in a fresh window against your goal and your note.`;
|
|
235
232
|
}
|
|
236
|
-
// ---------------------------------------------------------------------------
|
|
237
233
|
// Extension
|
|
238
|
-
// ---------------------------------------------------------------------------
|
|
239
234
|
/**
|
|
240
235
|
* Register the canvas turn and settlement handlers on `pi`.
|
|
241
236
|
*
|
|
@@ -245,7 +240,7 @@ export function steerNote(at, lifecycle, mode) {
|
|
|
245
240
|
* per node lifecycle, matching how pi loads extensions).
|
|
246
241
|
*/
|
|
247
242
|
export function registerCanvasStophook(pi) {
|
|
248
|
-
const nodeId =
|
|
243
|
+
const nodeId = envNodeId();
|
|
249
244
|
if (nodeId === undefined || nodeId.trim() === '')
|
|
250
245
|
return; // not a canvas node
|
|
251
246
|
const jobDirPath = jobDir(nodeId);
|
|
@@ -310,7 +305,6 @@ export function registerCanvasStophook(pi) {
|
|
|
310
305
|
touchBusy(nodeId);
|
|
311
306
|
clearFault(nodeId, { link: 'daemon→node' });
|
|
312
307
|
};
|
|
313
|
-
// ---------------------------------------------------------------------------
|
|
314
308
|
// session_start — capture pi's session id, and detect `/new`.
|
|
315
309
|
//
|
|
316
310
|
// pi tags each session_start with a `reason`: 'startup' on boot (a fresh
|
|
@@ -327,7 +321,6 @@ export function registerCanvasStophook(pi) {
|
|
|
327
321
|
//
|
|
328
322
|
// `/new` splits by who ran it: crtrd derives rootness from the node row and
|
|
329
323
|
// either directs a root relaunch or resets a child's session coordinates.
|
|
330
|
-
// ---------------------------------------------------------------------------
|
|
331
324
|
pi.on('session_start', async (event, ctx) => {
|
|
332
325
|
try {
|
|
333
326
|
const id = ctx?.sessionManager?.getSessionId?.();
|
|
@@ -390,11 +383,9 @@ export function registerCanvasStophook(pi) {
|
|
|
390
383
|
});
|
|
391
384
|
}
|
|
392
385
|
});
|
|
393
|
-
// ---------------------------------------------------------------------------
|
|
394
386
|
// agent_start — pi entered a turn. Mark the node mid-turn (busy) so a
|
|
395
387
|
// focus-away while it is genuinely working backstages it (Invariant F2)
|
|
396
388
|
// rather than reaping it. Cleared only after the whole run settles.
|
|
397
|
-
// ---------------------------------------------------------------------------
|
|
398
389
|
pi.on('agent_start', () => {
|
|
399
390
|
// A fresh turn started. Keep any active fault marker in place so the daemon's
|
|
400
391
|
// retry accounting survives a failed retry cycle; just mark the turn busy.
|
|
@@ -403,7 +394,6 @@ export function registerCanvasStophook(pi) {
|
|
|
403
394
|
}
|
|
404
395
|
catch { /* best-effort */ }
|
|
405
396
|
});
|
|
406
|
-
// ---------------------------------------------------------------------------
|
|
407
397
|
// input — a new user-directed run is beginning. This is the ONLY place stop
|
|
408
398
|
// signals are cleared: `agent_start` re-fires for pi's automatic retries and
|
|
409
399
|
// post-compaction continuations within the SAME run, so clearing there would
|
|
@@ -413,18 +403,15 @@ export function registerCanvasStophook(pi) {
|
|
|
413
403
|
// `agent_settled` consumes them; a leftover from an errored or interrupted run
|
|
414
404
|
// of this same broker is discarded here, when the next prompt arrives (the pid
|
|
415
405
|
// stamp only rules out a PRIOR broker's markers, not this broker's own).
|
|
416
|
-
// ---------------------------------------------------------------------------
|
|
417
406
|
pi.on('input', () => {
|
|
418
407
|
try {
|
|
419
408
|
clearStopSignals(nodeId);
|
|
420
409
|
}
|
|
421
410
|
catch { /* best-effort */ }
|
|
422
411
|
});
|
|
423
|
-
// ---------------------------------------------------------------------------
|
|
424
412
|
// tool_execution_start — capture the live "what is it doing" cue. Writes the
|
|
425
413
|
// one-line tool summary to telemetry.json so out-of-process readers (the nav
|
|
426
414
|
// chrome) show it inline without a second file or any extra read on their side.
|
|
427
|
-
// ---------------------------------------------------------------------------
|
|
428
415
|
pi.on('tool_execution_start', (event) => {
|
|
429
416
|
try {
|
|
430
417
|
lastActivity = summarizeActivity(String(event?.toolName ?? ''), event?.args);
|
|
@@ -434,7 +421,6 @@ export function registerCanvasStophook(pi) {
|
|
|
434
421
|
}
|
|
435
422
|
catch { /* best-effort */ }
|
|
436
423
|
});
|
|
437
|
-
// ---------------------------------------------------------------------------
|
|
438
424
|
// tool_execution_update — wedge heartbeat + fault clear only. Fired with
|
|
439
425
|
// partial/streaming tool output (when a tool reports progress); throttled via
|
|
440
426
|
// `heartbeat()` since it can arrive many times per second. Most tools (e.g.
|
|
@@ -442,27 +428,23 @@ export function registerCanvasStophook(pi) {
|
|
|
442
428
|
// for them — it exists so any tool that DOES stream partial output (now or in
|
|
443
429
|
// the future) counts as live progress instead of tripping the wedge detector,
|
|
444
430
|
// AND clears any wedge notice that already fired before this progress resumed.
|
|
445
|
-
// ---------------------------------------------------------------------------
|
|
446
431
|
pi.on('tool_execution_update', () => {
|
|
447
432
|
try {
|
|
448
433
|
heartbeat();
|
|
449
434
|
}
|
|
450
435
|
catch { /* best-effort */ }
|
|
451
436
|
});
|
|
452
|
-
// ---------------------------------------------------------------------------
|
|
453
437
|
// message_update — wedge heartbeat + fault clear only. Fired token-by-token
|
|
454
438
|
// while the assistant is actively streaming a reply — genuine progress,
|
|
455
439
|
// throttled the same way, and equally clears a stale wedge notice if streaming
|
|
456
440
|
// resumes before a coarser boundary. A node stuck streaming forever without
|
|
457
441
|
// ever firing this is exactly the daemon's busy+quiet wedge signature.
|
|
458
|
-
// ---------------------------------------------------------------------------
|
|
459
442
|
pi.on('message_update', () => {
|
|
460
443
|
try {
|
|
461
444
|
heartbeat();
|
|
462
445
|
}
|
|
463
446
|
catch { /* best-effort */ }
|
|
464
447
|
});
|
|
465
|
-
// ---------------------------------------------------------------------------
|
|
466
448
|
// tool_execution_end — IMMEDIATE refresh-yield. When a tool this turn set
|
|
467
449
|
// intent='refresh' (the node ran `crtr node yield`), shut the broker down NOW
|
|
468
450
|
// instead of letting the model keep burning its bloated context to the turn's
|
|
@@ -494,11 +476,9 @@ export function registerCanvasStophook(pi) {
|
|
|
494
476
|
}
|
|
495
477
|
catch { /* best-effort */ }
|
|
496
478
|
});
|
|
497
|
-
// ---------------------------------------------------------------------------
|
|
498
479
|
// session_shutdown — Pi's clean /quit fact goes to crtrd, which owns the
|
|
499
480
|
// finish transition, focus teardown, presence clear, and fault clear. Other
|
|
500
481
|
// session swaps keep the same node and need no durable settlement.
|
|
501
|
-
// ---------------------------------------------------------------------------
|
|
502
482
|
pi.on('session_shutdown', async (event, ctx) => {
|
|
503
483
|
clearBusy(nodeId); // turn marker is meaningless once Pi is exiting
|
|
504
484
|
if (event?.reason !== 'quit')
|
|
@@ -525,10 +505,8 @@ export function registerCanvasStophook(pi) {
|
|
|
525
505
|
if (typeof msg.model === 'string' && msg.model !== '')
|
|
526
506
|
model = msg.model;
|
|
527
507
|
};
|
|
528
|
-
// ---------------------------------------------------------------------------
|
|
529
508
|
// turn_end — live telemetry refresh.
|
|
530
509
|
// event shape: { message: AssistantMessage, ... }
|
|
531
|
-
// ---------------------------------------------------------------------------
|
|
532
510
|
pi.on('turn_end', async (event, ctx) => {
|
|
533
511
|
accumulate(event?.message);
|
|
534
512
|
// The CURRENT context size via ctx.getContextUsage() — the exact figure pi's
|
|
@@ -615,10 +593,8 @@ export function registerCanvasStophook(pi) {
|
|
|
615
593
|
}
|
|
616
594
|
catch { /* best-effort */ }
|
|
617
595
|
});
|
|
618
|
-
// ---------------------------------------------------------------------------
|
|
619
596
|
// agent_settled — Pi supplies stop facts; crtrd commits every canvas effect
|
|
620
597
|
// and returns the one Pi-side consequence to enact.
|
|
621
|
-
// ---------------------------------------------------------------------------
|
|
622
598
|
pi.on('agent_settled', async (_event, ctx) => {
|
|
623
599
|
const event = stagedAgentEnd;
|
|
624
600
|
stagedAgentEnd = null;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// Loaded into every canvas node. Inert unless nodes/<id>/output-schema.json exists
|
|
4
4
|
// and is valid. If the request file is malformed, the tool is not registered — the
|
|
5
5
|
// stop-guard will reprompt the node with an explicit error about the invalid file.
|
|
6
|
+
import { envNodeId } from '../shared/env.js';
|
|
6
7
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
7
8
|
import { dirname } from 'node:path';
|
|
8
9
|
import { validateToolArguments } from '@earendil-works/pi-ai';
|
|
@@ -168,7 +169,7 @@ function toolDescription(request) {
|
|
|
168
169
|
return 'Submit the requested one-off structured result. Calling this records the result, pushes an update report automatically, frees you from the structured-output gate, and lets you continue working.';
|
|
169
170
|
}
|
|
170
171
|
export function registerCanvasStructuredOutput(pi) {
|
|
171
|
-
const nodeId =
|
|
172
|
+
const nodeId = envNodeId();
|
|
172
173
|
if (nodeId === undefined || nodeId.trim() === '')
|
|
173
174
|
return;
|
|
174
175
|
let registeredKey = null;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// Capturing `crtr -h` builds the full configured command tree, including commands
|
|
4
4
|
// discovered from the node's cwd. It runs only at session start; before_agent_start
|
|
5
5
|
// injects the last successful capture without starting work or waiting.
|
|
6
|
+
import { envNodeId } from '../shared/env.js';
|
|
6
7
|
import { execFile } from 'node:child_process';
|
|
7
8
|
import { createHash } from 'node:crypto';
|
|
8
9
|
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
@@ -25,7 +26,7 @@ function injectToolGuide(systemPrompt, helpText) {
|
|
|
25
26
|
}
|
|
26
27
|
/** Register the root crtr tool-guide injection for a canvas node. */
|
|
27
28
|
export function registerCanvasToolGuide(pi) {
|
|
28
|
-
const nodeId =
|
|
29
|
+
const nodeId = envNodeId();
|
|
29
30
|
if (nodeId === undefined || nodeId.trim() === '')
|
|
30
31
|
return;
|
|
31
32
|
let helpText = '';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// `shared/env.ts` is the reader-side surface for the env vars listed below —
|
|
2
|
+
// every one of them was migrated off a scattered `process.env` read onto a
|
|
3
|
+
// named accessor there. This grep-enforces that boundary: outside the owner
|
|
4
|
+
// module itself, a read of any migrated var may live only in an explicitly
|
|
5
|
+
// documented exemption — a distinct, non-read use of the SAME var. Exemptions
|
|
6
|
+
// are itemized below so a new stray read fails loud instead of silently
|
|
7
|
+
// reintroducing the var outside its accessor.
|
|
8
|
+
import { test } from 'node:test';
|
|
9
|
+
import assert from 'node:assert/strict';
|
|
10
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
11
|
+
import { join, resolve, relative } from 'node:path';
|
|
12
|
+
const SRC_ROOT = resolve(process.cwd(), 'src');
|
|
13
|
+
// Every var migrated onto an accessor in `shared/env.ts`. Complete: every
|
|
14
|
+
// forbidden-file sweep has landed, so this is the full migrated set.
|
|
15
|
+
const MIGRATED_VARS = [
|
|
16
|
+
'CRTR_NODE_ID',
|
|
17
|
+
'CRTR_PROFILE_ID',
|
|
18
|
+
'CRTR_NODE_CWD',
|
|
19
|
+
'CRTR_MODEL_INTENT',
|
|
20
|
+
'CRTR_HOME',
|
|
21
|
+
'CRTR_STREAM_WATCHDOG_MS',
|
|
22
|
+
'CRTR_WATCHER_TICK_MS',
|
|
23
|
+
'CRTR_WATCHER_DEBOUNCE_MS',
|
|
24
|
+
'CRTR_RECAP_IDLE_MS',
|
|
25
|
+
'CRTR_RECAP_MODEL',
|
|
26
|
+
'CRTR_BASH_VALVE_MS',
|
|
27
|
+
'CRTR_PIDFILE',
|
|
28
|
+
'CRTR_BROKER_ENGINE',
|
|
29
|
+
'CRTR_PI_BINARY',
|
|
30
|
+
'CRTR_NO_DAEMON_AUTOSTART',
|
|
31
|
+
'CRTRD_TCP',
|
|
32
|
+
'CRTR_NO_EXPORTS',
|
|
33
|
+
'CRTR_DEBUG',
|
|
34
|
+
'CRTR_MAX_LIVE_BROKERS',
|
|
35
|
+
'CRTR_WARN_LIVE_BROKERS',
|
|
36
|
+
'CRTR_TEST_UNATTENDED_PARK_MS',
|
|
37
|
+
'CRTR_TEST_PARK_SUMMARY_GRACE_MS',
|
|
38
|
+
];
|
|
39
|
+
// Matches `process.env['VAR']`, `process.env.VAR`, or `process.env[\`VAR\`]`
|
|
40
|
+
// for exactly one of MIGRATED_VARS — not a longer name that merely starts
|
|
41
|
+
// with it (e.g. `CRTR_DEBUG_PID_LIVENESS` must NOT match `CRTR_DEBUG`).
|
|
42
|
+
const VAR_PATTERN = MIGRATED_VARS.join('|');
|
|
43
|
+
const READ_RE = new RegExp(String.raw `process\.env(?:\.(?:${VAR_PATTERN})\b|\[['"\`](?:${VAR_PATTERN})['"\`]\])`);
|
|
44
|
+
// Relative to src/, forward-slash form. Each entry is a genuinely distinct
|
|
45
|
+
// use of the SAME var name that the migration deliberately leaves in place —
|
|
46
|
+
// not an unmigrated read.
|
|
47
|
+
const EXEMPTIONS = new Map([
|
|
48
|
+
[
|
|
49
|
+
'core/canvas/paths.ts',
|
|
50
|
+
'crtrHome() is the canonical resolved-path accessor for CRTR_HOME; ' +
|
|
51
|
+
'envHomeOverride() in shared/env.ts is for callers that want the raw ' +
|
|
52
|
+
'override itself (see the header comment there).',
|
|
53
|
+
],
|
|
54
|
+
[
|
|
55
|
+
'core/runtime/broker.ts',
|
|
56
|
+
"clears CRTR_MODEL_INTENT via `delete process.env[...]` — a mutation, " +
|
|
57
|
+
'not a read, so it stays here per shared/env.ts\'s header comment.',
|
|
58
|
+
],
|
|
59
|
+
]);
|
|
60
|
+
function tsFilesUnder(dir) {
|
|
61
|
+
const out = [];
|
|
62
|
+
for (const entry of readdirSync(dir)) {
|
|
63
|
+
const path = join(dir, entry);
|
|
64
|
+
const stat = statSync(path);
|
|
65
|
+
if (stat.isDirectory()) {
|
|
66
|
+
if (entry === '__tests__')
|
|
67
|
+
continue;
|
|
68
|
+
out.push(...tsFilesUnder(path));
|
|
69
|
+
}
|
|
70
|
+
else if (entry.endsWith('.ts') && !entry.endsWith('.test.ts')) {
|
|
71
|
+
out.push(path);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
test('every migrated env var is read only through shared/env.ts or an explicit exemption', () => {
|
|
77
|
+
const offenders = [];
|
|
78
|
+
for (const file of tsFilesUnder(SRC_ROOT)) {
|
|
79
|
+
const relPath = relative(SRC_ROOT, file).split('\\').join('/');
|
|
80
|
+
if (relPath === 'shared/env.ts')
|
|
81
|
+
continue;
|
|
82
|
+
if (EXEMPTIONS.has(relPath))
|
|
83
|
+
continue;
|
|
84
|
+
const source = readFileSync(file, 'utf8');
|
|
85
|
+
const lines = source.split('\n');
|
|
86
|
+
lines.forEach((line, index) => {
|
|
87
|
+
if (READ_RE.test(line)) {
|
|
88
|
+
offenders.push(`${relPath}:${index + 1}: ${line.trim()}`);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
assert.deepEqual(offenders, [], `migrated env var read(s) outside shared/env.ts and its exemptions:\n${offenders.join('\n')}`);
|
|
93
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/** The current node's id (`CRTR_NODE_ID`), or undefined outside a node. */
|
|
2
|
+
export declare function envNodeId(): string | undefined;
|
|
3
|
+
/** The current node's target profile id (`CRTR_PROFILE_ID`), or undefined. */
|
|
4
|
+
export declare function envProfileId(): string | undefined;
|
|
5
|
+
/** The current node's working directory (`CRTR_NODE_CWD`), or undefined. */
|
|
6
|
+
export declare function envNodeCwd(): string | undefined;
|
|
7
|
+
/** An explicit model-routing override for this turn (`CRTR_MODEL_INTENT`), or
|
|
8
|
+
* undefined. Cleared (not read) via `delete process.env['CRTR_MODEL_INTENT']`
|
|
9
|
+
* in `runtime/broker.ts` — a mutation, not a read, so it stays there. */
|
|
10
|
+
export declare function envModelIntent(): string | undefined;
|
|
11
|
+
/** The raw `CRTR_HOME` override, unresolved. Use `crtrHome()`
|
|
12
|
+
* (`core/canvas/paths.ts`) to get the resolved canvas-home path; use this
|
|
13
|
+
* only when a caller needs the override itself — to check whether one is
|
|
14
|
+
* set, or to propagate it verbatim into a child process's env. */
|
|
15
|
+
export declare function envHomeOverride(): string | undefined;
|
|
16
|
+
/** Dead-provider watchdog timeout (`CRTR_STREAM_WATCHDOG_MS`), 5 minutes by
|
|
17
|
+
* default. See `runtime/stream-watchdog.ts` for what it guards. */
|
|
18
|
+
export declare function envStreamWatchdogMs(): number;
|
|
19
|
+
/** The canvas inbox watcher's poll tick (`CRTR_WATCHER_TICK_MS`). */
|
|
20
|
+
export declare function envWatcherTickMs(): number;
|
|
21
|
+
/** The canvas inbox watcher's debounce window (`CRTR_WATCHER_DEBOUNCE_MS`). */
|
|
22
|
+
export declare function envWatcherDebounceMs(): number;
|
|
23
|
+
/** No-new-message window before a recap is shown (`CRTR_RECAP_IDLE_MS`), 60s
|
|
24
|
+
* by default. */
|
|
25
|
+
export declare function envRecapIdleMs(): number;
|
|
26
|
+
/** Explicit recap-model override (`CRTR_RECAP_MODEL`), trimmed; undefined if
|
|
27
|
+
* unset or blank. */
|
|
28
|
+
export declare function envRecapModelOverride(): string | undefined;
|
|
29
|
+
/** The bash safety-valve deadline (`CRTR_BASH_VALVE_MS`), 5 minutes by
|
|
30
|
+
* default; undocumented test-only override so the E2E valve check doesn't
|
|
31
|
+
* sleep 5 minutes. */
|
|
32
|
+
export declare function envBashValveMs(): number;
|
|
33
|
+
/** Explicit pidfile path override (`CRTR_PIDFILE`, tests only); undefined if
|
|
34
|
+
* unset or blank. */
|
|
35
|
+
export declare function envPidfileOverride(): string | undefined;
|
|
36
|
+
/** The broker engine module spec (`CRTR_BROKER_ENGINE`, the T11 test seam),
|
|
37
|
+
* defaulting to the real SDK. `runtime/host.ts` layers `inv.env` ahead of
|
|
38
|
+
* this (a launch-time override mirrored into the child's env, since
|
|
39
|
+
* spawn-env.ts's default-deny allowlist strips `CRTR_*` from ambient env). */
|
|
40
|
+
export declare function envBrokerEngine(): string;
|
|
41
|
+
/** Test-only pi-binary substitution (`CRTR_PI_BINARY`) so the integration
|
|
42
|
+
* harness can point a real `crtr node new` at a deterministic fake-pi
|
|
43
|
+
* vehicle. Undefined in production. */
|
|
44
|
+
export declare function envPiBinaryOverride(): string | undefined;
|
|
45
|
+
/** Whether implicit daemon autostart is suppressed for this invocation
|
|
46
|
+
* (`CRTR_NO_DAEMON_AUTOSTART=1`). */
|
|
47
|
+
export declare function envNoDaemonAutostart(): boolean;
|
|
48
|
+
/** The `--tcp` fallback for crtrd's opt-in TCP listener (`CRTRD_TCP`), raw
|
|
49
|
+
* (`host:port` or undefined — absent means unix socket only). */
|
|
50
|
+
export declare function envCrtrdTcp(): string | undefined;
|
|
51
|
+
/** Kill switch for the host-exports writer/pruner (`CRTR_NO_EXPORTS=1`). */
|
|
52
|
+
export declare function envNoExports(): boolean;
|
|
53
|
+
/** Verbose-diagnostics gate for otherwise-silent best-effort catches
|
|
54
|
+
* (`CRTR_DEBUG=1`). Distinct from `CRTR_DEBUG_PID_LIVENESS`
|
|
55
|
+
* (`core/canvas/pid.ts`), a different, unrelated var. */
|
|
56
|
+
export declare function envDebug(): boolean;
|
|
57
|
+
/** Live-broker automatic-revive cap override (`CRTR_MAX_LIVE_BROKERS`); wins
|
|
58
|
+
* over `readConfig('user').brokerThresholds.automaticReviveCap` when set. */
|
|
59
|
+
export declare function envMaxLiveBrokers(): number | undefined;
|
|
60
|
+
/** Live-broker warning threshold override (`CRTR_WARN_LIVE_BROKERS`); wins
|
|
61
|
+
* over `readConfig('user').brokerThresholds.warning` when set. */
|
|
62
|
+
export declare function envWarnLiveBrokers(): number | undefined;
|
|
63
|
+
/** Test-only unattended-park interval override (`CRTR_TEST_UNATTENDED_PARK_MS`),
|
|
64
|
+
* gated by `envNoDaemonAutostart()` at the call site; no production default. */
|
|
65
|
+
export declare function envTestUnattendedParkMs(): number | undefined;
|
|
66
|
+
/** Test-only park-summary grace-period override
|
|
67
|
+
* (`CRTR_TEST_PARK_SUMMARY_GRACE_MS`); no production default. */
|
|
68
|
+
export declare function envTestParkSummaryGraceMs(): number | undefined;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// The reader-side surface for every environment variable crouter reads back
|
|
2
|
+
// out of `process.env`, outside `core/runtime/spawn-env.ts`'s writer
|
|
3
|
+
// allowlist. That module documents what a broker child is ADMITTED to see;
|
|
4
|
+
// this one documents what crouter itself reads. Two families:
|
|
5
|
+
//
|
|
6
|
+
// - Identity: raw passthrough (`string | undefined`, exactly what
|
|
7
|
+
// `process.env[name]` returns). Every existing call site keeps its own
|
|
8
|
+
// established fallback (`?? ''`, `|| null`, `?? cfg.cwd`, a presence
|
|
9
|
+
// check, ...) — the fallback has always been call-site-owned, not
|
|
10
|
+
// var-owned, so centralizing it here would be a behavior change, not a
|
|
11
|
+
// dedup. `CRTR_HOME` also has a resolved-path accessor, `crtrHome()` in
|
|
12
|
+
// `core/canvas/paths.ts`; that stays the canonical way to get the
|
|
13
|
+
// resolved canvas home; `envHomeOverride()` here is for the handful of
|
|
14
|
+
// sites that want the raw override value itself (to check presence or
|
|
15
|
+
// propagate it verbatim to a child env).
|
|
16
|
+
//
|
|
17
|
+
// - Tuning: parsed, with the default baked into the accessor. Each of
|
|
18
|
+
// these had exactly one parse site before this module existed; the
|
|
19
|
+
// parse logic moved here unchanged so a second site, if one appears,
|
|
20
|
+
// reads the single implementation instead of re-deriving it.
|
|
21
|
+
//
|
|
22
|
+
// `CRTR_DIR_NAME` is NOT here — it is a plain exported string constant
|
|
23
|
+
// (`types.ts`), never read off `process.env`.
|
|
24
|
+
// Identity
|
|
25
|
+
/** The current node's id (`CRTR_NODE_ID`), or undefined outside a node. */
|
|
26
|
+
export function envNodeId() {
|
|
27
|
+
return process.env['CRTR_NODE_ID'];
|
|
28
|
+
}
|
|
29
|
+
/** The current node's target profile id (`CRTR_PROFILE_ID`), or undefined. */
|
|
30
|
+
export function envProfileId() {
|
|
31
|
+
return process.env['CRTR_PROFILE_ID'];
|
|
32
|
+
}
|
|
33
|
+
/** The current node's working directory (`CRTR_NODE_CWD`), or undefined. */
|
|
34
|
+
export function envNodeCwd() {
|
|
35
|
+
return process.env['CRTR_NODE_CWD'];
|
|
36
|
+
}
|
|
37
|
+
/** An explicit model-routing override for this turn (`CRTR_MODEL_INTENT`), or
|
|
38
|
+
* undefined. Cleared (not read) via `delete process.env['CRTR_MODEL_INTENT']`
|
|
39
|
+
* in `runtime/broker.ts` — a mutation, not a read, so it stays there. */
|
|
40
|
+
export function envModelIntent() {
|
|
41
|
+
return process.env['CRTR_MODEL_INTENT'];
|
|
42
|
+
}
|
|
43
|
+
/** The raw `CRTR_HOME` override, unresolved. Use `crtrHome()`
|
|
44
|
+
* (`core/canvas/paths.ts`) to get the resolved canvas-home path; use this
|
|
45
|
+
* only when a caller needs the override itself — to check whether one is
|
|
46
|
+
* set, or to propagate it verbatim into a child process's env. */
|
|
47
|
+
export function envHomeOverride() {
|
|
48
|
+
return process.env['CRTR_HOME'];
|
|
49
|
+
}
|
|
50
|
+
// Tuning
|
|
51
|
+
/** Generic `Number(raw)` parse with a positive-finite guard, shared by every
|
|
52
|
+
* millisecond tuning var below (each previously reimplemented this locally,
|
|
53
|
+
* identically). */
|
|
54
|
+
function parsePositiveMs(raw, fallback) {
|
|
55
|
+
if (raw === undefined)
|
|
56
|
+
return fallback;
|
|
57
|
+
const n = Number(raw);
|
|
58
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
59
|
+
}
|
|
60
|
+
const DEFAULT_STREAM_WATCHDOG_MS = 5 * 60_000; // 5 minutes.
|
|
61
|
+
/** Dead-provider watchdog timeout (`CRTR_STREAM_WATCHDOG_MS`), 5 minutes by
|
|
62
|
+
* default. See `runtime/stream-watchdog.ts` for what it guards. */
|
|
63
|
+
export function envStreamWatchdogMs() {
|
|
64
|
+
return parsePositiveMs(process.env['CRTR_STREAM_WATCHDOG_MS'], DEFAULT_STREAM_WATCHDOG_MS);
|
|
65
|
+
}
|
|
66
|
+
const DEFAULT_WATCHER_TICK_MS = 800;
|
|
67
|
+
/** The canvas inbox watcher's poll tick (`CRTR_WATCHER_TICK_MS`). */
|
|
68
|
+
export function envWatcherTickMs() {
|
|
69
|
+
return parsePositiveMs(process.env['CRTR_WATCHER_TICK_MS'], DEFAULT_WATCHER_TICK_MS);
|
|
70
|
+
}
|
|
71
|
+
const DEFAULT_WATCHER_DEBOUNCE_MS = 1000;
|
|
72
|
+
/** The canvas inbox watcher's debounce window (`CRTR_WATCHER_DEBOUNCE_MS`). */
|
|
73
|
+
export function envWatcherDebounceMs() {
|
|
74
|
+
return parsePositiveMs(process.env['CRTR_WATCHER_DEBOUNCE_MS'], DEFAULT_WATCHER_DEBOUNCE_MS);
|
|
75
|
+
}
|
|
76
|
+
const DEFAULT_RECAP_IDLE_MS = 60_000;
|
|
77
|
+
/** No-new-message window before a recap is shown (`CRTR_RECAP_IDLE_MS`), 60s
|
|
78
|
+
* by default. */
|
|
79
|
+
export function envRecapIdleMs() {
|
|
80
|
+
return parsePositiveMs(process.env['CRTR_RECAP_IDLE_MS'], DEFAULT_RECAP_IDLE_MS);
|
|
81
|
+
}
|
|
82
|
+
/** Explicit recap-model override (`CRTR_RECAP_MODEL`), trimmed; undefined if
|
|
83
|
+
* unset or blank. */
|
|
84
|
+
export function envRecapModelOverride() {
|
|
85
|
+
const raw = process.env['CRTR_RECAP_MODEL'];
|
|
86
|
+
return raw !== undefined && raw.trim() !== '' ? raw.trim() : undefined;
|
|
87
|
+
}
|
|
88
|
+
const DEFAULT_BASH_VALVE_MS = 5 * 60 * 1000;
|
|
89
|
+
/** The bash safety-valve deadline (`CRTR_BASH_VALVE_MS`), 5 minutes by
|
|
90
|
+
* default; undocumented test-only override so the E2E valve check doesn't
|
|
91
|
+
* sleep 5 minutes. */
|
|
92
|
+
export function envBashValveMs() {
|
|
93
|
+
return parsePositiveMs(process.env['CRTR_BASH_VALVE_MS'], DEFAULT_BASH_VALVE_MS);
|
|
94
|
+
}
|
|
95
|
+
/** Explicit pidfile path override (`CRTR_PIDFILE`, tests only); undefined if
|
|
96
|
+
* unset or blank. */
|
|
97
|
+
export function envPidfileOverride() {
|
|
98
|
+
const raw = process.env['CRTR_PIDFILE'];
|
|
99
|
+
return raw !== undefined && raw !== '' ? raw : undefined;
|
|
100
|
+
}
|
|
101
|
+
const DEFAULT_BROKER_ENGINE = '@earendil-works/pi-coding-agent';
|
|
102
|
+
/** The broker engine module spec (`CRTR_BROKER_ENGINE`, the T11 test seam),
|
|
103
|
+
* defaulting to the real SDK. `runtime/host.ts` layers `inv.env` ahead of
|
|
104
|
+
* this (a launch-time override mirrored into the child's env, since
|
|
105
|
+
* spawn-env.ts's default-deny allowlist strips `CRTR_*` from ambient env). */
|
|
106
|
+
export function envBrokerEngine() {
|
|
107
|
+
return process.env['CRTR_BROKER_ENGINE'] ?? DEFAULT_BROKER_ENGINE;
|
|
108
|
+
}
|
|
109
|
+
/** Test-only pi-binary substitution (`CRTR_PI_BINARY`) so the integration
|
|
110
|
+
* harness can point a real `crtr node new` at a deterministic fake-pi
|
|
111
|
+
* vehicle. Undefined in production. */
|
|
112
|
+
export function envPiBinaryOverride() {
|
|
113
|
+
return process.env['CRTR_PI_BINARY'];
|
|
114
|
+
}
|
|
115
|
+
/** Whether implicit daemon autostart is suppressed for this invocation
|
|
116
|
+
* (`CRTR_NO_DAEMON_AUTOSTART=1`). */
|
|
117
|
+
export function envNoDaemonAutostart() {
|
|
118
|
+
return process.env['CRTR_NO_DAEMON_AUTOSTART'] === '1';
|
|
119
|
+
}
|
|
120
|
+
/** The `--tcp` fallback for crtrd's opt-in TCP listener (`CRTRD_TCP`), raw
|
|
121
|
+
* (`host:port` or undefined — absent means unix socket only). */
|
|
122
|
+
export function envCrtrdTcp() {
|
|
123
|
+
return process.env['CRTRD_TCP'];
|
|
124
|
+
}
|
|
125
|
+
/** Kill switch for the host-exports writer/pruner (`CRTR_NO_EXPORTS=1`). */
|
|
126
|
+
export function envNoExports() {
|
|
127
|
+
return process.env['CRTR_NO_EXPORTS'] === '1';
|
|
128
|
+
}
|
|
129
|
+
/** Verbose-diagnostics gate for otherwise-silent best-effort catches
|
|
130
|
+
* (`CRTR_DEBUG=1`). Distinct from `CRTR_DEBUG_PID_LIVENESS`
|
|
131
|
+
* (`core/canvas/pid.ts`), a different, unrelated var. */
|
|
132
|
+
export function envDebug() {
|
|
133
|
+
return process.env['CRTR_DEBUG'] === '1';
|
|
134
|
+
}
|
|
135
|
+
// Precedence — broker-supervision.ts's threshold/interval overrides. Each
|
|
136
|
+
// returns the raw parsed value with NO default: the caller (config for the
|
|
137
|
+
// thresholds, a hardcoded production constant for the intervals) supplies
|
|
138
|
+
// the default, and env wins over it when set. Undefined, unparseable, or
|
|
139
|
+
// non-positive all mean "no override" — the caller's own default applies.
|
|
140
|
+
function parsePositiveInteger(raw) {
|
|
141
|
+
if (raw === undefined || raw === '')
|
|
142
|
+
return undefined;
|
|
143
|
+
const n = Number(raw);
|
|
144
|
+
return Number.isSafeInteger(n) && n >= 1 ? n : undefined;
|
|
145
|
+
}
|
|
146
|
+
/** Live-broker automatic-revive cap override (`CRTR_MAX_LIVE_BROKERS`); wins
|
|
147
|
+
* over `readConfig('user').brokerThresholds.automaticReviveCap` when set. */
|
|
148
|
+
export function envMaxLiveBrokers() {
|
|
149
|
+
return parsePositiveInteger(process.env['CRTR_MAX_LIVE_BROKERS']);
|
|
150
|
+
}
|
|
151
|
+
/** Live-broker warning threshold override (`CRTR_WARN_LIVE_BROKERS`); wins
|
|
152
|
+
* over `readConfig('user').brokerThresholds.warning` when set. */
|
|
153
|
+
export function envWarnLiveBrokers() {
|
|
154
|
+
return parsePositiveInteger(process.env['CRTR_WARN_LIVE_BROKERS']);
|
|
155
|
+
}
|
|
156
|
+
function parsePositiveMsNoDefault(raw) {
|
|
157
|
+
if (raw === undefined)
|
|
158
|
+
return undefined;
|
|
159
|
+
const n = Number(raw);
|
|
160
|
+
return Number.isFinite(n) && n > 0 ? n : undefined;
|
|
161
|
+
}
|
|
162
|
+
/** Test-only unattended-park interval override (`CRTR_TEST_UNATTENDED_PARK_MS`),
|
|
163
|
+
* gated by `envNoDaemonAutostart()` at the call site; no production default. */
|
|
164
|
+
export function envTestUnattendedParkMs() {
|
|
165
|
+
return parsePositiveMsNoDefault(process.env['CRTR_TEST_UNATTENDED_PARK_MS']);
|
|
166
|
+
}
|
|
167
|
+
/** Test-only park-summary grace-period override
|
|
168
|
+
* (`CRTR_TEST_PARK_SUMMARY_GRACE_MS`); no production default. */
|
|
169
|
+
export function envTestParkSummaryGraceMs() {
|
|
170
|
+
return parsePositiveMsNoDefault(process.env['CRTR_TEST_PARK_SUMMARY_GRACE_MS']);
|
|
171
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/crouter",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.234",
|
|
4
4
|
"description": "crtr — agent runtime with memory, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -74,6 +74,8 @@
|
|
|
74
74
|
"typecheck:pi-packages": "npx tsc -p src/builtin-pi-packages/pi-crtr-extensions/tsconfig.json",
|
|
75
75
|
"test:build-output": "node scripts/build-concurrency-test.mjs",
|
|
76
76
|
"check:cli-no-canvas": "node scripts/check-cli-no-canvas.mjs",
|
|
77
|
+
"check:daemon-no-barrel": "node scripts/check-daemon-no-barrel.mjs",
|
|
78
|
+
"check:quote-style": "node scripts/check-quote-style.mjs",
|
|
77
79
|
"postinstall": "node scripts/postinstall.mjs",
|
|
78
80
|
"install-runtime": "node scripts/install-runtime.mjs",
|
|
79
81
|
"prepack": "node scripts/runtime-lock.mjs prepack",
|
package/runtime.lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/crouter",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.234",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@north-light/crouter",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.234",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { type DashboardRow } from './render-source.js';
|
|
2
|
-
export * from './render-source.js';
|
|
3
|
-
/**
|
|
4
|
-
* Render the subscription sub-DAG rooted at `rootId` as an ASCII tree.
|
|
5
|
-
* The root is the first line (no connector prefix); children are indented.
|
|
6
|
-
*
|
|
7
|
-
* Each line: `<glyph> <name> [<kind>/<mode>] ctx <Nk>[ ⚑<asks>]`
|
|
8
|
-
*
|
|
9
|
-
* Returns a multi-line string (no trailing newline).
|
|
10
|
-
*/
|
|
11
|
-
export declare function renderTree(rootId: string): string;
|
|
12
|
-
/**
|
|
13
|
-
* Render all canvas roots as a forest. A root is a node with no subscribers
|
|
14
|
-
* (no one subscribes to it = it has no managers in the org chart).
|
|
15
|
-
*
|
|
16
|
-
* If there are no roots on the canvas, returns a placeholder string.
|
|
17
|
-
*/
|
|
18
|
-
export declare function renderForest(): string;
|
|
19
|
-
/** One row per node visible in the sub-DAG of `rootId` (including root). */
|
|
20
|
-
export declare function dashboardRows(rootId: string): DashboardRow[];
|
|
21
|
-
/**
|
|
22
|
-
* CHEAP boot builder — one row per node across the entire canvas, with only the
|
|
23
|
-
* fields that need no per-node meta/telemetry/session read. Two db queries total:
|
|
24
|
-
* `listNodes()` + `listFocuses()` (the focus set replaces per-node getFocusByNode
|
|
25
|
-
* calls). See {@link dashboardRowFromNodeRow} for the per-row projection, and
|
|
26
|
-
* {@link enrichRow}/{@link enrichRows}/{@link loadPreview} for the lazy fields.
|
|
27
|
-
*/
|
|
28
|
-
export declare function dashboardRowsAll(): DashboardRow[];
|
|
29
|
-
/** Fold the cheap-boot row's deferred fields in for ONE row: the full label
|
|
30
|
-
* (meta.description → fullName), ctx tokens (telemetry.json), and ⚑ asks. One
|
|
31
|
-
* meta read + one telemetry read + one ticket scan. Idempotent (no-op once enriched).
|
|
32
|
-
* For a batch, prefer {@link enrichRows} — it scans each cwd's ticket inbox once. */
|
|
33
|
-
export declare function enrichRow(row: DashboardRow): DashboardRow;
|
|
34
|
-
/** Batch {@link enrichRow}: enrich every not-yet-enriched row, scanning each
|
|
35
|
-
* distinct cwd's ticket inbox exactly ONCE (via `ticketCountsForNodes`) instead
|
|
36
|
-
* of per row. Use this for a whole viewport / the full forest; mutates each row in place. */
|
|
37
|
-
export declare function enrichRows(rows: DashboardRow[]): void;
|
|
38
|
-
/** Load the SELECTED row's preview text: the spawn `goal` (initial-prompt.md) plus
|
|
39
|
-
* the whole-conversation `prompts` and the `lastAssistant` reply — the latter two
|
|
40
|
-
* folded into ONE session-file read (see {@link readSessionParts}). Mutates the row
|
|
41
|
-
* in place; idempotent. Call only for the cursor row (and lazily/in-background to
|
|
42
|
-
* warm the prompt super-search corpus), never on the boot path. */
|
|
43
|
-
export declare function loadPreview(row: DashboardRow): DashboardRow;
|
|
44
|
-
/** {@link isStreaming} keyed by node id alone — hydrates the broker pid off the
|
|
45
|
-
* db row. The exported "is this node actively generating right now?" guard so a
|
|
46
|
-
* reap never nukes a node mid-first-turn before its output lands on disk. */
|
|
47
|
-
export declare function isNodeStreaming(nodeId: string): boolean;
|