upfynai-code 2.2.0 → 2.4.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.
- package/client/dist/assets/AppContent-DTZ2FbvM.js +513 -0
- package/client/dist/assets/CanvasPanel-DlTW6Jh6.js +6 -0
- package/client/dist/assets/LoginModal-CWoFm0au.js +19 -0
- package/client/dist/assets/MarkdownPreview-CYdvwJaV.js +1 -0
- package/client/dist/assets/{Onboarding-Coxo6mFA.js → Onboarding-CtIoXiTp.js} +1 -1
- package/client/dist/assets/{SetupForm-BzYOsbji.js → SetupForm-B4p8im5O.js} +1 -1
- package/client/dist/assets/{ar-SA-G6X2FPQ2-Bmw2-hDt.js → ar-SA-G6X2FPQ2-2gfmdvHk.js} +1 -1
- package/client/dist/assets/{arc-BMqY7_Ci.js → arc-DCZSHhoJ.js} +1 -1
- package/client/dist/assets/{az-AZ-76LH7QW2-Dh1le_qs.js → az-AZ-76LH7QW2-CDdeucRZ.js} +1 -1
- package/client/dist/assets/{bg-BG-XCXSNQG7-Cbav8Z9z.js → bg-BG-XCXSNQG7-D6__XtOK.js} +1 -1
- package/client/dist/assets/{blockDiagram-38ab4fdb-ChHJxsXw.js → blockDiagram-38ab4fdb-Cfbaeyp6.js} +3 -3
- package/client/dist/assets/{bn-BD-2XOGV67Q-DCNjOaWz.js → bn-BD-2XOGV67Q-DHNJw3OG.js} +1 -1
- package/client/dist/assets/{c4Diagram-3d4e48cf-b8Xue4Z6.js → c4Diagram-3d4e48cf-BBCnjOTy.js} +1 -1
- package/client/dist/assets/{ca-ES-6MX7JW3Y-Dl_vM7NS.js → ca-ES-6MX7JW3Y-r5g4o3zQ.js} +1 -1
- package/client/dist/assets/channel-O3ovC0x9.js +1 -0
- package/client/dist/assets/{classDiagram-70f12bd4-BheP7Ggo.js → classDiagram-70f12bd4-D0lhAcxU.js} +1 -1
- package/client/dist/assets/classDiagram-v2-f2320105-BuwUsF3F.js +2 -0
- package/client/dist/assets/clone-BG9u7vLi.js +1 -0
- package/client/dist/assets/{createText-2e5e7dd3-_n4jI_fO.js → createText-2e5e7dd3-B8jCDmF_.js} +1 -1
- package/client/dist/assets/{cs-CZ-2BRQDIVT-ftsKDdz4.js → cs-CZ-2BRQDIVT-p08jRLRC.js} +1 -1
- package/client/dist/assets/{da-DK-5WZEPLOC-DAjdwGRO.js → da-DK-5WZEPLOC-CnhOImFf.js} +1 -1
- package/client/dist/assets/{de-DE-XR44H4JA-BJXczHGT.js → de-DE-XR44H4JA-BunSXZ-Y.js} +1 -1
- package/client/dist/assets/{edges-e0da2a9e-CfPZr4YM.js → edges-e0da2a9e-CGBBhG8k.js} +2 -2
- package/client/dist/assets/{el-GR-BZB4AONW-DW2p_uy7.js → el-GR-BZB4AONW-D4wv1oIz.js} +1 -1
- package/client/dist/assets/{erDiagram-9861fffd-CF33V-Of.js → erDiagram-9861fffd-CYaF3q1I.js} +1 -1
- package/client/dist/assets/{es-ES-U4NZUMDT-DLOIGnrl.js → es-ES-U4NZUMDT-CGeTKXgd.js} +1 -1
- package/client/dist/assets/{eu-ES-A7QVB2H4-LJXbf89m.js → eu-ES-A7QVB2H4-Cayx1TxR.js} +1 -1
- package/client/dist/assets/{fa-IR-HGAKTJCU-Dvx65fgW.js → fa-IR-HGAKTJCU-CmUg8pmw.js} +1 -1
- package/client/dist/assets/{fi-FI-Z5N7JZ37-EoL65BQh.js → fi-FI-Z5N7JZ37-xvHcPhsU.js} +1 -1
- package/client/dist/assets/{flowDb-956e92f1-HgoXVy2H.js → flowDb-956e92f1-C-_LFz70.js} +3 -3
- package/client/dist/assets/flowDiagram-66a62f08-C1sHdSjn.js +4 -0
- package/client/dist/assets/flowDiagram-v2-96b9c2cf-Cd0Iascd.js +1 -0
- package/client/dist/assets/{flowchart-elk-definition-4a651766-DJbI2dpv.js → flowchart-elk-definition-4a651766-CNGfpudb.js} +7 -7
- package/client/dist/assets/{fr-FR-RHASNOE6-DNk_jdDs.js → fr-FR-RHASNOE6-DBoHEcNj.js} +1 -1
- package/client/dist/assets/{ganttDiagram-c361ad54-2XX670FU.js → ganttDiagram-c361ad54-B8HJQqjt.js} +1 -1
- package/client/dist/assets/{gitGraphDiagram-72cf32ee-CcUfruAo.js → gitGraphDiagram-72cf32ee-DojCDvlS.js} +1 -1
- package/client/dist/assets/{gl-ES-HMX3MZ6V-dxzFjZlG.js → gl-ES-HMX3MZ6V-p6hrn2cN.js} +1 -1
- package/client/dist/assets/{graph-BSbiMSBC.js → graph-DXM7lcy1.js} +1 -1
- package/client/dist/assets/{he-IL-6SHJWFNN-Cogsfdt1.js → he-IL-6SHJWFNN-y2jEX6-0.js} +1 -1
- package/client/dist/assets/{hi-IN-IWLTKZ5I-L6wbgi4F.js → hi-IN-IWLTKZ5I-99pNfyWr.js} +1 -1
- package/client/dist/assets/{hu-HU-A5ZG7DT2-DSA6ZDsH.js → hu-HU-A5ZG7DT2-hygceGMS.js} +1 -1
- package/client/dist/assets/{id-ID-SAP4L64H-BK_vGGS6.js → id-ID-SAP4L64H-CyIqi1hv.js} +1 -1
- package/client/dist/assets/{image-blob-reduce.esm-BLtmMM_J.js → image-blob-reduce.esm-D6s-rqMO.js} +6 -1
- package/client/dist/assets/{index-3862675e-Bv32HUgT.js → index-3862675e-4idOQN2N.js} +1 -1
- package/client/dist/assets/{index-BPwf8Fw3.js → index-BGmwbRlb.js} +6 -6
- package/client/dist/assets/index-BHZfFT_V.js +97 -0
- package/client/dist/assets/{infoDiagram-f8f76790-w4mR4pxn.js → infoDiagram-f8f76790-CFLrHqtc.js} +1 -1
- package/client/dist/assets/{it-IT-JPQ66NNP-BLdHYMhn.js → it-IT-JPQ66NNP-DzVvVdQI.js} +1 -1
- package/client/dist/assets/{ja-JP-DBVTYXUO-B_vmexl_.js → ja-JP-DBVTYXUO-BI4fPexV.js} +1 -1
- package/client/dist/assets/{journeyDiagram-49397b02-D9nmO17e.js → journeyDiagram-49397b02-C3CFDo8z.js} +1 -1
- package/client/dist/assets/{kaa-6HZHGXH3-5s-3jl6F.js → kaa-6HZHGXH3-fwOleoQB.js} +1 -1
- package/client/dist/assets/{kab-KAB-ZGHBKWFO-2QaVDuSf.js → kab-KAB-ZGHBKWFO-DBI_ri48.js} +1 -1
- package/client/dist/assets/{kk-KZ-P5N5QNE5-CTC52Vbi.js → kk-KZ-P5N5QNE5-zpl7uvyF.js} +1 -1
- package/client/dist/assets/{km-KH-HSX4SM5Z-DxawH8UZ.js → km-KH-HSX4SM5Z-DOMFSres.js} +1 -1
- package/client/dist/assets/{ko-KR-MTYHY66A-CmosEM8_.js → ko-KR-MTYHY66A-tb08hXzd.js} +1 -1
- package/client/dist/assets/{ku-TR-6OUDTVRD-DbiLen4y.js → ku-TR-6OUDTVRD-DlIQCCY4.js} +1 -1
- package/client/dist/assets/{layout-jmt3H9tA.js → layout-B_11mCXA.js} +1 -1
- package/client/dist/assets/{line-JTlRayUJ.js → line-B-qmK_vI.js} +1 -1
- package/client/dist/assets/{linear-DJeB5p7x.js → linear-Ph6uuYcX.js} +1 -1
- package/client/dist/assets/{lt-LT-XHIRWOB4-CH15wrjA.js → lt-LT-XHIRWOB4--qWy24_Z.js} +1 -1
- package/client/dist/assets/{lv-LV-5QDEKY6T-dhgfPuCQ.js → lv-LV-5QDEKY6T-Bnd_1GDb.js} +1 -1
- package/client/dist/assets/mindmap-definition-fc14e90a-Do79tIc0.js +425 -0
- package/client/dist/assets/{mr-IN-CRQNXWMA-3Gi6iq7A.js → mr-IN-CRQNXWMA-BsV6HaD9.js} +1 -1
- package/client/dist/assets/{my-MM-5M5IBNSE-CpH4rdJj.js → my-MM-5M5IBNSE-kZQURVIi.js} +1 -1
- package/client/dist/assets/{nb-NO-T6EIAALU-Du6iiGql.js → nb-NO-T6EIAALU-Cvf9FdSF.js} +1 -1
- package/client/dist/assets/{nl-NL-IS3SIHDZ-BGvsd1MT.js → nl-NL-IS3SIHDZ-DA1yqpXw.js} +1 -1
- package/client/dist/assets/{nn-NO-6E72VCQL-B-odvJZW.js → nn-NO-6E72VCQL-89lm3vku.js} +1 -1
- package/client/dist/assets/{oc-FR-POXYY2M6-COC8xNjo.js → oc-FR-POXYY2M6-BsrjTJQh.js} +1 -1
- package/client/dist/assets/{pa-IN-N4M65BXN-CE21PUQH.js → pa-IN-N4M65BXN-CczefYaj.js} +1 -1
- package/client/dist/assets/pdf-CE_K4jFx.js +12 -0
- package/client/dist/assets/percentages-BXMCSKIN-Be6p9phi.js +207 -0
- package/client/dist/assets/pica-CQIY57Tf.js +7 -0
- package/client/dist/assets/{pieDiagram-8a3498a8-Cvfh7Qr5.js → pieDiagram-8a3498a8-CfblQHdm.js} +2 -2
- package/client/dist/assets/{pl-PL-T2D74RX3-D4xFVSoT.js → pl-PL-T2D74RX3-DdhH-zcK.js} +1 -1
- package/client/dist/assets/{pt-BR-5N22H2LF-CCq257gA.js → pt-BR-5N22H2LF-gpwlheL6.js} +1 -1
- package/client/dist/assets/{pt-PT-UZXXM6DQ-1l8gt5vA.js → pt-PT-UZXXM6DQ-Cs87vICi.js} +1 -1
- package/client/dist/assets/{quadrantDiagram-120e2f19-BA0js1aD.js → quadrantDiagram-120e2f19-CRMSamSP.js} +1 -1
- package/client/dist/assets/{requirementDiagram-deff3bca-B0QNFfIn.js → requirementDiagram-deff3bca-D3LBN016.js} +1 -1
- package/client/dist/assets/{ro-RO-JPDTUUEW-yosBW01E.js → ro-RO-JPDTUUEW-CWTSJ1Dt.js} +1 -1
- package/client/dist/assets/roundRect-0PYZxl1G.js +1 -0
- package/client/dist/assets/{ru-RU-B4JR7IUQ-8LkEJUix.js → ru-RU-B4JR7IUQ-Bq7aN2ep.js} +1 -1
- package/client/dist/assets/{sankeyDiagram-04a897e0-D4T9eCXn.js → sankeyDiagram-04a897e0-CsFqOQZN.js} +3 -3
- package/client/dist/assets/{sequenceDiagram-704730f1-CfBUTCrO.js → sequenceDiagram-704730f1-BRYXVDGX.js} +1 -1
- package/client/dist/assets/{si-LK-N5RQ5JYF-D8rjbqtd.js → si-LK-N5RQ5JYF-BBjcNYQh.js} +1 -1
- package/client/dist/assets/{sk-SK-C5VTKIMK-Bg14sAzN.js → sk-SK-C5VTKIMK-ByjKQzUb.js} +1 -1
- package/client/dist/assets/{sl-SI-NN7IZMDC-CMTib6Zs.js → sl-SI-NN7IZMDC-B8WCyMBU.js} +1 -1
- package/client/dist/assets/{stateDiagram-587899a1-BGgvmVSZ.js → stateDiagram-587899a1-BHoy9LtD.js} +1 -1
- package/client/dist/assets/{stateDiagram-v2-d93cdb3a-Qn3DpYuO.js → stateDiagram-v2-d93cdb3a-BvMUA6bS.js} +1 -1
- package/client/dist/assets/{styles-6aaf32cf-IdVZLPrD.js → styles-6aaf32cf-Dr-lfIOW.js} +2 -2
- package/client/dist/assets/{styles-9a916d00-BAC3L45X.js → styles-9a916d00-DS4wRpL7.js} +1 -1
- package/client/dist/assets/{styles-c10674c1-COhXxX8c.js → styles-c10674c1-nKRF6NrH.js} +1 -1
- package/client/dist/assets/{subset-shared.chunk-BWHnFai4.js → subset-shared.chunk-KT79s7KG.js} +64 -2
- package/client/dist/assets/subset-worker.chunk-BMx1eyv3.js +1 -0
- package/client/dist/assets/{sv-SE-XGPEYMSR-C1425rOF.js → sv-SE-XGPEYMSR-BiIPUVbv.js} +1 -1
- package/client/dist/assets/{svgDrawCommon-08f97a94-Cfk-fgnN.js → svgDrawCommon-08f97a94-C3uP9PYr.js} +1 -1
- package/client/dist/assets/{ta-IN-2NMHFXQM-BHHo1zpF.js → ta-IN-2NMHFXQM-Cidadso2.js} +1 -1
- package/client/dist/assets/{th-TH-HPSO5L25-CZVzm_WT.js → th-TH-HPSO5L25-CFNnJwSv.js} +1 -1
- package/client/dist/assets/{timeline-definition-85554ec2-VAvuJith.js → timeline-definition-85554ec2-BSsLsIgF.js} +1 -1
- package/client/dist/assets/{tr-TR-DEFEU3FU-DE1lclCq.js → tr-TR-DEFEU3FU-DaFcI-KL.js} +1 -1
- package/client/dist/assets/{uk-UA-QMV73CPH-D4lJZ85O.js → uk-UA-QMV73CPH-DkBW36St.js} +1 -1
- package/client/dist/assets/vendor-codemirror-langs-BH1ZcKHY.js +20 -0
- package/client/dist/assets/vendor-codemirror-rix45NST.js +16 -0
- package/client/dist/assets/vendor-i18n-DCFGyhQR.js +1 -0
- package/client/dist/assets/vendor-icons-Dh9m_Ydt.js +596 -0
- package/client/dist/assets/{vendor-markdown-CIVH08vJ.js → vendor-markdown-BXEi_H3G.js} +3 -3
- package/client/dist/assets/vendor-react-9mUTKBHH.js +67 -0
- package/client/dist/assets/{vendor-syntax-Djb62v3a.js → vendor-syntax-DnmwQQJF.js} +14 -7
- package/client/dist/assets/vendor-xterm-CZq1hqo1.js +66 -0
- package/client/dist/assets/vendor-xterm-qxJ8_QYu.css +32 -0
- package/client/dist/assets/{vi-VN-M7AON7JQ-Dgc_SShk.js → vi-VN-M7AON7JQ-KrtfxOzl.js} +1 -1
- package/client/dist/assets/{xychartDiagram-e933f94c-BeyVBJhb.js → xychartDiagram-e933f94c-CgNgZ4pp.js} +1 -1
- package/client/dist/assets/{zh-CN-LNUGB5OW-MH4Yh8in.js → zh-CN-LNUGB5OW-BQu12RoD.js} +1 -1
- package/client/dist/assets/{zh-HK-E62DVLB3-D4XHehjx.js → zh-HK-E62DVLB3-zx9CvERq.js} +1 -1
- package/client/dist/assets/{zh-TW-RAJ6MFWO--efj3evj.js → zh-TW-RAJ6MFWO-ffJWgVxn.js} +1 -1
- package/client/dist/index.html +6 -6
- package/commands/upfynai-connect.md +31 -18
- package/commands/upfynai.md +45 -26
- package/package.json +1 -1
- package/server/cli-ui.js +785 -0
- package/server/cli.js +235 -161
- package/server/index.js +159 -107
- package/server/middleware/auth.js +9 -5
- package/server/openrouter.js +137 -0
- package/server/relay-client.js +158 -47
- package/server/routes/agent.js +54 -19
- package/server/routes/auth.js +59 -22
- package/server/routes/settings.js +91 -0
- package/shared/modelConstants.js +29 -0
- package/client/dist/assets/AppContent-CTSHQdyq.js +0 -513
- package/client/dist/assets/CanvasPanel-Cig0Mo9s.js +0 -6
- package/client/dist/assets/LoginModal-silya-zP.js +0 -11
- package/client/dist/assets/MarkdownPreview-B3c7OEj6.js +0 -1
- package/client/dist/assets/channel-CSnvHe_M.js +0 -1
- package/client/dist/assets/classDiagram-v2-f2320105-xtym7GEZ.js +0 -2
- package/client/dist/assets/clone-B75abXxS.js +0 -1
- package/client/dist/assets/flowDiagram-66a62f08-tffoET0H.js +0 -4
- package/client/dist/assets/flowDiagram-v2-96b9c2cf-Byc3JCHh.js +0 -1
- package/client/dist/assets/index-D1urGMYu.js +0 -95
- package/client/dist/assets/mindmap-definition-fc14e90a-BOOrexmz.js +0 -415
- package/client/dist/assets/pdf-TYrZqVzP.js +0 -12
- package/client/dist/assets/percentages-BXMCSKIN-C9GT0OD3.js +0 -199
- package/client/dist/assets/pica-VkdyTzi8.js +0 -2
- package/client/dist/assets/roundRect-mAH3dD0p.js +0 -1
- package/client/dist/assets/subset-worker.chunk-C8QUSruZ.js +0 -1
- package/client/dist/assets/vendor-codemirror-BARtJV1V.js +0 -16
- package/client/dist/assets/vendor-codemirror-langs-52_y1wip.js +0 -20
- package/client/dist/assets/vendor-i18n-ByAl-gdx.js +0 -1
- package/client/dist/assets/vendor-icons-D33IkSIf.js +0 -1
- package/client/dist/assets/vendor-react-CHoMc7ka.js +0 -8
- package/client/dist/assets/vendor-xterm-DBb3RXlu.js +0 -66
- package/client/dist/assets/vendor-xterm-DrlLKa8f.css +0 -1
package/server/cli-ui.js
ADDED
|
@@ -0,0 +1,785 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upfyn-Code CLI — Terminal UI & Animations
|
|
3
|
+
*
|
|
4
|
+
* Beautiful blue-themed terminal experience inspired by Claude Code.
|
|
5
|
+
* Uses terminal-safe characters that render correctly on Windows CMD,
|
|
6
|
+
* PowerShell, Windows Terminal, Git Bash, macOS Terminal, and Linux.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// --- ANSI escape codes ---
|
|
10
|
+
const ESC = '\x1b';
|
|
11
|
+
const CSI = `${ESC}[`;
|
|
12
|
+
|
|
13
|
+
// Blue theme palette (24-bit RGB — works in all modern terminals)
|
|
14
|
+
const theme = {
|
|
15
|
+
// Core blues
|
|
16
|
+
blue: `${CSI}38;2;59;130;246m`, // #3B82F6
|
|
17
|
+
brightBlue: `${CSI}38;2;96;165;250m`, // #60A5FA
|
|
18
|
+
skyBlue: `${CSI}38;2;125;211;252m`, // #7DD3FC
|
|
19
|
+
deepBlue: `${CSI}38;2;30;58;138m`, // #1E3A8A
|
|
20
|
+
indigo: `${CSI}38;2;99;102;241m`, // #6366F1
|
|
21
|
+
violet: `${CSI}38;2;139;92;246m`, // #8B5CF6
|
|
22
|
+
|
|
23
|
+
// Accent
|
|
24
|
+
cyan: `${CSI}38;2;34;211;238m`, // #22D3EE
|
|
25
|
+
teal: `${CSI}38;2;45;212;191m`, // #2DD4BF
|
|
26
|
+
white: `${CSI}38;2;248;250;252m`, // #F8FAFC
|
|
27
|
+
gray: `${CSI}38;2;148;163;184m`, // #94A3B8
|
|
28
|
+
dimGray: `${CSI}38;2;71;85;105m`, // #475569
|
|
29
|
+
darkGray: `${CSI}38;2;51;65;85m`, // #334155
|
|
30
|
+
yellow: `${CSI}38;2;250;204;21m`, // #FACC15
|
|
31
|
+
green: `${CSI}38;2;74;222;128m`, // #4ADE80
|
|
32
|
+
red: `${CSI}38;2;248;113;113m`, // #F87171
|
|
33
|
+
orange: `${CSI}38;2;251;146;60m`, // #FB923C
|
|
34
|
+
|
|
35
|
+
// Background
|
|
36
|
+
bgDeep: `${CSI}48;2;15;23;42m`, // #0F172A
|
|
37
|
+
bgBlue: `${CSI}48;2;30;58;138m`, // #1E3A8A
|
|
38
|
+
bgBright: `${CSI}48;2;59;130;246m`, // #3B82F6
|
|
39
|
+
|
|
40
|
+
// Formatting
|
|
41
|
+
bold: `${CSI}1m`,
|
|
42
|
+
dim: `${CSI}2m`,
|
|
43
|
+
italic: `${CSI}3m`,
|
|
44
|
+
underline: `${CSI}4m`,
|
|
45
|
+
reset: `${CSI}0m`,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const t = theme;
|
|
49
|
+
const r = t.reset;
|
|
50
|
+
|
|
51
|
+
// --- Terminal capability detection ---
|
|
52
|
+
function detectTerminalSupport() {
|
|
53
|
+
// Windows Terminal, VS Code, modern terminals support full Unicode
|
|
54
|
+
if (process.env.WT_SESSION) return 'unicode';
|
|
55
|
+
if (process.env.TERM_PROGRAM === 'vscode') return 'unicode';
|
|
56
|
+
if (process.env.TERM_PROGRAM === 'iTerm.app') return 'unicode';
|
|
57
|
+
if (process.env.TERM_PROGRAM === 'Hyper') return 'unicode';
|
|
58
|
+
if (process.env.TERM === 'xterm-256color') return 'unicode';
|
|
59
|
+
if (process.env.TERM === 'xterm-kitty') return 'unicode';
|
|
60
|
+
if (process.env.COLORTERM === 'truecolor') return 'unicode';
|
|
61
|
+
|
|
62
|
+
// Windows without WT_SESSION — use ASCII
|
|
63
|
+
if (process.platform === 'win32') return 'ascii';
|
|
64
|
+
|
|
65
|
+
// Most modern Linux/Mac terminals support basic box-drawing
|
|
66
|
+
return 'unicode';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Box-drawing character sets
|
|
70
|
+
const CHARS_UNICODE = {
|
|
71
|
+
h: '\u2500', // ─
|
|
72
|
+
v: '\u2502', // │
|
|
73
|
+
tl: '\u250C', // ┌
|
|
74
|
+
tr: '\u2510', // ┐
|
|
75
|
+
bl: '\u2514', // └
|
|
76
|
+
br: '\u2518', // ┘
|
|
77
|
+
cross: '\u253C', // ┼
|
|
78
|
+
ltee: '\u251C', // ├
|
|
79
|
+
rtee: '\u2524', // ┤
|
|
80
|
+
ttee: '\u252C', // ┬
|
|
81
|
+
btee: '\u2534', // ┴
|
|
82
|
+
dot: '\u00B7', // ·
|
|
83
|
+
bullet: '\u2022', // •
|
|
84
|
+
star: '*',
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const CHARS_ASCII = {
|
|
88
|
+
h: '-',
|
|
89
|
+
v: '|',
|
|
90
|
+
tl: '+',
|
|
91
|
+
tr: '+',
|
|
92
|
+
bl: '+',
|
|
93
|
+
br: '+',
|
|
94
|
+
cross: '+',
|
|
95
|
+
ltee: '+',
|
|
96
|
+
rtee: '+',
|
|
97
|
+
ttee: '+',
|
|
98
|
+
btee: '+',
|
|
99
|
+
dot: '.',
|
|
100
|
+
bullet: '*',
|
|
101
|
+
star: '*',
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const termLevel = detectTerminalSupport();
|
|
105
|
+
const ch = termLevel === 'unicode' ? CHARS_UNICODE : CHARS_ASCII;
|
|
106
|
+
|
|
107
|
+
// Helper — colorize
|
|
108
|
+
const c = {
|
|
109
|
+
blue: (s) => `${t.blue}${s}${r}`,
|
|
110
|
+
bright: (s) => `${t.brightBlue}${s}${r}`,
|
|
111
|
+
sky: (s) => `${t.skyBlue}${s}${r}`,
|
|
112
|
+
cyan: (s) => `${t.cyan}${s}${r}`,
|
|
113
|
+
teal: (s) => `${t.teal}${s}${r}`,
|
|
114
|
+
white: (s) => `${t.bold}${t.white}${s}${r}`,
|
|
115
|
+
gray: (s) => `${t.gray}${s}${r}`,
|
|
116
|
+
dim: (s) => `${t.dimGray}${s}${r}`,
|
|
117
|
+
dark: (s) => `${t.darkGray}${s}${r}`,
|
|
118
|
+
green: (s) => `${t.green}${s}${r}`,
|
|
119
|
+
yellow: (s) => `${t.yellow}${s}${r}`,
|
|
120
|
+
red: (s) => `${t.red}${s}${r}`,
|
|
121
|
+
orange: (s) => `${t.orange}${s}${r}`,
|
|
122
|
+
violet: (s) => `${t.violet}${s}${r}`,
|
|
123
|
+
indigo: (s) => `${t.indigo}${s}${r}`,
|
|
124
|
+
bold: (s) => `${t.bold}${s}${r}`,
|
|
125
|
+
bBlue: (s) => `${t.bold}${t.blue}${s}${r}`,
|
|
126
|
+
bBright: (s) => `${t.bold}${t.brightBlue}${s}${r}`,
|
|
127
|
+
bWhite: (s) => `${t.bold}${t.white}${s}${r}`,
|
|
128
|
+
bCyan: (s) => `${t.bold}${t.cyan}${s}${r}`,
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// --- ASCII Art Logo ---
|
|
132
|
+
const LOGO = [
|
|
133
|
+
`${t.brightBlue} __ __ ____ ${t.skyBlue} ______ __ ${r}`,
|
|
134
|
+
`${t.brightBlue} / / / /___ / __/_ ______ ${t.skyBlue}/ ____/___ ____/ /__ ${r}`,
|
|
135
|
+
`${t.brightBlue} / / / / __ \\/ /_/ / / / __ \\ ${t.blue}____${t.skyBlue}/ / / __ \\/ __ / _ \\ ${r}`,
|
|
136
|
+
`${t.brightBlue} / /_/ / /_/ / __/ /_/ / / / / ${t.blue}/___ ${t.skyBlue}/ /___/ /_/ / /_/ / __/ ${r}`,
|
|
137
|
+
`${t.brightBlue} \\____/ .___/_/ \\__, /_/ /_/ ${t.skyBlue}\\____/\\____/\\__,_/\\___/ ${r}`,
|
|
138
|
+
`${t.brightBlue} /_/ /____/ ${r}`,
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
// --- Rocket ASCII Art (safe characters only) ---
|
|
142
|
+
const ROCKET_FRAMES = [
|
|
143
|
+
// Frame 0: Pre-launch
|
|
144
|
+
[
|
|
145
|
+
` ${t.dimGray}|${r}`,
|
|
146
|
+
` ${t.white}/${t.brightBlue}^${t.white}\\${r}`,
|
|
147
|
+
` ${t.white}|${t.blue}||${t.white}|${r}`,
|
|
148
|
+
` ${t.white}|${t.blue}||${t.white}|${r}`,
|
|
149
|
+
` ${t.white}|${t.brightBlue}||${t.white}|${r}`,
|
|
150
|
+
` ${t.white}/${t.blue}|||${t.white}\\${r}`,
|
|
151
|
+
` ${t.white}/${t.blue}=====${t.white}\\${r}`,
|
|
152
|
+
` ${t.dimGray}==========${r}`,
|
|
153
|
+
],
|
|
154
|
+
// Frame 1: Ignition
|
|
155
|
+
[
|
|
156
|
+
` ${t.dimGray}|${r}`,
|
|
157
|
+
` ${t.white}/${t.brightBlue}^${t.white}\\${r}`,
|
|
158
|
+
` ${t.white}|${t.blue}||${t.white}|${r}`,
|
|
159
|
+
` ${t.white}|${t.blue}||${t.white}|${r}`,
|
|
160
|
+
` ${t.white}|${t.brightBlue}||${t.white}|${r}`,
|
|
161
|
+
` ${t.white}/${t.blue}|||${t.white}\\${r}`,
|
|
162
|
+
` ${t.white}/${t.blue}=====${t.white}\\${r}`,
|
|
163
|
+
` ${t.orange}#${t.yellow}*${t.orange}#${t.yellow}*${t.orange}#${r}`,
|
|
164
|
+
],
|
|
165
|
+
// Frame 2: Lift-off
|
|
166
|
+
[
|
|
167
|
+
` ${t.white}/${t.brightBlue}^${t.white}\\${r}`,
|
|
168
|
+
` ${t.white}|${t.blue}||${t.white}|${r}`,
|
|
169
|
+
` ${t.white}|${t.blue}||${t.white}|${r}`,
|
|
170
|
+
` ${t.white}|${t.brightBlue}||${t.white}|${r}`,
|
|
171
|
+
` ${t.white}/${t.blue}|||${t.white}\\${r}`,
|
|
172
|
+
` ${t.white}/${t.blue}=====${t.white}\\${r}`,
|
|
173
|
+
` ${t.yellow}#${t.orange}@${t.yellow}#${t.orange}@${t.yellow}#${r}`,
|
|
174
|
+
` ${t.orange}*${t.yellow}o${t.orange}*${r}`,
|
|
175
|
+
],
|
|
176
|
+
// Frame 3: Ascending
|
|
177
|
+
[
|
|
178
|
+
` ${t.white}/${t.brightBlue}^${t.white}\\${r}`,
|
|
179
|
+
` ${t.white}|${t.blue}||${t.white}|${r}`,
|
|
180
|
+
` ${t.white}|${t.brightBlue}||${t.white}|${r}`,
|
|
181
|
+
` ${t.white}/${t.blue}|||${t.white}\\${r}`,
|
|
182
|
+
` ${t.white}/${t.blue}=====${t.white}\\${r}`,
|
|
183
|
+
` ${t.yellow}@${t.orange}#${t.yellow}@${t.orange}#${t.yellow}@${r}`,
|
|
184
|
+
` ${t.orange}#${t.yellow}@${t.orange}#${r}`,
|
|
185
|
+
` ${t.yellow}*${t.orange}*${r}`,
|
|
186
|
+
],
|
|
187
|
+
// Frame 4: Full thrust
|
|
188
|
+
[
|
|
189
|
+
` ${t.white}/${t.brightBlue}^${t.white}\\${r}`,
|
|
190
|
+
` ${t.white}|${t.blue}||${t.white}|${r}`,
|
|
191
|
+
` ${t.white}|${t.brightBlue}||${t.white}|${r}`,
|
|
192
|
+
` ${t.white}/${t.blue}|||${t.white}\\${r}`,
|
|
193
|
+
` ${t.white}/${t.blue}=====${t.white}\\${r}`,
|
|
194
|
+
` ${t.yellow}@${t.orange}#${t.yellow}@${t.orange}#${t.yellow}@${t.orange}#${r}`,
|
|
195
|
+
` ${t.orange}#${t.yellow}@${t.orange}#${t.yellow}@${r}`,
|
|
196
|
+
` ${t.yellow}o${t.orange}*${t.yellow}o${r}`,
|
|
197
|
+
` ${t.orange}*${t.yellow}*${r}`,
|
|
198
|
+
],
|
|
199
|
+
// Frame 5: Going up
|
|
200
|
+
[
|
|
201
|
+
``,
|
|
202
|
+
` ${t.white}/${t.brightBlue}^${t.white}\\${r}`,
|
|
203
|
+
` ${t.white}|${t.blue}||${t.white}|${r}`,
|
|
204
|
+
` ${t.white}/${t.blue}|||${t.white}\\${r}`,
|
|
205
|
+
` ${t.white}/${t.blue}=====${t.white}\\${r}`,
|
|
206
|
+
` ${t.yellow}@${t.orange}#${t.yellow}@${t.orange}#${t.yellow}@${t.orange}#${r}`,
|
|
207
|
+
` ${t.orange}@${t.yellow}#${t.orange}@${t.yellow}#${r}`,
|
|
208
|
+
` ${t.yellow}o${t.orange}o${t.yellow}o${r}`,
|
|
209
|
+
` ${t.orange}*${r} ${t.dimGray}.${r}`,
|
|
210
|
+
],
|
|
211
|
+
// Frame 6: Higher
|
|
212
|
+
[
|
|
213
|
+
``,
|
|
214
|
+
``,
|
|
215
|
+
` ${t.skyBlue}/${t.brightBlue}^${t.skyBlue}\\${r}`,
|
|
216
|
+
` ${t.skyBlue}|${t.blue}||${t.skyBlue}|${r}`,
|
|
217
|
+
` ${t.skyBlue}/${t.blue}==${t.skyBlue}\\${r}`,
|
|
218
|
+
` ${t.yellow}#${t.orange}@${t.yellow}#${t.orange}#${r}`,
|
|
219
|
+
` ${t.orange}o${t.yellow}o${r}`,
|
|
220
|
+
` ${t.yellow}*${r}`,
|
|
221
|
+
` ${t.dimGray}.${r} ${t.dimGray}.${r}`,
|
|
222
|
+
],
|
|
223
|
+
// Frame 7: Almost gone
|
|
224
|
+
[
|
|
225
|
+
``,
|
|
226
|
+
``,
|
|
227
|
+
``,
|
|
228
|
+
` ${t.skyBlue}/${t.brightBlue}^${t.skyBlue}\\${r}`,
|
|
229
|
+
` ${t.blue}==${r}`,
|
|
230
|
+
` ${t.orange}o${t.yellow}o${r}`,
|
|
231
|
+
` ${t.yellow}*${r}`,
|
|
232
|
+
``,
|
|
233
|
+
` ${t.dimGray}.${r} ${t.dimGray}.${r} ${t.dimGray}.${r}`,
|
|
234
|
+
],
|
|
235
|
+
// Frame 8: Gone — just stars
|
|
236
|
+
[
|
|
237
|
+
``,
|
|
238
|
+
``,
|
|
239
|
+
``,
|
|
240
|
+
` ${t.brightBlue}*${r}`,
|
|
241
|
+
``,
|
|
242
|
+
` ${t.dimGray}.${r}`,
|
|
243
|
+
``,
|
|
244
|
+
` ${t.dimGray}.${r} ${t.dimGray}.${r}`,
|
|
245
|
+
` ${t.dimGray}.${r} ${t.dimGray}.${r} ${t.dimGray}.${r}`,
|
|
246
|
+
],
|
|
247
|
+
];
|
|
248
|
+
|
|
249
|
+
// --- Sleep utility ---
|
|
250
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
251
|
+
|
|
252
|
+
// --- Clear screen ---
|
|
253
|
+
const clearScreen = () => process.stdout.write(`${CSI}2J${CSI}H`);
|
|
254
|
+
|
|
255
|
+
// --- Move cursor ---
|
|
256
|
+
const moveTo = (row, col) => process.stdout.write(`${CSI}${row};${col}H`);
|
|
257
|
+
|
|
258
|
+
// --- Hide/show cursor ---
|
|
259
|
+
const hideCursor = () => process.stdout.write(`${CSI}?25l`);
|
|
260
|
+
const showCursor = () => process.stdout.write(`${CSI}?25h`);
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Strip ANSI codes for length calculation
|
|
264
|
+
*/
|
|
265
|
+
function stripAnsi(str) {
|
|
266
|
+
return str.replace(/\x1b\[[0-9;]*m/g, '');
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Pad a string (with ANSI codes) to a visual width
|
|
271
|
+
*/
|
|
272
|
+
function padAnsi(str, width) {
|
|
273
|
+
const visible = stripAnsi(str).length;
|
|
274
|
+
const pad = Math.max(0, width - visible);
|
|
275
|
+
return str + ' '.repeat(pad);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Draw a horizontal line
|
|
280
|
+
*/
|
|
281
|
+
function hLine(width = 60) {
|
|
282
|
+
return c.dark(ch.h.repeat(width));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Play the rocket launch animation
|
|
287
|
+
*/
|
|
288
|
+
async function playRocketAnimation() {
|
|
289
|
+
hideCursor();
|
|
290
|
+
clearScreen();
|
|
291
|
+
|
|
292
|
+
const cols = process.stdout.columns || 80;
|
|
293
|
+
const centerX = Math.floor(cols / 2) - 12;
|
|
294
|
+
|
|
295
|
+
// Show pre-launch text
|
|
296
|
+
moveTo(2, centerX - 5);
|
|
297
|
+
process.stdout.write(c.dim('Initializing Upfyn-Code...'));
|
|
298
|
+
|
|
299
|
+
await sleep(400);
|
|
300
|
+
|
|
301
|
+
// Play each frame
|
|
302
|
+
const delays = [500, 300, 200, 150, 120, 120, 150, 200, 400];
|
|
303
|
+
|
|
304
|
+
for (let f = 0; f < ROCKET_FRAMES.length; f++) {
|
|
305
|
+
// Clear the animation area (rows 4-14)
|
|
306
|
+
for (let row = 4; row <= 14; row++) {
|
|
307
|
+
moveTo(row, 1);
|
|
308
|
+
process.stdout.write(' '.repeat(cols));
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const frame = ROCKET_FRAMES[f];
|
|
312
|
+
for (let i = 0; i < frame.length; i++) {
|
|
313
|
+
moveTo(4 + i, centerX);
|
|
314
|
+
process.stdout.write(frame[i]);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Status text under animation
|
|
318
|
+
moveTo(14, centerX - 2);
|
|
319
|
+
if (f === 0) process.stdout.write(c.dim('Systems check...'));
|
|
320
|
+
else if (f === 1) process.stdout.write(c.orange('Ignition sequence started'));
|
|
321
|
+
else if (f === 2) process.stdout.write(c.yellow('Lift-off!'));
|
|
322
|
+
else if (f <= 4) process.stdout.write(c.bright('Ascending...'));
|
|
323
|
+
else if (f <= 6) process.stdout.write(c.sky('Reaching orbit...'));
|
|
324
|
+
else if (f === 7) process.stdout.write(c.cyan('Entering space...'));
|
|
325
|
+
else process.stdout.write(c.bBright('Ready to code! *'));
|
|
326
|
+
|
|
327
|
+
await sleep(delays[f] || 200);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
await sleep(300);
|
|
331
|
+
showCursor();
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Draw a box with title (terminal-safe characters)
|
|
336
|
+
*/
|
|
337
|
+
function box(title, content, width = 58) {
|
|
338
|
+
const lines = [];
|
|
339
|
+
const inner = width - 4;
|
|
340
|
+
|
|
341
|
+
lines.push(` ${t.dimGray}${ch.tl}${ch.h}${r} ${c.bBright(title)} ${t.dimGray}${ch.h.repeat(Math.max(0, inner - title.length - 1))}${ch.tr}${r}`);
|
|
342
|
+
|
|
343
|
+
for (const line of content) {
|
|
344
|
+
lines.push(` ${t.dimGray}${ch.v}${r} ${line}`);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
lines.push(` ${t.dimGray}${ch.bl}${ch.h.repeat(width - 2)}${ch.br}${r}`);
|
|
348
|
+
return lines;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Show the main welcome screen (Claude Code-style layout)
|
|
353
|
+
*/
|
|
354
|
+
function showWelcomeScreen(version, options = {}) {
|
|
355
|
+
const cols = process.stdout.columns || 80;
|
|
356
|
+
const { serverUrl, username, cwd, isConnected } = options;
|
|
357
|
+
const W = Math.min(cols - 4, 72); // content width
|
|
358
|
+
const leftW = 32;
|
|
359
|
+
const rightW = W - leftW - 3; // 3 for separator + padding
|
|
360
|
+
|
|
361
|
+
clearScreen();
|
|
362
|
+
|
|
363
|
+
const lines = [];
|
|
364
|
+
|
|
365
|
+
// --- Top border with version ---
|
|
366
|
+
const verStr = `Upfyn-Code v${version}`;
|
|
367
|
+
const topPad = Math.max(0, W - verStr.length - 4);
|
|
368
|
+
lines.push('');
|
|
369
|
+
lines.push(` ${t.dimGray}${ch.h}${ch.h} ${r}${c.bBright(verStr)}${t.dimGray} ${ch.h.repeat(topPad)}${r}`);
|
|
370
|
+
lines.push('');
|
|
371
|
+
|
|
372
|
+
// --- Build left and right panels ---
|
|
373
|
+
const leftPanel = [];
|
|
374
|
+
const rightPanel = [];
|
|
375
|
+
|
|
376
|
+
// Left: Welcome + Rocket mascot
|
|
377
|
+
leftPanel.push(c.bWhite(' Welcome back!'));
|
|
378
|
+
leftPanel.push('');
|
|
379
|
+
leftPanel.push(` ${t.dimGray}|${r}`);
|
|
380
|
+
leftPanel.push(` ${t.white}/${t.brightBlue}^${t.white}\\${r}`);
|
|
381
|
+
leftPanel.push(` ${t.white}|${t.blue}|${t.brightBlue}o${t.blue}|${t.white}|${r}`);
|
|
382
|
+
leftPanel.push(` ${t.white}|${t.blue}||${t.white}|${r}`);
|
|
383
|
+
leftPanel.push(` ${t.white}/${t.blue}===${t.white}\\${r}`);
|
|
384
|
+
leftPanel.push(` ${t.cyan}~~~~~${r}`);
|
|
385
|
+
leftPanel.push('');
|
|
386
|
+
if (username) {
|
|
387
|
+
leftPanel.push(` ${c.gray('User:')} ${c.bright(username)}`);
|
|
388
|
+
}
|
|
389
|
+
leftPanel.push(` ${c.gray('Path:')} ${c.dim(cwd || process.cwd())}`);
|
|
390
|
+
|
|
391
|
+
// Right: Tips + Recent Activity
|
|
392
|
+
rightPanel.push(` ${c.bCyan('Tips for getting started')}`);
|
|
393
|
+
rightPanel.push(` ${c.gray('Run')} ${c.bright('uc connect')} ${c.gray('to bridge to web UI')}`);
|
|
394
|
+
rightPanel.push(` ${c.gray('Run')} ${c.bright('uc start')} ${c.gray('to launch local server')}`);
|
|
395
|
+
rightPanel.push(` ${c.gray('Run')} ${c.bright('uc status')} ${c.gray('to see configuration')}`);
|
|
396
|
+
rightPanel.push(` ${c.gray('Run')} ${c.bright('uc help')} ${c.gray('for all commands')}`);
|
|
397
|
+
rightPanel.push('');
|
|
398
|
+
rightPanel.push(` ${c.bCyan('Recent activity')}`);
|
|
399
|
+
if (isConnected) {
|
|
400
|
+
rightPanel.push(` ${c.green('*')} Connected to ${c.bright(serverUrl || 'server')}`);
|
|
401
|
+
} else {
|
|
402
|
+
rightPanel.push(` ${c.dim('No active connection')}`);
|
|
403
|
+
}
|
|
404
|
+
rightPanel.push('');
|
|
405
|
+
if (serverUrl) {
|
|
406
|
+
rightPanel.push(` ${c.gray('Server:')} ${c.cyan(serverUrl)}`);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Merge panels side by side
|
|
410
|
+
const maxRows = Math.max(leftPanel.length, rightPanel.length);
|
|
411
|
+
|
|
412
|
+
for (let i = 0; i < maxRows; i++) {
|
|
413
|
+
const left = padAnsi(leftPanel[i] || '', leftW);
|
|
414
|
+
const right = rightPanel[i] || '';
|
|
415
|
+
lines.push(`${left}${t.dimGray}${ch.v}${r} ${right}`);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
lines.push('');
|
|
419
|
+
|
|
420
|
+
// --- Bottom border ---
|
|
421
|
+
lines.push(` ${t.dimGray}${ch.h.repeat(W)}${r}`);
|
|
422
|
+
lines.push('');
|
|
423
|
+
|
|
424
|
+
// --- Status bar ---
|
|
425
|
+
const statusItems = [];
|
|
426
|
+
if (isConnected) {
|
|
427
|
+
statusItems.push(`${t.green}* Connected${r}`);
|
|
428
|
+
} else {
|
|
429
|
+
statusItems.push(`${t.dimGray}o Not connected${r}`);
|
|
430
|
+
}
|
|
431
|
+
statusItems.push(`${t.gray}v${version}${r}`);
|
|
432
|
+
|
|
433
|
+
lines.push(` ${statusItems.join(` ${t.dimGray}${ch.dot}${r} `)}`);
|
|
434
|
+
lines.push('');
|
|
435
|
+
|
|
436
|
+
// --- Input prompt area (between two lines like Claude Code) ---
|
|
437
|
+
lines.push(` ${t.dimGray}${ch.h.repeat(W)}${r}`);
|
|
438
|
+
lines.push(` ${t.brightBlue}>${r} ${c.dim('Type a command or use /upfynai-connect ...')}`);
|
|
439
|
+
lines.push(` ${t.dimGray}${ch.h.repeat(W)}${r}`);
|
|
440
|
+
lines.push('');
|
|
441
|
+
|
|
442
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Show connection success banner
|
|
447
|
+
*/
|
|
448
|
+
function showConnectionBanner(username, serverUrl) {
|
|
449
|
+
const W = 50;
|
|
450
|
+
const lines = [];
|
|
451
|
+
const bLine = (content) => ` ${t.green}${ch.v}${r}${padAnsi(content, W)}${t.green}${ch.v}${r}`;
|
|
452
|
+
lines.push('');
|
|
453
|
+
lines.push(` ${t.green}${ch.tl}${ch.h.repeat(W)}${ch.tr}${r}`);
|
|
454
|
+
lines.push(bLine(` ${c.green('OK')} ${c.bWhite('Connected successfully!')}`));
|
|
455
|
+
lines.push(bLine(''));
|
|
456
|
+
lines.push(bLine(` ${c.gray('User:')} ${c.bright(username || 'Unknown')}`));
|
|
457
|
+
lines.push(bLine(` ${c.gray('Server:')} ${c.cyan(serverUrl || 'Unknown')}`));
|
|
458
|
+
lines.push(bLine(''));
|
|
459
|
+
lines.push(bLine(` ${c.dim('Your machine is bridged to the web UI.')}`));
|
|
460
|
+
lines.push(bLine(` ${c.dim('Press Ctrl+C to disconnect.')}`));
|
|
461
|
+
lines.push(` ${t.green}${ch.bl}${ch.h.repeat(W)}${ch.br}${r}`);
|
|
462
|
+
lines.push('');
|
|
463
|
+
|
|
464
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Show a spinner with message
|
|
469
|
+
*/
|
|
470
|
+
function createSpinner(message) {
|
|
471
|
+
const frames = ['/', '-', '\\', '|'];
|
|
472
|
+
let i = 0;
|
|
473
|
+
let interval;
|
|
474
|
+
|
|
475
|
+
return {
|
|
476
|
+
start() {
|
|
477
|
+
hideCursor();
|
|
478
|
+
interval = setInterval(() => {
|
|
479
|
+
const frame = frames[i % frames.length];
|
|
480
|
+
process.stdout.write(`\r ${t.brightBlue}${frame}${r} ${c.gray(message)}`);
|
|
481
|
+
i++;
|
|
482
|
+
}, 100);
|
|
483
|
+
},
|
|
484
|
+
stop(finalMessage) {
|
|
485
|
+
clearInterval(interval);
|
|
486
|
+
process.stdout.write(`\r ${c.green('OK')} ${c.white(finalMessage || message)}${''.padEnd(20)}\n`);
|
|
487
|
+
showCursor();
|
|
488
|
+
},
|
|
489
|
+
fail(finalMessage) {
|
|
490
|
+
clearInterval(interval);
|
|
491
|
+
process.stdout.write(`\r ${c.red('FAIL')} ${c.red(finalMessage || message)}${''.padEnd(20)}\n`);
|
|
492
|
+
showCursor();
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Show styled help
|
|
499
|
+
*/
|
|
500
|
+
function showStyledHelp(version) {
|
|
501
|
+
const W = 60;
|
|
502
|
+
const lines = [];
|
|
503
|
+
|
|
504
|
+
lines.push('');
|
|
505
|
+
// Header box — build each line to exactly W visible chars inside the borders
|
|
506
|
+
const hdrLine1 = ` ${c.bBright('Upfyn-Code')} ${c.dim('--')} ${c.gray('by Thinqmesh Technologies')}`;
|
|
507
|
+
const hdrLine2 = ` ${c.dim('Visual AI Coding Interface with Upfyn-Canvas')}`;
|
|
508
|
+
lines.push(` ${t.brightBlue}${ch.tl}${ch.h.repeat(W)}${ch.tr}${r}`);
|
|
509
|
+
lines.push(` ${t.brightBlue}${ch.v}${r}${padAnsi(hdrLine1, W)}${t.brightBlue}${ch.v}${r}`);
|
|
510
|
+
lines.push(` ${t.brightBlue}${ch.v}${r}${padAnsi(hdrLine2, W)}${t.brightBlue}${ch.v}${r}`);
|
|
511
|
+
lines.push(` ${t.brightBlue}${ch.bl}${ch.h.repeat(W)}${ch.br}${r}`);
|
|
512
|
+
lines.push('');
|
|
513
|
+
|
|
514
|
+
// Usage
|
|
515
|
+
lines.push(` ${c.bBright('Usage:')}`);
|
|
516
|
+
lines.push(` ${c.bright('uc')} ${c.cyan('[command]')} ${c.dim('[options]')}`);
|
|
517
|
+
lines.push('');
|
|
518
|
+
|
|
519
|
+
// Commands
|
|
520
|
+
lines.push(` ${c.bBright('Commands:')}`);
|
|
521
|
+
const cmds = [
|
|
522
|
+
['(default)', 'Launch Claude Code with Upfyn branding'],
|
|
523
|
+
['start', 'Start the local server only'],
|
|
524
|
+
['connect', 'Connect local machine to hosted server'],
|
|
525
|
+
['config', 'View/set configuration (API key, etc.)'],
|
|
526
|
+
['status', 'Show configuration and data locations'],
|
|
527
|
+
['install-commands', 'Install /upfynai-* slash commands'],
|
|
528
|
+
['uninstall-commands', 'Remove /upfynai-* slash commands'],
|
|
529
|
+
['update', 'Update to the latest version'],
|
|
530
|
+
['help', 'Show this help information'],
|
|
531
|
+
['version', 'Show version information'],
|
|
532
|
+
];
|
|
533
|
+
for (const [cmd, desc] of cmds) {
|
|
534
|
+
lines.push(` ${c.cyan(cmd.padEnd(22))} ${c.gray(desc)}`);
|
|
535
|
+
}
|
|
536
|
+
lines.push('');
|
|
537
|
+
|
|
538
|
+
// Slash Commands
|
|
539
|
+
lines.push(` ${c.bBright('Slash Commands')} ${c.dim('(inside Claude Code CLI):')}`);
|
|
540
|
+
const slashCmds = [
|
|
541
|
+
['/upfynai', 'Start the web UI server'],
|
|
542
|
+
['/upfynai-connect', 'Connect CLI session to web UI'],
|
|
543
|
+
['/upfynai-disconnect', 'Disconnect from web UI'],
|
|
544
|
+
['/upfynai-status', 'Show connection status'],
|
|
545
|
+
['/upfynai-doctor', 'Run diagnostics'],
|
|
546
|
+
];
|
|
547
|
+
for (const [cmd, desc] of slashCmds) {
|
|
548
|
+
lines.push(` ${c.violet(cmd.padEnd(22))} ${c.gray(desc)}`);
|
|
549
|
+
}
|
|
550
|
+
lines.push('');
|
|
551
|
+
|
|
552
|
+
// Options
|
|
553
|
+
lines.push(` ${c.bBright('Options:')}`);
|
|
554
|
+
const opts = [
|
|
555
|
+
['-p, --port <port>', 'Set server port (default: 3001)'],
|
|
556
|
+
['--server <url>', 'Server URL for connect'],
|
|
557
|
+
['--key <token>', 'Relay token for connect'],
|
|
558
|
+
['--api-key <key>', 'Set Anthropic API key'],
|
|
559
|
+
['--database-path <path>', 'Custom database location'],
|
|
560
|
+
['-h, --help', 'Show help'],
|
|
561
|
+
['-v, --version', 'Show version'],
|
|
562
|
+
];
|
|
563
|
+
for (const [opt, desc] of opts) {
|
|
564
|
+
lines.push(` ${c.yellow(opt.padEnd(28))} ${c.gray(desc)}`);
|
|
565
|
+
}
|
|
566
|
+
lines.push('');
|
|
567
|
+
|
|
568
|
+
// Examples
|
|
569
|
+
lines.push(` ${c.bBright('Examples:')}`);
|
|
570
|
+
lines.push(` ${c.dim('$')} ${c.bright('uc')} ${c.dim('# Launch Claude Code')}`);
|
|
571
|
+
lines.push(` ${c.dim('$')} ${c.bright('uc connect --key upfyn_xxx')} ${c.dim('# Bridge to hosted server')}`);
|
|
572
|
+
lines.push(` ${c.dim('$')} ${c.bright('uc config --api-key sk-ant-xxx')} ${c.dim('# Save Anthropic API key')}`);
|
|
573
|
+
lines.push(` ${c.dim('$')} ${c.bright('uc start --port 8080')} ${c.dim('# Start on port 8080')}`);
|
|
574
|
+
lines.push(` ${c.dim('$')} ${c.bright('uc status')} ${c.dim('# Show configuration')}`);
|
|
575
|
+
lines.push('');
|
|
576
|
+
|
|
577
|
+
// Footer
|
|
578
|
+
lines.push(` ${c.dim('Documentation:')} ${c.cyan('https://cli.upfyn.com/docs')}`);
|
|
579
|
+
lines.push(` ${c.dim('Report Issues:')} ${c.cyan('https://github.com/thinqmesh/upfynai-code/issues')}`);
|
|
580
|
+
lines.push('');
|
|
581
|
+
|
|
582
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Show styled status
|
|
587
|
+
*/
|
|
588
|
+
function showStyledStatus(info) {
|
|
589
|
+
const lines = [];
|
|
590
|
+
|
|
591
|
+
lines.push('');
|
|
592
|
+
lines.push(` ${c.bBright('Upfyn-Code')} ${c.dim('-- Status')}`);
|
|
593
|
+
lines.push(` ${c.dark('='.repeat(50))}`);
|
|
594
|
+
lines.push('');
|
|
595
|
+
|
|
596
|
+
// Version
|
|
597
|
+
lines.push(` ${c.bright('Version')} ${c.white(info.version)}`);
|
|
598
|
+
lines.push('');
|
|
599
|
+
|
|
600
|
+
// Installation
|
|
601
|
+
lines.push(` ${c.bright('Install')} ${c.dim(info.installDir)}`);
|
|
602
|
+
lines.push(` ${c.bright('Database')} ${c.dim(info.dbPath)}`);
|
|
603
|
+
if (info.dbExists) {
|
|
604
|
+
lines.push(` ${c.green('OK')} ${c.gray(`Exists (${info.dbSize})`)}`);
|
|
605
|
+
} else {
|
|
606
|
+
lines.push(` ${c.yellow('--')} ${c.gray('Not created yet')}`);
|
|
607
|
+
}
|
|
608
|
+
lines.push('');
|
|
609
|
+
|
|
610
|
+
// Configuration
|
|
611
|
+
lines.push(` ${c.bright('Config')}`);
|
|
612
|
+
lines.push(` ${c.gray('PORT')} ${c.cyan(info.port)} ${info.portDefault ? c.dim('(default)') : ''}`);
|
|
613
|
+
lines.push(` ${c.gray('DATABASE')} ${c.dim(info.dbPath)}`);
|
|
614
|
+
lines.push(` ${c.gray('CLI')} ${c.dim(info.claudeCli || 'claude (default)')}`);
|
|
615
|
+
if (info.apiKey) {
|
|
616
|
+
lines.push(` ${c.gray('API KEY')} ${c.green('Set')} ${c.dim('(sk-ant-...' + info.apiKey.slice(-4) + ')')}`);
|
|
617
|
+
}
|
|
618
|
+
lines.push('');
|
|
619
|
+
|
|
620
|
+
// Bottom
|
|
621
|
+
lines.push(` ${c.dark('='.repeat(50))}`);
|
|
622
|
+
lines.push('');
|
|
623
|
+
lines.push(` ${c.bCyan('Tips:')}`);
|
|
624
|
+
lines.push(` ${c.dim('>')} Use ${c.bright('uc')} to launch Claude Code with Upfyn branding`);
|
|
625
|
+
lines.push(` ${c.dim('>')} Use ${c.bright('uc connect --key upfyn_xxx')} to bridge to web UI`);
|
|
626
|
+
lines.push(` ${c.dim('>')} Use ${c.bright('uc config --api-key sk-ant-xxx')} to save your API key`);
|
|
627
|
+
lines.push('');
|
|
628
|
+
|
|
629
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Show server startup banner
|
|
634
|
+
*/
|
|
635
|
+
function showServerBanner(port, version) {
|
|
636
|
+
const lines = [];
|
|
637
|
+
|
|
638
|
+
lines.push('');
|
|
639
|
+
for (const line of LOGO) lines.push(` ${line}`);
|
|
640
|
+
lines.push('');
|
|
641
|
+
lines.push(` ${c.dim('v' + version)} ${c.dim('--')} ${c.gray('by Thinqmesh Technologies')}`);
|
|
642
|
+
lines.push('');
|
|
643
|
+
lines.push(` ${c.dark(ch.h.repeat(52))}`);
|
|
644
|
+
lines.push('');
|
|
645
|
+
lines.push(` ${c.green('*')} ${c.bWhite('Server running')} ${c.gray('on')} ${c.bCyan(`http://localhost:${port}`)}`);
|
|
646
|
+
lines.push('');
|
|
647
|
+
lines.push(` ${c.dim('Press Ctrl+C to stop.')}`);
|
|
648
|
+
lines.push('');
|
|
649
|
+
|
|
650
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Show connect startup with animation
|
|
655
|
+
*/
|
|
656
|
+
async function showConnectStartup(serverUrl, machine, user, version) {
|
|
657
|
+
await playRocketAnimation();
|
|
658
|
+
|
|
659
|
+
clearScreen();
|
|
660
|
+
|
|
661
|
+
const lines = [];
|
|
662
|
+
|
|
663
|
+
lines.push('');
|
|
664
|
+
for (const line of LOGO) lines.push(` ${line}`);
|
|
665
|
+
lines.push('');
|
|
666
|
+
lines.push(` ${c.dim('v' + version)} ${c.dim('--')} ${c.gray('Relay Client')}`);
|
|
667
|
+
lines.push('');
|
|
668
|
+
lines.push(` ${c.dark(ch.h.repeat(52))}`);
|
|
669
|
+
lines.push('');
|
|
670
|
+
lines.push(` ${c.gray('Server:')} ${c.cyan(serverUrl)}`);
|
|
671
|
+
lines.push(` ${c.gray('Machine:')} ${c.dim(machine)}`);
|
|
672
|
+
lines.push(` ${c.gray('User:')} ${c.dim(user)}`);
|
|
673
|
+
lines.push('');
|
|
674
|
+
|
|
675
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Show interactive launch screen (before spawning Claude Code)
|
|
680
|
+
*/
|
|
681
|
+
function showLaunchScreen(version, claudeBin, options = {}) {
|
|
682
|
+
const cols = process.stdout.columns || 80;
|
|
683
|
+
const W = Math.min(cols - 4, 72);
|
|
684
|
+
|
|
685
|
+
const lines = [];
|
|
686
|
+
|
|
687
|
+
lines.push('');
|
|
688
|
+
for (const line of LOGO) lines.push(` ${line}`);
|
|
689
|
+
lines.push('');
|
|
690
|
+
lines.push(` ${c.dim('v' + version)} ${c.dim('--')} ${c.gray('by Thinqmesh Technologies')}`);
|
|
691
|
+
lines.push('');
|
|
692
|
+
lines.push(` ${c.dark(ch.h.repeat(W))}`);
|
|
693
|
+
lines.push('');
|
|
694
|
+
|
|
695
|
+
if (claudeBin) {
|
|
696
|
+
lines.push(` ${c.green('*')} ${c.bWhite('Claude Code detected:')} ${c.dim(claudeBin)}`);
|
|
697
|
+
}
|
|
698
|
+
if (options.relayStatus) {
|
|
699
|
+
lines.push(` ${c.green('*')} ${c.bWhite('Relay:')} ${c.dim(options.relayStatus)}`);
|
|
700
|
+
}
|
|
701
|
+
if (options.apiKey) {
|
|
702
|
+
lines.push(` ${c.green('*')} ${c.bWhite('API Key:')} ${c.dim('Configured')}`);
|
|
703
|
+
}
|
|
704
|
+
lines.push('');
|
|
705
|
+
|
|
706
|
+
if (claudeBin) {
|
|
707
|
+
lines.push(` ${c.dim('Launching Claude Code...')}`);
|
|
708
|
+
lines.push(` ${c.dim('Slash commands available: /upfynai-connect, /upfynai-status')}`);
|
|
709
|
+
} else {
|
|
710
|
+
lines.push(` ${c.yellow('!')} ${c.white('Claude Code CLI not found on PATH')}`);
|
|
711
|
+
lines.push('');
|
|
712
|
+
lines.push(` ${c.gray('Install Claude Code:')}`);
|
|
713
|
+
lines.push(` ${c.bright('npm install -g @anthropic-ai/claude-code')}`);
|
|
714
|
+
lines.push('');
|
|
715
|
+
lines.push(` ${c.gray('Or start the server instead:')}`);
|
|
716
|
+
lines.push(` ${c.bright('uc start')}`);
|
|
717
|
+
}
|
|
718
|
+
lines.push('');
|
|
719
|
+
lines.push(` ${c.dark(ch.h.repeat(W))}`);
|
|
720
|
+
lines.push('');
|
|
721
|
+
|
|
722
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* Show config display
|
|
727
|
+
*/
|
|
728
|
+
function showConfig(config) {
|
|
729
|
+
const lines = [];
|
|
730
|
+
lines.push('');
|
|
731
|
+
lines.push(` ${c.bBright('Upfyn-Code')} ${c.dim('-- Configuration')}`);
|
|
732
|
+
lines.push(` ${c.dark('='.repeat(50))}`);
|
|
733
|
+
lines.push('');
|
|
734
|
+
|
|
735
|
+
lines.push(` ${c.gray('Server')} ${config.server ? c.cyan(config.server) : c.dim('(not set)')}`);
|
|
736
|
+
lines.push(` ${c.gray('Relay Key')} ${config.relayKey ? c.green('Set') + ' ' + c.dim('(' + config.relayKey.slice(0, 10) + '...)') : c.dim('(not set)')}`);
|
|
737
|
+
lines.push(` ${c.gray('API Key')} ${config.anthropicApiKey ? c.green('Set') + ' ' + c.dim('(sk-ant-...' + config.anthropicApiKey.slice(-4) + ')') : c.dim('(not set)')}`);
|
|
738
|
+
lines.push('');
|
|
739
|
+
lines.push(` ${c.gray('Config file:')} ${c.dim(config._path || '~/.upfynai/config.json')}`);
|
|
740
|
+
lines.push('');
|
|
741
|
+
|
|
742
|
+
lines.push(` ${c.bCyan('Set values:')}`);
|
|
743
|
+
lines.push(` ${c.dim('$')} ${c.bright('uc config --api-key sk-ant-xxx')} ${c.dim('# Save Anthropic API key')}`);
|
|
744
|
+
lines.push(` ${c.dim('$')} ${c.bright('uc config --clear-api-key')} ${c.dim('# Remove API key')}`);
|
|
745
|
+
lines.push(` ${c.dim('$')} ${c.bright('uc connect --server <url> --key <token>')}`);
|
|
746
|
+
lines.push('');
|
|
747
|
+
|
|
748
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Log a relay event with icon
|
|
753
|
+
*/
|
|
754
|
+
function logRelayEvent(icon, message, color = 'gray') {
|
|
755
|
+
const colorFn = c[color] || c.gray;
|
|
756
|
+
const timestamp = new Date().toLocaleTimeString('en-US', { hour12: false });
|
|
757
|
+
console.log(` ${c.dim(timestamp)} ${icon} ${colorFn(message)}`);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
export {
|
|
761
|
+
theme,
|
|
762
|
+
c,
|
|
763
|
+
ch,
|
|
764
|
+
LOGO,
|
|
765
|
+
detectTerminalSupport,
|
|
766
|
+
playRocketAnimation,
|
|
767
|
+
showWelcomeScreen,
|
|
768
|
+
showConnectionBanner,
|
|
769
|
+
showStyledHelp,
|
|
770
|
+
showStyledStatus,
|
|
771
|
+
showServerBanner,
|
|
772
|
+
showConnectStartup,
|
|
773
|
+
showLaunchScreen,
|
|
774
|
+
showConfig,
|
|
775
|
+
logRelayEvent,
|
|
776
|
+
createSpinner,
|
|
777
|
+
hideCursor,
|
|
778
|
+
showCursor,
|
|
779
|
+
clearScreen,
|
|
780
|
+
sleep,
|
|
781
|
+
hLine,
|
|
782
|
+
box,
|
|
783
|
+
stripAnsi,
|
|
784
|
+
padAnsi,
|
|
785
|
+
};
|