anygate 0.5.11 → 0.6.0
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/{chunk-55RHVPE4.js → chunk-CRK6YGKY.js} +1290 -682
- package/dist/chunk-CRK6YGKY.js.map +1 -0
- package/dist/{chunk-5UF4TVCM.js → chunk-QLHVQYQN.js} +23 -3
- package/dist/chunk-QLHVQYQN.js.map +1 -0
- package/dist/{chunk-72WNE2IK.js → chunk-UT3JLF3M.js} +2 -13
- package/dist/{chunk-6AFYEDSU.js → chunk-VGM6EBG4.js} +10 -4
- package/dist/{chunk-6AFYEDSU.js.map → chunk-VGM6EBG4.js.map} +1 -1
- package/dist/cli.js +1124 -567
- package/dist/cli.js.map +1 -1
- package/dist/{command-7AI36ICY.js → command-PFFQI5YC.js} +185 -88
- package/dist/command-PFFQI5YC.js.map +1 -0
- package/dist/{constants-HE3EOSMH.js → constants-GW5BAY6G.js} +9 -3
- package/dist/{provider-templates-MNJZTG3Z.js → provider-templates-CRQJII3Z.js} +3 -3
- package/dist/registry/data/templates/agentrouter.json +19 -0
- package/dist/ui/dist/assets/{index-DWAOH_B3.css → index-D4hWZLit.css} +1 -1
- package/dist/ui/dist/assets/index-DyxtUjA-.js +7 -0
- package/dist/ui/dist/index.html +2 -2
- package/package.json +108 -94
- package/dist/chunk-55RHVPE4.js.map +0 -1
- package/dist/chunk-5UF4TVCM.js.map +0 -1
- package/dist/command-7AI36ICY.js.map +0 -1
- package/dist/ui/dist/assets/index-qxVU3kMy.js +0 -6
- /package/dist/{chunk-72WNE2IK.js.map → chunk-UT3JLF3M.js.map} +0 -0
- /package/dist/{constants-HE3EOSMH.js.map → constants-GW5BAY6G.js.map} +0 -0
- /package/dist/{provider-templates-MNJZTG3Z.js.map → provider-templates-CRQJII3Z.js.map} +0 -0
|
@@ -29,8 +29,6 @@ import {
|
|
|
29
29
|
getServerMaskGatewayIds,
|
|
30
30
|
getUiDebugLogPath,
|
|
31
31
|
guiCallbackRedirectUri,
|
|
32
|
-
init_config,
|
|
33
|
-
init_paths,
|
|
34
32
|
loadPreferences,
|
|
35
33
|
loadRegistry,
|
|
36
34
|
loadServerModels,
|
|
@@ -66,23 +64,29 @@ import {
|
|
|
66
64
|
summarizeServerProviders,
|
|
67
65
|
validateCustomEndpointUrl,
|
|
68
66
|
writeSecureLogLine
|
|
69
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-CRK6YGKY.js";
|
|
70
68
|
import {
|
|
71
69
|
BACKENDS,
|
|
72
70
|
MAX_MODEL_CATALOG
|
|
73
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-QLHVQYQN.js";
|
|
74
72
|
import {
|
|
75
73
|
getTemplateById,
|
|
76
74
|
listSupportedTemplates,
|
|
77
75
|
listVisibleOAuthTemplates
|
|
78
|
-
} from "./chunk-
|
|
79
|
-
import "./chunk-
|
|
76
|
+
} from "./chunk-VGM6EBG4.js";
|
|
77
|
+
import "./chunk-UT3JLF3M.js";
|
|
80
78
|
|
|
81
79
|
// src/ui/command.ts
|
|
82
|
-
init_paths();
|
|
83
80
|
import { createServer } from "http";
|
|
84
81
|
import { execSync } from "child_process";
|
|
85
|
-
import {
|
|
82
|
+
import {
|
|
83
|
+
readFileSync,
|
|
84
|
+
readdirSync,
|
|
85
|
+
writeFileSync as writeFileSync2,
|
|
86
|
+
unlinkSync,
|
|
87
|
+
existsSync as existsSync3,
|
|
88
|
+
mkdirSync
|
|
89
|
+
} from "fs";
|
|
86
90
|
import { join as join2 } from "path";
|
|
87
91
|
import { fileURLToPath } from "url";
|
|
88
92
|
import { dirname } from "path";
|
|
@@ -90,7 +94,6 @@ import pc from "picocolors";
|
|
|
90
94
|
import * as p from "@clack/prompts";
|
|
91
95
|
|
|
92
96
|
// src/apps/shared/native-launcher.ts
|
|
93
|
-
init_config();
|
|
94
97
|
import { chmodSync, existsSync, mkdtempSync, writeFileSync } from "fs";
|
|
95
98
|
import { homedir } from "os";
|
|
96
99
|
import { tmpdir } from "os";
|
|
@@ -98,10 +101,38 @@ import { join } from "path";
|
|
|
98
101
|
var isWindows = process.platform === "win32";
|
|
99
102
|
var isMac = process.platform === "darwin";
|
|
100
103
|
var SUPPORTED_APPS = [
|
|
101
|
-
{
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
{
|
|
105
|
+
id: "claude",
|
|
106
|
+
name: "Claude Code CLI",
|
|
107
|
+
type: "cli",
|
|
108
|
+
detectId: "claude",
|
|
109
|
+
gatewayCommand: "claude",
|
|
110
|
+
installHint: "npm install -g @anthropic-ai/claude-code"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: "codex",
|
|
114
|
+
name: "Codex CLI",
|
|
115
|
+
type: "cli",
|
|
116
|
+
detectId: "codex",
|
|
117
|
+
gatewayCommand: "codex",
|
|
118
|
+
installHint: "npm install -g @openai/codex"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
id: "gemini",
|
|
122
|
+
name: "Gemini CLI",
|
|
123
|
+
type: "cli",
|
|
124
|
+
detectId: "gemini",
|
|
125
|
+
gatewayCommand: "gemini",
|
|
126
|
+
installHint: "npm install -g @google/gemini-cli"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: "agy",
|
|
130
|
+
name: "Antigravity CLI",
|
|
131
|
+
type: "cli",
|
|
132
|
+
detectId: "agy",
|
|
133
|
+
gatewayCommand: "agy",
|
|
134
|
+
installHint: "npm install -g @google/antigravity-cli"
|
|
135
|
+
},
|
|
105
136
|
{
|
|
106
137
|
id: "antigravity",
|
|
107
138
|
name: "Antigravity (App)",
|
|
@@ -142,30 +173,21 @@ function fallbackPathsForApp(id, platform = process.platform) {
|
|
|
142
173
|
const localAppData = process.env["LOCALAPPDATA"] ?? join(homedir(), "AppData", "Local");
|
|
143
174
|
switch (id) {
|
|
144
175
|
case "claude":
|
|
145
|
-
return windows ? [
|
|
146
|
-
join(appData, "npm", "claude.cmd"),
|
|
147
|
-
join(appData, "npm", "claude")
|
|
148
|
-
] : [
|
|
176
|
+
return windows ? [join(appData, "npm", "claude.cmd"), join(appData, "npm", "claude")] : [
|
|
149
177
|
join(homedir(), ".local", "bin", "claude"),
|
|
150
178
|
join(homedir(), ".npm", "bin", "claude"),
|
|
151
179
|
"/usr/local/bin/claude",
|
|
152
180
|
"/opt/homebrew/bin/claude"
|
|
153
181
|
];
|
|
154
182
|
case "codex":
|
|
155
|
-
return windows ? [
|
|
156
|
-
join(appData, "npm", "codex.cmd"),
|
|
157
|
-
join(appData, "npm", "codex")
|
|
158
|
-
] : [
|
|
183
|
+
return windows ? [join(appData, "npm", "codex.cmd"), join(appData, "npm", "codex")] : [
|
|
159
184
|
join(homedir(), ".local", "bin", "codex"),
|
|
160
185
|
join(homedir(), ".npm", "bin", "codex"),
|
|
161
186
|
"/usr/local/bin/codex",
|
|
162
187
|
"/opt/homebrew/bin/codex"
|
|
163
188
|
];
|
|
164
189
|
case "gemini":
|
|
165
|
-
return windows ? [
|
|
166
|
-
join(appData, "npm", "gemini.cmd"),
|
|
167
|
-
join(appData, "npm", "gemini")
|
|
168
|
-
] : [
|
|
190
|
+
return windows ? [join(appData, "npm", "gemini.cmd"), join(appData, "npm", "gemini")] : [
|
|
169
191
|
join(homedir(), ".local", "bin", "gemini"),
|
|
170
192
|
join(homedir(), ".npm", "bin", "gemini"),
|
|
171
193
|
"/usr/local/bin/gemini",
|
|
@@ -186,7 +208,16 @@ function fallbackPathsForApp(id, platform = process.platform) {
|
|
|
186
208
|
if (mac) {
|
|
187
209
|
return [
|
|
188
210
|
"/Applications/Antigravity IDE.app/Contents/Resources/app/bin/antigravity-ide",
|
|
189
|
-
join(
|
|
211
|
+
join(
|
|
212
|
+
homedir(),
|
|
213
|
+
"Applications",
|
|
214
|
+
"Antigravity IDE.app",
|
|
215
|
+
"Contents",
|
|
216
|
+
"Resources",
|
|
217
|
+
"app",
|
|
218
|
+
"bin",
|
|
219
|
+
"antigravity-ide"
|
|
220
|
+
)
|
|
190
221
|
];
|
|
191
222
|
}
|
|
192
223
|
if (windows) {
|
|
@@ -205,15 +236,9 @@ function fallbackPathsForApp(id, platform = process.platform) {
|
|
|
205
236
|
];
|
|
206
237
|
}
|
|
207
238
|
if (windows) {
|
|
208
|
-
return [
|
|
209
|
-
join(localAppData, "Programs", "Antigravity", "Antigravity.exe")
|
|
210
|
-
];
|
|
239
|
+
return [join(localAppData, "Programs", "Antigravity", "Antigravity.exe")];
|
|
211
240
|
}
|
|
212
|
-
return [
|
|
213
|
-
"/opt/antigravity/antigravity",
|
|
214
|
-
"/usr/local/bin/antigravity",
|
|
215
|
-
"/usr/bin/antigravity"
|
|
216
|
-
];
|
|
241
|
+
return ["/opt/antigravity/antigravity", "/usr/local/bin/antigravity", "/usr/bin/antigravity"];
|
|
217
242
|
case "claude-app":
|
|
218
243
|
if (mac) {
|
|
219
244
|
return [
|
|
@@ -278,19 +303,23 @@ function getTerminalLaunchCommand(binPath, args, opts = {}) {
|
|
|
278
303
|
const dir2 = mkdtempSync(join(tmpdir(), "anygate-launch-"));
|
|
279
304
|
const scriptPath2 = join(dir2, "launch.command");
|
|
280
305
|
const displayCommand = opts.displayCommand ?? [binPath, ...args].join(" ");
|
|
281
|
-
writeFileSync(
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
306
|
+
writeFileSync(
|
|
307
|
+
scriptPath2,
|
|
308
|
+
[
|
|
309
|
+
"#!/bin/sh",
|
|
310
|
+
`trap 'rm -f "$0"; rmdir "$(dirname "$0")" 2>/dev/null' EXIT`,
|
|
311
|
+
"clear",
|
|
312
|
+
opts.cwd ? `cd ${quoteShellArg(opts.cwd)} || exit 1` : "",
|
|
313
|
+
`printf '%s\\n\\n' ${quoteShellArg(`$ ${displayCommand}`)}`,
|
|
314
|
+
fullCmd,
|
|
315
|
+
"status=$?",
|
|
316
|
+
'printf "\\nanygate session exited with code %s. Press Return to close this window. " "$status"',
|
|
317
|
+
"read _",
|
|
318
|
+
'exit "$status"',
|
|
319
|
+
""
|
|
320
|
+
].join("\n"),
|
|
321
|
+
{ encoding: "utf8", mode: 448 }
|
|
322
|
+
);
|
|
294
323
|
chmodSync(scriptPath2, 448);
|
|
295
324
|
return `open -a Terminal ${quoteShellArg(scriptPath2)}`;
|
|
296
325
|
}
|
|
@@ -300,12 +329,10 @@ function getTerminalLaunchCommand(binPath, args, opts = {}) {
|
|
|
300
329
|
}
|
|
301
330
|
const dir = mkdtempSync(join(tmpdir(), "anygate-launch-"));
|
|
302
331
|
const scriptPath = join(dir, "launch.sh");
|
|
303
|
-
writeFileSync(scriptPath, [
|
|
304
|
-
"
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
""
|
|
308
|
-
].join("\n"), { encoding: "utf8", mode: 448 });
|
|
332
|
+
writeFileSync(scriptPath, ["#!/bin/sh", runCmd, "exec sh", ""].join("\n"), {
|
|
333
|
+
encoding: "utf8",
|
|
334
|
+
mode: 448
|
|
335
|
+
});
|
|
309
336
|
chmodSync(scriptPath, 448);
|
|
310
337
|
const scriptArg = quoteShellArg(scriptPath);
|
|
311
338
|
return `x-terminal-emulator -e sh ${scriptArg} || gnome-terminal -- sh ${scriptArg} || xterm -e sh ${scriptArg}`;
|
|
@@ -355,21 +382,20 @@ function getSupportedApps() {
|
|
|
355
382
|
}
|
|
356
383
|
|
|
357
384
|
// src/ui/api.ts
|
|
358
|
-
init_config();
|
|
359
385
|
import { exec } from "child_process";
|
|
360
386
|
import { promisify } from "util";
|
|
361
387
|
import { existsSync as existsSync2, statSync } from "fs";
|
|
362
388
|
import { randomUUID } from "crypto";
|
|
363
389
|
|
|
364
390
|
// src/ui/server-control.ts
|
|
365
|
-
init_config();
|
|
366
391
|
var running = null;
|
|
367
392
|
var startInFlight = null;
|
|
368
393
|
var SAVED_PASSWORD_CACHE_TTL_MS = 3e4;
|
|
369
394
|
var hasSavedPasswordCache = null;
|
|
370
395
|
async function hasSavedPasswordCached() {
|
|
371
396
|
const now = Date.now();
|
|
372
|
-
if (hasSavedPasswordCache && hasSavedPasswordCache.expiresAt > now)
|
|
397
|
+
if (hasSavedPasswordCache && hasSavedPasswordCache.expiresAt > now)
|
|
398
|
+
return hasSavedPasswordCache.value;
|
|
373
399
|
const value = Boolean(await getSavedServerPassword());
|
|
374
400
|
hasSavedPasswordCache = { value, expiresAt: now + SAVED_PASSWORD_CACHE_TTL_MS };
|
|
375
401
|
return value;
|
|
@@ -384,9 +410,12 @@ function buildModelRows(models, gateway) {
|
|
|
384
410
|
}
|
|
385
411
|
const rows = [];
|
|
386
412
|
for (const [providerLabel, groupModels] of groups) {
|
|
387
|
-
for (const row of buildDedupedModelRows(groupModels, gateway))
|
|
413
|
+
for (const row of buildDedupedModelRows(groupModels, gateway))
|
|
414
|
+
rows.push({ providerLabel, ...row });
|
|
388
415
|
}
|
|
389
|
-
return rows.sort(
|
|
416
|
+
return rows.sort(
|
|
417
|
+
(a, b) => a.providerLabel.localeCompare(b.providerLabel) || a.name.localeCompare(b.name)
|
|
418
|
+
);
|
|
390
419
|
}
|
|
391
420
|
async function buildSavedConfig() {
|
|
392
421
|
return {
|
|
@@ -416,11 +445,13 @@ async function getServerStatus() {
|
|
|
416
445
|
models: modelRows
|
|
417
446
|
};
|
|
418
447
|
if (config.listenMode === "network") {
|
|
419
|
-
payload.networkUrls = getLocalIps().map(
|
|
420
|
-
name,
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
448
|
+
payload.networkUrls = getLocalIps().map(
|
|
449
|
+
({ name, address }) => ({
|
|
450
|
+
name,
|
|
451
|
+
anthropicUrl: `http://${address}:${handle.port}/anthropic`,
|
|
452
|
+
openaiUrl: `http://${address}:${handle.port}/openai/v1`
|
|
453
|
+
})
|
|
454
|
+
);
|
|
424
455
|
payload.apiKey = serverPassword ?? void 0;
|
|
425
456
|
} else {
|
|
426
457
|
payload.apiKey = "any non-empty value";
|
|
@@ -428,7 +459,8 @@ async function getServerStatus() {
|
|
|
428
459
|
return payload;
|
|
429
460
|
}
|
|
430
461
|
function startGatewayServer(req) {
|
|
431
|
-
if (running)
|
|
462
|
+
if (running)
|
|
463
|
+
return Promise.resolve({ ok: false, error: "Server is already running. Stop it first." });
|
|
432
464
|
if (startInFlight) return startInFlight;
|
|
433
465
|
startInFlight = doStartGatewayServer(req).finally(() => {
|
|
434
466
|
startInFlight = null;
|
|
@@ -441,7 +473,10 @@ async function doStartGatewayServer(req) {
|
|
|
441
473
|
}
|
|
442
474
|
const apiKey = await resolveServerUpstreamApiKey();
|
|
443
475
|
if (!apiKey) {
|
|
444
|
-
return {
|
|
476
|
+
return {
|
|
477
|
+
ok: false,
|
|
478
|
+
error: "No providers configured. Add a provider in Providers & Keys first."
|
|
479
|
+
};
|
|
445
480
|
}
|
|
446
481
|
let serverPassword = null;
|
|
447
482
|
if (req.listenMode === "network") {
|
|
@@ -463,13 +498,19 @@ async function doStartGatewayServer(req) {
|
|
|
463
498
|
try {
|
|
464
499
|
models = await loadServerModels();
|
|
465
500
|
} catch (err) {
|
|
466
|
-
return {
|
|
501
|
+
return {
|
|
502
|
+
ok: false,
|
|
503
|
+
error: `Failed to load models: ${err instanceof Error ? err.message : String(err)}`
|
|
504
|
+
};
|
|
467
505
|
}
|
|
468
506
|
if (req.exposedProviders) models = filterServerModelsByProviders(models, req.exposedProviders);
|
|
469
507
|
if (req.favoritesOnly) {
|
|
470
508
|
const favorites = loadPreferences().favoriteModels ?? [];
|
|
471
509
|
if (favorites.length === 0) {
|
|
472
|
-
return {
|
|
510
|
+
return {
|
|
511
|
+
ok: false,
|
|
512
|
+
error: "No favorite models configured. Add favorites in the Favorites tab first."
|
|
513
|
+
};
|
|
473
514
|
}
|
|
474
515
|
models = filterServerModelsByFavorites(models, favorites).slice(0, MAX_MODEL_CATALOG);
|
|
475
516
|
if (models.length === 0) {
|
|
@@ -483,7 +524,10 @@ async function doStartGatewayServer(req) {
|
|
|
483
524
|
}
|
|
484
525
|
}
|
|
485
526
|
if (models.length === 0) {
|
|
486
|
-
return {
|
|
527
|
+
return {
|
|
528
|
+
ok: false,
|
|
529
|
+
error: "No models to expose. Add providers or adjust the exposed-provider filter."
|
|
530
|
+
};
|
|
487
531
|
}
|
|
488
532
|
setServerFavoritesOnly(req.favoritesOnly);
|
|
489
533
|
setServerFreeModelsOnly(req.freeModelsOnly);
|
|
@@ -650,7 +694,8 @@ async function handlePostConfig(req, res) {
|
|
|
650
694
|
const body = JSON.parse(await readBody(req));
|
|
651
695
|
const update = {};
|
|
652
696
|
if (Array.isArray(body.favoriteModels)) update.favoriteModels = body.favoriteModels;
|
|
653
|
-
if (Array.isArray(body.antigravityCliFavoriteModels))
|
|
697
|
+
if (Array.isArray(body.antigravityCliFavoriteModels))
|
|
698
|
+
update.antigravityCliFavoriteModels = body.antigravityCliFavoriteModels;
|
|
654
699
|
if (Object.keys(update).length > 0) savePreferences(update);
|
|
655
700
|
sendJson(res, 200, { ok: true });
|
|
656
701
|
} catch (err) {
|
|
@@ -671,7 +716,9 @@ async function handleGetModels(res) {
|
|
|
671
716
|
try {
|
|
672
717
|
const catalog = await fetchModelsWithTimeout();
|
|
673
718
|
const registry = loadRegistry();
|
|
674
|
-
const rawCountById = new Map(
|
|
719
|
+
const rawCountById = new Map(
|
|
720
|
+
registry.providers.map((p2) => [p2.id, p2.modelsCache?.models.length ?? 0])
|
|
721
|
+
);
|
|
675
722
|
const providers = catalog.map((p2) => ({
|
|
676
723
|
id: p2.id,
|
|
677
724
|
name: p2.name,
|
|
@@ -704,7 +751,11 @@ async function handleGetModels(res) {
|
|
|
704
751
|
providers.push({
|
|
705
752
|
id: rp.id,
|
|
706
753
|
name: rp.name,
|
|
707
|
-
favoriteName: favoriteProviderDisplayName({
|
|
754
|
+
favoriteName: favoriteProviderDisplayName({
|
|
755
|
+
id: rp.id,
|
|
756
|
+
name: rp.name,
|
|
757
|
+
authType: rp.authType
|
|
758
|
+
}),
|
|
708
759
|
hasKey: true,
|
|
709
760
|
freeAccess: false,
|
|
710
761
|
authType: "oauth",
|
|
@@ -1030,8 +1081,20 @@ async function handlePostKeys(req, res) {
|
|
|
1030
1081
|
}
|
|
1031
1082
|
}
|
|
1032
1083
|
var CUSTOM_TEMPLATES = [
|
|
1033
|
-
{
|
|
1034
|
-
|
|
1084
|
+
{
|
|
1085
|
+
id: "__custom_openai__",
|
|
1086
|
+
name: "Custom OpenAI-compatible",
|
|
1087
|
+
signupUrl: null,
|
|
1088
|
+
authType: "api",
|
|
1089
|
+
custom: true
|
|
1090
|
+
},
|
|
1091
|
+
{
|
|
1092
|
+
id: "__custom_anthropic__",
|
|
1093
|
+
name: "Custom Anthropic-compatible",
|
|
1094
|
+
signupUrl: null,
|
|
1095
|
+
authType: "api",
|
|
1096
|
+
custom: true
|
|
1097
|
+
}
|
|
1035
1098
|
];
|
|
1036
1099
|
function handleGetTemplates(res) {
|
|
1037
1100
|
const registry = loadRegistry();
|
|
@@ -1040,6 +1103,7 @@ function handleGetTemplates(res) {
|
|
|
1040
1103
|
id: t.id,
|
|
1041
1104
|
name: t.name,
|
|
1042
1105
|
signupUrl: t.signupUrl ?? null,
|
|
1106
|
+
signupNote: t.signupNote ?? null,
|
|
1043
1107
|
authType: t.authType,
|
|
1044
1108
|
anonymousFreeModels: t.anonymousFreeModels ?? false,
|
|
1045
1109
|
urlPrompt: t.urlPrompt ?? null,
|
|
@@ -1098,7 +1162,7 @@ async function handleAddProvider(req, res) {
|
|
|
1098
1162
|
sendJson(res, 400, { error: "templateId required" });
|
|
1099
1163
|
return;
|
|
1100
1164
|
}
|
|
1101
|
-
const { listSupportedTemplates: listSupportedTemplates2 } = await import("./provider-templates-
|
|
1165
|
+
const { listSupportedTemplates: listSupportedTemplates2 } = await import("./provider-templates-CRQJII3Z.js");
|
|
1102
1166
|
const template = listSupportedTemplates2().find((t) => t.id === templateId);
|
|
1103
1167
|
if (!template) {
|
|
1104
1168
|
sendJson(res, 404, { error: `Template '${templateId}' not found` });
|
|
@@ -1118,13 +1182,17 @@ async function handleAddProvider(req, res) {
|
|
|
1118
1182
|
return;
|
|
1119
1183
|
}
|
|
1120
1184
|
const usesHttp = /^http:\/\//i.test(baseUrlOverride);
|
|
1121
|
-
const valid = await validateCustomEndpointUrl(baseUrlOverride, {
|
|
1185
|
+
const valid = await validateCustomEndpointUrl(baseUrlOverride, {
|
|
1186
|
+
allowInsecureLocal: usesHttp
|
|
1187
|
+
});
|
|
1122
1188
|
if (!valid.ok) {
|
|
1123
1189
|
sendJson(res, 400, { error: valid.error ?? "Invalid URL", hint: valid.hint });
|
|
1124
1190
|
return;
|
|
1125
1191
|
}
|
|
1126
1192
|
}
|
|
1127
|
-
const result = await addProviderFromTemplate(template, keyText, {
|
|
1193
|
+
const result = await addProviderFromTemplate(template, keyText, {
|
|
1194
|
+
baseUrl: baseUrlOverride
|
|
1195
|
+
});
|
|
1128
1196
|
if (result.added) {
|
|
1129
1197
|
sendJson(res, 200, { ok: true, name: template.name, count: result.modelCount ?? 0 });
|
|
1130
1198
|
} else {
|
|
@@ -1152,7 +1220,11 @@ async function handleRefreshAll(res) {
|
|
|
1152
1220
|
reason: r.reason
|
|
1153
1221
|
};
|
|
1154
1222
|
});
|
|
1155
|
-
sendJson(res, 200, {
|
|
1223
|
+
sendJson(res, 200, {
|
|
1224
|
+
ok: true,
|
|
1225
|
+
providers: summary,
|
|
1226
|
+
total: summary.reduce((n, p2) => n + p2.count, 0)
|
|
1227
|
+
});
|
|
1156
1228
|
} catch (err) {
|
|
1157
1229
|
sendJson(res, 500, { ok: false, error: String(err) });
|
|
1158
1230
|
}
|
|
@@ -1215,14 +1287,21 @@ async function handleOAuthStart(req, res) {
|
|
|
1215
1287
|
const body = JSON.parse(await readBody(req));
|
|
1216
1288
|
const { providerId } = body;
|
|
1217
1289
|
if (!providerId || !NATIVE_OAUTH_PROVIDER_IDS.has(providerId)) {
|
|
1218
|
-
sendJson(res, 400, {
|
|
1290
|
+
sendJson(res, 400, {
|
|
1291
|
+
error: `providerId must be one of: ${[...NATIVE_OAUTH_PROVIDER_IDS].join(", ")}`
|
|
1292
|
+
});
|
|
1219
1293
|
return;
|
|
1220
1294
|
}
|
|
1221
1295
|
const sessionId = randomUUID();
|
|
1222
1296
|
if (providerId === "xai-oauth") {
|
|
1223
1297
|
const device2 = await requestXaiDeviceCode();
|
|
1224
1298
|
const url2 = device2.verification_uri_complete ?? device2.verification_uri;
|
|
1225
|
-
const session2 = {
|
|
1299
|
+
const session2 = {
|
|
1300
|
+
status: "pending",
|
|
1301
|
+
url: url2,
|
|
1302
|
+
userCode: device2.user_code,
|
|
1303
|
+
providerId
|
|
1304
|
+
};
|
|
1226
1305
|
oauthSessions.set(sessionId, session2);
|
|
1227
1306
|
pollXaiDeviceCodeToken(device2).then(async (tokens) => {
|
|
1228
1307
|
await saveNativeOAuthCredential(providerId, tokens);
|
|
@@ -1237,7 +1316,12 @@ async function handleOAuthStart(req, res) {
|
|
|
1237
1316
|
if (providerId === "github-copilot") {
|
|
1238
1317
|
const device2 = await requestGithubDeviceCode();
|
|
1239
1318
|
const url2 = device2.verification_uri;
|
|
1240
|
-
const session2 = {
|
|
1319
|
+
const session2 = {
|
|
1320
|
+
status: "pending",
|
|
1321
|
+
url: url2,
|
|
1322
|
+
userCode: device2.user_code,
|
|
1323
|
+
providerId
|
|
1324
|
+
};
|
|
1241
1325
|
oauthSessions.set(sessionId, session2);
|
|
1242
1326
|
pollGithubDeviceCodeToken(device2).then(async (tokens) => {
|
|
1243
1327
|
await saveNativeOAuthCredential(providerId, tokens);
|
|
@@ -1405,7 +1489,9 @@ async function handleLaunchApp(req, res, opts) {
|
|
|
1405
1489
|
return;
|
|
1406
1490
|
}
|
|
1407
1491
|
if (!favorites && (providerId || modelId) && (!providerId || !modelId)) {
|
|
1408
|
-
sendJson(res, 400, {
|
|
1492
|
+
sendJson(res, 400, {
|
|
1493
|
+
error: "Both providerId and modelId are required to launch a specific anygate model."
|
|
1494
|
+
});
|
|
1409
1495
|
return;
|
|
1410
1496
|
}
|
|
1411
1497
|
const fullCatalog = Boolean(favoritesCatalog);
|
|
@@ -1464,7 +1550,9 @@ async function handleSetAppPath(req, res) {
|
|
|
1464
1550
|
return;
|
|
1465
1551
|
}
|
|
1466
1552
|
if (path !== null && (typeof path !== "string" || !path.trim())) {
|
|
1467
|
-
sendJson(res, 400, {
|
|
1553
|
+
sendJson(res, 400, {
|
|
1554
|
+
error: "path must be a non-empty string, or null to clear the override."
|
|
1555
|
+
});
|
|
1468
1556
|
return;
|
|
1469
1557
|
}
|
|
1470
1558
|
const trimmed = typeof path === "string" ? path.trim() : null;
|
|
@@ -1595,12 +1683,16 @@ async function handleBrowseFolder(res) {
|
|
|
1595
1683
|
const { stdout } = await execAsync(`powershell -NoProfile -Sta -EncodedCommand ${encoded}`);
|
|
1596
1684
|
resultPath = stdout.trim();
|
|
1597
1685
|
} catch (err) {
|
|
1598
|
-
sendJson(res, 500, {
|
|
1686
|
+
sendJson(res, 500, {
|
|
1687
|
+
error: `Failed to open folder picker: ${err instanceof Error ? err.message : String(err)}`
|
|
1688
|
+
});
|
|
1599
1689
|
return;
|
|
1600
1690
|
}
|
|
1601
1691
|
} else {
|
|
1602
1692
|
try {
|
|
1603
|
-
const { stdout } = await execAsync(
|
|
1693
|
+
const { stdout } = await execAsync(
|
|
1694
|
+
'zenity --file-selection --directory --title="Select launch folder"'
|
|
1695
|
+
);
|
|
1604
1696
|
resultPath = stdout.trim();
|
|
1605
1697
|
} catch {
|
|
1606
1698
|
try {
|
|
@@ -1679,7 +1771,10 @@ function checkExistingServer() {
|
|
|
1679
1771
|
let processExists = false;
|
|
1680
1772
|
if (isWindows2) {
|
|
1681
1773
|
try {
|
|
1682
|
-
const output = execSync(`tasklist /FI "PID eq ${pid}"`, {
|
|
1774
|
+
const output = execSync(`tasklist /FI "PID eq ${pid}"`, {
|
|
1775
|
+
encoding: "utf8",
|
|
1776
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
1777
|
+
});
|
|
1683
1778
|
processExists = output.includes(String(pid));
|
|
1684
1779
|
} catch {
|
|
1685
1780
|
processExists = false;
|
|
@@ -1796,10 +1891,12 @@ async function runUiCommand(opts = {}) {
|
|
|
1796
1891
|
process.on("SIGTERM", () => {
|
|
1797
1892
|
void handleSignal("SIGTERM");
|
|
1798
1893
|
});
|
|
1799
|
-
console.log(
|
|
1894
|
+
console.log(
|
|
1895
|
+
`
|
|
1800
1896
|
${pc.bold("anygate UI")} ${pc.cyan(url)}
|
|
1801
1897
|
${pc.dim("Press Ctrl+C to stop")}
|
|
1802
|
-
`
|
|
1898
|
+
`
|
|
1899
|
+
);
|
|
1803
1900
|
if (traceLogPath) {
|
|
1804
1901
|
console.log(` ${pc.dim(`Trace log: ${traceLogPath}`)}
|
|
1805
1902
|
`);
|
|
@@ -1822,4 +1919,4 @@ export {
|
|
|
1822
1919
|
resolveUiShutdownDecision,
|
|
1823
1920
|
runUiCommand
|
|
1824
1921
|
};
|
|
1825
|
-
//# sourceMappingURL=command-
|
|
1922
|
+
//# sourceMappingURL=command-PFFQI5YC.js.map
|