@jait/gateway 0.1.434 → 0.1.436
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/dist/providers/acp-provider.d.ts +2 -0
- package/dist/providers/acp-provider.d.ts.map +1 -1
- package/dist/providers/acp-provider.js +53 -0
- package/dist/providers/acp-provider.js.map +1 -1
- package/dist/providers/jait-provider.d.ts.map +1 -1
- package/dist/providers/jait-provider.js +2 -0
- package/dist/providers/jait-provider.js.map +1 -1
- package/dist/routes/chat.d.ts.map +1 -1
- package/dist/routes/chat.js +19 -2
- package/dist/routes/chat.js.map +1 -1
- package/dist/routes/jobs.d.ts.map +1 -1
- package/dist/routes/jobs.js +17 -34
- package/dist/routes/jobs.js.map +1 -1
- package/dist/routes/providers.d.ts +24 -0
- package/dist/routes/providers.d.ts.map +1 -0
- package/dist/routes/providers.js +300 -0
- package/dist/routes/providers.js.map +1 -0
- package/dist/routes/threads.d.ts +0 -3
- package/dist/routes/threads.d.ts.map +1 -1
- package/dist/routes/threads.js +0 -230
- package/dist/routes/threads.js.map +1 -1
- package/dist/scheduler/service.d.ts +4 -1
- package/dist/scheduler/service.d.ts.map +1 -1
- package/dist/scheduler/service.js +63 -6
- package/dist/scheduler/service.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +9 -0
- package/dist/server.js.map +1 -1
- package/dist/tools/agent-loop.d.ts +5 -1
- package/dist/tools/agent-loop.d.ts.map +1 -1
- package/dist/tools/agent-loop.js +4 -1
- package/dist/tools/agent-loop.js.map +1 -1
- package/dist/tools/agent-tools.d.ts.map +1 -1
- package/dist/tools/agent-tools.js +11 -1
- package/dist/tools/agent-tools.js.map +1 -1
- package/dist/tools/chat-modes.d.ts +5 -2
- package/dist/tools/chat-modes.d.ts.map +1 -1
- package/dist/tools/chat-modes.js +41 -1
- package/dist/tools/chat-modes.js.map +1 -1
- package/dist/tools/contracts.d.ts +1 -0
- package/dist/tools/contracts.d.ts.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +12 -10
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/prompts/shared-sections.d.ts +1 -0
- package/dist/tools/prompts/shared-sections.d.ts.map +1 -1
- package/dist/tools/prompts/shared-sections.js +5 -0
- package/dist/tools/prompts/shared-sections.js.map +1 -1
- package/package.json +1 -1
- package/web-dist/assets/{_basePickBy-CvK2xemr.js → _basePickBy-9TYNOM1l.js} +1 -1
- package/web-dist/assets/{_baseUniq-Ccy99IPA.js → _baseUniq-CpWsYINF.js} +1 -1
- package/web-dist/assets/{arc-oW1lE02M.js → arc-DSvVuoRa.js} +1 -1
- package/web-dist/assets/{architectureDiagram-2XIMDMQ5-BYHX8a08.js → architectureDiagram-2XIMDMQ5-tzgX3Vvn.js} +1 -1
- package/web-dist/assets/{blockDiagram-WCTKOSBZ-BZEfeNHP.js → blockDiagram-WCTKOSBZ-DjuKCu7h.js} +1 -1
- package/web-dist/assets/{c4Diagram-IC4MRINW-SCNnqv7_.js → c4Diagram-IC4MRINW-zbpmigpb.js} +1 -1
- package/web-dist/assets/channel-D1ANp35Z.js +1 -0
- package/web-dist/assets/{chunk-4BX2VUAB-DzlXwGuS.js → chunk-4BX2VUAB-CVadPDBZ.js} +1 -1
- package/web-dist/assets/{chunk-55IACEB6-DQRmVNB4.js → chunk-55IACEB6-CNWQUwk_.js} +1 -1
- package/web-dist/assets/{chunk-FMBD7UC4-e-8eV151.js → chunk-FMBD7UC4-BH9THwsk.js} +1 -1
- package/web-dist/assets/{chunk-JSJVCQXG-B-hVrCs-.js → chunk-JSJVCQXG-BX3PRvkI.js} +1 -1
- package/web-dist/assets/{chunk-KX2RTZJC-DWXheP03.js → chunk-KX2RTZJC-B7DF41n1.js} +1 -1
- package/web-dist/assets/{chunk-NQ4KR5QH-vLea6yKZ.js → chunk-NQ4KR5QH-DhBLWNF5.js} +1 -1
- package/web-dist/assets/{chunk-QZHKN3VN-Csus_DaG.js → chunk-QZHKN3VN-DZTA9dqS.js} +1 -1
- package/web-dist/assets/{chunk-WL4C6EOR-B8UbV37w.js → chunk-WL4C6EOR-DvFJqxTA.js} +1 -1
- package/web-dist/assets/classDiagram-VBA2DB6C-eekYA5Po.js +1 -0
- package/web-dist/assets/classDiagram-v2-RAHNMMFH-eekYA5Po.js +1 -0
- package/web-dist/assets/clone-CLQSY4Vh.js +1 -0
- package/web-dist/assets/{cose-bilkent-S5V4N54A-P8qowCT6.js → cose-bilkent-S5V4N54A-jfwYRSvf.js} +1 -1
- package/web-dist/assets/{dagre-KLK3FWXG-CgHzb9zM.js → dagre-KLK3FWXG-a-jKdMpQ.js} +1 -1
- package/web-dist/assets/{diagram-E7M64L7V-Cty-ONBE.js → diagram-E7M64L7V-WdQ2vS_J.js} +1 -1
- package/web-dist/assets/{diagram-IFDJBPK2-XIf3Qgu6.js → diagram-IFDJBPK2-CS1GA1Qv.js} +1 -1
- package/web-dist/assets/{diagram-P4PSJMXO-DWySMEyT.js → diagram-P4PSJMXO-CZan0aG6.js} +1 -1
- package/web-dist/assets/{erDiagram-INFDFZHY-Dh1_FSIK.js → erDiagram-INFDFZHY-io4hXPu2.js} +1 -1
- package/web-dist/assets/{flowDiagram-PKNHOUZH-BMiX0uPY.js → flowDiagram-PKNHOUZH-DB_tKlXg.js} +1 -1
- package/web-dist/assets/{ganttDiagram-A5KZAMGK-B44l64Yf.js → ganttDiagram-A5KZAMGK-DkU-deZW.js} +1 -1
- package/web-dist/assets/{gitGraphDiagram-K3NZZRJ6-DIOhjlWH.js → gitGraphDiagram-K3NZZRJ6-BlDmtRkv.js} +1 -1
- package/web-dist/assets/{graph-BoEfpqk_.js → graph-DfjSSucn.js} +1 -1
- package/web-dist/assets/{index-DphI1iGK.js → index-BOZSANwJ.js} +1 -1
- package/web-dist/assets/{index-DR9OwXwE.js → index-Bi2-02kA.js} +1 -1
- package/web-dist/assets/{index-B8gwqnk4.js → index-CM4cLE2g.js} +366 -366
- package/web-dist/assets/index-U0Q51fQQ.css +32 -0
- package/web-dist/assets/{infoDiagram-LFFYTUFH-CBGUCNAD.js → infoDiagram-LFFYTUFH-Bvx2qhAd.js} +1 -1
- package/web-dist/assets/{ishikawaDiagram-PHBUUO56-CRQbL1bS.js → ishikawaDiagram-PHBUUO56-DTEBYUHw.js} +1 -1
- package/web-dist/assets/{journeyDiagram-4ABVD52K-BOKxA77-.js → journeyDiagram-4ABVD52K-BbnZ4sxn.js} +1 -1
- package/web-dist/assets/{kanban-definition-K7BYSVSG-Bo5a_CCJ.js → kanban-definition-K7BYSVSG-xQlhwJm9.js} +1 -1
- package/web-dist/assets/{layout-laNAl--w.js → layout-6T2sGeQu.js} +1 -1
- package/web-dist/assets/{linear-zTrW2FL5.js → linear-P0Etymzw.js} +1 -1
- package/web-dist/assets/{mindmap-definition-YRQLILUH-Df4YxPbv.js → mindmap-definition-YRQLILUH-CZIkrTzQ.js} +1 -1
- package/web-dist/assets/{pieDiagram-SKSYHLDU-Yvq-CTyq.js → pieDiagram-SKSYHLDU-Bb9fLv4k.js} +1 -1
- package/web-dist/assets/{quadrantDiagram-337W2JSQ-Cr6HWBvS.js → quadrantDiagram-337W2JSQ-BEIfa773.js} +1 -1
- package/web-dist/assets/{requirementDiagram-Z7DCOOCP-BpHTZIf0.js → requirementDiagram-Z7DCOOCP-Bk5gMigd.js} +1 -1
- package/web-dist/assets/{sankeyDiagram-WA2Y5GQK-utlfmQrz.js → sankeyDiagram-WA2Y5GQK-DhzVf2Lu.js} +1 -1
- package/web-dist/assets/{sequenceDiagram-2WXFIKYE-DVoOuCVk.js → sequenceDiagram-2WXFIKYE-D2Pk_Gd4.js} +1 -1
- package/web-dist/assets/{stateDiagram-RAJIS63D-_KIAUk-L.js → stateDiagram-RAJIS63D-Dk8qXYTb.js} +1 -1
- package/web-dist/assets/stateDiagram-v2-FVOUBMTO-CBI7tCIp.js +1 -0
- package/web-dist/assets/{timeline-definition-YZTLITO2-Y9wggSgd.js → timeline-definition-YZTLITO2-Bc_OdSSU.js} +1 -1
- package/web-dist/assets/{treemap-KZPCXAKY-DOl8d3Yj.js → treemap-KZPCXAKY-Db7Q_nBv.js} +1 -1
- package/web-dist/assets/{vennDiagram-LZ73GAT5-Dp2vIilc.js → vennDiagram-LZ73GAT5-BOO3XPKa.js} +1 -1
- package/web-dist/assets/{xychartDiagram-JWTSCODW-ULAx69r3.js → xychartDiagram-JWTSCODW-Br5uXaC-.js} +1 -1
- package/web-dist/index.html +2 -2
- package/web-dist/assets/channel-By4cyEbd.js +0 -1
- package/web-dist/assets/classDiagram-VBA2DB6C-eF7Hmqh0.js +0 -1
- package/web-dist/assets/classDiagram-v2-RAHNMMFH-eF7Hmqh0.js +0 -1
- package/web-dist/assets/clone-DKnYTKn5.js +0 -1
- package/web-dist/assets/index-CmmJPAgU.css +0 -32
- package/web-dist/assets/stateDiagram-v2-FVOUBMTO-Cpd40KU-.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/routes/providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAuG/C,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,EAAE,CAAC,EAAE,cAAc,CAAC;CACrB;AAED,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,iBAAiB,GACtB,IAAI,CAuMN"}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider REST routes.
|
|
3
|
+
*
|
|
4
|
+
* Lists available providers, exposes auth flows, and returns
|
|
5
|
+
* dynamically-fetched model catalogues for each backend.
|
|
6
|
+
*
|
|
7
|
+
* GET /api/providers — list available providers
|
|
8
|
+
* GET /api/providers/:id/auth/status — get provider auth status
|
|
9
|
+
* POST /api/providers/:id/auth/login — start provider login
|
|
10
|
+
* POST /api/providers/:id/auth/logout — log out provider
|
|
11
|
+
* GET /api/providers/:id/models — list models for a provider
|
|
12
|
+
*/
|
|
13
|
+
import { requireAuth } from "../security/http-auth.js";
|
|
14
|
+
// ── Model fetchers with in-memory caches ─────────────────────────
|
|
15
|
+
/** Fetch models from OpenRouter API with a 5-second timeout and in-memory cache. */
|
|
16
|
+
let orCache = null;
|
|
17
|
+
const OR_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
18
|
+
async function fetchOpenRouterModels(apiKey) {
|
|
19
|
+
if (orCache && Date.now() - orCache.fetchedAt < OR_CACHE_TTL) {
|
|
20
|
+
return orCache.models;
|
|
21
|
+
}
|
|
22
|
+
const controller = new AbortController();
|
|
23
|
+
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
24
|
+
try {
|
|
25
|
+
const res = await fetch("https://openrouter.ai/api/v1/models", {
|
|
26
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
27
|
+
signal: controller.signal,
|
|
28
|
+
});
|
|
29
|
+
if (!res.ok)
|
|
30
|
+
return [];
|
|
31
|
+
const data = (await res.json());
|
|
32
|
+
const models = (data.data ?? [])
|
|
33
|
+
.filter((m) => m.id && !m.id.includes(":free"))
|
|
34
|
+
.slice(0, 100)
|
|
35
|
+
.map((m) => ({
|
|
36
|
+
id: m.id,
|
|
37
|
+
name: m.name || m.id.split("/").pop() || m.id,
|
|
38
|
+
description: m.description?.slice(0, 80),
|
|
39
|
+
}));
|
|
40
|
+
orCache = { models, fetchedAt: Date.now() };
|
|
41
|
+
return models;
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
clearTimeout(timeout);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Fetch models from OpenAI /v1/models with a 5-second timeout and in-memory cache. */
|
|
48
|
+
let openaiCache = null;
|
|
49
|
+
const OPENAI_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
50
|
+
/** Model ID prefixes that represent chat-completion-capable models. */
|
|
51
|
+
const OPENAI_CHAT_PREFIXES = ["gpt-", "o1", "o3", "o4", "chatgpt-"];
|
|
52
|
+
async function fetchOpenAIModels(apiKey, baseUrl) {
|
|
53
|
+
const url = baseUrl.replace(/\/+$/, "");
|
|
54
|
+
if (openaiCache && openaiCache.baseUrl === url && Date.now() - openaiCache.fetchedAt < OPENAI_CACHE_TTL) {
|
|
55
|
+
return openaiCache.models;
|
|
56
|
+
}
|
|
57
|
+
const controller = new AbortController();
|
|
58
|
+
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
59
|
+
try {
|
|
60
|
+
const res = await fetch(`${url}/models`, {
|
|
61
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
62
|
+
signal: controller.signal,
|
|
63
|
+
});
|
|
64
|
+
if (!res.ok)
|
|
65
|
+
return [];
|
|
66
|
+
const data = (await res.json());
|
|
67
|
+
const models = (data.data ?? [])
|
|
68
|
+
.filter((m) => m.id && OPENAI_CHAT_PREFIXES.some((p) => m.id.startsWith(p)))
|
|
69
|
+
// Remove fine-tune snapshots, realtime, audio-only, transcription variants
|
|
70
|
+
.filter((m) => !m.id.includes(":ft-") && !m.id.includes("realtime") && !m.id.includes("transcribe") && !m.id.includes("tts") && !m.id.includes("dall-e") && !m.id.includes("whisper"))
|
|
71
|
+
.sort((a, b) => a.id.localeCompare(b.id))
|
|
72
|
+
.map((m) => ({
|
|
73
|
+
id: m.id,
|
|
74
|
+
name: m.id,
|
|
75
|
+
description: m.owned_by ? `by ${m.owned_by}` : undefined,
|
|
76
|
+
}));
|
|
77
|
+
openaiCache = { models, fetchedAt: Date.now(), baseUrl: url };
|
|
78
|
+
return models;
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
clearTimeout(timeout);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
let ollamaCache = null;
|
|
85
|
+
const OLLAMA_CACHE_TTL = 30 * 1000; // 30 seconds (local, fast)
|
|
86
|
+
async function fetchOllamaModels(baseUrl) {
|
|
87
|
+
const url = baseUrl.replace(/\/+$/, "");
|
|
88
|
+
if (ollamaCache && ollamaCache.url === url && Date.now() - ollamaCache.fetchedAt < OLLAMA_CACHE_TTL) {
|
|
89
|
+
return ollamaCache.models;
|
|
90
|
+
}
|
|
91
|
+
const controller = new AbortController();
|
|
92
|
+
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
93
|
+
try {
|
|
94
|
+
const res = await fetch(`${url}/api/tags`, { signal: controller.signal });
|
|
95
|
+
if (!res.ok)
|
|
96
|
+
return [];
|
|
97
|
+
const data = (await res.json());
|
|
98
|
+
const models = (data.models ?? []).map((m) => ({
|
|
99
|
+
id: m.name,
|
|
100
|
+
name: m.name,
|
|
101
|
+
description: [m.details?.family, m.details?.parameter_size].filter(Boolean).join(" · ") || undefined,
|
|
102
|
+
}));
|
|
103
|
+
ollamaCache = { models, fetchedAt: Date.now(), url };
|
|
104
|
+
return models;
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
clearTimeout(timeout);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
export function registerProviderRoutes(app, config, deps) {
|
|
111
|
+
const { providerRegistry, ws } = deps;
|
|
112
|
+
/** List available providers (local + remote) */
|
|
113
|
+
app.get("/api/providers", async (request, reply) => {
|
|
114
|
+
const authUser = await requireAuth(request, reply, config.jwtSecret);
|
|
115
|
+
if (!authUser)
|
|
116
|
+
return;
|
|
117
|
+
const providers = providerRegistry.list();
|
|
118
|
+
const providerSnapshots = await Promise.all(providers.map(async (p) => {
|
|
119
|
+
await p.checkAvailability().catch(() => false);
|
|
120
|
+
const auth = await p.getAuthStatus?.().catch(() => p.info.auth
|
|
121
|
+
? { ...p.info.auth, authenticated: null, detail: "Failed to check provider auth status." }
|
|
122
|
+
: undefined);
|
|
123
|
+
return { provider: p, auth };
|
|
124
|
+
}));
|
|
125
|
+
// Collect remote provider info from connected filesystem nodes
|
|
126
|
+
const remoteProviders = [];
|
|
127
|
+
if (ws) {
|
|
128
|
+
for (const node of ws.getFsNodes()) {
|
|
129
|
+
if (node.isGateway)
|
|
130
|
+
continue;
|
|
131
|
+
remoteProviders.push({
|
|
132
|
+
nodeId: node.id,
|
|
133
|
+
nodeName: node.name,
|
|
134
|
+
platform: node.platform,
|
|
135
|
+
providers: node.providers ?? [],
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
providers: providerSnapshots.map(({ provider: p, auth }) => ({
|
|
141
|
+
id: p.id,
|
|
142
|
+
name: p.info.name,
|
|
143
|
+
description: p.info.description,
|
|
144
|
+
available: p.info.available,
|
|
145
|
+
unavailableReason: p.info.unavailableReason,
|
|
146
|
+
modes: p.info.modes,
|
|
147
|
+
auth: auth ?? p.info.auth,
|
|
148
|
+
})),
|
|
149
|
+
remoteProviders,
|
|
150
|
+
};
|
|
151
|
+
});
|
|
152
|
+
/** Get provider auth status */
|
|
153
|
+
app.get("/api/providers/:id/auth/status", async (request, reply) => {
|
|
154
|
+
const authUser = await requireAuth(request, reply, config.jwtSecret);
|
|
155
|
+
if (!authUser)
|
|
156
|
+
return;
|
|
157
|
+
const { id } = request.params;
|
|
158
|
+
const provider = providerRegistry.get(id);
|
|
159
|
+
if (!provider)
|
|
160
|
+
return reply.status(404).send({ error: `Unknown provider: ${id}` });
|
|
161
|
+
if (!provider.getAuthStatus) {
|
|
162
|
+
return reply.status(501).send({ error: `Provider ${id} does not support auth status` });
|
|
163
|
+
}
|
|
164
|
+
return provider.getAuthStatus();
|
|
165
|
+
});
|
|
166
|
+
/** Start provider login */
|
|
167
|
+
app.post("/api/providers/:id/auth/login", async (request, reply) => {
|
|
168
|
+
const authUser = await requireAuth(request, reply, config.jwtSecret);
|
|
169
|
+
if (!authUser)
|
|
170
|
+
return;
|
|
171
|
+
const { id } = request.params;
|
|
172
|
+
const provider = providerRegistry.get(id);
|
|
173
|
+
if (!provider)
|
|
174
|
+
return reply.status(404).send({ error: `Unknown provider: ${id}` });
|
|
175
|
+
if (!provider.startLogin) {
|
|
176
|
+
return reply.status(501).send({ error: `Provider ${id} does not support login` });
|
|
177
|
+
}
|
|
178
|
+
const result = await provider.startLogin();
|
|
179
|
+
if (!result.ok && result.status === "unsupported") {
|
|
180
|
+
return reply.status(501).send(result);
|
|
181
|
+
}
|
|
182
|
+
if (!result.ok) {
|
|
183
|
+
return reply.status(500).send(result);
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
186
|
+
});
|
|
187
|
+
/** Log out provider */
|
|
188
|
+
app.post("/api/providers/:id/auth/logout", async (request, reply) => {
|
|
189
|
+
const authUser = await requireAuth(request, reply, config.jwtSecret);
|
|
190
|
+
if (!authUser)
|
|
191
|
+
return;
|
|
192
|
+
const { id } = request.params;
|
|
193
|
+
const provider = providerRegistry.get(id);
|
|
194
|
+
if (!provider)
|
|
195
|
+
return reply.status(404).send({ error: `Unknown provider: ${id}` });
|
|
196
|
+
if (!provider.logout) {
|
|
197
|
+
return reply.status(501).send({ error: `Provider ${id} does not support logout` });
|
|
198
|
+
}
|
|
199
|
+
const result = await provider.logout();
|
|
200
|
+
if (!result.ok && result.status === "unsupported") {
|
|
201
|
+
return reply.status(501).send(result);
|
|
202
|
+
}
|
|
203
|
+
if (!result.ok) {
|
|
204
|
+
return reply.status(500).send(result);
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
});
|
|
208
|
+
/** List models for a specific provider */
|
|
209
|
+
app.get("/api/providers/:id/models", async (request, reply) => {
|
|
210
|
+
const authUser = await requireAuth(request, reply, config.jwtSecret);
|
|
211
|
+
if (!authUser)
|
|
212
|
+
return;
|
|
213
|
+
const { id } = request.params;
|
|
214
|
+
const provider = providerRegistry.get(id);
|
|
215
|
+
if (!provider) {
|
|
216
|
+
return reply.status(404).send({ error: `Unknown provider: ${id}` });
|
|
217
|
+
}
|
|
218
|
+
if (!provider.listModels) {
|
|
219
|
+
return { models: [] };
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
let models = await provider.listModels();
|
|
223
|
+
// For jait provider, return models from ALL configured backends, grouped
|
|
224
|
+
if (id === "jait" && deps.userService) {
|
|
225
|
+
const settings = deps.userService.getSettings(authUser.id);
|
|
226
|
+
const userApiKeys = settings.apiKeys ?? {};
|
|
227
|
+
const jaitBackend = settings.jaitBackend || "openai";
|
|
228
|
+
const allModels = [];
|
|
229
|
+
// ── OpenAI models (dynamic when API key available) ────────
|
|
230
|
+
const openaiKey = userApiKeys["OPENAI_API_KEY"]?.trim() || config.openaiApiKey;
|
|
231
|
+
const openaiBaseUrl = userApiKeys["OPENAI_BASE_URL"]?.trim() || config.openaiBaseUrl || "https://api.openai.com/v1";
|
|
232
|
+
if (openaiKey && openaiBaseUrl.includes("openai.com")) {
|
|
233
|
+
try {
|
|
234
|
+
const apiModels = await fetchOpenAIModels(openaiKey, openaiBaseUrl);
|
|
235
|
+
if (apiModels.length > 0) {
|
|
236
|
+
allModels.push(...apiModels.map((m) => ({ ...m, group: "OpenAI" })));
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
allModels.push(...models.map((m) => ({ ...m, group: "OpenAI" })));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
allModels.push(...models.map((m) => ({ ...m, group: "OpenAI" })));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
allModels.push(...models.map((m) => ({ ...m, group: "OpenAI" })));
|
|
248
|
+
}
|
|
249
|
+
// ── OpenRouter models ─────────────────────────────────────
|
|
250
|
+
const openRouterKey = userApiKeys["OPENROUTER_API_KEY"]?.trim();
|
|
251
|
+
if (openRouterKey) {
|
|
252
|
+
try {
|
|
253
|
+
const orModels = await fetchOpenRouterModels(openRouterKey);
|
|
254
|
+
if (orModels.length > 0) {
|
|
255
|
+
allModels.push(...orModels.map((m) => ({ ...m, group: "OpenRouter" })));
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
const { OPENROUTER_MODELS } = await import("../providers/jait-provider.js");
|
|
259
|
+
allModels.push(...OPENROUTER_MODELS.map((m) => ({ ...m, group: "OpenRouter" })));
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
const { OPENROUTER_MODELS } = await import("../providers/jait-provider.js");
|
|
264
|
+
allModels.push(...OPENROUTER_MODELS.map((m) => ({ ...m, group: "OpenRouter" })));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// ── Ollama models ─────────────────────────────────────────
|
|
268
|
+
const ollamaUrl = userApiKeys["OLLAMA_URL"]?.trim() || config.ollamaUrl;
|
|
269
|
+
if (ollamaUrl) {
|
|
270
|
+
try {
|
|
271
|
+
const ollamaModels = await fetchOllamaModels(ollamaUrl);
|
|
272
|
+
if (ollamaModels.length > 0) {
|
|
273
|
+
allModels.push(...ollamaModels.map((m) => ({ ...m, group: "Ollama" })));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
// Ollama unreachable — skip
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
models = allModels;
|
|
281
|
+
// Prepend recent models (if they exist in the full list)
|
|
282
|
+
const recentIds = settings.recentModels ?? [];
|
|
283
|
+
if (recentIds.length > 0) {
|
|
284
|
+
const modelMap = new Map(models.map((m) => [m.id, m]));
|
|
285
|
+
const recents = recentIds
|
|
286
|
+
.filter((rid) => modelMap.has(rid))
|
|
287
|
+
.map((rid) => ({ ...modelMap.get(rid), isRecent: true }));
|
|
288
|
+
return { models, currentBackend: jaitBackend, recentModels: recents.slice(0, 5).map((r) => r.id) };
|
|
289
|
+
}
|
|
290
|
+
return { models, currentBackend: jaitBackend };
|
|
291
|
+
}
|
|
292
|
+
return { models };
|
|
293
|
+
}
|
|
294
|
+
catch (err) {
|
|
295
|
+
return reply.status(500).send({ error: err instanceof Error ? err.message : "Failed to list models" });
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
app.log.info("Provider routes registered at /api/providers");
|
|
299
|
+
}
|
|
300
|
+
//# sourceMappingURL=providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/routes/providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,oEAAoE;AAEpE,oFAAoF;AACpF,IAAI,OAAO,GAA8D,IAAI,CAAC;AAC9E,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,YAAY;AAEhD,KAAK,UAAU,qBAAqB,CAAC,MAAc;IACjD,IAAI,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS,GAAG,YAAY,EAAE,CAAC;QAC7D,OAAO,OAAO,CAAC,MAAM,CAAC;IACxB,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC;IAC3D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,qCAAqC,EAAE;YAC7D,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,EAAE,EAAE;YAC9C,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA0E,CAAC;QACzG,MAAM,MAAM,GAAwB,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;aAClD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;aAC9C,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;aACb,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACX,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE;YAC7C,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACzC,CAAC,CAAC,CAAC;QACN,OAAO,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QAC5C,OAAO,MAAM,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,uFAAuF;AACvF,IAAI,WAAW,GAA+E,IAAI,CAAC;AACnG,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,YAAY;AAEpD,uEAAuE;AACvE,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AAEpE,KAAK,UAAU,iBAAiB,CAAC,MAAc,EAAE,OAAe;IAC9D,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACxC,IAAI,WAAW,IAAI,WAAW,CAAC,OAAO,KAAK,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,SAAS,GAAG,gBAAgB,EAAE,CAAC;QACxG,OAAO,WAAW,CAAC,MAAM,CAAC;IAC5B,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC;IAC3D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,GAAG,SAAS,EAAE;YACvC,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,EAAE,EAAE;YAC9C,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwD,CAAC;QACvF,MAAM,MAAM,GAAwB,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;aAClD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5E,2EAA2E;aAC1E,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;aACrL,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;aACxC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACX,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,IAAI,EAAE,CAAC,CAAC,EAAE;YACV,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS;SACzD,CAAC,CAAC,CAAC;QACN,WAAW,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QAC9D,OAAO,MAAM,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,IAAI,WAAW,GAA2E,IAAI,CAAC;AAC/F,MAAM,gBAAgB,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,2BAA2B;AAE/D,KAAK,UAAU,iBAAiB,CAAC,OAAe;IAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACxC,IAAI,WAAW,IAAI,WAAW,CAAC,GAAG,KAAK,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,SAAS,GAAG,gBAAgB,EAAE,CAAC;QACpG,OAAO,WAAW,CAAC,MAAM,CAAC;IAC5B,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC;IAC3D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,GAAG,WAAW,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAgH,CAAC;QAC/I,MAAM,MAAM,GAAwB,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAClE,EAAE,EAAE,CAAC,CAAC,IAAI;YACV,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,SAAS;SACrG,CAAC,CAAC,CAAC;QACJ,WAAW,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC;QACrD,OAAO,MAAM,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAUD,MAAM,UAAU,sBAAsB,CACpC,GAAoB,EACpB,MAAiB,EACjB,IAAuB;IAEvB,MAAM,EAAE,gBAAgB,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;IAEtC,gDAAgD;IAChD,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACjD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACrE,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAC1C,MAAM,iBAAiB,GAAG,MAAM,OAAO,CAAC,GAAG,CACzC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;YACxB,MAAM,CAAC,CAAC,iBAAiB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;YAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI;gBAC5D,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,uCAAuC,EAAE;gBAC1F,CAAC,CAAC,SAAS,CAAC,CAAC;YACf,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC;QAC/B,CAAC,CAAC,CACH,CAAC;QAEF,+DAA+D;QAC/D,MAAM,eAAe,GAAkF,EAAE,CAAC;QAC1G,IAAI,EAAE,EAAE,CAAC;YACP,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC;gBACnC,IAAI,IAAI,CAAC,SAAS;oBAAE,SAAS;gBAC7B,eAAe,CAAC,IAAI,CAAC;oBACnB,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,QAAQ,EAAE,IAAI,CAAC,IAAI;oBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,EAAE;iBAChC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO;YACL,SAAS,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;gBAC3D,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;gBACjB,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW;gBAC/B,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS;gBAC3B,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,iBAAiB;gBAC3C,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK;gBACnB,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI;aAC1B,CAAC,CAAC;YACH,eAAe;SAChB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,+BAA+B;IAC/B,GAAG,CAAC,GAAG,CAAC,gCAAgC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACjE,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACrE,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAwB,CAAC;QAChD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,EAAgB,CAAC,CAAC;QACxD,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,EAAE,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;YAC5B,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,+BAA+B,EAAE,CAAC,CAAC;QAC1F,CAAC;QACD,OAAO,QAAQ,CAAC,aAAa,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,2BAA2B;IAC3B,GAAG,CAAC,IAAI,CAAC,+BAA+B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACjE,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACrE,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAwB,CAAC;QAChD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,EAAgB,CAAC,CAAC;QACxD,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,EAAE,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,yBAAyB,EAAE,CAAC,CAAC;QACpF,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC;QAC3C,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;YAClD,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,uBAAuB;IACvB,GAAG,CAAC,IAAI,CAAC,gCAAgC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAClE,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACrE,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAwB,CAAC;QAChD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,EAAgB,CAAC,CAAC;QACxD,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,EAAE,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,0BAA0B,EAAE,CAAC,CAAC;QACrF,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;YAClD,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,0CAA0C;IAC1C,GAAG,CAAC,GAAG,CAAC,2BAA2B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC5D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACrE,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAwB,CAAC;QAChD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,EAAgB,CAAC,CAAC;QACxD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,EAAE,EAAE,CAAC,CAAC;QACtE,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;YACzB,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACxB,CAAC;QAED,IAAI,CAAC;YACH,IAAI,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC;YAEzC,yEAAyE;YACzE,IAAI,EAAE,KAAK,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC3D,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC;gBAC3C,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC;gBAErD,MAAM,SAAS,GAAwB,EAAE,CAAC;gBAE1C,6DAA6D;gBAC7D,MAAM,SAAS,GAAG,WAAW,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC,YAAY,CAAC;gBAC/E,MAAM,aAAa,GAAG,WAAW,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC,aAAa,IAAI,2BAA2B,CAAC;gBACpH,IAAI,SAAS,IAAI,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;oBACtD,IAAI,CAAC;wBACH,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;wBACpE,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;4BACzB,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;wBACvE,CAAC;6BAAM,CAAC;4BACN,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;wBACpE,CAAC;oBACH,CAAC;oBAAC,MAAM,CAAC;wBACP,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;oBACpE,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;gBACpE,CAAC;gBAED,6DAA6D;gBAC7D,MAAM,aAAa,GAAG,WAAW,CAAC,oBAAoB,CAAC,EAAE,IAAI,EAAE,CAAC;gBAChE,IAAI,aAAa,EAAE,CAAC;oBAClB,IAAI,CAAC;wBACH,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,aAAa,CAAC,CAAC;wBAC5D,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;4BACxB,SAAS,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;wBAC1E,CAAC;6BAAM,CAAC;4BACN,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,+BAA+B,CAAC,CAAC;4BAC5E,SAAS,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;wBACnF,CAAC;oBACH,CAAC;oBAAC,MAAM,CAAC;wBACP,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,+BAA+B,CAAC,CAAC;wBAC5E,SAAS,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;oBACnF,CAAC;gBACH,CAAC;gBAED,6DAA6D;gBAC7D,MAAM,SAAS,GAAG,WAAW,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC,SAAS,CAAC;gBACxE,IAAI,SAAS,EAAE,CAAC;oBACd,IAAI,CAAC;wBACH,MAAM,YAAY,GAAG,MAAM,iBAAiB,CAAC,SAAS,CAAC,CAAC;wBACxD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;4BAC5B,SAAS,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;wBAC1E,CAAC;oBACH,CAAC;oBAAC,MAAM,CAAC;wBACP,4BAA4B;oBAC9B,CAAC;gBACH,CAAC;gBAED,MAAM,GAAG,SAAS,CAAC;gBAEnB,yDAAyD;gBACzD,MAAM,SAAS,GAAG,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC;gBAC9C,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACzB,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;oBACvD,MAAM,OAAO,GAAG,SAAS;yBACtB,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;yBAClC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;oBAC7D,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;gBACrG,CAAC;gBAED,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC;YACjD,CAAC;YAED,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,EAAE,CAAC,CAAC;QACzG,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;AAC/D,CAAC"}
|
package/dist/routes/threads.d.ts
CHANGED
|
@@ -14,9 +14,6 @@
|
|
|
14
14
|
* POST /api/threads/:id/stop — stop agent session
|
|
15
15
|
* POST /api/threads/:id/interrupt — interrupt current turn
|
|
16
16
|
* POST /api/threads/:id/approve — approve a tool call
|
|
17
|
-
* POST /api/threads/:id/create-pr — create a PR for a completed thread
|
|
18
|
-
* GET /api/threads/:id/activities — get activity log
|
|
19
|
-
* GET /api/providers — list available providers
|
|
20
17
|
*/
|
|
21
18
|
import type { FastifyInstance } from "fastify";
|
|
22
19
|
import type { AppConfig } from "../config.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../../src/routes/threads.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../../src/routes/threads.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAK/C,OAAO,EAA0C,KAAK,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGrE,OAAO,KAAK,EAAS,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAmE/D,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,aAAa,CAAC;IAC7B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,EAAE,CAAC,EAAE,cAAc,CAAC;IACpB,UAAU,CAAC,EAAE;QACX,gBAAgB,CACd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,gBAAgB,EACxB,aAAa,CAAC,EAAE,MAAM,EACtB,aAAa,CAAC,EAAE,OAAO,EACvB,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,CAAC,CAAC;QAC1B,SAAS,CACP,GAAG,EAAE,MAAM,EACX,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;KAC3F,CAAC;CACH;AAuED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,eAAe,GACpB,IAAI,CA0iDN"}
|
package/dist/routes/threads.js
CHANGED
|
@@ -14,9 +14,6 @@
|
|
|
14
14
|
* POST /api/threads/:id/stop — stop agent session
|
|
15
15
|
* POST /api/threads/:id/interrupt — interrupt current turn
|
|
16
16
|
* POST /api/threads/:id/approve — approve a tool call
|
|
17
|
-
* POST /api/threads/:id/create-pr — create a PR for a completed thread
|
|
18
|
-
* GET /api/threads/:id/activities — get activity log
|
|
19
|
-
* GET /api/providers — list available providers
|
|
20
17
|
*/
|
|
21
18
|
import { requireAuth, signAuthToken } from "../security/http-auth.js";
|
|
22
19
|
import { extractTodoResultItems } from "../providers/todo-result.js";
|
|
@@ -74,64 +71,6 @@ function resolveThreadProviderId(userSelectedProvider, requestedProvider, fallba
|
|
|
74
71
|
}
|
|
75
72
|
return resolveSelectedProvider();
|
|
76
73
|
}
|
|
77
|
-
/** Fetch models from OpenRouter API with a 5-second timeout and in-memory cache. */
|
|
78
|
-
let orCache = null;
|
|
79
|
-
const OR_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
80
|
-
async function fetchOpenRouterModels(apiKey) {
|
|
81
|
-
if (orCache && Date.now() - orCache.fetchedAt < OR_CACHE_TTL) {
|
|
82
|
-
return orCache.models;
|
|
83
|
-
}
|
|
84
|
-
const controller = new AbortController();
|
|
85
|
-
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
86
|
-
try {
|
|
87
|
-
const res = await fetch("https://openrouter.ai/api/v1/models", {
|
|
88
|
-
headers: { Authorization: `Bearer ${apiKey}` },
|
|
89
|
-
signal: controller.signal,
|
|
90
|
-
});
|
|
91
|
-
if (!res.ok)
|
|
92
|
-
return [];
|
|
93
|
-
const data = (await res.json());
|
|
94
|
-
const models = (data.data ?? [])
|
|
95
|
-
.filter((m) => m.id && !m.id.includes(":free"))
|
|
96
|
-
.slice(0, 100)
|
|
97
|
-
.map((m) => ({
|
|
98
|
-
id: m.id,
|
|
99
|
-
name: m.name || m.id.split("/").pop() || m.id,
|
|
100
|
-
description: m.description?.slice(0, 80),
|
|
101
|
-
}));
|
|
102
|
-
orCache = { models, fetchedAt: Date.now() };
|
|
103
|
-
return models;
|
|
104
|
-
}
|
|
105
|
-
finally {
|
|
106
|
-
clearTimeout(timeout);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
let ollamaCache = null;
|
|
110
|
-
const OLLAMA_CACHE_TTL = 30 * 1000; // 30 seconds (local, fast)
|
|
111
|
-
async function fetchOllamaModels(baseUrl) {
|
|
112
|
-
const url = baseUrl.replace(/\/+$/, "");
|
|
113
|
-
if (ollamaCache && ollamaCache.url === url && Date.now() - ollamaCache.fetchedAt < OLLAMA_CACHE_TTL) {
|
|
114
|
-
return ollamaCache.models;
|
|
115
|
-
}
|
|
116
|
-
const controller = new AbortController();
|
|
117
|
-
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
118
|
-
try {
|
|
119
|
-
const res = await fetch(`${url}/api/tags`, { signal: controller.signal });
|
|
120
|
-
if (!res.ok)
|
|
121
|
-
return [];
|
|
122
|
-
const data = (await res.json());
|
|
123
|
-
const models = (data.models ?? []).map((m) => ({
|
|
124
|
-
id: m.name,
|
|
125
|
-
name: m.name,
|
|
126
|
-
description: [m.details?.family, m.details?.parameter_size].filter(Boolean).join(" · ") || undefined,
|
|
127
|
-
}));
|
|
128
|
-
ollamaCache = { models, fetchedAt: Date.now(), url };
|
|
129
|
-
return models;
|
|
130
|
-
}
|
|
131
|
-
finally {
|
|
132
|
-
clearTimeout(timeout);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
74
|
const QUEUED_THREAD_MESSAGES_KEY = "queued_thread_messages";
|
|
136
75
|
function parseQueuedThreadMessagesState(raw) {
|
|
137
76
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
@@ -1596,175 +1535,6 @@ export function registerThreadRoutes(app, config, deps) {
|
|
|
1596
1535
|
const activities = threadService.getActivities(id, limit);
|
|
1597
1536
|
return { activities };
|
|
1598
1537
|
});
|
|
1599
|
-
// ── Provider info ────────────────────────────────────────────────
|
|
1600
|
-
/** List available providers (local + remote) */
|
|
1601
|
-
app.get("/api/providers", async (request, reply) => {
|
|
1602
|
-
const authUser = await requireAuth(request, reply, config.jwtSecret);
|
|
1603
|
-
if (!authUser)
|
|
1604
|
-
return;
|
|
1605
|
-
const providers = providerRegistry.list();
|
|
1606
|
-
const providerSnapshots = await Promise.all(providers.map(async (p) => {
|
|
1607
|
-
await p.checkAvailability().catch(() => false);
|
|
1608
|
-
const auth = await p.getAuthStatus?.().catch(() => p.info.auth
|
|
1609
|
-
? { ...p.info.auth, authenticated: null, detail: "Failed to check provider auth status." }
|
|
1610
|
-
: undefined);
|
|
1611
|
-
return { provider: p, auth };
|
|
1612
|
-
}));
|
|
1613
|
-
// Collect remote provider info from connected filesystem nodes
|
|
1614
|
-
const remoteProviders = [];
|
|
1615
|
-
if (ws) {
|
|
1616
|
-
for (const node of ws.getFsNodes()) {
|
|
1617
|
-
if (node.isGateway)
|
|
1618
|
-
continue;
|
|
1619
|
-
remoteProviders.push({
|
|
1620
|
-
nodeId: node.id,
|
|
1621
|
-
nodeName: node.name,
|
|
1622
|
-
platform: node.platform,
|
|
1623
|
-
providers: node.providers ?? [],
|
|
1624
|
-
});
|
|
1625
|
-
}
|
|
1626
|
-
}
|
|
1627
|
-
return {
|
|
1628
|
-
providers: providerSnapshots.map(({ provider: p, auth }) => ({
|
|
1629
|
-
id: p.id,
|
|
1630
|
-
name: p.info.name,
|
|
1631
|
-
description: p.info.description,
|
|
1632
|
-
available: p.info.available,
|
|
1633
|
-
unavailableReason: p.info.unavailableReason,
|
|
1634
|
-
modes: p.info.modes,
|
|
1635
|
-
auth: auth ?? p.info.auth,
|
|
1636
|
-
})),
|
|
1637
|
-
remoteProviders,
|
|
1638
|
-
};
|
|
1639
|
-
});
|
|
1640
|
-
/** Get provider auth status */
|
|
1641
|
-
app.get("/api/providers/:id/auth/status", async (request, reply) => {
|
|
1642
|
-
const authUser = await requireAuth(request, reply, config.jwtSecret);
|
|
1643
|
-
if (!authUser)
|
|
1644
|
-
return;
|
|
1645
|
-
const { id } = request.params;
|
|
1646
|
-
const provider = providerRegistry.get(id);
|
|
1647
|
-
if (!provider)
|
|
1648
|
-
return reply.status(404).send({ error: `Unknown provider: ${id}` });
|
|
1649
|
-
if (!provider.getAuthStatus) {
|
|
1650
|
-
return reply.status(501).send({ error: `Provider ${id} does not support auth status` });
|
|
1651
|
-
}
|
|
1652
|
-
return provider.getAuthStatus();
|
|
1653
|
-
});
|
|
1654
|
-
/** Start provider login */
|
|
1655
|
-
app.post("/api/providers/:id/auth/login", async (request, reply) => {
|
|
1656
|
-
const authUser = await requireAuth(request, reply, config.jwtSecret);
|
|
1657
|
-
if (!authUser)
|
|
1658
|
-
return;
|
|
1659
|
-
const { id } = request.params;
|
|
1660
|
-
const provider = providerRegistry.get(id);
|
|
1661
|
-
if (!provider)
|
|
1662
|
-
return reply.status(404).send({ error: `Unknown provider: ${id}` });
|
|
1663
|
-
if (!provider.startLogin) {
|
|
1664
|
-
return reply.status(501).send({ error: `Provider ${id} does not support login` });
|
|
1665
|
-
}
|
|
1666
|
-
const result = await provider.startLogin();
|
|
1667
|
-
if (!result.ok && result.status === "unsupported") {
|
|
1668
|
-
return reply.status(501).send(result);
|
|
1669
|
-
}
|
|
1670
|
-
if (!result.ok) {
|
|
1671
|
-
return reply.status(500).send(result);
|
|
1672
|
-
}
|
|
1673
|
-
return result;
|
|
1674
|
-
});
|
|
1675
|
-
/** Log out provider */
|
|
1676
|
-
app.post("/api/providers/:id/auth/logout", async (request, reply) => {
|
|
1677
|
-
const authUser = await requireAuth(request, reply, config.jwtSecret);
|
|
1678
|
-
if (!authUser)
|
|
1679
|
-
return;
|
|
1680
|
-
const { id } = request.params;
|
|
1681
|
-
const provider = providerRegistry.get(id);
|
|
1682
|
-
if (!provider)
|
|
1683
|
-
return reply.status(404).send({ error: `Unknown provider: ${id}` });
|
|
1684
|
-
if (!provider.logout) {
|
|
1685
|
-
return reply.status(501).send({ error: `Provider ${id} does not support logout` });
|
|
1686
|
-
}
|
|
1687
|
-
const result = await provider.logout();
|
|
1688
|
-
if (!result.ok && result.status === "unsupported") {
|
|
1689
|
-
return reply.status(501).send(result);
|
|
1690
|
-
}
|
|
1691
|
-
if (!result.ok) {
|
|
1692
|
-
return reply.status(500).send(result);
|
|
1693
|
-
}
|
|
1694
|
-
return result;
|
|
1695
|
-
});
|
|
1696
|
-
/** List models for a specific provider */
|
|
1697
|
-
app.get("/api/providers/:id/models", async (request, reply) => {
|
|
1698
|
-
const authUser = await requireAuth(request, reply, config.jwtSecret);
|
|
1699
|
-
if (!authUser)
|
|
1700
|
-
return;
|
|
1701
|
-
const { id } = request.params;
|
|
1702
|
-
const provider = providerRegistry.get(id);
|
|
1703
|
-
if (!provider) {
|
|
1704
|
-
return reply.status(404).send({ error: `Unknown provider: ${id}` });
|
|
1705
|
-
}
|
|
1706
|
-
if (!provider.listModels) {
|
|
1707
|
-
return { models: [] };
|
|
1708
|
-
}
|
|
1709
|
-
try {
|
|
1710
|
-
let models = await provider.listModels();
|
|
1711
|
-
// For jait provider, return models from ALL configured backends, grouped
|
|
1712
|
-
if (id === "jait" && deps.userService) {
|
|
1713
|
-
const settings = deps.userService.getSettings(authUser.id);
|
|
1714
|
-
const userApiKeys = settings.apiKeys ?? {};
|
|
1715
|
-
const jaitBackend = settings.jaitBackend || "openai";
|
|
1716
|
-
const allModels = [];
|
|
1717
|
-
// ── OpenAI models (always shown) ──────────────────────────
|
|
1718
|
-
allModels.push(...models.map((m) => ({ ...m, group: "OpenAI" })));
|
|
1719
|
-
// ── OpenRouter models ─────────────────────────────────────
|
|
1720
|
-
const openRouterKey = userApiKeys["OPENROUTER_API_KEY"]?.trim();
|
|
1721
|
-
if (openRouterKey) {
|
|
1722
|
-
try {
|
|
1723
|
-
const orModels = await fetchOpenRouterModels(openRouterKey);
|
|
1724
|
-
if (orModels.length > 0) {
|
|
1725
|
-
allModels.push(...orModels.map((m) => ({ ...m, group: "OpenRouter" })));
|
|
1726
|
-
}
|
|
1727
|
-
else {
|
|
1728
|
-
const { OPENROUTER_MODELS } = await import("../providers/jait-provider.js");
|
|
1729
|
-
allModels.push(...OPENROUTER_MODELS.map((m) => ({ ...m, group: "OpenRouter" })));
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
catch {
|
|
1733
|
-
const { OPENROUTER_MODELS } = await import("../providers/jait-provider.js");
|
|
1734
|
-
allModels.push(...OPENROUTER_MODELS.map((m) => ({ ...m, group: "OpenRouter" })));
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
// ── Ollama models ─────────────────────────────────────────
|
|
1738
|
-
const ollamaUrl = userApiKeys["OLLAMA_URL"]?.trim() || config.ollamaUrl;
|
|
1739
|
-
if (ollamaUrl) {
|
|
1740
|
-
try {
|
|
1741
|
-
const ollamaModels = await fetchOllamaModels(ollamaUrl);
|
|
1742
|
-
if (ollamaModels.length > 0) {
|
|
1743
|
-
allModels.push(...ollamaModels.map((m) => ({ ...m, group: "Ollama" })));
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
catch {
|
|
1747
|
-
// Ollama unreachable — skip
|
|
1748
|
-
}
|
|
1749
|
-
}
|
|
1750
|
-
models = allModels;
|
|
1751
|
-
// Prepend recent models (if they exist in the full list)
|
|
1752
|
-
const recentIds = settings.recentModels ?? [];
|
|
1753
|
-
if (recentIds.length > 0) {
|
|
1754
|
-
const modelMap = new Map(models.map((m) => [m.id, m]));
|
|
1755
|
-
const recents = recentIds
|
|
1756
|
-
.filter((rid) => modelMap.has(rid))
|
|
1757
|
-
.map((rid) => ({ ...modelMap.get(rid), isRecent: true }));
|
|
1758
|
-
return { models, currentBackend: jaitBackend, recentModels: recents.slice(0, 5).map((r) => r.id) };
|
|
1759
|
-
}
|
|
1760
|
-
return { models, currentBackend: jaitBackend };
|
|
1761
|
-
}
|
|
1762
|
-
return { models };
|
|
1763
|
-
}
|
|
1764
|
-
catch (err) {
|
|
1765
|
-
return reply.status(500).send({ error: err instanceof Error ? err.message : "Failed to list models" });
|
|
1766
|
-
}
|
|
1767
|
-
});
|
|
1768
1538
|
app.log.info("Agent thread routes registered at /api/threads");
|
|
1769
1539
|
}
|
|
1770
1540
|
//# sourceMappingURL=threads.js.map
|