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.js
CHANGED
|
@@ -6,8 +6,10 @@
|
|
|
6
6
|
* Visual AI coding interface with Upfyn-Canvas for AI coding assistants
|
|
7
7
|
*
|
|
8
8
|
* Commands:
|
|
9
|
-
* (no args) -
|
|
9
|
+
* (no args) - Launch Claude Code with Upfyn branding (default)
|
|
10
10
|
* start - Start the server
|
|
11
|
+
* connect - Connect to hosted server (relay bridge)
|
|
12
|
+
* config - View/set configuration (API key, server, etc.)
|
|
11
13
|
* status - Show configuration and data locations
|
|
12
14
|
* help - Show help information
|
|
13
15
|
* version - Show version information
|
|
@@ -18,41 +20,32 @@ import path from 'path';
|
|
|
18
20
|
import os from 'os';
|
|
19
21
|
import { fileURLToPath } from 'url';
|
|
20
22
|
import { dirname } from 'path';
|
|
23
|
+
import { execSync, spawn } from 'child_process';
|
|
24
|
+
import {
|
|
25
|
+
c,
|
|
26
|
+
showStyledHelp,
|
|
27
|
+
showStyledStatus,
|
|
28
|
+
showServerBanner,
|
|
29
|
+
showConnectStartup,
|
|
30
|
+
showConnectionBanner,
|
|
31
|
+
showLaunchScreen,
|
|
32
|
+
showConfig,
|
|
33
|
+
logRelayEvent,
|
|
34
|
+
createSpinner,
|
|
35
|
+
playRocketAnimation,
|
|
36
|
+
clearScreen,
|
|
37
|
+
} from './cli-ui.js';
|
|
21
38
|
|
|
22
39
|
const __filename = fileURLToPath(import.meta.url);
|
|
23
40
|
const __dirname = dirname(__filename);
|
|
24
41
|
|
|
25
|
-
// ANSI color codes for terminal output
|
|
26
|
-
const colors = {
|
|
27
|
-
reset: '\x1b[0m',
|
|
28
|
-
bright: '\x1b[1m',
|
|
29
|
-
dim: '\x1b[2m',
|
|
30
|
-
|
|
31
|
-
// Foreground colors
|
|
32
|
-
cyan: '\x1b[36m',
|
|
33
|
-
green: '\x1b[32m',
|
|
34
|
-
yellow: '\x1b[33m',
|
|
35
|
-
blue: '\x1b[34m',
|
|
36
|
-
magenta: '\x1b[35m',
|
|
37
|
-
white: '\x1b[37m',
|
|
38
|
-
gray: '\x1b[90m',
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
// Helper to colorize text
|
|
42
|
-
const c = {
|
|
43
|
-
info: (text) => `${colors.cyan}${text}${colors.reset}`,
|
|
44
|
-
ok: (text) => `${colors.green}${text}${colors.reset}`,
|
|
45
|
-
warn: (text) => `${colors.yellow}${text}${colors.reset}`,
|
|
46
|
-
error: (text) => `${colors.yellow}${text}${colors.reset}`,
|
|
47
|
-
tip: (text) => `${colors.blue}${text}${colors.reset}`,
|
|
48
|
-
bright: (text) => `${colors.bright}${text}${colors.reset}`,
|
|
49
|
-
dim: (text) => `${colors.dim}${text}${colors.reset}`,
|
|
50
|
-
};
|
|
51
|
-
|
|
52
42
|
// Load package.json for version info
|
|
53
43
|
const packageJsonPath = path.join(__dirname, '../package.json');
|
|
54
44
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
55
45
|
|
|
46
|
+
const CONFIG_DIR = path.join(os.homedir(), '.upfynai');
|
|
47
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
48
|
+
|
|
56
49
|
// Load environment variables from .env file if it exists
|
|
57
50
|
function loadEnvFile() {
|
|
58
51
|
try {
|
|
@@ -72,6 +65,26 @@ function loadEnvFile() {
|
|
|
72
65
|
}
|
|
73
66
|
}
|
|
74
67
|
|
|
68
|
+
// Load saved config from ~/.upfynai/config.json
|
|
69
|
+
function loadConfig() {
|
|
70
|
+
try {
|
|
71
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
72
|
+
return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
|
|
73
|
+
}
|
|
74
|
+
} catch (e) { /* ignore */ }
|
|
75
|
+
return {};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Save config to ~/.upfynai/config.json
|
|
79
|
+
function saveConfig(config) {
|
|
80
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
81
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
82
|
+
}
|
|
83
|
+
// Don't save internal keys
|
|
84
|
+
const { _path, ...rest } = config;
|
|
85
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(rest, null, 2));
|
|
86
|
+
}
|
|
87
|
+
|
|
75
88
|
// Get the database path (same logic as db.js)
|
|
76
89
|
function getDatabasePath() {
|
|
77
90
|
loadEnvFile();
|
|
@@ -83,123 +96,54 @@ function getInstallDir() {
|
|
|
83
96
|
return path.join(__dirname, '..');
|
|
84
97
|
}
|
|
85
98
|
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
// --- OS Detection + Claude Binary Discovery ---
|
|
100
|
+
|
|
101
|
+
function findClaudeBinary() {
|
|
102
|
+
const isWindows = process.platform === 'win32';
|
|
103
|
+
const candidates = isWindows
|
|
104
|
+
? ['claude.exe', 'claude.cmd', 'claude']
|
|
105
|
+
: ['claude'];
|
|
106
|
+
|
|
107
|
+
for (const cmd of candidates) {
|
|
108
|
+
try {
|
|
109
|
+
const whichCmd = isWindows ? 'where' : 'which';
|
|
110
|
+
const result = execSync(`${whichCmd} ${cmd}`, { stdio: 'pipe', encoding: 'utf8' }).trim();
|
|
111
|
+
if (result) return cmd;
|
|
112
|
+
} catch {
|
|
113
|
+
// not found, try next
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
93
118
|
|
|
94
|
-
|
|
119
|
+
// --- Show status command ---
|
|
120
|
+
function showStatus() {
|
|
121
|
+
const config = loadConfig();
|
|
95
122
|
const installDir = getInstallDir();
|
|
96
|
-
console.log(`\n${c.info('[INFO]')} Installation Directory:`);
|
|
97
|
-
console.log(` ${c.dim(installDir)}`);
|
|
98
|
-
|
|
99
|
-
// Database location
|
|
100
123
|
const dbPath = getDatabasePath();
|
|
101
124
|
const dbExists = fs.existsSync(dbPath);
|
|
102
|
-
|
|
103
|
-
console.log(` ${c.dim(dbPath)}`);
|
|
104
|
-
console.log(` Status: ${dbExists ? c.ok('[OK] Exists') : c.warn('[WARN] Not created yet (will be created on first run)')}`);
|
|
105
|
-
|
|
125
|
+
let dbSize = '';
|
|
106
126
|
if (dbExists) {
|
|
107
127
|
const stats = fs.statSync(dbPath);
|
|
108
|
-
|
|
109
|
-
console.log(` Modified: ${c.dim(stats.mtime.toLocaleString())}`);
|
|
128
|
+
dbSize = (stats.size / 1024).toFixed(2) + ' KB';
|
|
110
129
|
}
|
|
111
130
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
console.log(` ${c.dim(claudeProjectsPath)}`);
|
|
124
|
-
console.log(` Status: ${projectsExists ? c.ok('[OK] Exists') : c.warn('[WARN] Not found')}`);
|
|
125
|
-
|
|
126
|
-
// Config file location
|
|
127
|
-
const envFilePath = path.join(__dirname, '../.env');
|
|
128
|
-
const envExists = fs.existsSync(envFilePath);
|
|
129
|
-
console.log(`\n${c.info('[INFO]')} Configuration File:`);
|
|
130
|
-
console.log(` ${c.dim(envFilePath)}`);
|
|
131
|
-
console.log(` Status: ${envExists ? c.ok('[OK] Exists') : c.warn('[WARN] Not found (using defaults)')}`);
|
|
132
|
-
|
|
133
|
-
console.log('\n' + c.dim('═'.repeat(60)));
|
|
134
|
-
console.log(`\n${c.tip('[TIP]')} Hints:`);
|
|
135
|
-
console.log(` ${c.dim('>')} Use ${c.bright('uc --port 8080')} to run on a custom port`);
|
|
136
|
-
console.log(` ${c.dim('>')} Use ${c.bright('uc --database-path /path/to/db')} for custom database`);
|
|
137
|
-
console.log(` ${c.dim('>')} Run ${c.bright('uc help')} for all options`);
|
|
138
|
-
console.log(` ${c.dim('>')} Access the UI at http://localhost:${process.env.PORT || '3001'}\n`);
|
|
131
|
+
showStyledStatus({
|
|
132
|
+
version: packageJson.version,
|
|
133
|
+
installDir,
|
|
134
|
+
dbPath,
|
|
135
|
+
dbExists,
|
|
136
|
+
dbSize,
|
|
137
|
+
port: process.env.PORT || '3001',
|
|
138
|
+
portDefault: !process.env.PORT,
|
|
139
|
+
claudeCli: findClaudeBinary() || null,
|
|
140
|
+
apiKey: config.anthropicApiKey || null,
|
|
141
|
+
});
|
|
139
142
|
}
|
|
140
143
|
|
|
141
144
|
// Show help
|
|
142
145
|
function showHelp() {
|
|
143
|
-
|
|
144
|
-
╔═══════════════════════════════════════════════════════════════╗
|
|
145
|
-
║ Upfyn-Code — by Thinqmesh Technologies ║
|
|
146
|
-
║ Visual AI Coding Interface with tldraw Canvas ║
|
|
147
|
-
╚═══════════════════════════════════════════════════════════════╝
|
|
148
|
-
|
|
149
|
-
Usage:
|
|
150
|
-
upfynai-code [command] [options]
|
|
151
|
-
uc [command] [options]
|
|
152
|
-
|
|
153
|
-
Commands:
|
|
154
|
-
start Start the server (default)
|
|
155
|
-
connect Connect local machine to hosted server (relay bridge)
|
|
156
|
-
status Show configuration and data locations
|
|
157
|
-
install-commands Install /upfynai-* slash commands to ~/.claude/commands/
|
|
158
|
-
uninstall-commands Remove /upfynai-* slash commands
|
|
159
|
-
update Update to the latest version
|
|
160
|
-
help Show this help information
|
|
161
|
-
version Show version information
|
|
162
|
-
|
|
163
|
-
Slash Commands (inside your AI CLI):
|
|
164
|
-
/upfynai Start the web UI server
|
|
165
|
-
/upfynai-connect Connect CLI session to web UI
|
|
166
|
-
/upfynai-disconnect Disconnect from web UI
|
|
167
|
-
/upfynai-status Show connection status
|
|
168
|
-
/upfynai-doctor Run diagnostics
|
|
169
|
-
/upfynai-export Export session/canvas data
|
|
170
|
-
/upfynai-stop Stop the web UI server
|
|
171
|
-
/upfynai-local Full local installation setup
|
|
172
|
-
/upfynai-uninstall Remove Upfyn-Code
|
|
173
|
-
|
|
174
|
-
Options:
|
|
175
|
-
-p, --port <port> Set server port (default: 3001)
|
|
176
|
-
--database-path <path> Set custom database location
|
|
177
|
-
-h, --help Show this help information
|
|
178
|
-
-v, --version Show version information
|
|
179
|
-
|
|
180
|
-
Options:
|
|
181
|
-
--server <url> Server URL for connect (default: https://upfynai.thinqmesh.com)
|
|
182
|
-
--key <token> Relay token for connect (get from Settings > Relay Tokens)
|
|
183
|
-
|
|
184
|
-
Examples:
|
|
185
|
-
$ uc # Start with defaults
|
|
186
|
-
$ uc --port 8080 # Start on port 8080
|
|
187
|
-
$ uc connect --key upfyn_xxx # Bridge to hosted server
|
|
188
|
-
$ uc start --port 4000 # Explicit start command
|
|
189
|
-
$ uc status # Show configuration
|
|
190
|
-
|
|
191
|
-
Environment Variables:
|
|
192
|
-
PORT Set server port (default: 3001)
|
|
193
|
-
DATABASE_PATH Set custom database location
|
|
194
|
-
CLAUDE_CLI_PATH Set custom Claude CLI path
|
|
195
|
-
CONTEXT_WINDOW Set context window size (default: 160000)
|
|
196
|
-
|
|
197
|
-
Documentation:
|
|
198
|
-
${packageJson.homepage || 'https://github.com/AnitChaudhry/UpfynAI-Code'}
|
|
199
|
-
|
|
200
|
-
Report Issues:
|
|
201
|
-
${packageJson.bugs?.url || 'https://github.com/AnitChaudhry/UpfynAI-Code/issues'}
|
|
202
|
-
`);
|
|
146
|
+
showStyledHelp(packageJson.version);
|
|
203
147
|
}
|
|
204
148
|
|
|
205
149
|
// Show version
|
|
@@ -221,21 +165,22 @@ function isNewerVersion(v1, v2) {
|
|
|
221
165
|
// Check for updates
|
|
222
166
|
async function checkForUpdates(silent = false) {
|
|
223
167
|
try {
|
|
224
|
-
const { execSync } = await import('child_process');
|
|
225
168
|
const latestVersion = execSync('npm show upfynai-code version', { encoding: 'utf8' }).trim();
|
|
226
169
|
const currentVersion = packageJson.version;
|
|
227
170
|
|
|
228
171
|
if (isNewerVersion(latestVersion, currentVersion)) {
|
|
229
|
-
|
|
230
|
-
|
|
172
|
+
if (!silent) {
|
|
173
|
+
console.log(`\n ${c.yellow('!')} New version available: ${c.bBright(latestVersion)} ${c.dim(`(current: ${currentVersion})`)}`);
|
|
174
|
+
console.log(` Run ${c.bright('uc update')} to update\n`);
|
|
175
|
+
}
|
|
231
176
|
return { hasUpdate: true, latestVersion, currentVersion };
|
|
232
177
|
} else if (!silent) {
|
|
233
|
-
console.log(
|
|
178
|
+
console.log(` ${c.green('OK')} You are on the latest version (${currentVersion})`);
|
|
234
179
|
}
|
|
235
180
|
return { hasUpdate: false, latestVersion, currentVersion };
|
|
236
181
|
} catch (e) {
|
|
237
182
|
if (!silent) {
|
|
238
|
-
console.log(
|
|
183
|
+
console.log(` ${c.yellow('!')} Could not check for updates`);
|
|
239
184
|
}
|
|
240
185
|
return { hasUpdate: false, error: e.message };
|
|
241
186
|
}
|
|
@@ -244,27 +189,28 @@ async function checkForUpdates(silent = false) {
|
|
|
244
189
|
// Update the package
|
|
245
190
|
async function updatePackage() {
|
|
246
191
|
try {
|
|
247
|
-
const
|
|
248
|
-
|
|
192
|
+
const spinner = createSpinner('Checking for updates...');
|
|
193
|
+
spinner.start();
|
|
249
194
|
|
|
250
195
|
const { hasUpdate, latestVersion, currentVersion } = await checkForUpdates(true);
|
|
251
|
-
|
|
252
196
|
if (!hasUpdate) {
|
|
253
|
-
|
|
197
|
+
spinner.stop(`Already on the latest version (${currentVersion})`);
|
|
254
198
|
return;
|
|
255
199
|
}
|
|
200
|
+
spinner.stop(`Update available: ${currentVersion} -> ${latestVersion}`);
|
|
256
201
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
202
|
+
const installSpinner = createSpinner(`Updating to v${latestVersion}...`);
|
|
203
|
+
installSpinner.start();
|
|
204
|
+
execSync('npm update -g upfynai-code', { stdio: 'pipe' });
|
|
205
|
+
installSpinner.stop(`Updated to v${latestVersion}! Restart uc to use the new version.`);
|
|
260
206
|
} catch (e) {
|
|
261
|
-
console.
|
|
262
|
-
console.log(
|
|
207
|
+
console.log(` ${c.red('FAIL')} Update failed: ${e.message}`);
|
|
208
|
+
console.log(` ${c.dim('Try running manually:')} ${c.bright('npm update -g upfynai-code')}`);
|
|
263
209
|
}
|
|
264
210
|
}
|
|
265
211
|
|
|
266
212
|
// Install slash commands to ~/.claude/commands/
|
|
267
|
-
async function installCommands() {
|
|
213
|
+
async function installCommands(silent = false) {
|
|
268
214
|
const commandsSource = path.join(__dirname, '..', 'commands');
|
|
269
215
|
const commandsDest = path.join(os.homedir(), '.claude', 'commands');
|
|
270
216
|
|
|
@@ -273,8 +219,8 @@ async function installCommands() {
|
|
|
273
219
|
}
|
|
274
220
|
|
|
275
221
|
if (!fs.existsSync(commandsSource)) {
|
|
276
|
-
console.
|
|
277
|
-
|
|
222
|
+
if (!silent) console.log(` ${c.red('FAIL')} Commands directory not found`);
|
|
223
|
+
return 0;
|
|
278
224
|
}
|
|
279
225
|
|
|
280
226
|
const files = fs.readdirSync(commandsSource).filter(f => f.endsWith('.md'));
|
|
@@ -285,12 +231,17 @@ async function installCommands() {
|
|
|
285
231
|
path.join(commandsSource, file),
|
|
286
232
|
path.join(commandsDest, file)
|
|
287
233
|
);
|
|
288
|
-
|
|
234
|
+
if (!silent) {
|
|
235
|
+
console.log(` ${c.green('OK')} Installed ${c.violet('/' + file.replace('.md', ''))}`);
|
|
236
|
+
}
|
|
289
237
|
count++;
|
|
290
238
|
}
|
|
291
239
|
|
|
292
|
-
|
|
293
|
-
|
|
240
|
+
if (!silent) {
|
|
241
|
+
console.log(`\n ${c.bBright(`${count} slash commands installed!`)}`);
|
|
242
|
+
console.log(` ${c.dim('Available in your AI CLI as /upfynai-*')}\n`);
|
|
243
|
+
}
|
|
244
|
+
return count;
|
|
294
245
|
}
|
|
295
246
|
|
|
296
247
|
// Remove slash commands from ~/.claude/commands/
|
|
@@ -301,16 +252,118 @@ async function uninstallCommands() {
|
|
|
301
252
|
: [];
|
|
302
253
|
|
|
303
254
|
if (files.length === 0) {
|
|
304
|
-
console.log(
|
|
255
|
+
console.log(` ${c.yellow('!')} No Upfyn-Code commands found to remove`);
|
|
305
256
|
return;
|
|
306
257
|
}
|
|
307
258
|
|
|
308
259
|
for (const file of files) {
|
|
309
260
|
fs.unlinkSync(path.join(commandsDest, file));
|
|
310
|
-
console.log(
|
|
261
|
+
console.log(` ${c.green('OK')} Removed ${c.violet('/' + file.replace('.md', ''))}`);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
console.log(`\n ${c.bBright(`${files.length} slash commands removed.`)}\n`);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// --- Config command ---
|
|
268
|
+
function handleConfig(options) {
|
|
269
|
+
const config = loadConfig();
|
|
270
|
+
|
|
271
|
+
if (options.apiKey) {
|
|
272
|
+
// Set API key
|
|
273
|
+
config.anthropicApiKey = options.apiKey;
|
|
274
|
+
saveConfig(config);
|
|
275
|
+
console.log(`\n ${c.green('OK')} ${c.white('Anthropic API key saved')}`);
|
|
276
|
+
console.log(` ${c.dim('Key:')} sk-ant-...${options.apiKey.slice(-4)}`);
|
|
277
|
+
console.log(` ${c.dim('Stored in:')} ${CONFIG_FILE}\n`);
|
|
278
|
+
return;
|
|
311
279
|
}
|
|
312
280
|
|
|
313
|
-
|
|
281
|
+
if (options.clearApiKey) {
|
|
282
|
+
delete config.anthropicApiKey;
|
|
283
|
+
saveConfig(config);
|
|
284
|
+
console.log(`\n ${c.green('OK')} ${c.white('Anthropic API key removed')}\n`);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Show current config
|
|
289
|
+
showConfig({ ...config, _path: CONFIG_FILE });
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// --- Launch Interactive (default command) ---
|
|
293
|
+
async function launchInteractive() {
|
|
294
|
+
// 1. Play rocket animation
|
|
295
|
+
await playRocketAnimation();
|
|
296
|
+
clearScreen();
|
|
297
|
+
|
|
298
|
+
// 2. Ensure slash commands are installed (silent)
|
|
299
|
+
await installCommands(true);
|
|
300
|
+
|
|
301
|
+
// 3. Find Claude Code binary
|
|
302
|
+
const claudeBin = findClaudeBinary();
|
|
303
|
+
|
|
304
|
+
// 4. Load config for relay + API key
|
|
305
|
+
const config = loadConfig();
|
|
306
|
+
|
|
307
|
+
// 5. Show launch screen
|
|
308
|
+
showLaunchScreen(packageJson.version, claudeBin, {
|
|
309
|
+
relayStatus: config.relayKey && config.server
|
|
310
|
+
? `Auto-connecting to ${config.server}`
|
|
311
|
+
: null,
|
|
312
|
+
apiKey: config.anthropicApiKey || null,
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// 6. If Claude Code not found, fall back to server mode
|
|
316
|
+
if (!claudeBin) {
|
|
317
|
+
console.log(` ${c.dim('Falling back to server mode...')}\n`);
|
|
318
|
+
await startServer();
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// 7. Build environment for Claude Code
|
|
323
|
+
const childEnv = { ...process.env };
|
|
324
|
+
if (config.anthropicApiKey) {
|
|
325
|
+
childEnv.ANTHROPIC_API_KEY = config.anthropicApiKey;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// 8. Start background relay if config exists
|
|
329
|
+
if (config.relayKey && config.server) {
|
|
330
|
+
startBackgroundRelay(config);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// 9. Spawn Claude Code interactively
|
|
334
|
+
const child = spawn(claudeBin, [], {
|
|
335
|
+
stdio: 'inherit',
|
|
336
|
+
cwd: process.cwd(),
|
|
337
|
+
shell: true,
|
|
338
|
+
env: childEnv,
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
child.on('exit', (code) => {
|
|
342
|
+
process.exit(code || 0);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
child.on('error', (err) => {
|
|
346
|
+
console.log(`\n ${c.red('FAIL')} Failed to launch Claude Code: ${err.message}`);
|
|
347
|
+
console.log(` ${c.dim('Make sure Claude Code is installed:')}`);
|
|
348
|
+
console.log(` ${c.bright('npm install -g @anthropic-ai/claude-code')}\n`);
|
|
349
|
+
process.exit(1);
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// --- Background relay connection ---
|
|
354
|
+
function startBackgroundRelay(config) {
|
|
355
|
+
// Import and start relay in background (non-blocking)
|
|
356
|
+
import('./relay-client.js').then(({ connectToServerBackground }) => {
|
|
357
|
+
if (typeof connectToServerBackground === 'function') {
|
|
358
|
+
connectToServerBackground({
|
|
359
|
+
server: config.server,
|
|
360
|
+
key: config.relayKey,
|
|
361
|
+
silent: true,
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}).catch(() => {
|
|
365
|
+
// Relay module not available or no background connect — that's ok
|
|
366
|
+
});
|
|
314
367
|
}
|
|
315
368
|
|
|
316
369
|
// Start the server
|
|
@@ -318,13 +371,17 @@ async function startServer() {
|
|
|
318
371
|
// Check for updates silently on startup
|
|
319
372
|
checkForUpdates(true);
|
|
320
373
|
|
|
374
|
+
// Show server banner
|
|
375
|
+
const port = process.env.PORT || '3001';
|
|
376
|
+
showServerBanner(port, packageJson.version);
|
|
377
|
+
|
|
321
378
|
// Import and run the server
|
|
322
379
|
await import('./index.js');
|
|
323
380
|
}
|
|
324
381
|
|
|
325
382
|
// Parse CLI arguments
|
|
326
383
|
function parseArgs(args) {
|
|
327
|
-
const parsed = { command:
|
|
384
|
+
const parsed = { command: null, options: {} };
|
|
328
385
|
|
|
329
386
|
for (let i = 0; i < args.length; i++) {
|
|
330
387
|
const arg = args[i];
|
|
@@ -345,15 +402,26 @@ function parseArgs(args) {
|
|
|
345
402
|
parsed.options.key = args[++i];
|
|
346
403
|
} else if (arg.startsWith('--key=')) {
|
|
347
404
|
parsed.options.key = arg.split('=')[1];
|
|
405
|
+
} else if (arg === '--api-key') {
|
|
406
|
+
parsed.options.apiKey = args[++i];
|
|
407
|
+
} else if (arg.startsWith('--api-key=')) {
|
|
408
|
+
parsed.options.apiKey = arg.split('=')[1];
|
|
409
|
+
} else if (arg === '--clear-api-key') {
|
|
410
|
+
parsed.options.clearApiKey = true;
|
|
348
411
|
} else if (arg === '--help' || arg === '-h') {
|
|
349
412
|
parsed.command = 'help';
|
|
350
413
|
} else if (arg === '--version' || arg === '-v') {
|
|
351
414
|
parsed.command = 'version';
|
|
352
|
-
} else if (!arg.startsWith('-')) {
|
|
415
|
+
} else if (!arg.startsWith('-') && !parsed.command) {
|
|
353
416
|
parsed.command = arg;
|
|
354
417
|
}
|
|
355
418
|
}
|
|
356
419
|
|
|
420
|
+
// Default command: launch interactive
|
|
421
|
+
if (!parsed.command) {
|
|
422
|
+
parsed.command = 'launch';
|
|
423
|
+
}
|
|
424
|
+
|
|
357
425
|
return parsed;
|
|
358
426
|
}
|
|
359
427
|
|
|
@@ -371,6 +439,9 @@ async function main() {
|
|
|
371
439
|
}
|
|
372
440
|
|
|
373
441
|
switch (command) {
|
|
442
|
+
case 'launch':
|
|
443
|
+
await launchInteractive();
|
|
444
|
+
break;
|
|
374
445
|
case 'start':
|
|
375
446
|
await startServer();
|
|
376
447
|
break;
|
|
@@ -391,6 +462,9 @@ async function main() {
|
|
|
391
462
|
case 'update':
|
|
392
463
|
await updatePackage();
|
|
393
464
|
break;
|
|
465
|
+
case 'config':
|
|
466
|
+
handleConfig(options);
|
|
467
|
+
break;
|
|
394
468
|
case 'install-commands':
|
|
395
469
|
await installCommands();
|
|
396
470
|
break;
|
|
@@ -406,14 +480,14 @@ async function main() {
|
|
|
406
480
|
break;
|
|
407
481
|
}
|
|
408
482
|
default:
|
|
409
|
-
console.error(`\n
|
|
410
|
-
console.log(
|
|
483
|
+
console.error(`\n ${c.red('FAIL')} Unknown command: ${command}`);
|
|
484
|
+
console.log(` Run ${c.bright('"uc help"')} for usage information.\n`);
|
|
411
485
|
process.exit(1);
|
|
412
486
|
}
|
|
413
487
|
}
|
|
414
488
|
|
|
415
489
|
// Run the CLI
|
|
416
490
|
main().catch(error => {
|
|
417
|
-
console.error('
|
|
491
|
+
console.error(`\n ${c.red('FAIL')} Error: ${error.message}`);
|
|
418
492
|
process.exit(1);
|
|
419
493
|
});
|