nexus-agents 2.55.0 → 2.55.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/{chunk-HQ43NDJW.js → chunk-BPMQRYGU.js} +6 -109
- package/dist/chunk-BPMQRYGU.js.map +1 -0
- package/dist/{chunk-KTJIEY77.js → chunk-KVWHK72T.js} +4 -4
- package/dist/{chunk-SY344FS5.js → chunk-OC7RMLN2.js} +3 -3
- package/dist/chunk-R66AWJJ7.js +120 -0
- package/dist/chunk-R66AWJJ7.js.map +1 -0
- package/dist/{chunk-JEKPVSC4.js → chunk-XYCS5X3H.js} +2 -2
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +56 -5
- package/dist/cli.js.map +1 -1
- package/dist/{consensus-vote-NRPXA57O.js → consensus-vote-G6H532ME.js} +3 -2
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/dist/{setup-command-NGAJEWE4.js → setup-command-B6AFJGZB.js} +3 -3
- package/dist/setup-custom-api-XAWKRDWV.js +107 -0
- package/dist/setup-custom-api-XAWKRDWV.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-HQ43NDJW.js.map +0 -1
- /package/dist/{chunk-KTJIEY77.js.map → chunk-KVWHK72T.js.map} +0 -0
- /package/dist/{chunk-SY344FS5.js.map → chunk-OC7RMLN2.js.map} +0 -0
- /package/dist/{chunk-JEKPVSC4.js.map → chunk-XYCS5X3H.js.map} +0 -0
- /package/dist/{consensus-vote-NRPXA57O.js.map → consensus-vote-G6H532ME.js.map} +0 -0
- /package/dist/{setup-command-NGAJEWE4.js.map → setup-command-B6AFJGZB.js.map} +0 -0
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
withAccessPolicy,
|
|
28
28
|
withProgressHeartbeat,
|
|
29
29
|
wrapToolWithTimeout
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-BPMQRYGU.js";
|
|
31
31
|
import {
|
|
32
32
|
REGISTRY_PATH,
|
|
33
33
|
getProjectRoot,
|
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
import {
|
|
68
68
|
DEFAULT_TASK_TTL_MS,
|
|
69
69
|
clampTaskTtl
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-OC7RMLN2.js";
|
|
71
71
|
import {
|
|
72
72
|
createSessionMemory
|
|
73
73
|
} from "./chunk-NYNBDP7M.js";
|
|
@@ -43037,7 +43037,7 @@ ${contextBlock}`;
|
|
|
43037
43037
|
const strategy = config.votingStrategy ?? "higher_order";
|
|
43038
43038
|
await postProgress(config, "Vote", `Running consensus with ${strategy} strategy...`);
|
|
43039
43039
|
try {
|
|
43040
|
-
const { executeVoting } = await import("./consensus-vote-
|
|
43040
|
+
const { executeVoting } = await import("./consensus-vote-G6H532ME.js");
|
|
43041
43041
|
const votingResult = await executeVoting(
|
|
43042
43042
|
{
|
|
43043
43043
|
proposal: plan.slice(0, 4e3),
|
|
@@ -54771,4 +54771,4 @@ export {
|
|
|
54771
54771
|
detectBackend,
|
|
54772
54772
|
createTaskTracker
|
|
54773
54773
|
};
|
|
54774
|
-
//# sourceMappingURL=chunk-
|
|
54774
|
+
//# sourceMappingURL=chunk-KVWHK72T.js.map
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
} from "./chunk-CLYZ7FWP.js";
|
|
25
25
|
|
|
26
26
|
// src/version.ts
|
|
27
|
-
var VERSION = true ? "2.55.
|
|
27
|
+
var VERSION = true ? "2.55.1" : "dev";
|
|
28
28
|
|
|
29
29
|
// src/cli/setup-data-dir.ts
|
|
30
30
|
import { mkdirSync, existsSync as existsSync2 } from "fs";
|
|
@@ -758,7 +758,7 @@ async function runDoctorFix(result) {
|
|
|
758
758
|
writeLine2("\u2500".repeat(40));
|
|
759
759
|
let fixCount = 0;
|
|
760
760
|
if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
|
|
761
|
-
const { runSetup } = await import("./setup-command-
|
|
761
|
+
const { runSetup } = await import("./setup-command-B6AFJGZB.js");
|
|
762
762
|
const setupResult = runSetup({
|
|
763
763
|
skipMcp: true,
|
|
764
764
|
skipRules: true,
|
|
@@ -836,4 +836,4 @@ export {
|
|
|
836
836
|
startStdioServer,
|
|
837
837
|
closeServer
|
|
838
838
|
};
|
|
839
|
-
//# sourceMappingURL=chunk-
|
|
839
|
+
//# sourceMappingURL=chunk-OC7RMLN2.js.map
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConfigError,
|
|
3
|
+
err,
|
|
4
|
+
ok
|
|
5
|
+
} from "./chunk-UOUJZIKH.js";
|
|
6
|
+
|
|
7
|
+
// src/adapters/sdk/types.ts
|
|
8
|
+
var PROVIDER_ENV_KEYS = {
|
|
9
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
10
|
+
openai: "OPENAI_API_KEY",
|
|
11
|
+
google: "GOOGLE_AI_API_KEY",
|
|
12
|
+
"custom-openai": "NEXUS_CUSTOM_API_KEY"
|
|
13
|
+
};
|
|
14
|
+
var CUSTOM_API_BASE_URL_ENV = "NEXUS_CUSTOM_API_BASE_URL";
|
|
15
|
+
var CUSTOM_API_ALLOW_PRIVATE_ENV = "NEXUS_CUSTOM_API_ALLOW_PRIVATE";
|
|
16
|
+
|
|
17
|
+
// src/adapters/sdk/custom-api-validation.ts
|
|
18
|
+
import { isIPv4, isIPv6 } from "net";
|
|
19
|
+
function validateCustomApiBaseUrl(raw, opts = {}) {
|
|
20
|
+
if (raw === void 0 || raw.trim() === "") {
|
|
21
|
+
return err(
|
|
22
|
+
new ConfigError(
|
|
23
|
+
"Custom API base URL is required but missing. Set NEXUS_CUSTOM_API_BASE_URL or pass `baseUrl` in config."
|
|
24
|
+
)
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
let url;
|
|
28
|
+
try {
|
|
29
|
+
url = new URL(raw);
|
|
30
|
+
} catch {
|
|
31
|
+
return err(new ConfigError(`Custom API base URL is not a valid URL: ${raw}`));
|
|
32
|
+
}
|
|
33
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
34
|
+
return err(
|
|
35
|
+
new ConfigError(`Custom API base URL must use http or https, got "${url.protocol}" in ${raw}`)
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
const allowPrivate = opts.allowPrivate === true || resolveAllowPrivateFromEnv();
|
|
39
|
+
if (!allowPrivate) {
|
|
40
|
+
const rejection = classifyPrivateHost(url.hostname);
|
|
41
|
+
if (rejection !== null) {
|
|
42
|
+
return err(
|
|
43
|
+
new ConfigError(
|
|
44
|
+
`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.`
|
|
45
|
+
)
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return ok(url);
|
|
50
|
+
}
|
|
51
|
+
function resolveAllowPrivateFromEnv() {
|
|
52
|
+
const v = process.env[CUSTOM_API_ALLOW_PRIVATE_ENV];
|
|
53
|
+
return v === "1" || v === "true";
|
|
54
|
+
}
|
|
55
|
+
function classifyPrivateHost(hostname) {
|
|
56
|
+
const stripped = hostname.startsWith("[") && hostname.endsWith("]") ? hostname.slice(1, -1) : hostname;
|
|
57
|
+
const normalized = stripped.toLowerCase();
|
|
58
|
+
if (isIPv4(normalized)) {
|
|
59
|
+
return classifyIPv4(normalized);
|
|
60
|
+
}
|
|
61
|
+
if (isIPv6(normalized)) {
|
|
62
|
+
return classifyIPv6(normalized);
|
|
63
|
+
}
|
|
64
|
+
if (normalized === "localhost" || normalized.endsWith(".localhost") || normalized.endsWith(".local")) {
|
|
65
|
+
return {
|
|
66
|
+
reason: "loopback",
|
|
67
|
+
message: `hostname "${hostname}" resolves to loopback/mDNS`
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
var IPV4_RULES = [
|
|
73
|
+
{ match: (a) => a === 127, reason: "loopback", label: "IPv4 loopback" },
|
|
74
|
+
{ match: (a) => a === 10, reason: "private_range", label: "IPv4 private (10/8)" },
|
|
75
|
+
{
|
|
76
|
+
match: (a, b) => a === 172 && b >= 16 && b <= 31,
|
|
77
|
+
reason: "private_range",
|
|
78
|
+
label: "IPv4 private (172.16/12)"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
match: (a, b) => a === 192 && b === 168,
|
|
82
|
+
reason: "private_range",
|
|
83
|
+
label: "IPv4 private (192.168/16)"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
match: (a, b) => a === 169 && b === 254,
|
|
87
|
+
reason: "link_local",
|
|
88
|
+
label: "IPv4 link-local (169.254/16 \u2014 AWS IMDS)"
|
|
89
|
+
},
|
|
90
|
+
{ match: (a) => a === 0, reason: "reserved", label: "IPv4 reserved (0/8)" }
|
|
91
|
+
];
|
|
92
|
+
function classifyIPv4(ip) {
|
|
93
|
+
const parts = ip.split(".").map((p) => Number.parseInt(p, 10));
|
|
94
|
+
if (parts.length !== 4 || parts.some((n) => Number.isNaN(n))) return null;
|
|
95
|
+
const [a, b] = parts;
|
|
96
|
+
for (const rule of IPV4_RULES) {
|
|
97
|
+
if (rule.match(a, b)) {
|
|
98
|
+
return { reason: rule.reason, message: `${rule.label} (${ip})` };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
function classifyIPv6(ip) {
|
|
104
|
+
const lower = ip.toLowerCase();
|
|
105
|
+
if (lower === "::1") return { reason: "loopback", message: `IPv6 loopback (${ip})` };
|
|
106
|
+
if (lower.startsWith("fe80:"))
|
|
107
|
+
return { reason: "link_local", message: `IPv6 link-local (${ip})` };
|
|
108
|
+
if (/^fc|^fd/.test(lower)) {
|
|
109
|
+
return { reason: "private_range", message: `IPv6 unique-local (${ip}, fc00::/7)` };
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export {
|
|
115
|
+
PROVIDER_ENV_KEYS,
|
|
116
|
+
CUSTOM_API_BASE_URL_ENV,
|
|
117
|
+
CUSTOM_API_ALLOW_PRIVATE_ENV,
|
|
118
|
+
validateCustomApiBaseUrl
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=chunk-R66AWJJ7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/sdk/types.ts","../src/adapters/sdk/custom-api-validation.ts"],"sourcesContent":["/**\n * nexus-agents/adapters/sdk - Shared Types\n *\n * Type definitions for AI SDK adapter layer.\n *\n * @module adapters/sdk/types\n * (Source: Issue #1123 — AI SDK provider layer)\n */\n\n/**\n * Supported AI SDK provider identifiers.\n *\n * `custom-openai` is for OpenAI-compatible gateways (multi-vendor proxies,\n * self-hosted LLM servers, corporate model gateways) — uses the same\n * @ai-sdk/openai package but with a configurable `baseURL`.\n */\nexport type SdkProviderId = 'anthropic' | 'openai' | 'google' | 'custom-openai';\n\n/**\n * Configuration for creating an AI SDK adapter.\n */\nexport interface SdkAdapterConfig {\n /** Provider identifier */\n providerId: SdkProviderId;\n /** Model to use (e.g., 'claude-sonnet-4-6', 'gpt-4o') */\n modelId: string;\n /** API key (falls back to environment variable) */\n apiKey?: string;\n /**\n * Base URL for OpenAI-compatible gateways. Required when\n * `providerId === 'custom-openai'`, ignored otherwise. Falls back to\n * the `NEXUS_CUSTOM_API_BASE_URL` environment variable.\n */\n baseUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n /** Maximum retries on transient failures */\n maxRetries?: number;\n}\n\n/**\n * Maps provider IDs to their environment variable names.\n */\nexport const PROVIDER_ENV_KEYS: Record<SdkProviderId, string> = {\n anthropic: 'ANTHROPIC_API_KEY',\n openai: 'OPENAI_API_KEY',\n google: 'GOOGLE_AI_API_KEY',\n 'custom-openai': 'NEXUS_CUSTOM_API_KEY',\n};\n\n/**\n * Environment variable name for the custom gateway base URL.\n * Keep in sync with `SdkAdapterConfig.baseUrl`.\n */\nexport const CUSTOM_API_BASE_URL_ENV = 'NEXUS_CUSTOM_API_BASE_URL';\n\n/**\n * Escape hatch: set to `1`/`true` to allow the custom gateway base URL to\n * resolve to a loopback or RFC 1918 private address. Default is DENY —\n * SSRF defense. Only disable this when you know the gateway runs on a\n * trusted internal host and you accept the risk.\n */\nexport const CUSTOM_API_ALLOW_PRIVATE_ENV = 'NEXUS_CUSTOM_API_ALLOW_PRIVATE';\n","/**\n * Validation for the `custom-openai` SDK adapter's gateway URL.\n *\n * The base URL is user-provided, so without validation the adapter becomes\n * an SSRF vector: a malicious prompt that reshaped env vars, or a typo in\n * the config, could point nexus-agents at `http://169.254.169.254/` (AWS\n * metadata) or `http://localhost:5432/` (internal services). This module\n * rejects such URLs unless the user explicitly opts in via\n * `NEXUS_CUSTOM_API_ALLOW_PRIVATE=1`.\n *\n * Called out in the #2119 consensus vote by the Security Engineer role.\n *\n * @module adapters/sdk/custom-api-validation\n */\n\nimport { isIPv4, isIPv6 } from 'node:net';\nimport { ConfigError, ok, err, type Result } from '../../core/index.js';\nimport { CUSTOM_API_ALLOW_PRIVATE_ENV } from './types.js';\n\n/**\n * Why a given URL was rejected. Machine-readable so error messages can\n * distinguish root causes in downstream tooling.\n */\nexport type BaseUrlRejectionReason =\n | 'empty'\n | 'not_a_url'\n | 'not_http_https'\n | 'loopback'\n | 'link_local'\n | 'private_range'\n | 'reserved';\n\ninterface RejectionDetail {\n readonly reason: BaseUrlRejectionReason;\n readonly message: string;\n}\n\n/**\n * Validates a user-provided custom-gateway base URL. Returns the URL as an\n * `ok` Result if it passes, or a `ConfigError` with a machine-readable\n * reason if it fails.\n *\n * Pass `{ allowPrivate: true }` (or set the env var) to bypass the SSRF\n * checks — use this only when the gateway is on a trusted internal host\n * and you accept the risk.\n */\nexport function validateCustomApiBaseUrl(\n raw: string | undefined,\n opts: { readonly allowPrivate?: boolean } = {}\n): Result<URL, ConfigError> {\n if (raw === undefined || raw.trim() === '') {\n return err(\n new ConfigError(\n 'Custom API base URL is required but missing. Set NEXUS_CUSTOM_API_BASE_URL or pass `baseUrl` in config.'\n )\n );\n }\n\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n return err(new ConfigError(`Custom API base URL is not a valid URL: ${raw}`));\n }\n\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n return err(\n new ConfigError(`Custom API base URL must use http or https, got \"${url.protocol}\" in ${raw}`)\n );\n }\n\n const allowPrivate = opts.allowPrivate === true || resolveAllowPrivateFromEnv();\n if (!allowPrivate) {\n const rejection = classifyPrivateHost(url.hostname);\n if (rejection !== null) {\n return err(\n new ConfigError(\n `Custom API base URL rejected (SSRF guard, reason=\"${rejection.reason}\"): ${rejection.message}. ` +\n `Set ${CUSTOM_API_ALLOW_PRIVATE_ENV}=1 to bypass if the gateway runs on a trusted internal host.`\n )\n );\n }\n }\n\n return ok(url);\n}\n\nfunction resolveAllowPrivateFromEnv(): boolean {\n const v = process.env[CUSTOM_API_ALLOW_PRIVATE_ENV];\n return v === '1' || v === 'true';\n}\n\n/**\n * Returns a rejection reason if the hostname resolves (by string form) to\n * a loopback, link-local, or RFC 1918 private address; `null` otherwise.\n *\n * Note: this is a string-level check. It does NOT perform DNS resolution,\n * so a public DNS name that secretly resolves to a private IP will pass.\n * Callers who need that level of defense should add a runtime connect\n * check and validate the socket peer address.\n */\nfunction classifyPrivateHost(hostname: string): RejectionDetail | null {\n // URL.hostname wraps IPv6 literals in brackets (e.g. \"[::1]\"); strip them\n // before the net-module checks, which expect bare forms.\n const stripped =\n hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;\n const normalized = stripped.toLowerCase();\n\n // Literal IPv4 loopback or private-range address\n if (isIPv4(normalized)) {\n return classifyIPv4(normalized);\n }\n\n // Literal IPv6 loopback (::1), link-local (fe80::/10), unique-local (fc00::/7)\n if (isIPv6(normalized)) {\n return classifyIPv6(normalized);\n }\n\n // Hostname literals that resolve to loopback without needing DNS\n if (\n normalized === 'localhost' ||\n normalized.endsWith('.localhost') ||\n normalized.endsWith('.local') // mDNS\n ) {\n return {\n reason: 'loopback',\n message: `hostname \"${hostname}\" resolves to loopback/mDNS`,\n };\n }\n\n return null;\n}\n\n/** IPv4 ranges the SSRF guard rejects, in order of specificity. */\nconst IPV4_RULES: ReadonlyArray<{\n readonly match: (a: number, b: number) => boolean;\n readonly reason: BaseUrlRejectionReason;\n readonly label: string;\n}> = [\n { match: (a) => a === 127, reason: 'loopback', label: 'IPv4 loopback' },\n { match: (a) => a === 10, reason: 'private_range', label: 'IPv4 private (10/8)' },\n {\n match: (a, b) => a === 172 && b >= 16 && b <= 31,\n reason: 'private_range',\n label: 'IPv4 private (172.16/12)',\n },\n {\n match: (a, b) => a === 192 && b === 168,\n reason: 'private_range',\n label: 'IPv4 private (192.168/16)',\n },\n {\n match: (a, b) => a === 169 && b === 254,\n reason: 'link_local',\n label: 'IPv4 link-local (169.254/16 — AWS IMDS)',\n },\n { match: (a) => a === 0, reason: 'reserved', label: 'IPv4 reserved (0/8)' },\n];\n\nfunction classifyIPv4(ip: string): RejectionDetail | null {\n const parts = ip.split('.').map((p) => Number.parseInt(p, 10));\n if (parts.length !== 4 || parts.some((n) => Number.isNaN(n))) return null;\n const [a, b] = parts as [number, number, number, number];\n for (const rule of IPV4_RULES) {\n if (rule.match(a, b)) {\n return { reason: rule.reason, message: `${rule.label} (${ip})` };\n }\n }\n return null;\n}\n\nfunction classifyIPv6(ip: string): RejectionDetail | null {\n const lower = ip.toLowerCase();\n if (lower === '::1') return { reason: 'loopback', message: `IPv6 loopback (${ip})` };\n if (lower.startsWith('fe80:'))\n return { reason: 'link_local', message: `IPv6 link-local (${ip})` };\n // Unique-local: fc00::/7 → first byte has high bit set and second-high bit set\n if (/^fc|^fd/.test(lower)) {\n return { reason: 'private_range', message: `IPv6 unique-local (${ip}, fc00::/7)` };\n }\n return null;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
VERSION,
|
|
6
6
|
initDataDirectories
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-OC7RMLN2.js";
|
|
8
8
|
import {
|
|
9
9
|
CLI_SUBPROCESS_TIMEOUTS,
|
|
10
10
|
createLogger,
|
|
@@ -1583,4 +1583,4 @@ export {
|
|
|
1583
1583
|
setupCommand,
|
|
1584
1584
|
setupCommandAsync
|
|
1585
1585
|
};
|
|
1586
|
-
//# sourceMappingURL=chunk-
|
|
1586
|
+
//# sourceMappingURL=chunk-XYCS5X3H.js.map
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import "./chunk-4FVISCDB.js";
|
|
16
16
|
import {
|
|
17
17
|
setupCommandAsync
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-XYCS5X3H.js";
|
|
19
19
|
import "./chunk-EKYT4NMD.js";
|
|
20
20
|
import {
|
|
21
21
|
AuthHandler,
|
|
@@ -151,7 +151,7 @@ import {
|
|
|
151
151
|
validateNexusEnv,
|
|
152
152
|
validateWorkflow,
|
|
153
153
|
wrapInMarkdownFence
|
|
154
|
-
} from "./chunk-
|
|
154
|
+
} from "./chunk-KVWHK72T.js";
|
|
155
155
|
import {
|
|
156
156
|
resolveToken
|
|
157
157
|
} from "./chunk-2SPRLBOS.js";
|
|
@@ -170,7 +170,8 @@ import {
|
|
|
170
170
|
registerConsensusVoteTool,
|
|
171
171
|
shutdownToolMemory,
|
|
172
172
|
validateTimeout
|
|
173
|
-
} from "./chunk-
|
|
173
|
+
} from "./chunk-BPMQRYGU.js";
|
|
174
|
+
import "./chunk-R66AWJJ7.js";
|
|
174
175
|
import {
|
|
175
176
|
loadPapersRegistry,
|
|
176
177
|
loadTechniquesRegistry,
|
|
@@ -201,7 +202,7 @@ import {
|
|
|
201
202
|
doctorCommand,
|
|
202
203
|
initDataDirectories,
|
|
203
204
|
runDoctor
|
|
204
|
-
} from "./chunk-
|
|
205
|
+
} from "./chunk-OC7RMLN2.js";
|
|
205
206
|
import "./chunk-NYNBDP7M.js";
|
|
206
207
|
import {
|
|
207
208
|
MemoryError
|
|
@@ -17516,6 +17517,16 @@ var PARSE_ARGS_CONFIG = {
|
|
|
17516
17517
|
type: "string",
|
|
17517
17518
|
default: "user"
|
|
17518
17519
|
},
|
|
17520
|
+
// Setup --custom-api for OpenAI-compatible gateway configuration (#2124)
|
|
17521
|
+
"custom-api": {
|
|
17522
|
+
type: "string"
|
|
17523
|
+
},
|
|
17524
|
+
"custom-api-key": {
|
|
17525
|
+
type: "string"
|
|
17526
|
+
},
|
|
17527
|
+
"custom-model": {
|
|
17528
|
+
type: "string"
|
|
17529
|
+
},
|
|
17519
17530
|
// Demo command options
|
|
17520
17531
|
mock: {
|
|
17521
17532
|
type: "boolean",
|
|
@@ -20523,6 +20534,10 @@ async function handleDoctorCommand(args) {
|
|
|
20523
20534
|
process.exit(exitCode === 0 ? EXIT_CODES.SUCCESS : EXIT_CODES.SERVER_START_FAILED);
|
|
20524
20535
|
}
|
|
20525
20536
|
async function handleSetupCommandAsync(args) {
|
|
20537
|
+
if (args.options.customApi !== void 0 && args.options.customApi !== "") {
|
|
20538
|
+
const exitCode2 = await runCustomApiSetup(args);
|
|
20539
|
+
process.exit(exitCode2);
|
|
20540
|
+
}
|
|
20526
20541
|
const exitCode = await setupCommandAsync({
|
|
20527
20542
|
interactive: args.options.interactive,
|
|
20528
20543
|
nonInteractive: args.options.nonInteractive,
|
|
@@ -20540,6 +20555,33 @@ async function handleSetupCommandAsync(args) {
|
|
|
20540
20555
|
});
|
|
20541
20556
|
process.exit(exitCode === 0 ? EXIT_CODES.SUCCESS : EXIT_CODES.SERVER_START_FAILED);
|
|
20542
20557
|
}
|
|
20558
|
+
async function runCustomApiSetup(args) {
|
|
20559
|
+
const { configureCustomApi } = await import("./setup-custom-api-XAWKRDWV.js");
|
|
20560
|
+
const baseUrl = args.options.customApi;
|
|
20561
|
+
if (baseUrl === void 0) return EXIT_CODES.SERVER_START_FAILED;
|
|
20562
|
+
const input = {
|
|
20563
|
+
baseUrl,
|
|
20564
|
+
nonInteractive: args.options.nonInteractive,
|
|
20565
|
+
...args.options.customApiKey !== void 0 ? { apiKey: args.options.customApiKey } : {},
|
|
20566
|
+
...args.options.customModel !== void 0 ? { model: args.options.customModel } : {}
|
|
20567
|
+
};
|
|
20568
|
+
const result = await configureCustomApi(input);
|
|
20569
|
+
if (!result.ok) {
|
|
20570
|
+
process.stderr.write(`\u2717 ${result.error.message}
|
|
20571
|
+
`);
|
|
20572
|
+
return EXIT_CODES.SERVER_START_FAILED;
|
|
20573
|
+
}
|
|
20574
|
+
const { baseUrl: canonical, model, probeSucceeded, shellFragment } = result.value;
|
|
20575
|
+
process.stdout.write(`\u2713 Gateway validated: ${canonical}
|
|
20576
|
+
`);
|
|
20577
|
+
process.stdout.write(`\u2713 Model: ${model}
|
|
20578
|
+
`);
|
|
20579
|
+
if (probeSucceeded) process.stdout.write(`\u2713 Probe succeeded (GET /models \u2192 2xx)
|
|
20580
|
+
`);
|
|
20581
|
+
process.stdout.write("\nAdd the following to your shell rc (~/.bashrc, ~/.zshrc, etc.):\n\n");
|
|
20582
|
+
process.stdout.write(shellFragment);
|
|
20583
|
+
return EXIT_CODES.SUCCESS;
|
|
20584
|
+
}
|
|
20543
20585
|
function handleHelloCommand(_args) {
|
|
20544
20586
|
const exitCode = helloCommand();
|
|
20545
20587
|
process.exit(exitCode === 0 ? EXIT_CODES.SUCCESS : EXIT_CODES.SERVER_START_FAILED);
|
|
@@ -22774,7 +22816,16 @@ var SETUP_HELP = {
|
|
|
22774
22816
|
description: "MCP config scope: user, project",
|
|
22775
22817
|
defaultValue: "user"
|
|
22776
22818
|
},
|
|
22777
|
-
{ flag: "--dry-run", description: "Show changes without applying them" }
|
|
22819
|
+
{ flag: "--dry-run", description: "Show changes without applying them" },
|
|
22820
|
+
{
|
|
22821
|
+
flag: "--custom-api <url>",
|
|
22822
|
+
description: "Configure OpenAI-compatible gateway (short-circuits normal setup; validates URL + probes /models) [#2124]"
|
|
22823
|
+
},
|
|
22824
|
+
{ flag: "--custom-api-key <key>", description: "API key for --custom-api (else prompt/env)" },
|
|
22825
|
+
{
|
|
22826
|
+
flag: "--custom-model <id>",
|
|
22827
|
+
description: "Default model for --custom-api (default: gpt-4o)"
|
|
22828
|
+
}
|
|
22778
22829
|
]
|
|
22779
22830
|
};
|
|
22780
22831
|
var CONFIG_HELP = {
|