@cnwenf/occ 2.1.291 → 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 CHANGED
@@ -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.219` — 2.1.218 fully aligned, 2.1.219 partial per OCC-39 gap report). The code is fully open, auditable, backdoor-free, and your data stays under your control.
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
 
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.291","BINARY_NAME":"occ","BUILD_TIME":"2026-07-30T17:31:04.907Z","FEEDBACK_CHANNEL":"","ISSUES_EXPLAINER":"","NATIVE_PACKAGE_URL":"","PACKAGE_URL":"@cnwenf/occ","VERSION_CHANGELOG":""};
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;
@@ -58238,7 +58238,7 @@ var init_hooks = __esm(() => {
58238
58238
  });
58239
58239
 
58240
58240
  // src/services/mcp/types.ts
58241
- 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;
58242
58242
  var init_types = __esm(() => {
58243
58243
  init_v4();
58244
58244
  ConfigScopeSchema = lazySchema(() => exports_external.enum([
@@ -58275,7 +58275,9 @@ var init_types = __esm(() => {
58275
58275
  headersHelper: exports_external.string().optional(),
58276
58276
  oauth: McpOAuthConfigSchema().optional(),
58277
58277
  alwaysLoad: exports_external.boolean().optional(),
58278
- 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()
58279
58281
  }));
58280
58282
  McpSSEIDEServerConfigSchema = lazySchema(() => exports_external.object({
58281
58283
  type: exports_external.literal("sse-ide"),
@@ -58291,13 +58293,15 @@ var init_types = __esm(() => {
58291
58293
  ideRunningInWindows: exports_external.boolean().optional()
58292
58294
  }));
58293
58295
  McpHTTPServerConfigSchema = lazySchema(() => exports_external.object({
58294
- type: exports_external.literal("http"),
58296
+ type: exports_external.enum(["http", "streamable-http"]).transform(() => "http"),
58295
58297
  url: exports_external.string(),
58296
58298
  headers: exports_external.record(exports_external.string(), exports_external.string()).optional(),
58297
58299
  headersHelper: exports_external.string().optional(),
58298
58300
  oauth: McpOAuthConfigSchema().optional(),
58299
58301
  alwaysLoad: exports_external.boolean().optional(),
58300
- 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()
58301
58305
  }));
58302
58306
  McpWebSocketServerConfigSchema = lazySchema(() => exports_external.object({
58303
58307
  type: exports_external.literal("ws"),
@@ -58305,7 +58309,9 @@ var init_types = __esm(() => {
58305
58309
  headers: exports_external.record(exports_external.string(), exports_external.string()).optional(),
58306
58310
  headersHelper: exports_external.string().optional(),
58307
58311
  alwaysLoad: exports_external.boolean().optional(),
58308
- 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()
58309
58315
  }));
58310
58316
  McpSdkServerConfigSchema = lazySchema(() => exports_external.object({
58311
58317
  type: exports_external.literal("sdk"),
@@ -58330,6 +58336,18 @@ var init_types = __esm(() => {
58330
58336
  McpJsonConfigSchema = lazySchema(() => exports_external.object({
58331
58337
  mcpServers: exports_external.record(exports_external.string(), McpServerConfigSchema())
58332
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
+ };
58333
58351
  });
58334
58352
 
58335
58353
  // src/utils/plugins/schemas.ts
@@ -386592,6 +386610,7 @@ function filterMcpServersByPolicy(configs) {
386592
386610
  }
386593
386611
  function expandEnvVars(config6) {
386594
386612
  const missingVars = [];
386613
+ let urlExpandedToEmpty = false;
386595
386614
  function expandString(str2) {
386596
386615
  const { expanded: expanded2, missingVars: vars } = expandEnvVarsInString(str2);
386597
386616
  missingVars.push(...vars);
@@ -386614,9 +386633,11 @@ function expandEnvVars(config6) {
386614
386633
  case "http":
386615
386634
  case "ws": {
386616
386635
  const remoteConfig = config6;
386636
+ const expandedUrl = expandString(remoteConfig.url);
386637
+ urlExpandedToEmpty = remoteConfig.url.trim() !== "" && expandedUrl.trim() === "";
386617
386638
  expanded = {
386618
386639
  ...remoteConfig,
386619
- url: expandString(remoteConfig.url),
386640
+ url: expandedUrl,
386620
386641
  headers: remoteConfig.headers ? mapValues_default(remoteConfig.headers, expandString) : undefined
386621
386642
  };
386622
386643
  break;
@@ -386634,7 +386655,8 @@ function expandEnvVars(config6) {
386634
386655
  }
386635
386656
  return {
386636
386657
  expanded,
386637
- missingVars: [...new Set(missingVars)]
386658
+ missingVars: [...new Set(missingVars)],
386659
+ urlExpandedToEmpty
386638
386660
  };
386639
386661
  }
386640
386662
  async function addMcpConfig(name3, config6, scope) {
@@ -387109,6 +387131,19 @@ function parseMcpConfig(params) {
387109
387131
  }
387110
387132
  function parseMcpConfigFromFilePath(params) {
387111
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;
387112
387147
  const fs17 = getFsImplementation();
387113
387148
  let configContent;
387114
387149
  try {
@@ -387117,7 +387152,6 @@ function parseMcpConfigFromFilePath(params) {
387117
387152
  const code = getErrnoCode(error52);
387118
387153
  if (code === "ENOENT") {
387119
387154
  return {
387120
- config: null,
387121
387155
  errors: [
387122
387156
  {
387123
387157
  file: filePath,
@@ -387134,7 +387168,6 @@ function parseMcpConfigFromFilePath(params) {
387134
387168
  }
387135
387169
  logForDebugging(`MCP config read error for ${filePath} (scope=${scope}): ${error52}`, { level: "error" });
387136
387170
  return {
387137
- config: null,
387138
387171
  errors: [
387139
387172
  {
387140
387173
  file: filePath,
@@ -387153,7 +387186,6 @@ function parseMcpConfigFromFilePath(params) {
387153
387186
  if (!parsedJson) {
387154
387187
  logForDebugging(`MCP config is not valid JSON: ${filePath} (scope=${scope}, length=${configContent.length}, first100=${jsonStringify(configContent.slice(0, 100))})`, { level: "error" });
387155
387188
  return {
387156
- config: null,
387157
387189
  errors: [
387158
387190
  {
387159
387191
  file: filePath,
@@ -387168,8 +387200,145 @@ function parseMcpConfigFromFilePath(params) {
387168
387200
  ]
387169
387201
  };
387170
387202
  }
387171
- return parseMcpConfig({
387172
- configObject: parsedJson,
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,
387173
387342
  expandVars,
387174
387343
  scope,
387175
387344
  filePath
@@ -387229,6 +387398,7 @@ var init_config6 = __esm(() => {
387229
387398
  init_memoize();
387230
387399
  init_platform2();
387231
387400
  init_common4();
387401
+ init_common();
387232
387402
  init_config4();
387233
387403
  init_cwd2();
387234
387404
  init_debug();
@@ -578444,10 +578614,15 @@ function getSonnet46Option() {
578444
578614
  descriptionForModel: "Sonnet 4.6 - previous Sonnet version"
578445
578615
  };
578446
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
+ }
578447
578623
  function getCustomFableOption() {
578448
- const is3P = getAPIProvider() !== "firstParty";
578449
578624
  const customFableModel = process.env.ANTHROPIC_DEFAULT_FABLE_MODEL;
578450
- if (is3P && customFableModel) {
578625
+ if (shouldUseCustomModelOptions() && customFableModel) {
578451
578626
  return {
578452
578627
  value: "fable",
578453
578628
  label: process.env.ANTHROPIC_DEFAULT_FABLE_MODEL_NAME ?? customFableModel,
@@ -578470,9 +578645,8 @@ function getFable5Option() {
578470
578645
  };
578471
578646
  }
578472
578647
  function getCustomSonnetOption() {
578473
- const is3P = getAPIProvider() !== "firstParty";
578474
578648
  const customSonnetModel = process.env.ANTHROPIC_DEFAULT_SONNET_MODEL;
578475
- if (is3P && customSonnetModel) {
578649
+ if (shouldUseCustomModelOptions() && customSonnetModel) {
578476
578650
  const is1m = has1mContext(customSonnetModel);
578477
578651
  return {
578478
578652
  value: "sonnet",
@@ -578483,9 +578657,8 @@ function getCustomSonnetOption() {
578483
578657
  }
578484
578658
  }
578485
578659
  function getCustomOpusOption() {
578486
- const is3P = getAPIProvider() !== "firstParty";
578487
578660
  const customOpusModel = process.env.ANTHROPIC_DEFAULT_OPUS_MODEL;
578488
- if (is3P && customOpusModel) {
578661
+ if (shouldUseCustomModelOptions() && customOpusModel) {
578489
578662
  const is1m = has1mContext(customOpusModel);
578490
578663
  return {
578491
578664
  value: "opus",
@@ -578558,9 +578731,8 @@ function getOpus46_1MOption(fastMode = false) {
578558
578731
  };
578559
578732
  }
578560
578733
  function getCustomHaikuOption() {
578561
- const is3P = getAPIProvider() !== "firstParty";
578562
578734
  const customHaikuModel = process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL;
578563
- if (is3P && customHaikuModel) {
578735
+ if (shouldUseCustomModelOptions() && customHaikuModel) {
578564
578736
  return {
578565
578737
  value: "haiku",
578566
578738
  label: process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME ?? customHaikuModel,
@@ -578677,6 +578849,33 @@ function getModelOptionsBase(fastMode = false) {
578677
578849
  return standardOptions;
578678
578850
  }
578679
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
+ }
578680
578879
  const payg1POptions = [getDefaultOptionForUser(fastMode)];
578681
578880
  if (checkSonnet1mAccess()) {
578682
578881
  payg1POptions.push(getSonnet5_1MOption());
@@ -812672,6 +812871,18 @@ var init_xaaIdpCommand = __esm(() => {
812672
812871
  init_settings2();
812673
812872
  });
812674
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
+
812675
812886
  // src/utils/cliArgs.ts
812676
812887
  function eagerParseCliFlag(flagName, argv = process.argv) {
812677
812888
  for (let i6 = 0;i6 < argv.length; i6++) {
@@ -814925,7 +815136,7 @@ class QueryEngine {
814925
815136
  yield buildSystemInitMessage({
814926
815137
  tools,
814927
815138
  mcpClients,
814928
- mcpServerErrors: [],
815139
+ mcpServerErrors: getSkippedMcpServerErrors(),
814929
815140
  model: mainLoopModel,
814930
815141
  permissionMode: initialAppState.toolPermissionContext.mode,
814931
815142
  commands: commands7,
@@ -815472,6 +815683,7 @@ var init_QueryEngine = __esm(() => {
815472
815683
  init_paths();
815473
815684
  init_query2();
815474
815685
  init_errors10();
815686
+ init_skippedMcpServerErrors();
815475
815687
  init_Tool();
815476
815688
  init_SyntheticOutputTool();
815477
815689
  init_pointer();
@@ -823645,13 +823857,14 @@ ${addendum}` : addendum;
823645
823857
  if (mcpConfig && mcpConfig.length > 0) {
823646
823858
  const processedConfigs = mcpConfig.map((config8) => config8.trim()).filter((config8) => config8.length > 0);
823647
823859
  let allConfigs = {};
823648
- const allErrors = [];
823860
+ const fatalErrors = [];
823861
+ const skippedCandidates = [];
823649
823862
  for (const configItem of processedConfigs) {
823650
823863
  let configs = null;
823651
823864
  let errors8 = [];
823652
823865
  const parsedJson = safeParseJSON(configItem);
823653
823866
  if (parsedJson) {
823654
- const result = parseMcpConfig({
823867
+ const result = parseDynamicMcpConfig({
823655
823868
  configObject: parsedJson,
823656
823869
  filePath: "command line",
823657
823870
  expandVars: true,
@@ -823659,35 +823872,48 @@ ${addendum}` : addendum;
823659
823872
  });
823660
823873
  if (result.config) {
823661
823874
  configs = result.config.mcpServers;
823662
- } else {
823663
- errors8 = result.errors;
823664
823875
  }
823876
+ errors8 = result.errors;
823665
823877
  } else {
823666
823878
  const configPath = resolve63(configItem);
823667
- const result = parseMcpConfigFromFilePath({
823879
+ const result = parseDynamicMcpConfigFromFile({
823668
823880
  filePath: configPath,
823669
823881
  expandVars: true,
823670
823882
  scope: "dynamic"
823671
823883
  });
823672
823884
  if (result.config) {
823673
823885
  configs = result.config.mcpServers;
823674
- } else {
823675
- errors8 = result.errors;
823676
823886
  }
823887
+ errors8 = result.errors;
823677
823888
  }
823678
- if (errors8.length > 0) {
823679
- allErrors.push(...errors8);
823680
- } else if (configs) {
823889
+ if (configs) {
823681
823890
  allConfigs = {
823682
823891
  ...allConfigs,
823683
823892
  ...configs
823684
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);
823685
823911
  }
823686
823912
  }
823687
- if (allErrors.length > 0) {
823688
- const formattedErrors = allErrors.map((err2) => `${err2.path ? err2.path + ": " : ""}${err2.message}`).join(`
823913
+ if (fatalErrors.length > 0) {
823914
+ const formattedErrors = fatalErrors.map((err2) => `${err2.path ? err2.path + ": " : ""}${err2.message}`).join(`
823689
823915
  `);
823690
- logForDebugging(`--mcp-config validation failed (${allErrors.length} errors): ${formattedErrors}`, {
823916
+ logForDebugging(`--mcp-config validation failed (${fatalErrors.length} errors): ${formattedErrors}`, {
823691
823917
  level: "error"
823692
823918
  });
823693
823919
  process.stderr.write(`Error: Invalid MCP configuration:
@@ -823695,25 +823921,27 @@ ${formattedErrors}
823695
823921
  `);
823696
823922
  process.exit(1);
823697
823923
  }
823698
- if (Object.keys(allConfigs).length > 0) {
823699
- const nonSdkConfigNames = Object.entries(allConfigs).filter(([, config8]) => config8.type !== "sdk").map(([name3]) => name3);
823700
- let reservedNameError = null;
823701
- if (nonSdkConfigNames.some(isClaudeInChromeMCPServer)) {
823702
- reservedNameError = `Invalid MCP configuration: "${CLAUDE_IN_CHROME_MCP_SERVER_NAME}" is a reserved MCP name.`;
823703
- } else if (feature("CHICAGO_MCP")) {
823704
- const {
823705
- isComputerUseMCPServer: isComputerUseMCPServer3,
823706
- COMPUTER_USE_MCP_SERVER_NAME: COMPUTER_USE_MCP_SERVER_NAME2
823707
- } = await Promise.resolve().then(() => (init_common(), exports_common));
823708
- if (nonSdkConfigNames.some(isComputerUseMCPServer3)) {
823709
- reservedNameError = `Invalid MCP configuration: "${COMPUTER_USE_MCP_SERVER_NAME2}" is a reserved MCP name.`;
823710
- }
823924
+ const skippedByName = new Map;
823925
+ for (const candidate of skippedCandidates) {
823926
+ if (!Object.hasOwn(allConfigs, candidate.name)) {
823927
+ skippedByName.set(candidate.name, candidate);
823711
823928
  }
823712
- if (reservedNameError) {
823713
- process.stderr.write(`Error: ${reservedNameError}
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
+ `)}
823714
823941
  `);
823715
- process.exit(1);
823716
823942
  }
823943
+ }
823944
+ if (Object.keys(allConfigs).length > 0) {
823717
823945
  const scopedConfigs = mapValues_default(allConfigs, (config8) => ({
823718
823946
  ...config8,
823719
823947
  scope: "dynamic"
@@ -826152,7 +826380,7 @@ var init_main7 = __esm(() => {
826152
826380
  init_xaaIdpLogin();
826153
826381
  init_tipRegistry();
826154
826382
  init_api4();
826155
- init_common4();
826383
+ init_skippedMcpServerErrors();
826156
826384
  init_cleanupRegistry();
826157
826385
  init_commitAttribution();
826158
826386
  init_concurrentSessions();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cnwenf/occ",
3
- "version": "2.1.291",
3
+ "version": "2.1.292",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "bin": {