openfox 2.0.133 → 2.0.135

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.
Files changed (84) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/CHANGELOG.md +30 -0
  3. package/dist/{chat-handler-T47GATL5.js → chat-handler-WGDFMOOD.js} +23 -22
  4. package/dist/chunk-24YKXKCG.js +35 -0
  5. package/dist/chunk-2OMGR7LN.js +45 -0
  6. package/dist/{chunk-GFW2HWJ6.js → chunk-4R5GV7RW.js} +37 -16
  7. package/dist/{chunk-P5MSY7ZI.js → chunk-5H5NRWHA.js} +22 -17
  8. package/dist/{chunk-MQMPIXON.js → chunk-5UMXFLET.js} +3 -3
  9. package/dist/{chunk-5JWJEZJ3.js → chunk-5UQ4CKOA.js} +2 -2
  10. package/dist/{chunk-7JVBDBXE.js → chunk-7QMWYNVF.js} +2 -2
  11. package/dist/{chunk-P57IBMK4.js → chunk-AATMPL7S.js} +4 -4
  12. package/dist/{chunk-OUQZZEIQ.js → chunk-BIZFY3QP.js} +487 -210
  13. package/dist/{chunk-LQKXJPKP.js → chunk-CTWZPN7G.js} +5 -1
  14. package/dist/{chunk-BKMWZTNO.js → chunk-DWA4IE65.js} +14 -2
  15. package/dist/{chunk-HXHPKGJE.js → chunk-ESZQTFQP.js} +614 -157
  16. package/dist/{chunk-KWAHD2JA.js → chunk-F2MOHHXB.js} +15 -2
  17. package/dist/{chunk-A7CB4USC.js → chunk-GP3CLMPQ.js} +132 -45
  18. package/dist/{chunk-HCYSGLY2.js → chunk-HF3NDXB4.js} +1 -1
  19. package/dist/{chunk-Y6ZGHOKM.js → chunk-I5ODJKYM.js} +4 -4
  20. package/dist/{chunk-OMMPTN6X.js → chunk-IAT2LBIX.js} +69 -27
  21. package/dist/{chunk-6EZDW4JS.js → chunk-J3NMNYGM.js} +2 -2
  22. package/dist/{chunk-M5T4RDPJ.js → chunk-MEEUXRFL.js} +2 -2
  23. package/dist/{chunk-RRUSYVQD.js → chunk-NFEZATSN.js} +8 -8
  24. package/dist/{chunk-MGEYAYGU.js → chunk-O3RCSKUH.js} +2 -2
  25. package/dist/{chunk-ELYHHEYL.js → chunk-ORCQ3EXQ.js} +2 -2
  26. package/dist/{chunk-FEIRWXLX.js → chunk-OZWHRBDY.js} +64 -17
  27. package/dist/{chunk-FGNJMKDV.js → chunk-QZOV4OVN.js} +29 -5
  28. package/dist/{chunk-TACWRDDC.js → chunk-S67WIWUG.js} +2 -2
  29. package/dist/{chunk-ZL4IAFF3.js → chunk-UKIUQAQZ.js} +3 -3
  30. package/dist/{chunk-VXG3AFFY.js → chunk-VHLD6PCZ.js} +8 -8
  31. package/dist/chunk-WY3PWHWY.js +7 -0
  32. package/dist/{chunk-CLDCHOEA.js → chunk-ZMK4VX7V.js} +2 -2
  33. package/dist/cli/dev.js +4 -1
  34. package/dist/cli/index.js +4 -1
  35. package/dist/{client-2K6PPPJJ.js → client-VVYOWXRR.js} +4 -4
  36. package/dist/{compactor-OEJAA2YP.js → compactor-454UEIEX.js} +9 -9
  37. package/dist/{dynamic-context-NJZKAZE3.js → dynamic-context-LKC6JYLQ.js} +10 -10
  38. package/dist/{events-ZJPRGVL2.js → events-335XAKFK.js} +6 -6
  39. package/dist/export-import-3WMRLO4A.js +137 -0
  40. package/dist/{folding-QRZOHY2I.js → folding-H7JTX6KI.js} +4 -4
  41. package/dist/{http-client-P4XTKAZA.js → http-client-A445WYZU.js} +3 -3
  42. package/dist/{install-VA2F6X6Z.js → install-AVTFA344.js} +64 -15
  43. package/dist/{launch-UKXVO37B.js → launch-GJ7EHQRI.js} +23 -22
  44. package/dist/{manager-TMBFBCQL.js → manager-ZACEUL5P.js} +4 -4
  45. package/dist/{mcp-YU7AM3UV.js → mcp-SQ4DOGPT.js} +22 -9
  46. package/dist/{orchestrator-GX22Y5EM.js → orchestrator-JGJWTRO5.js} +22 -21
  47. package/dist/package.json +3 -1
  48. package/dist/{path-security-CBACXAMS.js → path-security-4LROI7F4.js} +10 -10
  49. package/dist/{platform-5LQXOZO3.js → platform-XPMZKAUB.js} +3 -3
  50. package/dist/{processor-V35OLKRV.js → processor-MSQP63ML.js} +22 -21
  51. package/dist/{project-creator-6AGQTNXB.js → project-creator-T3A4H3YV.js} +42 -29
  52. package/dist/{protocol-BMUoqwYH.d.ts → protocol-Nr_H1_oC.d.ts} +3 -1
  53. package/dist/{protocol-Y7MRKRUO.js → protocol-XO4ZROAU.js} +3 -3
  54. package/dist/provider/index.d.ts +4 -4
  55. package/dist/provider-JWUNG2TD.js +507 -0
  56. package/dist/{provider-manager-BO5ZBG3T.js → provider-manager-2KKZ37XJ.js} +5 -5
  57. package/dist/pwa-V5PFB4OQ.js +502 -0
  58. package/dist/{registry-CMSSZHDC.js → registry-BEIR7Y5G.js} +3 -3
  59. package/dist/{serve-XRVT3D7Z.js → serve-CW5C3CBZ.js} +47 -36
  60. package/dist/server/index.d.ts +18 -3
  61. package/dist/server/index.js +27 -26
  62. package/dist/{server-GXMZMPXI.js → server-ZHEB7XS2.js} +26 -25
  63. package/dist/{service-WKABQHKL.js → service-M77VWL2M.js} +97 -32
  64. package/dist/{service-O3LCO3TQ.js → service-XIUNS5XV.js} +7 -6
  65. package/dist/{session-overrides-OECQYRDK.js → session-overrides-LYW5PJ3R.js} +5 -5
  66. package/dist/{sessions-NMPX5ICI.js → sessions-AOK3AGHY.js} +6 -4
  67. package/dist/{settings-MDCRNQBY.js → settings-ZJPM6PQV.js} +2 -2
  68. package/dist/shared/index.d.ts +31 -4
  69. package/dist/shared/index.js +16 -2
  70. package/dist/{tasks-WOC3QUFA.js → tasks-3JJWJJ3X.js} +34 -18
  71. package/dist/{tools-CW6POKUL.js → tools-E63MOJBO.js} +20 -19
  72. package/dist/{types-CoY8Ka1C.d.ts → types-BlQjLBui.d.ts} +1 -1
  73. package/dist/{types-BIkpxjaj.d.ts → types-G10ho8PT.d.ts} +1 -1
  74. package/dist/update-XVXNSSDK.js +76 -0
  75. package/dist/web/assets/{index-Y300llHY.css → index-Bg_Z8i3F.css} +1 -1
  76. package/dist/web/assets/index-wTFCxQAw.js +313 -0
  77. package/dist/web/index.html +2 -2
  78. package/dist/web/sw.js +1 -1
  79. package/package.json +3 -1
  80. package/dist/chunk-JKGHTBEV.js +0 -7
  81. package/dist/provider-NWRGNGS3.js +0 -403
  82. package/dist/pwa-2GRFSXD7.js +0 -363
  83. package/dist/update-VC3Y3EOP.js +0 -49
  84. package/dist/web/assets/index-ATAQvBwl.js +0 -312
@@ -0,0 +1,507 @@
1
+ import {
2
+ cancel,
3
+ isCancel,
4
+ log,
5
+ outro,
6
+ password,
7
+ select,
8
+ spinner,
9
+ text
10
+ } from "./chunk-AGXJ5O63.js";
11
+ import {
12
+ cliT
13
+ } from "./chunk-2OMGR7LN.js";
14
+ import {
15
+ detectModel,
16
+ fetchAvailableModelsFromBackend
17
+ } from "./chunk-5UQ4CKOA.js";
18
+ import "./chunk-OA2FURC3.js";
19
+ import "./chunk-J2GP3J3X.js";
20
+ import "./chunk-ZMK4VX7V.js";
21
+ import "./chunk-TS5WKTFB.js";
22
+ import "./chunk-UV6IH6HK.js";
23
+ import "./chunk-HNCM3D7Y.js";
24
+ import "./chunk-EUOWCVU6.js";
25
+ import "./chunk-J3NMNYGM.js";
26
+ import "./chunk-CTWZPN7G.js";
27
+ import "./chunk-JU757HVI.js";
28
+ import "./chunk-2AI7VYPN.js";
29
+ import "./chunk-K44MW7JJ.js";
30
+ import "./chunk-24YKXKCG.js";
31
+ import {
32
+ activateProvider,
33
+ addProvider,
34
+ getActiveProvider,
35
+ loadGlobalConfig,
36
+ removeProvider,
37
+ saveGlobalConfig
38
+ } from "./chunk-R5FAEKXQ.js";
39
+ import "./chunk-CQGTEGKL.js";
40
+ import "./chunk-YLJ4XMA6.js";
41
+
42
+ // src/cli/provider.ts
43
+ var BACKEND_OPTIONS = [
44
+ { value: "vllm", label: "vLLM" },
45
+ { value: "sglang", label: "SGLang" },
46
+ { value: "ollama", label: "Ollama" },
47
+ { value: "llamacpp", label: "llama.cpp" },
48
+ { value: "openai", label: "OpenAI" },
49
+ { value: "anthropic", label: "Anthropic" }
50
+ ];
51
+ function printProviderHelp() {
52
+ console.log(
53
+ cliT({
54
+ en: `
55
+ Provider Management Commands:
56
+
57
+ openfox provider add Add a new provider
58
+ openfox provider list List all configured providers
59
+ openfox provider use Switch to a different provider
60
+ openfox provider remove Remove a provider
61
+ `,
62
+ fr: `
63
+ Commandes de gestion des fournisseurs :
64
+
65
+ openfox provider add Ajouter un nouveau fournisseur
66
+ openfox provider list Lister tous les fournisseurs configur\xE9s
67
+ openfox provider use Changer de fournisseur
68
+ openfox provider remove Supprimer un fournisseur
69
+ `
70
+ })
71
+ );
72
+ }
73
+ async function runProviderAdd(mode) {
74
+ const config = await loadGlobalConfig(mode);
75
+ const name = await text({
76
+ message: cliT({ en: "Provider name:", fr: "Nom du fournisseur :" }),
77
+ placeholder: cliT({ en: "My Local vLLM", fr: "Mon vLLM local" }),
78
+ validate: (value) => {
79
+ if (!value || value.length === 0) return cliT({ en: "Name is required", fr: "Le nom est requis" });
80
+ if (config.providers.some((p) => p.name === value))
81
+ return cliT({ en: "Provider with this name already exists", fr: "Un fournisseur avec ce nom existe d\xE9j\xE0" });
82
+ }
83
+ });
84
+ if (isCancel(name)) {
85
+ cancel(cliT({ en: "Cancelled", fr: "Annul\xE9" }));
86
+ return;
87
+ }
88
+ log.info(
89
+ cliT({
90
+ en: `URL examples:
91
+ vLLM/SGLang: http://localhost:8000
92
+ Ollama: http://localhost:11434
93
+ llama.cpp: http://localhost:8080
94
+ OpenAI: https://api.openai.com
95
+ Anthropic: https://api.anthropic.com
96
+
97
+ (Don't include /v1 - it's added automatically)`,
98
+ fr: `Exemples d\u2019URL :
99
+ vLLM/SGLang : http://localhost:8000
100
+ Ollama : http://localhost:11434
101
+ llama.cpp : http://localhost:8080
102
+ OpenAI : https://api.openai.com
103
+ Anthropic : https://api.anthropic.com
104
+
105
+ (N\u2019incluez pas /v1 - il est ajout\xE9 automatiquement)`
106
+ })
107
+ );
108
+ const url = await text({
109
+ message: cliT({ en: "API URL:", fr: "URL de l\u2019API :" }),
110
+ placeholder: "http://localhost:8000",
111
+ initialValue: "http://localhost:8000",
112
+ validate: (value) => {
113
+ if (!value || value.length === 0) return cliT({ en: "URL is required", fr: "L\u2019URL est requise" });
114
+ if (!value.startsWith("http"))
115
+ return cliT({ en: "Must start with http:// or https://", fr: "Doit commencer par http:// ou https://" });
116
+ }
117
+ });
118
+ if (isCancel(url)) {
119
+ cancel(cliT({ en: "Cancelled", fr: "Annul\xE9" }));
120
+ return;
121
+ }
122
+ const backend = await select({
123
+ message: cliT({ en: "Backend type:", fr: "Type de backend :" }),
124
+ options: BACKEND_OPTIONS
125
+ });
126
+ if (isCancel(backend)) {
127
+ cancel(cliT({ en: "Cancelled", fr: "Annul\xE9" }));
128
+ return;
129
+ }
130
+ let selectedModel;
131
+ const s = spinner();
132
+ s.start(
133
+ cliT({
134
+ en: `Fetching available models from ${url}...`,
135
+ fr: `R\xE9cup\xE9ration des mod\xE8les disponibles depuis ${url}...`
136
+ })
137
+ );
138
+ let availableModels = [];
139
+ try {
140
+ availableModels = await fetchAvailableModelsFromBackend(url);
141
+ s.stop(
142
+ cliT({ en: `Found ${availableModels.length} model(s)`, fr: `${availableModels.length} mod\xE8le(s) trouv\xE9(s)` })
143
+ );
144
+ } catch {
145
+ s.stop(
146
+ cliT({
147
+ en: "\u26A0 Could not fetch models, will use auto-detect",
148
+ fr: "\u26A0 Impossible de r\xE9cup\xE9rer les mod\xE8les, auto-d\xE9tection utilis\xE9e"
149
+ })
150
+ );
151
+ }
152
+ if (availableModels.length > 0) {
153
+ const modelChoice = await select({
154
+ message: cliT({ en: "Select model:", fr: "S\xE9lectionnez un mod\xE8le :" }),
155
+ options: availableModels.map((m) => ({
156
+ value: m,
157
+ label: m.split("/").pop() ?? m,
158
+ hint: m
159
+ }))
160
+ });
161
+ if (isCancel(modelChoice)) {
162
+ cancel(cliT({ en: "Cancelled", fr: "Annul\xE9" }));
163
+ return;
164
+ }
165
+ selectedModel = modelChoice;
166
+ } else {
167
+ const model = await text({
168
+ message: cliT({ en: 'Model name (or "auto" to detect):', fr: "Nom du mod\xE8le (ou \xAB auto \xBB pour d\xE9tecter) :" }),
169
+ placeholder: "auto",
170
+ initialValue: "auto"
171
+ });
172
+ if (isCancel(model)) {
173
+ cancel(cliT({ en: "Cancelled", fr: "Annul\xE9" }));
174
+ return;
175
+ }
176
+ selectedModel = model;
177
+ if (selectedModel === "auto") {
178
+ const detectSpinner = spinner();
179
+ detectSpinner.start(cliT({ en: "Detecting model...", fr: "D\xE9tection du mod\xE8le..." }));
180
+ let detectedModel;
181
+ try {
182
+ detectedModel = await detectModel(url);
183
+ if (detectedModel) {
184
+ selectedModel = detectedModel;
185
+ detectSpinner.stop(cliT({ en: `Detected: ${detectedModel}`, fr: `D\xE9tect\xE9 : ${detectedModel}` }));
186
+ } else {
187
+ detectSpinner.stop(
188
+ cliT({
189
+ en: "Could not detect model, will use auto",
190
+ fr: "Impossible de d\xE9tecter le mod\xE8le, \xAB auto \xBB sera utilis\xE9"
191
+ })
192
+ );
193
+ }
194
+ } catch {
195
+ detectSpinner.stop(
196
+ cliT({ en: "Detection failed, will use auto", fr: "\xC9chec de la d\xE9tection, \xAB auto \xBB sera utilis\xE9" })
197
+ );
198
+ }
199
+ }
200
+ }
201
+ const localBackends = /* @__PURE__ */ new Set(["vllm", "sglang", "ollama", "llamacpp", "opencode-go"]);
202
+ const defaultIsLocal = localBackends.has(backend);
203
+ const isLocalChoice = await select({
204
+ message: cliT({ en: "Is this a local provider?", fr: "S\u2019agit-il d\u2019un fournisseur local ?" }),
205
+ options: [
206
+ { value: "yes", label: cliT({ en: "Yes", fr: "Oui" }) },
207
+ { value: "no", label: cliT({ en: "No", fr: "Non" }) }
208
+ ],
209
+ initialValue: defaultIsLocal ? "yes" : "no"
210
+ });
211
+ if (isCancel(isLocalChoice)) {
212
+ cancel(cliT({ en: "Cancelled", fr: "Annul\xE9" }));
213
+ return;
214
+ }
215
+ const isLocal = isLocalChoice === "yes";
216
+ let apiKey;
217
+ if (backend === "openai" || backend === "anthropic") {
218
+ const key = await password({
219
+ message: cliT({ en: "API Key:", fr: "Cl\xE9 API :" })
220
+ });
221
+ if (isCancel(key)) {
222
+ cancel(cliT({ en: "Cancelled", fr: "Annul\xE9" }));
223
+ return;
224
+ }
225
+ apiKey = key || void 0;
226
+ } else {
227
+ const needsKey = await select({
228
+ message: cliT({ en: "Does this provider require an API key?", fr: "Ce fournisseur requiert-il une cl\xE9 API ?" }),
229
+ options: [
230
+ { value: "no", label: cliT({ en: "No", fr: "Non" }) },
231
+ { value: "yes", label: cliT({ en: "Yes", fr: "Oui" }) }
232
+ ]
233
+ });
234
+ if (isCancel(needsKey)) {
235
+ cancel(cliT({ en: "Cancelled", fr: "Annul\xE9" }));
236
+ return;
237
+ }
238
+ if (needsKey === "yes") {
239
+ const key = await password({
240
+ message: cliT({ en: "API Key:", fr: "Cl\xE9 API :" })
241
+ });
242
+ if (isCancel(key)) {
243
+ cancel(cliT({ en: "Cancelled", fr: "Annul\xE9" }));
244
+ return;
245
+ }
246
+ apiKey = key || void 0;
247
+ }
248
+ }
249
+ const testSpinner = spinner();
250
+ testSpinner.start(cliT({ en: `Testing connection to ${url}...`, fr: `Test de la connexion \xE0 ${url}...` }));
251
+ const finalBackend = backend;
252
+ let finalDetectedModel = null;
253
+ try {
254
+ if (selectedModel === "auto") {
255
+ finalDetectedModel = await detectModel(url) ?? "auto";
256
+ }
257
+ testSpinner.stop(
258
+ cliT({
259
+ en: `\u2713 Connected to ${finalBackend}${finalDetectedModel !== "auto" ? ` (${finalDetectedModel})` : ""}`,
260
+ fr: `\u2713 Connect\xE9 \xE0 ${finalBackend}${finalDetectedModel !== "auto" ? ` (${finalDetectedModel})` : ""}`
261
+ })
262
+ );
263
+ } catch {
264
+ testSpinner.stop(cliT({ en: "\u26A0 Could not connect to provider", fr: "\u26A0 Impossible de se connecter au fournisseur" }));
265
+ const continueAnyway = await select({
266
+ message: cliT({
267
+ en: "Provider is not reachable. Save anyway?",
268
+ fr: "Le fournisseur est injoignable. Enregistrer quand m\xEAme ?"
269
+ }),
270
+ options: [
271
+ { value: "yes", label: cliT({ en: "Yes, save anyway", fr: "Oui, enregistrer quand m\xEAme" }) },
272
+ { value: "no", label: cliT({ en: "No, cancel", fr: "Non, annuler" }) }
273
+ ]
274
+ });
275
+ if (isCancel(continueAnyway) || continueAnyway === "no") {
276
+ cancel(cliT({ en: "Cancelled", fr: "Annul\xE9" }));
277
+ return;
278
+ }
279
+ }
280
+ const makeActive = config.providers.length === 0 || await (async () => {
281
+ const choice = await select({
282
+ message: cliT({ en: "Make this the active provider?", fr: "Faire de ce fournisseur le fournisseur actif ?" }),
283
+ options: [
284
+ { value: "yes", label: cliT({ en: "Yes", fr: "Oui" }) },
285
+ { value: "no", label: cliT({ en: "No", fr: "Non" }) }
286
+ ]
287
+ });
288
+ if (isCancel(choice)) return false;
289
+ return choice === "yes";
290
+ })();
291
+ const modelsWithContent = [];
292
+ if (availableModels.length > 0) {
293
+ const modelFetchSpinner = spinner();
294
+ modelFetchSpinner.start(
295
+ cliT({ en: "Fetching model metadata...", fr: "R\xE9cup\xE9ration des m\xE9tadonn\xE9es des mod\xE8les..." })
296
+ );
297
+ try {
298
+ const urlWithV1 = url.includes("/v1") ? url : `${url}/v1`;
299
+ const response = await fetch(`${urlWithV1}/models`, {
300
+ signal: AbortSignal.timeout(1e4)
301
+ });
302
+ if (response.ok) {
303
+ const data = await response.json();
304
+ if (data.data && Array.isArray(data.data)) {
305
+ for (const modelData of data.data) {
306
+ modelsWithContent.push({
307
+ id: modelData.id,
308
+ contextWindow: modelData.max_model_len ?? 2e5,
309
+ source: modelData.max_model_len ? "backend" : "default"
310
+ });
311
+ }
312
+ modelFetchSpinner.stop(
313
+ cliT({
314
+ en: `\u2713 Fetched ${modelsWithContent.length} model(s) with context windows`,
315
+ fr: `\u2713 ${modelsWithContent.length} mod\xE8le(s) r\xE9cup\xE9r\xE9(s) avec fen\xEAtres de contexte`
316
+ })
317
+ );
318
+ } else {
319
+ modelFetchSpinner.stop(cliT({ en: "\u26A0 No models in response", fr: "\u26A0 Aucun mod\xE8le dans la r\xE9ponse" }));
320
+ }
321
+ } else {
322
+ modelFetchSpinner.stop(
323
+ cliT({ en: "\u26A0 Could not fetch model metadata", fr: "\u26A0 Impossible de r\xE9cup\xE9rer les m\xE9tadonn\xE9es des mod\xE8les" })
324
+ );
325
+ }
326
+ } catch {
327
+ modelFetchSpinner.stop(
328
+ cliT({ en: "\u26A0 Failed to fetch model metadata", fr: "\u26A0 \xC9chec de la r\xE9cup\xE9ration des m\xE9tadonn\xE9es des mod\xE8les" })
329
+ );
330
+ }
331
+ }
332
+ const models = modelsWithContent.length > 0 ? modelsWithContent : [];
333
+ let newConfig = addProvider(config, {
334
+ name,
335
+ url,
336
+ backend: finalBackend,
337
+ apiKey,
338
+ isLocal,
339
+ models,
340
+ isActive: makeActive
341
+ });
342
+ if (makeActive) {
343
+ const { setDefaultModelSelection } = await import("./config-LOK3LXFH.js");
344
+ newConfig = setDefaultModelSelection(
345
+ newConfig,
346
+ newConfig.providers[newConfig.providers.length - 1].id,
347
+ selectedModel
348
+ );
349
+ }
350
+ await saveGlobalConfig(mode, newConfig);
351
+ outro(
352
+ cliT({
353
+ en: `\u2713 Provider "${name}" added${makeActive ? " and activated" : ""}`,
354
+ fr: `\u2713 Fournisseur \xAB ${name} \xBB ajout\xE9${makeActive ? " et activ\xE9" : ""}`
355
+ })
356
+ );
357
+ }
358
+ async function runProviderList(mode) {
359
+ const config = await loadGlobalConfig(mode);
360
+ if (config.providers.length === 0) {
361
+ log.warn(
362
+ cliT({
363
+ en: "No providers configured. Run `openfox provider add` to add one.",
364
+ fr: "Aucun fournisseur configur\xE9. Lancez `openfox provider add` pour en ajouter un."
365
+ })
366
+ );
367
+ return;
368
+ }
369
+ console.log(cliT({ en: "\nConfigured providers:\n", fr: "\nFournisseurs configur\xE9s :\n" }));
370
+ console.log(
371
+ cliT({
372
+ en: " NAME URL MODEL BACKEND",
373
+ fr: " NOM URL MOD\xC8LE BACKEND"
374
+ })
375
+ );
376
+ console.log(
377
+ cliT({
378
+ en: " \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
379
+ fr: " \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
380
+ })
381
+ );
382
+ for (const provider of config.providers) {
383
+ const marker = provider.isActive ? "\u25B8" : " ";
384
+ const name = provider.name.padEnd(18);
385
+ const url = provider.url.padEnd(32);
386
+ const model = (provider.models?.[0]?.id || "auto").padEnd(18);
387
+ const backend = provider.backend;
388
+ console.log(`${marker} ${name} ${url} ${model} ${backend}`);
389
+ }
390
+ console.log("");
391
+ }
392
+ async function runProviderUse(mode) {
393
+ const config = await loadGlobalConfig(mode);
394
+ if (config.providers.length === 0) {
395
+ log.warn(
396
+ cliT({
397
+ en: "No providers configured. Run `openfox provider add` to add one.",
398
+ fr: "Aucun fournisseur configur\xE9. Lancez `openfox provider add` pour en ajouter un."
399
+ })
400
+ );
401
+ return;
402
+ }
403
+ if (config.providers.length === 1) {
404
+ log.info(
405
+ cliT({ en: "Only one provider configured, already active.", fr: "Un seul fournisseur configur\xE9, d\xE9j\xE0 actif." })
406
+ );
407
+ return;
408
+ }
409
+ const activeProvider = getActiveProvider(config);
410
+ const choice = await select({
411
+ message: cliT({ en: "Select provider to activate:", fr: "S\xE9lectionnez le fournisseur \xE0 activer :" }),
412
+ options: config.providers.map((p) => ({
413
+ value: p.id,
414
+ label: `${p.name}${p.isActive ? cliT({ en: " (current)", fr: " (actuel)" }) : ""}`,
415
+ hint: `${p.url} - ${p.models?.[0]?.id ?? "auto"}`
416
+ })),
417
+ initialValue: activeProvider?.id
418
+ });
419
+ if (isCancel(choice)) {
420
+ cancel(cliT({ en: "Cancelled", fr: "Annul\xE9" }));
421
+ return;
422
+ }
423
+ if (choice === activeProvider?.id) {
424
+ log.info(cliT({ en: "Already the active provider.", fr: "D\xE9j\xE0 le fournisseur actif." }));
425
+ return;
426
+ }
427
+ const newConfig = activateProvider(config, choice);
428
+ await saveGlobalConfig(mode, newConfig);
429
+ const activated = newConfig.providers.find((p) => p.id === choice);
430
+ outro(cliT({ en: `\u2713 Now using "${activated?.name}"`, fr: `\u2713 Vous utilisez d\xE9sormais \xAB ${activated?.name} \xBB` }));
431
+ }
432
+ async function runProviderRemove(mode) {
433
+ const config = await loadGlobalConfig(mode);
434
+ if (config.providers.length === 0) {
435
+ log.warn(cliT({ en: "No providers configured.", fr: "Aucun fournisseur configur\xE9." }));
436
+ return;
437
+ }
438
+ const choice = await select({
439
+ message: cliT({ en: "Select provider to remove:", fr: "S\xE9lectionnez le fournisseur \xE0 supprimer :" }),
440
+ options: config.providers.map((p) => ({
441
+ value: p.id,
442
+ label: `${p.name}${p.isActive ? cliT({ en: " (active)", fr: " (actif)" }) : ""}`,
443
+ hint: p.url
444
+ }))
445
+ });
446
+ if (isCancel(choice)) {
447
+ cancel(cliT({ en: "Cancelled", fr: "Annul\xE9" }));
448
+ return;
449
+ }
450
+ const providerToRemove = config.providers.find((p) => p.id === choice);
451
+ if (providerToRemove?.isActive && config.providers.length > 1) {
452
+ const confirm = await select({
453
+ message: cliT({
454
+ en: `"${providerToRemove.name}" is the active provider. Remove it anyway?`,
455
+ fr: `\xAB ${providerToRemove.name} \xBB est le fournisseur actif. Le supprimer quand m\xEAme ?`
456
+ }),
457
+ options: [
458
+ {
459
+ value: "yes",
460
+ label: cliT({
461
+ en: "Yes, remove and activate next provider",
462
+ fr: "Oui, supprimer et activer le fournisseur suivant"
463
+ })
464
+ },
465
+ { value: "no", label: cliT({ en: "No, cancel", fr: "Non, annuler" }) }
466
+ ]
467
+ });
468
+ if (isCancel(confirm) || confirm === "no") {
469
+ cancel(cliT({ en: "Cancelled", fr: "Annul\xE9" }));
470
+ return;
471
+ }
472
+ }
473
+ const newConfig = removeProvider(config, choice);
474
+ await saveGlobalConfig(mode, newConfig);
475
+ outro(cliT({ en: `\u2713 Removed "${providerToRemove?.name}"`, fr: `\u2713 \xAB ${providerToRemove?.name} \xBB supprim\xE9` }));
476
+ }
477
+ async function runProviderCommand(mode, subcommand) {
478
+ switch (subcommand) {
479
+ case "add":
480
+ await runProviderAdd(mode);
481
+ break;
482
+ case "list":
483
+ case "ls":
484
+ await runProviderList(mode);
485
+ break;
486
+ case "use":
487
+ case "switch":
488
+ await runProviderUse(mode);
489
+ break;
490
+ case "remove":
491
+ case "rm":
492
+ case "delete":
493
+ await runProviderRemove(mode);
494
+ break;
495
+ default:
496
+ printProviderHelp();
497
+ }
498
+ }
499
+ export {
500
+ printProviderHelp,
501
+ runProviderAdd,
502
+ runProviderCommand,
503
+ runProviderList,
504
+ runProviderRemove,
505
+ runProviderUse
506
+ };
507
+ //# sourceMappingURL=provider-JWUNG2TD.js.map
@@ -3,16 +3,16 @@ import {
3
3
  fetchAvailableModelsFromBackend,
4
4
  fetchModelsWithContext,
5
5
  parseDefaultModelSelection
6
- } from "./chunk-5JWJEZJ3.js";
6
+ } from "./chunk-5UQ4CKOA.js";
7
7
  import "./chunk-OA2FURC3.js";
8
8
  import "./chunk-J2GP3J3X.js";
9
- import "./chunk-CLDCHOEA.js";
9
+ import "./chunk-ZMK4VX7V.js";
10
10
  import "./chunk-TS5WKTFB.js";
11
11
  import "./chunk-UV6IH6HK.js";
12
12
  import "./chunk-HNCM3D7Y.js";
13
13
  import "./chunk-EUOWCVU6.js";
14
- import "./chunk-6EZDW4JS.js";
15
- import "./chunk-LQKXJPKP.js";
14
+ import "./chunk-J3NMNYGM.js";
15
+ import "./chunk-CTWZPN7G.js";
16
16
  import "./chunk-JU757HVI.js";
17
17
  import "./chunk-2AI7VYPN.js";
18
18
  import "./chunk-K44MW7JJ.js";
@@ -23,4 +23,4 @@ export {
23
23
  fetchModelsWithContext,
24
24
  parseDefaultModelSelection
25
25
  };
26
- //# sourceMappingURL=provider-manager-BO5ZBG3T.js.map
26
+ //# sourceMappingURL=provider-manager-2KKZ37XJ.js.map