@cnwenf/occ 2.1.290 → 2.1.292
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/README.md +4 -4
- package/README.zh-CN.md +2 -2
- package/dist/cli.js +294 -52
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@cnwenf/occ)
|
|
6
6
|
[](./LICENSE)
|
|
7
7
|
[](https://bun.sh/)
|
|
8
|
-
[](https://docs.anthropic.com/en/docs/claude-code)
|
|
9
9
|
|
|
10
10
|
[简体中文](./README.zh-CN.md) · **English**
|
|
11
11
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
## What is OCC
|
|
15
15
|
|
|
16
|
-
**Open C Code (OCC)** is an open-source coding agent. Its capabilities are aligned with [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (currently tracking `2.1.218
|
|
16
|
+
**Open C Code (OCC)** is an open-source coding agent. Its capabilities are aligned with [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (currently tracking `2.1.219` — 2.1.218 fully aligned, 2.1.219 partial per OCC-43 gap report). The code is fully open, auditable, backdoor-free, and your data stays under your control.
|
|
17
17
|
|
|
18
18
|
If you worry that a closed-source CLI might hide backdoors, or that your code and credentials are uploaded to unauditable services, OCC is for you: all source is open and unobfuscated, the build is reproducible from source, and API credentials are sent only to endpoints you configure.
|
|
19
19
|
|
|
@@ -62,7 +62,7 @@ Requires a valid Anthropic API Key (or AWS Bedrock / Google Vertex / Azure Found
|
|
|
62
62
|
| **Auditability** | Line-by-line reviewable | No |
|
|
63
63
|
| **Telemetry** | Minimal (analytics stubbed) | Standard |
|
|
64
64
|
| **Data sovereignty** | Credentials stay on your machine; requests only to endpoints you configure | Anthropic endpoints |
|
|
65
|
-
| **Capability parity** | Tracks CC `2.1.
|
|
65
|
+
| **Capability parity** | Tracks CC `2.1.219` (partial) | Reference implementation |
|
|
66
66
|
| **Providers** | Anthropic Direct, Bedrock, Vertex, Azure | Anthropic, Bedrock, Vertex |
|
|
67
67
|
| **Cost** | Free & open-source (MIT) | Subscription |
|
|
68
68
|
| **Build** | Reproducible from source | N/A |
|
|
@@ -157,7 +157,7 @@ For architecture, entry/bootstrap, tool system, UI layer, and module-status deta
|
|
|
157
157
|
|
|
158
158
|
## Status
|
|
159
159
|
|
|
160
|
-
- Tracks Claude Code **`2.1.
|
|
160
|
+
- Tracks Claude Code **`2.1.219` (partial)**.
|
|
161
161
|
- Published to npm as [`@cnwenf/occ`](https://www.npmjs.com/package/@cnwenf/occ).
|
|
162
162
|
- Many modules are intentionally stubbed or feature-flagged off — see "Disabled / stubbed" above.
|
|
163
163
|
|
package/README.zh-CN.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
## 这是什么
|
|
10
10
|
|
|
11
|
-
**Open C Code(OCC)** 是一个开源的编码智能体。能力与 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 对齐(当前跟踪 `2.1.218
|
|
11
|
+
**Open C Code(OCC)** 是一个开源的编码智能体。能力与 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 对齐(当前跟踪 `2.1.219`:2.1.218 已完全对齐、2.1.219 部分对齐)。代码全开放、可审计、无暗门,数据由你掌控。
|
|
12
12
|
|
|
13
13
|
如果你担心闭源 CLI 可能植入后门、担心代码与凭据被上传到不可审计的服务,OCC 就是为你准备的:全部源码开放、无混淆,构建产物可由源码复现,API 凭据只发往你自己配置的端点。
|
|
14
14
|
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
## 现状
|
|
23
23
|
|
|
24
|
-
- 跟踪 Claude Code **`2.1.218
|
|
24
|
+
- 跟踪 Claude Code **`2.1.219`**(2.1.218 完全对齐、2.1.219 部分对齐)。
|
|
25
25
|
- 代码库有约 1300 个不阻塞的 `tsc` 类型错误(大量松散的 `unknown`/`never`/`{}` 类型),**不影响 Bun 运行时执行**。门槛是 Biome lint,不是 `tsc`。
|
|
26
26
|
- 所有内部 feature flag(`feature(...)`)已被 polyfill 为 `false` —— 内部功能(COORDINATOR_MODE、KAIROS、PROACTIVE 等)全部关闭。
|
|
27
27
|
- 已发布到 npm:[`@cnwenf/occ`](https://www.npmjs.com/package/@cnwenf/occ)。
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
globalThis.MACRO={"VERSION":"2.1.
|
|
2
|
+
globalThis.MACRO={"VERSION":"2.1.292","BINARY_NAME":"occ","BUILD_TIME":"2026-08-03T20:56:55.105Z","FEEDBACK_CHANNEL":"","ISSUES_EXPLAINER":"","NATIVE_PACKAGE_URL":"","PACKAGE_URL":"@cnwenf/occ","VERSION_CHANGELOG":""};
|
|
3
3
|
// @bun
|
|
4
4
|
var __create = Object.create;
|
|
5
5
|
var __getProtoOf = Object.getPrototypeOf;
|
|
@@ -57625,6 +57625,7 @@ var init_sandboxTypes = __esm(() => {
|
|
|
57625
57625
|
allowedDomains: exports_external.array(exports_external.string()).optional(),
|
|
57626
57626
|
deniedDomains: exports_external.array(exports_external.string()).optional().describe("Domains to block even when a broader allowedDomains wildcard would otherwise permit them."),
|
|
57627
57627
|
allowManagedDomainsOnly: exports_external.boolean().optional().describe("When true (and set in managed settings), only allowedDomains and WebFetch(domain:...) allow rules from managed settings are respected. " + "User, project, local, and flag settings domains are ignored. Denied domains are still respected from all sources."),
|
|
57628
|
+
strictAllowlist: exports_external.boolean().optional().describe("When true, the sandbox runtime deterministically denies hosts not in allowedDomains instead of prompting. " + "Enforced for sandboxed commands only \u2014 in-process tools such as WebFetch are not gated by this setting. " + "Only honored from user, managed/policy, or CLI (--settings) settings \u2014 " + "project settings (.claude/settings.json and .claude/settings.local.json) are ignored."),
|
|
57628
57629
|
allowUnixSockets: exports_external.array(exports_external.string()).optional().describe("macOS only: Unix socket paths to allow. Ignored on Linux (seccomp cannot filter by path)."),
|
|
57629
57630
|
allowAllUnixSockets: exports_external.boolean().optional().describe("If true, allow all Unix sockets (disables blocking on both platforms)."),
|
|
57630
57631
|
allowLocalBinding: exports_external.boolean().optional(),
|
|
@@ -58237,7 +58238,7 @@ var init_hooks = __esm(() => {
|
|
|
58237
58238
|
});
|
|
58238
58239
|
|
|
58239
58240
|
// src/services/mcp/types.ts
|
|
58240
|
-
var ConfigScopeSchema, TransportSchema, McpStdioServerConfigSchema, McpXaaConfigSchema, McpOAuthConfigSchema, McpSSEServerConfigSchema, McpSSEIDEServerConfigSchema, McpWebSocketIDEServerConfigSchema, McpHTTPServerConfigSchema, McpWebSocketServerConfigSchema, McpSdkServerConfigSchema, McpClaudeAIProxyServerConfigSchema, McpServerConfigSchema, McpJsonConfigSchema;
|
|
58241
|
+
var ConfigScopeSchema, TransportSchema, McpStdioServerConfigSchema, McpXaaConfigSchema, McpOAuthConfigSchema, McpSSEServerConfigSchema, McpSSEIDEServerConfigSchema, McpWebSocketIDEServerConfigSchema, McpHTTPServerConfigSchema, McpWebSocketServerConfigSchema, McpSdkServerConfigSchema, McpClaudeAIProxyServerConfigSchema, McpServerConfigSchema, McpJsonConfigSchema, McpJsonConfigShapeSchema, MCP_SERVER_TYPE_SCHEMA_REGISTRY;
|
|
58241
58242
|
var init_types = __esm(() => {
|
|
58242
58243
|
init_v4();
|
|
58243
58244
|
ConfigScopeSchema = lazySchema(() => exports_external.enum([
|
|
@@ -58274,7 +58275,9 @@ var init_types = __esm(() => {
|
|
|
58274
58275
|
headersHelper: exports_external.string().optional(),
|
|
58275
58276
|
oauth: McpOAuthConfigSchema().optional(),
|
|
58276
58277
|
alwaysLoad: exports_external.boolean().optional(),
|
|
58277
|
-
request_timeout_ms: exports_external.number().int().positive().optional()
|
|
58278
|
+
request_timeout_ms: exports_external.number().int().positive().optional(),
|
|
58279
|
+
configError: exports_external.string().optional(),
|
|
58280
|
+
configErrorReason: exports_external.string().optional()
|
|
58278
58281
|
}));
|
|
58279
58282
|
McpSSEIDEServerConfigSchema = lazySchema(() => exports_external.object({
|
|
58280
58283
|
type: exports_external.literal("sse-ide"),
|
|
@@ -58290,13 +58293,15 @@ var init_types = __esm(() => {
|
|
|
58290
58293
|
ideRunningInWindows: exports_external.boolean().optional()
|
|
58291
58294
|
}));
|
|
58292
58295
|
McpHTTPServerConfigSchema = lazySchema(() => exports_external.object({
|
|
58293
|
-
type: exports_external.
|
|
58296
|
+
type: exports_external.enum(["http", "streamable-http"]).transform(() => "http"),
|
|
58294
58297
|
url: exports_external.string(),
|
|
58295
58298
|
headers: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
58296
58299
|
headersHelper: exports_external.string().optional(),
|
|
58297
58300
|
oauth: McpOAuthConfigSchema().optional(),
|
|
58298
58301
|
alwaysLoad: exports_external.boolean().optional(),
|
|
58299
|
-
request_timeout_ms: exports_external.number().int().positive().optional()
|
|
58302
|
+
request_timeout_ms: exports_external.number().int().positive().optional(),
|
|
58303
|
+
configError: exports_external.string().optional(),
|
|
58304
|
+
configErrorReason: exports_external.string().optional()
|
|
58300
58305
|
}));
|
|
58301
58306
|
McpWebSocketServerConfigSchema = lazySchema(() => exports_external.object({
|
|
58302
58307
|
type: exports_external.literal("ws"),
|
|
@@ -58304,7 +58309,9 @@ var init_types = __esm(() => {
|
|
|
58304
58309
|
headers: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
58305
58310
|
headersHelper: exports_external.string().optional(),
|
|
58306
58311
|
alwaysLoad: exports_external.boolean().optional(),
|
|
58307
|
-
request_timeout_ms: exports_external.number().int().positive().optional()
|
|
58312
|
+
request_timeout_ms: exports_external.number().int().positive().optional(),
|
|
58313
|
+
configError: exports_external.string().optional(),
|
|
58314
|
+
configErrorReason: exports_external.string().optional()
|
|
58308
58315
|
}));
|
|
58309
58316
|
McpSdkServerConfigSchema = lazySchema(() => exports_external.object({
|
|
58310
58317
|
type: exports_external.literal("sdk"),
|
|
@@ -58329,6 +58336,18 @@ var init_types = __esm(() => {
|
|
|
58329
58336
|
McpJsonConfigSchema = lazySchema(() => exports_external.object({
|
|
58330
58337
|
mcpServers: exports_external.record(exports_external.string(), McpServerConfigSchema())
|
|
58331
58338
|
}));
|
|
58339
|
+
McpJsonConfigShapeSchema = lazySchema(() => exports_external.object({
|
|
58340
|
+
mcpServers: exports_external.record(exports_external.string(), exports_external.unknown())
|
|
58341
|
+
}));
|
|
58342
|
+
MCP_SERVER_TYPE_SCHEMA_REGISTRY = {
|
|
58343
|
+
stdio: McpStdioServerConfigSchema,
|
|
58344
|
+
sse: McpSSEServerConfigSchema,
|
|
58345
|
+
http: McpHTTPServerConfigSchema,
|
|
58346
|
+
"streamable-http": McpHTTPServerConfigSchema,
|
|
58347
|
+
ws: McpWebSocketServerConfigSchema,
|
|
58348
|
+
sdk: McpSdkServerConfigSchema,
|
|
58349
|
+
"claudeai-proxy": McpClaudeAIProxyServerConfigSchema
|
|
58350
|
+
};
|
|
58332
58351
|
});
|
|
58333
58352
|
|
|
58334
58353
|
// src/utils/plugins/schemas.ts
|
|
@@ -201072,6 +201091,7 @@ Usage notes:
|
|
|
201072
201091
|
// src/utils/sandbox/sandbox-adapter.ts
|
|
201073
201092
|
var exports_sandbox_adapter = {};
|
|
201074
201093
|
__export(exports_sandbox_adapter, {
|
|
201094
|
+
shouldEnforceStrictAllowlist: () => shouldEnforceStrictAllowlist,
|
|
201075
201095
|
shouldAllowManagedSandboxDomainsOnly: () => shouldAllowManagedSandboxDomainsOnly,
|
|
201076
201096
|
resolveSandboxFilesystemPath: () => resolveSandboxFilesystemPath,
|
|
201077
201097
|
resolvePathPatternForSandbox: () => resolvePathPatternForSandbox,
|
|
@@ -201119,6 +201139,14 @@ function resolveSandboxFilesystemPath(pattern, source) {
|
|
|
201119
201139
|
function shouldAllowManagedSandboxDomainsOnly() {
|
|
201120
201140
|
return getSettingsForSource("policySettings")?.sandbox?.network?.allowManagedDomainsOnly === true;
|
|
201121
201141
|
}
|
|
201142
|
+
function shouldEnforceStrictAllowlist() {
|
|
201143
|
+
const honoredSources = [
|
|
201144
|
+
"userSettings",
|
|
201145
|
+
"flagSettings",
|
|
201146
|
+
"policySettings"
|
|
201147
|
+
];
|
|
201148
|
+
return honoredSources.some((source) => getSettingsForSource(source)?.sandbox?.network?.strictAllowlist === true);
|
|
201149
|
+
}
|
|
201122
201150
|
function shouldAllowManagedReadPathsOnly() {
|
|
201123
201151
|
return getSettingsForSource("policySettings")?.sandbox?.filesystem?.allowManagedReadPathsOnly === true;
|
|
201124
201152
|
}
|
|
@@ -201480,6 +201508,10 @@ async function initialize3(sandboxAskCallback) {
|
|
|
201480
201508
|
logForDebugging(`[sandbox] Blocked network request to ${hostPattern.host} (allowManagedDomainsOnly)`);
|
|
201481
201509
|
return false;
|
|
201482
201510
|
}
|
|
201511
|
+
if (shouldEnforceStrictAllowlist()) {
|
|
201512
|
+
logForDebugging(`[sandbox] Blocked network request to ${hostPattern.host} (strictAllowlist)`);
|
|
201513
|
+
return false;
|
|
201514
|
+
}
|
|
201483
201515
|
return sandboxAskCallback(hostPattern);
|
|
201484
201516
|
} : undefined;
|
|
201485
201517
|
initializationPromise2 = (async () => {
|
|
@@ -386578,6 +386610,7 @@ function filterMcpServersByPolicy(configs) {
|
|
|
386578
386610
|
}
|
|
386579
386611
|
function expandEnvVars(config6) {
|
|
386580
386612
|
const missingVars = [];
|
|
386613
|
+
let urlExpandedToEmpty = false;
|
|
386581
386614
|
function expandString(str2) {
|
|
386582
386615
|
const { expanded: expanded2, missingVars: vars } = expandEnvVarsInString(str2);
|
|
386583
386616
|
missingVars.push(...vars);
|
|
@@ -386600,9 +386633,11 @@ function expandEnvVars(config6) {
|
|
|
386600
386633
|
case "http":
|
|
386601
386634
|
case "ws": {
|
|
386602
386635
|
const remoteConfig = config6;
|
|
386636
|
+
const expandedUrl = expandString(remoteConfig.url);
|
|
386637
|
+
urlExpandedToEmpty = remoteConfig.url.trim() !== "" && expandedUrl.trim() === "";
|
|
386603
386638
|
expanded = {
|
|
386604
386639
|
...remoteConfig,
|
|
386605
|
-
url:
|
|
386640
|
+
url: expandedUrl,
|
|
386606
386641
|
headers: remoteConfig.headers ? mapValues_default(remoteConfig.headers, expandString) : undefined
|
|
386607
386642
|
};
|
|
386608
386643
|
break;
|
|
@@ -386620,7 +386655,8 @@ function expandEnvVars(config6) {
|
|
|
386620
386655
|
}
|
|
386621
386656
|
return {
|
|
386622
386657
|
expanded,
|
|
386623
|
-
missingVars: [...new Set(missingVars)]
|
|
386658
|
+
missingVars: [...new Set(missingVars)],
|
|
386659
|
+
urlExpandedToEmpty
|
|
386624
386660
|
};
|
|
386625
386661
|
}
|
|
386626
386662
|
async function addMcpConfig(name3, config6, scope) {
|
|
@@ -387095,6 +387131,19 @@ function parseMcpConfig(params) {
|
|
|
387095
387131
|
}
|
|
387096
387132
|
function parseMcpConfigFromFilePath(params) {
|
|
387097
387133
|
const { filePath, expandVars, scope } = params;
|
|
387134
|
+
const read = readMcpConfigFileContents({ filePath, scope });
|
|
387135
|
+
if (read.errors) {
|
|
387136
|
+
return { config: null, errors: read.errors };
|
|
387137
|
+
}
|
|
387138
|
+
return parseMcpConfig({
|
|
387139
|
+
configObject: read.parsedJson,
|
|
387140
|
+
expandVars,
|
|
387141
|
+
scope,
|
|
387142
|
+
filePath
|
|
387143
|
+
});
|
|
387144
|
+
}
|
|
387145
|
+
function readMcpConfigFileContents(params) {
|
|
387146
|
+
const { filePath, scope } = params;
|
|
387098
387147
|
const fs17 = getFsImplementation();
|
|
387099
387148
|
let configContent;
|
|
387100
387149
|
try {
|
|
@@ -387103,7 +387152,6 @@ function parseMcpConfigFromFilePath(params) {
|
|
|
387103
387152
|
const code = getErrnoCode(error52);
|
|
387104
387153
|
if (code === "ENOENT") {
|
|
387105
387154
|
return {
|
|
387106
|
-
config: null,
|
|
387107
387155
|
errors: [
|
|
387108
387156
|
{
|
|
387109
387157
|
file: filePath,
|
|
@@ -387120,7 +387168,6 @@ function parseMcpConfigFromFilePath(params) {
|
|
|
387120
387168
|
}
|
|
387121
387169
|
logForDebugging(`MCP config read error for ${filePath} (scope=${scope}): ${error52}`, { level: "error" });
|
|
387122
387170
|
return {
|
|
387123
|
-
config: null,
|
|
387124
387171
|
errors: [
|
|
387125
387172
|
{
|
|
387126
387173
|
file: filePath,
|
|
@@ -387139,7 +387186,6 @@ function parseMcpConfigFromFilePath(params) {
|
|
|
387139
387186
|
if (!parsedJson) {
|
|
387140
387187
|
logForDebugging(`MCP config is not valid JSON: ${filePath} (scope=${scope}, length=${configContent.length}, first100=${jsonStringify(configContent.slice(0, 100))})`, { level: "error" });
|
|
387141
387188
|
return {
|
|
387142
|
-
config: null,
|
|
387143
387189
|
errors: [
|
|
387144
387190
|
{
|
|
387145
387191
|
file: filePath,
|
|
@@ -387154,8 +387200,145 @@ function parseMcpConfigFromFilePath(params) {
|
|
|
387154
387200
|
]
|
|
387155
387201
|
};
|
|
387156
387202
|
}
|
|
387157
|
-
return
|
|
387158
|
-
|
|
387203
|
+
return { parsedJson };
|
|
387204
|
+
}
|
|
387205
|
+
function isReservedMcpServerName(name3) {
|
|
387206
|
+
return isClaudeInChromeMCPServer(name3) || isComputerUseMCPServer(name3) || isReservedClaudeBrowserName(name3) || name3 === "workspace";
|
|
387207
|
+
}
|
|
387208
|
+
function findMcpConfigWhitespaceIssues(config6) {
|
|
387209
|
+
const issues = [];
|
|
387210
|
+
function check3(label, value) {
|
|
387211
|
+
if (value !== value.trim()) {
|
|
387212
|
+
issues.push(label);
|
|
387213
|
+
}
|
|
387214
|
+
}
|
|
387215
|
+
if ("command" in config6) {
|
|
387216
|
+
check3("command", config6.command);
|
|
387217
|
+
}
|
|
387218
|
+
if ("url" in config6) {
|
|
387219
|
+
check3("url", config6.url);
|
|
387220
|
+
}
|
|
387221
|
+
if ("args" in config6 && config6.args) {
|
|
387222
|
+
config6.args.forEach((arg, index2) => check3(`args[${index2}]`, arg));
|
|
387223
|
+
}
|
|
387224
|
+
if ("env" in config6 && config6.env) {
|
|
387225
|
+
for (const [envName, envValue] of Object.entries(config6.env)) {
|
|
387226
|
+
if (envName !== envName.trim()) {
|
|
387227
|
+
issues.push(`env name ${jsonStringify(envName)}`);
|
|
387228
|
+
}
|
|
387229
|
+
check3(`env.${envName}`, envValue);
|
|
387230
|
+
}
|
|
387231
|
+
}
|
|
387232
|
+
if ("headers" in config6 && config6.headers) {
|
|
387233
|
+
for (const [headerName, headerValue] of Object.entries(config6.headers)) {
|
|
387234
|
+
if (headerName !== headerName.trim()) {
|
|
387235
|
+
issues.push(`header name ${jsonStringify(headerName)}`);
|
|
387236
|
+
}
|
|
387237
|
+
check3(`headers.${headerName}`, headerValue);
|
|
387238
|
+
}
|
|
387239
|
+
}
|
|
387240
|
+
return issues;
|
|
387241
|
+
}
|
|
387242
|
+
function parseDynamicMcpConfig(params) {
|
|
387243
|
+
const { configObject, expandVars, scope, filePath } = params;
|
|
387244
|
+
const shapeResult = McpJsonConfigShapeSchema().safeParse(configObject);
|
|
387245
|
+
if (!shapeResult.success) {
|
|
387246
|
+
const foundServersKeyInstead = configObject !== null && typeof configObject === "object" && "servers" in configObject && !("mcpServers" in configObject);
|
|
387247
|
+
return {
|
|
387248
|
+
config: null,
|
|
387249
|
+
errors: shapeResult.error.issues.map((issue2) => ({
|
|
387250
|
+
...filePath && { file: filePath },
|
|
387251
|
+
path: issue2.path.join("."),
|
|
387252
|
+
message: foundServersKeyInstead ? 'Missing "mcpServers" \u2014 found "servers" instead. Claude Code reads MCP servers from the "mcpServers" key.' : issue2.message,
|
|
387253
|
+
...foundServersKeyInstead && {
|
|
387254
|
+
suggestion: `Rename the top-level "servers" key to "mcpServers" in ${filePath ?? "your MCP config"}.`
|
|
387255
|
+
},
|
|
387256
|
+
mcpErrorMetadata: {
|
|
387257
|
+
scope,
|
|
387258
|
+
severity: "fatal"
|
|
387259
|
+
}
|
|
387260
|
+
}))
|
|
387261
|
+
};
|
|
387262
|
+
}
|
|
387263
|
+
const errors8 = [];
|
|
387264
|
+
const validatedServers = {};
|
|
387265
|
+
function pushEntryError(serverName, message, suggestion, skipReason) {
|
|
387266
|
+
errors8.push({
|
|
387267
|
+
...filePath && { file: filePath },
|
|
387268
|
+
path: `mcpServers.${serverName}`,
|
|
387269
|
+
message,
|
|
387270
|
+
...suggestion && { suggestion },
|
|
387271
|
+
mcpErrorMetadata: {
|
|
387272
|
+
scope,
|
|
387273
|
+
serverName,
|
|
387274
|
+
severity: "warning",
|
|
387275
|
+
...skipReason && { skipReason }
|
|
387276
|
+
}
|
|
387277
|
+
});
|
|
387278
|
+
}
|
|
387279
|
+
const rawServers = configObject.mcpServers;
|
|
387280
|
+
if (Object.hasOwn(rawServers, "__proto__") && !Object.hasOwn(shapeResult.data.mcpServers, "__proto__")) {
|
|
387281
|
+
pushEntryError("__proto__", '"__proto__" is a reserved MCP server name and was not loaded', 'Rename this server in your MCP config \u2014 "__proto__" cannot be used as a server name', "reserved_name");
|
|
387282
|
+
}
|
|
387283
|
+
for (const [name3, rawEntry] of Object.entries(shapeResult.data.mcpServers)) {
|
|
387284
|
+
const declaredType = rawEntry && typeof rawEntry === "object" && "type" in rawEntry && typeof rawEntry.type === "string" ? rawEntry.type : "stdio";
|
|
387285
|
+
const schemaGetter = Object.hasOwn(MCP_SERVER_TYPE_SCHEMA_REGISTRY, declaredType) ? MCP_SERVER_TYPE_SCHEMA_REGISTRY[declaredType] : undefined;
|
|
387286
|
+
if (!schemaGetter) {
|
|
387287
|
+
pushEntryError(name3, `Skipped \u2014 unknown MCP server type "${declaredType}" for server "${name3}"`, "Valid types are: stdio, sse, http (or streamable-http), ws, sdk", "unknown_type");
|
|
387288
|
+
continue;
|
|
387289
|
+
}
|
|
387290
|
+
const entryResult = schemaGetter().safeParse(rawEntry);
|
|
387291
|
+
if (!entryResult.success) {
|
|
387292
|
+
if (rawEntry !== null && typeof rawEntry === "object" && !("type" in rawEntry) && "url" in rawEntry && !("command" in rawEntry)) {
|
|
387293
|
+
pushEntryError(name3, `Skipped \u2014 MCP server "${name3}" has a "url" but no "type"; add "type": "http" (or "sse" / "ws") to this entry`, undefined, "url_missing_type");
|
|
387294
|
+
continue;
|
|
387295
|
+
}
|
|
387296
|
+
const details = entryResult.error.issues.map((issue2) => {
|
|
387297
|
+
const issueMessage = issue2.message.replace(/^Invalid input: /, "");
|
|
387298
|
+
return `${issue2.path.join(".") || "(root)"}: ${issueMessage}`;
|
|
387299
|
+
}).join("; ");
|
|
387300
|
+
pushEntryError(name3, `Skipped \u2014 invalid MCP server config for "${name3}": ${details}`, undefined, "invalid_config");
|
|
387301
|
+
continue;
|
|
387302
|
+
}
|
|
387303
|
+
const validated = entryResult.data;
|
|
387304
|
+
if (isReservedMcpServerName(name3) && validated.type !== "sdk") {
|
|
387305
|
+
pushEntryError(name3, `"${name3}" is a reserved MCP server name and was not loaded`, `Rename this server in your MCP config \u2014 "${name3}" is reserved for internal use`, "reserved_name");
|
|
387306
|
+
continue;
|
|
387307
|
+
}
|
|
387308
|
+
const whitespaceIssues = findMcpConfigWhitespaceIssues(validated);
|
|
387309
|
+
if (whitespaceIssues.length > 0) {
|
|
387310
|
+
pushEntryError(name3, `Leading or trailing whitespace in: ${whitespaceIssues.join(", ")}`, `Remove the whitespace from these values in the "${name3}" entry \u2014 they are used exactly as written`, undefined);
|
|
387311
|
+
}
|
|
387312
|
+
let serverConfig = validated;
|
|
387313
|
+
if (expandVars) {
|
|
387314
|
+
const { expanded, missingVars, urlExpandedToEmpty } = expandEnvVars(validated);
|
|
387315
|
+
if (missingVars.length > 0) {
|
|
387316
|
+
pushEntryError(name3, `Missing environment variables: ${missingVars.join(", ")}`, `Set the following environment variables: ${missingVars.join(", ")}`, undefined);
|
|
387317
|
+
}
|
|
387318
|
+
serverConfig = expanded;
|
|
387319
|
+
if (urlExpandedToEmpty && "url" in validated) {
|
|
387320
|
+
serverConfig = {
|
|
387321
|
+
...expanded,
|
|
387322
|
+
configError: `'url' ${jsonStringify(validated.url)} expanded to an empty string. Set the referenced environment variable, or update the server's config and reconnect.`,
|
|
387323
|
+
configErrorReason: "url_invalid"
|
|
387324
|
+
};
|
|
387325
|
+
}
|
|
387326
|
+
}
|
|
387327
|
+
validatedServers[name3] = serverConfig;
|
|
387328
|
+
}
|
|
387329
|
+
return {
|
|
387330
|
+
config: { mcpServers: validatedServers },
|
|
387331
|
+
errors: errors8
|
|
387332
|
+
};
|
|
387333
|
+
}
|
|
387334
|
+
function parseDynamicMcpConfigFromFile(params) {
|
|
387335
|
+
const { filePath, expandVars, scope } = params;
|
|
387336
|
+
const read = readMcpConfigFileContents({ filePath, scope });
|
|
387337
|
+
if (read.errors) {
|
|
387338
|
+
return { config: null, errors: read.errors };
|
|
387339
|
+
}
|
|
387340
|
+
return parseDynamicMcpConfig({
|
|
387341
|
+
configObject: read.parsedJson,
|
|
387159
387342
|
expandVars,
|
|
387160
387343
|
scope,
|
|
387161
387344
|
filePath
|
|
@@ -387215,6 +387398,7 @@ var init_config6 = __esm(() => {
|
|
|
387215
387398
|
init_memoize();
|
|
387216
387399
|
init_platform2();
|
|
387217
387400
|
init_common4();
|
|
387401
|
+
init_common();
|
|
387218
387402
|
init_config4();
|
|
387219
387403
|
init_cwd2();
|
|
387220
387404
|
init_debug();
|
|
@@ -578430,10 +578614,15 @@ function getSonnet46Option() {
|
|
|
578430
578614
|
descriptionForModel: "Sonnet 4.6 - previous Sonnet version"
|
|
578431
578615
|
};
|
|
578432
578616
|
}
|
|
578617
|
+
function shouldUseCustomModelOptions() {
|
|
578618
|
+
const provider5 = getAPIProvider();
|
|
578619
|
+
const isAnthropicOwned = provider5 === "firstParty" || provider5 === "anthropic_aws" || provider5 === "gateway";
|
|
578620
|
+
const isAwsOrGoogleCloud = provider5 === "anthropic_aws";
|
|
578621
|
+
return !isAnthropicOwned || isAwsOrGoogleCloud || !isFirstPartyAnthropicBaseUrl();
|
|
578622
|
+
}
|
|
578433
578623
|
function getCustomFableOption() {
|
|
578434
|
-
const is3P = getAPIProvider() !== "firstParty";
|
|
578435
578624
|
const customFableModel = process.env.ANTHROPIC_DEFAULT_FABLE_MODEL;
|
|
578436
|
-
if (
|
|
578625
|
+
if (shouldUseCustomModelOptions() && customFableModel) {
|
|
578437
578626
|
return {
|
|
578438
578627
|
value: "fable",
|
|
578439
578628
|
label: process.env.ANTHROPIC_DEFAULT_FABLE_MODEL_NAME ?? customFableModel,
|
|
@@ -578456,9 +578645,8 @@ function getFable5Option() {
|
|
|
578456
578645
|
};
|
|
578457
578646
|
}
|
|
578458
578647
|
function getCustomSonnetOption() {
|
|
578459
|
-
const is3P = getAPIProvider() !== "firstParty";
|
|
578460
578648
|
const customSonnetModel = process.env.ANTHROPIC_DEFAULT_SONNET_MODEL;
|
|
578461
|
-
if (
|
|
578649
|
+
if (shouldUseCustomModelOptions() && customSonnetModel) {
|
|
578462
578650
|
const is1m = has1mContext(customSonnetModel);
|
|
578463
578651
|
return {
|
|
578464
578652
|
value: "sonnet",
|
|
@@ -578469,9 +578657,8 @@ function getCustomSonnetOption() {
|
|
|
578469
578657
|
}
|
|
578470
578658
|
}
|
|
578471
578659
|
function getCustomOpusOption() {
|
|
578472
|
-
const is3P = getAPIProvider() !== "firstParty";
|
|
578473
578660
|
const customOpusModel = process.env.ANTHROPIC_DEFAULT_OPUS_MODEL;
|
|
578474
|
-
if (
|
|
578661
|
+
if (shouldUseCustomModelOptions() && customOpusModel) {
|
|
578475
578662
|
const is1m = has1mContext(customOpusModel);
|
|
578476
578663
|
return {
|
|
578477
578664
|
value: "opus",
|
|
@@ -578544,9 +578731,8 @@ function getOpus46_1MOption(fastMode = false) {
|
|
|
578544
578731
|
};
|
|
578545
578732
|
}
|
|
578546
578733
|
function getCustomHaikuOption() {
|
|
578547
|
-
const is3P = getAPIProvider() !== "firstParty";
|
|
578548
578734
|
const customHaikuModel = process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL;
|
|
578549
|
-
if (
|
|
578735
|
+
if (shouldUseCustomModelOptions() && customHaikuModel) {
|
|
578550
578736
|
return {
|
|
578551
578737
|
value: "haiku",
|
|
578552
578738
|
label: process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME ?? customHaikuModel,
|
|
@@ -578663,6 +578849,33 @@ function getModelOptionsBase(fastMode = false) {
|
|
|
578663
578849
|
return standardOptions;
|
|
578664
578850
|
}
|
|
578665
578851
|
if (getAPIProvider() === "firstParty") {
|
|
578852
|
+
const customOpus2 = getCustomOpusOption();
|
|
578853
|
+
const customSonnet2 = getCustomSonnetOption();
|
|
578854
|
+
const customHaiku2 = getCustomHaikuOption();
|
|
578855
|
+
const customFable = getCustomFableOption();
|
|
578856
|
+
if (customOpus2 || customSonnet2 || customHaiku2 || customFable) {
|
|
578857
|
+
const customOptions = [getDefaultOptionForUser(fastMode)];
|
|
578858
|
+
if (customOpus2 !== undefined) {
|
|
578859
|
+
customOptions.push(customOpus2);
|
|
578860
|
+
} else if (isOpus1mMergeEnabled()) {
|
|
578861
|
+
customOptions.push(getMergedOpus1MOption(fastMode));
|
|
578862
|
+
} else {
|
|
578863
|
+
customOptions.push(getOpus5Option(fastMode));
|
|
578864
|
+
if (checkOpus1mAccess()) {
|
|
578865
|
+
customOptions.push(getOpus5_1MOption(fastMode));
|
|
578866
|
+
}
|
|
578867
|
+
}
|
|
578868
|
+
if (customFable !== undefined) {
|
|
578869
|
+
customOptions.push(customFable);
|
|
578870
|
+
}
|
|
578871
|
+
if (customSonnet2 !== undefined) {
|
|
578872
|
+
customOptions.push(customSonnet2);
|
|
578873
|
+
} else if (checkSonnet1mAccess()) {
|
|
578874
|
+
customOptions.push(getSonnet5_1MOption());
|
|
578875
|
+
}
|
|
578876
|
+
customOptions.push(customHaiku2 ?? getHaiku45Option());
|
|
578877
|
+
return customOptions;
|
|
578878
|
+
}
|
|
578666
578879
|
const payg1POptions = [getDefaultOptionForUser(fastMode)];
|
|
578667
578880
|
if (checkSonnet1mAccess()) {
|
|
578668
578881
|
payg1POptions.push(getSonnet5_1MOption());
|
|
@@ -812658,6 +812871,18 @@ var init_xaaIdpCommand = __esm(() => {
|
|
|
812658
812871
|
init_settings2();
|
|
812659
812872
|
});
|
|
812660
812873
|
|
|
812874
|
+
// src/services/mcp/skippedMcpServerErrors.ts
|
|
812875
|
+
function recordSkippedMcpServerErrors(errors8) {
|
|
812876
|
+
skippedMcpServerErrors.push(...errors8);
|
|
812877
|
+
}
|
|
812878
|
+
function getSkippedMcpServerErrors() {
|
|
812879
|
+
return skippedMcpServerErrors;
|
|
812880
|
+
}
|
|
812881
|
+
var skippedMcpServerErrors;
|
|
812882
|
+
var init_skippedMcpServerErrors = __esm(() => {
|
|
812883
|
+
skippedMcpServerErrors = [];
|
|
812884
|
+
});
|
|
812885
|
+
|
|
812661
812886
|
// src/utils/cliArgs.ts
|
|
812662
812887
|
function eagerParseCliFlag(flagName, argv = process.argv) {
|
|
812663
812888
|
for (let i6 = 0;i6 < argv.length; i6++) {
|
|
@@ -814911,7 +815136,7 @@ class QueryEngine {
|
|
|
814911
815136
|
yield buildSystemInitMessage({
|
|
814912
815137
|
tools,
|
|
814913
815138
|
mcpClients,
|
|
814914
|
-
mcpServerErrors:
|
|
815139
|
+
mcpServerErrors: getSkippedMcpServerErrors(),
|
|
814915
815140
|
model: mainLoopModel,
|
|
814916
815141
|
permissionMode: initialAppState.toolPermissionContext.mode,
|
|
814917
815142
|
commands: commands7,
|
|
@@ -815458,6 +815683,7 @@ var init_QueryEngine = __esm(() => {
|
|
|
815458
815683
|
init_paths();
|
|
815459
815684
|
init_query2();
|
|
815460
815685
|
init_errors10();
|
|
815686
|
+
init_skippedMcpServerErrors();
|
|
815461
815687
|
init_Tool();
|
|
815462
815688
|
init_SyntheticOutputTool();
|
|
815463
815689
|
init_pointer();
|
|
@@ -823631,13 +823857,14 @@ ${addendum}` : addendum;
|
|
|
823631
823857
|
if (mcpConfig && mcpConfig.length > 0) {
|
|
823632
823858
|
const processedConfigs = mcpConfig.map((config8) => config8.trim()).filter((config8) => config8.length > 0);
|
|
823633
823859
|
let allConfigs = {};
|
|
823634
|
-
const
|
|
823860
|
+
const fatalErrors = [];
|
|
823861
|
+
const skippedCandidates = [];
|
|
823635
823862
|
for (const configItem of processedConfigs) {
|
|
823636
823863
|
let configs = null;
|
|
823637
823864
|
let errors8 = [];
|
|
823638
823865
|
const parsedJson = safeParseJSON(configItem);
|
|
823639
823866
|
if (parsedJson) {
|
|
823640
|
-
const result =
|
|
823867
|
+
const result = parseDynamicMcpConfig({
|
|
823641
823868
|
configObject: parsedJson,
|
|
823642
823869
|
filePath: "command line",
|
|
823643
823870
|
expandVars: true,
|
|
@@ -823645,35 +823872,48 @@ ${addendum}` : addendum;
|
|
|
823645
823872
|
});
|
|
823646
823873
|
if (result.config) {
|
|
823647
823874
|
configs = result.config.mcpServers;
|
|
823648
|
-
} else {
|
|
823649
|
-
errors8 = result.errors;
|
|
823650
823875
|
}
|
|
823876
|
+
errors8 = result.errors;
|
|
823651
823877
|
} else {
|
|
823652
823878
|
const configPath = resolve63(configItem);
|
|
823653
|
-
const result =
|
|
823879
|
+
const result = parseDynamicMcpConfigFromFile({
|
|
823654
823880
|
filePath: configPath,
|
|
823655
823881
|
expandVars: true,
|
|
823656
823882
|
scope: "dynamic"
|
|
823657
823883
|
});
|
|
823658
823884
|
if (result.config) {
|
|
823659
823885
|
configs = result.config.mcpServers;
|
|
823660
|
-
} else {
|
|
823661
|
-
errors8 = result.errors;
|
|
823662
823886
|
}
|
|
823887
|
+
errors8 = result.errors;
|
|
823663
823888
|
}
|
|
823664
|
-
if (
|
|
823665
|
-
allErrors.push(...errors8);
|
|
823666
|
-
} else if (configs) {
|
|
823889
|
+
if (configs) {
|
|
823667
823890
|
allConfigs = {
|
|
823668
823891
|
...allConfigs,
|
|
823669
823892
|
...configs
|
|
823670
823893
|
};
|
|
823894
|
+
if (errors8.length > 0) {
|
|
823895
|
+
logForDebugging(`--mcp-config: ${errors8.length} entry warning(s): ${errors8.map((err2) => `${err2.path ? err2.path + ": " : ""}${err2.message}`).join("; ")}`, {
|
|
823896
|
+
level: "warn"
|
|
823897
|
+
});
|
|
823898
|
+
for (const err2 of errors8) {
|
|
823899
|
+
const metadata = err2.mcpErrorMetadata;
|
|
823900
|
+
if (metadata?.skipReason && metadata.serverName != null) {
|
|
823901
|
+
skippedCandidates.push({
|
|
823902
|
+
name: metadata.serverName,
|
|
823903
|
+
type: metadata.skipReason,
|
|
823904
|
+
message: err2.message
|
|
823905
|
+
});
|
|
823906
|
+
}
|
|
823907
|
+
}
|
|
823908
|
+
}
|
|
823909
|
+
} else {
|
|
823910
|
+
fatalErrors.push(...errors8);
|
|
823671
823911
|
}
|
|
823672
823912
|
}
|
|
823673
|
-
if (
|
|
823674
|
-
const formattedErrors =
|
|
823913
|
+
if (fatalErrors.length > 0) {
|
|
823914
|
+
const formattedErrors = fatalErrors.map((err2) => `${err2.path ? err2.path + ": " : ""}${err2.message}`).join(`
|
|
823675
823915
|
`);
|
|
823676
|
-
logForDebugging(`--mcp-config validation failed (${
|
|
823916
|
+
logForDebugging(`--mcp-config validation failed (${fatalErrors.length} errors): ${formattedErrors}`, {
|
|
823677
823917
|
level: "error"
|
|
823678
823918
|
});
|
|
823679
823919
|
process.stderr.write(`Error: Invalid MCP configuration:
|
|
@@ -823681,25 +823921,27 @@ ${formattedErrors}
|
|
|
823681
823921
|
`);
|
|
823682
823922
|
process.exit(1);
|
|
823683
823923
|
}
|
|
823684
|
-
|
|
823685
|
-
|
|
823686
|
-
|
|
823687
|
-
|
|
823688
|
-
reservedNameError = `Invalid MCP configuration: "${CLAUDE_IN_CHROME_MCP_SERVER_NAME}" is a reserved MCP name.`;
|
|
823689
|
-
} else if (feature("CHICAGO_MCP")) {
|
|
823690
|
-
const {
|
|
823691
|
-
isComputerUseMCPServer: isComputerUseMCPServer3,
|
|
823692
|
-
COMPUTER_USE_MCP_SERVER_NAME: COMPUTER_USE_MCP_SERVER_NAME2
|
|
823693
|
-
} = await Promise.resolve().then(() => (init_common(), exports_common));
|
|
823694
|
-
if (nonSdkConfigNames.some(isComputerUseMCPServer3)) {
|
|
823695
|
-
reservedNameError = `Invalid MCP configuration: "${COMPUTER_USE_MCP_SERVER_NAME2}" is a reserved MCP name.`;
|
|
823696
|
-
}
|
|
823924
|
+
const skippedByName = new Map;
|
|
823925
|
+
for (const candidate of skippedCandidates) {
|
|
823926
|
+
if (!Object.hasOwn(allConfigs, candidate.name)) {
|
|
823927
|
+
skippedByName.set(candidate.name, candidate);
|
|
823697
823928
|
}
|
|
823698
|
-
|
|
823699
|
-
|
|
823929
|
+
}
|
|
823930
|
+
if (skippedByName.size > 0) {
|
|
823931
|
+
const skipped = Array.from(skippedByName.values());
|
|
823932
|
+
recordSkippedMcpServerErrors(skipped);
|
|
823933
|
+
if (process.stderr.isTTY) {
|
|
823934
|
+
const sanitize = (message) => {
|
|
823935
|
+
const stripped = typeof Bun !== "undefined" && typeof Bun.stripANSI === "function" ? Bun.stripANSI(message) : message;
|
|
823936
|
+
return stripped.replace(/[\x00-\x1f\x7f-\x9f]+/g, " ").trim();
|
|
823937
|
+
};
|
|
823938
|
+
process.stderr.write(`Warning: ${skipped.length} ${plural(skipped.length, "MCP server")} skipped due to invalid config:
|
|
823939
|
+
${skipped.map((err2) => ` - ${sanitize(err2.message)}`).join(`
|
|
823940
|
+
`)}
|
|
823700
823941
|
`);
|
|
823701
|
-
process.exit(1);
|
|
823702
823942
|
}
|
|
823943
|
+
}
|
|
823944
|
+
if (Object.keys(allConfigs).length > 0) {
|
|
823703
823945
|
const scopedConfigs = mapValues_default(allConfigs, (config8) => ({
|
|
823704
823946
|
...config8,
|
|
823705
823947
|
scope: "dynamic"
|
|
@@ -826138,7 +826380,7 @@ var init_main7 = __esm(() => {
|
|
|
826138
826380
|
init_xaaIdpLogin();
|
|
826139
826381
|
init_tipRegistry();
|
|
826140
826382
|
init_api4();
|
|
826141
|
-
|
|
826383
|
+
init_skippedMcpServerErrors();
|
|
826142
826384
|
init_cleanupRegistry();
|
|
826143
826385
|
init_commitAttribution();
|
|
826144
826386
|
init_concurrentSessions();
|