nexus-agents 2.54.1 → 2.55.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-LSHIG4SR.js → chunk-HQ43NDJW.js} +145 -2
- package/dist/chunk-HQ43NDJW.js.map +1 -0
- package/dist/{chunk-PMKP3MCY.js → chunk-JEKPVSC4.js} +9 -6
- package/dist/chunk-JEKPVSC4.js.map +1 -0
- package/dist/{chunk-ODCEUZI7.js → chunk-KTJIEY77.js} +6 -6
- package/dist/chunk-KTJIEY77.js.map +1 -0
- package/dist/{chunk-CTQ4F636.js → chunk-SY344FS5.js} +3 -3
- package/dist/cli.js +6 -6
- package/dist/cli.js.map +1 -1
- package/dist/{consensus-vote-5GOWRJXL.js → consensus-vote-NRPXA57O.js} +2 -2
- package/dist/index.d.ts +13 -1
- package/dist/index.js +4 -4
- package/dist/{setup-command-T2EABH66.js → setup-command-NGAJEWE4.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-LSHIG4SR.js.map +0 -1
- package/dist/chunk-ODCEUZI7.js.map +0 -1
- package/dist/chunk-PMKP3MCY.js.map +0 -1
- /package/dist/{chunk-CTQ4F636.js.map → chunk-SY344FS5.js.map} +0 -0
- /package/dist/{consensus-vote-5GOWRJXL.js.map → consensus-vote-NRPXA57O.js.map} +0 -0
- /package/dist/{setup-command-T2EABH66.js.map → setup-command-NGAJEWE4.js.map} +0 -0
|
@@ -2792,8 +2792,108 @@ function createClaudeAdapter(config) {
|
|
|
2792
2792
|
var PROVIDER_ENV_KEYS = {
|
|
2793
2793
|
anthropic: "ANTHROPIC_API_KEY",
|
|
2794
2794
|
openai: "OPENAI_API_KEY",
|
|
2795
|
-
google: "GOOGLE_AI_API_KEY"
|
|
2795
|
+
google: "GOOGLE_AI_API_KEY",
|
|
2796
|
+
"custom-openai": "NEXUS_CUSTOM_API_KEY"
|
|
2796
2797
|
};
|
|
2798
|
+
var CUSTOM_API_BASE_URL_ENV = "NEXUS_CUSTOM_API_BASE_URL";
|
|
2799
|
+
var CUSTOM_API_ALLOW_PRIVATE_ENV = "NEXUS_CUSTOM_API_ALLOW_PRIVATE";
|
|
2800
|
+
|
|
2801
|
+
// src/adapters/sdk/custom-api-validation.ts
|
|
2802
|
+
import { isIPv4, isIPv6 } from "net";
|
|
2803
|
+
function validateCustomApiBaseUrl(raw, opts = {}) {
|
|
2804
|
+
if (raw === void 0 || raw.trim() === "") {
|
|
2805
|
+
return err(
|
|
2806
|
+
new ConfigError(
|
|
2807
|
+
"Custom API base URL is required but missing. Set NEXUS_CUSTOM_API_BASE_URL or pass `baseUrl` in config."
|
|
2808
|
+
)
|
|
2809
|
+
);
|
|
2810
|
+
}
|
|
2811
|
+
let url;
|
|
2812
|
+
try {
|
|
2813
|
+
url = new URL(raw);
|
|
2814
|
+
} catch {
|
|
2815
|
+
return err(new ConfigError(`Custom API base URL is not a valid URL: ${raw}`));
|
|
2816
|
+
}
|
|
2817
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
2818
|
+
return err(
|
|
2819
|
+
new ConfigError(`Custom API base URL must use http or https, got "${url.protocol}" in ${raw}`)
|
|
2820
|
+
);
|
|
2821
|
+
}
|
|
2822
|
+
const allowPrivate = opts.allowPrivate === true || resolveAllowPrivateFromEnv();
|
|
2823
|
+
if (!allowPrivate) {
|
|
2824
|
+
const rejection = classifyPrivateHost(url.hostname);
|
|
2825
|
+
if (rejection !== null) {
|
|
2826
|
+
return err(
|
|
2827
|
+
new ConfigError(
|
|
2828
|
+
`Custom API base URL rejected (SSRF guard, reason="${rejection.reason}"): ${rejection.message}. Set ${CUSTOM_API_ALLOW_PRIVATE_ENV}=1 to bypass if the gateway runs on a trusted internal host.`
|
|
2829
|
+
)
|
|
2830
|
+
);
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
return ok(url);
|
|
2834
|
+
}
|
|
2835
|
+
function resolveAllowPrivateFromEnv() {
|
|
2836
|
+
const v = process.env[CUSTOM_API_ALLOW_PRIVATE_ENV];
|
|
2837
|
+
return v === "1" || v === "true";
|
|
2838
|
+
}
|
|
2839
|
+
function classifyPrivateHost(hostname) {
|
|
2840
|
+
const stripped = hostname.startsWith("[") && hostname.endsWith("]") ? hostname.slice(1, -1) : hostname;
|
|
2841
|
+
const normalized = stripped.toLowerCase();
|
|
2842
|
+
if (isIPv4(normalized)) {
|
|
2843
|
+
return classifyIPv4(normalized);
|
|
2844
|
+
}
|
|
2845
|
+
if (isIPv6(normalized)) {
|
|
2846
|
+
return classifyIPv6(normalized);
|
|
2847
|
+
}
|
|
2848
|
+
if (normalized === "localhost" || normalized.endsWith(".localhost") || normalized.endsWith(".local")) {
|
|
2849
|
+
return {
|
|
2850
|
+
reason: "loopback",
|
|
2851
|
+
message: `hostname "${hostname}" resolves to loopback/mDNS`
|
|
2852
|
+
};
|
|
2853
|
+
}
|
|
2854
|
+
return null;
|
|
2855
|
+
}
|
|
2856
|
+
var IPV4_RULES = [
|
|
2857
|
+
{ match: (a) => a === 127, reason: "loopback", label: "IPv4 loopback" },
|
|
2858
|
+
{ match: (a) => a === 10, reason: "private_range", label: "IPv4 private (10/8)" },
|
|
2859
|
+
{
|
|
2860
|
+
match: (a, b) => a === 172 && b >= 16 && b <= 31,
|
|
2861
|
+
reason: "private_range",
|
|
2862
|
+
label: "IPv4 private (172.16/12)"
|
|
2863
|
+
},
|
|
2864
|
+
{
|
|
2865
|
+
match: (a, b) => a === 192 && b === 168,
|
|
2866
|
+
reason: "private_range",
|
|
2867
|
+
label: "IPv4 private (192.168/16)"
|
|
2868
|
+
},
|
|
2869
|
+
{
|
|
2870
|
+
match: (a, b) => a === 169 && b === 254,
|
|
2871
|
+
reason: "link_local",
|
|
2872
|
+
label: "IPv4 link-local (169.254/16 \u2014 AWS IMDS)"
|
|
2873
|
+
},
|
|
2874
|
+
{ match: (a) => a === 0, reason: "reserved", label: "IPv4 reserved (0/8)" }
|
|
2875
|
+
];
|
|
2876
|
+
function classifyIPv4(ip) {
|
|
2877
|
+
const parts = ip.split(".").map((p) => Number.parseInt(p, 10));
|
|
2878
|
+
if (parts.length !== 4 || parts.some((n) => Number.isNaN(n))) return null;
|
|
2879
|
+
const [a, b] = parts;
|
|
2880
|
+
for (const rule of IPV4_RULES) {
|
|
2881
|
+
if (rule.match(a, b)) {
|
|
2882
|
+
return { reason: rule.reason, message: `${rule.label} (${ip})` };
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
return null;
|
|
2886
|
+
}
|
|
2887
|
+
function classifyIPv6(ip) {
|
|
2888
|
+
const lower = ip.toLowerCase();
|
|
2889
|
+
if (lower === "::1") return { reason: "loopback", message: `IPv6 loopback (${ip})` };
|
|
2890
|
+
if (lower.startsWith("fe80:"))
|
|
2891
|
+
return { reason: "link_local", message: `IPv6 link-local (${ip})` };
|
|
2892
|
+
if (/^fc|^fd/.test(lower)) {
|
|
2893
|
+
return { reason: "private_range", message: `IPv6 unique-local (${ip}, fc00::/7)` };
|
|
2894
|
+
}
|
|
2895
|
+
return null;
|
|
2896
|
+
}
|
|
2797
2897
|
|
|
2798
2898
|
// src/adapters/sdk/sdk-adapter.ts
|
|
2799
2899
|
function extractProviderFactory(mod, factoryName) {
|
|
@@ -2822,6 +2922,13 @@ function resolveApiKey(providerId, configKey) {
|
|
|
2822
2922
|
const envVar = PROVIDER_ENV_KEYS[providerId];
|
|
2823
2923
|
return process.env[envVar];
|
|
2824
2924
|
}
|
|
2925
|
+
function resolveAndValidateCustomBaseUrl(config) {
|
|
2926
|
+
if (config.providerId !== "custom-openai") return void 0;
|
|
2927
|
+
const raw = config.baseUrl ?? process.env[CUSTOM_API_BASE_URL_ENV];
|
|
2928
|
+
const validated = validateCustomApiBaseUrl(raw);
|
|
2929
|
+
if (!validated.ok) throw validated.error;
|
|
2930
|
+
return validated.value.toString();
|
|
2931
|
+
}
|
|
2825
2932
|
function mapFinishReason(reason) {
|
|
2826
2933
|
switch (reason) {
|
|
2827
2934
|
case "stop":
|
|
@@ -2853,6 +2960,8 @@ var SdkAdapter = class extends BaseAdapter {
|
|
|
2853
2960
|
model;
|
|
2854
2961
|
sdkFunctions;
|
|
2855
2962
|
sdkConfig;
|
|
2963
|
+
/** Validated base URL for custom-openai provider; undefined for built-ins. */
|
|
2964
|
+
customBaseUrl;
|
|
2856
2965
|
/** Inflight init promise for coalescing concurrent calls (Issue #1438). */
|
|
2857
2966
|
initPromise;
|
|
2858
2967
|
constructor(config, logger11) {
|
|
@@ -2868,6 +2977,7 @@ var SdkAdapter = class extends BaseAdapter {
|
|
|
2868
2977
|
});
|
|
2869
2978
|
this.sdkProviderId = config.providerId;
|
|
2870
2979
|
this.sdkConfig = config;
|
|
2980
|
+
this.customBaseUrl = resolveAndValidateCustomBaseUrl(config);
|
|
2871
2981
|
}
|
|
2872
2982
|
/**
|
|
2873
2983
|
* Lazily initialize the AI SDK model and functions.
|
|
@@ -2926,6 +3036,14 @@ var SdkAdapter = class extends BaseAdapter {
|
|
|
2926
3036
|
const provider = factory({ apiKey });
|
|
2927
3037
|
return { model: provider(this.modelId) };
|
|
2928
3038
|
}
|
|
3039
|
+
case "custom-openai": {
|
|
3040
|
+
const mod = await import("@ai-sdk/openai");
|
|
3041
|
+
const factory = extractProviderFactory(mod, "createOpenAI");
|
|
3042
|
+
const opts = { apiKey };
|
|
3043
|
+
if (this.customBaseUrl !== void 0) opts["baseURL"] = this.customBaseUrl;
|
|
3044
|
+
const provider = factory(opts);
|
|
3045
|
+
return { model: provider(this.modelId) };
|
|
3046
|
+
}
|
|
2929
3047
|
}
|
|
2930
3048
|
}
|
|
2931
3049
|
/**
|
|
@@ -3115,9 +3233,34 @@ function tryApiAdapter(config, logger11) {
|
|
|
3115
3233
|
reason: `Using Google AI API via AI SDK (model: ${geminiModelId})`
|
|
3116
3234
|
};
|
|
3117
3235
|
}
|
|
3236
|
+
const custom = tryCustomOpenAiAdapter(logger11);
|
|
3237
|
+
if (custom !== null) return custom;
|
|
3118
3238
|
logger11.info("No API keys available for any provider");
|
|
3119
3239
|
return null;
|
|
3120
3240
|
}
|
|
3241
|
+
function tryCustomOpenAiAdapter(logger11) {
|
|
3242
|
+
const customKey = resolveApiKeyFromEnv(void 0, "NEXUS_CUSTOM_API_KEY");
|
|
3243
|
+
const customBaseUrl = process.env["NEXUS_CUSTOM_API_BASE_URL"];
|
|
3244
|
+
if (customKey === void 0 || customBaseUrl === void 0 || customBaseUrl === "") {
|
|
3245
|
+
return null;
|
|
3246
|
+
}
|
|
3247
|
+
const customModelId = process.env["NEXUS_CUSTOM_MODEL"] ?? "gpt-4o";
|
|
3248
|
+
logger11.info("Using custom-openai SDK adapter", {
|
|
3249
|
+
model: customModelId,
|
|
3250
|
+
baseUrl: customBaseUrl
|
|
3251
|
+
});
|
|
3252
|
+
return {
|
|
3253
|
+
adapter: new SdkAdapter({
|
|
3254
|
+
providerId: "custom-openai",
|
|
3255
|
+
modelId: customModelId,
|
|
3256
|
+
apiKey: customKey,
|
|
3257
|
+
baseUrl: customBaseUrl
|
|
3258
|
+
}),
|
|
3259
|
+
source: "api",
|
|
3260
|
+
name: "custom-openai",
|
|
3261
|
+
reason: `Using custom OpenAI-compatible gateway at ${customBaseUrl} (model: ${customModelId})`
|
|
3262
|
+
};
|
|
3263
|
+
}
|
|
3121
3264
|
async function selectCliFirst(config, logger11, cache) {
|
|
3122
3265
|
const cliResult = await tryCliAdapter(config, logger11, cache);
|
|
3123
3266
|
if (cliResult !== null) return cliResult;
|
|
@@ -12936,4 +13079,4 @@ export {
|
|
|
12936
13079
|
CONSENSUS_VOTE_OUTPUT_SCHEMA,
|
|
12937
13080
|
registerConsensusVoteTool
|
|
12938
13081
|
};
|
|
12939
|
-
//# sourceMappingURL=chunk-
|
|
13082
|
+
//# sourceMappingURL=chunk-HQ43NDJW.js.map
|