@fraziym/axoniz 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 (512) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +76 -0
  3. package/dist/agents/definition.d.ts +15 -0
  4. package/dist/agents/definition.d.ts.map +1 -0
  5. package/dist/agents/definition.js +41 -0
  6. package/dist/agents/definition.js.map +1 -0
  7. package/dist/agents/index.d.ts +12 -0
  8. package/dist/agents/index.d.ts.map +1 -0
  9. package/dist/agents/index.js +11 -0
  10. package/dist/agents/index.js.map +1 -0
  11. package/dist/agents/registry.d.ts +17 -0
  12. package/dist/agents/registry.d.ts.map +1 -0
  13. package/dist/agents/registry.js +23 -0
  14. package/dist/agents/registry.js.map +1 -0
  15. package/dist/agents/specialized.d.ts +31 -0
  16. package/dist/agents/specialized.d.ts.map +1 -0
  17. package/dist/agents/specialized.js +75 -0
  18. package/dist/agents/specialized.js.map +1 -0
  19. package/dist/awareness/index.d.ts +14 -0
  20. package/dist/awareness/index.d.ts.map +1 -0
  21. package/dist/awareness/index.js +22 -0
  22. package/dist/awareness/index.js.map +1 -0
  23. package/dist/awareness/service.d.ts +180 -0
  24. package/dist/awareness/service.d.ts.map +1 -0
  25. package/dist/awareness/service.js +789 -0
  26. package/dist/awareness/service.js.map +1 -0
  27. package/dist/cli/entry.d.ts +13 -0
  28. package/dist/cli/entry.d.ts.map +1 -0
  29. package/dist/cli/entry.js +35 -0
  30. package/dist/cli/entry.js.map +1 -0
  31. package/dist/comms/telegram.d.ts +41 -0
  32. package/dist/comms/telegram.d.ts.map +1 -0
  33. package/dist/comms/telegram.js +332 -0
  34. package/dist/comms/telegram.js.map +1 -0
  35. package/dist/core/agent.d.ts +252 -0
  36. package/dist/core/agent.d.ts.map +1 -0
  37. package/dist/core/agent.js +1399 -0
  38. package/dist/core/agent.js.map +1 -0
  39. package/dist/core/auth.d.ts +23 -0
  40. package/dist/core/auth.d.ts.map +1 -0
  41. package/dist/core/auth.js +113 -0
  42. package/dist/core/auth.js.map +1 -0
  43. package/dist/core/authority.d.ts +118 -0
  44. package/dist/core/authority.d.ts.map +1 -0
  45. package/dist/core/authority.js +402 -0
  46. package/dist/core/authority.js.map +1 -0
  47. package/dist/core/backend/async_queue.d.ts +17 -0
  48. package/dist/core/backend/async_queue.d.ts.map +1 -0
  49. package/dist/core/backend/async_queue.js +66 -0
  50. package/dist/core/backend/async_queue.js.map +1 -0
  51. package/dist/core/backend/index.d.ts +24 -0
  52. package/dist/core/backend/index.d.ts.map +1 -0
  53. package/dist/core/backend/index.js +128 -0
  54. package/dist/core/backend/index.js.map +1 -0
  55. package/dist/core/backend/llama_server.d.ts +39 -0
  56. package/dist/core/backend/llama_server.d.ts.map +1 -0
  57. package/dist/core/backend/llama_server.js +182 -0
  58. package/dist/core/backend/llama_server.js.map +1 -0
  59. package/dist/core/backend/llamacpp.d.ts +40 -0
  60. package/dist/core/backend/llamacpp.d.ts.map +1 -0
  61. package/dist/core/backend/llamacpp.js +200 -0
  62. package/dist/core/backend/llamacpp.js.map +1 -0
  63. package/dist/core/backend/lmstudio.d.ts +53 -0
  64. package/dist/core/backend/lmstudio.d.ts.map +1 -0
  65. package/dist/core/backend/lmstudio.js +274 -0
  66. package/dist/core/backend/lmstudio.js.map +1 -0
  67. package/dist/core/backend/ollama.d.ts +25 -0
  68. package/dist/core/backend/ollama.d.ts.map +1 -0
  69. package/dist/core/backend/ollama.js +86 -0
  70. package/dist/core/backend/ollama.js.map +1 -0
  71. package/dist/core/backend/openai.d.ts +27 -0
  72. package/dist/core/backend/openai.d.ts.map +1 -0
  73. package/dist/core/backend/openai.js +84 -0
  74. package/dist/core/backend/openai.js.map +1 -0
  75. package/dist/core/backend/types.d.ts +73 -0
  76. package/dist/core/backend/types.d.ts.map +1 -0
  77. package/dist/core/backend/types.js +137 -0
  78. package/dist/core/backend/types.js.map +1 -0
  79. package/dist/core/chat_store.d.ts +77 -0
  80. package/dist/core/chat_store.d.ts.map +1 -0
  81. package/dist/core/chat_store.js +332 -0
  82. package/dist/core/chat_store.js.map +1 -0
  83. package/dist/core/cli.d.ts +82 -0
  84. package/dist/core/cli.d.ts.map +1 -0
  85. package/dist/core/cli.js +602 -0
  86. package/dist/core/cli.js.map +1 -0
  87. package/dist/core/config.d.ts +127 -0
  88. package/dist/core/config.d.ts.map +1 -0
  89. package/dist/core/config.js +295 -0
  90. package/dist/core/config.js.map +1 -0
  91. package/dist/core/debug.d.ts +8 -0
  92. package/dist/core/debug.d.ts.map +1 -0
  93. package/dist/core/debug.js +8 -0
  94. package/dist/core/debug.js.map +1 -0
  95. package/dist/core/downloader.d.ts +31 -0
  96. package/dist/core/downloader.d.ts.map +1 -0
  97. package/dist/core/downloader.js +180 -0
  98. package/dist/core/downloader.js.map +1 -0
  99. package/dist/core/errors.d.ts +80 -0
  100. package/dist/core/errors.d.ts.map +1 -0
  101. package/dist/core/errors.js +134 -0
  102. package/dist/core/errors.js.map +1 -0
  103. package/dist/core/extras.d.ts +160 -0
  104. package/dist/core/extras.d.ts.map +1 -0
  105. package/dist/core/extras.js +553 -0
  106. package/dist/core/extras.js.map +1 -0
  107. package/dist/core/health.d.ts +27 -0
  108. package/dist/core/health.d.ts.map +1 -0
  109. package/dist/core/health.js +96 -0
  110. package/dist/core/health.js.map +1 -0
  111. package/dist/core/history.d.ts +50 -0
  112. package/dist/core/history.d.ts.map +1 -0
  113. package/dist/core/history.js +276 -0
  114. package/dist/core/history.js.map +1 -0
  115. package/dist/core/index.d.ts +6 -0
  116. package/dist/core/index.d.ts.map +1 -0
  117. package/dist/core/index.js +6 -0
  118. package/dist/core/index.js.map +1 -0
  119. package/dist/core/intelligence/ast_index.d.ts +255 -0
  120. package/dist/core/intelligence/ast_index.d.ts.map +1 -0
  121. package/dist/core/intelligence/ast_index.js +1369 -0
  122. package/dist/core/intelligence/ast_index.js.map +1 -0
  123. package/dist/core/intelligence/confidence.d.ts +113 -0
  124. package/dist/core/intelligence/confidence.d.ts.map +1 -0
  125. package/dist/core/intelligence/confidence.js +298 -0
  126. package/dist/core/intelligence/confidence.js.map +1 -0
  127. package/dist/core/intelligence/context_compressor.d.ts +80 -0
  128. package/dist/core/intelligence/context_compressor.d.ts.map +1 -0
  129. package/dist/core/intelligence/context_compressor.js +245 -0
  130. package/dist/core/intelligence/context_compressor.js.map +1 -0
  131. package/dist/core/intelligence/daemon.d.ts +247 -0
  132. package/dist/core/intelligence/daemon.d.ts.map +1 -0
  133. package/dist/core/intelligence/daemon.js +842 -0
  134. package/dist/core/intelligence/daemon.js.map +1 -0
  135. package/dist/core/intelligence/index.d.ts +60 -0
  136. package/dist/core/intelligence/index.d.ts.map +1 -0
  137. package/dist/core/intelligence/index.js +101 -0
  138. package/dist/core/intelligence/index.js.map +1 -0
  139. package/dist/core/intelligence/predictor.d.ts +246 -0
  140. package/dist/core/intelligence/predictor.d.ts.map +1 -0
  141. package/dist/core/intelligence/predictor.js +590 -0
  142. package/dist/core/intelligence/predictor.js.map +1 -0
  143. package/dist/core/intelligence/reflex.d.ts +84 -0
  144. package/dist/core/intelligence/reflex.d.ts.map +1 -0
  145. package/dist/core/intelligence/reflex.js +344 -0
  146. package/dist/core/intelligence/reflex.js.map +1 -0
  147. package/dist/core/intelligence/self_correction.d.ts +121 -0
  148. package/dist/core/intelligence/self_correction.d.ts.map +1 -0
  149. package/dist/core/intelligence/self_correction.js +327 -0
  150. package/dist/core/intelligence/self_correction.js.map +1 -0
  151. package/dist/core/intelligence/skill_distiller.d.ts +100 -0
  152. package/dist/core/intelligence/skill_distiller.d.ts.map +1 -0
  153. package/dist/core/intelligence/skill_distiller.js +246 -0
  154. package/dist/core/intelligence/skill_distiller.js.map +1 -0
  155. package/dist/core/intelligence/swarm.d.ts +330 -0
  156. package/dist/core/intelligence/swarm.d.ts.map +1 -0
  157. package/dist/core/intelligence/swarm.js +1064 -0
  158. package/dist/core/intelligence/swarm.js.map +1 -0
  159. package/dist/core/intelligence/trajectory.d.ts +107 -0
  160. package/dist/core/intelligence/trajectory.d.ts.map +1 -0
  161. package/dist/core/intelligence/trajectory.js +330 -0
  162. package/dist/core/intelligence/trajectory.js.map +1 -0
  163. package/dist/core/logger.d.ts +111 -0
  164. package/dist/core/logger.d.ts.map +1 -0
  165. package/dist/core/logger.js +640 -0
  166. package/dist/core/logger.js.map +1 -0
  167. package/dist/core/loop.d.ts +123 -0
  168. package/dist/core/loop.d.ts.map +1 -0
  169. package/dist/core/loop.js +423 -0
  170. package/dist/core/loop.js.map +1 -0
  171. package/dist/core/memory.d.ts +81 -0
  172. package/dist/core/memory.d.ts.map +1 -0
  173. package/dist/core/memory.js +328 -0
  174. package/dist/core/memory.js.map +1 -0
  175. package/dist/core/metrics.d.ts +29 -0
  176. package/dist/core/metrics.d.ts.map +1 -0
  177. package/dist/core/metrics.js +109 -0
  178. package/dist/core/metrics.js.map +1 -0
  179. package/dist/core/models.d.ts +51 -0
  180. package/dist/core/models.d.ts.map +1 -0
  181. package/dist/core/models.js +146 -0
  182. package/dist/core/models.js.map +1 -0
  183. package/dist/core/optimizer.d.ts +34 -0
  184. package/dist/core/optimizer.d.ts.map +1 -0
  185. package/dist/core/optimizer.js +131 -0
  186. package/dist/core/optimizer.js.map +1 -0
  187. package/dist/core/persona.d.ts +35 -0
  188. package/dist/core/persona.d.ts.map +1 -0
  189. package/dist/core/persona.js +126 -0
  190. package/dist/core/persona.js.map +1 -0
  191. package/dist/core/rate_limit.d.ts +23 -0
  192. package/dist/core/rate_limit.d.ts.map +1 -0
  193. package/dist/core/rate_limit.js +62 -0
  194. package/dist/core/rate_limit.js.map +1 -0
  195. package/dist/core/runner.d.ts +63 -0
  196. package/dist/core/runner.d.ts.map +1 -0
  197. package/dist/core/runner.js +671 -0
  198. package/dist/core/runner.js.map +1 -0
  199. package/dist/core/stream_parser.d.ts +43 -0
  200. package/dist/core/stream_parser.d.ts.map +1 -0
  201. package/dist/core/stream_parser.js +140 -0
  202. package/dist/core/stream_parser.js.map +1 -0
  203. package/dist/core/tool_schemas.d.ts +26 -0
  204. package/dist/core/tool_schemas.d.ts.map +1 -0
  205. package/dist/core/tool_schemas.js +124 -0
  206. package/dist/core/tool_schemas.js.map +1 -0
  207. package/dist/core/which.d.ts +2 -0
  208. package/dist/core/which.d.ts.map +1 -0
  209. package/dist/core/which.js +35 -0
  210. package/dist/core/which.js.map +1 -0
  211. package/dist/goals/index.d.ts +9 -0
  212. package/dist/goals/index.d.ts.map +1 -0
  213. package/dist/goals/index.js +17 -0
  214. package/dist/goals/index.js.map +1 -0
  215. package/dist/goals/service.d.ts +115 -0
  216. package/dist/goals/service.d.ts.map +1 -0
  217. package/dist/goals/service.js +415 -0
  218. package/dist/goals/service.js.map +1 -0
  219. package/dist/goals/types.d.ts +47 -0
  220. package/dist/goals/types.d.ts.map +1 -0
  221. package/dist/goals/types.js +66 -0
  222. package/dist/goals/types.js.map +1 -0
  223. package/dist/index.d.ts +22 -0
  224. package/dist/index.d.ts.map +1 -0
  225. package/dist/index.js +22 -0
  226. package/dist/index.js.map +1 -0
  227. package/dist/integrations/autonomous_startup.d.ts +51 -0
  228. package/dist/integrations/autonomous_startup.d.ts.map +1 -0
  229. package/dist/integrations/autonomous_startup.js +419 -0
  230. package/dist/integrations/autonomous_startup.js.map +1 -0
  231. package/dist/integrations/goose.d.ts +105 -0
  232. package/dist/integrations/goose.d.ts.map +1 -0
  233. package/dist/integrations/goose.js +408 -0
  234. package/dist/integrations/goose.js.map +1 -0
  235. package/dist/integrations/index.d.ts +21 -0
  236. package/dist/integrations/index.d.ts.map +1 -0
  237. package/dist/integrations/index.js +17 -0
  238. package/dist/integrations/index.js.map +1 -0
  239. package/dist/integrations/mcp.d.ts +73 -0
  240. package/dist/integrations/mcp.d.ts.map +1 -0
  241. package/dist/integrations/mcp.js +307 -0
  242. package/dist/integrations/mcp.js.map +1 -0
  243. package/dist/integrations/mempalace.d.ts +18 -0
  244. package/dist/integrations/mempalace.d.ts.map +1 -0
  245. package/dist/integrations/mempalace.js +25 -0
  246. package/dist/integrations/mempalace.js.map +1 -0
  247. package/dist/integrations/multi_agent.d.ts +82 -0
  248. package/dist/integrations/multi_agent.d.ts.map +1 -0
  249. package/dist/integrations/multi_agent.js +280 -0
  250. package/dist/integrations/multi_agent.js.map +1 -0
  251. package/dist/integrations/unified_memory.d.ts +415 -0
  252. package/dist/integrations/unified_memory.d.ts.map +1 -0
  253. package/dist/integrations/unified_memory.js +1489 -0
  254. package/dist/integrations/unified_memory.js.map +1 -0
  255. package/dist/roles/beru.yaml +48 -0
  256. package/dist/sidecar/client.d.ts +63 -0
  257. package/dist/sidecar/client.d.ts.map +1 -0
  258. package/dist/sidecar/client.js +222 -0
  259. package/dist/sidecar/client.js.map +1 -0
  260. package/dist/sidecar/index.d.ts +7 -0
  261. package/dist/sidecar/index.d.ts.map +1 -0
  262. package/dist/sidecar/index.js +6 -0
  263. package/dist/sidecar/index.js.map +1 -0
  264. package/dist/startup.d.ts +22 -0
  265. package/dist/startup.d.ts.map +1 -0
  266. package/dist/startup.js +194 -0
  267. package/dist/startup.js.map +1 -0
  268. package/dist/tools/_internal.d.ts +90 -0
  269. package/dist/tools/_internal.d.ts.map +1 -0
  270. package/dist/tools/_internal.js +375 -0
  271. package/dist/tools/_internal.js.map +1 -0
  272. package/dist/tools/_smoke.d.ts +2 -0
  273. package/dist/tools/_smoke.d.ts.map +1 -0
  274. package/dist/tools/_smoke.js +203 -0
  275. package/dist/tools/_smoke.js.map +1 -0
  276. package/dist/tools/axodex_tools.d.ts +51 -0
  277. package/dist/tools/axodex_tools.d.ts.map +1 -0
  278. package/dist/tools/axodex_tools.js +181 -0
  279. package/dist/tools/axodex_tools.js.map +1 -0
  280. package/dist/tools/code_tools.d.ts +33 -0
  281. package/dist/tools/code_tools.d.ts.map +1 -0
  282. package/dist/tools/code_tools.js +191 -0
  283. package/dist/tools/code_tools.js.map +1 -0
  284. package/dist/tools/computer_tools.d.ts +59 -0
  285. package/dist/tools/computer_tools.d.ts.map +1 -0
  286. package/dist/tools/computer_tools.js +348 -0
  287. package/dist/tools/computer_tools.js.map +1 -0
  288. package/dist/tools/file_tools.d.ts +51 -0
  289. package/dist/tools/file_tools.d.ts.map +1 -0
  290. package/dist/tools/file_tools.js +424 -0
  291. package/dist/tools/file_tools.js.map +1 -0
  292. package/dist/tools/index.d.ts +13 -0
  293. package/dist/tools/index.d.ts.map +1 -0
  294. package/dist/tools/index.js +13 -0
  295. package/dist/tools/index.js.map +1 -0
  296. package/dist/tools/shell_tools.d.ts +39 -0
  297. package/dist/tools/shell_tools.d.ts.map +1 -0
  298. package/dist/tools/shell_tools.js +163 -0
  299. package/dist/tools/shell_tools.js.map +1 -0
  300. package/dist/tools/web_tools.d.ts +31 -0
  301. package/dist/tools/web_tools.d.ts.map +1 -0
  302. package/dist/tools/web_tools.js +117 -0
  303. package/dist/tools/web_tools.js.map +1 -0
  304. package/dist/voice/index.d.ts +41 -0
  305. package/dist/voice/index.d.ts.map +1 -0
  306. package/dist/voice/index.js +58 -0
  307. package/dist/voice/index.js.map +1 -0
  308. package/dist/voice/light_daemon.d.ts +197 -0
  309. package/dist/voice/light_daemon.d.ts.map +1 -0
  310. package/dist/voice/light_daemon.js +746 -0
  311. package/dist/voice/light_daemon.js.map +1 -0
  312. package/dist/voice/setup.d.ts +63 -0
  313. package/dist/voice/setup.d.ts.map +1 -0
  314. package/dist/voice/setup.js +443 -0
  315. package/dist/voice/setup.js.map +1 -0
  316. package/dist/voice/stt.d.ts +148 -0
  317. package/dist/voice/stt.d.ts.map +1 -0
  318. package/dist/voice/stt.js +361 -0
  319. package/dist/voice/stt.js.map +1 -0
  320. package/dist/voice/tts.d.ts +168 -0
  321. package/dist/voice/tts.d.ts.map +1 -0
  322. package/dist/voice/tts.js +698 -0
  323. package/dist/voice/tts.js.map +1 -0
  324. package/dist/voice/voice_loop.d.ts +101 -0
  325. package/dist/voice/voice_loop.d.ts.map +1 -0
  326. package/dist/voice/voice_loop.js +463 -0
  327. package/dist/voice/voice_loop.js.map +1 -0
  328. package/dist/voice/wake_word.d.ts +153 -0
  329. package/dist/voice/wake_word.d.ts.map +1 -0
  330. package/dist/voice/wake_word.js +458 -0
  331. package/dist/voice/wake_word.js.map +1 -0
  332. package/dist/voice/wav.d.ts +99 -0
  333. package/dist/voice/wav.d.ts.map +1 -0
  334. package/dist/voice/wav.js +306 -0
  335. package/dist/voice/wav.js.map +1 -0
  336. package/dist/web/broker.d.ts +33 -0
  337. package/dist/web/broker.d.ts.map +1 -0
  338. package/dist/web/broker.js +58 -0
  339. package/dist/web/broker.js.map +1 -0
  340. package/dist/web/open_browser.d.ts +2 -0
  341. package/dist/web/open_browser.d.ts.map +1 -0
  342. package/dist/web/open_browser.js +42 -0
  343. package/dist/web/open_browser.js.map +1 -0
  344. package/dist/web/server.d.ts +54 -0
  345. package/dist/web/server.d.ts.map +1 -0
  346. package/dist/web/server.js +831 -0
  347. package/dist/web/server.js.map +1 -0
  348. package/dist/web/static/app.js +4121 -0
  349. package/dist/web/static/index.html +2281 -0
  350. package/dist/web/static/js/MODULE_SUMMARY.md +124 -0
  351. package/dist/web/static/js/a11y.js +165 -0
  352. package/dist/web/static/js/admin.js +2145 -0
  353. package/dist/web/static/js/assistant.js +475 -0
  354. package/dist/web/static/js/calendar/reminders.js +114 -0
  355. package/dist/web/static/js/calendar/utils.js +166 -0
  356. package/dist/web/static/js/calendar.js +3348 -0
  357. package/dist/web/static/js/censor.js +356 -0
  358. package/dist/web/static/js/chat.js +4546 -0
  359. package/dist/web/static/js/chatRenderer.js +2294 -0
  360. package/dist/web/static/js/chatStream.js +276 -0
  361. package/dist/web/static/js/codeRunner.js +398 -0
  362. package/dist/web/static/js/color/hex.js +14 -0
  363. package/dist/web/static/js/colorPicker.js +453 -0
  364. package/dist/web/static/js/compare/icons.js +77 -0
  365. package/dist/web/static/js/compare/index.js +1482 -0
  366. package/dist/web/static/js/compare/models.js +104 -0
  367. package/dist/web/static/js/compare/panes.js +817 -0
  368. package/dist/web/static/js/compare/probe.js +78 -0
  369. package/dist/web/static/js/compare/scoreboard.js +223 -0
  370. package/dist/web/static/js/compare/selector.js +1335 -0
  371. package/dist/web/static/js/compare/state.js +58 -0
  372. package/dist/web/static/js/compare/stream.js +695 -0
  373. package/dist/web/static/js/compare/vote.js +254 -0
  374. package/dist/web/static/js/cookbook-diagnosis.js +694 -0
  375. package/dist/web/static/js/cookbook-hwfit.js +1888 -0
  376. package/dist/web/static/js/cookbook.js +2093 -0
  377. package/dist/web/static/js/cookbookDownload.js +633 -0
  378. package/dist/web/static/js/cookbookProgressSignal.js +29 -0
  379. package/dist/web/static/js/cookbookRunning.js +3506 -0
  380. package/dist/web/static/js/cookbookServe.js +2128 -0
  381. package/dist/web/static/js/document.js +9731 -0
  382. package/dist/web/static/js/documentLibrary.js +3376 -0
  383. package/dist/web/static/js/dragSort.js +265 -0
  384. package/dist/web/static/js/editor/ai-inpaint.js +374 -0
  385. package/dist/web/static/js/editor/ai-models.js +273 -0
  386. package/dist/web/static/js/editor/ai-rembg.js +230 -0
  387. package/dist/web/static/js/editor/ai-tool-runner.js +147 -0
  388. package/dist/web/static/js/editor/ai-tools-misc.js +216 -0
  389. package/dist/web/static/js/editor/build/controls.js +366 -0
  390. package/dist/web/static/js/editor/build/popups.js +112 -0
  391. package/dist/web/static/js/editor/build/right-panel.js +200 -0
  392. package/dist/web/static/js/editor/build/toolbar.js +73 -0
  393. package/dist/web/static/js/editor/build/topbar.js +131 -0
  394. package/dist/web/static/js/editor/build/transform-popup.js +109 -0
  395. package/dist/web/static/js/editor/canvas-coords.js +21 -0
  396. package/dist/web/static/js/editor/canvas-events.js +197 -0
  397. package/dist/web/static/js/editor/canvas-transforms.js +132 -0
  398. package/dist/web/static/js/editor/checkerboard.js +24 -0
  399. package/dist/web/static/js/editor/clipboard-and-drop.js +133 -0
  400. package/dist/web/static/js/editor/composite-helpers.js +83 -0
  401. package/dist/web/static/js/editor/filters/blur.js +118 -0
  402. package/dist/web/static/js/editor/filters/edge-feather.js +70 -0
  403. package/dist/web/static/js/editor/fx/adj-popup.js +677 -0
  404. package/dist/web/static/js/editor/fx/filter-string.js +38 -0
  405. package/dist/web/static/js/editor/fx/histogram.js +67 -0
  406. package/dist/web/static/js/editor/fx/pixel-pass.js +249 -0
  407. package/dist/web/static/js/editor/harmonize-masks.js +116 -0
  408. package/dist/web/static/js/editor/history-panel.js +176 -0
  409. package/dist/web/static/js/editor/keyboard-shortcuts.js +271 -0
  410. package/dist/web/static/js/editor/layer-helpers.js +131 -0
  411. package/dist/web/static/js/editor/layer-panel.js +600 -0
  412. package/dist/web/static/js/editor/mask-utils.js +91 -0
  413. package/dist/web/static/js/editor/shortcuts-popover.js +149 -0
  414. package/dist/web/static/js/editor/slider-ux.js +191 -0
  415. package/dist/web/static/js/editor/snap.js +107 -0
  416. package/dist/web/static/js/editor/state.js +257 -0
  417. package/dist/web/static/js/editor/stroke-pipeline.js +162 -0
  418. package/dist/web/static/js/editor/stroke-tool-sliders.js +64 -0
  419. package/dist/web/static/js/editor/tools/clone.js +81 -0
  420. package/dist/web/static/js/editor/tools/crop.js +137 -0
  421. package/dist/web/static/js/editor/tools/flood-fill.js +72 -0
  422. package/dist/web/static/js/editor/tools/lasso-mask.js +171 -0
  423. package/dist/web/static/js/editor/tools/lasso.js +65 -0
  424. package/dist/web/static/js/editor/tools/move.js +79 -0
  425. package/dist/web/static/js/editor/tools/stroke.js +123 -0
  426. package/dist/web/static/js/editor/tools/transform-drag.js +174 -0
  427. package/dist/web/static/js/editor/tools/transform-handles.js +271 -0
  428. package/dist/web/static/js/editor/tools/transform-session.js +381 -0
  429. package/dist/web/static/js/editor/tools/wand.js +46 -0
  430. package/dist/web/static/js/editor/wire-import.js +148 -0
  431. package/dist/web/static/js/editor/wire-inpaint-controls.js +164 -0
  432. package/dist/web/static/js/editor/wire-merge-buttons.js +103 -0
  433. package/dist/web/static/js/editor/wire-selection-controls.js +170 -0
  434. package/dist/web/static/js/editor/wire-topbar-menus.js +174 -0
  435. package/dist/web/static/js/editor/wire-topbar-overflow.js +49 -0
  436. package/dist/web/static/js/editor/wire-topbar.js +188 -0
  437. package/dist/web/static/js/emailInbox.js +1245 -0
  438. package/dist/web/static/js/emailLibrary/replyRecipients.js +27 -0
  439. package/dist/web/static/js/emailLibrary/signatureFold.js +339 -0
  440. package/dist/web/static/js/emailLibrary/state.js +34 -0
  441. package/dist/web/static/js/emailLibrary/utils.js +202 -0
  442. package/dist/web/static/js/emailLibrary.js +5217 -0
  443. package/dist/web/static/js/emojiPicker.js +311 -0
  444. package/dist/web/static/js/escMenuStack.js +102 -0
  445. package/dist/web/static/js/fileHandler.js +295 -0
  446. package/dist/web/static/js/gallery.js +2835 -0
  447. package/dist/web/static/js/galleryEditor.js +3798 -0
  448. package/dist/web/static/js/group.js +955 -0
  449. package/dist/web/static/js/init.js +405 -0
  450. package/dist/web/static/js/keyboard-shortcuts.js +292 -0
  451. package/dist/web/static/js/langIcons.js +187 -0
  452. package/dist/web/static/js/markdown/tableRow.js +19 -0
  453. package/dist/web/static/js/markdown.js +806 -0
  454. package/dist/web/static/js/memory.js +1418 -0
  455. package/dist/web/static/js/modalManager.js +1552 -0
  456. package/dist/web/static/js/modalSnap.js +782 -0
  457. package/dist/web/static/js/model/matchKey.js +19 -0
  458. package/dist/web/static/js/modelPicker.js +695 -0
  459. package/dist/web/static/js/modelSort.js +33 -0
  460. package/dist/web/static/js/models.js +642 -0
  461. package/dist/web/static/js/notes.js +5054 -0
  462. package/dist/web/static/js/package.json +1 -0
  463. package/dist/web/static/js/platform.js +47 -0
  464. package/dist/web/static/js/presets.js +1110 -0
  465. package/dist/web/static/js/providers.js +93 -0
  466. package/dist/web/static/js/rag.js +177 -0
  467. package/dist/web/static/js/research/jobs.js +335 -0
  468. package/dist/web/static/js/research/panel.js +1233 -0
  469. package/dist/web/static/js/researchSynapse.js +225 -0
  470. package/dist/web/static/js/search-chat.js +201 -0
  471. package/dist/web/static/js/search.js +52 -0
  472. package/dist/web/static/js/section-management.js +260 -0
  473. package/dist/web/static/js/sessions.js +3108 -0
  474. package/dist/web/static/js/settings.js +4991 -0
  475. package/dist/web/static/js/sidebar-layout.js +573 -0
  476. package/dist/web/static/js/signature.js +504 -0
  477. package/dist/web/static/js/skills.js +1908 -0
  478. package/dist/web/static/js/slashAutocomplete.js +267 -0
  479. package/dist/web/static/js/slashCommands.js +6099 -0
  480. package/dist/web/static/js/spinner.js +406 -0
  481. package/dist/web/static/js/storage.js +123 -0
  482. package/dist/web/static/js/tasks.js +2699 -0
  483. package/dist/web/static/js/theme.js +2086 -0
  484. package/dist/web/static/js/tileManager.js +386 -0
  485. package/dist/web/static/js/tourAutoplay.js +133 -0
  486. package/dist/web/static/js/tourHints.js +179 -0
  487. package/dist/web/static/js/tts-ai.js +521 -0
  488. package/dist/web/static/js/ui.js +1288 -0
  489. package/dist/web/static/js/util/ordinal.js +13 -0
  490. package/dist/web/static/js/voiceRecorder.js +283 -0
  491. package/dist/web/static/js/windowDrag.js +326 -0
  492. package/dist/web/static/js/windowResize.js +233 -0
  493. package/dist/web/static/landing.html +824 -0
  494. package/dist/web/static/lib/docx.umd.min.js +20116 -0
  495. package/dist/web/static/lib/highlight.min.js +1213 -0
  496. package/dist/web/static/lib/html2pdf.bundle.min.js +3 -0
  497. package/dist/web/static/lib/mammoth.browser.min.js +21 -0
  498. package/dist/web/static/lib/qrcode.min.js +8 -0
  499. package/dist/web/static/lib/xlsx.full.min.js +24 -0
  500. package/dist/web/static/login.html +582 -0
  501. package/dist/web/static/manifest.json +15 -0
  502. package/dist/web/static/style.css +35733 -0
  503. package/dist/web/static/sw.js +144 -0
  504. package/dist/workflows/engine.d.ts +162 -0
  505. package/dist/workflows/engine.d.ts.map +1 -0
  506. package/dist/workflows/engine.js +625 -0
  507. package/dist/workflows/engine.js.map +1 -0
  508. package/dist/workflows/index.d.ts +8 -0
  509. package/dist/workflows/index.d.ts.map +1 -0
  510. package/dist/workflows/index.js +14 -0
  511. package/dist/workflows/index.js.map +1 -0
  512. package/package.json +112 -0
@@ -0,0 +1,13 @@
1
+ // Pure (browser-free) English ordinal suffix, e.g. 1 -> "st", 21 -> "st",
2
+ // 22 -> "nd", 23 -> "rd", 11/12/13 -> "th". Extracted so it can be unit-tested.
3
+ export function ordinalSuffix(n) {
4
+ const a = Math.abs(Math.trunc(Number(n) || 0));
5
+ const mod100 = a % 100;
6
+ if (mod100 >= 11 && mod100 <= 13) return 'th';
7
+ switch (a % 10) {
8
+ case 1: return 'st';
9
+ case 2: return 'nd';
10
+ case 3: return 'rd';
11
+ default: return 'th';
12
+ }
13
+ }
@@ -0,0 +1,283 @@
1
+ // static/js/voiceRecorder.js
2
+
3
+ /**
4
+ * Voice recording with optional Speech-to-Text transcription.
5
+ *
6
+ * STT providers:
7
+ * "disabled" — record audio as file attachment (original behavior)
8
+ * "browser" — use Web Speech API for real-time transcription
9
+ * "local" — send recording to server /api/stt/transcribe (Whisper)
10
+ * "endpoint:<id>" — send recording to server /api/stt/transcribe (API)
11
+ */
12
+
13
+ let mediaRecorder = null;
14
+ let audioChunks = [];
15
+ let isRecording = false;
16
+ let recordingStartTime = null;
17
+ let recordingInterval = null;
18
+
19
+ // Browser STT state
20
+ let _recognition = null;
21
+ let _browserTranscript = '';
22
+
23
+ // Cached STT provider — refreshed on settings change
24
+ let _sttProvider = 'disabled';
25
+
26
+ /**
27
+ * Fetch current STT provider from server settings
28
+ */
29
+ async function refreshSttProvider() {
30
+ try {
31
+ const res = await fetch('/api/stt/stats', { credentials: 'same-origin' });
32
+ if (res.ok) {
33
+ const stats = await res.json();
34
+ _sttProvider = stats.provider || 'disabled';
35
+ // Notify the send button to update its icon
36
+ if (window._updateSendBtnIcon) window._updateSendBtnIcon();
37
+ }
38
+ } catch (e) {
39
+ console.warn('Failed to fetch STT stats:', e);
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Format seconds as MM:SS
45
+ */
46
+ function formatTime(seconds) {
47
+ const mins = Math.floor(seconds / 60).toString().padStart(2, '0');
48
+ const secs = (seconds % 60).toString().padStart(2, '0');
49
+ return `${mins}:${secs}`;
50
+ }
51
+
52
+ /**
53
+ * Reset UI state after recording ends
54
+ */
55
+ function _resetRecordingUI() {
56
+ isRecording = false;
57
+ if (recordingInterval) {
58
+ clearInterval(recordingInterval);
59
+ recordingInterval = null;
60
+ }
61
+ // Reset send button via global callback
62
+ const sendBtn = document.querySelector('.send-btn');
63
+ if (sendBtn) {
64
+ sendBtn.classList.remove('recording');
65
+ sendBtn.dataset.mode = '';
66
+ }
67
+ if (window._updateSendBtnIcon) {
68
+ setTimeout(window._updateSendBtnIcon, 50);
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Start browser speech recognition alongside recording
74
+ */
75
+ function startBrowserSTT() {
76
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
77
+ if (!SpeechRecognition) return;
78
+
79
+ _browserTranscript = '';
80
+ _recognition = new SpeechRecognition();
81
+ _recognition.continuous = true;
82
+ _recognition.interimResults = false;
83
+ _recognition.lang = '';
84
+
85
+ _recognition.onresult = (event) => {
86
+ for (let i = event.resultIndex; i < event.results.length; i++) {
87
+ if (event.results[i].isFinal) {
88
+ _browserTranscript += event.results[i][0].transcript + ' ';
89
+ }
90
+ }
91
+ };
92
+
93
+ _recognition.onerror = (e) => {
94
+ console.warn('Browser STT error:', e.error);
95
+ };
96
+
97
+ _recognition.start();
98
+ }
99
+
100
+ function stopBrowserSTT() {
101
+ if (_recognition) {
102
+ try { _recognition.stop(); } catch (e) { /* ignore */ }
103
+ _recognition = null;
104
+ }
105
+ return _browserTranscript.trim();
106
+ }
107
+
108
+ /**
109
+ * Send audio to server for transcription
110
+ */
111
+ async function transcribeOnServer(audioBlob) {
112
+ const formData = new FormData();
113
+ formData.append('file', audioBlob, 'audio.webm');
114
+
115
+ const res = await fetch('/api/stt/transcribe', {
116
+ method: 'POST',
117
+ credentials: 'same-origin',
118
+ body: formData,
119
+ });
120
+
121
+ if (!res.ok) {
122
+ const err = await res.json().catch(() => ({}));
123
+ throw new Error(err.detail?.message || 'Transcription failed');
124
+ }
125
+
126
+ const data = await res.json();
127
+ return data.text || '';
128
+ }
129
+
130
+ /**
131
+ * Insert transcribed text into the chat input
132
+ */
133
+ function insertTranscription(text, showToast) {
134
+ if (!text) return;
135
+ const input = document.getElementById('message');
136
+ if (!input) return;
137
+
138
+ const existing = input.value.trim();
139
+ input.value = existing ? existing + ' ' + text : text;
140
+
141
+ // Trigger auto-resize and icon update
142
+ input.dispatchEvent(new Event('input', { bubbles: true }));
143
+ input.focus();
144
+
145
+ if (showToast) showToast('Transcribed');
146
+ }
147
+
148
+ /**
149
+ * Start voice recording
150
+ */
151
+ export function startRecording(onFileCreated, showToast, showError) {
152
+ // Check for secure context (getUserMedia requires HTTPS or localhost)
153
+ if (!window.isSecureContext) {
154
+ if (showError) showError('Microphone requires HTTPS. Use a reverse proxy with SSL or access via localhost.');
155
+ _resetRecordingUI();
156
+ return;
157
+ }
158
+
159
+ if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
160
+ if (showError) showError('Microphone not supported in this browser.');
161
+ _resetRecordingUI();
162
+ return;
163
+ }
164
+
165
+ audioChunks = [];
166
+
167
+ navigator.mediaDevices.getUserMedia({ audio: true })
168
+ .then(stream => {
169
+ mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm' });
170
+
171
+ mediaRecorder.ondataavailable = event => {
172
+ if (event.data.size > 0) {
173
+ audioChunks.push(event.data);
174
+ }
175
+ };
176
+
177
+ mediaRecorder.onstop = async () => {
178
+ stream.getTracks().forEach(track => track.stop());
179
+
180
+ const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
181
+ const provider = _sttProvider;
182
+
183
+ if (provider === 'browser') {
184
+ const transcript = stopBrowserSTT();
185
+ if (transcript) {
186
+ insertTranscription(transcript, showToast);
187
+ } else {
188
+ if (showToast) showToast('No speech detected');
189
+ const audioFile = new File([audioBlob], `voice-message-${Date.now()}.webm`, { type: 'audio/webm' });
190
+ if (onFileCreated) onFileCreated(audioFile);
191
+ }
192
+ } else if (provider === 'local' || provider.startsWith('endpoint:')) {
193
+ // Show "Transcribing..." feedback
194
+ if (showToast) showToast('Transcribing...', 5000);
195
+ try {
196
+ const transcript = await transcribeOnServer(audioBlob);
197
+ if (transcript) {
198
+ insertTranscription(transcript, showToast);
199
+ } else {
200
+ if (showToast) showToast('No speech detected');
201
+ }
202
+ } catch (e) {
203
+ console.error('STT transcription error:', e);
204
+ if (showError) showError('Transcription failed: ' + e.message);
205
+ // Fallback: attach as file
206
+ const audioFile = new File([audioBlob], `voice-message-${Date.now()}.webm`, { type: 'audio/webm' });
207
+ if (onFileCreated) onFileCreated(audioFile);
208
+ }
209
+ } else {
210
+ // STT disabled — attach audio file
211
+ const audioFile = new File([audioBlob], `voice-message-${Date.now()}.webm`, { type: 'audio/webm' });
212
+ if (onFileCreated) onFileCreated(audioFile);
213
+ }
214
+
215
+ _resetRecordingUI();
216
+ };
217
+
218
+ mediaRecorder.start();
219
+ isRecording = true;
220
+ recordingStartTime = new Date();
221
+
222
+ // Start browser STT if that's the provider
223
+ if (_sttProvider === 'browser') {
224
+ startBrowserSTT();
225
+ }
226
+
227
+ if (showToast) {
228
+ showToast('Recording...');
229
+ }
230
+ })
231
+ .catch(error => {
232
+ console.error('Microphone access error:', error);
233
+ if (showError) {
234
+ if (error.name === 'NotAllowedError') {
235
+ showError('Microphone access denied. Check browser permissions.');
236
+ } else if (error.name === 'NotFoundError') {
237
+ showError('No microphone found.');
238
+ } else {
239
+ showError('Microphone error: ' + error.message);
240
+ }
241
+ }
242
+ _resetRecordingUI();
243
+ });
244
+ }
245
+
246
+ /**
247
+ * Stop voice recording
248
+ */
249
+ export function stopRecording() {
250
+ if (mediaRecorder && mediaRecorder.state === 'recording') {
251
+ mediaRecorder.stop();
252
+ // isRecording will be set to false in _resetRecordingUI called from onstop
253
+ } else {
254
+ _resetRecordingUI();
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Check if currently recording
260
+ */
261
+ export function getIsRecording() {
262
+ return isRecording;
263
+ }
264
+
265
+ /**
266
+ * Initialize recording state
267
+ */
268
+ export function init() {
269
+ isRecording = false;
270
+ refreshSttProvider();
271
+ }
272
+
273
+ const voiceRecorderModule = {
274
+ startRecording,
275
+ stopRecording,
276
+ getIsRecording,
277
+ init,
278
+ refreshSttProvider,
279
+ get _sttProvider() { return _sttProvider; },
280
+ set _sttProvider(v) { _sttProvider = v; },
281
+ };
282
+
283
+ export default voiceRecorderModule;
@@ -0,0 +1,326 @@
1
+ // Shared window-drag helper. Replaces the duplicated mousedown / mousemove
2
+ // / mouseup + snap-to-top fullscreen + left/right edge dock patterns that
3
+ // were copy-pasted across calendar.js, tasks.js, gallery.js, emailLibrary.js,
4
+ // documentLibrary.js, theme.js. Behavior stays identical to the old per-file
5
+ // copies — each callsite provides its own enter/exit-fullscreen callbacks
6
+ // since the CSS class + inline styles differ per modal.
7
+ //
8
+ // API:
9
+ // makeWindowDraggable(modal, { content, header, ...options })
10
+ // modal: the wrapping .modal element (or a standalone pane)
11
+ // content: the element being moved (usually .modal-content)
12
+ // header: the drag handle (usually .modal-header)
13
+ // fsClass: optional class name representing "fullscreen" state
14
+ // onEnterFullscreen: optional () => void — called when cursor releases
15
+ // near the top edge (within SNAP_PX). Caller is
16
+ // responsible for adding fsClass + applying inline
17
+ // styles that produce the fullscreen layout.
18
+ // onExitFullscreen: optional (cx, cy) => void — called mid-drag when
19
+ // the cursor leaves the fullscreen "unsnap" band
20
+ // (down > UNSNAP_PX OR near either horizontal edge
21
+ // in dock-snap range). Caller restores windowed
22
+ // inline styles centered around the cursor.
23
+ // skipSelector: CSS selector for elements inside `header` whose
24
+ // clicks should NOT start a drag (close button,
25
+ // form fields, etc). Default: 'button, input, select'
26
+ // onDragEnd: optional (state) => void — fires after mouseup
27
+ // WHEN no snap was committed. state = { rect } so
28
+ // callers can persist the final position.
29
+ // enableTouch: bool — also wire touchstart/touchmove/touchend
30
+ // with the same drag (no fs/dock on touch). Default
31
+ // true on desktop, irrelevant on mobile (mobileSkip).
32
+ // mobileSkip: drag is disabled below this viewport width.
33
+ // Default 768. Set to 0 to never skip.
34
+ // enableDock: bool — enable left + right edge docks.
35
+ // Default true.
36
+ // enableFullscreen: bool — enable top-edge fullscreen snap.
37
+ // Default true when onEnterFullscreen is supplied.
38
+
39
+ import { makeEdgeDockController } from './modalSnap.js';
40
+ import { makeWindowResizable } from './windowResize.js';
41
+
42
+ const SNAP_PX = 6; // cursor distance from top edge for fullscreen snap
43
+ const UNSNAP_PX = 24; // cursor distance from top before fullscreen exits
44
+ const DOCK_EDGE_PX = 60; // cursor distance from L/R edge to trigger dock
45
+ // exit while still in fullscreen state
46
+
47
+ // CSS-var lookup for the rail+sidebar width — used to decide where the
48
+ // "left edge" effectively is during a fullscreen drag-out (the cursor
49
+ // has to pass the rail to count as "near left").
50
+ function _leftNavWidth() {
51
+ const rs = getComputedStyle(document.documentElement);
52
+ const rail = parseInt(rs.getPropertyValue('--icon-rail-w') || '48', 10) || 0;
53
+ const sb = parseInt(rs.getPropertyValue('--sidebar-w') || '0', 10) || 0;
54
+ return rail + sb;
55
+ }
56
+
57
+ export function makeWindowDraggable(modal, options = {}) {
58
+ const content = options.content;
59
+ const header = options.header;
60
+ if (!content || !header) return;
61
+ const fsClass = options.fsClass || null;
62
+ const onEnterFullscreen = options.onEnterFullscreen || null;
63
+ const onExitFullscreen = options.onExitFullscreen || null;
64
+ const enableFullscreen = options.enableFullscreen !== false && !!onEnterFullscreen;
65
+ const onDragEnd = options.onDragEnd || null;
66
+ const onDragStart = options.onDragStart || null;
67
+ const skipSelector = options.skipSelector || 'button, input, select';
68
+ const mobileSkip = (typeof options.mobileSkip === 'number') ? options.mobileSkip : 768;
69
+ const enableTouch = options.enableTouch !== false;
70
+ const enableDock = options.enableDock !== false && !!modal;
71
+
72
+ header.style.cursor = 'move';
73
+ header.style.userSelect = 'none';
74
+
75
+ // Edge/corner resize. Every draggable window also becomes resizable — the
76
+ // same gesture a native desktop window uses (grab an edge or corner, drag).
77
+ // Skipped on mobile (windows are full-screen sheets there) and while the
78
+ // window is fullscreen-snapped or docked. Wired here so all ~12 callsites
79
+ // get it without per-file changes.
80
+ if (options.enableResize !== false) {
81
+ const _dockClasses = ['modal-right-docked', 'modal-left-docked'];
82
+ makeWindowResizable(content, {
83
+ modal,
84
+ mobileSkip,
85
+ minWidth: options.minWidth,
86
+ minHeight: options.minHeight,
87
+ isLocked: () => (fsClass && modal && modal.classList.contains(fsClass))
88
+ || (modal && _dockClasses.some((c) => modal.classList.contains(c))),
89
+ storageKey: options.resizeStorageKey
90
+ || (modal && modal.id ? 'winsize-' + modal.id
91
+ : (content.id ? 'winsize-' + content.id : null)),
92
+ });
93
+ }
94
+
95
+ const rightDock = enableDock ? makeEdgeDockController(modal, 'right') : null;
96
+ // Left dock is opt-in (enableLeftDock). For most windows it's off — the
97
+ // sidebar lives on the left, so a left dock collides with it. The email
98
+ // window enables it so you can park the message on the left and read it
99
+ // while replying in the document on the right.
100
+ const leftDock = (enableDock && options.enableLeftDock) ? makeEdgeDockController(modal, 'left') : null;
101
+
102
+ // Per-drag state, reset on mousedown.
103
+ let dragging = false;
104
+ let startX = 0, startY = 0;
105
+ let startLeft = 0, startTop = 0;
106
+ let snapHint = null;
107
+ // Whether the pointer actually moved beyond a small threshold this drag.
108
+ // Used to suppress the synthetic click the browser fires on mouseup —
109
+ // header click handlers (e.g. "collapse expanded card / back to list")
110
+ // would otherwise fire after a drag and collapse the modal contents.
111
+ let movedDuringDrag = false;
112
+ const MOVE_THRESHOLD = 4;
113
+
114
+ const _showSnapHint = (on) => {
115
+ // Top-edge fullscreen hint. Side hints come from the dock controllers.
116
+ if (!on) {
117
+ if (snapHint) { snapHint.remove(); snapHint = null; }
118
+ return;
119
+ }
120
+ if (snapHint) return;
121
+ snapHint = document.createElement('div');
122
+ snapHint.className = 'modal-snap-hint';
123
+ snapHint.style.cssText =
124
+ 'position:fixed;left:0;top:0;right:0;bottom:0;' +
125
+ 'background:color-mix(in srgb, var(--accent-primary, #60a5fa) 12%, transparent);' +
126
+ 'border:2px dashed color-mix(in srgb, var(--accent-primary, #60a5fa) 60%, transparent);' +
127
+ 'z-index:9998;pointer-events:none;';
128
+ document.body.appendChild(snapHint);
129
+ };
130
+
131
+ const _enterFs = () => {
132
+ if (!onEnterFullscreen) return;
133
+ if (fsClass && modal && modal.classList.contains(fsClass)) return;
134
+ onEnterFullscreen();
135
+ };
136
+ const _exitFs = (cx, cy) => {
137
+ if (!onExitFullscreen) return;
138
+ if (fsClass && modal && !modal.classList.contains(fsClass)) return;
139
+ onExitFullscreen(cx, cy);
140
+ // After exit, re-anchor the drag offsets to the new windowed rect so
141
+ // the drag continues smoothly from the cursor's position.
142
+ const r = content.getBoundingClientRect();
143
+ startX = cx; startY = cy;
144
+ startLeft = r.left; startTop = r.top;
145
+ };
146
+
147
+ const _isFullscreen = () => fsClass && modal && modal.classList.contains(fsClass);
148
+
149
+ const _startDrag = (cx, cy) => {
150
+ dragging = true;
151
+ if (modal) modal.classList.add('modal-dragging');
152
+ const rect = content.getBoundingClientRect();
153
+ if (onDragStart) {
154
+ try { onDragStart({ rect, cx, cy }); } catch (_) {}
155
+ }
156
+ startX = cx; startY = cy;
157
+ startLeft = rect.left; startTop = rect.top;
158
+ // Pin position so the drag follows the cursor instead of fighting a
159
+ // centering transform / margin. Inline styles win unless CSS uses
160
+ // !important (the fullscreen rules do, by design).
161
+ content.style.position = 'fixed';
162
+ content.style.left = startLeft + 'px';
163
+ content.style.top = startTop + 'px';
164
+ content.style.transform = 'none';
165
+ content.style.margin = '0';
166
+ };
167
+
168
+ const _onMove = (cx, cy) => {
169
+ if (!dragging) return;
170
+ // Fullscreen state: unsnap on drag-down or drag toward either horizontal
171
+ // edge. Update dock hover immediately after exit so a fast release
172
+ // commits the dock instead of dropping the modal mid-air.
173
+ if (_isFullscreen()) {
174
+ // Corner guard: ignore the side edges while the cursor is still in the
175
+ // top fullscreen band, so dragging across the top corners keeps
176
+ // fullscreen instead of flipping into a corner dock.
177
+ const inTopBand = cy <= SNAP_PX;
178
+ const nearRight = !inTopBand && (window.innerWidth - cx) <= DOCK_EDGE_PX;
179
+ const nearLeft = !inTopBand && (cx - _leftNavWidth()) <= DOCK_EDGE_PX;
180
+ // Dragging a fullscreen window to a SIDE edge → keep it fullscreen and
181
+ // just arm the side-dock hint; releasing there docks it (handled in
182
+ // _onEnd, which drops the fullscreen class). Previously this exited
183
+ // fullscreen first, which re-CENTERED the window — so it looked like
184
+ // it "centered instead of docking". Only a downward drag unsnaps to a
185
+ // windowed (centered) modal.
186
+ if (nearRight && rightDock) {
187
+ if (leftDock) leftDock.release();
188
+ rightDock.onMove(cx, cy);
189
+ return;
190
+ }
191
+ if (nearLeft && leftDock) {
192
+ if (rightDock) rightDock.release();
193
+ leftDock.onMove(cx, cy);
194
+ return;
195
+ }
196
+ if (cy > UNSNAP_PX) {
197
+ _exitFs(cx, cy);
198
+ if (rightDock) rightDock.onMove(cx, cy);
199
+ if (leftDock) leftDock.onMove(cx, cy);
200
+ } else {
201
+ if (rightDock) rightDock.release();
202
+ if (leftDock) leftDock.release();
203
+ }
204
+ return;
205
+ }
206
+ // Right-docked: pulling away from the right edge un-docks. Same for left.
207
+ if (rightDock && modal && modal.classList.contains('modal-right-docked')) {
208
+ if (rightDock.onMove(cx, cy)) {
209
+ const r = content.getBoundingClientRect();
210
+ startX = cx; startY = cy;
211
+ startLeft = r.left; startTop = r.top;
212
+ }
213
+ return;
214
+ }
215
+ if (leftDock && modal && modal.classList.contains('modal-left-docked')) {
216
+ if (leftDock.onMove(cx, cy)) {
217
+ const r = content.getBoundingClientRect();
218
+ startX = cx; startY = cy;
219
+ startLeft = r.left; startTop = r.top;
220
+ }
221
+ return;
222
+ }
223
+ // Windowed: just follow the cursor.
224
+ if (Math.abs(cx - startX) > MOVE_THRESHOLD || Math.abs(cy - startY) > MOVE_THRESHOLD) {
225
+ movedDuringDrag = true;
226
+ }
227
+ content.style.left = (startLeft + cx - startX) + 'px';
228
+ content.style.top = (startTop + cy - startY) + 'px';
229
+ // Corner guard: in the top fullscreen band the side docks stay OFF, so a
230
+ // top corner only ever snaps to fullscreen — never the corner hybrid.
231
+ const inTopBand = cy <= SNAP_PX;
232
+ _showSnapHint(enableFullscreen && inTopBand);
233
+ if (inTopBand) {
234
+ if (rightDock) rightDock.release();
235
+ if (leftDock) leftDock.release();
236
+ } else {
237
+ if (rightDock) rightDock.onMove(cx, cy);
238
+ if (leftDock) leftDock.onMove(cx, cy);
239
+ }
240
+ };
241
+
242
+ const _onEnd = (cx, cy) => {
243
+ if (!dragging) return;
244
+ dragging = false;
245
+ if (modal) modal.classList.remove('modal-dragging');
246
+ _showSnapHint(false);
247
+ // Top edge wins over side edges — fullscreen is the more common gesture.
248
+ if (enableFullscreen && typeof cy === 'number' && cy <= SNAP_PX) {
249
+ if (rightDock) rightDock.release();
250
+ if (leftDock) leftDock.release();
251
+ _enterFs();
252
+ return;
253
+ }
254
+ if (rightDock && rightDock.hovering()) {
255
+ if (leftDock) leftDock.release();
256
+ if (fsClass && modal) modal.classList.remove(fsClass); // dock takes over from fullscreen
257
+ rightDock.commit();
258
+ return;
259
+ }
260
+ if (leftDock && leftDock.hovering()) {
261
+ if (rightDock) rightDock.release();
262
+ if (fsClass && modal) modal.classList.remove(fsClass);
263
+ leftDock.commit();
264
+ return;
265
+ }
266
+ if (rightDock) rightDock.release();
267
+ if (leftDock) leftDock.release();
268
+ if (onDragEnd) {
269
+ const r = content.getBoundingClientRect();
270
+ try { onDragEnd({ rect: r }); } catch (_) {}
271
+ }
272
+ };
273
+
274
+ header.addEventListener('mousedown', (e) => {
275
+ if (mobileSkip > 0 && window.innerWidth <= mobileSkip) return;
276
+ if (skipSelector && e.target.closest(skipSelector)) return;
277
+ e.preventDefault();
278
+ movedDuringDrag = false;
279
+ _startDrag(e.clientX, e.clientY);
280
+ const onMove = (ev) => _onMove(ev.clientX, ev.clientY);
281
+ const onUp = (ev) => {
282
+ _onEnd(ev.clientX, ev.clientY);
283
+ document.removeEventListener('mousemove', onMove);
284
+ document.removeEventListener('mouseup', onUp);
285
+ // If the pointer actually moved, swallow the synthetic click the
286
+ // browser fires next — otherwise a header click handler (collapse
287
+ // expanded card / "back to list") runs and undoes the drag intent.
288
+ if (movedDuringDrag) {
289
+ const swallow = (clickEv) => {
290
+ clickEv.stopPropagation();
291
+ clickEv.preventDefault();
292
+ };
293
+ header.addEventListener('click', swallow, { capture: true, once: true });
294
+ // Safety: if no click fires (some browsers), drop the listener.
295
+ setTimeout(() => header.removeEventListener('click', swallow, { capture: true }), 50);
296
+ }
297
+ };
298
+ document.addEventListener('mousemove', onMove);
299
+ document.addEventListener('mouseup', onUp);
300
+ });
301
+
302
+ if (enableTouch) {
303
+ header.addEventListener('touchstart', (e) => {
304
+ if (mobileSkip > 0 && window.innerWidth <= mobileSkip) return;
305
+ if (skipSelector && e.target.closest(skipSelector)) return;
306
+ const t = e.touches[0];
307
+ if (!t) return;
308
+ movedDuringDrag = false;
309
+ _startDrag(t.clientX, t.clientY);
310
+ const onMove = (ev) => {
311
+ const tt = ev.touches[0];
312
+ if (tt) _onMove(tt.clientX, tt.clientY);
313
+ };
314
+ const onEnd = (ev) => {
315
+ const tt = (ev.changedTouches && ev.changedTouches[0]) || null;
316
+ _onEnd(tt ? tt.clientX : null, tt ? tt.clientY : null);
317
+ document.removeEventListener('touchmove', onMove);
318
+ document.removeEventListener('touchend', onEnd);
319
+ document.removeEventListener('touchcancel', onEnd);
320
+ };
321
+ document.addEventListener('touchmove', onMove, { passive: true });
322
+ document.addEventListener('touchend', onEnd);
323
+ document.addEventListener('touchcancel', onEnd);
324
+ }, { passive: true });
325
+ }
326
+ }