opencode-acp 1.14.25-pr.350.76 → 1.14.25-pr.351.83

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
@@ -324,11 +324,12 @@ Each level overrides the previous, so project settings take priority over global
324
324
  // Soft upper threshold: above this, ACP keeps injecting strong
325
325
  // compression nudges (based on nudgeFrequency), so compression is
326
326
  // much more likely. Accepts: number or "X%" of model context window.
327
- "maxContextLimit": "55%",
328
- // Soft lower threshold for reminder nudges: below this, turn/iteration
329
- // reminders are off (compression less likely). At/above this, reminders
330
- // are on. Accepts: number or "X%" of model context window.
331
- "minContextLimit": "45%",
327
+ "maxContextLimit": "80%",
328
+ // Soft lower threshold for turn/iteration reminder nudges: below this,
329
+ // those reminders are off (compression less likely). At/above this, they
330
+ // are on. Growth nudges have their own floor: minNudgeContextPercent.
331
+ // Accepts: number or "X%" of model context window.
332
+ "minContextLimit": "80%",
332
333
  // Optional per-model override for maxContextLimit by providerID/modelID.
333
334
  // If present, this wins over the global maxContextLimit.
334
335
  // Accepts: number or "X%".
package/dist/index.js CHANGED
@@ -888,6 +888,7 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
888
888
  "compress.minContextLimit",
889
889
  "compress.modelMaxLimits",
890
890
  "compress.modelMinLimits",
891
+ "compress.providers",
891
892
  "compress.nudgeFrequency",
892
893
  "compress.minNudgeContextPercent",
893
894
  "compress.nudgeGrowthTokens",
@@ -908,7 +909,6 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
908
909
  "compress.preserveRecentMessages",
909
910
  "compress.preserveRecentTokens",
910
911
  "compress.preserveLastUserMessage",
911
- "compress.completionReserveTokens",
912
912
  "gc",
913
913
  "gc.algorithm",
914
914
  "gc.promotionThreshold",
@@ -932,7 +932,7 @@ function getConfigKeyPaths(obj, prefix = "") {
932
932
  for (const key of Object.keys(obj)) {
933
933
  const fullKey = prefix ? `${prefix}.${key}` : key;
934
934
  keys.push(fullKey);
935
- if (fullKey === "compress.modelMaxLimits" || fullKey === "compress.modelMinLimits" || fullKey === "messageFilters.filters") {
935
+ if (fullKey === "compress.modelMaxLimits" || fullKey === "compress.modelMinLimits" || fullKey === "compress.providers" || fullKey === "messageFilters.filters") {
936
936
  continue;
937
937
  }
938
938
  if (obj[key] && typeof obj[key] === "object" && !Array.isArray(obj[key])) {
@@ -1262,20 +1262,6 @@ function validateConfigTypes(config) {
1262
1262
  actual: typeof compress.preserveLastUserMessage
1263
1263
  });
1264
1264
  }
1265
- if (compress.completionReserveTokens !== void 0 && typeof compress.completionReserveTokens !== "number") {
1266
- errors.push({
1267
- key: "compress.completionReserveTokens",
1268
- expected: "number",
1269
- actual: typeof compress.completionReserveTokens
1270
- });
1271
- }
1272
- if (typeof compress.completionReserveTokens === "number" && compress.completionReserveTokens < 0) {
1273
- errors.push({
1274
- key: "compress.completionReserveTokens",
1275
- expected: "non-negative number (>= 0)",
1276
- actual: `${compress.completionReserveTokens}`
1277
- });
1278
- }
1279
1265
  if (typeof compress.iterationNudgeThreshold === "number" && compress.iterationNudgeThreshold < 1) {
1280
1266
  errors.push({
1281
1267
  key: "compress.iterationNudgeThreshold",
@@ -1326,6 +1312,85 @@ function validateConfigTypes(config) {
1326
1312
  }
1327
1313
  validateModelLimits("compress.modelMaxLimits", compress.modelMaxLimits);
1328
1314
  validateModelLimits("compress.modelMinLimits", compress.modelMinLimits);
1315
+ const validatePercentField = (key, value) => {
1316
+ if (value === void 0) {
1317
+ return;
1318
+ }
1319
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 100) {
1320
+ errors.push({
1321
+ key,
1322
+ expected: "number (0-100)",
1323
+ actual: JSON.stringify(value)
1324
+ });
1325
+ }
1326
+ };
1327
+ const validateModelOverrides = (prefix, overrides) => {
1328
+ if (overrides === void 0) {
1329
+ return;
1330
+ }
1331
+ if (typeof overrides !== "object" || overrides === null || Array.isArray(overrides)) {
1332
+ errors.push({ key: prefix, expected: "CompressModelOverrides", actual: typeof overrides });
1333
+ return;
1334
+ }
1335
+ const model = overrides;
1336
+ for (const field of Object.keys(model)) {
1337
+ if (field !== "minNudgeContextPercent") {
1338
+ errors.push({
1339
+ key: `${prefix}.${field}`,
1340
+ expected: "known override field (minNudgeContextPercent)",
1341
+ actual: "unknown field"
1342
+ });
1343
+ }
1344
+ }
1345
+ validatePercentField(`${prefix}.minNudgeContextPercent`, model.minNudgeContextPercent);
1346
+ };
1347
+ const validateProviderOverrides = (providers) => {
1348
+ if (providers === void 0) {
1349
+ return;
1350
+ }
1351
+ if (typeof providers !== "object" || providers === null || Array.isArray(providers)) {
1352
+ errors.push({
1353
+ key: "compress.providers",
1354
+ expected: "Record<string, ProviderOverrides>",
1355
+ actual: typeof providers
1356
+ });
1357
+ return;
1358
+ }
1359
+ for (const [providerId, providerValue] of Object.entries(providers)) {
1360
+ const prefix = `compress.providers.${providerId}`;
1361
+ if (typeof providerValue !== "object" || providerValue === null || Array.isArray(providerValue)) {
1362
+ errors.push({ key: prefix, expected: "ProviderOverrides", actual: typeof providerValue });
1363
+ continue;
1364
+ }
1365
+ const provider = providerValue;
1366
+ for (const field of Object.keys(provider)) {
1367
+ if (field !== "minNudgeContextPercent" && field !== "models") {
1368
+ errors.push({
1369
+ key: `${prefix}.${field}`,
1370
+ expected: "known override field (minNudgeContextPercent, models)",
1371
+ actual: "unknown field"
1372
+ });
1373
+ }
1374
+ }
1375
+ validatePercentField(`${prefix}.minNudgeContextPercent`, provider.minNudgeContextPercent);
1376
+ const models = provider.models;
1377
+ if (models === void 0) {
1378
+ continue;
1379
+ }
1380
+ if (typeof models !== "object" || models === null || Array.isArray(models)) {
1381
+ errors.push({
1382
+ key: `${prefix}.models`,
1383
+ expected: "Record<string, ModelOverrides>",
1384
+ actual: typeof models
1385
+ });
1386
+ continue;
1387
+ }
1388
+ for (const [modelId, modelValue] of Object.entries(models)) {
1389
+ validateModelOverrides(`${prefix}.models.${modelId}`, modelValue);
1390
+ }
1391
+ }
1392
+ };
1393
+ validateProviderOverrides(compress.providers);
1329
1394
  const validValues = ["ask", "allow", "deny"];
1330
1395
  if (compress.permission !== void 0 && !validValues.includes(compress.permission)) {
1331
1396
  errors.push({
@@ -1504,7 +1569,7 @@ var defaultConfig = {
1504
1569
  maxContextLimit: "80%",
1505
1570
  minContextLimit: "80%",
1506
1571
  nudgeFrequency: 5,
1507
- minNudgeContextPercent: 15,
1572
+ minNudgeContextPercent: 5,
1508
1573
  iterationNudgeThreshold: 15,
1509
1574
  nudgeForce: "soft",
1510
1575
  protectedTools: [...COMPRESS_DEFAULT_PROTECTED_TOOLS],
@@ -1626,6 +1691,39 @@ function loadConfigFile(configPath) {
1626
1691
  return { data: null, parseError: error.message || "Failed to parse config" };
1627
1692
  }
1628
1693
  }
1694
+ function stripUndefined(value) {
1695
+ const result = {};
1696
+ for (const [key, entry] of Object.entries(value)) {
1697
+ if (entry !== void 0) {
1698
+ result[key] = entry;
1699
+ }
1700
+ }
1701
+ return result;
1702
+ }
1703
+ function mergeModelOverrides(base, override) {
1704
+ if (base === void 0) return override;
1705
+ if (override === void 0) return base;
1706
+ const merged = { ...base };
1707
+ for (const [modelId, model] of Object.entries(override)) {
1708
+ merged[modelId] = { ...base[modelId], ...stripUndefined(model) };
1709
+ }
1710
+ return merged;
1711
+ }
1712
+ function mergeProviderOverrides(base, override) {
1713
+ if (base === void 0) return override;
1714
+ if (override === void 0) return base;
1715
+ const merged = { ...base };
1716
+ for (const [providerId, provider] of Object.entries(override)) {
1717
+ const baseProvider = base[providerId];
1718
+ const mergedModels = mergeModelOverrides(baseProvider?.models, provider.models);
1719
+ merged[providerId] = {
1720
+ ...baseProvider,
1721
+ ...stripUndefined(provider),
1722
+ ...mergedModels !== void 0 ? { models: mergedModels } : {}
1723
+ };
1724
+ }
1725
+ return merged;
1726
+ }
1629
1727
  function mergeCompress(base, override) {
1630
1728
  if (!override) {
1631
1729
  return base;
@@ -1638,6 +1736,7 @@ function mergeCompress(base, override) {
1638
1736
  minContextLimit: override.minContextLimit ?? base.minContextLimit,
1639
1737
  modelMaxLimits: override.modelMaxLimits ?? base.modelMaxLimits,
1640
1738
  modelMinLimits: override.modelMinLimits ?? base.modelMinLimits,
1739
+ providers: mergeProviderOverrides(base.providers, override.providers),
1641
1740
  nudgeFrequency: override.nudgeFrequency ?? base.nudgeFrequency,
1642
1741
  minNudgeContextPercent: override.minNudgeContextPercent ?? base.minNudgeContextPercent,
1643
1742
  nudgeGrowthTokens: override.nudgeGrowthTokens,
@@ -1657,8 +1756,7 @@ function mergeCompress(base, override) {
1657
1756
  lastSegmentSoftBlock: override.lastSegmentSoftBlock ?? base.lastSegmentSoftBlock,
1658
1757
  preserveRecentMessages: override.preserveRecentMessages ?? base.preserveRecentMessages,
1659
1758
  preserveRecentTokens: override.preserveRecentTokens ?? base.preserveRecentTokens,
1660
- preserveLastUserMessage: override.preserveLastUserMessage ?? base.preserveLastUserMessage,
1661
- completionReserveTokens: override.completionReserveTokens ?? base.completionReserveTokens
1759
+ preserveLastUserMessage: override.preserveLastUserMessage ?? base.preserveLastUserMessage
1662
1760
  };
1663
1761
  }
1664
1762
  function mergeCommands(base, override) {
@@ -1689,6 +1787,22 @@ function deepCloneConfig(config) {
1689
1787
  ...config.compress,
1690
1788
  modelMaxLimits: { ...config.compress.modelMaxLimits },
1691
1789
  modelMinLimits: { ...config.compress.modelMinLimits },
1790
+ providers: config.compress.providers ? Object.fromEntries(
1791
+ Object.entries(config.compress.providers).map(([providerId, provider]) => [
1792
+ providerId,
1793
+ {
1794
+ ...provider,
1795
+ ...provider.models ? {
1796
+ models: Object.fromEntries(
1797
+ Object.entries(provider.models).map(([modelId, model]) => [
1798
+ modelId,
1799
+ { ...model }
1800
+ ])
1801
+ )
1802
+ } : {}
1803
+ }
1804
+ ])
1805
+ ) : void 0,
1692
1806
  protectedTools: [...config.compress.protectedTools]
1693
1807
  },
1694
1808
  gc: {
@@ -4317,8 +4431,7 @@ function createSessionState() {
4317
4431
  modelProviderID: void 0,
4318
4432
  modelID: void 0,
4319
4433
  systemPromptTokens: void 0,
4320
- qualityGateRetryPending: false,
4321
- noContextLimitWarned: false
4434
+ qualityGateRetryPending: false
4322
4435
  };
4323
4436
  }
4324
4437
  function resetSessionState(state) {
@@ -4360,7 +4473,6 @@ function resetSessionState(state) {
4360
4473
  state.modelID = void 0;
4361
4474
  state.systemPromptTokens = void 0;
4362
4475
  state.qualityGateRetryPending = false;
4363
- state.noContextLimitWarned = false;
4364
4476
  }
4365
4477
  async function ensureSessionInitialized(client, state, sessionId, logger, messages, config) {
4366
4478
  if (state.sessionId === sessionId) {
@@ -6975,6 +7087,26 @@ function computeShouldNudge2(params) {
6975
7087
  return policy.computeShouldNudge(params);
6976
7088
  }
6977
7089
  var DEFAULT_NUDGE_GROWTH_TOKENS = 5e4;
7090
+ var DEFAULT_MIN_NUDGE_CONTEXT_PERCENT = 5;
7091
+ function resolveMinNudgeContextPercent(config, providerId, modelId) {
7092
+ const modelOverrides = providerId !== void 0 && modelId !== void 0 ? config.compress?.providers?.[providerId]?.models?.[modelId] : void 0;
7093
+ if (modelOverrides?.minNudgeContextPercent !== void 0) {
7094
+ return modelOverrides.minNudgeContextPercent;
7095
+ }
7096
+ const providerOverrides = providerId !== void 0 ? config.compress?.providers?.[providerId] : void 0;
7097
+ if (providerOverrides?.minNudgeContextPercent !== void 0) {
7098
+ return providerOverrides.minNudgeContextPercent;
7099
+ }
7100
+ return config.compress?.minNudgeContextPercent;
7101
+ }
7102
+ function resolveMinNudgeFloorTokens(config, modelContextLimit, providerId, modelId) {
7103
+ if (modelContextLimit === void 0) {
7104
+ return void 0;
7105
+ }
7106
+ const percent = resolveMinNudgeContextPercent(config, providerId, modelId) ?? DEFAULT_MIN_NUDGE_CONTEXT_PERCENT;
7107
+ const clamped = Math.min(100, Math.max(0, percent));
7108
+ return Math.round(clamped / 100 * modelContextLimit);
7109
+ }
6978
7110
  function addAnchor(anchorMessageIds, anchorMessageId, anchorMessageIndex, messages, interval) {
6979
7111
  if (anchorMessageIndex < 0) {
6980
7112
  return false;
@@ -7657,11 +7789,18 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
7657
7789
  overMinLimit,
7658
7790
  overMaxLimit,
7659
7791
  lastNudgeTokens: growthReference,
7660
- minNudgeContextPercent: config.compress?.minNudgeContextPercent ?? 15,
7792
+ minNudgeContextPercent: resolveMinNudgeContextPercent(config, providerId, modelId) ?? DEFAULT_MIN_NUDGE_CONTEXT_PERCENT,
7661
7793
  nudgeGrowthTokens: effectiveThreshold
7662
7794
  });
7663
7795
  const growthSinceBaseline = currentTokens !== void 0 && growthReference !== void 0 ? currentTokens - growthReference : void 0;
7664
- const nudgeAllowed = emergencyOverride || decision.shouldNudge && growthSinceBaseline !== void 0 && growthSinceBaseline >= growthFloor;
7796
+ const minNudgeFloorTokens = resolveMinNudgeFloorTokens(
7797
+ config,
7798
+ modelContextLimit,
7799
+ providerId,
7800
+ modelId
7801
+ );
7802
+ const overMinNudgeFloor = minNudgeFloorTokens === void 0 || currentTokens === void 0 || currentTokens >= minNudgeFloorTokens;
7803
+ const nudgeAllowed = emergencyOverride || decision.shouldNudge && (overMaxLimit || overMinNudgeFloor) && growthSinceBaseline !== void 0 && growthSinceBaseline >= growthFloor;
7665
7804
  const effectiveTipsVariant = emergencyOverride ? "maxLimit" : decision.tipsVariant;
7666
7805
  if (state.nudges.lastPerMessageNudgeTokens === void 0 && currentTokens !== void 0) {
7667
7806
  state.nudges.lastPerMessageNudgeTokens = currentTokens;
@@ -9128,7 +9267,7 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
9128
9267
  import { join as join3 } from "path";
9129
9268
  import { existsSync as existsSync3 } from "fs";
9130
9269
  import { homedir as homedir3 } from "os";
9131
- var LOG_VERSION = true ? "1.14.25-pr.350.76" : "dev";
9270
+ var LOG_VERSION = true ? "1.14.25-pr.351.83" : "dev";
9132
9271
  var LEVEL_RANK = {
9133
9272
  debug: 10,
9134
9273
  info: 20,
@@ -10013,153 +10152,6 @@ function truncateLargeToolOutputs(state, config, logger, messages) {
10013
10152
  }
10014
10153
  }
10015
10154
 
10016
- // lib/messages/enforce-budget.ts
10017
- var DEFAULT_COMPLETION_RESERVE_TOKENS = 32768;
10018
- var TRUNCATION_MARKER2 = "[truncated for context space";
10019
- var KEEP_PREFIX_CHARS2 = 2e3;
10020
- var KEEP_SUFFIX_CHARS2 = 2e3;
10021
- var PROTECT_RECENT_MESSAGES2 = 3;
10022
- var MIN_CLEAR_TOKENS = 200;
10023
- function resolveContextWindow(state) {
10024
- if (typeof state.modelContextLimit === "number" && state.modelContextLimit > 0) {
10025
- return state.modelContextLimit;
10026
- }
10027
- return void 0;
10028
- }
10029
- function estimateWireTokens(state, messages) {
10030
- const base = getCurrentTokenUsage(state, messages);
10031
- if (base > 0) {
10032
- let baseAssistant = -1;
10033
- for (let i = messages.length - 1; i >= 0; i--) {
10034
- if (messages[i].info.role !== "assistant") continue;
10035
- const tokens = messages[i].info.tokens;
10036
- if ((tokens?.input || 0) <= 0 && (tokens?.output || 0) <= 0) continue;
10037
- baseAssistant = i;
10038
- break;
10039
- }
10040
- if (baseAssistant >= 0) {
10041
- let additions = 0;
10042
- for (let i = baseAssistant + 1; i < messages.length; i++) {
10043
- additions += countAllMessageTokens(messages[i]);
10044
- }
10045
- return base + additions;
10046
- }
10047
- }
10048
- let total = 0;
10049
- for (const m of messages) total += countAllMessageTokens(m);
10050
- return total + (state.systemPromptTokens ?? 0);
10051
- }
10052
- function enforceContextBudget(state, config, logger, messages) {
10053
- const window = resolveContextWindow(state);
10054
- if (window === void 0) return void 0;
10055
- const configuredReserve = config.compress?.completionReserveTokens;
10056
- const reserve = typeof configuredReserve === "number" && Number.isFinite(configuredReserve) && configuredReserve >= 0 ? configuredReserve : DEFAULT_COMPLETION_RESERVE_TOKENS;
10057
- const budget = window - reserve;
10058
- if (budget <= 0) return void 0;
10059
- const estimatedTokens = estimateWireTokens(state, messages);
10060
- if (estimatedTokens <= budget) {
10061
- return {
10062
- applied: false,
10063
- window,
10064
- reserve,
10065
- budget,
10066
- estimatedTokens,
10067
- finalEstimate: estimatedTokens,
10068
- truncatedCount: 0,
10069
- clearedCount: 0
10070
- };
10071
- }
10072
- const protectedIndex = messages.length - PROTECT_RECENT_MESSAGES2;
10073
- const protectedTools = new Set(config.compress?.protectedTools ?? []);
10074
- const candidates = [];
10075
- for (let mi = 0; mi < protectedIndex; mi++) {
10076
- if (mi === 0 && messages[mi].info.role === "user") continue;
10077
- const msg = messages[mi];
10078
- const parts = Array.isArray(msg.parts) ? msg.parts : [];
10079
- for (const part of parts) {
10080
- if (part?.type !== "tool") continue;
10081
- if (part.state?.status !== "completed") continue;
10082
- if (part.tool === "compress") continue;
10083
- if (protectedTools.has(part.tool)) continue;
10084
- const content = extractCompletedToolOutput(part);
10085
- if (content === void 0) continue;
10086
- if (content === COMPACTED_TOOL_OUTPUT_PLACEHOLDER) continue;
10087
- const tokens = countTokens2(content);
10088
- if (tokens <= 0) continue;
10089
- candidates.push({ part, content, tokens, index: mi });
10090
- }
10091
- }
10092
- let saved = 0;
10093
- let truncatedCount = 0;
10094
- let clearedCount = 0;
10095
- const truncatable = candidates.filter(
10096
- (c) => !c.content.includes(TRUNCATION_MARKER2) && c.content.length > KEEP_PREFIX_CHARS2 + KEEP_SUFFIX_CHARS2
10097
- ).sort((a, b) => b.tokens - a.tokens);
10098
- for (const c of truncatable) {
10099
- if (estimatedTokens - saved <= budget) break;
10100
- const prefix = c.content.slice(0, KEEP_PREFIX_CHARS2);
10101
- const suffix = c.content.slice(-KEEP_SUFFIX_CHARS2);
10102
- const truncated = prefix + `
10103
-
10104
- ...${TRUNCATION_MARKER2} \u2014 original ~${c.tokens} tokens]...
10105
-
10106
- ` + suffix;
10107
- if (truncated.length >= c.content.length) continue;
10108
- c.part.state.output = truncated;
10109
- saved += c.tokens - countTokens2(truncated);
10110
- truncatedCount++;
10111
- }
10112
- if (estimatedTokens - saved > budget) {
10113
- const clearable = candidates.filter((c) => {
10114
- const out = extractCompletedToolOutput(c.part);
10115
- return out !== void 0 && out !== COMPACTED_TOOL_OUTPUT_PLACEHOLDER && countTokens2(out) > MIN_CLEAR_TOKENS;
10116
- }).sort((a, b) => a.index - b.index);
10117
- for (const c of clearable) {
10118
- if (estimatedTokens - saved <= budget) break;
10119
- const current = extractCompletedToolOutput(c.part);
10120
- if (current === void 0 || current === COMPACTED_TOOL_OUTPUT_PLACEHOLDER) continue;
10121
- c.part.state.output = COMPACTED_TOOL_OUTPUT_PLACEHOLDER;
10122
- saved += countTokens2(current) - countTokens2(COMPACTED_TOOL_OUTPUT_PLACEHOLDER);
10123
- clearedCount++;
10124
- }
10125
- }
10126
- const finalEstimate = Math.max(0, estimatedTokens - saved);
10127
- if (truncatedCount > 0 || clearedCount > 0) {
10128
- logger.warn("Context budget guard: pruned tool outputs to fit the request", {
10129
- session: state.sessionId,
10130
- estimatedTokens: Math.round(estimatedTokens),
10131
- budget,
10132
- window,
10133
- reserve,
10134
- truncatedCount,
10135
- clearedCount,
10136
- estimatedSavedTokens: Math.round(saved),
10137
- finalEstimate: Math.round(finalEstimate)
10138
- });
10139
- }
10140
- if (finalEstimate > budget) {
10141
- logger.warn(
10142
- "Context budget guard: still over budget after pruning all compressible tool outputs; the request may be rejected by the model",
10143
- {
10144
- session: state.sessionId,
10145
- finalEstimate: Math.round(finalEstimate),
10146
- budget,
10147
- window
10148
- }
10149
- );
10150
- }
10151
- return {
10152
- applied: truncatedCount > 0 || clearedCount > 0,
10153
- window,
10154
- reserve,
10155
- budget,
10156
- estimatedTokens,
10157
- finalEstimate,
10158
- truncatedCount,
10159
- clearedCount
10160
- };
10161
- }
10162
-
10163
10155
  // lib/commands/context.ts
10164
10156
  function analyzeTokens(state, messages) {
10165
10157
  const breakdown = {
@@ -11261,16 +11253,6 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
11261
11253
  });
11262
11254
  }
11263
11255
  await updatePerTurnState(state, logger, messages);
11264
- if (state.modelContextLimit === void 0 && !state.noContextLimitWarned && requestModel?.providerID && requestModel?.modelID && registry4.resolveModelLimit(requestModel.providerID, requestModel.modelID) === void 0) {
11265
- state.noContextLimitWarned = true;
11266
- logger.warn(
11267
- 'Model reports no context window and the catalog has no entry for it; all percentage thresholds (min/max/emergency, GC) and the context-budget guard are disabled. Set the model limit in opencode.json (e.g. "limit": {"context": 262144, "output": 16384}) to enable them (also fixes the 32000 max_tokens fallback); an absolute compress.maxContextLimit in acp.jsonc only enables proactive nudges, not the guard.',
11268
- {
11269
- session: state.sessionId,
11270
- model: `${requestModel.providerID}/${requestModel.modelID}`
11271
- }
11272
- );
11273
- }
11274
11256
  }
11275
11257
  syncCompressPermissionState(state, config, hostPermissions, output.messages);
11276
11258
  if (state.isSubAgent && !config.allowSubAgents) {
@@ -11301,7 +11283,6 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
11301
11283
  const prePruneTokens = getCurrentTokenUsage(state, output.messages);
11302
11284
  prune(state, logger, config, output.messages);
11303
11285
  truncateLargeToolOutputs(state, config, logger, output.messages);
11304
- enforceContextBudget(state, config, logger, output.messages);
11305
11286
  hideConsumedCompressCalls(state, output.messages);
11306
11287
  assignMessageRefs(state, output.messages);
11307
11288
  const compressionPriorities = buildPriorityMap(config, state, output.messages);
@@ -11727,7 +11708,7 @@ var server = (async (ctx) => {
11727
11708
  }
11728
11709
  const logger = new Logger(config.debug, config.debug ? "debug" : config.logLevel);
11729
11710
  logger.info("ACP plugin initialized", {
11730
- version: true ? "1.14.25-pr.350.76" : "dev",
11711
+ version: true ? "1.14.25-pr.351.83" : "dev",
11731
11712
  workspace: ctx.directory,
11732
11713
  logLevel: logger.level,
11733
11714
  debug: config.debug,