opencode-acp 1.16.0-pr.360.124 → 1.16.0-pr.360.128
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +417 -60
- package/dist/index.js.map +1 -1
- package/dist/lib/compress/decompress.d.ts.map +1 -1
- package/dist/lib/config-validation.d.ts.map +1 -1
- package/dist/lib/config.d.ts +16 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/gc/merge.d.ts.map +1 -1
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/messages/enforce-budget.d.ts +65 -0
- package/dist/lib/messages/enforce-budget.d.ts.map +1 -0
- package/dist/lib/messages/inject/inject.d.ts.map +1 -1
- package/dist/lib/messages/inject/utils.d.ts.map +1 -1
- package/dist/lib/messages/query.d.ts +16 -0
- package/dist/lib/messages/query.d.ts.map +1 -1
- package/dist/lib/messages/truncate-tools.d.ts +1 -0
- package/dist/lib/messages/truncate-tools.d.ts.map +1 -1
- package/dist/lib/state/state.d.ts +2 -0
- package/dist/lib/state/state.d.ts.map +1 -1
- package/dist/lib/state/types.d.ts +6 -0
- package/dist/lib/state/types.d.ts.map +1 -1
- package/dist/lib/state/utils.d.ts +16 -0
- package/dist/lib/state/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -890,6 +890,7 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
890
890
|
"compress.modelMaxLimits",
|
|
891
891
|
"compress.modelMinLimits",
|
|
892
892
|
"compress.providers",
|
|
893
|
+
"compress.contextLimitFallback",
|
|
893
894
|
"compress.nudgeFrequency",
|
|
894
895
|
"compress.minNudgeContextPercent",
|
|
895
896
|
"compress.nudgeGrowthTokens",
|
|
@@ -913,6 +914,7 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
913
914
|
"compress.reasoning",
|
|
914
915
|
"compress.reasoning.drop",
|
|
915
916
|
"compress.reasoning.threshold",
|
|
917
|
+
"compress.completionReserveTokens",
|
|
916
918
|
"gc",
|
|
917
919
|
"gc.algorithm",
|
|
918
920
|
"gc.promotionThreshold",
|
|
@@ -964,7 +966,11 @@ function validateConfigTypes(config) {
|
|
|
964
966
|
errors.push({ key: "storagePath", expected: "string", actual: typeof config.storagePath });
|
|
965
967
|
}
|
|
966
968
|
if (config.allowSubAgents !== void 0 && typeof config.allowSubAgents !== "boolean") {
|
|
967
|
-
errors.push({
|
|
969
|
+
errors.push({
|
|
970
|
+
key: "allowSubAgents",
|
|
971
|
+
expected: "boolean",
|
|
972
|
+
actual: typeof config.allowSubAgents
|
|
973
|
+
});
|
|
968
974
|
}
|
|
969
975
|
if (config.pruneNotification !== void 0) {
|
|
970
976
|
const validValues = ["off", "minimal", "detailed"];
|
|
@@ -1293,6 +1299,20 @@ function validateConfigTypes(config) {
|
|
|
1293
1299
|
}
|
|
1294
1300
|
}
|
|
1295
1301
|
}
|
|
1302
|
+
if (compress.completionReserveTokens !== void 0 && typeof compress.completionReserveTokens !== "number") {
|
|
1303
|
+
errors.push({
|
|
1304
|
+
key: "compress.completionReserveTokens",
|
|
1305
|
+
expected: "number",
|
|
1306
|
+
actual: typeof compress.completionReserveTokens
|
|
1307
|
+
});
|
|
1308
|
+
}
|
|
1309
|
+
if (typeof compress.completionReserveTokens === "number" && compress.completionReserveTokens < 0) {
|
|
1310
|
+
errors.push({
|
|
1311
|
+
key: "compress.completionReserveTokens",
|
|
1312
|
+
expected: "non-negative number (>= 0)",
|
|
1313
|
+
actual: `${compress.completionReserveTokens}`
|
|
1314
|
+
});
|
|
1315
|
+
}
|
|
1296
1316
|
if (typeof compress.iterationNudgeThreshold === "number" && compress.iterationNudgeThreshold < 1) {
|
|
1297
1317
|
errors.push({
|
|
1298
1318
|
key: "compress.iterationNudgeThreshold",
|
|
@@ -1411,12 +1431,20 @@ function validateConfigTypes(config) {
|
|
|
1411
1431
|
break;
|
|
1412
1432
|
case "nudgeForce":
|
|
1413
1433
|
if (value !== "strong" && value !== "soft") {
|
|
1414
|
-
errors.push({
|
|
1434
|
+
errors.push({
|
|
1435
|
+
key,
|
|
1436
|
+
expected: "'strong' | 'soft'",
|
|
1437
|
+
actual: JSON.stringify(value)
|
|
1438
|
+
});
|
|
1415
1439
|
}
|
|
1416
1440
|
break;
|
|
1417
1441
|
case "stringArray":
|
|
1418
1442
|
if (!Array.isArray(value) || !value.every((entry) => typeof entry === "string")) {
|
|
1419
|
-
errors.push({
|
|
1443
|
+
errors.push({
|
|
1444
|
+
key,
|
|
1445
|
+
expected: "string[]",
|
|
1446
|
+
actual: JSON.stringify(value)
|
|
1447
|
+
});
|
|
1420
1448
|
}
|
|
1421
1449
|
break;
|
|
1422
1450
|
case "reasoningConfig":
|
|
@@ -1451,7 +1479,11 @@ function validateConfigTypes(config) {
|
|
|
1451
1479
|
return;
|
|
1452
1480
|
}
|
|
1453
1481
|
if (typeof overrides !== "object" || overrides === null || Array.isArray(overrides)) {
|
|
1454
|
-
errors.push({
|
|
1482
|
+
errors.push({
|
|
1483
|
+
key: prefix,
|
|
1484
|
+
expected: "CompressModelOverrides",
|
|
1485
|
+
actual: typeof overrides
|
|
1486
|
+
});
|
|
1455
1487
|
return;
|
|
1456
1488
|
}
|
|
1457
1489
|
const model = overrides;
|
|
@@ -1484,7 +1516,11 @@ function validateConfigTypes(config) {
|
|
|
1484
1516
|
for (const [providerId, providerValue] of Object.entries(providers)) {
|
|
1485
1517
|
const prefix = `compress.providers.${providerId}`;
|
|
1486
1518
|
if (typeof providerValue !== "object" || providerValue === null || Array.isArray(providerValue)) {
|
|
1487
|
-
errors.push({
|
|
1519
|
+
errors.push({
|
|
1520
|
+
key: prefix,
|
|
1521
|
+
expected: "ProviderOverrides",
|
|
1522
|
+
actual: typeof providerValue
|
|
1523
|
+
});
|
|
1488
1524
|
continue;
|
|
1489
1525
|
}
|
|
1490
1526
|
const provider = providerValue;
|
|
@@ -1521,6 +1557,20 @@ function validateConfigTypes(config) {
|
|
|
1521
1557
|
}
|
|
1522
1558
|
};
|
|
1523
1559
|
validateProviderOverrides(compress.providers);
|
|
1560
|
+
if (compress.contextLimitFallback !== void 0 && typeof compress.contextLimitFallback !== "number") {
|
|
1561
|
+
errors.push({
|
|
1562
|
+
key: "compress.contextLimitFallback",
|
|
1563
|
+
expected: "number",
|
|
1564
|
+
actual: typeof compress.contextLimitFallback
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1567
|
+
if (typeof compress.contextLimitFallback === "number" && compress.contextLimitFallback < 0) {
|
|
1568
|
+
errors.push({
|
|
1569
|
+
key: "compress.contextLimitFallback",
|
|
1570
|
+
expected: "non-negative number (0 disables the fallback)",
|
|
1571
|
+
actual: `${compress.contextLimitFallback}`
|
|
1572
|
+
});
|
|
1573
|
+
}
|
|
1524
1574
|
const validValues = ["ask", "allow", "deny"];
|
|
1525
1575
|
if (compress.permission !== void 0 && !validValues.includes(compress.permission)) {
|
|
1526
1576
|
errors.push({
|
|
@@ -1606,13 +1656,22 @@ function validateConfigTypes(config) {
|
|
|
1606
1656
|
});
|
|
1607
1657
|
} else {
|
|
1608
1658
|
if (gc.batchCleanup.lowThreshold !== void 0) {
|
|
1609
|
-
validateBatchThreshold(
|
|
1659
|
+
validateBatchThreshold(
|
|
1660
|
+
"gc.batchCleanup.lowThreshold",
|
|
1661
|
+
gc.batchCleanup.lowThreshold
|
|
1662
|
+
);
|
|
1610
1663
|
}
|
|
1611
1664
|
if (gc.batchCleanup.highThreshold !== void 0) {
|
|
1612
|
-
validateBatchThreshold(
|
|
1665
|
+
validateBatchThreshold(
|
|
1666
|
+
"gc.batchCleanup.highThreshold",
|
|
1667
|
+
gc.batchCleanup.highThreshold
|
|
1668
|
+
);
|
|
1613
1669
|
}
|
|
1614
1670
|
if (gc.batchCleanup.forceThreshold !== void 0) {
|
|
1615
|
-
validateBatchThreshold(
|
|
1671
|
+
validateBatchThreshold(
|
|
1672
|
+
"gc.batchCleanup.forceThreshold",
|
|
1673
|
+
gc.batchCleanup.forceThreshold
|
|
1674
|
+
);
|
|
1616
1675
|
}
|
|
1617
1676
|
}
|
|
1618
1677
|
}
|
|
@@ -1702,6 +1761,7 @@ var defaultConfig = {
|
|
|
1702
1761
|
summaryBuffer: true,
|
|
1703
1762
|
maxContextLimit: "80%",
|
|
1704
1763
|
minContextLimit: "80%",
|
|
1764
|
+
contextLimitFallback: 128e3,
|
|
1705
1765
|
nudgeFrequency: 5,
|
|
1706
1766
|
minNudgeContextPercent: 5,
|
|
1707
1767
|
iterationNudgeThreshold: 15,
|
|
@@ -1872,6 +1932,7 @@ function mergeCompress(base, override) {
|
|
|
1872
1932
|
modelMaxLimits: override.modelMaxLimits ?? base.modelMaxLimits,
|
|
1873
1933
|
modelMinLimits: override.modelMinLimits ?? base.modelMinLimits,
|
|
1874
1934
|
providers: mergeProviderOverrides(base.providers, override.providers),
|
|
1935
|
+
contextLimitFallback: override.contextLimitFallback ?? base.contextLimitFallback,
|
|
1875
1936
|
nudgeFrequency: override.nudgeFrequency ?? base.nudgeFrequency,
|
|
1876
1937
|
minNudgeContextPercent: override.minNudgeContextPercent ?? base.minNudgeContextPercent,
|
|
1877
1938
|
nudgeGrowthTokens: override.nudgeGrowthTokens,
|
|
@@ -1895,7 +1956,8 @@ function mergeCompress(base, override) {
|
|
|
1895
1956
|
reasoning: {
|
|
1896
1957
|
drop: override.reasoning?.drop ?? base.reasoning?.drop ?? DEFAULT_COMPRESS_REASONING.drop,
|
|
1897
1958
|
threshold: override.reasoning?.threshold ?? base.reasoning?.threshold ?? DEFAULT_COMPRESS_REASONING.threshold
|
|
1898
|
-
}
|
|
1959
|
+
},
|
|
1960
|
+
completionReserveTokens: override.completionReserveTokens ?? base.completionReserveTokens
|
|
1899
1961
|
};
|
|
1900
1962
|
}
|
|
1901
1963
|
function mergeCommands(base, override) {
|
|
@@ -1933,10 +1995,9 @@ function deepCloneConfig(config) {
|
|
|
1933
1995
|
...provider,
|
|
1934
1996
|
...provider.models ? {
|
|
1935
1997
|
models: Object.fromEntries(
|
|
1936
|
-
Object.entries(provider.models).map(
|
|
1937
|
-
modelId,
|
|
1938
|
-
|
|
1939
|
-
])
|
|
1998
|
+
Object.entries(provider.models).map(
|
|
1999
|
+
([modelId, model]) => [modelId, { ...model }]
|
|
2000
|
+
)
|
|
1940
2001
|
)
|
|
1941
2002
|
} : {}
|
|
1942
2003
|
}
|
|
@@ -2010,8 +2071,14 @@ function mergeLayer(config, data) {
|
|
|
2010
2071
|
],
|
|
2011
2072
|
compress: mergeCompress(config.compress, data.compress),
|
|
2012
2073
|
gc: mergeGC(config.gc, data.gc),
|
|
2013
|
-
qualityGate: mergeQualityGate(
|
|
2014
|
-
|
|
2074
|
+
qualityGate: mergeQualityGate(
|
|
2075
|
+
config.qualityGate,
|
|
2076
|
+
data.qualityGate
|
|
2077
|
+
),
|
|
2078
|
+
messageFilters: mergeMessageFilters(
|
|
2079
|
+
config.messageFilters,
|
|
2080
|
+
data.messageFilters
|
|
2081
|
+
)
|
|
2015
2082
|
};
|
|
2016
2083
|
}
|
|
2017
2084
|
function scheduleParseWarning(ctx, title, message) {
|
|
@@ -2159,6 +2226,56 @@ var messageHasCompressAttempt = (message) => {
|
|
|
2159
2226
|
const parts = Array.isArray(message.parts) ? message.parts : [];
|
|
2160
2227
|
return parts.some((part) => part.type === "tool" && part.tool === "compress");
|
|
2161
2228
|
};
|
|
2229
|
+
var isCaptureOnlyCompress = (message) => {
|
|
2230
|
+
if (!isMessageWithInfo(message)) {
|
|
2231
|
+
return false;
|
|
2232
|
+
}
|
|
2233
|
+
if (message.info.role !== "assistant") {
|
|
2234
|
+
return false;
|
|
2235
|
+
}
|
|
2236
|
+
const parts = Array.isArray(message.parts) ? message.parts : [];
|
|
2237
|
+
let sawBoundary = false;
|
|
2238
|
+
for (const part of parts) {
|
|
2239
|
+
if (!(part.type === "tool" && part.tool === "compress")) {
|
|
2240
|
+
continue;
|
|
2241
|
+
}
|
|
2242
|
+
for (const startId of extractCompressBoundaryIds(part.state?.input)) {
|
|
2243
|
+
sawBoundary = true;
|
|
2244
|
+
if (/^b\d+$/i.test(startId)) {
|
|
2245
|
+
return false;
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
return sawBoundary;
|
|
2250
|
+
};
|
|
2251
|
+
function extractCompressBoundaryIds(rawInput) {
|
|
2252
|
+
let content = [];
|
|
2253
|
+
if (typeof rawInput === "string") {
|
|
2254
|
+
try {
|
|
2255
|
+
const parsed = JSON.parse(rawInput);
|
|
2256
|
+
const c = parsed?.content;
|
|
2257
|
+
content = Array.isArray(c) ? c : [];
|
|
2258
|
+
} catch {
|
|
2259
|
+
return [];
|
|
2260
|
+
}
|
|
2261
|
+
} else if (rawInput && typeof rawInput === "object") {
|
|
2262
|
+
const c = rawInput.content;
|
|
2263
|
+
content = Array.isArray(c) ? c : [];
|
|
2264
|
+
}
|
|
2265
|
+
const ids = [];
|
|
2266
|
+
for (const entry of content) {
|
|
2267
|
+
if (!entry || typeof entry !== "object") {
|
|
2268
|
+
continue;
|
|
2269
|
+
}
|
|
2270
|
+
const { startId, endId } = entry;
|
|
2271
|
+
for (const sid of [startId, endId]) {
|
|
2272
|
+
if (typeof sid === "string" && sid.trim() !== "") {
|
|
2273
|
+
ids.push(sid.trim());
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
return ids;
|
|
2278
|
+
}
|
|
2162
2279
|
var isIgnoredUserMessage = (message) => {
|
|
2163
2280
|
if (!isMessageWithInfo(message)) {
|
|
2164
2281
|
return false;
|
|
@@ -2635,6 +2752,16 @@ function resetOnCompaction(state) {
|
|
|
2635
2752
|
nextRef: 1
|
|
2636
2753
|
};
|
|
2637
2754
|
}
|
|
2755
|
+
function resolveEffectiveContextLimit(state, config) {
|
|
2756
|
+
if (typeof state.modelContextLimit === "number" && state.modelContextLimit > 0) {
|
|
2757
|
+
return { limit: state.modelContextLimit, source: "model" };
|
|
2758
|
+
}
|
|
2759
|
+
const fallback = config.compress.contextLimitFallback;
|
|
2760
|
+
if (typeof fallback === "number" && fallback > 0) {
|
|
2761
|
+
return { limit: fallback, source: "fallback" };
|
|
2762
|
+
}
|
|
2763
|
+
return void 0;
|
|
2764
|
+
}
|
|
2638
2765
|
|
|
2639
2766
|
// lib/state/persistence.ts
|
|
2640
2767
|
function getDefaultStorageDir() {
|
|
@@ -4506,6 +4633,24 @@ var SessionStateRegistry = class {
|
|
|
4506
4633
|
hydrateModelLimitsFromClient(client) {
|
|
4507
4634
|
return this.catalog.hydrateFromClient(client);
|
|
4508
4635
|
}
|
|
4636
|
+
// [FIX #346] The init-time seed (above) is fire-and-forget and races
|
|
4637
|
+
// server readiness: in headless spawn+resume mode the provider-config
|
|
4638
|
+
// call can fail before the server is up, leaving the catalog empty for
|
|
4639
|
+
// the process's lifetime. During a request the server is guaranteed up
|
|
4640
|
+
// (we are inside its pipeline), so on a catalog miss we retry hydration
|
|
4641
|
+
// once per process before giving up (the fallback limit then applies).
|
|
4642
|
+
// The in-flight promise (not a boolean) lets concurrent callers await the
|
|
4643
|
+
// same hydration instead of skipping it.
|
|
4644
|
+
lazyHydration;
|
|
4645
|
+
async hydrateAndResolve(client, providerId, modelId) {
|
|
4646
|
+
const existing = this.catalog.resolve(providerId, modelId);
|
|
4647
|
+
if (existing !== void 0) {
|
|
4648
|
+
return existing;
|
|
4649
|
+
}
|
|
4650
|
+
this.lazyHydration ??= this.catalog.hydrateFromClient(client);
|
|
4651
|
+
await this.lazyHydration;
|
|
4652
|
+
return this.catalog.resolve(providerId, modelId);
|
|
4653
|
+
}
|
|
4509
4654
|
get(sessionId) {
|
|
4510
4655
|
return this.states.get(sessionId);
|
|
4511
4656
|
}
|
|
@@ -4599,7 +4744,8 @@ function createSessionState() {
|
|
|
4599
4744
|
modelID: void 0,
|
|
4600
4745
|
systemPromptTokens: void 0,
|
|
4601
4746
|
storageDir: void 0,
|
|
4602
|
-
qualityGateRetryPending: false
|
|
4747
|
+
qualityGateRetryPending: false,
|
|
4748
|
+
noContextLimitWarned: false
|
|
4603
4749
|
};
|
|
4604
4750
|
}
|
|
4605
4751
|
function resetSessionState(state) {
|
|
@@ -4642,6 +4788,7 @@ function resetSessionState(state) {
|
|
|
4642
4788
|
state.systemPromptTokens = void 0;
|
|
4643
4789
|
state.storageDir = void 0;
|
|
4644
4790
|
state.qualityGateRetryPending = false;
|
|
4791
|
+
state.noContextLimitWarned = false;
|
|
4645
4792
|
}
|
|
4646
4793
|
async function ensureSessionInitialized(client, state, sessionId, logger, messages, config, projectDir) {
|
|
4647
4794
|
if (state.sessionId === sessionId) {
|
|
@@ -6657,6 +6804,7 @@ function getModelInfo(messages) {
|
|
|
6657
6804
|
};
|
|
6658
6805
|
}
|
|
6659
6806
|
function resolveContextTokenLimit(config, state, providerId, modelId, threshold) {
|
|
6807
|
+
const effectiveLimit = resolveEffectiveContextLimit(state, config);
|
|
6660
6808
|
const parseLimitValue = (limit) => {
|
|
6661
6809
|
if (limit === void 0) {
|
|
6662
6810
|
return void 0;
|
|
@@ -6664,7 +6812,7 @@ function resolveContextTokenLimit(config, state, providerId, modelId, threshold)
|
|
|
6664
6812
|
if (typeof limit === "number") {
|
|
6665
6813
|
return limit;
|
|
6666
6814
|
}
|
|
6667
|
-
if (!limit.endsWith("%") ||
|
|
6815
|
+
if (!limit.endsWith("%") || effectiveLimit === void 0) {
|
|
6668
6816
|
return void 0;
|
|
6669
6817
|
}
|
|
6670
6818
|
const parsedPercent = parseFloat(limit.slice(0, -1));
|
|
@@ -6673,7 +6821,7 @@ function resolveContextTokenLimit(config, state, providerId, modelId, threshold)
|
|
|
6673
6821
|
}
|
|
6674
6822
|
const roundedPercent = Math.round(parsedPercent);
|
|
6675
6823
|
const clampedPercent = Math.max(0, Math.min(100, roundedPercent));
|
|
6676
|
-
return Math.round(clampedPercent / 100 *
|
|
6824
|
+
return Math.round(clampedPercent / 100 * effectiveLimit.limit);
|
|
6677
6825
|
};
|
|
6678
6826
|
if (threshold === "max") {
|
|
6679
6827
|
const nestedLimit = resolveCompressOverrides(config, providerId, modelId).maxContextLimit;
|
|
@@ -6724,11 +6872,12 @@ function isContextOverLimits(config, state, providerId, modelId, messages) {
|
|
|
6724
6872
|
if (!overMaxLimit) break;
|
|
6725
6873
|
}
|
|
6726
6874
|
}
|
|
6875
|
+
const effectiveLimit = resolveEffectiveContextLimit(state, config);
|
|
6727
6876
|
return {
|
|
6728
6877
|
overMaxLimit,
|
|
6729
6878
|
overMinLimit,
|
|
6730
6879
|
currentTokens,
|
|
6731
|
-
modelContextLimit:
|
|
6880
|
+
modelContextLimit: effectiveLimit?.limit
|
|
6732
6881
|
};
|
|
6733
6882
|
}
|
|
6734
6883
|
ensureBuiltinTriggerPolicyRegistered();
|
|
@@ -7888,8 +8037,11 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
|
|
|
7888
8037
|
state.nudges.iterationNudgeAnchors.clear();
|
|
7889
8038
|
state.nudges.lastNudgeShownTokens = void 0;
|
|
7890
8039
|
state.nudges.lastToolOutputNudgeTokens = void 0;
|
|
7891
|
-
|
|
7892
|
-
|
|
8040
|
+
const captureOnly = isCaptureOnlyCompress(lastCompressMsg);
|
|
8041
|
+
if (!captureOnly) {
|
|
8042
|
+
state.nudges.lastTier2NudgeTokens = currentTokens;
|
|
8043
|
+
state.nudges.lastTier3NudgeTokens = currentTokens;
|
|
8044
|
+
}
|
|
7893
8045
|
const currentTurnHasSuccessfulCompress = messages.slice(currentTurnStart).some((m) => m.info.role === "assistant" && messageHasCompress(m));
|
|
7894
8046
|
if (currentTurnHasSuccessfulCompress && wasNudgeTriggered && !state.nudges.compressBaselineSet) {
|
|
7895
8047
|
const baseline = state.nudges.lastPerMessageNudgeTokens;
|
|
@@ -8802,8 +8954,9 @@ function createDecompressTool(factoryCtx) {
|
|
|
8802
8954
|
async execute(args, toolCtx) {
|
|
8803
8955
|
const ctx = resolveToolContext(factoryCtx, toolCtx.sessionID);
|
|
8804
8956
|
const { rawMessages } = await prepareDecompressSession(ctx, toolCtx);
|
|
8805
|
-
const
|
|
8806
|
-
|
|
8957
|
+
const effectiveLimitBefore = resolveEffectiveContextLimit(ctx.state, ctx.config);
|
|
8958
|
+
const contextUsageBefore = effectiveLimitBefore ? Math.round(
|
|
8959
|
+
getCurrentTokenUsage(ctx.state, rawMessages) / effectiveLimitBefore.limit * 100
|
|
8807
8960
|
) : void 0;
|
|
8808
8961
|
const resolved = resolveTargets(args, ctx.state, rawMessages, ctx.logger);
|
|
8809
8962
|
if (!resolved.ok) {
|
|
@@ -8867,8 +9020,9 @@ function createDecompressTool(factoryCtx) {
|
|
|
8867
9020
|
0,
|
|
8868
9021
|
ctx.state.stats.totalPruneTokens - restoredTokens
|
|
8869
9022
|
);
|
|
8870
|
-
const
|
|
8871
|
-
|
|
9023
|
+
const effectiveLimitAfter = resolveEffectiveContextLimit(ctx.state, ctx.config);
|
|
9024
|
+
const contextUsageAfter = effectiveLimitAfter ? Math.round(
|
|
9025
|
+
getCurrentTokenUsage(ctx.state, rawMessages) / effectiveLimitAfter.limit * 100
|
|
8872
9026
|
) : void 0;
|
|
8873
9027
|
await finalizeDecompressSession(ctx);
|
|
8874
9028
|
const restoredContentPreview = buildRestoredContentPreview(
|
|
@@ -9525,7 +9679,7 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
|
9525
9679
|
import { join as join4 } from "path";
|
|
9526
9680
|
import { existsSync as existsSync4 } from "fs";
|
|
9527
9681
|
import { homedir as homedir3 } from "os";
|
|
9528
|
-
var LOG_VERSION = true ? "1.16.0-pr.360.
|
|
9682
|
+
var LOG_VERSION = true ? "1.16.0-pr.360.128" : "dev";
|
|
9529
9683
|
var LEVEL_RANK = {
|
|
9530
9684
|
debug: 10,
|
|
9531
9685
|
info: 20,
|
|
@@ -10349,6 +10503,8 @@ var MIN_OUTPUT_TOKENS = 1e3;
|
|
|
10349
10503
|
var KEEP_PREFIX_CHARS = 2e3;
|
|
10350
10504
|
var KEEP_SUFFIX_CHARS = 2e3;
|
|
10351
10505
|
var PROTECT_RECENT_MESSAGES = 3;
|
|
10506
|
+
var OUTPUT_RESERVE_TOKENS = 16384;
|
|
10507
|
+
var overheadErrorLogged = /* @__PURE__ */ new Set();
|
|
10352
10508
|
function parseGcThreshold(threshold, modelContextLimit) {
|
|
10353
10509
|
if (typeof threshold === "number") return threshold;
|
|
10354
10510
|
const str = threshold ?? "100%";
|
|
@@ -10357,10 +10513,26 @@ function parseGcThreshold(threshold, modelContextLimit) {
|
|
|
10357
10513
|
return modelContextLimit;
|
|
10358
10514
|
}
|
|
10359
10515
|
function truncateLargeToolOutputs(state, config, logger, messages) {
|
|
10360
|
-
|
|
10516
|
+
const effective = resolveEffectiveContextLimit(state, config);
|
|
10517
|
+
if (!effective) return;
|
|
10361
10518
|
const currentTokens = getCurrentTokenUsage(state, messages);
|
|
10362
10519
|
if (currentTokens === 0) return;
|
|
10363
|
-
const
|
|
10520
|
+
const configuredThreshold = parseGcThreshold(config.gc?.majorGcThresholdPercent, effective.limit);
|
|
10521
|
+
const overhead = (state.systemPromptTokens ?? 0) + OUTPUT_RESERVE_TOKENS;
|
|
10522
|
+
const threshold = Math.min(configuredThreshold, effective.limit - overhead);
|
|
10523
|
+
if (threshold <= 0) {
|
|
10524
|
+
const sessionKey = state.sessionId ?? "unknown";
|
|
10525
|
+
if (!overheadErrorLogged.has(sessionKey)) {
|
|
10526
|
+
overheadErrorLogged.add(sessionKey);
|
|
10527
|
+
logger.error("ACP: model context window too small to fit overhead", {
|
|
10528
|
+
session: state.sessionId,
|
|
10529
|
+
limit: effective.limit,
|
|
10530
|
+
contextLimitSource: effective.source,
|
|
10531
|
+
overhead
|
|
10532
|
+
});
|
|
10533
|
+
}
|
|
10534
|
+
return;
|
|
10535
|
+
}
|
|
10364
10536
|
if (currentTokens < threshold) return;
|
|
10365
10537
|
const protectedIndex = messages.length - PROTECT_RECENT_MESSAGES;
|
|
10366
10538
|
const candidates = [];
|
|
@@ -10405,9 +10577,158 @@ function truncateLargeToolOutputs(state, config, logger, messages) {
|
|
|
10405
10577
|
truncatedCount,
|
|
10406
10578
|
estimatedSavedTokens: Math.round(savedTokens),
|
|
10407
10579
|
currentTokens,
|
|
10408
|
-
threshold
|
|
10580
|
+
threshold,
|
|
10581
|
+
contextLimit: effective.limit,
|
|
10582
|
+
contextLimitSource: effective.source
|
|
10583
|
+
});
|
|
10584
|
+
}
|
|
10585
|
+
}
|
|
10586
|
+
|
|
10587
|
+
// lib/messages/enforce-budget.ts
|
|
10588
|
+
var DEFAULT_COMPLETION_RESERVE_TOKENS = 32768;
|
|
10589
|
+
var TRUNCATION_MARKER2 = "[truncated for context space";
|
|
10590
|
+
var KEEP_PREFIX_CHARS2 = 2e3;
|
|
10591
|
+
var KEEP_SUFFIX_CHARS2 = 2e3;
|
|
10592
|
+
var PROTECT_RECENT_MESSAGES2 = 3;
|
|
10593
|
+
var MIN_CLEAR_TOKENS = 200;
|
|
10594
|
+
function resolveContextWindow(state) {
|
|
10595
|
+
if (typeof state.modelContextLimit === "number" && state.modelContextLimit > 0) {
|
|
10596
|
+
return state.modelContextLimit;
|
|
10597
|
+
}
|
|
10598
|
+
return void 0;
|
|
10599
|
+
}
|
|
10600
|
+
function estimateWireTokens(state, messages) {
|
|
10601
|
+
const base = getCurrentTokenUsage(state, messages);
|
|
10602
|
+
if (base > 0) {
|
|
10603
|
+
let baseAssistant = -1;
|
|
10604
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
10605
|
+
if (messages[i].info.role !== "assistant") continue;
|
|
10606
|
+
const tokens = messages[i].info.tokens;
|
|
10607
|
+
if ((tokens?.input || 0) <= 0 && (tokens?.output || 0) <= 0) continue;
|
|
10608
|
+
baseAssistant = i;
|
|
10609
|
+
break;
|
|
10610
|
+
}
|
|
10611
|
+
if (baseAssistant >= 0) {
|
|
10612
|
+
let additions = 0;
|
|
10613
|
+
for (let i = baseAssistant + 1; i < messages.length; i++) {
|
|
10614
|
+
additions += countAllMessageTokens(messages[i]);
|
|
10615
|
+
}
|
|
10616
|
+
return base + additions;
|
|
10617
|
+
}
|
|
10618
|
+
}
|
|
10619
|
+
let total = 0;
|
|
10620
|
+
for (const m of messages) total += countAllMessageTokens(m);
|
|
10621
|
+
return total + (state.systemPromptTokens ?? 0);
|
|
10622
|
+
}
|
|
10623
|
+
function enforceContextBudget(state, config, logger, messages) {
|
|
10624
|
+
const window = resolveContextWindow(state);
|
|
10625
|
+
if (window === void 0) return void 0;
|
|
10626
|
+
const configuredReserve = config.compress?.completionReserveTokens;
|
|
10627
|
+
const reserve = typeof configuredReserve === "number" && Number.isFinite(configuredReserve) && configuredReserve >= 0 ? configuredReserve : DEFAULT_COMPLETION_RESERVE_TOKENS;
|
|
10628
|
+
const budget = window - reserve;
|
|
10629
|
+
if (budget <= 0) return void 0;
|
|
10630
|
+
const estimatedTokens = estimateWireTokens(state, messages);
|
|
10631
|
+
if (estimatedTokens <= budget) {
|
|
10632
|
+
return {
|
|
10633
|
+
applied: false,
|
|
10634
|
+
window,
|
|
10635
|
+
reserve,
|
|
10636
|
+
budget,
|
|
10637
|
+
estimatedTokens,
|
|
10638
|
+
finalEstimate: estimatedTokens,
|
|
10639
|
+
truncatedCount: 0,
|
|
10640
|
+
clearedCount: 0
|
|
10641
|
+
};
|
|
10642
|
+
}
|
|
10643
|
+
const protectedIndex = messages.length - PROTECT_RECENT_MESSAGES2;
|
|
10644
|
+
const protectedTools = new Set(config.compress?.protectedTools ?? []);
|
|
10645
|
+
const candidates = [];
|
|
10646
|
+
for (let mi = 0; mi < protectedIndex; mi++) {
|
|
10647
|
+
if (mi === 0 && messages[mi].info.role === "user") continue;
|
|
10648
|
+
const msg = messages[mi];
|
|
10649
|
+
const parts = Array.isArray(msg.parts) ? msg.parts : [];
|
|
10650
|
+
for (const part of parts) {
|
|
10651
|
+
if (part?.type !== "tool") continue;
|
|
10652
|
+
if (part.state?.status !== "completed") continue;
|
|
10653
|
+
if (part.tool === "compress") continue;
|
|
10654
|
+
if (protectedTools.has(part.tool)) continue;
|
|
10655
|
+
const content = extractCompletedToolOutput(part);
|
|
10656
|
+
if (content === void 0) continue;
|
|
10657
|
+
if (content === COMPACTED_TOOL_OUTPUT_PLACEHOLDER) continue;
|
|
10658
|
+
const tokens = countTokens2(content);
|
|
10659
|
+
if (tokens <= 0) continue;
|
|
10660
|
+
candidates.push({ part, content, tokens, index: mi });
|
|
10661
|
+
}
|
|
10662
|
+
}
|
|
10663
|
+
let saved = 0;
|
|
10664
|
+
let truncatedCount = 0;
|
|
10665
|
+
let clearedCount = 0;
|
|
10666
|
+
const truncatable = candidates.filter(
|
|
10667
|
+
(c) => !c.content.includes(TRUNCATION_MARKER2) && c.content.length > KEEP_PREFIX_CHARS2 + KEEP_SUFFIX_CHARS2
|
|
10668
|
+
).sort((a, b) => b.tokens - a.tokens);
|
|
10669
|
+
for (const c of truncatable) {
|
|
10670
|
+
if (estimatedTokens - saved <= budget) break;
|
|
10671
|
+
const prefix = c.content.slice(0, KEEP_PREFIX_CHARS2);
|
|
10672
|
+
const suffix = c.content.slice(-KEEP_SUFFIX_CHARS2);
|
|
10673
|
+
const truncated = prefix + `
|
|
10674
|
+
|
|
10675
|
+
...${TRUNCATION_MARKER2} \u2014 original ~${c.tokens} tokens]...
|
|
10676
|
+
|
|
10677
|
+
` + suffix;
|
|
10678
|
+
if (truncated.length >= c.content.length) continue;
|
|
10679
|
+
c.part.state.output = truncated;
|
|
10680
|
+
saved += c.tokens - countTokens2(truncated);
|
|
10681
|
+
truncatedCount++;
|
|
10682
|
+
}
|
|
10683
|
+
if (estimatedTokens - saved > budget) {
|
|
10684
|
+
const clearable = candidates.filter((c) => {
|
|
10685
|
+
const out = extractCompletedToolOutput(c.part);
|
|
10686
|
+
return out !== void 0 && out !== COMPACTED_TOOL_OUTPUT_PLACEHOLDER && countTokens2(out) > MIN_CLEAR_TOKENS;
|
|
10687
|
+
}).sort((a, b) => a.index - b.index);
|
|
10688
|
+
for (const c of clearable) {
|
|
10689
|
+
if (estimatedTokens - saved <= budget) break;
|
|
10690
|
+
const current = extractCompletedToolOutput(c.part);
|
|
10691
|
+
if (current === void 0 || current === COMPACTED_TOOL_OUTPUT_PLACEHOLDER) continue;
|
|
10692
|
+
c.part.state.output = COMPACTED_TOOL_OUTPUT_PLACEHOLDER;
|
|
10693
|
+
saved += countTokens2(current) - countTokens2(COMPACTED_TOOL_OUTPUT_PLACEHOLDER);
|
|
10694
|
+
clearedCount++;
|
|
10695
|
+
}
|
|
10696
|
+
}
|
|
10697
|
+
const finalEstimate = Math.max(0, estimatedTokens - saved);
|
|
10698
|
+
if (truncatedCount > 0 || clearedCount > 0) {
|
|
10699
|
+
logger.warn("Context budget guard: pruned tool outputs to fit the request", {
|
|
10700
|
+
session: state.sessionId,
|
|
10701
|
+
estimatedTokens: Math.round(estimatedTokens),
|
|
10702
|
+
budget,
|
|
10703
|
+
window,
|
|
10704
|
+
reserve,
|
|
10705
|
+
truncatedCount,
|
|
10706
|
+
clearedCount,
|
|
10707
|
+
estimatedSavedTokens: Math.round(saved),
|
|
10708
|
+
finalEstimate: Math.round(finalEstimate)
|
|
10409
10709
|
});
|
|
10410
10710
|
}
|
|
10711
|
+
if (finalEstimate > budget) {
|
|
10712
|
+
logger.warn(
|
|
10713
|
+
"Context budget guard: still over budget after pruning all compressible tool outputs; the request may be rejected by the model",
|
|
10714
|
+
{
|
|
10715
|
+
session: state.sessionId,
|
|
10716
|
+
finalEstimate: Math.round(finalEstimate),
|
|
10717
|
+
budget,
|
|
10718
|
+
window
|
|
10719
|
+
}
|
|
10720
|
+
);
|
|
10721
|
+
}
|
|
10722
|
+
return {
|
|
10723
|
+
applied: truncatedCount > 0 || clearedCount > 0,
|
|
10724
|
+
window,
|
|
10725
|
+
reserve,
|
|
10726
|
+
budget,
|
|
10727
|
+
estimatedTokens,
|
|
10728
|
+
finalEstimate,
|
|
10729
|
+
truncatedCount,
|
|
10730
|
+
clearedCount
|
|
10731
|
+
};
|
|
10411
10732
|
}
|
|
10412
10733
|
|
|
10413
10734
|
// lib/commands/context.ts
|
|
@@ -11366,11 +11687,12 @@ function runBatchCleanup(state, config, logger, messages) {
|
|
|
11366
11687
|
mergedCount: 0,
|
|
11367
11688
|
savedTokens: 0
|
|
11368
11689
|
};
|
|
11369
|
-
|
|
11690
|
+
const effective = resolveEffectiveContextLimit(state, config);
|
|
11691
|
+
if (!effective) {
|
|
11370
11692
|
return noop;
|
|
11371
11693
|
}
|
|
11372
11694
|
const currentTokens = getCurrentTokenUsage(state, messages);
|
|
11373
|
-
if (currentTokens <
|
|
11695
|
+
if (currentTokens < effective.limit) {
|
|
11374
11696
|
return noop;
|
|
11375
11697
|
}
|
|
11376
11698
|
const maxMergedLength = config.gc.maxOldGenSummaryLength;
|
|
@@ -11387,7 +11709,8 @@ function runBatchCleanup(state, config, logger, messages) {
|
|
|
11387
11709
|
mergedCount: result.mergedCount,
|
|
11388
11710
|
savedTokens: result.savedTokens,
|
|
11389
11711
|
currentTokens,
|
|
11390
|
-
contextLimit:
|
|
11712
|
+
contextLimit: effective.limit,
|
|
11713
|
+
contextLimitSource: effective.source
|
|
11391
11714
|
});
|
|
11392
11715
|
return {
|
|
11393
11716
|
tier: 3,
|
|
@@ -11421,11 +11744,6 @@ function createSystemPromptHandler(registry4, logger, config, prompts) {
|
|
|
11421
11744
|
input.model?.limit?.context
|
|
11422
11745
|
);
|
|
11423
11746
|
const state = input.sessionID ? registry4.get(input.sessionID) : void 0;
|
|
11424
|
-
if (state && input.model?.limit?.context) {
|
|
11425
|
-
state.modelContextLimit = input.model.limit.context;
|
|
11426
|
-
state.modelProviderID = input.model?.providerID;
|
|
11427
|
-
state.modelID = input.model?.id;
|
|
11428
|
-
}
|
|
11429
11747
|
if (!state || state.isSubAgent && !config.allowSubAgents) {
|
|
11430
11748
|
return;
|
|
11431
11749
|
}
|
|
@@ -11434,6 +11752,23 @@ function createSystemPromptHandler(registry4, logger, config, prompts) {
|
|
|
11434
11752
|
logger.info("Skipping DCP system prompt injection for internal agent");
|
|
11435
11753
|
return;
|
|
11436
11754
|
}
|
|
11755
|
+
if (input.model?.limit?.context) {
|
|
11756
|
+
const limit = input.model.limit.context;
|
|
11757
|
+
const providerID = input.model?.providerID;
|
|
11758
|
+
const modelID = input.model?.id;
|
|
11759
|
+
const changed = state.modelContextLimit !== limit || providerID !== void 0 && state.modelProviderID !== providerID || modelID !== void 0 && state.modelID !== modelID;
|
|
11760
|
+
state.modelContextLimit = limit;
|
|
11761
|
+
if (providerID !== void 0) {
|
|
11762
|
+
state.modelProviderID = providerID;
|
|
11763
|
+
}
|
|
11764
|
+
if (modelID !== void 0) {
|
|
11765
|
+
state.modelID = modelID;
|
|
11766
|
+
}
|
|
11767
|
+
if (changed) {
|
|
11768
|
+
saveSessionState(state, logger).catch(() => {
|
|
11769
|
+
});
|
|
11770
|
+
}
|
|
11771
|
+
}
|
|
11437
11772
|
const effectivePermission = compressPermission(state, config);
|
|
11438
11773
|
if (effectivePermission === "deny") {
|
|
11439
11774
|
return;
|
|
@@ -11478,10 +11813,17 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
11478
11813
|
config
|
|
11479
11814
|
);
|
|
11480
11815
|
const requestModel = lastUserMessage.info.model;
|
|
11481
|
-
|
|
11816
|
+
let requestModelLimit = registry4.resolveModelLimit(
|
|
11482
11817
|
requestModel?.providerID,
|
|
11483
11818
|
requestModel?.modelID
|
|
11484
11819
|
);
|
|
11820
|
+
if (requestModelLimit === void 0 && requestModel?.providerID && requestModel?.modelID) {
|
|
11821
|
+
requestModelLimit = await registry4.hydrateAndResolve(
|
|
11822
|
+
client,
|
|
11823
|
+
requestModel.providerID,
|
|
11824
|
+
requestModel.modelID
|
|
11825
|
+
);
|
|
11826
|
+
}
|
|
11485
11827
|
const prevModelID = state.modelID;
|
|
11486
11828
|
if (requestModelLimit !== void 0) {
|
|
11487
11829
|
state.modelContextLimit = requestModelLimit;
|
|
@@ -11511,6 +11853,16 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
11511
11853
|
});
|
|
11512
11854
|
}
|
|
11513
11855
|
await updatePerTurnState(state, logger, messages);
|
|
11856
|
+
if (state.modelContextLimit === void 0 && !state.noContextLimitWarned && requestModel?.providerID && requestModel?.modelID && registry4.resolveModelLimit(requestModel.providerID, requestModel.modelID) === void 0) {
|
|
11857
|
+
state.noContextLimitWarned = true;
|
|
11858
|
+
logger.warn(
|
|
11859
|
+
'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.',
|
|
11860
|
+
{
|
|
11861
|
+
session: state.sessionId,
|
|
11862
|
+
model: `${requestModel.providerID}/${requestModel.modelID}`
|
|
11863
|
+
}
|
|
11864
|
+
);
|
|
11865
|
+
}
|
|
11514
11866
|
}
|
|
11515
11867
|
syncCompressPermissionState(state, config, hostPermissions, output.messages);
|
|
11516
11868
|
if (state.isSubAgent && !config.allowSubAgents) {
|
|
@@ -11536,10 +11888,11 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
11536
11888
|
}
|
|
11537
11889
|
}
|
|
11538
11890
|
ensureBuiltinFiltersRegistered();
|
|
11891
|
+
const effectiveLimit = resolveEffectiveContextLimit(state, config);
|
|
11539
11892
|
applyMessageFilters(output.messages, config.messageFilters, logger, {
|
|
11540
11893
|
sessionId: state.sessionId ?? "",
|
|
11541
11894
|
isSubAgent: state.isSubAgent,
|
|
11542
|
-
modelContextLimit:
|
|
11895
|
+
modelContextLimit: effectiveLimit?.limit
|
|
11543
11896
|
});
|
|
11544
11897
|
cacheSystemPromptTokens(state, output.messages);
|
|
11545
11898
|
assignMessageRefs(state, output.messages);
|
|
@@ -11559,6 +11912,7 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
11559
11912
|
const prePruneTokens = getCurrentTokenUsage(state, output.messages);
|
|
11560
11913
|
prune(state, logger, config, output.messages);
|
|
11561
11914
|
truncateLargeToolOutputs(state, config, logger, output.messages);
|
|
11915
|
+
enforceContextBudget(state, config, logger, output.messages);
|
|
11562
11916
|
hideConsumedCompressCalls(state, output.messages);
|
|
11563
11917
|
assignMessageRefs(state, output.messages);
|
|
11564
11918
|
const compressionPriorities = buildPriorityMap(config, state, output.messages);
|
|
@@ -11590,14 +11944,31 @@ ${text}`);
|
|
|
11590
11944
|
stripStaleMetadata(output.messages);
|
|
11591
11945
|
dropEmptyMessages(output.messages);
|
|
11592
11946
|
const postTokens = getCurrentTokenUsage(state, output.messages);
|
|
11947
|
+
if (postTokens !== void 0 && effectiveLimit) {
|
|
11948
|
+
const budget = effectiveLimit.limit - (state.systemPromptTokens ?? 0) - OUTPUT_RESERVE_TOKENS;
|
|
11949
|
+
if (postTokens > budget) {
|
|
11950
|
+
logger.error(
|
|
11951
|
+
"ACP hard guard: context exceeds model budget after in-flight reduction",
|
|
11952
|
+
{
|
|
11953
|
+
session: state.sessionId,
|
|
11954
|
+
postTokens,
|
|
11955
|
+
budget,
|
|
11956
|
+
contextLimit: effectiveLimit.limit,
|
|
11957
|
+
contextLimitSource: effectiveLimit.source,
|
|
11958
|
+
hint: "request will likely be rejected; run /compact or start a new session"
|
|
11959
|
+
}
|
|
11960
|
+
);
|
|
11961
|
+
}
|
|
11962
|
+
}
|
|
11593
11963
|
logger.info("Chat transform complete", {
|
|
11594
11964
|
session: state.sessionId,
|
|
11595
11965
|
model: state.modelID,
|
|
11596
11966
|
messages: output.messages.length,
|
|
11597
11967
|
prePruneTokens,
|
|
11598
11968
|
postTokens,
|
|
11599
|
-
contextLimit:
|
|
11600
|
-
|
|
11969
|
+
contextLimit: effectiveLimit?.limit,
|
|
11970
|
+
contextLimitSource: effectiveLimit?.source,
|
|
11971
|
+
usagePct: postTokens !== void 0 && effectiveLimit ? `${(postTokens / effectiveLimit.limit * 100).toFixed(1)}%` : void 0,
|
|
11601
11972
|
nudged: state.nudges.shouldInjectThisTurn
|
|
11602
11973
|
});
|
|
11603
11974
|
if (state.sessionId) {
|
|
@@ -11629,12 +12000,7 @@ function createCommandExecuteHandler(client, registry4, logger, config, workingD
|
|
|
11629
12000
|
path: { id: input.sessionID }
|
|
11630
12001
|
});
|
|
11631
12002
|
const messages = filterMessages(messagesResponse.data || messagesResponse);
|
|
11632
|
-
const state = await registry4.getOrCreate(
|
|
11633
|
-
client,
|
|
11634
|
-
input.sessionID,
|
|
11635
|
-
messages,
|
|
11636
|
-
config
|
|
11637
|
-
);
|
|
12003
|
+
const state = await registry4.getOrCreate(client, input.sessionID, messages, config);
|
|
11638
12004
|
syncCompressPermissionState(state, config, hostPermissions, messages);
|
|
11639
12005
|
const commandCtx = {
|
|
11640
12006
|
client,
|
|
@@ -11648,7 +12014,7 @@ function createCommandExecuteHandler(client, registry4, logger, config, workingD
|
|
|
11648
12014
|
const sub = input.arguments?.trim().toLowerCase();
|
|
11649
12015
|
if (sub === "stats" || sub === "status" || sub === "") {
|
|
11650
12016
|
await handleStatsCommand(commandCtx);
|
|
11651
|
-
|
|
12017
|
+
return;
|
|
11652
12018
|
}
|
|
11653
12019
|
if (sub === "export" || sub.startsWith("export ")) {
|
|
11654
12020
|
const exportArgs = input.arguments?.trim().slice("export".length).trim() || "";
|
|
@@ -11656,17 +12022,10 @@ function createCommandExecuteHandler(client, registry4, logger, config, workingD
|
|
|
11656
12022
|
throw new Error("__DCP_CONTEXT_HANDLED__");
|
|
11657
12023
|
}
|
|
11658
12024
|
if (sub === "help") {
|
|
11659
|
-
await sendIgnoredMessage(
|
|
11660
|
-
client,
|
|
11661
|
-
input.sessionID,
|
|
11662
|
-
buildHelpText(),
|
|
11663
|
-
{},
|
|
11664
|
-
logger
|
|
11665
|
-
);
|
|
12025
|
+
await sendIgnoredMessage(client, input.sessionID, buildHelpText(), {}, logger);
|
|
11666
12026
|
throw new Error("__DCP_CONTEXT_HANDLED__");
|
|
11667
12027
|
}
|
|
11668
12028
|
await handleContextCommand(commandCtx);
|
|
11669
|
-
throw new Error("__DCP_CONTEXT_HANDLED__");
|
|
11670
12029
|
}
|
|
11671
12030
|
};
|
|
11672
12031
|
}
|
|
@@ -11737,9 +12096,7 @@ function createEventHandler(registry4, logger) {
|
|
|
11737
12096
|
return;
|
|
11738
12097
|
}
|
|
11739
12098
|
if (typeof part.callID === "string" && typeof part.messageID === "string") {
|
|
11740
|
-
timing.startsByCallId.delete(
|
|
11741
|
-
buildCompressionTimingKey(part.messageID, part.callID)
|
|
11742
|
-
);
|
|
12099
|
+
timing.startsByCallId.delete(buildCompressionTimingKey(part.messageID, part.callID));
|
|
11743
12100
|
}
|
|
11744
12101
|
};
|
|
11745
12102
|
}
|
|
@@ -12016,7 +12373,7 @@ var server = (async (ctx) => {
|
|
|
12016
12373
|
}
|
|
12017
12374
|
const logger = new Logger(config.debug, config.debug ? "debug" : config.logLevel);
|
|
12018
12375
|
logger.info("ACP plugin initialized", {
|
|
12019
|
-
version: true ? "1.16.0-pr.360.
|
|
12376
|
+
version: true ? "1.16.0-pr.360.128" : "dev",
|
|
12020
12377
|
workspace: ctx.directory,
|
|
12021
12378
|
logLevel: logger.level,
|
|
12022
12379
|
debug: config.debug,
|