@almadar/shell-web 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. package/bundling.d.mts +18 -0
  2. package/bundling.mjs +28 -0
  3. package/dist/ArbitraryClassCompiler-Mzabq-UB.d.ts +100 -0
  4. package/dist/AvlGlyph-JKJOAH23.js +6 -0
  5. package/dist/AvlStateMachine-PI4YGREK.js +8 -0
  6. package/dist/AvlTransitionDetail-ZH7V24UG.js +12 -0
  7. package/dist/AvlTransitionExplainer-ZSRT7L6Y.js +13 -0
  8. package/dist/BehaviorValueFrame-6RUJXT4A.js +29 -0
  9. package/dist/BehaviorValueFrame-SSEMEBTG.css +1756 -0
  10. package/dist/BehaviorView-RFEE5J6E.js +10 -0
  11. package/dist/Canvas3DHost-_Y-5uLM_.d.ts +552 -0
  12. package/dist/EventBusProvider-CVwjkV_2.d.ts +284 -0
  13. package/dist/FileTree-BCFnBEuQ.d.ts +254 -0
  14. package/dist/FlowCanvas-3JRMNJLV.css +1756 -0
  15. package/dist/FlowCanvas-STDC4OWK.js +27 -0
  16. package/dist/GameAudioProvider-Cm9BnvmP.d.ts +93 -0
  17. package/dist/KaTeX_AMS-Regular-CYEKBG2K.woff +0 -0
  18. package/dist/KaTeX_AMS-Regular-JKX5W2C4.ttf +0 -0
  19. package/dist/KaTeX_AMS-Regular-U6PRYMIZ.woff2 +0 -0
  20. package/dist/KaTeX_Caligraphic-Bold-5QL5CMTE.woff2 +0 -0
  21. package/dist/KaTeX_Caligraphic-Bold-WZ3QSGD3.woff +0 -0
  22. package/dist/KaTeX_Caligraphic-Bold-ZTS3R3HK.ttf +0 -0
  23. package/dist/KaTeX_Caligraphic-Regular-3LKEU76G.woff +0 -0
  24. package/dist/KaTeX_Caligraphic-Regular-A7XRTZ5Q.ttf +0 -0
  25. package/dist/KaTeX_Caligraphic-Regular-KX5MEWCF.woff2 +0 -0
  26. package/dist/KaTeX_Fraktur-Bold-2QVFK6NQ.woff2 +0 -0
  27. package/dist/KaTeX_Fraktur-Bold-T4SWXBMT.woff +0 -0
  28. package/dist/KaTeX_Fraktur-Bold-WGHVTYOR.ttf +0 -0
  29. package/dist/KaTeX_Fraktur-Regular-2PEIFJSJ.woff2 +0 -0
  30. package/dist/KaTeX_Fraktur-Regular-5U4OPH2X.ttf +0 -0
  31. package/dist/KaTeX_Fraktur-Regular-PQMHCIK6.woff +0 -0
  32. package/dist/KaTeX_Main-Bold-2GA4IZIN.woff +0 -0
  33. package/dist/KaTeX_Main-Bold-W5FBVCZM.ttf +0 -0
  34. package/dist/KaTeX_Main-Bold-YP5VVQRP.woff2 +0 -0
  35. package/dist/KaTeX_Main-BoldItalic-4P4C7HJH.woff +0 -0
  36. package/dist/KaTeX_Main-BoldItalic-N4V3DX7S.woff2 +0 -0
  37. package/dist/KaTeX_Main-BoldItalic-ODMLBJJQ.ttf +0 -0
  38. package/dist/KaTeX_Main-Italic-I43T2HSR.ttf +0 -0
  39. package/dist/KaTeX_Main-Italic-RELBIK7M.woff2 +0 -0
  40. package/dist/KaTeX_Main-Italic-SASNQFN2.woff +0 -0
  41. package/dist/KaTeX_Main-Regular-ARRPAO67.woff2 +0 -0
  42. package/dist/KaTeX_Main-Regular-P5I74A2A.woff +0 -0
  43. package/dist/KaTeX_Main-Regular-W74P5G27.ttf +0 -0
  44. package/dist/KaTeX_Math-BoldItalic-6EBV3DK5.woff +0 -0
  45. package/dist/KaTeX_Math-BoldItalic-K4WTGH3J.woff2 +0 -0
  46. package/dist/KaTeX_Math-BoldItalic-VB447A4D.ttf +0 -0
  47. package/dist/KaTeX_Math-Italic-6KGCHLFN.woff2 +0 -0
  48. package/dist/KaTeX_Math-Italic-KKK3USB2.woff +0 -0
  49. package/dist/KaTeX_Math-Italic-SON4MRCA.ttf +0 -0
  50. package/dist/KaTeX_SansSerif-Bold-RRNVJFFW.woff2 +0 -0
  51. package/dist/KaTeX_SansSerif-Bold-STQ6RXC7.ttf +0 -0
  52. package/dist/KaTeX_SansSerif-Bold-X5M5EMOD.woff +0 -0
  53. package/dist/KaTeX_SansSerif-Italic-HMPFTM52.woff2 +0 -0
  54. package/dist/KaTeX_SansSerif-Italic-PSN4QKYX.woff +0 -0
  55. package/dist/KaTeX_SansSerif-Italic-WTBAZBGY.ttf +0 -0
  56. package/dist/KaTeX_SansSerif-Regular-2TL3USAE.ttf +0 -0
  57. package/dist/KaTeX_SansSerif-Regular-OQCII6EP.woff +0 -0
  58. package/dist/KaTeX_SansSerif-Regular-XIQ62X4E.woff2 +0 -0
  59. package/dist/KaTeX_Script-Regular-72OLXYNA.ttf +0 -0
  60. package/dist/KaTeX_Script-Regular-A5IFOEBS.woff +0 -0
  61. package/dist/KaTeX_Script-Regular-APUWIHLP.woff2 +0 -0
  62. package/dist/KaTeX_Size1-Regular-4HRHTS65.woff +0 -0
  63. package/dist/KaTeX_Size1-Regular-5LRUTBFT.woff2 +0 -0
  64. package/dist/KaTeX_Size1-Regular-7K6AASVL.ttf +0 -0
  65. package/dist/KaTeX_Size2-Regular-222HN3GT.ttf +0 -0
  66. package/dist/KaTeX_Size2-Regular-K5ZHAIS6.woff +0 -0
  67. package/dist/KaTeX_Size2-Regular-LELKET5D.woff2 +0 -0
  68. package/dist/KaTeX_Size3-Regular-TLFPAHDE.woff +0 -0
  69. package/dist/KaTeX_Size3-Regular-UFCO6WCA.ttf +0 -0
  70. package/dist/KaTeX_Size3-Regular-WQRQ47UD.woff2 +0 -0
  71. package/dist/KaTeX_Size4-Regular-7PGNVPQK.ttf +0 -0
  72. package/dist/KaTeX_Size4-Regular-CDMV7U5C.woff2 +0 -0
  73. package/dist/KaTeX_Size4-Regular-PKMWZHNC.woff +0 -0
  74. package/dist/KaTeX_Typewriter-Regular-3F5K6SQ6.ttf +0 -0
  75. package/dist/KaTeX_Typewriter-Regular-MJMFSK64.woff +0 -0
  76. package/dist/KaTeX_Typewriter-Regular-VBYJ4NRC.woff2 +0 -0
  77. package/dist/KernelEngineContext-BOCQoFwk.d.ts +43 -0
  78. package/dist/LayersPanel-BBQ54IVG.js +7 -0
  79. package/dist/ModuleCard-3TT2X7IW.js +7 -0
  80. package/dist/OrbInspector-K6T6O7GI.js +27 -0
  81. package/dist/OrbInspector-MHLJ6OEE.css +1756 -0
  82. package/dist/Select-mDZIwNqN.d.ts +199 -0
  83. package/dist/ServerBridge-Cm1On51b.d.ts +233 -0
  84. package/dist/ThemeContext-DJmO59xd.d.ts +147 -0
  85. package/dist/TraitValueFrame-2PJGLLVI.js +28 -0
  86. package/dist/TraitValueFrame-4G3KOUBR.css +1756 -0
  87. package/dist/UISlotContext-Dl_ewwCI.d.ts +79 -0
  88. package/dist/UISlotRenderer-JKFSX24W.js +27 -0
  89. package/dist/UISlotRenderer-KVFO6J7R.css +1756 -0
  90. package/dist/UserContext-DqWeZkUZ.d.ts +100 -0
  91. package/dist/auth/browser/index.d.ts +2 -0
  92. package/dist/auth/browser/index.js +1 -0
  93. package/dist/auth/react/index.d.ts +49 -0
  94. package/dist/auth/react/index.js +119 -0
  95. package/dist/avl/index.css +1756 -0
  96. package/dist/avl/index.d.ts +2238 -0
  97. package/dist/avl/index.js +2693 -0
  98. package/dist/avl-3d-context-BIRKWpaL.d.ts +204 -0
  99. package/dist/avl-schema-parser-CtJxJ9KU.d.ts +132 -0
  100. package/dist/avl-zoom-state-CKMVuBFg.d.ts +17 -0
  101. package/dist/chunk-2PY54Z44.js +227 -0
  102. package/dist/chunk-2QOH2HWM.js +95 -0
  103. package/dist/chunk-3BBUBJFF.js +339 -0
  104. package/dist/chunk-42FY4RYA.js +191 -0
  105. package/dist/chunk-5QTYQTPS.js +15 -0
  106. package/dist/chunk-6P3MWXYE.js +440 -0
  107. package/dist/chunk-73SRAB4P.js +1053 -0
  108. package/dist/chunk-A2LR6VQQ.js +349 -0
  109. package/dist/chunk-AILY3XPS.js +562 -0
  110. package/dist/chunk-B4BU77LT.js +432 -0
  111. package/dist/chunk-DFNZUYX4.js +378 -0
  112. package/dist/chunk-DJ433ET5.js +1327 -0
  113. package/dist/chunk-DLZF4PVE.js +24 -0
  114. package/dist/chunk-DYEKAA4L.js +787 -0
  115. package/dist/chunk-DZ42OJQC.js +176 -0
  116. package/dist/chunk-EOWMARUB.js +16 -0
  117. package/dist/chunk-EQAMU2ZC.js +14 -0
  118. package/dist/chunk-FAJDTHWC.js +98 -0
  119. package/dist/chunk-FIW6WN23.js +508 -0
  120. package/dist/chunk-FP3WIKTC.js +303 -0
  121. package/dist/chunk-G7DCAZ22.js +19 -0
  122. package/dist/chunk-GAR5TQ5B.js +199 -0
  123. package/dist/chunk-GKIFONTE.js +131 -0
  124. package/dist/chunk-GYTPOFVC.js +47155 -0
  125. package/dist/chunk-KVQS4GXU.js +328 -0
  126. package/dist/chunk-L2DEKY4J.js +97 -0
  127. package/dist/chunk-L677XGY3.js +701 -0
  128. package/dist/chunk-MBQAMMSE.js +11877 -0
  129. package/dist/chunk-P4LNHAFI.js +1051 -0
  130. package/dist/chunk-P4ZFUQFF.js +93 -0
  131. package/dist/chunk-PC7K4SK7.js +1384 -0
  132. package/dist/chunk-R5O5AUPI.js +573 -0
  133. package/dist/chunk-SGM3FASH.js +672 -0
  134. package/dist/chunk-SJGJJKBY.js +502 -0
  135. package/dist/chunk-TESBIVUA.js +11 -0
  136. package/dist/chunk-TZZBINQY.js +82 -0
  137. package/dist/chunk-U6QRZASX.js +280 -0
  138. package/dist/chunk-VFF5OO47.js +319 -0
  139. package/dist/chunk-YDNJLLG6.js +516 -0
  140. package/dist/chunk-YHMRX6YA.js +455 -0
  141. package/dist/chunk-ZO6MXAS3.js +69 -0
  142. package/dist/components/index.css +1756 -0
  143. package/dist/components/index.d.ts +11093 -0
  144. package/dist/components/index.js +1110 -0
  145. package/dist/context/index.d.ts +9 -0
  146. package/dist/context/index.js +7 -0
  147. package/dist/core.d.ts +2523 -0
  148. package/dist/core.js +2 -0
  149. package/dist/design-classes/index.cjs +429 -0
  150. package/dist/design-classes/index.d.cts +165 -0
  151. package/dist/design-classes/index.d.ts +165 -0
  152. package/dist/design-classes/index.js +397 -0
  153. package/dist/emojiItems-QGSNAABW.js +20 -0
  154. package/dist/fx-CmQjnHmT.d.ts +371 -0
  155. package/dist/hooks/index.d.ts +936 -0
  156. package/dist/hooks/index.js +7 -0
  157. package/dist/index.d.ts +486 -0
  158. package/dist/index.js +38 -0
  159. package/dist/katexPlugin-FA7NX4PE.css +1161 -0
  160. package/dist/katexPlugin-NCDKOOQY.js +2 -0
  161. package/dist/kernel-client-ZH4PSMCN.js +367 -0
  162. package/dist/kernel-wire-B4S8pnP3.d.ts +65 -0
  163. package/dist/lib/index.d.ts +602 -0
  164. package/dist/lib/index.js +1288 -0
  165. package/dist/paintDispatch-ChW5mVuK.d.ts +698 -0
  166. package/dist/parseLessonSegments-GpCeMrb2.d.ts +334 -0
  167. package/dist/perf-CKiBKbkw.d.ts +22 -0
  168. package/dist/perf-Dr28-AgT.d.ts +57 -0
  169. package/dist/prism-AIWGN2X5.js +134 -0
  170. package/dist/providers/index.css +1756 -0
  171. package/dist/providers/index.d.ts +340 -0
  172. package/dist/providers/index.js +30 -0
  173. package/dist/renderer/index.d.ts +467 -0
  174. package/dist/renderer/index.js +3 -0
  175. package/dist/runtime/index.css +1756 -0
  176. package/dist/runtime/index.d.ts +440 -0
  177. package/dist/runtime/index.js +31 -0
  178. package/dist/slot-host-CPzrxLo9.d.ts +48 -0
  179. package/dist/ssr/index.cjs +7631 -0
  180. package/dist/ssr/index.d.cts +487 -0
  181. package/dist/ssr/index.d.ts +487 -0
  182. package/dist/ssr/index.js +7599 -0
  183. package/dist/storage/browser/index.d.ts +1 -0
  184. package/dist/storage/browser/index.js +1 -0
  185. package/dist/test-support.d.ts +35 -0
  186. package/dist/test-support.js +114 -0
  187. package/dist/themeTokens-CRd8AEDF.d.ts +125 -0
  188. package/dist/three/index.css +503 -0
  189. package/dist/three/index.d.ts +1185 -0
  190. package/dist/three/index.js +3896 -0
  191. package/dist/useKeyboardRouter-Dsq553Ur.d.ts +42 -0
  192. package/dist/useUISlots-CiobNFGb.d.ts +211 -0
  193. package/dist/verification-C5pTeMJv.d.ts +66 -0
  194. package/dist/verificationRegistry-CabxhfTv.d.ts +122 -0
  195. package/dist/wrapCallbackForEvent-B9QLbhxX.d.ts +19 -0
  196. package/index.css +199 -0
  197. package/package.json +269 -3
  198. package/src/core/locales/ar.json +1263 -0
  199. package/src/core/locales/en.json +1263 -0
  200. package/src/core/locales/index.ts +54 -0
  201. package/src/core/locales/sl.json +1263 -0
  202. package/src/core/tokens/native-tokens.json +369 -0
  203. package/tailwind-compile.cjs +29 -0
  204. package/tailwind-preset.cjs +991 -0
  205. package/themes/_base.css +451 -0
  206. package/themes/_contract.md +307 -0
  207. package/themes/_fonts-kenney.css +11 -0
  208. package/themes/_fonts.css +12 -0
  209. package/themes/_foundation.css +105 -0
  210. package/themes/_head.css +22 -0
  211. package/themes/_presets.css +67 -0
  212. package/themes/almadar-heritage.css +455 -0
  213. package/themes/almadar-website.css +269 -0
  214. package/themes/almadar.css +269 -0
  215. package/themes/aqua.css +455 -0
  216. package/themes/arabesque.css +459 -0
  217. package/themes/art-deco.css +457 -0
  218. package/themes/art-nouveau.css +459 -0
  219. package/themes/atelier.css +463 -0
  220. package/themes/bauhaus.css +461 -0
  221. package/themes/bloomberg-dense.css +463 -0
  222. package/themes/blueprint.css +457 -0
  223. package/themes/clay.css +449 -0
  224. package/themes/comic.css +453 -0
  225. package/themes/constructivist.css +457 -0
  226. package/themes/corporate.css +449 -0
  227. package/themes/cyberpunk.css +453 -0
  228. package/themes/frutiger-aero.css +458 -0
  229. package/themes/game-adventure.css +201 -0
  230. package/themes/game-rpg.css +203 -0
  231. package/themes/game-sci-fi.css +201 -0
  232. package/themes/game-ui-pack.css +200 -0
  233. package/themes/gazette.css +449 -0
  234. package/themes/glass.css +457 -0
  235. package/themes/gothic.css +453 -0
  236. package/themes/index.css +21 -0
  237. package/themes/ink-wash.css +459 -0
  238. package/themes/kawaii.css +459 -0
  239. package/themes/kflow.css +310 -0
  240. package/themes/kiosk.css +449 -0
  241. package/themes/linear-clean.css +463 -0
  242. package/themes/luxury.css +451 -0
  243. package/themes/mac-classic.css +455 -0
  244. package/themes/material.css +463 -0
  245. package/themes/memphis.css +453 -0
  246. package/themes/mid-century.css +455 -0
  247. package/themes/minimalist.css +449 -0
  248. package/themes/mudcloth.css +459 -0
  249. package/themes/nata.css +310 -0
  250. package/themes/neon.css +453 -0
  251. package/themes/neumorphic.css +451 -0
  252. package/themes/newsprint.css +455 -0
  253. package/themes/notion-editorial.css +463 -0
  254. package/themes/orb.css +465 -0
  255. package/themes/pixel.css +449 -0
  256. package/themes/prism.css +309 -0
  257. package/themes/rawi.css +310 -0
  258. package/themes/retro.css +452 -0
  259. package/themes/risograph.css +463 -0
  260. package/themes/scandi.css +469 -0
  261. package/themes/sketch.css +455 -0
  262. package/themes/solarpunk.css +469 -0
  263. package/themes/steampunk.css +451 -0
  264. package/themes/swiss.css +455 -0
  265. package/themes/terminal.css +466 -0
  266. package/themes/trait-wars.css +487 -0
  267. package/themes/ukiyo-e.css +459 -0
  268. package/themes/vaporwave.css +455 -0
  269. package/themes/victorian.css +453 -0
  270. package/themes/wabi-sabi.css +459 -0
  271. package/themes/win95.css +455 -0
  272. package/themes/wireframe.css +439 -0
  273. package/themes/zine.css +455 -0
  274. package/README.md +0 -3
@@ -0,0 +1,1053 @@
1
+ import { claimDelivery } from './chunk-R5O5AUPI.js';
2
+ import { useEventBus, getTraitPresence, beginPending, endPending } from './chunk-MBQAMMSE.js';
3
+ import { createContext, useState, useCallback, useEffect, useMemo, useRef, useContext, useSyncExternalStore } from 'react';
4
+ import { createLogger } from '@almadar/logger';
5
+ import { mergeEntityFrame } from '@almadar/core';
6
+ import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
7
+
8
+ var log = createLogger("almadar:ui:filesystem");
9
+ function useFileSystem() {
10
+ const [status, setStatus] = useState("idle");
11
+ const [error, setError] = useState(null);
12
+ const [isLoading, setIsLoading] = useState(false);
13
+ const [files, setFiles] = useState([]);
14
+ const [selectedFile, setSelectedFile] = useState(null);
15
+ const [selectedPath, setSelectedPath] = useState(null);
16
+ const [previewUrl, setPreviewUrl] = useState(null);
17
+ const [fileContents, setFileContents] = useState(/* @__PURE__ */ new Map());
18
+ const boot = useCallback(async () => {
19
+ setStatus("booting");
20
+ setError(null);
21
+ setIsLoading(true);
22
+ try {
23
+ log.debug("Booting WebContainer");
24
+ await new Promise((resolve) => setTimeout(resolve, 100));
25
+ setStatus("ready");
26
+ } catch (err) {
27
+ setError(err instanceof Error ? err.message : "Failed to boot");
28
+ setStatus("error");
29
+ } finally {
30
+ setIsLoading(false);
31
+ }
32
+ }, []);
33
+ const mountFiles = useCallback(async (filesToMount) => {
34
+ setIsLoading(true);
35
+ try {
36
+ let filesArray;
37
+ if (Array.isArray(filesToMount)) {
38
+ filesArray = filesToMount;
39
+ } else {
40
+ filesArray = [];
41
+ const flattenTree = (obj, basePath = "") => {
42
+ for (const [key, value] of Object.entries(obj)) {
43
+ const path = basePath ? `${basePath}/${key}` : key;
44
+ if (value && "file" in value) {
45
+ filesArray.push({ path, content: value.file.contents || "" });
46
+ } else if (value && "directory" in value) {
47
+ flattenTree(value.directory, path);
48
+ }
49
+ }
50
+ };
51
+ flattenTree(filesToMount);
52
+ }
53
+ const newContents = /* @__PURE__ */ new Map();
54
+ for (const file of filesArray) {
55
+ newContents.set(file.path, file.content);
56
+ }
57
+ setFileContents(newContents);
58
+ const newTree = [];
59
+ for (const file of filesArray) {
60
+ const parts = file.path.split("/").filter(Boolean);
61
+ let current = newTree;
62
+ for (let i = 0; i < parts.length; i++) {
63
+ const part = parts[i];
64
+ const isFile = i === parts.length - 1;
65
+ const currentPath = "/" + parts.slice(0, i + 1).join("/");
66
+ let node = current.find((n) => n.name === part);
67
+ if (!node) {
68
+ node = {
69
+ path: currentPath,
70
+ name: part,
71
+ type: isFile ? "file" : "directory",
72
+ children: isFile ? void 0 : []
73
+ };
74
+ current.push(node);
75
+ }
76
+ if (!isFile && node && node.children) {
77
+ current = node.children;
78
+ }
79
+ }
80
+ }
81
+ setFiles(newTree);
82
+ setStatus("running");
83
+ } catch (err) {
84
+ log.error("Failed to mount files", { error: err instanceof Error ? err : String(err) });
85
+ } finally {
86
+ setIsLoading(false);
87
+ }
88
+ }, []);
89
+ const readFile = useCallback(async (path) => {
90
+ return fileContents.get(path) || "";
91
+ }, [fileContents]);
92
+ const writeFile = useCallback(async (path, content) => {
93
+ setFileContents((prev) => {
94
+ const next = new Map(prev);
95
+ next.set(path, content);
96
+ return next;
97
+ });
98
+ }, []);
99
+ const selectFile = useCallback(async (path) => {
100
+ const content = fileContents.get(path) || "";
101
+ const ext = path.split(".").pop()?.toLowerCase() || "";
102
+ const languageMap = {
103
+ ts: "typescript",
104
+ tsx: "typescript",
105
+ js: "javascript",
106
+ jsx: "javascript",
107
+ json: "json",
108
+ md: "markdown",
109
+ css: "css",
110
+ html: "html",
111
+ orb: "json"
112
+ };
113
+ setSelectedPath(path);
114
+ setSelectedFile({
115
+ path,
116
+ content,
117
+ language: languageMap[ext] || "plaintext",
118
+ isDirty: false
119
+ });
120
+ }, [fileContents]);
121
+ const updateContent = useCallback((pathOrContent, contentArg) => {
122
+ const path = contentArg !== void 0 ? pathOrContent : selectedPath;
123
+ const content = contentArg !== void 0 ? contentArg : pathOrContent;
124
+ if (!path) {
125
+ log.warn("updateContent called without path and no file selected");
126
+ return;
127
+ }
128
+ setFileContents((prev) => {
129
+ const next = new Map(prev);
130
+ next.set(path, content);
131
+ return next;
132
+ });
133
+ if (selectedPath === path) {
134
+ setSelectedFile((prev) => prev ? { ...prev, content, isDirty: true } : null);
135
+ }
136
+ }, [selectedPath]);
137
+ const updateSelectedContent = useCallback((content) => {
138
+ setSelectedFile((prev) => prev ? { ...prev, content, isDirty: true } : null);
139
+ }, []);
140
+ const refreshTree = useCallback(async () => {
141
+ log.debug("Refreshing tree");
142
+ }, []);
143
+ const runCommand = useCallback(async (command) => {
144
+ log.debug("Running command", { command });
145
+ return { exitCode: 0, output: "" };
146
+ }, []);
147
+ const startDevServer = useCallback(async () => {
148
+ log.debug("Starting dev server");
149
+ setPreviewUrl("http://localhost:5173");
150
+ }, []);
151
+ return {
152
+ status,
153
+ error,
154
+ isLoading,
155
+ files,
156
+ selectedFile,
157
+ selectedPath,
158
+ previewUrl,
159
+ boot,
160
+ mountFiles,
161
+ readFile,
162
+ writeFile,
163
+ selectFile,
164
+ updateContent,
165
+ updateSelectedContent,
166
+ refreshTree,
167
+ runCommand,
168
+ startDevServer
169
+ };
170
+ }
171
+ var log2 = createLogger("almadar:ui:extensions");
172
+ var defaultManifest = {
173
+ languages: {
174
+ typescript: { extensions: [".ts", ".tsx"], icon: "ts", color: "#3178c6" },
175
+ javascript: { extensions: [".js", ".jsx"], icon: "js", color: "#f7df1e" },
176
+ json: { extensions: [".json", ".orb"], icon: "json", color: "#000000" },
177
+ css: { extensions: [".css"], icon: "css", color: "#264de4" },
178
+ html: { extensions: [".html"], icon: "html", color: "#e34c26" },
179
+ markdown: { extensions: [".md", ".mdx"], icon: "md", color: "#083fa1" }
180
+ },
181
+ extensions: []
182
+ };
183
+ function useExtensions(options) {
184
+ const { appId, loadOnMount = true } = options;
185
+ const [extensions, setExtensions] = useState([]);
186
+ const [manifest] = useState(defaultManifest);
187
+ const [isLoading, setIsLoading] = useState(false);
188
+ const [error, setError] = useState(null);
189
+ const loadExtension = useCallback(async (extensionId) => {
190
+ log2.debug("Loading extension", { extensionId });
191
+ }, []);
192
+ const loadExtensions = useCallback(async () => {
193
+ setIsLoading(true);
194
+ setError(null);
195
+ try {
196
+ const defaultExtensions = [
197
+ { id: "typescript", name: "TypeScript", language: "typescript", loaded: true },
198
+ { id: "javascript", name: "JavaScript", language: "javascript", loaded: true },
199
+ { id: "json", name: "JSON", language: "json", loaded: true },
200
+ { id: "css", name: "CSS", language: "css", loaded: true },
201
+ { id: "html", name: "HTML", language: "html", loaded: true },
202
+ { id: "markdown", name: "Markdown", language: "markdown", loaded: true }
203
+ ];
204
+ setExtensions(defaultExtensions);
205
+ } catch (err) {
206
+ setError(err instanceof Error ? err.message : "Failed to load extensions");
207
+ } finally {
208
+ setIsLoading(false);
209
+ }
210
+ }, []);
211
+ const getExtensionForFile = useCallback((filename) => {
212
+ const ext = filename.split(".").pop()?.toLowerCase();
213
+ if (!ext) return null;
214
+ const languageMap = {
215
+ ts: "typescript",
216
+ tsx: "typescript",
217
+ js: "javascript",
218
+ jsx: "javascript",
219
+ json: "json",
220
+ md: "markdown",
221
+ css: "css",
222
+ html: "html",
223
+ orb: "json"
224
+ };
225
+ const language = languageMap[ext];
226
+ if (!language) return null;
227
+ return extensions.find((e) => e.language === language) || null;
228
+ }, [extensions]);
229
+ useEffect(() => {
230
+ if (!appId || !loadOnMount) return;
231
+ const loadExtensions2 = async () => {
232
+ setIsLoading(true);
233
+ setError(null);
234
+ try {
235
+ const defaultExtensions = [
236
+ { id: "typescript", name: "TypeScript", language: "typescript", loaded: true },
237
+ { id: "javascript", name: "JavaScript", language: "javascript", loaded: true },
238
+ { id: "json", name: "JSON", language: "json", loaded: true },
239
+ { id: "css", name: "CSS", language: "css", loaded: true },
240
+ { id: "html", name: "HTML", language: "html", loaded: true },
241
+ { id: "markdown", name: "Markdown", language: "markdown", loaded: true }
242
+ ];
243
+ setExtensions(defaultExtensions);
244
+ } catch (err) {
245
+ setError(err instanceof Error ? err.message : "Failed to load extensions");
246
+ } finally {
247
+ setIsLoading(false);
248
+ }
249
+ };
250
+ loadExtensions2();
251
+ }, [appId, loadOnMount]);
252
+ return {
253
+ extensions,
254
+ manifest,
255
+ isLoading,
256
+ error,
257
+ loadExtension,
258
+ loadExtensions,
259
+ getExtensionForFile
260
+ };
261
+ }
262
+ var log3 = createLogger("almadar:ui:file-editor");
263
+ function parseSchemaText(text) {
264
+ try {
265
+ return JSON.parse(text);
266
+ } catch {
267
+ return null;
268
+ }
269
+ }
270
+ function useFileEditor(options) {
271
+ const { extensions, fileSystem, onSchemaUpdate } = options;
272
+ const [openFiles, setOpenFiles] = useState([]);
273
+ const [activeFilePath, setActiveFilePath] = useState(null);
274
+ const [isSaving, setIsSaving] = useState(false);
275
+ const activeFile = openFiles.find((f) => f.path === activeFilePath) || null;
276
+ const openFile = useCallback(async (path) => {
277
+ const existing = openFiles.find((f) => f.path === path);
278
+ if (existing) {
279
+ setActiveFilePath(path);
280
+ return;
281
+ }
282
+ try {
283
+ const content = await fileSystem.readFile(path);
284
+ const ext = extensions.getExtensionForFile(path);
285
+ const newFile = {
286
+ path,
287
+ content,
288
+ isDirty: false,
289
+ language: ext?.language
290
+ };
291
+ setOpenFiles((prev) => [...prev, newFile]);
292
+ setActiveFilePath(path);
293
+ } catch (err) {
294
+ log3.error("Failed to open file", { error: err instanceof Error ? err : String(err) });
295
+ }
296
+ }, [openFiles, fileSystem, extensions]);
297
+ const closeFile = useCallback((path) => {
298
+ setOpenFiles((prev) => prev.filter((f) => f.path !== path));
299
+ if (activeFilePath === path) {
300
+ const remaining = openFiles.filter((f) => f.path !== path);
301
+ setActiveFilePath(remaining.length > 0 ? remaining[0].path : null);
302
+ }
303
+ }, [activeFilePath, openFiles]);
304
+ const setActiveFile = useCallback((path) => {
305
+ setActiveFilePath(path);
306
+ }, []);
307
+ const updateFileContent = useCallback((path, content) => {
308
+ setOpenFiles(
309
+ (prev) => prev.map(
310
+ (f) => f.path === path ? { ...f, content, isDirty: true } : f
311
+ )
312
+ );
313
+ }, []);
314
+ const handleFileEdit = useCallback(async (path, content) => {
315
+ try {
316
+ await fileSystem.writeFile(path, content);
317
+ let action = "saved";
318
+ if (path.endsWith(".orb") || path.endsWith("schema.json")) {
319
+ const schema = parseSchemaText(content);
320
+ if (schema !== null) {
321
+ await onSchemaUpdate?.(schema);
322
+ action = "updated_schema";
323
+ } else {
324
+ log3.warn("schema-file-not-json", { path });
325
+ }
326
+ } else if (path.includes("/extensions/")) {
327
+ action = path.endsWith(".new") ? "converted_extension" : "saved_extension";
328
+ }
329
+ return { success: true, action };
330
+ } catch (err) {
331
+ return {
332
+ success: false,
333
+ error: err instanceof Error ? err.message : "Failed to save file"
334
+ };
335
+ }
336
+ }, [fileSystem, onSchemaUpdate]);
337
+ const saveFile = useCallback(async (path) => {
338
+ const file = openFiles.find((f) => f.path === path);
339
+ if (!file) return;
340
+ setIsSaving(true);
341
+ try {
342
+ await fileSystem.writeFile(path, file.content);
343
+ setOpenFiles(
344
+ (prev) => prev.map(
345
+ (f) => f.path === path ? { ...f, isDirty: false } : f
346
+ )
347
+ );
348
+ if (path.endsWith(".orb") || path.endsWith("schema.json")) {
349
+ const schema = parseSchemaText(file.content);
350
+ if (schema !== null) await onSchemaUpdate?.(schema);
351
+ else log3.warn("schema-file-not-json", { path });
352
+ }
353
+ } catch (err) {
354
+ log3.error("Failed to save file", { error: err instanceof Error ? err : String(err) });
355
+ } finally {
356
+ setIsSaving(false);
357
+ }
358
+ }, [openFiles, fileSystem, onSchemaUpdate]);
359
+ const saveAllFiles = useCallback(async () => {
360
+ setIsSaving(true);
361
+ try {
362
+ const dirtyFiles = openFiles.filter((f) => f.isDirty);
363
+ for (const file of dirtyFiles) {
364
+ await saveFile(file.path);
365
+ }
366
+ } finally {
367
+ setIsSaving(false);
368
+ }
369
+ }, [openFiles, saveFile]);
370
+ return {
371
+ openFiles,
372
+ activeFile,
373
+ isSaving,
374
+ openFile,
375
+ closeFile,
376
+ setActiveFile,
377
+ updateFileContent,
378
+ handleFileEdit,
379
+ saveFile,
380
+ saveAllFiles
381
+ };
382
+ }
383
+ var log4 = createLogger("almadar:ui:compile");
384
+ function useCompile() {
385
+ const [isCompiling, setIsCompiling] = useState(false);
386
+ const [stage, setStage] = useState("idle");
387
+ const [lastResult, setLastResult] = useState(null);
388
+ const [error, setError] = useState(null);
389
+ const compileSchema = useCallback(async (schema) => {
390
+ setIsCompiling(true);
391
+ setStage("compiling");
392
+ setError(null);
393
+ try {
394
+ log4.debug("Compiling schema", { name: schema.name });
395
+ const result = {
396
+ success: true,
397
+ files: []
398
+ };
399
+ setLastResult(result);
400
+ setStage("done");
401
+ return result;
402
+ } catch (err) {
403
+ const errorMessage = err instanceof Error ? err.message : "Compilation failed";
404
+ setError(errorMessage);
405
+ setStage("error");
406
+ setLastResult({ success: false, errors: [errorMessage] });
407
+ return null;
408
+ } finally {
409
+ setIsCompiling(false);
410
+ }
411
+ }, []);
412
+ return {
413
+ isCompiling,
414
+ stage,
415
+ lastResult,
416
+ error,
417
+ compileSchema
418
+ };
419
+ }
420
+ var log5 = createLogger("almadar:ui:preview");
421
+ function usePreview(options) {
422
+ const [previewUrl, setPreviewUrl] = useState(null);
423
+ const [isLoading, setIsLoading] = useState(!!options?.appId);
424
+ const [error, setError] = useState(null);
425
+ const [loadError, setLoadError] = useState(null);
426
+ const [app, setApp] = useState(null);
427
+ const [isFullscreen, setIsFullscreen] = useState(false);
428
+ const [isExecutingEvent, setIsExecutingEvent] = useState(false);
429
+ const [errorToast, setErrorToast] = useState(null);
430
+ const [currentStateName, setCurrentStateName] = useState(null);
431
+ const [notificationsList, setNotificationsList] = useState([]);
432
+ const [isPanelOpen, setIsPanelOpen] = useState(false);
433
+ const notifications = useMemo(() => ({
434
+ notifications: notificationsList,
435
+ isPanelOpen,
436
+ closePanel: () => setIsPanelOpen(false),
437
+ dismissNotification: (id) => {
438
+ setNotificationsList((prev) => prev.filter((n) => n.id !== id));
439
+ },
440
+ markAsRead: (id) => {
441
+ setNotificationsList(
442
+ (prev) => prev.map((n) => n.id === id ? { ...n, read: true } : n)
443
+ );
444
+ },
445
+ clearAll: () => setNotificationsList([])
446
+ }), [notificationsList, isPanelOpen]);
447
+ useEffect(() => {
448
+ const appId = options?.appId;
449
+ if (!appId) {
450
+ setApp(null);
451
+ setIsLoading(false);
452
+ return;
453
+ }
454
+ log5.debug("Setting up preview for app", { appId });
455
+ setPreviewUrl(`/api/orbitals/${appId}`);
456
+ setIsLoading(false);
457
+ }, [options?.appId]);
458
+ const startPreview = useCallback(async () => {
459
+ log5.debug("startPreview called");
460
+ }, []);
461
+ const stopPreview = useCallback(async () => {
462
+ setIsLoading(true);
463
+ try {
464
+ log5.debug("Stopping preview server");
465
+ setPreviewUrl(null);
466
+ setApp(null);
467
+ } finally {
468
+ setIsLoading(false);
469
+ }
470
+ }, []);
471
+ const refresh = useCallback(async () => {
472
+ if (!previewUrl) return;
473
+ log5.debug("Refreshing preview");
474
+ setPreviewUrl(`${previewUrl.split("?")[0]}?t=${Date.now()}`);
475
+ }, [previewUrl]);
476
+ const handleRefresh = useCallback(async () => {
477
+ log5.debug("Handle refresh");
478
+ await refresh();
479
+ }, [refresh]);
480
+ const handleReset = useCallback(async () => {
481
+ log5.debug("Resetting preview");
482
+ setError(null);
483
+ setLoadError(null);
484
+ setErrorToast(null);
485
+ setIsExecutingEvent(false);
486
+ setCurrentStateName(null);
487
+ }, []);
488
+ const toggleFullscreen = useCallback(() => {
489
+ setIsFullscreen((prev) => !prev);
490
+ }, []);
491
+ const dismissErrorToast = useCallback(() => {
492
+ setErrorToast(null);
493
+ }, []);
494
+ return {
495
+ previewUrl,
496
+ isLoading,
497
+ error,
498
+ loadError,
499
+ app,
500
+ isFullscreen,
501
+ isExecutingEvent,
502
+ errorToast,
503
+ currentStateName,
504
+ notifications,
505
+ startPreview,
506
+ stopPreview,
507
+ refresh,
508
+ handleRefresh,
509
+ handleReset,
510
+ toggleFullscreen,
511
+ setErrorToast,
512
+ dismissErrorToast
513
+ };
514
+ }
515
+ var log6 = createLogger("almadar:ui:agent-chat");
516
+ function useAgentChat(options) {
517
+ const [messages, setMessages] = useState([]);
518
+ const [status, setStatus] = useState("idle");
519
+ const [activities, setActivities] = useState([]);
520
+ const [todos, setTodos] = useState([]);
521
+ const [schemaDiffs, setSchemaDiffs] = useState([]);
522
+ const [isLoading, setIsLoading] = useState(false);
523
+ const [error, setError] = useState(null);
524
+ const [threadId] = useState(null);
525
+ const [interrupt, setInterrupt] = useState(null);
526
+ const sendMessage = useCallback(async (content) => {
527
+ setIsLoading(true);
528
+ setStatus("running");
529
+ setError(null);
530
+ try {
531
+ const userMessage = {
532
+ id: Date.now().toString(),
533
+ role: "user",
534
+ content,
535
+ timestamp: Date.now()
536
+ };
537
+ setMessages((prev) => [...prev, userMessage]);
538
+ log6.debug("Sending message", { content });
539
+ const assistantMessage = {
540
+ id: (Date.now() + 1).toString(),
541
+ role: "assistant",
542
+ content: "Agent chat is not yet implemented.",
543
+ timestamp: Date.now()
544
+ };
545
+ setMessages((prev) => [...prev, assistantMessage]);
546
+ setStatus("idle");
547
+ options?.onComplete?.();
548
+ } catch (err) {
549
+ setError(err instanceof Error ? err.message : "Failed to send message");
550
+ setStatus("error");
551
+ } finally {
552
+ setIsLoading(false);
553
+ }
554
+ }, [options]);
555
+ const startGeneration = useCallback(async (skill, prompt, genOptions) => {
556
+ setStatus("running");
557
+ setIsLoading(true);
558
+ setError(null);
559
+ const skillName = Array.isArray(skill) ? skill[0] : skill;
560
+ try {
561
+ log6.debug("Starting generation", () => ({ skillName, prompt, genOptions: JSON.stringify(genOptions) }));
562
+ await new Promise((resolve) => setTimeout(resolve, 100));
563
+ setStatus("complete");
564
+ options?.onComplete?.();
565
+ } catch (err) {
566
+ setError(err instanceof Error ? err.message : "Generation failed");
567
+ setStatus("error");
568
+ } finally {
569
+ setIsLoading(false);
570
+ }
571
+ }, [options]);
572
+ const continueConversation = useCallback(async (message) => {
573
+ log6.debug("Continue conversation", { message: Array.isArray(message) ? message : [message] });
574
+ }, []);
575
+ const resumeWithDecision = useCallback(async (decisions) => {
576
+ log6.debug("Resume with decision", () => ({ decisions: JSON.stringify(decisions), count: decisions.length }));
577
+ setInterrupt(null);
578
+ }, []);
579
+ const cancel = useCallback(() => {
580
+ setStatus("idle");
581
+ setIsLoading(false);
582
+ setInterrupt(null);
583
+ }, []);
584
+ const clearMessages = useCallback(() => {
585
+ setMessages([]);
586
+ }, []);
587
+ const clearHistory = useCallback(() => {
588
+ setMessages([]);
589
+ setActivities([]);
590
+ setTodos([]);
591
+ setSchemaDiffs([]);
592
+ setError(null);
593
+ }, []);
594
+ return {
595
+ messages,
596
+ status,
597
+ activities,
598
+ todos,
599
+ schemaDiffs,
600
+ isLoading,
601
+ error,
602
+ threadId,
603
+ interrupt,
604
+ sendMessage,
605
+ startGeneration,
606
+ continueConversation,
607
+ resumeWithDecision,
608
+ cancel,
609
+ clearMessages,
610
+ clearHistory
611
+ };
612
+ }
613
+ var log7 = createLogger("almadar:ui:validation");
614
+ function useValidation() {
615
+ const [result, setResult] = useState(null);
616
+ const [isValidating, setIsValidating] = useState(false);
617
+ const [error, setError] = useState(null);
618
+ const [stage, setStage] = useState("idle");
619
+ const [isFixing, setIsFixing] = useState(false);
620
+ const [progressMessage, setProgressMessage] = useState(null);
621
+ const validate = useCallback(async (appId) => {
622
+ setIsValidating(true);
623
+ setError(null);
624
+ setStage("validating");
625
+ setProgressMessage("Validating schema...");
626
+ try {
627
+ log7.debug("Validating app", { appId });
628
+ const validationResult = {
629
+ valid: true,
630
+ errors: [],
631
+ warnings: []
632
+ };
633
+ setResult(validationResult);
634
+ setStage("complete");
635
+ setProgressMessage(null);
636
+ return validationResult;
637
+ } catch (err) {
638
+ const errorMessage = err instanceof Error ? err.message : "Validation failed";
639
+ setError(errorMessage);
640
+ const failedResult = {
641
+ valid: false,
642
+ errors: [{ code: "VALIDATION_ERROR", message: errorMessage, severity: "error" }],
643
+ warnings: []
644
+ };
645
+ setResult(failedResult);
646
+ setStage("complete");
647
+ setProgressMessage(null);
648
+ return failedResult;
649
+ } finally {
650
+ setIsValidating(false);
651
+ }
652
+ }, []);
653
+ const clearResult = useCallback(() => {
654
+ setResult(null);
655
+ setError(null);
656
+ }, []);
657
+ const reset = useCallback(() => {
658
+ setResult(null);
659
+ setError(null);
660
+ setStage("idle");
661
+ setIsFixing(false);
662
+ setProgressMessage(null);
663
+ setIsValidating(false);
664
+ }, []);
665
+ return {
666
+ result,
667
+ isValidating,
668
+ error,
669
+ stage,
670
+ isFixing,
671
+ progressMessage,
672
+ errors: result?.errors ?? [],
673
+ warnings: result?.warnings ?? [],
674
+ isValid: result?.valid ?? false,
675
+ validate,
676
+ clearResult,
677
+ reset
678
+ };
679
+ }
680
+ var log8 = createLogger("almadar:ui:deep-agent");
681
+ function useDeepAgentGeneration() {
682
+ const [requests, setRequests] = useState([]);
683
+ const [currentRequest, setCurrentRequest] = useState(null);
684
+ const [isGenerating, setIsGenerating] = useState(false);
685
+ const [isLoading, setIsLoading] = useState(false);
686
+ const [isComplete, setIsComplete] = useState(false);
687
+ const [progress, setProgress] = useState({ stage: "idle", percent: 0, message: "" });
688
+ const [error, setError] = useState(null);
689
+ const [interrupt, setInterrupt] = useState(null);
690
+ const generate = useCallback(async (prompt) => {
691
+ setIsGenerating(true);
692
+ setIsLoading(true);
693
+ setIsComplete(false);
694
+ setError(null);
695
+ setProgress({ stage: "starting", percent: 0, message: "Starting generation..." });
696
+ const request = {
697
+ id: Date.now().toString(),
698
+ prompt,
699
+ status: "running"
700
+ };
701
+ setCurrentRequest(request);
702
+ setRequests((prev) => [...prev, request]);
703
+ try {
704
+ log8.debug("Generating from prompt", { prompt });
705
+ await new Promise((resolve) => setTimeout(resolve, 100));
706
+ request.status = "completed";
707
+ setCurrentRequest(request);
708
+ setIsComplete(true);
709
+ setProgress({ stage: "complete", percent: 100, message: "Generation complete" });
710
+ return null;
711
+ } catch (err) {
712
+ const errorMessage = err instanceof Error ? err.message : "Generation failed";
713
+ setError(errorMessage);
714
+ request.status = "failed";
715
+ request.error = errorMessage;
716
+ setCurrentRequest(request);
717
+ return null;
718
+ } finally {
719
+ setIsGenerating(false);
720
+ setIsLoading(false);
721
+ }
722
+ }, []);
723
+ const startGeneration = useCallback(async (skill, prompt, _options) => {
724
+ log8.debug("Starting generation with skill", { skill });
725
+ await generate(prompt);
726
+ }, [generate]);
727
+ const cancelGeneration = useCallback(() => {
728
+ if (currentRequest) {
729
+ currentRequest.status = "failed";
730
+ currentRequest.error = "Cancelled by user";
731
+ setCurrentRequest(null);
732
+ }
733
+ setIsGenerating(false);
734
+ setIsLoading(false);
735
+ setIsComplete(false);
736
+ setProgress({ stage: "idle", percent: 0, message: "" });
737
+ }, [currentRequest]);
738
+ const clearRequests = useCallback(() => {
739
+ setRequests([]);
740
+ setCurrentRequest(null);
741
+ setError(null);
742
+ setProgress({ stage: "idle", percent: 0, message: "" });
743
+ setIsComplete(false);
744
+ }, []);
745
+ const submitInterruptDecisions = useCallback((decisions) => {
746
+ log8.debug("Submitting interrupt decisions", () => ({ decisions: JSON.stringify(decisions), count: decisions.length }));
747
+ setInterrupt(null);
748
+ }, []);
749
+ return {
750
+ requests,
751
+ currentRequest,
752
+ isGenerating,
753
+ isLoading,
754
+ isComplete,
755
+ progress,
756
+ error,
757
+ interrupt,
758
+ generate,
759
+ startGeneration,
760
+ cancelGeneration,
761
+ clearRequests,
762
+ submitInterruptDecisions
763
+ };
764
+ }
765
+ var UI_PREFIX = "UI:";
766
+ function useUIEvents(dispatch, traitName, validEvents, eventBusInstance) {
767
+ const defaultEventBus = useEventBus();
768
+ const eventBus = eventBusInstance ?? defaultEventBus;
769
+ const validEventsKey = validEvents.slice().sort().join(",");
770
+ const stableValidEvents = useMemo(
771
+ () => validEvents,
772
+ [validEventsKey]
773
+ // intentional — validEventsKey is the stable dep
774
+ );
775
+ useEffect(() => {
776
+ const unsubscribes = [];
777
+ for (const smEvent of stableValidEvents) {
778
+ const handler = (event) => {
779
+ if (event.source && event.source.dispatched) {
780
+ return;
781
+ }
782
+ if (!claimDelivery(event.source, traitName, smEvent)) return;
783
+ const pendingKey = event.source?.pendingKey;
784
+ const settled = dispatch(smEvent, event.payload);
785
+ if (pendingKey !== void 0 && settled instanceof Promise) {
786
+ beginPending(pendingKey);
787
+ void settled.finally(() => endPending(pendingKey));
788
+ }
789
+ };
790
+ unsubscribes.push(
791
+ eventBus.on(`${UI_PREFIX}${traitName}.${smEvent}`, handler)
792
+ );
793
+ }
794
+ return () => {
795
+ for (const unsub of unsubscribes) {
796
+ if (typeof unsub === "function") unsub();
797
+ }
798
+ };
799
+ }, [eventBus, dispatch, traitName, stableValidEvents]);
800
+ }
801
+ function useTraitListens(dispatch, listens, eventBusInstance) {
802
+ const defaultEventBus = useEventBus();
803
+ const eventBus = eventBusInstance ?? defaultEventBus;
804
+ const stableKey = listens.map((l) => `${l.sourceKey}->${l.trigger}`).sort().join("|");
805
+ const stableListens = useMemo(
806
+ () => listens,
807
+ [stableKey]
808
+ // intentional
809
+ );
810
+ useEffect(() => {
811
+ const unsubscribes = [];
812
+ for (const spec of stableListens) {
813
+ const handler = (event) => {
814
+ dispatch(spec.trigger, event.payload);
815
+ };
816
+ unsubscribes.push(eventBus.on(`${UI_PREFIX}${spec.sourceKey}`, handler));
817
+ }
818
+ return () => {
819
+ for (const unsub of unsubscribes) {
820
+ if (typeof unsub === "function") unsub();
821
+ }
822
+ };
823
+ }, [eventBus, dispatch, stableListens]);
824
+ }
825
+ var log9 = createLogger("almadar:ui:shared-entity-store");
826
+ var EMPTY_ENTITY_STATE = {};
827
+ function createSharedEntityStore() {
828
+ const states = /* @__PURE__ */ new Map();
829
+ const subscribers = /* @__PURE__ */ new Map();
830
+ const getSnapshot = (entityId) => states.get(entityId) ?? EMPTY_ENTITY_STATE;
831
+ const subscribe = (entityId, callback) => {
832
+ let set = subscribers.get(entityId);
833
+ if (!set) {
834
+ set = /* @__PURE__ */ new Set();
835
+ subscribers.set(entityId, set);
836
+ }
837
+ set.add(callback);
838
+ return () => {
839
+ const current = subscribers.get(entityId);
840
+ if (!current) return;
841
+ current.delete(callback);
842
+ if (current.size === 0) {
843
+ subscribers.delete(entityId);
844
+ }
845
+ };
846
+ };
847
+ const commit = (entityId, nextState) => {
848
+ states.set(entityId, nextState);
849
+ const set = subscribers.get(entityId);
850
+ if (!set) return;
851
+ set.forEach((callback) => {
852
+ try {
853
+ callback();
854
+ } catch (error) {
855
+ log9.error("Shared entity subscriber error", {
856
+ entityId,
857
+ error: error instanceof Error ? error : String(error)
858
+ });
859
+ }
860
+ });
861
+ };
862
+ const seed = (entityId, initialState) => {
863
+ if (!states.has(entityId)) {
864
+ states.set(entityId, initialState);
865
+ }
866
+ };
867
+ return { getSnapshot, subscribe, commit, seed };
868
+ }
869
+ function useSharedEntityStore() {
870
+ const storeRef = useRef(null);
871
+ if (storeRef.current === null) {
872
+ storeRef.current = createSharedEntityStore();
873
+ }
874
+ return storeRef.current;
875
+ }
876
+ var SharedEntityStoreContext = createContext(null);
877
+ function useSharedEntityStoreContext() {
878
+ const store = useContext(SharedEntityStoreContext);
879
+ if (!store) {
880
+ throw new Error(
881
+ "useSharedEntityStoreContext: no SharedEntityStoreContext.Provider found in the component tree"
882
+ );
883
+ }
884
+ return store;
885
+ }
886
+ function useSharedEntitySnapshot(store, entityId) {
887
+ return useSyncExternalStore(
888
+ (onStoreChange) => store.subscribe(entityId, onStoreChange),
889
+ () => store.getSnapshot(entityId)
890
+ );
891
+ }
892
+ function runTickFrame(entityId, orderedWriters, store) {
893
+ let scratch = store.getSnapshot(entityId);
894
+ for (const writer of orderedWriters) {
895
+ const writes = writer(scratch);
896
+ scratch = mergeEntityFrame(scratch, writes);
897
+ }
898
+ store.commit(entityId, scratch);
899
+ return scratch;
900
+ }
901
+ var log10 = createLogger("almadar:ui:render-interpolation");
902
+ function useRenderInterpolation(options = {}) {
903
+ const tickIntervalMs = options.tickIntervalMs ?? 1e3 / 30;
904
+ const prevRef = useRef(null);
905
+ const currRef = useRef(null);
906
+ const rafRef = useRef(null);
907
+ const onSnapshot = useCallback((entities) => {
908
+ prevRef.current = currRef.current;
909
+ currRef.current = { entities, arrivedAt: performance.now() };
910
+ }, []);
911
+ const getInterpolated = useCallback((now) => {
912
+ const out = /* @__PURE__ */ new Map();
913
+ const curr = currRef.current;
914
+ if (!curr) return out;
915
+ const prev = prevRef.current;
916
+ if (!prev) {
917
+ for (const e of curr.entities) out.set(e.id, { x: e.x, y: e.y });
918
+ return out;
919
+ }
920
+ const rawAlpha = (now - curr.arrivedAt) / tickIntervalMs;
921
+ const alpha = rawAlpha < 0 ? 0 : rawAlpha > 1 ? 1 : rawAlpha;
922
+ const prevMap = /* @__PURE__ */ new Map();
923
+ for (const e of prev.entities) prevMap.set(e.id, e);
924
+ for (const c of curr.entities) {
925
+ const p = prevMap.get(c.id);
926
+ if (!p) {
927
+ out.set(c.id, { x: c.x, y: c.y });
928
+ } else {
929
+ out.set(c.id, {
930
+ x: p.x + (c.x - p.x) * alpha,
931
+ y: p.y + (c.y - p.y) * alpha
932
+ });
933
+ }
934
+ }
935
+ return out;
936
+ }, [tickIntervalMs]);
937
+ const startLoop = useCallback(
938
+ (draw) => {
939
+ let active = true;
940
+ let reported = false;
941
+ const loop = () => {
942
+ if (!active) return;
943
+ try {
944
+ draw(getInterpolated(performance.now()));
945
+ } catch (error) {
946
+ if (!reported) log10.error("draw-failed", { error: error instanceof Error ? error.message : String(error) });
947
+ reported = true;
948
+ }
949
+ rafRef.current = requestAnimationFrame(loop);
950
+ };
951
+ rafRef.current = requestAnimationFrame(loop);
952
+ return () => {
953
+ active = false;
954
+ if (rafRef.current !== null) {
955
+ cancelAnimationFrame(rafRef.current);
956
+ rafRef.current = null;
957
+ }
958
+ };
959
+ },
960
+ [getInterpolated]
961
+ );
962
+ useEffect(() => {
963
+ return () => {
964
+ if (rafRef.current !== null) {
965
+ cancelAnimationFrame(rafRef.current);
966
+ rafRef.current = null;
967
+ }
968
+ };
969
+ }, []);
970
+ return { onSnapshot, getInterpolated, startLoop };
971
+ }
972
+ var API_BASE = typeof process !== "undefined" && process.env?.VITE_API_URL ? process.env.VITE_API_URL : "http://localhost:3000";
973
+ function getUserId() {
974
+ return localStorage.getItem("userId") || "anonymous";
975
+ }
976
+ async function fetchWithAuth(endpoint, options) {
977
+ const userId = getUserId();
978
+ const response = await fetch(`${API_BASE}${endpoint}`, {
979
+ ...options,
980
+ headers: {
981
+ "Content-Type": "application/json",
982
+ "x-user-id": userId,
983
+ ...options?.headers
984
+ }
985
+ });
986
+ if (!response.ok) {
987
+ const error = await response.json().catch(() => ({ error: response.statusText }));
988
+ throw new Error(error.error || error.message || "Request failed");
989
+ }
990
+ return response.json();
991
+ }
992
+ function useGitHubStatus() {
993
+ return useQuery({
994
+ queryKey: ["github", "status"],
995
+ queryFn: () => fetchWithAuth("/api/github/status"),
996
+ staleTime: 6e4,
997
+ // 1 minute
998
+ retry: false
999
+ });
1000
+ }
1001
+ function useConnectGitHub() {
1002
+ const connectGitHub = useCallback(() => {
1003
+ const userId = getUserId();
1004
+ const state = btoa(JSON.stringify({ userId, returnUrl: window.location.href }));
1005
+ window.location.href = `${API_BASE}/api/github/oauth/authorize?state=${state}`;
1006
+ }, []);
1007
+ return { connectGitHub };
1008
+ }
1009
+ function useDisconnectGitHub() {
1010
+ const queryClient = useQueryClient();
1011
+ return useMutation({
1012
+ mutationFn: () => fetchWithAuth("/api/github/disconnect", { method: "POST" }),
1013
+ onSuccess: () => {
1014
+ queryClient.invalidateQueries({ queryKey: ["github", "status"] });
1015
+ queryClient.removeQueries({ queryKey: ["github", "repos"] });
1016
+ }
1017
+ });
1018
+ }
1019
+ function useGitHubRepos(page = 1, perPage = 30) {
1020
+ return useQuery({
1021
+ queryKey: ["github", "repos", page, perPage],
1022
+ queryFn: () => fetchWithAuth(`/api/github/repos?page=${page}&per_page=${perPage}`),
1023
+ enabled: true,
1024
+ // Only fetch if user is connected
1025
+ staleTime: 3e5
1026
+ // 5 minutes
1027
+ });
1028
+ }
1029
+ function useGitHubRepo(owner, repo, enabled = true) {
1030
+ return useQuery({
1031
+ queryKey: ["github", "repo", owner, repo],
1032
+ queryFn: () => fetchWithAuth(`/api/github/repos/${owner}/${repo}`),
1033
+ enabled: enabled && !!owner && !!repo,
1034
+ staleTime: 3e5
1035
+ // 5 minutes
1036
+ });
1037
+ }
1038
+ function useGitHubBranches(owner, repo, enabled = true) {
1039
+ return useQuery({
1040
+ queryKey: ["github", "branches", owner, repo],
1041
+ queryFn: () => fetchWithAuth(`/api/github/repos/${owner}/${repo}/branches`),
1042
+ enabled: enabled && !!owner && !!repo,
1043
+ staleTime: 6e4
1044
+ // 1 minute
1045
+ });
1046
+ }
1047
+ function useTickVisibility(traits) {
1048
+ const key = traits.join("\0");
1049
+ useEffect(() => getTraitPresence().watch(key.split("\0")), [key]);
1050
+ return useCallback(() => getTraitPresence().state(key.split("\0")) !== "off-screen", [key]);
1051
+ }
1052
+
1053
+ export { SharedEntityStoreContext, createSharedEntityStore, runTickFrame, useAgentChat, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, usePreview, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSharedEntityStoreContext, useTickVisibility, useTraitListens, useUIEvents, useValidation };