upfynai-code 2.6.0 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/README.md +123 -88
  2. package/bin/cli.js +63 -0
  3. package/package.json +48 -106
  4. package/src/auth.js +115 -0
  5. package/src/config.js +33 -0
  6. package/src/connect.js +314 -0
  7. package/src/launch.js +54 -0
  8. package/src/mcp.js +57 -0
  9. package/src/server.js +54 -0
  10. package/client/dist/api-docs.html +0 -879
  11. package/client/dist/assets/AppContent-C0CyP3g5.js +0 -513
  12. package/client/dist/assets/CanvasPanel-0u9QR7U-.js +0 -34
  13. package/client/dist/assets/CanvasPanel-WhZulBJw.css +0 -1
  14. package/client/dist/assets/DashboardPanel-Dgqw1yZk.js +0 -1
  15. package/client/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  16. package/client/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  17. package/client/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  18. package/client/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  19. package/client/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  20. package/client/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  21. package/client/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  22. package/client/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  23. package/client/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  24. package/client/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  25. package/client/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  26. package/client/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  27. package/client/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  28. package/client/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  29. package/client/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  30. package/client/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  31. package/client/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  32. package/client/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  33. package/client/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  34. package/client/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  35. package/client/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  36. package/client/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  37. package/client/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  38. package/client/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  39. package/client/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  40. package/client/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  41. package/client/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  42. package/client/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  43. package/client/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  44. package/client/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  45. package/client/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  46. package/client/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  47. package/client/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  48. package/client/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  49. package/client/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  50. package/client/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  51. package/client/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  52. package/client/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  53. package/client/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  54. package/client/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  55. package/client/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  56. package/client/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  57. package/client/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  58. package/client/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  59. package/client/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  60. package/client/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  61. package/client/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  62. package/client/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  63. package/client/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  64. package/client/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  65. package/client/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  66. package/client/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  67. package/client/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  68. package/client/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  69. package/client/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  70. package/client/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  71. package/client/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  72. package/client/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  73. package/client/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  74. package/client/dist/assets/LoginModal-CZDEzqjK.js +0 -19
  75. package/client/dist/assets/MarkdownPreview-CYdvwJaV.js +0 -1
  76. package/client/dist/assets/Onboarding-DR6NZ4Vz.js +0 -1
  77. package/client/dist/assets/SetupForm-D49gtWY4.js +0 -1
  78. package/client/dist/assets/Tableau10-B-NsZVaP.js +0 -1
  79. package/client/dist/assets/WorkflowsPanel-CqlbEJA_.js +0 -1
  80. package/client/dist/assets/_commonjs-dynamic-modules-TDtrdbi3.js +0 -1
  81. package/client/dist/assets/ar-SA-G6X2FPQ2-BWqa1yBH.js +0 -10
  82. package/client/dist/assets/arc-BegSKqEW.js +0 -1
  83. package/client/dist/assets/array-BKyUJesY.js +0 -1
  84. package/client/dist/assets/az-AZ-76LH7QW2-DrVlbZDP.js +0 -1
  85. package/client/dist/assets/bg-BG-XCXSNQG7-DdunjBgT.js +0 -5
  86. package/client/dist/assets/blockDiagram-38ab4fdb-BKMbwGHu.js +0 -118
  87. package/client/dist/assets/bn-BD-2XOGV67Q-_7DtmvwO.js +0 -5
  88. package/client/dist/assets/c4Diagram-3d4e48cf-hJuiHhSn.js +0 -10
  89. package/client/dist/assets/ca-ES-6MX7JW3Y-BFIrmojG.js +0 -8
  90. package/client/dist/assets/channel-Bur-rRTp.js +0 -1
  91. package/client/dist/assets/classDiagram-70f12bd4-BjiAf9cM.js +0 -2
  92. package/client/dist/assets/classDiagram-v2-f2320105-pwBewejc.js +0 -2
  93. package/client/dist/assets/clone-BtqXeoBJ.js +0 -1
  94. package/client/dist/assets/createText-2e5e7dd3-Dq_acOWe.js +0 -5
  95. package/client/dist/assets/cs-CZ-2BRQDIVT-B-x4F6TJ.js +0 -11
  96. package/client/dist/assets/da-DK-5WZEPLOC-Btlc8Dgn.js +0 -5
  97. package/client/dist/assets/de-DE-XR44H4JA-BVu3ZIoD.js +0 -8
  98. package/client/dist/assets/directory-open-01563666-DWU9wJ6I.js +0 -1
  99. package/client/dist/assets/directory-open-4ed118d0-CunoC1EB.js +0 -1
  100. package/client/dist/assets/edges-e0da2a9e-DH0wVTXR.js +0 -4
  101. package/client/dist/assets/el-GR-BZB4AONW-h2ll8_ZC.js +0 -10
  102. package/client/dist/assets/erDiagram-9861fffd-BYezLIR7.js +0 -51
  103. package/client/dist/assets/es-ES-U4NZUMDT-Cveiulwt.js +0 -9
  104. package/client/dist/assets/eu-ES-A7QVB2H4-DQluL2PY.js +0 -11
  105. package/client/dist/assets/fa-IR-HGAKTJCU-BJtcMBSv.js +0 -8
  106. package/client/dist/assets/fi-FI-Z5N7JZ37-D8NfbVXV.js +0 -6
  107. package/client/dist/assets/file-open-002ab408-DIuFHtCF.js +0 -1
  108. package/client/dist/assets/file-open-7c801643-684qeFg4.js +0 -1
  109. package/client/dist/assets/file-save-3189631c-C1wFhQhH.js +0 -1
  110. package/client/dist/assets/file-save-745eba88-Bb9F9Kg7.js +0 -1
  111. package/client/dist/assets/flowDb-956e92f1-scnUykhM.js +0 -10
  112. package/client/dist/assets/flowDiagram-66a62f08-jVyWsfyU.js +0 -4
  113. package/client/dist/assets/flowDiagram-v2-96b9c2cf-N6xgi25h.js +0 -1
  114. package/client/dist/assets/flowchart-elk-definition-4a651766-gKGX3HqR.js +0 -139
  115. package/client/dist/assets/fr-FR-RHASNOE6-vdj42kC6.js +0 -9
  116. package/client/dist/assets/ganttDiagram-c361ad54-C2CiWFUP.js +0 -257
  117. package/client/dist/assets/gitGraphDiagram-72cf32ee-C59Yz2LK.js +0 -70
  118. package/client/dist/assets/gl-ES-HMX3MZ6V-DQo0TzoP.js +0 -10
  119. package/client/dist/assets/graph-Dx_H43Kv.js +0 -1
  120. package/client/dist/assets/he-IL-6SHJWFNN-DKXK5e33.js +0 -10
  121. package/client/dist/assets/hi-IN-IWLTKZ5I-C2Qgqc0R.js +0 -4
  122. package/client/dist/assets/hu-HU-A5ZG7DT2-Ss-6vX0m.js +0 -7
  123. package/client/dist/assets/id-ID-SAP4L64H-D7Wsg1S2.js +0 -10
  124. package/client/dist/assets/image-blob-reduce.esm-D6s-rqMO.js +0 -7
  125. package/client/dist/assets/index-3862675e-u8Nv7hHC.js +0 -1
  126. package/client/dist/assets/index-BVowJdZF.js +0 -97
  127. package/client/dist/assets/index-ce18TYkg.js +0 -27
  128. package/client/dist/assets/index-kQoJx-bc.css +0 -1
  129. package/client/dist/assets/infoDiagram-f8f76790-LmoJYsxo.js +0 -7
  130. package/client/dist/assets/init-Gi6I4Gst.js +0 -1
  131. package/client/dist/assets/it-IT-JPQ66NNP-CAPTVl7M.js +0 -11
  132. package/client/dist/assets/ja-JP-DBVTYXUO-eNVPawR2.js +0 -8
  133. package/client/dist/assets/journeyDiagram-49397b02-BaJqehpR.js +0 -139
  134. package/client/dist/assets/kaa-6HZHGXH3-tpuNkKhS.js +0 -1
  135. package/client/dist/assets/kab-KAB-ZGHBKWFO-Dp83kx4x.js +0 -8
  136. package/client/dist/assets/kk-KZ-P5N5QNE5-B9IlC6YN.js +0 -1
  137. package/client/dist/assets/km-KH-HSX4SM5Z-B_KMYaMj.js +0 -11
  138. package/client/dist/assets/ko-KR-MTYHY66A-yebnUNdb.js +0 -9
  139. package/client/dist/assets/ku-TR-6OUDTVRD-BR6fh6-5.js +0 -9
  140. package/client/dist/assets/layout-DLl5Jwcl.js +0 -1
  141. package/client/dist/assets/line-FpB7omSK.js +0 -1
  142. package/client/dist/assets/linear-CkXqUFJ8.js +0 -1
  143. package/client/dist/assets/lt-LT-XHIRWOB4-SutZSWtR.js +0 -3
  144. package/client/dist/assets/lv-LV-5QDEKY6T-DuAxdcZL.js +0 -7
  145. package/client/dist/assets/mindmap-definition-fc14e90a-DyxXOExh.js +0 -425
  146. package/client/dist/assets/mr-IN-CRQNXWMA-DqDUWM_8.js +0 -13
  147. package/client/dist/assets/my-MM-5M5IBNSE-C40kMFMR.js +0 -1
  148. package/client/dist/assets/nb-NO-T6EIAALU-DVij32Ju.js +0 -10
  149. package/client/dist/assets/nl-NL-IS3SIHDZ-rT84mDYq.js +0 -8
  150. package/client/dist/assets/nn-NO-6E72VCQL-BBZXBW8V.js +0 -8
  151. package/client/dist/assets/oc-FR-POXYY2M6-DzjOugOf.js +0 -8
  152. package/client/dist/assets/ordinal-Cboi1Yqb.js +0 -1
  153. package/client/dist/assets/pa-IN-N4M65BXN-DD1iU8_F.js +0 -4
  154. package/client/dist/assets/path-CbwjOpE9.js +0 -1
  155. package/client/dist/assets/pdf-CE_K4jFx.js +0 -12
  156. package/client/dist/assets/pdf.worker-BA9kU3Pw.mjs +0 -61080
  157. package/client/dist/assets/percentages-BXMCSKIN-WVlHS4wx.js +0 -207
  158. package/client/dist/assets/pica-CQIY57Tf.js +0 -7
  159. package/client/dist/assets/pieDiagram-8a3498a8-Dd_85qBH.js +0 -35
  160. package/client/dist/assets/pl-PL-T2D74RX3-ukVXa48G.js +0 -9
  161. package/client/dist/assets/pt-BR-5N22H2LF-BibawarT.js +0 -9
  162. package/client/dist/assets/pt-PT-UZXXM6DQ-So3i9l9w.js +0 -9
  163. package/client/dist/assets/quadrantDiagram-120e2f19-C4dFVDEx.js +0 -7
  164. package/client/dist/assets/requirementDiagram-deff3bca-DrTO7yFl.js +0 -52
  165. package/client/dist/assets/ro-RO-JPDTUUEW-DY0Xq_Hd.js +0 -11
  166. package/client/dist/assets/roundRect-0PYZxl1G.js +0 -1
  167. package/client/dist/assets/ru-RU-B4JR7IUQ-B7u_Zvkd.js +0 -9
  168. package/client/dist/assets/sankeyDiagram-04a897e0-D24gfzuS.js +0 -8
  169. package/client/dist/assets/sequenceDiagram-704730f1-Dgji2XLQ.js +0 -122
  170. package/client/dist/assets/si-LK-N5RQ5JYF-OejsLzQ_.js +0 -1
  171. package/client/dist/assets/sk-SK-C5VTKIMK-_vy2Bt-M.js +0 -6
  172. package/client/dist/assets/sl-SI-NN7IZMDC-DKOl_u2M.js +0 -6
  173. package/client/dist/assets/stateDiagram-587899a1-CJ8eBaiU.js +0 -1
  174. package/client/dist/assets/stateDiagram-v2-d93cdb3a-C5K3l-Nt.js +0 -1
  175. package/client/dist/assets/styles-6aaf32cf-DAKE0jbx.js +0 -207
  176. package/client/dist/assets/styles-9a916d00-LFAJCgEy.js +0 -160
  177. package/client/dist/assets/styles-c10674c1-CllKO8NG.js +0 -116
  178. package/client/dist/assets/subset-shared.chunk-Uy-J87FQ.js +0 -84
  179. package/client/dist/assets/subset-worker.chunk-dvgDvqt9.js +0 -1
  180. package/client/dist/assets/sv-SE-XGPEYMSR-CDCB2ZV5.js +0 -10
  181. package/client/dist/assets/svgDrawCommon-08f97a94-CObOzbFQ.js +0 -1
  182. package/client/dist/assets/ta-IN-2NMHFXQM-DHUNdO69.js +0 -9
  183. package/client/dist/assets/th-TH-HPSO5L25-zI2hnBq3.js +0 -2
  184. package/client/dist/assets/timeline-definition-85554ec2-C2XHRmxK.js +0 -61
  185. package/client/dist/assets/tr-TR-DEFEU3FU-l-6Hu4-D.js +0 -7
  186. package/client/dist/assets/uk-UA-QMV73CPH-CqSOwrl7.js +0 -6
  187. package/client/dist/assets/vendor-codemirror-D_s0aGBu.js +0 -35
  188. package/client/dist/assets/vendor-i18n-DCFGyhQR.js +0 -1
  189. package/client/dist/assets/vendor-icons-Lb69KSFJ.js +0 -646
  190. package/client/dist/assets/vendor-markdown-BXEi_H3G.js +0 -298
  191. package/client/dist/assets/vendor-react-9mUTKBHH.js +0 -67
  192. package/client/dist/assets/vendor-syntax-DnmwQQJF.js +0 -16
  193. package/client/dist/assets/vendor-xterm-CZq1hqo1.js +0 -66
  194. package/client/dist/assets/vendor-xterm-qxJ8_QYu.css +0 -32
  195. package/client/dist/assets/vi-VN-M7AON7JQ-CUL8-mBZ.js +0 -5
  196. package/client/dist/assets/xychartDiagram-e933f94c-1fmf6slj.js +0 -7
  197. package/client/dist/assets/zh-CN-LNUGB5OW-CB5y5VVU.js +0 -10
  198. package/client/dist/assets/zh-HK-E62DVLB3-BHcrrEeJ.js +0 -1
  199. package/client/dist/assets/zh-TW-RAJ6MFWO-DoDUdkaJ.js +0 -9
  200. package/client/dist/clear-cache.html +0 -85
  201. package/client/dist/convert-icons.md +0 -53
  202. package/client/dist/favicon.png +0 -0
  203. package/client/dist/favicon.svg +0 -9
  204. package/client/dist/generate-icons.js +0 -49
  205. package/client/dist/icons/claude-ai-icon.svg +0 -1
  206. package/client/dist/icons/codex-white.svg +0 -3
  207. package/client/dist/icons/codex.svg +0 -3
  208. package/client/dist/icons/cursor-white.svg +0 -12
  209. package/client/dist/icons/cursor.svg +0 -1
  210. package/client/dist/icons/icon-128x128.png +0 -0
  211. package/client/dist/icons/icon-128x128.svg +0 -12
  212. package/client/dist/icons/icon-144x144.png +0 -0
  213. package/client/dist/icons/icon-144x144.svg +0 -12
  214. package/client/dist/icons/icon-152x152.png +0 -0
  215. package/client/dist/icons/icon-152x152.svg +0 -12
  216. package/client/dist/icons/icon-192x192.png +0 -0
  217. package/client/dist/icons/icon-192x192.svg +0 -12
  218. package/client/dist/icons/icon-384x384.png +0 -0
  219. package/client/dist/icons/icon-384x384.svg +0 -12
  220. package/client/dist/icons/icon-512x512.png +0 -0
  221. package/client/dist/icons/icon-512x512.svg +0 -12
  222. package/client/dist/icons/icon-72x72.png +0 -0
  223. package/client/dist/icons/icon-72x72.svg +0 -12
  224. package/client/dist/icons/icon-96x96.png +0 -0
  225. package/client/dist/icons/icon-96x96.svg +0 -12
  226. package/client/dist/icons/icon-template.svg +0 -12
  227. package/client/dist/index.html +0 -128
  228. package/client/dist/logo-128.png +0 -0
  229. package/client/dist/logo-256.png +0 -0
  230. package/client/dist/logo-32.png +0 -0
  231. package/client/dist/logo-512.png +0 -0
  232. package/client/dist/logo-64.png +0 -0
  233. package/client/dist/logo.svg +0 -17
  234. package/client/dist/manifest.json +0 -61
  235. package/client/dist/mcp-docs.html +0 -119
  236. package/client/dist/screenshots/cli-selection.png +0 -0
  237. package/client/dist/screenshots/desktop-main.png +0 -0
  238. package/client/dist/screenshots/mobile-chat.png +0 -0
  239. package/client/dist/screenshots/tools-modal.png +0 -0
  240. package/client/dist/sw.js +0 -19
  241. package/commands/upfynai-connect.md +0 -59
  242. package/commands/upfynai-disconnect.md +0 -31
  243. package/commands/upfynai-doctor.md +0 -99
  244. package/commands/upfynai-export.md +0 -49
  245. package/commands/upfynai-local.md +0 -82
  246. package/commands/upfynai-status.md +0 -75
  247. package/commands/upfynai-stop.md +0 -49
  248. package/commands/upfynai-uninstall.md +0 -58
  249. package/commands/upfynai.md +0 -69
  250. package/scripts/build-client.js +0 -17
  251. package/scripts/fix-node-pty.js +0 -67
  252. package/scripts/install-commands.js +0 -78
  253. package/server/claude-sdk.js +0 -714
  254. package/server/cli-ui.js +0 -785
  255. package/server/cli.js +0 -596
  256. package/server/constants/config.js +0 -31
  257. package/server/cursor-cli.js +0 -270
  258. package/server/database/auth.db +0 -0
  259. package/server/database/db.js +0 -822
  260. package/server/database/init.sql +0 -70
  261. package/server/index.js +0 -2738
  262. package/server/load-env.js +0 -26
  263. package/server/mcp-server.js +0 -621
  264. package/server/middleware/auth.js +0 -181
  265. package/server/openai-codex.js +0 -403
  266. package/server/openrouter.js +0 -137
  267. package/server/projects.js +0 -1742
  268. package/server/relay-client.js +0 -672
  269. package/server/routes/agent.js +0 -1226
  270. package/server/routes/auth.js +0 -266
  271. package/server/routes/cli-auth.js +0 -263
  272. package/server/routes/codex.js +0 -344
  273. package/server/routes/commands.js +0 -598
  274. package/server/routes/cursor.js +0 -807
  275. package/server/routes/dashboard.js +0 -205
  276. package/server/routes/git.js +0 -1151
  277. package/server/routes/mcp-utils.js +0 -48
  278. package/server/routes/mcp.js +0 -535
  279. package/server/routes/payments.js +0 -172
  280. package/server/routes/projects.js +0 -552
  281. package/server/routes/settings.js +0 -261
  282. package/server/routes/taskmaster.js +0 -1928
  283. package/server/routes/user.js +0 -106
  284. package/server/routes/vapi-chat.js +0 -94
  285. package/server/routes/voice.js +0 -194
  286. package/server/routes/webhooks.js +0 -166
  287. package/server/routes/workflows.js +0 -118
  288. package/server/sandbox.js +0 -120
  289. package/server/services/whisperService.js +0 -84
  290. package/server/services/workflowScheduler.js +0 -186
  291. package/server/utils/commandParser.js +0 -303
  292. package/server/utils/gitConfig.js +0 -24
  293. package/server/utils/mcp-detector.js +0 -198
  294. package/server/utils/taskmaster-websocket.js +0 -129
  295. package/shared/modelConstants.js +0 -96
@@ -1,714 +0,0 @@
1
- /**
2
- * Claude SDK Integration
3
- *
4
- * This module provides SDK-based integration with Claude using the @anthropic-ai/claude-agent-sdk.
5
- * It mirrors the interface of claude-cli.js but uses the SDK internally for better performance
6
- * and maintainability.
7
- *
8
- * Key features:
9
- * - Direct SDK integration without child processes
10
- * - Session management with abort capability
11
- * - Options mapping between CLI and SDK formats
12
- * - WebSocket message streaming
13
- */
14
-
15
- import { query } from '@anthropic-ai/claude-agent-sdk';
16
- import crypto from 'crypto';
17
- import { promises as fs } from 'fs';
18
- import path from 'path';
19
- import os from 'os';
20
- import { CLAUDE_MODELS } from '../shared/modelConstants.js';
21
-
22
- const activeSessions = new Map();
23
- const pendingToolApprovals = new Map();
24
-
25
- const TOOL_APPROVAL_TIMEOUT_MS = parseInt(process.env.CLAUDE_TOOL_APPROVAL_TIMEOUT_MS, 10) || 55000;
26
-
27
- const TOOLS_REQUIRING_INTERACTION = new Set(['AskUserQuestion']);
28
-
29
- function createRequestId() {
30
- if (typeof crypto.randomUUID === 'function') {
31
- return crypto.randomUUID();
32
- }
33
- return crypto.randomBytes(16).toString('hex');
34
- }
35
-
36
- function waitForToolApproval(requestId, options = {}) {
37
- const { timeoutMs = TOOL_APPROVAL_TIMEOUT_MS, signal, onCancel } = options;
38
-
39
- return new Promise(resolve => {
40
- let settled = false;
41
-
42
- const finalize = (decision) => {
43
- if (settled) return;
44
- settled = true;
45
- cleanup();
46
- resolve(decision);
47
- };
48
-
49
- let timeout;
50
-
51
- const cleanup = () => {
52
- pendingToolApprovals.delete(requestId);
53
- if (timeout) clearTimeout(timeout);
54
- if (signal && abortHandler) {
55
- signal.removeEventListener('abort', abortHandler);
56
- }
57
- };
58
-
59
- // timeoutMs 0 = wait indefinitely (interactive tools)
60
- if (timeoutMs > 0) {
61
- timeout = setTimeout(() => {
62
- onCancel?.('timeout');
63
- finalize(null);
64
- }, timeoutMs);
65
- }
66
-
67
- const abortHandler = () => {
68
- onCancel?.('cancelled');
69
- finalize({ cancelled: true });
70
- };
71
-
72
- if (signal) {
73
- if (signal.aborted) {
74
- onCancel?.('cancelled');
75
- finalize({ cancelled: true });
76
- return;
77
- }
78
- signal.addEventListener('abort', abortHandler, { once: true });
79
- }
80
-
81
- pendingToolApprovals.set(requestId, (decision) => {
82
- finalize(decision);
83
- });
84
- });
85
- }
86
-
87
- function resolveToolApproval(requestId, decision) {
88
- const resolver = pendingToolApprovals.get(requestId);
89
- if (resolver) {
90
- resolver(decision);
91
- }
92
- }
93
-
94
- // Match stored permission entries against a tool + input combo.
95
- // This only supports exact tool names and the Bash(command:*) shorthand
96
- // used by the UI; it intentionally does not implement full glob semantics,
97
- // introduced to stay consistent with the UI's "Allow rule" format.
98
- function matchesToolPermission(entry, toolName, input) {
99
- if (!entry || !toolName) {
100
- return false;
101
- }
102
-
103
- if (entry === toolName) {
104
- return true;
105
- }
106
-
107
- const bashMatch = entry.match(/^Bash\((.+):\*\)$/);
108
- if (toolName === 'Bash' && bashMatch) {
109
- const allowedPrefix = bashMatch[1];
110
- let command = '';
111
-
112
- if (typeof input === 'string') {
113
- command = input.trim();
114
- } else if (input && typeof input === 'object' && typeof input.command === 'string') {
115
- command = input.command.trim();
116
- }
117
-
118
- if (!command) {
119
- return false;
120
- }
121
-
122
- return command.startsWith(allowedPrefix);
123
- }
124
-
125
- return false;
126
- }
127
-
128
- /**
129
- * Maps CLI options to SDK-compatible options format
130
- * @param {Object} options - CLI options
131
- * @returns {Object} SDK-compatible options
132
- */
133
- function mapCliOptionsToSDK(options = {}) {
134
- const { sessionId, cwd, toolsSettings, permissionMode, images } = options;
135
-
136
- const sdkOptions = {};
137
-
138
- // Map working directory
139
- if (cwd) {
140
- sdkOptions.cwd = cwd;
141
- }
142
-
143
- // Map permission mode
144
- if (permissionMode && permissionMode !== 'default') {
145
- sdkOptions.permissionMode = permissionMode;
146
- }
147
-
148
- // Map tool settings
149
- const settings = toolsSettings || {
150
- allowedTools: [],
151
- disallowedTools: [],
152
- skipPermissions: false
153
- };
154
-
155
- // Handle tool permissions
156
- if (settings.skipPermissions && permissionMode !== 'plan') {
157
- // When skipping permissions, use bypassPermissions mode
158
- sdkOptions.permissionMode = 'bypassPermissions';
159
- }
160
-
161
- let allowedTools = [...(settings.allowedTools || [])];
162
-
163
- // Add plan mode default tools
164
- if (permissionMode === 'plan') {
165
- const planModeTools = ['Read', 'Task', 'exit_plan_mode', 'TodoRead', 'TodoWrite', 'WebFetch', 'WebSearch'];
166
- for (const tool of planModeTools) {
167
- if (!allowedTools.includes(tool)) {
168
- allowedTools.push(tool);
169
- }
170
- }
171
- }
172
-
173
- sdkOptions.allowedTools = allowedTools;
174
-
175
- // Use the tools preset to make all default built-in tools available (including AskUserQuestion).
176
- // This was introduced in SDK 0.1.57. Omitting this preserves existing behavior (all tools available),
177
- // but being explicit ensures forward compatibility and clarity.
178
- sdkOptions.tools = { type: 'preset', preset: 'claude_code' };
179
-
180
- sdkOptions.disallowedTools = settings.disallowedTools || [];
181
-
182
- // Map model (default to sonnet)
183
- // Valid models: sonnet, opus, haiku, opusplan, sonnet[1m]
184
- sdkOptions.model = options.model || CLAUDE_MODELS.DEFAULT;
185
- // model selected
186
-
187
- // Map system prompt configuration
188
- sdkOptions.systemPrompt = {
189
- type: 'preset',
190
- preset: 'claude_code' // Required to use CLAUDE.md
191
- };
192
-
193
- // Map setting sources for CLAUDE.md loading
194
- // This loads CLAUDE.md from project, user (~/.config/claude/CLAUDE.md), and local directories
195
- sdkOptions.settingSources = ['project', 'user', 'local'];
196
-
197
- // Map resume session
198
- if (sessionId) {
199
- sdkOptions.resume = sessionId;
200
- }
201
-
202
- return sdkOptions;
203
- }
204
-
205
- /**
206
- * Adds a session to the active sessions map
207
- * @param {string} sessionId - Session identifier
208
- * @param {Object} queryInstance - SDK query instance
209
- * @param {Array<string>} tempImagePaths - Temp image file paths for cleanup
210
- * @param {string} tempDir - Temp directory for cleanup
211
- */
212
- function addSession(sessionId, queryInstance, tempImagePaths = [], tempDir = null) {
213
- activeSessions.set(sessionId, {
214
- instance: queryInstance,
215
- startTime: Date.now(),
216
- status: 'active',
217
- tempImagePaths,
218
- tempDir
219
- });
220
- }
221
-
222
- /**
223
- * Removes a session from the active sessions map
224
- * @param {string} sessionId - Session identifier
225
- */
226
- function removeSession(sessionId) {
227
- activeSessions.delete(sessionId);
228
- }
229
-
230
- /**
231
- * Gets a session from the active sessions map
232
- * @param {string} sessionId - Session identifier
233
- * @returns {Object|undefined} Session data or undefined
234
- */
235
- function getSession(sessionId) {
236
- return activeSessions.get(sessionId);
237
- }
238
-
239
- /**
240
- * Gets all active session IDs
241
- * @returns {Array<string>} Array of active session IDs
242
- */
243
- function getAllSessions() {
244
- return Array.from(activeSessions.keys());
245
- }
246
-
247
- /**
248
- * Transforms SDK messages to WebSocket format expected by frontend
249
- * @param {Object} sdkMessage - SDK message object
250
- * @returns {Object} Transformed message ready for WebSocket
251
- */
252
- function transformMessage(sdkMessage) {
253
- // Extract parent_tool_use_id for subagent tool grouping
254
- if (sdkMessage.parent_tool_use_id) {
255
- return {
256
- ...sdkMessage,
257
- parentToolUseId: sdkMessage.parent_tool_use_id
258
- };
259
- }
260
- return sdkMessage;
261
- }
262
-
263
- /**
264
- * Extracts token usage from SDK result messages
265
- * @param {Object} resultMessage - SDK result message
266
- * @returns {Object|null} Token budget object or null
267
- */
268
- function extractTokenBudget(resultMessage) {
269
- if (resultMessage.type !== 'result' || !resultMessage.modelUsage) {
270
- return null;
271
- }
272
-
273
- // Get the first model's usage data
274
- const modelKey = Object.keys(resultMessage.modelUsage)[0];
275
- const modelData = resultMessage.modelUsage[modelKey];
276
-
277
- if (!modelData) {
278
- return null;
279
- }
280
-
281
- // Use cumulative tokens if available (tracks total for the session)
282
- // Otherwise fall back to per-request tokens
283
- const inputTokens = modelData.cumulativeInputTokens || modelData.inputTokens || 0;
284
- const outputTokens = modelData.cumulativeOutputTokens || modelData.outputTokens || 0;
285
- const cacheReadTokens = modelData.cumulativeCacheReadInputTokens || modelData.cacheReadInputTokens || 0;
286
- const cacheCreationTokens = modelData.cumulativeCacheCreationInputTokens || modelData.cacheCreationInputTokens || 0;
287
-
288
- // Total used = input + output + cache tokens
289
- const totalUsed = inputTokens + outputTokens + cacheReadTokens + cacheCreationTokens;
290
-
291
- // Use configured context window budget from environment (default 160000)
292
- // This is the user's budget limit, not the model's context window
293
- const contextWindow = parseInt(process.env.CONTEXT_WINDOW) || 160000;
294
-
295
- // token calculation done
296
-
297
- return {
298
- used: totalUsed,
299
- total: contextWindow
300
- };
301
- }
302
-
303
- /**
304
- * Handles image processing for SDK queries
305
- * Saves base64 images to temporary files and returns modified prompt with file paths
306
- * @param {string} command - Original user prompt
307
- * @param {Array} images - Array of image objects with base64 data
308
- * @param {string} cwd - Working directory for temp file creation
309
- * @returns {Promise<Object>} {modifiedCommand, tempImagePaths, tempDir}
310
- */
311
- async function handleImages(command, images, cwd) {
312
- const tempImagePaths = [];
313
- let tempDir = null;
314
-
315
- if (!images || images.length === 0) {
316
- return { modifiedCommand: command, tempImagePaths, tempDir };
317
- }
318
-
319
- try {
320
- // Create temp directory in the project directory
321
- const workingDir = cwd || process.cwd();
322
- tempDir = path.join(workingDir, '.tmp', 'images', Date.now().toString());
323
- await fs.mkdir(tempDir, { recursive: true });
324
-
325
- // Save each image to a temp file
326
- for (const [index, image] of images.entries()) {
327
- // Extract base64 data and mime type
328
- const matches = image.data.match(/^data:([^;]+);base64,(.+)$/);
329
- if (!matches) {
330
- // invalid image format
331
- continue;
332
- }
333
-
334
- const [, mimeType, base64Data] = matches;
335
- const extension = mimeType.split('/')[1] || 'png';
336
- const filename = `image_${index}.${extension}`;
337
- const filepath = path.join(tempDir, filename);
338
-
339
- // Write base64 data to file
340
- await fs.writeFile(filepath, Buffer.from(base64Data, 'base64'));
341
- tempImagePaths.push(filepath);
342
- }
343
-
344
- // Include the full image paths in the prompt
345
- let modifiedCommand = command;
346
- if (tempImagePaths.length > 0 && command && command.trim()) {
347
- const imageNote = `\n\n[Images provided at the following paths:]\n${tempImagePaths.map((p, i) => `${i + 1}. ${p}`).join('\n')}`;
348
- modifiedCommand = command + imageNote;
349
- }
350
-
351
- // images processed
352
- return { modifiedCommand, tempImagePaths, tempDir };
353
- } catch (error) {
354
- // image processing error
355
- return { modifiedCommand: command, tempImagePaths, tempDir };
356
- }
357
- }
358
-
359
- /**
360
- * Cleans up temporary image files
361
- * @param {Array<string>} tempImagePaths - Array of temp file paths to delete
362
- * @param {string} tempDir - Temp directory to remove
363
- */
364
- async function cleanupTempFiles(tempImagePaths, tempDir) {
365
- if (!tempImagePaths || tempImagePaths.length === 0) {
366
- return;
367
- }
368
-
369
- try {
370
- // Delete individual temp files
371
- for (const imagePath of tempImagePaths) {
372
- await fs.unlink(imagePath).catch(() => {});
373
- }
374
-
375
- // Delete temp directory
376
- if (tempDir) {
377
- await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
378
- }
379
-
380
- // temp files cleaned
381
- } catch (error) {
382
- // cleanup error
383
- }
384
- }
385
-
386
- /**
387
- * Loads MCP server configurations from ~/.claude.json
388
- * @param {string} cwd - Current working directory for project-specific configs
389
- * @returns {Object|null} MCP servers object or null if none found
390
- */
391
- async function loadMcpConfig(cwd) {
392
- try {
393
- const claudeConfigPath = path.join(os.homedir(), '.claude.json');
394
-
395
- // Check if config file exists
396
- try {
397
- await fs.access(claudeConfigPath);
398
- } catch (error) {
399
- // File doesn't exist, return null
400
- // no MCP config found
401
- return null;
402
- }
403
-
404
- // Read and parse config file
405
- let claudeConfig;
406
- try {
407
- const configContent = await fs.readFile(claudeConfigPath, 'utf8');
408
- claudeConfig = JSON.parse(configContent);
409
- } catch (error) {
410
- // MCP config parse error
411
- return null;
412
- }
413
-
414
- // Extract MCP servers (merge global and project-specific)
415
- let mcpServers = {};
416
-
417
- // Add global MCP servers
418
- if (claudeConfig.mcpServers && typeof claudeConfig.mcpServers === 'object') {
419
- mcpServers = { ...claudeConfig.mcpServers };
420
- // global MCP servers loaded
421
- }
422
-
423
- // Add/override with project-specific MCP servers
424
- if (claudeConfig.claudeProjects && cwd) {
425
- const projectConfig = claudeConfig.claudeProjects[cwd];
426
- if (projectConfig && projectConfig.mcpServers && typeof projectConfig.mcpServers === 'object') {
427
- mcpServers = { ...mcpServers, ...projectConfig.mcpServers };
428
- // project MCP servers loaded
429
- }
430
- }
431
-
432
- // Return null if no servers found
433
- if (Object.keys(mcpServers).length === 0) {
434
- // no MCP servers configured
435
- return null;
436
- }
437
-
438
- // MCP config loaded
439
- return mcpServers;
440
- } catch (error) {
441
- // MCP config load error
442
- return null;
443
- }
444
- }
445
-
446
- /**
447
- * Executes a Claude query using the SDK
448
- * @param {string} command - User prompt/command
449
- * @param {Object} options - Query options
450
- * @param {Object} ws - WebSocket connection
451
- * @returns {Promise<void>}
452
- */
453
- async function queryClaudeSDK(command, options = {}, ws) {
454
- const { sessionId } = options;
455
- let capturedSessionId = sessionId;
456
- let sessionCreatedSent = false;
457
- let tempImagePaths = [];
458
- let tempDir = null;
459
-
460
- try {
461
- // Map CLI options to SDK format
462
- const sdkOptions = mapCliOptionsToSDK(options);
463
-
464
- // Load MCP configuration
465
- const mcpServers = await loadMcpConfig(options.cwd);
466
- if (mcpServers) {
467
- sdkOptions.mcpServers = mcpServers;
468
- }
469
-
470
- // Handle images - save to temp files and modify prompt
471
- const imageResult = await handleImages(command, options.images, options.cwd);
472
- const finalCommand = imageResult.modifiedCommand;
473
- tempImagePaths = imageResult.tempImagePaths;
474
- tempDir = imageResult.tempDir;
475
-
476
- sdkOptions.canUseTool = async (toolName, input, context) => {
477
- const requiresInteraction = TOOLS_REQUIRING_INTERACTION.has(toolName);
478
-
479
- if (!requiresInteraction) {
480
- if (sdkOptions.permissionMode === 'bypassPermissions') {
481
- return { behavior: 'allow', updatedInput: input };
482
- }
483
-
484
- const isDisallowed = (sdkOptions.disallowedTools || []).some(entry =>
485
- matchesToolPermission(entry, toolName, input)
486
- );
487
- if (isDisallowed) {
488
- return { behavior: 'deny', message: 'Tool disallowed by settings' };
489
- }
490
-
491
- const isAllowed = (sdkOptions.allowedTools || []).some(entry =>
492
- matchesToolPermission(entry, toolName, input)
493
- );
494
- if (isAllowed) {
495
- return { behavior: 'allow', updatedInput: input };
496
- }
497
- }
498
-
499
- const requestId = createRequestId();
500
- ws.send({
501
- type: 'claude-permission-request',
502
- requestId,
503
- toolName,
504
- input,
505
- sessionId: capturedSessionId || sessionId || null
506
- });
507
-
508
- const decision = await waitForToolApproval(requestId, {
509
- timeoutMs: requiresInteraction ? 0 : undefined,
510
- signal: context?.signal,
511
- onCancel: (reason) => {
512
- ws.send({
513
- type: 'claude-permission-cancelled',
514
- requestId,
515
- reason,
516
- sessionId: capturedSessionId || sessionId || null
517
- });
518
- }
519
- });
520
- if (!decision) {
521
- return { behavior: 'deny', message: 'Permission request timed out' };
522
- }
523
-
524
- if (decision.cancelled) {
525
- return { behavior: 'deny', message: 'Permission request cancelled' };
526
- }
527
-
528
- if (decision.allow) {
529
- if (decision.rememberEntry && typeof decision.rememberEntry === 'string') {
530
- if (!sdkOptions.allowedTools.includes(decision.rememberEntry)) {
531
- sdkOptions.allowedTools.push(decision.rememberEntry);
532
- }
533
- if (Array.isArray(sdkOptions.disallowedTools)) {
534
- sdkOptions.disallowedTools = sdkOptions.disallowedTools.filter(entry => entry !== decision.rememberEntry);
535
- }
536
- }
537
- return { behavior: 'allow', updatedInput: decision.updatedInput ?? input };
538
- }
539
-
540
- return { behavior: 'deny', message: decision.message ?? 'User denied tool use' };
541
- };
542
-
543
- // Set stream-close timeout for interactive tools (Query constructor reads it synchronously). Claude Agent SDK has a default of 5s and this overrides it
544
- const prevStreamTimeout = process.env.CLAUDE_CODE_STREAM_CLOSE_TIMEOUT;
545
- process.env.CLAUDE_CODE_STREAM_CLOSE_TIMEOUT = '300000';
546
-
547
- const queryInstance = query({
548
- prompt: finalCommand,
549
- options: sdkOptions
550
- });
551
-
552
- // Restore immediately — Query constructor already captured the value
553
- if (prevStreamTimeout !== undefined) {
554
- process.env.CLAUDE_CODE_STREAM_CLOSE_TIMEOUT = prevStreamTimeout;
555
- } else {
556
- delete process.env.CLAUDE_CODE_STREAM_CLOSE_TIMEOUT;
557
- }
558
-
559
- // Track the query instance for abort capability
560
- if (capturedSessionId) {
561
- addSession(capturedSessionId, queryInstance, tempImagePaths, tempDir);
562
- }
563
-
564
- // Process streaming messages
565
- // streaming session started
566
- for await (const message of queryInstance) {
567
- // Capture session ID from first message
568
- if (message.session_id && !capturedSessionId) {
569
-
570
- capturedSessionId = message.session_id;
571
- addSession(capturedSessionId, queryInstance, tempImagePaths, tempDir);
572
-
573
- // Set session ID on writer
574
- if (ws.setSessionId && typeof ws.setSessionId === 'function') {
575
- ws.setSessionId(capturedSessionId);
576
- }
577
-
578
- // Send session-created event only once for new sessions
579
- if (!sessionId && !sessionCreatedSent) {
580
- sessionCreatedSent = true;
581
- ws.send({
582
- type: 'session-created',
583
- sessionId: capturedSessionId
584
- });
585
- } else {
586
- // session-created already sent
587
- }
588
- } else {
589
- // session_id already captured or missing
590
- }
591
-
592
- // Transform and send message to WebSocket
593
- const transformedMessage = transformMessage(message);
594
- ws.send({
595
- type: 'claude-response',
596
- data: transformedMessage,
597
- sessionId: capturedSessionId || sessionId || null
598
- });
599
-
600
- // Extract and send token budget updates from result messages
601
- if (message.type === 'result') {
602
- const tokenBudget = extractTokenBudget(message);
603
- if (tokenBudget) {
604
- // token budget calculated
605
- ws.send({
606
- type: 'token-budget',
607
- data: tokenBudget,
608
- sessionId: capturedSessionId || sessionId || null
609
- });
610
- }
611
- }
612
- }
613
-
614
- // Clean up session on completion
615
- if (capturedSessionId) {
616
- removeSession(capturedSessionId);
617
- }
618
-
619
- // Clean up temporary image files
620
- await cleanupTempFiles(tempImagePaths, tempDir);
621
-
622
- // Send completion event
623
- // streaming complete
624
- ws.send({
625
- type: 'claude-complete',
626
- sessionId: capturedSessionId,
627
- exitCode: 0,
628
- isNewSession: !sessionId && !!command
629
- });
630
- // complete event sent
631
-
632
- } catch (error) {
633
- // SDK query error occurred
634
-
635
- // Clean up session on error
636
- if (capturedSessionId) {
637
- removeSession(capturedSessionId);
638
- }
639
-
640
- // Clean up temporary image files on error
641
- await cleanupTempFiles(tempImagePaths, tempDir);
642
-
643
- // Send error to WebSocket
644
- ws.send({
645
- type: 'claude-error',
646
- error: error.message,
647
- sessionId: capturedSessionId || sessionId || null
648
- });
649
-
650
- throw error;
651
- }
652
- }
653
-
654
- /**
655
- * Aborts an active SDK session
656
- * @param {string} sessionId - Session identifier
657
- * @returns {boolean} True if session was aborted, false if not found
658
- */
659
- async function abortClaudeSDKSession(sessionId) {
660
- const session = getSession(sessionId);
661
-
662
- if (!session) {
663
- // session not found
664
- return false;
665
- }
666
-
667
- try {
668
- // aborting SDK session
669
-
670
- // Call interrupt() on the query instance
671
- await session.instance.interrupt();
672
-
673
- // Update session status
674
- session.status = 'aborted';
675
-
676
- // Clean up temporary image files
677
- await cleanupTempFiles(session.tempImagePaths, session.tempDir);
678
-
679
- // Clean up session
680
- removeSession(sessionId);
681
-
682
- return true;
683
- } catch (error) {
684
- // abort error occurred
685
- return false;
686
- }
687
- }
688
-
689
- /**
690
- * Checks if an SDK session is currently active
691
- * @param {string} sessionId - Session identifier
692
- * @returns {boolean} True if session is active
693
- */
694
- function isClaudeSDKSessionActive(sessionId) {
695
- const session = getSession(sessionId);
696
- return session && session.status === 'active';
697
- }
698
-
699
- /**
700
- * Gets all active SDK session IDs
701
- * @returns {Array<string>} Array of active session IDs
702
- */
703
- function getActiveClaudeSDKSessions() {
704
- return getAllSessions();
705
- }
706
-
707
- // Export public API
708
- export {
709
- queryClaudeSDK,
710
- abortClaudeSDKSession,
711
- isClaudeSDKSessionActive,
712
- getActiveClaudeSDKSessions,
713
- resolveToolApproval
714
- };