anygate 0.5.7 → 0.5.9

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 (61) hide show
  1. package/README.md +2 -2
  2. package/dist/chunk-6AFYEDSU.js +6934 -0
  3. package/dist/chunk-6AFYEDSU.js.map +1 -0
  4. package/dist/chunk-72WNE2IK.js +43 -0
  5. package/dist/chunk-P36O5B7N.js +168 -0
  6. package/dist/chunk-P36O5B7N.js.map +1 -0
  7. package/dist/{chunk-BCPX3QLK.js → chunk-PJ3L2TW7.js} +6810 -6628
  8. package/dist/chunk-PJ3L2TW7.js.map +1 -0
  9. package/dist/cli.js +11456 -11079
  10. package/dist/cli.js.map +1 -1
  11. package/dist/{command-E7O6ZQWJ.js → command-5BWYQP5G.js} +333 -19
  12. package/dist/command-5BWYQP5G.js.map +1 -0
  13. package/dist/constants-5RN2WJSS.js +29 -0
  14. package/dist/constants-5RN2WJSS.js.map +1 -0
  15. package/dist/provider-templates-MNJZTG3Z.js +25 -0
  16. package/dist/provider-templates-MNJZTG3Z.js.map +1 -0
  17. package/dist/registry/data/providers/go.json +10 -0
  18. package/dist/registry/data/providers/zen.json +10 -0
  19. package/dist/registry/data/templates/anthropic.json +13 -0
  20. package/dist/registry/data/templates/antigravity.json +15 -0
  21. package/dist/registry/data/templates/azure.json +11 -0
  22. package/dist/registry/data/templates/bedrock.json +11 -0
  23. package/dist/registry/data/templates/cerebras.json +13 -0
  24. package/dist/registry/data/templates/claude-code.json +15 -0
  25. package/dist/registry/data/templates/cohere.json +10 -0
  26. package/dist/registry/data/templates/deepinfra.json +13 -0
  27. package/dist/registry/data/templates/deepseek.json +13 -0
  28. package/dist/registry/data/templates/fireworks.json +13 -0
  29. package/dist/registry/data/templates/github-copilot.json +16 -0
  30. package/dist/registry/data/templates/go.json +13 -0
  31. package/dist/registry/data/templates/groq.json +13 -0
  32. package/dist/registry/data/templates/kilo.json +15 -0
  33. package/dist/registry/data/templates/lmstudio.json +14 -0
  34. package/dist/registry/data/templates/mistral.json +13 -0
  35. package/dist/registry/data/templates/nvidia.json +13 -0
  36. package/dist/registry/data/templates/ollama.json +14 -0
  37. package/dist/registry/data/templates/openai-oauth.json +13 -0
  38. package/dist/registry/data/templates/opencode-cloud.json +13 -0
  39. package/dist/registry/data/templates/openrouter.json +13 -0
  40. package/dist/registry/data/templates/ovh.json +13 -0
  41. package/dist/registry/data/templates/perplexity.json +13 -0
  42. package/dist/registry/data/templates/sambanova.json +12 -0
  43. package/dist/registry/data/templates/scaleway.json +13 -0
  44. package/dist/registry/data/templates/togetherai.json +13 -0
  45. package/dist/registry/data/templates/venice.json +13 -0
  46. package/dist/registry/data/templates/vertex.json +11 -0
  47. package/dist/registry/data/templates/xai-oauth.json +13 -0
  48. package/dist/registry/data/templates/xai.json +13 -0
  49. package/dist/registry/data/templates/zen.json +13 -0
  50. package/dist/ui/dist/assets/index-DWAOH_B3.css +1 -0
  51. package/dist/ui/dist/assets/index-gjYfrAXg.js +6 -0
  52. package/dist/ui/dist/index.html +2 -2
  53. package/package.json +3 -3
  54. package/dist/chunk-BCPX3QLK.js.map +0 -1
  55. package/dist/chunk-VKROC37K.js +0 -390
  56. package/dist/chunk-VKROC37K.js.map +0 -1
  57. package/dist/command-E7O6ZQWJ.js.map +0 -1
  58. package/dist/provider-templates-TWR5XSYI.js +0 -18
  59. package/dist/ui/dist/assets/index-3sdSv_1I.js +0 -5
  60. package/dist/ui/dist/assets/index-C4xd3r4v.css +0 -1
  61. /package/dist/{provider-templates-TWR5XSYI.js.map → chunk-72WNE2IK.js.map} +0 -0
@@ -1,7 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- BACKENDS,
4
- MAX_MODEL_CATALOG,
5
3
  addCustomEndpointProvider,
6
4
  addProviderFromTemplate,
7
5
  aggregateAnalytics,
@@ -31,6 +29,8 @@ import {
31
29
  getServerMaskGatewayIds,
32
30
  getUiDebugLogPath,
33
31
  guiCallbackRedirectUri,
32
+ init_config,
33
+ init_paths,
34
34
  loadPreferences,
35
35
  loadRegistry,
36
36
  loadServerModels,
@@ -66,15 +66,22 @@ import {
66
66
  summarizeServerProviders,
67
67
  validateCustomEndpointUrl,
68
68
  writeSecureLogLine
69
- } from "./chunk-BCPX3QLK.js";
69
+ } from "./chunk-PJ3L2TW7.js";
70
+ import {
71
+ BACKENDS,
72
+ MAX_MODEL_CATALOG
73
+ } from "./chunk-P36O5B7N.js";
70
74
  import {
71
75
  getTemplateById,
72
- listAddableTemplates,
76
+ listSupportedTemplates,
73
77
  listVisibleOAuthTemplates
74
- } from "./chunk-VKROC37K.js";
78
+ } from "./chunk-6AFYEDSU.js";
79
+ import "./chunk-72WNE2IK.js";
75
80
 
76
81
  // src/ui/command.ts
82
+ init_paths();
77
83
  import { createServer } from "http";
84
+ import { execSync } from "child_process";
78
85
  import { readFileSync, readdirSync, writeFileSync as writeFileSync2, unlinkSync, existsSync as existsSync3, mkdirSync } from "fs";
79
86
  import { join as join2 } from "path";
80
87
  import { fileURLToPath } from "url";
@@ -82,7 +89,8 @@ import { dirname } from "path";
82
89
  import pc from "picocolors";
83
90
  import * as p from "@clack/prompts";
84
91
 
85
- // src/agents/shared/native-launcher.ts
92
+ // src/apps/shared/native-launcher.ts
93
+ init_config();
86
94
  import { chmodSync, existsSync, mkdtempSync, writeFileSync } from "fs";
87
95
  import { homedir } from "os";
88
96
  import { tmpdir } from "os";
@@ -347,12 +355,14 @@ function getSupportedApps() {
347
355
  }
348
356
 
349
357
  // src/ui/api.ts
358
+ init_config();
350
359
  import { exec } from "child_process";
351
360
  import { promisify } from "util";
352
361
  import { existsSync as existsSync2, statSync } from "fs";
353
362
  import { randomUUID } from "crypto";
354
363
 
355
364
  // src/ui/server-control.ts
365
+ init_config();
356
366
  var running = null;
357
367
  var startInFlight = null;
358
368
  var SAVED_PASSWORD_CACHE_TTL_MS = 3e4;
@@ -581,6 +591,8 @@ function handleUiApiRequest(req, res, opts = {}) {
581
591
  handlePostConfig(req, res);
582
592
  } else if (url === "/api/models" && req.method === "GET") {
583
593
  handleGetModels(res);
594
+ } else if (url === "/api/models/test" && req.method === "POST") {
595
+ handleTestModel(req, res);
584
596
  } else if (url === "/api/keys" && req.method === "POST") {
585
597
  handlePostKeys(req, res);
586
598
  } else if (url === "/api/providers/refresh" && req.method === "POST") {
@@ -595,11 +607,11 @@ function handleUiApiRequest(req, res, opts = {}) {
595
607
  handleAddCustomProvider(req, res);
596
608
  } else if (url === "/api/providers/delete" && req.method === "POST") {
597
609
  handleDeleteProvider(req, res);
598
- } else if (url === "/api/providers/oauth/start" && req.method === "POST") {
610
+ } else if (url === "/api/providers/auth/start" && req.method === "POST") {
599
611
  handleOAuthStart(req, res);
600
- } else if (url.startsWith("/api/providers/oauth/status") && req.method === "GET") {
612
+ } else if (url.startsWith("/api/providers/auth/status") && req.method === "GET") {
601
613
  handleOAuthStatus(req, res);
602
- } else if (url.startsWith("/oauth/callback") && req.method === "GET") {
614
+ } else if (url.startsWith("/auth/callback") && req.method === "GET") {
603
615
  handleOAuthCallback(req, res);
604
616
  } else if (url === "/api/apps" && req.method === "GET") {
605
617
  handleGetApps(res);
@@ -705,6 +717,294 @@ async function handleGetModels(res) {
705
717
  sendCatalogFetchError(res, err, "Model fetch");
706
718
  }
707
719
  }
720
+ var TEST_TIMEOUT_MS = 3e4;
721
+ var TEST_DEFAULT_PROMPT = "Reply with a single word: pong";
722
+ var TEST_MAX_SAMPLE = 400;
723
+ async function handleTestModel(req, res) {
724
+ let body;
725
+ try {
726
+ body = JSON.parse(await readBody(req));
727
+ } catch {
728
+ sendJson(res, 400, { error: "Invalid JSON body" });
729
+ return;
730
+ }
731
+ const { providerId, modelId, prompt } = body;
732
+ if (!providerId || typeof providerId !== "string") {
733
+ sendJson(res, 400, { error: "providerId required" });
734
+ return;
735
+ }
736
+ if (!modelId || typeof modelId !== "string") {
737
+ sendJson(res, 400, { error: "modelId required" });
738
+ return;
739
+ }
740
+ try {
741
+ const catalog = await fetchModelsWithTimeout();
742
+ const provider = catalog.find((p2) => p2.id === providerId);
743
+ if (!provider) {
744
+ sendJson(res, 200, {
745
+ ok: false,
746
+ providerId,
747
+ modelId,
748
+ format: "unknown",
749
+ connectMs: null,
750
+ ttftMs: null,
751
+ totalMs: null,
752
+ tokens: 0,
753
+ tokensPerSec: null,
754
+ streamStability: "n/a",
755
+ sample: "",
756
+ error: `Provider "${providerId}" not found in catalog`,
757
+ errorHint: "Connect or enable the provider in Providers & Keys first."
758
+ });
759
+ return;
760
+ }
761
+ const model = provider.models.find((m) => m.id === modelId);
762
+ if (!model) {
763
+ sendJson(res, 200, {
764
+ ok: false,
765
+ providerId,
766
+ modelId,
767
+ format: "unknown",
768
+ connectMs: null,
769
+ ttftMs: null,
770
+ totalMs: null,
771
+ tokens: 0,
772
+ tokensPerSec: null,
773
+ streamStability: "n/a",
774
+ sample: "",
775
+ error: `Model "${modelId}" not found on provider "${providerId}"`,
776
+ errorHint: "Pick a model that belongs to the selected provider."
777
+ });
778
+ return;
779
+ }
780
+ const registry = loadRegistry();
781
+ const registryProvider = registry.providers.find((p2) => p2.id === providerId);
782
+ let apiKey = provider.apiKey ?? null;
783
+ if (registryProvider?.authRef) {
784
+ apiKey = await resolveProviderCredential(providerId, registryProvider.authRef);
785
+ }
786
+ const format = model.modelFormat === "anthropic" || model.modelFormat === "openai" ? model.modelFormat : "unsupported";
787
+ const upstreamModelId = model.upstreamModelId || model.id;
788
+ const userPrompt = typeof prompt === "string" && prompt.trim() ? prompt : TEST_DEFAULT_PROMPT;
789
+ let upstreamUrl;
790
+ const headers = { "Content-Type": "application/json" };
791
+ let requestBody;
792
+ if (model.modelFormat === "anthropic") {
793
+ const base = (model.baseUrl || "").replace(/\/v1\/?$/, "");
794
+ if (!base) {
795
+ sendJson(res, 200, failNoEndpoint(providerId, modelId, format));
796
+ return;
797
+ }
798
+ upstreamUrl = `${base.replace(/\/$/, "")}/v1/messages`;
799
+ headers["x-api-key"] = apiKey ?? "";
800
+ headers["anthropic-version"] = "2023-06-01";
801
+ requestBody = {
802
+ model: upstreamModelId,
803
+ max_tokens: 256,
804
+ stream: true,
805
+ messages: [{ role: "user", content: userPrompt }]
806
+ };
807
+ } else if (model.modelFormat === "openai") {
808
+ const completionsUrl = model.completionsUrl || (model.apiBaseUrl ? `${model.apiBaseUrl.replace(/\/$/, "")}/chat/completions` : "");
809
+ if (!completionsUrl) {
810
+ sendJson(res, 200, failNoEndpoint(providerId, modelId, format));
811
+ return;
812
+ }
813
+ upstreamUrl = completionsUrl;
814
+ headers["Authorization"] = `Bearer ${apiKey ?? ""}`;
815
+ requestBody = {
816
+ model: upstreamModelId,
817
+ stream: true,
818
+ messages: [{ role: "user", content: userPrompt }]
819
+ };
820
+ } else {
821
+ sendJson(res, 200, {
822
+ ok: false,
823
+ providerId,
824
+ modelId,
825
+ format: "unsupported",
826
+ connectMs: null,
827
+ ttftMs: null,
828
+ totalMs: null,
829
+ tokens: 0,
830
+ tokensPerSec: null,
831
+ streamStability: "n/a",
832
+ sample: "",
833
+ error: `Model format "${model.modelFormat}" is not directly testable from the UI`,
834
+ errorHint: "This provider routes through anygate's SDK adapter. Use the CLI or Server gateway to exercise it."
835
+ });
836
+ return;
837
+ }
838
+ for (const [k, v] of Object.entries(provider.headers ?? {})) {
839
+ if (!(k.toLowerCase() in headers)) headers[k] = v;
840
+ }
841
+ const controller = new AbortController();
842
+ const timeout = setTimeout(() => controller.abort(), TEST_TIMEOUT_MS);
843
+ const t0 = performance.now();
844
+ let connectMs = null;
845
+ let ttftMs = null;
846
+ let totalMs = null;
847
+ let tokens = 0;
848
+ const gaps = [];
849
+ let lastChunkT = null;
850
+ let sample = "";
851
+ try {
852
+ const upstream = await fetch(upstreamUrl, {
853
+ method: "POST",
854
+ headers,
855
+ body: JSON.stringify(requestBody),
856
+ signal: controller.signal
857
+ });
858
+ connectMs = Math.round(performance.now() - t0);
859
+ if (!upstream.ok || !upstream.body) {
860
+ const snippet = upstream.body ? (await upstream.text()).slice(0, 240) : "";
861
+ clearTimeout(timeout);
862
+ sendJson(res, 200, {
863
+ ok: false,
864
+ providerId,
865
+ modelId,
866
+ format,
867
+ connectMs,
868
+ ttftMs: null,
869
+ totalMs: Math.round(performance.now() - t0),
870
+ tokens: 0,
871
+ tokensPerSec: null,
872
+ streamStability: "n/a",
873
+ sample: snippet,
874
+ error: `Upstream responded ${upstream.status} ${upstream.statusText}`,
875
+ errorHint: upstream.status === 401 ? "API key missing or rejected \u2014 add/refresh the key in Providers & Keys." : upstream.status === 404 ? "Endpoint not found \u2014 the provider base URL may be wrong." : "Check the provider key and base URL."
876
+ });
877
+ return;
878
+ }
879
+ const reader = upstream.body.getReader();
880
+ const decoder = new TextDecoder();
881
+ let buffer = "";
882
+ while (true) {
883
+ const { done, value } = await reader.read();
884
+ if (done) break;
885
+ const chunk = decoder.decode(value, { stream: true });
886
+ if (!chunk) continue;
887
+ const now = performance.now();
888
+ const delta = now - t0;
889
+ if (ttftMs === null) ttftMs = Math.round(delta);
890
+ if (lastChunkT !== null) gaps.push(now - lastChunkT);
891
+ lastChunkT = now;
892
+ buffer += chunk;
893
+ if (model.modelFormat === "anthropic") {
894
+ const lines = buffer.split("\n");
895
+ buffer = lines.pop() ?? "";
896
+ for (const line of lines) {
897
+ const trimmed = line.trim();
898
+ if (!trimmed.startsWith("data:")) continue;
899
+ const data = trimmed.slice(5).trim();
900
+ if (data === "[DONE]") continue;
901
+ try {
902
+ const evt = JSON.parse(data);
903
+ if (evt.type === "content_block_delta" && evt.delta?.type === "text_delta") {
904
+ tokens++;
905
+ if (sample.length < TEST_MAX_SAMPLE) sample += evt.delta.text;
906
+ }
907
+ } catch {
908
+ }
909
+ }
910
+ } else {
911
+ const lines = buffer.split("\n");
912
+ buffer = lines.pop() ?? "";
913
+ for (const line of lines) {
914
+ const trimmed = line.trim();
915
+ if (!trimmed.startsWith("data:")) continue;
916
+ const data = trimmed.slice(5).trim();
917
+ if (data === "[DONE]") continue;
918
+ try {
919
+ const evt = JSON.parse(data);
920
+ const piece = evt.choices?.[0]?.delta?.content;
921
+ if (typeof piece === "string" && piece) {
922
+ tokens++;
923
+ if (sample.length < TEST_MAX_SAMPLE) sample += piece;
924
+ }
925
+ } catch {
926
+ }
927
+ }
928
+ }
929
+ }
930
+ totalMs = Math.round(performance.now() - t0);
931
+ clearTimeout(timeout);
932
+ const tokensPerSec = tokens > 0 && ttftMs !== null ? Math.round(tokens / (totalMs - ttftMs + 1) * 1e3 * 10) / 10 : null;
933
+ const streamStability = computeStability(gaps);
934
+ sendJson(res, 200, {
935
+ ok: true,
936
+ providerId,
937
+ modelId,
938
+ format,
939
+ connectMs,
940
+ ttftMs,
941
+ totalMs,
942
+ tokens,
943
+ tokensPerSec,
944
+ streamStability,
945
+ sample: sample.trim()
946
+ });
947
+ } catch (fetchErr) {
948
+ clearTimeout(timeout);
949
+ const aborted = fetchErr instanceof Error && fetchErr.name === "AbortError";
950
+ sendJson(res, 200, {
951
+ ok: false,
952
+ providerId,
953
+ modelId,
954
+ format,
955
+ connectMs,
956
+ ttftMs,
957
+ totalMs: Math.round(performance.now() - t0),
958
+ tokens,
959
+ tokensPerSec: null,
960
+ streamStability: gaps.length ? computeStability(gaps) : "n/a",
961
+ sample,
962
+ error: aborted ? `Request timed out after ${TEST_TIMEOUT_MS / 1e3}s` : String(fetchErr),
963
+ errorHint: aborted ? "The endpoint did not respond in time \u2014 it may be slow, down, or the URL is unreachable." : "Network-level failure reaching the provider endpoint."
964
+ });
965
+ }
966
+ } catch (err) {
967
+ sendJson(res, 500, {
968
+ ok: false,
969
+ providerId,
970
+ modelId,
971
+ format: "unknown",
972
+ connectMs: null,
973
+ ttftMs: null,
974
+ totalMs: null,
975
+ tokens: 0,
976
+ tokensPerSec: null,
977
+ streamStability: "n/a",
978
+ sample: "",
979
+ error: String(err)
980
+ });
981
+ }
982
+ }
983
+ function failNoEndpoint(providerId, modelId, format) {
984
+ return {
985
+ ok: false,
986
+ providerId,
987
+ modelId,
988
+ format,
989
+ connectMs: null,
990
+ ttftMs: null,
991
+ totalMs: null,
992
+ tokens: 0,
993
+ tokensPerSec: null,
994
+ streamStability: "n/a",
995
+ sample: "",
996
+ error: "No usable upstream endpoint for this model",
997
+ errorHint: "The provider is missing a base URL / completions URL. Re-add or refresh it in Providers & Keys."
998
+ };
999
+ }
1000
+ function computeStability(gaps) {
1001
+ if (gaps.length < 3) return "steady";
1002
+ const mean = gaps.reduce((a, b) => a + b, 0) / gaps.length;
1003
+ if (mean === 0) return "steady";
1004
+ const variance = gaps.reduce((a, b) => a + (b - mean) ** 2, 0) / gaps.length;
1005
+ const cv = Math.sqrt(variance) / mean;
1006
+ return cv > 1.2 ? "intermittent" : "steady";
1007
+ }
708
1008
  async function handlePostKeys(req, res) {
709
1009
  try {
710
1010
  const body = JSON.parse(await readBody(req));
@@ -735,7 +1035,7 @@ var CUSTOM_TEMPLATES = [
735
1035
  function handleGetTemplates(res) {
736
1036
  const registry = loadRegistry();
737
1037
  const configured = new Set(registry.providers.map((p2) => p2.id));
738
- const apiTemplates = listAddableTemplates(configured).map((t) => ({
1038
+ const apiTemplates = listSupportedTemplates().map((t) => ({
739
1039
  id: t.id,
740
1040
  name: t.name,
741
1041
  signupUrl: t.signupUrl ?? null,
@@ -797,8 +1097,8 @@ async function handleAddProvider(req, res) {
797
1097
  sendJson(res, 400, { error: "templateId required" });
798
1098
  return;
799
1099
  }
800
- const { listSupportedTemplates } = await import("./provider-templates-TWR5XSYI.js");
801
- const template = listSupportedTemplates().find((t) => t.id === templateId);
1100
+ const { listSupportedTemplates: listSupportedTemplates2 } = await import("./provider-templates-MNJZTG3Z.js");
1101
+ const template = listSupportedTemplates2().find((t) => t.id === templateId);
802
1102
  if (!template) {
803
1103
  sendJson(res, 404, { error: `Template '${templateId}' not found` });
804
1104
  return;
@@ -1323,7 +1623,7 @@ async function handleBrowseFolder(res) {
1323
1623
 
1324
1624
  // src/ui/command.ts
1325
1625
  var __dirname = dirname(fileURLToPath(import.meta.url));
1326
- var PUBLIC_DIR = join2(__dirname, "ui", "dist");
1626
+ var PUBLIC_DIR = join2(__dirname, "app", "dist");
1327
1627
  var LOCK_FILE = join2(getAppHome(), "ui.lock");
1328
1628
  var MIME = {
1329
1629
  ".html": "text/html; charset=utf-8",
@@ -1374,15 +1674,29 @@ function checkExistingServer() {
1374
1674
  if (!existsSync3(LOCK_FILE)) return null;
1375
1675
  try {
1376
1676
  const { pid, port } = JSON.parse(readFileSync(LOCK_FILE, "utf8"));
1377
- process.kill(pid, 0);
1378
- return `http://127.0.0.1:${port}`;
1677
+ const isWindows2 = process.platform === "win32";
1678
+ let processExists = false;
1679
+ if (isWindows2) {
1680
+ try {
1681
+ const output = execSync(`tasklist /FI "PID eq ${pid}"`, { encoding: "utf8", stdio: ["pipe", "pipe", "ignore"] });
1682
+ processExists = output.includes(String(pid));
1683
+ } catch {
1684
+ processExists = false;
1685
+ }
1686
+ } else {
1687
+ process.kill(pid, 0);
1688
+ processExists = true;
1689
+ }
1690
+ if (processExists) {
1691
+ return `http://127.0.0.1:${port}`;
1692
+ }
1379
1693
  } catch {
1380
- removeLock();
1381
- return null;
1382
1694
  }
1695
+ removeLock();
1696
+ return null;
1383
1697
  }
1384
1698
  function isUiApiRoute(url) {
1385
- return url.startsWith("/api/") || url.startsWith("/oauth/callback");
1699
+ return url.startsWith("/api/") || url.startsWith("/auth/callback");
1386
1700
  }
1387
1701
  function formatUiServerLifecycleMessage(event) {
1388
1702
  if (event.type === "stopped") return "\u25C7 Server Gateway stopped";
@@ -1507,4 +1821,4 @@ export {
1507
1821
  resolveUiShutdownDecision,
1508
1822
  runUiCommand
1509
1823
  };
1510
- //# sourceMappingURL=command-E7O6ZQWJ.js.map
1824
+ //# sourceMappingURL=command-5BWYQP5G.js.map