@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
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// caller owns the Containers and the refresh trigger. beginFrame() memoizes the
|
|
13
13
|
// canvas.db reads for this one build pass (mirrors canvas-nav's per-frame cache),
|
|
14
14
|
// so a whole panel rebuild is a single fan-out of disk/db reads.
|
|
15
|
-
import { beginFrame, cNode, managerOf, liveReports, climbRoot, computeSubtreeActivity, navLabel,
|
|
15
|
+
import { beginFrame, cNode, managerOf, liveReports, climbRoot, computeSubtreeActivity, navLabel, nodeGlyph, truncate, tokensCell, cycleBadge, childBadge, liveBelowBadge, askBadge, activityCell, YELLOW, RESET, } from '../../core/canvas/nav-model.js';
|
|
16
16
|
/** Column widths for the aligned panel rows (visible columns). name is sized to
|
|
17
17
|
* the widest label across BOTH panels (capped); kind is wide enough for the
|
|
18
18
|
* longest persona kind (`orchestrator` = 12) so real kinds never truncate;
|
|
@@ -57,7 +57,7 @@ export function buildCanvasPanelLines(nodeId, asks, palette) {
|
|
|
57
57
|
const kind = faint(nameCell(n?.kind ?? '', KIND_W));
|
|
58
58
|
const tokens = muted(padStartVisible(tokensCell(id), TOK_W));
|
|
59
59
|
const badges = `${cycleBadge(n)}${childBadge(n)}${liveBelowBadge(n, activity.activeBelow)}${askBadge(id, asks)}${activityCell(id, n)}`;
|
|
60
|
-
return truncate(` ${
|
|
60
|
+
return truncate(` ${nodeGlyph(n)} ${name} ${kind} ${tokens}${badges}`);
|
|
61
61
|
};
|
|
62
62
|
// --- managers panel (↑) ---
|
|
63
63
|
const managers = [];
|
|
@@ -50,6 +50,8 @@ export declare class ChatView {
|
|
|
50
50
|
private streamingComponent;
|
|
51
51
|
/** Tool-call id → its execution component, for the duration of the call. */
|
|
52
52
|
private readonly pendingTools;
|
|
53
|
+
/** The `!` bash component currently streaming (between bash_start and bash_end). */
|
|
54
|
+
private bashComponent;
|
|
53
55
|
/** The single active activity loader (working/compaction/retry), if any. */
|
|
54
56
|
private activityLoader;
|
|
55
57
|
/** While true, `append` skips re-pinning the status container (bulk rebuild). */
|
|
@@ -78,6 +80,14 @@ export declare class ChatView {
|
|
|
78
80
|
* the container, so the loop covers it too). Returns the new HIDDEN state. */
|
|
79
81
|
toggleThinking(): boolean;
|
|
80
82
|
handleEvent(event: AgentSessionEvent): void;
|
|
83
|
+
bashStart(command: string, excludeFromContext?: boolean): void;
|
|
84
|
+
bashOutput(chunk: string): void;
|
|
85
|
+
bashEnd(result: {
|
|
86
|
+
exitCode: number | undefined;
|
|
87
|
+
cancelled: boolean;
|
|
88
|
+
truncated: boolean;
|
|
89
|
+
fullOutputPath?: string;
|
|
90
|
+
}): void;
|
|
81
91
|
private addMessageToChat;
|
|
82
92
|
/** Default-path tool component (toolDef undefined → builtin/default rendering). */
|
|
83
93
|
private makeToolComponent;
|
|
@@ -73,6 +73,8 @@ export class ChatView {
|
|
|
73
73
|
streamingComponent;
|
|
74
74
|
/** Tool-call id → its execution component, for the duration of the call. */
|
|
75
75
|
pendingTools = new Map();
|
|
76
|
+
/** The `!` bash component currently streaming (between bash_start and bash_end). */
|
|
77
|
+
bashComponent;
|
|
76
78
|
/** The single active activity loader (working/compaction/retry), if any. */
|
|
77
79
|
activityLoader;
|
|
78
80
|
/** While true, `append` skips re-pinning the status container (bulk rebuild). */
|
|
@@ -382,6 +384,27 @@ export class ChatView {
|
|
|
382
384
|
this.tui.requestRender();
|
|
383
385
|
}
|
|
384
386
|
// -------------------------------------------------------------------------
|
|
387
|
+
// `!` bash live stream (broker bash_start/bash_output/bash_end frames). Mirrors
|
|
388
|
+
// pi interactive mode's `!` handling: create the component on start, stream
|
|
389
|
+
// chunks into it, mark complete on end. The persisted `bashExecution` message
|
|
390
|
+
// also rides the next snapshot, so this only drives the LIVE view.
|
|
391
|
+
// -------------------------------------------------------------------------
|
|
392
|
+
bashStart(command, excludeFromContext) {
|
|
393
|
+
const component = new BashExecutionComponent(command, this.tui, excludeFromContext);
|
|
394
|
+
this.bashComponent = component;
|
|
395
|
+
this.append(component);
|
|
396
|
+
this.tui.requestRender();
|
|
397
|
+
}
|
|
398
|
+
bashOutput(chunk) {
|
|
399
|
+
this.bashComponent?.appendOutput(chunk);
|
|
400
|
+
this.tui.requestRender();
|
|
401
|
+
}
|
|
402
|
+
bashEnd(result) {
|
|
403
|
+
this.bashComponent?.setComplete(result.exitCode, result.cancelled, result.truncated ? { truncated: true } : undefined, result.fullOutputPath);
|
|
404
|
+
this.bashComponent = undefined;
|
|
405
|
+
this.tui.requestRender();
|
|
406
|
+
}
|
|
407
|
+
// -------------------------------------------------------------------------
|
|
385
408
|
// Rebuild path (ports addMessageToChat, interactive-mode.js:2483).
|
|
386
409
|
// -------------------------------------------------------------------------
|
|
387
410
|
addMessageToChat(message) {
|
|
@@ -63,11 +63,15 @@ export interface AttachPalette {
|
|
|
63
63
|
error: (s: string) => string;
|
|
64
64
|
/** Warning / transient notices. Same constraint as `error` → ANSI yellow. */
|
|
65
65
|
warning: (s: string) => string;
|
|
66
|
-
/** Editor border
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* the semantically-correct ANSI green
|
|
66
|
+
/** Editor border for a SINGLE-`!` bash command (output IS added to the agent's
|
|
67
|
+
* context). Dull/normal ANSI green — pi paints shell mode from its `bashMode`
|
|
68
|
+
* theme color (default `green`), which pi does NOT re-export through its public
|
|
69
|
+
* surface, so like `error`/`warning` this is the semantically-correct ANSI green. */
|
|
70
70
|
bashMode: (s: string) => string;
|
|
71
|
+
/** Editor border for a `!!` bash command (output is HIDDEN from the agent).
|
|
72
|
+
* BRIGHT ANSI green, so the more consequential "agent won't see this" form
|
|
73
|
+
* reads as visually hotter than the plain `!`. */
|
|
74
|
+
bashModeAlt: (s: string) => string;
|
|
71
75
|
}
|
|
72
76
|
/**
|
|
73
77
|
* Build the attach chrome's color palette from the LIVE theme. Call AFTER
|
|
@@ -206,6 +206,7 @@ const FAINT = (s) => `\x1b[2m${s}\x1b[22m`;
|
|
|
206
206
|
const RED = (s) => `\x1b[31m${s}\x1b[39m`;
|
|
207
207
|
const YELLOW = (s) => `\x1b[33m${s}\x1b[39m`;
|
|
208
208
|
const GREEN = (s) => `\x1b[32m${s}\x1b[39m`;
|
|
209
|
+
const BRIGHT_GREEN = (s) => `\x1b[92m${s}\x1b[39m`;
|
|
209
210
|
/**
|
|
210
211
|
* Build the attach chrome's color palette from the LIVE theme. Call AFTER
|
|
211
212
|
* `applyTheme()` — the colors are pulled from pi's `getMarkdownTheme()` /
|
|
@@ -237,6 +238,7 @@ export function attachPalette() {
|
|
|
237
238
|
error: RED,
|
|
238
239
|
warning: YELLOW,
|
|
239
240
|
bashMode: GREEN,
|
|
241
|
+
bashModeAlt: BRIGHT_GREEN,
|
|
240
242
|
surface: (line) => `${bgOn}${line.replace(/\x1b\[0m/g, `\x1b[0m${bgOn}`)}\x1b[49m`,
|
|
241
243
|
};
|
|
242
244
|
}
|
|
@@ -6,9 +6,8 @@ import type { RpcExtensionUIRequest, RpcExtensionUIResponse } from '../../core/r
|
|
|
6
6
|
export interface DialogHandle {
|
|
7
7
|
dismiss(): void;
|
|
8
8
|
}
|
|
9
|
-
/** The 4 user-blocking dialog methods.
|
|
10
|
-
*
|
|
11
|
-
* set_editor_text) the broker never forwards as a request. */
|
|
9
|
+
/** The 4 user-blocking dialog methods. Other RpcExtensionUIRequest methods are
|
|
10
|
+
* non-blocking display ops; callers handle them before rendering a dialog. */
|
|
12
11
|
export declare function isBlockingDialog(req: RpcExtensionUIRequest): boolean;
|
|
13
12
|
/**
|
|
14
13
|
* Render a blocking extension dialog as a focused overlay over `tui`, and resolve
|
|
@@ -5,12 +5,11 @@
|
|
|
5
5
|
// with pi's matching exported component and ships the resolved
|
|
6
6
|
// `extension_ui_response` (RpcExtensionUIResponse) back over the socket.
|
|
7
7
|
//
|
|
8
|
-
// Only the 4 blocking methods
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// response — there is nothing to answer).
|
|
8
|
+
// Only the 4 blocking methods render overlays here. Non-blocking display methods
|
|
9
|
+
// are handled by the viewer before calling `renderDialog` (notify becomes the
|
|
10
|
+
// normal notice line; status/widget/title use dedicated display frames). If one
|
|
11
|
+
// still reaches `renderDialog`, it returns an inert handle — no overlay, no
|
|
12
|
+
// response, because there is nothing to answer.
|
|
14
13
|
//
|
|
15
14
|
// Mapping (mirrors interactive-mode.js): select → ExtensionSelectorComponent;
|
|
16
15
|
// confirm → the SAME selector over ["Yes","No"] (pi has no separate confirm
|
|
@@ -22,9 +21,8 @@
|
|
|
22
21
|
// responding (the response would be a no-op the broker drops by id).
|
|
23
22
|
import { KeybindingsManager, TUI_KEYBINDINGS, } from '@earendil-works/pi-tui';
|
|
24
23
|
import { ExtensionEditorComponent, ExtensionInputComponent, ExtensionSelectorComponent, } from '@earendil-works/pi-coding-agent';
|
|
25
|
-
/** The 4 user-blocking dialog methods.
|
|
26
|
-
*
|
|
27
|
-
* set_editor_text) the broker never forwards as a request. */
|
|
24
|
+
/** The 4 user-blocking dialog methods. Other RpcExtensionUIRequest methods are
|
|
25
|
+
* non-blocking display ops; callers handle them before rendering a dialog. */
|
|
28
26
|
export function isBlockingDialog(req) {
|
|
29
27
|
return (req.method === 'select' ||
|
|
30
28
|
req.method === 'confirm' ||
|
|
@@ -64,8 +64,9 @@ export class GraphOverlay {
|
|
|
64
64
|
return;
|
|
65
65
|
this.scrollTop = 0;
|
|
66
66
|
this.pendingConfirm = undefined;
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
// Open with the cursor on the CURRENT (attached) node every time, not wherever
|
|
68
|
+
// it was left on the last open — the overlay should always default to self.
|
|
69
|
+
this.cursorId = this.self;
|
|
69
70
|
this.handle = this.tui.showOverlay(this, OVERLAY_OPTIONS);
|
|
70
71
|
this.tui.requestRender();
|
|
71
72
|
}
|
|
@@ -64,9 +64,10 @@ export declare class InputController {
|
|
|
64
64
|
/** Timestamp of the last lone Esc, for double-tap → tree detection (0 = none). */
|
|
65
65
|
private lastEscapeAt;
|
|
66
66
|
constructor(tui: TUI, editor: CustomEditor, keybindings: KeybindingsManager, hooks: InputControllerHooks);
|
|
67
|
-
/** Render
|
|
68
|
-
*
|
|
69
|
-
*
|
|
67
|
+
/** Render extension UI requests from the broker. Blocking dialogs route their
|
|
68
|
+
* answer back to the broker; non-blocking notify requests become the viewer's
|
|
69
|
+
* normal notice line. Supersedes any dialog already on screen (e.g. a re-route
|
|
70
|
+
* on control handoff) by dismissing it first. */
|
|
70
71
|
attachDialog(req: RpcExtensionUIRequest): void;
|
|
71
72
|
/** Feed the latest engine state so read-only commands (e.g. `/session`) report
|
|
72
73
|
* current values. Optional; the controller works without it. */
|
|
@@ -56,10 +56,17 @@ export class InputController {
|
|
|
56
56
|
this.hooks = hooks;
|
|
57
57
|
this.wire();
|
|
58
58
|
}
|
|
59
|
-
/** Render
|
|
60
|
-
*
|
|
61
|
-
*
|
|
59
|
+
/** Render extension UI requests from the broker. Blocking dialogs route their
|
|
60
|
+
* answer back to the broker; non-blocking notify requests become the viewer's
|
|
61
|
+
* normal notice line. Supersedes any dialog already on screen (e.g. a re-route
|
|
62
|
+
* on control handoff) by dismissing it first. */
|
|
62
63
|
attachDialog(req) {
|
|
64
|
+
if (req.method === 'notify') {
|
|
65
|
+
const prefix = req.notifyType === 'error' ? 'Error: ' : req.notifyType === 'warning' ? 'Warning: ' : '';
|
|
66
|
+
this.notify(`${prefix}${req.message}`);
|
|
67
|
+
this.tui.requestRender();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
63
70
|
this.dialog?.dismiss();
|
|
64
71
|
this.dialog = renderDialog(this.tui, req, (resp) => {
|
|
65
72
|
this.dialog = undefined;
|
|
@@ -292,6 +299,20 @@ export class InputController {
|
|
|
292
299
|
return;
|
|
293
300
|
}
|
|
294
301
|
}
|
|
302
|
+
// `!cmd` / `!!cmd` → run bash in the engine and inject output into context,
|
|
303
|
+
// WITHOUT starting an agent turn (pi-native `!` semantics). `!!` withholds
|
|
304
|
+
// the output from the LLM. The broker relays the run as bash_* frames.
|
|
305
|
+
if (trimmed.startsWith('!')) {
|
|
306
|
+
const excludeFromContext = trimmed.startsWith('!!');
|
|
307
|
+
const command = trimmed.slice(excludeFromContext ? 2 : 1).trim();
|
|
308
|
+
if (command === '')
|
|
309
|
+
return; // bare `!`/`!!`: nothing to run
|
|
310
|
+
if (!this.emitDrive({ type: 'bash', command, excludeFromContext }))
|
|
311
|
+
return;
|
|
312
|
+
this.editor.addToHistory(trimmed);
|
|
313
|
+
this.editor.setText('');
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
295
316
|
// Submit-while-streaming = steer (pi-native parity): interject into the
|
|
296
317
|
// running turn instead of queueing a fresh prompt. `isStreaming` is the
|
|
297
318
|
// broker snapshot's busy signal; the broker routes `steer` → session.steer()
|
|
@@ -44,13 +44,13 @@ export interface SlashContext {
|
|
|
44
44
|
/** Open the native /logout provider selector. */
|
|
45
45
|
openLogoutPicker?: () => void;
|
|
46
46
|
}
|
|
47
|
-
/** Canvas slash-commands —
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
47
|
+
/** Canvas slash-commands — implemented NATIVE in the viewer, the ONLY live host:
|
|
48
|
+
* the broker binds mode:'print', so broker pi-extensions never run their
|
|
49
|
+
* interactive (mode==='tui') paths. `/promote` triggers a turn after shelling
|
|
50
|
+
* `crtr node promote`; `/resume-node`, `/view`, `/context` each shell a `crtr`
|
|
51
|
+
* subcommand via `tmux display-popup` (the viewer runs inside a tmux pane);
|
|
52
|
+
* `/graph` toggles the in-process overlay. Exported so the editor folds these
|
|
53
|
+
* into the slash autocomplete list. */
|
|
54
54
|
export declare const CANVAS_SLASH_COMMANDS: ReadonlyArray<{
|
|
55
55
|
name: string;
|
|
56
56
|
description: string;
|
|
@@ -24,18 +24,19 @@
|
|
|
24
24
|
import { execFile } from 'node:child_process';
|
|
25
25
|
import { BUILTIN_SLASH_COMMANDS } from '../../core/runtime/pi-vendored.js';
|
|
26
26
|
import { surfaceTmuxStyleArgs } from '../../core/runtime/surface-bg.js';
|
|
27
|
-
/** Canvas slash-commands —
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
27
|
+
/** Canvas slash-commands — implemented NATIVE in the viewer, the ONLY live host:
|
|
28
|
+
* the broker binds mode:'print', so broker pi-extensions never run their
|
|
29
|
+
* interactive (mode==='tui') paths. `/promote` triggers a turn after shelling
|
|
30
|
+
* `crtr node promote`; `/resume-node`, `/view`, `/context` each shell a `crtr`
|
|
31
|
+
* subcommand via `tmux display-popup` (the viewer runs inside a tmux pane);
|
|
32
|
+
* `/graph` toggles the in-process overlay. Exported so the editor folds these
|
|
33
|
+
* into the slash autocomplete list. */
|
|
34
34
|
export const CANVAS_SLASH_COMMANDS = [
|
|
35
35
|
{ name: 'graph', description: 'Toggle the canvas GRAPH view (your local subscription tree)' },
|
|
36
36
|
{ name: 'promote', description: 'Promote this node to an orchestrator — /promote, or /promote <kind> to specialize' },
|
|
37
37
|
{ name: 'resume-node', description: 'Open the canvas navigator (search/scope/sort/tree) and resume the chosen node' },
|
|
38
38
|
{ name: 'view', description: 'Open a view in a popup — bare for the picker, or /view <name> to open that view directly' },
|
|
39
|
+
{ name: 'context', description: 'Browse this node + its subscriptions’ context dirs in a read-only nvim popup' },
|
|
39
40
|
];
|
|
40
41
|
const CANVAS_NAMES = new Set(CANVAS_SLASH_COMMANDS.map((c) => c.name));
|
|
41
42
|
/** Builtins with no Phase-4 engine method — scoped out (review m2). */
|
|
@@ -245,19 +246,24 @@ function dispatchCanvasCommand(name, arg, ctx) {
|
|
|
245
246
|
promoteNode(arg, ctx);
|
|
246
247
|
return true;
|
|
247
248
|
case 'resume-node':
|
|
248
|
-
//
|
|
249
|
-
//
|
|
249
|
+
// Open the full-screen canvas navigator as a popup; on Enter it focuses the
|
|
250
|
+
// chosen node back into THIS pane via `crtr node focus`.
|
|
250
251
|
return resumeNode(ctx);
|
|
251
252
|
case 'view':
|
|
252
|
-
//
|
|
253
|
-
//
|
|
253
|
+
// Bare `/view` opens the picker, `/view <name>` opens that view directly —
|
|
254
|
+
// each as a self-contained popup (no node-focus, no return-pane).
|
|
254
255
|
return openView(arg, ctx);
|
|
256
|
+
case 'context':
|
|
257
|
+
// A read-only nvim explorer over this node's + its subscriptions' context
|
|
258
|
+
// dirs, as a self-contained popup.
|
|
259
|
+
return openContext(ctx);
|
|
255
260
|
default:
|
|
256
261
|
ctx.notify(`/${name} is not available in attach`);
|
|
257
262
|
return true;
|
|
258
263
|
}
|
|
259
264
|
}
|
|
260
|
-
/** `/promote [kind]`
|
|
265
|
+
/** `/promote [kind]` — the live promote path (the broker is headless, so promotion
|
|
266
|
+
* has no in-engine command). Shells `crtr node promote --json` for
|
|
261
267
|
* this node (out-of-process), notifies the result, then triggers a turn so the
|
|
262
268
|
* persona injector steers in the new-role guidance at the turn boundary — exactly
|
|
263
269
|
* as the node would by running the command itself. */
|
|
@@ -309,7 +315,7 @@ function promoteNode(arg, ctx) {
|
|
|
309
315
|
});
|
|
310
316
|
});
|
|
311
317
|
}
|
|
312
|
-
/** `/resume-node
|
|
318
|
+
/** `/resume-node`. Opens `crtr canvas browse` as a tmux popup,
|
|
313
319
|
* scoped to this node's cwd; on Enter it focuses the chosen node back into this
|
|
314
320
|
* pane via `crtr node focus --pane` (which `canvas browse` shells). */
|
|
315
321
|
function resumeNode(ctx) {
|
|
@@ -323,7 +329,7 @@ function resumeNode(ctx) {
|
|
|
323
329
|
popup(cmd);
|
|
324
330
|
return true;
|
|
325
331
|
}
|
|
326
|
-
/** `/view [name]
|
|
332
|
+
/** `/view [name]`. Bare opens the picker (`crtr view pick`);
|
|
327
333
|
* `/view <name>` opens that view directly (`crtr view run <name>`). Self-contained
|
|
328
334
|
* popup — no node-focus, no return-pane. */
|
|
329
335
|
function openView(arg, ctx) {
|
|
@@ -336,6 +342,24 @@ function openView(arg, ctx) {
|
|
|
336
342
|
popup(cmd);
|
|
337
343
|
return true;
|
|
338
344
|
}
|
|
345
|
+
/** `/context`. Opens `crtr node context` as a popup — a
|
|
346
|
+
* read-only nvim explorer over this node's + its subscriptions' context dirs.
|
|
347
|
+
* Self-contained popup — no node-focus, no return-pane. */
|
|
348
|
+
function openContext(ctx) {
|
|
349
|
+
if (process.env['TMUX'] === undefined) {
|
|
350
|
+
ctx.notify('/context needs tmux');
|
|
351
|
+
return true;
|
|
352
|
+
}
|
|
353
|
+
// The popup runs server-side and won't reliably inherit CRTR_NODE_ID, so pass
|
|
354
|
+
// this viewer's node id explicitly (mirrors /promote, /resume-node).
|
|
355
|
+
const nodeId = (ctx.nodeId ?? process.env['CRTR_NODE_ID'] ?? '').trim();
|
|
356
|
+
if (nodeId === '') {
|
|
357
|
+
ctx.notify('/context: no node to root on (viewer has no node id)');
|
|
358
|
+
return true;
|
|
359
|
+
}
|
|
360
|
+
popup(`crtr node context --node ${shellQuote(nodeId)}`);
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
339
363
|
/** Open `cmd` as a fire-and-forget tmux display-popup (same geometry as the canvas
|
|
340
364
|
* extensions). tmux runs the trailing string through `sh -c`; the popup owns its
|
|
341
365
|
* screen and closes itself when the command exits, dropping back to this pane. */
|
|
@@ -7,22 +7,26 @@
|
|
|
7
7
|
// Both are pure render-layer chrome; nothing here touches the socket or session.
|
|
8
8
|
import { CustomEditor } from '@earendil-works/pi-coding-agent';
|
|
9
9
|
import { truncateToWidth, visibleWidth, } from '@earendil-works/pi-tui';
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
/** The thinking color scale is a deliberate cool→warm ramp between a blue and
|
|
11
|
+
* its orange complement, evenly spaced across the five active levels so each
|
|
12
|
+
* step stays readable without jumping through unrelated hues. `off` falls
|
|
13
|
+
* back to the caller's default border color. */
|
|
14
|
+
const THINKING_START = [68, 120, 228]; // blue
|
|
15
|
+
const THINKING_END = [228, 152, 68]; // orange
|
|
16
|
+
function interpolateRgb(start, end, t) {
|
|
17
|
+
return [
|
|
18
|
+
Math.round(start[0] + (end[0] - start[0]) * t),
|
|
19
|
+
Math.round(start[1] + (end[1] - start[1]) * t),
|
|
20
|
+
Math.round(start[2] + (end[2] - start[2]) * t),
|
|
21
|
+
];
|
|
22
|
+
}
|
|
19
23
|
const THINKING_RGB = {
|
|
20
24
|
off: undefined, // default border color
|
|
21
|
-
minimal:
|
|
22
|
-
low:
|
|
23
|
-
medium:
|
|
24
|
-
high:
|
|
25
|
-
xhigh:
|
|
25
|
+
minimal: interpolateRgb(THINKING_START, THINKING_END, 0 / 4),
|
|
26
|
+
low: interpolateRgb(THINKING_START, THINKING_END, 1 / 4),
|
|
27
|
+
medium: interpolateRgb(THINKING_START, THINKING_END, 2 / 4),
|
|
28
|
+
high: interpolateRgb(THINKING_START, THINKING_END, 3 / 4),
|
|
29
|
+
xhigh: interpolateRgb(THINKING_START, THINKING_END, 4 / 4),
|
|
26
30
|
};
|
|
27
31
|
/** The default (thinking `off`) title chip: reverse video + a space of padding
|
|
28
32
|
* each side, so the name reads as a label sitting on the border rule. Used as
|
|
@@ -46,6 +46,7 @@ export declare class ViewSocketClient extends EventEmitter {
|
|
|
46
46
|
* frame in {@link onData}, the request's timeout, or socket teardown. */
|
|
47
47
|
private pending;
|
|
48
48
|
constructor(nodeId: string);
|
|
49
|
+
private recordSocketFault;
|
|
49
50
|
/** Issue a correlated read-op and resolve with the broker's `data` reply (or
|
|
50
51
|
* reject on the correlated `error`, a timeout, or socket teardown). Mints the
|
|
51
52
|
* `id`, sends `{...frame, id}`, and parks a resolver consumed by {@link onData}.
|
|
@@ -54,7 +55,7 @@ export declare class ViewSocketClient extends EventEmitter {
|
|
|
54
55
|
/** Reject + clear every in-flight request (socket gone / decode error) so a
|
|
55
56
|
* picker fetch never hangs past the connection it rode on. */
|
|
56
57
|
private rejectAllPending;
|
|
57
|
-
/** The broker binds `
|
|
58
|
+
/** The broker binds `viewSocketPath(id)` — resolve it the same way. */
|
|
58
59
|
get socketPath(): string;
|
|
59
60
|
/** Open the connection. Wire up listeners; emits `connect` on success or
|
|
60
61
|
* `error` (a {@link BrokerUnavailableError} for ECONNREFUSED/ENOENT) on
|
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
import { EventEmitter } from 'node:events';
|
|
21
21
|
import { randomUUID } from 'node:crypto';
|
|
22
22
|
import { createConnection } from 'node:net';
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
23
|
+
import { viewSocketPath } from '../../core/canvas/paths.js';
|
|
24
|
+
import { classify } from '../../core/fault-classifier.js';
|
|
25
|
+
import { clearFault, recordFault } from '../../core/runtime/fault.js';
|
|
25
26
|
import { CLIENT_READ_CAPS, encodeFrame, FrameDecoder, FrameOverflowError, } from '../../core/runtime/broker-protocol.js';
|
|
26
27
|
/** How long {@link ViewSocketClient.request} waits for the correlated reply before
|
|
27
28
|
* rejecting — bounds a pending picker fetch if the broker drops the request
|
|
@@ -64,6 +65,18 @@ export class ViewSocketClient extends EventEmitter {
|
|
|
64
65
|
super();
|
|
65
66
|
this.nodeId = nodeId;
|
|
66
67
|
}
|
|
68
|
+
recordSocketFault(op, err) {
|
|
69
|
+
const classified = classify('viewer↔broker', err);
|
|
70
|
+
recordFault(this.nodeId, {
|
|
71
|
+
link: 'viewer↔broker',
|
|
72
|
+
op,
|
|
73
|
+
kind: classified.kind,
|
|
74
|
+
retry: op === 'redial'
|
|
75
|
+
? { disposition: 'auto', by: 'client' }
|
|
76
|
+
: { disposition: 'manual' },
|
|
77
|
+
message: err instanceof Error ? err.message : String(err),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
67
80
|
/** Issue a correlated read-op and resolve with the broker's `data` reply (or
|
|
68
81
|
* reject on the correlated `error`, a timeout, or socket teardown). Mints the
|
|
69
82
|
* `id`, sends `{...frame, id}`, and parks a resolver consumed by {@link onData}.
|
|
@@ -98,9 +111,9 @@ export class ViewSocketClient extends EventEmitter {
|
|
|
98
111
|
}
|
|
99
112
|
this.pending.clear();
|
|
100
113
|
}
|
|
101
|
-
/** The broker binds `
|
|
114
|
+
/** The broker binds `viewSocketPath(id)` — resolve it the same way. */
|
|
102
115
|
get socketPath() {
|
|
103
|
-
return
|
|
116
|
+
return viewSocketPath(this.nodeId);
|
|
104
117
|
}
|
|
105
118
|
/** Open the connection. Wire up listeners; emits `connect` on success or
|
|
106
119
|
* `error` (a {@link BrokerUnavailableError} for ECONNREFUSED/ENOENT) on
|
|
@@ -108,9 +121,12 @@ export class ViewSocketClient extends EventEmitter {
|
|
|
108
121
|
connect() {
|
|
109
122
|
const socket = createConnection(this.socketPath);
|
|
110
123
|
this.socket = socket;
|
|
111
|
-
socket.on('connect', () =>
|
|
124
|
+
socket.on('connect', () => {
|
|
125
|
+
clearFault(this.nodeId, { link: 'viewer↔broker' });
|
|
126
|
+
this.emit('connect');
|
|
127
|
+
});
|
|
112
128
|
socket.on('data', (chunk) => this.onData(chunk));
|
|
113
|
-
socket.on('error', (err) => this.onError(err));
|
|
129
|
+
socket.on('error', (err) => this.onError(err, 'connect'));
|
|
114
130
|
socket.on('close', () => this.onClose());
|
|
115
131
|
}
|
|
116
132
|
/** Re-establish the socket after a broker exit (a yield→revive cycle), on the
|
|
@@ -132,16 +148,18 @@ export class ViewSocketClient extends EventEmitter {
|
|
|
132
148
|
if (settled)
|
|
133
149
|
return;
|
|
134
150
|
settled = true;
|
|
151
|
+
clearFault(this.nodeId, { link: 'viewer↔broker' });
|
|
135
152
|
this.emit('connect');
|
|
136
153
|
resolve();
|
|
137
154
|
});
|
|
138
155
|
socket.on('data', (chunk) => this.onData(chunk));
|
|
139
156
|
socket.on('error', (err) => {
|
|
140
157
|
if (settled) {
|
|
141
|
-
this.onError(err);
|
|
158
|
+
this.onError(err, 'redial');
|
|
142
159
|
return;
|
|
143
160
|
}
|
|
144
161
|
settled = true;
|
|
162
|
+
this.recordSocketFault('redial', err);
|
|
145
163
|
try {
|
|
146
164
|
socket.destroy();
|
|
147
165
|
}
|
|
@@ -214,7 +232,8 @@ export class ViewSocketClient extends EventEmitter {
|
|
|
214
232
|
this.emit('frame', frame);
|
|
215
233
|
}
|
|
216
234
|
}
|
|
217
|
-
onError(err) {
|
|
235
|
+
onError(err, op) {
|
|
236
|
+
this.recordSocketFault(op, err);
|
|
218
237
|
if (err.code === 'ECONNREFUSED' || err.code === 'ENOENT') {
|
|
219
238
|
this.emitError(new BrokerUnavailableError(this.nodeId));
|
|
220
239
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { test } from 'node:test';
|
|
3
|
+
import { isCoalescableSourceRequest } from '../source-cache.js';
|
|
4
|
+
const exec = (args, extra = {}) => ({ kind: 'exec', bin: 'crtr', args, ...extra });
|
|
5
|
+
test('coalesces the idempotent crtr --json reads the SSE burst fans out', () => {
|
|
6
|
+
// Regression: a single SSE invalidation re-issued human/view/node reads as
|
|
7
|
+
// duplicate subprocesses because shouldCache only matched `canvas snapshot`.
|
|
8
|
+
assert.equal(isCoalescableSourceRequest(exec(['canvas', 'snapshot', '--json'])), true);
|
|
9
|
+
assert.equal(isCoalescableSourceRequest(exec(['human', 'list', '--json'])), true);
|
|
10
|
+
assert.equal(isCoalescableSourceRequest(exec(['view', 'list', '--json'])), true);
|
|
11
|
+
assert.equal(isCoalescableSourceRequest(exec(['node', 'snapshot', 'abc-123', '--json'])), true);
|
|
12
|
+
assert.equal(isCoalescableSourceRequest(exec(['node', 'inspect', 'show', 'abc-123', '--json'])), true);
|
|
13
|
+
});
|
|
14
|
+
test('does NOT coalesce writes, side-effecting, or target-mismatched requests', () => {
|
|
15
|
+
// Writes — must never be cached (would drop a mutation).
|
|
16
|
+
assert.equal(isCoalescableSourceRequest(exec(['node', 'new', '--json'], { stdin: 'prompt' })), false);
|
|
17
|
+
assert.equal(isCoalescableSourceRequest(exec(['canvas', 'revive', 'abc', '--json'])), false);
|
|
18
|
+
assert.equal(isCoalescableSourceRequest(exec(['node', 'msg', 'abc', '--json'], { stdin: 'hi' })), false);
|
|
19
|
+
// human resolve / deck are on-demand writes, not the cached list read.
|
|
20
|
+
assert.equal(isCoalescableSourceRequest(exec(['human', 'resolve', 'q1', '--json'])), false);
|
|
21
|
+
// Any stdin or cwd override disqualifies even an allowlisted command shape.
|
|
22
|
+
assert.equal(isCoalescableSourceRequest(exec(['canvas', 'snapshot', '--json'], { stdin: 'x' })), false);
|
|
23
|
+
assert.equal(isCoalescableSourceRequest(exec(['view', 'list', '--json'], { cwd: '/elsewhere' })), false);
|
|
24
|
+
// Non-exec requests are never cacheable.
|
|
25
|
+
assert.equal(isCoalescableSourceRequest({ kind: 'file', path: '/tmp/x' }), false);
|
|
26
|
+
assert.equal(isCoalescableSourceRequest({ kind: 'http', method: 'GET', url: 'http://x' }), false);
|
|
27
|
+
// Non-crtr bin, missing --json, or wrong arity must not match.
|
|
28
|
+
assert.equal(isCoalescableSourceRequest(exec(['human', 'list', '--json'], { bin: 'sh' })), false);
|
|
29
|
+
assert.equal(isCoalescableSourceRequest(exec(['human', 'list'])), false);
|
|
30
|
+
assert.equal(isCoalescableSourceRequest(exec(['node', 'snapshot', '--json'])), false);
|
|
31
|
+
assert.equal(isCoalescableSourceRequest(exec(['node', 'inspect', 'show', '--json'])), false);
|
|
32
|
+
});
|
|
@@ -41,6 +41,7 @@ export async function createDevServer(httpServer) {
|
|
|
41
41
|
alias: {
|
|
42
42
|
react: join(nodeModules, 'react'),
|
|
43
43
|
'react-dom': join(nodeModules, 'react-dom'),
|
|
44
|
+
'@': shellRoot,
|
|
44
45
|
// The crtr web runtime is a self-subpath of crouter's own package;
|
|
45
46
|
// pin it to the built barrel so the shell can import it from any root.
|
|
46
47
|
'@crouton-kit/crouter/web': join(packageRoot, 'dist', 'web', 'index.js'),
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
// events.ts — the `crtr web` realtime push lane
|
|
1
|
+
// events.ts — the `crtr web` realtime push lane.
|
|
2
2
|
//
|
|
3
|
-
// ONE server-sent-events stream, `GET /__crtr/events`, that carries
|
|
4
|
-
//
|
|
5
|
-
// event, re-pull through their existing
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// generic and the contract unchanged (a ViewPane still just runs `refresh`).
|
|
3
|
+
// ONE server-sent-events stream, `GET /__crtr/events`, that carries change
|
|
4
|
+
// invalidations — never data. The shell and built-in views subscribe and, on an
|
|
5
|
+
// event, re-pull through their existing bridge reads instead of waiting on a
|
|
6
|
+
// fixed poll tick. SSE carries "something in this class changed"; the consumer
|
|
7
|
+
// decides what to re-read.
|
|
9
8
|
//
|
|
10
9
|
// Event vocabulary (deliberately minimal): { kind: 'nodes' | 'inbox', ts }.
|
|
11
10
|
// - 'nodes' — the node graph changed (topology, status/intent transitions,
|
|
@@ -15,10 +14,9 @@
|
|
|
15
14
|
// - 'inbox' — a node's inbox.jsonl gained a message. Source: a recursive watch
|
|
16
15
|
// on the nodes/ tree, filtered to `inbox.jsonl` writes.
|
|
17
16
|
//
|
|
18
|
-
// WHY these sources
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
// the graph, inbox.jsonl appends for messages). No polling, no canvas.db reads.
|
|
17
|
+
// WHY these sources: they are the cheapest things that detect node-graph +
|
|
18
|
+
// inbox changes without a daemon hook or a db trigger — pure fs.watch on the
|
|
19
|
+
// two on-disk authorities (canvas.db for the graph, inbox.jsonl for messages).
|
|
22
20
|
import { watch } from 'node:fs';
|
|
23
21
|
import { crtrHome, nodesRoot, ensureHome } from '../../core/canvas/paths.js';
|
|
24
22
|
/** Coalesce a burst of fs events into one emission per kind. WAL writes and
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export interface WebServerOptions {
|
|
2
2
|
port: number;
|
|
3
3
|
host?: string;
|
|
4
|
+
token?: string;
|
|
4
5
|
/** --dev: mount a Vite dev server (middleware mode, HMR) for asset serving
|
|
5
6
|
* instead of the static dist/web-client/ bundle. The bridge + SSE + WS relay
|
|
6
7
|
* are identical in both modes. */
|
|
@@ -12,7 +13,7 @@ export interface RunningWebServer {
|
|
|
12
13
|
clientDir: string;
|
|
13
14
|
close: () => Promise<void>;
|
|
14
15
|
}
|
|
15
|
-
/** Build + start the unified web server. Binds
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
/** Build + start the unified web server. Binds the requested host/port and
|
|
17
|
+
* resolves once the server is listening. Async because --dev awaits a Vite
|
|
18
|
+
* middleware server before listening. */
|
|
18
19
|
export declare function startWebServer(opts: WebServerOptions): Promise<RunningWebServer>;
|