@north-light/crouter 0.3.197 → 0.3.199
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.d.ts +19 -19
- package/dist/api/client.js +29 -37
- package/dist/api/dto/broker-ops.d.ts +3 -1
- package/dist/api/dto/broker.d.ts +13 -2
- package/dist/api/dto/broker.js +4 -4
- package/dist/api/dto/human.d.ts +6 -5
- package/dist/api/dto/inbox.d.ts +126 -33
- package/dist/api/dto/nodes.d.ts +8 -2
- package/dist/api/dto/profiles.d.ts +23 -0
- package/dist/api/dto/profiles.js +2 -2
- package/dist/api/dto/worktree.d.ts +3 -5
- package/dist/api/routes.d.ts +3 -5
- package/dist/api/routes.js +4 -6
- package/dist/builtin-memory/00-runtime-base.md +8 -8
- package/dist/builtin-memory/01-spine/01-no-manager.md +1 -1
- package/dist/builtin-memory/02-lifecycle/00-terminal.md +3 -3
- package/dist/builtin-memory/04-orchestration-kernel.md +6 -6
- package/dist/builtin-memory/05-kinds/design/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +2 -2
- package/dist/builtin-memory/05-kinds/review/00-base.md +2 -2
- package/dist/builtin-memory/05-kinds/review/01-orchestrator.md +1 -1
- package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +1 -1
- package/dist/builtin-memory/insights/capture.md +2 -2
- package/dist/builtin-memory/insights/init.md +3 -3
- package/dist/builtin-memory/internal/INDEX.md +1 -1
- package/dist/builtin-memory/internal/memory-loading.md +1 -1
- package/dist/builtin-memory/internal/nodes-and-canvas.md +3 -3
- package/dist/builtin-memory/internal/plugins.md +59 -2
- package/dist/builtin-memory/internal/storage-tiers.md +3 -1
- package/dist/builtin-memory/spec/roadmap.md +2 -2
- package/dist/builtin-memory/testing.md +1 -1
- package/dist/builtin-memory/wedged-child-on-runaway-bash.md +1 -1
- package/dist/clients/attach/chrome/bash-jobs.js +3 -3
- package/dist/clients/attach/render/chat-view.d.ts +29 -9
- package/dist/clients/attach/render/chat-view.js +64 -35
- package/dist/clients/attach/render/markdown-source.js +0 -6
- package/dist/clients/attach/render/page-block.d.ts +34 -0
- package/dist/clients/attach/render/page-block.js +226 -0
- package/dist/clients/attach/render/tool-calls.js +16 -2
- package/dist/clients/attach/session/whip.d.ts +2 -0
- package/dist/clients/attach/session/whip.js +2 -0
- package/dist/clients/attach/viewer.js +1419 -982
- package/dist/clients/conversation/projection.js +18 -3
- package/dist/clients/inbox/__tests__/serial/inbox-controller.test.js +9 -6
- package/dist/clients/inbox/__tests__/serial/mount-panel.test.js +13 -14
- package/dist/clients/inbox/controller.js +10 -16
- package/dist/clients/inbox/page-adapter.d.ts +3 -4
- package/dist/clients/inbox/page-adapter.js +3 -4
- package/dist/clients/inbox/resolve.d.ts +1 -1
- package/dist/clients/inbox/resolve.js +3 -3
- package/dist/clients/inbox/review/document-surface.js +3 -1
- package/dist/clients/inbox/review/state.d.ts +2 -1
- package/dist/clients/inbox/review/state.js +5 -16
- package/dist/clients/inbox/tui/input.js +37 -19
- package/dist/clients/inbox/tui/panel.js +5 -31
- package/dist/clients/inbox/tui/render.d.ts +11 -0
- package/dist/clients/inbox/tui/render.js +101 -36
- package/dist/clients/inbox/tui/slots.d.ts +4 -4
- package/dist/clients/inbox/tui/slots.js +19 -44
- package/dist/clients/inbox/tui/types.d.ts +6 -10
- package/dist/clients/inbox/tui.js +2 -2
- package/dist/commands/__tests__/human.test.js +118 -24
- package/dist/commands/__tests__/node-message.test.js +14 -0
- package/dist/commands/attention.js +4 -4
- package/dist/commands/canvas-browse.js +1 -1
- package/dist/commands/canvas-snapshot.js +1 -1
- package/dist/commands/canvas.js +1 -1
- package/dist/commands/dashboard.js +1 -1
- package/dist/commands/human/{doc.d.ts → components.d.ts} +1 -1
- package/dist/commands/human/components.js +77 -0
- package/dist/commands/human/feedback.d.ts +2 -0
- package/dist/commands/human/feedback.js +108 -0
- package/dist/commands/human/prompts.d.ts +17 -8
- package/dist/commands/human/prompts.js +217 -226
- package/dist/commands/human/queue.js +57 -88
- package/dist/commands/human/shared.d.ts +4 -15
- package/dist/commands/human/shared.js +19 -61
- package/dist/commands/human.js +32 -19
- package/dist/commands/memory/origin.js +2 -2
- package/dist/commands/node/bash.js +4 -4
- package/dist/commands/node/inspect.js +3 -3
- package/dist/commands/node/lifecycle.js +1 -1
- package/dist/commands/node/message.js +2 -2
- package/dist/commands/node-worktree.js +8 -8
- package/dist/commands/pkg/browse.js +1 -1
- package/dist/commands/pkg/plugin-manage.js +129 -10
- package/dist/commands/profile/delete.js +41 -15
- package/dist/commands/profile.js +1 -1
- package/dist/commands/push.js +1 -1
- package/dist/commands/surface/node/focus.js +29 -14
- package/dist/commands/surface-edit.js +3 -3
- package/dist/commands/surface-inbox.d.ts +2 -0
- package/dist/commands/{human/inbox.js → surface-inbox.js} +14 -18
- package/dist/commands/surface.js +2 -1
- package/dist/commands/sys/doctor.js +60 -3
- package/dist/commands/sys/feedback.js +79 -25
- package/dist/commands/sys/settings.js +1 -1
- package/dist/core/__tests__/cron-broker-capacity.test.js +1 -1
- package/dist/core/__tests__/daemon-boot.test.js +7 -4
- package/dist/core/__tests__/dead-node-policy-table.test.js +20 -36
- package/dist/core/__tests__/extension-abort.test.js +5 -2
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +13 -2
- package/dist/core/__tests__/fixtures/fake-engine.js +47 -3
- package/dist/core/__tests__/human-cancel-guard.test.js +31 -10
- package/dist/core/__tests__/human-deliver.test.js +41 -45
- package/dist/core/__tests__/human-node-not-supervised.test.js +1 -1
- package/dist/core/__tests__/plugin-page-components.test.js +157 -0
- package/dist/core/__tests__/seam/broker-crash-teardown.test.js +13 -11
- package/dist/core/__tests__/seam/dormancy-release.test.js +103 -4
- package/dist/core/__tests__/serial/flagship-lifecycle.test.js +2 -2
- package/dist/core/__tests__/serial/human-deliver-e2e.test.js +12 -16
- package/dist/core/__tests__/serial/live-mutation.test.js +1 -1
- package/dist/core/__tests__/serial/tmux-surface.test.js +4 -2
- package/dist/core/__tests__/serial/worktree.test.js +24 -198
- package/dist/core/__tests__/session-cycles.test.js +22 -0
- package/dist/core/__tests__/stop-guard.test.js +4 -4
- package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +19 -4
- package/dist/core/bash-jobs.d.ts +6 -0
- package/dist/core/bash-jobs.js +10 -0
- package/dist/core/canvas/__tests__/attention.test.js +8 -5
- package/dist/core/canvas/__tests__/render-remote.test.js +5 -5
- package/dist/core/canvas/attention.js +8 -6
- package/dist/core/canvas/browse/app.d.ts +1 -1
- package/dist/core/canvas/browse/app.js +21 -3
- package/dist/core/canvas/browse/model.d.ts +8 -2
- package/dist/core/canvas/browse/model.js +11 -4
- package/dist/core/canvas/browse/render.d.ts +4 -0
- package/dist/core/canvas/browse/render.js +5 -1
- package/dist/core/canvas/canvas.d.ts +33 -0
- package/dist/core/canvas/canvas.js +92 -0
- package/dist/core/canvas/crons.d.ts +9 -0
- package/dist/core/canvas/crons.js +51 -0
- package/dist/core/canvas/node-order.d.ts +22 -1
- package/dist/core/canvas/node-order.js +26 -1
- package/dist/core/canvas/render-source.d.ts +5 -0
- package/dist/core/canvas/render-source.js +1 -0
- package/dist/core/canvas/types.d.ts +9 -3
- package/dist/core/command-plugins/bundle.d.ts +6 -1
- package/dist/core/command-plugins/bundle.js +26 -13
- package/dist/core/command.js +8 -12
- package/dist/core/config.d.ts +47 -1
- package/dist/core/config.js +138 -4
- package/dist/core/help.d.ts +3 -0
- package/dist/core/help.js +1 -1
- package/dist/core/human/__tests__/page-catalog.test.d.ts +1 -0
- package/dist/core/human/__tests__/page-catalog.test.js +20 -0
- package/dist/core/human/__tests__/page-tickets.test.js +68 -34
- package/dist/core/human/__tests__/page.test.js +60 -119
- package/dist/core/human/__tests__/serial/inbox-core.test.js +6 -16
- package/dist/core/human/answer-text.d.ts +3 -0
- package/dist/core/human/answer-text.js +98 -0
- package/dist/core/human/answer.d.ts +53 -0
- package/dist/core/human/answer.js +119 -0
- package/dist/core/human/component-docs.d.ts +18 -0
- package/dist/core/human/component-docs.js +434 -0
- package/dist/core/human/convention.d.ts +17 -3
- package/dist/core/human/convention.js +36 -5
- package/dist/core/human/feedback-companion.d.ts +20 -0
- package/dist/core/human/feedback-companion.js +98 -0
- package/dist/core/human/feedback.d.ts +65 -0
- package/dist/core/human/feedback.js +116 -0
- package/dist/core/human/page-catalog.d.ts +56 -5
- package/dist/core/human/page-catalog.js +151 -22
- package/dist/core/human/page-errors.d.ts +4 -0
- package/dist/core/human/page-errors.js +7 -0
- package/dist/core/human/page-eval.d.ts +20 -0
- package/dist/core/human/page-eval.js +123 -0
- package/dist/core/human/page-schema.d.ts +48 -116
- package/dist/core/human/page-schema.js +100 -72
- package/dist/core/human/page-synth.d.ts +2 -4
- package/dist/core/human/page-synth.js +20 -7
- package/dist/core/human/page.d.ts +13 -21
- package/dist/core/human/page.js +147 -391
- package/dist/core/human/review-schema.d.ts +1 -0
- package/dist/core/human/review-schema.js +1 -1
- package/dist/core/human/root.d.ts +6 -2
- package/dist/core/human/root.js +12 -4
- package/dist/core/human/scan.d.ts +3 -3
- package/dist/core/human/scan.js +21 -21
- package/dist/core/human/summary.d.ts +2 -6
- package/dist/core/human/summary.js +3 -59
- package/dist/core/human/tickets.d.ts +22 -15
- package/dist/core/human/tickets.js +90 -28
- package/dist/core/human/types.d.ts +14 -2
- package/dist/core/keybindings/catalog.d.ts +2 -2
- package/dist/core/keybindings/catalog.js +1 -0
- package/dist/core/preview-registry.js +8 -10
- package/dist/core/profiles/default-binding.d.ts +4 -0
- package/dist/core/profiles/default-binding.js +24 -0
- package/dist/core/profiles/deletion-reservation.d.ts +8 -0
- package/dist/core/profiles/deletion-reservation.js +38 -0
- package/dist/core/profiles/manifest.d.ts +3 -0
- package/dist/core/profiles/manifest.js +12 -0
- package/dist/core/profiles/select.js +2 -2
- package/dist/core/review/realize.js +12 -4
- package/dist/core/review/store.d.ts +6 -0
- package/dist/core/review/store.js +31 -0
- package/dist/core/runtime/bearings.d.ts +0 -4
- package/dist/core/runtime/bearings.js +4 -62
- package/dist/core/runtime/bin-contributions.d.ts +44 -0
- package/dist/core/runtime/bin-contributions.js +186 -0
- package/dist/core/runtime/boot-root.js +6 -1
- package/dist/core/runtime/broker/client-registry.d.ts +4 -0
- package/dist/core/runtime/broker/client-registry.js +13 -1
- package/dist/core/runtime/broker/extension-abort.d.ts +1 -1
- package/dist/core/runtime/broker/extension-abort.js +4 -2
- package/dist/core/runtime/broker/fault-retry.js +4 -0
- package/dist/core/runtime/broker/frame-dispatch.d.ts +3 -1
- package/dist/core/runtime/broker/frame-dispatch.js +5 -6
- package/dist/core/runtime/broker/read-ops.d.ts +1 -1
- package/dist/core/runtime/broker/read-ops.js +2 -2
- package/dist/core/runtime/broker/rebind.d.ts +1 -0
- package/dist/core/runtime/broker/rebind.js +6 -1
- package/dist/core/runtime/broker-extension-render.js +19 -0
- package/dist/core/runtime/broker-protocol.d.ts +14 -0
- package/dist/core/runtime/broker.d.ts +1 -1
- package/dist/core/runtime/broker.js +25 -12
- package/dist/core/runtime/busy.d.ts +4 -3
- package/dist/core/runtime/busy.js +4 -3
- package/dist/core/runtime/front-door-env.d.ts +5 -0
- package/dist/core/runtime/front-door-env.js +16 -0
- package/dist/core/runtime/front-door.d.ts +1 -5
- package/dist/core/runtime/front-door.js +2 -5
- package/dist/core/runtime/host.d.ts +1 -1
- package/dist/core/runtime/invocation.d.ts +6 -0
- package/dist/core/runtime/invocation.js +10 -0
- package/dist/core/runtime/kickoff.js +34 -0
- package/dist/core/runtime/launch.d.ts +2 -6
- package/dist/core/runtime/node-read.js +4 -1
- package/dist/core/runtime/nodes.js +2 -0
- package/dist/core/runtime/promote.d.ts +1 -0
- package/dist/core/runtime/promote.js +3 -1
- package/dist/core/runtime/session-cycles.d.ts +6 -0
- package/dist/core/runtime/session-cycles.js +15 -1
- package/dist/core/runtime/session-visibility.d.ts +17 -8
- package/dist/core/runtime/session-visibility.js +19 -10
- package/dist/core/runtime/spawn-env.d.ts +9 -1
- package/dist/core/runtime/spawn-env.js +62 -2
- package/dist/core/runtime/spawn.js +4 -4
- package/dist/core/runtime/stop-guard.d.ts +2 -2
- package/dist/core/runtime/stop-guard.js +2 -2
- package/dist/core/runtime/stop-signals.d.ts +1 -1
- package/dist/core/runtime/stop-signals.js +2 -2
- package/dist/core/runtime/tmux-bindings.js +1 -1
- package/dist/core/session-model/session-state.d.ts +4 -3
- package/dist/core/session-model/session-state.js +14 -1
- package/dist/core/user-settings.d.ts +36 -2
- package/dist/core/user-settings.js +56 -14
- package/dist/core/worktree.d.ts +15 -45
- package/dist/core/worktree.js +59 -261
- package/dist/daemon/api/__tests__/seam/profile-delete.test.d.ts +1 -0
- package/dist/daemon/api/__tests__/seam/profile-delete.test.js +386 -0
- package/dist/daemon/api/handlers/bash-jobs.js +1 -1
- package/dist/daemon/api/handlers/broker-ops.js +9 -5
- package/dist/daemon/api/handlers/feedback-comments.d.ts +2 -0
- package/dist/daemon/api/handlers/feedback-comments.js +207 -0
- package/dist/daemon/api/handlers/human.js +24 -20
- package/dist/daemon/api/handlers/inbox.d.ts +10 -0
- package/dist/daemon/api/handlers/inbox.js +48 -109
- package/dist/daemon/api/handlers/profiles.js +11 -29
- package/dist/daemon/api/map.d.ts +6 -1
- package/dist/daemon/api/map.js +23 -0
- package/dist/daemon/api/server.js +3 -1
- package/dist/daemon/companion-retire.d.ts +2 -0
- package/dist/daemon/companion-retire.js +33 -0
- package/dist/daemon/cron-run.js +29 -17
- package/dist/daemon/crtrd.js +1 -1
- package/dist/daemon/fleet.d.ts +22 -10
- package/dist/daemon/fleet.js +43 -24
- package/dist/daemon/human/finish.d.ts +12 -6
- package/dist/daemon/human/finish.js +134 -54
- package/dist/daemon/human/sweep.js +9 -3
- package/dist/daemon/profile-delete.d.ts +7 -0
- package/dist/daemon/profile-delete.js +306 -0
- package/dist/daemon/reconcilers/broker-supervision.js +14 -9
- package/dist/daemon/reconcilers/dormant-inbox.js +11 -6
- package/dist/daemon/reconcilers/live-obligation.d.ts +21 -1
- package/dist/daemon/reconcilers/live-obligation.js +30 -2
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +5 -0
- package/dist/daemon/reconcilers/storage-maintenance.js +28 -1
- package/dist/daemon/review/deliver.js +3 -3
- package/dist/daemon/review/finish.d.ts +0 -2
- package/dist/daemon/review/finish.js +1 -29
- package/dist/daemon/review/sweep.js +12 -1
- package/dist/pi-extensions/__tests__/canvas-bash-valve.test.js +56 -1
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +4 -4
- package/dist/pi-extensions/canvas-bash-valve.d.ts +9 -1
- package/dist/pi-extensions/canvas-bash-valve.js +31 -13
- package/dist/pi-extensions/canvas-inbox-watcher.js +1 -1
- package/dist/pi-extensions/canvas-review-boundary.d.ts +4 -0
- package/dist/pi-extensions/canvas-review-boundary.js +18 -9
- package/dist/pi-extensions/canvas-stophook.js +4 -4
- package/dist/shared/generated-context.js +2 -2
- package/dist/types.d.ts +61 -5
- package/dist/types.js +8 -2
- package/package.json +4 -4
- package/runtime.lock.json +5 -33
- package/scripts/install-runtime.mjs +19 -24
- package/dist/builtin-memory/init.md +0 -38
- package/dist/builtin-memory/plan.md +0 -19
- package/dist/builtin-memory/spec.md +0 -19
- package/dist/clients/attach/render/html-markdown.d.ts +0 -13
- package/dist/clients/attach/render/html-markdown.js +0 -206
- package/dist/commands/human/doc.js +0 -144
- package/dist/commands/human/inbox.d.ts +0 -2
- package/dist/core/human/__tests__/page-render.test.js +0 -49
- package/dist/core/human/markdown-html.d.ts +0 -8
- package/dist/core/human/markdown-html.js +0 -581
- package/dist/core/human/page-render.d.ts +0 -3
- package/dist/core/human/page-render.js +0 -131
- package/dist/pages/bundle.css +0 -1
- package/dist/pages/bundle.js +0 -1347
- package/dist/pages/comments.d.ts +0 -43
- package/dist/pages/comments.js +0 -125
- package/dist/pages/elements/cards.d.ts +0 -17
- package/dist/pages/elements/cards.js +0 -802
- package/dist/pages/elements/chart.js +0 -648
- package/dist/pages/elements/options.d.ts +0 -21
- package/dist/pages/elements/options.js +0 -629
- package/dist/pages/elements/pages.d.ts +0 -24
- package/dist/pages/elements/pages.js +0 -355
- package/dist/pages/elements/slot.d.ts +0 -21
- package/dist/pages/elements/slot.js +0 -105
- package/dist/pages/elements/table.d.ts +0 -19
- package/dist/pages/elements/table.js +0 -935
- package/dist/pages/elements/text.d.ts +0 -25
- package/dist/pages/elements/text.js +0 -968
- package/dist/pages/entry.d.ts +0 -8
- package/dist/pages/entry.js +0 -8
- package/dist/pages/host.d.ts +0 -158
- package/dist/pages/host.js +0 -182
- package/dist/pages/register.d.ts +0 -2
- package/dist/pages/register.js +0 -3
- package/dist/pages/slot-config.d.ts +0 -36
- package/dist/pages/slot-config.js +0 -50
- package/dist/pages/types.d.ts +0 -98
- package/dist/pages/types.js +0 -23
- /package/dist/{core/human/__tests__/page-render.test.d.ts → commands/__tests__/node-message.test.d.ts} +0 -0
- /package/dist/{pages/elements/chart.d.ts → core/__tests__/plugin-page-components.test.d.ts} +0 -0
package/runtime.lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/crouter",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.199",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@north-light/crouter",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.199",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
|
@@ -15,9 +15,11 @@
|
|
|
15
15
|
"@earendil-works/pi-coding-agent": "0.84.1",
|
|
16
16
|
"@earendil-works/pi-tui": "0.84.1",
|
|
17
17
|
"cron-parser": "^5.6.0",
|
|
18
|
+
"esbuild": "^0.27.7",
|
|
18
19
|
"proper-lockfile": "4.1.2",
|
|
19
20
|
"string-width": "^7.0.0",
|
|
20
21
|
"tar": "^7.5.22",
|
|
22
|
+
"typescript": "^5.7.0",
|
|
21
23
|
"ws": "^8.21.0",
|
|
22
24
|
"yaml": "^2.9.0",
|
|
23
25
|
"zod": "^4.3.6"
|
|
@@ -31,9 +33,7 @@
|
|
|
31
33
|
"@types/node": "^24.0.0",
|
|
32
34
|
"@types/proper-lockfile": "^4.1.4",
|
|
33
35
|
"@types/ws": "^8.18.1",
|
|
34
|
-
"
|
|
35
|
-
"tsx": "^4.0.0",
|
|
36
|
-
"typescript": "^5.7.0"
|
|
36
|
+
"tsx": "^4.0.0"
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
39
|
"node_modules/@anthropic-ai/sdk": {
|
|
@@ -2432,7 +2432,6 @@
|
|
|
2432
2432
|
"cpu": [
|
|
2433
2433
|
"ppc64"
|
|
2434
2434
|
],
|
|
2435
|
-
"dev": true,
|
|
2436
2435
|
"license": "MIT",
|
|
2437
2436
|
"optional": true,
|
|
2438
2437
|
"os": [
|
|
@@ -2449,7 +2448,6 @@
|
|
|
2449
2448
|
"cpu": [
|
|
2450
2449
|
"arm"
|
|
2451
2450
|
],
|
|
2452
|
-
"dev": true,
|
|
2453
2451
|
"license": "MIT",
|
|
2454
2452
|
"optional": true,
|
|
2455
2453
|
"os": [
|
|
@@ -2466,7 +2464,6 @@
|
|
|
2466
2464
|
"cpu": [
|
|
2467
2465
|
"arm64"
|
|
2468
2466
|
],
|
|
2469
|
-
"dev": true,
|
|
2470
2467
|
"license": "MIT",
|
|
2471
2468
|
"optional": true,
|
|
2472
2469
|
"os": [
|
|
@@ -2483,7 +2480,6 @@
|
|
|
2483
2480
|
"cpu": [
|
|
2484
2481
|
"x64"
|
|
2485
2482
|
],
|
|
2486
|
-
"dev": true,
|
|
2487
2483
|
"license": "MIT",
|
|
2488
2484
|
"optional": true,
|
|
2489
2485
|
"os": [
|
|
@@ -2500,7 +2496,6 @@
|
|
|
2500
2496
|
"cpu": [
|
|
2501
2497
|
"arm64"
|
|
2502
2498
|
],
|
|
2503
|
-
"dev": true,
|
|
2504
2499
|
"license": "MIT",
|
|
2505
2500
|
"optional": true,
|
|
2506
2501
|
"os": [
|
|
@@ -2517,7 +2512,6 @@
|
|
|
2517
2512
|
"cpu": [
|
|
2518
2513
|
"x64"
|
|
2519
2514
|
],
|
|
2520
|
-
"dev": true,
|
|
2521
2515
|
"license": "MIT",
|
|
2522
2516
|
"optional": true,
|
|
2523
2517
|
"os": [
|
|
@@ -2534,7 +2528,6 @@
|
|
|
2534
2528
|
"cpu": [
|
|
2535
2529
|
"arm64"
|
|
2536
2530
|
],
|
|
2537
|
-
"dev": true,
|
|
2538
2531
|
"license": "MIT",
|
|
2539
2532
|
"optional": true,
|
|
2540
2533
|
"os": [
|
|
@@ -2551,7 +2544,6 @@
|
|
|
2551
2544
|
"cpu": [
|
|
2552
2545
|
"x64"
|
|
2553
2546
|
],
|
|
2554
|
-
"dev": true,
|
|
2555
2547
|
"license": "MIT",
|
|
2556
2548
|
"optional": true,
|
|
2557
2549
|
"os": [
|
|
@@ -2568,7 +2560,6 @@
|
|
|
2568
2560
|
"cpu": [
|
|
2569
2561
|
"arm"
|
|
2570
2562
|
],
|
|
2571
|
-
"dev": true,
|
|
2572
2563
|
"license": "MIT",
|
|
2573
2564
|
"optional": true,
|
|
2574
2565
|
"os": [
|
|
@@ -2585,7 +2576,6 @@
|
|
|
2585
2576
|
"cpu": [
|
|
2586
2577
|
"arm64"
|
|
2587
2578
|
],
|
|
2588
|
-
"dev": true,
|
|
2589
2579
|
"license": "MIT",
|
|
2590
2580
|
"optional": true,
|
|
2591
2581
|
"os": [
|
|
@@ -2602,7 +2592,6 @@
|
|
|
2602
2592
|
"cpu": [
|
|
2603
2593
|
"ia32"
|
|
2604
2594
|
],
|
|
2605
|
-
"dev": true,
|
|
2606
2595
|
"license": "MIT",
|
|
2607
2596
|
"optional": true,
|
|
2608
2597
|
"os": [
|
|
@@ -2619,7 +2608,6 @@
|
|
|
2619
2608
|
"cpu": [
|
|
2620
2609
|
"loong64"
|
|
2621
2610
|
],
|
|
2622
|
-
"dev": true,
|
|
2623
2611
|
"license": "MIT",
|
|
2624
2612
|
"optional": true,
|
|
2625
2613
|
"os": [
|
|
@@ -2636,7 +2624,6 @@
|
|
|
2636
2624
|
"cpu": [
|
|
2637
2625
|
"mips64el"
|
|
2638
2626
|
],
|
|
2639
|
-
"dev": true,
|
|
2640
2627
|
"license": "MIT",
|
|
2641
2628
|
"optional": true,
|
|
2642
2629
|
"os": [
|
|
@@ -2653,7 +2640,6 @@
|
|
|
2653
2640
|
"cpu": [
|
|
2654
2641
|
"ppc64"
|
|
2655
2642
|
],
|
|
2656
|
-
"dev": true,
|
|
2657
2643
|
"license": "MIT",
|
|
2658
2644
|
"optional": true,
|
|
2659
2645
|
"os": [
|
|
@@ -2670,7 +2656,6 @@
|
|
|
2670
2656
|
"cpu": [
|
|
2671
2657
|
"riscv64"
|
|
2672
2658
|
],
|
|
2673
|
-
"dev": true,
|
|
2674
2659
|
"license": "MIT",
|
|
2675
2660
|
"optional": true,
|
|
2676
2661
|
"os": [
|
|
@@ -2687,7 +2672,6 @@
|
|
|
2687
2672
|
"cpu": [
|
|
2688
2673
|
"s390x"
|
|
2689
2674
|
],
|
|
2690
|
-
"dev": true,
|
|
2691
2675
|
"license": "MIT",
|
|
2692
2676
|
"optional": true,
|
|
2693
2677
|
"os": [
|
|
@@ -2704,7 +2688,6 @@
|
|
|
2704
2688
|
"cpu": [
|
|
2705
2689
|
"x64"
|
|
2706
2690
|
],
|
|
2707
|
-
"dev": true,
|
|
2708
2691
|
"license": "MIT",
|
|
2709
2692
|
"optional": true,
|
|
2710
2693
|
"os": [
|
|
@@ -2721,7 +2704,6 @@
|
|
|
2721
2704
|
"cpu": [
|
|
2722
2705
|
"arm64"
|
|
2723
2706
|
],
|
|
2724
|
-
"dev": true,
|
|
2725
2707
|
"license": "MIT",
|
|
2726
2708
|
"optional": true,
|
|
2727
2709
|
"os": [
|
|
@@ -2738,7 +2720,6 @@
|
|
|
2738
2720
|
"cpu": [
|
|
2739
2721
|
"x64"
|
|
2740
2722
|
],
|
|
2741
|
-
"dev": true,
|
|
2742
2723
|
"license": "MIT",
|
|
2743
2724
|
"optional": true,
|
|
2744
2725
|
"os": [
|
|
@@ -2755,7 +2736,6 @@
|
|
|
2755
2736
|
"cpu": [
|
|
2756
2737
|
"arm64"
|
|
2757
2738
|
],
|
|
2758
|
-
"dev": true,
|
|
2759
2739
|
"license": "MIT",
|
|
2760
2740
|
"optional": true,
|
|
2761
2741
|
"os": [
|
|
@@ -2772,7 +2752,6 @@
|
|
|
2772
2752
|
"cpu": [
|
|
2773
2753
|
"x64"
|
|
2774
2754
|
],
|
|
2775
|
-
"dev": true,
|
|
2776
2755
|
"license": "MIT",
|
|
2777
2756
|
"optional": true,
|
|
2778
2757
|
"os": [
|
|
@@ -2789,7 +2768,6 @@
|
|
|
2789
2768
|
"cpu": [
|
|
2790
2769
|
"arm64"
|
|
2791
2770
|
],
|
|
2792
|
-
"dev": true,
|
|
2793
2771
|
"license": "MIT",
|
|
2794
2772
|
"optional": true,
|
|
2795
2773
|
"os": [
|
|
@@ -2806,7 +2784,6 @@
|
|
|
2806
2784
|
"cpu": [
|
|
2807
2785
|
"x64"
|
|
2808
2786
|
],
|
|
2809
|
-
"dev": true,
|
|
2810
2787
|
"license": "MIT",
|
|
2811
2788
|
"optional": true,
|
|
2812
2789
|
"os": [
|
|
@@ -2823,7 +2800,6 @@
|
|
|
2823
2800
|
"cpu": [
|
|
2824
2801
|
"arm64"
|
|
2825
2802
|
],
|
|
2826
|
-
"dev": true,
|
|
2827
2803
|
"license": "MIT",
|
|
2828
2804
|
"optional": true,
|
|
2829
2805
|
"os": [
|
|
@@ -2840,7 +2816,6 @@
|
|
|
2840
2816
|
"cpu": [
|
|
2841
2817
|
"ia32"
|
|
2842
2818
|
],
|
|
2843
|
-
"dev": true,
|
|
2844
2819
|
"license": "MIT",
|
|
2845
2820
|
"optional": true,
|
|
2846
2821
|
"os": [
|
|
@@ -2857,7 +2832,6 @@
|
|
|
2857
2832
|
"cpu": [
|
|
2858
2833
|
"x64"
|
|
2859
2834
|
],
|
|
2860
|
-
"dev": true,
|
|
2861
2835
|
"license": "MIT",
|
|
2862
2836
|
"optional": true,
|
|
2863
2837
|
"os": [
|
|
@@ -3290,7 +3264,6 @@
|
|
|
3290
3264
|
"version": "0.27.7",
|
|
3291
3265
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz",
|
|
3292
3266
|
"integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==",
|
|
3293
|
-
"dev": true,
|
|
3294
3267
|
"hasInstallScript": true,
|
|
3295
3268
|
"license": "MIT",
|
|
3296
3269
|
"bin": {
|
|
@@ -4332,7 +4305,6 @@
|
|
|
4332
4305
|
"version": "5.9.3",
|
|
4333
4306
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
|
4334
4307
|
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
|
4335
|
-
"dev": true,
|
|
4336
4308
|
"license": "Apache-2.0",
|
|
4337
4309
|
"bin": {
|
|
4338
4310
|
"tsc": "bin/tsc",
|
|
@@ -14,7 +14,10 @@ const GENERATIONS = join(RUNTIME_HOME, 'generations');
|
|
|
14
14
|
const LOCK = join(RUNTIME_HOME, 'install.lock');
|
|
15
15
|
const LOCK_OWNER_FILE = 'owner.json';
|
|
16
16
|
const RUNTIME_LOCK = 'runtime.lock.json';
|
|
17
|
-
|
|
17
|
+
// The selected generation plus one prior, so a bad selection can be rolled
|
|
18
|
+
// back by hand. Anything older is reinstallable from npm and is not worth the
|
|
19
|
+
// ~500MB/generation it costs on disk.
|
|
20
|
+
const KEEP_RECENT_GENERATIONS = 2;
|
|
18
21
|
const FS_CONCURRENCY = 64;
|
|
19
22
|
// How long an install.lock with no readable owner record is given the
|
|
20
23
|
// benefit of the doubt (the owner is mid-write, or on an ancient version of
|
|
@@ -174,40 +177,36 @@ function generationIdsIn(text) {
|
|
|
174
177
|
return [...text.matchAll(/generations\/([a-f0-9]{64})(?:[/\s]|$)/g)].map((match) => match[1]);
|
|
175
178
|
}
|
|
176
179
|
|
|
177
|
-
/**
|
|
178
|
-
*
|
|
180
|
+
/** Every generation a running process is using — named in its argv, or held as
|
|
181
|
+
* an open entry-file lease (how a stable `crtr`/`crtrd` shim, whose argv names
|
|
182
|
+
* no generation, keeps the one it resolved; see `holdGenerationEntryFd` in
|
|
183
|
+
* bin/runtime-selector.mjs and the matching open in src/cli.ts).
|
|
184
|
+
*
|
|
185
|
+
* Detection is positive-only and that is deliberate: a generation nothing here
|
|
186
|
+
* names is prunable. An earlier revision also tracked whether every stable shim
|
|
187
|
+
* had exposed a lease and skipped the whole GC when one had not. That made one
|
|
188
|
+
* unidentifiable process veto all pruning permanently — a single pre-upgrade
|
|
189
|
+
* viewer, which could never hold a lease the mechanism predated, silently
|
|
190
|
+
* stopped GC forever and grew this directory by ~500MB per install. */
|
|
179
191
|
async function liveGenerationIds() {
|
|
180
192
|
const output = await run('ps', ['-axww', '-o', 'pid=,command='], RUNTIME_HOME, true);
|
|
181
193
|
const live = new Set(generationIdsIn(output));
|
|
182
194
|
const nodePids = [];
|
|
183
|
-
const opaqueStablePids = new Set();
|
|
184
195
|
for (const line of output.split('\n')) {
|
|
185
196
|
const match = /^\s*(\d+)\s+(.*)$/.exec(line);
|
|
186
197
|
if (!match) continue;
|
|
187
198
|
const [, pid, command] = match;
|
|
188
|
-
const stableSelector = /^(?:\S*node\s+)?\S*\/bin\/(?:crtr|crtrd|crouter)(?:\s|$)/.test(command);
|
|
189
|
-
if (stableSelector && generationIdsIn(command).length === 0) opaqueStablePids.add(pid);
|
|
190
199
|
if (/(?:^|[\s/])(?:node|crtrd?|crouter)(?:[\s]|$)/.test(command)) nodePids.push(pid);
|
|
191
200
|
}
|
|
192
|
-
if (nodePids.length === 0) return
|
|
201
|
+
if (nodePids.length === 0) return live;
|
|
193
202
|
|
|
194
203
|
// One lsof invocation resolves cwd references and the runtime entry-file
|
|
195
204
|
// lease held by each stable CLI process without a per-process startup penalty.
|
|
196
205
|
const open = await probe('lsof', ['-n', '-P', '-a', '-p', nodePids.join(','), '-Fn'], RUNTIME_HOME);
|
|
197
|
-
let pid;
|
|
198
|
-
const exposedStablePids = new Set();
|
|
199
206
|
for (const line of open.split('\n')) {
|
|
200
|
-
const
|
|
201
|
-
if (processMatch) {
|
|
202
|
-
pid = processMatch[1];
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
const ids = generationIdsIn(line);
|
|
206
|
-
for (const id of ids) live.add(id);
|
|
207
|
-
if (pid !== undefined && ids.length > 0 && opaqueStablePids.has(pid)) exposedStablePids.add(pid);
|
|
207
|
+
for (const id of generationIdsIn(line)) live.add(id);
|
|
208
208
|
}
|
|
209
|
-
|
|
210
|
-
return { live, uncertain };
|
|
209
|
+
return live;
|
|
211
210
|
}
|
|
212
211
|
|
|
213
212
|
async function selectedGenerationId() {
|
|
@@ -219,11 +218,7 @@ async function selectedGenerationId() {
|
|
|
219
218
|
|
|
220
219
|
async function pruneGenerations() {
|
|
221
220
|
const selected = await selectedGenerationId();
|
|
222
|
-
const
|
|
223
|
-
if (uncertain) {
|
|
224
|
-
process.stderr.write('runtime generation GC skipped: a live stable crouter shim does not expose its generation lease\n');
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
221
|
+
const live = await liveGenerationIds();
|
|
227
222
|
const entries = await readdir(GENERATIONS, { withFileTypes: true });
|
|
228
223
|
const candidates = [];
|
|
229
224
|
for (const entry of entries) {
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
kind: knowledge
|
|
3
|
-
when-and-why-to-read: When bootstrapping a project's memory store — the user invoked /init or a workspace has no .crouter/memory/INDEX.md front door — this knowledge should be read because a lean routed front door gives every future agent in that workspace its operating contract for a fraction of the standing context cost an unstructured guidance dump would charge each session forever.
|
|
4
|
-
short-form: "Bootstrap a project memory store: survey the repo, then author a lean INDEX front door plus a linked dev doc — commands, map, non-default rules, pointers — and lint. Depth splits into linked docs; every always-loaded line must earn its keep."
|
|
5
|
-
system-prompt-visibility: none
|
|
6
|
-
file-read-visibility: none
|
|
7
|
-
slash: true
|
|
8
|
-
rationale: Unguided agents bootstrap project memory badly in both directions — either no front door at all, or a monolithic CLAUDE.md-style manual (copied README, generic framework advice, exhaustive command catalogs) that taxes every future session and decays. Distilled 2026-07-31 from ecosystem research across Anthropic/OpenAI/Cursor/GitHub guidance and production AGENTS.md files — the strongest evidence being Sentry's consolidation postmortem (critical commands buried in nested files got missed) and Anthropic's under-200-line target with adherence falling as always-loaded files grow.
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# /init — bootstrap this project's memory store
|
|
12
|
-
|
|
13
|
-
Give this workspace its memory front door: a root INDEX every future agent boots with when the project mounts, plus a small graph of linked docs carrying the depth. The front door is an operating contract and routing layer, never a manual — every line it carries is paid by every session here forever, so a line earns its place only by changing behavior: a fact every task needs, a non-obvious hazard, or a rule an agent would otherwise get wrong.
|
|
14
|
-
|
|
15
|
-
## 1. Survey before writing
|
|
16
|
-
|
|
17
|
-
Learn the project from its own artifacts: README, package manifests and lockfiles, build/CI config, scripts, existing CLAUDE.md/AGENTS.md or docs. Extract the real commands (setup, run, build, targeted test, full verification) and RUN the important ones — record only commands you have seen work, with any required ordering, environment, or package-manager constraint. Note the architecture in a few sentences: major components, dependency direction, where generated or externally-owned code lives. Collect the conventions that differ from what a competent agent would assume — those deviations are the highest-value lines you will write.
|
|
18
|
-
|
|
19
|
-
## 2. Read the contract, then author the front door
|
|
20
|
-
|
|
21
|
-
Run `crtr memory write -h` first — it carries the substrate frontmatter contract and the exact root-INDEX shape, including the workspace-mount route that `crtr memory lint` validates. Then author the INDEX with these sections, total well under the length lint's cap:
|
|
22
|
-
|
|
23
|
-
- **Project in one paragraph** — purpose, major components, dependency direction.
|
|
24
|
-
- **Common commands** — the 3–8 commands most changes need, copyable, verified.
|
|
25
|
-
- **Where to work** — a task-to-path map; mark generated or externally-owned areas.
|
|
26
|
-
- **Non-default rules and gotchas** — only high-impact deviations from defaults. Skip anything a formatter, linter, or typechecker already enforces; point at the check instead.
|
|
27
|
-
- **Done** — the minimum credible gate for an ordinary change.
|
|
28
|
-
- **Pointers** — a `[[link]]` per deeper doc with a one-clause read trigger (e.g. "debugging the daemon → the dev doc").
|
|
29
|
-
|
|
30
|
-
Exclude generic language/framework advice, copied docs or style guides, volatile version detail, rare edge cases, and multi-step procedures — depth belongs behind links, not in the standing load.
|
|
31
|
-
|
|
32
|
-
## 3. Split depth into linked docs
|
|
33
|
-
|
|
34
|
-
Author `dev` alongside the INDEX by default: validated setup/run/build/test/debug commands with required order and environment, targeted-vs-full verification, and common failure modes. Add `architecture` only when the tree cannot be understood from the INDEX's brief map, and a conventions/gotchas doc only once real project-specific rules outgrow a few INDEX bullets — never pre-populate generic security or style manuals. These reference docs take `none` visibility on both axes; the INDEX's links are how they are found, so they cost nothing until followed.
|
|
35
|
-
|
|
36
|
-
## 4. Validate
|
|
37
|
-
|
|
38
|
-
Run `crtr memory lint` — it strict-parses the store, checks the INDEX front-door contract, and fails on dangling links or over-length bodies. Fix findings rather than suppressing them. The store is a living contract: when commands, architecture, or conventions change, rewrite the affected doc in place and delete superseded guidance — an always-loaded line that has stopped being true is worse than no line at all.
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
kind: knowledge
|
|
3
|
-
when-and-why-to-read: When an agent invokes /plan to pause work and map an implementation, this knowledge should be read because implementation can proceed from a grounded path instead of making consequential decisions while editing.
|
|
4
|
-
short-form: "Pause to write one right-sized implementation plan in the node context, then stop."
|
|
5
|
-
system-prompt-visibility: none
|
|
6
|
-
file-read-visibility: none
|
|
7
|
-
slash: true
|
|
8
|
-
rationale: The prior /plan plugin prompt forced ordinary planning through a fixed question loop, reviewer node, and human approval, adding ceremony rather than letting the plan match the work.
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# /plan — write an implementation plan
|
|
12
|
-
|
|
13
|
-
Pause the current work and write one right-sized implementation plan for: $ARGUMENTS
|
|
14
|
-
|
|
15
|
-
Ground it in the relevant code and requirements. Make the approach, affected areas, ordering or dependencies, and verification clear enough that an implementer can carry it out without guessing. Resolve only the decisions the plan needs; point to existing patterns rather than repeating source code.
|
|
16
|
-
|
|
17
|
-
Write the artifact in `$CRTR_CONTEXT_DIR`. For work that genuinely needs a broader planning roadmap, read [[plan/roadmap]] instead.
|
|
18
|
-
|
|
19
|
-
Report the artifact's absolute path, then stop. Do not implement as part of this invocation.
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
kind: knowledge
|
|
3
|
-
when-and-why-to-read: When an agent invokes /spec to pause work and capture a request, this knowledge should be read because the work can resume from settled intent instead of rediscovering what it is meant to achieve.
|
|
4
|
-
short-form: "Pause to write one right-sized specification in the node context, then stop."
|
|
5
|
-
system-prompt-visibility: none
|
|
6
|
-
file-read-visibility: none
|
|
7
|
-
slash: true
|
|
8
|
-
rationale: The prior /spec plugin prompt forced ordinary artifact requests through discovery loops, reviewer nodes, and human approval, turning a small pause to clarify work into prescribed ceremony.
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# /spec — write a specification
|
|
12
|
-
|
|
13
|
-
Pause the current work and write one right-sized specification for: $ARGUMENTS
|
|
14
|
-
|
|
15
|
-
Ground it in the relevant request and context. Make the intended outcome, behavior, and scope boundary clear enough that a downstream reader does not have to guess. Leave implementation choices to design and planning unless they constrain the outcome.
|
|
16
|
-
|
|
17
|
-
Write the artifact in `$CRTR_CONTEXT_DIR`. Read [[spec/guide]] when the request needs elicitation or a fuller quality check; for work that genuinely needs separate discovery, design, and requirements work across nodes, read [[spec/roadmap]].
|
|
18
|
-
|
|
19
|
-
Report the artifact's absolute path, then stop. Do not implement as part of this invocation.
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export interface HtmlMarkdownStyles {
|
|
2
|
-
kbd: (text: string) => string;
|
|
3
|
-
mark: (text: string) => string;
|
|
4
|
-
hint: (text: string) => string;
|
|
5
|
-
}
|
|
6
|
-
export interface HtmlMarkdownOptions {
|
|
7
|
-
/** Undefined honors each block's `open` attribute. A boolean is the viewer's
|
|
8
|
-
* global Ctrl+O override. */
|
|
9
|
-
detailsExpanded: boolean | undefined;
|
|
10
|
-
styles: HtmlMarkdownStyles;
|
|
11
|
-
}
|
|
12
|
-
/** Transform the strict supported HTML subset in one Markdown string. */
|
|
13
|
-
export declare function transformHtmlMarkdown(source: string, options: HtmlMarkdownOptions): string;
|
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
// Supported raw HTML for assistant Markdown in the attach viewer.
|
|
2
|
-
//
|
|
3
|
-
// This is deliberately a semantic allowlist, not an HTML renderer. Complete
|
|
4
|
-
// details/summary blocks become terminal disclosure rows, while kbd and mark
|
|
5
|
-
// become theme-styled inline text. Everything else stays literal, and Markdown
|
|
6
|
-
// code spans/fences are protected before the allowlist scanner runs.
|
|
7
|
-
const PROTECTED_PREFIX = '\u0000\u0001CRTR_HTML_CODE_';
|
|
8
|
-
const PROTECTED_SUFFIX = '\u0002';
|
|
9
|
-
const DETAILS_OPEN = /<details\b[^>]*>/gi;
|
|
10
|
-
const DETAILS_TAG = /<\/?details\b[^>]*>/gi;
|
|
11
|
-
const VALID_DETAILS_OPEN = /^<details(?:[ \t\r\n]+open)?[ \t\r\n]*>$/i;
|
|
12
|
-
const VALID_DETAILS_CLOSE = /^<\/details[ \t\r\n]*>$/i;
|
|
13
|
-
const SUMMARY_OPEN = /^[ \t\r\n]*<summary[ \t\r\n]*>/i;
|
|
14
|
-
const SUMMARY_CLOSE = /<\/summary[ \t\r\n]*>/i;
|
|
15
|
-
const INLINE_HTML = /<(kbd|mark)>([^<>\n]*?)<\/\1[ \t]*>/gi;
|
|
16
|
-
const SUPPORTED_HTML = /<(?:details|kbd|mark)\b/i;
|
|
17
|
-
function protectedToken(index) {
|
|
18
|
-
return `${PROTECTED_PREFIX}${index}${PROTECTED_SUFFIX}`;
|
|
19
|
-
}
|
|
20
|
-
function lineWithoutEnding(line) {
|
|
21
|
-
return line.endsWith('\n') ? line.slice(0, -1).replace(/\r$/, '') : line;
|
|
22
|
-
}
|
|
23
|
-
function protectFencedCode(source, protectedParts) {
|
|
24
|
-
const lines = source.match(/[^\n]*(?:\n|$)/g)?.filter((line) => line !== '') ?? [];
|
|
25
|
-
const out = [];
|
|
26
|
-
for (let index = 0; index < lines.length;) {
|
|
27
|
-
const openingLine = lineWithoutEnding(lines[index]);
|
|
28
|
-
const opening = /^ {0,3}(`{3,}|~{3,})[^\n]*$/.exec(openingLine);
|
|
29
|
-
if (!opening) {
|
|
30
|
-
out.push(lines[index]);
|
|
31
|
-
index++;
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
const marker = opening[1];
|
|
35
|
-
const markerChar = marker[0];
|
|
36
|
-
let end = index + 1;
|
|
37
|
-
for (; end < lines.length; end++) {
|
|
38
|
-
const candidate = lineWithoutEnding(lines[end]);
|
|
39
|
-
const closing = /^ {0,3}(`+|~+)[ \t]*$/.exec(candidate)?.[1];
|
|
40
|
-
if (closing?.[0] === markerChar && closing.length >= marker.length) {
|
|
41
|
-
end++;
|
|
42
|
-
break;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const raw = lines.slice(index, end).join('');
|
|
46
|
-
const tokenIndex = protectedParts.push(raw) - 1;
|
|
47
|
-
out.push(protectedToken(tokenIndex));
|
|
48
|
-
index = end;
|
|
49
|
-
}
|
|
50
|
-
return out.join('');
|
|
51
|
-
}
|
|
52
|
-
function protectInlineCode(source, protectedParts) {
|
|
53
|
-
let out = '';
|
|
54
|
-
let index = 0;
|
|
55
|
-
while (index < source.length) {
|
|
56
|
-
if (source[index] !== '`') {
|
|
57
|
-
out += source[index];
|
|
58
|
-
index++;
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
let openingEnd = index + 1;
|
|
62
|
-
while (source[openingEnd] === '`')
|
|
63
|
-
openingEnd++;
|
|
64
|
-
const markerLength = openingEnd - index;
|
|
65
|
-
let cursor = openingEnd;
|
|
66
|
-
let closingEnd = -1;
|
|
67
|
-
while (cursor < source.length) {
|
|
68
|
-
const next = source.indexOf('`', cursor);
|
|
69
|
-
if (next === -1)
|
|
70
|
-
break;
|
|
71
|
-
let runEnd = next + 1;
|
|
72
|
-
while (source[runEnd] === '`')
|
|
73
|
-
runEnd++;
|
|
74
|
-
if (runEnd - next === markerLength) {
|
|
75
|
-
closingEnd = runEnd;
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
cursor = runEnd;
|
|
79
|
-
}
|
|
80
|
-
if (closingEnd === -1) {
|
|
81
|
-
out += source.slice(index, openingEnd);
|
|
82
|
-
index = openingEnd;
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
const tokenIndex = protectedParts.push(source.slice(index, closingEnd)) - 1;
|
|
86
|
-
out += protectedToken(tokenIndex);
|
|
87
|
-
index = closingEnd;
|
|
88
|
-
}
|
|
89
|
-
return out;
|
|
90
|
-
}
|
|
91
|
-
function protectMarkdownCode(source) {
|
|
92
|
-
const protectedParts = [];
|
|
93
|
-
const fenced = protectFencedCode(source, protectedParts);
|
|
94
|
-
const masked = protectInlineCode(fenced, protectedParts);
|
|
95
|
-
return {
|
|
96
|
-
masked,
|
|
97
|
-
restore: (text) => text.replace(/\u0000\u0001CRTR_HTML_CODE_(\d+)\u0002/g, (_whole, rawIndex) => protectedParts[Number(rawIndex)] ?? ''),
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
function isEscaped(source, index) {
|
|
101
|
-
let slashes = 0;
|
|
102
|
-
for (let cursor = index - 1; cursor >= 0 && source[cursor] === '\\'; cursor--)
|
|
103
|
-
slashes++;
|
|
104
|
-
return slashes % 2 === 1;
|
|
105
|
-
}
|
|
106
|
-
/** HTML phrasing content for this allowlist is plain text. Escape CommonMark's
|
|
107
|
-
* ASCII punctuation so a key label such as `[x]` cannot become a link, while
|
|
108
|
-
* the Markdown renderer removes the escapes from the displayed text. */
|
|
109
|
-
function escapeMarkdownInline(text) {
|
|
110
|
-
return [...text].map((char) => /[!-/:-@[-`{-~]/.test(char) ? `\\${char}` : char).join('');
|
|
111
|
-
}
|
|
112
|
-
function transformInlineHtml(text, styles) {
|
|
113
|
-
return text.replace(INLINE_HTML, (whole, rawTag, rawBody, offset) => {
|
|
114
|
-
if (isEscaped(text, offset))
|
|
115
|
-
return whole;
|
|
116
|
-
const tag = rawTag.toLowerCase();
|
|
117
|
-
const body = tag === 'kbd' ? rawBody.replace(/\s+/g, ' ').trim() : rawBody.trim();
|
|
118
|
-
if (body === '')
|
|
119
|
-
return whole;
|
|
120
|
-
const escaped = escapeMarkdownInline(body);
|
|
121
|
-
return tag === 'kbd' ? styles.kbd(escaped) : styles.mark(escaped);
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
function findDetailsRange(source, openEnd) {
|
|
125
|
-
DETAILS_TAG.lastIndex = openEnd;
|
|
126
|
-
let depth = 1;
|
|
127
|
-
let nested = false;
|
|
128
|
-
for (let match = DETAILS_TAG.exec(source); match; match = DETAILS_TAG.exec(source)) {
|
|
129
|
-
if (isEscaped(source, match.index))
|
|
130
|
-
continue;
|
|
131
|
-
const closing = /^<\//.test(match[0]);
|
|
132
|
-
if (closing) {
|
|
133
|
-
depth--;
|
|
134
|
-
if (depth === 0)
|
|
135
|
-
return { closeStart: match.index, closeTag: match[0], end: DETAILS_TAG.lastIndex, nested };
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
depth++;
|
|
139
|
-
nested = true;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
DETAILS_TAG.lastIndex = 0;
|
|
143
|
-
return undefined;
|
|
144
|
-
}
|
|
145
|
-
function renderDetails(source, openTag, openEnd, range, options) {
|
|
146
|
-
if (!VALID_DETAILS_OPEN.test(openTag) || !VALID_DETAILS_CLOSE.test(range.closeTag) || range.nested)
|
|
147
|
-
return undefined;
|
|
148
|
-
const inner = source.slice(openEnd, range.closeStart);
|
|
149
|
-
const summaryOpen = SUMMARY_OPEN.exec(inner);
|
|
150
|
-
if (!summaryOpen)
|
|
151
|
-
return undefined;
|
|
152
|
-
const afterSummaryOpen = summaryOpen[0].length;
|
|
153
|
-
const summaryClose = SUMMARY_CLOSE.exec(inner.slice(afterSummaryOpen));
|
|
154
|
-
if (!summaryClose)
|
|
155
|
-
return undefined;
|
|
156
|
-
const summaryEnd = afterSummaryOpen + summaryClose.index;
|
|
157
|
-
const summary = inner.slice(afterSummaryOpen, summaryEnd).trim();
|
|
158
|
-
if (summary === '')
|
|
159
|
-
return undefined;
|
|
160
|
-
const summaryRendered = transformInlineHtml(summary, options.styles);
|
|
161
|
-
const openByAttribute = /[ \t\r\n]open[ \t\r\n]*>$/i.test(openTag);
|
|
162
|
-
const expanded = options.detailsExpanded ?? openByAttribute;
|
|
163
|
-
const glyph = expanded ? '▾' : '▸';
|
|
164
|
-
if (!expanded)
|
|
165
|
-
return `${glyph} ${summaryRendered} ${options.styles.hint('— ctrl+o to expand')}`;
|
|
166
|
-
const bodyStart = summaryEnd + summaryClose[0].length;
|
|
167
|
-
const body = inner.slice(bodyStart).trim();
|
|
168
|
-
if (body === '')
|
|
169
|
-
return `${glyph} ${summaryRendered}`;
|
|
170
|
-
return `${glyph} ${summaryRendered}\n\n${transformInlineHtml(body, options.styles)}`;
|
|
171
|
-
}
|
|
172
|
-
/** Transform the strict supported HTML subset in one Markdown string. */
|
|
173
|
-
export function transformHtmlMarkdown(source, options) {
|
|
174
|
-
if (!SUPPORTED_HTML.test(source))
|
|
175
|
-
return source;
|
|
176
|
-
const protectedMarkdown = protectMarkdownCode(source);
|
|
177
|
-
const masked = protectedMarkdown.masked;
|
|
178
|
-
let out = '';
|
|
179
|
-
let cursor = 0;
|
|
180
|
-
DETAILS_OPEN.lastIndex = 0;
|
|
181
|
-
for (let match = DETAILS_OPEN.exec(masked); match; match = DETAILS_OPEN.exec(masked)) {
|
|
182
|
-
if (match.index < cursor)
|
|
183
|
-
continue;
|
|
184
|
-
const range = findDetailsRange(masked, DETAILS_OPEN.lastIndex);
|
|
185
|
-
if (!range) {
|
|
186
|
-
out += transformInlineHtml(masked.slice(cursor, match.index), options.styles);
|
|
187
|
-
out += masked.slice(match.index);
|
|
188
|
-
cursor = masked.length;
|
|
189
|
-
break;
|
|
190
|
-
}
|
|
191
|
-
out += transformInlineHtml(masked.slice(cursor, match.index), options.styles);
|
|
192
|
-
const whole = masked.slice(match.index, range.end);
|
|
193
|
-
if (isEscaped(masked, match.index)) {
|
|
194
|
-
out += whole;
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
const rendered = renderDetails(masked, match[0], DETAILS_OPEN.lastIndex, range, options);
|
|
198
|
-
out += rendered ?? whole;
|
|
199
|
-
}
|
|
200
|
-
cursor = range.end;
|
|
201
|
-
DETAILS_OPEN.lastIndex = range.end;
|
|
202
|
-
}
|
|
203
|
-
if (cursor < masked.length)
|
|
204
|
-
out += transformInlineHtml(masked.slice(cursor), options.styles);
|
|
205
|
-
return protectedMarkdown.restore(out);
|
|
206
|
-
}
|