@axhub/genie 0.1.8 → 0.1.9

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 (397) hide show
  1. package/README.md +1 -1
  2. package/dist/api-docs.html +2 -2
  3. package/dist/assets/App-IUhj6pRQ.js +546 -0
  4. package/dist/assets/App-qxJ8_QYu.css +32 -0
  5. package/dist/assets/ReviewApp-B8aNlXpI.js +1 -0
  6. package/dist/assets/_basePickBy-DF_C8v-X.js +1 -0
  7. package/dist/assets/_baseUniq-Dl8X6bvw.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-TwO_Ni8v.js +1 -0
  20. package/dist/assets/architectureDiagram-2XIMDMQ5-Dgm9kjQy.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-BhTxXYHE.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-D3xrrPyf.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-D6xYGBae.js +1 -0
  49. package/dist/assets/chunk-4BX2VUAB-Fb3wkGSX.js +1 -0
  50. package/dist/assets/chunk-55IACEB6-CQwPJLM_.js +1 -0
  51. package/dist/assets/chunk-FMBD7UC4-B3SocdK3.js +15 -0
  52. package/dist/assets/chunk-JSJVCQXG-4LjhKVWX.js +1 -0
  53. package/dist/assets/chunk-KX2RTZJC-B5NX8jxL.js +1 -0
  54. package/dist/assets/chunk-NQ4KR5QH-6puKzw3k.js +220 -0
  55. package/dist/assets/chunk-QZHKN3VN-CxscPgdC.js +1 -0
  56. package/dist/assets/chunk-WL4C6EOR-uBFUeI3B.js +189 -0
  57. package/dist/assets/clarity-D53aC0YG.js +1 -0
  58. package/dist/assets/classDiagram-VBA2DB6C-CAq2xBD7.js +1 -0
  59. package/dist/assets/classDiagram-v2-RAHNMMFH-CAq2xBD7.js +1 -0
  60. package/dist/assets/clojure-P80f7IUj.js +1 -0
  61. package/dist/assets/clone-Ci5Ji0hp.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-DlbARPn2.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-D5rHdqja.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-1UmM7jTs.js +24 -0
  86. package/dist/assets/diagram-IFDJBPK2-BiB8xLQb.js +43 -0
  87. package/dist/assets/diagram-P4PSJMXO-D0DHiPZv.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-CnRJ2Jix.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-CEgo6QRr.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-BIuQLJvD.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-BgM4MazK.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-CAfp4sq_.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-qMmmT5JC.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-DIJsxqXa.css +1 -0
  162. package/dist/assets/index-DLN_-tVh.js +2 -0
  163. package/dist/assets/infoDiagram-LFFYTUFH-CWSerJ0x.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-CzeVsiJ6.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-D_NYt9lf.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-CX7AUuup.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-DSvVDs_y.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-CVh3kWAl.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-CrPRD2Zy.js +964 -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-w_orDc4B.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-Ddit1h2q.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-DVw1s8Ut.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-DQPZpp_9.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-CfbFynOx.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-BO9n1wra.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-CRL3ceNd.js +1 -0
  307. package/dist/assets/stateDiagram-v2-FVOUBMTO-CZOgjDCg.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-BR7smGEM.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-DkR8x0Kw.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-D5if-Qdt.js} +3 -3
  337. package/dist/assets/{vendor-react-C3RJLQGO.js → vendor-react-CSz7XC90.js} +11 -11
  338. package/dist/assets/vennDiagram-LZ73GAT5-DS7XpPV_.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-BgjSBvNS.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 +34 -20
  364. package/dist/sw.js +18 -46
  365. package/package.json +10 -7
  366. package/server/bin/codex-sdk-wrapper.js +49 -0
  367. package/server/channels/runtime/AgentRuntimeAdapter.js +2 -5
  368. package/server/channels/store/ChannelStore.js +73 -107
  369. package/server/claude-sdk.js +151 -3
  370. package/server/cli.js +21 -21
  371. package/server/database/db.js +438 -372
  372. package/server/gemini-cli.js +106 -19
  373. package/server/index.js +63 -105
  374. package/server/load-env.js +16 -13
  375. package/server/openai-codex.js +144 -9
  376. package/server/projects.js +340 -331
  377. package/server/routes/agent.js +424 -29
  378. package/server/routes/auth.js +14 -36
  379. package/server/routes/cli-auth.js +60 -113
  380. package/server/routes/commands.js +16 -26
  381. package/server/routes/git.js +5 -16
  382. package/server/routes/projects.js +2 -7
  383. package/server/routes/session-core.js +177 -0
  384. package/server/session-core/abortSession.js +48 -0
  385. package/server/session-core/eventStore.js +139 -0
  386. package/server/session-core/providerAdapters.js +84 -0
  387. package/server/session-core/providerDiscovery.js +235 -0
  388. package/server/session-core/runtimeWriter.js +55 -0
  389. package/server/utils/agentCallback.js +273 -0
  390. package/server/utils/codexPath.js +47 -0
  391. package/shared/conversationEvents.js +1031 -0
  392. package/shared/modelConstants.js +18 -24
  393. package/dist/assets/index-CVjMty4a.js +0 -902
  394. package/dist/assets/index-eo5scY_Z.css +0 -32
  395. package/server/cursor-cli.js +0 -276
  396. package/server/database/init.sql +0 -98
  397. package/server/routes/cursor.js +0 -795
@@ -7,10 +7,19 @@ import crypto from 'crypto';
7
7
  import { userDb, apiKeysDb, githubTokensDb } from '../database/db.js';
8
8
  import { addProjectManually } from '../projects.js';
9
9
  import { queryClaudeSDK } from '../claude-sdk.js';
10
- import { spawnCursor } from '../cursor-cli.js';
11
10
  import { queryCodex } from '../openai-codex.js';
12
11
  import { queryGemini } from '../gemini-cli.js';
13
12
  import { queryOpencode } from '../opencode-cli.js';
13
+ import { SessionEventMirrorWriter } from '../session-core/runtimeWriter.js';
14
+ import { ABORTABLE_AGENT_PROVIDERS, abortAgentSessionWithWriter, isAbortableAgentProvider } from '../session-core/abortSession.js';
15
+ import {
16
+ buildAgentCallbackPayload,
17
+ createAgentCallbackEventId,
18
+ createEmptyTokenSummary,
19
+ normalizeAgentCallbackConfig,
20
+ scheduleAgentCallbackDelivery,
21
+ shouldDeliverAgentCallback
22
+ } from '../utils/agentCallback.js';
14
23
  import { Octokit } from '@octokit/rest';
15
24
  import { CODEX_MODELS, GEMINI_MODELS, OPENCODE_MODELS } from '../../shared/modelConstants.js';
16
25
  import { IS_PLATFORM } from '../constants/config.js';
@@ -632,6 +641,182 @@ class ResponseCollector {
632
641
  }
633
642
  }
634
643
 
644
+ class AgentSessionAbortedError extends Error {
645
+ constructor(message = 'Session aborted') {
646
+ super(message);
647
+ this.name = 'AgentSessionAbortedError';
648
+ }
649
+ }
650
+
651
+ function extractTerminalErrorMessage(payload) {
652
+ if (!payload || typeof payload !== 'object') {
653
+ return null;
654
+ }
655
+
656
+ if (typeof payload.error === 'string' && payload.error.trim()) {
657
+ return payload.error.trim();
658
+ }
659
+
660
+ if (payload.error && typeof payload.error.message === 'string' && payload.error.message.trim()) {
661
+ return payload.error.message.trim();
662
+ }
663
+
664
+ const nestedData = payload.data;
665
+ if (nestedData && typeof nestedData === 'object') {
666
+ if (typeof nestedData.error === 'string' && nestedData.error.trim()) {
667
+ return nestedData.error.trim();
668
+ }
669
+
670
+ if (nestedData.error && typeof nestedData.error.message === 'string' && nestedData.error.message.trim()) {
671
+ return nestedData.error.message.trim();
672
+ }
673
+
674
+ if (typeof nestedData.message === 'string' && nestedData.message.trim()) {
675
+ return nestedData.message.trim();
676
+ }
677
+ }
678
+
679
+ return null;
680
+ }
681
+
682
+ class CallbackCaptureWriter {
683
+ constructor() {
684
+ this.sessionId = null;
685
+ this.assistantMessages = [];
686
+ this.tokenSummary = createEmptyTokenSummary();
687
+ this.terminalState = null;
688
+ this.terminalErrorMessage = null;
689
+ }
690
+
691
+ send(payload) {
692
+ if (!payload || typeof payload !== 'object') {
693
+ return;
694
+ }
695
+
696
+ if (typeof payload.sessionId === 'string' && payload.sessionId.trim()) {
697
+ this.sessionId = payload.sessionId.trim();
698
+ }
699
+
700
+ if (payload.type === 'session-created' && typeof payload.sessionId === 'string' && payload.sessionId.trim()) {
701
+ this.sessionId = payload.sessionId.trim();
702
+ }
703
+
704
+ if (payload.type === 'token-budget' && payload.data && typeof payload.data === 'object') {
705
+ this.tokenSummary = {
706
+ inputTokens: Number(payload.data.inputTokens) || 0,
707
+ outputTokens: Number(payload.data.outputTokens) || 0,
708
+ cacheReadTokens: Number(payload.data.cacheReadTokens) || 0,
709
+ cacheCreationTokens: Number(payload.data.cacheCreationTokens) || 0,
710
+ totalTokens: Number(payload.data.totalTokens) || 0
711
+ };
712
+ }
713
+
714
+ if (payload.type === 'claude-response' && payload.data?.type === 'assistant') {
715
+ this.assistantMessages.push(payload.data);
716
+ }
717
+
718
+ if (
719
+ payload.type === 'codex-response' &&
720
+ payload.data?.type === 'item_done' &&
721
+ payload.data?.itemType === 'agent_message' &&
722
+ typeof payload.data?.content === 'string' &&
723
+ payload.data.content.trim()
724
+ ) {
725
+ this.assistantMessages.push({
726
+ type: 'assistant',
727
+ message: {
728
+ role: 'assistant',
729
+ content: payload.data.content
730
+ }
731
+ });
732
+ }
733
+
734
+ if (payload.type === 'session-aborted') {
735
+ this.terminalState = 'aborted';
736
+ this.terminalErrorMessage = 'Session aborted';
737
+ return;
738
+ }
739
+
740
+ if (payload.type === 'claude-complete' || payload.type === 'codex-complete') {
741
+ this.terminalState = 'completed';
742
+ this.terminalErrorMessage = null;
743
+ return;
744
+ }
745
+
746
+ if (
747
+ payload.type === 'claude-error' ||
748
+ payload.type === 'codex-error' ||
749
+ payload.type === 'error' ||
750
+ (payload.type === 'codex-response' && payload.data?.type === 'turn_failed')
751
+ ) {
752
+ this.terminalState = 'errored';
753
+ this.terminalErrorMessage = extractTerminalErrorMessage(payload) || this.terminalErrorMessage || 'Agent session failed';
754
+ }
755
+ }
756
+
757
+ end() {}
758
+
759
+ setSessionId(sessionId) {
760
+ if (typeof sessionId === 'string' && sessionId.trim()) {
761
+ this.sessionId = sessionId.trim();
762
+ }
763
+ }
764
+
765
+ getSessionId() {
766
+ return this.sessionId;
767
+ }
768
+
769
+ getAssistantMessages() {
770
+ return this.assistantMessages;
771
+ }
772
+
773
+ getTotalTokens() {
774
+ return this.tokenSummary;
775
+ }
776
+
777
+ getTerminalState() {
778
+ return this.terminalState;
779
+ }
780
+
781
+ getTerminalErrorMessage() {
782
+ return this.terminalErrorMessage;
783
+ }
784
+ }
785
+
786
+ class TeeWriter {
787
+ constructor(primaryWriter, secondaryWriter) {
788
+ this.primaryWriter = primaryWriter;
789
+ this.secondaryWriter = secondaryWriter;
790
+ this.isSSEStreamWriter = !!primaryWriter?.isSSEStreamWriter;
791
+ this.isWebSocketWriter = !!primaryWriter?.isWebSocketWriter;
792
+ }
793
+
794
+ send(payload) {
795
+ this.primaryWriter?.send?.(payload);
796
+ this.secondaryWriter?.send?.(payload);
797
+ }
798
+
799
+ end() {
800
+ this.primaryWriter?.end?.();
801
+ this.secondaryWriter?.end?.();
802
+ }
803
+
804
+ setSessionId(sessionId) {
805
+ this.primaryWriter?.setSessionId?.(sessionId);
806
+ this.secondaryWriter?.setSessionId?.(sessionId);
807
+ }
808
+
809
+ getSessionId() {
810
+ return this.primaryWriter?.getSessionId?.() || this.secondaryWriter?.getSessionId?.() || null;
811
+ }
812
+ }
813
+
814
+ class NoopWriter {
815
+ send() {}
816
+
817
+ end() {}
818
+ }
819
+
635
820
  // ===============================
636
821
  // External API Endpoint
637
822
  // ===============================
@@ -639,7 +824,7 @@ class ResponseCollector {
639
824
  /**
640
825
  * POST /api/agent
641
826
  *
642
- * Trigger an AI agent (Claude, Cursor, Codex, or Gemini) to work on a project.
827
+ * Trigger an AI agent (Claude, Codex, Gemini, or OpenCode) to work on a project.
643
828
  * Supports automatic GitHub branch and pull request creation after successful completion.
644
829
  *
645
830
  * ================================================================================================
@@ -667,7 +852,7 @@ class ResponseCollector {
667
852
  * @param {string} sessionId - (Optional) Existing session ID to resume.
668
853
  * If provided, the request continues that session instead of creating a new one.
669
854
  *
670
- * @param {string} provider - (Optional) AI provider to use. Options: 'claude' | 'cursor' | 'codex' | 'gemini'
855
+ * @param {string} provider - (Optional) AI provider to use. Options: 'claude' | 'codex' | 'gemini' | 'opencode'
671
856
  * Default: 'claude'
672
857
  *
673
858
  * @param {boolean} stream - (Optional) Enable Server-Sent Events (SSE) streaming for real-time updates.
@@ -678,8 +863,7 @@ class ResponseCollector {
678
863
  * @param {string} model - (Optional) Model identifier for providers.
679
864
  *
680
865
  * Claude models: 'sonnet' (default), 'opus', 'haiku', 'opusplan', 'sonnet[1m]'
681
- * Cursor models: 'gpt-5' (default), 'gpt-5.2', 'gpt-5.2-high', 'sonnet-4.5', 'opus-4.5',
682
- * 'gemini-3-pro', 'composer-1', 'auto', 'gpt-5.1', 'gpt-5.1-high',
866
+ * * 'gemini-3-pro', 'composer-1', 'auto', 'gpt-5.1', 'gpt-5.1-high',
683
867
  * 'gpt-5.1-codex', 'gpt-5.1-codex-high', 'gpt-5.1-codex-max',
684
868
  * 'gpt-5.1-codex-max-high', 'opus-4.1', 'grok', and thinking variants
685
869
  * Codex models: 'gpt-5.2' (default), 'gpt-5.1-codex-max', 'o3', 'o4-mini'
@@ -733,6 +917,16 @@ class ResponseCollector {
733
917
  * - If PR already exists: GitHub returns error with details
734
918
  * - Requires either githubUrl OR projectPath with GitHub remote
735
919
  *
920
+ * @param {object} callback - (Optional) Terminal webhook configuration for external systems.
921
+ * Behavior:
922
+ * - Sent once when the run ends as completed, errored, or aborted
923
+ * - Delivery is asynchronous and never blocks the main API response
924
+ * - Not supported with openOnly=true
925
+ * Fields:
926
+ * - url: Required HTTP/HTTPS target URL
927
+ * - events: Optional subset of ["completed", "errored", "aborted"]
928
+ * - secret: Optional shared secret for HMAC signing
929
+ *
736
930
  * ================================================================================================
737
931
  * PATH HANDLING BEHAVIOR
738
932
  * ================================================================================================
@@ -786,9 +980,13 @@ class ResponseCollector {
786
980
  * Input Validations (400 Bad Request):
787
981
  * - Either githubUrl OR projectPath must be provided (not neither)
788
982
  * - message must be non-empty string
789
- * - provider must be 'claude', 'cursor', 'codex', or 'gemini'
983
+ * - provider must be 'claude', 'codex', 'gemini', or 'opencode'
790
984
  * - createBranch/createPR requires githubUrl OR projectPath (not neither)
791
985
  * - branchName must pass Git naming rules (if provided)
986
+ * - callback must be an object when provided
987
+ * - callback.url must be a valid HTTP/HTTPS URL
988
+ * - callback.events can only include completed/errored/aborted
989
+ * - callback is not supported when openOnly=true
792
990
  *
793
991
  * Runtime Validations (500 Internal Server Error or specific error in response):
794
992
  * - projectPath must exist (if used alone)
@@ -847,6 +1045,14 @@ class ResponseCollector {
847
1045
  * Content-Type: application/json
848
1046
  * { success: false, error: "Error description" }
849
1047
  *
1048
+ * Callback Delivery:
1049
+ * Content-Type: application/json
1050
+ * Headers:
1051
+ * - X-Agent-Event
1052
+ * - X-Agent-Event-Id
1053
+ * - X-Agent-Delivery-Attempt
1054
+ * - X-Agent-Signature (only when callback.secret is provided)
1055
+ *
850
1056
  * ================================================================================================
851
1057
  * EXAMPLES
852
1058
  * ================================================================================================
@@ -876,6 +1082,7 @@ class ResponseCollector {
876
1082
  */
877
1083
  router.post('/', validateExternalApiKey, async (req, res) => {
878
1084
  const { githubUrl, projectPath, message, provider = 'claude', model, githubToken, branchName, sessionId, openOnly } = req.body;
1085
+ const startedAt = new Date().toISOString();
879
1086
 
880
1087
  // Parse stream and cleanup as booleans (handle string "true"/"false" from curl)
881
1088
  const stream = req.body.stream === undefined ? true : (req.body.stream === true || req.body.stream === 'true');
@@ -891,10 +1098,17 @@ router.post('/', validateExternalApiKey, async (req, res) => {
891
1098
  // Keep openOnly requests backward-compatible with existing docs/examples:
892
1099
  // cleanup is irrelevant when we only generate session navigation.
893
1100
  const cleanup = isOpenOnly ? false : requestedCleanup;
1101
+ let callbackConfig = null;
1102
+
1103
+ try {
1104
+ callbackConfig = normalizeAgentCallbackConfig(req.body.callback);
1105
+ } catch (error) {
1106
+ return res.status(400).json({ error: error.message });
1107
+ }
894
1108
 
895
1109
  // Validate inputs
896
- if (!['claude', 'cursor', 'codex', 'gemini', 'opencode'].includes(provider)) {
897
- return res.status(400).json({ error: 'provider must be "claude", "cursor", "codex", "gemini", or "opencode"' });
1110
+ if (!['claude', 'codex', 'gemini', 'opencode'].includes(provider)) {
1111
+ return res.status(400).json({ error: 'provider must be "claude", "codex", "gemini", or "opencode"' });
898
1112
  }
899
1113
 
900
1114
  if (sessionId !== undefined && (typeof sessionId !== 'string' || !sessionId.trim())) {
@@ -921,6 +1135,10 @@ router.post('/', validateExternalApiKey, async (req, res) => {
921
1135
  return res.status(400).json({ error: 'createBranch and createPR are not supported when openOnly=true' });
922
1136
  }
923
1137
 
1138
+ if (isOpenOnly && callbackConfig) {
1139
+ return res.status(400).json({ error: 'callback is not supported when openOnly=true' });
1140
+ }
1141
+
924
1142
  // Validate GitHub branch/PR creation requirements
925
1143
  // Allow branch/PR creation with projectPath as long as it has a GitHub remote
926
1144
  if ((createBranch || createPR) && !githubUrl && !projectPath) {
@@ -959,6 +1177,10 @@ router.post('/', validateExternalApiKey, async (req, res) => {
959
1177
 
960
1178
  let finalProjectPath = null;
961
1179
  let writer = null;
1180
+ let transportWriter = null;
1181
+ let callbackCaptureWriter = new CallbackCaptureWriter();
1182
+ let callbackResult = null;
1183
+ let callbackSessionId = normalizedSessionId;
962
1184
 
963
1185
  try {
964
1186
  // Determine the final project path
@@ -1015,26 +1237,28 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1015
1237
  res.setHeader('Connection', 'keep-alive');
1016
1238
  res.setHeader('X-Accel-Buffering', 'no'); // Disable nginx buffering
1017
1239
 
1018
- writer = new SSEStreamWriter(res);
1240
+ transportWriter = new SSEStreamWriter(res);
1019
1241
 
1020
1242
  // Send initial status
1021
- writer.send({
1243
+ transportWriter.send({
1022
1244
  type: 'status',
1023
1245
  message: statusMessage,
1024
1246
  projectPath: finalProjectPath
1025
1247
  });
1026
1248
  } else {
1027
1249
  // Non-streaming mode: collect messages
1028
- writer = new ResponseCollector();
1250
+ transportWriter = new ResponseCollector();
1029
1251
 
1030
1252
  // Collect initial status message
1031
- writer.send({
1253
+ transportWriter.send({
1032
1254
  type: 'status',
1033
1255
  message: statusMessage,
1034
1256
  projectPath: finalProjectPath
1035
1257
  });
1036
1258
  }
1037
1259
 
1260
+ writer = new TeeWriter(transportWriter, callbackCaptureWriter);
1261
+
1038
1262
  // Start the appropriate session
1039
1263
  if (provider === 'claude') {
1040
1264
  console.log('🤖 Starting Claude SDK session');
@@ -1046,18 +1270,6 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1046
1270
  model: model,
1047
1271
  permissionMode: 'bypassPermissions' // Bypass all permissions for API calls
1048
1272
  }, writer);
1049
-
1050
- } else if (provider === 'cursor') {
1051
- console.log('🖱️ Starting Cursor CLI session');
1052
-
1053
- await spawnCursor(normalizedMessage, {
1054
- projectPath: finalProjectPath,
1055
- cwd: finalProjectPath,
1056
- sessionId: normalizedSessionId,
1057
- resume: !!normalizedSessionId,
1058
- model: model || undefined,
1059
- skipPermissions: true // Bypass permissions for Cursor
1060
- }, writer);
1061
1273
  } else if (provider === 'codex') {
1062
1274
  console.log('🤖 Starting Codex SDK session');
1063
1275
 
@@ -1092,6 +1304,17 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1092
1304
  }, writer);
1093
1305
  }
1094
1306
 
1307
+ callbackSessionId = writer.getSessionId() || callbackCaptureWriter.getSessionId() || normalizedSessionId;
1308
+
1309
+ const terminalState = callbackCaptureWriter.getTerminalState();
1310
+ if (terminalState === 'errored') {
1311
+ throw new Error(callbackCaptureWriter.getTerminalErrorMessage() || `${provider} session failed`);
1312
+ }
1313
+
1314
+ if (terminalState !== 'completed') {
1315
+ throw new AgentSessionAbortedError();
1316
+ }
1317
+
1095
1318
  // Handle GitHub branch and PR creation after successful agent completion
1096
1319
  let branchInfo = null;
1097
1320
  let prInfo = null;
@@ -1274,15 +1497,26 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1274
1497
  }
1275
1498
 
1276
1499
  // Handle response based on streaming mode
1500
+ callbackSessionId = writer.getSessionId() || callbackCaptureWriter.getSessionId() || normalizedSessionId;
1501
+ const { sessionPath, sessionUrl } = buildSessionNavigation(callbackSessionId);
1502
+
1277
1503
  if (stream) {
1504
+ callbackResult = {
1505
+ sessionPath,
1506
+ sessionUrl,
1507
+ messages: callbackCaptureWriter.getAssistantMessages(),
1508
+ tokens: callbackCaptureWriter.getTotalTokens(),
1509
+ branch: branchInfo,
1510
+ pullRequest: prInfo
1511
+ };
1512
+
1278
1513
  // Streaming mode: end the SSE stream
1279
1514
  writer.end();
1280
1515
  } else {
1281
1516
  // Non-streaming mode: send filtered messages and token summary as JSON
1282
- const assistantMessages = writer.getAssistantMessages();
1283
- const tokenSummary = writer.getTotalTokens();
1284
- const resolvedSessionId = writer.getSessionId() || normalizedSessionId;
1285
- const { sessionPath, sessionUrl } = buildSessionNavigation(resolvedSessionId);
1517
+ const assistantMessages = transportWriter.getAssistantMessages();
1518
+ const tokenSummary = transportWriter.getTotalTokens();
1519
+ const resolvedSessionId = transportWriter.getSessionId() || callbackSessionId;
1286
1520
 
1287
1521
  const response = {
1288
1522
  success: true,
@@ -1303,9 +1537,37 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1303
1537
  response.pullRequest = prInfo;
1304
1538
  }
1305
1539
 
1540
+ callbackResult = {
1541
+ sessionPath,
1542
+ sessionUrl,
1543
+ messages: assistantMessages,
1544
+ tokens: tokenSummary,
1545
+ branch: branchInfo,
1546
+ pullRequest: prInfo
1547
+ };
1548
+
1306
1549
  res.json(response);
1307
1550
  }
1308
1551
 
1552
+ if (callbackConfig && shouldDeliverAgentCallback(callbackConfig, 'completed')) {
1553
+ const payload = buildAgentCallbackPayload({
1554
+ event: 'completed',
1555
+ eventId: createAgentCallbackEventId(),
1556
+ sessionId: callbackSessionId,
1557
+ provider,
1558
+ projectPath: finalProjectPath,
1559
+ isResumed: !!normalizedSessionId,
1560
+ startedAt,
1561
+ finishedAt: new Date().toISOString(),
1562
+ result: callbackResult
1563
+ });
1564
+
1565
+ void scheduleAgentCallbackDelivery({
1566
+ callback: callbackConfig,
1567
+ payload
1568
+ });
1569
+ }
1570
+
1309
1571
  // Clean up if requested
1310
1572
  if (cleanup && githubUrl) {
1311
1573
  // Only cleanup if we cloned a repo (not for existing project paths)
@@ -1317,6 +1579,15 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1317
1579
 
1318
1580
  } catch (error) {
1319
1581
  console.error('❌ External session error:', error);
1582
+ const terminalEvent = error instanceof AgentSessionAbortedError ? 'aborted' : 'errored';
1583
+ callbackSessionId = (writer && writer.getSessionId()) || callbackCaptureWriter.getSessionId() || normalizedSessionId;
1584
+ const { sessionPath, sessionUrl } = buildSessionNavigation(callbackSessionId);
1585
+ callbackResult = {
1586
+ sessionPath,
1587
+ sessionUrl,
1588
+ messages: callbackCaptureWriter.getAssistantMessages(),
1589
+ tokens: callbackCaptureWriter.getTotalTokens()
1590
+ };
1320
1591
 
1321
1592
  // Clean up on error
1322
1593
  if (finalProjectPath && cleanup && githubUrl) {
@@ -1332,7 +1603,8 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1332
1603
  res.setHeader('Cache-Control', 'no-cache');
1333
1604
  res.setHeader('Connection', 'keep-alive');
1334
1605
  res.setHeader('X-Accel-Buffering', 'no');
1335
- writer = new SSEStreamWriter(res);
1606
+ transportWriter = new SSEStreamWriter(res);
1607
+ writer = new TeeWriter(transportWriter, callbackCaptureWriter);
1336
1608
  }
1337
1609
 
1338
1610
  if (!res.writableEnded) {
@@ -1349,6 +1621,129 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1349
1621
  error: error.message
1350
1622
  });
1351
1623
  }
1624
+
1625
+ if (callbackConfig && shouldDeliverAgentCallback(callbackConfig, terminalEvent)) {
1626
+ const callbackError = terminalEvent === 'aborted'
1627
+ ? { message: 'Session aborted' }
1628
+ : { message: error.message };
1629
+
1630
+ const payload = buildAgentCallbackPayload({
1631
+ event: terminalEvent,
1632
+ eventId: createAgentCallbackEventId(),
1633
+ sessionId: callbackSessionId,
1634
+ provider,
1635
+ projectPath: finalProjectPath,
1636
+ isResumed: !!normalizedSessionId,
1637
+ startedAt,
1638
+ finishedAt: new Date().toISOString(),
1639
+ result: callbackResult,
1640
+ error: callbackError
1641
+ });
1642
+
1643
+ void scheduleAgentCallbackDelivery({
1644
+ callback: callbackConfig,
1645
+ payload
1646
+ });
1647
+ }
1648
+ }
1649
+ });
1650
+
1651
+ /**
1652
+ * POST /api/agent/abort
1653
+ *
1654
+ * Interrupt an active AI agent session.
1655
+ *
1656
+ * ================================================================================================
1657
+ * REQUEST BODY PARAMETERS
1658
+ * ================================================================================================
1659
+ *
1660
+ * @param {string} sessionId - (Required) Session ID to interrupt.
1661
+ * @param {string} provider - (Optional) AI provider for the active session.
1662
+ * Options: 'claude' | 'codex' | 'gemini' | 'opencode'
1663
+ * Default: 'claude'
1664
+ *
1665
+ * ================================================================================================
1666
+ * VALIDATION & ERROR HANDLING
1667
+ * ================================================================================================
1668
+ *
1669
+ * Input Validations (400 Bad Request):
1670
+ * - sessionId must be a non-empty string
1671
+ * - provider must be 'claude', 'codex', 'gemini', or 'opencode' when provided
1672
+ *
1673
+ * Success Response (200 OK):
1674
+ * {
1675
+ * success: true,
1676
+ * aborted: true,
1677
+ * sessionId: "session-123",
1678
+ * provider: "claude",
1679
+ * message: "Session aborted"
1680
+ * }
1681
+ *
1682
+ * Not Found Response (200 OK):
1683
+ * {
1684
+ * success: false,
1685
+ * aborted: false,
1686
+ * sessionId: "session-123",
1687
+ * provider: "claude",
1688
+ * error: "Active session not found"
1689
+ * }
1690
+ *
1691
+ * Error Response:
1692
+ * HTTP Status: 400, 401, 500
1693
+ * Content-Type: application/json
1694
+ * { success: false, error: "Error description" }
1695
+ */
1696
+ router.post('/abort', validateExternalApiKey, async (req, res) => {
1697
+ const normalizedSessionId = typeof req.body.sessionId === 'string' ? req.body.sessionId.trim() : '';
1698
+ const provider = typeof req.body.provider === 'string' && req.body.provider.trim()
1699
+ ? req.body.provider.trim().toLowerCase()
1700
+ : 'claude';
1701
+
1702
+ if (!normalizedSessionId) {
1703
+ return res.status(400).json({
1704
+ success: false,
1705
+ error: 'sessionId is required'
1706
+ });
1707
+ }
1708
+
1709
+ if (!isAbortableAgentProvider(provider)) {
1710
+ return res.status(400).json({
1711
+ success: false,
1712
+ error: `provider must be one of: ${ABORTABLE_AGENT_PROVIDERS.join(', ')}`
1713
+ });
1714
+ }
1715
+
1716
+ try {
1717
+ const writer = new SessionEventMirrorWriter(new NoopWriter(), provider);
1718
+ const { success } = await abortAgentSessionWithWriter({
1719
+ provider,
1720
+ sessionId: normalizedSessionId,
1721
+ writer
1722
+ });
1723
+
1724
+ if (!success) {
1725
+ return res.json({
1726
+ success: false,
1727
+ aborted: false,
1728
+ sessionId: normalizedSessionId,
1729
+ provider,
1730
+ error: 'Active session not found'
1731
+ });
1732
+ }
1733
+
1734
+ return res.json({
1735
+ success: true,
1736
+ aborted: true,
1737
+ sessionId: normalizedSessionId,
1738
+ provider,
1739
+ message: 'Session aborted'
1740
+ });
1741
+ } catch (error) {
1742
+ console.error('❌ External abort session error:', error);
1743
+ return res.status(500).json({
1744
+ success: false,
1745
+ error: error.message
1746
+ });
1352
1747
  }
1353
1748
  });
1354
1749
 
@@ -1,6 +1,6 @@
1
1
  import express from 'express';
2
2
  import bcrypt from 'bcrypt';
3
- import { userDb, db } from '../database/db.js';
3
+ import { userDb } from '../database/db.js';
4
4
  import { generateToken, authenticateToken } from '../middleware/auth.js';
5
5
 
6
6
  const router = express.Router();
@@ -33,45 +33,23 @@ router.post('/register', async (req, res) => {
33
33
  return res.status(400).json({ error: 'Username must be at least 3 characters, password at least 6 characters' });
34
34
  }
35
35
 
36
- // Use a transaction to prevent race conditions
37
- db.prepare('BEGIN').run();
38
- try {
39
- // Check if users already exist (only allow one user)
40
- const hasUsers = userDb.hasUsers();
41
- if (hasUsers) {
42
- db.prepare('ROLLBACK').run();
43
- return res.status(403).json({ error: 'User already exists. This is a single-user system.' });
44
- }
45
-
46
- // Hash password
47
- const saltRounds = 12;
48
- const passwordHash = await bcrypt.hash(password, saltRounds);
49
-
50
- // Create user
51
- const user = userDb.createUser(username, passwordHash);
52
-
53
- // Generate token
54
- const token = generateToken(user);
55
-
56
- // Update last login
57
- userDb.updateLastLogin(user.id);
36
+ const saltRounds = 12;
37
+ const passwordHash = await bcrypt.hash(password, saltRounds);
38
+ const user = userDb.registerUser(username, passwordHash);
39
+ const token = generateToken(user);
58
40
 
59
- db.prepare('COMMIT').run();
60
-
61
- res.json({
62
- success: true,
63
- user: { id: user.id, username: user.username },
64
- token
65
- });
66
- } catch (error) {
67
- db.prepare('ROLLBACK').run();
68
- throw error;
69
- }
41
+ res.json({
42
+ success: true,
43
+ user: { id: user.id, username: user.username },
44
+ token
45
+ });
70
46
 
71
47
  } catch (error) {
72
48
  console.error('Registration error:', error);
73
- if (error.code === 'SQLITE_CONSTRAINT_UNIQUE') {
49
+ if (error.code === 'USERNAME_EXISTS') {
74
50
  res.status(409).json({ error: 'Username already exists' });
51
+ } else if (error.code === 'USER_EXISTS') {
52
+ res.status(403).json({ error: 'User already exists. This is a single-user system.' });
75
53
  } else {
76
54
  res.status(500).json({ error: 'Internal server error' });
77
55
  }
@@ -132,4 +110,4 @@ router.post('/logout', authenticateToken, (req, res) => {
132
110
  res.json({ success: true, message: 'Logged out successfully' });
133
111
  });
134
112
 
135
- export default router;
113
+ export default router;