synabun 2.0.10 → 2.1.0
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/CHANGELOG.md +86 -0
- package/README.md +25 -2
- package/THIRD-PARTY-LICENSES.md +22 -0
- package/bin/synabun.js +71 -24
- package/docs/whatsapp.md +2 -2
- package/hooks/claude-code/pre-websearch.mjs +12 -1
- package/hooks/claude-code/shared.mjs +5 -0
- package/hooks/claude-code/stop.mjs +1 -1
- package/lib/claude-hooks.js +172 -18
- package/lib/client-config-repair.js +17 -8
- package/lib/desktop-app.js +7 -1
- package/lib/external-tools.js +1 -1
- package/lib/first-launch-protection.js +57 -12
- package/lib/mcp-dist.js +176 -0
- package/lib/release-npm-ci.mjs +138 -0
- package/lib/release-publish.mjs +91 -0
- package/lib/release-scan.mjs +50 -0
- package/lib/server-crash-record.js +123 -0
- package/lib/server-exit.js +318 -0
- package/lib/server-supervisor.js +508 -0
- package/lib/start-launcher.js +37 -4
- package/lib/tools-cli.js +45 -0
- package/lib/update-snapshot.js +228 -0
- package/lib/virustotal.mjs +192 -0
- package/lib/windows-crash-event.js +269 -0
- package/mcp-server/dist/http.d.ts +20 -1
- package/mcp-server/dist/http.d.ts.map +1 -1
- package/mcp-server/dist/http.js +59 -12
- package/mcp-server/dist/http.js.map +1 -1
- package/mcp-server/dist/index.d.ts +33 -27
- package/mcp-server/dist/index.d.ts.map +1 -1
- package/mcp-server/dist/index.js +128 -143
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/preload.js +1 -1
- package/mcp-server/dist/preload.js.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.d.ts +6 -2
- package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.js +81 -28
- package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
- package/mcp-server/dist/services/memory-judge-backfill.d.ts +6 -0
- package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
- package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
- package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
- package/mcp-server/dist/services/neural-interface.d.ts +16 -10
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js +67 -11
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/server-instructions.d.ts +7 -2
- package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
- package/mcp-server/dist/services/server-instructions.js +20 -62
- package/mcp-server/dist/services/server-instructions.js.map +1 -1
- package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
- package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-catalog.js +339 -0
- package/mcp-server/dist/services/tool-catalog.js.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
- package/mcp-server/dist/services/tool-list.d.ts +108 -0
- package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list.js +334 -0
- package/mcp-server/dist/services/tool-list.js.map +1 -0
- package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
- package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-runtime.js +400 -0
- package/mcp-server/dist/services/tool-runtime.js.map +1 -0
- package/mcp-server/dist/services/whiteboard-geometry.d.ts +26 -2
- package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
- package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
- package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +10 -10
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +22 -13
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
- package/mcp-server/dist/tools/image-tools.d.ts +1 -1
- package/mcp-server/dist/tools/image-tools.js +1 -1
- package/mcp-server/dist/tools/skill-tools.d.ts +505 -0
- package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill-tools.js +639 -0
- package/mcp-server/dist/tools/skill-tools.js.map +1 -0
- package/mcp-server/dist/tools/skill.d.ts +7 -0
- package/mcp-server/dist/tools/skill.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill.js +11 -0
- package/mcp-server/dist/tools/skill.js.map +1 -0
- package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
- package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
- package/mcp-server/dist/tools/tool-groups.js +147 -0
- package/mcp-server/dist/tools/tool-groups.js.map +1 -0
- package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-format.js +7 -4
- package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
- package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
- package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/src/http.ts +75 -12
- package/mcp-server/src/index.ts +147 -154
- package/mcp-server/src/preload.ts +12 -12
- package/mcp-server/src/services/codex-config-heal.ts +80 -29
- package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
- package/mcp-server/src/services/neural-interface.ts +79 -20
- package/mcp-server/src/services/server-instructions.ts +27 -63
- package/mcp-server/src/services/tool-catalog.ts +403 -0
- package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
- package/mcp-server/src/services/tool-list.ts +410 -0
- package/mcp-server/src/services/tool-runtime.ts +457 -0
- package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
- package/mcp-server/src/tools/agents.ts +22 -14
- package/mcp-server/src/tools/image-tools.ts +1 -1
- package/mcp-server/src/tools/skill-tools.ts +589 -0
- package/mcp-server/src/tools/skill.ts +13 -0
- package/mcp-server/src/tools/tool-groups.ts +164 -0
- package/mcp-server/src/tools/whiteboard-format.ts +9 -3
- package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
- package/neural-interface/i18n/en.json +3463 -200
- package/neural-interface/i18n/pt-BR.json +3411 -151
- package/neural-interface/lib/assistant-api.js +127 -28
- package/neural-interface/lib/assistant-brains/claude.js +4 -3
- package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +12 -2
- package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +32 -9
- package/neural-interface/lib/assistant-brains/codex.js +9 -5
- package/neural-interface/lib/assistant-brains/opencode.js +120 -54
- package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +28 -13
- package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +59 -19
- package/neural-interface/lib/assistant-catalog.js +6 -7
- package/neural-interface/lib/assistant-dispatch.js +871 -156
- package/neural-interface/lib/assistant-envelope.js +3 -1
- package/neural-interface/lib/assistant-persona.js +80 -11
- package/neural-interface/lib/assistant-plan-permissions.js +10 -9
- package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
- package/neural-interface/lib/assistant-route-gate.js +6 -4
- package/neural-interface/lib/assistant-router.js +13 -8
- package/neural-interface/lib/assistant-runtime.js +56 -18
- package/neural-interface/lib/assistant-task-prompt.js +78 -14
- package/neural-interface/lib/assistant-tools.js +51 -0
- package/neural-interface/lib/backup-service.js +620 -3
- package/neural-interface/lib/backup-zip-reader.js +10 -5
- package/neural-interface/lib/backup-zip-writer.js +257 -0
- package/neural-interface/lib/browser-execution.js +10 -2
- package/neural-interface/lib/browser-guard-cdp.js +83 -0
- package/neural-interface/lib/browser-network-guard.js +284 -0
- package/neural-interface/lib/browser-policy-roots.js +64 -0
- package/neural-interface/lib/browser-tool-policy.js +186 -31
- package/neural-interface/lib/claude-agent-bridge.js +4 -2
- package/neural-interface/lib/claude-hooks-status.js +103 -0
- package/neural-interface/lib/claude-temporary.js +5 -11
- package/neural-interface/lib/cli-install.js +18 -138
- package/neural-interface/lib/cli-resolver.js +4 -1
- package/neural-interface/lib/cli-update-planner.js +32 -31
- package/neural-interface/lib/cloudflared/tunnel.js +42 -2
- package/neural-interface/lib/codex-mcp-approvals.js +11 -0
- package/neural-interface/lib/codex-worker-app-server.js +172 -0
- package/neural-interface/lib/confined-fs.js +30 -3
- package/neural-interface/lib/crash-notice-api.js +98 -0
- package/neural-interface/lib/editor-completion-opencode.js +68 -68
- package/neural-interface/lib/exec-loop-command.js +4 -8
- package/neural-interface/lib/http-guards.js +8 -2
- package/neural-interface/lib/install-details.js +4 -1
- package/neural-interface/lib/mcp-agent-servers.js +67 -0
- package/neural-interface/lib/mcp-client-config.js +0 -29
- package/neural-interface/lib/mcp-external-servers.js +323 -0
- package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
- package/neural-interface/lib/morelogin.js +30 -0
- package/neural-interface/lib/native-loop-providers.js +547 -47
- package/neural-interface/lib/native-loop-runtime.js +268 -41
- package/neural-interface/lib/opencode-config.js +557 -0
- package/neural-interface/lib/opencode-db-schema.js +17 -34
- package/neural-interface/lib/opencode-history.js +48 -218
- package/neural-interface/lib/opencode-mcp-ready.js +108 -0
- package/neural-interface/lib/opencode-native-boundary.js +44 -0
- package/neural-interface/lib/opencode-protocol.js +249 -112
- package/neural-interface/lib/opencode-runtime-config.js +32 -22
- package/neural-interface/lib/opencode-serve-records.js +39 -21
- package/neural-interface/lib/opencode-v2-client.js +48 -153
- package/neural-interface/lib/opencode-v2-ws-requests.js +36 -210
- package/neural-interface/lib/opencode-worker-data.js +27 -0
- package/neural-interface/lib/opencode2-client.js +73 -37
- package/neural-interface/lib/opencode2-proxy.js +23 -63
- package/neural-interface/lib/opencode2-translate.js +51 -2
- package/neural-interface/lib/owner-authority.js +249 -0
- package/neural-interface/lib/page-session.js +275 -0
- package/neural-interface/lib/peer-identity.js +763 -0
- package/neural-interface/lib/request-gate.js +17 -2
- package/neural-interface/lib/rulesets/api.js +1 -1
- package/neural-interface/lib/rulesets/fs-safe.js +1 -1
- package/neural-interface/lib/rulesets/installer.js +92 -27
- package/neural-interface/lib/rulesets/json-edit.js +1 -1
- package/neural-interface/lib/session-cache-builder.js +17 -30
- package/neural-interface/lib/session-title-generator.js +58 -36
- package/neural-interface/lib/skills/api-v2.js +495 -0
- package/neural-interface/lib/skills/bundle.js +418 -0
- package/neural-interface/lib/skills/catalog.js +294 -0
- package/neural-interface/lib/skills/creation-api.js +191 -0
- package/neural-interface/lib/skills/creation-brief.js +247 -0
- package/neural-interface/lib/skills/creation-sources.js +267 -0
- package/neural-interface/lib/skills/creation.js +843 -0
- package/neural-interface/lib/skills/deploy.js +564 -0
- package/neural-interface/lib/skills/digest.js +119 -0
- package/neural-interface/lib/skills/discover.js +111 -0
- package/neural-interface/lib/skills/draft-confinement.js +214 -0
- package/neural-interface/lib/skills/eval-confinement.js +397 -0
- package/neural-interface/lib/skills/eval-sandbox.js +280 -0
- package/neural-interface/lib/skills/eval-trace.js +119 -0
- package/neural-interface/lib/skills/evals-api.js +212 -0
- package/neural-interface/lib/skills/evals.js +1573 -0
- package/neural-interface/lib/skills/export.js +200 -0
- package/neural-interface/lib/skills/frontmatter.js +64 -0
- package/neural-interface/lib/skills/health.js +75 -0
- package/neural-interface/lib/skills/json-edit.js +165 -0
- package/neural-interface/lib/skills/known-bridge-digests.json +387 -0
- package/neural-interface/lib/skills/known-bridges.js +96 -0
- package/neural-interface/lib/skills/library.js +823 -0
- package/neural-interface/lib/skills/local-store.js +21 -0
- package/neural-interface/lib/skills/migration.js +433 -0
- package/neural-interface/lib/skills/operations.js +45 -0
- package/neural-interface/lib/skills/ownership.js +427 -0
- package/neural-interface/lib/skills/packages.js +88 -0
- package/neural-interface/lib/skills/reviews.js +212 -0
- package/neural-interface/lib/skills/revision.js +80 -0
- package/neural-interface/lib/skills/roots.js +262 -0
- package/neural-interface/lib/skills/runtime-checks.js +355 -0
- package/neural-interface/lib/skills/scan-assets.js +252 -0
- package/neural-interface/lib/skills/scan-context.js +26 -0
- package/neural-interface/lib/skills/scan-shell.js +324 -0
- package/neural-interface/lib/skills/scan.js +364 -0
- package/neural-interface/lib/skills/scanners.js +54 -0
- package/neural-interface/lib/skills/service.js +522 -0
- package/neural-interface/lib/skills/telemetry.js +113 -0
- package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
- package/neural-interface/lib/tool-lists.js +124 -0
- package/neural-interface/lib/whatsapp/bridge.js +6 -3
- package/neural-interface/lib/worker-confinement.js +1192 -0
- package/neural-interface/lib/worker-guard-setting.js +56 -0
- package/neural-interface/lib/worker-mcp-channel.js +175 -0
- package/neural-interface/lib/worker-relay-ports.js +227 -0
- package/neural-interface/lib/worker-resume.js +229 -0
- package/neural-interface/lib/worker-sandbox.js +299 -0
- package/neural-interface/package-lock.json +18 -12
- package/neural-interface/package.json +2 -2
- package/neural-interface/public/index.html +3 -1
- package/neural-interface/public/index2d.html +19 -11
- package/neural-interface/public/onboarding.html +2 -2
- package/neural-interface/public/shared/account-menu.js +8 -5
- package/neural-interface/public/shared/agent-runtime-options.js +35 -19
- package/neural-interface/public/shared/api.js +1527 -1336
- package/neural-interface/public/shared/app-frame.js +192 -0
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +33 -2
- package/neural-interface/public/shared/assistant/asst-ask-styles.js +270 -0
- package/neural-interface/public/shared/assistant/asst-ask-tail.js +118 -0
- package/neural-interface/public/shared/assistant/asst-ask.js +397 -0
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +49 -35
- package/neural-interface/public/shared/assistant/asst-control.js +157 -26
- package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
- package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
- package/neural-interface/public/shared/assistant/asst-limit-dock.js +40 -0
- package/neural-interface/public/shared/assistant/asst-limit-wait.js +294 -0
- package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
- package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
- package/neural-interface/public/shared/assistant/asst-menu.js +7 -6
- package/neural-interface/public/shared/assistant/asst-panel.js +106 -11
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +66 -49
- package/neural-interface/public/shared/assistant/asst-render.js +401 -77
- package/neural-interface/public/shared/assistant/asst-route.js +83 -12
- package/neural-interface/public/shared/assistant/asst-scenes.js +2 -0
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +67 -4
- package/neural-interface/public/shared/assistant/asst-slash.js +9 -7
- package/neural-interface/public/shared/assistant/asst-state.js +11 -15
- package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +59 -21
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +156 -16
- package/neural-interface/public/shared/automation-context.js +5 -2
- package/neural-interface/public/shared/cc-dropdown.js +89 -19
- package/neural-interface/public/shared/cdx/cdx-context-menu.js +10 -9
- package/neural-interface/public/shared/cdx/cdx-copy.js +16 -0
- package/neural-interface/public/shared/cdx/cdx-output-model.js +22 -1
- package/neural-interface/public/shared/cdx/cdx-output.js +8 -7
- package/neural-interface/public/shared/cdx/cdx-panel.js +45 -149
- package/neural-interface/public/shared/cdx/cdx-protocol.js +28 -1
- package/neural-interface/public/shared/cdx/cdx-render.js +47 -29
- package/neural-interface/public/shared/cdx/cdx-requests.js +3 -3
- package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
- package/neural-interface/public/shared/cdx/cdx-styles.js +11 -3
- package/neural-interface/public/shared/cdx/cdx-tabs.js +52 -39
- package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
- package/neural-interface/public/shared/cli-install-view.js +4 -8
- package/neural-interface/public/shared/cli-status.js +2 -2
- package/neural-interface/public/shared/constants.js +2 -2
- package/neural-interface/public/shared/context-menu-areas.js +34 -0
- package/neural-interface/public/shared/context-menu-logic.js +243 -0
- package/neural-interface/public/shared/context-menu-model.js +366 -0
- package/neural-interface/public/shared/context-menu.js +372 -0
- package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
- package/neural-interface/public/shared/crash-notice-view.js +168 -0
- package/neural-interface/public/shared/desktop-update-view.js +20 -0
- package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
- package/neural-interface/public/shared/html-shell.js +9 -11
- package/neural-interface/public/shared/i18n.js +2 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +7 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +4 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +3 -101
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +2 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +1 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +2 -6
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +11 -11
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +0 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +8 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +7 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-outcome-notifications.js +16 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +47 -252
- package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
- package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +95 -202
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +6 -21
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +4 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +8 -61
- package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +2 -91
- package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +16 -15
- package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +8 -21
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +1 -99
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +5 -35
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +0 -21
- package/neural-interface/public/shared/ocp-v2/{ocp-v2-profile-inheritance.js → ocp-v2-tools-inheritance.js} +16 -16
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +14 -47
- package/neural-interface/public/shared/page-session.js +96 -0
- package/neural-interface/public/shared/registry.js +5 -3
- package/neural-interface/public/shared/retired-2d.js +3 -0
- package/neural-interface/public/shared/schedules-view.js +195 -61
- package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
- package/neural-interface/public/shared/settings/settings-data.js +3 -1
- package/neural-interface/public/shared/settings/settings-ia.js +6 -6
- package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
- package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +265 -0
- package/neural-interface/public/shared/settings/settings-skill-folders.js +130 -0
- package/neural-interface/public/shared/settings/settings-worker-guard.js +72 -0
- package/neural-interface/public/shared/skills/ss-args.js +96 -0
- package/neural-interface/public/shared/skills/ss-creation.js +219 -0
- package/neural-interface/public/shared/skills/ss-dialog.js +130 -0
- package/neural-interface/public/shared/skills/ss-doc.js +173 -0
- package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
- package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
- package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
- package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
- package/neural-interface/public/shared/skills/ss-evals.js +417 -0
- package/neural-interface/public/shared/skills/ss-form.js +159 -0
- package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
- package/neural-interface/public/shared/skills/ss-ids.js +32 -0
- package/neural-interface/public/shared/skills/ss-lint.js +141 -0
- package/neural-interface/public/shared/skills/ss-presets.js +117 -0
- package/neural-interface/public/shared/skills/ss-profiles.js +475 -0
- package/neural-interface/public/shared/skills/ss-resources.js +165 -0
- package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
- package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
- package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
- package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
- package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai.js +236 -0
- package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
- package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
- package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
- package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
- package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
- package/neural-interface/public/shared/skills/studio/sx-dom.js +229 -0
- package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
- package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
- package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
- package/neural-interface/public/shared/skills/studio/sx-geometry.js +82 -0
- package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
- package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
- package/neural-interface/public/shared/skills/studio/sx-install-flow.js +279 -0
- package/neural-interface/public/shared/skills/studio/sx-install.js +296 -0
- package/neural-interface/public/shared/skills/studio/sx-library-view.js +639 -0
- package/neural-interface/public/shared/skills/studio/sx-library.js +475 -0
- package/neural-interface/public/shared/skills/studio/sx-main.js +681 -0
- package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
- package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
- package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
- package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
- package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
- package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
- package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
- package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
- package/neural-interface/public/shared/skills/studio/sx-subject.js +248 -0
- package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
- package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
- package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
- package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +425 -0
- package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
- package/neural-interface/public/shared/styles.css +1525 -1779
- package/neural-interface/public/shared/synabun-mascot.js +1115 -9
- package/neural-interface/public/shared/tool-list-picker.js +55 -0
- package/neural-interface/public/shared/tool-list-storage.js +24 -0
- package/neural-interface/public/shared/tool-list-view.js +112 -0
- package/neural-interface/public/shared/tour/tour-actor.js +268 -0
- package/neural-interface/public/shared/tour/tour-beats.js +336 -0
- package/neural-interface/public/shared/tour/tour-engine.js +884 -0
- package/neural-interface/public/shared/tour/tour-ink.js +390 -0
- package/neural-interface/public/shared/tour/tour-stage.js +440 -0
- package/neural-interface/public/shared/tour/tour-state.js +40 -0
- package/neural-interface/public/shared/tour/tour-tips.js +99 -0
- package/neural-interface/public/shared/tour/tour.css +144 -0
- package/neural-interface/public/shared/ui-automation-studio.js +91 -128
- package/neural-interface/public/shared/ui-claude-panel.js +77 -5
- package/neural-interface/public/shared/ui-command-runner.js +6 -3
- package/neural-interface/public/shared/ui-context-menu.js +295 -0
- package/neural-interface/public/shared/ui-cost-widget.js +57 -59
- package/neural-interface/public/shared/ui-crash-notice.js +187 -0
- package/neural-interface/public/shared/ui-detail.js +15 -3
- package/neural-interface/public/shared/ui-image-gallery.js +50 -47
- package/neural-interface/public/shared/ui-keybinds.js +26 -1
- package/neural-interface/public/shared/ui-menubar.js +8 -18
- package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +7 -1
- package/neural-interface/public/shared/ui-navbar.js +4 -24
- package/neural-interface/public/shared/ui-panels.js +96 -65
- package/neural-interface/public/shared/ui-schedules-studio.js +507 -423
- package/neural-interface/public/shared/ui-sessions.js +5 -3
- package/neural-interface/public/shared/ui-settings.js +594 -462
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +1 -1
- package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
- package/neural-interface/public/shared/ui-sidepanel-windows.js +16 -11
- package/neural-interface/public/shared/ui-skills.js +33 -2830
- package/neural-interface/public/shared/ui-styleguide.js +5 -2
- package/neural-interface/public/shared/ui-sync.js +15 -5
- package/neural-interface/public/shared/ui-terminal.js +124 -180
- package/neural-interface/public/shared/ui-tool-updates.js +3 -1
- package/neural-interface/public/shared/ui-tooltip.js +10 -5
- package/neural-interface/public/shared/ui-trash.js +6 -4
- package/neural-interface/public/shared/ui-tutorial-layout.js +3 -117
- package/neural-interface/public/shared/ui-tutorial-preview.js +103 -0
- package/neural-interface/public/shared/ui-tutorial-steps.js +3 -65
- package/neural-interface/public/shared/ui-tutorial.css +47 -100
- package/neural-interface/public/shared/ui-tutorial.js +285 -509
- package/neural-interface/public/shared/ui-update.js +38 -2
- package/neural-interface/public/shared/ui-whiteboard.js +311 -58
- package/neural-interface/public/shared/ui-worker-end.js +4 -0
- package/neural-interface/public/shared/ui-workspaces.js +3 -2
- package/neural-interface/public/shared/view-variant.js +66 -0
- package/neural-interface/public/shared/whatsapp/wa-view.js +1 -1
- package/neural-interface/public/shared/whiteboard-list.js +172 -0
- package/neural-interface/public/shared/worker-end.js +10 -3
- package/neural-interface/public/shared/worker-restart.js +12 -0
- package/neural-interface/public/sidepanel-session.html +1 -1
- package/neural-interface/public/variant/2d/background.js +2 -1
- package/neural-interface/public/variant/2d/context-menu.js +8 -2
- package/neural-interface/public/variant/2d/graph.js +42 -20
- package/neural-interface/public/variant/2d/hulls.js +14 -9
- package/neural-interface/public/variant/2d/lasso.js +11 -7
- package/neural-interface/public/variant/2d/main.js +32 -1
- package/neural-interface/public/variant/2d/minimap.js +11 -13
- package/neural-interface/public/variant/3d/main.js +69 -6
- package/neural-interface/public/variant/3d/map-controls.js +24 -9
- package/neural-interface/public/vendor/caveat/OFL.txt +93 -0
- package/neural-interface/public/vendor/caveat/caveat-latin-400-normal.woff2 +0 -0
- package/neural-interface/public/vendor/caveat/caveat-latin-700-normal.woff2 +0 -0
- package/neural-interface/public/vendor/caveat/caveat.css +17 -0
- package/neural-interface/public/vendor/caveat/manifest.json +12 -0
- package/neural-interface/public/vendor/yaml/LICENSE +13 -0
- package/neural-interface/public/vendor/yaml/manifest.json +4 -0
- package/neural-interface/public/vendor/yaml/yaml-2.9.1.min.js +137 -0
- package/neural-interface/scripts/build-vendor.mjs +32 -0
- package/neural-interface/server.js +3934 -2454
- package/neural-interface/templates/rulesets/core.md +1 -1
- package/neural-interface/templates/rulesets/legacy-hashes.json +18 -0
- package/neural-interface/templates/rulesets/manifest.json +8 -8
- package/npm-shrinkwrap.json +18 -12
- package/package.json +16 -3
- package/postinstall.js +9 -4
- package/preuninstall.js +1 -1
- package/setup.js +97 -322
- package/skills/skill-forge/SKILL.md +177 -0
- package/skills/skill-forge/evals/evals.json +54 -0
- package/skills/skill-forge/references/package.md +105 -0
- package/skills/skill-forge/references/review-and-recovery.md +63 -0
- package/skills/skill-forge/references/runtime-profiles.md +20 -0
- package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
- package/skills/synabun/SKILL.md +10 -7
- package/skills/synabun/modules/audit.md +1 -5
- package/skills/synabun/modules/changelog.md +1 -5
- package/skills/synabun/modules/idea.md +1 -1
- package/skills/synabun/modules/memorize.md +6 -9
- package/skills/synabun/modules/schedule.md +4 -4
- package/mcp-server/dist/services/profiles.d.ts +0 -120
- package/mcp-server/dist/services/profiles.d.ts.map +0 -1
- package/mcp-server/dist/services/profiles.js +0 -387
- package/mcp-server/dist/services/profiles.js.map +0 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +0 -97
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +0 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.js +0 -228
- package/mcp-server/dist/tools/leonardo-browser-tools.js.map +0 -1
- package/mcp-server/dist/tools/leonardo.d.ts +0 -13
- package/mcp-server/dist/tools/leonardo.d.ts.map +0 -1
- package/mcp-server/dist/tools/leonardo.js +0 -21
- package/mcp-server/dist/tools/leonardo.js.map +0 -1
- package/mcp-server/dist/tools/profile.d.ts +0 -17
- package/mcp-server/dist/tools/profile.d.ts.map +0 -1
- package/mcp-server/dist/tools/profile.js +0 -114
- package/mcp-server/dist/tools/profile.js.map +0 -1
- package/mcp-server/src/services/profiles.ts +0 -428
- package/mcp-server/src/tools/leonardo-browser-tools.ts +0 -291
- package/mcp-server/src/tools/leonardo.ts +0 -30
- package/mcp-server/src/tools/profile.ts +0 -122
- package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +0 -47
- package/neural-interface/lib/assistant-brains/opencode-route-gate.js +0 -62
- package/neural-interface/lib/mcp-profile-servers.js +0 -120
- package/neural-interface/public/shared/ui-tutorial-draw.js +0 -311
- package/skills/leonardo/SKILL.md +0 -168
- package/skills/leonardo/icon.svg +0 -1
- package/skills/leonardo/modules/browser-guide.md +0 -378
- package/skills/leonardo/modules/image-prompter.md +0 -283
- package/skills/leonardo/modules/model-advisor.md +0 -100
- package/skills/leonardo/modules/prompt-library.md +0 -110
- package/skills/leonardo/modules/style-guide.md +0 -186
- package/skills/leonardo/modules/video-prompter.md +0 -317
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Neural Interface — the notice after an automatic restart: the page side
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// Asks GET /api/system/crash-notice when the page starts and every time its sync
|
|
6
|
+
// socket connects: a page that was open through the crash is not reloaded, its
|
|
7
|
+
// sockets reconnect (ui-sync.js `session:info`). What crash-notice-view.js says is
|
|
8
|
+
// drawn in the update toast's shape (bottom right, styles.css .update-check-toast,
|
|
9
|
+
// .crash-notice) once the loading screen is gone, and stays until it is dismissed.
|
|
10
|
+
// Dismiss asks the server to drop it (POST /api/system/crash-notice/dismiss), which
|
|
11
|
+
// tells every other window (`sync:crash-notice:changed`); this browser also keeps
|
|
12
|
+
// the id it dismissed, for a server that could not remove its record. Open logs
|
|
13
|
+
// is Settings > App's own: the desktop app's bridge, or POST
|
|
14
|
+
// /api/system/app/open-folder, which only a page on this computer may ask. Never
|
|
15
|
+
// asked by an invite guest, and never drawn for one, whatever reaches its sync
|
|
16
|
+
// socket: /api/system is the owner's (the server sends `crash-notice:` to the
|
|
17
|
+
// owner's pages only).
|
|
18
|
+
|
|
19
|
+
import { on } from './state.js';
|
|
20
|
+
import { getLocale, t } from './i18n.js';
|
|
21
|
+
import { desktopApp } from './desktop-bridge.js';
|
|
22
|
+
import { isGuest } from './ui-sync.js';
|
|
23
|
+
import { crashNoticeView, isLoopbackHost, readCrashNotice } from './crash-notice-view.js';
|
|
24
|
+
|
|
25
|
+
const NOTICE_URL = '/api/system/crash-notice';
|
|
26
|
+
const OPEN_FOLDER_URL = '/api/system/app/open-folder';
|
|
27
|
+
const WRITE = Object.freeze({ 'Content-Type': 'application/json', 'X-SynaBun-UI': '1', Accept: 'application/json' });
|
|
28
|
+
const DISMISSED_KEY = 'synabun-crash-notice-dismissed';
|
|
29
|
+
const NOTICE_ID = 'crash-notice';
|
|
30
|
+
|
|
31
|
+
const translate = (key, params) => t(`crashNotice.${key}`, params);
|
|
32
|
+
|
|
33
|
+
let _wired = false;
|
|
34
|
+
let _asking = null;
|
|
35
|
+
let _current = null; // { id, el }
|
|
36
|
+
let _waiting = null; // the notice that waits for the loading screen to go
|
|
37
|
+
let _guest = false; // what the last `session:info` said (ui-sync.js isGuest() is the socket's own word)
|
|
38
|
+
|
|
39
|
+
const guestPage = () => _guest || isGuest();
|
|
40
|
+
|
|
41
|
+
function esc(value) {
|
|
42
|
+
return String(value ?? '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function dismissedHere(id) {
|
|
46
|
+
try { return localStorage.getItem(DISMISSED_KEY) === id; } catch { return false; }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function rememberDismissed(id) {
|
|
50
|
+
try { localStorage.setItem(DISMISSED_KEY, id); } catch { /* storage refused: the server's word is enough */ }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function canOpenLogs() {
|
|
54
|
+
if (typeof desktopApp()?.openFolder === 'function') return true;
|
|
55
|
+
return isLoopbackHost(location.hostname);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function hide() {
|
|
59
|
+
const current = _current;
|
|
60
|
+
_current = null;
|
|
61
|
+
if (!current) return;
|
|
62
|
+
current.el.classList.remove('show');
|
|
63
|
+
setTimeout(() => current.el.remove(), 250);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** The loading screen covers the page while it starts: the notice waits for it to go. */
|
|
67
|
+
function whenPageShown(run) {
|
|
68
|
+
const overlay = document.getElementById('loading-overlay');
|
|
69
|
+
if (!overlay || overlay.classList.contains('hidden')) { run(); return; }
|
|
70
|
+
const watch = new MutationObserver(() => {
|
|
71
|
+
if (!overlay.classList.contains('hidden')) return;
|
|
72
|
+
watch.disconnect();
|
|
73
|
+
run();
|
|
74
|
+
});
|
|
75
|
+
watch.observe(overlay, { attributes: true, attributeFilter: ['class'] });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function show(view) {
|
|
79
|
+
hide();
|
|
80
|
+
document.querySelectorAll(`#${NOTICE_ID}`).forEach((el) => el.remove());
|
|
81
|
+
const el = document.createElement('div');
|
|
82
|
+
el.className = 'update-check-toast crash-notice';
|
|
83
|
+
el.id = NOTICE_ID;
|
|
84
|
+
el.setAttribute('role', 'status');
|
|
85
|
+
el.setAttribute('aria-label', view.label);
|
|
86
|
+
el.dataset.noticeId = view.id;
|
|
87
|
+
const buttons = view.actions.map((item) => `<button class="action-btn action-btn--ghost crash-notice-btn" type="button" data-crash-action="${esc(item.id)}" id="crash-notice-${esc(item.id)}">${esc(item.label)}</button>`).join('');
|
|
88
|
+
el.innerHTML = `
|
|
89
|
+
<div class="utc-icon utc-icon--err" aria-hidden="true">!</div>
|
|
90
|
+
<div class="utc-body">
|
|
91
|
+
<div class="utc-title" id="crash-notice-title">${esc(view.title)}</div>
|
|
92
|
+
<div class="utc-sub" id="crash-notice-when">${esc(view.when)}</div>
|
|
93
|
+
${view.how ? `<div class="utc-sub" id="crash-notice-how">${esc(view.how)}</div>` : ''}
|
|
94
|
+
<div class="crash-notice-lost-title" id="crash-notice-lost-title">${esc(view.lostTitle)}</div>
|
|
95
|
+
<ul class="utc-list crash-notice-lost" aria-labelledby="crash-notice-lost-title">${view.lost.map((line) => `<li>${esc(line)}</li>`).join('')}</ul>
|
|
96
|
+
<div class="utc-sub crash-notice-note" id="crash-notice-note" role="status" hidden></div>
|
|
97
|
+
<div class="update-notice-actions">${buttons}</div>
|
|
98
|
+
</div>`;
|
|
99
|
+
el.querySelectorAll('[data-crash-action]').forEach((btn) => {
|
|
100
|
+
btn.addEventListener('click', (event) => {
|
|
101
|
+
event.stopPropagation();
|
|
102
|
+
if (btn.dataset.crashAction === 'dismiss') dismiss(view.id);
|
|
103
|
+
else if (btn.dataset.crashAction === 'logs') openLogs(el);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
document.body.appendChild(el);
|
|
107
|
+
requestAnimationFrame(() => el.classList.add('show'));
|
|
108
|
+
_current = { id: view.id, el };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Show this notice (or none): once per crash, never one this browser dismissed, never on a guest's page. */
|
|
112
|
+
function present(notice) {
|
|
113
|
+
if (!notice || guestPage()) {
|
|
114
|
+
_waiting = null;
|
|
115
|
+
hide();
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// A notice something else took off the page is drawn again: it stays until it is dismissed.
|
|
119
|
+
if (_current && !_current.el.isConnected) _current = null;
|
|
120
|
+
if (dismissedHere(notice.id) || _current?.id === notice.id || _waiting?.id === notice.id) return;
|
|
121
|
+
_waiting = notice;
|
|
122
|
+
whenPageShown(() => {
|
|
123
|
+
if (_waiting !== notice) return;
|
|
124
|
+
_waiting = null;
|
|
125
|
+
if (dismissedHere(notice.id) || guestPage()) return;
|
|
126
|
+
show(crashNoticeView(notice, { t: translate, locale: getLocale(), canOpenLogs: canOpenLogs() }));
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Ask the server; an older server (404) or a guest (403) has nothing to say. */
|
|
131
|
+
export function checkCrashNotice() {
|
|
132
|
+
if (guestPage()) return Promise.resolve(null);
|
|
133
|
+
if (_asking) return _asking;
|
|
134
|
+
_asking = (async () => {
|
|
135
|
+
try {
|
|
136
|
+
const res = await fetch(NOTICE_URL, { headers: { Accept: 'application/json' }, cache: 'no-store' });
|
|
137
|
+
if (!res.ok) return null;
|
|
138
|
+
const notice = readCrashNotice(await res.json());
|
|
139
|
+
present(notice);
|
|
140
|
+
return notice;
|
|
141
|
+
} catch {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
})().finally(() => { _asking = null; });
|
|
145
|
+
return _asking;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async function dismiss(id) {
|
|
149
|
+
rememberDismissed(id);
|
|
150
|
+
hide();
|
|
151
|
+
try {
|
|
152
|
+
const res = await fetch(`${NOTICE_URL}/dismiss`, { method: 'POST', headers: WRITE, body: JSON.stringify({ id }) });
|
|
153
|
+
const next = res.ok ? readCrashNotice(await res.json()) : null;
|
|
154
|
+
// A newer crash came while this one was shown: that one is news.
|
|
155
|
+
if (next && next.id !== id) present(next);
|
|
156
|
+
} catch { /* the server is away: this browser keeps it dismissed */ }
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function openLogs(el) {
|
|
160
|
+
const note = el.querySelector('#crash-notice-note');
|
|
161
|
+
const bridge = desktopApp();
|
|
162
|
+
let ok = false;
|
|
163
|
+
if (typeof bridge?.openFolder === 'function') {
|
|
164
|
+
try { ok = !!(await bridge.openFolder('logs'))?.ok; } catch { ok = false; }
|
|
165
|
+
} else {
|
|
166
|
+
try {
|
|
167
|
+
const res = await fetch(OPEN_FOLDER_URL, { method: 'POST', headers: WRITE, body: JSON.stringify({ which: 'logs' }) });
|
|
168
|
+
ok = res.ok;
|
|
169
|
+
} catch { ok = false; }
|
|
170
|
+
}
|
|
171
|
+
if (!note) return;
|
|
172
|
+
note.hidden = ok;
|
|
173
|
+
note.textContent = ok ? '' : translate('openLogsFailed');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Wire the notice once: ask now, and again every time the sync socket connects. */
|
|
177
|
+
export function initCrashNotice() {
|
|
178
|
+
if (_wired) return;
|
|
179
|
+
_wired = true;
|
|
180
|
+
on('session:info', (info) => {
|
|
181
|
+
_guest = !!info?.isGuest;
|
|
182
|
+
if (_guest) present(null);
|
|
183
|
+
else checkCrashNotice();
|
|
184
|
+
});
|
|
185
|
+
on('sync:crash-notice:changed', (message) => present(readCrashNotice(message)));
|
|
186
|
+
checkCrashNotice();
|
|
187
|
+
}
|
|
@@ -14,7 +14,8 @@ import { storage } from './storage.js';
|
|
|
14
14
|
import { catColor } from './colors.js';
|
|
15
15
|
import { truncate, formatMemoryContent, exportMemoryAsMarkdown, rafThrottle, escapeHtml } from './utils.js';
|
|
16
16
|
import { t, getLocale } from './i18n.js';
|
|
17
|
-
import { savePanelLayout, restorePanelLayout } from './ui-panels.js';
|
|
17
|
+
import { savePanelLayout, restorePanelLayout, clampPanelToFrame } from './ui-panels.js';
|
|
18
|
+
import { frameRect } from './app-frame.js';
|
|
18
19
|
import { sendSync as _sendSync, hasPermission, isGuest } from './ui-sync.js';
|
|
19
20
|
|
|
20
21
|
// Wrap sendSync — skip card events when guest lacks cards permission
|
|
@@ -546,9 +547,11 @@ function bringToFront(cardEl) {
|
|
|
546
547
|
function getNextCardPosition() {
|
|
547
548
|
const count = _openCards.size;
|
|
548
549
|
const offset = count * 30;
|
|
550
|
+
// Cascading from 200 / 80 px of the window (192 / 24 px into the app frame), inside the frame.
|
|
551
|
+
const f = frameRect();
|
|
549
552
|
return {
|
|
550
|
-
left: Math.min(
|
|
551
|
-
top: Math.min(
|
|
553
|
+
left: Math.max(f.left, Math.min(f.right - 540, f.left + 192 + (offset % 300))) + 'px',
|
|
554
|
+
top: Math.max(f.top, Math.min(f.bottom - 300, f.top + 24 + (offset % 200))) + 'px',
|
|
552
555
|
};
|
|
553
556
|
}
|
|
554
557
|
|
|
@@ -587,6 +590,13 @@ export function getOpenCardCount() {
|
|
|
587
590
|
return _openCards.size;
|
|
588
591
|
}
|
|
589
592
|
|
|
593
|
+
/** Press an open card's Linked button from outside it (the context menu), unless it is on already. */
|
|
594
|
+
export function focusLinkedMemories(memoryId) {
|
|
595
|
+
const card = _openCards.get(memoryId);
|
|
596
|
+
if (!card || state.focusedNodeId === memoryId) return;
|
|
597
|
+
q(card.el, 'focus-btn')?.click();
|
|
598
|
+
}
|
|
599
|
+
|
|
590
600
|
export function restoreOpenCards() {
|
|
591
601
|
const raw = storage.getItem(KEYS.OPEN_CARDS);
|
|
592
602
|
if (!raw) return;
|
|
@@ -1062,6 +1072,8 @@ export function openMemoryCard(node, savedPosition) {
|
|
|
1062
1072
|
// ── Add to DOM and state ──
|
|
1063
1073
|
_openCards.set(node.id, cardState);
|
|
1064
1074
|
document.body.appendChild(card);
|
|
1075
|
+
// A position saved in another window size, or with the explorers closed, comes back inside the app frame.
|
|
1076
|
+
if (savedPosition) clampPanelToFrame(card);
|
|
1065
1077
|
bringToFront(card);
|
|
1066
1078
|
|
|
1067
1079
|
// Trigger entrance animation on next frame
|
|
@@ -8,6 +8,7 @@ import { emit, on } from './state.js';
|
|
|
8
8
|
import { fetchImages, toggleImageFavorite, deleteImage } from './api.js';
|
|
9
9
|
import { addImageToWhiteboard } from './ui-whiteboard.js';
|
|
10
10
|
import { escapeHtml } from './utils.js';
|
|
11
|
+
import { centeredInFrame } from './app-frame.js';
|
|
11
12
|
|
|
12
13
|
const $ = (id) => document.getElementById(id);
|
|
13
14
|
|
|
@@ -23,33 +24,33 @@ let _lightboxImg = null; // filename currently in lightbox
|
|
|
23
24
|
let isVisible = false;
|
|
24
25
|
|
|
25
26
|
// ── Drag state ──
|
|
26
|
-
let _dragging = false;
|
|
27
|
-
let _dragOff = { x: 0, y: 0 };
|
|
28
|
-
let _dragRaf = 0;
|
|
29
|
-
let _pendingDrag = null;
|
|
30
|
-
|
|
31
|
-
function applyDragPosition() {
|
|
32
|
-
_dragRaf = 0;
|
|
33
|
-
if (!_panel || !_pendingDrag) return;
|
|
34
|
-
_panel.style.left = _pendingDrag.left + 'px';
|
|
35
|
-
_panel.style.top = _pendingDrag.top + 'px';
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function scheduleDragPosition(left, top) {
|
|
39
|
-
_pendingDrag = { left, top };
|
|
40
|
-
if (!_dragRaf) _dragRaf = requestAnimationFrame(applyDragPosition);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function flushDragPosition() {
|
|
44
|
-
if (_dragRaf) {
|
|
45
|
-
cancelAnimationFrame(_dragRaf);
|
|
46
|
-
_dragRaf = 0;
|
|
47
|
-
}
|
|
48
|
-
applyDragPosition();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// ── Icons ──
|
|
52
|
-
const ICON_CLOSE = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M4 4l8 8M12 4l-8 8"/></svg>';
|
|
27
|
+
let _dragging = false;
|
|
28
|
+
let _dragOff = { x: 0, y: 0 };
|
|
29
|
+
let _dragRaf = 0;
|
|
30
|
+
let _pendingDrag = null;
|
|
31
|
+
|
|
32
|
+
function applyDragPosition() {
|
|
33
|
+
_dragRaf = 0;
|
|
34
|
+
if (!_panel || !_pendingDrag) return;
|
|
35
|
+
_panel.style.left = _pendingDrag.left + 'px';
|
|
36
|
+
_panel.style.top = _pendingDrag.top + 'px';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function scheduleDragPosition(left, top) {
|
|
40
|
+
_pendingDrag = { left, top };
|
|
41
|
+
if (!_dragRaf) _dragRaf = requestAnimationFrame(applyDragPosition);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function flushDragPosition() {
|
|
45
|
+
if (_dragRaf) {
|
|
46
|
+
cancelAnimationFrame(_dragRaf);
|
|
47
|
+
_dragRaf = 0;
|
|
48
|
+
}
|
|
49
|
+
applyDragPosition();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ── Icons ──
|
|
53
|
+
const ICON_CLOSE = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M4 4l8 8M12 4l-8 8"/></svg>';
|
|
53
54
|
const ICON_REFRESH = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 8a5.5 5.5 0 019.2-4M13.5 8a5.5 5.5 0 01-9.2 4"/><path d="M11.5 2v2.5H14M4.5 14v-2.5H2"/></svg>';
|
|
54
55
|
const ICON_HEART = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 13.7C4.3 11 2 8.7 2 6.3A3.3 3.3 0 018 4.6a3.3 3.3 0 016 1.7c0 2.4-2.3 4.7-6 7.4z"/></svg>';
|
|
55
56
|
const ICON_HEART_FILL = '<svg viewBox="0 0 16 16" fill="currentColor" stroke="none"><path d="M8 13.7C4.3 11 2 8.7 2 6.3A3.3 3.3 0 018 4.6a3.3 3.3 0 016 1.7c0 2.4-2.3 4.7-6 7.4z"/></svg>';
|
|
@@ -388,13 +389,13 @@ function wirePanel() {
|
|
|
388
389
|
header.addEventListener('mousedown', (e) => {
|
|
389
390
|
if (e.target.closest('button')) return;
|
|
390
391
|
_dragging = true;
|
|
391
|
-
_panel.classList.add('dragging');
|
|
392
|
-
const rect = _panel.getBoundingClientRect();
|
|
393
|
-
_dragOff = { x: e.clientX - rect.left, y: e.clientY - rect.top };
|
|
394
|
-
_pendingDrag = null;
|
|
395
|
-
e.preventDefault();
|
|
396
|
-
});
|
|
397
|
-
}
|
|
392
|
+
_panel.classList.add('dragging');
|
|
393
|
+
const rect = _panel.getBoundingClientRect();
|
|
394
|
+
_dragOff = { x: e.clientX - rect.left, y: e.clientY - rect.top };
|
|
395
|
+
_pendingDrag = null;
|
|
396
|
+
e.preventDefault();
|
|
397
|
+
});
|
|
398
|
+
}
|
|
398
399
|
|
|
399
400
|
// Keyboard in lightbox
|
|
400
401
|
document.addEventListener('keydown', handleKey);
|
|
@@ -425,24 +426,26 @@ function openPanel() {
|
|
|
425
426
|
_panel.innerHTML = buildPanelHTML();
|
|
426
427
|
document.body.appendChild(_panel);
|
|
427
428
|
|
|
428
|
-
|
|
429
|
-
|
|
429
|
+
// Centred in the app frame
|
|
430
|
+
const at = centeredInFrame(780, 560);
|
|
431
|
+
_panel.style.left = at.left + 'px';
|
|
432
|
+
_panel.style.top = at.top + 'px';
|
|
430
433
|
|
|
431
434
|
wirePanel();
|
|
432
435
|
isVisible = true;
|
|
433
436
|
refreshImages();
|
|
434
437
|
|
|
435
|
-
// Global mouse handlers for drag
|
|
436
|
-
const onMouseMove = (e) => {
|
|
437
|
-
if (!_dragging) return;
|
|
438
|
-
scheduleDragPosition(e.clientX - _dragOff.x, e.clientY - _dragOff.y);
|
|
439
|
-
};
|
|
440
|
-
const onMouseUp = () => {
|
|
441
|
-
if (!_dragging) return;
|
|
442
|
-
_dragging = false;
|
|
443
|
-
flushDragPosition();
|
|
444
|
-
if (_panel) _panel.classList.remove('dragging');
|
|
445
|
-
};
|
|
438
|
+
// Global mouse handlers for drag
|
|
439
|
+
const onMouseMove = (e) => {
|
|
440
|
+
if (!_dragging) return;
|
|
441
|
+
scheduleDragPosition(e.clientX - _dragOff.x, e.clientY - _dragOff.y);
|
|
442
|
+
};
|
|
443
|
+
const onMouseUp = () => {
|
|
444
|
+
if (!_dragging) return;
|
|
445
|
+
_dragging = false;
|
|
446
|
+
flushDragPosition();
|
|
447
|
+
if (_panel) _panel.classList.remove('dragging');
|
|
448
|
+
};
|
|
446
449
|
document.addEventListener('mousemove', onMouseMove);
|
|
447
450
|
document.addEventListener('mouseup', onMouseUp);
|
|
448
451
|
|
|
@@ -26,7 +26,7 @@ let _recording = null; // { actionId, originalCombo } when recording
|
|
|
26
26
|
let _pendingBindings = null; // working copy during modal editing
|
|
27
27
|
let _modalOpen = false;
|
|
28
28
|
// Actions that were removed ("toggle-toolbar" was "Hide all toolbars"): a saved key for one is dropped on load.
|
|
29
|
-
const RETIRED_ACTIONS = ['toggle-toolbar'];
|
|
29
|
+
const RETIRED_ACTIONS = ['toggle-toolbar', 'toggle-minimap'];
|
|
30
30
|
|
|
31
31
|
// ── Combo building ──
|
|
32
32
|
|
|
@@ -94,6 +94,31 @@ export function getBinding(actionId) {
|
|
|
94
94
|
return _bindings[actionId] || null;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
/** The key an action is bound to as a menu shows it, or '' while it has none (the context menu, read at each open). */
|
|
98
|
+
export function getShortcutLabel(actionId) {
|
|
99
|
+
const combo = _bindings[actionId];
|
|
100
|
+
return combo ? comboToDisplay(combo) : '';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Whether a module registered an action with this id. */
|
|
104
|
+
export function hasAction(actionId) {
|
|
105
|
+
return _actions.has(actionId);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** The action a key press is bound to, or null (a key the user bound stays that action, Shift+F10 included). */
|
|
109
|
+
export function actionForKey(e) {
|
|
110
|
+
const combo = buildCombo(e);
|
|
111
|
+
return (combo && _reverseMap.get(combo)) || null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Run a registered action as its key would. False when nothing registered it. */
|
|
115
|
+
export function runAction(actionId) {
|
|
116
|
+
const handler = _actions.get(actionId);
|
|
117
|
+
if (!handler) return false;
|
|
118
|
+
handler();
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
97
122
|
// ── Central dispatcher ──
|
|
98
123
|
|
|
99
124
|
function centralKeyHandler(e) {
|
|
@@ -12,12 +12,12 @@ import { openHelp } from './ui-help.js';
|
|
|
12
12
|
import { armPwaInstallHandoff, initPwaInstall, installGuideUrl, isStandalone, requestPwaInstall } from './pwa-install.js';
|
|
13
13
|
import { registerAction } from './ui-keybinds.js';
|
|
14
14
|
import { isGuest, hasPermission } from './ui-sync.js';
|
|
15
|
-
import { sendToPanel } from './ui-claude-panel.js';
|
|
16
15
|
import { forceCheckToolUpdates, showUpdateToast, TOOL_LABELS } from './ui-tool-updates.js';
|
|
17
16
|
import { forceCheckSynabunUpdate, openSynabunUpdateModal, synabunUpdateSourceLabel } from './ui-update.js';
|
|
18
17
|
import { requestServerRestart } from './ui-loading.js';
|
|
19
18
|
import { desktopBridge, isDesktopApp } from './desktop-bridge.js';
|
|
20
19
|
import { t } from './i18n.js';
|
|
20
|
+
import { frameRect } from './app-frame.js';
|
|
21
21
|
|
|
22
22
|
const $ = (id) => document.getElementById(id);
|
|
23
23
|
|
|
@@ -221,7 +221,7 @@ function fitDropdown(item) {
|
|
|
221
221
|
dropdown.style.maxHeight = '';
|
|
222
222
|
dropdown.classList.remove('menubar-dropdown--scroll');
|
|
223
223
|
const top = item.getBoundingClientRect().bottom + 14;
|
|
224
|
-
const room = Math.floor(
|
|
224
|
+
const room = Math.floor(frameRect().bottom - top - 12); // down to the app frame's bottom edge
|
|
225
225
|
if (room > 120 && dropdown.scrollHeight > room) {
|
|
226
226
|
dropdown.style.maxHeight = room + 'px';
|
|
227
227
|
dropdown.classList.add('menubar-dropdown--scroll');
|
|
@@ -278,12 +278,6 @@ function wireSubmenus() {
|
|
|
278
278
|
sync();
|
|
279
279
|
});
|
|
280
280
|
window.addEventListener('resize', () => { if (openSub) placeSubmenu(openSub.parent, openSub.panel); });
|
|
281
|
-
// The tour shows a submenu by name (ui-tutorial.js showStage); null closes it.
|
|
282
|
-
on('menubar:submenu', (name) => {
|
|
283
|
-
const row = name ? [...SUBMENUS.keys()].find(r => r.dataset.submenu === name) : null;
|
|
284
|
-
if (row && !row.hidden) openSubmenu(row);
|
|
285
|
-
else closeSubmenu();
|
|
286
|
-
});
|
|
287
281
|
}
|
|
288
282
|
|
|
289
283
|
function openSubmenu(row, { focusFirst = false } = {}) {
|
|
@@ -377,8 +371,9 @@ function submenuEntries(panel) {
|
|
|
377
371
|
.filter(el => !el.hidden && !el.classList.contains('disabled') && getComputedStyle(el).display !== 'none');
|
|
378
372
|
}
|
|
379
373
|
|
|
380
|
-
// Right of the dropdown with its first entry level with the row; on the left when the
|
|
381
|
-
// on the right, and kept inside the
|
|
374
|
+
// Right of the dropdown with its first entry level with the row; on the left when the app frame has no room
|
|
375
|
+
// on the right, and kept inside its right and bottom edges (the menu hangs from the bar, which is outside the
|
|
376
|
+
// frame, so its left stays the window's). The dropdown's laid-out place (offsetTop/Left) is what its
|
|
382
377
|
// drop-in animation does not move, so a submenu opened together with the menu (the tour) lines up too.
|
|
383
378
|
function placeSubmenu(row, panel) {
|
|
384
379
|
const dropdown = row.parentElement, host = panel.parentElement;
|
|
@@ -386,9 +381,10 @@ function placeSubmenu(row, panel) {
|
|
|
386
381
|
const first = submenuEntries(panel)[0];
|
|
387
382
|
const lead = first ? first.getBoundingClientRect().top - panelBox.top : 0;
|
|
388
383
|
const top = dropdown.offsetTop + row.getBoundingClientRect().top - dropdown.getBoundingClientRect().top - lead;
|
|
384
|
+
const f = frameRect();
|
|
389
385
|
let left = dropdown.offsetLeft + dropdown.offsetWidth + SUBMENU_GAP;
|
|
390
|
-
if (hostBox.left + left + panelBox.width >
|
|
391
|
-
const maxTop =
|
|
386
|
+
if (hostBox.left + left + panelBox.width > f.right - VIEWPORT_MARGIN) left = dropdown.offsetLeft - SUBMENU_GAP - panelBox.width;
|
|
387
|
+
const maxTop = f.bottom - VIEWPORT_MARGIN - panelBox.height - hostBox.top;
|
|
392
388
|
panel.style.left = `${Math.max(VIEWPORT_MARGIN - hostBox.left, left)}px`;
|
|
393
389
|
panel.style.top = `${Math.max(VIEWPORT_MARGIN - hostBox.top, Math.min(top, maxTop))}px`;
|
|
394
390
|
}
|
|
@@ -611,7 +607,6 @@ function wireTerminalMenu() {
|
|
|
611
607
|
'menu-terminal-discord': () => emit('browser:open', { url: 'https://discord.com/app' }),
|
|
612
608
|
'menu-terminal-x': () => emit('browser:open', { url: 'https://x.com' }),
|
|
613
609
|
'menu-terminal-whatsapp': () => emit('browser:open', { url: 'https://web.whatsapp.com' }),
|
|
614
|
-
'menu-app-leonardo': () => { emit('browser:open', { url: 'https://app.leonardo.ai' }); emit('leonardo:launch'); },
|
|
615
610
|
'menu-open-styleguide': () => emit('styleguide:open'),
|
|
616
611
|
'menu-command-runner': () => emit('command-runner:open'),
|
|
617
612
|
'menu-terminal-link': () => emit('link:toggle'),
|
|
@@ -645,11 +640,6 @@ function wireTerminalMenu() {
|
|
|
645
640
|
if (el) el.addEventListener('click', () => { closeAll(); handler(); });
|
|
646
641
|
});
|
|
647
642
|
|
|
648
|
-
// Leonardo.AI — open panel with /leonardo skill after browser launches
|
|
649
|
-
on('leonardo:launch', () => {
|
|
650
|
-
setTimeout(() => sendToPanel('/leonardo', { newTab: true, tabLabel: 'Leonardo.AI', autoSubmit: true }), 500);
|
|
651
|
-
});
|
|
652
|
-
|
|
653
643
|
// Keyboard shortcuts: toggle terminal (via central keybinds)
|
|
654
644
|
registerAction('toggle-terminal', () => emit('terminal:toggle'));
|
|
655
645
|
registerAction('toggle-terminal-alt', () => emit('terminal:toggle'));
|
|
@@ -3,6 +3,11 @@ export function isNewerRunDescriptor(next, current, terminalStatuses) {
|
|
|
3
3
|
const nextTerminal = terminalStatuses.has(next.status);
|
|
4
4
|
const currentTerminal = terminalStatuses.has(current.status);
|
|
5
5
|
if (currentTerminal !== nextTerminal) return nextTerminal;
|
|
6
|
+
// A run resumed after a server restart (`resumes` only grows) is newer whatever its version: a crash can lose the
|
|
7
|
+
// last ledger writes, and with them versions a page already saw.
|
|
8
|
+
const nextResumes = Number(next.resumes) || 0;
|
|
9
|
+
const currentResumes = Number(current.resumes) || 0;
|
|
10
|
+
if (nextResumes !== currentResumes) return nextResumes > currentResumes;
|
|
6
11
|
const nextVersion = Number(next.version) || 0;
|
|
7
12
|
const currentVersion = Number(current.version) || 0;
|
|
8
13
|
if (nextVersion !== currentVersion) return nextVersion > currentVersion;
|
|
@@ -13,7 +13,10 @@ import {
|
|
|
13
13
|
const DISMISSED_KEY = 'synabun-native-loop-dismissed';
|
|
14
14
|
const CLAIM_TTL_MS = 90_000;
|
|
15
15
|
const TERMINAL_RESTORE_LIMIT = 10;
|
|
16
|
+
// 'suspended' is not among them: a dispatched worker a server restart cut off keeps its tab until the next start
|
|
17
|
+
// resumes it (or ends it as interrupted).
|
|
16
18
|
const TERMINAL_STATUSES = new Set(['completed', 'failed', 'stopped', 'interrupted']);
|
|
19
|
+
const LIVE_STATUSES = new Set(['starting', 'running', 'suspended']);
|
|
17
20
|
const _windowId = nativeLoopWindowId;
|
|
18
21
|
|
|
19
22
|
const _attached = new Map();
|
|
@@ -355,7 +358,7 @@ async function reconcileRuns() {
|
|
|
355
358
|
const newestFirst = (data.runs || [])
|
|
356
359
|
.filter(hasIdentity)
|
|
357
360
|
.sort((a, b) => String(b.updatedAt || b.startedAt || '').localeCompare(String(a.updatedAt || a.startedAt || '')));
|
|
358
|
-
const activeRuns = newestFirst.filter((run) =>
|
|
361
|
+
const activeRuns = newestFirst.filter((run) => LIVE_STATUSES.has(run.status));
|
|
359
362
|
const terminalRuns = newestFirst.filter((run) => {
|
|
360
363
|
if (!TERMINAL_STATUSES.has(run.status)) return false;
|
|
361
364
|
if (new Date(run.updatedAt || run.startedAt || 0).getTime() < cutoff) return false;
|
|
@@ -403,6 +406,9 @@ export function initNativeLoopRouter() {
|
|
|
403
406
|
on('sync:sidepanel:run-completed', route);
|
|
404
407
|
on('sync:sidepanel:run-failed', route);
|
|
405
408
|
on('sync:sidepanel:run-stopped', route);
|
|
409
|
+
// The sync socket (re)connected (ui-sync.js 'connected'): after a server restart the runs are read again at once,
|
|
410
|
+
// not at the next 30 s heartbeat, so a tab whose run was suspended sees it resume (or end) as soon as it can.
|
|
411
|
+
on('session:info', () => { scheduleReconcile(); });
|
|
406
412
|
on('sync:sidepanel:provider-event', (message) => {
|
|
407
413
|
// An OpenCode worker's panel streams from its own serve: the sync copy of its tool calls is the Assistant's.
|
|
408
414
|
if (message?.event?.provider === 'opencode') return;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { initDetachedAgentSessions } from './ui-sidepanel-sessions.js';
|
|
2
2
|
// ═══════════════════════════════════════════
|
|
3
3
|
// SynaBun Neural Interface — Navbar
|
|
4
|
-
// Initializes
|
|
4
|
+
// Initializes right-side icon buttons and menubar action buttons. The memory map is 3D only.
|
|
5
5
|
// Menu items (View, Graph, Bookmarks, Layouts) are handled by ui-menubar.js.
|
|
6
6
|
// ═══════════════════════════════════════════
|
|
7
7
|
|
|
8
8
|
import { state, emit, on } from './state.js';
|
|
9
|
-
import { getVariant } from './registry.js';
|
|
10
9
|
import { KEYS } from './constants.js';
|
|
11
10
|
import { storage } from './storage.js';
|
|
12
11
|
import { t } from './i18n.js';
|
|
@@ -23,6 +22,7 @@ import { toggleImageGallery } from './ui-image-gallery.js';
|
|
|
23
22
|
import { toggleScheduleQueue } from './ui-schedule-queue.js';
|
|
24
23
|
import { initUpdate } from './ui-update.js';
|
|
25
24
|
import { initToolUpdates } from './ui-tool-updates.js';
|
|
25
|
+
import { initCrashNotice } from './ui-crash-notice.js';
|
|
26
26
|
import { initSidepanelTrayPlaceholders } from './ui-sidepanel-tray.js';
|
|
27
27
|
import { initDesktopTitleBar } from './desktop-titlebar.js';
|
|
28
28
|
|
|
@@ -30,28 +30,6 @@ const $ = (id) => document.getElementById(id);
|
|
|
30
30
|
|
|
31
31
|
export function initNavbar() {
|
|
32
32
|
initDetachedAgentSessions();
|
|
33
|
-
const variant = getVariant() || '3d';
|
|
34
|
-
|
|
35
|
-
// ── View toggle ──
|
|
36
|
-
const nav2d = $('nav-2d-link');
|
|
37
|
-
const nav3d = $('nav-3d-link');
|
|
38
|
-
|
|
39
|
-
const activeLink = variant === '3d' ? nav3d : nav2d;
|
|
40
|
-
const inactiveLink = variant === '3d' ? nav2d : nav3d;
|
|
41
|
-
|
|
42
|
-
if (activeLink) {
|
|
43
|
-
activeLink.addEventListener('click', (e) => e.preventDefault());
|
|
44
|
-
}
|
|
45
|
-
if (inactiveLink) {
|
|
46
|
-
inactiveLink.addEventListener('click', (e) => {
|
|
47
|
-
e.preventDefault();
|
|
48
|
-
if (state.selectedNodeId) {
|
|
49
|
-
sessionStorage.setItem(KEYS.SELECTED_SWITCH, state.selectedNodeId);
|
|
50
|
-
}
|
|
51
|
-
window.location.href = inactiveLink.getAttribute('href');
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
33
|
// ── Claude panel toggle (topright workspace toolbar) ──
|
|
56
34
|
const assistantPanelBtn = $('topright-assistant-panel-btn');
|
|
57
35
|
const claudePanelBtn = $('topright-claude-panel-btn');
|
|
@@ -380,4 +358,6 @@ export function initNavbar() {
|
|
|
380
358
|
// ── Update alert ──
|
|
381
359
|
initUpdate();
|
|
382
360
|
initToolUpdates();
|
|
361
|
+
// ── The notice after an automatic restart (the server crashed and its supervisor started it again) ──
|
|
362
|
+
initCrashNotice();
|
|
383
363
|
}
|