opencode-acp 1.18.1-pr.408.164 → 1.18.1-pr.409.166
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 +473 -503
- package/dist/index.js.map +1 -1
- package/dist/lib/compress/decompress.d.ts.map +1 -1
- package/dist/lib/compress/range.d.ts.map +1 -1
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/state/rebuild.d.ts.map +1 -1
- package/dist/lib/state/state.d.ts +0 -17
- package/dist/lib/state/state.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4555,8 +4555,29 @@ function fingerprintMessage(message) {
|
|
|
4555
4555
|
});
|
|
4556
4556
|
return createHash("sha256").update(JSON.stringify({ role: message.info.role, parts })).digest("hex");
|
|
4557
4557
|
}
|
|
4558
|
+
function normalizeParentMessageIds(messageIds) {
|
|
4559
|
+
if (!messageIds) return void 0;
|
|
4560
|
+
const migrate = (ref) => {
|
|
4561
|
+
const parsed = parseMessageRef(ref);
|
|
4562
|
+
return parsed !== null ? formatMessageRef(parsed) : ref;
|
|
4563
|
+
};
|
|
4564
|
+
const byRawId = {};
|
|
4565
|
+
const byRef = {};
|
|
4566
|
+
for (const [rawId, ref] of Object.entries(messageIds.byRawId || {})) {
|
|
4567
|
+
const normalized = migrate(ref);
|
|
4568
|
+
byRawId[rawId] = normalized;
|
|
4569
|
+
byRef[normalized] = rawId;
|
|
4570
|
+
}
|
|
4571
|
+
for (const [ref, rawId] of Object.entries(messageIds.byRef || {})) {
|
|
4572
|
+
const normalized = migrate(ref);
|
|
4573
|
+
if (byRef[normalized] === void 0) {
|
|
4574
|
+
byRef[normalized] = rawId;
|
|
4575
|
+
}
|
|
4576
|
+
}
|
|
4577
|
+
return { byRef, byRawId, nextRef: messageIds.nextRef || 1 };
|
|
4578
|
+
}
|
|
4558
4579
|
function mapForkIds(state, parent, parentMessages, forkMessages) {
|
|
4559
|
-
const parentRefs = parent.messageIds?.byRef;
|
|
4580
|
+
const parentRefs = normalizeParentMessageIds(parent.messageIds)?.byRef;
|
|
4560
4581
|
if (!parentRefs) return null;
|
|
4561
4582
|
const parentById = new Map(parentMessages.map((message) => [message.info.id, message]));
|
|
4562
4583
|
const forkById = new Map(forkMessages.map((message) => [message.info.id, message]));
|
|
@@ -4830,30 +4851,6 @@ async function updatePerTurnState(state, logger, messages) {
|
|
|
4830
4851
|
state.currentTurn = countTurns(state, messages);
|
|
4831
4852
|
}
|
|
4832
4853
|
var REGISTRY_SOFT_CAP = 32;
|
|
4833
|
-
function createSessionGuard() {
|
|
4834
|
-
const locks = /* @__PURE__ */ new Map();
|
|
4835
|
-
return async (sessionId, fn) => {
|
|
4836
|
-
const previous = locks.get(sessionId) ?? Promise.resolve();
|
|
4837
|
-
let release;
|
|
4838
|
-
const released = new Promise((resolve2) => {
|
|
4839
|
-
release = resolve2;
|
|
4840
|
-
});
|
|
4841
|
-
const chain = previous.then(() => released);
|
|
4842
|
-
locks.set(sessionId, chain);
|
|
4843
|
-
try {
|
|
4844
|
-
await previous;
|
|
4845
|
-
} catch {
|
|
4846
|
-
}
|
|
4847
|
-
try {
|
|
4848
|
-
return await fn();
|
|
4849
|
-
} finally {
|
|
4850
|
-
release();
|
|
4851
|
-
if (locks.get(sessionId) === chain) {
|
|
4852
|
-
locks.delete(sessionId);
|
|
4853
|
-
}
|
|
4854
|
-
}
|
|
4855
|
-
};
|
|
4856
|
-
}
|
|
4857
4854
|
var SessionStateRegistry = class {
|
|
4858
4855
|
constructor(logger, projectDir) {
|
|
4859
4856
|
this.logger = logger;
|
|
@@ -4913,15 +4910,9 @@ var SessionStateRegistry = class {
|
|
|
4913
4910
|
get size() {
|
|
4914
4911
|
return this.states.size;
|
|
4915
4912
|
}
|
|
4916
|
-
// [Issue #404] Per-session FIFO mutex serializing same-session mutations
|
|
4917
|
-
// (message transforms, compress/decompress tools, event-hook saves,
|
|
4918
|
-
// system-hook limit writes). Shared factory so test stubs compose the
|
|
4919
|
-
// exact same implementation instead of drifting.
|
|
4920
|
-
withSessionGuard = createSessionGuard();
|
|
4921
4913
|
// Idempotent: ensureSessionInitialized returns immediately once
|
|
4922
|
-
// state.sessionId === sessionId
|
|
4923
|
-
//
|
|
4924
|
-
// re-reset or observe partially initialized state.
|
|
4914
|
+
// state.sessionId === sessionId (assigned synchronously before any await),
|
|
4915
|
+
// so repeat calls for the same session never re-reset.
|
|
4925
4916
|
async getOrCreate(client, sessionId, messages, config) {
|
|
4926
4917
|
let state = this.states.get(sessionId);
|
|
4927
4918
|
if (!state) {
|
|
@@ -5049,25 +5040,10 @@ function resetSessionState(state) {
|
|
|
5049
5040
|
state.qualityGateRetryPending = false;
|
|
5050
5041
|
state.noContextLimitWarned = false;
|
|
5051
5042
|
}
|
|
5052
|
-
var inflightInits = /* @__PURE__ */ new WeakMap();
|
|
5053
5043
|
async function ensureSessionInitialized(client, state, sessionId, logger, messages, config, projectDir) {
|
|
5054
|
-
const inflight = inflightInits.get(state);
|
|
5055
|
-
if (inflight) {
|
|
5056
|
-
await inflight;
|
|
5057
|
-
return;
|
|
5058
|
-
}
|
|
5059
5044
|
if (state.sessionId === sessionId) {
|
|
5060
5045
|
return;
|
|
5061
5046
|
}
|
|
5062
|
-
const run = runSessionInitialization(client, state, sessionId, logger, messages, config, projectDir);
|
|
5063
|
-
inflightInits.set(state, run);
|
|
5064
|
-
try {
|
|
5065
|
-
await run;
|
|
5066
|
-
} finally {
|
|
5067
|
-
inflightInits.delete(state);
|
|
5068
|
-
}
|
|
5069
|
-
}
|
|
5070
|
-
async function runSessionInitialization(client, state, sessionId, logger, messages, config, projectDir) {
|
|
5071
5047
|
resetSessionState(state);
|
|
5072
5048
|
state.sessionId = sessionId;
|
|
5073
5049
|
state.storageDir = config?.storagePath ? resolveStorageDir(config.storagePath, projectDir ?? cwd()) : void 0;
|
|
@@ -5090,7 +5066,10 @@ async function runSessionInitialization(client, state, sessionId, logger, messag
|
|
|
5090
5066
|
let restored = 0;
|
|
5091
5067
|
if (parentSessionId) {
|
|
5092
5068
|
try {
|
|
5093
|
-
|
|
5069
|
+
let parent = await loadSessionState(parentSessionId, logger, state.storageDir);
|
|
5070
|
+
if (!parent && state.storageDir) {
|
|
5071
|
+
parent = await loadSessionState(parentSessionId, logger);
|
|
5072
|
+
}
|
|
5094
5073
|
const response = parent ? await client.session.messages({ path: { id: parentSessionId } }) : void 0;
|
|
5095
5074
|
const parentMessages = Array.isArray(response?.data) ? response.data : Array.isArray(response) ? response : [];
|
|
5096
5075
|
if (parent && parentMessages.length > 0) {
|
|
@@ -5171,6 +5150,14 @@ async function runSessionInitialization(client, state, sessionId, logger, messag
|
|
|
5171
5150
|
if (persistedAny._persistedLastCompaction !== void 0) {
|
|
5172
5151
|
state.lastCompaction = Math.max(state.lastCompaction, persistedAny._persistedLastCompaction);
|
|
5173
5152
|
}
|
|
5153
|
+
const persistedBoundary = typeof persistedAny._persistedLastCompaction === "number" ? persistedAny._persistedLastCompaction : 0;
|
|
5154
|
+
if (state.lastCompaction > persistedBoundary) {
|
|
5155
|
+
resetOnCompaction(state);
|
|
5156
|
+
logger.info("Restarted after native compaction - reset stale transient state", {
|
|
5157
|
+
timestamp: state.lastCompaction,
|
|
5158
|
+
persistedBoundary
|
|
5159
|
+
});
|
|
5160
|
+
}
|
|
5174
5161
|
if (typeof persisted.modelContextLimit === "number" && persisted.modelContextLimit > 0) {
|
|
5175
5162
|
state.modelContextLimit = persisted.modelContextLimit;
|
|
5176
5163
|
state.modelProviderID = persisted.modelProviderID;
|
|
@@ -7713,217 +7700,214 @@ function createCompressRangeTool(factoryCtx) {
|
|
|
7713
7700
|
}
|
|
7714
7701
|
}
|
|
7715
7702
|
const callId = typeof toolCtx.callID === "string" ? toolCtx.callID : void 0;
|
|
7716
|
-
const
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7703
|
+
const { rawMessages, searchContext } = await prepareSession(
|
|
7704
|
+
ctx0,
|
|
7705
|
+
toolCtx,
|
|
7706
|
+
`Compress Range: ${input.topic ?? "(batch)"}`
|
|
7707
|
+
);
|
|
7708
|
+
const { providerId, modelId } = getModelInfo(rawMessages);
|
|
7709
|
+
const ctx = {
|
|
7710
|
+
...ctx0,
|
|
7711
|
+
config: applyCompressOverrides(ctx0.config, providerId, modelId)
|
|
7712
|
+
};
|
|
7713
|
+
const { plans: filteredPlans } = prepareExecutableRangePlans(
|
|
7714
|
+
input,
|
|
7715
|
+
searchContext,
|
|
7716
|
+
ctx.state,
|
|
7717
|
+
ctx.config,
|
|
7718
|
+
ctx.logger
|
|
7719
|
+
);
|
|
7720
|
+
const notifications = [];
|
|
7721
|
+
let preparedPlans = [];
|
|
7722
|
+
let totalCompressedMessages = 0;
|
|
7723
|
+
for (const plan of filteredPlans) {
|
|
7724
|
+
const parsedPlaceholders = parseBlockPlaceholders(plan.entry.summary);
|
|
7725
|
+
validateSummaryPlaceholders(
|
|
7726
|
+
parsedPlaceholders,
|
|
7727
|
+
plan.selection.requiredBlockIds,
|
|
7728
|
+
plan.selection.startReference,
|
|
7729
|
+
plan.selection.endReference,
|
|
7730
|
+
searchContext.summaryByBlockId,
|
|
7731
|
+
ctx.logger
|
|
7721
7732
|
);
|
|
7722
|
-
const
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7733
|
+
const injected = injectBlockPlaceholders(
|
|
7734
|
+
plan.entry.summary,
|
|
7735
|
+
parsedPlaceholders,
|
|
7736
|
+
searchContext.summaryByBlockId,
|
|
7737
|
+
plan.selection.startReference,
|
|
7738
|
+
plan.selection.endReference
|
|
7739
|
+
);
|
|
7740
|
+
const summaryWithUsers = appendProtectedUserMessages(
|
|
7741
|
+
injected.expandedSummary,
|
|
7742
|
+
plan.selection,
|
|
7729
7743
|
searchContext,
|
|
7730
7744
|
ctx.state,
|
|
7731
|
-
ctx.config
|
|
7732
|
-
ctx.logger
|
|
7745
|
+
ctx.config.compress.protectUserMessages
|
|
7733
7746
|
);
|
|
7734
|
-
const
|
|
7735
|
-
|
|
7736
|
-
|
|
7737
|
-
|
|
7738
|
-
|
|
7739
|
-
|
|
7740
|
-
parsedPlaceholders,
|
|
7741
|
-
plan.selection.requiredBlockIds,
|
|
7742
|
-
plan.selection.startReference,
|
|
7743
|
-
plan.selection.endReference,
|
|
7744
|
-
searchContext.summaryByBlockId,
|
|
7745
|
-
ctx.logger
|
|
7746
|
-
);
|
|
7747
|
-
const injected = injectBlockPlaceholders(
|
|
7748
|
-
plan.entry.summary,
|
|
7749
|
-
parsedPlaceholders,
|
|
7750
|
-
searchContext.summaryByBlockId,
|
|
7751
|
-
plan.selection.startReference,
|
|
7752
|
-
plan.selection.endReference
|
|
7753
|
-
);
|
|
7754
|
-
const summaryWithUsers = appendProtectedUserMessages(
|
|
7755
|
-
injected.expandedSummary,
|
|
7756
|
-
plan.selection,
|
|
7757
|
-
searchContext,
|
|
7758
|
-
ctx.state,
|
|
7759
|
-
ctx.config.compress.protectUserMessages
|
|
7760
|
-
);
|
|
7761
|
-
const summaryWithPromptInfo = appendProtectedPromptInfo(
|
|
7762
|
-
summaryWithUsers,
|
|
7763
|
-
plan.selection,
|
|
7764
|
-
searchContext,
|
|
7765
|
-
ctx.state,
|
|
7766
|
-
ctx.config.compress.protectTags
|
|
7767
|
-
);
|
|
7768
|
-
const summaryWithTools = await appendProtectedTools(
|
|
7769
|
-
ctx.client,
|
|
7770
|
-
ctx.state,
|
|
7771
|
-
summaryWithPromptInfo,
|
|
7772
|
-
plan.selection,
|
|
7773
|
-
searchContext,
|
|
7774
|
-
ctx.config.compress.protectedTools,
|
|
7775
|
-
ctx.config.protectedFilePatterns
|
|
7776
|
-
);
|
|
7777
|
-
const completedSummary = appendMissingBlockSummaries(
|
|
7778
|
-
summaryWithTools,
|
|
7779
|
-
[],
|
|
7780
|
-
searchContext.summaryByBlockId,
|
|
7781
|
-
injected.consumedBlockIds
|
|
7782
|
-
);
|
|
7783
|
-
const boundaryConsumed = extractBoundaryConsumedBlocks2(
|
|
7784
|
-
plan.selection.startReference,
|
|
7785
|
-
plan.selection.endReference
|
|
7786
|
-
);
|
|
7787
|
-
const seenConsumed = /* @__PURE__ */ new Set();
|
|
7788
|
-
const mergeConsumedBlockIds = [
|
|
7789
|
-
...plan.selection.requiredBlockIds,
|
|
7790
|
-
...boundaryConsumed
|
|
7791
|
-
].filter((id) => {
|
|
7792
|
-
if (seenConsumed.has(id)) return false;
|
|
7793
|
-
seenConsumed.add(id);
|
|
7794
|
-
return true;
|
|
7795
|
-
});
|
|
7796
|
-
preparedPlans.push({
|
|
7797
|
-
entry: plan.entry,
|
|
7798
|
-
selection: plan.selection,
|
|
7799
|
-
anchorMessageId: plan.anchorMessageId,
|
|
7800
|
-
finalSummary: completedSummary.expandedSummary,
|
|
7801
|
-
consumedBlockIds: mergeConsumedBlockIds
|
|
7802
|
-
});
|
|
7803
|
-
}
|
|
7804
|
-
const partition = partitionPhantomPlans(
|
|
7805
|
-
identifyPhantomPlans(
|
|
7806
|
-
ctx.state,
|
|
7807
|
-
preparedPlans.map((p) => ({
|
|
7808
|
-
messageIds: p.selection.messageIds,
|
|
7809
|
-
consumedBlockIds: p.consumedBlockIds
|
|
7810
|
-
}))
|
|
7811
|
-
),
|
|
7812
|
-
preparedPlans.length
|
|
7747
|
+
const summaryWithPromptInfo = appendProtectedPromptInfo(
|
|
7748
|
+
summaryWithUsers,
|
|
7749
|
+
plan.selection,
|
|
7750
|
+
searchContext,
|
|
7751
|
+
ctx.state,
|
|
7752
|
+
ctx.config.compress.protectTags
|
|
7813
7753
|
);
|
|
7814
|
-
|
|
7815
|
-
|
|
7816
|
-
ctx.
|
|
7817
|
-
|
|
7818
|
-
|
|
7819
|
-
|
|
7820
|
-
|
|
7821
|
-
|
|
7822
|
-
|
|
7823
|
-
|
|
7824
|
-
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
const
|
|
7834
|
-
const
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7754
|
+
const summaryWithTools = await appendProtectedTools(
|
|
7755
|
+
ctx.client,
|
|
7756
|
+
ctx.state,
|
|
7757
|
+
summaryWithPromptInfo,
|
|
7758
|
+
plan.selection,
|
|
7759
|
+
searchContext,
|
|
7760
|
+
ctx.config.compress.protectedTools,
|
|
7761
|
+
ctx.config.protectedFilePatterns
|
|
7762
|
+
);
|
|
7763
|
+
const completedSummary = appendMissingBlockSummaries(
|
|
7764
|
+
summaryWithTools,
|
|
7765
|
+
[],
|
|
7766
|
+
searchContext.summaryByBlockId,
|
|
7767
|
+
injected.consumedBlockIds
|
|
7768
|
+
);
|
|
7769
|
+
const boundaryConsumed = extractBoundaryConsumedBlocks2(
|
|
7770
|
+
plan.selection.startReference,
|
|
7771
|
+
plan.selection.endReference
|
|
7772
|
+
);
|
|
7773
|
+
const seenConsumed = /* @__PURE__ */ new Set();
|
|
7774
|
+
const mergeConsumedBlockIds = [
|
|
7775
|
+
...plan.selection.requiredBlockIds,
|
|
7776
|
+
...boundaryConsumed
|
|
7777
|
+
].filter((id) => {
|
|
7778
|
+
if (seenConsumed.has(id)) return false;
|
|
7779
|
+
seenConsumed.add(id);
|
|
7780
|
+
return true;
|
|
7781
|
+
});
|
|
7782
|
+
preparedPlans.push({
|
|
7783
|
+
entry: plan.entry,
|
|
7784
|
+
selection: plan.selection,
|
|
7785
|
+
anchorMessageId: plan.anchorMessageId,
|
|
7786
|
+
finalSummary: completedSummary.expandedSummary,
|
|
7787
|
+
consumedBlockIds: mergeConsumedBlockIds
|
|
7788
|
+
});
|
|
7789
|
+
}
|
|
7790
|
+
const partition = partitionPhantomPlans(
|
|
7791
|
+
identifyPhantomPlans(
|
|
7792
|
+
ctx.state,
|
|
7793
|
+
preparedPlans.map((p) => ({
|
|
7794
|
+
messageIds: p.selection.messageIds,
|
|
7795
|
+
consumedBlockIds: p.consumedBlockIds
|
|
7796
|
+
}))
|
|
7797
|
+
),
|
|
7798
|
+
preparedPlans.length
|
|
7799
|
+
);
|
|
7800
|
+
let phantomSkipNotice = null;
|
|
7801
|
+
if (partition.kind === "all-phantom") {
|
|
7802
|
+
ctx.logger.warn("Batch compress: ALL entries phantom", {
|
|
7803
|
+
totalCount: preparedPlans.length,
|
|
7804
|
+
details: partition.details
|
|
7805
|
+
});
|
|
7806
|
+
throw new Error(buildPhantomErrorMessage(partition.details));
|
|
7807
|
+
}
|
|
7808
|
+
if (partition.kind === "partial") {
|
|
7809
|
+
ctx.logger.warn("Batch compress: phantom entries detected", {
|
|
7810
|
+
phantomCount: partition.dropIndices.length,
|
|
7811
|
+
totalCount: preparedPlans.length,
|
|
7812
|
+
phantomIndices: partition.dropIndices,
|
|
7813
|
+
details: partition.details
|
|
7814
|
+
});
|
|
7815
|
+
const dropSet = new Set(partition.dropIndices);
|
|
7816
|
+
preparedPlans = preparedPlans.filter((_, i) => !dropSet.has(i));
|
|
7817
|
+
phantomSkipNotice = partition.notice;
|
|
7818
|
+
}
|
|
7819
|
+
const acknowledgeRisk = args.acknowledgeRisk === true;
|
|
7820
|
+
const qualityGateRetryPendingBefore = ctx.state.qualityGateRetryPending;
|
|
7821
|
+
const bypassQuality = acknowledgeRisk && ctx.state.qualityGateRetryPending;
|
|
7822
|
+
const ignoredAcknowledgeRisk = acknowledgeRisk && !ctx.state.qualityGateRetryPending;
|
|
7823
|
+
if (ignoredAcknowledgeRisk) {
|
|
7824
|
+
ctx.logger.warn(
|
|
7825
|
+
"compress: acknowledgeRisk ignored \u2014 no quality gate rejection pending"
|
|
7826
|
+
);
|
|
7827
|
+
}
|
|
7828
|
+
ctx.state.qualityGateRetryPending = false;
|
|
7829
|
+
if (!bypassQuality) {
|
|
7830
|
+
for (const plan of preparedPlans) {
|
|
7831
|
+
const result = evaluatePreCommitQuality(
|
|
7832
|
+
rawMessages,
|
|
7833
|
+
plan.selection.messageIds,
|
|
7834
|
+
plan.selection.messageTokenById,
|
|
7835
|
+
plan.finalSummary,
|
|
7836
|
+
ctx.config,
|
|
7837
|
+
ctx.logger
|
|
7840
7838
|
);
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
for (const plan of preparedPlans) {
|
|
7845
|
-
const result = evaluatePreCommitQuality(
|
|
7846
|
-
rawMessages,
|
|
7847
|
-
plan.selection.messageIds,
|
|
7848
|
-
plan.selection.messageTokenById,
|
|
7849
|
-
plan.finalSummary,
|
|
7850
|
-
ctx.config,
|
|
7851
|
-
ctx.logger
|
|
7852
|
-
);
|
|
7853
|
-
if (result && !result.passed) {
|
|
7854
|
-
ctx.state.qualityGateRetryPending = true;
|
|
7855
|
-
throw buildQualityRejectionError(
|
|
7856
|
-
{
|
|
7857
|
-
startId: plan.entry.startId,
|
|
7858
|
-
endId: plan.entry.endId,
|
|
7859
|
-
summary: plan.finalSummary,
|
|
7860
|
-
messageIds: plan.selection.messageIds,
|
|
7861
|
-
messageTokenById: plan.selection.messageTokenById
|
|
7862
|
-
},
|
|
7863
|
-
result
|
|
7864
|
-
);
|
|
7865
|
-
}
|
|
7866
|
-
}
|
|
7867
|
-
}
|
|
7868
|
-
const snapshot = snapshotCompressionState(ctx.state);
|
|
7869
|
-
const runId = allocateRunId(ctx.state);
|
|
7870
|
-
try {
|
|
7871
|
-
for (const preparedPlan of preparedPlans) {
|
|
7872
|
-
const blockId = allocateBlockId(ctx.state);
|
|
7873
|
-
const keepResult = resolveKeepMarkers(
|
|
7874
|
-
preparedPlan.finalSummary,
|
|
7875
|
-
rawMessages,
|
|
7876
|
-
ctx.state,
|
|
7877
|
-
ctx.config
|
|
7878
|
-
);
|
|
7879
|
-
preparedPlan.finalSummary = keepResult.summary;
|
|
7880
|
-
const storedSummary = wrapCompressedSummary(blockId, preparedPlan.finalSummary);
|
|
7881
|
-
const summaryTokens = countTokens2(storedSummary);
|
|
7882
|
-
const applied = applyCompressionState(
|
|
7883
|
-
ctx.state,
|
|
7839
|
+
if (result && !result.passed) {
|
|
7840
|
+
ctx.state.qualityGateRetryPending = true;
|
|
7841
|
+
throw buildQualityRejectionError(
|
|
7884
7842
|
{
|
|
7885
|
-
|
|
7886
|
-
|
|
7887
|
-
|
|
7888
|
-
|
|
7889
|
-
|
|
7890
|
-
runId,
|
|
7891
|
-
compressMessageId: toolCtx.messageID,
|
|
7892
|
-
compressCallId: callId,
|
|
7893
|
-
summaryTokens
|
|
7843
|
+
startId: plan.entry.startId,
|
|
7844
|
+
endId: plan.entry.endId,
|
|
7845
|
+
summary: plan.finalSummary,
|
|
7846
|
+
messageIds: plan.selection.messageIds,
|
|
7847
|
+
messageTokenById: plan.selection.messageTokenById
|
|
7894
7848
|
},
|
|
7895
|
-
|
|
7896
|
-
preparedPlan.anchorMessageId,
|
|
7897
|
-
blockId,
|
|
7898
|
-
storedSummary,
|
|
7899
|
-
preparedPlan.consumedBlockIds,
|
|
7900
|
-
ctx.config.gc
|
|
7849
|
+
result
|
|
7901
7850
|
);
|
|
7902
|
-
|
|
7903
|
-
|
|
7904
|
-
|
|
7851
|
+
}
|
|
7852
|
+
}
|
|
7853
|
+
}
|
|
7854
|
+
const snapshot = snapshotCompressionState(ctx.state);
|
|
7855
|
+
const runId = allocateRunId(ctx.state);
|
|
7856
|
+
try {
|
|
7857
|
+
for (const preparedPlan of preparedPlans) {
|
|
7858
|
+
const blockId = allocateBlockId(ctx.state);
|
|
7859
|
+
const keepResult = resolveKeepMarkers(
|
|
7860
|
+
preparedPlan.finalSummary,
|
|
7861
|
+
rawMessages,
|
|
7862
|
+
ctx.state,
|
|
7863
|
+
ctx.config
|
|
7864
|
+
);
|
|
7865
|
+
preparedPlan.finalSummary = keepResult.summary;
|
|
7866
|
+
const storedSummary = wrapCompressedSummary(blockId, preparedPlan.finalSummary);
|
|
7867
|
+
const summaryTokens = countTokens2(storedSummary);
|
|
7868
|
+
const applied = applyCompressionState(
|
|
7869
|
+
ctx.state,
|
|
7870
|
+
{
|
|
7871
|
+
topic: preparedPlan.entry.topic ?? input.topic ?? "",
|
|
7872
|
+
batchTopic: input.topic,
|
|
7873
|
+
startId: preparedPlan.entry.startId,
|
|
7874
|
+
endId: preparedPlan.entry.endId,
|
|
7875
|
+
mode: "range",
|
|
7905
7876
|
runId,
|
|
7906
|
-
|
|
7877
|
+
compressMessageId: toolCtx.messageID,
|
|
7878
|
+
compressCallId: callId,
|
|
7907
7879
|
summaryTokens
|
|
7908
|
-
}
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7880
|
+
},
|
|
7881
|
+
preparedPlan.selection,
|
|
7882
|
+
preparedPlan.anchorMessageId,
|
|
7883
|
+
blockId,
|
|
7884
|
+
storedSummary,
|
|
7885
|
+
preparedPlan.consumedBlockIds,
|
|
7886
|
+
ctx.config.gc
|
|
7887
|
+
);
|
|
7888
|
+
totalCompressedMessages += applied.messageIds.length;
|
|
7889
|
+
notifications.push({
|
|
7890
|
+
blockId,
|
|
7891
|
+
runId,
|
|
7892
|
+
summary: preparedPlan.finalSummary,
|
|
7893
|
+
summaryTokens
|
|
7894
|
+
});
|
|
7915
7895
|
}
|
|
7916
|
-
|
|
7896
|
+
await finalizeSession(ctx, toolCtx, rawMessages, notifications, input.topic);
|
|
7897
|
+
} catch (error) {
|
|
7898
|
+
restoreCompressionState(ctx.state, snapshot);
|
|
7899
|
+
ctx.state.qualityGateRetryPending = qualityGateRetryPendingBefore;
|
|
7900
|
+
throw error;
|
|
7901
|
+
}
|
|
7902
|
+
const skippedNote = phantomSkipNotice !== null ? `
|
|
7917
7903
|
\u26A0\uFE0F ${phantomSkipNotice}
|
|
7918
7904
|
` : "";
|
|
7919
|
-
|
|
7905
|
+
const ackNote = ignoredAcknowledgeRisk ? `
|
|
7920
7906
|
\u26A0\uFE0F acknowledgeRisk was ignored: no quality gate rejection was pending, so quality checks ran normally. Only pass it when retrying immediately after a quality gate rejection.
|
|
7921
7907
|
` : "";
|
|
7922
|
-
|
|
7908
|
+
return `Compressed ${totalCompressedMessages} messages into ${COMPRESSED_BLOCK_HEADER}.${skippedNote}${ackNote}
|
|
7923
7909
|
IMPORTANT: This was an automatic context compression. You MUST continue your previous task exactly where you left off. Do NOT ask the user what to do next.
|
|
7924
7910
|
\u{1F4A1} Tip: Use search_context('keyword') to find compressed content when you need it later.`;
|
|
7925
|
-
};
|
|
7926
|
-
return factoryCtx.registry.withSessionGuard(toolCtx.sessionID, () => run());
|
|
7927
7911
|
}
|
|
7928
7912
|
});
|
|
7929
7913
|
}
|
|
@@ -9804,112 +9788,109 @@ function createDecompressTool(factoryCtx) {
|
|
|
9804
9788
|
args: buildSchema2(),
|
|
9805
9789
|
async execute(args, toolCtx) {
|
|
9806
9790
|
const ctx = resolveToolContext(factoryCtx, toolCtx.sessionID);
|
|
9807
|
-
const
|
|
9808
|
-
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
|
|
9818
|
-
|
|
9819
|
-
|
|
9820
|
-
for (const
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
activeBlocks.push(block);
|
|
9824
|
-
}
|
|
9791
|
+
const { rawMessages } = await prepareDecompressSession(ctx, toolCtx);
|
|
9792
|
+
const effectiveLimitBefore = resolveEffectiveContextLimit(ctx.state, ctx.config);
|
|
9793
|
+
const contextUsageBefore = effectiveLimitBefore ? Math.round(
|
|
9794
|
+
getCurrentTokenUsage(ctx.state, rawMessages) / effectiveLimitBefore.limit * 100
|
|
9795
|
+
) : void 0;
|
|
9796
|
+
const resolved = resolveTargets(args, ctx.state, rawMessages, ctx.logger);
|
|
9797
|
+
if (!resolved.ok) {
|
|
9798
|
+
return resolved.error;
|
|
9799
|
+
}
|
|
9800
|
+
const targets = resolved.targets;
|
|
9801
|
+
const messagesState = ctx.state.prune.messages;
|
|
9802
|
+
const activeBlocks = [];
|
|
9803
|
+
for (const target of targets) {
|
|
9804
|
+
for (const block of target.blocks) {
|
|
9805
|
+
if (block.active) {
|
|
9806
|
+
activeBlocks.push(block);
|
|
9825
9807
|
}
|
|
9826
9808
|
}
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
}
|
|
9843
|
-
const msgIdSet = /* @__PURE__ */ new Set();
|
|
9844
|
-
for (const block of activeBlocks) {
|
|
9845
|
-
for (const id of block.effectiveMessageIds ?? []) {
|
|
9846
|
-
msgIdSet.add(id);
|
|
9847
|
-
}
|
|
9848
|
-
}
|
|
9849
|
-
const blockMessages = rawMessages.filter((m) => msgIdSet.has(extractMessageId(m)));
|
|
9850
|
-
const lines2 = blockMessages.map(extractMessageText2);
|
|
9851
|
-
const { writeFile: writeFile4 } = await import("fs/promises");
|
|
9852
|
-
const fileContent = lines2.length > 0 ? lines2.join("\n\n---\n\n") : targets[0]?.blocks[0]?.summary ?? "(no content available)";
|
|
9853
|
-
await writeFile4(targetPath, fileContent, "utf-8");
|
|
9854
|
-
const displayIds2 = targets.map((t) => `b${t.displayId}`).join(", ");
|
|
9855
|
-
return `Block(s) ${displayIds2} content (${blockMessages.length} messages, ${fileContent.length} chars) written to ${targetPath}. Block(s) stay compressed \u2014 context unchanged. Use read tool to access specific parts.`;
|
|
9856
|
-
}
|
|
9857
|
-
const activeMessagesBefore = snapshotActiveMessages(messagesState);
|
|
9858
|
-
const activeBlockIdsBefore = new Set(messagesState.activeBlockIds);
|
|
9859
|
-
for (const target of targets) {
|
|
9860
|
-
deactivateCompressionTarget(messagesState, target, { full: args.full === true });
|
|
9861
|
-
}
|
|
9862
|
-
syncCompressionBlocks(ctx.state, ctx.logger, rawMessages);
|
|
9863
|
-
const { restoredMessageCount, restoredTokens } = computeRestoredMessages(
|
|
9864
|
-
messagesState,
|
|
9865
|
-
activeMessagesBefore
|
|
9866
|
-
);
|
|
9867
|
-
const reactivatedBlockIds = computeReactivatedBlockIds(
|
|
9868
|
-
messagesState,
|
|
9869
|
-
activeBlockIdsBefore
|
|
9870
|
-
);
|
|
9871
|
-
ctx.state.stats.totalPruneTokens = Math.max(
|
|
9872
|
-
0,
|
|
9873
|
-
ctx.state.stats.totalPruneTokens - restoredTokens
|
|
9874
|
-
);
|
|
9875
|
-
const effectiveLimitAfter = resolveEffectiveContextLimit(ctx.state, ctx.config);
|
|
9876
|
-
const contextUsageAfter = effectiveLimitAfter ? Math.round(
|
|
9877
|
-
getCurrentTokenUsage(ctx.state, rawMessages) / effectiveLimitAfter.limit * 100
|
|
9878
|
-
) : void 0;
|
|
9879
|
-
await finalizeDecompressSession(ctx);
|
|
9880
|
-
const restoredContentPreview = buildRestoredContentPreview(
|
|
9881
|
-
rawMessages,
|
|
9882
|
-
activeMessagesBefore,
|
|
9883
|
-
messagesState
|
|
9884
|
-
);
|
|
9885
|
-
const displayIds = targets.map((t) => `b${t.displayId}`).join(", ");
|
|
9886
|
-
const lines = [];
|
|
9887
|
-
const headerNoun = targets.length === 1 ? "block" : "blocks";
|
|
9888
|
-
lines.push(
|
|
9889
|
-
`Decompressed ${headerNoun} ${displayIds}. Restored ${restoredMessageCount} message(s) (~${formatTokenCount(restoredTokens)}).`
|
|
9890
|
-
);
|
|
9891
|
-
if (contextUsageBefore !== void 0 && contextUsageAfter !== void 0) {
|
|
9892
|
-
lines.push(`Context usage: ${contextUsageBefore}% \u2192 ${contextUsageAfter}%.`);
|
|
9893
|
-
}
|
|
9894
|
-
if (reactivatedBlockIds.length > 0) {
|
|
9895
|
-
const refs = reactivatedBlockIds.map((id) => `b${id}`).join(", ");
|
|
9896
|
-
lines.push(`Also restored nested block(s): ${refs}.`);
|
|
9809
|
+
}
|
|
9810
|
+
if (args.toFile) {
|
|
9811
|
+
const targetPath = args.toFile;
|
|
9812
|
+
const os = await import("os");
|
|
9813
|
+
const path = await import("path");
|
|
9814
|
+
const allowedDirs = [
|
|
9815
|
+
os.tmpdir() + "/",
|
|
9816
|
+
path.join(os.homedir(), ".cache", "opencode") + "/"
|
|
9817
|
+
];
|
|
9818
|
+
const resolvedPath = path.resolve(targetPath);
|
|
9819
|
+
const isAllowed = allowedDirs.some((dir) => {
|
|
9820
|
+
const rel = path.relative(dir, resolvedPath);
|
|
9821
|
+
return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
9822
|
+
});
|
|
9823
|
+
if (!isAllowed) {
|
|
9824
|
+
return `Error: toFile path must be under ${os.tmpdir()} or ~/.cache/opencode/. Got: ${targetPath}`;
|
|
9897
9825
|
}
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
|
|
9901
|
-
|
|
9826
|
+
const msgIdSet = /* @__PURE__ */ new Set();
|
|
9827
|
+
for (const block of activeBlocks) {
|
|
9828
|
+
for (const id of block.effectiveMessageIds ?? []) {
|
|
9829
|
+
msgIdSet.add(id);
|
|
9830
|
+
}
|
|
9902
9831
|
}
|
|
9903
|
-
|
|
9904
|
-
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
|
|
9908
|
-
|
|
9909
|
-
})
|
|
9910
|
-
|
|
9911
|
-
|
|
9912
|
-
|
|
9832
|
+
const blockMessages = rawMessages.filter((m) => msgIdSet.has(extractMessageId(m)));
|
|
9833
|
+
const lines2 = blockMessages.map(extractMessageText2);
|
|
9834
|
+
const { writeFile: writeFile4 } = await import("fs/promises");
|
|
9835
|
+
const fileContent = lines2.length > 0 ? lines2.join("\n\n---\n\n") : targets[0]?.blocks[0]?.summary ?? "(no content available)";
|
|
9836
|
+
await writeFile4(targetPath, fileContent, "utf-8");
|
|
9837
|
+
const displayIds2 = targets.map((t) => `b${t.displayId}`).join(", ");
|
|
9838
|
+
return `Block(s) ${displayIds2} content (${blockMessages.length} messages, ${fileContent.length} chars) written to ${targetPath}. Block(s) stay compressed \u2014 context unchanged. Use read tool to access specific parts.`;
|
|
9839
|
+
}
|
|
9840
|
+
const activeMessagesBefore = snapshotActiveMessages(messagesState);
|
|
9841
|
+
const activeBlockIdsBefore = new Set(messagesState.activeBlockIds);
|
|
9842
|
+
for (const target of targets) {
|
|
9843
|
+
deactivateCompressionTarget(messagesState, target, { full: args.full === true });
|
|
9844
|
+
}
|
|
9845
|
+
syncCompressionBlocks(ctx.state, ctx.logger, rawMessages);
|
|
9846
|
+
const { restoredMessageCount, restoredTokens } = computeRestoredMessages(
|
|
9847
|
+
messagesState,
|
|
9848
|
+
activeMessagesBefore
|
|
9849
|
+
);
|
|
9850
|
+
const reactivatedBlockIds = computeReactivatedBlockIds(
|
|
9851
|
+
messagesState,
|
|
9852
|
+
activeBlockIdsBefore
|
|
9853
|
+
);
|
|
9854
|
+
ctx.state.stats.totalPruneTokens = Math.max(
|
|
9855
|
+
0,
|
|
9856
|
+
ctx.state.stats.totalPruneTokens - restoredTokens
|
|
9857
|
+
);
|
|
9858
|
+
const effectiveLimitAfter = resolveEffectiveContextLimit(ctx.state, ctx.config);
|
|
9859
|
+
const contextUsageAfter = effectiveLimitAfter ? Math.round(
|
|
9860
|
+
getCurrentTokenUsage(ctx.state, rawMessages) / effectiveLimitAfter.limit * 100
|
|
9861
|
+
) : void 0;
|
|
9862
|
+
await finalizeDecompressSession(ctx);
|
|
9863
|
+
const restoredContentPreview = buildRestoredContentPreview(
|
|
9864
|
+
rawMessages,
|
|
9865
|
+
activeMessagesBefore,
|
|
9866
|
+
messagesState
|
|
9867
|
+
);
|
|
9868
|
+
const displayIds = targets.map((t) => `b${t.displayId}`).join(", ");
|
|
9869
|
+
const lines = [];
|
|
9870
|
+
const headerNoun = targets.length === 1 ? "block" : "blocks";
|
|
9871
|
+
lines.push(
|
|
9872
|
+
`Decompressed ${headerNoun} ${displayIds}. Restored ${restoredMessageCount} message(s) (~${formatTokenCount(restoredTokens)}).`
|
|
9873
|
+
);
|
|
9874
|
+
if (contextUsageBefore !== void 0 && contextUsageAfter !== void 0) {
|
|
9875
|
+
lines.push(`Context usage: ${contextUsageBefore}% \u2192 ${contextUsageAfter}%.`);
|
|
9876
|
+
}
|
|
9877
|
+
if (reactivatedBlockIds.length > 0) {
|
|
9878
|
+
const refs = reactivatedBlockIds.map((id) => `b${id}`).join(", ");
|
|
9879
|
+
lines.push(`Also restored nested block(s): ${refs}.`);
|
|
9880
|
+
}
|
|
9881
|
+
if (restoredContentPreview) {
|
|
9882
|
+
lines.push("");
|
|
9883
|
+
lines.push("RESTORED CONTENT (condensed):");
|
|
9884
|
+
lines.push(restoredContentPreview);
|
|
9885
|
+
}
|
|
9886
|
+
ctx.logger.info("Decompress tool completed", {
|
|
9887
|
+
mode: typeof args.startId === "string" ? "range" : "block",
|
|
9888
|
+
targetBlockIds: targets.map((t) => t.displayId),
|
|
9889
|
+
restoredMessageCount,
|
|
9890
|
+
restoredTokens,
|
|
9891
|
+
reactivatedBlockIds
|
|
9892
|
+
});
|
|
9893
|
+
return lines.join("\n");
|
|
9913
9894
|
}
|
|
9914
9895
|
});
|
|
9915
9896
|
}
|
|
@@ -10595,7 +10576,7 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
|
10595
10576
|
import { join as join4 } from "path";
|
|
10596
10577
|
import { existsSync as existsSync4 } from "fs";
|
|
10597
10578
|
import { homedir as homedir3 } from "os";
|
|
10598
|
-
var LOG_VERSION = true ? "1.18.1-pr.
|
|
10579
|
+
var LOG_VERSION = true ? "1.18.1-pr.409.166" : "dev";
|
|
10599
10580
|
var LEVEL_RANK = {
|
|
10600
10581
|
debug: 10,
|
|
10601
10582
|
info: 20,
|
|
@@ -12650,24 +12631,22 @@ function createSystemPromptHandler(registry4, logger, config, prompts) {
|
|
|
12650
12631
|
logger.info("Skipping DCP system prompt injection for internal agent");
|
|
12651
12632
|
return;
|
|
12652
12633
|
}
|
|
12653
|
-
if (input.model?.limit?.context
|
|
12654
|
-
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
|
|
12659
|
-
|
|
12660
|
-
|
|
12661
|
-
|
|
12662
|
-
|
|
12663
|
-
|
|
12664
|
-
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
}
|
|
12670
|
-
});
|
|
12634
|
+
if (input.model?.limit?.context) {
|
|
12635
|
+
const limit = input.model.limit.context;
|
|
12636
|
+
const providerID = input.model?.providerID;
|
|
12637
|
+
const modelID = input.model?.id;
|
|
12638
|
+
const changed = state.modelContextLimit !== limit || providerID !== void 0 && state.modelProviderID !== providerID || modelID !== void 0 && state.modelID !== modelID;
|
|
12639
|
+
state.modelContextLimit = limit;
|
|
12640
|
+
if (providerID !== void 0) {
|
|
12641
|
+
state.modelProviderID = providerID;
|
|
12642
|
+
}
|
|
12643
|
+
if (modelID !== void 0) {
|
|
12644
|
+
state.modelID = modelID;
|
|
12645
|
+
}
|
|
12646
|
+
if (changed) {
|
|
12647
|
+
saveSessionState(state, logger).catch(() => {
|
|
12648
|
+
});
|
|
12649
|
+
}
|
|
12671
12650
|
}
|
|
12672
12651
|
const effectivePermission = compressPermission(state, config);
|
|
12673
12652
|
if (effectivePermission === "deny") {
|
|
@@ -12702,131 +12681,11 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
12702
12681
|
return;
|
|
12703
12682
|
}
|
|
12704
12683
|
const lastUserMessage = getLastUserMessage(messages);
|
|
12705
|
-
|
|
12706
|
-
syncCompressPermissionState(state, config, hostPermissions, output.messages);
|
|
12707
|
-
if (state.isSubAgent && !config.allowSubAgents) {
|
|
12708
|
-
return;
|
|
12709
|
-
}
|
|
12710
|
-
stripHallucinations(output.messages);
|
|
12711
|
-
const dropReasoningModel = lastUserMessage?.info?.model;
|
|
12712
|
-
const reasoningConfig = applyCompressOverrides(
|
|
12713
|
-
config,
|
|
12714
|
-
dropReasoningModel?.providerID ?? state.modelProviderID,
|
|
12715
|
-
dropReasoningModel?.modelID ?? state.modelID
|
|
12716
|
-
).compress.reasoning;
|
|
12717
|
-
if (reasoningConfig?.drop !== false) {
|
|
12718
|
-
const droppedReasoning = dropCompressReasoning(
|
|
12719
|
-
output.messages,
|
|
12720
|
-
reasoningConfig?.threshold ?? DEFAULT_COMPRESS_REASONING.threshold
|
|
12721
|
-
);
|
|
12722
|
-
if (droppedReasoning > 0) {
|
|
12723
|
-
logger.debug("compress.reasoning: dropped oversized reasoning parts", {
|
|
12724
|
-
dropped: droppedReasoning,
|
|
12725
|
-
threshold: reasoningConfig?.threshold ?? DEFAULT_COMPRESS_REASONING.threshold
|
|
12726
|
-
});
|
|
12727
|
-
}
|
|
12728
|
-
}
|
|
12729
|
-
ensureBuiltinFiltersRegistered();
|
|
12730
|
-
const effectiveLimit = resolveEffectiveContextLimit(state, config);
|
|
12731
|
-
applyMessageFilters(output.messages, config.messageFilters, logger, {
|
|
12732
|
-
sessionId: state.sessionId ?? "",
|
|
12733
|
-
isSubAgent: state.isSubAgent,
|
|
12734
|
-
modelContextLimit: effectiveLimit?.limit
|
|
12735
|
-
});
|
|
12736
|
-
cacheSystemPromptTokens(state, output.messages);
|
|
12737
|
-
assignMessageRefs(state, output.messages);
|
|
12738
|
-
const activeBlockCountBefore = state.prune.messages.activeBlockIds.size;
|
|
12739
|
-
const compressionStateChanged = syncCompressionBlocks(state, logger, output.messages);
|
|
12740
|
-
if (compressionStateChanged || state.prune.messages.activeBlockIds.size !== activeBlockCountBefore) {
|
|
12741
|
-
saveSessionState(state, logger).catch(() => {
|
|
12742
|
-
});
|
|
12743
|
-
}
|
|
12744
|
-
syncToolCache(state, config, logger, output.messages);
|
|
12745
|
-
buildToolIdList(state, output.messages);
|
|
12746
|
-
const batchResult = runBatchCleanup(state, config, logger, output.messages);
|
|
12747
|
-
if (batchResult.mergedCount > 0) {
|
|
12748
|
-
saveSessionState(state, logger).catch(() => {
|
|
12749
|
-
});
|
|
12750
|
-
}
|
|
12751
|
-
const prePruneTokens = getCurrentTokenUsage(state, output.messages);
|
|
12752
|
-
const candidateMessages = config.compress.candidates === true ? output.messages.slice() : void 0;
|
|
12753
|
-
prune(state, logger, config, output.messages);
|
|
12754
|
-
hideConsumedCompressCalls(state, output.messages);
|
|
12755
|
-
assignMessageRefs(state, output.messages);
|
|
12756
|
-
const compressionPriorities = buildPriorityMap(config, state, output.messages);
|
|
12757
|
-
prompts.reload();
|
|
12758
|
-
injectCompressNudges(
|
|
12759
|
-
state,
|
|
12760
|
-
config,
|
|
12761
|
-
logger,
|
|
12762
|
-
output.messages,
|
|
12763
|
-
prompts.getRuntimePrompts(),
|
|
12764
|
-
compressionPriorities,
|
|
12765
|
-
config.debug ? (text) => {
|
|
12766
|
-
logger.debug(`[ACP Debug] Nudge injected:
|
|
12767
|
-
${text}`);
|
|
12768
|
-
client.tui.showToast({
|
|
12769
|
-
body: {
|
|
12770
|
-
title: "ACP: Nudge Injected",
|
|
12771
|
-
message: text.slice(0, 500),
|
|
12772
|
-
variant: "info",
|
|
12773
|
-
duration: 5e3
|
|
12774
|
-
}
|
|
12775
|
-
}).catch(() => {
|
|
12776
|
-
});
|
|
12777
|
-
} : void 0,
|
|
12778
|
-
prePruneTokens,
|
|
12779
|
-
candidateMessages
|
|
12780
|
-
);
|
|
12781
|
-
truncateLargeToolOutputs(
|
|
12782
|
-
state,
|
|
12783
|
-
config,
|
|
12784
|
-
logger,
|
|
12785
|
-
output.messages.filter((message) => !isSyntheticMessage(message))
|
|
12786
|
-
);
|
|
12787
|
-
enforceContextBudget(state, config, logger, output.messages);
|
|
12788
|
-
injectMessageIds(state, config, output.messages, compressionPriorities);
|
|
12789
|
-
hideFailedCompressCalls(output.messages);
|
|
12790
|
-
stripStaleMetadata(output.messages);
|
|
12791
|
-
dropEmptyMessages(output.messages);
|
|
12792
|
-
const postTokens = getCurrentTokenUsage(state, output.messages);
|
|
12793
|
-
if (postTokens !== void 0 && effectiveLimit) {
|
|
12794
|
-
const budget = effectiveLimit.limit - (state.systemPromptTokens ?? 0) - OUTPUT_RESERVE_TOKENS;
|
|
12795
|
-
if (postTokens > budget) {
|
|
12796
|
-
logger.error(
|
|
12797
|
-
"ACP hard guard: context exceeds model budget after in-flight reduction",
|
|
12798
|
-
{
|
|
12799
|
-
session: state.sessionId,
|
|
12800
|
-
postTokens,
|
|
12801
|
-
budget,
|
|
12802
|
-
contextLimit: effectiveLimit.limit,
|
|
12803
|
-
contextLimitSource: effectiveLimit.source,
|
|
12804
|
-
hint: "request will likely be rejected; run /compact or start a new session"
|
|
12805
|
-
}
|
|
12806
|
-
);
|
|
12807
|
-
}
|
|
12808
|
-
}
|
|
12809
|
-
logger.info("Chat transform complete", {
|
|
12810
|
-
session: state.sessionId,
|
|
12811
|
-
model: state.modelID,
|
|
12812
|
-
messages: output.messages.length,
|
|
12813
|
-
prePruneTokens,
|
|
12814
|
-
postTokens,
|
|
12815
|
-
contextLimit: effectiveLimit?.limit,
|
|
12816
|
-
contextLimitSource: effectiveLimit?.source,
|
|
12817
|
-
usagePct: postTokens !== void 0 && effectiveLimit ? `${(postTokens / effectiveLimit.limit * 100).toFixed(1)}%` : void 0,
|
|
12818
|
-
nudged: state.nudges.shouldInjectThisTurn
|
|
12819
|
-
});
|
|
12820
|
-
if (state.sessionId) {
|
|
12821
|
-
await logger.saveContext(state.sessionId, output.messages);
|
|
12822
|
-
}
|
|
12823
|
-
};
|
|
12684
|
+
let state;
|
|
12824
12685
|
if (!lastUserMessage) {
|
|
12825
|
-
|
|
12826
|
-
|
|
12827
|
-
|
|
12828
|
-
await registry4.withSessionGuard(lastUserMessage.info.sessionID, async () => {
|
|
12829
|
-
const state = await registry4.getOrCreate(
|
|
12686
|
+
state = createSessionState();
|
|
12687
|
+
} else {
|
|
12688
|
+
state = await registry4.getOrCreate(
|
|
12830
12689
|
client,
|
|
12831
12690
|
lastUserMessage.info.sessionID,
|
|
12832
12691
|
messages,
|
|
@@ -12883,8 +12742,124 @@ ${text}`);
|
|
|
12883
12742
|
}
|
|
12884
12743
|
);
|
|
12885
12744
|
}
|
|
12886
|
-
|
|
12745
|
+
}
|
|
12746
|
+
syncCompressPermissionState(state, config, hostPermissions, output.messages);
|
|
12747
|
+
if (state.isSubAgent && !config.allowSubAgents) {
|
|
12748
|
+
return;
|
|
12749
|
+
}
|
|
12750
|
+
stripHallucinations(output.messages);
|
|
12751
|
+
const dropReasoningModel = lastUserMessage?.info?.model;
|
|
12752
|
+
const reasoningConfig = applyCompressOverrides(
|
|
12753
|
+
config,
|
|
12754
|
+
dropReasoningModel?.providerID ?? state.modelProviderID,
|
|
12755
|
+
dropReasoningModel?.modelID ?? state.modelID
|
|
12756
|
+
).compress.reasoning;
|
|
12757
|
+
if (reasoningConfig?.drop !== false) {
|
|
12758
|
+
const droppedReasoning = dropCompressReasoning(
|
|
12759
|
+
output.messages,
|
|
12760
|
+
reasoningConfig?.threshold ?? DEFAULT_COMPRESS_REASONING.threshold
|
|
12761
|
+
);
|
|
12762
|
+
if (droppedReasoning > 0) {
|
|
12763
|
+
logger.debug("compress.reasoning: dropped oversized reasoning parts", {
|
|
12764
|
+
dropped: droppedReasoning,
|
|
12765
|
+
threshold: reasoningConfig?.threshold ?? DEFAULT_COMPRESS_REASONING.threshold
|
|
12766
|
+
});
|
|
12767
|
+
}
|
|
12768
|
+
}
|
|
12769
|
+
ensureBuiltinFiltersRegistered();
|
|
12770
|
+
const effectiveLimit = resolveEffectiveContextLimit(state, config);
|
|
12771
|
+
applyMessageFilters(output.messages, config.messageFilters, logger, {
|
|
12772
|
+
sessionId: state.sessionId ?? "",
|
|
12773
|
+
isSubAgent: state.isSubAgent,
|
|
12774
|
+
modelContextLimit: effectiveLimit?.limit
|
|
12887
12775
|
});
|
|
12776
|
+
cacheSystemPromptTokens(state, output.messages);
|
|
12777
|
+
assignMessageRefs(state, output.messages);
|
|
12778
|
+
const activeBlockCountBefore = state.prune.messages.activeBlockIds.size;
|
|
12779
|
+
const compressionStateChanged = syncCompressionBlocks(state, logger, output.messages);
|
|
12780
|
+
if (compressionStateChanged || state.prune.messages.activeBlockIds.size !== activeBlockCountBefore) {
|
|
12781
|
+
saveSessionState(state, logger).catch(() => {
|
|
12782
|
+
});
|
|
12783
|
+
}
|
|
12784
|
+
syncToolCache(state, config, logger, output.messages);
|
|
12785
|
+
buildToolIdList(state, output.messages);
|
|
12786
|
+
const batchResult = runBatchCleanup(state, config, logger, output.messages);
|
|
12787
|
+
if (batchResult.mergedCount > 0) {
|
|
12788
|
+
saveSessionState(state, logger).catch(() => {
|
|
12789
|
+
});
|
|
12790
|
+
}
|
|
12791
|
+
const prePruneTokens = getCurrentTokenUsage(state, output.messages);
|
|
12792
|
+
const candidateMessages = config.compress.candidates === true ? output.messages.slice() : void 0;
|
|
12793
|
+
prune(state, logger, config, output.messages);
|
|
12794
|
+
hideConsumedCompressCalls(state, output.messages);
|
|
12795
|
+
assignMessageRefs(state, output.messages);
|
|
12796
|
+
const compressionPriorities = buildPriorityMap(config, state, output.messages);
|
|
12797
|
+
prompts.reload();
|
|
12798
|
+
injectCompressNudges(
|
|
12799
|
+
state,
|
|
12800
|
+
config,
|
|
12801
|
+
logger,
|
|
12802
|
+
output.messages,
|
|
12803
|
+
prompts.getRuntimePrompts(),
|
|
12804
|
+
compressionPriorities,
|
|
12805
|
+
config.debug ? (text) => {
|
|
12806
|
+
logger.debug(`[ACP Debug] Nudge injected:
|
|
12807
|
+
${text}`);
|
|
12808
|
+
client.tui.showToast({
|
|
12809
|
+
body: {
|
|
12810
|
+
title: "ACP: Nudge Injected",
|
|
12811
|
+
message: text.slice(0, 500),
|
|
12812
|
+
variant: "info",
|
|
12813
|
+
duration: 5e3
|
|
12814
|
+
}
|
|
12815
|
+
}).catch(() => {
|
|
12816
|
+
});
|
|
12817
|
+
} : void 0,
|
|
12818
|
+
prePruneTokens,
|
|
12819
|
+
candidateMessages
|
|
12820
|
+
);
|
|
12821
|
+
truncateLargeToolOutputs(
|
|
12822
|
+
state,
|
|
12823
|
+
config,
|
|
12824
|
+
logger,
|
|
12825
|
+
output.messages.filter((message) => !isSyntheticMessage(message))
|
|
12826
|
+
);
|
|
12827
|
+
enforceContextBudget(state, config, logger, output.messages);
|
|
12828
|
+
injectMessageIds(state, config, output.messages, compressionPriorities);
|
|
12829
|
+
hideFailedCompressCalls(output.messages);
|
|
12830
|
+
stripStaleMetadata(output.messages);
|
|
12831
|
+
dropEmptyMessages(output.messages);
|
|
12832
|
+
const postTokens = getCurrentTokenUsage(state, output.messages);
|
|
12833
|
+
if (postTokens !== void 0 && effectiveLimit) {
|
|
12834
|
+
const budget = effectiveLimit.limit - (state.systemPromptTokens ?? 0) - OUTPUT_RESERVE_TOKENS;
|
|
12835
|
+
if (postTokens > budget) {
|
|
12836
|
+
logger.error(
|
|
12837
|
+
"ACP hard guard: context exceeds model budget after in-flight reduction",
|
|
12838
|
+
{
|
|
12839
|
+
session: state.sessionId,
|
|
12840
|
+
postTokens,
|
|
12841
|
+
budget,
|
|
12842
|
+
contextLimit: effectiveLimit.limit,
|
|
12843
|
+
contextLimitSource: effectiveLimit.source,
|
|
12844
|
+
hint: "request will likely be rejected; run /compact or start a new session"
|
|
12845
|
+
}
|
|
12846
|
+
);
|
|
12847
|
+
}
|
|
12848
|
+
}
|
|
12849
|
+
logger.info("Chat transform complete", {
|
|
12850
|
+
session: state.sessionId,
|
|
12851
|
+
model: state.modelID,
|
|
12852
|
+
messages: output.messages.length,
|
|
12853
|
+
prePruneTokens,
|
|
12854
|
+
postTokens,
|
|
12855
|
+
contextLimit: effectiveLimit?.limit,
|
|
12856
|
+
contextLimitSource: effectiveLimit?.source,
|
|
12857
|
+
usagePct: postTokens !== void 0 && effectiveLimit ? `${(postTokens / effectiveLimit.limit * 100).toFixed(1)}%` : void 0,
|
|
12858
|
+
nudged: state.nudges.shouldInjectThisTurn
|
|
12859
|
+
});
|
|
12860
|
+
if (state.sessionId) {
|
|
12861
|
+
await logger.saveContext(state.sessionId, output.messages);
|
|
12862
|
+
}
|
|
12888
12863
|
};
|
|
12889
12864
|
}
|
|
12890
12865
|
function buildHelpText() {
|
|
@@ -12991,21 +12966,16 @@ function createEventHandler(registry4, logger) {
|
|
|
12991
12966
|
durationMs
|
|
12992
12967
|
});
|
|
12993
12968
|
for (const state of registry4.all()) {
|
|
12994
|
-
|
|
12995
|
-
|
|
12969
|
+
const updates = applyPendingCompressionDurations(state);
|
|
12970
|
+
if (updates > 0) {
|
|
12971
|
+
await saveSessionState(state, logger);
|
|
12972
|
+
logger.info("Attached compression time to blocks", {
|
|
12973
|
+
messageID: part.messageID,
|
|
12974
|
+
callID: part.callID,
|
|
12975
|
+
blocks: updates,
|
|
12976
|
+
durationMs
|
|
12977
|
+
});
|
|
12996
12978
|
}
|
|
12997
|
-
await registry4.withSessionGuard(state.sessionId, async () => {
|
|
12998
|
-
const updates = applyPendingCompressionDurations(state);
|
|
12999
|
-
if (updates > 0) {
|
|
13000
|
-
await saveSessionState(state, logger);
|
|
13001
|
-
logger.info("Attached compression time to blocks", {
|
|
13002
|
-
messageID: part.messageID,
|
|
13003
|
-
callID: part.callID,
|
|
13004
|
-
blocks: updates,
|
|
13005
|
-
durationMs
|
|
13006
|
-
});
|
|
13007
|
-
}
|
|
13008
|
-
});
|
|
13009
12979
|
}
|
|
13010
12980
|
return;
|
|
13011
12981
|
}
|
|
@@ -13290,7 +13260,7 @@ var server = (async (ctx) => {
|
|
|
13290
13260
|
}
|
|
13291
13261
|
const logger = new Logger(config.debug, config.debug ? "debug" : config.logLevel);
|
|
13292
13262
|
logger.info("ACP plugin initialized", {
|
|
13293
|
-
version: true ? "1.18.1-pr.
|
|
13263
|
+
version: true ? "1.18.1-pr.409.166" : "dev",
|
|
13294
13264
|
workspace: ctx.directory,
|
|
13295
13265
|
logLevel: logger.level,
|
|
13296
13266
|
debug: config.debug,
|