synabun 1.3.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 +665 -0
- package/LICENSE +191 -0
- package/README.md +853 -0
- package/hooks/claude-code/post-plan.mjs +391 -0
- package/hooks/claude-code/post-remember.mjs +239 -0
- package/hooks/claude-code/pre-compact.mjs +241 -0
- package/hooks/claude-code/pre-websearch.mjs +90 -0
- package/hooks/claude-code/prompt-submit.mjs +861 -0
- package/hooks/claude-code/session-start.mjs +494 -0
- package/hooks/claude-code/shared.mjs +368 -0
- package/hooks/claude-code/stop.mjs +646 -0
- package/hooks/claude-code/test-user-learning.mjs +531 -0
- package/mcp-server/package.json +38 -0
- package/mcp-server/run.mjs +10 -0
- package/mcp-server/src/config.ts +70 -0
- package/mcp-server/src/http.ts +93 -0
- package/mcp-server/src/index.ts +203 -0
- package/mcp-server/src/preload-http.ts +25 -0
- package/mcp-server/src/preload.ts +29 -0
- package/mcp-server/src/scripts/migrate-qdrant-to-sqlite.ts +506 -0
- package/mcp-server/src/services/categories.ts +429 -0
- package/mcp-server/src/services/discord.ts +702 -0
- package/mcp-server/src/services/file-checksums.ts +33 -0
- package/mcp-server/src/services/local-embeddings.ts +77 -0
- package/mcp-server/src/services/neural-interface.ts +344 -0
- package/mcp-server/src/services/sqlite.ts +823 -0
- package/mcp-server/src/tools/browser-advanced.ts +123 -0
- package/mcp-server/src/tools/browser-interact.ts +255 -0
- package/mcp-server/src/tools/browser-navigate.ts +77 -0
- package/mcp-server/src/tools/browser-observe.ts +1330 -0
- package/mcp-server/src/tools/browser.ts +107 -0
- package/mcp-server/src/tools/card-tools.ts +193 -0
- package/mcp-server/src/tools/card.ts +22 -0
- package/mcp-server/src/tools/category.ts +379 -0
- package/mcp-server/src/tools/discord-channel.ts +274 -0
- package/mcp-server/src/tools/discord-guild.ts +188 -0
- package/mcp-server/src/tools/discord-member.ts +158 -0
- package/mcp-server/src/tools/discord-message.ts +231 -0
- package/mcp-server/src/tools/discord-onboarding.ts +228 -0
- package/mcp-server/src/tools/discord-role.ts +209 -0
- package/mcp-server/src/tools/discord-thread.ts +110 -0
- package/mcp-server/src/tools/discord-webhook.ts +176 -0
- package/mcp-server/src/tools/discord.ts +40 -0
- package/mcp-server/src/tools/forget.ts +38 -0
- package/mcp-server/src/tools/git-tools.ts +141 -0
- package/mcp-server/src/tools/git.ts +13 -0
- package/mcp-server/src/tools/image-tools.ts +98 -0
- package/mcp-server/src/tools/image.ts +17 -0
- package/mcp-server/src/tools/leonardo-browser-tools.ts +281 -0
- package/mcp-server/src/tools/leonardo.ts +28 -0
- package/mcp-server/src/tools/loop.ts +348 -0
- package/mcp-server/src/tools/memories.ts +118 -0
- package/mcp-server/src/tools/recall.ts +323 -0
- package/mcp-server/src/tools/reflect.ts +145 -0
- package/mcp-server/src/tools/remember.ts +115 -0
- package/mcp-server/src/tools/response.ts +26 -0
- package/mcp-server/src/tools/restore.ts +34 -0
- package/mcp-server/src/tools/sync.ts +114 -0
- package/mcp-server/src/tools/tictactoe-tools.ts +98 -0
- package/mcp-server/src/tools/tictactoe.ts +13 -0
- package/mcp-server/src/tools/utils.ts +25 -0
- package/mcp-server/src/tools/whiteboard-tools.ts +260 -0
- package/mcp-server/src/tools/whiteboard.ts +22 -0
- package/mcp-server/src/tui.ts +940 -0
- package/mcp-server/src/types.ts +85 -0
- package/mcp-server/tsconfig.json +19 -0
- package/neural-interface/package.json +27 -0
- package/neural-interface/public/apple-touch-icon.png +0 -0
- package/neural-interface/public/category-logos/claude.svg +1 -0
- package/neural-interface/public/category-logos/gemini-color.svg +1 -0
- package/neural-interface/public/category-logos/openai.svg +1 -0
- package/neural-interface/public/category-logos/synabun.png +0 -0
- package/neural-interface/public/claude-chat.css +878 -0
- package/neural-interface/public/claude-chat.html +92 -0
- package/neural-interface/public/claude-chat.js +1168 -0
- package/neural-interface/public/favicon-16x16.png +0 -0
- package/neural-interface/public/favicon-32x32.png +0 -0
- package/neural-interface/public/gallery.svg +6 -0
- package/neural-interface/public/icon-192.png +0 -0
- package/neural-interface/public/icon-512.png +0 -0
- package/neural-interface/public/index-legacy.html +14677 -0
- package/neural-interface/public/index.html +212 -0
- package/neural-interface/public/index2d-legacy.html +8193 -0
- package/neural-interface/public/index2d.html +127 -0
- package/neural-interface/public/invite.html +351 -0
- package/neural-interface/public/leonardoai.svg +1 -0
- package/neural-interface/public/logo-synabun.png +0 -0
- package/neural-interface/public/logoHD.png +0 -0
- package/neural-interface/public/manifest.json +14 -0
- package/neural-interface/public/offline.html +299 -0
- package/neural-interface/public/onboarding.html +2335 -0
- package/neural-interface/public/openclaw-logo-text.png +0 -0
- package/neural-interface/public/pin-svgrepo-com.svg +25 -0
- package/neural-interface/public/sessionicon.svg +8 -0
- package/neural-interface/public/shared/ansi-parser.js +305 -0
- package/neural-interface/public/shared/api.js +1043 -0
- package/neural-interface/public/shared/colors.js +153 -0
- package/neural-interface/public/shared/constants.js +141 -0
- package/neural-interface/public/shared/html-shell.js +777 -0
- package/neural-interface/public/shared/html-term-renderer.js +1022 -0
- package/neural-interface/public/shared/i18n.js +147 -0
- package/neural-interface/public/shared/registry.js +82 -0
- package/neural-interface/public/shared/state.js +86 -0
- package/neural-interface/public/shared/storage.js +150 -0
- package/neural-interface/public/shared/styles.css +21212 -0
- package/neural-interface/public/shared/ui-automation-studio.js +3573 -0
- package/neural-interface/public/shared/ui-bookmarks.js +231 -0
- package/neural-interface/public/shared/ui-claude-panel.js +6333 -0
- package/neural-interface/public/shared/ui-command-runner.js +534 -0
- package/neural-interface/public/shared/ui-cost-widget.js +602 -0
- package/neural-interface/public/shared/ui-detail.js +1454 -0
- package/neural-interface/public/shared/ui-explorer.js +1356 -0
- package/neural-interface/public/shared/ui-file-explorer.js +2750 -0
- package/neural-interface/public/shared/ui-games.js +411 -0
- package/neural-interface/public/shared/ui-help.js +107 -0
- package/neural-interface/public/shared/ui-image-gallery.js +461 -0
- package/neural-interface/public/shared/ui-invite.js +519 -0
- package/neural-interface/public/shared/ui-keybinds.js +452 -0
- package/neural-interface/public/shared/ui-layouts.js +297 -0
- package/neural-interface/public/shared/ui-link.js +731 -0
- package/neural-interface/public/shared/ui-loading.js +255 -0
- package/neural-interface/public/shared/ui-menubar.js +499 -0
- package/neural-interface/public/shared/ui-multiselect.js +93 -0
- package/neural-interface/public/shared/ui-navbar.js +222 -0
- package/neural-interface/public/shared/ui-notifications.js +287 -0
- package/neural-interface/public/shared/ui-panels.js +309 -0
- package/neural-interface/public/shared/ui-resume.js +653 -0
- package/neural-interface/public/shared/ui-search.js +145 -0
- package/neural-interface/public/shared/ui-sessions.js +531 -0
- package/neural-interface/public/shared/ui-settings.js +5987 -0
- package/neural-interface/public/shared/ui-sidebar.js +1905 -0
- package/neural-interface/public/shared/ui-skills.js +2805 -0
- package/neural-interface/public/shared/ui-stats.js +38 -0
- package/neural-interface/public/shared/ui-sync.js +201 -0
- package/neural-interface/public/shared/ui-terminal.js +6385 -0
- package/neural-interface/public/shared/ui-tooltip.js +123 -0
- package/neural-interface/public/shared/ui-trash.js +439 -0
- package/neural-interface/public/shared/ui-tutorial-draw.js +875 -0
- package/neural-interface/public/shared/ui-tutorial-steps.js +2276 -0
- package/neural-interface/public/shared/ui-tutorial.js +1117 -0
- package/neural-interface/public/shared/ui-update.js +244 -0
- package/neural-interface/public/shared/ui-whiteboard.js +3262 -0
- package/neural-interface/public/shared/ui-workspaces.js +722 -0
- package/neural-interface/public/shared/utils.js +360 -0
- package/neural-interface/public/shared/vterm-buffer.js +1102 -0
- package/neural-interface/public/sw.js +52 -0
- package/neural-interface/public/synabun.png +0 -0
- package/neural-interface/public/toolbar-album.svg +8 -0
- package/neural-interface/public/toolbar-question.svg +6 -0
- package/neural-interface/public/toolbar-sessions.svg +6 -0
- package/neural-interface/public/variant/2d/background.js +113 -0
- package/neural-interface/public/variant/2d/context-menu.js +133 -0
- package/neural-interface/public/variant/2d/gfx.js +45 -0
- package/neural-interface/public/variant/2d/graph.js +1635 -0
- package/neural-interface/public/variant/2d/hulls.js +207 -0
- package/neural-interface/public/variant/2d/lasso.js +135 -0
- package/neural-interface/public/variant/2d/layout.js +594 -0
- package/neural-interface/public/variant/2d/main.js +521 -0
- package/neural-interface/public/variant/2d/minimap.js +312 -0
- package/neural-interface/public/variant/2d/settings-gfx.js +98 -0
- package/neural-interface/public/variant/3d/background.js +884 -0
- package/neural-interface/public/variant/3d/camera.js +661 -0
- package/neural-interface/public/variant/3d/gfx.js +116 -0
- package/neural-interface/public/variant/3d/graph.js +2399 -0
- package/neural-interface/public/variant/3d/main.js +500 -0
- package/neural-interface/public/variant/3d/settings-gfx.js +228 -0
- package/neural-interface/scripts/rebuild-pty.js +100 -0
- package/neural-interface/server.js +15000 -0
- package/neural-interface/templates/CLAUDE-template.md +211 -0
- package/package.json +53 -0
- package/postinstall.js +135 -0
- package/setup.js +260 -0
- package/skills/leonardo/SKILL.md +159 -0
- package/skills/leonardo/icon.svg +1 -0
- package/skills/leonardo/modules/browser-guide.md +378 -0
- package/skills/leonardo/modules/image-prompter.md +277 -0
- package/skills/leonardo/modules/model-advisor.md +100 -0
- package/skills/leonardo/modules/prompt-library.md +110 -0
- package/skills/leonardo/modules/style-guide.md +186 -0
- package/skills/leonardo/modules/video-prompter.md +311 -0
- package/skills/synabun/SKILL.md +185 -0
- package/skills/synabun/icon.png +0 -0
- package/skills/synabun/modules/audit.md +374 -0
- package/skills/synabun/modules/changelog.md +194 -0
- package/skills/synabun/modules/idea.md +144 -0
- package/skills/synabun/modules/memorize.md +188 -0
- package/skills/synabun/synabunicon.png +0 -0
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Neural Interface — 3D Variant Entry Point
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// Registers the 3D variant, imports all shared & variant modules,
|
|
6
|
+
// wires event listeners, and boots the application.
|
|
7
|
+
|
|
8
|
+
// ── Storage (self-hydrating — importing it populates the cache) ──
|
|
9
|
+
import { storage } from '../../shared/storage.js';
|
|
10
|
+
|
|
11
|
+
// ── Shared foundation ──
|
|
12
|
+
import { state, emit, on } from '../../shared/state.js';
|
|
13
|
+
import { registerVariant, registerMenuItem, registerHelpSection } from '../../shared/registry.js';
|
|
14
|
+
import { fetchMemories } from '../../shared/api.js';
|
|
15
|
+
import { normalizeNodes } from '../../shared/utils.js';
|
|
16
|
+
import { injectSharedHTML } from '../../shared/html-shell.js';
|
|
17
|
+
import { KEYS } from '../../shared/constants.js';
|
|
18
|
+
import { initI18n, t } from '../../shared/i18n.js';
|
|
19
|
+
|
|
20
|
+
// ── Shared UI modules (side-effect: each registers its own event listeners) ──
|
|
21
|
+
import { initTooltip } from '../../shared/ui-tooltip.js';
|
|
22
|
+
import { initPanelSystem, initPinToggle, clampPanelsToViewport } from '../../shared/ui-panels.js';
|
|
23
|
+
import { initLoading, showLoadingError, hideLoading } from '../../shared/ui-loading.js';
|
|
24
|
+
import { initNavbar } from '../../shared/ui-navbar.js';
|
|
25
|
+
import { initMenubar } from '../../shared/ui-menubar.js';
|
|
26
|
+
import { initSearch } from '../../shared/ui-search.js';
|
|
27
|
+
import { buildCategorySidebar, initSidebar, preloadCategoryLogos, loadCategories } from '../../shared/ui-sidebar.js';
|
|
28
|
+
import { openMemoryCard, restoreOpenCards, initDetailPanel, setDetailCallbacks } from '../../shared/ui-detail.js';
|
|
29
|
+
import { initSettings, restoreInterfaceConfig, restoreSkin, loadIfaceConfig } from '../../shared/ui-settings.js';
|
|
30
|
+
import { initTrash } from '../../shared/ui-trash.js';
|
|
31
|
+
import { initBookmarks } from '../../shared/ui-bookmarks.js';
|
|
32
|
+
import { initResume } from '../../shared/ui-resume.js';
|
|
33
|
+
import { initLayouts, registerBuiltinPresets } from '../../shared/ui-layouts.js';
|
|
34
|
+
import { initHelp } from '../../shared/ui-help.js';
|
|
35
|
+
import { initMultiSelect } from '../../shared/ui-multiselect.js';
|
|
36
|
+
import { updateStats, initStats } from '../../shared/ui-stats.js';
|
|
37
|
+
import { initExplorer } from '../../shared/ui-explorer.js';
|
|
38
|
+
import { initFileExplorer } from '../../shared/ui-file-explorer.js';
|
|
39
|
+
import { initSkillsStudio } from '../../shared/ui-skills.js';
|
|
40
|
+
import { initTerminal } from '../../shared/ui-terminal.js';
|
|
41
|
+
import { initLink } from '../../shared/ui-link.js';
|
|
42
|
+
import { initWhiteboard } from '../../shared/ui-whiteboard.js';
|
|
43
|
+
import { initCostWidget } from '../../shared/ui-cost-widget.js';
|
|
44
|
+
import { initGames, clearGameOnLoad } from '../../shared/ui-games.js';
|
|
45
|
+
import { initWorkspaces } from '../../shared/ui-workspaces.js';
|
|
46
|
+
import { initInvite } from '../../shared/ui-invite.js';
|
|
47
|
+
import { initSync } from '../../shared/ui-sync.js';
|
|
48
|
+
import { initKeybinds } from '../../shared/ui-keybinds.js';
|
|
49
|
+
import { initTutorial } from '../../shared/ui-tutorial.js';
|
|
50
|
+
import { initImageGallery } from '../../shared/ui-image-gallery.js';
|
|
51
|
+
|
|
52
|
+
// ── 3D variant modules ──
|
|
53
|
+
import { gfx } from './gfx.js';
|
|
54
|
+
import { setGraphicsHooks } from './settings-gfx.js';
|
|
55
|
+
import { initAutomationStudio } from '../../shared/ui-automation-studio.js';
|
|
56
|
+
import { initCommandRunner } from '../../shared/ui-command-runner.js';
|
|
57
|
+
import { initCamera, updateCameraMovement, animateCameraToNode, frameCameraToExtent, saveCameraState, restoreCameraState, pauseCamera, resumeCamera } from './camera.js';
|
|
58
|
+
import { applyFloorStyle, applyBgTheme, animateBackground } from './background.js';
|
|
59
|
+
import {
|
|
60
|
+
initGraph, getGraph, getBloomPass, applyGraphData,
|
|
61
|
+
preloadCategoryLogos as preloadGraphLogos,
|
|
62
|
+
applyLinkVisibility, setLinkMode, setLinkTypeFilter,
|
|
63
|
+
navigateToNode, scheduleGraphRemoval, cancelScheduledRemoval,
|
|
64
|
+
saveNodePositions, clearSavedPositions, resetLayout,
|
|
65
|
+
setBloomParams, setBloomEnabled, stopAnimation, startAnimation,
|
|
66
|
+
pauseInteraction, resumeInteraction,
|
|
67
|
+
} from './graph.js';
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
// ═══════════════════════════════════════════
|
|
71
|
+
// 1. REGISTER VARIANT
|
|
72
|
+
// ═══════════════════════════════════════════
|
|
73
|
+
|
|
74
|
+
registerVariant({
|
|
75
|
+
variant: '3d',
|
|
76
|
+
capabilities: ['camera-hud', 'controls-panel', 'bloom', 'floor-effects', 'background-theme'],
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
// ═══════════════════════════════════════════
|
|
81
|
+
// 2. REGISTER VARIANT-SPECIFIC MENU ITEMS
|
|
82
|
+
// ═══════════════════════════════════════════
|
|
83
|
+
|
|
84
|
+
registerMenuItem({
|
|
85
|
+
menu: 'view',
|
|
86
|
+
order: 25,
|
|
87
|
+
type: 'toggle',
|
|
88
|
+
id: 'menu-3d-controls',
|
|
89
|
+
label: '3D Controls',
|
|
90
|
+
init: (el) => {
|
|
91
|
+
el.addEventListener('click', () => {
|
|
92
|
+
const panel = document.getElementById('controls-panel');
|
|
93
|
+
if (panel) panel.classList.toggle('visible');
|
|
94
|
+
el.classList.toggle('active', panel?.classList.contains('visible'));
|
|
95
|
+
});
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
// ═══════════════════════════════════════════
|
|
101
|
+
// 3. REGISTER VARIANT HELP SECTION
|
|
102
|
+
// ═══════════════════════════════════════════
|
|
103
|
+
|
|
104
|
+
registerHelpSection({
|
|
105
|
+
order: 50,
|
|
106
|
+
html: `<div class="help-section">
|
|
107
|
+
<div class="help-section-title">3D Navigation</div>
|
|
108
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">W</span><span class="help-key">A</span><span class="help-key">S</span><span class="help-key">D</span></div><span class="help-desc">Move camera</span></div>
|
|
109
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">Q</span><span class="help-key">E</span></div><span class="help-desc">Move camera down / up</span></div>
|
|
110
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">Shift</span></div><span class="help-desc">Boost speed (hold)</span></div>
|
|
111
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">Mouse</span><span class="help-key">+</span><span class="help-key">W</span></div><span class="help-desc">Fly towards look direction</span></div>
|
|
112
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">Drag</span></div><span class="help-desc">Orbit camera</span></div>
|
|
113
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">Scroll</span></div><span class="help-desc">Zoom in / out</span></div>
|
|
114
|
+
</div>`,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
// ═══════════════════════════════════════════
|
|
119
|
+
// 4. LOAD TRANSLATIONS & INJECT SHARED HTML
|
|
120
|
+
// ═══════════════════════════════════════════
|
|
121
|
+
|
|
122
|
+
await initI18n();
|
|
123
|
+
injectSharedHTML();
|
|
124
|
+
|
|
125
|
+
// Provide hooks to the 3D graphics settings tab
|
|
126
|
+
setGraphicsHooks({
|
|
127
|
+
applyBgTheme: (theme) => {
|
|
128
|
+
const g = getGraph();
|
|
129
|
+
const bloom = getBloomPass();
|
|
130
|
+
if (g) applyBgTheme(g, bloom);
|
|
131
|
+
},
|
|
132
|
+
applyFloorStyle: (style) => {
|
|
133
|
+
const g = getGraph();
|
|
134
|
+
if (g) applyFloorStyle(style, g);
|
|
135
|
+
},
|
|
136
|
+
getGraph,
|
|
137
|
+
setBloomEnabled,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
// ═══════════════════════════════════════════
|
|
142
|
+
// 5. WIRE EVENT BUS — connect shared events to variant actions
|
|
143
|
+
// ═══════════════════════════════════════════
|
|
144
|
+
|
|
145
|
+
// When shared UI emits graph:navigate, move camera to node
|
|
146
|
+
on('graph:navigate', ({ node, zoom }) => {
|
|
147
|
+
if (node) navigateToNode(node, { zoom });
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// When shared UI requests data reload (e.g. after OpenClaw bridge sync)
|
|
151
|
+
on('data:reload', async () => {
|
|
152
|
+
try {
|
|
153
|
+
const needLinks = state.linkMode !== 'off';
|
|
154
|
+
const res = await fetch(`/api/memories${needLinks ? '' : '?links=false'}`);
|
|
155
|
+
if (!res.ok) return;
|
|
156
|
+
const data = await res.json();
|
|
157
|
+
state.allNodes = normalizeNodes(data.nodes);
|
|
158
|
+
state.allLinks = data.links;
|
|
159
|
+
|
|
160
|
+
await loadCategories();
|
|
161
|
+
// Preload logos into graph module's own map (sidebar has a separate one)
|
|
162
|
+
const _logoCats = Object.entries(state.categoryMetadata)
|
|
163
|
+
.filter(([, m]) => m.logo)
|
|
164
|
+
.map(([name, m]) => ({ name, logo: m.logo }));
|
|
165
|
+
preloadGraphLogos(_logoCats);
|
|
166
|
+
|
|
167
|
+
const presentCats = new Set(state.allNodes.map(n => n.payload.category));
|
|
168
|
+
state.activeCategories = new Set([...presentCats, ...state.allCategoryNames]);
|
|
169
|
+
|
|
170
|
+
buildCategorySidebar(presentCats);
|
|
171
|
+
applyGraphData();
|
|
172
|
+
updateStats();
|
|
173
|
+
} catch (err) {
|
|
174
|
+
console.error('data:reload failed:', err);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// When categories change, rebuild sidebar and refresh graph
|
|
179
|
+
on('categories-changed', () => {
|
|
180
|
+
// Re-preload logos in case a category logo was added/changed
|
|
181
|
+
const _lc = Object.entries(state.categoryMetadata)
|
|
182
|
+
.filter(([, m]) => m.logo)
|
|
183
|
+
.map(([name, m]) => ({ name, logo: m.logo }));
|
|
184
|
+
preloadGraphLogos(_lc);
|
|
185
|
+
applyGraphData();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// When search applies, refresh graph to show/hide nodes
|
|
189
|
+
on('search:apply', () => {
|
|
190
|
+
applyGraphData();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
on('search:clear', () => {
|
|
194
|
+
applyGraphData();
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Link mode changes
|
|
198
|
+
on('link-mode-changed', (mode) => {
|
|
199
|
+
setLinkMode(mode);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
on('link-type-changed', (filter) => {
|
|
203
|
+
setLinkTypeFilter(filter);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Node selection — zoom camera + open detail card
|
|
207
|
+
on('node-selected', (node) => {
|
|
208
|
+
if (node) {
|
|
209
|
+
animateCameraToNode(node, { zoom: 'close' });
|
|
210
|
+
openMemoryCard(node);
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Graph refresh request (from settings sliders, etc.)
|
|
215
|
+
on('graph:refresh', () => {
|
|
216
|
+
applyGraphData();
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// Per-frame WASD camera movement
|
|
220
|
+
on('camera-tick', () => {
|
|
221
|
+
updateCameraMovement();
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// Animation tick — update background animations
|
|
225
|
+
on('animate-tick', ({ time, graph: g }) => {
|
|
226
|
+
animateBackground(time, g);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// When a category is removed and its nodes should disappear
|
|
230
|
+
on('category:schedule-removal', () => {
|
|
231
|
+
scheduleGraphRemoval();
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
on('category:cancel-removal', () => {
|
|
235
|
+
cancelScheduledRemoval();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Layout commands
|
|
239
|
+
on('layout:reset', () => {
|
|
240
|
+
clearSavedPositions();
|
|
241
|
+
resetLayout();
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
on('layout:frame', (nodes) => {
|
|
245
|
+
frameCameraToExtent(nodes || state.allNodes);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// Stats update
|
|
249
|
+
on('stats-changed', () => {
|
|
250
|
+
updateStats();
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
// ═══════════════════════════════════════════
|
|
255
|
+
// 6. DETAIL PANEL CALLBACKS
|
|
256
|
+
// ═══════════════════════════════════════════
|
|
257
|
+
|
|
258
|
+
setDetailCallbacks({
|
|
259
|
+
navigateToNode: (node) => navigateToNode(node, { zoom: 'close' }),
|
|
260
|
+
refreshGraph: () => applyGraphData(),
|
|
261
|
+
scheduleRemoval: () => scheduleGraphRemoval(),
|
|
262
|
+
cancelRemoval: () => cancelScheduledRemoval(),
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
// ═══════════════════════════════════════════
|
|
267
|
+
// 7. BOOT SEQUENCE
|
|
268
|
+
// ═══════════════════════════════════════════
|
|
269
|
+
|
|
270
|
+
async function boot() {
|
|
271
|
+
try {
|
|
272
|
+
// Restore interface customization + active skin before anything renders
|
|
273
|
+
restoreInterfaceConfig();
|
|
274
|
+
restoreSkin();
|
|
275
|
+
|
|
276
|
+
// Pre-flight health check
|
|
277
|
+
try {
|
|
278
|
+
const healthRes = await fetch('/api/health');
|
|
279
|
+
const health = await healthRes.json();
|
|
280
|
+
if (!health.ok) {
|
|
281
|
+
const messages = {
|
|
282
|
+
db_missing: [t('loading.health.databaseUnreachable.title'), health.detail || t('loading.health.databaseUnreachable.sub')],
|
|
283
|
+
db_error: [t('loading.health.databaseUnreachable.title'), health.detail || t('loading.health.databaseUnreachable.sub')],
|
|
284
|
+
remote_unreachable: [t('loading.health.remoteUnreachable.title'), health.detail || t('loading.health.remoteUnreachable.sub')],
|
|
285
|
+
auth_error: [t('loading.health.authError.title'), health.detail || t('loading.health.authError.sub')],
|
|
286
|
+
};
|
|
287
|
+
const [title, sub] = messages[health.reason] || [t('loading.health.connectionError.title'), health.detail || t('loading.health.connectionError.sub')];
|
|
288
|
+
showLoadingError(title, sub, !!health.canAutoStart);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
} catch {
|
|
292
|
+
// /api/health failed — continue to try /api/memories
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Fetch all memories (skip expensive link computation — loaded on demand)
|
|
296
|
+
const res = await fetch('/api/memories?links=false');
|
|
297
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
298
|
+
const data = await res.json();
|
|
299
|
+
|
|
300
|
+
state.allNodes = normalizeNodes(data.nodes);
|
|
301
|
+
state.allLinks = data.links;
|
|
302
|
+
|
|
303
|
+
// Fetch category definitions
|
|
304
|
+
await loadCategories();
|
|
305
|
+
// Preload logos into graph module's own map (sidebar has a separate one)
|
|
306
|
+
const _logoCats = Object.entries(state.categoryMetadata)
|
|
307
|
+
.filter(([, m]) => m.logo)
|
|
308
|
+
.map(([name, m]) => ({ name, logo: m.logo }));
|
|
309
|
+
preloadGraphLogos(_logoCats);
|
|
310
|
+
|
|
311
|
+
// Discover all categories present
|
|
312
|
+
const presentCats = new Set(state.allNodes.map(n => n.payload.category));
|
|
313
|
+
state.activeCategories = new Set([...presentCats, ...state.allCategoryNames]);
|
|
314
|
+
|
|
315
|
+
// Build category sidebar
|
|
316
|
+
buildCategorySidebar(presentCats);
|
|
317
|
+
|
|
318
|
+
// Init the 3D graph (skip if visualization is disabled or already init'd by viz:toggle)
|
|
319
|
+
const container = document.getElementById('graph-container');
|
|
320
|
+
const vizEnabled = loadIfaceConfig().visualizationEnabled !== false;
|
|
321
|
+
|
|
322
|
+
if (vizEnabled && !getGraph()) {
|
|
323
|
+
initGraph(container, {
|
|
324
|
+
onApplyBgTheme: (theme) => {
|
|
325
|
+
const g = getGraph();
|
|
326
|
+
const bloom = getBloomPass();
|
|
327
|
+
if (g) applyBgTheme(g, bloom);
|
|
328
|
+
},
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
// Init camera controls
|
|
332
|
+
const g = getGraph();
|
|
333
|
+
if (g) initCamera(g);
|
|
334
|
+
|
|
335
|
+
// Apply floor style from saved config
|
|
336
|
+
if (g) applyFloorStyle(gfx.floorStyle || 'grid', g);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Update stats
|
|
340
|
+
updateStats();
|
|
341
|
+
|
|
342
|
+
// Notify shared modules that data is ready
|
|
343
|
+
emit('data-loaded', data);
|
|
344
|
+
|
|
345
|
+
// Restore previously open memory cards (persisted positions)
|
|
346
|
+
restoreOpenCards();
|
|
347
|
+
|
|
348
|
+
// Check for cross-variant node switch
|
|
349
|
+
const switchNodeId = sessionStorage.getItem('neural-selected-node-switch');
|
|
350
|
+
if (switchNodeId) {
|
|
351
|
+
sessionStorage.removeItem('neural-selected-node-switch');
|
|
352
|
+
const switchNode = state.allNodes.find(n => n.id === switchNodeId);
|
|
353
|
+
if (switchNode) {
|
|
354
|
+
state.selectedNodeId = switchNodeId;
|
|
355
|
+
openMemoryCard(switchNode);
|
|
356
|
+
setTimeout(() => navigateToNode(switchNode, { zoom: 'close' }), 500);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Fetch trash count
|
|
361
|
+
try { emit('trash:refresh'); } catch {}
|
|
362
|
+
|
|
363
|
+
// Fade out loading
|
|
364
|
+
hideLoading(400);
|
|
365
|
+
|
|
366
|
+
// Mark boot complete — viz:toggle handler can now respond to user toggles
|
|
367
|
+
_bootComplete = true;
|
|
368
|
+
|
|
369
|
+
} catch (err) {
|
|
370
|
+
console.error('Init error:', err);
|
|
371
|
+
const isNetworkError = err.message === 'Failed to fetch' || err.name === 'TypeError';
|
|
372
|
+
showLoadingError(
|
|
373
|
+
isNetworkError ? t('loading.serverOffline') : t('loading.connectionFailed'),
|
|
374
|
+
isNetworkError ? t('loading.serverNotRunning') : err.message,
|
|
375
|
+
false,
|
|
376
|
+
isNetworkError
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
// ═══════════════════════════════════════════
|
|
383
|
+
// 8. INIT ALL SHARED UI SYSTEMS
|
|
384
|
+
// ═══════════════════════════════════════════
|
|
385
|
+
|
|
386
|
+
initLoading({ onInit: boot });
|
|
387
|
+
initKeybinds(); // async — loads keybinds from server, installs central dispatcher
|
|
388
|
+
initTooltip();
|
|
389
|
+
initPanelSystem();
|
|
390
|
+
initPinToggle();
|
|
391
|
+
initNavbar();
|
|
392
|
+
initMenubar();
|
|
393
|
+
initSearch();
|
|
394
|
+
initSidebar();
|
|
395
|
+
initDetailPanel();
|
|
396
|
+
initSettings();
|
|
397
|
+
initTrash();
|
|
398
|
+
initBookmarks();
|
|
399
|
+
initResume();
|
|
400
|
+
initLayouts();
|
|
401
|
+
initWorkspaces();
|
|
402
|
+
initInvite();
|
|
403
|
+
initSync();
|
|
404
|
+
initHelp();
|
|
405
|
+
initMultiSelect();
|
|
406
|
+
initStats();
|
|
407
|
+
initExplorer();
|
|
408
|
+
initFileExplorer();
|
|
409
|
+
initSkillsStudio();
|
|
410
|
+
initAutomationStudio();
|
|
411
|
+
initImageGallery();
|
|
412
|
+
initCommandRunner();
|
|
413
|
+
initTerminal();
|
|
414
|
+
initLink();
|
|
415
|
+
clearGameOnLoad();
|
|
416
|
+
initWhiteboard();
|
|
417
|
+
initCostWidget();
|
|
418
|
+
initGames();
|
|
419
|
+
initTutorial();
|
|
420
|
+
|
|
421
|
+
// View switch handler
|
|
422
|
+
{
|
|
423
|
+
const switchBtn = document.querySelector('.view-toggle-btn:not(.active)');
|
|
424
|
+
if (switchBtn) {
|
|
425
|
+
switchBtn.addEventListener('click', (e) => {
|
|
426
|
+
e.preventDefault();
|
|
427
|
+
if (state.selectedNodeId) sessionStorage.setItem('neural-selected-node-switch', state.selectedNodeId);
|
|
428
|
+
window.location.href = switchBtn.getAttribute('href');
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Window resize handler
|
|
434
|
+
window.addEventListener('resize', () => {
|
|
435
|
+
clampPanelsToViewport();
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
// Visualization toggle — pause/resume 3D rendering
|
|
439
|
+
// Guard: ignore viz:toggle events emitted during boot (from restoreInterfaceConfig).
|
|
440
|
+
// Boot handles graph init itself; this handler is only for runtime user toggles.
|
|
441
|
+
let _bootComplete = false;
|
|
442
|
+
on('viz:toggle', (enabled) => {
|
|
443
|
+
if (!_bootComplete) return;
|
|
444
|
+
if (enabled) {
|
|
445
|
+
if (!getGraph()) {
|
|
446
|
+
// First-time init if graph was never created (was disabled at boot)
|
|
447
|
+
const container = document.getElementById('graph-container');
|
|
448
|
+
initGraph(container, {
|
|
449
|
+
onApplyBgTheme: () => {
|
|
450
|
+
const g = getGraph();
|
|
451
|
+
const bloom = getBloomPass();
|
|
452
|
+
if (g) applyBgTheme(g, bloom);
|
|
453
|
+
},
|
|
454
|
+
});
|
|
455
|
+
const g = getGraph();
|
|
456
|
+
if (g) initCamera(g);
|
|
457
|
+
if (g) applyFloorStyle(gfx.floorStyle || 'grid', g);
|
|
458
|
+
applyGraphData();
|
|
459
|
+
}
|
|
460
|
+
startAnimation();
|
|
461
|
+
} else {
|
|
462
|
+
stopAnimation();
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
// Focus mode isolation — zero-resource mode for 3D
|
|
467
|
+
on('focus:enter', () => {
|
|
468
|
+
state.hoveredNodeId = null;
|
|
469
|
+
document.body.style.cursor = 'default';
|
|
470
|
+
pauseInteraction();
|
|
471
|
+
pauseCamera();
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
on('focus:exit', () => {
|
|
475
|
+
resumeInteraction();
|
|
476
|
+
resumeCamera();
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
// Workspace scene snapshot (3D)
|
|
480
|
+
on('workspace:get-scene', (callback) => {
|
|
481
|
+
const graph = getGraph();
|
|
482
|
+
if (!graph) return callback({ nodePositions: {}, camera: null });
|
|
483
|
+
const gd = graph.graphData();
|
|
484
|
+
const positions = {};
|
|
485
|
+
for (const n of gd.nodes) {
|
|
486
|
+
if (n.x != null) positions[n.id] = { x: n.x, y: n.y, z: n.z };
|
|
487
|
+
}
|
|
488
|
+
callback({ nodePositions: positions, camera: saveCameraState() });
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
on('workspace:restore-scene', ({ nodePositions, camera }) => {
|
|
492
|
+
if (nodePositions && Object.keys(nodePositions).length > 0) {
|
|
493
|
+
storage.setItem(KEYS.NODE_POS_3D, JSON.stringify(nodePositions));
|
|
494
|
+
}
|
|
495
|
+
if (camera) restoreCameraState(camera, 1500);
|
|
496
|
+
applyGraphData();
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
// Boot
|
|
500
|
+
boot();
|