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,521 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Neural Interface — 2D Variant Entry Point
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// Registers the 2D 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
|
+
|
|
15
|
+
import { injectSharedHTML } from '../../shared/html-shell.js';
|
|
16
|
+
import { KEYS } from '../../shared/constants.js';
|
|
17
|
+
import { normalizeNodes } from '../../shared/utils.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, 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 } 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, registerAction, getDisplayKey } from '../../shared/ui-keybinds.js';
|
|
49
|
+
import { initTutorial } from '../../shared/ui-tutorial.js';
|
|
50
|
+
import { initImageGallery } from '../../shared/ui-image-gallery.js';
|
|
51
|
+
|
|
52
|
+
// ── 2D variant modules ──
|
|
53
|
+
import { gfx, saveGfxConfig } from './gfx.js';
|
|
54
|
+
import './settings-gfx.js'; // side-effect: self-registers Graphics tab
|
|
55
|
+
import { initAutomationStudio } from '../../shared/ui-automation-studio.js';
|
|
56
|
+
import { initCommandRunner } from '../../shared/ui-command-runner.js';
|
|
57
|
+
import { stopBackground } from './background.js';
|
|
58
|
+
import { initMinimap, drawMinimap, toggleMinimap, isMinimapVisible, forceHideMinimap, restoreMinimap } from './minimap.js';
|
|
59
|
+
import { initLasso, clearLasso } from './lasso.js';
|
|
60
|
+
import { initContextMenu, hideContextMenu } from './context-menu.js';
|
|
61
|
+
import {
|
|
62
|
+
initGraph, getGraph, applyGraphData,
|
|
63
|
+
preloadCategoryLogos, scheduleGraphRemoval, cancelScheduledRemoval,
|
|
64
|
+
refreshGraph, reheatSimulation, getAllCards,
|
|
65
|
+
stopAnimation, startAnimation,
|
|
66
|
+
pauseInteraction, resumeInteraction,
|
|
67
|
+
} from './graph.js';
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
// ═══════════════════════════════════════════
|
|
71
|
+
// 1. REGISTER VARIANT
|
|
72
|
+
// ═══════════════════════════════════════════
|
|
73
|
+
|
|
74
|
+
registerVariant({
|
|
75
|
+
variant: '2d',
|
|
76
|
+
capabilities: ['minimap', 'lasso', 'context-menu', 'orbital-layout'],
|
|
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-region-glow',
|
|
89
|
+
label: 'Region Glow',
|
|
90
|
+
init: (el) => {
|
|
91
|
+
el.classList.toggle('active', gfx.regionGlowOpacity > 0);
|
|
92
|
+
el.addEventListener('click', () => {
|
|
93
|
+
if (gfx.regionGlowOpacity > 0) {
|
|
94
|
+
gfx.regionGlowOpacity = 0;
|
|
95
|
+
} else {
|
|
96
|
+
gfx.regionGlowOpacity = 0.05;
|
|
97
|
+
}
|
|
98
|
+
saveGfxConfig(gfx);
|
|
99
|
+
el.classList.toggle('active', gfx.regionGlowOpacity > 0);
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
registerMenuItem({
|
|
105
|
+
menu: 'view',
|
|
106
|
+
order: 26,
|
|
107
|
+
type: 'toggle',
|
|
108
|
+
id: 'menu-minimap',
|
|
109
|
+
label: 'Minimap',
|
|
110
|
+
shortcut: 'M',
|
|
111
|
+
init: (el) => {
|
|
112
|
+
// Set initial active state (minimap starts visible)
|
|
113
|
+
el.classList.add('active');
|
|
114
|
+
|
|
115
|
+
const doToggle = () => {
|
|
116
|
+
toggleMinimap();
|
|
117
|
+
el.classList.toggle('active', isMinimapVisible());
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
el.addEventListener('click', doToggle);
|
|
121
|
+
|
|
122
|
+
// Register keybind action so the central dispatcher can trigger it
|
|
123
|
+
registerAction('toggle-minimap', doToggle);
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
// ═══════════════════════════════════════════
|
|
129
|
+
// 3. REGISTER VARIANT HELP SECTION
|
|
130
|
+
// ═══════════════════════════════════════════
|
|
131
|
+
|
|
132
|
+
registerHelpSection({
|
|
133
|
+
order: 50,
|
|
134
|
+
html: `
|
|
135
|
+
<h4>2D Canvas Controls</h4>
|
|
136
|
+
<div class="help-key-row"><span class="help-key">Mouse Drag</span> Pan the canvas</div>
|
|
137
|
+
<div class="help-key-row"><span class="help-key">Scroll</span> Zoom in/out</div>
|
|
138
|
+
<div class="help-key-row"><span class="help-key">Click Card</span> Select & open detail</div>
|
|
139
|
+
<div class="help-key-row"><span class="help-key">Click Category</span> Zoom to category</div>
|
|
140
|
+
<div class="help-key-row"><span class="help-key">Double-Click Card</span> Unpin card</div>
|
|
141
|
+
<div class="help-key-row"><span class="help-key">Double-Click BG</span> Zoom to fit all</div>
|
|
142
|
+
<div class="help-key-row"><span class="help-key">Right-Click Card</span> Context menu</div>
|
|
143
|
+
<div class="help-key-row"><span class="help-key">Shift + Drag</span> Lasso select</div>
|
|
144
|
+
<div class="help-key-row"><span class="help-key">Drag Card</span> Move & pin card</div>
|
|
145
|
+
<div class="help-key-row"><span class="help-key">Drag Category</span> Move entire group</div>
|
|
146
|
+
`,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
// ═══════════════════════════════════════════
|
|
151
|
+
// 4. LOAD TRANSLATIONS & INJECT SHARED HTML
|
|
152
|
+
// ═══════════════════════════════════════════
|
|
153
|
+
|
|
154
|
+
await initI18n();
|
|
155
|
+
injectSharedHTML();
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
// ═══════════════════════════════════════════
|
|
159
|
+
// 5. WIRE EVENT BUS — connect shared events to variant actions
|
|
160
|
+
// ═══════════════════════════════════════════
|
|
161
|
+
|
|
162
|
+
// When shared UI emits graph:navigate, center on node
|
|
163
|
+
on('graph:navigate', ({ node, zoom }) => {
|
|
164
|
+
const g = getGraph();
|
|
165
|
+
if (!node || !g) return;
|
|
166
|
+
const cards = getAllCards();
|
|
167
|
+
const card = cards.find(c => c.node.id === node.id);
|
|
168
|
+
if (card) {
|
|
169
|
+
g.centerAt(card.x, card.y, 500);
|
|
170
|
+
if (zoom === 'close') g.zoom(4, 500);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// Data reload (e.g. after OpenClaw bridge sync)
|
|
175
|
+
on('data:reload', async () => {
|
|
176
|
+
try {
|
|
177
|
+
await refreshGraph();
|
|
178
|
+
const presentCats = new Set(state.allNodes.map(n => n.payload.category));
|
|
179
|
+
buildCategorySidebar(presentCats);
|
|
180
|
+
updateStats();
|
|
181
|
+
} catch (err) {
|
|
182
|
+
console.error('data:reload failed:', err);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Categories changed
|
|
187
|
+
on('categories-changed', () => {
|
|
188
|
+
applyGraphData();
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Search apply/clear
|
|
192
|
+
on('search:apply', () => {
|
|
193
|
+
// No layout recompute needed — just re-renders with dimming
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
on('search:clear', () => {
|
|
197
|
+
// No layout recompute needed
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// Link mode changes — just triggers re-render (no API call needed)
|
|
201
|
+
on('link-mode-changed', () => {
|
|
202
|
+
// Render loop picks up state.linkMode automatically
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
on('link-type-changed', () => {
|
|
206
|
+
// Render loop picks up state.linkTypeFilter automatically
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Node selection — center camera on selected card + open detail card
|
|
210
|
+
on('node-selected', (node) => {
|
|
211
|
+
if (!node) return;
|
|
212
|
+
const g = getGraph();
|
|
213
|
+
if (g) {
|
|
214
|
+
const cards = getAllCards();
|
|
215
|
+
const card = cards.find(c => c.node.id === node.id);
|
|
216
|
+
if (card) {
|
|
217
|
+
g.centerAt(card.x, card.y, 500);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
openMemoryCard(node);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// Graph refresh
|
|
224
|
+
on('graph:refresh', () => {
|
|
225
|
+
applyGraphData();
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Category removal scheduling
|
|
229
|
+
on('category:schedule-removal', () => {
|
|
230
|
+
scheduleGraphRemoval();
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
on('category:cancel-removal', () => {
|
|
234
|
+
cancelScheduledRemoval();
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// Layout commands
|
|
238
|
+
on('layout:reset', () => {
|
|
239
|
+
reheatSimulation(); // clears saved positions + recomputes layout
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
on('layout:frame', () => {
|
|
243
|
+
const g = getGraph();
|
|
244
|
+
if (g) g.zoomToFit(400, 60);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Stats update
|
|
248
|
+
on('stats-changed', () => {
|
|
249
|
+
updateStats();
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
// Context menu hide
|
|
253
|
+
on('context-menu-hide', () => {
|
|
254
|
+
hideContextMenu();
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// Render frame post — draw minimap
|
|
258
|
+
on('render-frame-post', () => {
|
|
259
|
+
if (isMinimapVisible()) drawMinimap();
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
// ═══════════════════════════════════════════
|
|
264
|
+
// 6. DETAIL PANEL CALLBACKS
|
|
265
|
+
// ═══════════════════════════════════════════
|
|
266
|
+
|
|
267
|
+
setDetailCallbacks({
|
|
268
|
+
navigateToNode: (node) => {
|
|
269
|
+
const g = getGraph();
|
|
270
|
+
if (!g || !node) return;
|
|
271
|
+
const cards = getAllCards();
|
|
272
|
+
const card = cards.find(c => c.node.id === node.id);
|
|
273
|
+
if (card) g.centerAt(card.x, card.y, 500);
|
|
274
|
+
},
|
|
275
|
+
refreshGraph: () => applyGraphData(),
|
|
276
|
+
scheduleRemoval: () => scheduleGraphRemoval(),
|
|
277
|
+
cancelRemoval: () => cancelScheduledRemoval(),
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
// ═══════════════════════════════════════════
|
|
282
|
+
// 7. BOOT SEQUENCE
|
|
283
|
+
// ═══════════════════════════════════════════
|
|
284
|
+
|
|
285
|
+
async function boot() {
|
|
286
|
+
try {
|
|
287
|
+
// Restore interface customization + active skin before anything renders
|
|
288
|
+
restoreInterfaceConfig();
|
|
289
|
+
restoreSkin();
|
|
290
|
+
|
|
291
|
+
// Pre-flight health check
|
|
292
|
+
try {
|
|
293
|
+
const healthRes = await fetch('/api/health');
|
|
294
|
+
const health = await healthRes.json();
|
|
295
|
+
if (!health.ok) {
|
|
296
|
+
const messages = {
|
|
297
|
+
db_missing: [t('loading.health.databaseUnreachable.title'), health.detail || t('loading.health.databaseUnreachable.sub')],
|
|
298
|
+
db_error: [t('loading.health.databaseUnreachable.title'), health.detail || t('loading.health.databaseUnreachable.sub')],
|
|
299
|
+
remote_unreachable: [t('loading.health.remoteUnreachable.title'), health.detail || t('loading.health.remoteUnreachable.sub')],
|
|
300
|
+
auth_error: [t('loading.health.authError.title'), health.detail || t('loading.health.authError.sub')],
|
|
301
|
+
};
|
|
302
|
+
const [title, sub] = messages[health.reason] || [t('loading.health.connectionError.title'), health.detail || t('loading.health.connectionError.sub')];
|
|
303
|
+
showLoadingError(title, sub, !!health.canAutoStart);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
} catch {}
|
|
307
|
+
|
|
308
|
+
// Fetch all memories
|
|
309
|
+
const res = await fetch('/api/memories');
|
|
310
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
311
|
+
const data = await res.json();
|
|
312
|
+
|
|
313
|
+
state.allNodes = normalizeNodes(data.nodes);
|
|
314
|
+
state.allLinks = data.links;
|
|
315
|
+
|
|
316
|
+
// Fetch category definitions
|
|
317
|
+
await loadCategories();
|
|
318
|
+
|
|
319
|
+
// Discover all categories
|
|
320
|
+
const presentCats = new Set(state.allNodes.map(n => n.payload.category));
|
|
321
|
+
state.activeCategories = new Set([...presentCats, ...state.allCategoryNames]);
|
|
322
|
+
|
|
323
|
+
// Build category sidebar
|
|
324
|
+
buildCategorySidebar(presentCats);
|
|
325
|
+
|
|
326
|
+
// Init the 2D canvas renderer (skip if visualization is disabled)
|
|
327
|
+
const container = document.getElementById('graph-container');
|
|
328
|
+
const vizEnabled = loadIfaceConfig().visualizationEnabled !== false;
|
|
329
|
+
let g = null;
|
|
330
|
+
|
|
331
|
+
if (vizEnabled && !getGraph()) {
|
|
332
|
+
g = initGraph(container, {
|
|
333
|
+
onRenderFramePost: () => {
|
|
334
|
+
if (isMinimapVisible()) drawMinimap();
|
|
335
|
+
},
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// Init overlays
|
|
339
|
+
initMinimap(g);
|
|
340
|
+
initLasso(g);
|
|
341
|
+
initContextMenu(g);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Apply data to compute layout and start rendering
|
|
345
|
+
applyGraphData();
|
|
346
|
+
|
|
347
|
+
// Update stats
|
|
348
|
+
updateStats();
|
|
349
|
+
|
|
350
|
+
// Signal data is ready
|
|
351
|
+
emit('data-loaded', data);
|
|
352
|
+
|
|
353
|
+
// Restore previously open memory cards
|
|
354
|
+
restoreOpenCards();
|
|
355
|
+
|
|
356
|
+
// Handle view-switch handoff
|
|
357
|
+
const switchNodeId = sessionStorage.getItem('neural-selected-node-switch');
|
|
358
|
+
if (switchNodeId) {
|
|
359
|
+
sessionStorage.removeItem('neural-selected-node-switch');
|
|
360
|
+
const node = state.allNodes.find(n => n.id === switchNodeId);
|
|
361
|
+
if (node) {
|
|
362
|
+
state.selectedNodeId = switchNodeId;
|
|
363
|
+
openMemoryCard(node);
|
|
364
|
+
setTimeout(() => {
|
|
365
|
+
if (g) {
|
|
366
|
+
const cards = getAllCards();
|
|
367
|
+
const card = cards.find(c => c.node.id === switchNodeId);
|
|
368
|
+
if (card) g.centerAt(card.x, card.y, 500);
|
|
369
|
+
}
|
|
370
|
+
}, 600);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Fetch trash count
|
|
375
|
+
try { emit('trash:refresh'); } catch {}
|
|
376
|
+
|
|
377
|
+
// Fade out loading
|
|
378
|
+
hideLoading(400);
|
|
379
|
+
|
|
380
|
+
// Mark boot complete
|
|
381
|
+
_bootComplete = true;
|
|
382
|
+
|
|
383
|
+
} catch (err) {
|
|
384
|
+
console.error('Init error:', err);
|
|
385
|
+
const isNetworkError = err.message === 'Failed to fetch' || err.name === 'TypeError';
|
|
386
|
+
showLoadingError(
|
|
387
|
+
isNetworkError ? t('loading.serverOffline') : t('loading.connectionFailed'),
|
|
388
|
+
isNetworkError ? t('loading.serverNotRunning') : err.message,
|
|
389
|
+
false,
|
|
390
|
+
isNetworkError
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
// ═══════════════════════════════════════════
|
|
397
|
+
// 8. INIT ALL SHARED UI SYSTEMS
|
|
398
|
+
// ═══════════════════════════════════════════
|
|
399
|
+
|
|
400
|
+
initLoading({ onInit: boot });
|
|
401
|
+
initKeybinds();
|
|
402
|
+
initTooltip();
|
|
403
|
+
initPanelSystem();
|
|
404
|
+
initPinToggle();
|
|
405
|
+
initNavbar();
|
|
406
|
+
initMenubar();
|
|
407
|
+
initSearch();
|
|
408
|
+
initSidebar();
|
|
409
|
+
initDetailPanel();
|
|
410
|
+
initSettings();
|
|
411
|
+
initTrash();
|
|
412
|
+
initBookmarks();
|
|
413
|
+
initResume();
|
|
414
|
+
initLayouts();
|
|
415
|
+
initWorkspaces();
|
|
416
|
+
initInvite();
|
|
417
|
+
initSync();
|
|
418
|
+
initHelp();
|
|
419
|
+
initMultiSelect();
|
|
420
|
+
initStats();
|
|
421
|
+
initExplorer();
|
|
422
|
+
initFileExplorer();
|
|
423
|
+
initSkillsStudio();
|
|
424
|
+
initAutomationStudio();
|
|
425
|
+
initImageGallery();
|
|
426
|
+
initCommandRunner();
|
|
427
|
+
initTerminal();
|
|
428
|
+
initLink();
|
|
429
|
+
clearGameOnLoad();
|
|
430
|
+
initWhiteboard();
|
|
431
|
+
initCostWidget();
|
|
432
|
+
initGames();
|
|
433
|
+
initTutorial();
|
|
434
|
+
|
|
435
|
+
// View switch handler
|
|
436
|
+
{
|
|
437
|
+
const switchBtn = document.querySelector('.view-toggle-btn:not(.active)');
|
|
438
|
+
if (switchBtn) {
|
|
439
|
+
switchBtn.addEventListener('click', (e) => {
|
|
440
|
+
e.preventDefault();
|
|
441
|
+
if (state.selectedNodeId) sessionStorage.setItem('neural-selected-node-switch', state.selectedNodeId);
|
|
442
|
+
window.location.href = switchBtn.getAttribute('href');
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Window resize handler
|
|
448
|
+
window.addEventListener('resize', () => {
|
|
449
|
+
clampPanelsToViewport();
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
// Visualization toggle — pause/resume 2D rendering
|
|
453
|
+
let _bootComplete = false;
|
|
454
|
+
on('viz:toggle', (enabled) => {
|
|
455
|
+
if (!_bootComplete) return;
|
|
456
|
+
if (enabled) {
|
|
457
|
+
if (!getGraph()) {
|
|
458
|
+
// First-time init if graph was never created (was disabled at boot)
|
|
459
|
+
const container = document.getElementById('graph-container');
|
|
460
|
+
const g = initGraph(container, {
|
|
461
|
+
onRenderFramePost: () => {
|
|
462
|
+
if (isMinimapVisible()) drawMinimap();
|
|
463
|
+
},
|
|
464
|
+
});
|
|
465
|
+
initMinimap(g);
|
|
466
|
+
initLasso(g);
|
|
467
|
+
initContextMenu(g);
|
|
468
|
+
applyGraphData();
|
|
469
|
+
}
|
|
470
|
+
// Show the main canvas (it's position:fixed, not affected by container opacity)
|
|
471
|
+
const mainCanvas = document.getElementById('canvas-main');
|
|
472
|
+
if (mainCanvas) mainCanvas.classList.remove('viz-hidden-2d');
|
|
473
|
+
// Restart the render loop
|
|
474
|
+
startAnimation();
|
|
475
|
+
// Restore minimap to user's preference
|
|
476
|
+
restoreMinimap();
|
|
477
|
+
} else {
|
|
478
|
+
// Stop the render loop entirely — no wasted frames in focus mode
|
|
479
|
+
stopAnimation();
|
|
480
|
+
stopBackground();
|
|
481
|
+
// Hide the main canvas when entering focus mode
|
|
482
|
+
const mainCanvas = document.getElementById('canvas-main');
|
|
483
|
+
if (mainCanvas) mainCanvas.classList.add('viz-hidden-2d');
|
|
484
|
+
// Always hide minimap in focus mode
|
|
485
|
+
forceHideMinimap();
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
// Focus mode isolation — zero-resource mode for 2D
|
|
490
|
+
on('focus:enter', () => {
|
|
491
|
+
state.hoveredNodeId = null;
|
|
492
|
+
clearLasso();
|
|
493
|
+
hideContextMenu();
|
|
494
|
+
pauseInteraction();
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
on('focus:exit', () => {
|
|
498
|
+
resumeInteraction();
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
// Workspace scene snapshot (2D)
|
|
502
|
+
on('workspace:get-scene', (callback) => {
|
|
503
|
+
const graph = getGraph();
|
|
504
|
+
if (!graph) return callback({ nodePositions: {}, camera: null });
|
|
505
|
+
const gd = graph.graphData();
|
|
506
|
+
const positions = {};
|
|
507
|
+
for (const n of gd.nodes) {
|
|
508
|
+
if (n.x != null) positions[n.id] = { x: n.x, y: n.y };
|
|
509
|
+
}
|
|
510
|
+
callback({ nodePositions: positions, camera: null });
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
on('workspace:restore-scene', ({ nodePositions }) => {
|
|
514
|
+
if (nodePositions && Object.keys(nodePositions).length > 0) {
|
|
515
|
+
storage.setItem(KEYS.NODE_POS_2D, JSON.stringify(nodePositions));
|
|
516
|
+
}
|
|
517
|
+
applyGraphData();
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
// Boot
|
|
521
|
+
boot();
|