@cnwenf/occ 2.1.327 → 2.1.329

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
@@ -5,7 +5,7 @@
5
5
  [![npm version](https://img.shields.io/npm/v/@cnwenf/occ.svg)](https://www.npmjs.com/package/@cnwenf/occ)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
7
7
  [![Runtime: Bun](https://img.shields.io/badge/Runtime-Bun-%23000000.svg)](https://bun.sh/)
8
- [![Tracks: Claude Code 2.1.223](https://img.shields.io/badge/Tracks-Claude%20Code%202.1.223-blueviolet.svg)](https://docs.anthropic.com/en/docs/claude-code)
8
+ [![Tracks: Claude Code 2.1.267](https://img.shields.io/badge/Tracks-Claude%20Code%202.1.267-blueviolet.svg)](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.223` — 2.1.218 fully aligned, 2.1.219 + 2.1.221 + 2.1.223 partial, 2.1.222 staged, per OCC-46 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.267` — 2.1.266 fully aligned; 2.1.267 partial: settings-side effort cap + E8/E9/E10/E12/E32/E33 landed, E8-runtime-realpath / E11 / E19 / E20 / E34 / prompt-cache-snapshot staged, per OCC-121 + OCC-82 gap reports). 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.223` (partial) | Reference implementation |
65
+ | **Capability parity** | Tracks CC `2.1.267` (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.223` (partial)** (2.1.218 fully aligned; 2.1.219 + 2.1.221 + 2.1.223 partial, 2.1.222 staged — see `docs/upstream-version-gap-occ46.md`).
160
+ - Tracks Claude Code **`2.1.267` (partial)** (2.1.266 fully aligned; 2.1.267 partial: settings-side effort cap + E8/E9/E10/E12/E32/E33 landed, E8-runtime-realpath / E11 / E19 / E20 / E34 / prompt-cache-snapshot staged — see `docs/upstream-version-gap-occ121.md` and `docs/upstream-version-gap-occ82.md`).
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.223`:2.1.218 已完全对齐、2.1.219 / 2.1.221 / 2.1.223 部分对齐、2.1.222 待补齐)。代码全开放、可审计、无暗门,数据由你掌控。
11
+ **Open C Code(OCC)** 是一个开源的编码智能体。能力与 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 对齐(当前跟踪 `2.1.267`:2.1.266 已完全对齐、2.1.267 部分对齐——settings 侧 effort cap 与 E8/E9/E10/E12/E32/E33 已落地,E8-runtime-realpath / E11 / E19 / E20 / E34 / prompt-cache 快照子系统暂缓,详见 OCC-121 与 OCC-82 台账)。代码全开放、可审计、无暗门,数据由你掌控。
12
12
 
13
13
  如果你担心闭源 CLI 可能植入后门、担心代码与凭据被上传到不可审计的服务,OCC 就是为你准备的:全部源码开放、无混淆,构建产物可由源码复现,API 凭据只发往你自己配置的端点。
14
14
 
@@ -21,7 +21,7 @@
21
21
 
22
22
  ## 现状
23
23
 
24
- - 跟踪 Claude Code **`2.1.223`**(2.1.218 完全对齐、2.1.219 / 2.1.221 / 2.1.223 部分对齐、2.1.222 待补齐)。
24
+ - 跟踪 Claude Code **`2.1.267`**(2.1.266 已完全对齐、2.1.267 部分对齐——settings 侧 effort cap 与 E8/E9/E10/E12/E32/E33 已落地,E8-runtime-realpath / E11 / E19 / E20 / E34 / prompt-cache 快照子系统暂缓)。
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.327","BINARY_NAME":"occ","BUILD_TIME":"2026-09-09T22:35:02.507Z","FEEDBACK_CHANNEL":"","ISSUES_EXPLAINER":"","NATIVE_PACKAGE_URL":"","PACKAGE_URL":"@cnwenf/occ","VERSION_CHANGELOG":""};
2
+ globalThis.MACRO={"VERSION":"2.1.329","BINARY_NAME":"occ","BUILD_TIME":"2026-09-11T03:55:52.872Z","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;
@@ -59707,6 +59707,22 @@ var init_types2 = __esm(() => {
59707
59707
  prUrlTemplate: exports_external.string().optional().describe('URL template for the footer PR badge (e.g. "https://internal-review.example.com/pr/{number}"). Uses {number} as the PR number placeholder. Defaults to github.com.'),
59708
59708
  alwaysThinkingEnabled: exports_external.boolean().optional().describe("When false, thinking is disabled. When absent or true, thinking is " + "enabled automatically for supported models."),
59709
59709
  effortLevel: exports_external.enum(["low", "medium", "high", "xhigh"]).optional().catch(undefined).describe("Persisted effort level for supported models."),
59710
+ maxEffortLevel: exports_external.enum(["low", "medium", "high", "xhigh", "max"]).optional().catch(undefined).describe("Maximum effort level. Anything above it (an /effort or /model pick, --effort, CLAUDE_CODE_EFFORT_LEVEL, a model default) is clamped to it, on every provider including Bedrock, Vertex and Foundry. Combines with an organization's per-model effort cap by taking the lower of the two; across settings files the lowest value wins, and modelSettings.<model>.maxEffortLevel replaces it per model. Enforced client-side: an effort supplied through CLAUDE_CODE_EXTRA_BODY is not clamped."),
59711
+ modelSettings: exports_external.preprocess((value) => {
59712
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
59713
+ return value;
59714
+ }
59715
+ const stripped = {};
59716
+ for (const [key, entry] of Object.entries(value)) {
59717
+ if (!Object.hasOwn(Object.prototype, key)) {
59718
+ stripped[key] = entry;
59719
+ }
59720
+ }
59721
+ return stripped;
59722
+ }, exports_external.record(exports_external.string(), exports_external.object({
59723
+ effortLevel: exports_external.enum(["low", "medium", "high", "xhigh"]).optional().catch(undefined).describe("Persisted effort level for this model."),
59724
+ maxEffortLevel: exports_external.enum(["low", "medium", "high", "xhigh", "max"]).optional().catch(undefined).describe('Maximum effort level for this model. Within one settings file it replaces the top-level maxEffortLevel for the model ("max" exempts it); across settings files the lowest applicable value wins. Keyed like effortLevel: the canonical model name also matches its dated, [1m], Bedrock and Vertex spellings.')
59725
+ }).passthrough().optional().catch(undefined))).optional().catch(undefined).describe("Per-model settings keyed by canonical model name."),
59710
59726
  dynamicWorkflowSize: exports_external.enum(["small", "medium", "large"]).optional().catch(undefined).describe("Advisory guideline for how large Claude makes dynamic workflows (small/medium/large agent counts). Not an enforced cap."),
59711
59727
  advisorModel: exports_external.string().optional().describe("Advisor model for the server-side advisor tool."),
59712
59728
  fastMode: exports_external.boolean().optional().describe("When true, fast mode is enabled. When absent or false, fast mode is off."),
@@ -60319,6 +60335,102 @@ var init_settings = __esm(() => {
60319
60335
  EMPTY_RESULT = Object.freeze({ settings: {}, errors: [] });
60320
60336
  });
60321
60337
 
60338
+ // src/utils/settings/sanitizeAllowlists.ts
60339
+ function issueDetail(error49) {
60340
+ const issue2 = error49.issues[0];
60341
+ if (issue2 === undefined)
60342
+ return "failed validation";
60343
+ return issue2.path.length > 0 ? `${issue2.path.join(".")}: ${issue2.message}` : issue2.message;
60344
+ }
60345
+ function validateAllowlistEntry(key, entry) {
60346
+ if (key === "allowedChannelPlugins") {
60347
+ if (typeof entry === "string") {
60348
+ const at = entry.indexOf("@");
60349
+ const plugin = entry.slice(0, at);
60350
+ const marketplace = entry.slice(at + 1);
60351
+ if (at > 0 && marketplace.length > 0) {
60352
+ return {
60353
+ ok: true,
60354
+ value: { marketplace, plugin },
60355
+ notice: `"allowedChannelPlugins" entry "${entry}" was accepted; prefer the documented object form {"plugin": "${plugin}", "marketplace": "${marketplace}"}.`
60356
+ };
60357
+ }
60358
+ }
60359
+ const parsed2 = CHANNEL_PLUGIN_ENTRY.safeParse(entry);
60360
+ return parsed2.success ? { ok: true, value: parsed2.data } : { ok: false, detail: issueDetail(parsed2.error) };
60361
+ }
60362
+ const parsed = STRING_ENTRY.safeParse(entry);
60363
+ return parsed.success ? { ok: true, value: parsed.data } : { ok: false, detail: issueDetail(parsed.error) };
60364
+ }
60365
+ function sanitizeSecurityAllowlists(data, filePath) {
60366
+ if (!data || typeof data !== "object")
60367
+ return [];
60368
+ const obj = data;
60369
+ const warnings = [];
60370
+ for (const { key, emptyReason } of ALLOWLIST_SPECS) {
60371
+ if (!(key in obj))
60372
+ continue;
60373
+ const raw = obj[key];
60374
+ if (!Array.isArray(raw)) {
60375
+ obj[key] = [];
60376
+ warnings.push({
60377
+ file: filePath,
60378
+ path: key,
60379
+ message: `"${key}" was present but invalid; enforcing an empty allowlist (${emptyReason}) until it is fixed.`,
60380
+ invalidValue: raw
60381
+ });
60382
+ continue;
60383
+ }
60384
+ const valid = [];
60385
+ for (const [index2, entry] of raw.entries()) {
60386
+ const result = validateAllowlistEntry(key, entry);
60387
+ if (result.ok) {
60388
+ valid.push(result.value);
60389
+ if (result.notice !== undefined) {
60390
+ warnings.push({
60391
+ file: filePath,
60392
+ path: `${key}[${index2}]`,
60393
+ message: result.notice
60394
+ });
60395
+ }
60396
+ } else {
60397
+ warnings.push({
60398
+ file: filePath,
60399
+ path: `${key}[${index2}]`,
60400
+ message: `Invalid entry was ignored: ${result.detail}`,
60401
+ invalidValue: entry
60402
+ });
60403
+ }
60404
+ }
60405
+ if (raw.length > 0 && valid.length === 0) {
60406
+ warnings.push({
60407
+ file: filePath,
60408
+ path: key,
60409
+ message: `Every entry of "${key}" was invalid; enforcing an empty allowlist (${emptyReason}) until it is fixed.`
60410
+ });
60411
+ }
60412
+ obj[key] = valid;
60413
+ }
60414
+ return warnings;
60415
+ }
60416
+ var STRING_ENTRY, CHANNEL_PLUGIN_ENTRY, ALLOWLIST_SPECS;
60417
+ var init_sanitizeAllowlists = __esm(() => {
60418
+ init_v4();
60419
+ STRING_ENTRY = exports_external.string();
60420
+ CHANNEL_PLUGIN_ENTRY = exports_external.object({
60421
+ marketplace: exports_external.string(),
60422
+ plugin: exports_external.string()
60423
+ });
60424
+ ALLOWLIST_SPECS = [
60425
+ { key: "allowedHttpHookUrls", emptyReason: "no HTTP hooks may run" },
60426
+ {
60427
+ key: "httpHookAllowedEnvVars",
60428
+ emptyReason: "no environment variables may be interpolated into HTTP hook headers"
60429
+ },
60430
+ { key: "allowedChannelPlugins", emptyReason: "no channel plugins admitted" }
60431
+ ];
60432
+ });
60433
+
60322
60434
  // src/utils/settings/settings.ts
60323
60435
  var exports_settings = {};
60324
60436
  __export(exports_settings, {
@@ -60455,12 +60567,19 @@ function parseSettingsFileUncached(path9) {
60455
60567
  }
60456
60568
  const data = safeParseJSON(content, false);
60457
60569
  const ruleWarnings = filterInvalidPermissionRules(data, path9);
60570
+ const allowlistWarnings = sanitizeSecurityAllowlists(data, path9);
60458
60571
  const result = SettingsSchema().safeParse(data);
60459
60572
  if (!result.success) {
60460
60573
  const errors3 = formatZodError(result.error, path9);
60461
- return { settings: null, errors: [...ruleWarnings, ...errors3] };
60574
+ return {
60575
+ settings: null,
60576
+ errors: [...ruleWarnings, ...allowlistWarnings, ...errors3]
60577
+ };
60462
60578
  }
60463
- return { settings: result.data, errors: ruleWarnings };
60579
+ return {
60580
+ settings: result.data,
60581
+ errors: [...ruleWarnings, ...allowlistWarnings]
60582
+ };
60464
60583
  } catch (error49) {
60465
60584
  handleFileSystemError(error49, path9);
60466
60585
  return { settings: null, errors: [] };
@@ -61086,6 +61205,7 @@ var init_settings2 = __esm(() => {
61086
61205
  init_managedPath();
61087
61206
  init_settings();
61088
61207
  init_settingsCache();
61208
+ init_sanitizeAllowlists();
61089
61209
  init_types2();
61090
61210
  init_validation2();
61091
61211
  MAX_SETTINGS_FILE_BYTES = 2 * 1024 * 1024;
@@ -203834,6 +203954,122 @@ var init_thinking = __esm(() => {
203834
203954
  ];
203835
203955
  });
203836
203956
 
203957
+ // src/utils/effort/cap.ts
203958
+ function effortLevelIndex(level) {
203959
+ return EFFORT_LEVELS.indexOf(level);
203960
+ }
203961
+ function isKnownEffortLevel(value) {
203962
+ return typeof value === "string" && EFFORT_LEVELS.includes(value);
203963
+ }
203964
+ function getSettingsEffortCap(model) {
203965
+ const sources = getEnabledSettingSources().map((source) => getSettingsForSource(source));
203966
+ const canonicalTarget = sources.some((settings) => Object.values(settings?.modelSettings ?? {}).some((entry) => entry?.maxEffortLevel !== undefined)) ? getCanonicalName(model) : undefined;
203967
+ let lowest = null;
203968
+ for (const settings of sources) {
203969
+ if (!settings)
203970
+ continue;
203971
+ let perFile;
203972
+ if (canonicalTarget !== undefined) {
203973
+ for (const [key, entry] of Object.entries(settings.modelSettings ?? {})) {
203974
+ if (Object.hasOwn(Object.prototype, key))
203975
+ continue;
203976
+ const candidate = entry?.maxEffortLevel;
203977
+ if (candidate !== undefined && (perFile === undefined || effortLevelIndex(candidate) < effortLevelIndex(perFile)) && getCanonicalName(key) === canonicalTarget) {
203978
+ perFile = candidate;
203979
+ }
203980
+ }
203981
+ }
203982
+ perFile ??= settings.maxEffortLevel;
203983
+ if (perFile !== undefined && perFile !== "max" && (lowest === null || effortLevelIndex(perFile) < effortLevelIndex(lowest))) {
203984
+ lowest = perFile;
203985
+ }
203986
+ }
203987
+ return lowest;
203988
+ }
203989
+ function getEffectiveEffortCap(model) {
203990
+ const cap = getSettingsEffortCap(model);
203991
+ return cap === "max" ? null : cap;
203992
+ }
203993
+ function isEffortLevelAllowed(level, model) {
203994
+ const cap = getEffectiveEffortCap(model);
203995
+ return cap === null || effortLevelIndex(level) <= effortLevelIndex(cap);
203996
+ }
203997
+ function getAllowedEffortLevels(model) {
203998
+ return EFFORT_LEVELS.filter((level) => isEffortLevelAllowed(level, model));
203999
+ }
204000
+ function modelSupportsEffortLevel(model, level) {
204001
+ if (level === "xhigh")
204002
+ return modelSupportsXhighEffort(model);
204003
+ if (level === "max")
204004
+ return modelSupportsMaxEffort(model);
204005
+ return true;
204006
+ }
204007
+ function clampEffortToCap(value, model) {
204008
+ const cap = getEffectiveEffortCap(model);
204009
+ if (cap !== null && isKnownEffortLevel(value)) {
204010
+ return effortLevelIndex(value) > effortLevelIndex(cap) ? cap : value;
204011
+ }
204012
+ return value;
204013
+ }
204014
+ function applyEffortCapabilityDowngrade(value, model) {
204015
+ let result = value;
204016
+ if (result === "max" && !modelSupportsMaxEffort(model))
204017
+ result = "high";
204018
+ if (result === "xhigh" && !modelSupportsXhighEffort(model))
204019
+ result = "high";
204020
+ return result;
204021
+ }
204022
+ function clampEffortValue(value, model) {
204023
+ return applyEffortCapabilityDowngrade(clampEffortToCap(value, model), model);
204024
+ }
204025
+ function hasEffortLevelsAboveCap(model) {
204026
+ const cap = getEffectiveEffortCap(model);
204027
+ if (cap === null)
204028
+ return false;
204029
+ return EFFORT_LEVELS.some((level) => effortLevelIndex(level) > effortLevelIndex(cap) && modelSupportsEffortLevel(model, level));
204030
+ }
204031
+ function getEffortCapWarning(requested, model) {
204032
+ if (!isKnownEffortLevel(requested))
204033
+ return null;
204034
+ const cap = getEffectiveEffortCap(model);
204035
+ if (cap === null || effortLevelIndex(requested) <= effortLevelIndex(cap)) {
204036
+ return null;
204037
+ }
204038
+ const using = clampEffortValue(requested, model);
204039
+ return `Effort '${requested}' exceeds the cap for ${model} set by your settings or organization; using '${using}'.`;
204040
+ }
204041
+ function emitStartupEffortCapWarning(requestedEffort, model, outputFormat) {
204042
+ const warning = getEffortCapWarning(requestedEffort, model);
204043
+ if (warning === null)
204044
+ return;
204045
+ if (outputFormat !== "json" && outputFormat !== "stream-json" && process.env.CLAUDE_CODE_SESSION_KIND !== "bg") {
204046
+ console.warn(source_default.yellow(warning));
204047
+ return;
204048
+ }
204049
+ logForDebugging(`[effort] ${warning}`);
204050
+ }
204051
+ function isUltracodeAvailableForModel(model) {
204052
+ return model === undefined || modelSupportsXhighEffort(model) && isEffortLevelAllowed("xhigh", model);
204053
+ }
204054
+ function formatEffortValidOptions(model) {
204055
+ const levels = getAllowedEffortLevels(model);
204056
+ const ultracode = isUltracodeAvailableForModel(model) ? ", ultracode" : "";
204057
+ return `${levels.join(", ")}${ultracode}, auto`;
204058
+ }
204059
+ function buildEffortArgumentHint(open6, close, model) {
204060
+ const levels = getAllowedEffortLevels(model);
204061
+ const ultracode = isUltracodeAvailableForModel(model) ? "|ultracode" : "";
204062
+ return `${open6}${levels.join("|")}${ultracode}|auto${close}`;
204063
+ }
204064
+ var init_cap = __esm(() => {
204065
+ init_source();
204066
+ init_debug();
204067
+ init_model();
204068
+ init_constants2();
204069
+ init_settings2();
204070
+ init_effort();
204071
+ });
204072
+
203837
204073
  // src/utils/effort.ts
203838
204074
  function modelSupportsEffort(model) {
203839
204075
  const m5 = model.toLowerCase();
@@ -203922,24 +204158,30 @@ function getEffortEnvOverride() {
203922
204158
  }
203923
204159
  function resolveAppliedEffort(model, appStateEffortValue) {
203924
204160
  const envOverride = getEffortEnvOverride();
203925
- if (envOverride === null) {
204161
+ const hasSettingsCap = getSettingsEffortCap(model) !== null;
204162
+ if (envOverride === null && !hasSettingsCap) {
203926
204163
  return;
203927
204164
  }
203928
- const resolved = envOverride ?? appStateEffortValue ?? getDefaultEffortForModel(model);
203929
- if (resolved === "max" && !modelSupportsMaxEffort(model)) {
203930
- return "high";
204165
+ const modelDefault = getDefaultEffortForModel(model);
204166
+ let resolved = envOverride ?? (envOverride === null ? modelDefault : undefined) ?? appStateEffortValue ?? modelDefault;
204167
+ if (typeof resolved === "number" && hasSettingsCap) {
204168
+ resolved = "high";
203931
204169
  }
203932
- if (resolved === "xhigh" && !modelSupportsXhighEffort(model)) {
203933
- return "high";
204170
+ if (resolved === undefined) {
204171
+ return;
203934
204172
  }
203935
- return resolved;
204173
+ return clampEffortValue(resolved, model);
203936
204174
  }
203937
204175
  function resolveConfiguredEffort(model, appStateEffortValue) {
203938
204176
  const envOverride = getEffortEnvOverride();
203939
204177
  if (envOverride === null) {
203940
204178
  return;
203941
204179
  }
203942
- return envOverride ?? appStateEffortValue ?? getDefaultEffortForModel(model);
204180
+ const resolved = envOverride ?? appStateEffortValue ?? getDefaultEffortForModel(model);
204181
+ if (resolved === undefined) {
204182
+ return;
204183
+ }
204184
+ return clampEffortToCap(resolved, model);
203943
204185
  }
203944
204186
  function getDisplayedEffortLevel(model, appStateEffort) {
203945
204187
  const configured = resolveConfiguredEffort(model, appStateEffort) ?? "high";
@@ -204044,6 +204286,7 @@ var init_effort = __esm(() => {
204044
204286
  init_providers();
204045
204287
  init_modelSupportOverrides();
204046
204288
  init_envUtils();
204289
+ init_cap();
204047
204290
  EFFORT_LEVELS = [
204048
204291
  "low",
204049
204292
  "medium",
@@ -266184,6 +266427,9 @@ async function* withRetry(getClient2, operation, options) {
266184
266427
  let persistentAttempt = 0;
266185
266428
  let apiKeyHelperAuthRetries = 0;
266186
266429
  const API_KEY_HELPER_AUTH_RETRY_CAP = 2;
266430
+ let awsAuthRetries = 0;
266431
+ let gcpAuthRetries = 0;
266432
+ const CLOUD_AUTH_RETRY_CAP = 2;
266187
266433
  let mediaStrips = 0;
266188
266434
  const MAX_MEDIA_STRIPS = 20;
266189
266435
  for (let attempt = 1;attempt <= maxRetries + 1; attempt++) {
@@ -266312,6 +266558,25 @@ async function* withRetry(getClient2, operation, options) {
266312
266558
  }
266313
266559
  apiKeyHelperAuthRetries++;
266314
266560
  }
266561
+ const cloudCredentialKind = classifyCloudCredentialError(error52);
266562
+ if (cloudCredentialKind === "AWS" || getAPIProvider() !== "firstParty" && isBedrockAuthError(error52)) {
266563
+ if (awsAuthRetries >= CLOUD_AUTH_RETRY_CAP) {
266564
+ logEvent2("api_request", {
266565
+ reason: "api_request_aws_auth_exhausted"
266566
+ });
266567
+ throw new CannotRetryError(error52, retryContext);
266568
+ }
266569
+ awsAuthRetries++;
266570
+ }
266571
+ if (cloudCredentialKind === "Google Cloud" || getAPIProvider() !== "firstParty" && isVertexAuthError(error52)) {
266572
+ if (gcpAuthRetries >= CLOUD_AUTH_RETRY_CAP) {
266573
+ logEvent2("api_request", {
266574
+ reason: "api_request_gcp_auth_exhausted"
266575
+ });
266576
+ throw new CannotRetryError(error52, retryContext);
266577
+ }
266578
+ gcpAuthRetries++;
266579
+ }
266315
266580
  const handledCloudAuthError = handleAwsCredentialError(error52) || handleGcpCredentialError(error52);
266316
266581
  if (!handledCloudAuthError && (!(error52 instanceof APIError) || !shouldRetry(error52))) {
266317
266582
  throw new CannotRetryError(error52, retryContext);
@@ -266474,6 +266739,34 @@ function getFallbackTriggerReason(error52) {
266474
266739
  function isOAuthTokenRevokedError(error52) {
266475
266740
  return error52 instanceof APIError && error52.status === 403 && (error52.message?.includes("OAuth token has been revoked") ?? false);
266476
266741
  }
266742
+ function findInErrorCauseChain(error52, predicate, maxDepth = 5) {
266743
+ let current = error52;
266744
+ for (let depth = 0;depth < maxDepth; depth++) {
266745
+ if (!(current instanceof Error))
266746
+ return;
266747
+ if (predicate(current))
266748
+ return current;
266749
+ current = current.cause;
266750
+ }
266751
+ return;
266752
+ }
266753
+ function errorChainMessageIncludes(error52, needles) {
266754
+ return findInErrorCauseChain(error52, (e4) => needles.some((needle) => e4.message.includes(needle))) !== undefined;
266755
+ }
266756
+ function isGoogleCloudEnv() {
266757
+ return !!(process.env.CLAUDE_CODE_USE_VERTEX || process.env.CLAUDE_CODE_USE_ANTHROPIC_GOOGLE_CLOUD);
266758
+ }
266759
+ function classifyCloudCredentialError(error52) {
266760
+ if (error52 instanceof APIError && error52.status !== undefined)
266761
+ return null;
266762
+ if (findInErrorCauseChain(error52, (e4) => e4.name === "CredentialsProviderError") !== undefined) {
266763
+ return "AWS";
266764
+ }
266765
+ if (isGoogleCloudEnv() && errorChainMessageIncludes(error52, GOOGLE_CREDENTIAL_CLASSIFIER_MESSAGES)) {
266766
+ return "Google Cloud";
266767
+ }
266768
+ return null;
266769
+ }
266477
266770
  function isBedrockAuthError(error52) {
266478
266771
  if (isEnvTruthy(process.env.CLAUDE_CODE_USE_BEDROCK)) {
266479
266772
  if (isAwsCredentialsProviderError(error52) || error52 instanceof APIError && error52.status === 403) {
@@ -266490,10 +266783,11 @@ function handleAwsCredentialError(error52) {
266490
266783
  return false;
266491
266784
  }
266492
266785
  function isGoogleAuthLibraryCredentialError(error52) {
266493
- if (!(error52 instanceof Error))
266494
- return false;
266495
- const msg = error52.message;
266496
- return msg.includes("Could not load the default credentials") || msg.includes("Could not refresh access token") || msg.includes("invalid_grant");
266786
+ return errorChainMessageIncludes(error52, [
266787
+ ...GOOGLE_CREDENTIAL_CLASSIFIER_MESSAGES,
266788
+ GOOGLE_OAUTH_FAILURE_MESSAGE,
266789
+ GOOGLE_TOKEN_REFRESH_FAILURE_MESSAGE
266790
+ ]);
266497
266791
  }
266498
266792
  function isVertexAuthError(error52) {
266499
266793
  if (isEnvTruthy(process.env.CLAUDE_CODE_USE_VERTEX)) {
@@ -266593,7 +266887,7 @@ function getRateLimitResetDelayMs(error52) {
266593
266887
  return null;
266594
266888
  return Math.min(delayMs, PERSISTENT_RESET_CAP_MS);
266595
266889
  }
266596
- var abortError = () => new APIUserAbortError, DEFAULT_MAX_RETRIES2 = 10, FLOOR_OUTPUT_TOKENS = 3000, MAX_529_RETRIES = 3, BASE_DELAY_MS = 500, MAX_RETRIES_CLAMP = 15, WATCHDOG_DEFAULT_MAX_RETRIES = 300, maxRetriesClampWarned = false, FOREGROUND_529_RETRY_SOURCES, PERSISTENT_MAX_BACKOFF_MS, PERSISTENT_RESET_CAP_MS, HEARTBEAT_INTERVAL_MS = 30000, CannotRetryError, FallbackTriggeredError, DEFAULT_FAST_MODE_FALLBACK_HOLD_MS, SHORT_RETRY_THRESHOLD_MS, MIN_COOLDOWN_MS;
266890
+ var abortError = () => new APIUserAbortError, DEFAULT_MAX_RETRIES2 = 10, FLOOR_OUTPUT_TOKENS = 3000, MAX_529_RETRIES = 3, BASE_DELAY_MS = 500, MAX_RETRIES_CLAMP = 15, WATCHDOG_DEFAULT_MAX_RETRIES = 300, maxRetriesClampWarned = false, FOREGROUND_529_RETRY_SOURCES, PERSISTENT_MAX_BACKOFF_MS, PERSISTENT_RESET_CAP_MS, HEARTBEAT_INTERVAL_MS = 30000, CannotRetryError, FallbackTriggeredError, GOOGLE_CREDENTIAL_CLASSIFIER_MESSAGES, GOOGLE_OAUTH_FAILURE_MESSAGE = "Failed to acquire Google OAuth credentials.", GOOGLE_TOKEN_REFRESH_FAILURE_MESSAGE = "Could not refresh access token", DEFAULT_FAST_MODE_FALLBACK_HOLD_MS, SHORT_RETRY_THRESHOLD_MS, MIN_COOLDOWN_MS;
266597
266891
  var init_withRetry = __esm(() => {
266598
266892
  init_featureFlags();
266599
266893
  init_sdk();
@@ -266659,6 +266953,12 @@ var init_withRetry = __esm(() => {
266659
266953
  this.name = "FallbackTriggeredError";
266660
266954
  }
266661
266955
  };
266956
+ GOOGLE_CREDENTIAL_CLASSIFIER_MESSAGES = [
266957
+ "Could not load the default credentials",
266958
+ "invalid_grant",
266959
+ "invalid_client",
266960
+ "unauthorized_client"
266961
+ ];
266662
266962
  DEFAULT_FAST_MODE_FALLBACK_HOLD_MS = 30 * 60 * 1000;
266663
266963
  SHORT_RETRY_THRESHOLD_MS = 20 * 1000;
266664
266964
  MIN_COOLDOWN_MS = 10 * 60 * 1000;
@@ -377715,7 +378015,8 @@ function getSimpleSandboxSection() {
377715
378015
  ];
377716
378016
  const items = [
377717
378017
  ...sandboxOverrideItems,
377718
- "For temporary files, always use the `$TMPDIR` environment variable. TMPDIR is automatically set to the correct sandbox-writable directory in sandbox mode. Do NOT use `/tmp` directly - use `$TMPDIR` instead."
378018
+ "For temporary files, always use the `$TMPDIR` environment variable. TMPDIR is automatically set to the correct sandbox-writable directory in sandbox mode. Do NOT use `/tmp` directly - use `$TMPDIR` instead.",
378019
+ "If a clipboard utility such as `pbcopy`, `xclip`, or `wl-copy` fails inside the sandbox and the user wants the text on their clipboard, put the text in a fenced code block in your response and tell them to run `/copy` (it copies from outside the sandbox; when the picker appears they can select just that block), rather than writing a file for them to copy manually."
377719
378020
  ];
377720
378021
  return [
377721
378022
  "",
@@ -383975,6 +384276,8 @@ var init_BashTool = __esm(() => {
383975
384276
  timeout: semanticNumber(exports_external.number().optional()).describe(`Optional timeout in milliseconds (max ${getMaxTimeoutMs()})`),
383976
384277
  description: exports_external.string().optional().describe(`Clear, concise description of what this command does in active voice. Never use words like "complex" or "risk" in the description - just describe what it does.
383977
384278
 
384279
+ Say what the command does in plain words: do not echo the command's text, its flags, or file paths - the user reads this description, often without seeing the command.
384280
+
383978
384281
  For simple commands (git, npm, standard CLI tools), keep it brief (5-10 words):
383979
384282
  - ls \u2192 "List files in current directory"
383980
384283
  - git status \u2192 "Show working tree status"
@@ -475491,7 +475794,7 @@ function deserializeMessagesWithInterruptDetection(serializedMessages) {
475491
475794
  turnInterruptionState = internalState;
475492
475795
  }
475493
475796
  const lastRelevantIdx = filteredMessages.findLastIndex((m5) => m5.type !== "system" && m5.type !== "progress");
475494
- if (lastRelevantIdx !== -1 && filteredMessages[lastRelevantIdx].type === "user") {
475797
+ if (lastRelevantIdx !== -1 && filteredMessages[lastRelevantIdx].type === "user" && !isCompleteLocalCommandTail(filteredMessages, lastRelevantIdx)) {
475495
475798
  filteredMessages.splice(lastRelevantIdx + 1, 0, createAssistantMessage({
475496
475799
  content: NO_RESPONSE_REQUESTED
475497
475800
  }));
@@ -475515,6 +475818,9 @@ function detectTurnInterruption(messages) {
475515
475818
  return { kind: "none" };
475516
475819
  }
475517
475820
  if (lastMessage.type === "user") {
475821
+ if (isCompleteLocalCommandTail(messages, lastMessageIdx)) {
475822
+ return { kind: "none" };
475823
+ }
475518
475824
  if (lastMessage.isMeta || lastMessage.isCompactSummary) {
475519
475825
  return { kind: "none" };
475520
475826
  }
@@ -475554,6 +475860,43 @@ function isTerminalToolResult(result, messages, resultIdx) {
475554
475860
  }
475555
475861
  return false;
475556
475862
  }
475863
+ function classifyLocalCommandKind(message) {
475864
+ const content = message.message?.content;
475865
+ const text2 = Array.isArray(content) ? content.findLast((block) => block?.type === "text")?.text : typeof content === "string" ? content : undefined;
475866
+ if (typeof text2 !== "string")
475867
+ return;
475868
+ return LOCAL_COMMAND_TAG_KINDS.find(([prefix]) => text2.startsWith(prefix))?.[1];
475869
+ }
475870
+ function localCommandBreadcrumbKind(message) {
475871
+ if (message.type !== "user")
475872
+ return;
475873
+ if (message.promptSource !== undefined)
475874
+ return;
475875
+ const kind = classifyLocalCommandKind(message);
475876
+ if (kind === "caveat" && message.isMeta !== true)
475877
+ return;
475878
+ return kind;
475879
+ }
475880
+ function isCompleteLocalCommandTail(messages, idx) {
475881
+ if (localCommandBreadcrumbKind(messages[idx]) === undefined)
475882
+ return false;
475883
+ let seenRecord = false;
475884
+ let allMetaUsers = true;
475885
+ for (let i6 = idx;i6 >= 0; i6--) {
475886
+ const msg = messages[i6];
475887
+ if (msg.type === "system" || msg.type === "progress" || msg.type === "attachment") {
475888
+ continue;
475889
+ }
475890
+ const kind = localCommandBreadcrumbKind(msg);
475891
+ if (kind === "caveat")
475892
+ return true;
475893
+ if (kind === undefined || seenRecord)
475894
+ break;
475895
+ seenRecord = kind === "record";
475896
+ allMetaUsers = allMetaUsers && msg.type === "user" && msg.isMeta === true;
475897
+ }
475898
+ return allMetaUsers;
475899
+ }
475557
475900
  function restoreSkillStateFromMessages(messages) {
475558
475901
  for (const message of messages) {
475559
475902
  if (message.type !== "attachment") {
@@ -475671,11 +476014,12 @@ async function loadConversationForResume(source, sourceJsonlFile) {
475671
476014
  throw error52;
475672
476015
  }
475673
476016
  }
475674
- var BRIEF_TOOL_NAME4, LEGACY_BRIEF_TOOL_NAME2, SEND_USER_FILE_TOOL_NAME3;
476017
+ var BRIEF_TOOL_NAME4, LEGACY_BRIEF_TOOL_NAME2, SEND_USER_FILE_TOOL_NAME3, LOCAL_COMMAND_TAG_KINDS;
475675
476018
  var init_conversationRecovery = __esm(() => {
475676
476019
  init_featureFlags();
475677
476020
  init_cwd2();
475678
476021
  init_state();
476022
+ init_xml();
475679
476023
  init_ids();
475680
476024
  init_permissions();
475681
476025
  init_attachments2();
@@ -475688,6 +476032,12 @@ var init_conversationRecovery = __esm(() => {
475688
476032
  BRIEF_TOOL_NAME4 = feature("KAIROS") || feature("KAIROS_BRIEF") ? (init_prompt(), __toCommonJS(exports_prompt)).BRIEF_TOOL_NAME : null;
475689
476033
  LEGACY_BRIEF_TOOL_NAME2 = feature("KAIROS") || feature("KAIROS_BRIEF") ? (init_prompt(), __toCommonJS(exports_prompt)).LEGACY_BRIEF_TOOL_NAME : null;
475690
476034
  SEND_USER_FILE_TOOL_NAME3 = feature("KAIROS") ? (init_prompt8(), __toCommonJS(exports_prompt2)).SEND_USER_FILE_TOOL_NAME : null;
476035
+ LOCAL_COMMAND_TAG_KINDS = [
476036
+ [`<${COMMAND_NAME_TAG}>`, "record"],
476037
+ [`<${LOCAL_COMMAND_STDOUT_TAG}>`, "output"],
476038
+ [`<${LOCAL_COMMAND_STDERR_TAG}>`, "output"],
476039
+ [`<${LOCAL_COMMAND_CAVEAT_TAG}>`, "caveat"]
476040
+ ];
475691
476041
  });
475692
476042
 
475693
476043
  // src/services/api/filesApi.ts
@@ -560691,18 +561041,18 @@ function parseFolderPath(folderPath) {
560691
561041
  }
560692
561042
  return { platform: platform5, buildId };
560693
561043
  }
560694
- var import_debug177, debugCache;
561044
+ var import_debug178, debugCache;
560695
561045
  var init_Cache = __esm(() => {
560696
561046
  init_browser_data();
560697
561047
  init_detectPlatform();
560698
- import_debug177 = __toESM(require_src(), 1);
560699
- debugCache = import_debug177.default("puppeteer:browsers:cache");
561048
+ import_debug178 = __toESM(require_src(), 1);
561049
+ debugCache = import_debug178.default("puppeteer:browsers:cache");
560700
561050
  });
560701
561051
 
560702
561052
  // node_modules/.bun/@puppeteer+browsers@2.13.2/node_modules/@puppeteer/browsers/lib/esm/debug.js
560703
- var import_debug178;
561053
+ var import_debug179;
560704
561054
  var init_debug3 = __esm(() => {
560705
- import_debug178 = __toESM(require_src(), 1);
561055
+ import_debug179 = __toESM(require_src(), 1);
560706
561056
  });
560707
561057
 
560708
561058
  // node_modules/.bun/@puppeteer+browsers@2.13.2/node_modules/@puppeteer/browsers/lib/esm/launch.js
@@ -561021,7 +561371,7 @@ var init_launch = __esm(() => {
561021
561371
  init_Cache();
561022
561372
  init_debug3();
561023
561373
  init_detectPlatform();
561024
- debugLaunch = import_debug178.default("puppeteer:browsers:launcher");
561374
+ debugLaunch = import_debug179.default("puppeteer:browsers:launcher");
561025
561375
  CDP_WEBSOCKET_ENDPOINT_REGEX = /^DevTools listening on (ws:\/\/.*)$/;
561026
561376
  WEBDRIVER_BIDI_WEBSOCKET_ENDPOINT_REGEX = /^WebDriver BiDi listening on (ws:\/\/.*)$/;
561027
561377
  processListeners = new Map;
@@ -566105,10 +566455,10 @@ async function installDMG(dmgPath, folderPath) {
566105
566455
  spawnSync4("hdiutil", ["detach", mountPath, "-quiet"]);
566106
566456
  }
566107
566457
  }
566108
- var import_debug180, debugFileUtil, internalConstantsForTesting;
566458
+ var import_debug181, debugFileUtil, internalConstantsForTesting;
566109
566459
  var init_fileUtil = __esm(() => {
566110
- import_debug180 = __toESM(require_src(), 1);
566111
- debugFileUtil = import_debug180.default("puppeteer:browsers:fileUtil");
566460
+ import_debug181 = __toESM(require_src(), 1);
566461
+ debugFileUtil = import_debug181.default("puppeteer:browsers:fileUtil");
566112
566462
  internalConstantsForTesting = {
566113
566463
  xz: "xz",
566114
566464
  bzip2: "bzip2"
@@ -566401,7 +566751,7 @@ var init_install = __esm(() => {
566401
566751
  init_fileUtil();
566402
566752
  init_httpUtil();
566403
566753
  import_progress = __toESM(require_node_progress(), 1);
566404
- debugInstall = import_debug178.default("puppeteer:browsers:install");
566754
+ debugInstall = import_debug179.default("puppeteer:browsers:install");
566405
566755
  times = new Map;
566406
566756
  });
566407
566757
 
@@ -572676,7 +573026,7 @@ import fs23 from "fs";
572676
573026
  import os16 from "os";
572677
573027
  import { dirname as dirname45 } from "path";
572678
573028
  import { PassThrough as PassThrough4 } from "stream";
572679
- var import_debug182, __runInitializers23 = function(thisArg, initializers, value) {
573029
+ var import_debug183, __runInitializers23 = function(thisArg, initializers, value) {
572680
573030
  var useValue = arguments.length > 2;
572681
573031
  for (var i6 = 0;i6 < initializers.length; i6++) {
572682
573032
  value = useValue ? initializers[i6].call(thisArg, value) : initializers[i6].call(thisArg);
@@ -572736,8 +573086,8 @@ var init_ScreenRecorder = __esm(() => {
572736
573086
  init_util6();
572737
573087
  init_decorators();
572738
573088
  init_disposable();
572739
- import_debug182 = __toESM(require_src(), 1);
572740
- debugFfmpeg = import_debug182.default("puppeteer:ffmpeg");
573089
+ import_debug183 = __toESM(require_src(), 1);
573090
+ debugFfmpeg = import_debug183.default("puppeteer:ffmpeg");
572741
573091
  ScreenRecorder = (() => {
572742
573092
  let _classSuper = PassThrough4;
572743
573093
  let _instanceExtraInitializers = [];
@@ -612335,6 +612685,9 @@ function getCurrentTimestamp() {
612335
612685
  return new Date().toISOString();
612336
612686
  }
612337
612687
  function validatePathWithinBase(basePath, relativePath) {
612688
+ if (process.platform !== "win32" && relativePath.includes("\\")) {
612689
+ throw new Error(`Path traversal detected: "${relativePath}" would escape the base directory`);
612690
+ }
612338
612691
  const resolvedPath = resolve51(basePath, relativePath);
612339
612692
  const normalizedBase = resolve51(basePath) + sep38;
612340
612693
  if (!resolvedPath.startsWith(normalizedBase) && resolvedPath !== resolve51(basePath)) {
@@ -632469,7 +632822,11 @@ function should1hCacheTTL(querySource, agentCacheTtlOverride) {
632469
632822
  return resolvePromptCacheTtl(querySource, { agentCacheTtlOverride }).ttl === "1h";
632470
632823
  }
632471
632824
  function configureEffortParams(effortValue, outputConfig, extraBodyParams, betas, model) {
632472
- if (!modelSupportsEffort(model) || "effort" in outputConfig) {
632825
+ if (!modelSupportsEffort(model)) {
632826
+ delete outputConfig.effort;
632827
+ return;
632828
+ }
632829
+ if ("effort" in outputConfig) {
632473
632830
  return;
632474
632831
  }
632475
632832
  if (effortValue === undefined) {
@@ -632477,12 +632834,6 @@ function configureEffortParams(effortValue, outputConfig, extraBodyParams, betas
632477
632834
  } else if (typeof effortValue === "string") {
632478
632835
  outputConfig.effort = effortValue;
632479
632836
  betas.push(EFFORT_BETA_HEADER);
632480
- } else if (process.env.USER_TYPE === "ant") {
632481
- const existingInternal = extraBodyParams.anthropic_internal || {};
632482
- extraBodyParams.anthropic_internal = {
632483
- ...existingInternal,
632484
- effort_override: effortValue
632485
- };
632486
632837
  }
632487
632838
  }
632488
632839
  function configureTaskBudgetParams(taskBudget, outputConfig, betas) {
@@ -637074,17 +637425,23 @@ function applySettingsChange(source2, setAppState) {
637074
637425
  const prevEffort = prev.settings.effortLevel;
637075
637426
  const newEffort = newSettings.effortLevel;
637076
637427
  const effortChanged = prevEffort !== newEffort;
637428
+ const effortSyncModel = getMainLoopModel();
637429
+ const effortSyncBlocked = !modelSupportsEffort(effortSyncModel) || getEffortEnvOverride() !== undefined;
637430
+ const clampedEffort = effortSyncBlocked || newEffort === undefined ? undefined : clampEffortToCap(newEffort, effortSyncModel);
637077
637431
  return {
637078
637432
  ...prev,
637079
637433
  settings: newSettings,
637080
637434
  toolPermissionContext: newContext,
637081
- ...effortChanged && newEffort !== undefined ? { effortValue: newEffort } : {}
637435
+ ...effortChanged && clampedEffort !== undefined ? { effortValue: clampedEffort } : {}
637082
637436
  };
637083
637437
  });
637084
637438
  }
637085
637439
  var init_applySettingsChange = __esm(() => {
637086
637440
  init_debug();
637441
+ init_effort();
637442
+ init_cap();
637087
637443
  init_hooksConfigSnapshot();
637444
+ init_model();
637088
637445
  init_permissionSetup();
637089
637446
  init_permissions2();
637090
637447
  init_permissionsLoader();
@@ -649243,7 +649600,7 @@ var init_EffortIndicator = __esm(() => {
649243
649600
 
649244
649601
  // src/components/ModelPicker.tsx
649245
649602
  function ModelPicker(t0) {
649246
- const $4 = import_compiler_runtime133.c(84);
649603
+ const $4 = import_compiler_runtime133.c(86);
649247
649604
  const {
649248
649605
  initial,
649249
649606
  sessionModel,
@@ -649369,6 +649726,9 @@ function ModelPicker(t0) {
649369
649726
  t8 = $4[22];
649370
649727
  }
649371
649728
  const focusedSupportsMax = t8;
649729
+ const focusedModelForCap = resolveOptionModel(focusedValue);
649730
+ const focusedCap = focusedModelForCap ? getEffectiveEffortCap(focusedModelForCap) : null;
649731
+ const focusedCapped = focusedModelForCap ? hasEffortLevelsAboveCap(focusedModelForCap) : false;
649372
649732
  let t9;
649373
649733
  if ($4[23] !== focusedValue) {
649374
649734
  t9 = getDefaultEffortLevelForOption(focusedValue);
@@ -649378,13 +649738,16 @@ function ModelPicker(t0) {
649378
649738
  t9 = $4[24];
649379
649739
  }
649380
649740
  const focusedDefaultEffort = t9;
649381
- const displayEffort = effort === "max" && !focusedSupportsMax || effort === "xhigh" && !focusedSupportsXhigh ? "high" : effort;
649741
+ const t8b = effort === "max" && !focusedSupportsMax || effort === "xhigh" && !focusedSupportsXhigh ? "high" : effort;
649742
+ const displayEffort = t8b !== undefined && focusedModelForCap ? clampEffortToCap(t8b, focusedModelForCap) : t8b;
649382
649743
  let t10;
649383
649744
  if ($4[25] !== effortValue || $4[26] !== hasToggledEffort) {
649384
649745
  t10 = (value) => {
649385
649746
  setFocusedValue(value);
649386
649747
  if (!hasToggledEffort && effortValue === undefined) {
649387
- setEffort(getDefaultEffortLevelForOption(value));
649748
+ const focusModel = resolveOptionModel(value);
649749
+ const defaultEffort = getDefaultEffortLevelForOption(value);
649750
+ setEffort(focusModel ? clampEffortToCap(defaultEffort, focusModel) : defaultEffort);
649388
649751
  }
649389
649752
  };
649390
649753
  $4[25] = effortValue;
@@ -649395,12 +649758,12 @@ function ModelPicker(t0) {
649395
649758
  }
649396
649759
  const handleFocus = t10;
649397
649760
  let t11;
649398
- if ($4[28] !== focusedDefaultEffort || $4[29] !== focusedSupportsEffort || $4[30] !== focusedSupportsMax || $4[83] !== focusedSupportsXhigh) {
649761
+ if ($4[28] !== focusedDefaultEffort || $4[29] !== focusedSupportsEffort || $4[30] !== focusedSupportsMax || $4[83] !== focusedSupportsXhigh || $4[84] !== focusedCap) {
649399
649762
  t11 = (direction) => {
649400
649763
  if (!focusedSupportsEffort) {
649401
649764
  return;
649402
649765
  }
649403
- setEffort((prev) => cycleEffortLevel(prev ?? focusedDefaultEffort, direction, focusedSupportsMax, focusedSupportsXhigh));
649766
+ setEffort((prev) => cycleEffortLevel(prev ?? focusedDefaultEffort, direction, focusedSupportsMax, focusedSupportsXhigh, focusedCap));
649404
649767
  setHasToggledEffort(true);
649405
649768
  };
649406
649769
  $4[28] = focusedDefaultEffort;
@@ -649408,6 +649771,7 @@ function ModelPicker(t0) {
649408
649771
  $4[30] = focusedSupportsMax;
649409
649772
  $4[31] = t11;
649410
649773
  $4[83] = focusedSupportsXhigh;
649774
+ $4[84] = focusedCap;
649411
649775
  } else {
649412
649776
  t11 = $4[31];
649413
649777
  }
@@ -649448,11 +649812,14 @@ function ModelPicker(t0) {
649448
649812
  let t14;
649449
649813
  if ($4[35] !== effort || $4[36] !== hasToggledEffort || $4[37] !== onSelect || $4[38] !== setAppState || $4[39] !== skipSettingsWrite) {
649450
649814
  t14 = function handleSelect2(value_0) {
649815
+ const selectedModel = resolveOptionModel(value_0);
649816
+ const clampedSelectEffort = selectedModel && effort !== undefined ? clampEffortToCap(effort, selectedModel) : effort;
649451
649817
  logEvent2("tengu_model_command_menu_effort", {
649452
- effort
649818
+ effort: clampedSelectEffort
649453
649819
  });
649454
649820
  if (!skipSettingsWrite) {
649455
- const effortLevel = resolvePickerEffortPersistence(effort, getDefaultEffortLevelForOption(value_0), getSettingsForSource("userSettings")?.effortLevel, hasToggledEffort);
649821
+ const persistModel = selectedModel ?? getDefaultMainLoopModel();
649822
+ const effortLevel = clampEffortToCap(resolvePickerEffortPersistence(effort, getDefaultEffortLevelForOption(value_0), getSettingsForSource("userSettings")?.effortLevel, hasToggledEffort), persistModel);
649456
649823
  const persistable = toPersistableEffort(effortLevel);
649457
649824
  if (persistable !== undefined) {
649458
649825
  updateSettingsForSource("userSettings", {
@@ -649464,8 +649831,7 @@ function ModelPicker(t0) {
649464
649831
  effortValue: effortLevel
649465
649832
  }));
649466
649833
  }
649467
- const selectedModel = resolveOptionModel(value_0);
649468
- const selectedEffort = hasToggledEffort && selectedModel && modelSupportsEffort(selectedModel) ? effort : undefined;
649834
+ const selectedEffort = hasToggledEffort && selectedModel && modelSupportsEffort(selectedModel) ? clampedSelectEffort : undefined;
649469
649835
  if (value_0 === NO_PREFERENCE) {
649470
649836
  onSelect(null, selectedEffort);
649471
649837
  return;
@@ -649598,42 +649964,49 @@ function ModelPicker(t0) {
649598
649964
  t23 = $4[61];
649599
649965
  }
649600
649966
  let t24;
649601
- if ($4[62] !== displayEffort || $4[63] !== focusedDefaultEffort || $4[64] !== focusedModelName || $4[65] !== focusedSupportsEffort) {
649602
- t24 = /* @__PURE__ */ jsx_runtime183.jsx(ThemedBox_default, {
649967
+ if ($4[62] !== displayEffort || $4[63] !== focusedDefaultEffort || $4[64] !== focusedModelName || $4[65] !== focusedSupportsEffort || $4[85] !== focusedCapped) {
649968
+ t24 = /* @__PURE__ */ jsx_runtime183.jsxs(ThemedBox_default, {
649603
649969
  marginBottom: 1,
649604
649970
  flexDirection: "column",
649605
- children: focusedSupportsEffort ? /* @__PURE__ */ jsx_runtime183.jsxs(ThemedText, {
649606
- dimColor: true,
649607
- children: [
649608
- /* @__PURE__ */ jsx_runtime183.jsx(EffortLevelIndicator, {
649609
- effort: displayEffort
649610
- }),
649611
- " ",
649612
- capitalize_default(displayEffort),
649613
- " effort",
649614
- displayEffort === focusedDefaultEffort ? " (default)" : "",
649615
- " ",
649616
- /* @__PURE__ */ jsx_runtime183.jsx(ThemedText, {
649617
- color: "subtle",
649618
- children: "\u2190 \u2192 to adjust"
649619
- })
649620
- ]
649621
- }) : /* @__PURE__ */ jsx_runtime183.jsxs(ThemedText, {
649622
- color: "subtle",
649623
- children: [
649624
- /* @__PURE__ */ jsx_runtime183.jsx(EffortLevelIndicator, {
649625
- effort: undefined
649626
- }),
649627
- " Effort not supported",
649628
- focusedModelName ? ` for ${focusedModelName}` : ""
649629
- ]
649630
- })
649971
+ children: [
649972
+ focusedSupportsEffort ? /* @__PURE__ */ jsx_runtime183.jsxs(ThemedText, {
649973
+ dimColor: true,
649974
+ children: [
649975
+ /* @__PURE__ */ jsx_runtime183.jsx(EffortLevelIndicator, {
649976
+ effort: displayEffort
649977
+ }),
649978
+ " ",
649979
+ capitalize_default(displayEffort),
649980
+ " effort",
649981
+ displayEffort === focusedDefaultEffort ? " (default)" : "",
649982
+ " ",
649983
+ /* @__PURE__ */ jsx_runtime183.jsx(ThemedText, {
649984
+ color: "subtle",
649985
+ children: "\u2190 \u2192 to adjust"
649986
+ })
649987
+ ]
649988
+ }) : /* @__PURE__ */ jsx_runtime183.jsxs(ThemedText, {
649989
+ color: "subtle",
649990
+ children: [
649991
+ /* @__PURE__ */ jsx_runtime183.jsx(EffortLevelIndicator, {
649992
+ effort: undefined
649993
+ }),
649994
+ " Effort not supported",
649995
+ focusedModelName ? ` for ${focusedModelName}` : ""
649996
+ ]
649997
+ }),
649998
+ focusedCapped ? /* @__PURE__ */ jsx_runtime183.jsx(ThemedText, {
649999
+ color: "subtle",
650000
+ children: "Higher effort levels are capped by your settings or organization."
650001
+ }) : null
650002
+ ]
649631
650003
  });
649632
650004
  $4[62] = displayEffort;
649633
650005
  $4[63] = focusedDefaultEffort;
649634
650006
  $4[64] = focusedModelName;
649635
650007
  $4[65] = focusedSupportsEffort;
649636
650008
  $4[66] = t24;
650009
+ $4[85] = focusedCapped;
649637
650010
  } else {
649638
650011
  t24 = $4[66];
649639
650012
  }
@@ -649817,8 +650190,9 @@ function EffortLevelIndicator(t0) {
649817
650190
  }
649818
650191
  return t4;
649819
650192
  }
649820
- function cycleEffortLevel(current, direction, includeMax, includeXhigh) {
649821
- const levels = ["low", "medium", "high", "xhigh", "max"].filter((level) => (level !== "max" || includeMax) && (level !== "xhigh" || includeXhigh));
650193
+ function cycleEffortLevel(current, direction, includeMax, includeXhigh, cap) {
650194
+ const capIndex = cap !== undefined && cap !== null ? EFFORT_LEVEL_ORDER.indexOf(cap) : EFFORT_LEVEL_ORDER.length - 1;
650195
+ const levels = EFFORT_LEVEL_ORDER.filter((level, index2) => index2 <= capIndex && (level !== "max" || includeMax) && (level !== "xhigh" || includeXhigh));
649822
650196
  const clamped = current === "max" && !includeMax || current === "xhigh" && !includeXhigh ? "high" : current;
649823
650197
  const idx = levels.indexOf(clamped);
649824
650198
  const currentIndex = idx !== -1 ? idx : levels.length - 1;
@@ -649833,7 +650207,7 @@ function getDefaultEffortLevelForOption(value) {
649833
650207
  const defaultValue = getDefaultEffortForModel(resolved);
649834
650208
  return defaultValue !== undefined ? convertEffortValueToLevel(defaultValue) : "high";
649835
650209
  }
649836
- var import_compiler_runtime133, import_react103, jsx_runtime183, NO_PREFERENCE = "__NO_PREFERENCE__";
650210
+ var import_compiler_runtime133, import_react103, jsx_runtime183, NO_PREFERENCE = "__NO_PREFERENCE__", EFFORT_LEVEL_ORDER;
649837
650211
  var init_ModelPicker = __esm(() => {
649838
650212
  init_capitalize();
649839
650213
  init_useExitOnCtrlCDWithKeybindings();
@@ -649843,6 +650217,7 @@ var init_ModelPicker = __esm(() => {
649843
650217
  init_useKeybinding();
649844
650218
  init_AppState();
649845
650219
  init_effort();
650220
+ init_cap();
649846
650221
  init_model();
649847
650222
  init_modelOptions();
649848
650223
  init_settings2();
@@ -649855,6 +650230,7 @@ var init_ModelPicker = __esm(() => {
649855
650230
  import_compiler_runtime133 = __toESM(require_compiler_runtime(), 1);
649856
650231
  import_react103 = __toESM(require_react(), 1);
649857
650232
  jsx_runtime183 = __toESM(require_jsx_runtime(), 1);
650233
+ EFFORT_LEVEL_ORDER = ["low", "medium", "high", "xhigh", "max"];
649858
650234
  });
649859
650235
 
649860
650236
  // src/components/ClaudeMdExternalIncludesDialog.tsx
@@ -716217,6 +716593,19 @@ __export(exports_effort, {
716217
716593
  call: () => call82
716218
716594
  });
716219
716595
  function setEffortValue(effortValue) {
716596
+ const model = getMainLoopModel();
716597
+ const clamped = typeof effortValue === "string" ? clampEffortToCap(effortValue, model) : effortValue;
716598
+ if (clamped !== effortValue) {
716599
+ logEvent2("tengu_effort_command", {
716600
+ effort: effortValue
716601
+ });
716602
+ return {
716603
+ message: `Effort '${effortValue}' exceeds the cap for ${model} set by your settings or organization; set to '${clamped}' instead (this session only): ${getEffortValueDescription(clamped)}`,
716604
+ effortUpdate: {
716605
+ value: clamped
716606
+ }
716607
+ };
716608
+ }
716220
716609
  const persistable = toPersistableEffort(effortValue);
716221
716610
  if (persistable !== undefined) {
716222
716611
  const result = updateSettingsForSource("userSettings", {
@@ -716267,9 +716656,10 @@ function showCurrentEffort(appStateEffort, model) {
716267
716656
  message: `Effort level: auto (currently ${level})`
716268
716657
  };
716269
716658
  }
716270
- const description = getEffortValueDescription(effectiveValue);
716659
+ const clamped = clampEffortToCap(effectiveValue, model);
716660
+ const description = getEffortValueDescription(clamped);
716271
716661
  return {
716272
- message: `Current effort level: ${effectiveValue} (${description})`
716662
+ message: `Current effort level: ${clamped} (${description})`
716273
716663
  };
716274
716664
  }
716275
716665
  function unsetEffortLevel() {
@@ -716301,7 +716691,17 @@ function unsetEffortLevel() {
716301
716691
  }
716302
716692
  };
716303
716693
  }
716304
- function enableUltracode() {
716694
+ function enableUltracode(model) {
716695
+ if (modelSupportsXhighEffort(model) && !isEffortLevelAllowed("xhigh", model)) {
716696
+ return {
716697
+ message: `Ultracode runs at xhigh effort, which is above the effort cap for ${model} set by your settings or organization. Valid options are: ${formatEffortValidOptions(model)}`
716698
+ };
716699
+ }
716700
+ if (!isUltracodeAvailableForModel(model)) {
716701
+ return {
716702
+ message: `Ultracode runs at xhigh effort, which ${model} doesn't support \u2014 switch to an xhigh-capable model (${XHIGH_CAPABLE_MODELS_HINT}). Valid options are: ${formatEffortValidOptions(model)}`
716703
+ };
716704
+ }
716305
716705
  enableUltracodeForSession();
716306
716706
  logEvent2("tengu_effort_command", {
716307
716707
  effort: "ultracode"
@@ -716323,11 +716723,11 @@ function executeEffort(args) {
716323
716723
  return unsetEffortLevel();
716324
716724
  }
716325
716725
  if (normalized === "ultracode") {
716326
- return enableUltracode();
716726
+ return enableUltracode(getMainLoopModel());
716327
716727
  }
716328
716728
  if (!isEffortLevel(normalized)) {
716329
716729
  return {
716330
- message: `Invalid argument: ${args}. Valid options are: low, medium, high, xhigh, max, ultracode, auto`
716730
+ message: `Invalid argument: ${args}. Valid options are: ${formatEffortValidOptions(getMainLoopModel())}`
716331
716731
  };
716332
716732
  }
716333
716733
  if (isUltracodeEnabled()) {
@@ -716390,14 +716790,17 @@ function ApplyEffortAndClose(t0) {
716390
716790
  async function call82(onDone, _context, args) {
716391
716791
  args = args?.trim() || "";
716392
716792
  if (COMMON_HELP_ARGS2.includes(args)) {
716393
- onDone(`Usage: /effort [low|medium|high|xhigh|max|ultracode|auto]
716394
- ` + `- low: Quick, straightforward implementation
716395
- ` + `- medium: Balanced approach with standard testing
716396
- ` + `- high: Comprehensive implementation with extensive testing
716397
- ` + `- xhigh: Extended reasoning with thorough analysis (Fable 5, Opus 4.7+, Sonnet 5)
716398
- ` + `- max: Maximum capability with deepest reasoning (Fable 5, Opus 4.6+, Sonnet 4.6+)
716399
- ` + `- ultracode: xhigh + dynamic workflow orchestration (this session only)
716400
- ` + "- auto: Use the default effort level for your model");
716793
+ const model = getMainLoopModel();
716794
+ const lines2 = [buildEffortArgumentHint("Usage: /effort [", "]", model)];
716795
+ for (const level of getAllowedEffortLevels(model)) {
716796
+ lines2.push(`- ${level}: ${SHORT_EFFORT_HELP[level]}`);
716797
+ }
716798
+ if (isUltracodeAvailableForModel(model)) {
716799
+ lines2.push("- ultracode: xhigh + dynamic workflow orchestration (this session only)");
716800
+ }
716801
+ lines2.push("- auto: Use the default effort level for your model");
716802
+ onDone(lines2.join(`
716803
+ `));
716401
716804
  return;
716402
716805
  }
716403
716806
  if (!args || args === "current" || args === "status") {
@@ -716411,29 +716814,42 @@ async function call82(onDone, _context, args) {
716411
716814
  onDone
716412
716815
  });
716413
716816
  }
716414
- var import_compiler_runtime248, React108, jsx_runtime350, COMMON_HELP_ARGS2;
716817
+ var import_compiler_runtime248, React108, jsx_runtime350, COMMON_HELP_ARGS2, XHIGH_CAPABLE_MODELS_HINT = "Fable 5, Opus 4.7+, Sonnet 5", SHORT_EFFORT_HELP;
716415
716818
  var init_effort2 = __esm(() => {
716416
716819
  init_useMainLoopModel();
716417
716820
  init_analytics();
716418
716821
  init_AppState();
716419
716822
  init_effort();
716823
+ init_cap();
716420
716824
  init_ultracode();
716825
+ init_model();
716421
716826
  init_settings2();
716422
716827
  import_compiler_runtime248 = __toESM(require_compiler_runtime(), 1);
716423
716828
  React108 = __toESM(require_react(), 1);
716424
716829
  jsx_runtime350 = __toESM(require_jsx_runtime(), 1);
716425
716830
  COMMON_HELP_ARGS2 = ["help", "-h", "--help"];
716831
+ SHORT_EFFORT_HELP = {
716832
+ low: "Quick, straightforward implementation",
716833
+ medium: "Balanced approach with standard testing",
716834
+ high: "Comprehensive implementation with extensive testing",
716835
+ xhigh: "Extended reasoning with thorough analysis (Fable 5, Opus 4.7+, Sonnet 5)",
716836
+ max: "Maximum capability with deepest reasoning (Fable 5, Opus 4.6+, Sonnet 4.6+)"
716837
+ };
716426
716838
  });
716427
716839
 
716428
716840
  // src/commands/effort/index.ts
716429
716841
  var effort_default;
716430
716842
  var init_effort3 = __esm(() => {
716843
+ init_cap();
716431
716844
  init_immediateCommand();
716845
+ init_model();
716432
716846
  effort_default = {
716433
716847
  type: "local-jsx",
716434
716848
  name: "effort",
716435
716849
  description: "Set effort level for model usage",
716436
- argumentHint: "[low|medium|high|xhigh|max|ultracode|auto]",
716850
+ get argumentHint() {
716851
+ return buildEffortArgumentHint("[", "]", getMainLoopModel());
716852
+ },
716437
716853
  get immediate() {
716438
716854
  return shouldInferenceConfigCommandBeImmediate();
716439
716855
  },
@@ -827382,6 +827798,7 @@ ${inputPrompt}` : mainThreadAgentDefinition.initialPrompt;
827382
827798
  effectiveMainLoopModel = ensureFableConsentSync(effectiveMainLoopModel);
827383
827799
  setInitialMainLoopModel(effectiveMainLoopModel);
827384
827800
  }
827801
+ emitStartupEffortCapWarning(parseEffortValue(options.effort) ?? getInitialEffortSetting(), parseUserSpecifiedModel(effectiveMainLoopModel ?? getDefaultMainLoopModel()), outputFormat);
827385
827802
  let advisorModel;
827386
827803
  if (isAdvisorEnabled()) {
827387
827804
  const advisorOption = canUserConfigureAdvisor() ? options.advisor : undefined;
@@ -829355,6 +829772,7 @@ var init_main7 = __esm(() => {
829355
829772
  init_autoCompactWindow();
829356
829773
  init_earlyInput();
829357
829774
  init_effort();
829775
+ init_cap();
829358
829776
  init_fastMode();
829359
829777
  init_managedEnv();
829360
829778
  init_messages3();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cnwenf/occ",
3
- "version": "2.1.327",
3
+ "version": "2.1.329",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "bin": {