@crouton-kit/crouter 0.3.31 → 0.3.33
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/README.md +8 -0
- package/dist/build-root.js +1 -0
- package/dist/builtin-memory/crouter-development/marketplaces.md +2 -2
- package/dist/builtin-memory/crouter-development/personas/base-prompt.md +2 -2
- package/dist/builtin-memory/crouter-development/personas/orchestrator-prompt.md +5 -5
- package/dist/builtin-memory/crouter-development/personas.md +3 -4
- package/dist/builtin-memory/crouter-development/plugins.md +18 -18
- package/dist/builtin-memory/design.md +4 -1
- package/dist/builtin-memory/development.md +4 -1
- package/dist/builtin-memory/internal/INDEX.md +1 -1
- package/dist/builtin-memory/internal/nodes-and-canvas.md +6 -6
- package/dist/builtin-memory/internal/storage-tiers.md +5 -5
- package/dist/builtin-memory/planning.md +4 -1
- package/dist/builtin-memory/product.md +80 -0
- package/dist/builtin-memory/spec.md +4 -1
- package/dist/builtin-personas/advisor/PERSONA.md +10 -0
- package/dist/builtin-personas/design/PERSONA.md +2 -2
- package/dist/builtin-personas/design/orchestrator.md +3 -3
- package/dist/builtin-personas/developer/PERSONA.md +1 -1
- package/dist/builtin-personas/developer/orchestrator.md +2 -2
- package/dist/builtin-personas/explore/PERSONA.md +3 -3
- package/dist/builtin-personas/explore/orchestrator.md +4 -2
- package/dist/builtin-personas/general/PERSONA.md +1 -1
- package/dist/builtin-personas/general/orchestrator.md +1 -1
- package/dist/builtin-personas/orchestration-kernel.md +7 -14
- package/dist/builtin-personas/plan/PERSONA.md +1 -1
- package/dist/builtin-personas/plan/orchestrator.md +2 -2
- package/dist/builtin-personas/plan/reviewers/architecture-fit/PERSONA.md +1 -1
- package/dist/builtin-personas/plan/reviewers/code-smells/PERSONA.md +1 -1
- package/dist/builtin-personas/plan/reviewers/pattern-consistency/PERSONA.md +1 -1
- package/dist/builtin-personas/plan/reviewers/requirements-coverage/PERSONA.md +1 -1
- package/dist/builtin-personas/plan/reviewers/security/PERSONA.md +1 -1
- package/dist/builtin-personas/product/PERSONA.md +18 -0
- package/dist/builtin-personas/product/orchestrator.md +14 -0
- package/dist/builtin-personas/product/teardown/PERSONA.md +13 -0
- package/dist/builtin-personas/review/PERSONA.md +1 -1
- package/dist/builtin-personas/review/orchestrator.md +1 -1
- package/dist/builtin-personas/runtime-base.md +5 -0
- package/dist/builtin-personas/spec/PERSONA.md +1 -1
- package/dist/builtin-personas/spec/orchestrator.md +2 -2
- package/dist/builtin-personas/spec/requirements/PERSONA.md +1 -1
- package/dist/builtin-views/canvas/core.mjs +82 -1
- package/dist/builtin-views/canvas/tui.mjs +9 -5
- package/dist/builtin-views/canvas/web.jsx +3 -2
- package/dist/builtin-views/chat/core.mjs +725 -0
- package/dist/builtin-views/chat/text.mjs +101 -0
- package/dist/builtin-views/chat/tui.mjs +368 -0
- package/dist/builtin-views/chat/web.jsx +367 -0
- package/dist/builtin-views/prompt-review/core.mjs +863 -0
- package/dist/builtin-views/prompt-review/text.mjs +15 -0
- package/dist/builtin-views/prompt-review/tui.mjs +196 -0
- package/dist/builtin-views/prompt-review/web.jsx +484 -0
- package/dist/builtin-views/settings/core.mjs +397 -0
- package/dist/builtin-views/settings/text.mjs +40 -0
- package/dist/builtin-views/settings/tui.mjs +95 -0
- package/dist/builtin-views/settings/web.jsx +167 -0
- package/dist/cli.js +16 -3
- package/dist/clients/attach/__tests__/autocomplete-and-bash-mode.test.js +96 -0
- package/dist/clients/attach/__tests__/bash-bang-routing.test.js +58 -0
- package/dist/clients/attach/__tests__/bundle-pi-tui-dedup.test.d.ts +1 -0
- package/dist/clients/attach/__tests__/bundle-pi-tui-dedup.test.js +56 -0
- package/dist/clients/attach/__tests__/titled-editor.test.js +22 -1
- package/dist/clients/attach/attach-cmd.d.ts +18 -0
- package/dist/clients/attach/attach-cmd.js +1723 -795
- package/dist/clients/attach/canvas-panels.js +2 -2
- package/dist/clients/attach/chat-view.d.ts +10 -0
- package/dist/clients/attach/chat-view.js +23 -0
- package/dist/clients/attach/config-load.d.ts +8 -4
- package/dist/clients/attach/config-load.js +2 -0
- package/dist/clients/attach/extension-dialogs.d.ts +2 -3
- package/dist/clients/attach/extension-dialogs.js +7 -9
- package/dist/clients/attach/graph-overlay.js +3 -2
- package/dist/clients/attach/input-controller.d.ts +4 -3
- package/dist/clients/attach/input-controller.js +24 -3
- package/dist/clients/attach/slash-commands.d.ts +7 -7
- package/dist/clients/attach/slash-commands.js +38 -14
- package/dist/clients/attach/titled-editor.js +18 -14
- package/dist/clients/attach/view-socket.d.ts +2 -1
- package/dist/clients/attach/view-socket.js +27 -8
- package/dist/clients/web/__tests__/source-cache.test.d.ts +1 -0
- package/dist/clients/web/__tests__/source-cache.test.js +32 -0
- package/dist/clients/web/dev-server.js +1 -0
- package/dist/clients/web/events.js +9 -11
- package/dist/clients/web/server.d.ts +4 -3
- package/dist/clients/web/server.js +138 -31
- package/dist/clients/web/source-cache.d.ts +10 -0
- package/dist/clients/web/source-cache.js +57 -0
- package/dist/clients/web/web-cmd.js +28 -9
- package/dist/commands/__tests__/human.test.js +30 -28
- package/dist/commands/canvas-history/search.js +1 -1
- package/dist/commands/canvas-history.js +5 -8
- package/dist/commands/canvas-issue.d.ts +2 -0
- package/dist/commands/canvas-issue.js +148 -0
- package/dist/commands/canvas-prune.js +19 -0
- package/dist/commands/canvas-rebuild-index.d.ts +2 -0
- package/dist/commands/canvas-rebuild-index.js +57 -0
- package/dist/commands/canvas-snapshot.d.ts +2 -0
- package/dist/commands/canvas-snapshot.js +48 -0
- package/dist/commands/canvas-tmux-spread.d.ts +2 -0
- package/dist/commands/canvas-tmux-spread.js +188 -0
- package/dist/commands/canvas.d.ts +1 -0
- package/dist/commands/canvas.js +16 -1
- package/dist/commands/chord.js +143 -48
- package/dist/commands/daemon.js +3 -3
- package/dist/commands/human/prompts.d.ts +0 -1
- package/dist/commands/human/prompts.js +39 -54
- package/dist/commands/human/queue.d.ts +12 -1
- package/dist/commands/human/queue.js +468 -73
- package/dist/commands/human/shared.d.ts +3 -4
- package/dist/commands/human/shared.js +3 -3
- package/dist/commands/human.js +11 -10
- package/dist/commands/memory/find.js +3 -2
- package/dist/commands/memory/list.js +4 -3
- package/dist/commands/memory/read.js +3 -3
- package/dist/commands/memory/shared.d.ts +1 -4
- package/dist/commands/memory/shared.js +6 -9
- package/dist/commands/memory/write.js +3 -3
- package/dist/commands/memory.js +4 -7
- package/dist/commands/node-context.d.ts +2 -0
- package/dist/commands/node-context.js +172 -0
- package/dist/commands/node-snapshot.d.ts +2 -0
- package/dist/commands/node-snapshot.js +123 -0
- package/dist/commands/node.js +228 -52
- package/dist/commands/pkg/plugin-inspect.js +6 -6
- package/dist/commands/pkg/plugin-manage.js +1 -1
- package/dist/commands/pkg/plugin.js +2 -2
- package/dist/commands/pkg.js +2 -2
- package/dist/commands/push.d.ts +2 -0
- package/dist/commands/push.js +79 -11
- package/dist/commands/revive.js +74 -1
- package/dist/commands/search/answer.d.ts +1 -0
- package/dist/commands/search/answer.js +50 -0
- package/dist/commands/search/contents.d.ts +1 -0
- package/dist/commands/search/contents.js +96 -0
- package/dist/commands/search/exa.d.ts +53 -0
- package/dist/commands/search/exa.js +155 -0
- package/dist/commands/search/puremd.d.ts +11 -0
- package/dist/commands/search/puremd.js +53 -0
- package/dist/commands/search/web.d.ts +1 -0
- package/dist/commands/search/web.js +65 -0
- package/dist/commands/search.d.ts +2 -0
- package/dist/commands/search.js +24 -0
- package/dist/commands/sys/__tests__/sync-import.test.d.ts +1 -0
- package/dist/commands/sys/__tests__/sync-import.test.js +72 -0
- package/dist/commands/sys/config.js +59 -10
- package/dist/commands/sys/doctor.js +56 -4
- package/dist/commands/sys/prompt-review.d.ts +1 -0
- package/dist/commands/sys/prompt-review.js +178 -0
- package/dist/commands/sys/promptstudio.d.ts +2 -0
- package/dist/commands/sys/promptstudio.js +65 -0
- package/dist/commands/sys/settings.d.ts +2 -0
- package/dist/commands/sys/settings.js +16 -0
- package/dist/commands/sys/sync.js +311 -159
- package/dist/commands/sys/sysprompt.d.ts +1 -0
- package/dist/commands/sys/sysprompt.js +86 -0
- package/dist/commands/sys.js +9 -5
- package/dist/commands/view-new.js +2 -2
- package/dist/core/__tests__/artifact-paths.test.d.ts +1 -0
- package/dist/core/__tests__/artifact-paths.test.js +44 -0
- package/dist/core/__tests__/broker-preflight.test.d.ts +1 -0
- package/dist/core/__tests__/broker-preflight.test.js +85 -0
- package/dist/core/__tests__/broker-sdk-wiring.test.js +15 -0
- package/dist/core/__tests__/canvas.test.js +37 -1
- package/dist/core/__tests__/chat-view-reconnect.test.d.ts +1 -0
- package/dist/core/__tests__/chat-view-reconnect.test.js +70 -0
- package/dist/core/__tests__/child-death-wake.test.js +11 -2
- package/dist/core/__tests__/close.test.js +39 -1
- package/dist/core/__tests__/connection-reconnect-resume.test.d.ts +1 -0
- package/dist/core/__tests__/connection-reconnect-resume.test.js +37 -0
- package/dist/core/__tests__/context-intro.test.js +48 -14
- package/dist/core/__tests__/daemon-boot.test.js +182 -9
- package/dist/core/__tests__/editor-label.test.d.ts +1 -0
- package/dist/core/__tests__/editor-label.test.js +26 -0
- package/dist/core/__tests__/fault-marker.test.d.ts +1 -0
- package/dist/core/__tests__/fault-marker.test.js +112 -0
- package/dist/core/__tests__/fault-retry-rewind.test.d.ts +1 -0
- package/dist/core/__tests__/fault-retry-rewind.test.js +123 -0
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +30 -4
- package/dist/core/__tests__/fixtures/fake-engine.js +156 -17
- package/dist/core/__tests__/fixtures/fake-pi-host.js +10 -1
- package/dist/core/__tests__/full/human-new-window-regression.test.js +1 -1
- package/dist/core/__tests__/helpers/harness.d.ts +1 -1
- package/dist/core/__tests__/helpers/harness.js +9 -3
- package/dist/core/__tests__/human-stranded-deliver.test.js +38 -1
- package/dist/core/__tests__/human-surface-target.test.js +1 -1
- package/dist/core/__tests__/kickoff.test.js +18 -19
- package/dist/core/__tests__/memory-resolver.test.js +12 -1
- package/dist/core/__tests__/migration.test.js +49 -14
- package/dist/core/__tests__/model-ladders.test.d.ts +1 -0
- package/dist/core/__tests__/model-ladders.test.js +160 -0
- package/dist/core/__tests__/node-env.test.d.ts +1 -0
- package/dist/core/__tests__/node-env.test.js +26 -0
- package/dist/core/__tests__/push-final-guard.test.js +7 -1
- package/dist/core/__tests__/relaunch-root.test.js +9 -9
- package/dist/core/__tests__/revive.test.js +36 -6
- package/dist/core/__tests__/spawn-root.test.js +24 -1
- package/dist/core/__tests__/stop-guard.test.js +10 -0
- package/dist/core/__tests__/stranded-relaunch.test.d.ts +1 -0
- package/dist/core/__tests__/stranded-relaunch.test.js +72 -0
- package/dist/core/__tests__/tmux-surface.test.js +5 -1
- package/dist/core/__tests__/unknown-path.test.js +19 -19
- package/dist/core/__tests__/yield-ensures-daemon.test.d.ts +1 -0
- package/dist/core/__tests__/yield-ensures-daemon.test.js +54 -0
- package/dist/core/artifact.d.ts +2 -33
- package/dist/core/artifact.js +27 -87
- package/dist/core/bootstrap.js +2 -0
- package/dist/core/canvas/browse/__tests__/model.test.js +35 -1
- package/dist/core/canvas/browse/app.js +87 -17
- package/dist/core/canvas/browse/model.d.ts +10 -1
- package/dist/core/canvas/browse/model.js +37 -1
- package/dist/core/canvas/browse/render.js +35 -33
- package/dist/core/canvas/canvas.d.ts +7 -0
- package/dist/core/canvas/canvas.js +54 -5
- package/dist/core/canvas/db.js +35 -8
- package/dist/core/canvas/labels.d.ts +6 -8
- package/dist/core/canvas/labels.js +8 -11
- package/dist/core/canvas/nav-model.d.ts +5 -4
- package/dist/core/canvas/nav-model.js +31 -17
- package/dist/core/canvas/paths.d.ts +18 -1
- package/dist/core/canvas/paths.js +37 -2
- package/dist/core/canvas/render.d.ts +25 -0
- package/dist/core/canvas/render.js +96 -13
- package/dist/core/canvas/status-glyph.d.ts +35 -0
- package/dist/core/canvas/status-glyph.js +104 -0
- package/dist/core/canvas/types.d.ts +2 -2
- package/dist/core/config.js +114 -16
- package/dist/core/fault-classifier.d.ts +41 -0
- package/dist/core/fault-classifier.js +110 -0
- package/dist/core/feed/__tests__/empty-node-guard.test.d.ts +1 -0
- package/dist/core/feed/__tests__/empty-node-guard.test.js +45 -0
- package/dist/core/feed/feed.js +8 -0
- package/dist/core/feed/inbox.d.ts +15 -0
- package/dist/core/feed/inbox.js +40 -14
- package/dist/core/frontmatter.d.ts +1 -11
- package/dist/core/frontmatter.js +1 -55
- package/dist/core/hearth/config.d.ts +2 -0
- package/dist/core/hearth/config.js +75 -0
- package/dist/core/hearth/guest-env.d.ts +2 -0
- package/dist/core/hearth/guest-env.js +11 -0
- package/dist/core/hearth/index.d.ts +5 -0
- package/dist/core/hearth/index.js +5 -0
- package/dist/core/hearth/provider.d.ts +21 -0
- package/dist/core/hearth/provider.js +10 -0
- package/dist/core/hearth/providers/blaxel-bootstrap.d.ts +10 -0
- package/dist/core/hearth/providers/blaxel-bootstrap.js +39 -0
- package/dist/core/hearth/providers/blaxel-home.d.ts +11 -0
- package/dist/core/hearth/providers/blaxel-home.js +126 -0
- package/dist/core/hearth/providers/blaxel.d.ts +26 -0
- package/dist/core/hearth/providers/blaxel.js +208 -0
- package/dist/core/hearth/providers/types.d.ts +72 -0
- package/dist/core/hearth/providers/types.js +1 -0
- package/dist/core/hearth/registry.d.ts +15 -0
- package/dist/core/hearth/registry.js +179 -0
- package/dist/core/hearth/types.d.ts +121 -0
- package/dist/core/hearth/types.js +1 -0
- package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.d.ts +1 -0
- package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.js +79 -0
- package/dist/core/{skill-sync → host-exports}/builtins.d.ts +21 -13
- package/dist/core/host-exports/builtins.js +68 -0
- package/dist/core/{skill-sync → host-exports}/export.d.ts +9 -6
- package/dist/core/{skill-sync → host-exports}/export.js +37 -14
- package/dist/core/io.js +1 -1
- package/dist/core/log.d.ts +9 -0
- package/dist/core/log.js +113 -0
- package/dist/core/memory-resolver.d.ts +8 -8
- package/dist/core/memory-resolver.js +15 -28
- package/dist/core/personas/index.d.ts +4 -4
- package/dist/core/personas/index.js +2 -2
- package/dist/core/personas/loader.d.ts +51 -0
- package/dist/core/personas/loader.js +54 -50
- package/dist/core/personas/resolve.d.ts +43 -27
- package/dist/core/personas/resolve.js +336 -94
- package/dist/core/runtime/auth-reload.d.ts +7 -0
- package/dist/core/runtime/auth-reload.js +69 -0
- package/dist/core/runtime/bearings.d.ts +35 -15
- package/dist/core/runtime/bearings.js +305 -44
- package/dist/core/runtime/branded-host.d.ts +4 -2
- package/dist/core/runtime/branded-host.js +66 -4
- package/dist/core/runtime/broker-protocol.d.ts +38 -3
- package/dist/core/runtime/broker.js +343 -18
- package/dist/core/runtime/close.js +37 -29
- package/dist/core/runtime/connectivity.d.ts +12 -0
- package/dist/core/runtime/connectivity.js +73 -0
- package/dist/core/runtime/fault-recovery-nudge.d.ts +2 -0
- package/dist/core/runtime/fault-recovery-nudge.js +2 -0
- package/dist/core/runtime/fault-recovery.d.ts +23 -0
- package/dist/core/runtime/fault-recovery.js +74 -0
- package/dist/core/runtime/fault.d.ts +25 -0
- package/dist/core/runtime/fault.js +176 -0
- package/dist/core/runtime/front-door.d.ts +1 -1
- package/dist/core/runtime/front-door.js +2 -2
- package/dist/core/runtime/host.d.ts +10 -0
- package/dist/core/runtime/host.js +71 -9
- package/dist/core/runtime/kickoff.js +31 -45
- package/dist/core/runtime/launch.d.ts +32 -18
- package/dist/core/runtime/launch.js +148 -43
- package/dist/core/runtime/model-swap.d.ts +18 -0
- package/dist/core/runtime/model-swap.js +95 -0
- package/dist/core/runtime/naming.d.ts +7 -0
- package/dist/core/runtime/naming.js +61 -9
- package/dist/core/runtime/nodes.js +6 -1
- package/dist/core/runtime/persona.js +16 -17
- package/dist/core/runtime/placement.d.ts +36 -31
- package/dist/core/runtime/placement.js +149 -64
- package/dist/core/runtime/promote.d.ts +2 -0
- package/dist/core/runtime/promote.js +23 -3
- package/dist/core/runtime/recycle.js +6 -4
- package/dist/core/runtime/reset.d.ts +5 -2
- package/dist/core/runtime/reset.js +2 -2
- package/dist/core/runtime/revive.d.ts +4 -0
- package/dist/core/runtime/revive.js +27 -9
- package/dist/core/runtime/roadmap.d.ts +1 -1
- package/dist/core/runtime/roadmap.js +1 -1
- package/dist/core/runtime/spawn.d.ts +2 -2
- package/dist/core/runtime/spawn.js +30 -6
- package/dist/core/runtime/stop-guard.js +6 -1
- package/dist/core/runtime/tmux-chrome.d.ts +1 -1
- package/dist/core/runtime/tmux-chrome.js +1 -1
- package/dist/core/runtime/tmux.d.ts +29 -6
- package/dist/core/runtime/tmux.js +134 -80
- package/dist/core/runtime/view-socket-client.d.ts +46 -0
- package/dist/core/runtime/view-socket-client.js +203 -0
- package/dist/core/substrate/index.d.ts +1 -1
- package/dist/core/substrate/index.js +1 -1
- package/dist/core/substrate/on-read.js +16 -4
- package/dist/core/substrate/render.d.ts +10 -13
- package/dist/core/substrate/render.js +56 -51
- package/dist/core/tui/host.js +83 -18
- package/dist/core/view/__tests__/transport-cache.test.d.ts +1 -0
- package/dist/core/view/__tests__/transport-cache.test.js +62 -0
- package/dist/core/view/contract.d.ts +20 -0
- package/dist/core/view/stream-local.d.ts +3 -0
- package/dist/core/view/stream-local.js +184 -0
- package/dist/core/view/transport-cache.d.ts +8 -0
- package/dist/core/view/transport-cache.js +38 -0
- package/dist/core/view/transport-local.js +4 -0
- package/dist/core/view/transport.d.ts +7 -1
- package/dist/daemon/crtrd.d.ts +3 -19
- package/dist/daemon/crtrd.js +139 -178
- package/dist/daemon/manage.d.ts +18 -1
- package/dist/daemon/manage.js +54 -9
- package/dist/hearth/wake-proxy/__tests__/anthropic-oauth.test.d.ts +1 -0
- package/dist/hearth/wake-proxy/__tests__/anthropic-oauth.test.js +289 -0
- package/dist/hearth/wake-proxy/__tests__/config-timeout.test.d.ts +1 -0
- package/dist/hearth/wake-proxy/__tests__/config-timeout.test.js +34 -0
- package/dist/hearth/wake-proxy/__tests__/guest-source.test.d.ts +1 -0
- package/dist/hearth/wake-proxy/__tests__/guest-source.test.js +203 -0
- package/dist/hearth/wake-proxy/__tests__/hardening.test.d.ts +1 -0
- package/dist/hearth/wake-proxy/__tests__/hardening.test.js +59 -0
- package/dist/hearth/wake-proxy/__tests__/hearth-status-route.test.d.ts +1 -0
- package/dist/hearth/wake-proxy/__tests__/hearth-status-route.test.js +372 -0
- package/dist/hearth/wake-proxy/__tests__/http-running-route-fast-path.test.d.ts +1 -0
- package/dist/hearth/wake-proxy/__tests__/http-running-route-fast-path.test.js +258 -0
- package/dist/hearth/wake-proxy/__tests__/model-auth-routes.test.d.ts +1 -0
- package/dist/hearth/wake-proxy/__tests__/model-auth-routes.test.js +437 -0
- package/dist/hearth/wake-proxy/__tests__/source-bridge-gate.test.d.ts +1 -0
- package/dist/hearth/wake-proxy/__tests__/source-bridge-gate.test.js +455 -0
- package/dist/hearth/wake-proxy/__tests__/static-asset-allowlist.test.d.ts +1 -0
- package/dist/hearth/wake-proxy/__tests__/static-asset-allowlist.test.js +15 -0
- package/dist/hearth/wake-proxy/__tests__/warm-path-concurrency.test.d.ts +1 -0
- package/dist/hearth/wake-proxy/__tests__/warm-path-concurrency.test.js +141 -0
- package/dist/hearth/wake-proxy/__tests__/ws-teardown-accounting.test.d.ts +1 -0
- package/dist/hearth/wake-proxy/__tests__/ws-teardown-accounting.test.js +143 -0
- package/dist/hearth/wake-proxy/anthropic-oauth.d.ts +58 -0
- package/dist/hearth/wake-proxy/anthropic-oauth.js +189 -0
- package/dist/hearth/wake-proxy/auth.d.ts +22 -0
- package/dist/hearth/wake-proxy/auth.js +128 -0
- package/dist/hearth/wake-proxy/config.d.ts +2 -0
- package/dist/hearth/wake-proxy/config.js +151 -0
- package/dist/hearth/wake-proxy/guest-source.d.ts +14 -0
- package/dist/hearth/wake-proxy/guest-source.js +130 -0
- package/dist/hearth/wake-proxy/hearth-status.d.ts +44 -0
- package/dist/hearth/wake-proxy/hearth-status.js +267 -0
- package/dist/hearth/wake-proxy/home.d.ts +67 -0
- package/dist/hearth/wake-proxy/home.js +297 -0
- package/dist/hearth/wake-proxy/main.d.ts +1 -0
- package/dist/hearth/wake-proxy/main.js +134 -0
- package/dist/hearth/wake-proxy/model-auth.d.ts +13 -0
- package/dist/hearth/wake-proxy/model-auth.js +345 -0
- package/dist/hearth/wake-proxy/proxy.d.ts +35 -0
- package/dist/hearth/wake-proxy/proxy.js +716 -0
- package/dist/hearth/wake-proxy/public-source-gate.d.ts +9 -0
- package/dist/hearth/wake-proxy/public-source-gate.js +409 -0
- package/dist/hearth/wake-proxy/redact.d.ts +1 -0
- package/dist/hearth/wake-proxy/redact.js +17 -0
- package/dist/hearth/wake-proxy/server.d.ts +11 -0
- package/dist/hearth/wake-proxy/server.js +142 -0
- package/dist/hearth/wake-proxy/state.d.ts +18 -0
- package/dist/hearth/wake-proxy/state.js +342 -0
- package/dist/hearth/wake-proxy/types.d.ts +76 -0
- package/dist/hearth/wake-proxy/types.js +1 -0
- package/dist/index.js +3 -2
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +6 -5
- package/dist/pi-extensions/canvas-context-intro.js +7 -7
- package/dist/pi-extensions/canvas-doc-substrate.js +19 -22
- package/dist/pi-extensions/canvas-nav.js +15 -8
- package/dist/pi-extensions/canvas-stophook.d.ts +1 -1
- package/dist/pi-extensions/canvas-stophook.js +78 -11
- package/dist/types.d.ts +39 -20
- package/dist/types.js +38 -13
- package/dist/web/runtime.js +141 -42
- package/dist/web/transport-http.js +7 -5
- package/dist/web/transport-stream.d.ts +3 -0
- package/dist/web/transport-stream.js +204 -0
- package/dist/web-client/assets/fragment-mono-latin-400-normal-BYwT3kSJ.woff +0 -0
- package/dist/web-client/assets/fragment-mono-latin-400-normal-yxdJ5AmL.woff2 +0 -0
- package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-BbKYyvR9.woff2 +0 -0
- package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-CT4YFKeK.woff +0 -0
- package/dist/web-client/assets/fraunces-latin-ext-wght-normal-Ca2vKHc0.woff2 +0 -0
- package/dist/web-client/assets/fraunces-latin-wght-normal-ukD16Tqj.woff2 +0 -0
- package/dist/web-client/assets/fraunces-vietnamese-wght-normal-CnvboYUG.woff2 +0 -0
- package/dist/web-client/assets/index-BZUxTkv5.css +2 -0
- package/dist/web-client/assets/index-D36PNBj4.js +80 -0
- package/dist/web-client/assets/instrument-sans-latin-ext-wght-normal-B5bTHO_g.woff2 +0 -0
- package/dist/web-client/assets/instrument-sans-latin-wght-normal-BbzFLZTg.woff2 +0 -0
- package/dist/web-client/assets/martian-mono-cyrillic-wght-normal-B84CD5C_.woff2 +0 -0
- package/dist/web-client/assets/martian-mono-latin-ext-wght-normal-DlL6xMw5.woff2 +0 -0
- package/dist/web-client/assets/martian-mono-latin-wght-normal-5W32yIyr.woff2 +0 -0
- package/dist/web-client/index.html +3 -2
- package/package.json +32 -10
- package/dist/core/__tests__/error-stall-recycle.test.js +0 -141
- package/dist/core/skill-sync/__tests__/dry-run-wrote-count.test.js +0 -57
- package/dist/core/skill-sync/builtins.js +0 -112
- package/dist/core/skill-sync/claude-plugins.d.ts +0 -23
- package/dist/core/skill-sync/claude-plugins.js +0 -71
- package/dist/core/skill-sync/engine.d.ts +0 -42
- package/dist/core/skill-sync/engine.js +0 -633
- package/dist/core/skill-sync/manifest.d.ts +0 -64
- package/dist/core/skill-sync/manifest.js +0 -181
- package/dist/core/skill-sync/profile.d.ts +0 -76
- package/dist/core/skill-sync/profile.js +0 -173
- package/dist/core/skill-sync/snapshot.d.ts +0 -57
- package/dist/core/skill-sync/snapshot.js +0 -120
- package/dist/pi-extensions/canvas-commands.d.ts +0 -37
- package/dist/pi-extensions/canvas-commands.js +0 -113
- package/dist/pi-extensions/canvas-resume.d.ts +0 -21
- package/dist/pi-extensions/canvas-resume.js +0 -83
- package/dist/pi-extensions/canvas-view.d.ts +0 -21
- package/dist/pi-extensions/canvas-view.js +0 -76
- package/dist/web-client/assets/index-BUvQb4hR.css +0 -2
- package/dist/web-client/assets/index-ClLQXYAE.js +0 -10
- /package/dist/{core/__tests__/error-stall-recycle.test.d.ts → clients/attach/__tests__/autocomplete-and-bash-mode.test.d.ts} +0 -0
- /package/dist/{core/skill-sync/__tests__/dry-run-wrote-count.test.d.ts → clients/attach/__tests__/bash-bang-routing.test.d.ts} +0 -0
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
// bearings.ts — the boot-intro prose (the <crtr-
|
|
2
|
-
// <
|
|
3
|
-
// never drift:
|
|
1
|
+
// bearings.ts — the boot-intro prose (the <crtr-bearings> orientation block +
|
|
2
|
+
// the <memory kind="knowledge"> catalog that rides beside it), shared by the
|
|
3
|
+
// paths that deliver it so they can never drift:
|
|
4
4
|
//
|
|
5
5
|
// • the context-intro pi-extension injects buildContextBearings() as the
|
|
6
|
-
// node's first session message in every brand-new chat.
|
|
7
|
-
//
|
|
6
|
+
// node's first session message in every brand-new chat. The <crtr-bearings>
|
|
7
|
+
// block opens with the identity assertion (buildIdentityAssertion) that
|
|
8
|
+
// names the node (id, kind, mode), then a `## Your place in the canvas`
|
|
9
|
+
// mini-map (ancestry trunk up + immediate children with statuses, via
|
|
10
|
+
// buildGraphMap) and a `## Your context directory` note; identity leads,
|
|
8
11
|
// ONLY for a fork, disowns the source's copied first-person narrative as
|
|
9
12
|
// inherited context — the fix for the `--fork-from` bug where a fork copies
|
|
10
13
|
// the source's whole conversation and then impersonates it. A non-fork
|
|
11
14
|
// node's bearings are its FIRST entry, so there is nothing earlier to
|
|
12
|
-
// disown; it gets only the declarative identity line
|
|
15
|
+
// disown; it gets only the declarative identity line. The message also
|
|
16
|
+
// carries the <project_context> block (buildProjectContextBlock) — the
|
|
17
|
+
// AGENTS.md/CLAUDE.md project instructions, moved OUT of the system prompt
|
|
18
|
+
// (pi's copy is suppressed via noContextFiles in broker.ts) so they ride
|
|
19
|
+
// this user message instead;
|
|
13
20
|
// • promote.ts folds orchestratorContextNote() into the promotion guidance
|
|
14
21
|
// dump, so a node that becomes an orchestrator MID-LIFE gets the
|
|
15
22
|
// orchestrator framing it never received at spawn — it spawned as a base
|
|
@@ -19,21 +26,186 @@
|
|
|
19
26
|
// one place other nodes on the canvas can read from, so it is for documents
|
|
20
27
|
// worth a shared reference, NOT a task tracker, and NOT a "future memory-wiped
|
|
21
28
|
// you" stash (a terminal worker has no future cycle — that framing only makes
|
|
22
|
-
// sense once a node is a resident orchestrator). The `<knowledge>`
|
|
23
|
-
// (substrate knowledge docs + node-local docs) rides
|
|
29
|
+
// sense once a node is a resident orchestrator). The `<memory kind="knowledge">`
|
|
30
|
+
// block (substrate knowledge docs + node-local docs) rides as a SIBLING of
|
|
31
|
+
// <crtr-bearings> — never nested under the context dir, which would imply the
|
|
32
|
+
// catalog belongs to that one directory rather than spanning all memory scopes.
|
|
24
33
|
//
|
|
25
34
|
// Orchestrator addendum (gated on orchestrator MODE): the dir ALSO survives
|
|
26
35
|
// refresh cycles, so it is where a future cycle of the orchestrator resumes.
|
|
27
36
|
// This across-cycles note is the ONE thing a terminal worker's bearings drop.
|
|
28
|
-
import { contextDir, getNode, fullName } from '../canvas/index.js';
|
|
37
|
+
import { contextDir, getNode, fullName, subscriptionsOf, } from '../canvas/index.js';
|
|
38
|
+
import { execSync } from 'node:child_process';
|
|
39
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
40
|
+
import { homedir } from 'node:os';
|
|
41
|
+
import { join, resolve } from 'node:path';
|
|
29
42
|
import { cadenceDisplay } from '../wake.js';
|
|
30
43
|
import { renderKnowledgeBlock } from '../substrate/index.js';
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// Project context (<project_context>) — the AGENTS.md/CLAUDE.md files pi would
|
|
46
|
+
// otherwise inject into its SYSTEM PROMPT, rendered here so they ride the
|
|
47
|
+
// first-message bearings instead (pi's copy is suppressed via
|
|
48
|
+
// resourceLoaderOptions.noContextFiles in broker.ts). We re-implement pi's
|
|
49
|
+
// loadProjectContextFiles + getAgentDir (resource-loader.js / config.js) rather
|
|
50
|
+
// than IMPORT pi: bearings.ts is statically imported by the thin daemon (crtrd,
|
|
51
|
+
// for wakeOriginFrom), so a static @earendil-works import would pull the whole
|
|
52
|
+
// pi engine into the supervisor. The discovery is a stable convention + pure fs.
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
/** pi's getAgentDir(): the global agent config dir holding a user-wide context
|
|
55
|
+
* file. Honors PI_CODING_AGENT_DIR (tilde-expanded), else ~/.pi/agent (pi's
|
|
56
|
+
* piConfig.configDir is ".pi"). */
|
|
57
|
+
function piAgentDir() {
|
|
58
|
+
const env = process.env['PI_CODING_AGENT_DIR'];
|
|
59
|
+
if (env !== undefined && env !== '') {
|
|
60
|
+
return env.startsWith('~') ? join(homedir(), env.slice(1)) : env;
|
|
61
|
+
}
|
|
62
|
+
return join(homedir(), '.pi', 'agent');
|
|
63
|
+
}
|
|
64
|
+
/** Per-dir context-file candidates, in pi's precedence order (first match wins). */
|
|
65
|
+
const CONTEXT_FILE_CANDIDATES = ['AGENTS.md', 'AGENTS.MD', 'CLAUDE.md', 'CLAUDE.MD'];
|
|
66
|
+
function loadContextFileFromDir(dir) {
|
|
67
|
+
for (const name of CONTEXT_FILE_CANDIDATES) {
|
|
68
|
+
const p = join(dir, name);
|
|
69
|
+
if (existsSync(p)) {
|
|
70
|
+
try {
|
|
71
|
+
return { path: p, content: readFileSync(p, 'utf8') };
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Unreadable candidate — skip, mirroring pi (best-effort).
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
/** Mirror of pi's loadProjectContextFiles: the global agent-dir file first, then
|
|
81
|
+
* every AGENTS.md/CLAUDE.md up the cwd's ancestry, ordered root→cwd (so the
|
|
82
|
+
* most-specific project file reads last). Deduped by absolute path. */
|
|
83
|
+
function loadProjectContextFiles(cwd) {
|
|
84
|
+
const files = [];
|
|
85
|
+
const seen = new Set();
|
|
86
|
+
const global = loadContextFileFromDir(piAgentDir());
|
|
87
|
+
if (global !== null) {
|
|
88
|
+
files.push(global);
|
|
89
|
+
seen.add(global.path);
|
|
90
|
+
}
|
|
91
|
+
const ancestors = [];
|
|
92
|
+
let dir = resolve(cwd);
|
|
93
|
+
const root = resolve('/');
|
|
94
|
+
for (;;) {
|
|
95
|
+
const f = loadContextFileFromDir(dir);
|
|
96
|
+
if (f !== null && !seen.has(f.path)) {
|
|
97
|
+
ancestors.unshift(f);
|
|
98
|
+
seen.add(f.path);
|
|
99
|
+
}
|
|
100
|
+
if (dir === root)
|
|
101
|
+
break;
|
|
102
|
+
const parent = resolve(dir, '..');
|
|
103
|
+
if (parent === dir)
|
|
104
|
+
break;
|
|
105
|
+
dir = parent;
|
|
106
|
+
}
|
|
107
|
+
files.push(...ancestors);
|
|
108
|
+
return files;
|
|
109
|
+
}
|
|
110
|
+
function escapeAttribute(value) {
|
|
111
|
+
return value.replaceAll('&', '&').replaceAll('"', '"').replaceAll('<', '<').replaceAll('>', '>');
|
|
112
|
+
}
|
|
113
|
+
function directoryListingLines(cwd) {
|
|
114
|
+
try {
|
|
115
|
+
const entries = readdirSync(cwd, { withFileTypes: true });
|
|
116
|
+
const sorted = entries.sort((a, b) => {
|
|
117
|
+
if (a.isDirectory() !== b.isDirectory())
|
|
118
|
+
return a.isDirectory() ? -1 : 1;
|
|
119
|
+
return a.name.localeCompare(b.name);
|
|
120
|
+
});
|
|
121
|
+
const shown = sorted.slice(0, 50).map((entry) => `${entry.name}${entry.isDirectory() ? '/' : ''}`);
|
|
122
|
+
const hidden = sorted.length - shown.length;
|
|
123
|
+
return hidden > 0 ? [...shown, `[+${hidden} more]`] : shown;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return ['Directory listing: unavailable (cwd missing or unreadable).'];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function gitSnapshot(cwd) {
|
|
130
|
+
try {
|
|
131
|
+
execSync('git rev-parse --is-inside-work-tree', { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return { lines: ['Git: not a git repository.'] };
|
|
135
|
+
}
|
|
136
|
+
const branch = runGit(cwd, 'git branch --show-current') || runGit(cwd, 'git rev-parse --abbrev-ref HEAD') || 'HEAD';
|
|
137
|
+
const sha = runGit(cwd, 'git rev-parse --short HEAD') || 'unknown';
|
|
138
|
+
const statusCount = runGit(cwd, 'git status --porcelain')
|
|
139
|
+
.split('\n')
|
|
140
|
+
.filter((line) => line !== '').length;
|
|
141
|
+
const worktreeLines = runGit(cwd, 'git worktree list --porcelain').split('\n');
|
|
142
|
+
const worktrees = parseWorktrees(worktreeLines);
|
|
143
|
+
const dirty = statusCount === 0 ? 'clean' : `${statusCount} uncommitted change${statusCount === 1 ? '' : 's'}`;
|
|
144
|
+
const summary = `Git: ${branch} @ ${sha}; ${dirty}; ${worktrees.length} worktree${worktrees.length === 1 ? '' : 's'}.`;
|
|
145
|
+
const worktreeSummary = worktrees.length === 0
|
|
146
|
+
? 'Worktrees: none.'
|
|
147
|
+
: `Worktrees: ${worktrees.map((w) => `${w.path} (${w.branch})`).join(', ')}`;
|
|
148
|
+
return { lines: [summary, worktreeSummary] };
|
|
149
|
+
}
|
|
150
|
+
function runGit(cwd, command) {
|
|
151
|
+
try {
|
|
152
|
+
return execSync(command, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return '';
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function parseWorktrees(lines) {
|
|
159
|
+
const worktrees = [];
|
|
160
|
+
let cur = {};
|
|
161
|
+
for (const line of lines) {
|
|
162
|
+
if (line.startsWith('worktree ')) {
|
|
163
|
+
if (cur.path !== undefined) {
|
|
164
|
+
worktrees.push({ path: cur.path, branch: cur.branch ?? 'detached HEAD' });
|
|
165
|
+
}
|
|
166
|
+
cur = { path: line.slice('worktree '.length) };
|
|
167
|
+
}
|
|
168
|
+
else if (line.startsWith('branch ')) {
|
|
169
|
+
cur.branch = line.slice('branch '.length).replace(/^refs\/heads\//, '');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (cur.path !== undefined) {
|
|
173
|
+
worktrees.push({ path: cur.path, branch: cur.branch ?? 'detached HEAD' });
|
|
174
|
+
}
|
|
175
|
+
return worktrees;
|
|
176
|
+
}
|
|
177
|
+
/** The `<project_context>` block for the files discovered from `cwd`, plus the
|
|
178
|
+
* cwd/git environment snapshot that now rides at the end of the wrapper.
|
|
179
|
+
* Always emits the wrapper because the environment snapshot is always present
|
|
180
|
+
* even when no project instructions exist. Exported for testing. */
|
|
181
|
+
export function buildProjectContextBlock(cwd) {
|
|
182
|
+
const files = loadProjectContextFiles(cwd);
|
|
183
|
+
const envLines = directoryListingLines(cwd);
|
|
184
|
+
const git = gitSnapshot(cwd);
|
|
185
|
+
let out = '<project_context>\n\nProject-specific instructions and guidelines:\n\n';
|
|
186
|
+
for (const { path, content } of files) {
|
|
187
|
+
out += `<project_instructions path="${path}">\n${content}\n</project_instructions>\n\n`;
|
|
188
|
+
}
|
|
189
|
+
out += `<environment cwd="${escapeAttribute(cwd)}">\n`;
|
|
190
|
+
out += `Directory:\n${envLines.map((line) => ` ${line}`).join('\n')}\n`;
|
|
191
|
+
out += `${git.lines.map((line) => `${line}`).join('\n')}\n`;
|
|
192
|
+
out += '</environment>\n</project_context>';
|
|
193
|
+
return out;
|
|
194
|
+
}
|
|
195
|
+
/** The context-directory note — names the path INLINE (no XML attribute, so it
|
|
196
|
+
* never scopes a sibling block) and frames the dir as durable, shared scratch.
|
|
197
|
+
* Present for every node, rendered as the `## Your context directory`
|
|
198
|
+
* subsection of <crtr-bearings>. */
|
|
199
|
+
export function contextDirNote(nodeId) {
|
|
200
|
+
return (`Your context directory is \`${contextDir(nodeId)}\` (also in the env as \`$CRTR_CONTEXT_DIR\`) — ` +
|
|
201
|
+
'durable scratch space on disk, and the one place the other nodes on the canvas can read from. ' +
|
|
202
|
+
'Put documents here that you want to share by reference instead of re-explaining them in a ' +
|
|
203
|
+
'prompt: specs, designs, findings, notes worth pointing a sibling, child, or parent at. It is a ' +
|
|
204
|
+
'shared document store, not a task tracker. **Address it by absolute path** — write artifacts as ' +
|
|
205
|
+
'`$CRTR_CONTEXT_DIR/<name>.md` (or the full path above). Your working dir is the project, NOT ' +
|
|
206
|
+
'this directory, so a bare relative `context/...` lands in the repo, not here — and other nodes ' +
|
|
207
|
+
'can only read what is actually here. When you report a file, report its absolute path.');
|
|
208
|
+
}
|
|
37
209
|
/** Orchestrator-only framing: a resident orchestrator survives refresh cycles,
|
|
38
210
|
* so its context dir is also where a future cycle of itself resumes the work.
|
|
39
211
|
* Used inside the bearings block AND in the promotion guidance dump, so a
|
|
@@ -43,39 +215,121 @@ export function orchestratorContextNote(nodeId) {
|
|
|
43
215
|
`also where a future cycle of you resumes the work — keep the working notes and decisions a ` +
|
|
44
216
|
`refreshed you would need there, alongside the docs you share with the nodes you spawn.`);
|
|
45
217
|
}
|
|
218
|
+
// ---------------------------------------------------------------------------
|
|
219
|
+
// Graph mini-map — the node's place in the canvas, rendered into the identity
|
|
220
|
+
// block so a node boots oriented: who is above it (its ancestry trunk, root
|
|
221
|
+
// first) and who is directly below it (its immediate children + their statuses).
|
|
222
|
+
// Not the full subtree — just the load-bearing spine up and one level down.
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
/** Live-first sibling ordering, so running children surface above finished ones. */
|
|
225
|
+
function statusRank(status) {
|
|
226
|
+
switch (status) {
|
|
227
|
+
case 'active': return 0;
|
|
228
|
+
case 'idle': return 1;
|
|
229
|
+
case 'done': return 2;
|
|
230
|
+
case 'canceled': return 3;
|
|
231
|
+
case 'dead': return 4;
|
|
232
|
+
default: return 5;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/** One relative's line in the map: `<id> — <kind> · <status>`, plus the node's
|
|
236
|
+
* task description when it carries one (orientation: what that relative is for). */
|
|
237
|
+
function relativeLabel(meta) {
|
|
238
|
+
const desc = fullName(meta);
|
|
239
|
+
const descPart = desc !== '' && desc !== meta.kind && desc !== meta.name ? ` — ${desc}` : '';
|
|
240
|
+
return `${meta.node_id} (${meta.kind} · ${meta.status})${descPart}`;
|
|
241
|
+
}
|
|
242
|
+
/** Ancestry trunk from the root DOWN to (but excluding) `nodeId`, climbing the
|
|
243
|
+
* spine `parent` edge. Cycle-guarded. Root first. */
|
|
244
|
+
function ancestorTrunk(nodeId) {
|
|
245
|
+
const trunk = [];
|
|
246
|
+
const seen = new Set([nodeId]);
|
|
247
|
+
let cur = getNode(nodeId)?.parent ?? null;
|
|
248
|
+
while (cur !== null && cur !== '' && !seen.has(cur)) {
|
|
249
|
+
seen.add(cur);
|
|
250
|
+
const m = getNode(cur);
|
|
251
|
+
if (m === null)
|
|
252
|
+
break;
|
|
253
|
+
trunk.unshift(m);
|
|
254
|
+
cur = m.parent ?? null;
|
|
255
|
+
}
|
|
256
|
+
return trunk;
|
|
257
|
+
}
|
|
258
|
+
/** Most children listed in the mini-map before the rest collapse to `+N more`. */
|
|
259
|
+
const MAX_CHILDREN_SHOWN = 5;
|
|
260
|
+
/** The node's immediate children — the nodes it subscribes to (its reports) —
|
|
261
|
+
* with human-ask control-plane nodes dropped, sorted live-first. */
|
|
262
|
+
function childNodes(nodeId) {
|
|
263
|
+
return subscriptionsOf(nodeId)
|
|
264
|
+
.map((s) => getNode(s.node_id))
|
|
265
|
+
.filter((m) => m !== null && m.kind !== 'human')
|
|
266
|
+
.sort((a, b) => statusRank(a.status) - statusRank(b.status));
|
|
267
|
+
}
|
|
268
|
+
/** The graph mini-map: the ancestry trunk (root first), then this node marked
|
|
269
|
+
* `● you`, then its immediate children. Returns '' for a lone root with no
|
|
270
|
+
* children (nothing to map). Exported for testing. */
|
|
271
|
+
export function buildGraphMap(nodeId) {
|
|
272
|
+
const meta = getNode(nodeId);
|
|
273
|
+
if (meta === null)
|
|
274
|
+
return '';
|
|
275
|
+
const trunk = ancestorTrunk(nodeId);
|
|
276
|
+
const children = childNodes(nodeId);
|
|
277
|
+
if (trunk.length === 0 && children.length === 0)
|
|
278
|
+
return '';
|
|
279
|
+
const indent = (depth) => ' '.repeat(depth);
|
|
280
|
+
const lines = [
|
|
281
|
+
'Your place in the canvas graph (ancestry above you, your direct children below):',
|
|
282
|
+
];
|
|
283
|
+
trunk.forEach((m, i) => {
|
|
284
|
+
lines.push(`${indent(i)}${i === 0 ? '' : '└ '}${relativeLabel(m)}`);
|
|
285
|
+
});
|
|
286
|
+
const selfDepth = trunk.length;
|
|
287
|
+
lines.push(`${indent(selfDepth)}${selfDepth === 0 ? '' : '└ '}● you: ${nodeId} (${meta.kind}, ${meta.mode})`);
|
|
288
|
+
// Cap the child list so a wide fan-out can't flood the boot context. Children
|
|
289
|
+
// are sorted live-first, so the shown slice favors active nodes; the rest
|
|
290
|
+
// collapse to a `+N more` tail (active-first ordering means anything elided is
|
|
291
|
+
// the most-finished work).
|
|
292
|
+
const shown = children.slice(0, MAX_CHILDREN_SHOWN);
|
|
293
|
+
const hidden = children.length - shown.length;
|
|
294
|
+
shown.forEach((m, i) => {
|
|
295
|
+
const last = i === shown.length - 1 && hidden === 0;
|
|
296
|
+
lines.push(`${indent(selfDepth + 1)}${last ? '└ ' : '├ '}${relativeLabel(m)}`);
|
|
297
|
+
});
|
|
298
|
+
if (hidden > 0) {
|
|
299
|
+
lines.push(`${indent(selfDepth + 1)}└ +${hidden} more`);
|
|
300
|
+
}
|
|
301
|
+
return lines.join('\n');
|
|
302
|
+
}
|
|
46
303
|
/** The IDENTITY assertion that opens every boot intro — the load-bearing fix
|
|
47
304
|
* for the `--fork-from` impersonation bug. A fork copies the SOURCE node's
|
|
48
305
|
* entire first-person conversation into its own session, so without an explicit
|
|
49
306
|
* re-assertion the forked agent reads that copied narrative as its own and
|
|
50
307
|
* impersonates the source (it kept "monitoring itself" as a phantom child).
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
308
|
+
* These lines name the node unambiguously and lead the <crtr-bearings> block
|
|
309
|
+
* (no wrapper of their own — identity is the first prose the model reads). ONLY
|
|
310
|
+
* when the node IS a fork do they additionally name the source AND disown the
|
|
311
|
+
* copied first-person narrative as inherited reference material — a non-fork
|
|
312
|
+
* node's bearings are its first session entry, so there is no earlier narrative
|
|
313
|
+
* to disown (emitting a disown line there is dead weight that reads as a
|
|
314
|
+
* contradiction with no referent). Also prepended to a fork's kickoff prompt in
|
|
315
|
+
* spawn.ts. Exported for testing. */
|
|
57
316
|
export function buildIdentityAssertion(nodeId) {
|
|
58
317
|
const meta = getNode(nodeId);
|
|
59
|
-
const name = meta?.name ?? nodeId;
|
|
60
318
|
const kind = meta?.kind ?? 'general';
|
|
61
319
|
const mode = meta?.mode ?? 'base';
|
|
62
|
-
const lines = [
|
|
63
|
-
'<crtr-identity>',
|
|
64
|
-
`You are node ${nodeId} — name "${name}", kind ${kind}, mode ${mode}.`,
|
|
65
|
-
];
|
|
320
|
+
const lines = [`You are node ${nodeId} — kind ${kind}, mode ${mode}.`];
|
|
66
321
|
const forkFrom = meta?.fork_from;
|
|
67
322
|
if (forkFrom !== undefined && forkFrom !== null && forkFrom !== '') {
|
|
68
323
|
// Name the source: a known node id gets its human label; a raw path/uuid
|
|
69
324
|
// passes through as-is.
|
|
70
325
|
const src = getNode(forkFrom);
|
|
71
326
|
const sourceLabel = src !== null ? `${forkFrom} ("${fullName(src)}")` : forkFrom;
|
|
72
|
-
lines.push(`You are a FORK of ${sourceLabel}: at spawn pi COPIED that node's conversation into your ` +
|
|
327
|
+
lines.push('', `You are a FORK of ${sourceLabel}: at spawn pi COPIED that node's conversation into your ` +
|
|
73
328
|
`session as a starting point. You are NOT ${sourceLabel}. Everything earlier in this ` +
|
|
74
329
|
'conversation is THEIR first-person history — inherited reference material, not your own ' +
|
|
75
330
|
'past. Do not speak or act as them, do not continue their task as if it were yours, and do ' +
|
|
76
331
|
'not "monitor yourself" as though you were a child they spawned.');
|
|
77
332
|
}
|
|
78
|
-
lines.push('</crtr-identity>');
|
|
79
333
|
return lines.join('\n');
|
|
80
334
|
}
|
|
81
335
|
/** Build a WakeOrigin from a fired wakeup row, resolving the armer's display
|
|
@@ -141,25 +395,32 @@ export function buildWakeBearings(origin) {
|
|
|
141
395
|
}
|
|
142
396
|
return `<crtr-wake>\n${body}\n</crtr-wake>`;
|
|
143
397
|
}
|
|
144
|
-
/** The full boot intro
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
398
|
+
/** The full boot intro, three top-level sections:
|
|
399
|
+
*
|
|
400
|
+
* 1. `<crtr-bearings>` — the orienting facts about THIS node: the identity
|
|
401
|
+
* assertion (always first, so it overrides any copied-in persona), then a
|
|
402
|
+
* `## Your place in the canvas` graph map and a `## Your context directory`
|
|
403
|
+
* note. The across-cycles context-dir framing is added ONLY for an
|
|
404
|
+
* orchestrator (by mode) — the one node whose dir a future cycle resumes
|
|
405
|
+
* from.
|
|
406
|
+
* 2. `<memory kind="knowledge">` — the consultable catalog, a SIBLING of the
|
|
407
|
+
* bearings (never nested under the context dir). Dropped when empty.
|
|
408
|
+
* 3. `<project_context>` — the AGENTS.md/CLAUDE.md instructions + the cwd/git
|
|
409
|
+
* environment snapshot, moved OUT of the system prompt (pi's copy is
|
|
410
|
+
* suppressed via noContextFiles in broker.ts) so it rides this message. */
|
|
150
411
|
export function buildContextBearings(nodeId) {
|
|
151
|
-
const identity = buildIdentityAssertion(nodeId);
|
|
152
|
-
const dir = contextDir(nodeId);
|
|
153
412
|
const node = getNode(nodeId);
|
|
154
|
-
const
|
|
413
|
+
const bearings = ['<crtr-bearings>', buildIdentityAssertion(nodeId)];
|
|
414
|
+
const map = buildGraphMap(nodeId);
|
|
415
|
+
if (map !== '')
|
|
416
|
+
bearings.push('', '## Your place in the canvas', map);
|
|
417
|
+
bearings.push('', '## Your context directory', contextDirNote(nodeId));
|
|
155
418
|
// Orchestrator-only: the across-cycles framing (a terminal has no future cycle).
|
|
156
419
|
if (node?.mode === 'orchestrator')
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
//
|
|
160
|
-
// nothing is eligible.
|
|
420
|
+
bearings.push('', orchestratorContextNote(nodeId));
|
|
421
|
+
bearings.push('</crtr-bearings>');
|
|
422
|
+
// The consultable catalog rides BESIDE the bearings, not inside them.
|
|
161
423
|
const knowledge = renderKnowledgeBlock(nodeId);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return `${identity}\n<crtr-context dir="${dir}">\n${parts.join('\n')}\n</crtr-context>`;
|
|
424
|
+
const projectCtx = node?.cwd !== undefined ? buildProjectContextBlock(node.cwd) : '';
|
|
425
|
+
return [bearings.join('\n'), knowledge, projectCtx].filter((s) => s !== '').join('\n');
|
|
165
426
|
}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* to the installed node, shared across every canvas home. */
|
|
4
4
|
export declare function brandedHostDir(): string;
|
|
5
5
|
export declare function brandedHostBin(): string;
|
|
6
|
+
export declare function signBrandedHostArtifacts(binPath: string, libnodePath: string | null, sign?: (path: string) => void): void;
|
|
7
|
+
export declare function brandedHostWorks(binPath: string): boolean;
|
|
6
8
|
/** Ensure the branded host binary exists and matches the live node; return its
|
|
7
9
|
* absolute path. Idempotent and self-healing. Throws on a genuine build failure
|
|
8
10
|
* (disk full / permissions) — branding is load-bearing for FDA, so a failure is
|
|
@@ -11,6 +13,6 @@ export declare function ensureBrandedHost(): string;
|
|
|
11
13
|
/** The path the engine (broker / daemon) should be launched from. On macOS in a
|
|
12
14
|
* compiled (production) build this is the branded host; otherwise — non-darwin
|
|
13
15
|
* (TCC is macOS-only), source/tsx (dev + the test suite: never copy 70 MB into
|
|
14
|
-
* the real ~/.crouter),
|
|
15
|
-
*
|
|
16
|
+
* the real ~/.crouter), an explicit `CRTR_BRANDED_HOST=0` opt-out, or a copied
|
|
17
|
+
* host that macOS kills before it can execute JS — it is the live node. */
|
|
16
18
|
export declare function hostExecPath(): string;
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
import { copyFileSync, mkdirSync, existsSync, readFileSync, writeFileSync, chmodSync, readdirSync, renameSync, realpathSync, unlinkSync, } from 'node:fs';
|
|
25
25
|
import { homedir } from 'node:os';
|
|
26
26
|
import { dirname, join } from 'node:path';
|
|
27
|
+
import { spawnSync } from 'node:child_process';
|
|
27
28
|
import { CRTR_DIR_NAME } from '../../types.js';
|
|
28
29
|
/** The filename the FDA / TCC entry is shown under. */
|
|
29
30
|
const BRANDED_BIN_NAME = 'crouter';
|
|
@@ -71,6 +72,61 @@ function readMarker() {
|
|
|
71
72
|
return null;
|
|
72
73
|
}
|
|
73
74
|
}
|
|
75
|
+
/** Sign a copied branded-host artifact with the Apple Development identity.
|
|
76
|
+
* macOS keys FDA grants on the Mach-O cdhash, so ad-hoc signing loses grants
|
|
77
|
+
* after each rebuild. Stable signing preserves them. Non-fatal — if signing
|
|
78
|
+
* fails (no certificate, non-macOS, etc), return silently. */
|
|
79
|
+
function signBrandedHost(binPath) {
|
|
80
|
+
if (process.platform !== 'darwin')
|
|
81
|
+
return;
|
|
82
|
+
try {
|
|
83
|
+
const res = spawnSync('codesign', [
|
|
84
|
+
'-s',
|
|
85
|
+
'Apple Development: Silas Rhyneer (8W9CF7WS32)',
|
|
86
|
+
'--deep',
|
|
87
|
+
'--force',
|
|
88
|
+
binPath,
|
|
89
|
+
], { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
90
|
+
if (res.status !== 0) {
|
|
91
|
+
const stderr = (res.stderr ?? '').toString().trim();
|
|
92
|
+
if (stderr && !stderr.includes('valid on disk')) {
|
|
93
|
+
console.debug(`[crouter] codesign failed (expected on some systems): ${stderr}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// codesign not found or other spawn error — non-fatal, continue.
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export function signBrandedHostArtifacts(binPath, libnodePath, sign = signBrandedHost) {
|
|
102
|
+
if (libnodePath !== null)
|
|
103
|
+
sign(libnodePath);
|
|
104
|
+
sign(binPath);
|
|
105
|
+
}
|
|
106
|
+
let brandedHostWarningShown = false;
|
|
107
|
+
export function brandedHostWorks(binPath) {
|
|
108
|
+
try {
|
|
109
|
+
const res = spawnSync(binPath, ['-e', ''], {
|
|
110
|
+
stdio: 'ignore',
|
|
111
|
+
timeout: 2_000,
|
|
112
|
+
});
|
|
113
|
+
return res.status === 0;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function warnBrandedHostFallback(binPath) {
|
|
120
|
+
if (brandedHostWarningShown)
|
|
121
|
+
return;
|
|
122
|
+
brandedHostWarningShown = true;
|
|
123
|
+
try {
|
|
124
|
+
process.stderr.write(`[crouter] branded host ${binPath} failed its startup check; using ${process.execPath} for broker/daemon processes.\n`);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
/* best effort */
|
|
128
|
+
}
|
|
129
|
+
}
|
|
74
130
|
/** Ensure the branded host binary exists and matches the live node; return its
|
|
75
131
|
* absolute path. Idempotent and self-healing. Throws on a genuine build failure
|
|
76
132
|
* (disk full / permissions) — branding is load-bearing for FDA, so a failure is
|
|
@@ -89,6 +145,7 @@ export function ensureBrandedHost() {
|
|
|
89
145
|
const libnodeName = libnodeSrc !== null ? libnodeSrc.split('/').pop() : null;
|
|
90
146
|
const fresh = existsSync(dst) &&
|
|
91
147
|
marker !== null &&
|
|
148
|
+
marker.version === 2 &&
|
|
92
149
|
marker.source === src &&
|
|
93
150
|
marker.libnode === libnodeName &&
|
|
94
151
|
(libnodeName === null || existsSync(join(brandedHostDir(), libnodeName)));
|
|
@@ -108,14 +165,15 @@ export function ensureBrandedHost() {
|
|
|
108
165
|
atomicCopy(libnodeSrc, join(brandedHostDir(), libnodeName));
|
|
109
166
|
}
|
|
110
167
|
atomicCopy(src, dst, 0o755);
|
|
111
|
-
|
|
168
|
+
signBrandedHostArtifacts(dst, libnodeName !== null ? join(brandedHostDir(), libnodeName) : null);
|
|
169
|
+
writeFileSync(markerPath(), JSON.stringify({ version: 2, source: src, libnode: libnodeName }));
|
|
112
170
|
return dst;
|
|
113
171
|
}
|
|
114
172
|
/** The path the engine (broker / daemon) should be launched from. On macOS in a
|
|
115
173
|
* compiled (production) build this is the branded host; otherwise — non-darwin
|
|
116
174
|
* (TCC is macOS-only), source/tsx (dev + the test suite: never copy 70 MB into
|
|
117
|
-
* the real ~/.crouter),
|
|
118
|
-
*
|
|
175
|
+
* the real ~/.crouter), an explicit `CRTR_BRANDED_HOST=0` opt-out, or a copied
|
|
176
|
+
* host that macOS kills before it can execute JS — it is the live node. */
|
|
119
177
|
export function hostExecPath() {
|
|
120
178
|
if (process.env['CRTR_BRANDED_HOST'] === '0')
|
|
121
179
|
return process.execPath;
|
|
@@ -123,5 +181,9 @@ export function hostExecPath() {
|
|
|
123
181
|
return process.execPath;
|
|
124
182
|
if (import.meta.url.endsWith('.ts'))
|
|
125
183
|
return process.execPath;
|
|
126
|
-
|
|
184
|
+
const host = ensureBrandedHost();
|
|
185
|
+
if (brandedHostWorks(host))
|
|
186
|
+
return host;
|
|
187
|
+
warnBrandedHostFallback(host);
|
|
188
|
+
return process.execPath;
|
|
127
189
|
}
|
|
@@ -128,6 +128,17 @@ export interface FollowUpFrame {
|
|
|
128
128
|
export interface AbortFrame {
|
|
129
129
|
type: 'abort';
|
|
130
130
|
}
|
|
131
|
+
/** Run a `!` bash command — controller only. Maps to `session.executeBash()`,
|
|
132
|
+
* which runs the command, records a `bashExecution` message in context, and
|
|
133
|
+
* starts NO agent turn (pi's interactive `!`/`!!` semantics). `command` is the
|
|
134
|
+
* text AFTER the leading `!`/`!!`; `excludeFromContext` is the `!!` form (output
|
|
135
|
+
* shown but withheld from the LLM). The broker streams the result back as
|
|
136
|
+
* `bash_start`/`bash_output`/`bash_end` frames. */
|
|
137
|
+
export interface BashFrame {
|
|
138
|
+
type: 'bash';
|
|
139
|
+
command: string;
|
|
140
|
+
excludeFromContext?: boolean;
|
|
141
|
+
}
|
|
131
142
|
/** Controller arbitration (§5.3). */
|
|
132
143
|
export interface RequestControlFrame {
|
|
133
144
|
type: 'request_control';
|
|
@@ -284,11 +295,15 @@ export interface ShareFrame {
|
|
|
284
295
|
type: 'share';
|
|
285
296
|
}
|
|
286
297
|
/** Reload credentials + refresh model registry after a viewer-side auth change.
|
|
287
|
-
*
|
|
298
|
+
* Open to any client — reload_auth is an idempotent local re-read that doesn't
|
|
299
|
+
* steer the conversation, so the daemon's canvas-wide fan (one /login → every
|
|
300
|
+
* live broker) can trigger it without claiming controller and demoting an
|
|
301
|
+
* attached human. Broker handler: services.authStorage.reload() +
|
|
302
|
+
* services.modelRegistry.refresh(). */
|
|
288
303
|
export interface ReloadAuthFrame {
|
|
289
304
|
type: 'reload_auth';
|
|
290
305
|
}
|
|
291
|
-
export type ClientToBroker = HelloFrame | PromptFrame | SteerFrame | FollowUpFrame | AbortFrame | RequestControlFrame | ReleaseControlFrame | ByeFrame | ShutdownFrame | SetModelFrame | CycleModelFrame | CycleThinkingFrame | SetThinkingLevelFrame | DequeueFrame | SetAutoRetryFrame | SetAutoCompactionFrame | CompactFrame | NewSessionFrame | SwitchSessionFrame | ForkFrame | SetSessionNameFrame | GetCommandsFrame | NavigateTreeFrame | ReloadFrame | ExportFrame | ListModelsFrame | ListSessionsFrame | GetTreeFrame | GetSettingsFrame | ListScopedModelsFrame | ExtensionUIResponseFrame | CloneFrame | ShareFrame | ReloadAuthFrame;
|
|
306
|
+
export type ClientToBroker = HelloFrame | PromptFrame | SteerFrame | FollowUpFrame | AbortFrame | BashFrame | RequestControlFrame | ReleaseControlFrame | ByeFrame | ShutdownFrame | SetModelFrame | CycleModelFrame | CycleThinkingFrame | SetThinkingLevelFrame | DequeueFrame | SetAutoRetryFrame | SetAutoCompactionFrame | CompactFrame | NewSessionFrame | SwitchSessionFrame | ForkFrame | SetSessionNameFrame | GetCommandsFrame | NavigateTreeFrame | ReloadFrame | ExportFrame | ListModelsFrame | ListSessionsFrame | GetTreeFrame | GetSettingsFrame | ListScopedModelsFrame | ExtensionUIResponseFrame | CloneFrame | ShareFrame | ReloadAuthFrame;
|
|
292
307
|
export interface WelcomeFrame {
|
|
293
308
|
type: 'welcome';
|
|
294
309
|
snapshot: BrokerSnapshot;
|
|
@@ -335,6 +350,26 @@ export interface AckFrame {
|
|
|
335
350
|
ok: boolean;
|
|
336
351
|
detail?: string;
|
|
337
352
|
}
|
|
353
|
+
/** A `!` run has begun — viewers create the bash component. */
|
|
354
|
+
export interface BashStartFrame {
|
|
355
|
+
type: 'bash_start';
|
|
356
|
+
command: string;
|
|
357
|
+
excludeFromContext?: boolean;
|
|
358
|
+
}
|
|
359
|
+
/** A streamed chunk of combined stdout+stderr for the in-flight `!` run. */
|
|
360
|
+
export interface BashOutputFrame {
|
|
361
|
+
type: 'bash_output';
|
|
362
|
+
chunk: string;
|
|
363
|
+
}
|
|
364
|
+
/** The `!` run finished — viewers mark the bash component complete. Mirrors
|
|
365
|
+
* `BashResult` minus the (already-streamed) `output`. */
|
|
366
|
+
export interface BashEndFrame {
|
|
367
|
+
type: 'bash_end';
|
|
368
|
+
exitCode: number | undefined;
|
|
369
|
+
cancelled: boolean;
|
|
370
|
+
truncated: boolean;
|
|
371
|
+
fullOutputPath?: string;
|
|
372
|
+
}
|
|
338
373
|
/** `provider/id` model reference — the wire form of a current/selected model. */
|
|
339
374
|
export interface WireModelRef {
|
|
340
375
|
provider: string;
|
|
@@ -462,7 +497,7 @@ export type ExtensionUIRequestFrame = RpcExtensionUIRequest;
|
|
|
462
497
|
/** Everything the broker can send. Live `AgentSessionEvent`s are relayed
|
|
463
498
|
* verbatim (the broker adds nothing); the broker's own control frames carry
|
|
464
499
|
* non-colliding `type` discriminants. */
|
|
465
|
-
export type BrokerToClient = WelcomeFrame | ControlChangedFrame | ModelChangedFrame | ErrorFrame | AckFrame | BrokerDataFrame | DisplayStatusFrame | DisplayWidgetFrame | DisplayTitleFrame | ExtensionUIRequestFrame | AgentSessionEvent;
|
|
500
|
+
export type BrokerToClient = WelcomeFrame | ControlChangedFrame | ModelChangedFrame | ErrorFrame | AckFrame | BrokerDataFrame | DisplayStatusFrame | DisplayWidgetFrame | DisplayTitleFrame | BashStartFrame | BashOutputFrame | BashEndFrame | ExtensionUIRequestFrame | AgentSessionEvent;
|
|
466
501
|
/** Encode one frame as a single newline-terminated JSON line. */
|
|
467
502
|
export declare function encodeFrame(frame: ClientToBroker | BrokerToClient): string;
|
|
468
503
|
/** Byte bounds for a {@link FrameDecoder} (C5). */
|