@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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { defineLeaf } from '../../core/command.js';
|
|
3
|
+
import { startWebServer } from '../../clients/web/server.js';
|
|
4
|
+
const DEFAULT_PORT = 7878;
|
|
5
|
+
const PROMPT_STUDIO_PATH = '/views/prompt-review';
|
|
6
|
+
function openBrowser(url) {
|
|
7
|
+
const [cmd, args] = process.platform === 'darwin'
|
|
8
|
+
? ['open', [url]]
|
|
9
|
+
: process.platform === 'win32'
|
|
10
|
+
? ['cmd', ['/c', 'start', '', url]]
|
|
11
|
+
: ['xdg-open', [url]];
|
|
12
|
+
try {
|
|
13
|
+
const child = spawn(cmd, args, { stdio: 'ignore', detached: true });
|
|
14
|
+
child.on('error', () => {
|
|
15
|
+
/* the printed URL is enough when no browser opener is available */
|
|
16
|
+
});
|
|
17
|
+
child.unref();
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
/* the printed URL is enough when no browser opener is available */
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export const sysPromptStudioLeaf = defineLeaf({
|
|
24
|
+
name: 'promptstudio',
|
|
25
|
+
description: 'open Prompt Studio in the browser',
|
|
26
|
+
whenToUse: 'you want the Prompt Studio browser UI — a prompt review surface for toggling crouter persona/mode/lifecycle configs, inspecting the assembled system prompt, comparing configurations, and exporting review comments with source-file pointers.',
|
|
27
|
+
help: {
|
|
28
|
+
name: 'sys promptstudio',
|
|
29
|
+
summary: 'start the crouter web server and open Prompt Studio directly',
|
|
30
|
+
params: [
|
|
31
|
+
{ kind: 'flag', name: 'port', type: 'int', required: false, default: DEFAULT_PORT, constraint: `TCP port to bind on 127.0.0.1. Default ${DEFAULT_PORT}.` },
|
|
32
|
+
{ kind: 'flag', name: 'dev', type: 'bool', required: false, default: false, constraint: 'Serve the web shell through Vite middleware/HMR while iterating on Prompt Studio or the web client.' },
|
|
33
|
+
],
|
|
34
|
+
output: [
|
|
35
|
+
{ name: 'url', type: 'string', required: true, constraint: 'Prompt Studio URL opened in the browser.' },
|
|
36
|
+
],
|
|
37
|
+
outputKind: 'object',
|
|
38
|
+
effects: [
|
|
39
|
+
'Binds the same long-running local web server as `crtr web serve`, opens `/views/prompt-review` in the default browser, and keeps serving until ctrl+c/SIGTERM.',
|
|
40
|
+
'The Prompt Studio view uses the existing source bridge to call `crtr sys prompt-review` for composed prompts and review export.',
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
run: async (input) => {
|
|
44
|
+
const port = input['port'] ?? DEFAULT_PORT;
|
|
45
|
+
const dev = input['dev'] ?? false;
|
|
46
|
+
const server = await startWebServer({ port, dev });
|
|
47
|
+
const url = `${server.url}${PROMPT_STUDIO_PATH}`;
|
|
48
|
+
process.stdout.write(`Prompt Studio serving at ${url}${dev ? ' (--dev: Vite middleware)' : ''}\n` +
|
|
49
|
+
` bridge: POST ${server.url}/__crtr/source\n` +
|
|
50
|
+
` events (SSE): GET ${server.url}/__crtr/events\n` +
|
|
51
|
+
` shell assets: ${dev ? 'Vite middleware (HMR)' : server.clientDir}\n` +
|
|
52
|
+
` (ctrl+c to stop)\n`);
|
|
53
|
+
openBrowser(url);
|
|
54
|
+
await new Promise((resolveShutdown) => {
|
|
55
|
+
const shutdown = () => {
|
|
56
|
+
void server.close().then(() => resolveShutdown());
|
|
57
|
+
};
|
|
58
|
+
process.once('SIGINT', shutdown);
|
|
59
|
+
process.once('SIGTERM', shutdown);
|
|
60
|
+
process.once('SIGHUP', shutdown);
|
|
61
|
+
});
|
|
62
|
+
return { url };
|
|
63
|
+
},
|
|
64
|
+
render: () => '',
|
|
65
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineLeaf } from '../../core/command.js';
|
|
2
|
+
import { viewRunLeaf } from '../view-run.js';
|
|
3
|
+
export const sysSettingsLeaf = defineLeaf({
|
|
4
|
+
name: 'settings',
|
|
5
|
+
description: 'open the model ladders settings view',
|
|
6
|
+
whenToUse: 'you want to open the built-in model ladders settings view in tmux — the same interactive surface as `crtr view run settings`. Use this from `crtr sys` when you want the settings opener beside the rest of system config.',
|
|
7
|
+
help: {
|
|
8
|
+
name: 'sys settings',
|
|
9
|
+
summary: 'open the built-in model ladders settings view',
|
|
10
|
+
inputNote: 'No input parameters.',
|
|
11
|
+
output: [],
|
|
12
|
+
outputKind: 'object',
|
|
13
|
+
effects: ['Hosts the built-in `settings` view via `crtr view run settings`, preserving the same tmux and non-TTY behavior.'],
|
|
14
|
+
},
|
|
15
|
+
run: async () => viewRunLeaf.run({ name: 'settings' }),
|
|
16
|
+
});
|
|
@@ -1,187 +1,339 @@
|
|
|
1
|
-
// `crtr sys sync` —
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
// `crtr sys sync` — explicit migration from legacy host Agent Skill bundles into
|
|
2
|
+
// crouter memory documents. It is NOT a bidirectional SKILL.md sync surface: the
|
|
3
|
+
// crouter side after a sync is a plain memory/<name>.md document.
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
import { basename, dirname, join, relative, resolve, sep } from 'node:path';
|
|
7
7
|
import { defineLeaf } from '../../core/command.js';
|
|
8
8
|
import { usage } from '../../core/errors.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
9
|
+
import { parseFrontmatterGeneric } from '../../core/frontmatter.js';
|
|
10
|
+
import { pathExists, readJsonIfExists, readText, walkFiles, writeJson, writeText } from '../../core/fs-utils.js';
|
|
11
|
+
import { findProjectScopeRoot, scopeMemoryDir } from '../../core/scope.js';
|
|
12
|
+
import { memoryFilePath, resolveWriteTarget, serializeMemoryDoc } from '../memory/shared.js';
|
|
13
|
+
const LEGACY_BOOT_SKILL_MARKER_PREFIX = '<!-- crtr-boot-skill v';
|
|
14
|
+
const HOST_SKILL_FILE = 'SKILL.md';
|
|
15
|
+
const IGNORE_FILE = 'skill-import-ignore.json';
|
|
16
|
+
function projectDir() {
|
|
17
|
+
const root = findProjectScopeRoot();
|
|
18
|
+
return root ? dirname(root) : null;
|
|
19
|
+
}
|
|
20
|
+
function ignoreFilePath() {
|
|
21
|
+
return join(homedir(), '.crouter', IGNORE_FILE);
|
|
22
|
+
}
|
|
23
|
+
function defaultSourceRoots() {
|
|
24
|
+
const roots = [
|
|
25
|
+
{ label: 'claude-user', root: join(homedir(), '.claude', 'skills'), defaultScope: 'user' },
|
|
26
|
+
{ label: 'pi-user', root: join(homedir(), '.pi', 'agent', 'skills'), defaultScope: 'user' },
|
|
27
|
+
];
|
|
28
|
+
const proj = projectDir();
|
|
29
|
+
if (proj) {
|
|
30
|
+
roots.push({ label: 'claude-project', root: join(proj, '.claude', 'skills'), defaultScope: 'project' });
|
|
31
|
+
roots.push({ label: 'pi-project', root: join(proj, '.pi', 'agent', 'skills'), defaultScope: 'project' });
|
|
32
|
+
}
|
|
33
|
+
return roots;
|
|
34
|
+
}
|
|
35
|
+
function sourceRootsFromArg(sourceArg, scopeArg) {
|
|
36
|
+
if (sourceArg === undefined)
|
|
37
|
+
return defaultSourceRoots();
|
|
38
|
+
const root = resolve(sourceArg);
|
|
39
|
+
if (scopeArg !== undefined && scopeArg !== 'user' && scopeArg !== 'project') {
|
|
40
|
+
resolveWriteTarget(scopeArg);
|
|
41
|
+
}
|
|
42
|
+
return [{ label: 'source', root, defaultScope: scopeArg ?? 'user' }];
|
|
43
|
+
}
|
|
44
|
+
function collectCandidates(rootDef) {
|
|
45
|
+
const root = rootDef.root;
|
|
46
|
+
if (!existsSync(root))
|
|
47
|
+
return [];
|
|
48
|
+
const statRoot = resolve(root);
|
|
49
|
+
const candidates = [];
|
|
50
|
+
if (basename(statRoot) === HOST_SKILL_FILE) {
|
|
51
|
+
candidates.push({ path: statRoot, root: dirname(statRoot), source: rootDef.label, defaultScope: rootDef.defaultScope });
|
|
52
|
+
return candidates;
|
|
53
|
+
}
|
|
54
|
+
const directSkill = join(statRoot, HOST_SKILL_FILE);
|
|
55
|
+
if (existsSync(directSkill)) {
|
|
56
|
+
candidates.push({ path: directSkill, root: dirname(statRoot), source: rootDef.label, defaultScope: rootDef.defaultScope });
|
|
57
|
+
return candidates;
|
|
58
|
+
}
|
|
59
|
+
for (const file of walkFiles(statRoot, (name) => name === HOST_SKILL_FILE)) {
|
|
60
|
+
candidates.push({ path: file, root: statRoot, source: rootDef.label, defaultScope: rootDef.defaultScope });
|
|
61
|
+
}
|
|
62
|
+
return candidates;
|
|
63
|
+
}
|
|
64
|
+
function scalarString(value) {
|
|
65
|
+
if (typeof value === 'string')
|
|
66
|
+
return value;
|
|
67
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
68
|
+
return String(value);
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
function cleanClause(s) {
|
|
72
|
+
let out = s.replace(/\s+/g, ' ').trim();
|
|
73
|
+
out = out.replace(/^[,;:.\s]+/, '').replace(/[,;:.\s]+$/, '');
|
|
74
|
+
if (/^[A-Z][a-z]/.test(out))
|
|
75
|
+
out = out.charAt(0).toLowerCase() + out.slice(1);
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
const USE_WHEN_RE = /\b(?:use\s+this\s+skill\s+when|use\s+this\s+when|this\s+skill\s+should\s+be\s+used\s+when|used\s+when|use\s+when)\b\s*/i;
|
|
79
|
+
function routeFromDescription(description, kind) {
|
|
80
|
+
const desc = description.replace(/\s+/g, ' ').trim();
|
|
81
|
+
if (desc === '')
|
|
82
|
+
return `When this migrated ${kind} applies, this ${kind} should be read.`;
|
|
83
|
+
const m = desc.match(USE_WHEN_RE);
|
|
84
|
+
if (m && m.index !== undefined) {
|
|
85
|
+
const gist = cleanClause(desc.slice(0, m.index));
|
|
86
|
+
const situation = cleanClause(desc.slice(m.index + m[0].length));
|
|
87
|
+
if (situation !== '') {
|
|
88
|
+
let out = `When ${situation}, this ${kind} should be read`;
|
|
89
|
+
if (gist !== '')
|
|
90
|
+
out += ` because ${gist}`;
|
|
91
|
+
return `${out}.`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return `When ${cleanClause(desc)}, this ${kind} should be read.`;
|
|
95
|
+
}
|
|
96
|
+
function normalizedName(raw) {
|
|
97
|
+
const segments = raw
|
|
98
|
+
.replace(/\\/g, '/')
|
|
99
|
+
.replace(/\.md$/i, '')
|
|
100
|
+
.split('/')
|
|
101
|
+
.map((s) => s.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^-+|-+$/g, ''))
|
|
102
|
+
.filter(Boolean);
|
|
103
|
+
return segments.join('/');
|
|
104
|
+
}
|
|
105
|
+
function nameForCandidate(candidate, fm) {
|
|
106
|
+
const fmName = scalarString(fm?.name);
|
|
107
|
+
if (fmName && fmName.trim() !== '')
|
|
108
|
+
return normalizedName(fmName);
|
|
109
|
+
const relDir = relative(candidate.root, dirname(candidate.path)).split(sep).join('/');
|
|
110
|
+
return normalizedName(relDir || basename(dirname(candidate.path)));
|
|
111
|
+
}
|
|
112
|
+
function targetMemoryDir(scope) {
|
|
113
|
+
const dir = scopeMemoryDir(scope);
|
|
114
|
+
if (!dir)
|
|
115
|
+
return resolveWriteTarget(scope).memoryDir;
|
|
116
|
+
return dir;
|
|
117
|
+
}
|
|
118
|
+
function readIgnoreState() {
|
|
119
|
+
let doc;
|
|
120
|
+
try {
|
|
121
|
+
doc = readJsonIfExists(ignoreFilePath());
|
|
24
122
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
.map((r) => `| ${r.id} | ${r.status} | ${r.wrote} |`)
|
|
28
|
-
.join('\n');
|
|
29
|
-
parts.push(`| pair | status | wrote |\n| --- | --- | --- |\n${rows}`);
|
|
123
|
+
catch (e) {
|
|
124
|
+
throw usage(`invalid JSON in ${ignoreFilePath()}: ${e instanceof Error ? e.message : String(e)}`);
|
|
30
125
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
126
|
+
if (doc === null)
|
|
127
|
+
return { version: 1, ignored: [] };
|
|
128
|
+
if (typeof doc !== 'object' ||
|
|
129
|
+
doc === null ||
|
|
130
|
+
doc.version !== 1 ||
|
|
131
|
+
!Array.isArray(doc.ignored)) {
|
|
132
|
+
throw usage(`malformed ${ignoreFilePath()}: expected {"version":1,"ignored":[...]}`);
|
|
37
133
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
/** Render one endpoint as `scope/name` (or `<scope>:<plugin>/<name>` for a
|
|
50
|
-
* plugin-scoped side) so a reader sees where each half of the pair lives. */
|
|
51
|
-
function endpointLabel(ep) {
|
|
52
|
-
return ep.scope === 'plugin' || ep.scope === 'claude-plugin'
|
|
53
|
-
? `${ep.scope}:${ep.plugin}/${ep.name}`
|
|
54
|
-
: `${ep.scope}/${ep.name}`;
|
|
55
|
-
}
|
|
56
|
-
/** Render the read-only `--status` inventory: every selected pair with its
|
|
57
|
-
* crtr↔Claude endpoints and drift state, computed via a dry-run reconcile so
|
|
58
|
-
* nothing is written. `results` is keyed back to `pairs` by id. */
|
|
59
|
-
function renderStatus(pairs, results) {
|
|
60
|
-
const parts = [];
|
|
61
|
-
parts.push('crtr ↔ Claude skill-sync pairs (read-only; nothing written):');
|
|
62
|
-
if (pairs.length === 0) {
|
|
63
|
-
parts.push('No enrolled pairs.');
|
|
64
|
-
return parts.join('\n\n');
|
|
134
|
+
const ignored = [];
|
|
135
|
+
for (const entry of doc.ignored) {
|
|
136
|
+
if (typeof entry !== 'object' || entry === null)
|
|
137
|
+
continue;
|
|
138
|
+
const e = entry;
|
|
139
|
+
if (typeof e.source === 'string' &&
|
|
140
|
+
typeof e.name === 'string' &&
|
|
141
|
+
(e.scope === 'user' || e.scope === 'project') &&
|
|
142
|
+
typeof e.ignoredAt === 'string') {
|
|
143
|
+
ignored.push({ source: resolve(e.source), name: e.name, scope: e.scope, ignoredAt: e.ignoredAt });
|
|
144
|
+
}
|
|
65
145
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
146
|
+
return { version: 1, ignored };
|
|
147
|
+
}
|
|
148
|
+
function writeIgnoreState(state) {
|
|
149
|
+
writeJson(ignoreFilePath(), state);
|
|
150
|
+
}
|
|
151
|
+
function isIgnored(prepared, state) {
|
|
152
|
+
const source = resolve(prepared.candidate.path);
|
|
153
|
+
return state.ignored.some((entry) => entry.source === source ||
|
|
154
|
+
(entry.scope === prepared.scope && entry.name === prepared.name));
|
|
155
|
+
}
|
|
156
|
+
function rememberIgnored(prepared, state) {
|
|
157
|
+
if (isIgnored(prepared, state))
|
|
158
|
+
return false;
|
|
159
|
+
state.ignored.push({
|
|
160
|
+
source: resolve(prepared.candidate.path),
|
|
161
|
+
name: prepared.name,
|
|
162
|
+
scope: prepared.scope,
|
|
163
|
+
ignoredAt: new Date().toISOString(),
|
|
164
|
+
});
|
|
165
|
+
state.ignored.sort((a, b) => `${a.scope}/${a.name}`.localeCompare(`${b.scope}/${b.name}`));
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
function skipResult(candidate, scope, reason) {
|
|
169
|
+
return { source: candidate.path, target: '', name: '', scope, status: 'skipped', reason };
|
|
170
|
+
}
|
|
171
|
+
function prepareCandidate(candidate, scopeOverride) {
|
|
172
|
+
const raw = readText(candidate.path);
|
|
173
|
+
const scope = scopeOverride ?? candidate.defaultScope;
|
|
174
|
+
if (raw.includes(LEGACY_BOOT_SKILL_MARKER_PREFIX)) {
|
|
175
|
+
return skipResult(candidate, scope, 'legacy generated crtr boot skill is pruned by host exports, not imported');
|
|
176
|
+
}
|
|
177
|
+
const parsed = parseFrontmatterGeneric(raw);
|
|
178
|
+
const sourceFm = parsed.data ?? {};
|
|
179
|
+
const kind = sourceFm.kind === 'preference' ? 'preference' : 'knowledge';
|
|
180
|
+
const name = nameForCandidate(candidate, sourceFm);
|
|
181
|
+
if (name === '')
|
|
182
|
+
return skipResult(candidate, scope, 'could not derive memory document name');
|
|
183
|
+
const memoryDir = targetMemoryDir(scope);
|
|
184
|
+
const target = memoryFilePath(memoryDir, name);
|
|
185
|
+
return { candidate, raw, parsed, sourceFm, kind, name, scope, target };
|
|
186
|
+
}
|
|
187
|
+
function convertPrepared(prepared, opts) {
|
|
188
|
+
if (pathExists(prepared.target) && !opts.overwrite) {
|
|
189
|
+
return {
|
|
190
|
+
source: prepared.candidate.path,
|
|
191
|
+
target: prepared.target,
|
|
192
|
+
name: prepared.name,
|
|
193
|
+
scope: prepared.scope,
|
|
194
|
+
status: 'skipped',
|
|
195
|
+
reason: 'target memory doc already exists; re-run with --overwrite to replace it',
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
const description = scalarString(prepared.sourceFm.description) ?? '';
|
|
199
|
+
const frontmatter = { ...prepared.sourceFm };
|
|
200
|
+
delete frontmatter.name;
|
|
201
|
+
delete frontmatter.description;
|
|
202
|
+
delete frontmatter.type;
|
|
203
|
+
delete frontmatter.keywords;
|
|
204
|
+
frontmatter.kind = prepared.kind;
|
|
205
|
+
if (typeof frontmatter['when-and-why-to-read'] !== 'string' || frontmatter['when-and-why-to-read'].trim() === '') {
|
|
206
|
+
frontmatter['when-and-why-to-read'] = routeFromDescription(description, prepared.kind);
|
|
207
|
+
}
|
|
208
|
+
if (typeof frontmatter['short-form'] !== 'string' || frontmatter['short-form'].trim() === '') {
|
|
209
|
+
frontmatter['short-form'] = description.replace(/\s+/g, ' ').trim();
|
|
210
|
+
}
|
|
211
|
+
if (typeof frontmatter['system-prompt-visibility'] !== 'string')
|
|
212
|
+
frontmatter['system-prompt-visibility'] = 'preview';
|
|
213
|
+
if (typeof frontmatter['file-read-visibility'] !== 'string')
|
|
214
|
+
frontmatter['file-read-visibility'] = 'none';
|
|
215
|
+
if (!opts.dryRun)
|
|
216
|
+
writeText(prepared.target, serializeMemoryDoc(frontmatter, prepared.parsed.body));
|
|
217
|
+
return {
|
|
218
|
+
source: prepared.candidate.path,
|
|
219
|
+
target: prepared.target,
|
|
220
|
+
name: prepared.name,
|
|
221
|
+
scope: prepared.scope,
|
|
222
|
+
status: opts.dryRun ? 'would-import' : 'imported',
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function ignoreResult(prepared, reason, dryRun) {
|
|
226
|
+
return {
|
|
227
|
+
source: prepared.candidate.path,
|
|
228
|
+
target: prepared.target,
|
|
229
|
+
name: prepared.name,
|
|
230
|
+
scope: prepared.scope,
|
|
231
|
+
status: dryRun ? 'would-ignore' : 'ignored',
|
|
232
|
+
reason,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function renderSummary(results, ignoreMode) {
|
|
236
|
+
const imported = results.filter((r) => r.status === 'imported').length;
|
|
237
|
+
const wouldImport = results.filter((r) => r.status === 'would-import').length;
|
|
238
|
+
const skipped = results.filter((r) => r.status === 'skipped').length;
|
|
239
|
+
const ignored = results.filter((r) => r.status === 'ignored').length;
|
|
240
|
+
const wouldIgnore = results.filter((r) => r.status === 'would-ignore').length;
|
|
241
|
+
let header;
|
|
242
|
+
if (ignoreMode)
|
|
243
|
+
header = `crtr sys sync — ${wouldIgnore > 0 ? `${wouldIgnore} would ignore` : `${ignored} ignored`}, ${skipped} skipped`;
|
|
244
|
+
else if (wouldImport > 0)
|
|
245
|
+
header = `crtr sys sync — dry run: ${wouldImport} would import, ${skipped} skipped, ${ignored} ignored`;
|
|
246
|
+
else
|
|
247
|
+
header = `crtr sys sync — ${imported} imported, ${skipped} skipped, ${ignored} ignored`;
|
|
248
|
+
const rows = results.map((r) => {
|
|
249
|
+
const target = r.target || '—';
|
|
250
|
+
const reason = r.reason ? ` (${r.reason})` : '';
|
|
251
|
+
return `| ${r.status} | ${r.scope}/${r.name || '—'} | ${target} | ${r.source}${reason} |`;
|
|
252
|
+
});
|
|
253
|
+
const body = rows.length === 0
|
|
254
|
+
? ['No sync candidates.']
|
|
255
|
+
: ['| status | memory doc | target | source |', '| --- | --- | --- | --- |', ...rows];
|
|
256
|
+
return [header, '', ...body].join('\n');
|
|
79
257
|
}
|
|
80
258
|
export const sysSyncLeaf = defineLeaf({
|
|
81
259
|
name: 'sync',
|
|
82
|
-
description: '
|
|
83
|
-
whenToUse: '
|
|
260
|
+
description: 'convert legacy SKILL.md bundles into crouter memory docs',
|
|
261
|
+
whenToUse: 'migrating host-native Agent Skill bundles into the crouter memory-doc model. This is a one-way import from SKILL.md to memory/<name>.md; it never exports memory docs back to SKILL.md and never treats SKILL.md as an active crouter guidance surface.',
|
|
84
262
|
help: {
|
|
85
263
|
name: 'sys sync',
|
|
86
|
-
summary: '
|
|
264
|
+
summary: 'one-way import: SKILL.md bundles → crouter memory docs',
|
|
87
265
|
params: [
|
|
88
|
-
{
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
kind: 'flag',
|
|
97
|
-
name: 'dry-run',
|
|
98
|
-
type: 'bool',
|
|
99
|
-
required: false,
|
|
100
|
-
constraint: 'Compute every merge and report the would-be status, but write nothing — no endpoint, snapshot, or conflict report touched.',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
kind: 'flag',
|
|
104
|
-
name: 'status',
|
|
105
|
-
type: 'bool',
|
|
106
|
-
required: false,
|
|
107
|
-
constraint: 'Read-only inventory mode: instead of reconciling, list every enrolled pair (honoring --pair) with its crtr↔Claude endpoints and drift state (in-sync / would-write / conflict), computed via a dry-run reconcile. Writes nothing and never exits non-zero on drift; a malformed manifest or unknown --pair id still aborts hard.',
|
|
108
|
-
},
|
|
266
|
+
{ kind: 'flag', name: 'source', type: 'string', required: false, constraint: 'A SKILL.md file, a single skill bundle dir containing SKILL.md, or a skills root to scan recursively. Default: user/project Claude and pi skill roots that exist.' },
|
|
267
|
+
{ kind: 'flag', name: 'scope', type: 'enum', choices: ['user', 'project'], required: false, constraint: 'Target memory scope. Default: user for user host roots and project for project host roots; explicit value applies to every imported source.' },
|
|
268
|
+
{ kind: 'flag', name: 'dry-run', type: 'bool', required: false, constraint: 'Show what would be imported without writing memory docs.' },
|
|
269
|
+
{ kind: 'flag', name: 'overwrite', type: 'bool', required: false, constraint: 'Replace an existing target memory doc. Default: skip existing docs to avoid clobbering user-authored memory.' },
|
|
270
|
+
{ kind: 'flag', name: 'ignore', type: 'bool', required: false, constraint: `Permanently ignore every selected source by recording it in ~/.crouter/${IGNORE_FILE}. Honors --source/--scope; with no --source, ignores every currently discovered default host skill candidate.` },
|
|
271
|
+
{ kind: 'flag', name: 'include-ignored', type: 'bool', required: false, constraint: 'Include ignored candidates in the report without making sync read-only. Pair with --dry-run to audit the full candidate set without importing non-ignored skills.' },
|
|
109
272
|
],
|
|
110
273
|
output: [
|
|
111
|
-
{ name: '
|
|
112
|
-
{ name: '
|
|
113
|
-
{ name: '
|
|
114
|
-
{ name: '
|
|
274
|
+
{ name: 'imported', type: 'number', required: true, constraint: 'Count of memory docs written.' },
|
|
275
|
+
{ name: 'skipped', type: 'number', required: true, constraint: 'Count of SKILL.md files skipped.' },
|
|
276
|
+
{ name: 'ignored', type: 'number', required: true, constraint: 'Count of selected SKILL.md files that are permanently ignored.' },
|
|
277
|
+
{ name: 'wouldIgnore', type: 'number', required: true, constraint: 'Count of selected SKILL.md files that would be ignored under --dry-run.' },
|
|
278
|
+
{ name: 'results', type: 'object[]', required: true, constraint: 'Each: {source,target,name,scope,status,reason?}; status may be imported, skipped, would-import, ignored, or would-ignore.' },
|
|
115
279
|
],
|
|
116
280
|
outputKind: 'object',
|
|
117
281
|
effects: [
|
|
118
|
-
'
|
|
119
|
-
'
|
|
120
|
-
'
|
|
121
|
-
|
|
122
|
-
'With --
|
|
282
|
+
'Writes memory/<name>.md in the selected crouter scope with substrate frontmatter and the SKILL.md body.',
|
|
283
|
+
'Skips existing memory docs unless --overwrite is present.',
|
|
284
|
+
'Skips marker-bearing generated crtr boot skills; host exports prune those legacy artifacts instead.',
|
|
285
|
+
`With --ignore: writes ~/.crouter/${IGNORE_FILE} and does not import the selected sources.`,
|
|
286
|
+
'With --dry-run: read-only; writes nothing.',
|
|
123
287
|
],
|
|
124
288
|
},
|
|
125
289
|
run: async (input) => {
|
|
126
|
-
const
|
|
290
|
+
const sourceArg = input['source'];
|
|
291
|
+
const scopeArg = input['scope'];
|
|
127
292
|
const dryRun = input['dryRun'] ?? false;
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
next: `Valid pair ids: ${valid.length > 0 ? valid.join(', ') : '(none)'}. Run \`crtr sys sync -h\`.`,
|
|
141
|
-
});
|
|
293
|
+
const overwrite = input['overwrite'] ?? false;
|
|
294
|
+
const ignoreMode = input['ignore'] ?? false;
|
|
295
|
+
const includeIgnored = input['includeIgnored'] ?? false;
|
|
296
|
+
const roots = sourceRootsFromArg(sourceArg, scopeArg);
|
|
297
|
+
const seen = new Set();
|
|
298
|
+
const candidates = [];
|
|
299
|
+
for (const root of roots) {
|
|
300
|
+
for (const c of collectCandidates(root)) {
|
|
301
|
+
if (seen.has(c.path))
|
|
302
|
+
continue;
|
|
303
|
+
seen.add(c.path);
|
|
304
|
+
candidates.push(c);
|
|
142
305
|
}
|
|
143
306
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
crtr: p.crtr,
|
|
153
|
-
claude: p.claude,
|
|
154
|
-
drift: DRIFT[results[i].status],
|
|
155
|
-
})),
|
|
156
|
-
});
|
|
307
|
+
const ignoreState = readIgnoreState();
|
|
308
|
+
const results = [];
|
|
309
|
+
let changedIgnoreState = false;
|
|
310
|
+
for (const candidate of candidates) {
|
|
311
|
+
const prepared = prepareCandidate(candidate, scopeArg);
|
|
312
|
+
if ('status' in prepared) {
|
|
313
|
+
results.push(prepared);
|
|
314
|
+
continue;
|
|
157
315
|
}
|
|
158
|
-
|
|
159
|
-
|
|
316
|
+
if (ignoreMode) {
|
|
317
|
+
if (!dryRun)
|
|
318
|
+
changedIgnoreState = rememberIgnored(prepared, ignoreState) || changedIgnoreState;
|
|
319
|
+
results.push(ignoreResult(prepared, dryRun ? 'would record permanent ignore' : `recorded in ~/.crouter/${IGNORE_FILE}`, dryRun));
|
|
320
|
+
continue;
|
|
160
321
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const results = [];
|
|
168
|
-
for (const pair of selected) {
|
|
169
|
-
const profile = resolveProfile(pair.frontmatter);
|
|
170
|
-
results.push(reconcilePair(pair, profile, { dryRun }));
|
|
171
|
-
}
|
|
172
|
-
const summary = {
|
|
173
|
-
synced: results.filter((r) => r.status === 'synced').map((r) => r.id),
|
|
174
|
-
conflicts: results.filter((r) => r.status === 'conflict').map((r) => r.id),
|
|
175
|
-
noop: results.filter((r) => r.status === 'noop').map((r) => r.id),
|
|
176
|
-
wrote: results.reduce((n, r) => n + r.wrote, 0),
|
|
177
|
-
};
|
|
178
|
-
if (isJsonOutput()) {
|
|
179
|
-
emit(summary);
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
process.stdout.write(renderSync(results, summary, dryRun) + '\n');
|
|
322
|
+
if (isIgnored(prepared, ignoreState)) {
|
|
323
|
+
if (includeIgnored)
|
|
324
|
+
results.push(ignoreResult(prepared, `matched ~/.crouter/${IGNORE_FILE}`, false));
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
results.push(convertPrepared(prepared, { dryRun, overwrite }));
|
|
183
328
|
}
|
|
184
|
-
|
|
185
|
-
|
|
329
|
+
if (changedIgnoreState)
|
|
330
|
+
writeIgnoreState(ignoreState);
|
|
331
|
+
const imported = results.filter((r) => r.status === 'imported').length;
|
|
332
|
+
const wouldImport = results.filter((r) => r.status === 'would-import').length;
|
|
333
|
+
const skipped = results.filter((r) => r.status === 'skipped').length;
|
|
334
|
+
const ignored = results.filter((r) => r.status === 'ignored').length;
|
|
335
|
+
const wouldIgnore = results.filter((r) => r.status === 'would-ignore').length;
|
|
336
|
+
return { imported, wouldImport, skipped, ignored, wouldIgnore, results, ignoreFile: ignoreFilePath(), ignoreMode };
|
|
186
337
|
},
|
|
338
|
+
render: (result) => renderSummary(result.results, result.ignoreMode === true),
|
|
187
339
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const sysSyspromptLeaf: import("../../core/command.js").LeafDef;
|