upfynai-code 3.0.4 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/README.md +69 -92
  2. package/bin/cli.js +191 -0
  3. package/dist/client/assets/AppContent-M14Au3SB.js +542 -0
  4. package/{client/dist/assets/BrowserPanel-0TLEl-IC.js → dist/client/assets/BrowserPanel-TFKm2NDJ.js} +2 -2
  5. package/dist/client/assets/DashboardPanel-C88HjsCh.js +1 -0
  6. package/dist/client/assets/FileTree-DvO1xnDE.js +1 -0
  7. package/{client/dist/assets/GitPanel-C_xFM-N2.js → dist/client/assets/GitPanel-D-slVlyy.js} +2 -2
  8. package/dist/client/assets/LoginModal-Chi4SYcr.js +21 -0
  9. package/{client/dist/assets/MarkdownPreview-CESjI261.js → dist/client/assets/MarkdownPreview-CuIix2u9.js} +1 -1
  10. package/dist/client/assets/MermaidBlock-Dq9uFv82.js +2 -0
  11. package/dist/client/assets/Onboarding-QYXx24dX.js +1 -0
  12. package/{client/dist/assets/PreviewPanel-CqCa92Tf.js → dist/client/assets/PreviewPanel-Dd8q-jo0.js} +1 -1
  13. package/dist/client/assets/SetupForm-CrspaUva.js +1 -0
  14. package/dist/client/assets/WorkflowsPanel-DIlYAdhB.js +1 -0
  15. package/dist/client/assets/index-CnNNzw9A.css +1 -0
  16. package/{client/dist/assets/index-HaY-3pK1.js → dist/client/assets/index-rUkK9FDP.js} +26 -26
  17. package/{client/dist/assets/vendor-codemirror-D2ALgpaX.js → dist/client/assets/vendor-codemirror-jc6nyJQg.js} +1 -1
  18. package/{client/dist/assets/vendor-diff-DNQpbhrT.js → dist/client/assets/vendor-diff-THJmAcEI.js} +1 -1
  19. package/{client/dist/assets/vendor-icons-GyYE35HP.js → dist/client/assets/vendor-icons-CfjIpdrD.js} +145 -155
  20. package/{client/dist/assets/vendor-markdown-CimbIo6Y.js → dist/client/assets/vendor-markdown-Cdm6NEGf.js} +1 -1
  21. package/dist/client/assets/vendor-mermaid-DTPaBx-U.js +2559 -0
  22. package/{client/dist/assets/vendor-react-96lCPsRK.js → dist/client/assets/vendor-react-wFkb6mSf.js} +1 -1
  23. package/{client/dist/assets/vendor-syntax-LS_Nt30I.js → dist/client/assets/vendor-syntax-C_UZR7tc.js} +1 -1
  24. package/dist/client/favicon.png +0 -0
  25. package/dist/client/icons/icon-128x128.png +0 -0
  26. package/dist/client/icons/icon-144x144.png +0 -0
  27. package/dist/client/icons/icon-152x152.png +0 -0
  28. package/dist/client/icons/icon-192x192.png +0 -0
  29. package/dist/client/icons/icon-384x384.png +0 -0
  30. package/dist/client/icons/icon-512x512.png +0 -0
  31. package/dist/client/icons/icon-72x72.png +0 -0
  32. package/dist/client/icons/icon-96x96.png +0 -0
  33. package/{client/dist → dist/client}/index.html +37 -36
  34. package/dist/client/logo-128.png +0 -0
  35. package/dist/client/logo-256.png +0 -0
  36. package/dist/client/logo-32.png +0 -0
  37. package/dist/client/logo-512.png +0 -0
  38. package/dist/client/logo-64.png +0 -0
  39. package/dist/client/logo.png +0 -0
  40. package/{client/dist → dist/client}/manifest.json +12 -12
  41. package/{client/dist → dist/client}/mcp-docs.html +1 -1
  42. package/{client/dist → dist/client}/sw.js +2 -2
  43. package/package.json +56 -105
  44. package/scripts/postinstall.js +9 -0
  45. package/scripts/prepublish.js +77 -0
  46. package/src/animation.js +228 -0
  47. package/src/auth.js +142 -0
  48. package/src/config.js +40 -0
  49. package/src/connect.js +416 -0
  50. package/src/launch.js +81 -0
  51. package/src/mcp.js +57 -0
  52. package/src/permissions.js +140 -0
  53. package/src/persistent-shell.js +261 -0
  54. package/src/server.js +54 -0
  55. package/client/dist/assets/AppContent-CwrTP6TW.js +0 -545
  56. package/client/dist/assets/CanvasFullScreen-D1GWQsGL.js +0 -1
  57. package/client/dist/assets/CanvasWorkspace-D7ORj358.js +0 -163
  58. package/client/dist/assets/DashboardPanel-BV7ybUDe.js +0 -1
  59. package/client/dist/assets/FileTree-5qfhBqdE.js +0 -1
  60. package/client/dist/assets/LoginModal-CImJHRjX.js +0 -13
  61. package/client/dist/assets/MermaidBlock-BFM21cwe.js +0 -2
  62. package/client/dist/assets/Onboarding-B3cteLu2.js +0 -1
  63. package/client/dist/assets/SetupForm-P6dsYgHO.js +0 -1
  64. package/client/dist/assets/WorkflowsPanel-CBoN80kc.js +0 -1
  65. package/client/dist/assets/index-46kkVu2i.css +0 -1
  66. package/client/dist/assets/pdf-CE_K4jFx.js +0 -12
  67. package/client/dist/assets/vendor-canvas-BZV40eAE.css +0 -1
  68. package/client/dist/assets/vendor-canvas-DvHJ_Pn2.js +0 -49
  69. package/client/dist/assets/vendor-mermaid-DucWyDEe.js +0 -2556
  70. package/client/dist/favicon.png +0 -0
  71. package/client/dist/icons/icon-128x128.png +0 -0
  72. package/client/dist/icons/icon-144x144.png +0 -0
  73. package/client/dist/icons/icon-152x152.png +0 -0
  74. package/client/dist/icons/icon-192x192.png +0 -0
  75. package/client/dist/icons/icon-384x384.png +0 -0
  76. package/client/dist/icons/icon-512x512.png +0 -0
  77. package/client/dist/icons/icon-72x72.png +0 -0
  78. package/client/dist/icons/icon-96x96.png +0 -0
  79. package/client/dist/logo-128.png +0 -0
  80. package/client/dist/logo-256.png +0 -0
  81. package/client/dist/logo-32.png +0 -0
  82. package/client/dist/logo-512.png +0 -0
  83. package/client/dist/logo-64.png +0 -0
  84. package/commands/upfynai-connect.md +0 -59
  85. package/commands/upfynai-disconnect.md +0 -31
  86. package/commands/upfynai-doctor.md +0 -99
  87. package/commands/upfynai-export.md +0 -49
  88. package/commands/upfynai-local.md +0 -82
  89. package/commands/upfynai-status.md +0 -75
  90. package/commands/upfynai-stop.md +0 -49
  91. package/commands/upfynai-uninstall.md +0 -58
  92. package/commands/upfynai.md +0 -69
  93. package/scripts/build-client.js +0 -17
  94. package/scripts/fix-node-pty.js +0 -67
  95. package/scripts/install-commands.js +0 -78
  96. package/server/agent-loop.js +0 -242
  97. package/server/auto-compact.js +0 -99
  98. package/server/browser.js +0 -131
  99. package/server/claude-sdk.js +0 -797
  100. package/server/cli-ui.js +0 -798
  101. package/server/cli.js +0 -751
  102. package/server/constants/config.js +0 -31
  103. package/server/cursor-cli.js +0 -270
  104. package/server/database/auth.db +0 -0
  105. package/server/database/db.js +0 -1547
  106. package/server/database/init.sql +0 -70
  107. package/server/index.js +0 -3813
  108. package/server/load-env.js +0 -26
  109. package/server/mcp-server.js +0 -621
  110. package/server/middleware/auth.js +0 -184
  111. package/server/middleware/relayHelpers.js +0 -44
  112. package/server/middleware/sandboxRouter.js +0 -174
  113. package/server/openai-codex.js +0 -403
  114. package/server/openrouter.js +0 -137
  115. package/server/projects.js +0 -1807
  116. package/server/provider-factory.js +0 -174
  117. package/server/relay-client.js +0 -390
  118. package/server/routes/agent.js +0 -1234
  119. package/server/routes/auth.js +0 -559
  120. package/server/routes/browser.js +0 -419
  121. package/server/routes/canvas.js +0 -53
  122. package/server/routes/cli-auth.js +0 -263
  123. package/server/routes/codex.js +0 -396
  124. package/server/routes/commands.js +0 -707
  125. package/server/routes/composio.js +0 -176
  126. package/server/routes/cursor.js +0 -770
  127. package/server/routes/dashboard.js +0 -295
  128. package/server/routes/git.js +0 -1208
  129. package/server/routes/keys.js +0 -34
  130. package/server/routes/mcp-utils.js +0 -48
  131. package/server/routes/mcp.js +0 -661
  132. package/server/routes/payments.js +0 -227
  133. package/server/routes/projects.js +0 -754
  134. package/server/routes/sessions.js +0 -146
  135. package/server/routes/settings.js +0 -261
  136. package/server/routes/taskmaster.js +0 -1928
  137. package/server/routes/user.js +0 -106
  138. package/server/routes/vapi-chat.js +0 -624
  139. package/server/routes/voice.js +0 -235
  140. package/server/routes/webhooks.js +0 -166
  141. package/server/routes/workflows.js +0 -312
  142. package/server/sandbox.js +0 -120
  143. package/server/services/browser-ai.js +0 -154
  144. package/server/services/composio.js +0 -204
  145. package/server/services/sessionRegistry.js +0 -139
  146. package/server/services/whisperService.js +0 -84
  147. package/server/services/workflowScheduler.js +0 -211
  148. package/server/tests/relay-flow.test.js +0 -570
  149. package/server/tests/sessions.test.js +0 -259
  150. package/server/utils/commandParser.js +0 -303
  151. package/server/utils/email.js +0 -66
  152. package/server/utils/gitConfig.js +0 -24
  153. package/server/utils/mcp-detector.js +0 -198
  154. package/server/utils/taskmaster-websocket.js +0 -129
  155. package/shared/integrationCatalog.d.ts +0 -12
  156. package/shared/integrationCatalog.js +0 -172
  157. package/shared/modelConstants.js +0 -96
  158. /package/{shared → dist}/agents/claude.js +0 -0
  159. /package/{shared → dist}/agents/codex.js +0 -0
  160. /package/{shared → dist}/agents/cursor.js +0 -0
  161. /package/{shared → dist}/agents/detect.js +0 -0
  162. /package/{shared → dist}/agents/exec.js +0 -0
  163. /package/{shared → dist}/agents/files.js +0 -0
  164. /package/{shared → dist}/agents/git.js +0 -0
  165. /package/{shared → dist}/agents/gitagent.js +0 -0
  166. /package/{shared → dist}/agents/index.js +0 -0
  167. /package/{shared → dist}/agents/shell.js +0 -0
  168. /package/{shared → dist}/agents/utils.js +0 -0
  169. /package/{client/dist → dist/client}/api-docs.html +0 -0
  170. /package/{client/dist → dist/client}/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  171. /package/{client/dist → dist/client}/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  172. /package/{client/dist → dist/client}/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  173. /package/{client/dist → dist/client}/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  174. /package/{client/dist → dist/client}/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  175. /package/{client/dist → dist/client}/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  176. /package/{client/dist → dist/client}/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  177. /package/{client/dist → dist/client}/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  178. /package/{client/dist → dist/client}/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  179. /package/{client/dist → dist/client}/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  180. /package/{client/dist → dist/client}/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  181. /package/{client/dist → dist/client}/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  182. /package/{client/dist → dist/client}/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  183. /package/{client/dist → dist/client}/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  184. /package/{client/dist → dist/client}/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  185. /package/{client/dist → dist/client}/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  186. /package/{client/dist → dist/client}/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  187. /package/{client/dist → dist/client}/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  188. /package/{client/dist → dist/client}/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  189. /package/{client/dist → dist/client}/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  190. /package/{client/dist → dist/client}/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  191. /package/{client/dist → dist/client}/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  192. /package/{client/dist → dist/client}/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  193. /package/{client/dist → dist/client}/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  194. /package/{client/dist → dist/client}/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  195. /package/{client/dist → dist/client}/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  196. /package/{client/dist → dist/client}/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  197. /package/{client/dist → dist/client}/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  198. /package/{client/dist → dist/client}/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  199. /package/{client/dist → dist/client}/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  200. /package/{client/dist → dist/client}/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  201. /package/{client/dist → dist/client}/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  202. /package/{client/dist → dist/client}/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  203. /package/{client/dist → dist/client}/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  204. /package/{client/dist → dist/client}/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  205. /package/{client/dist → dist/client}/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  206. /package/{client/dist → dist/client}/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  207. /package/{client/dist → dist/client}/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  208. /package/{client/dist → dist/client}/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  209. /package/{client/dist → dist/client}/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  210. /package/{client/dist → dist/client}/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  211. /package/{client/dist → dist/client}/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  212. /package/{client/dist → dist/client}/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  213. /package/{client/dist → dist/client}/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  214. /package/{client/dist → dist/client}/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  215. /package/{client/dist → dist/client}/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  216. /package/{client/dist → dist/client}/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  217. /package/{client/dist → dist/client}/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  218. /package/{client/dist → dist/client}/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  219. /package/{client/dist → dist/client}/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  220. /package/{client/dist → dist/client}/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  221. /package/{client/dist → dist/client}/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  222. /package/{client/dist → dist/client}/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  223. /package/{client/dist → dist/client}/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  224. /package/{client/dist → dist/client}/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  225. /package/{client/dist → dist/client}/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  226. /package/{client/dist → dist/client}/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  227. /package/{client/dist → dist/client}/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  228. /package/{client/dist → dist/client}/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  229. /package/{client/dist → dist/client}/assets/vendor-i18n-DCFGyhQR.js +0 -0
  230. /package/{client/dist → dist/client}/assets/vendor-xterm-CZq1hqo1.js +0 -0
  231. /package/{client/dist → dist/client}/assets/vendor-xterm-qxJ8_QYu.css +0 -0
  232. /package/{client/dist → dist/client}/clear-cache.html +0 -0
  233. /package/{client/dist → dist/client}/convert-icons.md +0 -0
  234. /package/{client/dist → dist/client}/favicon.svg +0 -0
  235. /package/{client/dist → dist/client}/generate-icons.js +0 -0
  236. /package/{client/dist → dist/client}/icons/claude-ai-icon.svg +0 -0
  237. /package/{client/dist → dist/client}/icons/codex-white.svg +0 -0
  238. /package/{client/dist → dist/client}/icons/codex.svg +0 -0
  239. /package/{client/dist → dist/client}/icons/cursor-white.svg +0 -0
  240. /package/{client/dist → dist/client}/icons/cursor.svg +0 -0
  241. /package/{client/dist → dist/client}/icons/icon-128x128.svg +0 -0
  242. /package/{client/dist → dist/client}/icons/icon-144x144.svg +0 -0
  243. /package/{client/dist → dist/client}/icons/icon-152x152.svg +0 -0
  244. /package/{client/dist → dist/client}/icons/icon-192x192.svg +0 -0
  245. /package/{client/dist → dist/client}/icons/icon-384x384.svg +0 -0
  246. /package/{client/dist → dist/client}/icons/icon-512x512.svg +0 -0
  247. /package/{client/dist → dist/client}/icons/icon-72x72.svg +0 -0
  248. /package/{client/dist → dist/client}/icons/icon-96x96.svg +0 -0
  249. /package/{client/dist → dist/client}/icons/icon-template.svg +0 -0
  250. /package/{client/dist → dist/client}/logo.svg +0 -0
  251. /package/{client/dist → dist/client}/offline.html +0 -0
  252. /package/{client/dist → dist/client}/screenshots/cli-selection.png +0 -0
  253. /package/{client/dist → dist/client}/screenshots/desktop-main.png +0 -0
  254. /package/{client/dist → dist/client}/screenshots/mobile-chat.png +0 -0
  255. /package/{client/dist → dist/client}/screenshots/tools-modal.png +0 -0
  256. /package/{shared → dist}/gitagent/index.js +0 -0
  257. /package/{shared → dist}/gitagent/parser.js +0 -0
  258. /package/{shared → dist}/gitagent/prompt-builder.js +0 -0
@@ -0,0 +1,228 @@
1
+ /**
2
+ * CLI spaceship-to-star animation for Upfyn-Code.
3
+ * Plays after install (postinstall) and before `uc connect` starts.
4
+ */
5
+
6
+ const STAR_FRAMES = ['✦', '✧', '✦', '★'];
7
+
8
+ // Spaceship frames (4 animation states)
9
+ const SHIP = [
10
+ ' ╱▏▔▔╲ ',
11
+ ' ╱ ▏══ ╲ ',
12
+ '╱ ▏▁▁ ╲ ',
13
+ ' ╱▏▔▔╲ ',
14
+ ];
15
+
16
+ // Simpler inline ship for the travel animation
17
+ const SHIP_R = [
18
+ ' ▄▄ ',
19
+ ' ◁━━██━━▷ ',
20
+ ' ▀▀ ',
21
+ ];
22
+
23
+ const SHIP_SMALL = '◁━━▶';
24
+ const SHIP_TRAVEL = '⟫⟫';
25
+ const EXHAUST_CHARS = ['░', '▒', '▓', '═', '~', '·'];
26
+
27
+ function sleep(ms) {
28
+ return new Promise(r => setTimeout(r, ms));
29
+ }
30
+
31
+ function clearLines(n) {
32
+ for (let i = 0; i < n; i++) {
33
+ process.stdout.write('\x1b[1A\x1b[2K');
34
+ }
35
+ }
36
+
37
+ function dim(s) { return `\x1b[2m${s}\x1b[0m`; }
38
+ function cyan(s) { return `\x1b[36m${s}\x1b[0m`; }
39
+ function yellow(s) { return `\x1b[33m${s}\x1b[0m`; }
40
+ function bold(s) { return `\x1b[1m${s}\x1b[0m`; }
41
+ function magenta(s) { return `\x1b[35m${s}\x1b[0m`; }
42
+ function white(s) { return `\x1b[97m${s}\x1b[0m`; }
43
+ function green(s) { return `\x1b[32m${s}\x1b[0m`; }
44
+ function blue(s) { return `\x1b[34m${s}\x1b[0m`; }
45
+
46
+ /**
47
+ * Generate a star field background line
48
+ */
49
+ function starFieldLine(width, density = 0.08, frame = 0) {
50
+ let line = '';
51
+ for (let i = 0; i < width; i++) {
52
+ if (Math.random() < density) {
53
+ const stars = ['.', '·', '∘', '°', '✧'];
54
+ const s = stars[Math.floor(Math.random() * stars.length)];
55
+ line += dim(s);
56
+ } else {
57
+ line += ' ';
58
+ }
59
+ }
60
+ return line;
61
+ }
62
+
63
+ /**
64
+ * Main spaceship-to-star animation
65
+ * @param {'install'|'connect'} mode
66
+ */
67
+ export async function playSpaceshipAnimation(mode = 'connect') {
68
+ const cols = Math.min(process.stdout.columns || 70, 80);
69
+ const totalFrames = 28;
70
+ const LINES = 11; // total lines we'll use
71
+
72
+ const starX = cols - 6;
73
+
74
+ // Phase 1: Launch sequence text
75
+ const tagline = mode === 'install'
76
+ ? 'Installation complete!'
77
+ : 'Launching relay bridge...';
78
+
79
+ console.log('');
80
+ console.log(dim(' ─'.repeat(Math.floor(cols / 3))));
81
+ console.log('');
82
+
83
+ // Phase 2: Spaceship travels across the screen toward a star
84
+ for (let frame = 0; frame < totalFrames; frame++) {
85
+ const progress = frame / (totalFrames - 1); // 0 → 1
86
+ const shipX = Math.floor(progress * (cols - 16)) + 2;
87
+
88
+ // Build exhaust trail
89
+ const exhaustLen = Math.min(shipX, Math.floor(progress * 20));
90
+ let exhaust = '';
91
+ for (let e = 0; e < exhaustLen; e++) {
92
+ const intensity = 1 - (e / exhaustLen);
93
+ if (intensity > 0.7) exhaust = '▓' + exhaust;
94
+ else if (intensity > 0.4) exhaust = '▒' + exhaust;
95
+ else if (intensity > 0.2) exhaust = '░' + exhaust;
96
+ else exhaust = '·' + exhaust;
97
+ }
98
+
99
+ // Star pulse
100
+ const starChar = STAR_FRAMES[frame % STAR_FRAMES.length];
101
+ const starGlow = progress > 0.7 ? yellow('✦ ') : '';
102
+
103
+ // Build the 5 display lines
104
+ const lines = [];
105
+
106
+ // Line 1: starfield
107
+ lines.push(' ' + starFieldLine(cols - 4, 0.05, frame));
108
+
109
+ // Line 2: top space
110
+ lines.push(' ' + starFieldLine(cols - 4, 0.03, frame));
111
+
112
+ // Line 3: ship row (main action)
113
+ let shipRow = '';
114
+ const beforeShip = Math.max(0, shipX - exhaustLen);
115
+ shipRow += ' '.repeat(beforeShip);
116
+ shipRow += dim(exhaust);
117
+ shipRow += cyan(' ◁━━▶');
118
+ // Fill to star position
119
+ const afterShip = Math.max(0, starX - shipX - 7);
120
+ // Dots between ship and star
121
+ let midSpace = '';
122
+ for (let d = 0; d < afterShip; d++) {
123
+ midSpace += Math.random() < 0.06 ? dim('·') : ' ';
124
+ }
125
+ shipRow += midSpace;
126
+ if (progress < 0.92) {
127
+ shipRow += starGlow + yellow(starChar);
128
+ } else {
129
+ shipRow += yellow('✦★✦');
130
+ }
131
+ lines.push(shipRow);
132
+
133
+ // Line 4: thrust glow
134
+ let thrustRow = ' '.repeat(Math.max(0, shipX + 1));
135
+ if (frame % 2 === 0) {
136
+ thrustRow += dim(magenta('~≈~'));
137
+ } else {
138
+ thrustRow += dim(magenta('≈~≈'));
139
+ }
140
+ lines.push(thrustRow);
141
+
142
+ // Line 5: starfield
143
+ lines.push(' ' + starFieldLine(cols - 4, 0.04, frame));
144
+
145
+ // Line 6: message (centered)
146
+ const msg = progress < 0.3
147
+ ? dim(` ${tagline}`)
148
+ : progress < 0.6
149
+ ? cyan(` ⟫ Navigating to the stars...`)
150
+ : progress < 0.9
151
+ ? magenta(` ⟫⟫ Almost there...`)
152
+ : green(` ★ ${mode === 'install' ? 'Ready for launch!' : 'Connection established!'}`);
153
+ lines.push(msg);
154
+
155
+ // Line 7: progress bar
156
+ const barWidth = cols - 10;
157
+ const filled = Math.floor(progress * barWidth);
158
+ const bar = ' ' + dim('[')
159
+ + cyan('█'.repeat(filled))
160
+ + dim('░'.repeat(barWidth - filled))
161
+ + dim(']')
162
+ + dim(` ${Math.floor(progress * 100)}%`);
163
+ lines.push(bar);
164
+
165
+ // Print
166
+ if (frame > 0) clearLines(lines.length);
167
+ for (const l of lines) console.log(l);
168
+
169
+ // Speed: start slow, middle fast, end slow
170
+ const delay = progress < 0.2 ? 120
171
+ : progress > 0.85 ? 150
172
+ : 60;
173
+ await sleep(delay);
174
+ }
175
+
176
+ // Phase 3: Final flash
177
+ await sleep(200);
178
+ clearLines(7);
179
+
180
+ // Arrival burst
181
+ const burstLines = [];
182
+ burstLines.push(' ' + starFieldLine(cols - 4, 0.06));
183
+ burstLines.push('');
184
+ burstLines.push(
185
+ ' '.repeat(Math.floor(cols / 2 - 12))
186
+ + yellow('· ✧ · ★ ')
187
+ + bold(white('UPFYN'))
188
+ + yellow(' ★ · ✧ ·')
189
+ );
190
+ burstLines.push('');
191
+
192
+ if (mode === 'install') {
193
+ burstLines.push(
194
+ ' '.repeat(Math.floor(cols / 2 - 20))
195
+ + green('✓ ') + bold('upfynai-code') + dim(' installed successfully')
196
+ );
197
+ burstLines.push('');
198
+ burstLines.push(dim(' Quick start:'));
199
+ burstLines.push(cyan(' uc login ') + dim('— authenticate'));
200
+ burstLines.push(cyan(' uc connect ') + dim('— bridge to cloud'));
201
+ burstLines.push(cyan(' uc --local ') + dim('— start local server'));
202
+ } else {
203
+ burstLines.push(
204
+ ' '.repeat(Math.floor(cols / 2 - 16))
205
+ + green('✓ ') + bold('Relay bridge activated')
206
+ );
207
+ }
208
+
209
+ burstLines.push('');
210
+ burstLines.push(dim(' ─'.repeat(Math.floor(cols / 3))));
211
+ burstLines.push('');
212
+
213
+ for (const l of burstLines) console.log(l);
214
+ }
215
+
216
+ /**
217
+ * Postinstall animation (shorter variant)
218
+ */
219
+ export async function playInstallAnimation() {
220
+ return playSpaceshipAnimation('install');
221
+ }
222
+
223
+ /**
224
+ * Connect animation
225
+ */
226
+ export async function playConnectAnimation() {
227
+ return playSpaceshipAnimation('connect');
228
+ }
package/src/auth.js ADDED
@@ -0,0 +1,142 @@
1
+ import prompts from 'prompts';
2
+ import chalk from 'chalk';
3
+ import { readConfig, writeConfig, clearConfig, displayUrl } from './config.js';
4
+
5
+ async function apiCall(path, options = {}) {
6
+ const config = readConfig();
7
+ const url = `${config.serverUrl}${path}`;
8
+ const res = await fetch(url, {
9
+ ...options,
10
+ headers: {
11
+ 'Content-Type': 'application/json',
12
+ ...(options.headers || {}),
13
+ },
14
+ });
15
+ return res;
16
+ }
17
+
18
+ export function getToken() {
19
+ const config = readConfig();
20
+ return config.token || null;
21
+ }
22
+
23
+ export async function validateToken() {
24
+ const token = getToken();
25
+ if (!token) return null;
26
+
27
+ try {
28
+ const res = await apiCall('/api/auth/user', {
29
+ headers: { Authorization: `Bearer ${token}` },
30
+ });
31
+ if (!res.ok) return null;
32
+ const data = await res.json();
33
+ return data.user || null;
34
+ } catch {
35
+ return null;
36
+ }
37
+ }
38
+
39
+ export async function login(options = {}) {
40
+ // Allow --server flag to override the server URL
41
+ if (options.server) {
42
+ writeConfig({ serverUrl: options.server.replace(/\/+$/, '') });
43
+ }
44
+
45
+ console.log(chalk.bold('\n Upfyn Code — Login\n'));
46
+
47
+ const response = await prompts([
48
+ {
49
+ type: 'text',
50
+ name: 'username',
51
+ message: 'Username',
52
+ validate: v => (v.trim() ? true : 'Username is required'),
53
+ },
54
+ {
55
+ type: 'password',
56
+ name: 'password',
57
+ message: 'Password',
58
+ validate: v => (v ? true : 'Password is required'),
59
+ },
60
+ ], {
61
+ onCancel: () => {
62
+ console.log(chalk.dim('\n Login cancelled.\n'));
63
+ process.exit(0);
64
+ },
65
+ });
66
+
67
+ const { username, password } = response;
68
+
69
+ try {
70
+ const res = await apiCall('/api/auth/login', {
71
+ method: 'POST',
72
+ body: JSON.stringify({ username: username.trim(), password }),
73
+ });
74
+
75
+ const data = await res.json();
76
+
77
+ if (!res.ok) {
78
+ console.log(chalk.red(`\n Login failed: ${data.error || 'Unknown error'}\n`));
79
+ process.exit(1);
80
+ }
81
+
82
+ writeConfig({
83
+ token: data.token,
84
+ user: data.user,
85
+ });
86
+
87
+ const name = data.user.first_name || data.user.username;
88
+ console.log(chalk.green(`\n Logged in as ${chalk.bold(name)}!`));
89
+
90
+ // Auto-fetch and save relay token for one-command connect
91
+ try {
92
+ const config = readConfig();
93
+ const tokenRes = await fetch(`${config.serverUrl}/api/auth/connect-token`, {
94
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${data.token}` },
95
+ });
96
+ if (tokenRes.ok) {
97
+ const tokenData = await tokenRes.json();
98
+ if (tokenData.token) {
99
+ writeConfig({ relayKey: tokenData.token });
100
+ console.log(chalk.dim(' Relay token saved.'));
101
+ console.log(chalk.cyan(`\n Run ${chalk.bold('uc web connect')} to bridge your machine to the web UI.\n`));
102
+ }
103
+ }
104
+ } catch { /* best-effort — relay token fetch is optional */ }
105
+
106
+ if (!readConfig().relayKey) {
107
+ console.log('');
108
+ }
109
+ } catch (err) {
110
+ const config = readConfig();
111
+ console.log(chalk.red(`\n Connection error. Could not reach ${displayUrl(config.serverUrl)}.`));
112
+ console.log(chalk.dim(' Check your network and try again.\n'));
113
+ process.exit(1);
114
+ }
115
+ }
116
+
117
+ export async function logout() {
118
+ clearConfig();
119
+ console.log(chalk.green('\n Logged out. Credentials cleared.\n'));
120
+ }
121
+
122
+ export async function status() {
123
+ const config = readConfig();
124
+
125
+ if (!config.token) {
126
+ console.log(chalk.yellow('\n Not logged in. Run `uc login` to authenticate.\n'));
127
+ return;
128
+ }
129
+
130
+ console.log(chalk.dim('\n Checking session...'));
131
+ const user = await validateToken();
132
+
133
+ if (!user) {
134
+ console.log(chalk.yellow(' Session expired. Run `uc login` to re-authenticate.\n'));
135
+ return;
136
+ }
137
+
138
+ const name = user.first_name || user.username;
139
+ console.log(chalk.bold(` Logged in as: ${chalk.cyan(name)} (${chalk.dim(user.username)})`));
140
+ console.log(chalk.dim(` Server: ${displayUrl(config.serverUrl)}`));
141
+ console.log(chalk.dim(` Local port: ${config.localPort}\n`));
142
+ }
package/src/config.js ADDED
@@ -0,0 +1,40 @@
1
+ import { readFileSync, writeFileSync, mkdirSync } from 'fs';
2
+ import { homedir } from 'os';
3
+ import { join, dirname } from 'path';
4
+
5
+ const CONFIG_PATH = join(homedir(), '.upfynrc');
6
+
7
+ const DEFAULTS = {
8
+ serverUrl: 'https://upfynai-code-production.up.railway.app',
9
+ localPort: 4200,
10
+ };
11
+
12
+ export function readConfig() {
13
+ try {
14
+ const raw = readFileSync(CONFIG_PATH, 'utf-8');
15
+ return { ...DEFAULTS, ...JSON.parse(raw) };
16
+ } catch {
17
+ return { ...DEFAULTS };
18
+ }
19
+ }
20
+
21
+ export function writeConfig(data) {
22
+ const existing = readConfig();
23
+ const merged = { ...existing, ...data };
24
+ mkdirSync(dirname(CONFIG_PATH), { recursive: true });
25
+ writeFileSync(CONFIG_PATH, JSON.stringify(merged, null, 2) + '\n', 'utf-8');
26
+ return merged;
27
+ }
28
+
29
+ export function clearConfig() {
30
+ writeFileSync(CONFIG_PATH, JSON.stringify(DEFAULTS, null, 2) + '\n', 'utf-8');
31
+ }
32
+
33
+ /** Display-friendly server label — masks the internal URL */
34
+ export function displayUrl(url) {
35
+ if (!url || url === DEFAULTS.serverUrl) return 'Upfyn Cloud';
36
+ // Custom server — show the hostname only
37
+ try { return new URL(url).host; } catch { return url; }
38
+ }
39
+
40
+ export { CONFIG_PATH, DEFAULTS };