cli-jaw 2.0.10 → 2.0.16
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.ja.md +8 -5
- package/README.ko.md +8 -5
- package/README.md +31 -14
- package/README.zh-CN.md +8 -5
- package/dist/bin/commands/browser-web-ai.js +1 -0
- package/dist/bin/commands/browser-web-ai.js.map +1 -1
- package/dist/bin/commands/browser.js +1 -1
- package/dist/bin/commands/dashboard-memory.js +1 -0
- package/dist/bin/commands/dashboard-memory.js.map +1 -1
- package/dist/bin/commands/dispatch.js +34 -7
- package/dist/bin/commands/dispatch.js.map +1 -1
- package/dist/bin/commands/doctor.js +12 -6
- package/dist/bin/commands/doctor.js.map +1 -1
- package/dist/bin/commands/init.js +1 -2
- package/dist/bin/commands/init.js.map +1 -1
- package/dist/bin/commands/orchestrate.js +6 -4
- package/dist/bin/commands/orchestrate.js.map +1 -1
- package/dist/bin/commands/serve.js +3 -1
- package/dist/bin/commands/serve.js.map +1 -1
- package/dist/bin/commands/tui/overlays.js +4 -4
- package/dist/bin/commands/tui/overlays.js.map +1 -1
- package/dist/bin/commands/tui/types.js +2 -0
- package/dist/bin/commands/tui/types.js.map +1 -1
- package/dist/bin/postinstall.js +0 -176
- package/dist/bin/postinstall.js.map +1 -1
- package/dist/scripts/fresh-install-smoke.js +1 -2
- package/dist/scripts/fresh-install-smoke.js.map +1 -1
- package/dist/server.js +52 -18
- package/dist/server.js.map +1 -1
- package/dist/src/agent/agy-runtime.js +4 -0
- package/dist/src/agent/agy-runtime.js.map +1 -1
- package/dist/src/agent/alert-escalation.js +8 -2
- package/dist/src/agent/alert-escalation.js.map +1 -1
- package/dist/src/agent/args.js +35 -2
- package/dist/src/agent/args.js.map +1 -1
- package/dist/src/agent/codex-app-client.js +3 -0
- package/dist/src/agent/codex-app-client.js.map +1 -1
- package/dist/src/agent/cursor-runtime.js +240 -0
- package/dist/src/agent/cursor-runtime.js.map +1 -0
- package/dist/src/agent/events/acp.js +7 -3
- package/dist/src/agent/events/acp.js.map +1 -1
- package/dist/src/agent/events/claude.js +5 -2
- package/dist/src/agent/events/claude.js.map +1 -1
- package/dist/src/agent/events/codex.js +21 -13
- package/dist/src/agent/events/codex.js.map +1 -1
- package/dist/src/agent/events/cursor.js +176 -0
- package/dist/src/agent/events/cursor.js.map +1 -0
- package/dist/src/agent/events/grok.js +13 -3
- package/dist/src/agent/events/grok.js.map +1 -1
- package/dist/src/agent/events/index.js +27 -0
- package/dist/src/agent/events/index.js.map +1 -1
- package/dist/src/agent/events/tool-labels.js +13 -6
- package/dist/src/agent/events/tool-labels.js.map +1 -1
- package/dist/src/agent/lifecycle-handler.js +150 -5
- package/dist/src/agent/lifecycle-handler.js.map +1 -1
- package/dist/src/agent/resume-classifier.js +2 -0
- package/dist/src/agent/resume-classifier.js.map +1 -1
- package/dist/src/agent/spawn/resume.js +13 -2
- package/dist/src/agent/spawn/resume.js.map +1 -1
- package/dist/src/agent/spawn.js +44 -17
- package/dist/src/agent/spawn.js.map +1 -1
- package/dist/src/cli/claude-models.js +3 -0
- package/dist/src/cli/claude-models.js.map +1 -1
- package/dist/src/cli/commands.js +66 -10
- package/dist/src/cli/commands.js.map +1 -1
- package/dist/src/cli/handlers-runtime.js +2 -2
- package/dist/src/cli/handlers-runtime.js.map +1 -1
- package/dist/src/cli/handlers-workflows.js +339 -0
- package/dist/src/cli/handlers-workflows.js.map +1 -0
- package/dist/src/cli/handlers.js +11 -1
- package/dist/src/cli/handlers.js.map +1 -1
- package/dist/src/cli/readiness.js +22 -1
- package/dist/src/cli/readiness.js.map +1 -1
- package/dist/src/cli/registry.js +12 -0
- package/dist/src/cli/registry.js.map +1 -1
- package/dist/src/cli/tui/overlay.js +2 -2
- package/dist/src/cli/tui/overlay.js.map +1 -1
- package/dist/src/command-contract/catalog.js +3 -1
- package/dist/src/command-contract/catalog.js.map +1 -1
- package/dist/src/core/cli-detection.js +203 -0
- package/dist/src/core/cli-detection.js.map +1 -0
- package/dist/src/core/config.js +2 -140
- package/dist/src/core/config.js.map +1 -1
- package/dist/src/core/runtime-settings.js +31 -0
- package/dist/src/core/runtime-settings.js.map +1 -1
- package/dist/src/discord/bot.js +47 -26
- package/dist/src/discord/bot.js.map +1 -1
- package/dist/src/discord/commands.js +4 -10
- package/dist/src/discord/commands.js.map +1 -1
- package/dist/src/discord/send-only-client.js +79 -0
- package/dist/src/discord/send-only-client.js.map +1 -0
- package/dist/src/goal/heartbeat.js +51 -0
- package/dist/src/goal/heartbeat.js.map +1 -0
- package/dist/src/goal/runtime.js +31 -0
- package/dist/src/goal/runtime.js.map +1 -0
- package/dist/src/goal/store.js +153 -0
- package/dist/src/goal/store.js.map +1 -0
- package/dist/src/goal/types.js +2 -0
- package/dist/src/goal/types.js.map +1 -0
- package/dist/src/goal-run/controller.js +113 -0
- package/dist/src/goal-run/controller.js.map +1 -0
- package/dist/src/goal-run/events.js +25 -0
- package/dist/src/goal-run/events.js.map +1 -0
- package/dist/src/goal-run/failure-matrix.js +26 -0
- package/dist/src/goal-run/failure-matrix.js.map +1 -0
- package/dist/src/goal-run/policy.js +46 -0
- package/dist/src/goal-run/policy.js.map +1 -0
- package/dist/src/goal-run/types.js +2 -0
- package/dist/src/goal-run/types.js.map +1 -0
- package/dist/src/manager/git/diff-service.js +202 -0
- package/dist/src/manager/git/diff-service.js.map +1 -0
- package/dist/src/manager/notes/assets.js +11 -4
- package/dist/src/manager/notes/assets.js.map +1 -1
- package/dist/src/manager/notes/auth.js +123 -0
- package/dist/src/manager/notes/auth.js.map +1 -0
- package/dist/src/manager/notes/git.js +154 -0
- package/dist/src/manager/notes/git.js.map +1 -0
- package/dist/src/manager/notes/plugins.js +107 -0
- package/dist/src/manager/notes/plugins.js.map +1 -0
- package/dist/src/manager/notes/routes.js +91 -2
- package/dist/src/manager/notes/routes.js.map +1 -1
- package/dist/src/manager/notes/store.js +71 -1
- package/dist/src/manager/notes/store.js.map +1 -1
- package/dist/src/manager/notes/watcher.js +40 -4
- package/dist/src/manager/notes/watcher.js.map +1 -1
- package/dist/src/manager/notes/wiki-links.js +99 -10
- package/dist/src/manager/notes/wiki-links.js.map +1 -1
- package/dist/src/manager/notes/ws.js +62 -0
- package/dist/src/manager/notes/ws.js.map +1 -0
- package/dist/src/manager/preview-link-policy.js +46 -0
- package/dist/src/manager/preview-link-policy.js.map +1 -0
- package/dist/src/manager/preview-origin-proxy.js +28 -5
- package/dist/src/manager/preview-origin-proxy.js.map +1 -1
- package/dist/src/manager/preview-ports.js +12 -0
- package/dist/src/manager/preview-ports.js.map +1 -0
- package/dist/src/manager/proxy.js +15 -3
- package/dist/src/manager/proxy.js.map +1 -1
- package/dist/src/manager/registry.js +115 -0
- package/dist/src/manager/registry.js.map +1 -1
- package/dist/src/manager/routes/dashboard-git.js +106 -0
- package/dist/src/manager/routes/dashboard-git.js.map +1 -0
- package/dist/src/manager/server.js +60 -4
- package/dist/src/manager/server.js.map +1 -1
- package/dist/src/memory/heartbeat.js +4 -1
- package/dist/src/memory/heartbeat.js.map +1 -1
- package/dist/src/messaging/channel-health.js +54 -0
- package/dist/src/messaging/channel-health.js.map +1 -0
- package/dist/src/messaging/runtime.js +1 -0
- package/dist/src/messaging/runtime.js.map +1 -1
- package/dist/src/messaging/send-result.js +9 -0
- package/dist/src/messaging/send-result.js.map +1 -0
- package/dist/src/orchestrator/pipeline.js +45 -0
- package/dist/src/orchestrator/pipeline.js.map +1 -1
- package/dist/src/orchestrator/state-machine.js +50 -1
- package/dist/src/orchestrator/state-machine.js.map +1 -1
- package/dist/src/prompt/templates/a1-system.md +16 -8
- package/dist/src/prompt/templates/employee.md +3 -1
- package/dist/src/prompt/templates/orchestration.md +15 -5
- package/dist/src/routes/goal-run.js +86 -0
- package/dist/src/routes/goal-run.js.map +1 -0
- package/dist/src/routes/goal.js +118 -0
- package/dist/src/routes/goal.js.map +1 -0
- package/dist/src/routes/messaging.js +17 -11
- package/dist/src/routes/messaging.js.map +1 -1
- package/dist/src/routes/orchestrate.js +47 -17
- package/dist/src/routes/orchestrate.js.map +1 -1
- package/dist/src/routes/quota-agy-reverse.js +133 -0
- package/dist/src/routes/quota-agy-reverse.js.map +1 -0
- package/dist/src/routes/quota-cursor-dashboard.js +200 -0
- package/dist/src/routes/quota-cursor-dashboard.js.map +1 -0
- package/dist/src/routes/settings.js +6 -6
- package/dist/src/routes/settings.js.map +1 -1
- package/dist/src/team/collector.js +45 -0
- package/dist/src/team/collector.js.map +1 -0
- package/dist/src/team/dispatcher.js +35 -0
- package/dist/src/team/dispatcher.js.map +1 -0
- package/dist/src/team/planner.js +58 -0
- package/dist/src/team/planner.js.map +1 -0
- package/dist/src/team/preflight.js +46 -0
- package/dist/src/team/preflight.js.map +1 -0
- package/dist/src/team/types.js +12 -0
- package/dist/src/team/types.js.map +1 -0
- package/dist/src/telegram/bot.js +41 -10
- package/dist/src/telegram/bot.js.map +1 -1
- package/dist/src/types/cli-engine.js +1 -0
- package/dist/src/types/cli-engine.js.map +1 -1
- package/dist/src/types/cli-events.js +1 -1
- package/dist/src/types/cli-events.js.map +1 -1
- package/dist/src/workflows/artifacts.js +148 -0
- package/dist/src/workflows/artifacts.js.map +1 -0
- package/dist/src/workflows/browser-web-ai.js +18 -0
- package/dist/src/workflows/browser-web-ai.js.map +1 -0
- package/dist/src/workflows/checkpoint/store.js +31 -0
- package/dist/src/workflows/checkpoint/store.js.map +1 -0
- package/dist/src/workflows/checkpoint/types.js +4 -0
- package/dist/src/workflows/checkpoint/types.js.map +1 -0
- package/dist/src/workflows/competitive-gap.js +96 -0
- package/dist/src/workflows/competitive-gap.js.map +1 -0
- package/dist/src/workflows/context-map/builder.js +61 -0
- package/dist/src/workflows/context-map/builder.js.map +1 -0
- package/dist/src/workflows/context.js +19 -0
- package/dist/src/workflows/context.js.map +1 -0
- package/dist/src/workflows/deliberate.js +67 -0
- package/dist/src/workflows/deliberate.js.map +1 -0
- package/dist/src/workflows/employee-boundary.js +33 -0
- package/dist/src/workflows/employee-boundary.js.map +1 -0
- package/dist/src/workflows/events.js +24 -0
- package/dist/src/workflows/events.js.map +1 -0
- package/dist/src/workflows/guards.js +18 -0
- package/dist/src/workflows/guards.js.map +1 -0
- package/dist/src/workflows/handoff.js +48 -0
- package/dist/src/workflows/handoff.js.map +1 -0
- package/dist/src/workflows/index.js +6 -0
- package/dist/src/workflows/index.js.map +1 -0
- package/dist/src/workflows/permissions/policy.js +25 -0
- package/dist/src/workflows/permissions/policy.js.map +1 -0
- package/dist/src/workflows/permissions/types.js +26 -0
- package/dist/src/workflows/permissions/types.js.map +1 -0
- package/dist/src/workflows/plan.js +70 -0
- package/dist/src/workflows/plan.js.map +1 -0
- package/dist/src/workflows/planaudit.js +64 -0
- package/dist/src/workflows/planaudit.js.map +1 -0
- package/dist/src/workflows/runtime-guards.js +46 -0
- package/dist/src/workflows/runtime-guards.js.map +1 -0
- package/dist/src/workflows/runtime.js +25 -0
- package/dist/src/workflows/runtime.js.map +1 -0
- package/dist/src/workflows/status.js +49 -0
- package/dist/src/workflows/status.js.map +1 -0
- package/dist/src/workflows/types.js +4 -0
- package/dist/src/workflows/types.js.map +1 -0
- package/dist/src/workflows/web-ai-guards.js +22 -0
- package/dist/src/workflows/web-ai-guards.js.map +1 -0
- package/package.json +9 -4
- package/public/assets/providers/cursor-color.svg +2 -0
- package/public/assets/providers/cursor.svg +2 -0
- package/public/css/chat.css +99 -0
- package/public/css/orc-state.css +11 -1
- package/public/css/sidebar.css +34 -0
- package/public/css/variables.css +23 -2
- package/public/css/workflow-cockpit.css +62 -0
- package/public/dist/assets/{AdvancedExport-CZEVPqHb.js → AdvancedExport-DLCgT_ZP.js} +1 -1
- package/public/dist/assets/{Agent-BBrJGd5m.js → Agent-CIUGaUVn.js} +1 -1
- package/public/dist/assets/{Browser-dBaU9G9D.js → Browser-C4TCAhKR.js} +1 -1
- package/public/dist/assets/BrowserPanel-BN01Lfc5.css +1 -0
- package/public/dist/assets/BrowserPanel-weeCb2qu.js +1 -0
- package/public/dist/assets/ChannelsDiscord-Bwt2-Jva.js +1 -0
- package/public/dist/assets/ChannelsTelegram-xjA3-Mr8.js +1 -0
- package/public/dist/assets/{DashboardMeta-LVAL7TtE.js → DashboardMeta-CBckkL_V.js} +1 -1
- package/public/dist/assets/DiffPanel-BHvC0wCX.css +1 -0
- package/public/dist/assets/DiffPanel-DZ4-3QSH.js +3 -0
- package/public/dist/assets/{Display-CFm1UmEo.js → Display-BPbCVOoi.js} +1 -1
- package/public/dist/assets/DocPanel-C1pGgE-S.js +1 -0
- package/public/dist/assets/DocPanel-CL1scIfq.css +1 -0
- package/public/dist/assets/Employees-BL9MAzzx.js +1 -0
- package/public/dist/assets/FolderPanel-DSkanaGN.js +1 -0
- package/public/dist/assets/FolderPanel-XCno5AI9.css +1 -0
- package/public/dist/assets/Heartbeat-D64JCg4t.js +1 -0
- package/public/dist/assets/MarkdownRenderer-CS6jvLpf.js +15 -0
- package/public/dist/assets/{Mcp-9NU4YkKO.js → Mcp-wYwJA_61.js} +1 -1
- package/public/dist/assets/{Memory-uZT30fww.js → Memory-BgN8djV4.js} +1 -1
- package/public/dist/assets/MilkdownWysiwygEditor-Btwmr5Re.js +160 -0
- package/public/dist/assets/{ModelProvider-CsIOyoZP.js → ModelProvider-DHQ1Zvw0.js} +1 -1
- package/public/dist/assets/{Network-D7hGwnyG.js → Network-B-WvB6R5.js} +1 -1
- package/public/dist/assets/NotesGraphWorkspace-CK8kKY8A.js +1 -0
- package/public/dist/assets/{Permissions-DwdU3wi8.js → Permissions-BvtVczZS.js} +1 -1
- package/public/dist/assets/Permissions-QxvByCop.js +1 -0
- package/public/dist/assets/{Profile-BNTKD_Ex.js → Profile-D_6kFj73.js} +1 -1
- package/public/dist/assets/{Prompts-D_mCfYiu.js → Prompts--4CM3enz.js} +1 -1
- package/public/dist/assets/{SpeechKeys-BTXCM-Fs.js → SpeechKeys-Cx4_SXTM.js} +1 -1
- package/public/dist/assets/TerminalPanel-AKKXu8dJ.js +36 -0
- package/public/dist/assets/TerminalPanel-DdE69MNo.css +1 -0
- package/public/dist/assets/TransportStatusChips-BwR7Sq4s.js +1 -0
- package/public/dist/assets/agent-meta-BhEbjy4P.js +1 -0
- package/public/dist/assets/api-30EcU_Lb.js +1 -0
- package/public/dist/assets/app-DLDdZ41k.js +48 -0
- package/public/dist/assets/app-RpnKs-sT.css +1 -0
- package/public/dist/assets/architecture-7EHR7CIX-GHIeXYpv.js +1 -0
- package/public/dist/assets/{architectureDiagram-3BPJPVTR-CJCPEsxo.js → architectureDiagram-3BPJPVTR-ByOUFrxp.js} +1 -1
- package/public/dist/assets/{blockDiagram-GPEHLZMM-CO1bkn0E.js → blockDiagram-GPEHLZMM-BcefwseF.js} +2 -2
- package/public/dist/assets/{c4Diagram-AAUBKEIU-D2R36Xu6.js → c4Diagram-AAUBKEIU-C9FinBRA.js} +1 -1
- package/public/dist/assets/channel-5QxFRU5l.js +1 -0
- package/public/dist/assets/{chunk-2J33WTMH-xiPJWKcl.js → chunk-2J33WTMH-N9wxleFR.js} +1 -1
- package/public/dist/assets/{chunk-3OPIFGDE-DixnEkZw.js → chunk-3OPIFGDE-B1qdy3mP.js} +1 -1
- package/public/dist/assets/{chunk-4BX2VUAB-6lTRwyT0.js → chunk-4BX2VUAB-Dbg5PjGD.js} +1 -1
- package/public/dist/assets/{chunk-4EGX6M5U-DXtAEgX6.js → chunk-4EGX6M5U-BIFnMXqg.js} +1 -1
- package/public/dist/assets/chunk-55IACEB6-C9gRJHcb.js +1 -0
- package/public/dist/assets/{chunk-5DO6E6H7-DDcMHB95.js → chunk-5DO6E6H7-Dc9k92pO.js} +1 -1
- package/public/dist/assets/{chunk-5ZQYHXKU-Bli4k6GI.js → chunk-5ZQYHXKU-BOYB4Qmp.js} +2 -2
- package/public/dist/assets/{chunk-727SXJPM-sp4W8bhf.js → chunk-727SXJPM-2OgKkBMF.js} +1 -1
- package/public/dist/assets/{chunk-AQP2D5EJ-Co6ucdGq.js → chunk-AQP2D5EJ-CIXopxD6.js} +1 -1
- package/public/dist/assets/{chunk-BR22UD5L-CVuYkAd1.js → chunk-BR22UD5L-DlNCrhSA.js} +1 -1
- package/public/dist/assets/{chunk-BSJP7CBP-B47GpxcW.js → chunk-BSJP7CBP-CpgaSqhR.js} +1 -1
- package/public/dist/assets/{chunk-CSCIHK7Q-CAE1p4Em.js → chunk-CSCIHK7Q-R-Y9ue5N.js} +1 -1
- package/public/dist/assets/{chunk-FHYWG6QK-CxZt-yZZ.js → chunk-FHYWG6QK-DVrRFYRd.js} +1 -1
- package/public/dist/assets/{chunk-FMBD7UC4-CwqBlx0l.js → chunk-FMBD7UC4-jn5b6_kv.js} +1 -1
- package/public/dist/assets/{chunk-KSCS5N6A-Beq1s5eO.js → chunk-KSCS5N6A-DayXQgYz.js} +2 -2
- package/public/dist/assets/{chunk-L5ZTLDWV-DfUlBdXN.js → chunk-L5ZTLDWV-CtcQ12uz.js} +1 -1
- package/public/dist/assets/{chunk-LZXEDZCA-B_yP4UKw.js → chunk-LZXEDZCA-BuEa86aU.js} +1 -1
- package/public/dist/assets/{chunk-MPE355IW-Bp4qAOUf.js → chunk-MPE355IW-Be8tT5FQ.js} +1 -1
- package/public/dist/assets/{chunk-MZUSXYTE-DAU-v-0c.js → chunk-MZUSXYTE-bFnwST0F.js} +1 -1
- package/public/dist/assets/{chunk-N66VUXT2-CpPz1L5u.js → chunk-N66VUXT2-BSpsJq6A.js} +1 -1
- package/public/dist/assets/{chunk-ND2GUHAM-3qbNb7I9.js → chunk-ND2GUHAM-CnEcVn6T.js} +1 -1
- package/public/dist/assets/{chunk-NZK2D7GU-CTqFQ8K5.js → chunk-NZK2D7GU-asW9Yrwq.js} +1 -1
- package/public/dist/assets/{chunk-O5CBEL6O-D-jDqsN2.js → chunk-O5CBEL6O-BVoXQ09V.js} +1 -1
- package/public/dist/assets/{chunk-PUPMXCY4-ppZvktf-.js → chunk-PUPMXCY4-BU48euO5.js} +1 -1
- package/public/dist/assets/chunk-QZHKN3VN-CC7ecfZE.js +1 -0
- package/public/dist/assets/{chunk-UIBZB4QT-rJZEVBX0.js → chunk-UIBZB4QT-aXCea_7h.js} +1 -1
- package/public/dist/assets/{chunk-WCWK7LTN-CGvUyB8h.js → chunk-WCWK7LTN-fR0CutHV.js} +1 -1
- package/public/dist/assets/chunk-WU5MYG2G-CDC6hlhk.js +1 -0
- package/public/dist/assets/{chunk-XPW4576I-BaQfzRci.js → chunk-XPW4576I-CFkDqujt.js} +1 -1
- package/public/dist/assets/classDiagram-4FO5ZUOK-Bfu4_8Yk.js +1 -0
- package/public/dist/assets/classDiagram-v2-Q7XG4LA2-_XyS72AY.js +1 -0
- package/public/dist/assets/constants-ahKI_aEG.js +1 -0
- package/public/dist/assets/{cose-bilkent-S5V4N54A-Bt9AAJCx.js → cose-bilkent-S5V4N54A-CZbCTJt4.js} +1 -1
- package/public/dist/assets/{dagre-BM42HDAG-CXEA1wvZ.js → dagre-BM42HDAG-BB0IJKjW.js} +1 -1
- package/public/dist/assets/{dagre-Ve-IAfyz.js → dagre-D4AB5Dyv.js} +1 -1
- package/public/dist/assets/desktop-bridge-CrqidwSb.js +1 -0
- package/public/dist/assets/{diagram-2AECGRRQ-CCB0OKc2.js → diagram-2AECGRRQ-CHUQ78BD.js} +1 -1
- package/public/dist/assets/{diagram-5GNKFQAL-Cki9HABy.js → diagram-5GNKFQAL-onxHMGMn.js} +1 -1
- package/public/dist/assets/{diagram-KO2AKTUF-DNBDjE2o.js → diagram-KO2AKTUF-BlgkTTwi.js} +1 -1
- package/public/dist/assets/{diagram-LMA3HP47-Cy23RDPa.js → diagram-LMA3HP47-BVWYubzU.js} +1 -1
- package/public/dist/assets/{diagram-OG6HWLK6-CT_YF8cA.js → diagram-OG6HWLK6-BM7IcJ6z.js} +1 -1
- package/public/dist/assets/dist-2S2B_MeU.js +1 -0
- package/public/dist/assets/dist-B2d2NOJ3.js +1 -0
- package/public/dist/assets/dist-BSF2Z7j1.js +6 -0
- package/public/dist/assets/dist-BZh7LRrp.js +1 -0
- package/public/dist/assets/dist-BaazPVzw.js +1 -0
- package/public/dist/assets/dist-Bn4kv_Se.js +1 -0
- package/public/dist/assets/dist-CB1fgeSN.js +1 -0
- package/public/dist/assets/dist-CG0XIeov.js +1 -0
- package/public/dist/assets/dist-CG65f_qI.js +1 -0
- package/public/dist/assets/dist-CJwXuDux.js +39 -0
- package/public/dist/assets/dist-CU9b0vPA.js +1 -0
- package/public/dist/assets/dist-CkWMWu5F.js +23 -0
- package/public/dist/assets/dist-CsK9fYYW.js +1 -0
- package/public/dist/assets/dist-CuNACpdD.js +1 -0
- package/public/dist/assets/dist-CzDHA1yv.js +1 -0
- package/public/dist/assets/dist-D0mdXpwq.js +1 -0
- package/public/dist/assets/{dist-3R3GxjCf.js → dist-DCefgfkj.js} +5 -5
- package/public/dist/assets/dist-DJ5byDHS2.js +1 -0
- package/public/dist/assets/dist-DLSl_Nbu.js +1 -0
- package/public/dist/assets/dist-DLa7--1u.js +1 -0
- package/public/dist/assets/dist-DZ1vWpde.js +1 -0
- package/public/dist/assets/dist-D_ULP6ER.js +1 -0
- package/public/dist/assets/dist-Dgo6P711.js +1 -0
- package/public/dist/assets/dist-DtkJvqbT.js +9 -0
- package/public/dist/assets/dist-DwzmyMDC.js +1 -0
- package/public/dist/assets/dist-H3yurMdo.js +11 -0
- package/public/dist/assets/dist-HtoUbUb4.js +1 -0
- package/public/dist/assets/dist-P76w4V8t.js +2 -0
- package/public/dist/assets/{dist-DuuoJfRB.js → dist-SWkyI5gN.js} +2 -2
- package/public/dist/assets/dist-w85EQGWO.js +1 -0
- package/public/dist/assets/{dockerfile-DAfh5qoE.js → dockerfile-O79f3xVO.js} +1 -1
- package/public/dist/assets/employees-DZSPGlaH.js +33 -0
- package/public/dist/assets/{erDiagram-TEJ5UH35-Cq7oHdXg.js → erDiagram-TEJ5UH35-Dr-3ziJG.js} +1 -1
- package/public/dist/assets/eventmodeling-FCH6USID-Du0rADZ8.js +1 -0
- package/public/dist/assets/{factor-BpoYJieo.js → factor-2MJ0aFHQ.js} +1 -1
- package/public/dist/assets/{flowDiagram-I6XJVG4X-D8CdEnfM.js → flowDiagram-I6XJVG4X-COxvv8bU.js} +1 -1
- package/public/dist/assets/{ganttDiagram-6RSMTGT7-B1rzKXi_.js → ganttDiagram-6RSMTGT7-BztWk1Ow.js} +2 -2
- package/public/dist/assets/gitGraph-WXDBUCRP-Cw5oPUI1.js +1 -0
- package/public/dist/assets/{gitGraphDiagram-PVQCEYII-CqLh-joi.js → gitGraphDiagram-PVQCEYII-Dw-pLiB8.js} +1 -1
- package/public/dist/assets/{graphlib-W5bESv3F.js → graphlib-DCNdUnXF.js} +1 -1
- package/public/dist/assets/info-J43DQDTF-bda--3fv.js +1 -0
- package/public/dist/assets/{infoDiagram-5YYISTIA-C1zVxumj.js → infoDiagram-5YYISTIA-BSM5RFYV.js} +1 -1
- package/public/dist/assets/{ishikawaDiagram-YF4QCWOH-x-9J6xPM.js → ishikawaDiagram-YF4QCWOH-DGqEaMN9.js} +1 -1
- package/public/dist/assets/javascript-BIzwdG_f.js +1 -0
- package/public/dist/assets/{journeyDiagram-JHISSGLW-BDYzHrtn.js → journeyDiagram-JHISSGLW-CBGlHr__.js} +1 -1
- package/public/dist/assets/{kanban-definition-UN3LZRKU-BJ-06i6Z.js → kanban-definition-UN3LZRKU-CtvwD90I.js} +1 -1
- package/public/dist/assets/manager-CFxbpg7j.css +1 -0
- package/public/dist/assets/manager-wAHlX68t.js +12 -0
- package/public/dist/assets/memory-B4RpXXJ7.js +20 -0
- package/public/dist/assets/memory-C9EVOb_D.js +1 -0
- package/public/dist/assets/mermaid-loader-BPeAxEES.js +1 -0
- package/public/dist/assets/{mermaid-parser.core-C62NUJRb.js → mermaid-parser.core-BB62R3s0.js} +1 -1
- package/public/dist/assets/mermaid.core-86z3EI0c.js +1 -0
- package/public/dist/assets/{mermaid.core-D8VnfThU.js → mermaid.core-Eh0d41ge.js} +2 -2
- package/public/dist/assets/{mindmap-definition-RKZ34NQL-D8NDuIhn.js → mindmap-definition-RKZ34NQL-Cg1Nirgc.js} +1 -1
- package/public/dist/assets/notes-graph-settings-CznA-Qu0.js +1 -0
- package/public/dist/assets/{nsis-Ch4QINLN.js → nsis-CVYtDIFk.js} +1 -1
- package/public/dist/assets/packet-YPE3B663-CdmMldz9.js +1 -0
- package/public/dist/assets/pie-LRSECV5Y-Bh7evnjl.js +1 -0
- package/public/dist/assets/{pieDiagram-4H26LBE5-CpBePil_.js → pieDiagram-4H26LBE5--PRag7Te.js} +1 -1
- package/public/dist/assets/{provider-icons-ClVd2suJ.js → provider-icons-XEfJPGTe.js} +9 -5
- package/public/dist/assets/{pug-CXYqmmpP.js → pug-DplZiQL-.js} +1 -1
- package/public/dist/assets/{quadrantDiagram-W4KKPZXB-C1WWpn88.js → quadrantDiagram-W4KKPZXB-BTql-Bsn.js} +1 -1
- package/public/dist/assets/radar-GUYGQ44K-Bi6iY53d.js +1 -0
- package/public/dist/assets/render-DnylWKO1.js +28 -0
- package/public/dist/assets/{requirementDiagram-4Y6WPE33-C_D5VbNk.js → requirementDiagram-4Y6WPE33-43_zBMme.js} +1 -1
- package/public/dist/assets/{sankeyDiagram-5OEKKPKP--RH3Es8R.js → sankeyDiagram-5OEKKPKP-Bhvu7fVp.js} +1 -1
- package/public/dist/assets/{sequenceDiagram-3UESZ5HK-CVI4AjhN.js → sequenceDiagram-3UESZ5HK-DiT6UbHL.js} +1 -1
- package/public/dist/assets/settings-DIG_i79X.js +1 -0
- package/public/dist/assets/settings-VCXKhhhz.js +66 -0
- package/public/dist/assets/sidebar-Bi_ktFVw.js +18 -0
- package/public/dist/assets/{skills-DbRVI-zf.js → skills-CW7NEhew.js} +2 -2
- package/public/dist/assets/skills-RjRqvykb.js +1 -0
- package/public/dist/assets/slash-commands-CAydTUgf.js +19 -0
- package/public/dist/assets/slash-commands-DdXu96Zd.js +1 -0
- package/public/dist/assets/{state-xhhyIPlq.js → state-D04-chBy.js} +1 -1
- package/public/dist/assets/{stateDiagram-AJRCARHV-4bx1rPZ3.js → stateDiagram-AJRCARHV-EdHNB699.js} +1 -1
- package/public/dist/assets/stateDiagram-v2-BHNVJYJU-CwXjV0-w.js +1 -0
- package/public/dist/assets/{timeline-definition-PNZ67QCA-DeQoGRE2.js → timeline-definition-PNZ67QCA-DLCG8ciJ.js} +1 -1
- package/public/dist/assets/{trace-drawer-CIVBXyRH.js → trace-drawer-G-KP3IbQ.js} +1 -1
- package/public/dist/assets/treeView-BLDUP644-gIRuNooA.js +1 -0
- package/public/dist/assets/treemap-LRROVOQU-DGFQnuQ3.js +1 -0
- package/public/dist/assets/ui-CIQjTLzc.js +1 -0
- package/public/dist/assets/ui-CkHB9Jmo.js +140 -0
- package/public/dist/assets/vendor-utils-BydMkEGM.js +1 -0
- package/public/dist/assets/{vennDiagram-CIIHVFJN-CejyJK0L.js → vennDiagram-CIIHVFJN-C93tL0id.js} +1 -1
- package/public/dist/assets/wardley-L42UT6IY-D7Pv8rzC.js +1 -0
- package/public/dist/assets/{wardleyDiagram-YWT4CUSO-DqXV0sa1.js → wardleyDiagram-YWT4CUSO-BQQr2bW2.js} +1 -1
- package/public/dist/assets/wiki-link-resolver-CQwLeKpN.js +22 -0
- package/public/dist/assets/wiki-link-suggestions-DnVtu7Jb.js +2 -0
- package/public/dist/assets/{xychartDiagram-2RQKCTM6-CWLoVl2b.js → xychartDiagram-2RQKCTM6-DGZ5VpP9.js} +2 -2
- package/public/dist/index.html +36 -10
- package/public/dist/manager/index.html +2 -2
- package/public/index.html +35 -8
- package/public/js/constants.ts +22 -1
- package/public/js/diagram/iframe-renderer.ts +2 -1
- package/public/js/features/chat-messages.ts +2 -2
- package/public/js/features/chat.ts +144 -17
- package/public/js/features/copy-text.ts +39 -0
- package/public/js/features/employees.ts +5 -5
- package/public/js/features/memory.ts +3 -4
- package/public/js/features/message-actions.ts +3 -2
- package/public/js/features/message-history.ts +2 -2
- package/public/js/features/pending-queue.ts +3 -2
- package/public/js/features/preview-shortcut-bridge.ts +25 -10
- package/public/js/features/settings-channel.ts +3 -0
- package/public/js/features/settings-cli-status.ts +254 -45
- package/public/js/features/settings-core.ts +8 -0
- package/public/js/features/settings.ts +1 -1
- package/public/js/features/slash-commands.ts +34 -2
- package/public/js/features/theme.ts +34 -6
- package/public/js/features/transport-status-row.ts +91 -0
- package/public/js/features/workflow-event-adapter.ts +77 -0
- package/public/js/main.ts +21 -4
- package/public/js/preview-parent-origin.ts +38 -0
- package/public/js/provider-icons.ts +6 -1
- package/public/js/render/code-copy.ts +16 -18
- package/public/js/render/file-links.ts +127 -30
- package/public/js/render/notes-vault-path.ts +64 -0
- package/public/js/render/post-render.ts +2 -2
- package/public/js/render/svg-actions.ts +4 -1
- package/public/js/render.ts +1 -0
- package/public/js/state.ts +19 -1
- package/public/js/ws.ts +121 -8
- package/public/locales/en.json +40 -0
- package/public/locales/ja.json +31 -0
- package/public/locales/ko.json +40 -0
- package/public/locales/zh.json +31 -0
- package/public/manager/src/App.tsx +65 -64
- package/public/manager/src/AppChrome.tsx +14 -5
- package/public/manager/src/InstancePreview.tsx +113 -2
- package/public/manager/src/SidebarRailRouter.tsx +67 -4
- package/public/manager/src/api.ts +46 -0
- package/public/manager/src/browser-panel/BrowserPanel.tsx +445 -0
- package/public/manager/src/browser-panel/browser-panel.css +241 -0
- package/public/manager/src/browser-panel/browser-url.ts +55 -0
- package/public/manager/src/clipboard/copy-text.ts +27 -0
- package/public/manager/src/components/CommandBar.tsx +2 -0
- package/public/manager/src/components/CommandCenter.tsx +3 -1
- package/public/manager/src/components/DesktopPanelControls.tsx +79 -0
- package/public/manager/src/components/SidebarRail.tsx +1 -1
- package/public/manager/src/components/WorkspaceLayout.tsx +71 -1
- package/public/manager/src/dashboard-settings/DashboardDeveloperSettingsSection.tsx +123 -0
- package/public/manager/src/dashboard-settings/DashboardSettingsSidebar.tsx +6 -2
- package/public/manager/src/dashboard-settings/DashboardSettingsWorkspace.tsx +4 -1
- package/public/manager/src/dashboard-settings/dashboard-settings-ui.ts +8 -0
- package/public/manager/src/desktop-link.tsx +6 -1
- package/public/manager/src/diff-panel/DiffPanel.tsx +219 -0
- package/public/manager/src/diff-panel/diff-client.ts +46 -0
- package/public/manager/src/diff-panel/diff-panel.css +163 -0
- package/public/manager/src/diff-panel/diff-root-candidates.ts +54 -0
- package/public/manager/src/doc-panel/DocPanel.tsx +113 -0
- package/public/manager/src/doc-panel/doc-panel.css +57 -0
- package/public/manager/src/folder-panel/FolderPanel.tsx +144 -0
- package/public/manager/src/folder-panel/folder-panel.css +82 -0
- package/public/manager/src/folder-panel/folder-sources.ts +93 -0
- package/public/manager/src/help/helpContent.tsx +3 -0
- package/public/manager/src/hooks/useDashboardView.ts +22 -1
- package/public/manager/src/main.tsx +2 -0
- package/public/manager/src/manager-components.css +12 -0
- package/public/manager/src/manager-dashboard-reminders-priority.css +11 -0
- package/public/manager/src/manager-dashboard-reminders.css +29 -0
- package/public/manager/src/manager-layout.css +68 -22
- package/public/manager/src/manager-notes.css +181 -0
- package/public/manager/src/manager-p0-1-1.css +118 -1
- package/public/manager/src/manager-polish.css +15 -12
- package/public/manager/src/manager-shortcuts.ts +17 -0
- package/public/manager/src/manager-tokens.css +25 -0
- package/public/manager/src/notes/MarkdownEditor.tsx +26 -3
- package/public/manager/src/notes/NotesFileTree.tsx +24 -2
- package/public/manager/src/notes/NotesGraphView.tsx +1 -145
- package/public/manager/src/notes/NotesSidebar.tsx +4 -0
- package/public/manager/src/notes/NotesThemeLoader.tsx +104 -0
- package/public/manager/src/notes/NotesWorkspace.tsx +33 -5
- package/public/manager/src/notes/graph/NotesGraphCanvas.tsx +195 -0
- package/public/manager/src/notes/graph/NotesGraphControlsPanel.tsx +172 -0
- package/public/manager/src/notes/graph/NotesGraphWorkspace.tsx +116 -0
- package/public/manager/src/notes/graph/notes-graph-filter.ts +192 -0
- package/public/manager/src/notes/graph/notes-graph-force.ts +36 -0
- package/public/manager/src/notes/graph/notes-graph-settings.ts +121 -0
- package/public/manager/src/notes/notes-graph.css +382 -0
- package/public/manager/src/notes/rendering/CodeBlock.tsx +5 -4
- package/public/manager/src/notes/rendering/MarkdownRenderer.tsx +3 -0
- package/public/manager/src/notes/useNoteSync.ts +67 -0
- package/public/manager/src/notes/wysiwyg/MilkdownWysiwygEditor.tsx +4 -0
- package/public/manager/src/notes/wysiwyg/milkdown-code-block-view.ts +5 -1
- package/public/manager/src/notes/wysiwyg/milkdown-slash-menu.ts +192 -0
- package/public/manager/src/notes/wysiwyg/milkdown-table-menu.ts +120 -0
- package/public/manager/src/panels/BottomPanel.tsx +61 -0
- package/public/manager/src/panels/BottomPanelTabBar.tsx +71 -0
- package/public/manager/src/panels/PanelLayoutProvider.tsx +288 -0
- package/public/manager/src/panels/PanelResizer.tsx +71 -0
- package/public/manager/src/panels/RightSidebar.tsx +192 -0
- package/public/manager/src/panels/desktop-bridge.ts +112 -0
- package/public/manager/src/panels/panel-capabilities.ts +44 -0
- package/public/manager/src/panels/panel-layout-registry-state.ts +38 -0
- package/public/manager/src/panels/panel-shortcut-bus.ts +15 -0
- package/public/manager/src/panels/panels.css +274 -0
- package/public/manager/src/panels/types.ts +16 -0
- package/public/manager/src/preview.ts +11 -1
- package/public/manager/src/settings/pages/ChannelsDiscord.tsx +3 -1
- package/public/manager/src/settings/pages/ChannelsTelegram.tsx +3 -1
- package/public/manager/src/settings/pages/components/ActiveChannelToggle.tsx +2 -2
- package/public/manager/src/settings/pages/components/TransportStatusChips.tsx +108 -0
- package/public/manager/src/settings/pages/components/agent/agent-meta.ts +22 -3
- package/public/manager/src/settings/pages/components/employees-helpers.ts +1 -0
- package/public/manager/src/settings/pages/components/heartbeat-helpers.ts +1 -0
- package/public/manager/src/settings-controls.css +57 -0
- package/public/manager/src/settings-embedding.css +3 -3
- package/public/manager/src/terminal/TerminalPanel.tsx +362 -0
- package/public/manager/src/terminal/terminal-bridge.ts +12 -0
- package/public/manager/src/terminal/terminal.css +175 -0
- package/public/manager/src/types.ts +66 -2
- package/public/manager/src/usePreviewShortcutMessages.ts +12 -3
- package/scripts/fresh-install-smoke.ts +1 -2
- package/scripts/install-risk-gate.mjs +0 -18
- package/scripts/install-wsl.sh +0 -46
- package/scripts/install.sh +0 -28
- package/scripts/release-gates.mjs +52 -0
- package/scripts/release.sh +9 -1
- package/scripts/require-release-evidence.mjs +0 -2
- package/public/dist/assets/ChannelsDiscord-CbmWms9-.js +0 -1
- package/public/dist/assets/ChannelsTelegram-BD4Eyztg.js +0 -1
- package/public/dist/assets/Employees-DcMChleU.js +0 -1
- package/public/dist/assets/HealthBadge-CfLTPTPW.js +0 -1
- package/public/dist/assets/Heartbeat-BoobN35p.js +0 -1
- package/public/dist/assets/MilkdownWysiwygEditor-Otw40DDF.js +0 -160
- package/public/dist/assets/NotesGraphView-CwdEnL7d.js +0 -1
- package/public/dist/assets/Permissions-CcIBptg3.js +0 -1
- package/public/dist/assets/agent-meta-BC7mLqo6.js +0 -1
- package/public/dist/assets/app-C7MAcAMu.js +0 -39
- package/public/dist/assets/app-CkFBKUf8.css +0 -1
- package/public/dist/assets/architecture-7EHR7CIX-wVaUQezY.js +0 -1
- package/public/dist/assets/channel-CCQujL1n.js +0 -1
- package/public/dist/assets/chunk-55IACEB6-DhWWzzdj.js +0 -1
- package/public/dist/assets/chunk-QZHKN3VN-CBAtPPT7.js +0 -1
- package/public/dist/assets/chunk-WU5MYG2G-DlBJtD7-.js +0 -1
- package/public/dist/assets/classDiagram-4FO5ZUOK-DmPJvqRM.js +0 -1
- package/public/dist/assets/classDiagram-v2-Q7XG4LA2-ECmTUt7U.js +0 -1
- package/public/dist/assets/constants-BXWl7LTi.js +0 -1
- package/public/dist/assets/dist-BLd7xdyq.js +0 -1
- package/public/dist/assets/dist-BaRrwDy3.js +0 -1
- package/public/dist/assets/dist-Bbsp4OF7.js +0 -1
- package/public/dist/assets/dist-BkBGlG70.js +0 -1
- package/public/dist/assets/dist-BkJ_1mj9.js +0 -1
- package/public/dist/assets/dist-BxCRVW5D.js +0 -1
- package/public/dist/assets/dist-C-v7Rm67.js +0 -23
- package/public/dist/assets/dist-CNgDEAy8.js +0 -1
- package/public/dist/assets/dist-CO_W5rr2.js +0 -1
- package/public/dist/assets/dist-ChAUfTbO.js +0 -1
- package/public/dist/assets/dist-D-k-lzQT.js +0 -1
- package/public/dist/assets/dist-D1hPukqY.js +0 -1
- package/public/dist/assets/dist-D5Qx-jQQ.js +0 -1
- package/public/dist/assets/dist-D7VNzYBv.js +0 -6
- package/public/dist/assets/dist-DAxnodoa.js +0 -1
- package/public/dist/assets/dist-DHSyODkR.js +0 -1
- package/public/dist/assets/dist-DaYTPjbb2.js +0 -1
- package/public/dist/assets/dist-DlWi9tVO.js +0 -1
- package/public/dist/assets/dist-Dv36UUXz.js +0 -1
- package/public/dist/assets/dist-F4CVhitP.js +0 -9
- package/public/dist/assets/dist-LHbJYy3N.js +0 -1
- package/public/dist/assets/dist-VIlx7JdU.js +0 -1
- package/public/dist/assets/dist-cgDt2PmY.js +0 -11
- package/public/dist/assets/dist-eW2LjRIK.js +0 -1
- package/public/dist/assets/dist-vGn3_sWA.js +0 -1
- package/public/dist/assets/employees-BmxY8Mw3.js +0 -33
- package/public/dist/assets/eventmodeling-FCH6USID-Cq0nylxO.js +0 -1
- package/public/dist/assets/gitGraph-WXDBUCRP-DDq6-3D3.js +0 -1
- package/public/dist/assets/info-J43DQDTF-OUnqwpUV.js +0 -1
- package/public/dist/assets/javascript-CZjRNq5R.js +0 -1
- package/public/dist/assets/manager-B2NWzG7j.css +0 -1
- package/public/dist/assets/manager-q68thm66.js +0 -25
- package/public/dist/assets/memory-BqqibBIE.js +0 -1
- package/public/dist/assets/memory-CRL72HB-.js +0 -20
- package/public/dist/assets/mermaid-loader-Dqb4ZUz6.js +0 -1
- package/public/dist/assets/mermaid.core-DYHvk6Pd.js +0 -1
- package/public/dist/assets/packet-YPE3B663-Bb9hBQ06.js +0 -1
- package/public/dist/assets/pie-LRSECV5Y-CNRQnRNZ.js +0 -1
- package/public/dist/assets/radar-GUYGQ44K-BxngU2v0.js +0 -1
- package/public/dist/assets/render-o_YEiCEO.js +0 -28
- package/public/dist/assets/settings-B0RlyAkI.js +0 -1
- package/public/dist/assets/settings-CCXRL5Ar.js +0 -46
- package/public/dist/assets/sidebar-DRJffqO1.js +0 -14
- package/public/dist/assets/skills-CFdzXbtK.js +0 -1
- package/public/dist/assets/slash-commands-BUM6u-Ex.js +0 -1
- package/public/dist/assets/slash-commands-C2YBMaQV.js +0 -14
- package/public/dist/assets/stateDiagram-v2-BHNVJYJU-CrfGPzHb.js +0 -1
- package/public/dist/assets/treeView-BLDUP644-cXRzPGzz.js +0 -1
- package/public/dist/assets/treemap-LRROVOQU-BsZE5HPE.js +0 -1
- package/public/dist/assets/ui-C3ArwMhv.js +0 -140
- package/public/dist/assets/ui-CboUuc_E.js +0 -1
- package/public/dist/assets/vendor-utils-rVejrfMR.js +0 -1
- package/public/dist/assets/wardley-L42UT6IY-D_qm0cZD.js +0 -1
- package/public/dist/assets/wiki-link-suggestions-e5BzJAZH.js +0 -23
- /package/public/dist/assets/{DashboardEmbeddingSection-6F8zSSja.js → DashboardEmbeddingSection-ChF63KXJ.js} +0 -0
- /package/public/dist/assets/{InlineWarn-C7ISyzDI.js → InlineWarn-CY6dBBMq.js} +0 -0
- /package/public/dist/assets/{apl-CieDeb7B.js → apl-CQGZdmVU.js} +0 -0
- /package/public/dist/assets/{asciiarmor-BRTyulZY.js → asciiarmor-6rdc1JOx.js} +0 -0
- /package/public/dist/assets/{asn1-DoNAtQ5o.js → asn1-D8iCH-On.js} +0 -0
- /package/public/dist/assets/{asterisk-CR7oKPxi.js → asterisk-ChqZLgq_.js} +0 -0
- /package/public/dist/assets/{brainfuck-abzPcrOz.js → brainfuck-CDmGO_27.js} +0 -0
- /package/public/dist/assets/{chunk-AGHRB4JF-CYdXVA2-.js → chunk-AGHRB4JF-BgIXD8KY.js} +0 -0
- /package/public/dist/assets/{chunk-NNHCCRGN-BaiX9a5F.js → chunk-NNHCCRGN-BPmsUfnh.js} +0 -0
- /package/public/dist/assets/{clike-B71Zq38G.js → clike-CSGpadKW.js} +0 -0
- /package/public/dist/assets/{clojure-Zm0UzHPq.js → clojure-CST35Ic-.js} +0 -0
- /package/public/dist/assets/{cmake-D3UNdg6L.js → cmake-BVvLLL-M.js} +0 -0
- /package/public/dist/assets/{cobol-4fYvwQR0.js → cobol-Ck6DkJOz.js} +0 -0
- /package/public/dist/assets/{coffeescript-Ct6bZdRU.js → coffeescript-D_Wxovbg.js} +0 -0
- /package/public/dist/assets/{commonlisp-CrgXVPcd.js → commonlisp-B8ANOF1p.js} +0 -0
- /package/public/dist/assets/{crystal-bGOl67VM.js → crystal-Daoo63FI.js} +0 -0
- /package/public/dist/assets/{css-B_EV3Xq2.js → css-BLiiJuyL.js} +0 -0
- /package/public/dist/assets/{cypher-DXDlHTYf.js → cypher-BMqftmWo.js} +0 -0
- /package/public/dist/assets/{cytoscape.esm-BK7ao2Ti.js → cytoscape.esm-Dgu56jtY.js} +0 -0
- /package/public/dist/assets/{d-RL5ynsiz.js → d-DOGkwbDi.js} +0 -0
- /package/public/dist/assets/{diff-B5McBGjz.js → diff-VsLDmRbo.js} +0 -0
- /package/public/dist/assets/{dist-DrIWh2fi.js → dist-DJlNCT5R.js} +0 -0
- /package/public/dist/assets/{dtd-l3sK4p_C.js → dtd-CxrLPib8.js} +0 -0
- /package/public/dist/assets/{dylan-WjJGY-rW.js → dylan-QB82VE9N.js} +0 -0
- /package/public/dist/assets/{ebnf-BGY79HOS.js → ebnf-B6cp6Red.js} +0 -0
- /package/public/dist/assets/{ecl-BKh7OE1d.js → ecl-zYbBq-k7.js} +0 -0
- /package/public/dist/assets/{eiffel-Bzvlg3oK.js → eiffel-DnQZC9e4.js} +0 -0
- /package/public/dist/assets/{elm-5_BqNmKu.js → elm-Cx44SA5e.js} +0 -0
- /package/public/dist/assets/{erlang-BdVwz8I8.js → erlang-CEHBsR_g.js} +0 -0
- /package/public/dist/assets/{fcl-B9cnfODD.js → fcl-D0vOEWq5.js} +0 -0
- /package/public/dist/assets/{fields-BwD_NGxe.js → fields-C-y_8RgA.js} +0 -0
- /package/public/dist/assets/{forth-wZbbnGzb.js → forth-KL0mdDBU.js} +0 -0
- /package/public/dist/assets/{fortran-BAJZrRfU.js → fortran-Dq4mvV2Z.js} +0 -0
- /package/public/dist/assets/{gas-D60ZhBat.js → gas-C1IQIiP2.js} +0 -0
- /package/public/dist/assets/{gherkin-B8tKjAAi.js → gherkin-DJavHCGq.js} +0 -0
- /package/public/dist/assets/{groovy-BAG9eJUD.js → groovy-DYXu3zX-.js} +0 -0
- /package/public/dist/assets/{haskell-Cj4TmWbg.js → haskell-CEbLR9qt.js} +0 -0
- /package/public/dist/assets/{haxe-8chnvz-o.js → haxe-BpJF7A4A.js} +0 -0
- /package/public/dist/assets/{http-DDYeO71z.js → http-DWdENtd1.js} +0 -0
- /package/public/dist/assets/{idl-D1hY-Gp_.js → idl-CE1kS3NQ.js} +0 -0
- /package/public/dist/assets/{javascript-Sh0ZUMP2.js → javascript-CJNkmBfh.js} +0 -0
- /package/public/dist/assets/{julia-BibioBF2.js → julia-BJgPYrDa.js} +0 -0
- /package/public/dist/assets/{livescript-CSZrB6F4.js → livescript-DsrJVqPX.js} +0 -0
- /package/public/dist/assets/{lua-BvTlo5w3.js → lua-C7UuQSXZ.js} +0 -0
- /package/public/dist/assets/{mathematica-Bexv8BWZ.js → mathematica-DUerNKxF.js} +0 -0
- /package/public/dist/assets/{mbox-BAhbA8z2.js → mbox-l0MV8RAb.js} +0 -0
- /package/public/dist/assets/{mirc-BzT5Kh4S.js → mirc-Bs-bacTk.js} +0 -0
- /package/public/dist/assets/{mllike-DeoJnUZQ.js → mllike-DDa-ra-x.js} +0 -0
- /package/public/dist/assets/{modelica-FD_-Fxlc.js → modelica-DorVekoh.js} +0 -0
- /package/public/dist/assets/{mscgen-C-OyhbwB.js → mscgen-Bu9Rmf5j.js} +0 -0
- /package/public/dist/assets/{mumps-BxkCDTK7.js → mumps-BERv0OoY.js} +0 -0
- /package/public/dist/assets/{nginx-2JaV__gC.js → nginx-Bsa-KRWy.js} +0 -0
- /package/public/dist/assets/{ntriples--rhhCzqb.js → ntriples-CQMTRhrZ.js} +0 -0
- /package/public/dist/assets/{octave-rS4nMzRe.js → octave-Bl83K6Ag.js} +0 -0
- /package/public/dist/assets/{oz-I4fMb_NC.js → oz-CCTboWOh.js} +0 -0
- /package/public/dist/assets/{page-shell-uNOxwdbr.js → page-shell-k5-hYhKb.js} +0 -0
- /package/public/dist/assets/{pascal-BEghJs8t.js → pascal-D-i7gVLf.js} +0 -0
- /package/public/dist/assets/{path-utils-h2GAj3hH.js → path-utils-ztBHV7MX.js} +0 -0
- /package/public/dist/assets/{perl-BRO9ZFo9.js → perl-BiLLXF9c.js} +0 -0
- /package/public/dist/assets/{pig-L4Ii6KI0.js → pig-D_F2azNe.js} +0 -0
- /package/public/dist/assets/{powershell-BBeqUCRp.js → powershell-AJ59gf0u.js} +0 -0
- /package/public/dist/assets/{properties-Boi0jF2J.js → properties-CPYgUZZu.js} +0 -0
- /package/public/dist/assets/{protobuf-fB2aGypX.js → protobuf-BTkGCn64.js} +0 -0
- /package/public/dist/assets/{puppet-BRmsErtO.js → puppet-CQcFSvge.js} +0 -0
- /package/public/dist/assets/{python-Be4P9Dgp.js → python-txj4co98.js} +0 -0
- /package/public/dist/assets/{q-DZGhDLYt.js → q-D48iiS-J.js} +0 -0
- /package/public/dist/assets/{r-B4NERjRM.js → r-KvgSjvcw.js} +0 -0
- /package/public/dist/assets/{rough.esm-C0Gkx4O1.js → rough.esm-DEk5_dnJ.js} +0 -0
- /package/public/dist/assets/{rpm-e-QbHJ1q.js → rpm-BcHYZFkz.js} +0 -0
- /package/public/dist/assets/{ruby-BSVP_v59.js → ruby-C_Hj_59H.js} +0 -0
- /package/public/dist/assets/{sas-DHlU4v4g.js → sas-iqYBvleh.js} +0 -0
- /package/public/dist/assets/{scheme-BGXbz5Hz.js → scheme-BIcb4en6.js} +0 -0
- /package/public/dist/assets/{shell-yonx6xY2.js → shell-CJbQRqgD.js} +0 -0
- /package/public/dist/assets/{sieve-ClPJUZyi.js → sieve-CEVqHONw.js} +0 -0
- /package/public/dist/assets/{simple-mode-CjViblDK.js → simple-mode-CyEi8-qy.js} +0 -0
- /package/public/dist/assets/{smalltalk-CHXubeqS.js → smalltalk-CzJ9RPAW.js} +0 -0
- /package/public/dist/assets/{solr-C6q6YwPz.js → solr-DhrIF5tD.js} +0 -0
- /package/public/dist/assets/{sparql-CcspZvEd.js → sparql-p9uHdCLs.js} +0 -0
- /package/public/dist/assets/{spreadsheet-DH3a4LBS.js → spreadsheet-BEYojJ7u.js} +0 -0
- /package/public/dist/assets/{sql-meoY6gNi.js → sql-CnA4GIza.js} +0 -0
- /package/public/dist/assets/{stex-D2bn6Zsh.js → stex-6IVJg-2X.js} +0 -0
- /package/public/dist/assets/{stylus-DbXGih0S.js → stylus-fqPouKsv.js} +0 -0
- /package/public/dist/assets/{swift-Ch391uOd.js → swift-DHXFQ55a.js} +0 -0
- /package/public/dist/assets/{tcl-CQBgGWDP.js → tcl-DI621_2I.js} +0 -0
- /package/public/dist/assets/{textile-4i3oG3tg.js → textile-CpiPRB46.js} +0 -0
- /package/public/dist/assets/{tiddlywiki-CXG1-CcK.js → tiddlywiki-DASPoia0.js} +0 -0
- /package/public/dist/assets/{tiki-DJqKUhA-.js → tiki-H2_-xfcb.js} +0 -0
- /package/public/dist/assets/{toml-C1FnyICQ.js → toml-BLGegqRu.js} +0 -0
- /package/public/dist/assets/{troff-Cp8NvRO0.js → troff-BH_j1MPi.js} +0 -0
- /package/public/dist/assets/{ttcn-cfg-BVuxfGZf.js → ttcn-cfg-kxhuYjqY.js} +0 -0
- /package/public/dist/assets/{ttcn-NlmW_fji.js → ttcn-q84VxP8I.js} +0 -0
- /package/public/dist/assets/{turtle-Ba9ERlnm.js → turtle-COu2Ajrp.js} +0 -0
- /package/public/dist/assets/{vb-DDs4gjJb.js → vb-7GRadaxb.js} +0 -0
- /package/public/dist/assets/{vbscript-gOFmdMJN.js → vbscript-Bibo3Rcb.js} +0 -0
- /package/public/dist/assets/{velocity-DtSNZA7i.js → velocity-CRfDkZn8.js} +0 -0
- /package/public/dist/assets/{verilog-Pldmtxe7.js → verilog-B1kgqsBR.js} +0 -0
- /package/public/dist/assets/{vhdl-BFfSgWGp.js → vhdl-qL7iOc7c.js} +0 -0
- /package/public/dist/assets/{w3c-keyname-BggQEPNo.js → w3c-keyname-BkTDclMX.js} +0 -0
- /package/public/dist/assets/{webidl-B6ZFYE2L.js → webidl-Bpu8XQq2.js} +0 -0
- /package/public/dist/assets/{xquery-DhxUT98N.js → xquery-C_ocxvPR.js} +0 -0
- /package/public/dist/assets/{yacas-jSkQeF1Q.js → yacas-DByFiVRK.js} +0 -0
- /package/public/dist/assets/{z80-D7Lt6v61.js → z80-CKuzqVbN.js} +0 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import * as d3 from 'd3';
|
|
3
|
+
import { graphForceConfigFromSettings, labelVisibleForNode, radiusForNode } from './notes-graph-force';
|
|
4
|
+
import type { NotesGraphRenderData, NotesGraphRenderEdge, NotesGraphRenderNode } from './notes-graph-filter';
|
|
5
|
+
import type { NotesGraphSettings } from './notes-graph-settings';
|
|
6
|
+
|
|
7
|
+
type NotesGraphCanvasProps = {
|
|
8
|
+
data: NotesGraphRenderData;
|
|
9
|
+
selectedPath: string | null;
|
|
10
|
+
settings: NotesGraphSettings;
|
|
11
|
+
fitToken: number;
|
|
12
|
+
onNavigate: (path: string) => void;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
type SimNode = NotesGraphRenderNode & d3.SimulationNodeDatum;
|
|
16
|
+
type SimEdge = Omit<NotesGraphRenderEdge, 'source' | 'target'> & {
|
|
17
|
+
source: SimNode;
|
|
18
|
+
target: SimNode;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function nodeClassName(node: NotesGraphRenderNode, selectedPath: string | null): string {
|
|
22
|
+
const selected = node.id === selectedPath ? ' is-selected' : '';
|
|
23
|
+
return `notes-graph-node notes-graph-node-${node.kind}${selected}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function edgeClassName(edge: Pick<NotesGraphRenderEdge, 'status' | 'virtual'>): string {
|
|
27
|
+
return `notes-graph-link notes-graph-link-${edge.status}${edge.virtual ? ' is-virtual' : ''}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function NotesGraphCanvas(props: NotesGraphCanvasProps) {
|
|
31
|
+
const svgRef = useRef<SVGSVGElement | null>(null);
|
|
32
|
+
const hostRef = useRef<HTMLDivElement | null>(null);
|
|
33
|
+
const navigateRef = useRef(props.onNavigate);
|
|
34
|
+
const [size, setSize] = useState({ width: 900, height: 650 });
|
|
35
|
+
navigateRef.current = props.onNavigate;
|
|
36
|
+
const config = useMemo(() => graphForceConfigFromSettings(props.settings), [props.settings]);
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const host = hostRef.current;
|
|
40
|
+
if (!host) return undefined;
|
|
41
|
+
const updateSize = (): void => {
|
|
42
|
+
const rect = host.getBoundingClientRect();
|
|
43
|
+
setSize({
|
|
44
|
+
width: Math.max(320, Math.floor(rect.width || 900)),
|
|
45
|
+
height: Math.max(320, Math.floor(rect.height || 650)),
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
updateSize();
|
|
49
|
+
if (typeof window.ResizeObserver !== 'function') return undefined;
|
|
50
|
+
const observer = new window.ResizeObserver(updateSize);
|
|
51
|
+
observer.observe(host);
|
|
52
|
+
return () => observer.disconnect();
|
|
53
|
+
}, []);
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
const svgElement = svgRef.current;
|
|
57
|
+
if (!svgElement) return undefined;
|
|
58
|
+
const svg = d3.select(svgElement);
|
|
59
|
+
svg.selectAll('*').remove();
|
|
60
|
+
svg.attr('viewBox', `0 0 ${size.width} ${size.height}`);
|
|
61
|
+
if (props.data.nodes.length === 0) return undefined;
|
|
62
|
+
|
|
63
|
+
const reduceMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;
|
|
64
|
+
const nodes: SimNode[] = props.data.nodes.map(node => ({ ...node }));
|
|
65
|
+
const nodeById = new Map(nodes.map(node => [node.id, node]));
|
|
66
|
+
const edges: SimEdge[] = props.data.edges.flatMap(edge => {
|
|
67
|
+
const source = nodeById.get(edge.source);
|
|
68
|
+
const target = nodeById.get(edge.target);
|
|
69
|
+
const edgeMeta = {
|
|
70
|
+
raw: edge.raw,
|
|
71
|
+
status: edge.status,
|
|
72
|
+
...(edge.resolvedPath ? { resolvedPath: edge.resolvedPath } : {}),
|
|
73
|
+
...(edge.virtual ? { virtual: edge.virtual } : {}),
|
|
74
|
+
};
|
|
75
|
+
return source && target ? [{ ...edgeMeta, source, target }] : [];
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const defs = svg.append('defs');
|
|
79
|
+
defs.append('marker')
|
|
80
|
+
.attr('id', 'notes-graph-arrow')
|
|
81
|
+
.attr('viewBox', '0 -5 10 10')
|
|
82
|
+
.attr('refX', 15)
|
|
83
|
+
.attr('refY', 0)
|
|
84
|
+
.attr('markerWidth', 6)
|
|
85
|
+
.attr('markerHeight', 6)
|
|
86
|
+
.attr('orient', 'auto')
|
|
87
|
+
.append('path')
|
|
88
|
+
.attr('d', 'M0,-5L10,0L0,5')
|
|
89
|
+
.attr('fill', 'currentColor');
|
|
90
|
+
|
|
91
|
+
const viewport = svg.append('g').attr('class', 'notes-graph-viewport');
|
|
92
|
+
const link = viewport.append('g')
|
|
93
|
+
.attr('class', 'notes-graph-links')
|
|
94
|
+
.selectAll<SVGLineElement, SimEdge>('line')
|
|
95
|
+
.data(edges)
|
|
96
|
+
.join('line')
|
|
97
|
+
.attr('class', edgeClassName)
|
|
98
|
+
.attr('marker-end', config.showArrows ? 'url(#notes-graph-arrow)' : null);
|
|
99
|
+
|
|
100
|
+
const node = viewport.append('g')
|
|
101
|
+
.attr('class', 'notes-graph-nodes')
|
|
102
|
+
.selectAll<SVGGElement, SimNode>('g')
|
|
103
|
+
.data(nodes)
|
|
104
|
+
.join('g')
|
|
105
|
+
.attr('class', d => nodeClassName(d, props.selectedPath))
|
|
106
|
+
.attr('tabindex', d => d.kind === 'note' ? 0 : -1)
|
|
107
|
+
.attr('role', d => d.kind === 'note' ? 'button' : 'img')
|
|
108
|
+
.attr('aria-label', d => `${d.title}, ${d.kind}, ${d.degree} links`)
|
|
109
|
+
.on('click', (_event: MouseEvent, d: SimNode) => {
|
|
110
|
+
if (d.kind === 'note' && d.path) navigateRef.current(d.path);
|
|
111
|
+
})
|
|
112
|
+
.on('keydown', (event: KeyboardEvent, d: SimNode) => {
|
|
113
|
+
if (d.kind !== 'note' || !d.path) return;
|
|
114
|
+
if (event.key !== 'Enter' && event.key !== ' ') return;
|
|
115
|
+
event.preventDefault();
|
|
116
|
+
navigateRef.current(d.path);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
node.append('circle')
|
|
120
|
+
.attr('r', d => radiusForNode(d, config))
|
|
121
|
+
.attr('fill', d => d.groupColor ?? null);
|
|
122
|
+
|
|
123
|
+
node.append('text')
|
|
124
|
+
.attr('class', 'notes-graph-label')
|
|
125
|
+
.attr('x', d => radiusForNode(d, config) + 8)
|
|
126
|
+
.attr('y', 4)
|
|
127
|
+
.text(d => d.title);
|
|
128
|
+
|
|
129
|
+
node.append('title')
|
|
130
|
+
.text(d => d.groupLabel ? `${d.title} · ${d.groupLabel}` : d.title);
|
|
131
|
+
|
|
132
|
+
const simulation = d3.forceSimulation<SimNode>(nodes)
|
|
133
|
+
.force('link', d3.forceLink<SimNode, SimEdge>(edges).id(d => d.id).distance(config.linkDistance))
|
|
134
|
+
.force('charge', d3.forceManyBody().strength(config.chargeStrength))
|
|
135
|
+
.force('center', d3.forceCenter(size.width / 2, size.height / 2))
|
|
136
|
+
.force('collision', d3.forceCollide<SimNode>().radius(d => radiusForNode(d, config) + 8));
|
|
137
|
+
|
|
138
|
+
function renderFrame(): void {
|
|
139
|
+
link
|
|
140
|
+
.attr('x1', d => d.source.x ?? 0)
|
|
141
|
+
.attr('y1', d => d.source.y ?? 0)
|
|
142
|
+
.attr('x2', d => d.target.x ?? 0)
|
|
143
|
+
.attr('y2', d => d.target.y ?? 0);
|
|
144
|
+
node.attr('transform', d => `translate(${d.x ?? size.width / 2},${d.y ?? size.height / 2})`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const zoom = d3.zoom<SVGSVGElement, unknown>()
|
|
148
|
+
.scaleExtent([0.18, 5])
|
|
149
|
+
.on('zoom', (event) => {
|
|
150
|
+
viewport.attr('transform', event.transform);
|
|
151
|
+
node.classed('is-label-visible', d => labelVisibleForNode(d, event.transform.k, config));
|
|
152
|
+
});
|
|
153
|
+
svg.call(zoom);
|
|
154
|
+
const initialTransform = d3.zoomIdentity.translate(0, 0).scale(1);
|
|
155
|
+
svg.call(zoom.transform, initialTransform);
|
|
156
|
+
|
|
157
|
+
const drag = d3.drag<SVGGElement, SimNode>()
|
|
158
|
+
.on('start', (event, d) => {
|
|
159
|
+
if (!event.active && config.animate && !reduceMotion) simulation.alphaTarget(0.25).restart();
|
|
160
|
+
d.fx = d.x;
|
|
161
|
+
d.fy = d.y;
|
|
162
|
+
})
|
|
163
|
+
.on('drag', (event, d) => {
|
|
164
|
+
d.fx = event.x;
|
|
165
|
+
d.fy = event.y;
|
|
166
|
+
})
|
|
167
|
+
.on('end', (event, d) => {
|
|
168
|
+
if (!event.active) simulation.alphaTarget(0);
|
|
169
|
+
d.fx = null;
|
|
170
|
+
d.fy = null;
|
|
171
|
+
});
|
|
172
|
+
node.call(drag);
|
|
173
|
+
|
|
174
|
+
if (config.animate && !reduceMotion) {
|
|
175
|
+
simulation.on('tick', renderFrame);
|
|
176
|
+
} else {
|
|
177
|
+
simulation.tick(120);
|
|
178
|
+
renderFrame();
|
|
179
|
+
simulation.stop();
|
|
180
|
+
}
|
|
181
|
+
return () => {
|
|
182
|
+
simulation.stop();
|
|
183
|
+
svg.on('.zoom', null);
|
|
184
|
+
};
|
|
185
|
+
}, [props.data, props.selectedPath, size, config, props.fitToken]);
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<div ref={hostRef} className="notes-graph-canvas" data-empty={props.data.nodes.length === 0 ? 'true' : 'false'}>
|
|
189
|
+
{props.data.nodes.length === 0 ? (
|
|
190
|
+
<div className="notes-graph-empty-state">No matching graph nodes</div>
|
|
191
|
+
) : null}
|
|
192
|
+
<svg ref={svgRef} className="notes-graph-svg" aria-label="Notes graph" />
|
|
193
|
+
</div>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { NotesGraphGroup, NotesGraphSection, NotesGraphSettings } from './notes-graph-settings';
|
|
3
|
+
import { createNotesGraphGroup, NOTES_GRAPH_GROUP_COLORS, NOTES_GRAPH_SECTIONS } from './notes-graph-settings';
|
|
4
|
+
|
|
5
|
+
type NotesGraphControlsPanelProps = {
|
|
6
|
+
settings: NotesGraphSettings;
|
|
7
|
+
selectedPath: string | null;
|
|
8
|
+
onChange: (settings: NotesGraphSettings) => void;
|
|
9
|
+
onReset: () => void;
|
|
10
|
+
onFit: () => void;
|
|
11
|
+
onClose: () => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type ToggleKey =
|
|
15
|
+
| 'existingFilesOnly'
|
|
16
|
+
| 'showOrphans'
|
|
17
|
+
| 'showTags'
|
|
18
|
+
| 'showAttachments'
|
|
19
|
+
| 'focusSelected'
|
|
20
|
+
| 'showArrows'
|
|
21
|
+
| 'animate';
|
|
22
|
+
|
|
23
|
+
function sectionLabel(section: NotesGraphSection): string {
|
|
24
|
+
if (section === 'filters') return 'Filters';
|
|
25
|
+
if (section === 'display') return 'Display';
|
|
26
|
+
if (section === 'forces') return 'Forces';
|
|
27
|
+
return 'Groups';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function nextSettings(settings: NotesGraphSettings, patch: Partial<NotesGraphSettings>): NotesGraphSettings {
|
|
31
|
+
return {
|
|
32
|
+
...settings,
|
|
33
|
+
...patch,
|
|
34
|
+
collapsedSections: patch.collapsedSections ?? settings.collapsedSections,
|
|
35
|
+
groups: patch.groups ?? settings.groups,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function ToggleRow(props: {
|
|
40
|
+
label: string;
|
|
41
|
+
checked: boolean;
|
|
42
|
+
onChange: (value: boolean) => void;
|
|
43
|
+
disabled?: boolean;
|
|
44
|
+
}): ReactElement {
|
|
45
|
+
return (
|
|
46
|
+
<label className={`notes-graph-toggle${props.disabled ? ' is-disabled' : ''}`}>
|
|
47
|
+
<span>{props.label}</span>
|
|
48
|
+
<input type="checkbox" checked={props.checked} disabled={props.disabled} onChange={event => props.onChange(event.currentTarget.checked)} />
|
|
49
|
+
</label>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function NotesGraphControlsPanel(props: NotesGraphControlsPanelProps) {
|
|
54
|
+
const { settings } = props;
|
|
55
|
+
|
|
56
|
+
function patch(patchValue: Partial<NotesGraphSettings>): void {
|
|
57
|
+
props.onChange(nextSettings(settings, patchValue));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function toggle(key: ToggleKey): void {
|
|
61
|
+
patch({ [key]: !settings[key] } as Partial<Pick<NotesGraphSettings, ToggleKey>>);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function toggleSection(section: NotesGraphSection): void {
|
|
65
|
+
patch({
|
|
66
|
+
collapsedSections: {
|
|
67
|
+
...settings.collapsedSections,
|
|
68
|
+
[section]: !settings.collapsedSections[section],
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function updateGroup(id: string, patchValue: Partial<NotesGraphGroup>): void {
|
|
74
|
+
patch({ groups: settings.groups.map(group => group.id === id ? { ...group, ...patchValue } : group) });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function addGroup(): void {
|
|
78
|
+
patch({ groups: [...settings.groups, createNotesGraphGroup(settings.groups.length, settings.query)] });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function removeGroup(id: string): void {
|
|
82
|
+
patch({ groups: settings.groups.filter(group => group.id !== id) });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<aside className="notes-graph-controls" aria-label="Graph controls">
|
|
87
|
+
<header className="notes-graph-controls-header">
|
|
88
|
+
<div>
|
|
89
|
+
<h3>Graph</h3>
|
|
90
|
+
<span>{props.selectedPath ? 'Focus-ready' : 'Global view'}</span>
|
|
91
|
+
</div>
|
|
92
|
+
<button type="button" className="notes-graph-icon-button" onClick={props.onClose} aria-label="Close graph controls">X</button>
|
|
93
|
+
</header>
|
|
94
|
+
|
|
95
|
+
{NOTES_GRAPH_SECTIONS.map(section => (
|
|
96
|
+
<section key={section} className="notes-graph-control-section">
|
|
97
|
+
<button type="button" className="notes-graph-section-toggle" onClick={() => toggleSection(section)} aria-expanded={!settings.collapsedSections[section]}>
|
|
98
|
+
<span>{sectionLabel(section)}</span>
|
|
99
|
+
<span>{settings.collapsedSections[section] ? '+' : '-'}</span>
|
|
100
|
+
</button>
|
|
101
|
+
{!settings.collapsedSections[section] && section === 'filters' ? (
|
|
102
|
+
<div className="notes-graph-control-body">
|
|
103
|
+
<label className="notes-graph-field">
|
|
104
|
+
<span>Search</span>
|
|
105
|
+
<input value={settings.query} onChange={event => patch({ query: event.currentTarget.value })} placeholder="title, path:, tag:, kind:" />
|
|
106
|
+
</label>
|
|
107
|
+
<ToggleRow label="Existing files only" checked={settings.existingFilesOnly} onChange={() => toggle('existingFilesOnly')} />
|
|
108
|
+
<ToggleRow label="Show orphans" checked={settings.showOrphans} onChange={() => toggle('showOrphans')} />
|
|
109
|
+
<ToggleRow label="Show tags" checked={settings.showTags} onChange={() => toggle('showTags')} />
|
|
110
|
+
<ToggleRow label="Show attachments" checked={settings.showAttachments} onChange={() => toggle('showAttachments')} />
|
|
111
|
+
<ToggleRow label="Focus selected" checked={settings.focusSelected} disabled={!props.selectedPath} onChange={() => toggle('focusSelected')} />
|
|
112
|
+
<label className="notes-graph-field">
|
|
113
|
+
<span>Depth {settings.focusDepth}</span>
|
|
114
|
+
<input type="range" min="1" max="4" value={settings.focusDepth} disabled={!settings.focusSelected || !props.selectedPath} onChange={event => patch({ focusDepth: Number(event.currentTarget.value) })} />
|
|
115
|
+
</label>
|
|
116
|
+
</div>
|
|
117
|
+
) : null}
|
|
118
|
+
{!settings.collapsedSections[section] && section === 'display' ? (
|
|
119
|
+
<div className="notes-graph-control-body">
|
|
120
|
+
<label className="notes-graph-field">
|
|
121
|
+
<span>Node size {settings.nodeSize.toFixed(1)}</span>
|
|
122
|
+
<input type="range" min="0.6" max="2" step="0.1" value={settings.nodeSize} onChange={event => patch({ nodeSize: Number(event.currentTarget.value) })} />
|
|
123
|
+
</label>
|
|
124
|
+
<label className="notes-graph-field">
|
|
125
|
+
<span>Labels {Math.round(settings.labelDensity * 100)}%</span>
|
|
126
|
+
<input type="range" min="0" max="1" step="0.05" value={settings.labelDensity} onChange={event => patch({ labelDensity: Number(event.currentTarget.value) })} />
|
|
127
|
+
</label>
|
|
128
|
+
<ToggleRow label="Show arrows" checked={settings.showArrows} onChange={() => toggle('showArrows')} />
|
|
129
|
+
<ToggleRow label="Animate" checked={settings.animate} onChange={() => toggle('animate')} />
|
|
130
|
+
</div>
|
|
131
|
+
) : null}
|
|
132
|
+
{!settings.collapsedSections[section] && section === 'forces' ? (
|
|
133
|
+
<div className="notes-graph-control-body">
|
|
134
|
+
<label className="notes-graph-field">
|
|
135
|
+
<span>Link distance {settings.linkDistance}</span>
|
|
136
|
+
<input type="range" min="40" max="240" value={settings.linkDistance} onChange={event => patch({ linkDistance: Number(event.currentTarget.value) })} />
|
|
137
|
+
</label>
|
|
138
|
+
<label className="notes-graph-field">
|
|
139
|
+
<span>Repel {Math.abs(settings.chargeStrength)}</span>
|
|
140
|
+
<input type="range" min="-800" max="-20" value={settings.chargeStrength} onChange={event => patch({ chargeStrength: Number(event.currentTarget.value) })} />
|
|
141
|
+
</label>
|
|
142
|
+
<div className="notes-graph-control-row">
|
|
143
|
+
<button type="button" onClick={props.onFit}>Fit</button>
|
|
144
|
+
<button type="button" onClick={props.onReset}>Reset</button>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
) : null}
|
|
148
|
+
{!settings.collapsedSections[section] && section === 'groups' ? (
|
|
149
|
+
<div className="notes-graph-control-body">
|
|
150
|
+
<ToggleRow label="Query groups" checked={settings.groupMode === 'query'} onChange={value => patch({ groupMode: value ? 'query' : 'off' })} />
|
|
151
|
+
<div className="notes-graph-groups">
|
|
152
|
+
{settings.groups.map((group, index) => (
|
|
153
|
+
<div key={group.id} className="notes-graph-group-row">
|
|
154
|
+
<input className="notes-graph-color" type="color" value={group.color} onChange={event => updateGroup(group.id, { color: event.currentTarget.value })} />
|
|
155
|
+
<input value={group.label} onChange={event => updateGroup(group.id, { label: event.currentTarget.value })} aria-label={`Group ${index + 1} label`} />
|
|
156
|
+
<input value={group.query} onChange={event => updateGroup(group.id, { query: event.currentTarget.value })} aria-label={`Group ${index + 1} query`} />
|
|
157
|
+
<button type="button" onClick={() => updateGroup(group.id, { enabled: !group.enabled })} aria-pressed={group.enabled}>{group.enabled ? 'On' : 'Off'}</button>
|
|
158
|
+
<button type="button" className="notes-graph-icon-button" onClick={() => removeGroup(group.id)} aria-label={`Remove ${group.label}`}>X</button>
|
|
159
|
+
</div>
|
|
160
|
+
))}
|
|
161
|
+
</div>
|
|
162
|
+
<div className="notes-graph-swatches" aria-label="Group color presets">
|
|
163
|
+
{NOTES_GRAPH_GROUP_COLORS.map(color => <span key={color} style={{ background: color }} />)}
|
|
164
|
+
</div>
|
|
165
|
+
<button type="button" onClick={addGroup}>Add group</button>
|
|
166
|
+
</div>
|
|
167
|
+
) : null}
|
|
168
|
+
</section>
|
|
169
|
+
))}
|
|
170
|
+
</aside>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { NotesGraphCanvas } from './NotesGraphCanvas';
|
|
3
|
+
import { NotesGraphControlsPanel } from './NotesGraphControlsPanel';
|
|
4
|
+
import { deriveNotesGraphData } from './notes-graph-filter';
|
|
5
|
+
import {
|
|
6
|
+
cloneNotesGraphSettings,
|
|
7
|
+
DEFAULT_NOTES_GRAPH_SETTINGS,
|
|
8
|
+
normalizeNotesGraphSettings,
|
|
9
|
+
type NotesGraphSettings,
|
|
10
|
+
} from './notes-graph-settings';
|
|
11
|
+
import type { NotesVaultIndexSnapshot } from '../notes-types';
|
|
12
|
+
|
|
13
|
+
export type NotesGraphRuntimeBoundary = {
|
|
14
|
+
dataPlane: 'dashboard-notes-api';
|
|
15
|
+
shellPanels: 'render-only';
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const NOTES_GRAPH_RUNTIME_BOUNDARY: NotesGraphRuntimeBoundary = {
|
|
19
|
+
dataPlane: 'dashboard-notes-api',
|
|
20
|
+
shellPanels: 'render-only',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type NotesGraphWorkspaceProps = {
|
|
24
|
+
vaultIndex: NotesVaultIndexSnapshot | null;
|
|
25
|
+
selectedPath: string | null;
|
|
26
|
+
settings?: NotesGraphSettings | undefined;
|
|
27
|
+
onSettingsChange?: (settings: NotesGraphSettings) => void;
|
|
28
|
+
onNavigate: (path: string) => void;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
function defaultSettings(): NotesGraphSettings {
|
|
32
|
+
return cloneNotesGraphSettings(DEFAULT_NOTES_GRAPH_SETTINGS);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function NotesGraphWorkspace(props: NotesGraphWorkspaceProps) {
|
|
36
|
+
// Graph is intentionally web-capable: data comes from the dashboard notes API.
|
|
37
|
+
// Electron side panels may render Jawsidian content, but must not become the
|
|
38
|
+
// source of graph connectivity or persistence.
|
|
39
|
+
const [draft, setDraft] = useState<NotesGraphSettings>(() => normalizeNotesGraphSettings(props.settings ?? defaultSettings()));
|
|
40
|
+
const [fitToken, setFitToken] = useState(0);
|
|
41
|
+
const persistTimerRef = useRef<number | null>(null);
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
setDraft(normalizeNotesGraphSettings(props.settings ?? defaultSettings()));
|
|
45
|
+
}, [props.settings]);
|
|
46
|
+
|
|
47
|
+
useEffect(() => () => {
|
|
48
|
+
if (persistTimerRef.current != null) window.clearTimeout(persistTimerRef.current);
|
|
49
|
+
}, []);
|
|
50
|
+
|
|
51
|
+
function persist(next: NotesGraphSettings, immediate = false): void {
|
|
52
|
+
setDraft(next);
|
|
53
|
+
if (!props.onSettingsChange) return;
|
|
54
|
+
if (persistTimerRef.current != null) window.clearTimeout(persistTimerRef.current);
|
|
55
|
+
if (immediate) {
|
|
56
|
+
props.onSettingsChange(next);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
persistTimerRef.current = window.setTimeout(() => props.onSettingsChange?.(next), 140);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function resetSettings(): void {
|
|
63
|
+
persist(defaultSettings(), true);
|
|
64
|
+
setFitToken(token => token + 1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function closePanel(): void {
|
|
68
|
+
persist({ ...draft, panelOpen: false }, true);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function openPanel(): void {
|
|
72
|
+
persist({ ...draft, panelOpen: true }, true);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const graphData = useMemo(
|
|
76
|
+
() => deriveNotesGraphData(props.vaultIndex, draft, props.selectedPath),
|
|
77
|
+
[props.vaultIndex, draft, props.selectedPath],
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<div className={`notes-graph-workspace${draft.panelOpen ? ' has-controls' : ''}`}>
|
|
82
|
+
<header className="notes-graph-toolbar">
|
|
83
|
+
<div className="notes-graph-counts" aria-live="polite">
|
|
84
|
+
<strong>{graphData.noteCount}</strong> notes
|
|
85
|
+
<span>{graphData.linkCount} links</span>
|
|
86
|
+
<span>{graphData.missingCount} unresolved</span>
|
|
87
|
+
{graphData.tagCount > 0 ? <span>{graphData.tagCount} tags</span> : null}
|
|
88
|
+
</div>
|
|
89
|
+
<div className="notes-graph-actions">
|
|
90
|
+
<button type="button" onClick={() => setFitToken(token => token + 1)}>Fit</button>
|
|
91
|
+
<button type="button" onClick={resetSettings}>Reset</button>
|
|
92
|
+
{!draft.panelOpen ? <button type="button" onClick={openPanel}>Controls</button> : null}
|
|
93
|
+
</div>
|
|
94
|
+
</header>
|
|
95
|
+
<div className="notes-graph-body">
|
|
96
|
+
<NotesGraphCanvas
|
|
97
|
+
data={graphData}
|
|
98
|
+
selectedPath={props.selectedPath}
|
|
99
|
+
settings={draft}
|
|
100
|
+
fitToken={fitToken}
|
|
101
|
+
onNavigate={props.onNavigate}
|
|
102
|
+
/>
|
|
103
|
+
{draft.panelOpen ? (
|
|
104
|
+
<NotesGraphControlsPanel
|
|
105
|
+
settings={draft}
|
|
106
|
+
selectedPath={props.selectedPath}
|
|
107
|
+
onChange={next => persist(next)}
|
|
108
|
+
onReset={resetSettings}
|
|
109
|
+
onFit={() => setFitToken(token => token + 1)}
|
|
110
|
+
onClose={closePanel}
|
|
111
|
+
/>
|
|
112
|
+
) : null}
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import type { NoteGraphEdge, NoteGraphNode, NoteMetadata } from '../../types';
|
|
2
|
+
import type { NotesVaultIndexSnapshot } from '../notes-types';
|
|
3
|
+
import type { NotesGraphGroup, NotesGraphSettings } from './notes-graph-settings';
|
|
4
|
+
|
|
5
|
+
export type NotesGraphRenderNode = NoteGraphNode & {
|
|
6
|
+
degree: number;
|
|
7
|
+
groupColor?: string;
|
|
8
|
+
groupLabel?: string;
|
|
9
|
+
searchMatch: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type NotesGraphRenderEdge = NoteGraphEdge & {
|
|
13
|
+
virtual?: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type NotesGraphRenderData = {
|
|
17
|
+
nodes: NotesGraphRenderNode[];
|
|
18
|
+
edges: NotesGraphRenderEdge[];
|
|
19
|
+
noteCount: number;
|
|
20
|
+
linkCount: number;
|
|
21
|
+
missingCount: number;
|
|
22
|
+
tagCount: number;
|
|
23
|
+
hiddenCount: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type GraphShape = { nodes: NoteGraphNode[]; edges: NoteGraphEdge[] };
|
|
27
|
+
|
|
28
|
+
const NODE_KIND_ORDER: Record<NoteGraphNode['kind'], number> = {
|
|
29
|
+
note: 0,
|
|
30
|
+
tag: 1,
|
|
31
|
+
missing: 2,
|
|
32
|
+
ambiguous: 3,
|
|
33
|
+
attachment: 4,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function normalizeTag(tag: string): string {
|
|
37
|
+
return tag.trim().replace(/^#/, '').toLowerCase();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function tagNodeId(tag: string): string {
|
|
41
|
+
return `tag:${normalizeTag(tag)}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function nodeSearchFields(node: NoteGraphNode, metadata: NoteMetadata | undefined): string[] {
|
|
45
|
+
const fields = [node.id, node.title, node.path ?? ''];
|
|
46
|
+
if (metadata) fields.push(metadata.title, metadata.path, ...metadata.aliases, ...metadata.tags);
|
|
47
|
+
return fields.filter(Boolean).map(field => field.toLowerCase());
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function tokenMatchesNode(token: string, node: NoteGraphNode, metadata: NoteMetadata | undefined): boolean {
|
|
51
|
+
const lower = token.toLowerCase();
|
|
52
|
+
if (lower.startsWith('kind:')) return node.kind === lower.slice(5);
|
|
53
|
+
if (lower.startsWith('path:')) return (node.path ?? node.id).toLowerCase().includes(lower.slice(5));
|
|
54
|
+
if (lower.startsWith('tag:')) {
|
|
55
|
+
const tag = normalizeTag(lower.slice(4));
|
|
56
|
+
if (!tag) return true;
|
|
57
|
+
if (node.kind === 'tag') return normalizeTag(node.title).includes(tag) || node.id.includes(tag);
|
|
58
|
+
return Boolean(metadata?.tags.some(noteTag => normalizeTag(noteTag).includes(tag)));
|
|
59
|
+
}
|
|
60
|
+
return nodeSearchFields(node, metadata).some(field => field.includes(lower));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function matchesQuery(query: string, node: NoteGraphNode, metadata: NoteMetadata | undefined): boolean {
|
|
64
|
+
const tokens = query.trim().split(/\s+/).filter(Boolean);
|
|
65
|
+
if (tokens.length === 0) return true;
|
|
66
|
+
return tokens.every(token => tokenMatchesNode(token, node, metadata));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function matchingGroup(
|
|
70
|
+
node: NoteGraphNode,
|
|
71
|
+
metadata: NoteMetadata | undefined,
|
|
72
|
+
settings: NotesGraphSettings,
|
|
73
|
+
): NotesGraphGroup | undefined {
|
|
74
|
+
if (settings.groupMode === 'off') return undefined;
|
|
75
|
+
return settings.groups.find(group => group.enabled && matchesQuery(group.query, node, metadata));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function buildWorkingGraph(snapshot: NotesVaultIndexSnapshot, settings: NotesGraphSettings): GraphShape {
|
|
79
|
+
const nodes = new Map<string, NoteGraphNode>();
|
|
80
|
+
for (const node of snapshot.graph.nodes) nodes.set(node.id, { ...node });
|
|
81
|
+
for (const note of snapshot.notes) {
|
|
82
|
+
if (!nodes.has(note.path)) nodes.set(note.path, { id: note.path, title: note.title, kind: 'note', path: note.path });
|
|
83
|
+
}
|
|
84
|
+
const edges: NoteGraphEdge[] = snapshot.graph.edges.map(edge => ({ ...edge }));
|
|
85
|
+
// The server-owned vault index is the authority for wikilink connectivity,
|
|
86
|
+
// including missing/ambiguous nodes. The client only adds virtual tag edges.
|
|
87
|
+
if (settings.showTags) {
|
|
88
|
+
for (const note of snapshot.notes) {
|
|
89
|
+
for (const rawTag of note.tags) {
|
|
90
|
+
const tag = normalizeTag(rawTag);
|
|
91
|
+
if (!tag) continue;
|
|
92
|
+
const id = tagNodeId(tag);
|
|
93
|
+
if (!nodes.has(id)) nodes.set(id, { id, title: `#${tag}`, kind: 'tag' });
|
|
94
|
+
edges.push({ source: note.path, target: id, raw: `#${tag}`, status: 'resolved', resolvedPath: note.path });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return { nodes: [...nodes.values()], edges };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function degreeByNode(edges: NoteGraphEdge[]): Map<string, number> {
|
|
102
|
+
const degree = new Map<string, number>();
|
|
103
|
+
for (const edge of edges) {
|
|
104
|
+
degree.set(edge.source, (degree.get(edge.source) ?? 0) + 1);
|
|
105
|
+
degree.set(edge.target, (degree.get(edge.target) ?? 0) + 1);
|
|
106
|
+
}
|
|
107
|
+
return degree;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function focusedNodeIds(edges: NoteGraphEdge[], selectedPath: string, maxDepth: number): Set<string> {
|
|
111
|
+
const adjacency = new Map<string, Set<string>>();
|
|
112
|
+
for (const edge of edges) {
|
|
113
|
+
if (!adjacency.has(edge.source)) adjacency.set(edge.source, new Set());
|
|
114
|
+
if (!adjacency.has(edge.target)) adjacency.set(edge.target, new Set());
|
|
115
|
+
adjacency.get(edge.source)?.add(edge.target);
|
|
116
|
+
adjacency.get(edge.target)?.add(edge.source);
|
|
117
|
+
}
|
|
118
|
+
const visible = new Set<string>([selectedPath]);
|
|
119
|
+
let frontier = new Set<string>([selectedPath]);
|
|
120
|
+
for (let depth = 0; depth < maxDepth; depth += 1) {
|
|
121
|
+
const next = new Set<string>();
|
|
122
|
+
for (const nodeId of frontier) {
|
|
123
|
+
for (const neighbor of adjacency.get(nodeId) ?? []) {
|
|
124
|
+
if (visible.has(neighbor)) continue;
|
|
125
|
+
visible.add(neighbor);
|
|
126
|
+
next.add(neighbor);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
frontier = next;
|
|
130
|
+
if (frontier.size === 0) break;
|
|
131
|
+
}
|
|
132
|
+
return visible;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function compareNodes(a: NotesGraphRenderNode, b: NotesGraphRenderNode): number {
|
|
136
|
+
return NODE_KIND_ORDER[a.kind] - NODE_KIND_ORDER[b.kind] || a.title.localeCompare(b.title) || a.id.localeCompare(b.id);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function deriveNotesGraphData(
|
|
140
|
+
snapshot: NotesVaultIndexSnapshot | null,
|
|
141
|
+
settings: NotesGraphSettings,
|
|
142
|
+
selectedPath: string | null,
|
|
143
|
+
): NotesGraphRenderData {
|
|
144
|
+
if (!snapshot) return { nodes: [], edges: [], noteCount: 0, linkCount: 0, missingCount: 0, tagCount: 0, hiddenCount: 0 };
|
|
145
|
+
const metadataByPath = new Map(snapshot.notes.map(note => [note.path, note]));
|
|
146
|
+
const graph = buildWorkingGraph(snapshot, settings);
|
|
147
|
+
let candidateNodes = graph.nodes.filter(node => {
|
|
148
|
+
if (settings.existingFilesOnly && (node.kind === 'missing' || node.kind === 'ambiguous')) return false;
|
|
149
|
+
if (!settings.showTags && node.kind === 'tag') return false;
|
|
150
|
+
if (!settings.showAttachments && node.kind === 'attachment') return false;
|
|
151
|
+
return matchesQuery(settings.query, node, metadataByPath.get(node.path ?? node.id));
|
|
152
|
+
});
|
|
153
|
+
let candidateIds = new Set(candidateNodes.map(node => node.id));
|
|
154
|
+
let candidateEdges = graph.edges.filter(edge => candidateIds.has(edge.source) && candidateIds.has(edge.target));
|
|
155
|
+
if (!settings.showOrphans) {
|
|
156
|
+
const degree = degreeByNode(candidateEdges);
|
|
157
|
+
candidateNodes = candidateNodes.filter(node => node.id === selectedPath || (degree.get(node.id) ?? 0) > 0 || node.kind !== 'note');
|
|
158
|
+
candidateIds = new Set(candidateNodes.map(node => node.id));
|
|
159
|
+
candidateEdges = candidateEdges.filter(edge => candidateIds.has(edge.source) && candidateIds.has(edge.target));
|
|
160
|
+
}
|
|
161
|
+
if (settings.focusSelected && selectedPath && candidateIds.has(selectedPath)) {
|
|
162
|
+
const focusedIds = focusedNodeIds(candidateEdges, selectedPath, settings.focusDepth);
|
|
163
|
+
candidateNodes = candidateNodes.filter(node => focusedIds.has(node.id));
|
|
164
|
+
candidateIds = new Set(candidateNodes.map(node => node.id));
|
|
165
|
+
candidateEdges = candidateEdges.filter(edge => candidateIds.has(edge.source) && candidateIds.has(edge.target));
|
|
166
|
+
}
|
|
167
|
+
const degree = degreeByNode(candidateEdges);
|
|
168
|
+
const renderNodes: NotesGraphRenderNode[] = candidateNodes.map(node => {
|
|
169
|
+
const metadata = metadataByPath.get(node.path ?? node.id);
|
|
170
|
+
const group = matchingGroup(node, metadata, settings);
|
|
171
|
+
return {
|
|
172
|
+
...node,
|
|
173
|
+
degree: degree.get(node.id) ?? 0,
|
|
174
|
+
...(group ? { groupColor: group.color, groupLabel: group.label } : {}),
|
|
175
|
+
searchMatch: matchesQuery(settings.query, node, metadata),
|
|
176
|
+
};
|
|
177
|
+
}).sort(compareNodes);
|
|
178
|
+
const visibleIds = new Set(renderNodes.map(node => node.id));
|
|
179
|
+
const edges = candidateEdges
|
|
180
|
+
.filter(edge => visibleIds.has(edge.source) && visibleIds.has(edge.target))
|
|
181
|
+
.map(edge => ({ ...edge, virtual: edge.target.startsWith('tag:') || edge.source.startsWith('tag:') }))
|
|
182
|
+
.sort((a, b) => a.source.localeCompare(b.source) || a.target.localeCompare(b.target) || a.raw.localeCompare(b.raw));
|
|
183
|
+
return {
|
|
184
|
+
nodes: renderNodes,
|
|
185
|
+
edges,
|
|
186
|
+
noteCount: renderNodes.filter(node => node.kind === 'note').length,
|
|
187
|
+
linkCount: edges.filter(edge => !edge.virtual).length,
|
|
188
|
+
missingCount: renderNodes.filter(node => node.kind === 'missing' || node.kind === 'ambiguous').length,
|
|
189
|
+
tagCount: renderNodes.filter(node => node.kind === 'tag').length,
|
|
190
|
+
hiddenCount: graph.nodes.length - renderNodes.length,
|
|
191
|
+
};
|
|
192
|
+
}
|