upfynai-code 2.3.0 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +128 -66
- package/client/dist/manifest.json +61 -15
- package/client/dist/sw.js +19 -55
- package/commands/upfynai-connect.md +31 -18
- package/commands/upfynai.md +45 -26
- package/package.json +1 -1
- package/server/cli-ui.js +320 -169
- package/server/cli.js +255 -23
- package/server/constants/config.js +29 -3
- package/server/database/auth.db +0 -0
- package/server/index.js +380 -121
- package/server/mcp-server.js +2 -1
- package/server/middleware/auth.js +18 -8
- package/server/openrouter.js +137 -0
- package/server/relay-client.js +262 -18
- package/server/routes/agent.js +54 -19
- package/server/routes/auth.js +23 -12
- package/server/routes/commands.js +1 -1
- 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-BnXuHrpJ.js +0 -523
- package/client/dist/assets/index-BwxNox94.css +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/client/dist/llms.txt +0 -40
- package/client/dist/robots.txt +0 -11
- package/client/dist/sitemap.xml +0 -45
package/server/cli.js
CHANGED
|
@@ -6,9 +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
11
|
* connect - Connect to hosted server (relay bridge)
|
|
12
|
+
* config - View/set configuration (API key, server, etc.)
|
|
12
13
|
* status - Show configuration and data locations
|
|
13
14
|
* help - Show help information
|
|
14
15
|
* version - Show version information
|
|
@@ -19,6 +20,7 @@ import path from 'path';
|
|
|
19
20
|
import os from 'os';
|
|
20
21
|
import { fileURLToPath } from 'url';
|
|
21
22
|
import { dirname } from 'path';
|
|
23
|
+
import { execSync, spawn } from 'child_process';
|
|
22
24
|
import {
|
|
23
25
|
c,
|
|
24
26
|
showStyledHelp,
|
|
@@ -26,8 +28,12 @@ import {
|
|
|
26
28
|
showServerBanner,
|
|
27
29
|
showConnectStartup,
|
|
28
30
|
showConnectionBanner,
|
|
31
|
+
showLaunchScreen,
|
|
32
|
+
showConfig,
|
|
29
33
|
logRelayEvent,
|
|
30
34
|
createSpinner,
|
|
35
|
+
playRocketAnimation,
|
|
36
|
+
clearScreen,
|
|
31
37
|
} from './cli-ui.js';
|
|
32
38
|
|
|
33
39
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -37,6 +43,9 @@ const __dirname = dirname(__filename);
|
|
|
37
43
|
const packageJsonPath = path.join(__dirname, '../package.json');
|
|
38
44
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
39
45
|
|
|
46
|
+
const CONFIG_DIR = path.join(os.homedir(), '.upfynai');
|
|
47
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
48
|
+
|
|
40
49
|
// Load environment variables from .env file if it exists
|
|
41
50
|
function loadEnvFile() {
|
|
42
51
|
try {
|
|
@@ -56,6 +65,26 @@ function loadEnvFile() {
|
|
|
56
65
|
}
|
|
57
66
|
}
|
|
58
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
|
+
|
|
59
88
|
// Get the database path (same logic as db.js)
|
|
60
89
|
function getDatabasePath() {
|
|
61
90
|
loadEnvFile();
|
|
@@ -67,8 +96,29 @@ function getInstallDir() {
|
|
|
67
96
|
return path.join(__dirname, '..');
|
|
68
97
|
}
|
|
69
98
|
|
|
70
|
-
//
|
|
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
|
+
}
|
|
118
|
+
|
|
119
|
+
// --- Show status command ---
|
|
71
120
|
function showStatus() {
|
|
121
|
+
const config = loadConfig();
|
|
72
122
|
const installDir = getInstallDir();
|
|
73
123
|
const dbPath = getDatabasePath();
|
|
74
124
|
const dbExists = fs.existsSync(dbPath);
|
|
@@ -86,11 +136,12 @@ function showStatus() {
|
|
|
86
136
|
dbSize,
|
|
87
137
|
port: process.env.PORT || '3001',
|
|
88
138
|
portDefault: !process.env.PORT,
|
|
89
|
-
claudeCli:
|
|
139
|
+
claudeCli: findClaudeBinary() || null,
|
|
140
|
+
apiKey: config.anthropicApiKey || null,
|
|
90
141
|
});
|
|
91
142
|
}
|
|
92
143
|
|
|
93
|
-
// Show help
|
|
144
|
+
// Show help
|
|
94
145
|
function showHelp() {
|
|
95
146
|
showStyledHelp(packageJson.version);
|
|
96
147
|
}
|
|
@@ -114,18 +165,17 @@ function isNewerVersion(v1, v2) {
|
|
|
114
165
|
// Check for updates
|
|
115
166
|
async function checkForUpdates(silent = false) {
|
|
116
167
|
try {
|
|
117
|
-
const { execSync } = await import('child_process');
|
|
118
168
|
const latestVersion = execSync('npm show upfynai-code version', { encoding: 'utf8' }).trim();
|
|
119
169
|
const currentVersion = packageJson.version;
|
|
120
170
|
|
|
121
171
|
if (isNewerVersion(latestVersion, currentVersion)) {
|
|
122
172
|
if (!silent) {
|
|
123
|
-
console.log(`\n ${c.yellow('
|
|
173
|
+
console.log(`\n ${c.yellow('!')} New version available: ${c.bBright(latestVersion)} ${c.dim(`(current: ${currentVersion})`)}`);
|
|
124
174
|
console.log(` Run ${c.bright('uc update')} to update\n`);
|
|
125
175
|
}
|
|
126
176
|
return { hasUpdate: true, latestVersion, currentVersion };
|
|
127
177
|
} else if (!silent) {
|
|
128
|
-
console.log(` ${c.green('
|
|
178
|
+
console.log(` ${c.green('OK')} You are on the latest version (${currentVersion})`);
|
|
129
179
|
}
|
|
130
180
|
return { hasUpdate: false, latestVersion, currentVersion };
|
|
131
181
|
} catch (e) {
|
|
@@ -139,7 +189,6 @@ async function checkForUpdates(silent = false) {
|
|
|
139
189
|
// Update the package
|
|
140
190
|
async function updatePackage() {
|
|
141
191
|
try {
|
|
142
|
-
const { execSync } = await import('child_process');
|
|
143
192
|
const spinner = createSpinner('Checking for updates...');
|
|
144
193
|
spinner.start();
|
|
145
194
|
|
|
@@ -148,20 +197,20 @@ async function updatePackage() {
|
|
|
148
197
|
spinner.stop(`Already on the latest version (${currentVersion})`);
|
|
149
198
|
return;
|
|
150
199
|
}
|
|
151
|
-
spinner.stop(`Update available: ${currentVersion}
|
|
200
|
+
spinner.stop(`Update available: ${currentVersion} -> ${latestVersion}`);
|
|
152
201
|
|
|
153
202
|
const installSpinner = createSpinner(`Updating to v${latestVersion}...`);
|
|
154
203
|
installSpinner.start();
|
|
155
204
|
execSync('npm update -g upfynai-code', { stdio: 'pipe' });
|
|
156
205
|
installSpinner.stop(`Updated to v${latestVersion}! Restart uc to use the new version.`);
|
|
157
206
|
} catch (e) {
|
|
158
|
-
console.log(` ${c.red('
|
|
207
|
+
console.log(` ${c.red('FAIL')} Update failed: ${e.message}`);
|
|
159
208
|
console.log(` ${c.dim('Try running manually:')} ${c.bright('npm update -g upfynai-code')}`);
|
|
160
209
|
}
|
|
161
210
|
}
|
|
162
211
|
|
|
163
212
|
// Install slash commands to ~/.claude/commands/
|
|
164
|
-
async function installCommands() {
|
|
213
|
+
async function installCommands(silent = false) {
|
|
165
214
|
const commandsSource = path.join(__dirname, '..', 'commands');
|
|
166
215
|
const commandsDest = path.join(os.homedir(), '.claude', 'commands');
|
|
167
216
|
|
|
@@ -170,8 +219,8 @@ async function installCommands() {
|
|
|
170
219
|
}
|
|
171
220
|
|
|
172
221
|
if (!fs.existsSync(commandsSource)) {
|
|
173
|
-
console.log(` ${c.red('
|
|
174
|
-
|
|
222
|
+
if (!silent) console.log(` ${c.red('FAIL')} Commands directory not found`);
|
|
223
|
+
return 0;
|
|
175
224
|
}
|
|
176
225
|
|
|
177
226
|
const files = fs.readdirSync(commandsSource).filter(f => f.endsWith('.md'));
|
|
@@ -182,12 +231,17 @@ async function installCommands() {
|
|
|
182
231
|
path.join(commandsSource, file),
|
|
183
232
|
path.join(commandsDest, file)
|
|
184
233
|
);
|
|
185
|
-
|
|
234
|
+
if (!silent) {
|
|
235
|
+
console.log(` ${c.green('OK')} Installed ${c.violet('/' + file.replace('.md', ''))}`);
|
|
236
|
+
}
|
|
186
237
|
count++;
|
|
187
238
|
}
|
|
188
239
|
|
|
189
|
-
|
|
190
|
-
|
|
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;
|
|
191
245
|
}
|
|
192
246
|
|
|
193
247
|
// Remove slash commands from ~/.claude/commands/
|
|
@@ -204,28 +258,189 @@ async function uninstallCommands() {
|
|
|
204
258
|
|
|
205
259
|
for (const file of files) {
|
|
206
260
|
fs.unlinkSync(path.join(commandsDest, file));
|
|
207
|
-
console.log(` ${c.green('
|
|
261
|
+
console.log(` ${c.green('OK')} Removed ${c.violet('/' + file.replace('.md', ''))}`);
|
|
208
262
|
}
|
|
209
263
|
|
|
210
264
|
console.log(`\n ${c.bBright(`${files.length} slash commands removed.`)}\n`);
|
|
211
265
|
}
|
|
212
266
|
|
|
213
|
-
//
|
|
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;
|
|
279
|
+
}
|
|
280
|
+
|
|
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 the local web UI server in the background
|
|
329
|
+
const port = process.env.PORT || '3001';
|
|
330
|
+
process.env.VITE_IS_PLATFORM = 'true'; // local mode
|
|
331
|
+
startBackgroundServer(port);
|
|
332
|
+
|
|
333
|
+
// 9. Start background relay if config exists (for cloud mode)
|
|
334
|
+
if (config.relayKey && config.server) {
|
|
335
|
+
startBackgroundRelay(config);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// 10. Spawn Claude Code interactively
|
|
339
|
+
const child = spawn(claudeBin, [], {
|
|
340
|
+
stdio: 'inherit',
|
|
341
|
+
cwd: process.cwd(),
|
|
342
|
+
shell: true,
|
|
343
|
+
env: childEnv,
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
child.on('exit', (code) => {
|
|
347
|
+
process.exit(code || 0);
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
child.on('error', (err) => {
|
|
351
|
+
console.log(`\n ${c.red('FAIL')} Failed to launch Claude Code: ${err.message}`);
|
|
352
|
+
console.log(` ${c.dim('Make sure Claude Code is installed:')}`);
|
|
353
|
+
console.log(` ${c.bright('npm install -g @anthropic-ai/claude-code')}\n`);
|
|
354
|
+
process.exit(1);
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// --- Background server for local mode ---
|
|
359
|
+
function startBackgroundServer(port) {
|
|
360
|
+
// Start the server in the background so the web UI is available
|
|
361
|
+
import('./index.js').then(() => {
|
|
362
|
+
// Server started successfully in background
|
|
363
|
+
}).catch(() => {
|
|
364
|
+
// Server failed to start — user still has Claude Code CLI
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
// Open browser after a short delay
|
|
368
|
+
setTimeout(() => {
|
|
369
|
+
const url = `http://localhost:${port}`;
|
|
370
|
+
try {
|
|
371
|
+
const openCmd = process.platform === 'win32' ? 'start'
|
|
372
|
+
: process.platform === 'darwin' ? 'open'
|
|
373
|
+
: 'xdg-open';
|
|
374
|
+
execSync(`${openCmd} ${url}`, { stdio: 'ignore' });
|
|
375
|
+
} catch {
|
|
376
|
+
// Browser open failed — not critical
|
|
377
|
+
}
|
|
378
|
+
}, 2000);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// --- Background relay connection ---
|
|
382
|
+
function startBackgroundRelay(config) {
|
|
383
|
+
// Import and start relay in background (non-blocking)
|
|
384
|
+
import('./relay-client.js').then(({ connectToServerBackground }) => {
|
|
385
|
+
if (typeof connectToServerBackground === 'function') {
|
|
386
|
+
connectToServerBackground({
|
|
387
|
+
server: config.server,
|
|
388
|
+
key: config.relayKey,
|
|
389
|
+
silent: true,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
}).catch(() => {
|
|
393
|
+
// Relay module not available or no background connect — that's ok
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Start the server (self-hosted local mode)
|
|
214
398
|
async function startServer() {
|
|
215
399
|
// Check for updates silently on startup
|
|
216
400
|
checkForUpdates(true);
|
|
217
401
|
|
|
218
|
-
// Show server banner
|
|
219
402
|
const port = process.env.PORT || '3001';
|
|
403
|
+
|
|
404
|
+
// Auto-detect local mode — set IS_PLATFORM flag
|
|
405
|
+
if (!process.env.RAILWAY_ENVIRONMENT && !process.env.VERCEL && !process.env.FORCE_HOSTED_MODE) {
|
|
406
|
+
process.env.VITE_IS_PLATFORM = 'true';
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Show server banner
|
|
220
410
|
showServerBanner(port, packageJson.version);
|
|
221
411
|
|
|
412
|
+
// Detect local agents
|
|
413
|
+
const claudeBin = findClaudeBinary();
|
|
414
|
+
if (claudeBin) {
|
|
415
|
+
console.log(` ${c.green('OK')} Claude Code detected: ${c.bright(claudeBin)}`);
|
|
416
|
+
} else {
|
|
417
|
+
console.log(` ${c.yellow('!')} Claude Code not found. Install: ${c.bright('npm i -g @anthropic-ai/claude-code')}`);
|
|
418
|
+
}
|
|
419
|
+
console.log('');
|
|
420
|
+
|
|
222
421
|
// Import and run the server
|
|
223
422
|
await import('./index.js');
|
|
423
|
+
|
|
424
|
+
// Auto-open browser after server starts (local mode only)
|
|
425
|
+
if (!process.env.RAILWAY_ENVIRONMENT && !process.env.VERCEL) {
|
|
426
|
+
const url = `http://localhost:${port}`;
|
|
427
|
+
setTimeout(() => {
|
|
428
|
+
try {
|
|
429
|
+
const openCmd = process.platform === 'win32' ? 'start'
|
|
430
|
+
: process.platform === 'darwin' ? 'open'
|
|
431
|
+
: 'xdg-open';
|
|
432
|
+
execSync(`${openCmd} ${url}`, { stdio: 'ignore' });
|
|
433
|
+
console.log(` ${c.green('OK')} Opened ${c.cyan(url)} in browser\n`);
|
|
434
|
+
} catch {
|
|
435
|
+
console.log(` ${c.dim('Open in browser:')} ${c.cyan(url)}\n`);
|
|
436
|
+
}
|
|
437
|
+
}, 1500);
|
|
438
|
+
}
|
|
224
439
|
}
|
|
225
440
|
|
|
226
441
|
// Parse CLI arguments
|
|
227
442
|
function parseArgs(args) {
|
|
228
|
-
const parsed = { command:
|
|
443
|
+
const parsed = { command: null, options: {} };
|
|
229
444
|
|
|
230
445
|
for (let i = 0; i < args.length; i++) {
|
|
231
446
|
const arg = args[i];
|
|
@@ -246,15 +461,26 @@ function parseArgs(args) {
|
|
|
246
461
|
parsed.options.key = args[++i];
|
|
247
462
|
} else if (arg.startsWith('--key=')) {
|
|
248
463
|
parsed.options.key = arg.split('=')[1];
|
|
464
|
+
} else if (arg === '--api-key') {
|
|
465
|
+
parsed.options.apiKey = args[++i];
|
|
466
|
+
} else if (arg.startsWith('--api-key=')) {
|
|
467
|
+
parsed.options.apiKey = arg.split('=')[1];
|
|
468
|
+
} else if (arg === '--clear-api-key') {
|
|
469
|
+
parsed.options.clearApiKey = true;
|
|
249
470
|
} else if (arg === '--help' || arg === '-h') {
|
|
250
471
|
parsed.command = 'help';
|
|
251
472
|
} else if (arg === '--version' || arg === '-v') {
|
|
252
473
|
parsed.command = 'version';
|
|
253
|
-
} else if (!arg.startsWith('-')) {
|
|
474
|
+
} else if (!arg.startsWith('-') && !parsed.command) {
|
|
254
475
|
parsed.command = arg;
|
|
255
476
|
}
|
|
256
477
|
}
|
|
257
478
|
|
|
479
|
+
// Default command: launch interactive
|
|
480
|
+
if (!parsed.command) {
|
|
481
|
+
parsed.command = 'launch';
|
|
482
|
+
}
|
|
483
|
+
|
|
258
484
|
return parsed;
|
|
259
485
|
}
|
|
260
486
|
|
|
@@ -272,6 +498,9 @@ async function main() {
|
|
|
272
498
|
}
|
|
273
499
|
|
|
274
500
|
switch (command) {
|
|
501
|
+
case 'launch':
|
|
502
|
+
await launchInteractive();
|
|
503
|
+
break;
|
|
275
504
|
case 'start':
|
|
276
505
|
await startServer();
|
|
277
506
|
break;
|
|
@@ -292,6 +521,9 @@ async function main() {
|
|
|
292
521
|
case 'update':
|
|
293
522
|
await updatePackage();
|
|
294
523
|
break;
|
|
524
|
+
case 'config':
|
|
525
|
+
handleConfig(options);
|
|
526
|
+
break;
|
|
295
527
|
case 'install-commands':
|
|
296
528
|
await installCommands();
|
|
297
529
|
break;
|
|
@@ -307,7 +539,7 @@ async function main() {
|
|
|
307
539
|
break;
|
|
308
540
|
}
|
|
309
541
|
default:
|
|
310
|
-
console.error(`\n ${c.red('
|
|
542
|
+
console.error(`\n ${c.red('FAIL')} Unknown command: ${command}`);
|
|
311
543
|
console.log(` Run ${c.bright('"uc help"')} for usage information.\n`);
|
|
312
544
|
process.exit(1);
|
|
313
545
|
}
|
|
@@ -315,6 +547,6 @@ async function main() {
|
|
|
315
547
|
|
|
316
548
|
// Run the CLI
|
|
317
549
|
main().catch(error => {
|
|
318
|
-
console.error(`\n ${c.red('
|
|
550
|
+
console.error(`\n ${c.red('FAIL')} Error: ${error.message}`);
|
|
319
551
|
process.exit(1);
|
|
320
552
|
});
|
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Environment Flag: Is Platform
|
|
3
|
-
*
|
|
2
|
+
* Environment Flag: Is Platform (Self-Hosted / Local Mode)
|
|
3
|
+
*
|
|
4
|
+
* When true, the app runs in single-user local mode:
|
|
5
|
+
* - Skips JWT authentication (uses first DB user)
|
|
6
|
+
* - Claude Code SDK runs directly on the machine
|
|
7
|
+
* - No relay connection needed
|
|
8
|
+
*
|
|
9
|
+
* Auto-detected when:
|
|
10
|
+
* - VITE_IS_PLATFORM=true is set, OR
|
|
11
|
+
* - Running locally (not on Railway/Vercel/cloud)
|
|
4
12
|
*/
|
|
5
|
-
|
|
13
|
+
const isCloudEnv = !!(
|
|
14
|
+
process.env.RAILWAY_ENVIRONMENT ||
|
|
15
|
+
process.env.VERCEL ||
|
|
16
|
+
process.env.RENDER ||
|
|
17
|
+
process.env.FLY_APP_NAME ||
|
|
18
|
+
process.env.HEROKU_APP_NAME
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export const IS_PLATFORM = process.env.VITE_IS_PLATFORM === 'true' || (!isCloudEnv && !process.env.FORCE_HOSTED_MODE);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* True when running on a cloud provider (Railway, Vercel, etc.)
|
|
25
|
+
*/
|
|
26
|
+
export const IS_CLOUD = isCloudEnv;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* True when running locally (self-hosted mode)
|
|
30
|
+
*/
|
|
31
|
+
export const IS_LOCAL = IS_PLATFORM && !isCloudEnv;
|
package/server/database/auth.db
CHANGED
|
Binary file
|