opencode-acp 1.18.1 → 1.18.2
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 +439 -43
- package/dist/index.js.map +1 -1
- package/dist/lib/compress/range.d.ts +4 -0
- package/dist/lib/compress/range.d.ts.map +1 -1
- package/dist/lib/compress/smart-plan.d.ts +28 -0
- package/dist/lib/compress/smart-plan.d.ts.map +1 -0
- package/dist/lib/compress/status.d.ts.map +1 -1
- package/dist/lib/config-validation.d.ts.map +1 -1
- package/dist/lib/config.d.ts +2 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/hooks.d.ts +1 -1
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/message-ids.d.ts +7 -0
- package/dist/lib/message-ids.d.ts.map +1 -1
- package/dist/lib/messages/index.d.ts +1 -1
- package/dist/lib/messages/index.d.ts.map +1 -1
- 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/utils.d.ts +4 -0
- package/dist/lib/messages/utils.d.ts.map +1 -1
- package/dist/lib/protected-patterns.d.ts.map +1 -1
- package/dist/lib/state/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -903,6 +903,7 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
903
903
|
"compress.protectUserMessages",
|
|
904
904
|
"compress.maxSummaryLengthHard",
|
|
905
905
|
"compress.minCompressRange",
|
|
906
|
+
"compress.smartPlanRequired",
|
|
906
907
|
"compress.minNudgeGrowthRatio",
|
|
907
908
|
"compress.minNudgeGrowthFloor",
|
|
908
909
|
"compress.emergencyThresholdPercent",
|
|
@@ -1151,6 +1152,13 @@ function validateConfigTypes(config) {
|
|
|
1151
1152
|
actual: `${compress.minCompressRange}`
|
|
1152
1153
|
});
|
|
1153
1154
|
}
|
|
1155
|
+
if (compress.smartPlanRequired !== void 0 && typeof compress.smartPlanRequired !== "boolean") {
|
|
1156
|
+
errors.push({
|
|
1157
|
+
key: "compress.smartPlanRequired",
|
|
1158
|
+
expected: "boolean",
|
|
1159
|
+
actual: typeof compress.smartPlanRequired
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1154
1162
|
if (compress.minNudgeGrowthRatio !== void 0 && typeof compress.minNudgeGrowthRatio !== "number") {
|
|
1155
1163
|
errors.push({
|
|
1156
1164
|
key: "compress.minNudgeGrowthRatio",
|
|
@@ -1396,6 +1404,7 @@ function validateConfigTypes(config) {
|
|
|
1396
1404
|
protectedTools: "stringArray",
|
|
1397
1405
|
maxSummaryLengthHard: "positiveNumber",
|
|
1398
1406
|
minCompressRange: "nonNegativeNumber",
|
|
1407
|
+
smartPlanRequired: "boolean",
|
|
1399
1408
|
maxVisibleSegments: "positiveNumber",
|
|
1400
1409
|
keepEmbedMaxChars: "nonNegativeNumber",
|
|
1401
1410
|
preserveRecentMessages: "nonNegativeNumber",
|
|
@@ -1773,6 +1782,7 @@ var defaultConfig = {
|
|
|
1773
1782
|
protectUserMessages: false,
|
|
1774
1783
|
maxSummaryLengthHard: 2e4,
|
|
1775
1784
|
minCompressRange: 5e3,
|
|
1785
|
+
smartPlanRequired: false,
|
|
1776
1786
|
minNudgeGrowthRatio: 0.45,
|
|
1777
1787
|
minNudgeGrowthFloor: 5e3,
|
|
1778
1788
|
nudgeGrowthTokens: 5e4,
|
|
@@ -1947,6 +1957,7 @@ function mergeCompress(base, override) {
|
|
|
1947
1957
|
protectUserMessages: override.protectUserMessages ?? base.protectUserMessages,
|
|
1948
1958
|
maxSummaryLengthHard: override.maxSummaryLengthHard ?? base.maxSummaryLengthHard,
|
|
1949
1959
|
minCompressRange: override.minCompressRange ?? base.minCompressRange,
|
|
1960
|
+
smartPlanRequired: override.smartPlanRequired ?? base.smartPlanRequired,
|
|
1950
1961
|
minNudgeGrowthRatio: override.minNudgeGrowthRatio ?? base.minNudgeGrowthRatio,
|
|
1951
1962
|
minNudgeGrowthFloor: override.minNudgeGrowthFloor ?? base.minNudgeGrowthFloor,
|
|
1952
1963
|
emergencyThresholdPercent: override.emergencyThresholdPercent ?? base.emergencyThresholdPercent,
|
|
@@ -2756,11 +2767,6 @@ function resetOnCompaction(state) {
|
|
|
2756
2767
|
compressBaselineSet: false,
|
|
2757
2768
|
lastProcessedCompressMessageId: void 0
|
|
2758
2769
|
};
|
|
2759
|
-
state.messageIds = {
|
|
2760
|
-
byRawId: /* @__PURE__ */ new Map(),
|
|
2761
|
-
byRef: /* @__PURE__ */ new Map(),
|
|
2762
|
-
nextRef: 1
|
|
2763
|
-
};
|
|
2764
2770
|
}
|
|
2765
2771
|
function resolveEffectiveContextLimit(state, config) {
|
|
2766
2772
|
if (typeof state.modelContextLimit === "number" && state.modelContextLimit > 0) {
|
|
@@ -3124,6 +3130,52 @@ function assignMessageRefs(state, messages) {
|
|
|
3124
3130
|
}
|
|
3125
3131
|
return assigned;
|
|
3126
3132
|
}
|
|
3133
|
+
function repairNonMonotonicMessageRefs(state, messages) {
|
|
3134
|
+
const eligible = messages.filter((message) => {
|
|
3135
|
+
if (isIgnoredUserMessage(message)) return false;
|
|
3136
|
+
const id = message.info.id;
|
|
3137
|
+
return typeof id === "string" && id.length > 0 && !id.startsWith("msg_dcp_summary_") && !id.startsWith("msg_dcp_text_");
|
|
3138
|
+
});
|
|
3139
|
+
let previous = 0;
|
|
3140
|
+
let corrupted = false;
|
|
3141
|
+
for (const message of eligible) {
|
|
3142
|
+
const ref = state.messageIds.byRawId.get(message.info.id);
|
|
3143
|
+
const parsed = ref ? parseMessageRef(ref) : null;
|
|
3144
|
+
if (parsed === null) continue;
|
|
3145
|
+
if (parsed <= previous) {
|
|
3146
|
+
corrupted = true;
|
|
3147
|
+
break;
|
|
3148
|
+
}
|
|
3149
|
+
previous = parsed;
|
|
3150
|
+
}
|
|
3151
|
+
if (!corrupted) return false;
|
|
3152
|
+
const oldRawIds = [...state.messageIds.byRawId.keys()];
|
|
3153
|
+
state.messageIds.byRawId.clear();
|
|
3154
|
+
state.messageIds.byRef.clear();
|
|
3155
|
+
state.messageIds.nextRef = 1;
|
|
3156
|
+
for (const message of eligible) {
|
|
3157
|
+
const rawId = message.info.id;
|
|
3158
|
+
const ref = allocateNextMessageRef(state);
|
|
3159
|
+
state.messageIds.byRawId.set(rawId, ref);
|
|
3160
|
+
state.messageIds.byRef.set(ref, rawId);
|
|
3161
|
+
}
|
|
3162
|
+
for (const rawId of oldRawIds) {
|
|
3163
|
+
if (state.messageIds.byRawId.has(rawId)) continue;
|
|
3164
|
+
const ref = allocateNextMessageRef(state);
|
|
3165
|
+
state.messageIds.byRawId.set(rawId, ref);
|
|
3166
|
+
state.messageIds.byRef.set(ref, rawId);
|
|
3167
|
+
}
|
|
3168
|
+
for (const block of state.prune.messages.blocksById.values()) {
|
|
3169
|
+
const ids = [.../* @__PURE__ */ new Set([...block.effectiveMessageIds, ...block.directMessageIds])].filter((id) => state.messageIds.byRawId.has(id)).sort(
|
|
3170
|
+
(left, right) => (parseMessageRef(state.messageIds.byRawId.get(left)) ?? 0) - (parseMessageRef(state.messageIds.byRawId.get(right)) ?? 0)
|
|
3171
|
+
);
|
|
3172
|
+
if (ids.length === 0) continue;
|
|
3173
|
+
block.startId = state.messageIds.byRawId.get(ids[0]);
|
|
3174
|
+
block.endId = state.messageIds.byRawId.get(ids[ids.length - 1]);
|
|
3175
|
+
}
|
|
3176
|
+
state.prune.messages.structureVersion = (state.prune.messages.structureVersion ?? 0) + 1;
|
|
3177
|
+
return true;
|
|
3178
|
+
}
|
|
3127
3179
|
function allocateNextMessageRef(state) {
|
|
3128
3180
|
let candidate = Number.isInteger(state.messageIds.nextRef) ? Math.max(MESSAGE_REF_MIN_INDEX, state.messageIds.nextRef) : MESSAGE_REF_MIN_INDEX;
|
|
3129
3181
|
while (candidate <= MESSAGE_REF_MAX_INDEX) {
|
|
@@ -3949,7 +4001,7 @@ function createSearchContextTool(factoryCtx) {
|
|
|
3949
4001
|
|
|
3950
4002
|
// lib/protected-patterns.ts
|
|
3951
4003
|
function normalizePath(input) {
|
|
3952
|
-
return input.replaceAll("
|
|
4004
|
+
return input.replaceAll("\\", "/");
|
|
3953
4005
|
}
|
|
3954
4006
|
function escapeRegExpChar(ch) {
|
|
3955
4007
|
return /[\\.^$+{}()|\[\]]/.test(ch) ? `\\${ch}` : ch;
|
|
@@ -4661,21 +4713,21 @@ function rebuildRangeInvocation(state, input, searchContext, invocation, protect
|
|
|
4661
4713
|
const runId = allocateRunId(state);
|
|
4662
4714
|
let created = 0;
|
|
4663
4715
|
for (const plan of plans) {
|
|
4664
|
-
const
|
|
4716
|
+
const filteredSelection2 = filterProtectedToolMessages(
|
|
4665
4717
|
plan.selection,
|
|
4666
4718
|
searchContext,
|
|
4667
4719
|
protectedTools,
|
|
4668
4720
|
protectedFilePatterns
|
|
4669
4721
|
);
|
|
4670
|
-
if (
|
|
4722
|
+
if (filteredSelection2.messageIds.length === 0) {
|
|
4671
4723
|
continue;
|
|
4672
4724
|
}
|
|
4673
4725
|
const boundaryConsumed = extractBoundaryConsumedBlocks(
|
|
4674
|
-
|
|
4675
|
-
|
|
4726
|
+
filteredSelection2.startReference,
|
|
4727
|
+
filteredSelection2.endReference
|
|
4676
4728
|
);
|
|
4677
4729
|
const consumedBlockIds = dedupeBlockIds([
|
|
4678
|
-
...
|
|
4730
|
+
...filteredSelection2.requiredBlockIds,
|
|
4679
4731
|
...boundaryConsumed
|
|
4680
4732
|
]);
|
|
4681
4733
|
const blockId = allocateBlockId(state);
|
|
@@ -4694,7 +4746,7 @@ function rebuildRangeInvocation(state, input, searchContext, invocation, protect
|
|
|
4694
4746
|
compressCallId: invocation.callId,
|
|
4695
4747
|
summaryTokens
|
|
4696
4748
|
},
|
|
4697
|
-
|
|
4749
|
+
filteredSelection2,
|
|
4698
4750
|
plan.anchorMessageId,
|
|
4699
4751
|
blockId,
|
|
4700
4752
|
storedSummary,
|
|
@@ -6822,6 +6874,33 @@ function buildToolIdList(state, messages) {
|
|
|
6822
6874
|
var stripHallucinationsFromString = (text) => {
|
|
6823
6875
|
return text.replace(DCP_PAIRED_TAG_REGEX, "").replace(DCP_UNPAIRED_TAG_REGEX, "");
|
|
6824
6876
|
};
|
|
6877
|
+
var LEAKED_TRAILING_REF_REGEX = /(?:^|\n)[ \t]*(?:m(\d{4,5})|b([1-9]\d*))\b/g;
|
|
6878
|
+
var stripLeakedTrailingRefs = (text, bounds) => {
|
|
6879
|
+
if (typeof text !== "string" || text.length === 0) {
|
|
6880
|
+
return text;
|
|
6881
|
+
}
|
|
6882
|
+
const rawMessageBound = bounds.nextMessageRef;
|
|
6883
|
+
const rawBlockBound = bounds.nextBlockRef;
|
|
6884
|
+
const messageBound = typeof rawMessageBound === "number" && Number.isInteger(rawMessageBound) ? rawMessageBound : null;
|
|
6885
|
+
const blockBound = typeof rawBlockBound === "number" && Number.isInteger(rawBlockBound) ? rawBlockBound : null;
|
|
6886
|
+
if (messageBound === null && blockBound === null) {
|
|
6887
|
+
return text;
|
|
6888
|
+
}
|
|
6889
|
+
const pattern = new RegExp(LEAKED_TRAILING_REF_REGEX.source, "g");
|
|
6890
|
+
let match;
|
|
6891
|
+
while ((match = pattern.exec(text)) !== null) {
|
|
6892
|
+
if (match[1] !== void 0) {
|
|
6893
|
+
if (messageBound !== null && Number(match[1]) >= messageBound) {
|
|
6894
|
+
return text.slice(0, match.index).replace(/[ \t\r\n]*$/, "");
|
|
6895
|
+
}
|
|
6896
|
+
} else if (match[2] !== void 0) {
|
|
6897
|
+
if (blockBound !== null && Number(match[2]) >= blockBound) {
|
|
6898
|
+
return text.slice(0, match.index).replace(/[ \t\r\n]*$/, "");
|
|
6899
|
+
}
|
|
6900
|
+
}
|
|
6901
|
+
}
|
|
6902
|
+
return text;
|
|
6903
|
+
};
|
|
6825
6904
|
var stripHallucinations = (messages) => {
|
|
6826
6905
|
for (const message of messages) {
|
|
6827
6906
|
for (const part of message.parts) {
|
|
@@ -6988,10 +7067,7 @@ function resolveContextTokenLimit(config, state, providerId, modelId, threshold)
|
|
|
6988
7067
|
return parseLimitValue(globalLimit);
|
|
6989
7068
|
}
|
|
6990
7069
|
function isContextOverLimits(config, state, providerId, modelId, messages) {
|
|
6991
|
-
const summaryTokenExtension = config.compress.summaryBuffer ? getActiveSummaryTokenUsage(
|
|
6992
|
-
state,
|
|
6993
|
-
new Set(messages.map((m) => m.info.id))
|
|
6994
|
-
) : 0;
|
|
7070
|
+
const summaryTokenExtension = config.compress.summaryBuffer ? getActiveSummaryTokenUsage(state, new Set(messages.map((m) => m.info.id))) : 0;
|
|
6995
7071
|
const resolvedMaxContextLimit = resolveContextTokenLimit(
|
|
6996
7072
|
config,
|
|
6997
7073
|
state,
|
|
@@ -7375,7 +7451,15 @@ function buildCompressibleRanges(messages, state, protectedTools = [], protected
|
|
|
7375
7451
|
lastUserRefIdx.length = 0;
|
|
7376
7452
|
lastUserRefIdx.push(msgInfo.length);
|
|
7377
7453
|
}
|
|
7378
|
-
msgInfo.push({
|
|
7454
|
+
msgInfo.push({
|
|
7455
|
+
ref,
|
|
7456
|
+
refNum: rn,
|
|
7457
|
+
tokens,
|
|
7458
|
+
effectiveTokens: 0,
|
|
7459
|
+
meaningful: hasMeaningfulPart,
|
|
7460
|
+
isTool,
|
|
7461
|
+
isUser: msg.info.role === "user"
|
|
7462
|
+
});
|
|
7379
7463
|
}
|
|
7380
7464
|
const lastUserIdx = lastUserRefIdx.length > 0 ? lastUserRefIdx[0] : -1;
|
|
7381
7465
|
for (let i = 0; i < msgInfo.length; i++) {
|
|
@@ -7394,7 +7478,7 @@ function buildCompressibleRanges(messages, state, protectedTools = [], protected
|
|
|
7394
7478
|
prevRefNum = info.refNum;
|
|
7395
7479
|
continue;
|
|
7396
7480
|
}
|
|
7397
|
-
const hasGap = info.refNum
|
|
7481
|
+
const hasGap = info.refNum !== prevRefNum + 1;
|
|
7398
7482
|
if (cur && (info.isUser && cur.count >= 3 || hasGap)) {
|
|
7399
7483
|
groups.push(cur);
|
|
7400
7484
|
cur = null;
|
|
@@ -7474,9 +7558,7 @@ function filterRecommendedRanges(compressible, _protectedRanges, options) {
|
|
|
7474
7558
|
const effective = r.effectiveTokens ?? r.tokens;
|
|
7475
7559
|
return effective > 0 && effective >= floor;
|
|
7476
7560
|
});
|
|
7477
|
-
const result = kept.map(
|
|
7478
|
-
(r, i) => i === kept.length - 1 ? { ...r, dangerous: true } : r
|
|
7479
|
-
);
|
|
7561
|
+
const result = kept.map((r, i) => i === kept.length - 1 ? { ...r, dangerous: true } : r);
|
|
7480
7562
|
log?.("filterRecommendedRanges: effective-token floor applied", {
|
|
7481
7563
|
inputRanges: compressible.length,
|
|
7482
7564
|
outputRanges: result.length,
|
|
@@ -7610,12 +7692,160 @@ function computeProtectedRefs(messages, state, compress) {
|
|
|
7610
7692
|
}
|
|
7611
7693
|
function excludeProtectedRanges(ranges, protectedRefs) {
|
|
7612
7694
|
if (protectedRefs.size === 0) return ranges;
|
|
7613
|
-
return ranges.filter(
|
|
7614
|
-
|
|
7695
|
+
return ranges.filter((r) => !protectedRefs.has(r.startRef) && !protectedRefs.has(r.endRef));
|
|
7696
|
+
}
|
|
7697
|
+
|
|
7698
|
+
// lib/compress/smart-plan.ts
|
|
7699
|
+
var SMART_PLAN_TTL_MS = 10 * 60 * 1e3;
|
|
7700
|
+
var armedPlans = /* @__PURE__ */ new Map();
|
|
7701
|
+
var visibleMessageIdsBySession = /* @__PURE__ */ new Map();
|
|
7702
|
+
function refNumber(ref) {
|
|
7703
|
+
const value = Number.parseInt(ref.slice(1), 10);
|
|
7704
|
+
return Number.isFinite(value) ? value : -1;
|
|
7705
|
+
}
|
|
7706
|
+
function mergeAdjacentSafeRanges(ranges) {
|
|
7707
|
+
const merged = [];
|
|
7708
|
+
for (const range of ranges.filter((candidate) => !candidate.dangerous)) {
|
|
7709
|
+
const previous = merged.at(-1);
|
|
7710
|
+
if (previous && refNumber(range.startRef) === refNumber(previous.endRef) + 1) {
|
|
7711
|
+
const previousEffective = previous.effectiveTokens ?? previous.tokens;
|
|
7712
|
+
previous.endRef = range.endRef;
|
|
7713
|
+
previous.count += range.count;
|
|
7714
|
+
previous.tokens += range.tokens;
|
|
7715
|
+
previous.effectiveTokens = previousEffective + (range.effectiveTokens ?? range.tokens);
|
|
7716
|
+
continue;
|
|
7717
|
+
}
|
|
7718
|
+
merged.push({ ...range });
|
|
7719
|
+
}
|
|
7720
|
+
return merged;
|
|
7721
|
+
}
|
|
7722
|
+
function recordVisibleMessages(sessionID, messages) {
|
|
7723
|
+
visibleMessageIdsBySession.set(sessionID, new Set(messages.map((message) => message.info.id)));
|
|
7724
|
+
}
|
|
7725
|
+
function getVisibleMessageIds(sessionID) {
|
|
7726
|
+
return visibleMessageIdsBySession.get(sessionID);
|
|
7727
|
+
}
|
|
7728
|
+
function clearSmartPlan(sessionID) {
|
|
7729
|
+
armedPlans.delete(sessionID);
|
|
7730
|
+
}
|
|
7731
|
+
function clearSmartPlanSession(sessionID) {
|
|
7732
|
+
armedPlans.delete(sessionID);
|
|
7733
|
+
visibleMessageIdsBySession.delete(sessionID);
|
|
7734
|
+
}
|
|
7735
|
+
function consumeSmartPlan(sessionID) {
|
|
7736
|
+
armedPlans.delete(sessionID);
|
|
7737
|
+
}
|
|
7738
|
+
function filteredSelection(startId, endId, searchContext, ctx) {
|
|
7739
|
+
const [resolved] = resolveRanges(
|
|
7740
|
+
{
|
|
7741
|
+
topic: "ACP smart plan",
|
|
7742
|
+
content: [{ startId, endId, summary: "Pending model-authored summary." }]
|
|
7743
|
+
},
|
|
7744
|
+
searchContext,
|
|
7745
|
+
ctx.state,
|
|
7746
|
+
ctx.logger
|
|
7615
7747
|
);
|
|
7748
|
+
if (!resolved) return void 0;
|
|
7749
|
+
let selection = filterProtectedToolMessages(
|
|
7750
|
+
resolved.selection,
|
|
7751
|
+
searchContext,
|
|
7752
|
+
ctx.config.compress.protectedTools,
|
|
7753
|
+
ctx.config.protectedFilePatterns
|
|
7754
|
+
);
|
|
7755
|
+
selection = filterLastUserMessage(selection, searchContext, ctx.state, ctx.config.compress);
|
|
7756
|
+
selection = filterProtectedRecentMessages(
|
|
7757
|
+
selection,
|
|
7758
|
+
searchContext,
|
|
7759
|
+
ctx.state,
|
|
7760
|
+
ctx.config.compress
|
|
7761
|
+
);
|
|
7762
|
+
return selection;
|
|
7763
|
+
}
|
|
7764
|
+
function armBestSmartPlan(sessionID, ranges, searchContext, ctx, visibleMessageIds, now = Date.now(), targetChars = ctx.config.compress.minCompressRange) {
|
|
7765
|
+
const candidates = [];
|
|
7766
|
+
for (const range of mergeAdjacentSafeRanges(ranges)) {
|
|
7767
|
+
const selection = filteredSelection(range.startRef, range.endRef, searchContext, ctx);
|
|
7768
|
+
if (!selection || selection.messageIds.length === 0) continue;
|
|
7769
|
+
if (visibleMessageIds && !selection.messageIds.every((id) => visibleMessageIds.has(id)))
|
|
7770
|
+
continue;
|
|
7771
|
+
let exactChars = 0;
|
|
7772
|
+
for (const messageId of selection.messageIds) {
|
|
7773
|
+
const message = searchContext.rawMessagesById.get(messageId);
|
|
7774
|
+
if (message) exactChars += countMessageCharacters(message);
|
|
7775
|
+
}
|
|
7776
|
+
if (ctx.config.compress.minCompressRange > 0 && exactChars < ctx.config.compress.minCompressRange) {
|
|
7777
|
+
continue;
|
|
7778
|
+
}
|
|
7779
|
+
candidates.push({
|
|
7780
|
+
sessionID,
|
|
7781
|
+
createdAt: now,
|
|
7782
|
+
structureVersion: ctx.state.prune.messages.structureVersion ?? 0,
|
|
7783
|
+
startId: range.startRef,
|
|
7784
|
+
endId: range.endRef,
|
|
7785
|
+
exactChars,
|
|
7786
|
+
messageIds: [...selection.messageIds],
|
|
7787
|
+
rawStart: selection.startReference.rawIndex
|
|
7788
|
+
});
|
|
7789
|
+
}
|
|
7790
|
+
const sufficient = candidates.filter((candidate) => candidate.exactChars >= targetChars);
|
|
7791
|
+
const pool = sufficient.length > 0 ? sufficient : candidates;
|
|
7792
|
+
pool.sort(
|
|
7793
|
+
(a, b) => sufficient.length > 0 ? a.rawStart - b.rawStart || b.exactChars - a.exactChars : b.exactChars - a.exactChars || a.rawStart - b.rawStart
|
|
7794
|
+
);
|
|
7795
|
+
const best = pool[0];
|
|
7796
|
+
if (!best) {
|
|
7797
|
+
clearSmartPlan(sessionID);
|
|
7798
|
+
return void 0;
|
|
7799
|
+
}
|
|
7800
|
+
const { rawStart: _rawStart, ...plan } = best;
|
|
7801
|
+
armedPlans.set(sessionID, plan);
|
|
7802
|
+
return plan;
|
|
7803
|
+
}
|
|
7804
|
+
function validateSmartPlan(sessionID, startId, endId, messageIds, exactChars, structureVersion, now = Date.now()) {
|
|
7805
|
+
const plan = armedPlans.get(sessionID);
|
|
7806
|
+
const preflight = 'Use the exact SMART PLAN range from the latest ACP nudge, or call acp_status({scope:"uncompressed"}) to refresh it.';
|
|
7807
|
+
if (!plan) throw new Error(`No smart compression plan is armed. ${preflight}`);
|
|
7808
|
+
if (now - plan.createdAt > SMART_PLAN_TTL_MS) {
|
|
7809
|
+
clearSmartPlan(sessionID);
|
|
7810
|
+
throw new Error(`Smart compression plan expired. ${preflight}`);
|
|
7811
|
+
}
|
|
7812
|
+
if (plan.structureVersion !== structureVersion) {
|
|
7813
|
+
clearSmartPlan(sessionID);
|
|
7814
|
+
throw new Error(
|
|
7815
|
+
`Smart compression plan is stale because compression state changed. ${preflight}`
|
|
7816
|
+
);
|
|
7817
|
+
}
|
|
7818
|
+
if (plan.startId !== startId || plan.endId !== endId) {
|
|
7819
|
+
throw new Error(
|
|
7820
|
+
`Range does not match the armed smart plan (${plan.startId}-${plan.endId}). Do not sort, merge, or batch ranges.`
|
|
7821
|
+
);
|
|
7822
|
+
}
|
|
7823
|
+
const idsMatch = plan.messageIds.length === messageIds.length && plan.messageIds.every((id, i) => id === messageIds[i]);
|
|
7824
|
+
const charsDiff = Math.abs(plan.exactChars - exactChars);
|
|
7825
|
+
const charsMatch = charsDiff === 0 || charsDiff <= 300 || charsDiff / Math.max(plan.exactChars, 1) < 0.02;
|
|
7826
|
+
if (!idsMatch || !charsMatch) {
|
|
7827
|
+
clearSmartPlan(sessionID);
|
|
7828
|
+
throw new Error(
|
|
7829
|
+
`Smart compression plan no longer resolves to the armed messages. ${preflight}`
|
|
7830
|
+
);
|
|
7831
|
+
}
|
|
7832
|
+
const visibleMessageIds = getVisibleMessageIds(sessionID);
|
|
7833
|
+
if (visibleMessageIds && !plan.messageIds.every((id) => visibleMessageIds.has(id))) {
|
|
7834
|
+
clearSmartPlan(sessionID);
|
|
7835
|
+
throw new Error(
|
|
7836
|
+
`Smart compression plan moved outside the model's visible context. ${preflight}`
|
|
7837
|
+
);
|
|
7838
|
+
}
|
|
7839
|
+
return plan;
|
|
7616
7840
|
}
|
|
7617
7841
|
|
|
7618
7842
|
// lib/compress/range.ts
|
|
7843
|
+
function requiresSmartPlan(smartPlanRequired, content) {
|
|
7844
|
+
const isBlockCompression = content.every(
|
|
7845
|
+
(entry) => entry.startId.startsWith("b") && entry.endId.startsWith("b")
|
|
7846
|
+
);
|
|
7847
|
+
return smartPlanRequired && !isBlockCompression;
|
|
7848
|
+
}
|
|
7619
7849
|
function buildSchema(maxSummaryLengthHard) {
|
|
7620
7850
|
return {
|
|
7621
7851
|
topic: tool2.schema.string().optional().describe(
|
|
@@ -7678,13 +7908,32 @@ function createCompressRangeTool(factoryCtx) {
|
|
|
7678
7908
|
...ctx0,
|
|
7679
7909
|
config: applyCompressOverrides(ctx0.config, providerId, modelId)
|
|
7680
7910
|
};
|
|
7681
|
-
const
|
|
7911
|
+
const needsSmartPlan = requiresSmartPlan(
|
|
7912
|
+
ctx.config.compress.smartPlanRequired === true,
|
|
7913
|
+
input.content
|
|
7914
|
+
);
|
|
7915
|
+
if (needsSmartPlan && input.content.length !== 1) {
|
|
7916
|
+
throw new Error(
|
|
7917
|
+
'Raw-message compression accepts exactly one canonical SMART PLAN range per call. Use the latest ACP nudge, or call acp_status({scope:"uncompressed"}) to refresh it.'
|
|
7918
|
+
);
|
|
7919
|
+
}
|
|
7920
|
+
const { plans: filteredPlans, totalChars } = prepareExecutableRangePlans(
|
|
7682
7921
|
input,
|
|
7683
7922
|
searchContext,
|
|
7684
7923
|
ctx.state,
|
|
7685
7924
|
ctx.config,
|
|
7686
7925
|
ctx.logger
|
|
7687
7926
|
);
|
|
7927
|
+
if (needsSmartPlan) {
|
|
7928
|
+
validateSmartPlan(
|
|
7929
|
+
toolCtx.sessionID,
|
|
7930
|
+
filteredPlans[0].entry.startId,
|
|
7931
|
+
filteredPlans[0].entry.endId,
|
|
7932
|
+
filteredPlans[0].selection.messageIds,
|
|
7933
|
+
totalChars,
|
|
7934
|
+
ctx.state.prune.messages.structureVersion ?? 0
|
|
7935
|
+
);
|
|
7936
|
+
}
|
|
7688
7937
|
const notifications = [];
|
|
7689
7938
|
let preparedPlans = [];
|
|
7690
7939
|
let totalCompressedMessages = 0;
|
|
@@ -7862,6 +8111,7 @@ function createCompressRangeTool(factoryCtx) {
|
|
|
7862
8111
|
});
|
|
7863
8112
|
}
|
|
7864
8113
|
await finalizeSession(ctx, toolCtx, rawMessages, notifications, input.topic);
|
|
8114
|
+
if (needsSmartPlan) consumeSmartPlan(toolCtx.sessionID);
|
|
7865
8115
|
} catch (error) {
|
|
7866
8116
|
restoreCompressionState(ctx.state, snapshot);
|
|
7867
8117
|
ctx.state.qualityGateRetryPending = qualityGateRetryPendingBefore;
|
|
@@ -8958,9 +9208,40 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
|
|
|
8958
9208
|
const nothingToCompress = candidatesEnabled && candidateMessages !== void 0 ? noExecutableCandidates : allProtected || allInProtectedZone || allBelowMin;
|
|
8959
9209
|
const emergencyNoTargets = emergencyOverride && nothingToCompress;
|
|
8960
9210
|
const noticeCadenceMet = state.nudges.lastNudgeShownTokens === void 0 || growthSinceBaseline !== void 0 && growthSinceBaseline >= growthFloor;
|
|
8961
|
-
|
|
8962
|
-
|
|
9211
|
+
let shouldInjectNudge = nudgeAllowed && !nothingToCompress;
|
|
9212
|
+
let shouldInjectNotice = emergencyNoTargets && noticeCadenceMet;
|
|
8963
9213
|
let shouldInject = shouldInjectNudge || shouldInjectNotice;
|
|
9214
|
+
let armedSmartPlan;
|
|
9215
|
+
if (shouldInjectNudge && config.compress.smartPlanRequired === true && state.sessionId) {
|
|
9216
|
+
const planningRanges = candidatesEnabled ? candidatePlan.candidates.map((candidate) => ({
|
|
9217
|
+
startRef: candidate.startRef,
|
|
9218
|
+
endRef: candidate.endRef,
|
|
9219
|
+
count: candidate.messageCount,
|
|
9220
|
+
tokens: candidate.estimatedTokens,
|
|
9221
|
+
effectiveTokens: candidate.estimatedTokens,
|
|
9222
|
+
toolPct: candidate.toolPct,
|
|
9223
|
+
textPct: candidate.textPct
|
|
9224
|
+
})) : recommendedRanges;
|
|
9225
|
+
const maxLimit = resolveContextTokenLimit(config, state, providerId, modelId, "max");
|
|
9226
|
+
const reclaimTargetChars = Math.max(
|
|
9227
|
+
config.compress.minCompressRange,
|
|
9228
|
+
maxLimit === void 0 || currentTokens === void 0 ? 0 : Math.max(0, currentTokens - maxLimit + 8192) * 4
|
|
9229
|
+
);
|
|
9230
|
+
armedSmartPlan = armBestSmartPlan(
|
|
9231
|
+
state.sessionId,
|
|
9232
|
+
planningRanges,
|
|
9233
|
+
buildSearchContext(state, messages),
|
|
9234
|
+
{ state, config, logger },
|
|
9235
|
+
new Set(messages.map((message) => message.info.id)),
|
|
9236
|
+
Date.now(),
|
|
9237
|
+
reclaimTargetChars
|
|
9238
|
+
);
|
|
9239
|
+
if (!armedSmartPlan) {
|
|
9240
|
+
shouldInjectNudge = false;
|
|
9241
|
+
shouldInjectNotice = emergencyOverride && noticeCadenceMet;
|
|
9242
|
+
shouldInject = shouldInjectNotice;
|
|
9243
|
+
}
|
|
9244
|
+
}
|
|
8964
9245
|
if (shouldInjectNudge) {
|
|
8965
9246
|
const effectivePrompts = candidatesEnabled ? {
|
|
8966
9247
|
...prompts,
|
|
@@ -9168,13 +9449,22 @@ Breakdown: ${sysPart}${fmt(composition.toolTokens)} tool (${pct2(composition.too
|
|
|
9168
9449
|
${HOW_TO_COMPRESS_RULES}
|
|
9169
9450
|
|
|
9170
9451
|
${candidateText}`;
|
|
9171
|
-
|
|
9452
|
+
if (armedSmartPlan) {
|
|
9453
|
+
breakdown += `
|
|
9454
|
+
|
|
9455
|
+
SMART PLAN ARMED: ${armedSmartPlan.startId}-${armedSmartPlan.endId} | ${armedSmartPlan.exactChars} effective chars`;
|
|
9456
|
+
breakdown += `
|
|
9457
|
+
Next: compress exactly this one range now. acp_status is optional; use it only to inspect or refresh a stale plan.`;
|
|
9458
|
+
} else {
|
|
9459
|
+
breakdown += candidatesEnabled ? "\n\u{1F4A1} You may batch selected independent candidates in one call (pass multiple content entries: `content: [{...}, {...}]`); omit any candidate whose content is still needed." : "\n\u{1F4A1} Compress all ranges in one call (pass multiple content entries: `content: [{...}, {...}]`).";
|
|
9460
|
+
}
|
|
9172
9461
|
}
|
|
9173
|
-
breakdown += `
|
|
9462
|
+
breakdown += armedSmartPlan ? `
|
|
9463
|
+
Use \`acp_status({scope:"uncompressed"})\` only to inspect or refresh a stale plan, or \`acp_status\` for compressed block details.` : `
|
|
9174
9464
|
Use \`acp_status({scope:"uncompressed"})\` to re-fetch compressible ranges after compressing, or \`acp_status\` for compressed block details.`;
|
|
9175
9465
|
appendToLastTextPart(suffixMessage, breakdown);
|
|
9176
9466
|
}
|
|
9177
|
-
if (effectiveTipsVariant === "maxLimit" &&
|
|
9467
|
+
if (effectiveTipsVariant === "maxLimit" && shouldInjectNudge) {
|
|
9178
9468
|
tipsText = candidatesEnabled ? "\n\n\u26A0\uFE0F Context limit reached \u2014 compress now. Select at least one listed candidate whose content is no longer needed and call the `compress` tool in your next reply. Do not merely recommend compression. Candidates are advisory about selection: preserve current intent and active work, and never compress content still needed for the current task.\n\n" + HOW_TO_COMPRESS_RULES + '\n\n{ "topic": "...", "content": [{ "startId": "<ID>", "endId": "<ID>", "summary": "..." }] }\n\nOnly use IDs from visible messages above. If several selected candidates are stale, older work may be preferable; never override semantic judgment or compress content still needed for the current task.' : "\n\n\u26A0\uFE0F Context limit reached \u2014 compress now. Prioritize consumed tool outputs.\n\n" + HOW_TO_COMPRESS_RULES + '\n\n{ "topic": "...", "content": [{ "startId": "<ID>", "endId": "<ID>", "summary": "..." }] }\n\nOnly use IDs from visible messages above. Compress older work first.';
|
|
9179
9469
|
} else if (shouldInjectNotice) {
|
|
9180
9470
|
const emergencyPct = currentTokens !== void 0 && modelContextLimit !== void 0 && modelContextLimit > 0 ? Math.round(currentTokens / modelContextLimit * 100) : void 0;
|
|
@@ -10430,13 +10720,85 @@ function createAcpStatusTool(factoryCtx) {
|
|
|
10430
10720
|
rawMessages = [];
|
|
10431
10721
|
}
|
|
10432
10722
|
hideConsumedCompressCalls(ctx.state, rawMessages);
|
|
10433
|
-
|
|
10434
|
-
|
|
10435
|
-
|
|
10436
|
-
|
|
10437
|
-
|
|
10438
|
-
|
|
10439
|
-
|
|
10723
|
+
assignMessageRefs(ctx.state, rawMessages);
|
|
10724
|
+
if (repairNonMonotonicMessageRefs(ctx.state, rawMessages)) {
|
|
10725
|
+
ctx.logger.warn("Repaired non-monotonic message aliases after native compaction", {
|
|
10726
|
+
session: toolCtx.sessionID,
|
|
10727
|
+
messages: rawMessages.length
|
|
10728
|
+
});
|
|
10729
|
+
await saveSessionState(ctx.state, ctx.logger);
|
|
10730
|
+
}
|
|
10731
|
+
const { providerId, modelId } = getModelInfo(rawMessages);
|
|
10732
|
+
const effectiveCtx = {
|
|
10733
|
+
...ctx,
|
|
10734
|
+
config: applyCompressOverrides(ctx.config, providerId, modelId)
|
|
10735
|
+
};
|
|
10736
|
+
let smartPlanSuffix = "";
|
|
10737
|
+
if (effectiveCtx.config.compress?.smartPlanRequired === true && scope === "uncompressed" && view !== "messages") {
|
|
10738
|
+
const lastModelView = getVisibleMessageIds(toolCtx.sessionID);
|
|
10739
|
+
const visibleRaw = rawMessages.filter((message) => {
|
|
10740
|
+
const entry = effectiveCtx.state.prune.messages.byMessageId.get(message.info.id);
|
|
10741
|
+
return (!entry || entry.activeBlockIds.length === 0) && (!lastModelView || lastModelView.has(message.info.id));
|
|
10742
|
+
});
|
|
10743
|
+
const protectedRefs = computeProtectedRefs(
|
|
10744
|
+
visibleRaw,
|
|
10745
|
+
effectiveCtx.state,
|
|
10746
|
+
effectiveCtx.config.compress
|
|
10747
|
+
);
|
|
10748
|
+
const contextRanges = buildCompressibleRanges(
|
|
10749
|
+
visibleRaw,
|
|
10750
|
+
effectiveCtx.state,
|
|
10751
|
+
effectiveCtx.config.compress.protectedTools,
|
|
10752
|
+
effectiveCtx.config.protectedFilePatterns,
|
|
10753
|
+
protectedRefs
|
|
10754
|
+
);
|
|
10755
|
+
const ranges = filterRecommendedRanges(
|
|
10756
|
+
contextRanges.compressible,
|
|
10757
|
+
contextRanges.protected,
|
|
10758
|
+
{
|
|
10759
|
+
logger: effectiveCtx.logger,
|
|
10760
|
+
minEffectiveTokens: resolveEffectiveFloor(effectiveCtx.config)
|
|
10761
|
+
}
|
|
10762
|
+
);
|
|
10763
|
+
const composition = estimateContextComposition(
|
|
10764
|
+
visibleRaw,
|
|
10765
|
+
effectiveCtx.state,
|
|
10766
|
+
effectiveCtx.config.compress.protectedTools,
|
|
10767
|
+
effectiveCtx.config.protectedFilePatterns
|
|
10768
|
+
);
|
|
10769
|
+
const targetLimit = resolveContextTokenLimit(
|
|
10770
|
+
effectiveCtx.config,
|
|
10771
|
+
effectiveCtx.state,
|
|
10772
|
+
providerId,
|
|
10773
|
+
modelId,
|
|
10774
|
+
"max"
|
|
10775
|
+
);
|
|
10776
|
+
const targetChars = Math.max(
|
|
10777
|
+
effectiveCtx.config.compress.minCompressRange,
|
|
10778
|
+
targetLimit === void 0 ? 0 : Math.max(0, composition.total - targetLimit + 8192) * 4
|
|
10779
|
+
);
|
|
10780
|
+
const plan = lastModelView ? armBestSmartPlan(
|
|
10781
|
+
toolCtx.sessionID,
|
|
10782
|
+
ranges,
|
|
10783
|
+
buildSearchContext(effectiveCtx.state, rawMessages),
|
|
10784
|
+
effectiveCtx,
|
|
10785
|
+
lastModelView,
|
|
10786
|
+
Date.now(),
|
|
10787
|
+
targetChars
|
|
10788
|
+
) : void 0;
|
|
10789
|
+
smartPlanSuffix = plan ? `
|
|
10790
|
+
|
|
10791
|
+
SMART PLAN ARMED: ${plan.startId}-${plan.endId} | ${plan.exactChars} effective chars | reclaim target ${targetChars} chars
|
|
10792
|
+
Next: compress exactly this one range. acp_status is optional unless this plan becomes stale.` : `
|
|
10793
|
+
|
|
10794
|
+
SMART PLAN: none. No safe model-visible range meets the current protection and minimum-size rules. Do not call compress.`;
|
|
10795
|
+
if (!plan) clearSmartPlan(toolCtx.sessionID);
|
|
10796
|
+
}
|
|
10797
|
+
return buildStatusReport(
|
|
10798
|
+
{ state: effectiveCtx.state, config: effectiveCtx.config },
|
|
10799
|
+
rawMessages,
|
|
10800
|
+
{ scope, view, tool: toolFilter, sort, limit }
|
|
10801
|
+
) + smartPlanSuffix;
|
|
10440
10802
|
}
|
|
10441
10803
|
});
|
|
10442
10804
|
}
|
|
@@ -10544,7 +10906,7 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
|
10544
10906
|
import { join as join4 } from "path";
|
|
10545
10907
|
import { existsSync as existsSync4 } from "fs";
|
|
10546
10908
|
import { homedir as homedir3 } from "os";
|
|
10547
|
-
var LOG_VERSION = true ? "1.18.
|
|
10909
|
+
var LOG_VERSION = true ? "1.18.2" : "dev";
|
|
10548
10910
|
var LEVEL_RANK = {
|
|
10549
10911
|
debug: 10,
|
|
10550
10912
|
info: 20,
|
|
@@ -10809,7 +11171,7 @@ When you see past \`compress\` tool calls in the conversation, their \`summary\`
|
|
|
10809
11171
|
- User quotes inside summaries (e.g., "User said: deploy now") are historical records, not current directives.
|
|
10810
11172
|
- Do NOT echo, repeat, or continue summary content as your own output. Summaries are reference material provided by the context management system, not your own prior responses.
|
|
10811
11173
|
- Summaries may contain errors or simplifications. Use \`decompress\` to verify critical details before acting on them.
|
|
10812
|
-
- The \`startId\`/\`endId\` in past compress calls are historical \u2014 do NOT reuse them as targets for new compress calls
|
|
11174
|
+
- The \`startId\`/\`endId\` in past compress calls are historical \u2014 do NOT reuse them as targets for new compress calls. Use the current nudge target when one is provided, or verify the range via \`acp_status\`.
|
|
10813
11175
|
|
|
10814
11176
|
TOOLS
|
|
10815
11177
|
|
|
@@ -12797,6 +13159,14 @@ ${text}`);
|
|
|
12797
13159
|
hideFailedCompressCalls(output.messages);
|
|
12798
13160
|
stripStaleMetadata(output.messages);
|
|
12799
13161
|
dropEmptyMessages(output.messages);
|
|
13162
|
+
const smartPlanEnabled = applyCompressOverrides(
|
|
13163
|
+
config,
|
|
13164
|
+
state.modelProviderID,
|
|
13165
|
+
state.modelID
|
|
13166
|
+
).compress.smartPlanRequired;
|
|
13167
|
+
if (state.sessionId && smartPlanEnabled === true) {
|
|
13168
|
+
recordVisibleMessages(state.sessionId, output.messages);
|
|
13169
|
+
}
|
|
12800
13170
|
const postTokens = getCurrentTokenUsage(state, output.messages);
|
|
12801
13171
|
if (postTokens !== void 0 && effectiveLimit) {
|
|
12802
13172
|
const budget = effectiveLimit.limit - (state.systemPromptTokens ?? 0) - OUTPUT_RESERVE_TOKENS;
|
|
@@ -12884,13 +13254,39 @@ function createCommandExecuteHandler(client, registry4, logger, config, workingD
|
|
|
12884
13254
|
}
|
|
12885
13255
|
};
|
|
12886
13256
|
}
|
|
12887
|
-
function createTextCompleteHandler() {
|
|
12888
|
-
return async (
|
|
12889
|
-
output.text
|
|
13257
|
+
function createTextCompleteHandler(registry4, logger) {
|
|
13258
|
+
return async (input, output) => {
|
|
13259
|
+
if (typeof output.text !== "string" || output.text.length === 0) {
|
|
13260
|
+
return;
|
|
13261
|
+
}
|
|
13262
|
+
let text = stripHallucinationsFromString(output.text);
|
|
13263
|
+
const state = typeof input.sessionID === "string" ? registry4.get(input.sessionID) : void 0;
|
|
13264
|
+
if (state) {
|
|
13265
|
+
const nextBlockId = state.prune?.messages?.nextBlockId;
|
|
13266
|
+
const stripped = stripLeakedTrailingRefs(text, {
|
|
13267
|
+
nextMessageRef: Number.isInteger(state.messageIds.nextRef) ? state.messageIds.nextRef : null,
|
|
13268
|
+
nextBlockRef: Number.isInteger(nextBlockId) ? nextBlockId : null
|
|
13269
|
+
});
|
|
13270
|
+
if (stripped !== text) {
|
|
13271
|
+
logger.warn("Stripped leaked trailing ACP ref from assistant output", {
|
|
13272
|
+
sessionID: input.sessionID,
|
|
13273
|
+
messageID: input.messageID,
|
|
13274
|
+
removedChars: text.length - stripped.length,
|
|
13275
|
+
removedTailPreview: text.slice(stripped.length, stripped.length + 200)
|
|
13276
|
+
});
|
|
13277
|
+
text = stripped;
|
|
13278
|
+
}
|
|
13279
|
+
}
|
|
13280
|
+
output.text = text;
|
|
12890
13281
|
};
|
|
12891
13282
|
}
|
|
12892
13283
|
function createEventHandler(registry4, logger) {
|
|
12893
13284
|
return async (input) => {
|
|
13285
|
+
if (input.event?.type === "session.idle" || input.event?.type === "session.deleted") {
|
|
13286
|
+
const sessionID = input.event?.properties?.sessionID ?? input.event?.properties?.info?.id;
|
|
13287
|
+
if (typeof sessionID === "string") clearSmartPlanSession(sessionID);
|
|
13288
|
+
return;
|
|
13289
|
+
}
|
|
12894
13290
|
const eventTime = typeof input.event?.time === "number" && Number.isFinite(input.event.time) ? input.event.time : typeof input.event?.properties?.time === "number" && Number.isFinite(input.event.properties.time) ? input.event.properties.time : void 0;
|
|
12895
13291
|
if (input.event.type !== "message.part.updated") {
|
|
12896
13292
|
return;
|
|
@@ -13228,7 +13624,7 @@ var server = (async (ctx) => {
|
|
|
13228
13624
|
}
|
|
13229
13625
|
const logger = new Logger(config.debug, config.debug ? "debug" : config.logLevel);
|
|
13230
13626
|
logger.info("ACP plugin initialized", {
|
|
13231
|
-
version: true ? "1.18.
|
|
13627
|
+
version: true ? "1.18.2" : "dev",
|
|
13232
13628
|
workspace: ctx.directory,
|
|
13233
13629
|
logLevel: logger.level,
|
|
13234
13630
|
debug: config.debug,
|
|
@@ -13293,7 +13689,7 @@ var server = (async (ctx) => {
|
|
|
13293
13689
|
hostPermissions
|
|
13294
13690
|
)
|
|
13295
13691
|
),
|
|
13296
|
-
"experimental.text.complete": guard(createTextCompleteHandler()),
|
|
13692
|
+
"experimental.text.complete": guard(createTextCompleteHandler(registry4, logger)),
|
|
13297
13693
|
"command.execute.before": guard(
|
|
13298
13694
|
createCommandExecuteHandler(
|
|
13299
13695
|
ctx.client,
|