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,181 +0,0 @@
1
- import jwt from 'jsonwebtoken';
2
- import crypto from 'crypto';
3
- import { userDb, relayTokensDb } from '../database/db.js';
4
- import { IS_PLATFORM } from '../constants/config.js';
5
-
6
- let JWT_SECRET = process.env.JWT_SECRET?.trim();
7
- if (!JWT_SECRET) {
8
- if (IS_PLATFORM) {
9
- // In local/self-hosted mode, generate a random secret (auth is bypassed anyway)
10
- JWT_SECRET = crypto.randomBytes(32).toString('hex');
11
- } else {
12
- console.error('[SECURITY] JWT_SECRET environment variable is required. Server cannot start without it.');
13
- process.exit(1);
14
- }
15
- }
16
-
17
- // Optional static API key middleware
18
- const validateApiKey = (req, res, next) => {
19
- if (!process.env.API_KEY) return next();
20
- const apiKey = req.headers['x-api-key'];
21
- if (apiKey !== process.env.API_KEY.trim()) {
22
- return res.status(401).json({ error: 'Invalid API key' });
23
- }
24
- next();
25
- };
26
-
27
- // Extract JWT from request: cookie → Bearer header → query param (SSE only)
28
- const extractToken = (req) => {
29
- // 1. httpOnly cookie (browser sessions — primary auth method)
30
- if (req.cookies?.session) return req.cookies.session;
31
-
32
- // 2. Bearer header (API clients, MCP)
33
- const authHeader = req.headers['authorization'];
34
- if (authHeader?.startsWith('Bearer ')) return authHeader.slice(7);
35
-
36
- // 3. Query param — for GET requests (SSE EventSource + iframe embedding)
37
- if (req.query?.token && req.method === 'GET') {
38
- return req.query.token;
39
- }
40
-
41
- return null;
42
- };
43
-
44
- // JWT authentication middleware
45
- const authenticateToken = async (req, res, next) => {
46
- // Platform mode: use first database user
47
- if (IS_PLATFORM) {
48
- try {
49
- const user = await userDb.getFirstUser();
50
- if (!user) return res.status(500).json({ error: 'Platform mode: No user found in database' });
51
- req.user = user;
52
- return next();
53
- } catch (error) {
54
- console.error('Platform mode error:', error);
55
- return res.status(500).json({ error: 'Platform mode: Failed to fetch user' });
56
- }
57
- }
58
-
59
- const token = extractToken(req);
60
- if (!token) {
61
- return res.status(401).json({ error: 'Access denied. No token provided.' });
62
- }
63
-
64
- try {
65
- const decoded = jwt.verify(token, JWT_SECRET);
66
- const user = await userDb.getUserById(decoded.userId);
67
- if (!user) return res.status(401).json({ error: 'Invalid token. User not found.' });
68
- req.user = user;
69
- // If token came from query param, set session cookie for subsequent requests (iframe auto-auth)
70
- if (req.query?.token && !req.cookies?.session) {
71
- res.cookie('session', token, COOKIE_OPTIONS);
72
- }
73
- next();
74
- } catch (error) {
75
- return res.status(403).json({ error: 'Invalid or expired token' });
76
- }
77
- };
78
-
79
- // Generate JWT token (30-day expiration)
80
- const generateToken = (user) => {
81
- return jwt.sign(
82
- { userId: user.id, username: user.username },
83
- JWT_SECRET,
84
- { expiresIn: '30d' }
85
- );
86
- };
87
-
88
- // Cookie config for httpOnly session
89
- // Works for both self-hosted (same origin) and split deploy (Vercel proxy → Railway)
90
- const isSecureEnv = process.env.NODE_ENV === 'production' || !!process.env.VERCEL || !!process.env.RAILWAY_ENVIRONMENT;
91
- const COOKIE_OPTIONS = {
92
- httpOnly: true,
93
- secure: isSecureEnv,
94
- // 'none' required for cross-origin iframe embedding (Vercel frontend → Railway backend)
95
- // 'strict' used in local/dev mode where everything is same-origin
96
- sameSite: isSecureEnv ? 'none' : 'strict',
97
- maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
98
- path: '/',
99
- };
100
-
101
- // Set session cookie on response
102
- const setSessionCookie = (res, token) => {
103
- res.cookie('session', token, COOKIE_OPTIONS);
104
- };
105
-
106
- // Clear session cookie
107
- const clearSessionCookie = (res) => {
108
- res.clearCookie('session', { path: '/' });
109
- };
110
-
111
- // WebSocket authentication (parse cookie from upgrade request headers)
112
- const authenticateWebSocket = async (request) => {
113
- // Platform mode: bypass
114
- if (IS_PLATFORM) {
115
- try {
116
- const user = await userDb.getFirstUser();
117
- return user ? { userId: user.id, username: user.username } : null;
118
- } catch { return null; }
119
- }
120
-
121
- let token = null;
122
-
123
- // 1. Parse cookie from upgrade request
124
- const cookieHeader = request.headers?.cookie || '';
125
- if (cookieHeader) {
126
- const cookies = Object.fromEntries(
127
- cookieHeader.split(';').map(c => {
128
- const [k, ...v] = c.trim().split('=');
129
- return [k, v.join('=')];
130
- })
131
- );
132
- token = cookies.session || null;
133
- }
134
-
135
- // 2. Fallback: query param (legacy)
136
- if (!token) {
137
- try {
138
- const url = new URL(request.url, 'http://localhost');
139
- token = url.searchParams.get('token');
140
- } catch { /* ignore */ }
141
- }
142
-
143
- if (!token) {
144
- console.log('[WS-Auth] No token found in cookies or query params');
145
- return null;
146
- }
147
-
148
- // Relay token (upfyn_ prefix) — validate against DB, not JWT
149
- if (token.startsWith('upfyn_') || token.startsWith('rt_')) {
150
- console.log(`[WS-Auth] Relay token detected: ${token.slice(0, 12)}...`);
151
- try {
152
- const tokenData = await relayTokensDb.validateToken(token);
153
- if (tokenData) {
154
- console.log(`[WS-Auth] Relay token VALID: userId=${tokenData.user_id} username=${tokenData.username}`);
155
- return { userId: Number(tokenData.user_id), username: tokenData.username };
156
- }
157
- console.log('[WS-Auth] Relay token NOT FOUND in database');
158
- } catch (err) {
159
- console.error('[WS-Auth] Relay token validation error:', err.message);
160
- }
161
- return null;
162
- }
163
-
164
- try {
165
- const decoded = jwt.verify(token, JWT_SECRET);
166
- // Validate against Turso — DB is source of truth
167
- const user = await userDb.getUserById(decoded.userId);
168
- if (!user) return null;
169
- return { userId: user.id, username: user.username };
170
- } catch { return null; }
171
- };
172
-
173
- export {
174
- validateApiKey,
175
- authenticateToken,
176
- generateToken,
177
- authenticateWebSocket,
178
- setSessionCookie,
179
- clearSessionCookie,
180
- JWT_SECRET
181
- };
@@ -1,403 +0,0 @@
1
- /**
2
- * OpenAI Codex SDK Integration
3
- * =============================
4
- *
5
- * This module provides integration with the OpenAI Codex SDK for non-interactive
6
- * chat sessions. It mirrors the pattern used in claude-sdk.js for consistency.
7
- *
8
- * ## Usage
9
- *
10
- * - queryCodex(command, options, ws) - Execute a prompt with streaming via WebSocket
11
- * - abortCodexSession(sessionId) - Cancel an active session
12
- * - isCodexSessionActive(sessionId) - Check if a session is running
13
- * - getActiveCodexSessions() - List all active sessions
14
- */
15
-
16
- import { Codex } from '@openai/codex-sdk';
17
-
18
- // Track active sessions
19
- const activeCodexSessions = new Map();
20
-
21
- /**
22
- * Transform Codex SDK event to WebSocket message format
23
- * @param {object} event - SDK event
24
- * @returns {object} - Transformed event for WebSocket
25
- */
26
- function transformCodexEvent(event) {
27
- // Map SDK event types to a consistent format
28
- switch (event.type) {
29
- case 'item.started':
30
- case 'item.updated':
31
- case 'item.completed':
32
- const item = event.item;
33
- if (!item) {
34
- return { type: event.type, item: null };
35
- }
36
-
37
- // Transform based on item type
38
- switch (item.type) {
39
- case 'agent_message':
40
- return {
41
- type: 'item',
42
- itemType: 'agent_message',
43
- message: {
44
- role: 'assistant',
45
- content: item.text
46
- }
47
- };
48
-
49
- case 'reasoning':
50
- return {
51
- type: 'item',
52
- itemType: 'reasoning',
53
- message: {
54
- role: 'assistant',
55
- content: item.text,
56
- isReasoning: true
57
- }
58
- };
59
-
60
- case 'command_execution':
61
- return {
62
- type: 'item',
63
- itemType: 'command_execution',
64
- command: item.command,
65
- output: item.aggregated_output,
66
- exitCode: item.exit_code,
67
- status: item.status
68
- };
69
-
70
- case 'file_change':
71
- return {
72
- type: 'item',
73
- itemType: 'file_change',
74
- changes: item.changes,
75
- status: item.status
76
- };
77
-
78
- case 'mcp_tool_call':
79
- return {
80
- type: 'item',
81
- itemType: 'mcp_tool_call',
82
- server: item.server,
83
- tool: item.tool,
84
- arguments: item.arguments,
85
- result: item.result,
86
- error: item.error,
87
- status: item.status
88
- };
89
-
90
- case 'web_search':
91
- return {
92
- type: 'item',
93
- itemType: 'web_search',
94
- query: item.query
95
- };
96
-
97
- case 'todo_list':
98
- return {
99
- type: 'item',
100
- itemType: 'todo_list',
101
- items: item.items
102
- };
103
-
104
- case 'error':
105
- return {
106
- type: 'item',
107
- itemType: 'error',
108
- message: {
109
- role: 'error',
110
- content: item.message
111
- }
112
- };
113
-
114
- default:
115
- return {
116
- type: 'item',
117
- itemType: item.type,
118
- item: item
119
- };
120
- }
121
-
122
- case 'turn.started':
123
- return {
124
- type: 'turn_started'
125
- };
126
-
127
- case 'turn.completed':
128
- return {
129
- type: 'turn_complete',
130
- usage: event.usage
131
- };
132
-
133
- case 'turn.failed':
134
- return {
135
- type: 'turn_failed',
136
- error: event.error
137
- };
138
-
139
- case 'thread.started':
140
- return {
141
- type: 'thread_started',
142
- threadId: event.id
143
- };
144
-
145
- case 'error':
146
- return {
147
- type: 'error',
148
- message: event.message
149
- };
150
-
151
- default:
152
- return {
153
- type: event.type,
154
- data: event
155
- };
156
- }
157
- }
158
-
159
- /**
160
- * Map permission mode to Codex SDK options
161
- * @param {string} permissionMode - 'default', 'acceptEdits', or 'bypassPermissions'
162
- * @returns {object} - { sandboxMode, approvalPolicy }
163
- */
164
- function mapPermissionModeToCodexOptions(permissionMode) {
165
- switch (permissionMode) {
166
- case 'acceptEdits':
167
- return {
168
- sandboxMode: 'workspace-write',
169
- approvalPolicy: 'never'
170
- };
171
- case 'bypassPermissions':
172
- return {
173
- sandboxMode: 'danger-full-access',
174
- approvalPolicy: 'never'
175
- };
176
- case 'default':
177
- default:
178
- return {
179
- sandboxMode: 'workspace-write',
180
- approvalPolicy: 'untrusted'
181
- };
182
- }
183
- }
184
-
185
- /**
186
- * Execute a Codex query with streaming
187
- * @param {string} command - The prompt to send
188
- * @param {object} options - Options including cwd, sessionId, model, permissionMode
189
- * @param {WebSocket|object} ws - WebSocket connection or response writer
190
- */
191
- export async function queryCodex(command, options = {}, ws) {
192
- const {
193
- sessionId,
194
- cwd,
195
- projectPath,
196
- model,
197
- permissionMode = 'default'
198
- } = options;
199
-
200
- const workingDirectory = cwd || projectPath || process.cwd();
201
- const { sandboxMode, approvalPolicy } = mapPermissionModeToCodexOptions(permissionMode);
202
-
203
- let codex;
204
- let thread;
205
- let currentSessionId = sessionId;
206
- const abortController = new AbortController();
207
-
208
- try {
209
- // Initialize Codex SDK
210
- codex = new Codex();
211
-
212
- // Thread options with sandbox and approval settings
213
- const threadOptions = {
214
- workingDirectory,
215
- skipGitRepoCheck: true,
216
- sandboxMode,
217
- approvalPolicy,
218
- model
219
- };
220
-
221
- // Start or resume thread
222
- if (sessionId) {
223
- thread = codex.resumeThread(sessionId, threadOptions);
224
- } else {
225
- thread = codex.startThread(threadOptions);
226
- }
227
-
228
- // Get the thread ID
229
- currentSessionId = thread.id || sessionId || `codex-${Date.now()}`;
230
-
231
- // Track the session
232
- activeCodexSessions.set(currentSessionId, {
233
- thread,
234
- codex,
235
- status: 'running',
236
- abortController,
237
- startedAt: new Date().toISOString()
238
- });
239
-
240
- // Send session created event
241
- sendMessage(ws, {
242
- type: 'session-created',
243
- sessionId: currentSessionId,
244
- provider: 'codex'
245
- });
246
-
247
- // Execute with streaming
248
- const streamedTurn = await thread.runStreamed(command, {
249
- signal: abortController.signal
250
- });
251
-
252
- for await (const event of streamedTurn.events) {
253
- // Check if session was aborted
254
- const session = activeCodexSessions.get(currentSessionId);
255
- if (!session || session.status === 'aborted') {
256
- break;
257
- }
258
-
259
- if (event.type === 'item.started' || event.type === 'item.updated') {
260
- continue;
261
- }
262
-
263
- const transformed = transformCodexEvent(event);
264
-
265
- sendMessage(ws, {
266
- type: 'codex-response',
267
- data: transformed,
268
- sessionId: currentSessionId
269
- });
270
-
271
- // Extract and send token usage if available (normalized to match Claude format)
272
- if (event.type === 'turn.completed' && event.usage) {
273
- const totalTokens = (event.usage.input_tokens || 0) + (event.usage.output_tokens || 0);
274
- sendMessage(ws, {
275
- type: 'token-budget',
276
- data: {
277
- used: totalTokens,
278
- total: 200000 // Default context window for Codex models
279
- },
280
- sessionId: currentSessionId
281
- });
282
- }
283
- }
284
-
285
- // Send completion event
286
- sendMessage(ws, {
287
- type: 'codex-complete',
288
- sessionId: currentSessionId,
289
- actualSessionId: thread.id
290
- });
291
-
292
- } catch (error) {
293
- const session = currentSessionId ? activeCodexSessions.get(currentSessionId) : null;
294
- const wasAborted =
295
- session?.status === 'aborted' ||
296
- error?.name === 'AbortError' ||
297
- String(error?.message || '').toLowerCase().includes('aborted');
298
-
299
- if (!wasAborted) {
300
- console.error('[Codex] Error:', error);
301
- sendMessage(ws, {
302
- type: 'codex-error',
303
- error: error.message,
304
- sessionId: currentSessionId
305
- });
306
- }
307
-
308
- } finally {
309
- // Update session status
310
- if (currentSessionId) {
311
- const session = activeCodexSessions.get(currentSessionId);
312
- if (session) {
313
- session.status = session.status === 'aborted' ? 'aborted' : 'completed';
314
- }
315
- }
316
- }
317
- }
318
-
319
- /**
320
- * Abort an active Codex session
321
- * @param {string} sessionId - Session ID to abort
322
- * @returns {boolean} - Whether abort was successful
323
- */
324
- export function abortCodexSession(sessionId) {
325
- const session = activeCodexSessions.get(sessionId);
326
-
327
- if (!session) {
328
- return false;
329
- }
330
-
331
- session.status = 'aborted';
332
- try {
333
- session.abortController?.abort();
334
- } catch (error) {
335
- console.warn(`[Codex] Failed to abort session ${sessionId}:`, error);
336
- }
337
-
338
- return true;
339
- }
340
-
341
- /**
342
- * Check if a session is active
343
- * @param {string} sessionId - Session ID to check
344
- * @returns {boolean} - Whether session is active
345
- */
346
- export function isCodexSessionActive(sessionId) {
347
- const session = activeCodexSessions.get(sessionId);
348
- return session?.status === 'running';
349
- }
350
-
351
- /**
352
- * Get all active sessions
353
- * @returns {Array} - Array of active session info
354
- */
355
- export function getActiveCodexSessions() {
356
- const sessions = [];
357
-
358
- for (const [id, session] of activeCodexSessions.entries()) {
359
- if (session.status === 'running') {
360
- sessions.push({
361
- id,
362
- status: session.status,
363
- startedAt: session.startedAt
364
- });
365
- }
366
- }
367
-
368
- return sessions;
369
- }
370
-
371
- /**
372
- * Helper to send message via WebSocket or writer
373
- * @param {WebSocket|object} ws - WebSocket or response writer
374
- * @param {object} data - Data to send
375
- */
376
- function sendMessage(ws, data) {
377
- try {
378
- if (ws.isSSEStreamWriter || ws.isWebSocketWriter) {
379
- // Writer handles stringification (SSEStreamWriter or WebSocketWriter)
380
- ws.send(data);
381
- } else if (typeof ws.send === 'function') {
382
- // Raw WebSocket - stringify here
383
- ws.send(JSON.stringify(data));
384
- }
385
- } catch (error) {
386
- console.error('[Codex] Error sending message:', error);
387
- }
388
- }
389
-
390
- // Clean up old completed sessions periodically
391
- setInterval(() => {
392
- const now = Date.now();
393
- const maxAge = 30 * 60 * 1000; // 30 minutes
394
-
395
- for (const [id, session] of activeCodexSessions.entries()) {
396
- if (session.status !== 'running') {
397
- const startedAt = new Date(session.startedAt).getTime();
398
- if (now - startedAt > maxAge) {
399
- activeCodexSessions.delete(id);
400
- }
401
- }
402
- }
403
- }, 5 * 60 * 1000); // Every 5 minutes
@@ -1,137 +0,0 @@
1
- /**
2
- * OpenRouter Integration
3
- *
4
- * Lightweight wrapper for OpenRouter API, which provides access to
5
- * hundreds of AI models (GPT-4, Claude, Gemini, Llama, Mistral, etc.)
6
- * through a single API key and endpoint.
7
- *
8
- * Users provide their own OpenRouter API key via BYOK settings.
9
- */
10
-
11
- const OPENROUTER_BASE_URL = 'https://openrouter.ai/api/v1';
12
-
13
- // Popular models available on OpenRouter
14
- export const OPENROUTER_MODELS = {
15
- OPTIONS: [
16
- { value: 'anthropic/claude-sonnet-4', label: 'Claude Sonnet 4' },
17
- { value: 'anthropic/claude-opus-4', label: 'Claude Opus 4' },
18
- { value: 'openai/gpt-4o', label: 'GPT-4o' },
19
- { value: 'openai/o3', label: 'O3' },
20
- { value: 'google/gemini-2.5-pro', label: 'Gemini 2.5 Pro' },
21
- { value: 'meta-llama/llama-4-maverick', label: 'Llama 4 Maverick' },
22
- { value: 'mistralai/mistral-large', label: 'Mistral Large' },
23
- { value: 'deepseek/deepseek-r1', label: 'DeepSeek R1' },
24
- ],
25
- DEFAULT: 'anthropic/claude-sonnet-4',
26
- };
27
-
28
- /**
29
- * Query OpenRouter API with streaming support
30
- * @param {string} message - User message
31
- * @param {Object} options - { model, apiKey, systemPrompt }
32
- * @param {Object} writer - WebSocketWriter or SSEStreamWriter
33
- */
34
- export async function queryOpenRouter(message, options = {}, writer) {
35
- const {
36
- model = OPENROUTER_MODELS.DEFAULT,
37
- apiKey,
38
- systemPrompt,
39
- sessionId,
40
- } = options;
41
-
42
- if (!apiKey) {
43
- writer.send({
44
- type: 'error',
45
- error: 'OpenRouter API key required. Add your key in Settings > AI Providers.',
46
- });
47
- return;
48
- }
49
-
50
- // Generate session ID
51
- const sid = sessionId || `or-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
52
- writer.send({ type: 'session-created', sessionId: sid });
53
-
54
- const messages = [];
55
- if (systemPrompt) {
56
- messages.push({ role: 'system', content: systemPrompt });
57
- }
58
- messages.push({ role: 'user', content: message });
59
-
60
- try {
61
- const response = await fetch(`${OPENROUTER_BASE_URL}/chat/completions`, {
62
- method: 'POST',
63
- headers: {
64
- 'Authorization': `Bearer ${apiKey}`,
65
- 'Content-Type': 'application/json',
66
- 'HTTP-Referer': 'https://cli.upfyn.com',
67
- 'X-Title': 'Upfyn-Code',
68
- },
69
- body: JSON.stringify({
70
- model,
71
- messages,
72
- stream: true,
73
- }),
74
- });
75
-
76
- if (!response.ok) {
77
- const errBody = await response.text();
78
- let errMsg = `OpenRouter API error (${response.status})`;
79
- try {
80
- const parsed = JSON.parse(errBody);
81
- errMsg = parsed.error?.message || errMsg;
82
- } catch {}
83
- writer.send({ type: 'error', error: errMsg, sessionId: sid });
84
- return;
85
- }
86
-
87
- // Stream SSE response
88
- const reader = response.body.getReader();
89
- const decoder = new TextDecoder();
90
- let buffer = '';
91
- let fullContent = '';
92
-
93
- while (true) {
94
- const { done, value } = await reader.read();
95
- if (done) break;
96
-
97
- buffer += decoder.decode(value, { stream: true });
98
- const lines = buffer.split('\n');
99
- buffer = lines.pop() || '';
100
-
101
- for (const line of lines) {
102
- if (!line.startsWith('data: ')) continue;
103
- const data = line.slice(6).trim();
104
- if (data === '[DONE]') break;
105
-
106
- try {
107
- const parsed = JSON.parse(data);
108
- const delta = parsed.choices?.[0]?.delta?.content;
109
- if (delta) {
110
- fullContent += delta;
111
- writer.send({
112
- type: 'assistant',
113
- content: delta,
114
- sessionId: sid,
115
- });
116
- }
117
- } catch {}
118
- }
119
- }
120
-
121
- // Send completion
122
- writer.send({
123
- type: 'result',
124
- subtype: 'success',
125
- sessionId: sid,
126
- content: fullContent,
127
- model,
128
- provider: 'openrouter',
129
- });
130
- } catch (error) {
131
- writer.send({
132
- type: 'error',
133
- error: `OpenRouter request failed: ${error.message}`,
134
- sessionId: sid,
135
- });
136
- }
137
- }