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/routes/auth.js
CHANGED
|
@@ -19,8 +19,12 @@ router.get('/status', async (req, res) => {
|
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
// User registration — allows multiple users
|
|
23
|
-
router.post('/register',
|
|
22
|
+
// User registration — allows multiple users (rate limited)
|
|
23
|
+
router.post('/register', (req, res, next) => {
|
|
24
|
+
const rl = req.app.locals.authRateLimit;
|
|
25
|
+
if (rl) return rl(req, res, next);
|
|
26
|
+
next();
|
|
27
|
+
}, async (req, res) => {
|
|
24
28
|
try {
|
|
25
29
|
const { username, password, email, phone, firstName, lastName } = req.body;
|
|
26
30
|
|
|
@@ -28,13 +32,16 @@ router.post('/register', async (req, res) => {
|
|
|
28
32
|
if (!password) {
|
|
29
33
|
return res.status(400).json({ error: 'Password is required' });
|
|
30
34
|
}
|
|
31
|
-
if (password.length <
|
|
32
|
-
return res.status(400).json({ error: 'Password must be at least
|
|
35
|
+
if (password.length < 8) {
|
|
36
|
+
return res.status(400).json({ error: 'Password must be at least 8 characters' });
|
|
37
|
+
}
|
|
38
|
+
if (password.length > 128) {
|
|
39
|
+
return res.status(400).json({ error: 'Password is too long' });
|
|
33
40
|
}
|
|
34
41
|
|
|
35
|
-
//
|
|
36
|
-
const fName = (firstName || '').trim();
|
|
37
|
-
const lName = (lastName || '').trim();
|
|
42
|
+
// Sanitize and validate name/phone inputs
|
|
43
|
+
const fName = (firstName || '').trim().slice(0, 50);
|
|
44
|
+
const lName = (lastName || '').trim().slice(0, 50);
|
|
38
45
|
const displayName = username || [fName, lName].filter(Boolean).join(' ') || 'User';
|
|
39
46
|
|
|
40
47
|
if (displayName.length < 2) {
|
|
@@ -86,8 +93,12 @@ router.post('/register', async (req, res) => {
|
|
|
86
93
|
}
|
|
87
94
|
});
|
|
88
95
|
|
|
89
|
-
// User login
|
|
90
|
-
router.post('/login',
|
|
96
|
+
// User login (rate limited)
|
|
97
|
+
router.post('/login', (req, res, next) => {
|
|
98
|
+
const rl = req.app.locals.authRateLimit;
|
|
99
|
+
if (rl) return rl(req, res, next);
|
|
100
|
+
next();
|
|
101
|
+
}, async (req, res) => {
|
|
91
102
|
try {
|
|
92
103
|
const { username, password, firstName, lastName, phone } = req.body;
|
|
93
104
|
|
|
@@ -106,9 +117,9 @@ router.post('/login', async (req, res) => {
|
|
|
106
117
|
}
|
|
107
118
|
|
|
108
119
|
// Update name/phone if provided and different from stored values
|
|
109
|
-
const fName = (firstName || '').trim();
|
|
110
|
-
const lName = (lastName || '').trim();
|
|
111
|
-
const ph = (phone || '').trim();
|
|
120
|
+
const fName = (firstName || '').trim().slice(0, 50);
|
|
121
|
+
const lName = (lastName || '').trim().slice(0, 50);
|
|
122
|
+
const ph = (phone || '').trim().slice(0, 20);
|
|
112
123
|
const updates = [];
|
|
113
124
|
const args = [];
|
|
114
125
|
if (fName && fName !== user.first_name) { updates.push('first_name = ?'); args.push(fName); }
|
|
@@ -293,7 +293,7 @@ Custom commands can be created in:
|
|
|
293
293
|
// Read version from package.json
|
|
294
294
|
const packageJsonPath = path.join(path.dirname(__dirname), '..', 'package.json');
|
|
295
295
|
let version = 'unknown';
|
|
296
|
-
let packageName = '
|
|
296
|
+
let packageName = 'upfynai-code';
|
|
297
297
|
|
|
298
298
|
try {
|
|
299
299
|
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
|
@@ -175,4 +175,95 @@ router.patch('/credentials/:credentialId/toggle', async (req, res) => {
|
|
|
175
175
|
}
|
|
176
176
|
});
|
|
177
177
|
|
|
178
|
+
// ===============================
|
|
179
|
+
// AI Provider Keys (BYOK)
|
|
180
|
+
// ===============================
|
|
181
|
+
|
|
182
|
+
const AI_PROVIDER_TYPES = [
|
|
183
|
+
'anthropic_key',
|
|
184
|
+
'openai_key',
|
|
185
|
+
'openrouter_key',
|
|
186
|
+
'google_key',
|
|
187
|
+
];
|
|
188
|
+
|
|
189
|
+
// Get all AI provider keys for the authenticated user (masked values)
|
|
190
|
+
router.get('/ai-providers', async (req, res) => {
|
|
191
|
+
try {
|
|
192
|
+
const allCreds = [];
|
|
193
|
+
for (const type of AI_PROVIDER_TYPES) {
|
|
194
|
+
const creds = await credentialsDb.getCredentials(req.user.id, type);
|
|
195
|
+
allCreds.push(...creds.map(c => ({
|
|
196
|
+
id: c.id,
|
|
197
|
+
credential_name: c.credential_name,
|
|
198
|
+
credential_type: c.credential_type,
|
|
199
|
+
description: c.description,
|
|
200
|
+
is_active: c.is_active,
|
|
201
|
+
created_at: c.created_at,
|
|
202
|
+
// Mask the key — show first 8 and last 4 chars
|
|
203
|
+
masked_value: c.credential_value
|
|
204
|
+
? c.credential_value.slice(0, 8) + '...' + c.credential_value.slice(-4)
|
|
205
|
+
: '***',
|
|
206
|
+
})));
|
|
207
|
+
}
|
|
208
|
+
res.json({ providers: allCreds });
|
|
209
|
+
} catch (error) {
|
|
210
|
+
res.status(500).json({ error: 'Failed to fetch AI provider keys' });
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Save an AI provider key
|
|
215
|
+
router.post('/ai-providers', async (req, res) => {
|
|
216
|
+
try {
|
|
217
|
+
const { providerType, apiKey, name } = req.body;
|
|
218
|
+
|
|
219
|
+
if (!providerType || !AI_PROVIDER_TYPES.includes(providerType)) {
|
|
220
|
+
return res.status(400).json({ error: `Invalid provider type. Supported: ${AI_PROVIDER_TYPES.join(', ')}` });
|
|
221
|
+
}
|
|
222
|
+
if (!apiKey || !apiKey.trim()) {
|
|
223
|
+
return res.status(400).json({ error: 'API key is required' });
|
|
224
|
+
}
|
|
225
|
+
if (apiKey.trim().length < 10 || apiKey.trim().length > 256) {
|
|
226
|
+
return res.status(400).json({ error: 'Invalid API key length' });
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const label = providerType.replace('_key', '').replace('_', ' ');
|
|
230
|
+
const credName = name?.trim() || `${label} API key`;
|
|
231
|
+
|
|
232
|
+
// Deactivate existing keys of same type (user should only have one active per provider)
|
|
233
|
+
const existing = await credentialsDb.getCredentials(req.user.id, providerType);
|
|
234
|
+
for (const cred of existing) {
|
|
235
|
+
if (cred.is_active) {
|
|
236
|
+
await credentialsDb.toggleCredential(req.user.id, cred.id, false);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const result = await credentialsDb.createCredential(
|
|
241
|
+
req.user.id,
|
|
242
|
+
credName,
|
|
243
|
+
providerType,
|
|
244
|
+
apiKey.trim(),
|
|
245
|
+
`User-provided ${label} API key`
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
res.json({ success: true, credential: { id: result.id, credential_type: providerType, credential_name: credName } });
|
|
249
|
+
} catch (error) {
|
|
250
|
+
res.status(500).json({ error: 'Failed to save AI provider key' });
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Delete an AI provider key
|
|
255
|
+
router.delete('/ai-providers/:credentialId', async (req, res) => {
|
|
256
|
+
try {
|
|
257
|
+
const { credentialId } = req.params;
|
|
258
|
+
const success = await credentialsDb.deleteCredential(req.user.id, parseInt(credentialId));
|
|
259
|
+
if (success) {
|
|
260
|
+
res.json({ success: true });
|
|
261
|
+
} else {
|
|
262
|
+
res.status(404).json({ error: 'Provider key not found' });
|
|
263
|
+
}
|
|
264
|
+
} catch (error) {
|
|
265
|
+
res.status(500).json({ error: 'Failed to delete provider key' });
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
|
|
178
269
|
export default router;
|
package/shared/modelConstants.js
CHANGED
|
@@ -65,3 +65,32 @@ export const CODEX_MODELS = {
|
|
|
65
65
|
|
|
66
66
|
DEFAULT: 'gpt-5.2'
|
|
67
67
|
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* OpenRouter Models (BYOK — user brings their own API key)
|
|
71
|
+
* Access 200+ models from all major providers through a single API.
|
|
72
|
+
*/
|
|
73
|
+
export const OPENROUTER_MODELS = {
|
|
74
|
+
OPTIONS: [
|
|
75
|
+
{ value: 'anthropic/claude-sonnet-4', label: 'Claude Sonnet 4' },
|
|
76
|
+
{ value: 'anthropic/claude-opus-4', label: 'Claude Opus 4' },
|
|
77
|
+
{ value: 'openai/gpt-4o', label: 'GPT-4o' },
|
|
78
|
+
{ value: 'openai/o3', label: 'O3' },
|
|
79
|
+
{ value: 'google/gemini-2.5-pro', label: 'Gemini 2.5 Pro' },
|
|
80
|
+
{ value: 'meta-llama/llama-4-maverick', label: 'Llama 4 Maverick' },
|
|
81
|
+
{ value: 'mistralai/mistral-large', label: 'Mistral Large' },
|
|
82
|
+
{ value: 'deepseek/deepseek-r1', label: 'DeepSeek R1' },
|
|
83
|
+
],
|
|
84
|
+
|
|
85
|
+
DEFAULT: 'anthropic/claude-sonnet-4'
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* AI Provider types for BYOK (Bring Your Own Key)
|
|
90
|
+
*/
|
|
91
|
+
export const AI_PROVIDER_TYPES = [
|
|
92
|
+
{ type: 'anthropic_key', label: 'Anthropic', prefix: 'sk-ant-', placeholder: 'sk-ant-api03-...' },
|
|
93
|
+
{ type: 'openai_key', label: 'OpenAI', prefix: 'sk-', placeholder: 'sk-...' },
|
|
94
|
+
{ type: 'openrouter_key', label: 'OpenRouter', prefix: 'sk-or-', placeholder: 'sk-or-v1-...' },
|
|
95
|
+
{ type: 'google_key', label: 'Google AI', prefix: 'AI', placeholder: 'AIza...' },
|
|
96
|
+
];
|