@crouton-kit/crouter 0.3.32 → 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 +2 -2
- 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 +31 -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/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
package/dist/commands/node.js
CHANGED
|
@@ -13,12 +13,17 @@ import { reviveNode } from '../core/runtime/revive.js';
|
|
|
13
13
|
import { newNodeId } from '../core/runtime/nodes.js';
|
|
14
14
|
import { readRoadmap } from '../core/runtime/roadmap.js';
|
|
15
15
|
import { parseWhen, parseCadence, cadenceDisplay } from '../core/wake.js';
|
|
16
|
+
import { nodeSnapshotLeaf } from './node-snapshot.js';
|
|
17
|
+
import { nodeContextLeaf } from './node-context.js';
|
|
16
18
|
import { recycleNode } from '../core/runtime/recycle.js';
|
|
19
|
+
import { readFaultAsync } from '../core/runtime/fault.js';
|
|
20
|
+
import { activeFaultForDisplay } from '../core/canvas/render.js';
|
|
17
21
|
import { detachToBackground, focus as placementFocus, windowAlive, windowOfPane, currentTmux, getPaneOption } from '../core/runtime/placement.js';
|
|
18
|
-
import { buildLaunchSpec } from '../core/runtime/launch.js';
|
|
22
|
+
import { buildLaunchSpec, normalizeModel } from '../core/runtime/launch.js';
|
|
19
23
|
import { closeNode } from '../core/runtime/close.js';
|
|
24
|
+
import { isBrokerLive, setModelLive, persistDormantModel } from '../core/runtime/model-swap.js';
|
|
20
25
|
import { appendInbox } from '../core/feed/inbox.js';
|
|
21
|
-
import { availableKinds, kindWhenToUse
|
|
26
|
+
import { availableKinds, kindWhenToUse } from '../core/personas/index.js';
|
|
22
27
|
import { stateBlock } from '../core/help.js';
|
|
23
28
|
import { getNode, updateNode, listNodes, subscribe, unsubscribe, subscriptionsOf, subscribersOf, readContextTokens, view, armWake, listWakes, cancelWake, WakeArmError, } from '../core/canvas/index.js';
|
|
24
29
|
// Past this much context, an ORCHESTRATOR that spawns a managed child is better
|
|
@@ -56,11 +61,8 @@ function assertKind(kind) {
|
|
|
56
61
|
* it reflects the caller's cwd/project scope. Appended to `node new -h` and
|
|
57
62
|
* `node promote -h` so custom kinds appear in help. Soft-fails via the renderer.
|
|
58
63
|
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* block is appended right after — the specialist sub-personas THAT kind may
|
|
62
|
-
* spawn (full kind string + whenToUse). Everything but the top-level `<kinds>`
|
|
63
|
-
* block soft-fails to omission (caller block wrapped in its own try/catch). */
|
|
64
|
+
* Keep this block cheap and caller-agnostic: help should not depend on the
|
|
65
|
+
* running node's current persona env, which can lag after polymorph. */
|
|
64
66
|
function kindsStateBlock() {
|
|
65
67
|
const kinds = availableKinds();
|
|
66
68
|
const lines = kinds
|
|
@@ -69,33 +71,7 @@ function kindsStateBlock() {
|
|
|
69
71
|
return w ? `${k} — ${w}` : k;
|
|
70
72
|
})
|
|
71
73
|
.join('\n');
|
|
72
|
-
|
|
73
|
-
const sub = callerSubPersonasBlock();
|
|
74
|
-
return sub ? `${block}\n${sub}` : block;
|
|
75
|
-
}
|
|
76
|
-
/** When the caller is a live node whose kind has sub-personas available to it,
|
|
77
|
-
* render a `<sub-personas for="<kind>" count=M>` block — one
|
|
78
|
-
* `<full-kind-string> — <whenToUse>` line per sub-persona spawnable BY that
|
|
79
|
-
* kind (e.g. `plan/reviewers/security`). Returns '' (so the second block is
|
|
80
|
-
* omitted) when CRTR_NODE_ID is unset, getNode returns null, the caller kind
|
|
81
|
-
* has no sub-personas, or anything throws — this is help output, never error. */
|
|
82
|
-
function callerSubPersonasBlock() {
|
|
83
|
-
try {
|
|
84
|
-
const id = process.env['CRTR_NODE_ID'];
|
|
85
|
-
if (id === undefined || id === '')
|
|
86
|
-
return '';
|
|
87
|
-
const node = getNode(id);
|
|
88
|
-
if (node === null)
|
|
89
|
-
return '';
|
|
90
|
-
const subs = subPersonasFor(node.kind);
|
|
91
|
-
if (subs.length === 0)
|
|
92
|
-
return '';
|
|
93
|
-
const lines = subs.map((s) => (s.whenToUse ? `${s.kind} — ${s.whenToUse}` : s.kind)).join('\n');
|
|
94
|
-
return stateBlock('sub-personas', { for: node.kind, count: subs.length }, lines);
|
|
95
|
-
}
|
|
96
|
-
catch {
|
|
97
|
-
return '';
|
|
98
|
-
}
|
|
74
|
+
return stateBlock('kinds', { count: kinds.length }, lines);
|
|
99
75
|
}
|
|
100
76
|
// ---------------------------------------------------------------------------
|
|
101
77
|
// node new — spawn a terminal worker as a detached headless broker under the root
|
|
@@ -110,14 +86,14 @@ const nodeNew = defineLeaf({
|
|
|
110
86
|
summary: 'spawn a terminal worker onto the canvas as a detached broker — returns its node id',
|
|
111
87
|
params: [
|
|
112
88
|
{ kind: 'stdin', name: 'prompt', required: true, constraint: 'First user message for the spawned node. Deliver it on stdin from a quoted heredoc (`<<\'EOF\'`) or a file (`< prompt.md`).' },
|
|
113
|
-
{ kind: 'flag', name: 'kind', type: 'string', required: false, default: 'general', constraint: 'Persona kind — match the work to the kind. The <kinds> list below names every installable kind and when to use each
|
|
89
|
+
{ kind: 'flag', name: 'kind', type: 'string', required: false, default: 'general', constraint: 'Persona kind — match the work to the kind. The <kinds> list below names every installable kind and when to use each. For an exact composed persona list, use `crtr sys prompt-review --list --kind <kind>`.' },
|
|
114
90
|
{ kind: 'flag', name: 'mode', type: 'enum', choices: ['base', 'orchestrator'], required: false, default: 'base', constraint: 'Persona mode. base for a worker that finishes in one window; orchestrator to create the child directly as a sub-orchestrator (it boots with the orchestrator persona + a seeded roadmap and fans its scope out) — use it when the unit is too large for one window, e.g. a big review, instead of spawning a base worker and counting on it to promote itself.' },
|
|
115
91
|
{ kind: 'flag', name: 'cwd', type: 'path', required: false, constraint: 'Dir the node is pinned to. Defaults to the caller cwd.' },
|
|
116
92
|
{ kind: 'flag', name: 'name', type: 'string', required: false, constraint: 'Display name (tmux window + resume picker). Defaults to the kind.' },
|
|
117
93
|
{ kind: 'flag', name: 'parent', type: 'string', required: false, constraint: 'Parent node id. Defaults to the calling node (CRTR_NODE_ID).' },
|
|
118
94
|
{ kind: 'flag', name: 'root', type: 'bool', required: false, constraint: 'Spawn an INDEPENDENT root instead of a managed child: no parent (top-level on the canvas), NO subscription back to you (you are NOT woken by it), resident lifecycle. It records spawned_by=you for provenance and is brought forefront so it can be driven directly. Use for a node you hand off and do not manage (e.g. a sub-orchestrator a human will discuss with).' },
|
|
119
95
|
{ kind: 'flag', name: 'fork-from', type: 'string', required: false, constraint: 'FORK the new node from an existing pi conversation instead of starting it fresh: pass a node id (forks from that node\'s session), an absolute session `.jsonl` path, or a partial pi session uuid. pi copies that whole history into a NEW session for the child (the source is untouched), then the prompt is delivered as the next message — i.e. the child wakes up as a continuation of that conversation. Use to branch exploratory work off a node that already built up the context you need, instead of re-deriving it. One-shot at birth: the fork resumes its own session thereafter.' },
|
|
120
|
-
{ kind: 'flag', name: 'model', type: 'enum', choices: ['ultra', 'strong', 'medium', 'light'], required: false, constraint: 'Override the model the node runs on, by capability TIER: ultra (frontier), strong (opus), medium (sonnet), light (haiku). Omit to use the kind\'s persona default (explore=light,
|
|
96
|
+
{ kind: 'flag', name: 'model', type: 'enum', choices: ['ultra', 'strong', 'medium', 'light'], required: false, constraint: 'Override the model the node runs on, by capability TIER: ultra (frontier), strong (opus), medium (sonnet), light (haiku). Omit to use the kind\'s persona default (advisor=ultra, explore=light, most other builtins=strong). The override is durable — it survives revives and polymorphs (promote/demote).' },
|
|
121
97
|
],
|
|
122
98
|
output: [
|
|
123
99
|
{ name: 'node_id', type: 'string', required: true, constraint: 'The new node id.' },
|
|
@@ -148,7 +124,7 @@ const nodeNew = defineLeaf({
|
|
|
148
124
|
const root = input['root'] === true;
|
|
149
125
|
const forkFrom = input['forkFrom'];
|
|
150
126
|
const model = input['model'];
|
|
151
|
-
const res = spawnChild({ kind, mode, cwd, name, prompt, parent, root, forkFrom, model });
|
|
127
|
+
const res = await spawnChild({ kind, mode, cwd, name, prompt, parent, root, forkFrom, model });
|
|
152
128
|
return {
|
|
153
129
|
node_id: res.node.node_id,
|
|
154
130
|
name: res.node.name,
|
|
@@ -175,24 +151,67 @@ const nodeNew = defineLeaf({
|
|
|
175
151
|
const nodeList = defineLeaf({
|
|
176
152
|
name: 'list',
|
|
177
153
|
description: 'list nodes on the canvas',
|
|
178
|
-
whenToUse: 'you want a flat roster of the nodes on the canvas,
|
|
154
|
+
whenToUse: 'you want a flat roster of the nodes on the canvas, sliced by any combination of attribute filters (status, kind, mode, lifecycle, cwd, hanging) and graph scope (--under a node, for that node plus its subscription descendants). The filters AND together, so "every human node in my subtree" is `--kind human --under <me>` and "every parked orchestrator" is `--mode orchestrator --hanging`. Use `node inspect show` instead to drill into one node and its spine neighbors, `canvas dashboard` for the tree SHAPE, and `canvas attention` to find which nodes are blocked on a human',
|
|
179
155
|
help: {
|
|
180
156
|
name: 'node inspect list',
|
|
181
|
-
summary: 'list nodes on the canvas,
|
|
157
|
+
summary: 'list nodes on the canvas, filtered by any combination of attribute slices and a graph-scope (--under) that AND together',
|
|
182
158
|
params: [
|
|
183
159
|
{ kind: 'flag', name: 'status', type: 'string', required: false, constraint: 'Filter: active | idle | done | dead | canceled. Comma-separated for several. NOTE: `active` means the engine process is live (never closed), NOT that the node is generating right now — an active node is usually dormant between turns. To tell working-vs-idle, check the pi session-file mtime or CPU, not status.' },
|
|
160
|
+
{ kind: 'flag', name: 'kind', type: 'string', required: false, constraint: 'Filter by persona kind (general, explore, developer, design, plan, review, spec, human, …). Comma-separated for several (OR within the flag).' },
|
|
161
|
+
{ kind: 'flag', name: 'mode', type: 'string', required: false, constraint: 'Filter by mode: base | orchestrator. Comma-separated for several.' },
|
|
162
|
+
{ kind: 'flag', name: 'lifecycle', type: 'string', required: false, constraint: 'Filter by lifecycle: terminal | resident. Comma-separated for several.' },
|
|
163
|
+
{ kind: 'flag', name: 'cwd', type: 'string', required: false, constraint: 'Filter to nodes pinned to this exact cwd (absolute path). Roster is canvas-wide (all cwds) by default.' },
|
|
164
|
+
{ kind: 'flag', name: 'under', type: 'string', required: false, constraint: 'Graph scope: restrict to this node and its subscription descendants (the sub-DAG reachable downward — its reports, theirs, …). This is "one initiative / my subtree". Combine with attribute filters, e.g. `--kind human --under <me>`.' },
|
|
165
|
+
{ kind: 'flag', name: 'hanging', type: 'bool', required: false, constraint: 'Only nodes PARKED on an active fault (live broker + marker when provider-owned). Use to find stuck/rate-limited nodes awaiting auto-revive.' },
|
|
184
166
|
],
|
|
185
167
|
output: [
|
|
186
|
-
{ name: 'nodes', type: 'object[]', required: true, constraint: 'Rows: {node_id, name, kind, mode, lifecycle, status, cwd, parent, created}.' },
|
|
168
|
+
{ name: 'nodes', type: 'object[]', required: true, constraint: 'Rows: {node_id, name, kind, mode, lifecycle, status, cwd, parent, created, hanging}. `hanging` is null normally, or {kind, message, since} when the node is PARKED on an active fault (rate-limit/overloaded/connection/other); the canvas-graph views render it with ⚠ + a countdown or state cue.' },
|
|
187
169
|
],
|
|
188
170
|
outputKind: 'object',
|
|
189
|
-
effects: ['Read-only: queries canvas.db.'],
|
|
171
|
+
effects: ['Read-only: queries canvas.db (+ an active-fault marker read).'],
|
|
190
172
|
},
|
|
191
173
|
run: async (input) => {
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
174
|
+
const csv = (k) => {
|
|
175
|
+
const raw = input[k];
|
|
176
|
+
return raw !== undefined && raw !== '' ? raw.split(',').map((s) => s.trim()).filter((s) => s !== '') : undefined;
|
|
177
|
+
};
|
|
178
|
+
const status = csv('status');
|
|
179
|
+
const kinds = csv('kind');
|
|
180
|
+
const modes = csv('mode');
|
|
181
|
+
const lifecycles = csv('lifecycle');
|
|
182
|
+
const cwd = input['cwd'];
|
|
183
|
+
const under = input['under'];
|
|
184
|
+
const hangingOnly = input['hanging'] === true;
|
|
185
|
+
// Graph scope (--under): self + subscription descendants. Validate the anchor
|
|
186
|
+
// so a typo'd id is a structured error, not a silently-empty roster.
|
|
187
|
+
let scope;
|
|
188
|
+
if (under !== undefined && under !== '') {
|
|
189
|
+
if (getNode(under) === null) {
|
|
190
|
+
throw new InputError({ error: 'not_found', message: `no node: ${under}`, next: 'List nodes with `crtr node inspect list`, then pass a real id to --under.' });
|
|
191
|
+
}
|
|
192
|
+
scope = new Set([under, ...view(under)]);
|
|
193
|
+
}
|
|
194
|
+
const rows = listNodes(status !== undefined ? { status } : undefined).filter((row) => {
|
|
195
|
+
if (scope !== undefined && !scope.has(row.node_id))
|
|
196
|
+
return false;
|
|
197
|
+
if (kinds !== undefined && !kinds.includes(row.kind))
|
|
198
|
+
return false;
|
|
199
|
+
if (modes !== undefined && !modes.includes(row.mode))
|
|
200
|
+
return false;
|
|
201
|
+
if (lifecycles !== undefined && !lifecycles.includes(row.lifecycle))
|
|
202
|
+
return false;
|
|
203
|
+
if (cwd !== undefined && cwd !== '' && row.cwd !== cwd)
|
|
204
|
+
return false;
|
|
205
|
+
return true;
|
|
206
|
+
});
|
|
207
|
+
// Enrich each row with its active-fault state. Daemon-owned provider faults
|
|
208
|
+
// are suppressed when the broker pid is gone; manual/client faults stay
|
|
209
|
+
// visible until cleared.
|
|
210
|
+
const nodes = await Promise.all(rows.map(async (row) => {
|
|
211
|
+
const hanging = activeFaultForDisplay(row, await readFaultAsync(row.node_id));
|
|
212
|
+
return { ...row, hanging };
|
|
213
|
+
}));
|
|
214
|
+
return { nodes: nodes.filter((n) => !hangingOnly || n.hanging !== null) };
|
|
196
215
|
},
|
|
197
216
|
});
|
|
198
217
|
// ---------------------------------------------------------------------------
|
|
@@ -282,10 +301,10 @@ const nodeFocus = defineLeaf({
|
|
|
282
301
|
// (revive it if dormant), then open/move its one viewer pane beside the
|
|
283
302
|
// caller (or split a fresh viewer with --new-pane). The reviver is injected
|
|
284
303
|
// so placement need not import revive.ts.
|
|
285
|
-
const res = placementFocus(id, {
|
|
304
|
+
const res = await placementFocus(id, {
|
|
286
305
|
pane: input['pane'],
|
|
287
306
|
newPane: input['newPane'] === true,
|
|
288
|
-
revive: (nid) =>
|
|
307
|
+
revive: (nid) => reviveNode(nid, { resume: true }),
|
|
289
308
|
});
|
|
290
309
|
return { focused: res.focused, session: res.session, revived: res.revived, in_place: res.inPlace };
|
|
291
310
|
},
|
|
@@ -439,6 +458,74 @@ const nodeClose = defineLeaf({
|
|
|
439
458
|
},
|
|
440
459
|
});
|
|
441
460
|
// ---------------------------------------------------------------------------
|
|
461
|
+
// node model — headless live model/provider swap for a node (no viewer attach)
|
|
462
|
+
// ---------------------------------------------------------------------------
|
|
463
|
+
const nodeModel = defineLeaf({
|
|
464
|
+
name: 'model',
|
|
465
|
+
description: 'swap a node\'s model/provider headlessly (durable, survives revives)',
|
|
466
|
+
whenToUse: 'you want to change which model (and thus provider) a node runs on WITHOUT opening its viewer — flip a running node to a stronger/cheaper model or a different provider, or repin a dormant node\'s model before its next revive. The choice is durable: it survives revives and polymorphs. This is the headless twin of the in-viewer `/model` slash command; reach for `node promote --model` instead when you are also changing a node\'s role',
|
|
467
|
+
help: {
|
|
468
|
+
name: 'node model',
|
|
469
|
+
summary: 'swap a node\'s model headlessly — if its broker is live, drive the switch over view.sock (no viewer attached); if dormant, repin its durable recipe for the next revive. The choice persists across revives either way.',
|
|
470
|
+
params: [
|
|
471
|
+
{ kind: 'positional', name: 'spec', required: true, constraint: 'Model query: an exact `provider/id` (e.g. `openai-codex/gpt-5.5`), a capability tier (`ultra|strong|medium|light`), a bare family alias (`opus|sonnet|haiku`), or a free-text substring matched against the live registry. A free-text substring only resolves against a LIVE broker; a dormant node needs a concrete `provider/id` (or a tier/alias).' },
|
|
472
|
+
{ kind: 'flag', name: 'node', type: 'string', required: false, constraint: 'Node to repoint. Defaults to the node occupying --pane (or your current pane).' },
|
|
473
|
+
{ kind: 'flag', name: 'pane', type: 'string', required: false, constraint: 'tmux pane id whose node to repoint. Defaults to $TMUX_PANE / your current pane.' },
|
|
474
|
+
],
|
|
475
|
+
output: [
|
|
476
|
+
{ name: 'node_id', type: 'string', required: true, constraint: 'The node whose model was swapped.' },
|
|
477
|
+
{ name: 'model', type: 'string', required: true, constraint: 'The resolved model — a concrete `provider/id` for a live broker (registry-resolved) or the normalized recipe value for a dormant node.' },
|
|
478
|
+
{ name: 'applied', type: 'string', required: true, constraint: '"live" (the running broker switched immediately and persisted it) or "next-revive" (the dormant node\'s recipe was repinned; takes effect when it next revives).' },
|
|
479
|
+
],
|
|
480
|
+
outputKind: 'object',
|
|
481
|
+
effects: [
|
|
482
|
+
'LIVE broker: connects to the node\'s view.sock, claims controller, and drives `set_model` on the running engine; the broker persists the choice (model_override + launch.model) itself.',
|
|
483
|
+
'DORMANT node: writes model_override + launch.model directly into the node\'s durable recipe — no engine runs until its next revive.',
|
|
484
|
+
],
|
|
485
|
+
},
|
|
486
|
+
run: async (input) => {
|
|
487
|
+
const pane = input['pane'] ?? process.env['TMUX_PANE'];
|
|
488
|
+
let id = input['node'];
|
|
489
|
+
if (id === undefined || id === '')
|
|
490
|
+
id = nodeInPane(pane);
|
|
491
|
+
if (id === undefined || id === '') {
|
|
492
|
+
throw new InputError({ error: 'no_node', message: 'no node found in this pane to repoint', next: 'Pass --node <id>, or run from inside the agent\'s pane.' });
|
|
493
|
+
}
|
|
494
|
+
const meta = getNode(id);
|
|
495
|
+
if (meta === null) {
|
|
496
|
+
throw new InputError({ error: 'not_found', message: `no node: ${id}`, next: 'List nodes with `crtr node inspect list`.' });
|
|
497
|
+
}
|
|
498
|
+
const spec = (input['spec'] ?? '').trim();
|
|
499
|
+
if (spec === '') {
|
|
500
|
+
throw new InputError({ error: 'empty_spec', message: 'a model spec is required', field: 'spec', next: 'Pass a `provider/id`, a tier (ultra|strong|medium|light), an alias (opus|sonnet|haiku), or a substring.' });
|
|
501
|
+
}
|
|
502
|
+
if (isBrokerLive(meta)) {
|
|
503
|
+
// Live: drive the running engine over its socket. The broker resolves the
|
|
504
|
+
// query against the live registry (substrings included) and persists.
|
|
505
|
+
let model;
|
|
506
|
+
try {
|
|
507
|
+
model = await setModelLive(id, spec);
|
|
508
|
+
}
|
|
509
|
+
catch (err) {
|
|
510
|
+
throw new InputError({ error: 'switch_failed', message: `live model switch failed: ${err instanceof Error ? err.message : String(err)}`, next: 'Check the spec resolves (`provider/id`, tier, alias, or a substring of a registered model).' });
|
|
511
|
+
}
|
|
512
|
+
return { node_id: id, model, applied: 'live' };
|
|
513
|
+
}
|
|
514
|
+
// Dormant: no live registry to search, so normalizeModel only maps
|
|
515
|
+
// tiers/aliases. A bare substring that isn't a tier/alias can't resolve to a
|
|
516
|
+
// concrete id offline — reject rather than write a meaningless override.
|
|
517
|
+
const normalized = normalizeModel(spec);
|
|
518
|
+
if (!normalized.includes('/')) {
|
|
519
|
+
throw new InputError({ error: 'unresolvable_dormant', message: `'${spec}' does not resolve to a concrete model for a dormant node`, field: 'spec', next: 'Pass an exact `provider/id` (e.g. openai-codex/gpt-5.5) or a tier/alias — the live registry search is only available while the node\'s broker is up.' });
|
|
520
|
+
}
|
|
521
|
+
persistDormantModel(id, normalized);
|
|
522
|
+
return { node_id: id, model: normalized, applied: 'next-revive' };
|
|
523
|
+
},
|
|
524
|
+
render: (r) => r['applied'] === 'live'
|
|
525
|
+
? `Switched ${r['node_id']} to ${r['model']} (live — applied now and persisted).`
|
|
526
|
+
: `Repinned ${r['node_id']} to ${r['model']} (applies on next revive).`,
|
|
527
|
+
});
|
|
528
|
+
// ---------------------------------------------------------------------------
|
|
442
529
|
// node cycle — DFS-walk the canvas one window at a time (Alt+] / Alt+[)
|
|
443
530
|
// ---------------------------------------------------------------------------
|
|
444
531
|
/** Every live node in DFS pre-order across the whole forest. The spawn tree is
|
|
@@ -513,9 +600,9 @@ const nodeCycle = defineLeaf({
|
|
|
513
600
|
return { focused: false, from: fromId };
|
|
514
601
|
// Placement brings the neighbor's viewer forefront beside the caller,
|
|
515
602
|
// relaunching its broker engine first if it was dormant.
|
|
516
|
-
const res = placementFocus(targetId, {
|
|
603
|
+
const res = await placementFocus(targetId, {
|
|
517
604
|
pane,
|
|
518
|
-
revive: (nid) =>
|
|
605
|
+
revive: (nid) => reviveNode(nid, { resume: true }),
|
|
519
606
|
});
|
|
520
607
|
return { focused: res.focused, node_id: targetId, name: target.name, from: fromId };
|
|
521
608
|
},
|
|
@@ -556,13 +643,15 @@ const nodeMsg = defineLeaf({
|
|
|
556
643
|
throw new InputError({ error: 'empty_body', message: 'a message body is required', field: 'body', next: 'Pass the message after the node id or on stdin.' });
|
|
557
644
|
const tier = (input['tier'] ?? 'normal');
|
|
558
645
|
const from = process.env['CRTR_NODE_ID'] ?? 'human';
|
|
646
|
+
// A long body clips in the receiver's digest; appendInbox mints a short `id`
|
|
647
|
+
// for it so the receiver can read the full text back via `feed message <id>`.
|
|
559
648
|
appendInbox(id, { from, tier, kind: 'message', label: body.split('\n')[0].slice(0, 120), data: { body } });
|
|
560
649
|
// A direct message wakes any node: if the target has no live window
|
|
561
650
|
// (done/dead/idle-released), revive it so its inbox-watcher delivers this.
|
|
562
651
|
let woke = false;
|
|
563
652
|
if (!windowAlive(target.tmux_session, target.window)) {
|
|
564
653
|
try {
|
|
565
|
-
reviveNode(id, { resume: true });
|
|
654
|
+
void reviveNode(id, { resume: true });
|
|
566
655
|
woke = true;
|
|
567
656
|
}
|
|
568
657
|
catch { /* best-effort wake */ }
|
|
@@ -657,7 +746,7 @@ const nodePromote = defineLeaf({
|
|
|
657
746
|
name: 'node promote',
|
|
658
747
|
summary: 'promote yourself to an orchestrator — do this when your task outgrows one context window (many phases to delegate and persist across refreshes); not for work that fits one window, and not merely because you spawned a child. Mode only — lifecycle stays as-is unless you pass --resident',
|
|
659
748
|
params: [
|
|
660
|
-
{ kind: 'flag', name: 'kind', type: 'string', required: false, constraint: 'Specialize as this kind of orchestrator. The <kinds> list below names every installable kind and when to use each
|
|
749
|
+
{ kind: 'flag', name: 'kind', type: 'string', required: false, constraint: 'Specialize as this kind of orchestrator. The <kinds> list below names every installable kind and when to use each. For an exact composed persona list, use `crtr sys prompt-review --list --kind <kind>` with the target kind. Defaults to your current kind. Promoting from a generic kind? CHOOSE a concrete one — it sets the orchestrator persona you revive into.' },
|
|
661
750
|
{ kind: 'flag', name: 'resident', type: 'bool', required: false, constraint: 'ALSO flip lifecycle→resident: make the node interactable — it stays dormant, woken by inbox/human, and is never forced to submit a final. Omit to stay terminal/orchestrator (delegates + holds a roadmap, but still owes a final up the spine and reaps when done).' },
|
|
662
751
|
{ kind: 'flag', name: 'model', type: 'enum', choices: ['ultra', 'strong'], required: false, constraint: 'Change the model you run on, by capability tier: `ultra` (frontier — reserve for high-taste judgment or enormous work: speccing, planning something large, e2e-testing something hard to test) or `strong` (opus — regular dev work). Omit to keep your current model. An orchestrator steering work is never weaker than opus, so these are the only two choices; the change is durable across future revives.' },
|
|
663
752
|
{ kind: 'flag', name: 'node', type: 'string', required: false, constraint: 'Node to promote. Defaults to the caller (CRTR_NODE_ID).' },
|
|
@@ -1335,9 +1424,96 @@ const nodeWake = defineBranch({
|
|
|
1335
1424
|
},
|
|
1336
1425
|
children: [nodeWakeAt, nodeWakeUntil, nodeWakeSpawn, nodeWakeList, nodeWakeCancel],
|
|
1337
1426
|
});
|
|
1427
|
+
// ── /pyramid slash command ───────────────────────────────────────────────────
|
|
1428
|
+
// Rides on the `node` subtree, not because pyramid is a `node` verb, but because
|
|
1429
|
+
// (1) the workflow IS node orchestration — it fans out explore agents — and
|
|
1430
|
+
// (2) provisionExports lazy-loads only the invoked subtree (build-root.ts), so a
|
|
1431
|
+
// slash spec only gets (re)written to the host's command dirs when its host
|
|
1432
|
+
// subtree runs; `node` is the most-invoked subtree, so `/pyramid` provisions
|
|
1433
|
+
// reliably. The body is a self-contained agent workflow prompt (pi prompt
|
|
1434
|
+
// template / Claude Code command), exported one-way by host-exports.
|
|
1435
|
+
const pyramidSlash = {
|
|
1436
|
+
name: 'pyramid',
|
|
1437
|
+
description: 'Explain a topic as a live-building Minto pyramid diagram, backed by parallel explore agents.',
|
|
1438
|
+
argumentHint: '<topic to explain>',
|
|
1439
|
+
body: [
|
|
1440
|
+
'# Pyramid explanation',
|
|
1441
|
+
'',
|
|
1442
|
+
'Explain **$ARGUMENTS** as a *pyramid*: lead with the answer, support it with a few key pillars, ground each pillar in evidence. You build this as a LIVE termrender diagram that fills in as parallel research lands — the user watches the skeleton grow into a complete picture.',
|
|
1443
|
+
'',
|
|
1444
|
+
'## The pyramid (Minto principle)',
|
|
1445
|
+
'- **Apex** — ONE crisp sentence: the single governing answer/claim, the thing worth remembering.',
|
|
1446
|
+
'- **Pillars** — 2–4 MECE supporting arguments that together prove the apex.',
|
|
1447
|
+
'- **Base** — concrete evidence under each pillar (mechanisms, `file:line` refs, numbers, sources).',
|
|
1448
|
+
'',
|
|
1449
|
+
'Top-down: the reader gets the conclusion first, then descends for as much support as they want.',
|
|
1450
|
+
'',
|
|
1451
|
+
'## Workflow',
|
|
1452
|
+
'',
|
|
1453
|
+
'1. **Frame it.** Restate the topic in one line and commit to a *working* apex hypothesis (you will sharpen it). Name the 2–4 pillars you expect to need.',
|
|
1454
|
+
'',
|
|
1455
|
+
'2. **Scaffold the live diagram FIRST.** Write the termrender skeleton below to `./pyramid-<slug>.md` (apex = your hypothesis, pillars = titles, every base entry marked `[?]` pending). Then open it live so the user watches it build:',
|
|
1456
|
+
' ```bash',
|
|
1457
|
+
' termrender pane open ./pyramid-<slug>.md --watch # detached tmux side-pane; re-renders on every save',
|
|
1458
|
+
' ```',
|
|
1459
|
+
' Not in tmux? Tell the user to run `termrender doc watch ./pyramid-<slug>.md` in another terminal, then continue regardless.',
|
|
1460
|
+
'',
|
|
1461
|
+
'3. **Investigate in parallel — do not block.** Fan out ONE explore agent per pillar/unknown AND dig into what you can answer yourself, concurrently:',
|
|
1462
|
+
' ```bash',
|
|
1463
|
+
' crtr node new "Investigate: <focused question for this pillar>. Report findings with sources / file:line refs." --kind explore',
|
|
1464
|
+
' ```',
|
|
1465
|
+
' You auto-subscribe; each finish wakes you. Never poll or wait — kick them all off, then start filling in what you already know.',
|
|
1466
|
+
'',
|
|
1467
|
+
'4. **Live-update as findings land.** Every time you learn something — your own digging or an explore report — EDIT the diagram file: flip a `[?]` to `[x]` (or `[!]` for a caveat/risk), add evidence under the right pillar, sharpen or rewrite the apex, drop a pillar that did not hold. Each save re-renders the pane. The diagram visibly grows skeleton → complete.',
|
|
1468
|
+
'',
|
|
1469
|
+
'5. **Land it.** When the apex is one crisp sentence, the pillars are MECE, and the base is concrete, do a final pass for accuracy, then give the user a 3–4 sentence spoken summary that mirrors apex → pillars. Tell them the diagram file path.',
|
|
1470
|
+
'',
|
|
1471
|
+
'## termrender skeleton (write this verbatim, then keep editing it)',
|
|
1472
|
+
'',
|
|
1473
|
+
'Apex panel on top, a divider, then the pillars as a row of boxes below — a literal pyramid: 1 claim over N supports.',
|
|
1474
|
+
'```markdown',
|
|
1475
|
+
':::panel{title="<TOPIC>" color="cyan"}',
|
|
1476
|
+
'**<one-line apex answer — your governing claim>**',
|
|
1477
|
+
':::',
|
|
1478
|
+
'',
|
|
1479
|
+
':::divider{label="why"}',
|
|
1480
|
+
':::',
|
|
1481
|
+
'',
|
|
1482
|
+
'::::::columns',
|
|
1483
|
+
':::::col{width="33%"}',
|
|
1484
|
+
'::::panel{title="Pillar 1 — <claim>" color="green"}',
|
|
1485
|
+
':::tree',
|
|
1486
|
+
'evidence A [x]',
|
|
1487
|
+
'evidence B [?]',
|
|
1488
|
+
':::',
|
|
1489
|
+
'::::',
|
|
1490
|
+
':::::',
|
|
1491
|
+
':::::col{width="33%"}',
|
|
1492
|
+
'::::panel{title="Pillar 2 — <claim>" color="green"}',
|
|
1493
|
+
':::tree',
|
|
1494
|
+
'evidence C [?]',
|
|
1495
|
+
':::',
|
|
1496
|
+
'::::',
|
|
1497
|
+
':::::',
|
|
1498
|
+
':::::col{width="34%"}',
|
|
1499
|
+
'::::panel{title="Pillar 3 — <claim>" color="green"}',
|
|
1500
|
+
':::tree',
|
|
1501
|
+
'evidence D [?]',
|
|
1502
|
+
':::',
|
|
1503
|
+
'::::',
|
|
1504
|
+
':::::',
|
|
1505
|
+
'::::::',
|
|
1506
|
+
'```',
|
|
1507
|
+
'',
|
|
1508
|
+
'**Nesting rule (termrender will reject the file otherwise): an OUTER directive needs strictly MORE colons than the directive nested inside it.** Hence `::::::columns` (6) wraps `:::::col` (5) wraps `::::panel` (4) wraps `:::tree` (3). Every block closes with a bare run of its OWN colon count on its own line. Run `termrender doc check ./pyramid-<slug>.md` after each edit — if it errors, fix the colon counts before re-saving.',
|
|
1509
|
+
'',
|
|
1510
|
+
'Markers inside a tree: `[x]` → ✔ confirmed, `[!]` → ⚠ caveat/risk; `[?]` is not a marker and stays literal — use it for still-pending. Write structure only — termrender draws every box, border, and guide line; never hand-draw ASCII. Keep the apex to one sentence; push all detail into the base.',
|
|
1511
|
+
].join('\n'),
|
|
1512
|
+
};
|
|
1338
1513
|
export function registerNode() {
|
|
1339
1514
|
return defineBranch({
|
|
1340
1515
|
name: 'node',
|
|
1516
|
+
slash: pyramidSlash,
|
|
1341
1517
|
rootEntry: {
|
|
1342
1518
|
concept: 'a unit of the agent runtime — an agent on the canvas with its own context dir and pi vehicle. Spawning nodes is how work gets done here, not an optimization you reach for late',
|
|
1343
1519
|
desc: 'spawn, inspect, and navigate nodes on the canvas',
|
|
@@ -1351,6 +1527,6 @@ export function registerNode() {
|
|
|
1351
1527
|
'HOW: `crtr node new "<task>" --kind <kind>` returns a node id immediately and runs the worker as a detached headless broker (no window opens; open a viewer on demand with `crtr node focus`). Match the kind to the work (see `node new -h`). You are woken when a child finishes — the wake message ALREADY IS the coalesced digest (the watcher drains your inbox to wake you), so don\'t re-run `crtr feed read` to "open" it (it would read empty, the cursor already advanced); instead dereference the report paths in that digest that matter, don\'t act on a one-line label. (`crtr feed read` is for proactively polling before a wake, or inspecting a child\'s inbox via `--node`; `--all` re-reads history with full message bodies.) Integrate, then either delegate the next units or finish.\n\n' +
|
|
1352
1528
|
'FINISH: a worker ends its own work with `crtr push final "<result>"` (writes the canonical result, marks done, closes the window) — stopping without it is not finishing. For a job too big for one context window, `node promote` to an orchestrator (holds a roadmap, delegates phases); when context fills, `node yield` to refresh against that roadmap.',
|
|
1353
1529
|
},
|
|
1354
|
-
children: [nodeNew, nodeInspect, nodeFocus, nodeCycle, nodeRecycle, nodeClose, nodeMsg, nodeSubscribe, nodeUnsubscribe, nodePromote, nodeDemote, nodeLifecycle, nodeYield, nodeWake],
|
|
1530
|
+
children: [nodeNew, nodeInspect, nodeSnapshotLeaf, nodeContextLeaf, nodeFocus, nodeCycle, nodeRecycle, nodeClose, nodeMsg, nodeModel, nodeSubscribe, nodeUnsubscribe, nodePromote, nodeDemote, nodeLifecycle, nodeYield, nodeWake],
|
|
1355
1531
|
});
|
|
1356
1532
|
}
|
|
@@ -94,7 +94,7 @@ const pluginShow = defineLeaf({
|
|
|
94
94
|
{ name: 'path', type: 'string', required: true, constraint: 'Absolute path to the plugin directory.' },
|
|
95
95
|
{ name: 'enabled', type: 'boolean', required: true, constraint: 'Whether the plugin is active.' },
|
|
96
96
|
{ name: 'manifest', type: 'object', required: true, constraint: 'Full plugin.json contents.' },
|
|
97
|
-
{ name: '
|
|
97
|
+
{ name: 'docs', type: 'object[]', required: true, constraint: 'Each: {name, path}. Memory docs provided by the plugin (its `<pluginName>/` memory subtree).' },
|
|
98
98
|
],
|
|
99
99
|
outputKind: 'object',
|
|
100
100
|
effects: ['None. Read-only.'],
|
|
@@ -119,16 +119,16 @@ const pluginShow = defineLeaf({
|
|
|
119
119
|
throw notFound(`plugin not found: ${name}`);
|
|
120
120
|
}
|
|
121
121
|
const prefix = `${found.name}/`;
|
|
122
|
-
const
|
|
122
|
+
const docs = listAllMemoryDocs().filter((d) => d.name.startsWith(prefix));
|
|
123
123
|
return {
|
|
124
124
|
name: found.name,
|
|
125
125
|
scope: found.scope,
|
|
126
126
|
path: found.root,
|
|
127
127
|
enabled: found.enabled,
|
|
128
128
|
manifest: found.manifest,
|
|
129
|
-
|
|
130
|
-
name:
|
|
131
|
-
path:
|
|
129
|
+
docs: docs.map((d) => ({
|
|
130
|
+
name: d.name,
|
|
131
|
+
path: d.path,
|
|
132
132
|
})),
|
|
133
133
|
};
|
|
134
134
|
},
|
|
@@ -136,7 +136,7 @@ const pluginShow = defineLeaf({
|
|
|
136
136
|
export const pluginInspectBranch = defineBranch({
|
|
137
137
|
name: 'inspect',
|
|
138
138
|
description: 'list or show installed plugins',
|
|
139
|
-
whenToUse: 'reading installed plugin metadata to decide before you change anything — list what is installed, or show the manifest and
|
|
139
|
+
whenToUse: 'reading installed plugin metadata to decide before you change anything — list what is installed, or show the manifest and memory docs of one plugin. Read-only; switch to `pkg plugin manage` to actually install, enable, disable, or remove',
|
|
140
140
|
help: {
|
|
141
141
|
name: 'pkg plugin inspect',
|
|
142
142
|
summary: 'read plugin metadata without modifying state',
|
|
@@ -146,7 +146,7 @@ const pluginRemove = defineLeaf({
|
|
|
146
146
|
const pluginEnable = defineLeaf({
|
|
147
147
|
name: 'enable',
|
|
148
148
|
description: 'enable a plugin',
|
|
149
|
-
whenToUse: 'reactivating a plugin that was previously disabled so its
|
|
149
|
+
whenToUse: 'reactivating a plugin that was previously disabled so its memory docs resolve again',
|
|
150
150
|
help: {
|
|
151
151
|
name: 'pkg plugin manage enable',
|
|
152
152
|
summary: 'enable a plugin in the given scope',
|
|
@@ -7,8 +7,8 @@ export const pluginBranch = defineBranch({
|
|
|
7
7
|
whenToUse: 'working with individual plugins directly — installing one from a git URL, inspecting or showing what a plugin provides, or enabling, disabling, removing, and updating an installed plugin. Use `pkg market` instead when you want a curated collection: browsing a marketplace index and installing plugins by name from it rather than handling raw git URLs yourself',
|
|
8
8
|
help: {
|
|
9
9
|
name: 'pkg plugin',
|
|
10
|
-
summary: 'install and manage plugins that extend crtr with
|
|
11
|
-
model: 'Plugins are git repos or local directories containing a .crouter-plugin/plugin.json manifest and a
|
|
10
|
+
summary: 'install and manage plugins that extend crtr with memory docs',
|
|
11
|
+
model: 'Plugins are git repos or local directories containing a .crouter-plugin/plugin.json manifest and a memory/ directory.',
|
|
12
12
|
},
|
|
13
13
|
children: [pluginManageBranch, pluginInspectBranch],
|
|
14
14
|
});
|
package/dist/commands/pkg.js
CHANGED
|
@@ -8,9 +8,9 @@ export function registerPkg() {
|
|
|
8
8
|
return defineBranch({
|
|
9
9
|
name: 'pkg',
|
|
10
10
|
rootEntry: {
|
|
11
|
-
concept: 'plugins and marketplaces that supply
|
|
11
|
+
concept: 'plugins and marketplaces that supply memory docs',
|
|
12
12
|
desc: 'manage plugins and marketplaces',
|
|
13
|
-
useWhen: 'installing or browsing
|
|
13
|
+
useWhen: 'installing or browsing memory-doc collections',
|
|
14
14
|
},
|
|
15
15
|
help: {
|
|
16
16
|
name: 'pkg',
|
package/dist/commands/push.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { BranchDef } from '../core/command.js';
|
|
2
|
+
import { InputError } from '../core/io.js';
|
|
3
|
+
export declare function mapFinalizeTransitionRaceError(nodeStatus: string | null | undefined, err: unknown): InputError | null;
|
|
2
4
|
export declare function registerPush(): BranchDef;
|
|
3
5
|
export declare function registerFeed(): BranchDef;
|