codesynapt 0.0.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +686 -0
  3. package/LICENSES.md +141 -0
  4. package/README.md +331 -0
  5. package/electron/main.cjs +2849 -0
  6. package/electron/plugin-loader.cjs +184 -0
  7. package/electron/preload.cjs +108 -0
  8. package/package.json +216 -0
  9. package/packages/core/bin/codesynapt-mcp.cjs +611 -0
  10. package/packages/core/bin/codesynapt.cjs +1933 -0
  11. package/packages/core/legacy.js +300 -0
  12. package/packages/core/lib/control-server.cjs +1539 -0
  13. package/packages/core/lib/embedding.cjs +89 -0
  14. package/packages/core/lib/logger.cjs +63 -0
  15. package/packages/core/lib/search-cache.cjs +140 -0
  16. package/packages/core/lib/search-worker.cjs +255 -0
  17. package/packages/core/lib/search.cjs +211 -0
  18. package/packages/core/lib/symbol-graph.cjs +402 -0
  19. package/packages/core/lib/symbol-parser-js.cjs +542 -0
  20. package/packages/core/lib/symbol-parser-misc.cjs +394 -0
  21. package/packages/core/lib/symbol-parser-py.cjs +215 -0
  22. package/packages/core/lib/symbol-parser-treesitter.cjs +658 -0
  23. package/packages/core/lib/symbol-parser-tsc.cjs +332 -0
  24. package/packages/core/monorepo.js +310 -0
  25. package/packages/core/parser.js +2234 -0
  26. package/packages/core/scanner.js +623 -0
  27. package/plugin-api/LICENSE +21 -0
  28. package/plugin-api/README.md +114 -0
  29. package/plugin-api/docs/01-getting-started.md +197 -0
  30. package/plugin-api/docs/02-concepts.md +269 -0
  31. package/plugin-api/docs/api-reference.md +463 -0
  32. package/plugin-api/docs/troubleshooting.md +332 -0
  33. package/plugin-api/docs/types/exporter.md +377 -0
  34. package/plugin-api/docs/types/theme.md +312 -0
  35. package/plugin-api/examples/hello-world-plugin/README.md +70 -0
  36. package/plugin-api/examples/hello-world-plugin/main.js +36 -0
  37. package/plugin-api/examples/hello-world-plugin/manifest.json +12 -0
  38. package/plugin-api/examples/mermaid-exporter/README.md +125 -0
  39. package/plugin-api/examples/mermaid-exporter/main.js +58 -0
  40. package/plugin-api/examples/mermaid-exporter/manifest.json +12 -0
  41. package/plugin-api/examples/rust-parser/README.md +71 -0
  42. package/plugin-api/examples/rust-parser/main.js +123 -0
  43. package/plugin-api/examples/rust-parser/manifest.json +12 -0
  44. package/plugin-api/examples/sunset-theme/README.md +95 -0
  45. package/plugin-api/examples/sunset-theme/manifest.json +12 -0
  46. package/plugin-api/examples/sunset-theme/theme.css +31 -0
  47. package/plugin-api/package.json +20 -0
  48. package/plugin-api/types.d.ts +395 -0
  49. package/public/app.js +6837 -0
  50. package/public/backend.js +285 -0
  51. package/public/index.html +647 -0
  52. package/public/plugin-host.js +321 -0
  53. package/public/style.css +4359 -0
  54. package/public/vendor/three.module.js +53044 -0
  55. package/scripts/competitor-watch.mjs +144 -0
  56. package/scripts/copy-vendor.js +21 -0
  57. package/scripts/download-bundled-node.cjs +53 -0
  58. package/scripts/fuses-after-pack.cjs +34 -0
  59. package/scripts/license-check.js +119 -0
  60. package/scripts/perf-test.js +200 -0
  61. package/server.js +132 -0
@@ -0,0 +1,285 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // backend.js — physics backend dispatcher
3
+ //
4
+ // Three modes:
5
+ // 'gpu' → WebGPU compute (when available, not contended)
6
+ // 'cpu' → CPU stepCPU() in app.js (always available, scales OK)
7
+ // 'auto' → Start GPU if available; if GPU becomes saturated
8
+ // (sustained >60% of frame budget), transparently
9
+ // switch to CPU. If GPU recovers later, switch back.
10
+ //
11
+ // Public surface:
12
+ // init({ onStatusChange }) — async, sets up GPU if possible
13
+ // setMode('gpu' | 'cpu' | 'auto') — user choice from settings UI
14
+ // getStatus() — { mode, active, gpuAvailable,
15
+ // gpuTimeMs, reason }
16
+ // runStep(dt, stepCPU, stepGPU) — dispatched per frame from
17
+ // app.js render loop
18
+ //
19
+ // Persists user preference in localStorage so the toggle survives
20
+ // app restarts.
21
+ //
22
+ // GPU contention detection:
23
+ // Each GPU step ends with await device.queue.onSubmittedWorkDone(),
24
+ // timed via performance.now(). If the average of the last
25
+ // SAMPLE_WINDOW frames exceeds CONTENTION_MS, we declare the GPU
26
+ // contended (likely a heavy app like Wan 2.2 inference is using
27
+ // it) and fall back to CPU. We keep probing every PROBE_INTERVAL_MS
28
+ // by running one GPU step and checking its timing.
29
+ // ═══════════════════════════════════════════════════════════════
30
+
31
+ const STORAGE_KEY = 'codesynapt:backend_mode'
32
+ const SAMPLE_WINDOW = 30 // frames to average for contention
33
+ const CONTENTION_MS = 10 // GPU step >10ms avg = contended
34
+ const RECOVERY_MS = 4 // probe shows <4ms = healthy again
35
+ const PROBE_INTERVAL_MS = 3000 // re-test GPU every 3s in fallback
36
+
37
+ const state = {
38
+ mode: 'auto', // user preference: 'auto'|'gpu'|'cpu'
39
+ active: 'cpu', // what's actually running this frame
40
+ gpuAvailable: false, // navigator.gpu and adapter exist
41
+ gpuInitError: null, // string describing init failure
42
+ device: null, // GPUDevice, populated on init
43
+ adapter: null, // GPUAdapter
44
+ gpuTimeMs: 0, // smoothed GPU step time
45
+ reason: 'not initialized', // human-readable status
46
+ sampleBuffer: new Float32Array(SAMPLE_WINDOW),
47
+ sampleIdx: 0,
48
+ sampleCount: 0,
49
+ lastProbeAt: 0,
50
+ listeners: [],
51
+ }
52
+
53
+ function loadPreference() {
54
+ try {
55
+ const v = localStorage.getItem(STORAGE_KEY)
56
+ if (v === 'auto' || v === 'gpu' || v === 'cpu') state.mode = v
57
+ } catch { /* localStorage may be blocked */ }
58
+ }
59
+ function savePreference() {
60
+ try { localStorage.setItem(STORAGE_KEY, state.mode) } catch { /* ignore */ }
61
+ }
62
+
63
+ function emit() {
64
+ const snapshot = getStatus()
65
+ for (const fn of state.listeners) fn(snapshot)
66
+ }
67
+
68
+ function recordSample(ms) {
69
+ state.sampleBuffer[state.sampleIdx] = ms
70
+ state.sampleIdx = (state.sampleIdx + 1) % SAMPLE_WINDOW
71
+ if (state.sampleCount < SAMPLE_WINDOW) state.sampleCount++
72
+ // Exponential moving average for display
73
+ state.gpuTimeMs = state.gpuTimeMs * 0.9 + ms * 0.1
74
+ }
75
+
76
+ function averageGpuTime() {
77
+ if (state.sampleCount === 0) return 0
78
+ let sum = 0
79
+ for (let i = 0; i < state.sampleCount; i++) sum += state.sampleBuffer[i]
80
+ return sum / state.sampleCount
81
+ }
82
+
83
+ function clearSamples() {
84
+ state.sampleCount = 0
85
+ state.sampleIdx = 0
86
+ state.gpuTimeMs = 0
87
+ }
88
+
89
+ // ─── Public API ─────────────────────────────────────────────────
90
+
91
+ export async function init({ onStatusChange } = {}) {
92
+ if (onStatusChange) state.listeners.push(onStatusChange)
93
+ loadPreference()
94
+
95
+ if (!('gpu' in navigator)) {
96
+ state.gpuInitError = 'WebGPU not available in this browser/build'
97
+ state.reason = state.gpuInitError
98
+ state.active = 'cpu'
99
+ emit()
100
+ return
101
+ }
102
+
103
+ try {
104
+ const adapter = await navigator.gpu.requestAdapter({
105
+ powerPreference: 'high-performance',
106
+ })
107
+ if (!adapter) {
108
+ state.gpuInitError = 'No WebGPU adapter found'
109
+ state.reason = state.gpuInitError
110
+ state.active = 'cpu'
111
+ emit()
112
+ return
113
+ }
114
+ const device = await adapter.requestDevice({
115
+ // Ask for the limits we need for big graphs
116
+ requiredLimits: {
117
+ maxBufferSize: Math.min(adapter.limits.maxBufferSize, 256 * 1024 * 1024),
118
+ maxStorageBufferBindingSize: Math.min(
119
+ adapter.limits.maxStorageBufferBindingSize,
120
+ 256 * 1024 * 1024,
121
+ ),
122
+ },
123
+ })
124
+ device.lost.then((info) => {
125
+ console.warn('WebGPU device lost:', info.message)
126
+ state.gpuAvailable = false
127
+ state.device = null
128
+ state.active = 'cpu'
129
+ state.reason = `GPU device lost: ${info.message}`
130
+ emit()
131
+ })
132
+ state.adapter = adapter
133
+ state.device = device
134
+ state.gpuAvailable = true
135
+ state.reason = 'GPU ready'
136
+
137
+ // Initial active backend based on preference
138
+ if (state.mode === 'cpu') {
139
+ state.active = 'cpu'
140
+ state.reason = 'CPU mode selected by user'
141
+ } else {
142
+ state.active = 'gpu'
143
+ state.reason = 'GPU active'
144
+ }
145
+ } catch (err) {
146
+ state.gpuInitError = err.message || String(err)
147
+ state.reason = `GPU init failed: ${state.gpuInitError}`
148
+ state.active = 'cpu'
149
+ }
150
+ emit()
151
+ }
152
+
153
+ export function setMode(mode) {
154
+ if (mode !== 'auto' && mode !== 'gpu' && mode !== 'cpu') return
155
+ state.mode = mode
156
+ savePreference()
157
+ clearSamples()
158
+ if (mode === 'cpu') {
159
+ state.active = 'cpu'
160
+ state.reason = 'CPU mode selected'
161
+ } else if (mode === 'gpu') {
162
+ if (state.gpuAvailable) {
163
+ state.active = 'gpu'
164
+ state.reason = 'GPU mode forced'
165
+ } else {
166
+ state.active = 'cpu'
167
+ state.reason = state.gpuInitError || 'GPU not available'
168
+ }
169
+ } else {
170
+ // auto
171
+ state.active = state.gpuAvailable ? 'gpu' : 'cpu'
172
+ state.reason = state.gpuAvailable
173
+ ? 'auto: GPU active'
174
+ : (state.gpuInitError || 'auto: GPU unavailable, using CPU')
175
+ }
176
+ emit()
177
+ }
178
+
179
+ export function getStatus() {
180
+ return {
181
+ mode: state.mode,
182
+ active: state.active,
183
+ gpuAvailable: state.gpuAvailable,
184
+ gpuTimeMs: state.gpuTimeMs,
185
+ reason: state.reason,
186
+ gpuInitError: state.gpuInitError,
187
+ }
188
+ }
189
+
190
+ export function subscribe(fn) {
191
+ state.listeners.push(fn)
192
+ fn(getStatus())
193
+ return () => {
194
+ const i = state.listeners.indexOf(fn)
195
+ if (i >= 0) state.listeners.splice(i, 1)
196
+ }
197
+ }
198
+
199
+ // ─── Per-frame dispatch ─────────────────────────────────────────
200
+ //
201
+ // app.js calls runStep(dt, stepCPU, stepGPU) each frame. We
202
+ // decide which backend to use based on state.active, then measure
203
+ // GPU time if applicable, and consider switching modes for 'auto'.
204
+ //
205
+ // stepGPU is OPTIONAL — until v0.6 implements actual compute
206
+ // shaders, it can be null. In that case any 'gpu' request silently
207
+ // runs CPU and updates state.reason.
208
+ //
209
+ export function runStep(dt, stepCPU, stepGPU) {
210
+ // No GPU implementation yet? Always CPU.
211
+ if (!stepGPU || !state.device) {
212
+ if (state.active === 'gpu') {
213
+ state.active = 'cpu'
214
+ state.reason = 'GPU backend not implemented yet (CPU active)'
215
+ emit()
216
+ }
217
+ stepCPU(dt)
218
+ return
219
+ }
220
+
221
+ if (state.active === 'cpu') {
222
+ stepCPU(dt)
223
+ if (state.mode === 'auto' && state.gpuAvailable) {
224
+ maybeProbeGpu(stepGPU)
225
+ }
226
+ return
227
+ }
228
+
229
+ // GPU path
230
+ const t0 = performance.now()
231
+ const promise = stepGPU(dt, state.device)
232
+ // stepGPU may be sync (just queue.submit) or return a Promise that
233
+ // resolves when GPU work is done. We don't await — we measure
234
+ // submission-to-resolve in the background.
235
+ if (promise && typeof promise.then === 'function') {
236
+ promise.then(() => {
237
+ const ms = performance.now() - t0
238
+ recordSample(ms)
239
+ considerAutoSwitch()
240
+ }).catch((err) => {
241
+ console.warn('GPU step failed, falling back to CPU:', err)
242
+ state.active = 'cpu'
243
+ state.reason = `GPU error: ${err.message || err}`
244
+ emit()
245
+ })
246
+ } else {
247
+ const ms = performance.now() - t0
248
+ recordSample(ms)
249
+ considerAutoSwitch()
250
+ }
251
+ }
252
+
253
+ function considerAutoSwitch() {
254
+ if (state.mode !== 'auto') return
255
+ if (state.sampleCount < SAMPLE_WINDOW / 2) return
256
+ const avg = averageGpuTime()
257
+ if (state.active === 'gpu' && avg > CONTENTION_MS) {
258
+ state.active = 'cpu'
259
+ state.reason = `auto: GPU contended (${avg.toFixed(1)}ms avg), using CPU`
260
+ state.lastProbeAt = performance.now()
261
+ emit()
262
+ }
263
+ }
264
+
265
+ function maybeProbeGpu(stepGPU) {
266
+ // While in CPU fallback under 'auto', occasionally try a single
267
+ // GPU step to check if the GPU has freed up.
268
+ if (state.mode !== 'auto') return
269
+ const now = performance.now()
270
+ if (now - state.lastProbeAt < PROBE_INTERVAL_MS) return
271
+ state.lastProbeAt = now
272
+ const t0 = performance.now()
273
+ const r = stepGPU(0, state.device) // dt=0 == probe-only, no-op step
274
+ const finish = () => {
275
+ const ms = performance.now() - t0
276
+ if (ms < RECOVERY_MS) {
277
+ state.active = 'gpu'
278
+ state.reason = `auto: GPU recovered (${ms.toFixed(1)}ms probe)`
279
+ clearSamples()
280
+ emit()
281
+ }
282
+ }
283
+ if (r && typeof r.then === 'function') r.then(finish).catch(() => {})
284
+ else finish()
285
+ }