@axhub/genie 0.1.8 → 0.2.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 (408) hide show
  1. package/README.md +1 -1
  2. package/dist/api-docs.html +6 -6
  3. package/dist/assets/App-BfaNALgf.js +504 -0
  4. package/dist/assets/App-qxJ8_QYu.css +32 -0
  5. package/dist/assets/ReviewApp-DIT2yWk-.js +1 -0
  6. package/dist/assets/_basePickBy-Dz3NcIVK.js +1 -0
  7. package/dist/assets/_baseUniq-DON_Sg7x.js +1 -0
  8. package/dist/assets/abap-BdImnpbu.js +1 -0
  9. package/dist/assets/actionscript-3-CoDkCxhg.js +1 -0
  10. package/dist/assets/ada-bCR0ucgS.js +1 -0
  11. package/dist/assets/andromeeda-C4gqWexZ.js +1 -0
  12. package/dist/assets/angular-html-CU67Zn6k.js +1 -0
  13. package/dist/assets/angular-ts-BwZT4LLn.js +1 -0
  14. package/dist/assets/apache-Pmp26Uib.js +1 -0
  15. package/dist/assets/apex-D8_7TLub.js +1 -0
  16. package/dist/assets/apl-dKokRX4l.js +1 -0
  17. package/dist/assets/applescript-Co6uUVPk.js +1 -0
  18. package/dist/assets/ara-BRHolxvo.js +1 -0
  19. package/dist/assets/arc-Y4G80q-l.js +1 -0
  20. package/dist/assets/architectureDiagram-2XIMDMQ5-D_qR4657.js +36 -0
  21. package/dist/assets/asciidoc-Ve4PFQV2.js +1 -0
  22. package/dist/assets/asm-D_Q5rh1f.js +1 -0
  23. package/dist/assets/astro-CbQHKStN.js +1 -0
  24. package/dist/assets/aurora-x-D-2ljcwZ.js +1 -0
  25. package/dist/assets/awk-DMzUqQB5.js +1 -0
  26. package/dist/assets/ayu-dark-DYE7WIF3.js +1 -0
  27. package/dist/assets/ayu-light-BA47KaF1.js +1 -0
  28. package/dist/assets/ayu-mirage-32ctXXKs.js +1 -0
  29. package/dist/assets/ballerina-BFfxhgS-.js +1 -0
  30. package/dist/assets/bat-BkioyH1T.js +1 -0
  31. package/dist/assets/beancount-k_qm7-4y.js +1 -0
  32. package/dist/assets/berry-uYugtg8r.js +1 -0
  33. package/dist/assets/bibtex-CHM0blh-.js +1 -0
  34. package/dist/assets/bicep-Bmn6On1c.js +1 -0
  35. package/dist/assets/bird2-DPOp833l.js +1 -0
  36. package/dist/assets/blade-D4QpJJKB.js +1 -0
  37. package/dist/assets/blockDiagram-WCTKOSBZ-NsmAlV5_.js +132 -0
  38. package/dist/assets/bsl-BO_Y6i37.js +1 -0
  39. package/dist/assets/c-BIGW1oBm.js +1 -0
  40. package/dist/assets/c3-eo99z4R2.js +1 -0
  41. package/dist/assets/c4Diagram-IC4MRINW-cbOJM4yr.js +10 -0
  42. package/dist/assets/cadence-Bv_4Rxtq.js +1 -0
  43. package/dist/assets/cairo-KRGpt6FW.js +1 -0
  44. package/dist/assets/catppuccin-frappe-DFWUc33u.js +1 -0
  45. package/dist/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
  46. package/dist/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
  47. package/dist/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
  48. package/dist/assets/channel-C6KNnXlA.js +1 -0
  49. package/dist/assets/chunk-4BX2VUAB-bLBhl74J.js +1 -0
  50. package/dist/assets/chunk-55IACEB6-D8kNkDUO.js +1 -0
  51. package/dist/assets/chunk-FMBD7UC4-BjR6UbXB.js +15 -0
  52. package/dist/assets/chunk-JSJVCQXG-luNqWn64.js +1 -0
  53. package/dist/assets/chunk-KX2RTZJC-CNnKm6dK.js +1 -0
  54. package/dist/assets/chunk-NQ4KR5QH-Cp9gb43u.js +220 -0
  55. package/dist/assets/chunk-QZHKN3VN-HlVYo2Oq.js +1 -0
  56. package/dist/assets/chunk-WL4C6EOR-CjSZoOGO.js +189 -0
  57. package/dist/assets/clarity-D53aC0YG.js +1 -0
  58. package/dist/assets/classDiagram-VBA2DB6C-BQlzzlH7.js +1 -0
  59. package/dist/assets/classDiagram-v2-RAHNMMFH-BQlzzlH7.js +1 -0
  60. package/dist/assets/clojure-P80f7IUj.js +1 -0
  61. package/dist/assets/clone-DMxS3qWP.js +1 -0
  62. package/dist/assets/cmake-D1j8_8rp.js +1 -0
  63. package/dist/assets/cobol-nwyudZeR.js +1 -0
  64. package/dist/assets/codeowners-Bp6g37R7.js +1 -0
  65. package/dist/assets/codeql-DsOJ9woJ.js +1 -0
  66. package/dist/assets/coffee-Ch7k5sss.js +1 -0
  67. package/dist/assets/common-lisp-Cg-RD9OK.js +1 -0
  68. package/dist/assets/coq-DkFqJrB1.js +1 -0
  69. package/dist/assets/cose-bilkent-S5V4N54A-DZWRjeEd.js +1 -0
  70. package/dist/assets/cpp-CofmeUqb.js +1 -0
  71. package/dist/assets/crystal-tKQVLTB8.js +1 -0
  72. package/dist/assets/csharp-COcwbKMJ.js +1 -0
  73. package/dist/assets/css-DPfMkruS.js +1 -0
  74. package/dist/assets/csv-fuZLfV_i.js +1 -0
  75. package/dist/assets/cue-D82EKSYY.js +1 -0
  76. package/dist/assets/cypher-COkxafJQ.js +1 -0
  77. package/dist/assets/cytoscape.esm-2ZfV8NB5.js +331 -0
  78. package/dist/assets/d-85-TOEBH.js +1 -0
  79. package/dist/assets/dagre-KLK3FWXG-yAzUmqI7.js +4 -0
  80. package/dist/assets/dark-plus-C3mMm8J8.js +1 -0
  81. package/dist/assets/dart-CF10PKvl.js +1 -0
  82. package/dist/assets/dax-CEL-wOlO.js +1 -0
  83. package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  84. package/dist/assets/desktop-BmXAJ9_W.js +1 -0
  85. package/dist/assets/diagram-E7M64L7V-CvzlIvDJ.js +24 -0
  86. package/dist/assets/diagram-IFDJBPK2-DFMIJpuM.js +43 -0
  87. package/dist/assets/diagram-P4PSJMXO-KL-J3gyb.js +24 -0
  88. package/dist/assets/diff-D97Zzqfu.js +1 -0
  89. package/dist/assets/docker-BcOcwvcX.js +1 -0
  90. package/dist/assets/dotenv-Da5cRb03.js +1 -0
  91. package/dist/assets/dracula-BzJJZx-M.js +1 -0
  92. package/dist/assets/dracula-soft-BXkSAIEj.js +1 -0
  93. package/dist/assets/dream-maker-BtqSS_iP.js +1 -0
  94. package/dist/assets/edge-BkV0erSs.js +1 -0
  95. package/dist/assets/elixir-CDX3lj18.js +1 -0
  96. package/dist/assets/elm-DbKCFpqz.js +1 -0
  97. package/dist/assets/emacs-lisp-C9XAeP06.js +1 -0
  98. package/dist/assets/erDiagram-INFDFZHY-BXszHbTM.js +70 -0
  99. package/dist/assets/erb-B12qg9BL.js +1 -0
  100. package/dist/assets/erlang-DsQrWhSR.js +1 -0
  101. package/dist/assets/everforest-dark-BgDCqdQA.js +1 -0
  102. package/dist/assets/everforest-light-C8M2exoo.js +1 -0
  103. package/dist/assets/fennel-BYunw83y.js +1 -0
  104. package/dist/assets/fish-BvzEVeQv.js +1 -0
  105. package/dist/assets/flowDiagram-PKNHOUZH-Ba43NVp6.js +162 -0
  106. package/dist/assets/fluent-C4IJs8-o.js +1 -0
  107. package/dist/assets/fortran-fixed-form-CkoXwp7k.js +1 -0
  108. package/dist/assets/fortran-free-form-BxgE0vQu.js +1 -0
  109. package/dist/assets/fsharp-CXgrBDvD.js +1 -0
  110. package/dist/assets/ganttDiagram-A5KZAMGK-uLHfhCrg.js +292 -0
  111. package/dist/assets/gdresource-BOOCDP_w.js +1 -0
  112. package/dist/assets/gdscript-C5YyOfLZ.js +1 -0
  113. package/dist/assets/gdshader-DkwncUOv.js +1 -0
  114. package/dist/assets/genie-D0YGMca9.js +1 -0
  115. package/dist/assets/gherkin-DyxjwDmM.js +1 -0
  116. package/dist/assets/git-commit-F4YmCXRG.js +1 -0
  117. package/dist/assets/git-rebase-r7XF79zn.js +1 -0
  118. package/dist/assets/gitGraphDiagram-K3NZZRJ6-BTEuFaiL.js +65 -0
  119. package/dist/assets/github-dark-DHJKELXO.js +1 -0
  120. package/dist/assets/github-dark-default-Cuk6v7N8.js +1 -0
  121. package/dist/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  122. package/dist/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
  123. package/dist/assets/github-light-DAi9KRSo.js +1 -0
  124. package/dist/assets/github-light-default-D7oLnXFd.js +1 -0
  125. package/dist/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
  126. package/dist/assets/gleam-BspZqrRM.js +1 -0
  127. package/dist/assets/glimmer-js-Rg0-pVw9.js +1 -0
  128. package/dist/assets/glimmer-ts-U6CK756n.js +1 -0
  129. package/dist/assets/glsl-DplSGwfg.js +1 -0
  130. package/dist/assets/gn-n2N0HUVH.js +1 -0
  131. package/dist/assets/gnuplot-DdkO51Og.js +1 -0
  132. package/dist/assets/go-CxLEBnE3.js +1 -0
  133. package/dist/assets/graph-h2nuWjx4.js +1 -0
  134. package/dist/assets/graphql-ChdNCCLP.js +1 -0
  135. package/dist/assets/groovy-gcz8RCvz.js +1 -0
  136. package/dist/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
  137. package/dist/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
  138. package/dist/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
  139. package/dist/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
  140. package/dist/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
  141. package/dist/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
  142. package/dist/assets/hack-CaT9iCJl.js +1 -0
  143. package/dist/assets/haml-B8DHNrY2.js +1 -0
  144. package/dist/assets/handlebars-BL8al0AC.js +1 -0
  145. package/dist/assets/haskell-Df6bDoY_.js +1 -0
  146. package/dist/assets/haxe-CzTSHFRz.js +1 -0
  147. package/dist/assets/hcl-BWvSN4gD.js +1 -0
  148. package/dist/assets/highlighted-body-TPN3WLV5-C6BY7XZJ.js +1 -0
  149. package/dist/assets/hjson-D5-asLiD.js +1 -0
  150. package/dist/assets/hlsl-D3lLCCz7.js +1 -0
  151. package/dist/assets/horizon-BUw7H-hv.js +1 -0
  152. package/dist/assets/horizon-bright-Cn-bp-IR.js +1 -0
  153. package/dist/assets/houston-DnULxvSX.js +1 -0
  154. package/dist/assets/html-GMplVEZG.js +1 -0
  155. package/dist/assets/html-derivative-BFtXZ54Q.js +1 -0
  156. package/dist/assets/http-jrhK8wxY.js +1 -0
  157. package/dist/assets/hurl-irOxFIW8.js +1 -0
  158. package/dist/assets/hxml-Bvhsp5Yf.js +1 -0
  159. package/dist/assets/hy-DFXneXwc.js +1 -0
  160. package/dist/assets/imba-DGztddWO.js +1 -0
  161. package/dist/assets/index-2198VgsK.css +1 -0
  162. package/dist/assets/index-C6Bb2jGF.js +2 -0
  163. package/dist/assets/infoDiagram-LFFYTUFH-BOLfvCIq.js +2 -0
  164. package/dist/assets/ini-BEwlwnbL.js +1 -0
  165. package/dist/assets/init-Gi6I4Gst.js +1 -0
  166. package/dist/assets/ishikawaDiagram-PHBUUO56-BRzQ1ee5.js +70 -0
  167. package/dist/assets/java-CylS5w8V.js +1 -0
  168. package/dist/assets/javascript-wDzz0qaB.js +1 -0
  169. package/dist/assets/jinja-4LBKfQ-Z.js +1 -0
  170. package/dist/assets/jison-wvAkD_A8.js +1 -0
  171. package/dist/assets/journeyDiagram-4ABVD52K-DXm_VcMy.js +139 -0
  172. package/dist/assets/json-Cp-IABpG.js +1 -0
  173. package/dist/assets/json5-C9tS-k6U.js +1 -0
  174. package/dist/assets/jsonc-Des-eS-w.js +1 -0
  175. package/dist/assets/jsonl-DcaNXYhu.js +1 -0
  176. package/dist/assets/jsonnet-DFQXde-d.js +1 -0
  177. package/dist/assets/jssm-C2t-YnRu.js +1 -0
  178. package/dist/assets/jsx-g9-lgVsj.js +1 -0
  179. package/dist/assets/julia-CxzCAyBv.js +1 -0
  180. package/dist/assets/just-Cw27pwNe.js +1 -0
  181. package/dist/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
  182. package/dist/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
  183. package/dist/assets/kanagawa-wave-DWedfzmr.js +1 -0
  184. package/dist/assets/kanban-definition-K7BYSVSG-D_oyzopl.js +89 -0
  185. package/dist/assets/kdl-DV7GczEv.js +1 -0
  186. package/dist/assets/kotlin-BdnUsdx6.js +1 -0
  187. package/dist/assets/kusto-DZf3V79B.js +1 -0
  188. package/dist/assets/laserwave-DUszq2jm.js +1 -0
  189. package/dist/assets/latex-CWtU0Tv5.js +1 -0
  190. package/dist/assets/layout-Q8YoR_E1.js +1 -0
  191. package/dist/assets/lean-BZvkOJ9d.js +1 -0
  192. package/dist/assets/less-B1dDrJ26.js +1 -0
  193. package/dist/assets/light-plus-B7mTdjB0.js +1 -0
  194. package/dist/assets/linear-B3qNg7di.js +1 -0
  195. package/dist/assets/liquid-DYVedYrR.js +1 -0
  196. package/dist/assets/llvm-DjAJT7YJ.js +1 -0
  197. package/dist/assets/log-2UxHyX5q.js +1 -0
  198. package/dist/assets/logo-BtOb2qkB.js +1 -0
  199. package/dist/assets/lua-BaeVxFsk.js +1 -0
  200. package/dist/assets/luau-C-HG3fhB.js +1 -0
  201. package/dist/assets/make-CHLpvVh8.js +1 -0
  202. package/dist/assets/markdown-Cvjx9yec.js +1 -0
  203. package/dist/assets/marko-CnJfTvn9.js +1 -0
  204. package/dist/assets/material-theme-D5KoaKCx.js +1 -0
  205. package/dist/assets/material-theme-darker-BfHTSMKl.js +1 -0
  206. package/dist/assets/material-theme-lighter-B0m2ddpp.js +1 -0
  207. package/dist/assets/material-theme-ocean-CyktbL80.js +1 -0
  208. package/dist/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
  209. package/dist/assets/matlab-D7o27uSR.js +1 -0
  210. package/dist/assets/mdc-BMNejdWA.js +1 -0
  211. package/dist/assets/mdx-Cmh6b_Ma.js +1 -0
  212. package/dist/assets/mermaid-O7DHMXV3-BVZ_4MKo.js +988 -0
  213. package/dist/assets/mermaid-mWjccvbQ.js +1 -0
  214. package/dist/assets/min-dark-CafNBF8u.js +1 -0
  215. package/dist/assets/min-light-CTRr51gU.js +1 -0
  216. package/dist/assets/mindmap-definition-YRQLILUH-CjulgYdi.js +68 -0
  217. package/dist/assets/mipsasm-CKIfxQSi.js +1 -0
  218. package/dist/assets/mojo-rZm6bMo-.js +1 -0
  219. package/dist/assets/monokai-D4h5O-jR.js +1 -0
  220. package/dist/assets/moonbit-_H4v1dQx.js +1 -0
  221. package/dist/assets/move-IF9eRakj.js +1 -0
  222. package/dist/assets/narrat-DRg8JJMk.js +1 -0
  223. package/dist/assets/nextflow-Zz6hmt5N.js +1 -0
  224. package/dist/assets/nextflow-groovy-BeH2EWoN.js +1 -0
  225. package/dist/assets/nginx-BpAMiNFr.js +1 -0
  226. package/dist/assets/night-owl-C39BiMTA.js +1 -0
  227. package/dist/assets/night-owl-light-CMTm3GFP.js +1 -0
  228. package/dist/assets/nim-CVrawwO9.js +1 -0
  229. package/dist/assets/nix-CwoSXNpI.js +1 -0
  230. package/dist/assets/nord-Ddv68eIx.js +1 -0
  231. package/dist/assets/nushell-Cz2AlsmD.js +1 -0
  232. package/dist/assets/objective-c-DXmwc3jG.js +1 -0
  233. package/dist/assets/objective-cpp-CLxacb5B.js +1 -0
  234. package/dist/assets/ocaml-C0hk2d4L.js +1 -0
  235. package/dist/assets/odin-BBf5iR-q.js +1 -0
  236. package/dist/assets/one-dark-pro-DVMEJ2y_.js +1 -0
  237. package/dist/assets/one-light-C3Wv6jpd.js +1 -0
  238. package/dist/assets/openscad-C4EeE6gA.js +1 -0
  239. package/dist/assets/ordinal-Cboi1Yqb.js +1 -0
  240. package/dist/assets/pascal-D93ZcfNL.js +1 -0
  241. package/dist/assets/perl-C0TMdlhV.js +1 -0
  242. package/dist/assets/php-Dhbhpdrm.js +1 -0
  243. package/dist/assets/pieDiagram-SKSYHLDU-8VzrefxA.js +30 -0
  244. package/dist/assets/pkl-u5AG7uiY.js +1 -0
  245. package/dist/assets/plastic-3e1v2bzS.js +1 -0
  246. package/dist/assets/plsql-ChMvpjG-.js +1 -0
  247. package/dist/assets/po-BTJTHyun.js +1 -0
  248. package/dist/assets/poimandres-CS3Unz2-.js +1 -0
  249. package/dist/assets/polar-C0HS_06l.js +1 -0
  250. package/dist/assets/postcss-CXtECtnM.js +1 -0
  251. package/dist/assets/powerquery-CEu0bR-o.js +1 -0
  252. package/dist/assets/powershell-Dpen1YoG.js +1 -0
  253. package/dist/assets/prisma-Dd19v3D-.js +1 -0
  254. package/dist/assets/prolog-CbFg5uaA.js +1 -0
  255. package/dist/assets/proto-C7zT0LnQ.js +1 -0
  256. package/dist/assets/pug-CGlum2m_.js +1 -0
  257. package/dist/assets/puppet-BMWR74SV.js +1 -0
  258. package/dist/assets/purescript-CklMAg4u.js +1 -0
  259. package/dist/assets/python-B6aJPvgy.js +1 -0
  260. package/dist/assets/qml-3beO22l8.js +1 -0
  261. package/dist/assets/qmldir-C8lEn-DE.js +1 -0
  262. package/dist/assets/qss-IeuSbFQv.js +1 -0
  263. package/dist/assets/quadrantDiagram-337W2JSQ-CFh-ijm2.js +7 -0
  264. package/dist/assets/r-Dspwwk_N.js +1 -0
  265. package/dist/assets/racket-BqYA7rlc.js +1 -0
  266. package/dist/assets/raku-DXvB9xmW.js +1 -0
  267. package/dist/assets/razor-Uh8Bk_45.js +1 -0
  268. package/dist/assets/red-bN70gL4F.js +1 -0
  269. package/dist/assets/reg-C-SQnVFl.js +1 -0
  270. package/dist/assets/regexp-CDVJQ6XC.js +1 -0
  271. package/dist/assets/rel-C3B-1QV4.js +1 -0
  272. package/dist/assets/requirementDiagram-Z7DCOOCP-BNPlTs5Q.js +73 -0
  273. package/dist/assets/riscv-BM1_JUlF.js +1 -0
  274. package/dist/assets/ron-D8l8udqQ.js +1 -0
  275. package/dist/assets/rose-pine-dawn-DHQR4-dF.js +1 -0
  276. package/dist/assets/rose-pine-moon-D4_iv3hh.js +1 -0
  277. package/dist/assets/rose-pine-qdsjHGoJ.js +1 -0
  278. package/dist/assets/rosmsg-BJDFO7_C.js +1 -0
  279. package/dist/assets/rst-BrH8l1NY.js +1 -0
  280. package/dist/assets/ruby-Dw2BHqvy.js +1 -0
  281. package/dist/assets/rust-B1yitclQ.js +1 -0
  282. package/dist/assets/sankeyDiagram-WA2Y5GQK-C5l_hYst.js +10 -0
  283. package/dist/assets/sas-cz2c8ADy.js +1 -0
  284. package/dist/assets/sass-Cj5Yp3dK.js +1 -0
  285. package/dist/assets/scala-C151Ov-r.js +1 -0
  286. package/dist/assets/scheme-C98Dy4si.js +1 -0
  287. package/dist/assets/scss-OYdSNvt2.js +1 -0
  288. package/dist/assets/sdbl-DVxCFoDh.js +1 -0
  289. package/dist/assets/sequenceDiagram-2WXFIKYE-B4a_rQw8.js +145 -0
  290. package/dist/assets/shaderlab-Dg9Lc6iA.js +1 -0
  291. package/dist/assets/shellscript-Yzrsuije.js +1 -0
  292. package/dist/assets/shellsession-BADoaaVG.js +1 -0
  293. package/dist/assets/slack-dark-BthQWCQV.js +1 -0
  294. package/dist/assets/slack-ochin-DqwNpetd.js +1 -0
  295. package/dist/assets/smalltalk-BERRCDM3.js +1 -0
  296. package/dist/assets/snazzy-light-Bw305WKR.js +1 -0
  297. package/dist/assets/solarized-dark-DXbdFlpD.js +1 -0
  298. package/dist/assets/solarized-light-L9t79GZl.js +1 -0
  299. package/dist/assets/solidity-rGO070M0.js +1 -0
  300. package/dist/assets/soy-Brmx7dQM.js +1 -0
  301. package/dist/assets/sparql-rVzFXLq3.js +1 -0
  302. package/dist/assets/splunk-BtCnVYZw.js +1 -0
  303. package/dist/assets/sql-BLtJtn59.js +1 -0
  304. package/dist/assets/ssh-config-_ykCGR6B.js +1 -0
  305. package/dist/assets/stata-BH5u7GGu.js +1 -0
  306. package/dist/assets/stateDiagram-RAJIS63D-Bt4mMmKB.js +1 -0
  307. package/dist/assets/stateDiagram-v2-FVOUBMTO-6NYMazfq.js +1 -0
  308. package/dist/assets/stylus-BEDo0Tqx.js +1 -0
  309. package/dist/assets/surrealql-Bq5Q-fJD.js +1 -0
  310. package/dist/assets/svelte-C_ipcX3V.js +1 -0
  311. package/dist/assets/swift-D82vCrfD.js +1 -0
  312. package/dist/assets/synthwave-84-CbfX1IO0.js +1 -0
  313. package/dist/assets/system-verilog-CnnmHF94.js +1 -0
  314. package/dist/assets/systemd-4A_iFExJ.js +1 -0
  315. package/dist/assets/talonscript-CkByrt1z.js +1 -0
  316. package/dist/assets/tasl-QIJgUcNo.js +1 -0
  317. package/dist/assets/tcl-dwOrl1Do.js +1 -0
  318. package/dist/assets/templ-P3uqSqPl.js +1 -0
  319. package/dist/assets/terraform-BETggiCN.js +1 -0
  320. package/dist/assets/tex-idrVyKtj.js +1 -0
  321. package/dist/assets/timeline-definition-YZTLITO2-CLYvSw_R.js +61 -0
  322. package/dist/assets/tokyo-night-hegEt444.js +1 -0
  323. package/dist/assets/toml-vGWfd6FD.js +1 -0
  324. package/dist/assets/treemap-KZPCXAKY-ksND0hZK.js +162 -0
  325. package/dist/assets/ts-tags-zn1MmPIZ.js +1 -0
  326. package/dist/assets/tsv-B_m7g4N7.js +1 -0
  327. package/dist/assets/tsx-COt5Ahok.js +1 -0
  328. package/dist/assets/turtle-BsS91CYL.js +1 -0
  329. package/dist/assets/twig-DNn4PbVi.js +1 -0
  330. package/dist/assets/typescript-BPQ3VLAy.js +1 -0
  331. package/dist/assets/typespec-BGHnOYBU.js +1 -0
  332. package/dist/assets/typst-DHCkPAjA.js +1 -0
  333. package/dist/assets/v-BcVCzyr7.js +1 -0
  334. package/dist/assets/vala-CsfeWuGM.js +1 -0
  335. package/dist/assets/vb-D17OF-Vu.js +1 -0
  336. package/dist/assets/{vendor-codemirror-B88_OPWf.js → vendor-codemirror-Dz7_EqNA.js} +3 -3
  337. package/dist/assets/{vendor-react-C3RJLQGO.js → vendor-react-Cpt6D04s.js} +11 -11
  338. package/dist/assets/vennDiagram-LZ73GAT5-CaQg4oZK.js +34 -0
  339. package/dist/assets/verilog-BQ8w6xss.js +1 -0
  340. package/dist/assets/vesper-DU1UobuO.js +1 -0
  341. package/dist/assets/vhdl-CeAyd5Ju.js +1 -0
  342. package/dist/assets/viml-CJc9bBzg.js +1 -0
  343. package/dist/assets/vitesse-black-Bkuqu6BP.js +1 -0
  344. package/dist/assets/vitesse-dark-D0r3Knsf.js +1 -0
  345. package/dist/assets/vitesse-light-CVO1_9PV.js +1 -0
  346. package/dist/assets/vue-DN_0RTcg.js +1 -0
  347. package/dist/assets/vue-html-AaS7Mt5G.js +1 -0
  348. package/dist/assets/vue-vine-CQOfvN7w.js +1 -0
  349. package/dist/assets/vyper-CDx5xZoG.js +1 -0
  350. package/dist/assets/wasm-CG6Dc4jp.js +1 -0
  351. package/dist/assets/wasm-MzD3tlZU.js +1 -0
  352. package/dist/assets/wenyan-BV7otONQ.js +1 -0
  353. package/dist/assets/wgsl-Dx-B1_4e.js +1 -0
  354. package/dist/assets/wikitext-BhOHFoWU.js +1 -0
  355. package/dist/assets/wit-5i3qLPDT.js +1 -0
  356. package/dist/assets/wolfram-lXgVvXCa.js +1 -0
  357. package/dist/assets/xml-sdJ4AIDG.js +1 -0
  358. package/dist/assets/xsl-CtQFsRM5.js +1 -0
  359. package/dist/assets/xychartDiagram-JWTSCODW-C8dCbTeM.js +7 -0
  360. package/dist/assets/yaml-Buea-lGh.js +1 -0
  361. package/dist/assets/zenscript-DVFEvuxE.js +1 -0
  362. package/dist/assets/zig-VOosw3JB.js +1 -0
  363. package/dist/index.html +35 -21
  364. package/dist/manifest.json +1 -1
  365. package/dist/sw.js +18 -46
  366. package/package.json +12 -8
  367. package/server/bin/codex-sdk-wrapper.js +49 -0
  368. package/server/channels/runtime/AgentRuntimeAdapter.js +2 -5
  369. package/server/channels/store/ChannelStore.js +73 -107
  370. package/server/claude-sdk.js +160 -6
  371. package/server/cli.js +590 -32
  372. package/server/cli.test.js +76 -0
  373. package/server/database/db.js +438 -372
  374. package/server/external-agent/auth.js +88 -0
  375. package/server/external-agent/service.js +1052 -0
  376. package/server/external-agent/service.test.js +41 -0
  377. package/server/external-agent/ws.js +1526 -0
  378. package/server/external-agent/ws.test.js +289 -0
  379. package/server/gemini-cli.js +108 -20
  380. package/server/index.js +115 -121
  381. package/server/load-env.js +16 -13
  382. package/server/openai-codex.js +165 -11
  383. package/server/opencode-cli.js +3 -2
  384. package/server/projects.js +432 -338
  385. package/server/routes/agent.js +347 -459
  386. package/server/routes/auth.js +14 -36
  387. package/server/routes/cli-auth.js +60 -113
  388. package/server/routes/commands.js +16 -26
  389. package/server/routes/git.js +5 -16
  390. package/server/routes/projects.js +2 -7
  391. package/server/routes/session-core.js +177 -0
  392. package/server/session-core/abortSession.js +48 -0
  393. package/server/session-core/eventStore.js +139 -0
  394. package/server/session-core/providerAdapters.js +84 -0
  395. package/server/session-core/providerDiscovery.js +235 -0
  396. package/server/session-core/runtimeState.js +390 -0
  397. package/server/session-core/runtimeWriter.js +59 -0
  398. package/server/utils/agentCallback.js +273 -0
  399. package/server/utils/agentImages.js +253 -0
  400. package/server/utils/codexPath.js +47 -0
  401. package/server/utils/defaultWorkingDirectory.js +34 -0
  402. package/shared/conversationEvents.js +1071 -0
  403. package/shared/modelConstants.js +18 -24
  404. package/dist/assets/index-CVjMty4a.js +0 -902
  405. package/dist/assets/index-eo5scY_Z.css +0 -32
  406. package/server/cursor-cli.js +0 -276
  407. package/server/database/init.sql +0 -98
  408. package/server/routes/cursor.js +0 -795
@@ -1,469 +1,535 @@
1
- import Database from 'better-sqlite3';
1
+ import crypto from 'crypto';
2
2
  import path from 'path';
3
3
  import fs from 'fs';
4
- import crypto from 'crypto';
5
4
  import { fileURLToPath } from 'url';
6
5
  import { dirname } from 'path';
7
6
 
8
7
  const __filename = fileURLToPath(import.meta.url);
9
8
  const __dirname = dirname(__filename);
10
9
 
11
- // ANSI color codes for terminal output
12
10
  const colors = {
13
- reset: '\x1b[0m',
14
- bright: '\x1b[1m',
15
- cyan: '\x1b[36m',
16
- dim: '\x1b[2m',
11
+ reset: '\x1b[0m',
12
+ bright: '\x1b[1m',
13
+ cyan: '\x1b[36m',
14
+ dim: '\x1b[2m',
17
15
  };
18
16
 
19
17
  const c = {
20
- info: (text) => `${colors.cyan}${text}${colors.reset}`,
21
- bright: (text) => `${colors.bright}${text}${colors.reset}`,
22
- dim: (text) => `${colors.dim}${text}${colors.reset}`,
18
+ info: (text) => `${colors.cyan}${text}${colors.reset}`,
19
+ bright: (text) => `${colors.bright}${text}${colors.reset}`,
20
+ dim: (text) => `${colors.dim}${text}${colors.reset}`,
23
21
  };
24
22
 
25
- // Use DATABASE_PATH environment variable if set, otherwise use default location
26
- const DB_PATH = process.env.DATABASE_PATH || path.join(__dirname, 'auth.db');
27
- const INIT_SQL_PATH = path.join(__dirname, 'init.sql');
28
-
29
- // Ensure database directory exists if custom path is provided
30
- if (process.env.DATABASE_PATH) {
31
- const dbDir = path.dirname(DB_PATH);
32
- try {
33
- if (!fs.existsSync(dbDir)) {
34
- fs.mkdirSync(dbDir, { recursive: true });
35
- console.log(`Created database directory: ${dbDir}`);
36
- }
37
- } catch (error) {
38
- console.error(`Failed to create database directory ${dbDir}:`, error.message);
39
- throw error;
40
- }
41
- }
42
-
43
- // Create database connection
44
- const db = new Database(DB_PATH);
45
-
46
- // Show app installation path prominently
23
+ const DATA_FILE_PATH = process.env.DATA_FILE_PATH || path.join(__dirname, 'state.json');
47
24
  const appInstallPath = path.join(__dirname, '../..');
48
- console.log('');
49
- console.log(c.dim('═'.repeat(60)));
50
- console.log(`${c.info('[INFO]')} App Installation: ${c.bright(appInstallPath)}`);
51
- console.log(`${c.info('[INFO]')} Database: ${c.dim(path.relative(appInstallPath, DB_PATH))}`);
52
- if (process.env.DATABASE_PATH) {
53
- console.log(` ${c.dim('(Using custom DATABASE_PATH from environment)')}`);
25
+
26
+ const DEFAULT_STATE = Object.freeze({
27
+ meta: {
28
+ version: 1,
29
+ counters: {
30
+ userId: 0,
31
+ apiKeyId: 0,
32
+ credentialId: 0,
33
+ allowedUserId: 0,
34
+ },
35
+ },
36
+ users: [],
37
+ apiKeys: [],
38
+ credentials: [],
39
+ channelPlugins: [],
40
+ channelAllowedUsers: [],
41
+ channelSessions: [],
42
+ });
43
+
44
+ let stateCache = null;
45
+
46
+ function cloneDefaultState() {
47
+ return JSON.parse(JSON.stringify(DEFAULT_STATE));
54
48
  }
55
- console.log(c.dim('═'.repeat(60)));
56
- console.log('');
57
-
58
- const tableExists = (tableName) => {
59
- const row = db
60
- .prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?")
61
- .get(tableName);
62
- return !!row;
63
- };
64
49
 
65
- const getTableColumns = (tableName) => {
66
- if (!tableExists(tableName)) {
67
- return [];
50
+ function ensureDataDirectory() {
51
+ const dataDir = path.dirname(DATA_FILE_PATH);
52
+ if (!fs.existsSync(dataDir)) {
53
+ fs.mkdirSync(dataDir, { recursive: true });
54
+ console.log(`Created data directory: ${dataDir}`);
68
55
  }
69
- return db.prepare(`PRAGMA table_info(${tableName})`).all().map((col) => col.name);
70
- };
56
+ }
71
57
 
72
- const hasIndex = (indexName) => {
73
- const row = db
74
- .prepare("SELECT name FROM sqlite_master WHERE type = 'index' AND name = ?")
75
- .get(indexName);
76
- return !!row;
77
- };
58
+ function normalizeState(rawState) {
59
+ const nextState = cloneDefaultState();
60
+ const source = rawState && typeof rawState === 'object' ? rawState : {};
61
+ const meta = source.meta && typeof source.meta === 'object' ? source.meta : {};
62
+ const counters = meta.counters && typeof meta.counters === 'object' ? meta.counters : {};
63
+
64
+ nextState.meta.version = Number.isFinite(Number(meta.version)) ? Number(meta.version) : 1;
65
+ nextState.meta.counters.userId = Number.isFinite(Number(counters.userId)) ? Number(counters.userId) : 0;
66
+ nextState.meta.counters.apiKeyId = Number.isFinite(Number(counters.apiKeyId)) ? Number(counters.apiKeyId) : 0;
67
+ nextState.meta.counters.credentialId = Number.isFinite(Number(counters.credentialId)) ? Number(counters.credentialId) : 0;
68
+ nextState.meta.counters.allowedUserId = Number.isFinite(Number(counters.allowedUserId)) ? Number(counters.allowedUserId) : 0;
69
+
70
+ nextState.users = Array.isArray(source.users) ? source.users : [];
71
+ nextState.apiKeys = Array.isArray(source.apiKeys) ? source.apiKeys : [];
72
+ nextState.credentials = Array.isArray(source.credentials) ? source.credentials : [];
73
+ nextState.channelPlugins = Array.isArray(source.channelPlugins) ? source.channelPlugins : [];
74
+ nextState.channelAllowedUsers = Array.isArray(source.channelAllowedUsers) ? source.channelAllowedUsers : [];
75
+ nextState.channelSessions = Array.isArray(source.channelSessions) ? source.channelSessions : [];
76
+
77
+ return nextState;
78
+ }
78
79
 
79
- const ensureChannelAllowedUsersSchema = () => {
80
- if (!tableExists('channel_allowed_users')) {
81
- return;
82
- }
80
+ function persistStateSync(nextState) {
81
+ ensureDataDirectory();
82
+ const tempPath = `${DATA_FILE_PATH}.tmp`;
83
+ fs.writeFileSync(tempPath, `${JSON.stringify(nextState, null, 2)}\n`, 'utf8');
84
+ fs.renameSync(tempPath, DATA_FILE_PATH);
85
+ stateCache = nextState;
86
+ }
83
87
 
84
- const columns = getTableColumns('channel_allowed_users');
85
- const tableSqlRow = db
86
- .prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'channel_allowed_users'")
87
- .get();
88
- const tableSql = String(tableSqlRow?.sql || '');
89
- const hasLegacyUserIdUnique = /user_id\s+TEXT\s+UNIQUE/i.test(tableSql);
90
- const needsRebuild = !columns.includes('platform_type') || hasLegacyUserIdUnique;
91
-
92
- if (needsRebuild) {
93
- console.log('Running migration: Rebuilding channel_allowed_users with platform isolation');
94
- const beforeCount = db.prepare('SELECT COUNT(*) AS count FROM channel_allowed_users').get()?.count || 0;
95
-
96
- db.transaction(() => {
97
- db.exec('ALTER TABLE channel_allowed_users RENAME TO channel_allowed_users_old');
98
- db.exec(`
99
- CREATE TABLE channel_allowed_users (
100
- id INTEGER PRIMARY KEY AUTOINCREMENT,
101
- platform_type TEXT NOT NULL DEFAULT 'lark',
102
- user_id TEXT NOT NULL,
103
- display_name TEXT,
104
- note TEXT,
105
- is_active BOOLEAN DEFAULT 1,
106
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
107
- updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
108
- )
109
- `);
110
-
111
- const oldColumns = getTableColumns('channel_allowed_users_old');
112
- const hasOldPlatformType = oldColumns.includes('platform_type');
113
-
114
- if (hasOldPlatformType) {
115
- db.exec(`
116
- INSERT INTO channel_allowed_users (id, platform_type, user_id, display_name, note, is_active, created_at, updated_at)
117
- SELECT id, COALESCE(platform_type, 'lark'), user_id, display_name, note, is_active, created_at, updated_at
118
- FROM channel_allowed_users_old
119
- `);
120
- } else {
121
- db.exec(`
122
- INSERT INTO channel_allowed_users (id, platform_type, user_id, display_name, note, is_active, created_at, updated_at)
123
- SELECT id, 'lark', user_id, display_name, note, is_active, created_at, updated_at
124
- FROM channel_allowed_users_old
125
- `);
126
- }
88
+ function loadStateSync() {
89
+ ensureDataDirectory();
127
90
 
128
- db.exec('DROP TABLE channel_allowed_users_old');
129
- })();
91
+ if (stateCache) {
92
+ return stateCache;
93
+ }
130
94
 
131
- const afterCount = db.prepare('SELECT COUNT(*) AS count FROM channel_allowed_users').get()?.count || 0;
132
- console.log(`channel_allowed_users rows migrated: ${beforeCount} -> ${afterCount}`);
95
+ if (!fs.existsSync(DATA_FILE_PATH)) {
96
+ const initialState = cloneDefaultState();
97
+ persistStateSync(initialState);
98
+ return initialState;
133
99
  }
134
100
 
135
- db.exec("UPDATE channel_allowed_users SET platform_type = 'lark' WHERE platform_type IS NULL OR TRIM(platform_type) = ''");
136
- db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_channel_allowed_users_platform_user ON channel_allowed_users(platform_type, user_id)');
137
- db.exec('CREATE INDEX IF NOT EXISTS idx_channel_allowed_users_user_id ON channel_allowed_users(user_id)');
138
- db.exec('CREATE INDEX IF NOT EXISTS idx_channel_allowed_users_platform_type ON channel_allowed_users(platform_type)');
139
- db.exec('CREATE INDEX IF NOT EXISTS idx_channel_allowed_users_active ON channel_allowed_users(is_active)');
140
- };
101
+ const raw = fs.readFileSync(DATA_FILE_PATH, 'utf8').trim();
102
+ const parsed = raw ? JSON.parse(raw) : {};
103
+ const normalized = normalizeState(parsed);
141
104
 
142
- const ensureChannelSessionsSchema = () => {
143
- if (!tableExists('channel_sessions')) {
144
- return;
105
+ if (JSON.stringify(parsed || {}) !== JSON.stringify(normalized)) {
106
+ persistStateSync(normalized);
107
+ return normalized;
145
108
  }
146
109
 
147
- const columns = getTableColumns('channel_sessions');
148
- if (!columns.includes('platform_type')) {
149
- console.log('Running migration: Adding platform_type to channel_sessions');
150
- db.exec("ALTER TABLE channel_sessions ADD COLUMN platform_type TEXT NOT NULL DEFAULT 'lark'");
151
- }
110
+ stateCache = normalized;
111
+ return normalized;
112
+ }
152
113
 
153
- db.exec("UPDATE channel_sessions SET platform_type = 'lark' WHERE platform_type IS NULL OR TRIM(platform_type) = ''");
114
+ function getStateSnapshot() {
115
+ return loadStateSync();
116
+ }
154
117
 
155
- if (hasIndex('idx_channel_sessions_unique')) {
156
- db.exec('DROP INDEX IF EXISTS idx_channel_sessions_unique');
157
- }
158
- db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_channel_sessions_unique ON channel_sessions(platform_type, user_id, chat_id, backend)');
159
- db.exec('CREATE INDEX IF NOT EXISTS idx_channel_sessions_platform_type ON channel_sessions(platform_type)');
160
- db.exec('CREATE INDEX IF NOT EXISTS idx_channel_sessions_user_id ON channel_sessions(user_id)');
161
- };
118
+ function updateStateSync(mutator) {
119
+ const currentState = getStateSnapshot();
120
+ const workingCopy = JSON.parse(JSON.stringify(currentState));
121
+ const result = mutator(workingCopy);
122
+ persistStateSync(workingCopy);
123
+ return result;
124
+ }
162
125
 
163
- const runMigrations = () => {
164
- try {
165
- const tableInfo = db.prepare("PRAGMA table_info(users)").all();
166
- const columnNames = tableInfo.map(col => col.name);
126
+ function nextCounter(state, key) {
127
+ state.meta.counters[key] = Number(state.meta.counters[key] || 0) + 1;
128
+ return state.meta.counters[key];
129
+ }
167
130
 
168
- if (!columnNames.includes('git_name')) {
169
- console.log('Running migration: Adding git_name column');
170
- db.exec('ALTER TABLE users ADD COLUMN git_name TEXT');
171
- }
131
+ function nowIso() {
132
+ return new Date().toISOString();
133
+ }
172
134
 
173
- if (!columnNames.includes('git_email')) {
174
- console.log('Running migration: Adding git_email column');
175
- db.exec('ALTER TABLE users ADD COLUMN git_email TEXT');
176
- }
135
+ function sanitizeActiveUser(user) {
136
+ if (!user || user.is_active === false) {
137
+ return null;
138
+ }
177
139
 
178
- if (!columnNames.includes('has_completed_onboarding')) {
179
- console.log('Running migration: Adding has_completed_onboarding column');
180
- db.exec('ALTER TABLE users ADD COLUMN has_completed_onboarding BOOLEAN DEFAULT 0');
181
- }
140
+ return user;
141
+ }
182
142
 
183
- ensureChannelAllowedUsersSchema();
184
- ensureChannelSessionsSchema();
143
+ function toUserPublic(user) {
144
+ const activeUser = sanitizeActiveUser(user);
145
+ if (!activeUser) return null;
146
+ return {
147
+ id: activeUser.id,
148
+ username: activeUser.username,
149
+ created_at: activeUser.created_at,
150
+ last_login: activeUser.last_login,
151
+ };
152
+ }
185
153
 
186
- console.log('Database migrations completed successfully');
187
- } catch (error) {
188
- console.error('Error running migrations:', error.message);
189
- throw error;
190
- }
191
- };
154
+ function findActiveUserById(state, userId) {
155
+ return sanitizeActiveUser(state.users.find((user) => user.id === userId));
156
+ }
192
157
 
193
- // Initialize database with schema
194
- const initializeDatabase = async () => {
195
- try {
196
- const initSQL = fs.readFileSync(INIT_SQL_PATH, 'utf8');
197
- db.exec(initSQL);
198
- console.log('Database initialized successfully');
199
- runMigrations();
200
- } catch (error) {
201
- console.error('Error initializing database:', error.message);
202
- throw error;
203
- }
204
- };
158
+ function findActiveUserByUsername(state, username) {
159
+ return sanitizeActiveUser(state.users.find((user) => user.username === username));
160
+ }
205
161
 
206
- // User database operations
207
162
  const userDb = {
208
- // Check if any users exist
209
- hasUsers: () => {
210
- try {
211
- const row = db.prepare('SELECT COUNT(*) as count FROM users').get();
212
- return row.count > 0;
213
- } catch (err) {
214
- throw err;
215
- }
216
- },
163
+ hasUsers: () => getStateSnapshot().users.some((user) => user.is_active !== false),
217
164
 
218
- // Create a new user
219
- createUser: (username, passwordHash) => {
220
- try {
221
- const stmt = db.prepare('INSERT INTO users (username, password_hash) VALUES (?, ?)');
222
- const result = stmt.run(username, passwordHash);
223
- return { id: result.lastInsertRowid, username };
224
- } catch (err) {
225
- throw err;
165
+ registerUser: (username, passwordHash) => updateStateSync((state) => {
166
+ if (state.users.some((user) => user.is_active !== false)) {
167
+ const error = new Error('User already exists. This is a single-user system.');
168
+ error.code = 'USER_EXISTS';
169
+ throw error;
226
170
  }
227
- },
228
171
 
229
- // Get user by username
230
- getUserByUsername: (username) => {
231
- try {
232
- const row = db.prepare('SELECT * FROM users WHERE username = ? AND is_active = 1').get(username);
233
- return row;
234
- } catch (err) {
235
- throw err;
172
+ if (state.users.some((user) => user.username === username)) {
173
+ const error = new Error('Username already exists');
174
+ error.code = 'USERNAME_EXISTS';
175
+ throw error;
236
176
  }
237
- },
238
177
 
239
- // Update last login time
240
- updateLastLogin: (userId) => {
241
- try {
242
- db.prepare('UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE id = ?').run(userId);
243
- } catch (err) {
244
- throw err;
178
+ const timestamp = nowIso();
179
+ const user = {
180
+ id: nextCounter(state, 'userId'),
181
+ username,
182
+ password_hash: passwordHash,
183
+ created_at: timestamp,
184
+ last_login: timestamp,
185
+ is_active: true,
186
+ git_name: null,
187
+ git_email: null,
188
+ has_completed_onboarding: false,
189
+ };
190
+
191
+ state.users.push(user);
192
+ return { id: user.id, username: user.username };
193
+ }),
194
+
195
+ createUser: (username, passwordHash) => updateStateSync((state) => {
196
+ if (state.users.some((user) => user.username === username)) {
197
+ const error = new Error('Username already exists');
198
+ error.code = 'USERNAME_EXISTS';
199
+ throw error;
245
200
  }
246
- },
247
201
 
248
- // Get user by ID
249
- getUserById: (userId) => {
250
- try {
251
- const row = db.prepare('SELECT id, username, created_at, last_login FROM users WHERE id = ? AND is_active = 1').get(userId);
252
- return row;
253
- } catch (err) {
254
- throw err;
202
+ const user = {
203
+ id: nextCounter(state, 'userId'),
204
+ username,
205
+ password_hash: passwordHash,
206
+ created_at: nowIso(),
207
+ last_login: null,
208
+ is_active: true,
209
+ git_name: null,
210
+ git_email: null,
211
+ has_completed_onboarding: false,
212
+ };
213
+ state.users.push(user);
214
+ return { id: user.id, username: user.username };
215
+ }),
216
+
217
+ getUserByUsername: (username) => findActiveUserByUsername(getStateSnapshot(), username) || null,
218
+
219
+ updateLastLogin: (userId) => updateStateSync((state) => {
220
+ const user = findActiveUserById(state, userId);
221
+ if (user) {
222
+ user.last_login = nowIso();
255
223
  }
256
- },
224
+ }),
225
+
226
+ getUserById: (userId) => toUserPublic(findActiveUserById(getStateSnapshot(), userId)),
257
227
 
258
228
  getFirstUser: () => {
259
- try {
260
- const row = db.prepare('SELECT id, username, created_at, last_login FROM users WHERE is_active = 1 LIMIT 1').get();
261
- return row;
262
- } catch (err) {
263
- throw err;
264
- }
229
+ const user = getStateSnapshot().users.find((entry) => entry.is_active !== false);
230
+ return toUserPublic(user);
265
231
  },
266
232
 
267
- updateGitConfig: (userId, gitName, gitEmail) => {
268
- try {
269
- const stmt = db.prepare('UPDATE users SET git_name = ?, git_email = ? WHERE id = ?');
270
- stmt.run(gitName, gitEmail, userId);
271
- } catch (err) {
272
- throw err;
273
- }
274
- },
233
+ updateGitConfig: (userId, gitName, gitEmail) => updateStateSync((state) => {
234
+ const user = findActiveUserById(state, userId);
235
+ if (!user) return;
236
+ user.git_name = gitName || null;
237
+ user.git_email = gitEmail || null;
238
+ }),
275
239
 
276
240
  getGitConfig: (userId) => {
277
- try {
278
- const row = db.prepare('SELECT git_name, git_email FROM users WHERE id = ?').get(userId);
279
- return row;
280
- } catch (err) {
281
- throw err;
241
+ const user = findActiveUserById(getStateSnapshot(), userId);
242
+ if (!user) {
243
+ return null;
282
244
  }
245
+ return {
246
+ git_name: user.git_name || null,
247
+ git_email: user.git_email || null,
248
+ };
283
249
  },
284
250
 
285
- completeOnboarding: (userId) => {
286
- try {
287
- const stmt = db.prepare('UPDATE users SET has_completed_onboarding = 1 WHERE id = ?');
288
- stmt.run(userId);
289
- } catch (err) {
290
- throw err;
251
+ completeOnboarding: (userId) => updateStateSync((state) => {
252
+ const user = findActiveUserById(state, userId);
253
+ if (user) {
254
+ user.has_completed_onboarding = true;
291
255
  }
292
- },
256
+ }),
293
257
 
294
258
  hasCompletedOnboarding: (userId) => {
295
- try {
296
- const row = db.prepare('SELECT has_completed_onboarding FROM users WHERE id = ?').get(userId);
297
- return row?.has_completed_onboarding === 1;
298
- } catch (err) {
299
- throw err;
300
- }
301
- }
259
+ const user = findActiveUserById(getStateSnapshot(), userId);
260
+ return !!user?.has_completed_onboarding;
261
+ },
302
262
  };
303
263
 
304
- // API Keys database operations
305
264
  const apiKeysDb = {
306
- // Generate a new API key
307
- generateApiKey: () => {
308
- return 'ck_' + crypto.randomBytes(32).toString('hex');
309
- },
310
-
311
- // Create a new API key
312
- createApiKey: (userId, keyName) => {
313
- try {
314
- const apiKey = apiKeysDb.generateApiKey();
315
- const stmt = db.prepare('INSERT INTO api_keys (user_id, key_name, api_key) VALUES (?, ?, ?)');
316
- const result = stmt.run(userId, keyName, apiKey);
317
- return { id: result.lastInsertRowid, keyName, apiKey };
318
- } catch (err) {
319
- throw err;
265
+ generateApiKey: () => `ck_${crypto.randomBytes(32).toString('hex')}`,
266
+
267
+ createApiKey: (userId, keyName) => updateStateSync((state) => {
268
+ const timestamp = nowIso();
269
+ const entry = {
270
+ id: nextCounter(state, 'apiKeyId'),
271
+ user_id: userId,
272
+ key_name: keyName,
273
+ api_key: apiKeysDb.generateApiKey(),
274
+ created_at: timestamp,
275
+ last_used: null,
276
+ is_active: true,
277
+ };
278
+ state.apiKeys.push(entry);
279
+ return { id: entry.id, keyName: entry.key_name, apiKey: entry.api_key };
280
+ }),
281
+
282
+ getApiKeys: (userId) => getStateSnapshot().apiKeys
283
+ .filter((entry) => entry.user_id === userId)
284
+ .sort((left, right) => String(right.created_at).localeCompare(String(left.created_at)))
285
+ .map((entry) => ({ ...entry })),
286
+
287
+ validateApiKey: (apiKey) => updateStateSync((state) => {
288
+ const entry = state.apiKeys.find((item) => item.api_key === apiKey && item.is_active !== false);
289
+ if (!entry) {
290
+ return null;
320
291
  }
321
- },
322
292
 
323
- // Get all API keys for a user
324
- getApiKeys: (userId) => {
325
- try {
326
- const rows = db.prepare('SELECT id, key_name, api_key, created_at, last_used, is_active FROM api_keys WHERE user_id = ? ORDER BY created_at DESC').all(userId);
327
- return rows;
328
- } catch (err) {
329
- throw err;
293
+ const user = findActiveUserById(state, entry.user_id);
294
+ if (!user) {
295
+ return null;
330
296
  }
331
- },
332
297
 
333
- // Validate API key and get user
334
- validateApiKey: (apiKey) => {
335
- try {
336
- const row = db.prepare(`
337
- SELECT u.id, u.username, ak.id as api_key_id
338
- FROM api_keys ak
339
- JOIN users u ON ak.user_id = u.id
340
- WHERE ak.api_key = ? AND ak.is_active = 1 AND u.is_active = 1
341
- `).get(apiKey);
342
-
343
- if (row) {
344
- // Update last_used timestamp
345
- db.prepare('UPDATE api_keys SET last_used = CURRENT_TIMESTAMP WHERE id = ?').run(row.api_key_id);
346
- }
298
+ entry.last_used = nowIso();
347
299
 
348
- return row;
349
- } catch (err) {
350
- throw err;
351
- }
352
- },
300
+ return {
301
+ id: user.id,
302
+ username: user.username,
303
+ api_key_id: entry.id,
304
+ };
305
+ }),
353
306
 
354
- // Delete an API key
355
- deleteApiKey: (userId, apiKeyId) => {
356
- try {
357
- const stmt = db.prepare('DELETE FROM api_keys WHERE id = ? AND user_id = ?');
358
- const result = stmt.run(apiKeyId, userId);
359
- return result.changes > 0;
360
- } catch (err) {
361
- throw err;
307
+ deleteApiKey: (userId, apiKeyId) => updateStateSync((state) => {
308
+ const index = state.apiKeys.findIndex((entry) => entry.id === apiKeyId && entry.user_id === userId);
309
+ if (index < 0) {
310
+ return false;
362
311
  }
363
- },
364
-
365
- // Toggle API key active status
366
- toggleApiKey: (userId, apiKeyId, isActive) => {
367
- try {
368
- const stmt = db.prepare('UPDATE api_keys SET is_active = ? WHERE id = ? AND user_id = ?');
369
- const result = stmt.run(isActive ? 1 : 0, apiKeyId, userId);
370
- return result.changes > 0;
371
- } catch (err) {
372
- throw err;
312
+ state.apiKeys.splice(index, 1);
313
+ return true;
314
+ }),
315
+
316
+ toggleApiKey: (userId, apiKeyId, isActive) => updateStateSync((state) => {
317
+ const entry = state.apiKeys.find((item) => item.id === apiKeyId && item.user_id === userId);
318
+ if (!entry) {
319
+ return false;
373
320
  }
374
- }
321
+ entry.is_active = !!isActive;
322
+ return true;
323
+ }),
375
324
  };
376
325
 
377
- // User credentials database operations (for GitHub tokens, GitLab tokens, etc.)
378
326
  const credentialsDb = {
379
- // Create a new credential
380
- createCredential: (userId, credentialName, credentialType, credentialValue, description = null) => {
381
- try {
382
- const stmt = db.prepare('INSERT INTO user_credentials (user_id, credential_name, credential_type, credential_value, description) VALUES (?, ?, ?, ?, ?)');
383
- const result = stmt.run(userId, credentialName, credentialType, credentialValue, description);
384
- return { id: result.lastInsertRowid, credentialName, credentialType };
385
- } catch (err) {
386
- throw err;
387
- }
327
+ createCredential: (userId, credentialName, credentialType, credentialValue, description = null) => updateStateSync((state) => {
328
+ const entry = {
329
+ id: nextCounter(state, 'credentialId'),
330
+ user_id: userId,
331
+ credential_name: credentialName,
332
+ credential_type: credentialType,
333
+ credential_value: credentialValue,
334
+ description,
335
+ created_at: nowIso(),
336
+ is_active: true,
337
+ };
338
+ state.credentials.push(entry);
339
+ return { id: entry.id, credentialName: entry.credential_name, credentialType: entry.credential_type };
340
+ }),
341
+
342
+ getCredentials: (userId, credentialType = null) => getStateSnapshot().credentials
343
+ .filter((entry) => entry.user_id === userId && (!credentialType || entry.credential_type === credentialType))
344
+ .sort((left, right) => String(right.created_at).localeCompare(String(left.created_at)))
345
+ .map(({ credential_value, ...rest }) => ({ ...rest })),
346
+
347
+ getActiveCredential: (userId, credentialType) => {
348
+ const match = getStateSnapshot().credentials
349
+ .filter((entry) => entry.user_id === userId && entry.credential_type === credentialType && entry.is_active !== false)
350
+ .sort((left, right) => String(right.created_at).localeCompare(String(left.created_at)))[0];
351
+ return match?.credential_value || null;
388
352
  },
389
353
 
390
- // Get all credentials for a user, optionally filtered by type
391
- getCredentials: (userId, credentialType = null) => {
392
- try {
393
- let query = 'SELECT id, credential_name, credential_type, description, created_at, is_active FROM user_credentials WHERE user_id = ?';
394
- const params = [userId];
354
+ getCredentialById: (userId, credentialId, credentialType = null) => {
355
+ const entry = getStateSnapshot().credentials.find((item) => (
356
+ item.id === credentialId
357
+ && item.user_id === userId
358
+ && item.is_active !== false
359
+ && (!credentialType || item.credential_type === credentialType)
360
+ ));
361
+ return entry ? { ...entry } : null;
362
+ },
395
363
 
396
- if (credentialType) {
397
- query += ' AND credential_type = ?';
398
- params.push(credentialType);
399
- }
364
+ deleteCredential: (userId, credentialId) => updateStateSync((state) => {
365
+ const index = state.credentials.findIndex((entry) => entry.id === credentialId && entry.user_id === userId);
366
+ if (index < 0) {
367
+ return false;
368
+ }
369
+ state.credentials.splice(index, 1);
370
+ return true;
371
+ }),
372
+
373
+ toggleCredential: (userId, credentialId, isActive) => updateStateSync((state) => {
374
+ const entry = state.credentials.find((item) => item.id === credentialId && item.user_id === userId);
375
+ if (!entry) {
376
+ return false;
377
+ }
378
+ entry.is_active = !!isActive;
379
+ return true;
380
+ }),
381
+ };
400
382
 
401
- query += ' ORDER BY created_at DESC';
383
+ const githubTokensDb = {
384
+ createGithubToken: (userId, tokenName, githubToken, description = null) => credentialsDb.createCredential(userId, tokenName, 'github_token', githubToken, description),
385
+ getGithubTokens: (userId) => credentialsDb.getCredentials(userId, 'github_token'),
386
+ getActiveGithubToken: (userId) => credentialsDb.getActiveCredential(userId, 'github_token'),
387
+ getGithubTokenById: (userId, tokenId) => credentialsDb.getCredentialById(userId, tokenId, 'github_token'),
388
+ deleteGithubToken: (userId, tokenId) => credentialsDb.deleteCredential(userId, tokenId),
389
+ toggleGithubToken: (userId, tokenId, isActive) => credentialsDb.toggleCredential(userId, tokenId, isActive),
390
+ };
402
391
 
403
- const rows = db.prepare(query).all(...params);
404
- return rows;
405
- } catch (err) {
406
- throw err;
407
- }
392
+ const channelDb = {
393
+ getPlugin(pluginId) {
394
+ return getStateSnapshot().channelPlugins.find((entry) => entry.id === pluginId) || null;
408
395
  },
409
396
 
410
- // Get active credential value for a user by type (returns most recent active)
411
- getActiveCredential: (userId, credentialType) => {
412
- try {
413
- const row = db.prepare('SELECT credential_value FROM user_credentials WHERE user_id = ? AND credential_type = ? AND is_active = 1 ORDER BY created_at DESC LIMIT 1').get(userId, credentialType);
414
- return row?.credential_value || null;
415
- } catch (err) {
416
- throw err;
417
- }
397
+ upsertPlugin(plugin) {
398
+ return updateStateSync((state) => {
399
+ const index = state.channelPlugins.findIndex((entry) => entry.id === plugin.id);
400
+ if (index >= 0) {
401
+ state.channelPlugins[index] = { ...state.channelPlugins[index], ...plugin };
402
+ } else {
403
+ state.channelPlugins.push({ ...plugin });
404
+ }
405
+ return { ...state.channelPlugins.find((entry) => entry.id === plugin.id) };
406
+ });
418
407
  },
419
408
 
420
- // Delete a credential
421
- deleteCredential: (userId, credentialId) => {
422
- try {
423
- const stmt = db.prepare('DELETE FROM user_credentials WHERE id = ? AND user_id = ?');
424
- const result = stmt.run(credentialId, userId);
425
- return result.changes > 0;
426
- } catch (err) {
427
- throw err;
428
- }
409
+ listAllowedUsers(platform) {
410
+ return getStateSnapshot().channelAllowedUsers
411
+ .filter((entry) => entry.platform_type === platform)
412
+ .sort((left, right) => String(right.created_at).localeCompare(String(left.created_at)))
413
+ .map((entry) => ({ ...entry }));
429
414
  },
430
415
 
431
- // Toggle credential active status
432
- toggleCredential: (userId, credentialId, isActive) => {
433
- try {
434
- const stmt = db.prepare('UPDATE user_credentials SET is_active = ? WHERE id = ? AND user_id = ?');
435
- const result = stmt.run(isActive ? 1 : 0, credentialId, userId);
436
- return result.changes > 0;
437
- } catch (err) {
438
- throw err;
439
- }
440
- }
441
- };
416
+ addAllowedUser(platform, { userId, displayName = null, note = null }) {
417
+ return updateStateSync((state) => {
418
+ const duplicate = state.channelAllowedUsers.find((entry) => entry.platform_type === platform && entry.user_id === userId);
419
+ if (duplicate) {
420
+ const error = new Error('Allowed user already exists');
421
+ error.code = 'CHANNEL_ALLOWED_USER_EXISTS';
422
+ throw error;
423
+ }
442
424
 
443
- // Backward compatibility - keep old names pointing to new system
444
- const githubTokensDb = {
445
- createGithubToken: (userId, tokenName, githubToken, description = null) => {
446
- return credentialsDb.createCredential(userId, tokenName, 'github_token', githubToken, description);
425
+ const timestamp = nowIso();
426
+ const entry = {
427
+ id: nextCounter(state, 'allowedUserId'),
428
+ platform_type: platform,
429
+ user_id: userId,
430
+ display_name: displayName,
431
+ note,
432
+ is_active: true,
433
+ created_at: timestamp,
434
+ updated_at: timestamp,
435
+ };
436
+ state.channelAllowedUsers.push(entry);
437
+ return { ...entry };
438
+ });
447
439
  },
448
- getGithubTokens: (userId) => {
449
- return credentialsDb.getCredentials(userId, 'github_token');
440
+
441
+ removeAllowedUser(platform, id) {
442
+ return updateStateSync((state) => {
443
+ const index = state.channelAllowedUsers.findIndex((entry) => entry.platform_type === platform && entry.id === id);
444
+ if (index < 0) return false;
445
+ state.channelAllowedUsers.splice(index, 1);
446
+ return true;
447
+ });
450
448
  },
451
- getActiveGithubToken: (userId) => {
452
- return credentialsDb.getActiveCredential(userId, 'github_token');
449
+
450
+ toggleAllowedUser(platform, id, isActive) {
451
+ return updateStateSync((state) => {
452
+ const entry = state.channelAllowedUsers.find((item) => item.platform_type === platform && item.id === id);
453
+ if (!entry) return false;
454
+ entry.is_active = !!isActive;
455
+ entry.updated_at = nowIso();
456
+ return true;
457
+ });
453
458
  },
454
- deleteGithubToken: (userId, tokenId) => {
455
- return credentialsDb.deleteCredential(userId, tokenId);
459
+
460
+ isAllowedUser(platform, userId) {
461
+ return !!getStateSnapshot().channelAllowedUsers.find((entry) => entry.platform_type === platform && entry.user_id === userId && entry.is_active !== false);
462
+ },
463
+
464
+ getChannelSession({ platform, userId, chatId, backend }) {
465
+ const entry = getStateSnapshot().channelSessions.find((item) => (
466
+ item.platform_type === platform
467
+ && item.user_id === userId
468
+ && item.chat_id === chatId
469
+ && item.backend === backend
470
+ ));
471
+ return entry ? { ...entry } : null;
472
+ },
473
+
474
+ upsertChannelSession({ platform, userId, chatId, backend, providerSessionId, projectPath }) {
475
+ return updateStateSync((state) => {
476
+ const timestamp = nowIso();
477
+ const existing = state.channelSessions.find((item) => (
478
+ item.platform_type === platform
479
+ && item.user_id === userId
480
+ && item.chat_id === chatId
481
+ && item.backend === backend
482
+ ));
483
+
484
+ if (existing) {
485
+ existing.provider_session_id = providerSessionId || null;
486
+ existing.project_path = projectPath || null;
487
+ existing.updated_at = timestamp;
488
+ return { ...existing };
489
+ }
490
+
491
+ const entry = {
492
+ id: crypto.randomUUID(),
493
+ platform_type: platform,
494
+ user_id: userId,
495
+ chat_id: chatId,
496
+ backend,
497
+ provider_session_id: providerSessionId || null,
498
+ project_path: projectPath || null,
499
+ updated_at: timestamp,
500
+ };
501
+ state.channelSessions.push(entry);
502
+ return { ...entry };
503
+ });
456
504
  },
457
- toggleGithubToken: (userId, tokenId, isActive) => {
458
- return credentialsDb.toggleCredential(userId, tokenId, isActive);
459
- }
460
505
  };
461
506
 
507
+ async function initializeDatabase() {
508
+ const state = getStateSnapshot();
509
+
510
+ console.log('');
511
+ console.log(c.dim('═'.repeat(60)));
512
+ console.log(`${c.info('[INFO]')} App Installation: ${c.bright(appInstallPath)}`);
513
+ console.log(`${c.info('[INFO]')} Data File: ${c.dim(path.relative(appInstallPath, DATA_FILE_PATH))}`);
514
+ if (process.env.DATA_FILE_PATH) {
515
+ console.log(` ${c.dim('(Using custom DATA_FILE_PATH from environment)')}`);
516
+ }
517
+ console.log(c.dim('═'.repeat(60)));
518
+ console.log('');
519
+ console.log('Data file initialized successfully');
520
+ return state;
521
+ }
522
+
523
+ function getDataFilePath() {
524
+ return DATA_FILE_PATH;
525
+ }
526
+
462
527
  export {
463
- db,
464
528
  initializeDatabase,
529
+ getDataFilePath,
465
530
  userDb,
466
531
  apiKeysDb,
467
532
  credentialsDb,
468
- githubTokensDb // Backward compatibility
533
+ githubTokensDb,
534
+ channelDb,
469
535
  };