@agent-proxy/gateway 0.12.0 → 0.12.1
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/index.js +53 -60
- package/dist/ui/index.html +2 -2
- package/package.json +9 -9
- package/schemas/gateway-config.schema.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1020,8 +1020,8 @@ function readObject(file) {
|
|
|
1020
1020
|
}
|
|
1021
1021
|
function migrateManagedDefaultPaths(config, legacyHome, nextHome) {
|
|
1022
1022
|
const result = structuredClone(config);
|
|
1023
|
-
if (result.
|
|
1024
|
-
result.
|
|
1023
|
+
if (result.modelMergeJson === path6.join(legacyHome, "models.json"))
|
|
1024
|
+
result.modelMergeJson = path6.join(nextHome, "models.json");
|
|
1025
1025
|
return result;
|
|
1026
1026
|
}
|
|
1027
1027
|
function prepareDefaultInstallMigration(paths, env = process.env, platform = process.platform, launchctlExecutor, manualCodexConfig = false) {
|
|
@@ -6005,12 +6005,12 @@ async function resolveModelMergeJson(cacheFile, bundledFile, url, refresh = fals
|
|
|
6005
6005
|
try {
|
|
6006
6006
|
source = new URL(url);
|
|
6007
6007
|
} catch {
|
|
6008
|
-
throw new Error(`Invalid
|
|
6008
|
+
throw new Error(`Invalid modelMergeJson URL: ${url}`);
|
|
6009
6009
|
}
|
|
6010
6010
|
const parts = source.pathname.split("/").filter(Boolean);
|
|
6011
6011
|
const githubRepository = ["github.com", "www.github.com"].includes(source.hostname) && parts.length === 2;
|
|
6012
6012
|
if (!["http:", "https:"].includes(source.protocol) || source.username || source.password || parts.length === 0 || !githubRepository && source.pathname.endsWith("/")) {
|
|
6013
|
-
throw new Error("
|
|
6013
|
+
throw new Error("modelMergeJson must be a GitHub repository or an HTTP(S) URL with a file name");
|
|
6014
6014
|
}
|
|
6015
6015
|
if (githubRepository) {
|
|
6016
6016
|
source.hostname = "github.com";
|
|
@@ -6020,10 +6020,10 @@ async function resolveModelMergeJson(cacheFile, bundledFile, url, refresh = fals
|
|
|
6020
6020
|
}
|
|
6021
6021
|
const response = await fetch(source, { redirect: "follow" });
|
|
6022
6022
|
if (!response.ok)
|
|
6023
|
-
throw new Error(`
|
|
6023
|
+
throw new Error(`modelMergeJson download returned HTTP ${response.status}`);
|
|
6024
6024
|
const contents = await response.text();
|
|
6025
6025
|
if (Buffer.byteLength(contents) > 16 * 1024 * 1024) {
|
|
6026
|
-
throw new Error("
|
|
6026
|
+
throw new Error("modelMergeJson download exceeds 16 MiB");
|
|
6027
6027
|
}
|
|
6028
6028
|
const stagingFile = `${cacheFile}.download`;
|
|
6029
6029
|
try {
|
|
@@ -6680,7 +6680,7 @@ function upstreamClientVersion(paths, type) {
|
|
|
6680
6680
|
return type === "cliproxy" ? resolveCodexClientVersion(paths.upstreamModelsCacheFile) : FALLBACK_CLIENT_VERSION;
|
|
6681
6681
|
}
|
|
6682
6682
|
async function loadModelOverrideRules(paths, config, refreshModelMerge) {
|
|
6683
|
-
const modelsConfigFile = await resolveModelMergeJson(paths.modelMergeFile, undefined, config.
|
|
6683
|
+
const modelsConfigFile = await resolveModelMergeJson(paths.modelMergeFile, undefined, config.modelMergeJson, refreshModelMerge);
|
|
6684
6684
|
return {
|
|
6685
6685
|
modelsConfigFile,
|
|
6686
6686
|
rules: modelsConfigFile === undefined ? compileModelOverrides(models_default, "bundled models.json") : loadModelOverrides(modelsConfigFile)
|
|
@@ -6720,6 +6720,33 @@ import { createQoderPlugin, QODER_MODEL_PATTERNS, QODER_RUNTIME_ARTIFACTS } from
|
|
|
6720
6720
|
import { createAgyPlugin, AGY_MODEL_PATTERNS, AGY_RUNTIME_ARTIFACTS } from "@agent-proxy/agy";
|
|
6721
6721
|
import { createOpencodeZenPlugin, OPENCODE_ZEN_MODEL_PATTERNS, OPENCODE_ZEN_RUNTIME_ARTIFACTS } from "@agent-proxy/opencode-zen";
|
|
6722
6722
|
|
|
6723
|
+
// src/plugin-config.ts
|
|
6724
|
+
import { validateZcodeConfig } from "@agent-proxy/zcode";
|
|
6725
|
+
import { validateCodebuddyAccount, validateCodebuddyConfig } from "@agent-proxy/codebuddy";
|
|
6726
|
+
import { validateQoderConfig } from "@agent-proxy/qoder";
|
|
6727
|
+
import { validateAgyConfig } from "@agent-proxy/agy";
|
|
6728
|
+
import { validateOpencodeZenConfig } from "@agent-proxy/opencode-zen";
|
|
6729
|
+
var validators = {
|
|
6730
|
+
zcode: validateZcodeConfig,
|
|
6731
|
+
codebuddy: validateCodebuddyConfig,
|
|
6732
|
+
qoder: validateQoderConfig,
|
|
6733
|
+
agy: validateAgyConfig,
|
|
6734
|
+
opencodeZen: validateOpencodeZenConfig
|
|
6735
|
+
};
|
|
6736
|
+
function validateConfiguredPlugins(config) {
|
|
6737
|
+
const keys = Object.keys(AGENT_DEFAULTS);
|
|
6738
|
+
for (const key of keys) {
|
|
6739
|
+
if (config[key] !== undefined && typeof config[key] !== "boolean") {
|
|
6740
|
+
throw new Error(`${key} \u5FC5\u987B\u4E3A boolean`);
|
|
6741
|
+
}
|
|
6742
|
+
}
|
|
6743
|
+
validateCodebuddyAccount(config.codebuddyAccount);
|
|
6744
|
+
for (const key of keys) {
|
|
6745
|
+
if (agentConfigEnabled(config, key))
|
|
6746
|
+
validators[key](config);
|
|
6747
|
+
}
|
|
6748
|
+
}
|
|
6749
|
+
|
|
6723
6750
|
// src/process-log.ts
|
|
6724
6751
|
import fs12 from "fs";
|
|
6725
6752
|
import path9 from "path";
|
|
@@ -6985,14 +7012,11 @@ function logRequestSummary(target, entry) {
|
|
|
6985
7012
|
}
|
|
6986
7013
|
|
|
6987
7014
|
// src/host-services.ts
|
|
6988
|
-
function agentConfigView(config) {
|
|
6989
|
-
return { ...config, prefix: configuredModelPrefix(config) };
|
|
6990
|
-
}
|
|
6991
7015
|
function createGatewayHostServices(config, processLog, runtimePaths, apiKey) {
|
|
6992
7016
|
const getPaths = () => runtimePaths ?? resolvePaths();
|
|
6993
7017
|
return {
|
|
6994
7018
|
runtimeDirectory: getPaths().runtimeHome,
|
|
6995
|
-
getConfig: () =>
|
|
7019
|
+
getConfig: () => ({ ...config }),
|
|
6996
7020
|
getPaths,
|
|
6997
7021
|
fetch: globalThis.fetch,
|
|
6998
7022
|
getApiKey: () => apiKey,
|
|
@@ -8816,7 +8840,7 @@ function createPluginGatewayHandler(config, registry, apiKey = readApiKey(), rea
|
|
|
8816
8840
|
return catalogModelsResponse(request, config, clientVersionFile, registry, config.upstreamOnly === true ? { models: [] } : await registry.getCatalog(), codexCatalogFile(effectivePaths), ownsLocalModel, effectivePaths);
|
|
8817
8841
|
}
|
|
8818
8842
|
const endpoint = identifyClientEndpoint(incomingUrl.pathname, mountPath);
|
|
8819
|
-
const responsePath = endpoint?.
|
|
8843
|
+
const responsePath = endpoint?.to === "responses" && endpoint.operation === "generate";
|
|
8820
8844
|
const compactPath = endpoint?.operation === "compact";
|
|
8821
8845
|
const hintedModel = modelFromRoutingHint(request);
|
|
8822
8846
|
if (endpoint && request.headers.get("upgrade")?.toLowerCase() === "websocket" && hintedModel) {
|
|
@@ -8848,7 +8872,7 @@ function createPluginGatewayHandler(config, registry, apiKey = readApiKey(), rea
|
|
|
8848
8872
|
}
|
|
8849
8873
|
}
|
|
8850
8874
|
preparedBodies.set(request, { bytes: bytes2, json: json2 });
|
|
8851
|
-
const model = typeof json2?.model === "string" ? json2.model : hintedModel;
|
|
8875
|
+
const model = typeof json2?.model === "string" ? json2.model : endpoint.pathModel ?? hintedModel;
|
|
8852
8876
|
if (model && ownsLocalModel(model) && modelExclusion.isExcluded(model)) {
|
|
8853
8877
|
pluginRequests.add(request);
|
|
8854
8878
|
logGatewayError(processLog, {
|
|
@@ -9338,6 +9362,7 @@ function managedRuntimeCatalogFiles(runtimePaths = resolvePaths()) {
|
|
|
9338
9362
|
}
|
|
9339
9363
|
function createConfiguredPluginRegistry(config, dependencies = {}, processLog, runtimePaths = resolvePaths(), apiKey, catalogMode = config.upstreamOnly === true ? "manual" : "dynamic") {
|
|
9340
9364
|
config = { ...config };
|
|
9365
|
+
validateConfiguredPlugins(config);
|
|
9341
9366
|
const host = createGatewayHostServices(config, processLog, runtimePaths, apiKey);
|
|
9342
9367
|
const factories = [];
|
|
9343
9368
|
if (agentConfigEnabled(config, "zcode"))
|
|
@@ -9373,7 +9398,7 @@ function bodyWithJson(context, json) {
|
|
|
9373
9398
|
function withCodexCompaction(plugin) {
|
|
9374
9399
|
const handleHttp = plugin.handleHttp.bind(plugin);
|
|
9375
9400
|
return { ...plugin, async handleHttp(context) {
|
|
9376
|
-
if (context.
|
|
9401
|
+
if (context.to !== "responses")
|
|
9377
9402
|
return handleHttp(context);
|
|
9378
9403
|
const payload = await context.body.json();
|
|
9379
9404
|
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
@@ -9821,15 +9846,11 @@ async function stopCodexAppServers(runtime = SYSTEM_RUNTIME) {
|
|
|
9821
9846
|
// src/config-update.ts
|
|
9822
9847
|
import fs19 from "fs";
|
|
9823
9848
|
import bytes from "bytes";
|
|
9824
|
-
import { validateZcodeConfig } from "@agent-proxy/zcode";
|
|
9825
9849
|
import { isZcodeModel, zcodeStaticModelPrefixes } from "@agent-proxy/zcode/catalog";
|
|
9826
|
-
import { validateCodebuddyConfig } from "@agent-proxy/codebuddy";
|
|
9827
9850
|
import { isCodebuddyAccountValue } from "@agent-proxy/codebuddy/credentials";
|
|
9828
9851
|
import { CODEBUDDY_PREFIX, isCodebuddyModel, WORKBUDDY_PREFIX, codebuddyModelPrefixes } from "@agent-proxy/codebuddy/catalog";
|
|
9829
|
-
import { validateQoderConfig } from "@agent-proxy/qoder";
|
|
9830
9852
|
import { isQoderModel, QODER_CN_PREFIX, QODER_INTL_PREFIX } from "@agent-proxy/qoder/catalog";
|
|
9831
|
-
import {
|
|
9832
|
-
import { validateOpencodeZenConfig } from "@agent-proxy/opencode-zen";
|
|
9853
|
+
import { isAgyModel } from "@agent-proxy/agy";
|
|
9833
9854
|
import { isOpencodeZenModel, OPENCODE_ZEN_PREFIX } from "@agent-proxy/opencode-zen/catalog";
|
|
9834
9855
|
function parseMaxRequestLogs(value) {
|
|
9835
9856
|
if (!/^\d+$/.test(value) || !Number.isSafeInteger(Number(value))) {
|
|
@@ -10022,12 +10043,7 @@ function applySelectedModelsPatch(paths, selectedModels, syncState = true) {
|
|
|
10022
10043
|
return { applied: [] };
|
|
10023
10044
|
}
|
|
10024
10045
|
config.selectedModels = selectedModels;
|
|
10025
|
-
|
|
10026
|
-
validateZcodeConfig(agentConfig);
|
|
10027
|
-
validateCodebuddyConfig(agentConfig);
|
|
10028
|
-
validateQoderConfig(agentConfig);
|
|
10029
|
-
validateAgyConfig(agentConfig);
|
|
10030
|
-
validateOpencodeZenConfig(agentConfig);
|
|
10046
|
+
validateConfiguredPlugins(config);
|
|
10031
10047
|
writeGatewayConfigFile(paths.gatewayConfig, config);
|
|
10032
10048
|
if (syncState && fs19.existsSync(paths.stateFile)) {
|
|
10033
10049
|
const state = JSON.parse(fs19.readFileSync(paths.stateFile, "utf8"));
|
|
@@ -10144,12 +10160,7 @@ function applyWebUiConfigPatch(paths, patch, syncState = true, { write = true }
|
|
|
10144
10160
|
if (applied.length === 0) {
|
|
10145
10161
|
return { config, applied };
|
|
10146
10162
|
}
|
|
10147
|
-
|
|
10148
|
-
validateZcodeConfig(agentConfig);
|
|
10149
|
-
validateCodebuddyConfig(agentConfig);
|
|
10150
|
-
validateQoderConfig(agentConfig);
|
|
10151
|
-
validateAgyConfig(agentConfig);
|
|
10152
|
-
validateOpencodeZenConfig(agentConfig);
|
|
10163
|
+
validateConfiguredPlugins(config);
|
|
10153
10164
|
if (!write)
|
|
10154
10165
|
return { config, applied };
|
|
10155
10166
|
writeGatewayConfigFile(paths.gatewayConfig, config);
|
|
@@ -10464,8 +10475,8 @@ function configResponse(paths, providerDeps, instanceOnly = false) {
|
|
|
10464
10475
|
routerMode: live.upstreamOnly === true ? "upstream-only" : "dynamic",
|
|
10465
10476
|
host: live.host,
|
|
10466
10477
|
port: live.port,
|
|
10467
|
-
mountPath:
|
|
10468
|
-
officialBaseUrl: sanitizeUrlValue(
|
|
10478
|
+
mountPath: MOUNT_PATH,
|
|
10479
|
+
officialBaseUrl: sanitizeUrlValue(OFFICIAL_BASE_URL),
|
|
10469
10480
|
codexConfigManaged,
|
|
10470
10481
|
...codexConfigManaged ? {} : { manualCodexConfig: manualCodexConfigGuidance(paths, live) }
|
|
10471
10482
|
},
|
|
@@ -10821,24 +10832,12 @@ async function handleWebUiRequestCore(request, config, ctx, port) {
|
|
|
10821
10832
|
}
|
|
10822
10833
|
return notFound();
|
|
10823
10834
|
}
|
|
10824
|
-
|
|
10825
10835
|
// src/cli.ts
|
|
10826
|
-
import { validateZcodeConfig as validateZcodeConfig2, zcodeEnabled } from "@agent-proxy/zcode";
|
|
10827
|
-
import {
|
|
10828
|
-
codebuddyEnabled,
|
|
10829
|
-
validateCodebuddyConfig as validateCodebuddyConfig2
|
|
10830
|
-
} from "@agent-proxy/codebuddy";
|
|
10831
10836
|
import {
|
|
10832
10837
|
defaultAuthDirectory as defaultAuthDirectory2,
|
|
10833
10838
|
listCodebuddyAccounts as listCodebuddyAccounts2,
|
|
10834
10839
|
resolveCodebuddyAccountFile as resolveCodebuddyAccountFile2
|
|
10835
10840
|
} from "@agent-proxy/codebuddy/credentials";
|
|
10836
|
-
import {
|
|
10837
|
-
qoderEnabled,
|
|
10838
|
-
validateQoderConfig as validateQoderConfig2
|
|
10839
|
-
} from "@agent-proxy/qoder";
|
|
10840
|
-
import { agyEnabled, validateAgyConfig as validateAgyConfig2 } from "@agent-proxy/agy";
|
|
10841
|
-
import { opencodeZenEnabled, validateOpencodeZenConfig as validateOpencodeZenConfig2 } from "@agent-proxy/opencode-zen";
|
|
10842
10841
|
var DEFAULTS = {
|
|
10843
10842
|
host: "127.0.0.1",
|
|
10844
10843
|
port: 8320,
|
|
@@ -11336,7 +11335,7 @@ var AUDITED_FIELDS = [
|
|
|
11336
11335
|
"port",
|
|
11337
11336
|
"upstreamBaseUrl",
|
|
11338
11337
|
"upstreamType",
|
|
11339
|
-
"
|
|
11338
|
+
"modelMergeJson",
|
|
11340
11339
|
"selectedModels",
|
|
11341
11340
|
"excludedModels"
|
|
11342
11341
|
];
|
|
@@ -11473,7 +11472,7 @@ async function installCurrent(options, completeMigration) {
|
|
|
11473
11472
|
if (upstreamType)
|
|
11474
11473
|
overrides.upstreamType = upstreamType;
|
|
11475
11474
|
if (modelMergeJson)
|
|
11476
|
-
overrides.
|
|
11475
|
+
overrides.modelMergeJson = modelMergeJson;
|
|
11477
11476
|
if (switching && options.yes !== true) {
|
|
11478
11477
|
if (!process.stdin.isTTY) {
|
|
11479
11478
|
console.log("An installation already exists; rerun with --yes to update it in place.");
|
|
@@ -11914,7 +11913,7 @@ async function models(options) {
|
|
|
11914
11913
|
const auditBefore = { ...config };
|
|
11915
11914
|
const upstreamOnly = config.upstreamOnly === true;
|
|
11916
11915
|
if (modelMergeJson)
|
|
11917
|
-
config.
|
|
11916
|
+
config.modelMergeJson = modelMergeJson;
|
|
11918
11917
|
const currentSelection = configuredSelectedModels(paths, config);
|
|
11919
11918
|
if (options.exclude !== undefined) {
|
|
11920
11919
|
if (options.sync === true)
|
|
@@ -12246,12 +12245,7 @@ function codebuddyAccountApplied(account) {
|
|
|
12246
12245
|
return account === "auto" ? "CodeBuddy account set to auto (follows the most recently refreshed login)." : `CodeBuddy account locked to ${account}.`;
|
|
12247
12246
|
}
|
|
12248
12247
|
async function writeConfigAndRestart(paths, config, auditBefore, command, applied, options = {}) {
|
|
12249
|
-
|
|
12250
|
-
validateZcodeConfig2(agentConfig);
|
|
12251
|
-
validateCodebuddyConfig2(agentConfig);
|
|
12252
|
-
validateQoderConfig2(agentConfig);
|
|
12253
|
-
validateAgyConfig2(agentConfig);
|
|
12254
|
-
validateOpencodeZenConfig2(agentConfig);
|
|
12248
|
+
validateConfiguredPlugins(config);
|
|
12255
12249
|
const persist = async () => {
|
|
12256
12250
|
writeGatewayConfig(paths.gatewayConfig, config);
|
|
12257
12251
|
if (fs21.existsSync(paths.stateFile)) {
|
|
@@ -12303,12 +12297,11 @@ async function configCommand(options) {
|
|
|
12303
12297
|
const config = loadGatewayConfig(paths.gatewayConfig);
|
|
12304
12298
|
const auditBefore = { ...config };
|
|
12305
12299
|
if (upstreamOnlyTarget === undefined && zcodeTarget === undefined && codebuddyTarget === undefined && qoderTarget === undefined && agyTarget === undefined && opencodeZenTarget === undefined && logTarget === undefined && debugTarget === undefined && maxLogsOption === undefined && maxLogSizeOption === undefined) {
|
|
12306
|
-
const
|
|
12307
|
-
const
|
|
12308
|
-
const
|
|
12309
|
-
const
|
|
12310
|
-
const
|
|
12311
|
-
const opencodeZenActive = opencodeZenEnabled(agentConfig);
|
|
12300
|
+
const zcodeActive = agentConfigEnabled(config, "zcode");
|
|
12301
|
+
const codebuddyActive = agentConfigEnabled(config, "codebuddy");
|
|
12302
|
+
const qoderActive = agentConfigEnabled(config, "qoder");
|
|
12303
|
+
const agyActive = agentConfigEnabled(config, "agy");
|
|
12304
|
+
const opencodeZenActive = agentConfigEnabled(config, "opencodeZen");
|
|
12312
12305
|
console.log(JSON.stringify({
|
|
12313
12306
|
upstreamOnly: config.upstreamOnly === true,
|
|
12314
12307
|
zcode: zcodeActive,
|