@nocturnium/svelte-ide 1.0.0-rc.1

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 (330) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +251 -0
  3. package/dist/components/agents/AgentActivityPanel.svelte +565 -0
  4. package/dist/components/agents/AgentActivityPanel.svelte.d.ts +24 -0
  5. package/dist/components/agents/AgentAvatar.svelte +417 -0
  6. package/dist/components/agents/AgentAvatar.svelte.d.ts +23 -0
  7. package/dist/components/agents/AgentCursor.svelte +224 -0
  8. package/dist/components/agents/AgentCursor.svelte.d.ts +35 -0
  9. package/dist/components/agents/AgentPresenceBar.svelte +261 -0
  10. package/dist/components/agents/AgentPresenceBar.svelte.d.ts +20 -0
  11. package/dist/components/agents/index.d.ts +4 -0
  12. package/dist/components/agents/index.js +5 -0
  13. package/dist/components/ai/AIConversationList.svelte +524 -0
  14. package/dist/components/ai/AIConversationList.svelte.d.ts +17 -0
  15. package/dist/components/ai/AIEditPreview.svelte +132 -0
  16. package/dist/components/ai/AIEditPreview.svelte.d.ts +8 -0
  17. package/dist/components/ai/AIInlineEdit.svelte +155 -0
  18. package/dist/components/ai/AIInlineEdit.svelte.d.ts +10 -0
  19. package/dist/components/ai/AIMessage.svelte +239 -0
  20. package/dist/components/ai/AIMessage.svelte.d.ts +13 -0
  21. package/dist/components/ai/AIMessageActions.svelte +176 -0
  22. package/dist/components/ai/AIMessageActions.svelte.d.ts +12 -0
  23. package/dist/components/ai/AIMessageContent.svelte +355 -0
  24. package/dist/components/ai/AIMessageContent.svelte.d.ts +7 -0
  25. package/dist/components/ai/AIPanel.svelte +561 -0
  26. package/dist/components/ai/AIPanel.svelte.d.ts +7 -0
  27. package/dist/components/ai/AISuggestionWidget.svelte +132 -0
  28. package/dist/components/ai/AISuggestionWidget.svelte.d.ts +10 -0
  29. package/dist/components/ai/AIToolCallDisplay.svelte +317 -0
  30. package/dist/components/ai/AIToolCallDisplay.svelte.d.ts +12 -0
  31. package/dist/components/ai/index.d.ts +9 -0
  32. package/dist/components/ai/index.js +10 -0
  33. package/dist/components/core/Avatar.svelte +110 -0
  34. package/dist/components/core/Avatar.svelte.d.ts +12 -0
  35. package/dist/components/core/Badge.svelte +98 -0
  36. package/dist/components/core/Badge.svelte.d.ts +11 -0
  37. package/dist/components/core/Button.svelte +175 -0
  38. package/dist/components/core/Button.svelte.d.ts +18 -0
  39. package/dist/components/core/ConnectionStatus.svelte +294 -0
  40. package/dist/components/core/ConnectionStatus.svelte.d.ts +20 -0
  41. package/dist/components/core/ContextMenu.svelte +176 -0
  42. package/dist/components/core/ContextMenu.svelte.d.ts +19 -0
  43. package/dist/components/core/ErrorBoundary.svelte +277 -0
  44. package/dist/components/core/ErrorBoundary.svelte.d.ts +23 -0
  45. package/dist/components/core/Icon.svelte +107 -0
  46. package/dist/components/core/Icon.svelte.d.ts +8 -0
  47. package/dist/components/core/Input.svelte +138 -0
  48. package/dist/components/core/Input.svelte.d.ts +20 -0
  49. package/dist/components/core/Kbd.svelte +34 -0
  50. package/dist/components/core/Kbd.svelte.d.ts +7 -0
  51. package/dist/components/core/ResizeHandle.svelte +200 -0
  52. package/dist/components/core/ResizeHandle.svelte.d.ts +23 -0
  53. package/dist/components/core/Spinner.svelte +35 -0
  54. package/dist/components/core/Spinner.svelte.d.ts +7 -0
  55. package/dist/components/core/Textarea.svelte +112 -0
  56. package/dist/components/core/Textarea.svelte.d.ts +18 -0
  57. package/dist/components/core/Tooltip.svelte +103 -0
  58. package/dist/components/core/Tooltip.svelte.d.ts +11 -0
  59. package/dist/components/core/index.d.ts +13 -0
  60. package/dist/components/core/index.js +14 -0
  61. package/dist/components/editor/AIFocusLayer.svelte +430 -0
  62. package/dist/components/editor/AIFocusLayer.svelte.d.ts +32 -0
  63. package/dist/components/editor/Breadcrumbs.svelte +435 -0
  64. package/dist/components/editor/Breadcrumbs.svelte.d.ts +33 -0
  65. package/dist/components/editor/BreakpointLayer.svelte +642 -0
  66. package/dist/components/editor/BreakpointLayer.svelte.d.ts +20 -0
  67. package/dist/components/editor/CognitiveLoadMeter.svelte +324 -0
  68. package/dist/components/editor/CognitiveLoadMeter.svelte.d.ts +18 -0
  69. package/dist/components/editor/CollaborativeEditor.svelte +218 -0
  70. package/dist/components/editor/CollaborativeEditor.svelte.d.ts +32 -0
  71. package/dist/components/editor/CommandPalette.svelte +434 -0
  72. package/dist/components/editor/CommandPalette.svelte.d.ts +11 -0
  73. package/dist/components/editor/ComplexityLayer.svelte +293 -0
  74. package/dist/components/editor/ComplexityLayer.svelte.d.ts +23 -0
  75. package/dist/components/editor/ConflictZoneLayer.svelte +441 -0
  76. package/dist/components/editor/ConflictZoneLayer.svelte.d.ts +25 -0
  77. package/dist/components/editor/ContextLens.svelte +262 -0
  78. package/dist/components/editor/ContextLens.svelte.d.ts +27 -0
  79. package/dist/components/editor/CustomEditor.svelte +1242 -0
  80. package/dist/components/editor/CustomEditor.svelte.d.ts +37 -0
  81. package/dist/components/editor/DebugConsole.svelte +646 -0
  82. package/dist/components/editor/DebugConsole.svelte.d.ts +41 -0
  83. package/dist/components/editor/EchoCursorLayer.svelte +363 -0
  84. package/dist/components/editor/EchoCursorLayer.svelte.d.ts +24 -0
  85. package/dist/components/editor/Editor.svelte +61 -0
  86. package/dist/components/editor/Editor.svelte.d.ts +22 -0
  87. package/dist/components/editor/EditorGutter.svelte +119 -0
  88. package/dist/components/editor/EditorGutter.svelte.d.ts +19 -0
  89. package/dist/components/editor/EditorLines.svelte +182 -0
  90. package/dist/components/editor/EditorLines.svelte.d.ts +43 -0
  91. package/dist/components/editor/EditorPane.svelte +134 -0
  92. package/dist/components/editor/EditorPane.svelte.d.ts +9 -0
  93. package/dist/components/editor/EditorSelections.svelte +186 -0
  94. package/dist/components/editor/EditorSelections.svelte.d.ts +25 -0
  95. package/dist/components/editor/EditorTabs.svelte +170 -0
  96. package/dist/components/editor/EditorTabs.svelte.d.ts +12 -0
  97. package/dist/components/editor/FileExplorer.svelte +811 -0
  98. package/dist/components/editor/FileExplorer.svelte.d.ts +67 -0
  99. package/dist/components/editor/FileIcon.svelte +110 -0
  100. package/dist/components/editor/FileIcon.svelte.d.ts +10 -0
  101. package/dist/components/editor/FindReplace.svelte +448 -0
  102. package/dist/components/editor/FindReplace.svelte.d.ts +40 -0
  103. package/dist/components/editor/GhostBracketLayer.svelte +391 -0
  104. package/dist/components/editor/GhostBracketLayer.svelte.d.ts +24 -0
  105. package/dist/components/editor/GitBlameLayer.svelte +436 -0
  106. package/dist/components/editor/GitBlameLayer.svelte.d.ts +18 -0
  107. package/dist/components/editor/InlineDiagnosticsLayer.svelte +540 -0
  108. package/dist/components/editor/InlineDiagnosticsLayer.svelte.d.ts +35 -0
  109. package/dist/components/editor/InlineDiffLayer.svelte +337 -0
  110. package/dist/components/editor/InlineDiffLayer.svelte.d.ts +31 -0
  111. package/dist/components/editor/MinimalEditor.svelte +75 -0
  112. package/dist/components/editor/MinimalEditor.svelte.d.ts +6 -0
  113. package/dist/components/editor/MinimalEditor2.svelte +84 -0
  114. package/dist/components/editor/MinimalEditor2.svelte.d.ts +6 -0
  115. package/dist/components/editor/Minimap.svelte +327 -0
  116. package/dist/components/editor/Minimap.svelte.d.ts +34 -0
  117. package/dist/components/editor/PluginPreviewSandbox.svelte +793 -0
  118. package/dist/components/editor/PluginPreviewSandbox.svelte.d.ts +49 -0
  119. package/dist/components/editor/ProblemsPanel.svelte +628 -0
  120. package/dist/components/editor/ProblemsPanel.svelte.d.ts +25 -0
  121. package/dist/components/editor/QuickActionsMenu.svelte +403 -0
  122. package/dist/components/editor/QuickActionsMenu.svelte.d.ts +18 -0
  123. package/dist/components/editor/SnippetPalette.svelte +530 -0
  124. package/dist/components/editor/SnippetPalette.svelte.d.ts +16 -0
  125. package/dist/components/editor/StructureMap.svelte +431 -0
  126. package/dist/components/editor/StructureMap.svelte.d.ts +37 -0
  127. package/dist/components/editor/SymbolOutline.svelte +722 -0
  128. package/dist/components/editor/SymbolOutline.svelte.d.ts +44 -0
  129. package/dist/components/editor/TimelineScrubber.svelte +470 -0
  130. package/dist/components/editor/TimelineScrubber.svelte.d.ts +40 -0
  131. package/dist/components/editor/TokenRenderer.svelte +69 -0
  132. package/dist/components/editor/TokenRenderer.svelte.d.ts +15 -0
  133. package/dist/components/editor/constants.d.ts +32 -0
  134. package/dist/components/editor/constants.js +36 -0
  135. package/dist/components/editor/core/ai-awareness.d.ts +176 -0
  136. package/dist/components/editor/core/ai-awareness.js +210 -0
  137. package/dist/components/editor/core/bracket-healer.d.ts +189 -0
  138. package/dist/components/editor/core/bracket-healer.js +406 -0
  139. package/dist/components/editor/core/breakpoints.d.ts +203 -0
  140. package/dist/components/editor/core/breakpoints.js +414 -0
  141. package/dist/components/editor/core/commands.d.ts +108 -0
  142. package/dist/components/editor/core/commands.js +246 -0
  143. package/dist/components/editor/core/complexity-analyzer.d.ts +123 -0
  144. package/dist/components/editor/core/complexity-analyzer.js +376 -0
  145. package/dist/components/editor/core/conflict-predictor.d.ts +135 -0
  146. package/dist/components/editor/core/conflict-predictor.js +316 -0
  147. package/dist/components/editor/core/crdt-binding.d.ts +118 -0
  148. package/dist/components/editor/core/crdt-binding.js +286 -0
  149. package/dist/components/editor/core/diagnostics.d.ts +210 -0
  150. package/dist/components/editor/core/diagnostics.js +335 -0
  151. package/dist/components/editor/core/echo-cursor.d.ts +201 -0
  152. package/dist/components/editor/core/echo-cursor.js +267 -0
  153. package/dist/components/editor/core/folding.d.ts +124 -0
  154. package/dist/components/editor/core/folding.js +672 -0
  155. package/dist/components/editor/core/ghost-pair.d.ts +122 -0
  156. package/dist/components/editor/core/ghost-pair.js +221 -0
  157. package/dist/components/editor/core/git-blame.d.ts +170 -0
  158. package/dist/components/editor/core/git-blame.js +324 -0
  159. package/dist/components/editor/core/index.d.ts +26 -0
  160. package/dist/components/editor/core/index.js +24 -0
  161. package/dist/components/editor/core/keybindings.d.ts +79 -0
  162. package/dist/components/editor/core/keybindings.js +357 -0
  163. package/dist/components/editor/core/multi-cursor.d.ts +196 -0
  164. package/dist/components/editor/core/multi-cursor.js +521 -0
  165. package/dist/components/editor/core/navigation.d.ts +107 -0
  166. package/dist/components/editor/core/navigation.js +408 -0
  167. package/dist/components/editor/core/quick-actions.d.ts +189 -0
  168. package/dist/components/editor/core/quick-actions.js +427 -0
  169. package/dist/components/editor/core/search.d.ts +88 -0
  170. package/dist/components/editor/core/search.js +192 -0
  171. package/dist/components/editor/core/semantic-analyzer.d.ts +77 -0
  172. package/dist/components/editor/core/semantic-analyzer.js +424 -0
  173. package/dist/components/editor/core/snippet-manager.d.ts +202 -0
  174. package/dist/components/editor/core/snippet-manager.js +565 -0
  175. package/dist/components/editor/core/state.d.ts +367 -0
  176. package/dist/components/editor/core/state.js +900 -0
  177. package/dist/components/editor/core/timeline.d.ts +204 -0
  178. package/dist/components/editor/core/timeline.js +349 -0
  179. package/dist/components/editor/editor-find.d.ts +56 -0
  180. package/dist/components/editor/editor-find.js +148 -0
  181. package/dist/components/editor/editor-input.d.ts +77 -0
  182. package/dist/components/editor/editor-input.js +445 -0
  183. package/dist/components/editor/editor-multicursor.d.ts +21 -0
  184. package/dist/components/editor/editor-multicursor.js +196 -0
  185. package/dist/components/editor/editor-scroll.d.ts +14 -0
  186. package/dist/components/editor/editor-scroll.js +34 -0
  187. package/dist/components/editor/index.d.ts +15 -0
  188. package/dist/components/editor/index.js +21 -0
  189. package/dist/components/editor/languages.d.ts +62 -0
  190. package/dist/components/editor/languages.js +285 -0
  191. package/dist/components/editor/theme.d.ts +88 -0
  192. package/dist/components/editor/theme.js +139 -0
  193. package/dist/components/editor/tokenizer/base.d.ts +40 -0
  194. package/dist/components/editor/tokenizer/base.js +203 -0
  195. package/dist/components/editor/tokenizer/index.d.ts +56 -0
  196. package/dist/components/editor/tokenizer/index.js +215 -0
  197. package/dist/components/editor/tokenizer/languages/css.d.ts +17 -0
  198. package/dist/components/editor/tokenizer/languages/css.js +194 -0
  199. package/dist/components/editor/tokenizer/languages/go.d.ts +17 -0
  200. package/dist/components/editor/tokenizer/languages/go.js +220 -0
  201. package/dist/components/editor/tokenizer/languages/html.d.ts +24 -0
  202. package/dist/components/editor/tokenizer/languages/html.js +145 -0
  203. package/dist/components/editor/tokenizer/languages/javascript.d.ts +56 -0
  204. package/dist/components/editor/tokenizer/languages/javascript.js +452 -0
  205. package/dist/components/editor/tokenizer/languages/json.d.ts +12 -0
  206. package/dist/components/editor/tokenizer/languages/json.js +91 -0
  207. package/dist/components/editor/tokenizer/languages/markdown.d.ts +16 -0
  208. package/dist/components/editor/tokenizer/languages/markdown.js +156 -0
  209. package/dist/components/editor/tokenizer/languages/python.d.ts +20 -0
  210. package/dist/components/editor/tokenizer/languages/python.js +227 -0
  211. package/dist/components/editor/tokenizer/languages/svelte.d.ts +40 -0
  212. package/dist/components/editor/tokenizer/languages/svelte.js +326 -0
  213. package/dist/components/editor/tokenizer/types.d.ts +86 -0
  214. package/dist/components/editor/tokenizer/types.js +4 -0
  215. package/dist/components/layout/IDELayout.svelte +274 -0
  216. package/dist/components/layout/IDELayout.svelte.d.ts +29 -0
  217. package/dist/components/layout/StatusBar.svelte +511 -0
  218. package/dist/components/layout/StatusBar.svelte.d.ts +47 -0
  219. package/dist/components/layout/index.d.ts +2 -0
  220. package/dist/components/layout/index.js +3 -0
  221. package/dist/components/lsp/AutocompleteWidget.svelte +364 -0
  222. package/dist/components/lsp/AutocompleteWidget.svelte.d.ts +33 -0
  223. package/dist/components/lsp/DiagnosticMarker.svelte +166 -0
  224. package/dist/components/lsp/DiagnosticMarker.svelte.d.ts +19 -0
  225. package/dist/components/lsp/DiagnosticsPanel.svelte +388 -0
  226. package/dist/components/lsp/DiagnosticsPanel.svelte.d.ts +21 -0
  227. package/dist/components/lsp/HoverTooltip.svelte +274 -0
  228. package/dist/components/lsp/HoverTooltip.svelte.d.ts +24 -0
  229. package/dist/components/lsp/LSPEditor.svelte +486 -0
  230. package/dist/components/lsp/LSPEditor.svelte.d.ts +39 -0
  231. package/dist/components/lsp/SignatureHelpWidget.svelte +216 -0
  232. package/dist/components/lsp/SignatureHelpWidget.svelte.d.ts +22 -0
  233. package/dist/components/lsp/index.d.ts +6 -0
  234. package/dist/components/lsp/index.js +7 -0
  235. package/dist/components/plugins/PluginCard.svelte +153 -0
  236. package/dist/components/plugins/PluginCard.svelte.d.ts +19 -0
  237. package/dist/components/plugins/PluginPanel.svelte +280 -0
  238. package/dist/components/plugins/PluginPanel.svelte.d.ts +8 -0
  239. package/dist/components/plugins/PluginProposalForm.svelte +250 -0
  240. package/dist/components/plugins/PluginProposalForm.svelte.d.ts +6 -0
  241. package/dist/components/plugins/PluginStatusBadge.svelte +14 -0
  242. package/dist/components/plugins/PluginStatusBadge.svelte.d.ts +8 -0
  243. package/dist/components/plugins/index.d.ts +4 -0
  244. package/dist/components/plugins/index.js +5 -0
  245. package/dist/components/vfs/LockConflictDialog.svelte +705 -0
  246. package/dist/components/vfs/LockConflictDialog.svelte.d.ts +21 -0
  247. package/dist/components/vfs/LockIndicator.svelte +194 -0
  248. package/dist/components/vfs/LockIndicator.svelte.d.ts +29 -0
  249. package/dist/components/vfs/LockOverlay.svelte +344 -0
  250. package/dist/components/vfs/LockOverlay.svelte.d.ts +17 -0
  251. package/dist/components/vfs/VersionConflictDialog.svelte +549 -0
  252. package/dist/components/vfs/VersionConflictDialog.svelte.d.ts +24 -0
  253. package/dist/components/vfs/index.d.ts +4 -0
  254. package/dist/components/vfs/index.js +5 -0
  255. package/dist/crdt/awareness.d.ts +42 -0
  256. package/dist/crdt/awareness.js +109 -0
  257. package/dist/crdt/document.d.ts +101 -0
  258. package/dist/crdt/document.js +187 -0
  259. package/dist/crdt/index.d.ts +9 -0
  260. package/dist/crdt/index.js +8 -0
  261. package/dist/crdt/provider.d.ts +85 -0
  262. package/dist/crdt/provider.js +150 -0
  263. package/dist/crdt/types.d.ts +61 -0
  264. package/dist/crdt/types.js +4 -0
  265. package/dist/crdt/undo.d.ts +34 -0
  266. package/dist/crdt/undo.js +70 -0
  267. package/dist/index.d.ts +277 -0
  268. package/dist/index.js +280 -0
  269. package/dist/plugins/index.d.ts +103 -0
  270. package/dist/plugins/index.js +153 -0
  271. package/dist/services/error-handling.d.ts +95 -0
  272. package/dist/services/error-handling.js +413 -0
  273. package/dist/services/ide-integration.d.ts +83 -0
  274. package/dist/services/ide-integration.js +367 -0
  275. package/dist/services/lsp-client.d.ts +69 -0
  276. package/dist/services/lsp-client.js +667 -0
  277. package/dist/services/mock-ai.d.ts +37 -0
  278. package/dist/services/mock-ai.js +318 -0
  279. package/dist/services/optimistic.d.ts +141 -0
  280. package/dist/services/optimistic.js +367 -0
  281. package/dist/services/vfs-client.d.ts +81 -0
  282. package/dist/services/vfs-client.js +348 -0
  283. package/dist/stores/agents.svelte.d.ts +85 -0
  284. package/dist/stores/agents.svelte.js +459 -0
  285. package/dist/stores/ai-persistence.svelte.d.ts +76 -0
  286. package/dist/stores/ai-persistence.svelte.js +334 -0
  287. package/dist/stores/ai.svelte.d.ts +140 -0
  288. package/dist/stores/ai.svelte.js +383 -0
  289. package/dist/stores/collaboration.svelte.d.ts +164 -0
  290. package/dist/stores/collaboration.svelte.js +334 -0
  291. package/dist/stores/editor.svelte.d.ts +131 -0
  292. package/dist/stores/editor.svelte.js +250 -0
  293. package/dist/stores/index.d.ts +10 -0
  294. package/dist/stores/index.js +29 -0
  295. package/dist/stores/layout.svelte.d.ts +171 -0
  296. package/dist/stores/layout.svelte.js +351 -0
  297. package/dist/stores/plugin.svelte.d.ts +121 -0
  298. package/dist/stores/plugin.svelte.js +410 -0
  299. package/dist/stores/vfs.svelte.d.ts +123 -0
  300. package/dist/stores/vfs.svelte.js +680 -0
  301. package/dist/styles/theme.css +623 -0
  302. package/dist/types/agents.d.ts +127 -0
  303. package/dist/types/agents.js +5 -0
  304. package/dist/types/ai.d.ts +137 -0
  305. package/dist/types/ai.js +4 -0
  306. package/dist/types/crdt.d.ts +222 -0
  307. package/dist/types/crdt.js +5 -0
  308. package/dist/types/editor.d.ts +52 -0
  309. package/dist/types/editor.js +18 -0
  310. package/dist/types/events.d.ts +133 -0
  311. package/dist/types/events.js +4 -0
  312. package/dist/types/filesystem.d.ts +77 -0
  313. package/dist/types/filesystem.js +4 -0
  314. package/dist/types/index.d.ts +9 -0
  315. package/dist/types/index.js +12 -0
  316. package/dist/types/lsp.d.ts +691 -0
  317. package/dist/types/lsp.js +108 -0
  318. package/dist/types/plugin.d.ts +239 -0
  319. package/dist/types/plugin.js +5 -0
  320. package/dist/types/vfs.d.ts +191 -0
  321. package/dist/types/vfs.js +18 -0
  322. package/dist/utils/format.d.ts +55 -0
  323. package/dist/utils/format.js +152 -0
  324. package/dist/utils/index.d.ts +3 -0
  325. package/dist/utils/index.js +4 -0
  326. package/dist/utils/keybindings.d.ts +33 -0
  327. package/dist/utils/keybindings.js +171 -0
  328. package/dist/utils/language.d.ts +27 -0
  329. package/dist/utils/language.js +222 -0
  330. package/package.json +178 -0
@@ -0,0 +1,334 @@
1
+ /**
2
+ * Collaboration store using Svelte 5 runes
3
+ * Manages CRDT-based real-time collaboration
4
+ *
5
+ * Note: Svelte 5 modules cannot directly export $derived values.
6
+ * We use getter functions to expose reactive derived state.
7
+ */
8
+ // Reactive state
9
+ let state = $state({
10
+ config: null,
11
+ status: 'disconnected',
12
+ error: null,
13
+ synced: false,
14
+ users: [],
15
+ cursors: new Map(),
16
+ awareness: new Map(),
17
+ aiSessions: [],
18
+ pendingChanges: [],
19
+ snapshots: [],
20
+ localUser: null
21
+ });
22
+ // Event handlers
23
+ const eventHandlers = new Set();
24
+ // Getter functions for derived values (Svelte 5 module-safe)
25
+ export function getConfig() {
26
+ return state.config;
27
+ }
28
+ export function getStatus() {
29
+ return state.status;
30
+ }
31
+ export function getError() {
32
+ return state.error;
33
+ }
34
+ export function getSynced() {
35
+ return state.synced;
36
+ }
37
+ export function getUsers() {
38
+ return state.users;
39
+ }
40
+ export function getCursors() {
41
+ return Array.from(state.cursors.values());
42
+ }
43
+ export function getAwareness() {
44
+ return Array.from(state.awareness.values());
45
+ }
46
+ export function getAISessions() {
47
+ return state.aiSessions;
48
+ }
49
+ export function getActiveAISessions() {
50
+ return state.aiSessions.filter((s) => s.status === 'active');
51
+ }
52
+ export function getPendingChanges() {
53
+ return state.pendingChanges;
54
+ }
55
+ export function getSnapshots() {
56
+ return state.snapshots;
57
+ }
58
+ export function getLocalUser() {
59
+ return state.localUser;
60
+ }
61
+ export function getIsConnected() {
62
+ return state.status === 'connected';
63
+ }
64
+ export function getOtherUsers() {
65
+ return state.users.filter((u) => u.id !== state.localUser?.id);
66
+ }
67
+ // Legacy aliases for backward compatibility
68
+ export const config = { get current() { return getConfig(); } };
69
+ export const status = { get current() { return getStatus(); } };
70
+ export const error = { get current() { return getError(); } };
71
+ export const synced = { get current() { return getSynced(); } };
72
+ export const users = { get current() { return getUsers(); } };
73
+ export const cursors = { get current() { return getCursors(); } };
74
+ export const awareness = { get current() { return getAwareness(); } };
75
+ export const aiSessions = { get current() { return getAISessions(); } };
76
+ export const activeAISessions = { get current() { return getActiveAISessions(); } };
77
+ export const pendingChanges = { get current() { return getPendingChanges(); } };
78
+ export const snapshots = { get current() { return getSnapshots(); } };
79
+ export const localUser = { get current() { return getLocalUser(); } };
80
+ export const isConnected = { get current() { return getIsConnected(); } };
81
+ export const otherUsers = { get current() { return getOtherUsers(); } };
82
+ // Collaboration colors for cursors
83
+ const CURSOR_COLORS = [
84
+ 'var(--ide-collab-cursor-1)',
85
+ 'var(--ide-collab-cursor-2)',
86
+ 'var(--ide-collab-cursor-3)',
87
+ 'var(--ide-collab-cursor-4)',
88
+ 'var(--ide-collab-cursor-5)'
89
+ ];
90
+ /**
91
+ * Initialize collaboration with config
92
+ */
93
+ export function initialize(collabConfig) {
94
+ state.config = collabConfig;
95
+ state.localUser = collabConfig.user;
96
+ state.status = 'connecting';
97
+ }
98
+ /**
99
+ * Set connection status
100
+ */
101
+ export function setStatus(newStatus, errorMsg) {
102
+ state.status = newStatus;
103
+ state.error = errorMsg ?? null;
104
+ if (newStatus === 'connected') {
105
+ emitEvent({ type: 'connected', users: state.users });
106
+ }
107
+ else if (newStatus === 'disconnected') {
108
+ emitEvent({ type: 'disconnected', reason: errorMsg });
109
+ }
110
+ }
111
+ /**
112
+ * Set synced state
113
+ */
114
+ export function setSynced(syncedState) {
115
+ state.synced = syncedState;
116
+ }
117
+ /**
118
+ * Add a user to the session
119
+ */
120
+ export function addUser(user) {
121
+ // Assign a color if not provided
122
+ if (!user.color) {
123
+ const colorIndex = state.users.length % CURSOR_COLORS.length;
124
+ user = { ...user, color: CURSOR_COLORS[colorIndex] };
125
+ }
126
+ if (!state.users.some((u) => u.id === user.id)) {
127
+ state.users = [...state.users, user];
128
+ emitEvent({ type: 'user_joined', user });
129
+ }
130
+ }
131
+ /**
132
+ * Remove a user from the session
133
+ */
134
+ export function removeUser(userId) {
135
+ state.users = state.users.filter((u) => u.id !== userId);
136
+ state.cursors.delete(userId);
137
+ state.awareness.delete(userId);
138
+ emitEvent({ type: 'user_left', userId });
139
+ }
140
+ /**
141
+ * Update cursor position for a user
142
+ */
143
+ export function updateCursor(cursor) {
144
+ state.cursors.set(cursor.userId, cursor);
145
+ emitEvent({ type: 'cursor_moved', cursor });
146
+ }
147
+ /**
148
+ * Update awareness for a user
149
+ */
150
+ export function updateAwareness(awarenessData) {
151
+ state.awareness.set(awarenessData.userId, awarenessData);
152
+ }
153
+ /**
154
+ * Update local user's cursor
155
+ */
156
+ export function setLocalCursor(position, selection) {
157
+ if (!state.localUser)
158
+ return;
159
+ const cursor = {
160
+ userId: state.localUser.id,
161
+ user: state.localUser,
162
+ position,
163
+ selection,
164
+ lastActivity: new Date()
165
+ };
166
+ state.cursors.set(state.localUser.id, cursor);
167
+ }
168
+ /**
169
+ * Update local user's awareness
170
+ */
171
+ export function setLocalAwareness(updates) {
172
+ if (!state.localUser)
173
+ return;
174
+ const current = state.awareness.get(state.localUser.id);
175
+ const awarenessData = {
176
+ ...current,
177
+ userId: state.localUser.id,
178
+ user: state.localUser,
179
+ state: 'active',
180
+ ...updates
181
+ };
182
+ state.awareness.set(state.localUser.id, awarenessData);
183
+ }
184
+ /**
185
+ * Start an AI collaboration session
186
+ */
187
+ export function startAISession(documentId, aiUser) {
188
+ const id = crypto.randomUUID();
189
+ const session = {
190
+ id,
191
+ documentId,
192
+ status: 'pending',
193
+ aiUser: { ...aiUser, isAI: true, color: 'var(--ide-collab-ai)' },
194
+ humanUsers: state.users.filter((u) => !u.isAI),
195
+ startedAt: new Date(),
196
+ updatedAt: new Date()
197
+ };
198
+ state.aiSessions = [...state.aiSessions, session];
199
+ // Add AI as a user
200
+ addUser(session.aiUser);
201
+ emitEvent({ type: 'ai_edit_started', session });
202
+ return id;
203
+ }
204
+ /**
205
+ * Update AI session status
206
+ */
207
+ export function updateAISession(sessionId, updates) {
208
+ state.aiSessions = state.aiSessions.map((s) => s.id === sessionId ? { ...s, ...updates, updatedAt: new Date() } : s);
209
+ }
210
+ /**
211
+ * Set current task for AI session
212
+ */
213
+ export function setAITask(sessionId, task) {
214
+ updateAISession(sessionId, { currentTask: task, status: 'active' });
215
+ }
216
+ /**
217
+ * Propose a change from AI
218
+ */
219
+ export function proposeAIChange(sessionId, change) {
220
+ const id = crypto.randomUUID();
221
+ const proposedChange = {
222
+ ...change,
223
+ id,
224
+ sessionId,
225
+ status: 'pending'
226
+ };
227
+ state.pendingChanges = [...state.pendingChanges, proposedChange];
228
+ emitEvent({ type: 'ai_edit_proposed', change: proposedChange });
229
+ return id;
230
+ }
231
+ /**
232
+ * Review an AI proposed change
233
+ */
234
+ export function reviewAIChange(changeId, approved, reviewerId) {
235
+ state.pendingChanges = state.pendingChanges.map((c) => c.id === changeId
236
+ ? {
237
+ ...c,
238
+ status: approved ? 'approved' : 'rejected',
239
+ reviewedBy: reviewerId,
240
+ reviewedAt: new Date()
241
+ }
242
+ : c);
243
+ }
244
+ /**
245
+ * Complete an AI session
246
+ */
247
+ export function completeAISession(sessionId) {
248
+ const session = state.aiSessions.find((s) => s.id === sessionId);
249
+ if (!session)
250
+ return;
251
+ updateAISession(sessionId, { status: 'completed' });
252
+ // Remove AI user
253
+ removeUser(session.aiUser.id);
254
+ // Clear pending changes for this session
255
+ state.pendingChanges = state.pendingChanges.filter((c) => c.sessionId !== sessionId);
256
+ emitEvent({ type: 'ai_edit_completed', sessionId });
257
+ }
258
+ /**
259
+ * Cancel an AI session
260
+ */
261
+ export function cancelAISession(sessionId) {
262
+ const session = state.aiSessions.find((s) => s.id === sessionId);
263
+ if (!session)
264
+ return;
265
+ updateAISession(sessionId, { status: 'cancelled' });
266
+ removeUser(session.aiUser.id);
267
+ // Reject all pending changes for this session
268
+ state.pendingChanges = state.pendingChanges.map((c) => c.sessionId === sessionId ? { ...c, status: 'rejected' } : c);
269
+ }
270
+ /**
271
+ * Create a document snapshot
272
+ */
273
+ export function createSnapshot(documentId, content, reason = 'manual') {
274
+ const id = crypto.randomUUID();
275
+ const snapshot = {
276
+ id,
277
+ documentId,
278
+ content,
279
+ version: state.snapshots.filter((s) => s.documentId === documentId).length + 1,
280
+ createdAt: new Date(),
281
+ createdBy: state.localUser,
282
+ reason
283
+ };
284
+ state.snapshots = [...state.snapshots, snapshot];
285
+ emitEvent({ type: 'snapshot_created', snapshot });
286
+ return id;
287
+ }
288
+ /**
289
+ * Get snapshots for a document
290
+ */
291
+ export function getDocumentSnapshots(documentId) {
292
+ return state.snapshots.filter((s) => s.documentId === documentId);
293
+ }
294
+ /**
295
+ * Subscribe to collaboration events
296
+ */
297
+ export function onEvent(handler) {
298
+ eventHandlers.add(handler);
299
+ return () => eventHandlers.delete(handler);
300
+ }
301
+ /**
302
+ * Emit a collaboration event
303
+ */
304
+ function emitEvent(event) {
305
+ eventHandlers.forEach((handler) => handler(event));
306
+ }
307
+ /**
308
+ * Disconnect and cleanup
309
+ */
310
+ export function disconnect() {
311
+ state.status = 'disconnected';
312
+ state.users = [];
313
+ state.cursors.clear();
314
+ state.awareness.clear();
315
+ state.synced = false;
316
+ }
317
+ /**
318
+ * Reset collaboration state
319
+ */
320
+ export function reset() {
321
+ disconnect();
322
+ state.config = null;
323
+ state.localUser = null;
324
+ state.aiSessions = [];
325
+ state.pendingChanges = [];
326
+ state.snapshots = [];
327
+ state.error = null;
328
+ }
329
+ /**
330
+ * Get user color by index
331
+ */
332
+ export function getUserColor(index) {
333
+ return CURSOR_COLORS[index % CURSOR_COLORS.length];
334
+ }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Editor store using Svelte 5 runes
3
+ * Manages tabs, active file, and editor preferences
4
+ *
5
+ * Note: Svelte 5 modules cannot directly export $derived values.
6
+ * We use getter functions to expose reactive derived state.
7
+ */
8
+ import type { EditorTab, EditorPreferences, SplitMode, CursorPosition } from '../types';
9
+ export declare function getTabs(): EditorTab[];
10
+ export declare function getActiveTabId(): string | null;
11
+ export declare function getActiveTab(): EditorTab | null;
12
+ export declare function getSplitMode(): SplitMode;
13
+ export declare function getPreferences(): EditorPreferences;
14
+ export declare function getRecentFiles(): string[];
15
+ export declare function getLoading(): boolean;
16
+ export declare function getError(): string | null;
17
+ export declare function getDirtyTabs(): EditorTab[];
18
+ export declare function getHasDirtyTabs(): boolean;
19
+ export declare const tabs: {
20
+ readonly current: EditorTab[];
21
+ };
22
+ export declare const activeTabId: {
23
+ readonly current: string | null;
24
+ };
25
+ export declare const activeTab: {
26
+ readonly current: EditorTab | null;
27
+ };
28
+ export declare const splitMode: {
29
+ readonly current: SplitMode;
30
+ };
31
+ export declare const preferences: {
32
+ readonly current: EditorPreferences;
33
+ };
34
+ export declare const recentFiles: {
35
+ readonly current: string[];
36
+ };
37
+ export declare const loading: {
38
+ readonly current: boolean;
39
+ };
40
+ export declare const error: {
41
+ readonly current: string | null;
42
+ };
43
+ export declare const dirtyTabs: {
44
+ readonly current: EditorTab[];
45
+ };
46
+ export declare const hasDirtyTabs: {
47
+ readonly current: boolean;
48
+ };
49
+ /**
50
+ * Open a file in a new tab or focus existing tab
51
+ */
52
+ export declare function openFile(path: string, content: string, options?: {
53
+ language?: string;
54
+ focus?: boolean;
55
+ }): string;
56
+ /**
57
+ * Close a tab by ID
58
+ */
59
+ export declare function closeTab(tabId: string): boolean;
60
+ /**
61
+ * Force close a tab, ignoring dirty state
62
+ */
63
+ export declare function forceCloseTab(tabId: string): void;
64
+ /**
65
+ * Close all tabs
66
+ */
67
+ export declare function closeAllTabs(force?: boolean): boolean;
68
+ /**
69
+ * Close other tabs (keep the specified one)
70
+ */
71
+ export declare function closeOtherTabs(keepTabId: string, force?: boolean): boolean;
72
+ /**
73
+ * Set the active tab
74
+ */
75
+ export declare function setActiveTab(tabId: string): void;
76
+ /**
77
+ * Update content for a tab
78
+ */
79
+ export declare function updateContent(tabId: string, content: string): void;
80
+ /**
81
+ * Mark a tab as saved
82
+ */
83
+ export declare function markSaved(tabId: string, newContent?: string): void;
84
+ /**
85
+ * Update cursor position for a tab
86
+ */
87
+ export declare function updateCursor(tabId: string, position: CursorPosition): void;
88
+ /**
89
+ * Mark a tab as being edited by AI
90
+ */
91
+ export declare function setAIEditing(tabId: string, editing: boolean): void;
92
+ /**
93
+ * Reorder tabs
94
+ */
95
+ export declare function reorderTabs(fromIndex: number, toIndex: number): void;
96
+ /**
97
+ * Set split mode
98
+ */
99
+ export declare function setSplitMode(mode: SplitMode): void;
100
+ /**
101
+ * Update editor preferences
102
+ */
103
+ export declare function updatePreferences(updates: Partial<EditorPreferences>): void;
104
+ /**
105
+ * Reset preferences to defaults
106
+ */
107
+ export declare function resetPreferences(): void;
108
+ /**
109
+ * Get a tab by ID
110
+ */
111
+ export declare function getTab(tabId: string): EditorTab | undefined;
112
+ /**
113
+ * Get a tab by path
114
+ */
115
+ export declare function getTabByPath(path: string): EditorTab | undefined;
116
+ /**
117
+ * Navigate to next tab
118
+ */
119
+ export declare function nextTab(): void;
120
+ /**
121
+ * Navigate to previous tab
122
+ */
123
+ export declare function prevTab(): void;
124
+ /**
125
+ * Set loading state
126
+ */
127
+ export declare function setLoading(loadingState: boolean): void;
128
+ /**
129
+ * Set error state
130
+ */
131
+ export declare function setError(errorState: string | null): void;
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Editor store using Svelte 5 runes
3
+ * Manages tabs, active file, and editor preferences
4
+ *
5
+ * Note: Svelte 5 modules cannot directly export $derived values.
6
+ * We use getter functions to expose reactive derived state.
7
+ */
8
+ import { DEFAULT_EDITOR_PREFERENCES } from '../types';
9
+ import { detectLanguage } from '../utils/language';
10
+ // Reactive state using $state rune
11
+ let state = $state({
12
+ tabs: [],
13
+ activeTabId: null,
14
+ splitMode: 'none',
15
+ preferences: { ...DEFAULT_EDITOR_PREFERENCES },
16
+ recentFiles: [],
17
+ loading: false,
18
+ error: null
19
+ });
20
+ // Getter functions for derived values (Svelte 5 module-safe)
21
+ export function getTabs() {
22
+ return state.tabs;
23
+ }
24
+ export function getActiveTabId() {
25
+ return state.activeTabId;
26
+ }
27
+ export function getActiveTab() {
28
+ return state.tabs.find((t) => t.id === state.activeTabId) ?? null;
29
+ }
30
+ export function getSplitMode() {
31
+ return state.splitMode;
32
+ }
33
+ export function getPreferences() {
34
+ return state.preferences;
35
+ }
36
+ export function getRecentFiles() {
37
+ return state.recentFiles;
38
+ }
39
+ export function getLoading() {
40
+ return state.loading;
41
+ }
42
+ export function getError() {
43
+ return state.error;
44
+ }
45
+ export function getDirtyTabs() {
46
+ return state.tabs.filter((t) => t.isDirty);
47
+ }
48
+ export function getHasDirtyTabs() {
49
+ return state.tabs.some((t) => t.isDirty);
50
+ }
51
+ // Legacy aliases for backward compatibility
52
+ export const tabs = { get current() { return getTabs(); } };
53
+ export const activeTabId = { get current() { return getActiveTabId(); } };
54
+ export const activeTab = { get current() { return getActiveTab(); } };
55
+ export const splitMode = { get current() { return getSplitMode(); } };
56
+ export const preferences = { get current() { return getPreferences(); } };
57
+ export const recentFiles = { get current() { return getRecentFiles(); } };
58
+ export const loading = { get current() { return getLoading(); } };
59
+ export const error = { get current() { return getError(); } };
60
+ export const dirtyTabs = { get current() { return getDirtyTabs(); } };
61
+ export const hasDirtyTabs = { get current() { return getHasDirtyTabs(); } };
62
+ /**
63
+ * Open a file in a new tab or focus existing tab
64
+ */
65
+ export function openFile(path, content, options) {
66
+ const existing = state.tabs.find((t) => t.path === path);
67
+ if (existing) {
68
+ if (options?.focus !== false) {
69
+ state.activeTabId = existing.id;
70
+ }
71
+ return existing.id;
72
+ }
73
+ const name = path.split('/').pop() ?? path;
74
+ const language = options?.language ?? detectLanguage(name);
75
+ const id = crypto.randomUUID();
76
+ const tab = {
77
+ id,
78
+ path,
79
+ name,
80
+ content,
81
+ language,
82
+ isDirty: false,
83
+ cursorPosition: { line: 1, column: 1 }
84
+ };
85
+ state.tabs = [...state.tabs, tab];
86
+ if (options?.focus !== false) {
87
+ state.activeTabId = id;
88
+ }
89
+ // Update recent files
90
+ state.recentFiles = [path, ...state.recentFiles.filter((f) => f !== path)].slice(0, 20);
91
+ return id;
92
+ }
93
+ /**
94
+ * Close a tab by ID
95
+ */
96
+ export function closeTab(tabId) {
97
+ const index = state.tabs.findIndex((t) => t.id === tabId);
98
+ if (index === -1)
99
+ return false;
100
+ const tab = state.tabs[index];
101
+ if (tab.isDirty) {
102
+ // Could prompt for save here - returning false indicates unsaved changes
103
+ return false;
104
+ }
105
+ state.tabs = state.tabs.filter((t) => t.id !== tabId);
106
+ // Update active tab if we closed the active one
107
+ if (state.activeTabId === tabId) {
108
+ const newIndex = Math.min(index, state.tabs.length - 1);
109
+ state.activeTabId = state.tabs[newIndex]?.id ?? null;
110
+ }
111
+ return true;
112
+ }
113
+ /**
114
+ * Force close a tab, ignoring dirty state
115
+ */
116
+ export function forceCloseTab(tabId) {
117
+ const index = state.tabs.findIndex((t) => t.id === tabId);
118
+ if (index === -1)
119
+ return;
120
+ state.tabs = state.tabs.filter((t) => t.id !== tabId);
121
+ if (state.activeTabId === tabId) {
122
+ const newIndex = Math.min(index, state.tabs.length - 1);
123
+ state.activeTabId = state.tabs[newIndex]?.id ?? null;
124
+ }
125
+ }
126
+ /**
127
+ * Close all tabs
128
+ */
129
+ export function closeAllTabs(force = false) {
130
+ if (!force && state.tabs.some((t) => t.isDirty)) {
131
+ return false;
132
+ }
133
+ state.tabs = [];
134
+ state.activeTabId = null;
135
+ return true;
136
+ }
137
+ /**
138
+ * Close other tabs (keep the specified one)
139
+ */
140
+ export function closeOtherTabs(keepTabId, force = false) {
141
+ if (!force && state.tabs.some((t) => t.id !== keepTabId && t.isDirty)) {
142
+ return false;
143
+ }
144
+ state.tabs = state.tabs.filter((t) => t.id === keepTabId);
145
+ state.activeTabId = keepTabId;
146
+ return true;
147
+ }
148
+ /**
149
+ * Set the active tab
150
+ */
151
+ export function setActiveTab(tabId) {
152
+ if (state.tabs.some((t) => t.id === tabId)) {
153
+ state.activeTabId = tabId;
154
+ }
155
+ }
156
+ /**
157
+ * Update content for a tab
158
+ */
159
+ export function updateContent(tabId, content) {
160
+ state.tabs = state.tabs.map((t) => t.id === tabId ? { ...t, content, isDirty: t.content !== content || t.isDirty } : t);
161
+ }
162
+ /**
163
+ * Mark a tab as saved
164
+ */
165
+ export function markSaved(tabId, newContent) {
166
+ state.tabs = state.tabs.map((t) => t.id === tabId ? { ...t, isDirty: false, content: newContent ?? t.content } : t);
167
+ }
168
+ /**
169
+ * Update cursor position for a tab
170
+ */
171
+ export function updateCursor(tabId, position) {
172
+ state.tabs = state.tabs.map((t) => (t.id === tabId ? { ...t, cursorPosition: position } : t));
173
+ }
174
+ /**
175
+ * Mark a tab as being edited by AI
176
+ */
177
+ export function setAIEditing(tabId, editing) {
178
+ state.tabs = state.tabs.map((t) => (t.id === tabId ? { ...t, aiEditing: editing } : t));
179
+ }
180
+ /**
181
+ * Reorder tabs
182
+ */
183
+ export function reorderTabs(fromIndex, toIndex) {
184
+ const newTabs = [...state.tabs];
185
+ const [removed] = newTabs.splice(fromIndex, 1);
186
+ newTabs.splice(toIndex, 0, removed);
187
+ state.tabs = newTabs;
188
+ }
189
+ /**
190
+ * Set split mode
191
+ */
192
+ export function setSplitMode(mode) {
193
+ state.splitMode = mode;
194
+ }
195
+ /**
196
+ * Update editor preferences
197
+ */
198
+ export function updatePreferences(updates) {
199
+ state.preferences = { ...state.preferences, ...updates };
200
+ }
201
+ /**
202
+ * Reset preferences to defaults
203
+ */
204
+ export function resetPreferences() {
205
+ state.preferences = { ...DEFAULT_EDITOR_PREFERENCES };
206
+ }
207
+ /**
208
+ * Get a tab by ID
209
+ */
210
+ export function getTab(tabId) {
211
+ return state.tabs.find((t) => t.id === tabId);
212
+ }
213
+ /**
214
+ * Get a tab by path
215
+ */
216
+ export function getTabByPath(path) {
217
+ return state.tabs.find((t) => t.path === path);
218
+ }
219
+ /**
220
+ * Navigate to next tab
221
+ */
222
+ export function nextTab() {
223
+ if (state.tabs.length === 0)
224
+ return;
225
+ const currentIndex = state.tabs.findIndex((t) => t.id === state.activeTabId);
226
+ const nextIndex = (currentIndex + 1) % state.tabs.length;
227
+ state.activeTabId = state.tabs[nextIndex].id;
228
+ }
229
+ /**
230
+ * Navigate to previous tab
231
+ */
232
+ export function prevTab() {
233
+ if (state.tabs.length === 0)
234
+ return;
235
+ const currentIndex = state.tabs.findIndex((t) => t.id === state.activeTabId);
236
+ const prevIndex = (currentIndex - 1 + state.tabs.length) % state.tabs.length;
237
+ state.activeTabId = state.tabs[prevIndex].id;
238
+ }
239
+ /**
240
+ * Set loading state
241
+ */
242
+ export function setLoading(loadingState) {
243
+ state.loading = loadingState;
244
+ }
245
+ /**
246
+ * Set error state
247
+ */
248
+ export function setError(errorState) {
249
+ state.error = errorState;
250
+ }