dr-claw 1.1.2
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/LICENSE +1380 -0
- package/NOTICE +17 -0
- package/README.md +875 -0
- package/README.zh-CN.md +857 -0
- package/dist/api-docs.html +878 -0
- package/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/assets/_basePickBy-C0n1uo4u.js +1 -0
- package/dist/assets/_baseUniq-BRNmhFkc.js +1 -0
- package/dist/assets/arc-DOMBmC_A.js +1 -0
- package/dist/assets/architectureDiagram-VXUJARFQ-CtMWglbD.js +36 -0
- package/dist/assets/blockDiagram-VD42YOAC-DK_gTkJy.js +122 -0
- package/dist/assets/c4Diagram-YG6GDRKO-DrDAvsn7.js +10 -0
- package/dist/assets/channel-BFOE7OyC.js +1 -0
- package/dist/assets/chunk-4BX2VUAB-CGbhdZcN.js +1 -0
- package/dist/assets/chunk-55IACEB6-sGeFSxen.js +1 -0
- package/dist/assets/chunk-B4BG7PRW-RxgHAU_P.js +165 -0
- package/dist/assets/chunk-DI55MBZ5-CvHUXZrx.js +220 -0
- package/dist/assets/chunk-FMBD7UC4-Sn7cXVNU.js +15 -0
- package/dist/assets/chunk-QN33PNHL-bDKOHppN.js +1 -0
- package/dist/assets/chunk-QZHKN3VN-B9kN5LGm.js +1 -0
- package/dist/assets/chunk-TZMSLE5B-CCBe6len.js +1 -0
- package/dist/assets/classDiagram-2ON5EDUG-DQoMNYlY.js +1 -0
- package/dist/assets/classDiagram-v2-WZHVMYZB-DQoMNYlY.js +1 -0
- package/dist/assets/clone-BulQSblH.js +1 -0
- package/dist/assets/cose-bilkent-S5V4N54A-r6sLiHBW.js +1 -0
- package/dist/assets/cytoscape.esm-5J0xJHOV.js +321 -0
- package/dist/assets/dagre-6UL2VRFP-AbsaR1Oa.js +4 -0
- package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/assets/diagram-PSM6KHXK-DjCvdUyy.js +24 -0
- package/dist/assets/diagram-QEK2KX5R-CqiocXkH.js +43 -0
- package/dist/assets/diagram-S2PKOQOG-D5ALeoII.js +24 -0
- package/dist/assets/erDiagram-Q2GNP2WA-C1AeOsiz.js +60 -0
- package/dist/assets/flowDiagram-NV44I4VS-C98ve_DO.js +162 -0
- package/dist/assets/ganttDiagram-JELNMOA3-3zdLvcxD.js +267 -0
- package/dist/assets/gitGraphDiagram-V2S2FVAM-nDuDMsHh.js +65 -0
- package/dist/assets/graph-Blm-emkR.js +1 -0
- package/dist/assets/index-B8Yutsnm.css +1 -0
- package/dist/assets/index-Cf6gyhc3.js +654 -0
- package/dist/assets/infoDiagram-HS3SLOUP-CmzE3q0R.js +2 -0
- package/dist/assets/init-Gi6I4Gst.js +1 -0
- package/dist/assets/journeyDiagram-XKPGCS4Q-CYaW7LrP.js +139 -0
- package/dist/assets/kanban-definition-3W4ZIXB7-mkmW7p0j.js +89 -0
- package/dist/assets/layout-Ct2kFIId.js +1 -0
- package/dist/assets/linear-CKG9EwIJ.js +1 -0
- package/dist/assets/mermaid.core-CaKcUnnd.js +250 -0
- package/dist/assets/mindmap-definition-VGOIOE7T-Bct-pYin.js +68 -0
- package/dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/assets/pieDiagram-ADFJNKIX-C8wFD4Jr.js +30 -0
- package/dist/assets/quadrantDiagram-AYHSOK5B-CuiE_f46.js +7 -0
- package/dist/assets/requirementDiagram-UZGBJVZJ-C4v1CqU8.js +64 -0
- package/dist/assets/sankeyDiagram-TZEHDZUN-keAqqs-Y.js +10 -0
- package/dist/assets/sequenceDiagram-WL72ISMW-ClNbvKTB.js +145 -0
- package/dist/assets/stateDiagram-FKZM4ZOC-D8We-2vq.js +1 -0
- package/dist/assets/stateDiagram-v2-4FDKWEC3-BUURfjrE.js +1 -0
- package/dist/assets/timeline-definition-IT6M3QCI-DsvEMT5T.js +61 -0
- package/dist/assets/treemap-GDKQZRPO-TJrzN7Bj.js +162 -0
- package/dist/assets/vendor-codemirror-ansM-eig.js +33 -0
- package/dist/assets/vendor-react-BWF6YQQ3.js +8 -0
- package/dist/assets/vendor-xterm-DfcmCpbH.js +66 -0
- package/dist/assets/xychartDiagram-PRI3JC2R-BdATmY5F.js +7 -0
- package/dist/clear-cache.html +85 -0
- package/dist/convert-icons.md +53 -0
- package/dist/dr-claw.png +0 -0
- package/dist/favicon.png +0 -0
- package/dist/generate-icons.js +49 -0
- package/dist/icons/claude-ai-icon.svg +1 -0
- package/dist/icons/codex-white.svg +3 -0
- package/dist/icons/codex.svg +3 -0
- package/dist/icons/cursor-white.svg +12 -0
- package/dist/icons/cursor.svg +1 -0
- package/dist/icons/file.svg +16997 -0
- package/dist/icons/generate-icons.md +19 -0
- package/dist/icons/icon-128x128.png +0 -0
- package/dist/icons/icon-144x144.png +0 -0
- package/dist/icons/icon-152x152.png +0 -0
- package/dist/icons/icon-192x192.png +0 -0
- package/dist/icons/icon-384x384.png +0 -0
- package/dist/icons/icon-512x512.png +0 -0
- package/dist/icons/icon-72x72.png +0 -0
- package/dist/icons/icon-96x96.png +0 -0
- package/dist/icons/news/arxiv.svg +1 -0
- package/dist/icons/news/huggingface.svg +8 -0
- package/dist/icons/news/x-black.png +0 -0
- package/dist/icons/news/x-white.png +0 -0
- package/dist/icons/news/xiaohongshu.png +0 -0
- package/dist/index.html +51 -0
- package/dist/leveraged-cognition.png +0 -0
- package/dist/manifest.json +61 -0
- package/dist/screenshots/chat.png +0 -0
- package/dist/screenshots/new_claw.png +0 -0
- package/dist/screenshots/news_dashboard.png +0 -0
- package/dist/screenshots/project_dashboard.png +0 -0
- package/dist/screenshots/research_lab.png +0 -0
- package/dist/screenshots/skill_library.png +0 -0
- package/dist/screenshots/task_list.png +0 -0
- package/dist/screenshots/terminal_example.png +0 -0
- package/dist/screenshots/terminal_example1.png +0 -0
- package/dist/sw.js +58 -0
- package/dist/wechat-group-qr.jpg +0 -0
- package/package.json +133 -0
- package/public/api-docs.html +878 -0
- package/public/clear-cache.html +85 -0
- package/public/convert-icons.md +53 -0
- package/public/dr-claw.png +0 -0
- package/public/favicon.png +0 -0
- package/public/generate-icons.js +49 -0
- package/public/icons/claude-ai-icon.svg +1 -0
- package/public/icons/codex-white.svg +3 -0
- package/public/icons/codex.svg +3 -0
- package/public/icons/cursor-white.svg +12 -0
- package/public/icons/cursor.svg +1 -0
- package/public/icons/file.svg +16997 -0
- package/public/icons/generate-icons.md +19 -0
- package/public/icons/icon-128x128.png +0 -0
- package/public/icons/icon-144x144.png +0 -0
- package/public/icons/icon-152x152.png +0 -0
- package/public/icons/icon-192x192.png +0 -0
- package/public/icons/icon-384x384.png +0 -0
- package/public/icons/icon-512x512.png +0 -0
- package/public/icons/icon-72x72.png +0 -0
- package/public/icons/icon-96x96.png +0 -0
- package/public/icons/news/arxiv.svg +1 -0
- package/public/icons/news/huggingface.svg +8 -0
- package/public/icons/news/x-black.png +0 -0
- package/public/icons/news/x-white.png +0 -0
- package/public/icons/news/xiaohongshu.png +0 -0
- package/public/leveraged-cognition.png +0 -0
- package/public/manifest.json +61 -0
- package/public/screenshots/chat.png +0 -0
- package/public/screenshots/new_claw.png +0 -0
- package/public/screenshots/news_dashboard.png +0 -0
- package/public/screenshots/project_dashboard.png +0 -0
- package/public/screenshots/research_lab.png +0 -0
- package/public/screenshots/skill_library.png +0 -0
- package/public/screenshots/task_list.png +0 -0
- package/public/screenshots/terminal_example.png +0 -0
- package/public/screenshots/terminal_example1.png +0 -0
- package/public/sw.js +58 -0
- package/public/wechat-group-qr.jpg +0 -0
- package/scripts/export-skills-catalog-v2.mjs +746 -0
- package/scripts/fix-node-pty.js +45 -0
- package/scripts/gemini_image_core.py +470 -0
- package/scripts/install-python-tools.js +64 -0
- package/server/AGENTS.md +73 -0
- package/server/__tests__/gemini-legacy-thought.test.mjs +88 -0
- package/server/__tests__/runtimePorts.test.mjs +115 -0
- package/server/__tests__/session-delete.test.mjs +166 -0
- package/server/bin/compute-node +70 -0
- package/server/claude-sdk.js +799 -0
- package/server/cli-chat.js +488 -0
- package/server/cli.js +354 -0
- package/server/compute-node.js +439 -0
- package/server/constants/config.js +5 -0
- package/server/cursor-cli.js +340 -0
- package/server/database/auth.db +0 -0
- package/server/database/db.js +1852 -0
- package/server/database/init.sql +194 -0
- package/server/gemini-cli.js +1352 -0
- package/server/index.js +3154 -0
- package/server/load-env.js +71 -0
- package/server/local-gpu.js +860 -0
- package/server/middleware/auth.js +100 -0
- package/server/openai-codex.js +724 -0
- package/server/openrouter.js +890 -0
- package/server/project-token-usage.js +407 -0
- package/server/projects.js +3973 -0
- package/server/routes/agent.js +1272 -0
- package/server/routes/auth.js +128 -0
- package/server/routes/auto-research.js +558 -0
- package/server/routes/cli-auth.js +958 -0
- package/server/routes/codex.js +344 -0
- package/server/routes/commands.js +601 -0
- package/server/routes/compute.js +358 -0
- package/server/routes/cursor.js +795 -0
- package/server/routes/git.js +1348 -0
- package/server/routes/mcp-utils.js +48 -0
- package/server/routes/mcp.js +618 -0
- package/server/routes/news.js +711 -0
- package/server/routes/projects.js +633 -0
- package/server/routes/references.js +338 -0
- package/server/routes/settings.js +285 -0
- package/server/routes/skills.js +914 -0
- package/server/routes/taskmaster.js +2566 -0
- package/server/routes/telemetry.js +89 -0
- package/server/routes/user.js +155 -0
- package/server/scripts/fix_session_names.js +57 -0
- package/server/scripts/research-news/common_words.py +19 -0
- package/server/scripts/research-news/link_keywords.py +298 -0
- package/server/scripts/research-news/scan_existing_notes.py +266 -0
- package/server/scripts/research-news/scoring_utils.py +227 -0
- package/server/scripts/research-news/search_arxiv.py +842 -0
- package/server/scripts/research-news/search_huggingface.py +438 -0
- package/server/scripts/research-news/search_x.py +490 -0
- package/server/scripts/research-news/search_xiaohongshu.py +610 -0
- package/server/taskmaster-templates/README.md +150 -0
- package/server/taskmaster-templates/README.zh-CN.md +150 -0
- package/server/taskmaster-templates/ai-research-dataset.json +230 -0
- package/server/taskmaster-templates/ai-research-method-model.json +230 -0
- package/server/taskmaster-templates/ai-research-position-paper.json +230 -0
- package/server/telemetry.js +121 -0
- package/server/templates/AGENTS.md +103 -0
- package/server/templates/CLAUDE.md +104 -0
- package/server/templates/GEMINI.md +103 -0
- package/server/templates/cursor-project.md +108 -0
- package/server/templates/index.js +37 -0
- package/server/utils/__tests__/sessionTokenUsage.test.js +82 -0
- package/server/utils/auto-research-mailer.js +57 -0
- package/server/utils/cliResolution.js +170 -0
- package/server/utils/commandParser.js +303 -0
- package/server/utils/cursorCommand.js +61 -0
- package/server/utils/geminiApiKey.js +28 -0
- package/server/utils/gitConfig.js +24 -0
- package/server/utils/imageAttachmentFiles.js +35 -0
- package/server/utils/mcp-detector.js +198 -0
- package/server/utils/parsers/bibtex-parser.js +207 -0
- package/server/utils/permissions.js +100 -0
- package/server/utils/runtimePorts.js +212 -0
- package/server/utils/sessionFormatting.js +68 -0
- package/server/utils/sessionIndex.js +100 -0
- package/server/utils/sessionMode.js +95 -0
- package/server/utils/sessionTokenUsage.js +105 -0
- package/server/utils/taskmaster-websocket.js +129 -0
- package/server/utils/zotero-client.js +136 -0
- package/shared/errorClassifier.js +102 -0
- package/shared/geminiThinkingSupport.d.ts +22 -0
- package/shared/geminiThinkingSupport.js +96 -0
- package/shared/geminiThoughtParser.d.ts +8 -0
- package/shared/geminiThoughtParser.js +30 -0
- package/shared/modelConstants.js +139 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zotero Client — interface for local Zotero desktop API.
|
|
3
|
+
*
|
|
4
|
+
* Local API: http://localhost:23119/api (Zotero desktop, no auth)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const LOCAL_BASE = 'http://localhost:23119/api';
|
|
8
|
+
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Helpers
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
async function fetchJson(url, options = {}) {
|
|
14
|
+
const res = await fetch(url, { ...options, signal: AbortSignal.timeout(15000) });
|
|
15
|
+
if (!res.ok) {
|
|
16
|
+
const text = await res.text().catch(() => '');
|
|
17
|
+
throw new Error(`Zotero API ${res.status}: ${text}`);
|
|
18
|
+
}
|
|
19
|
+
return res.json();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function fetchBuffer(url, options = {}) {
|
|
23
|
+
const res = await fetch(url, { ...options, signal: AbortSignal.timeout(60000) });
|
|
24
|
+
if (!res.ok) {
|
|
25
|
+
throw new Error(`Zotero file fetch ${res.status}`);
|
|
26
|
+
}
|
|
27
|
+
const arrayBuffer = await res.arrayBuffer();
|
|
28
|
+
return Buffer.from(arrayBuffer);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function mapZoteroItem(raw) {
|
|
32
|
+
const d = raw.data || raw;
|
|
33
|
+
const creators = (d.creators || []).map((c) => ({
|
|
34
|
+
family: c.lastName || '',
|
|
35
|
+
given: c.firstName || '',
|
|
36
|
+
}));
|
|
37
|
+
return {
|
|
38
|
+
sourceId: d.key || raw.key,
|
|
39
|
+
title: d.title || 'Untitled',
|
|
40
|
+
authors: creators,
|
|
41
|
+
year: d.date ? parseInt(d.date.match(/\b(\d{4})\b/)?.[1], 10) || null : null,
|
|
42
|
+
abstract: d.abstractNote || null,
|
|
43
|
+
doi: d.DOI || null,
|
|
44
|
+
url: d.url || null,
|
|
45
|
+
journal: d.publicationTitle || d.journalAbbreviation || null,
|
|
46
|
+
itemType: d.itemType || 'article',
|
|
47
|
+
keywords: (d.tags || []).map((t) => t.tag),
|
|
48
|
+
citationKey: d.citationKey || d.extra?.match(/Citation Key:\s*(\S+)/i)?.[1] || null,
|
|
49
|
+
rawData: raw,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Local client (Zotero Desktop — localhost:23119)
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
export class ZoteroLocalClient {
|
|
58
|
+
constructor() {
|
|
59
|
+
this.base = LOCAL_BASE;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Detailed status: { available, running, apiDisabled }. */
|
|
63
|
+
async checkStatus() {
|
|
64
|
+
try {
|
|
65
|
+
const res = await fetch(`${this.base}/users/0/items?limit=1`, { signal: AbortSignal.timeout(3000) });
|
|
66
|
+
if (res.ok) return { available: true, running: true, apiDisabled: false };
|
|
67
|
+
// 403 means Zotero is running but local API is disabled
|
|
68
|
+
return { available: false, running: true, apiDisabled: true };
|
|
69
|
+
} catch {
|
|
70
|
+
return { available: false, running: false, apiDisabled: false };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Returns true if the Zotero desktop app is reachable with API enabled. */
|
|
75
|
+
async isAvailable() {
|
|
76
|
+
const { available } = await this.checkStatus();
|
|
77
|
+
return available;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async getLibraries() {
|
|
81
|
+
// Local API only has the personal library (users/0).
|
|
82
|
+
return [{ id: 0, type: 'user', name: 'My Library' }];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async getCollections(libraryId = 0) {
|
|
86
|
+
const raw = await fetchJson(`${this.base}/users/${libraryId}/collections`);
|
|
87
|
+
return raw.map((c) => ({
|
|
88
|
+
key: c.data?.key || c.key,
|
|
89
|
+
name: c.data?.name || c.name || '',
|
|
90
|
+
parentKey: c.data?.parentCollection || null,
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async getItems(libraryId = 0, { collectionKey, query, limit = 50, start = 0 } = {}) {
|
|
95
|
+
const params = new URLSearchParams({ limit: String(limit), start: String(start), itemType: '-attachment' });
|
|
96
|
+
if (query) params.set('q', query);
|
|
97
|
+
const base = collectionKey
|
|
98
|
+
? `${this.base}/users/${libraryId}/collections/${encodeURIComponent(collectionKey)}/items`
|
|
99
|
+
: `${this.base}/users/${libraryId}/items`;
|
|
100
|
+
const raw = await fetchJson(`${base}?${params}`);
|
|
101
|
+
return raw.map(mapZoteroItem);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async searchItems(libraryId = 0, query) {
|
|
105
|
+
return this.getItems(libraryId, { query });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async getItemPdf(libraryId = 0, itemKey) {
|
|
109
|
+
// Fetch children to find the PDF attachment.
|
|
110
|
+
const children = await fetchJson(`${this.base}/users/${libraryId}/items/${encodeURIComponent(itemKey)}/children`);
|
|
111
|
+
const pdfAttachment = children.find(
|
|
112
|
+
(c) => (c.data?.contentType || c.contentType) === 'application/pdf',
|
|
113
|
+
);
|
|
114
|
+
if (!pdfAttachment) return null;
|
|
115
|
+
const attachKey = pdfAttachment.data?.key || pdfAttachment.key;
|
|
116
|
+
return fetchBuffer(`${this.base}/users/${libraryId}/items/${attachKey}/file`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// Factory: local-only
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Returns {client, mode} where mode is 'local' | null.
|
|
126
|
+
*/
|
|
127
|
+
export async function getZoteroClient() {
|
|
128
|
+
const local = new ZoteroLocalClient();
|
|
129
|
+
const localStatus = await local.checkStatus();
|
|
130
|
+
|
|
131
|
+
if (localStatus.available) {
|
|
132
|
+
return { client: local, mode: 'local', localRunning: true, localApiDisabled: false };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return { client: null, mode: null, localRunning: localStatus.running, localApiDisabled: localStatus.apiDisabled };
|
|
136
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared error classification for all agent providers.
|
|
3
|
+
* Single source of truth for error type detection and retryability.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const ERROR_TYPES = /** @type {const} */ ({
|
|
7
|
+
USAGE_LIMIT: 'usage_limit',
|
|
8
|
+
OVERLOADED: 'overloaded',
|
|
9
|
+
NETWORK: 'network',
|
|
10
|
+
AUTH: 'auth',
|
|
11
|
+
UNKNOWN: 'unknown',
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const RE_USAGE_LIMIT = /usage[_ ]limit|rate[_ ]limit|Too Many Requests|\b429\b|RESOURCE_EXHAUSTED|capacity exhausted|quota/i;
|
|
15
|
+
const RE_OVERLOADED = /overloaded|MODEL_CAPACITY_EXHAUSTED|No capacity available|server[_ ]error/i;
|
|
16
|
+
const RE_NETWORK = /network|ECONNREFUSED|ETIMEDOUT|ECONNRESET|ENOTFOUND|socket hang up/i;
|
|
17
|
+
const RE_AUTH = /\bauth\b|unauthorized|forbidden|authentication[_ ]failed|billing[_ ]error|invalid[_ ]api[_ ]key/i;
|
|
18
|
+
|
|
19
|
+
function makeResult(errorType) {
|
|
20
|
+
return { errorType, isRetryable: errorType !== ERROR_TYPES.AUTH };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** @param {string} message */
|
|
24
|
+
export function classifyError(message) {
|
|
25
|
+
const msg = String(message || '');
|
|
26
|
+
|
|
27
|
+
if (RE_USAGE_LIMIT.test(msg)) return makeResult(ERROR_TYPES.USAGE_LIMIT);
|
|
28
|
+
if (RE_OVERLOADED.test(msg)) return makeResult(ERROR_TYPES.OVERLOADED);
|
|
29
|
+
if (RE_NETWORK.test(msg)) return makeResult(ERROR_TYPES.NETWORK);
|
|
30
|
+
if (RE_AUTH.test(msg)) return makeResult(ERROR_TYPES.AUTH);
|
|
31
|
+
|
|
32
|
+
return makeResult(ERROR_TYPES.UNKNOWN);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const TRANSIENT_ERROR_TYPES = /** @type {const} */ ([
|
|
36
|
+
ERROR_TYPES.NETWORK,
|
|
37
|
+
ERROR_TYPES.OVERLOADED,
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Per-provider SDK error code → ERROR_TYPES mappings.
|
|
42
|
+
*
|
|
43
|
+
* Claude (AssistantMessageError):
|
|
44
|
+
* 'authentication_failed' | 'billing_error' | 'rate_limit' |
|
|
45
|
+
* 'invalid_request' | 'server_error' | 'max_output_tokens' | 'unknown'
|
|
46
|
+
*
|
|
47
|
+
* Codex (ResponseError.code):
|
|
48
|
+
* 'server_error' | 'rate_limit_exceeded' | 'invalid_prompt' | ...
|
|
49
|
+
*
|
|
50
|
+
* Gemini (structured error codes from CLI stderr):
|
|
51
|
+
* 'RESOURCE_EXHAUSTED' | 'PERMISSION_DENIED' | 'INTERNAL' | ...
|
|
52
|
+
*/
|
|
53
|
+
const CLAUDE_ERROR_MAP = {
|
|
54
|
+
rate_limit: ERROR_TYPES.USAGE_LIMIT,
|
|
55
|
+
authentication_failed: ERROR_TYPES.AUTH,
|
|
56
|
+
billing_error: ERROR_TYPES.AUTH,
|
|
57
|
+
server_error: ERROR_TYPES.OVERLOADED,
|
|
58
|
+
invalid_request: ERROR_TYPES.UNKNOWN,
|
|
59
|
+
max_output_tokens: ERROR_TYPES.UNKNOWN,
|
|
60
|
+
unknown: ERROR_TYPES.UNKNOWN,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const CODEX_ERROR_MAP = {
|
|
64
|
+
rate_limit_exceeded: ERROR_TYPES.USAGE_LIMIT,
|
|
65
|
+
server_error: ERROR_TYPES.OVERLOADED,
|
|
66
|
+
invalid_prompt: ERROR_TYPES.UNKNOWN,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const GEMINI_ERROR_MAP = {
|
|
70
|
+
RESOURCE_EXHAUSTED: ERROR_TYPES.USAGE_LIMIT,
|
|
71
|
+
PERMISSION_DENIED: ERROR_TYPES.AUTH,
|
|
72
|
+
UNAUTHENTICATED: ERROR_TYPES.AUTH,
|
|
73
|
+
INTERNAL: ERROR_TYPES.OVERLOADED,
|
|
74
|
+
UNAVAILABLE: ERROR_TYPES.OVERLOADED,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const PROVIDER_ERROR_MAPS = {
|
|
78
|
+
claude: CLAUDE_ERROR_MAP,
|
|
79
|
+
codex: CODEX_ERROR_MAP,
|
|
80
|
+
gemini: GEMINI_ERROR_MAP,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Classify from a provider SDK structured error code.
|
|
85
|
+
* @param {string} sdkErrorCode - e.g. 'rate_limit', 'rate_limit_exceeded', 'RESOURCE_EXHAUSTED'
|
|
86
|
+
* @param {'claude' | 'codex' | 'gemini'} [provider] - provider name for precise mapping; omit to search all
|
|
87
|
+
* @returns {{ errorType: string, isRetryable: boolean }}
|
|
88
|
+
*/
|
|
89
|
+
export function classifySDKError(sdkErrorCode, provider) {
|
|
90
|
+
let errorType;
|
|
91
|
+
|
|
92
|
+
if (provider && PROVIDER_ERROR_MAPS[provider]) {
|
|
93
|
+
errorType = PROVIDER_ERROR_MAPS[provider][sdkErrorCode];
|
|
94
|
+
} else {
|
|
95
|
+
for (const map of Object.values(PROVIDER_ERROR_MAPS)) {
|
|
96
|
+
errorType = map[sdkErrorCode];
|
|
97
|
+
if (errorType) break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return makeResult(errorType || ERROR_TYPES.UNKNOWN);
|
|
102
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type GeminiThinkingModeId =
|
|
2
|
+
| 'default'
|
|
3
|
+
| 'minimal'
|
|
4
|
+
| 'low'
|
|
5
|
+
| 'medium'
|
|
6
|
+
| 'high'
|
|
7
|
+
| 'dynamic'
|
|
8
|
+
| 'off'
|
|
9
|
+
| 'light'
|
|
10
|
+
| 'balanced'
|
|
11
|
+
| 'deep'
|
|
12
|
+
| 'max';
|
|
13
|
+
|
|
14
|
+
export type GeminiThinkingFamily = 'gemini-3' | 'gemini-2.5' | null;
|
|
15
|
+
|
|
16
|
+
export function getGeminiThinkingFamily(model: string): GeminiThinkingFamily;
|
|
17
|
+
export function getSupportedGeminiThinkingModes(model: string): GeminiThinkingModeId[];
|
|
18
|
+
export function supportsExplicitGeminiThinkingMode(model: string): boolean;
|
|
19
|
+
export function buildGeminiThinkingConfig(
|
|
20
|
+
model: string,
|
|
21
|
+
mode?: GeminiThinkingModeId | null,
|
|
22
|
+
): { thinkingLevel?: 'MINIMAL' | 'LOW' | 'MEDIUM' | 'HIGH'; thinkingBudget?: number } | null;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export const GEMINI_THINKING_MODE_IDS = [
|
|
2
|
+
'default',
|
|
3
|
+
'minimal',
|
|
4
|
+
'low',
|
|
5
|
+
'medium',
|
|
6
|
+
'high',
|
|
7
|
+
'dynamic',
|
|
8
|
+
'off',
|
|
9
|
+
'light',
|
|
10
|
+
'balanced',
|
|
11
|
+
'deep',
|
|
12
|
+
'max',
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
function isGemini3Model(model) {
|
|
16
|
+
return typeof model === 'string' && model.startsWith('gemini-3');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isGemini25Model(model) {
|
|
20
|
+
return typeof model === 'string' && model.startsWith('gemini-2.5');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getGeminiThinkingFamily(model) {
|
|
24
|
+
if (isGemini3Model(model)) return 'gemini-3';
|
|
25
|
+
if (isGemini25Model(model)) return 'gemini-2.5';
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getSupportedGeminiThinkingModes(model) {
|
|
30
|
+
switch (model) {
|
|
31
|
+
case 'gemini-3.1-pro-preview':
|
|
32
|
+
return ['default', 'low', 'medium', 'high'];
|
|
33
|
+
case 'gemini-3.1-flash-lite-preview':
|
|
34
|
+
case 'gemini-3-flash-preview':
|
|
35
|
+
return ['default', 'minimal', 'low', 'medium', 'high'];
|
|
36
|
+
case 'gemini-2.5-pro':
|
|
37
|
+
return ['default', 'dynamic', 'light', 'balanced', 'deep', 'max'];
|
|
38
|
+
case 'gemini-2.5-flash':
|
|
39
|
+
case 'gemini-2.5-flash-lite':
|
|
40
|
+
return ['default', 'dynamic', 'off', 'light', 'balanced', 'deep'];
|
|
41
|
+
default:
|
|
42
|
+
return ['default'];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function supportsExplicitGeminiThinkingMode(model) {
|
|
47
|
+
return getSupportedGeminiThinkingModes(model).length > 1;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function buildGeminiThinkingConfig(model, mode) {
|
|
51
|
+
if (!model || !mode || mode === 'default') {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (isGemini3Model(model)) {
|
|
56
|
+
const levelMap = {
|
|
57
|
+
minimal: 'MINIMAL',
|
|
58
|
+
low: 'LOW',
|
|
59
|
+
medium: 'MEDIUM',
|
|
60
|
+
high: 'HIGH',
|
|
61
|
+
};
|
|
62
|
+
const thinkingLevel = levelMap[mode];
|
|
63
|
+
return thinkingLevel ? { thinkingLevel } : null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (isGemini25Model(model)) {
|
|
67
|
+
const budgetMapByModel = {
|
|
68
|
+
'gemini-2.5-pro': {
|
|
69
|
+
dynamic: -1,
|
|
70
|
+
light: 1024,
|
|
71
|
+
balanced: 8192,
|
|
72
|
+
deep: 24576,
|
|
73
|
+
max: 32768,
|
|
74
|
+
},
|
|
75
|
+
'gemini-2.5-flash': {
|
|
76
|
+
dynamic: -1,
|
|
77
|
+
off: 0,
|
|
78
|
+
light: 1024,
|
|
79
|
+
balanced: 8192,
|
|
80
|
+
deep: 24576,
|
|
81
|
+
},
|
|
82
|
+
'gemini-2.5-flash-lite': {
|
|
83
|
+
dynamic: -1,
|
|
84
|
+
off: 0,
|
|
85
|
+
light: 512,
|
|
86
|
+
balanced: 8192,
|
|
87
|
+
deep: 24576,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const budget = budgetMapByModel[model]?.[mode];
|
|
92
|
+
return Number.isInteger(budget) ? { thinkingBudget: budget } : null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Splits Gemini legacy "[Thought: true]" markers in assistant text
|
|
3
|
+
* into structured segments with thinking/final flags.
|
|
4
|
+
*
|
|
5
|
+
* Shared between server (gemini-cli.js) and client (chatFormatting.ts)
|
|
6
|
+
* to ensure consistent parsing behavior.
|
|
7
|
+
*
|
|
8
|
+
* @param {string} text - The assistant message text to parse.
|
|
9
|
+
* @returns {{ content: string, isThinking: boolean }[] | null}
|
|
10
|
+
* Array of segments if markers are found, null otherwise.
|
|
11
|
+
*/
|
|
12
|
+
export function splitLegacyGeminiThoughtContent(text) {
|
|
13
|
+
if (!text || typeof text !== 'string' || !/\[Thought:\s*true\]/i.test(text)) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const segments = text
|
|
18
|
+
.split(/\n?\s*\[Thought:\s*true\]\s*/i)
|
|
19
|
+
.map((segment) => segment.trim())
|
|
20
|
+
.filter(Boolean);
|
|
21
|
+
|
|
22
|
+
if (segments.length < 2) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return segments.map((segment, index) => ({
|
|
27
|
+
content: segment,
|
|
28
|
+
isThinking: index < segments.length - 1,
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized Model Definitions
|
|
3
|
+
* Single source of truth for all supported AI models
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Claude (Anthropic) Models
|
|
8
|
+
*
|
|
9
|
+
* Note: Claude uses two different formats:
|
|
10
|
+
* - SDK format ('sonnet', 'opus') - used by the UI and claude-sdk.js
|
|
11
|
+
* - API format ('claude-sonnet-4.5') - used by slash commands for display
|
|
12
|
+
*/
|
|
13
|
+
export const CLAUDE_MODELS = {
|
|
14
|
+
// Models in SDK format (what the actual SDK accepts)
|
|
15
|
+
OPTIONS: [
|
|
16
|
+
{ value: 'sonnet', label: 'Sonnet' },
|
|
17
|
+
{ value: 'opus', label: 'Opus' },
|
|
18
|
+
{ value: 'haiku', label: 'Haiku' },
|
|
19
|
+
{ value: 'opusplan', label: 'Opus (Plan Mode Only)' },
|
|
20
|
+
{ value: 'sonnet[1m]', label: 'Sonnet [1M]' },
|
|
21
|
+
{ value: 'claude-opus-4-6', label: 'Opus 4.6' }
|
|
22
|
+
],
|
|
23
|
+
|
|
24
|
+
DEFAULT: (typeof process !== 'undefined' && process.env?.ANTHROPIC_MODEL) || 'claude-opus-4-6'
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Cursor Models
|
|
29
|
+
*/
|
|
30
|
+
export const CURSOR_MODELS = {
|
|
31
|
+
OPTIONS: [
|
|
32
|
+
{ value: 'gpt-5.2-high', label: 'GPT-5.2 High' },
|
|
33
|
+
{ value: 'gemini-3-pro', label: 'Gemini 3 Pro' },
|
|
34
|
+
{ value: 'opus-4.5-thinking', label: 'Claude 4.5 Opus (Thinking)' },
|
|
35
|
+
{ value: 'gpt-5.2', label: 'GPT-5.2' },
|
|
36
|
+
{ value: 'gpt-5.1', label: 'GPT-5.1' },
|
|
37
|
+
{ value: 'gpt-5.1-high', label: 'GPT-5.1 High' },
|
|
38
|
+
{ value: 'composer-1', label: 'Composer 1' },
|
|
39
|
+
{ value: 'auto', label: 'Auto' },
|
|
40
|
+
{ value: 'sonnet-4.5', label: 'Claude 4.5 Sonnet' },
|
|
41
|
+
{ value: 'sonnet-4.5-thinking', label: 'Claude 4.5 Sonnet (Thinking)' },
|
|
42
|
+
{ value: 'opus-4.5', label: 'Claude 4.5 Opus' },
|
|
43
|
+
{ value: 'gpt-5.1-codex', label: 'GPT-5.1 Codex' },
|
|
44
|
+
{ value: 'gpt-5.1-codex-high', label: 'GPT-5.1 Codex High' },
|
|
45
|
+
{ value: 'gpt-5.1-codex-max', label: 'GPT-5.1 Codex Max' },
|
|
46
|
+
{ value: 'gpt-5.1-codex-max-high', label: 'GPT-5.1 Codex Max High' },
|
|
47
|
+
{ value: 'opus-4.1', label: 'Claude 4.1 Opus' },
|
|
48
|
+
{ value: 'grok', label: 'Grok' }
|
|
49
|
+
],
|
|
50
|
+
|
|
51
|
+
DEFAULT: 'gpt-5'
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Codex (OpenAI) Models
|
|
56
|
+
*/
|
|
57
|
+
export const CODEX_MODELS = {
|
|
58
|
+
OPTIONS: [
|
|
59
|
+
{ value: 'gpt-5.4', label: 'GPT-5.4' },
|
|
60
|
+
{ value: 'gpt-5.3-codex', label: 'GPT-5.3 Codex' },
|
|
61
|
+
{ value: 'gpt-5.2-codex', label: 'GPT-5.2 Codex' },
|
|
62
|
+
{ value: 'gpt-5.2', label: 'GPT-5.2' },
|
|
63
|
+
{ value: 'gpt-5.1-codex-max', label: 'GPT-5.1 Codex Max' },
|
|
64
|
+
{ value: 'o3', label: 'O3' },
|
|
65
|
+
{ value: 'o4-mini', label: 'O4-mini' }
|
|
66
|
+
],
|
|
67
|
+
|
|
68
|
+
DEFAULT: 'gpt-5.4'
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* OpenRouter Models
|
|
73
|
+
* Users can also type any model slug from https://openrouter.ai/models
|
|
74
|
+
*/
|
|
75
|
+
export const OPENROUTER_MODELS = {
|
|
76
|
+
OPTIONS: [
|
|
77
|
+
// Anthropic
|
|
78
|
+
{ value: 'anthropic/claude-sonnet-4', label: 'Claude Sonnet 4 (Anthropic)' },
|
|
79
|
+
{ value: 'anthropic/claude-opus-4', label: 'Claude Opus 4 (Anthropic)' },
|
|
80
|
+
{ value: 'anthropic/claude-haiku-3.5', label: 'Claude 3.5 Haiku (Anthropic)' },
|
|
81
|
+
// OpenAI
|
|
82
|
+
{ value: 'openai/gpt-5', label: 'GPT-5 (OpenAI)' },
|
|
83
|
+
{ value: 'openai/gpt-4.1', label: 'GPT-4.1 (OpenAI)' },
|
|
84
|
+
{ value: 'openai/gpt-4.1-mini', label: 'GPT-4.1 Mini (OpenAI)' },
|
|
85
|
+
{ value: 'openai/o3', label: 'O3 (OpenAI)' },
|
|
86
|
+
{ value: 'openai/o4-mini', label: 'O4 Mini (OpenAI)' },
|
|
87
|
+
// Google
|
|
88
|
+
{ value: 'google/gemini-2.5-pro', label: 'Gemini 2.5 Pro (Google)' },
|
|
89
|
+
{ value: 'google/gemini-2.5-flash', label: 'Gemini 2.5 Flash (Google)' },
|
|
90
|
+
// DeepSeek
|
|
91
|
+
{ value: 'deepseek/deepseek-r1', label: 'DeepSeek R1' },
|
|
92
|
+
{ value: 'deepseek/deepseek-chat-v3-0324', label: 'DeepSeek V3 0324' },
|
|
93
|
+
// Meta
|
|
94
|
+
{ value: 'meta-llama/llama-4-maverick', label: 'Llama 4 Maverick (Meta)' },
|
|
95
|
+
{ value: 'meta-llama/llama-4-scout', label: 'Llama 4 Scout (Meta)' },
|
|
96
|
+
// Mistral
|
|
97
|
+
{ value: 'mistralai/mistral-large', label: 'Mistral Large' },
|
|
98
|
+
{ value: 'mistralai/codestral', label: 'Codestral (Mistral)' },
|
|
99
|
+
// Qwen
|
|
100
|
+
{ value: 'qwen/qwen3-235b-a22b', label: 'Qwen3 235B' },
|
|
101
|
+
{ value: 'qwen/qwen3-32b', label: 'Qwen3 32B' },
|
|
102
|
+
// xAI
|
|
103
|
+
{ value: 'x-ai/grok-3', label: 'Grok 3 (xAI)' },
|
|
104
|
+
{ value: 'x-ai/grok-3-mini', label: 'Grok 3 Mini (xAI)' },
|
|
105
|
+
// Cohere
|
|
106
|
+
{ value: 'cohere/command-a', label: 'Command A (Cohere)' },
|
|
107
|
+
],
|
|
108
|
+
|
|
109
|
+
ALLOWS_CUSTOM: true,
|
|
110
|
+
|
|
111
|
+
DEFAULT: (typeof process !== 'undefined' && process.env?.OPENROUTER_MODEL) || 'anthropic/claude-sonnet-4'
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Local GPU Models (open-source models for self-hosted deployment)
|
|
116
|
+
*/
|
|
117
|
+
export const LOCAL_MODELS = {
|
|
118
|
+
OPTIONS: [],
|
|
119
|
+
|
|
120
|
+
IS_LOCAL: true,
|
|
121
|
+
|
|
122
|
+
DEFAULT: ''
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Gemini (Google) Models
|
|
127
|
+
*/
|
|
128
|
+
export const GEMINI_MODELS = {
|
|
129
|
+
OPTIONS: [
|
|
130
|
+
{ value: 'gemini-3.1-pro-preview', label: 'Gemini 3.1 Pro Preview' },
|
|
131
|
+
{ value: 'gemini-3.1-flash-lite-preview', label: 'Gemini 3.1 Flash Lite Preview' },
|
|
132
|
+
{ value: 'gemini-3-flash-preview', label: 'Gemini 3 Flash Preview' },
|
|
133
|
+
{ value: 'gemini-2.5-pro', label: 'Gemini 2.5 Pro' },
|
|
134
|
+
{ value: 'gemini-2.5-flash', label: 'Gemini 2.5 Flash' },
|
|
135
|
+
{ value: 'gemini-2.5-flash-lite', label: 'Gemini 2.5 Flash Lite' }
|
|
136
|
+
],
|
|
137
|
+
|
|
138
|
+
DEFAULT: 'gemini-3-flash-preview'
|
|
139
|
+
};
|