opencode-acp 1.17.1-pr.393.148 → 1.17.1
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.d.ts.map +1 -1
- package/dist/index.js +236 -999
- package/dist/index.js.map +1 -1
- package/dist/lib/compress/range-utils.d.ts +1 -16
- package/dist/lib/compress/range-utils.d.ts.map +1 -1
- package/dist/lib/compress/range.d.ts.map +1 -1
- package/dist/lib/compress/search.d.ts +1 -3
- package/dist/lib/compress/search.d.ts.map +1 -1
- package/dist/lib/compress/status.d.ts +1 -1
- 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 +1 -7
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/messages/inject/inject.d.ts +1 -1
- package/dist/lib/messages/inject/inject.d.ts.map +1 -1
- package/dist/lib/messages/sync.d.ts +1 -1
- package/dist/lib/messages/sync.d.ts.map +1 -1
- package/dist/lib/prompts/compress-range.d.ts +1 -9
- package/dist/lib/prompts/compress-range.d.ts.map +1 -1
- package/dist/lib/prompts/context-limit-nudge.d.ts +0 -6
- package/dist/lib/prompts/context-limit-nudge.d.ts.map +1 -1
- package/dist/lib/prompts/iteration-nudge.d.ts +0 -5
- package/dist/lib/prompts/iteration-nudge.d.ts.map +1 -1
- package/dist/lib/prompts/store.d.ts +1 -2
- package/dist/lib/prompts/store.d.ts.map +1 -1
- package/dist/lib/prompts/system.d.ts +1 -10
- package/dist/lib/prompts/system.d.ts.map +1 -1
- package/dist/lib/prompts/turn-nudge.d.ts +0 -5
- package/dist/lib/prompts/turn-nudge.d.ts.map +1 -1
- package/dist/lib/state/rebuild.d.ts +0 -8
- package/dist/lib/state/rebuild.d.ts.map +1 -1
- package/dist/lib/state/state.d.ts.map +1 -1
- package/dist/lib/state/types.d.ts +0 -2
- package/dist/lib/state/types.d.ts.map +1 -1
- package/dist/lib/state/utils.d.ts +0 -1
- package/dist/lib/state/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/lib/messages/inject/candidates.d.ts +0 -30
- package/dist/lib/messages/inject/candidates.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -885,7 +885,6 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
885
885
|
"compress.permission",
|
|
886
886
|
"compress.showCompression",
|
|
887
887
|
"compress.summaryBuffer",
|
|
888
|
-
"compress.candidates",
|
|
889
888
|
"compress.maxContextLimit",
|
|
890
889
|
"compress.minContextLimit",
|
|
891
890
|
"compress.modelMaxLimits",
|
|
@@ -1760,7 +1759,6 @@ var defaultConfig = {
|
|
|
1760
1759
|
permission: "allow",
|
|
1761
1760
|
showCompression: true,
|
|
1762
1761
|
summaryBuffer: true,
|
|
1763
|
-
candidates: false,
|
|
1764
1762
|
maxContextLimit: "80%",
|
|
1765
1763
|
minContextLimit: "80%",
|
|
1766
1764
|
contextLimitFallback: 128e3,
|
|
@@ -1929,7 +1927,6 @@ function mergeCompress(base, override) {
|
|
|
1929
1927
|
permission: override.permission ?? base.permission,
|
|
1930
1928
|
showCompression: override.showCompression ?? base.showCompression,
|
|
1931
1929
|
summaryBuffer: override.summaryBuffer ?? base.summaryBuffer,
|
|
1932
|
-
candidates: override.candidates ?? base.candidates,
|
|
1933
1930
|
maxContextLimit: override.maxContextLimit ?? base.maxContextLimit,
|
|
1934
1931
|
minContextLimit: override.minContextLimit ?? base.minContextLimit,
|
|
1935
1932
|
modelMaxLimits: override.modelMaxLimits ?? base.modelMaxLimits,
|
|
@@ -2516,12 +2513,12 @@ function serializePruneMessagesState(messagesState) {
|
|
|
2516
2513
|
markedForCleanup: Array.from(messagesState.markedForCleanup)
|
|
2517
2514
|
};
|
|
2518
2515
|
}
|
|
2519
|
-
async function
|
|
2516
|
+
async function isSubAgentSession(client, sessionID) {
|
|
2520
2517
|
try {
|
|
2521
2518
|
const result = await client.session.get({ path: { id: sessionID } });
|
|
2522
|
-
return
|
|
2519
|
+
return !!result.data?.parentID;
|
|
2523
2520
|
} catch (error) {
|
|
2524
|
-
return
|
|
2521
|
+
return false;
|
|
2525
2522
|
}
|
|
2526
2523
|
}
|
|
2527
2524
|
function findLastCompactionTimestamp(messages) {
|
|
@@ -2562,8 +2559,7 @@ function createPruneMessagesState() {
|
|
|
2562
2559
|
activeByAnchorMessageId: /* @__PURE__ */ new Map(),
|
|
2563
2560
|
nextBlockId: 1,
|
|
2564
2561
|
nextRunId: 1,
|
|
2565
|
-
markedForCleanup: /* @__PURE__ */ new Set()
|
|
2566
|
-
membershipsVerified: false
|
|
2562
|
+
markedForCleanup: /* @__PURE__ */ new Set()
|
|
2567
2563
|
};
|
|
2568
2564
|
}
|
|
2569
2565
|
function loadPruneMessagesState(persisted) {
|
|
@@ -3695,7 +3691,7 @@ function clampMessageRef(requested, context, state) {
|
|
|
3695
3691
|
if (maxIndex < 0 || requested.index <= maxIndex) return null;
|
|
3696
3692
|
return { ref: formatMessageRef(maxIndex) };
|
|
3697
3693
|
}
|
|
3698
|
-
function resolveSelection(context, startReference, endReference
|
|
3694
|
+
function resolveSelection(context, startReference, endReference) {
|
|
3699
3695
|
const startRawIndex = startReference.rawIndex;
|
|
3700
3696
|
const endRawIndex = endReference.rawIndex;
|
|
3701
3697
|
const messageIds = [];
|
|
@@ -3718,7 +3714,7 @@ function resolveSelection(context, startReference, endReference, options) {
|
|
|
3718
3714
|
messageSeen.add(messageId);
|
|
3719
3715
|
messageIds.push(messageId);
|
|
3720
3716
|
}
|
|
3721
|
-
if (
|
|
3717
|
+
if (!messageTokenById.has(messageId)) {
|
|
3722
3718
|
messageTokenById.set(messageId, estimateAllMessageTokensFast(rawMessage));
|
|
3723
3719
|
}
|
|
3724
3720
|
const parts = Array.isArray(rawMessage.parts) ? rawMessage.parts : [];
|
|
@@ -3829,10 +3825,10 @@ function buildBoundaryLookup(context, state) {
|
|
|
3829
3825
|
}
|
|
3830
3826
|
return lookup;
|
|
3831
3827
|
}
|
|
3832
|
-
var SEARCH_CONTEXT_TOOL_DESCRIPTION = `Search through
|
|
3828
|
+
var SEARCH_CONTEXT_TOOL_DESCRIPTION = `Search through all compressed block summaries AND visible messages to find relevant content. Use this BEFORE decompressing to find the right block. Returns a hit list with block/message IDs, relevance scores, and previews.
|
|
3833
3829
|
|
|
3834
3830
|
Examples:
|
|
3835
|
-
- search_context({ query: "decoder accuracy" }) \u2014 find
|
|
3831
|
+
- search_context({ query: "decoder accuracy" }) \u2014 find blocks/messages about decoder accuracy
|
|
3836
3832
|
- search_context({ query: "training loss PPL" }) \u2014 find training results
|
|
3837
3833
|
- search_context({ query: "architecture design", limit: 5 }) \u2014 top 5 results`;
|
|
3838
3834
|
function countOccurrences(text, term) {
|
|
@@ -3863,7 +3859,7 @@ function createSearchContextTool(factoryCtx) {
|
|
|
3863
3859
|
query: tool.schema.string().describe("Search query \u2014 keywords or phrase to find"),
|
|
3864
3860
|
limit: tool.schema.number().optional().describe("Maximum results to return (default: 10)"),
|
|
3865
3861
|
deep: tool.schema.boolean().optional().describe(
|
|
3866
|
-
"
|
|
3862
|
+
"If true, also search visible (uncompressed) messages. Slower but more thorough (default: false)"
|
|
3867
3863
|
)
|
|
3868
3864
|
},
|
|
3869
3865
|
async execute(args, toolCtx) {
|
|
@@ -4315,7 +4311,7 @@ function validateArgs(args) {
|
|
|
4315
4311
|
}
|
|
4316
4312
|
}
|
|
4317
4313
|
}
|
|
4318
|
-
function resolveRanges(args, searchContext, state, logger
|
|
4314
|
+
function resolveRanges(args, searchContext, state, logger) {
|
|
4319
4315
|
return args.content.map((entry, index) => {
|
|
4320
4316
|
const normalizedEntry = {
|
|
4321
4317
|
topic: typeof entry.topic === "string" && entry.topic.trim().length > 0 ? entry.topic.trim() : void 0,
|
|
@@ -4330,7 +4326,7 @@ function resolveRanges(args, searchContext, state, logger, options) {
|
|
|
4330
4326
|
normalizedEntry.endId,
|
|
4331
4327
|
logger
|
|
4332
4328
|
);
|
|
4333
|
-
const selection = resolveSelection(searchContext, startReference, endReference
|
|
4329
|
+
const selection = resolveSelection(searchContext, startReference, endReference);
|
|
4334
4330
|
return {
|
|
4335
4331
|
index,
|
|
4336
4332
|
entry: normalizedEntry,
|
|
@@ -4363,54 +4359,6 @@ function validateNonOverlapping(plans) {
|
|
|
4363
4359
|
);
|
|
4364
4360
|
}
|
|
4365
4361
|
}
|
|
4366
|
-
function prepareExecutableRangePlans(args, searchContext, state, config, logger, options) {
|
|
4367
|
-
const normalizedArgs = "content" in args ? args : {
|
|
4368
|
-
content: [args]
|
|
4369
|
-
};
|
|
4370
|
-
const resolvedPlans = resolveRanges(normalizedArgs, searchContext, state, logger, options);
|
|
4371
|
-
validateNonOverlapping(resolvedPlans);
|
|
4372
|
-
const plans = resolvedPlans.map((plan) => ({
|
|
4373
|
-
...plan,
|
|
4374
|
-
selection: filterProtectedToolMessages(
|
|
4375
|
-
plan.selection,
|
|
4376
|
-
searchContext,
|
|
4377
|
-
config.compress.protectedTools,
|
|
4378
|
-
config.protectedFilePatterns
|
|
4379
|
-
)
|
|
4380
|
-
})).map((plan) => ({
|
|
4381
|
-
...plan,
|
|
4382
|
-
selection: filterLastUserMessage(plan.selection, searchContext, state, config.compress)
|
|
4383
|
-
})).map((plan) => ({
|
|
4384
|
-
...plan,
|
|
4385
|
-
selection: filterProtectedRecentMessages(
|
|
4386
|
-
plan.selection,
|
|
4387
|
-
searchContext,
|
|
4388
|
-
state,
|
|
4389
|
-
config.compress
|
|
4390
|
-
)
|
|
4391
|
-
})).filter((plan) => plan.selection.messageIds.length > 0);
|
|
4392
|
-
if (plans.length === 0) {
|
|
4393
|
-
throw new Error(
|
|
4394
|
-
"All selected messages were filtered out (protected tool outputs and/or the last user message). They must remain in visible context."
|
|
4395
|
-
);
|
|
4396
|
-
}
|
|
4397
|
-
const counted = /* @__PURE__ */ new Set();
|
|
4398
|
-
let totalChars = 0;
|
|
4399
|
-
for (const plan of plans) {
|
|
4400
|
-
for (const messageId of plan.selection.messageIds) {
|
|
4401
|
-
if (counted.has(messageId)) continue;
|
|
4402
|
-
counted.add(messageId);
|
|
4403
|
-
const rawMessage = searchContext.rawMessagesById.get(messageId);
|
|
4404
|
-
if (rawMessage) totalChars += countMessageCharacters(rawMessage);
|
|
4405
|
-
}
|
|
4406
|
-
}
|
|
4407
|
-
if (config.compress.minCompressRange > 0 && totalChars < config.compress.minCompressRange) {
|
|
4408
|
-
throw new Error(
|
|
4409
|
-
`Range too small (${totalChars} chars, min ${config.compress.minCompressRange}). Not worth compressing \u2014 overhead exceeds savings.`
|
|
4410
|
-
);
|
|
4411
|
-
}
|
|
4412
|
-
return { plans, totalChars };
|
|
4413
|
-
}
|
|
4414
4362
|
function parseBlockPlaceholders(summary) {
|
|
4415
4363
|
const placeholders = [];
|
|
4416
4364
|
const regex = new RegExp(BLOCK_PLACEHOLDER_REGEX);
|
|
@@ -4482,7 +4430,6 @@ function appendMissingBlockSummaries(summary, _missingBlockIds, _summaryByBlockI
|
|
|
4482
4430
|
}
|
|
4483
4431
|
|
|
4484
4432
|
// lib/state/rebuild.ts
|
|
4485
|
-
import { createHash } from "crypto";
|
|
4486
4433
|
function collectCompressInvocations(messages) {
|
|
4487
4434
|
const invocations = [];
|
|
4488
4435
|
for (const message of messages) {
|
|
@@ -4534,128 +4481,6 @@ function dedupeBlockIds(ids) {
|
|
|
4534
4481
|
}
|
|
4535
4482
|
return result;
|
|
4536
4483
|
}
|
|
4537
|
-
function fingerprintMessage(message) {
|
|
4538
|
-
const parts = (message.parts ?? []).map((part) => {
|
|
4539
|
-
if (part.type === "text") {
|
|
4540
|
-
return { type: "text", text: part.text };
|
|
4541
|
-
}
|
|
4542
|
-
if (part.type === "tool") {
|
|
4543
|
-
if (part.tool === "compress") {
|
|
4544
|
-
return { type: "tool", tool: part.tool, status: part.state?.status };
|
|
4545
|
-
}
|
|
4546
|
-
return {
|
|
4547
|
-
type: "tool",
|
|
4548
|
-
tool: part.tool,
|
|
4549
|
-
status: part.state?.status,
|
|
4550
|
-
input: part.state?.input,
|
|
4551
|
-
output: part.state?.status === "completed" ? part.state.output : void 0
|
|
4552
|
-
};
|
|
4553
|
-
}
|
|
4554
|
-
return { type: part.type };
|
|
4555
|
-
});
|
|
4556
|
-
return createHash("sha256").update(JSON.stringify({ role: message.info.role, parts })).digest("hex");
|
|
4557
|
-
}
|
|
4558
|
-
function mapForkIds(state, parent, parentMessages, forkMessages) {
|
|
4559
|
-
const parentRefs = parent.messageIds?.byRef;
|
|
4560
|
-
if (!parentRefs) return null;
|
|
4561
|
-
const parentById = new Map(parentMessages.map((message) => [message.info.id, message]));
|
|
4562
|
-
const forkById = new Map(forkMessages.map((message) => [message.info.id, message]));
|
|
4563
|
-
const messages = /* @__PURE__ */ new Map();
|
|
4564
|
-
const tools = /* @__PURE__ */ new Map();
|
|
4565
|
-
for (const [ref, parentId] of Object.entries(parentRefs)) {
|
|
4566
|
-
const forkId = state.messageIds.byRef.get(ref);
|
|
4567
|
-
if (!forkId) continue;
|
|
4568
|
-
const parentMessage = parentById.get(parentId);
|
|
4569
|
-
const forkMessage = forkById.get(forkId);
|
|
4570
|
-
if (!parentMessage || !forkMessage) continue;
|
|
4571
|
-
if (fingerprintMessage(parentMessage) !== fingerprintMessage(forkMessage)) continue;
|
|
4572
|
-
messages.set(parentId, forkId);
|
|
4573
|
-
for (let index = 0; index < parentMessage.parts.length; index++) {
|
|
4574
|
-
const parentPart = parentMessage.parts[index];
|
|
4575
|
-
const forkPart = forkMessage.parts[index];
|
|
4576
|
-
if (parentPart?.type === "tool" && typeof parentPart.callID === "string" && forkPart?.type === "tool" && forkPart.tool === parentPart.tool && typeof forkPart.callID === "string") {
|
|
4577
|
-
tools.set(parentPart.callID, forkPart.callID);
|
|
4578
|
-
}
|
|
4579
|
-
}
|
|
4580
|
-
}
|
|
4581
|
-
return { messages, tools };
|
|
4582
|
-
}
|
|
4583
|
-
function translateIds(ids, mapped) {
|
|
4584
|
-
const translated = ids.map((id) => mapped.get(id));
|
|
4585
|
-
return translated.some((id) => !id) ? null : translated;
|
|
4586
|
-
}
|
|
4587
|
-
function restoreForkCompressionState(state, forkMessages, parent, parentMessages, logger) {
|
|
4588
|
-
if (!parent.prune.messages || !parent.messageIds) return 0;
|
|
4589
|
-
assignMessageRefs(state, forkMessages);
|
|
4590
|
-
const mapped = mapForkIds(state, parent, parentMessages, forkMessages);
|
|
4591
|
-
if (!mapped) return 0;
|
|
4592
|
-
const parentBlocks = Object.values(parent.prune.messages.blocksById);
|
|
4593
|
-
const translatedBlocks = /* @__PURE__ */ new Map();
|
|
4594
|
-
for (const block of parentBlocks) {
|
|
4595
|
-
const anchorMessageId = mapped.messages.get(block.anchorMessageId);
|
|
4596
|
-
const compressMessageId = mapped.messages.get(block.compressMessageId);
|
|
4597
|
-
const directMessageIds = translateIds(block.directMessageIds, mapped.messages);
|
|
4598
|
-
const effectiveMessageIds = translateIds(block.effectiveMessageIds, mapped.messages);
|
|
4599
|
-
const directToolIds = translateIds(block.directToolIds, mapped.tools);
|
|
4600
|
-
const effectiveToolIds = translateIds(block.effectiveToolIds, mapped.tools);
|
|
4601
|
-
const compressCallId = block.compressCallId ? mapped.tools.get(block.compressCallId) : void 0;
|
|
4602
|
-
if (!anchorMessageId || !compressMessageId || !directMessageIds || !effectiveMessageIds || !directToolIds || !effectiveToolIds || block.compressCallId && !compressCallId) {
|
|
4603
|
-
continue;
|
|
4604
|
-
}
|
|
4605
|
-
translatedBlocks.set(block.blockId, {
|
|
4606
|
-
...block,
|
|
4607
|
-
anchorMessageId,
|
|
4608
|
-
compressMessageId,
|
|
4609
|
-
compressCallId,
|
|
4610
|
-
directMessageIds,
|
|
4611
|
-
directToolIds,
|
|
4612
|
-
effectiveMessageIds,
|
|
4613
|
-
effectiveToolIds
|
|
4614
|
-
});
|
|
4615
|
-
}
|
|
4616
|
-
const activeParentIds = new Set(parent.prune.messages.activeBlockIds);
|
|
4617
|
-
if (activeParentIds.size === 0 || Array.from(activeParentIds).some((blockId) => !translatedBlocks.has(blockId))) {
|
|
4618
|
-
return 0;
|
|
4619
|
-
}
|
|
4620
|
-
const copiedBlockIds = new Set(translatedBlocks.keys());
|
|
4621
|
-
for (const block of translatedBlocks.values()) {
|
|
4622
|
-
if (block.active && [...block.consumedBlockIds, ...block.includedBlockIds].some(
|
|
4623
|
-
(blockId) => !copiedBlockIds.has(blockId)
|
|
4624
|
-
)) {
|
|
4625
|
-
return 0;
|
|
4626
|
-
}
|
|
4627
|
-
}
|
|
4628
|
-
const messagesState = createPruneMessagesState();
|
|
4629
|
-
for (const block of translatedBlocks.values()) {
|
|
4630
|
-
messagesState.blocksById.set(block.blockId, block);
|
|
4631
|
-
if (block.active) {
|
|
4632
|
-
messagesState.activeBlockIds.add(block.blockId);
|
|
4633
|
-
messagesState.activeByAnchorMessageId.set(block.anchorMessageId, block.blockId);
|
|
4634
|
-
}
|
|
4635
|
-
}
|
|
4636
|
-
for (const [parentMessageId, entry] of Object.entries(parent.prune.messages.byMessageId)) {
|
|
4637
|
-
const forkMessageId = mapped.messages.get(parentMessageId);
|
|
4638
|
-
if (!forkMessageId) continue;
|
|
4639
|
-
const allBlockIds = entry.allBlockIds.filter((blockId) => copiedBlockIds.has(blockId));
|
|
4640
|
-
if (allBlockIds.length === 0) continue;
|
|
4641
|
-
messagesState.byMessageId.set(forkMessageId, {
|
|
4642
|
-
tokenCount: entry.tokenCount,
|
|
4643
|
-
allBlockIds,
|
|
4644
|
-
activeBlockIds: allBlockIds.filter(
|
|
4645
|
-
(blockId) => messagesState.activeBlockIds.has(blockId)
|
|
4646
|
-
)
|
|
4647
|
-
});
|
|
4648
|
-
}
|
|
4649
|
-
messagesState.nextBlockId = Math.max(parent.prune.messages.nextBlockId, ...copiedBlockIds) + 1;
|
|
4650
|
-
messagesState.nextRunId = parent.prune.messages.nextRunId;
|
|
4651
|
-
messagesState.membershipsVerified = true;
|
|
4652
|
-
state.prune.messages = messagesState;
|
|
4653
|
-
logger.info("fork: restored compression state from parent", {
|
|
4654
|
-
blocks: copiedBlockIds.size,
|
|
4655
|
-
activeBlocks: messagesState.activeBlockIds.size
|
|
4656
|
-
});
|
|
4657
|
-
return copiedBlockIds.size;
|
|
4658
|
-
}
|
|
4659
4484
|
function rebuildRangeInvocation(state, input, searchContext, invocation, protectedTools, protectedFilePatterns, gcConfig, logger) {
|
|
4660
4485
|
const plans = resolveRanges(input, searchContext, state);
|
|
4661
4486
|
const runId = allocateRunId(state);
|
|
@@ -4722,7 +4547,12 @@ function resolveMessageEntry(entry, searchContext, state) {
|
|
|
4722
4547
|
return null;
|
|
4723
4548
|
}
|
|
4724
4549
|
try {
|
|
4725
|
-
const { startReference, endReference } = resolveBoundaryIds(
|
|
4550
|
+
const { startReference, endReference } = resolveBoundaryIds(
|
|
4551
|
+
searchContext,
|
|
4552
|
+
state,
|
|
4553
|
+
ref,
|
|
4554
|
+
ref
|
|
4555
|
+
);
|
|
4726
4556
|
const selection = resolveSelection(searchContext, startReference, endReference);
|
|
4727
4557
|
return {
|
|
4728
4558
|
selection,
|
|
@@ -5026,9 +4856,8 @@ async function ensureSessionInitialized(client, state, sessionId, logger, messag
|
|
|
5026
4856
|
resetSessionState(state);
|
|
5027
4857
|
state.sessionId = sessionId;
|
|
5028
4858
|
state.storageDir = config?.storagePath ? resolveStorageDir(config.storagePath, projectDir ?? cwd()) : void 0;
|
|
5029
|
-
const
|
|
5030
|
-
|
|
5031
|
-
state.isSubAgent = isChildSession;
|
|
4859
|
+
const isSubAgent = await isSubAgentSession(client, sessionId);
|
|
4860
|
+
state.isSubAgent = isSubAgent;
|
|
5032
4861
|
state.lastCompaction = findLastCompactionTimestamp(messages);
|
|
5033
4862
|
state.currentTurn = countTurns(state, messages);
|
|
5034
4863
|
state.nudges.turnNudgeAnchors = collectTurnNudgeAnchors(messages);
|
|
@@ -5042,42 +4871,13 @@ async function ensureSessionInitialized(client, state, sessionId, logger, messag
|
|
|
5042
4871
|
);
|
|
5043
4872
|
}
|
|
5044
4873
|
if (config) {
|
|
5045
|
-
|
|
5046
|
-
if (
|
|
5047
|
-
try {
|
|
5048
|
-
const parent = await loadSessionState(parentSessionId, logger);
|
|
5049
|
-
const response = parent ? await client.session.messages({ path: { id: parentSessionId } }) : void 0;
|
|
5050
|
-
const parentMessages = Array.isArray(response?.data) ? response.data : Array.isArray(response) ? response : [];
|
|
5051
|
-
if (parent && parentMessages.length > 0) {
|
|
5052
|
-
state.isSubAgent = false;
|
|
5053
|
-
try {
|
|
5054
|
-
restored = restoreForkCompressionState(
|
|
5055
|
-
state,
|
|
5056
|
-
messages,
|
|
5057
|
-
parent,
|
|
5058
|
-
parentMessages,
|
|
5059
|
-
logger
|
|
5060
|
-
);
|
|
5061
|
-
} finally {
|
|
5062
|
-
state.isSubAgent = isChildSession;
|
|
5063
|
-
}
|
|
5064
|
-
}
|
|
5065
|
-
} catch (error) {
|
|
5066
|
-
logger.warn("fork: parent state transfer unavailable, replaying history", {
|
|
5067
|
-
parentSessionId,
|
|
5068
|
-
error: error?.message
|
|
5069
|
-
});
|
|
5070
|
-
}
|
|
5071
|
-
}
|
|
5072
|
-
const rebuilt = restored > 0 ? 0 : rebuildCompressionState(state, messages, config, logger);
|
|
5073
|
-
if (restored > 0 || rebuilt > 0) {
|
|
4874
|
+
const rebuilt = rebuildCompressionState(state, messages, config, logger);
|
|
4875
|
+
if (rebuilt > 0) {
|
|
5074
4876
|
await saveSessionState(state, logger);
|
|
5075
4877
|
}
|
|
5076
4878
|
}
|
|
5077
|
-
state.isSubAgent = isChildSession;
|
|
5078
4879
|
return;
|
|
5079
4880
|
}
|
|
5080
|
-
state.isSubAgent = isChildSession;
|
|
5081
4881
|
state.prune.messages = loadPruneMessagesState(persisted.prune.messages);
|
|
5082
4882
|
state.nudges.contextLimitAnchors = new Set(persisted.nudges.contextLimitAnchors || []);
|
|
5083
4883
|
state.nudges.turnNudgeAnchors = /* @__PURE__ */ new Set([
|
|
@@ -6788,12 +6588,12 @@ ${afterClose}`;
|
|
|
6788
6588
|
}
|
|
6789
6589
|
|
|
6790
6590
|
// lib/messages/utils.ts
|
|
6791
|
-
import { createHash
|
|
6591
|
+
import { createHash } from "crypto";
|
|
6792
6592
|
var SUMMARY_ID_HASH_LENGTH = 16;
|
|
6793
6593
|
var DCP_PAIRED_TAG_REGEX = /<(?:dcp|acp)[^>]*>[\s\S]*?<\/(?:dcp|acp)[^>]*>/gi;
|
|
6794
6594
|
var DCP_UNPAIRED_TAG_REGEX = /<\/?(?:dcp|acp)[^>]*>/gi;
|
|
6795
6595
|
var generateStableId = (prefix, seed) => {
|
|
6796
|
-
const hash =
|
|
6596
|
+
const hash = createHash("sha256").update(seed).digest("hex").slice(0, SUMMARY_ID_HASH_LENGTH);
|
|
6797
6597
|
return `${prefix}_${hash}`;
|
|
6798
6598
|
};
|
|
6799
6599
|
var createSyntheticMessage = (baseMessage, content, stableSeed, role = "user") => {
|
|
@@ -7790,13 +7590,58 @@ function createCompressRangeTool(factoryCtx) {
|
|
|
7790
7590
|
...ctx0,
|
|
7791
7591
|
config: applyCompressOverrides(ctx0.config, providerId, modelId)
|
|
7792
7592
|
};
|
|
7793
|
-
const
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
|
|
7799
|
-
|
|
7593
|
+
const resolvedPlans = resolveRanges(input, searchContext, ctx.state, ctx.logger);
|
|
7594
|
+
validateNonOverlapping(resolvedPlans);
|
|
7595
|
+
const filteredPlans = resolvedPlans.map((plan) => ({
|
|
7596
|
+
...plan,
|
|
7597
|
+
selection: filterProtectedToolMessages(
|
|
7598
|
+
plan.selection,
|
|
7599
|
+
searchContext,
|
|
7600
|
+
ctx.config.compress.protectedTools,
|
|
7601
|
+
ctx.config.protectedFilePatterns
|
|
7602
|
+
)
|
|
7603
|
+
})).map((plan) => ({
|
|
7604
|
+
...plan,
|
|
7605
|
+
selection: filterLastUserMessage(
|
|
7606
|
+
plan.selection,
|
|
7607
|
+
searchContext,
|
|
7608
|
+
ctx.state,
|
|
7609
|
+
ctx.config.compress
|
|
7610
|
+
)
|
|
7611
|
+
})).map((plan) => ({
|
|
7612
|
+
...plan,
|
|
7613
|
+
selection: filterProtectedRecentMessages(
|
|
7614
|
+
plan.selection,
|
|
7615
|
+
searchContext,
|
|
7616
|
+
ctx.state,
|
|
7617
|
+
ctx.config.compress
|
|
7618
|
+
)
|
|
7619
|
+
})).filter((plan) => plan.selection.messageIds.length > 0);
|
|
7620
|
+
if (filteredPlans.length === 0) {
|
|
7621
|
+
throw new Error(
|
|
7622
|
+
"All selected messages were filtered out (protected tool outputs and/or the last user message). They must remain in visible context."
|
|
7623
|
+
);
|
|
7624
|
+
}
|
|
7625
|
+
const minCompressRange = ctx.config.compress.minCompressRange;
|
|
7626
|
+
if (minCompressRange > 0) {
|
|
7627
|
+
let totalChars = 0;
|
|
7628
|
+
const counted = /* @__PURE__ */ new Set();
|
|
7629
|
+
for (const plan of filteredPlans) {
|
|
7630
|
+
for (const messageId of plan.selection.messageIds) {
|
|
7631
|
+
if (counted.has(messageId)) continue;
|
|
7632
|
+
counted.add(messageId);
|
|
7633
|
+
const rawMessage = searchContext.rawMessagesById.get(messageId);
|
|
7634
|
+
if (rawMessage) {
|
|
7635
|
+
totalChars += countMessageCharacters(rawMessage);
|
|
7636
|
+
}
|
|
7637
|
+
}
|
|
7638
|
+
}
|
|
7639
|
+
if (totalChars < minCompressRange) {
|
|
7640
|
+
throw new Error(
|
|
7641
|
+
`Range too small (${totalChars} chars, min ${minCompressRange}). Not worth compressing \u2014 overhead exceeds savings.`
|
|
7642
|
+
);
|
|
7643
|
+
}
|
|
7644
|
+
}
|
|
7800
7645
|
const notifications = [];
|
|
7801
7646
|
let preparedPlans = [];
|
|
7802
7647
|
let totalCompressedMessages = 0;
|
|
@@ -7901,9 +7746,7 @@ function createCompressRangeTool(factoryCtx) {
|
|
|
7901
7746
|
const bypassQuality = acknowledgeRisk && ctx.state.qualityGateRetryPending;
|
|
7902
7747
|
const ignoredAcknowledgeRisk = acknowledgeRisk && !ctx.state.qualityGateRetryPending;
|
|
7903
7748
|
if (ignoredAcknowledgeRisk) {
|
|
7904
|
-
ctx.logger.warn(
|
|
7905
|
-
"compress: acknowledgeRisk ignored \u2014 no quality gate rejection pending"
|
|
7906
|
-
);
|
|
7749
|
+
ctx.logger.warn("compress: acknowledgeRisk ignored \u2014 no quality gate rejection pending");
|
|
7907
7750
|
}
|
|
7908
7751
|
ctx.state.qualityGateRetryPending = false;
|
|
7909
7752
|
if (!bypassQuality) {
|
|
@@ -8073,24 +7916,10 @@ function sortBlocksByCreation(a, b) {
|
|
|
8073
7916
|
}
|
|
8074
7917
|
return a.blockId - b.blockId;
|
|
8075
7918
|
}
|
|
8076
|
-
function sameBlockIds(left, right) {
|
|
8077
|
-
if (left.size !== right.size) return false;
|
|
8078
|
-
return Array.from(left).every((id) => right.has(id));
|
|
8079
|
-
}
|
|
8080
7919
|
var syncCompressionBlocks = (state, logger, messages) => {
|
|
8081
7920
|
const messagesState = state.prune.messages;
|
|
8082
7921
|
if (!messagesState?.blocksById?.size) {
|
|
8083
|
-
|
|
8084
|
-
messagesState.activeBlockIds.clear();
|
|
8085
|
-
messagesState.activeByAnchorMessageId.clear();
|
|
8086
|
-
for (const entry of messagesState.byMessageId.values()) {
|
|
8087
|
-
entry.allBlockIds = Array.isArray(entry.allBlockIds) ? [...new Set(entry.allBlockIds.filter((id) => Number.isInteger(id) && id > 0))] : [];
|
|
8088
|
-
entry.activeBlockIds = [];
|
|
8089
|
-
}
|
|
8090
|
-
messagesState.membershipsVerified = true;
|
|
8091
|
-
return true;
|
|
8092
|
-
}
|
|
8093
|
-
return false;
|
|
7922
|
+
return;
|
|
8094
7923
|
}
|
|
8095
7924
|
const messageIds = new Set(messages.map((msg) => msg.info.id));
|
|
8096
7925
|
const structureVersion = messagesState.structureVersion ?? 0;
|
|
@@ -8108,12 +7937,11 @@ var syncCompressionBlocks = (state, logger, messages) => {
|
|
|
8108
7937
|
previous.set(anchor, id);
|
|
8109
7938
|
}
|
|
8110
7939
|
}
|
|
8111
|
-
return
|
|
7940
|
+
return;
|
|
8112
7941
|
}
|
|
8113
7942
|
const previousActiveBlockIds = new Set(
|
|
8114
7943
|
Array.from(messagesState.blocksById.values()).filter((block) => block.active).map((block) => block.blockId)
|
|
8115
7944
|
);
|
|
8116
|
-
const indexedActiveBlockIds = new Set(messagesState.activeBlockIds);
|
|
8117
7945
|
messagesState.activeBlockIds.clear();
|
|
8118
7946
|
messagesState.activeByAnchorMessageId.clear();
|
|
8119
7947
|
const now = Date.now();
|
|
@@ -8153,14 +7981,10 @@ var syncCompressionBlocks = (state, logger, messages) => {
|
|
|
8153
7981
|
messagesState.activeByAnchorMessageId.set(block.anchorMessageId, block.blockId);
|
|
8154
7982
|
}
|
|
8155
7983
|
}
|
|
8156
|
-
const
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
entry.allBlockIds = allBlockIds;
|
|
8161
|
-
entry.activeBlockIds = allBlockIds.filter((id) => messagesState.activeBlockIds.has(id));
|
|
8162
|
-
}
|
|
8163
|
-
messagesState.membershipsVerified = true;
|
|
7984
|
+
for (const entry of messagesState.byMessageId.values()) {
|
|
7985
|
+
const allBlockIds = Array.isArray(entry.allBlockIds) ? [...new Set(entry.allBlockIds.filter((id) => Number.isInteger(id) && id > 0))] : [];
|
|
7986
|
+
entry.allBlockIds = allBlockIds;
|
|
7987
|
+
entry.activeBlockIds = allBlockIds.filter((id) => messagesState.activeBlockIds.has(id));
|
|
8164
7988
|
}
|
|
8165
7989
|
const nextActiveBlockIds = messagesState.activeBlockIds;
|
|
8166
7990
|
let deactivatedCount = 0;
|
|
@@ -8182,7 +8006,6 @@ var syncCompressionBlocks = (state, logger, messages) => {
|
|
|
8182
8006
|
});
|
|
8183
8007
|
}
|
|
8184
8008
|
messagesState.lastSyncedStructureVersion = structureVersion;
|
|
8185
|
-
return membershipsRebuilt || deactivatedCount > 0 || reactivatedCount > 0;
|
|
8186
8009
|
};
|
|
8187
8010
|
|
|
8188
8011
|
// lib/host-permissions.ts
|
|
@@ -8257,484 +8080,6 @@ var syncCompressPermissionState = (state, config, hostPermissions, messages) =>
|
|
|
8257
8080
|
);
|
|
8258
8081
|
};
|
|
8259
8082
|
|
|
8260
|
-
// lib/prompts/context-limit-nudge.ts
|
|
8261
|
-
var CONTEXT_LIMIT_NUDGE = `
|
|
8262
|
-
<system-reminder>
|
|
8263
|
-
\u26A0\uFE0F Context limit reached \u2014 time to compress the largest ranges you no longer need. Prioritize completed tool outputs and resolved work. You can decompress specific blocks later if you need details. Keeping context lean helps you stay accurate.
|
|
8264
|
-
|
|
8265
|
-
If mid-atomic-operation, finish that step first, then compress.
|
|
8266
|
-
|
|
8267
|
-
HOW TO CALL COMPRESS:
|
|
8268
|
-
{
|
|
8269
|
-
"topic": "Short Label",
|
|
8270
|
-
"content": [
|
|
8271
|
-
{
|
|
8272
|
-
"startId": "<ID from early in this conversation>",
|
|
8273
|
-
"endId": "<ID from later in this conversation>",
|
|
8274
|
-
"summary": "Complete technical summary of everything in the range"
|
|
8275
|
-
}
|
|
8276
|
-
]
|
|
8277
|
-
}
|
|
8278
|
-
|
|
8279
|
-
\u26A0\uFE0F ID RULES \u2014 MOST COMMON CAUSE OF ERRORS:
|
|
8280
|
-
- ONLY use IDs you can see in tags in the messages ABOVE.
|
|
8281
|
-
- Do NOT copy IDs from this example. Do NOT invent IDs.
|
|
8282
|
-
- Do NOT use IDs from compressed block summaries \u2014 they are stale.
|
|
8283
|
-
- startId must appear BEFORE endId in the conversation.
|
|
8284
|
-
|
|
8285
|
-
RANGE STRATEGY:
|
|
8286
|
-
- Prefer one large range over multiple small ones.
|
|
8287
|
-
- Compress OLDER resolved history first. Keep recent active work.
|
|
8288
|
-
</system-reminder>
|
|
8289
|
-
`;
|
|
8290
|
-
var CANDIDATE_GUIDANCE = `
|
|
8291
|
-
<system-reminder>
|
|
8292
|
-
COMPRESSION CANDIDATES:
|
|
8293
|
-
- MICRO identifies one large message or complete tool transaction.
|
|
8294
|
-
- EPISODE identifies a contiguous historical segment made from smaller units.
|
|
8295
|
-
- Candidate entries are independent and non-overlapping, so they can be batched in one \`content[]\` array.
|
|
8296
|
-
- Candidates are suggestions, not mandatory targets. Choose only content no longer needed for the current task and do not invent a target when none is listed.
|
|
8297
|
-
- Use \`acp_status\` for a fresh candidate view if the list is stale or missing.
|
|
8298
|
-
- When the context limit is reached and candidates are listed, select at least one clearly stale candidate and call the \`compress\` tool in your next reply. Batch only additional candidates that are also clearly stale. Do not merely recommend compression.
|
|
8299
|
-
</system-reminder>
|
|
8300
|
-
`;
|
|
8301
|
-
|
|
8302
|
-
// lib/prompts/turn-nudge.ts
|
|
8303
|
-
var TURN_NUDGE = `
|
|
8304
|
-
<system-reminder>
|
|
8305
|
-
Context is getting full. If you've finished reading tool outputs or exploration results, compress them \u2014 you can decompress later if needed. This keeps your focus on the current task and improves accuracy.
|
|
8306
|
-
|
|
8307
|
-
{
|
|
8308
|
-
"topic": "Short Label",
|
|
8309
|
-
"content": [{ "startId": "<visible message ID>", "endId": "<visible message ID>", "summary": "..." }]
|
|
8310
|
-
}
|
|
8311
|
-
|
|
8312
|
-
\u26A0\uFE0F ONLY use IDs from tags visible above. Do NOT invent or copy example IDs.
|
|
8313
|
-
</system-reminder>
|
|
8314
|
-
`;
|
|
8315
|
-
var TURN_CANDIDATE_GUIDANCE = `
|
|
8316
|
-
MICRO candidates are complete large messages or tool transactions. EPISODE candidates are contiguous historical segments. They are independent suggestions and may be batched, but compress only content no longer needed for the current task. Do not compress active work or every candidate.
|
|
8317
|
-
`;
|
|
8318
|
-
|
|
8319
|
-
// lib/prompts/iteration-nudge.ts
|
|
8320
|
-
var ITERATION_NUDGE = `
|
|
8321
|
-
<system-reminder>
|
|
8322
|
-
You've been iterating for a while. If any earlier work is closed and unlikely to be referenced, compress it now.
|
|
8323
|
-
|
|
8324
|
-
{
|
|
8325
|
-
"topic": "Short Label",
|
|
8326
|
-
"content": [{ "startId": "<visible message ID>", "endId": "<visible message ID>", "summary": "..." }]
|
|
8327
|
-
}
|
|
8328
|
-
|
|
8329
|
-
\u26A0\uFE0F ONLY use IDs from tags visible above. Do NOT invent or copy example IDs.
|
|
8330
|
-
</system-reminder>
|
|
8331
|
-
`;
|
|
8332
|
-
var ITERATION_CANDIDATE_GUIDANCE = `
|
|
8333
|
-
MICRO candidates are complete large messages or tool transactions. EPISODE candidates are contiguous historical segments. They are independent suggestions and may be batched, but preserve anything still needed for the current task. Do not compress active work or every candidate.
|
|
8334
|
-
`;
|
|
8335
|
-
|
|
8336
|
-
// lib/messages/inject/candidates.ts
|
|
8337
|
-
function partToolNames(message) {
|
|
8338
|
-
const names = /* @__PURE__ */ new Set();
|
|
8339
|
-
for (const part of message.parts ?? []) {
|
|
8340
|
-
if (part.type === "tool" && part.tool !== "compress") {
|
|
8341
|
-
names.add(part.tool);
|
|
8342
|
-
}
|
|
8343
|
-
}
|
|
8344
|
-
return [...names];
|
|
8345
|
-
}
|
|
8346
|
-
function hasNonCompressTool(message) {
|
|
8347
|
-
return partToolNames(message).length > 0;
|
|
8348
|
-
}
|
|
8349
|
-
function collectToolSpans(messages) {
|
|
8350
|
-
const spansByCallId = /* @__PURE__ */ new Map();
|
|
8351
|
-
for (let index = 0; index < messages.length; index++) {
|
|
8352
|
-
const message = messages[index];
|
|
8353
|
-
if (!message) continue;
|
|
8354
|
-
const callIds = /* @__PURE__ */ new Set();
|
|
8355
|
-
for (const part of message.parts ?? []) {
|
|
8356
|
-
if (part.type !== "tool" || part.tool === "compress" || !part.callID) continue;
|
|
8357
|
-
callIds.add(part.callID);
|
|
8358
|
-
}
|
|
8359
|
-
for (const callID of callIds) {
|
|
8360
|
-
const existing = spansByCallId.get(callID);
|
|
8361
|
-
if (existing) {
|
|
8362
|
-
existing.endIndex = index;
|
|
8363
|
-
} else {
|
|
8364
|
-
spansByCallId.set(callID, { startIndex: index, endIndex: index });
|
|
8365
|
-
}
|
|
8366
|
-
}
|
|
8367
|
-
}
|
|
8368
|
-
return [...spansByCallId.values()].sort(
|
|
8369
|
-
(left, right) => left.startIndex - right.startIndex || left.endIndex - right.endIndex
|
|
8370
|
-
);
|
|
8371
|
-
}
|
|
8372
|
-
function mergeOverlappingSpans(messages, spans) {
|
|
8373
|
-
const merged = [];
|
|
8374
|
-
for (const span of spans) {
|
|
8375
|
-
const last = merged[merged.length - 1];
|
|
8376
|
-
if (last && span.startIndex <= last.endIndex) {
|
|
8377
|
-
last.endIndex = Math.max(last.endIndex, span.endIndex);
|
|
8378
|
-
} else {
|
|
8379
|
-
merged.push({ ...span });
|
|
8380
|
-
}
|
|
8381
|
-
}
|
|
8382
|
-
const result = [];
|
|
8383
|
-
let spanIndex = 0;
|
|
8384
|
-
let index = 0;
|
|
8385
|
-
while (index < messages.length) {
|
|
8386
|
-
while (spanIndex < merged.length && merged[spanIndex].endIndex < index) {
|
|
8387
|
-
spanIndex++;
|
|
8388
|
-
}
|
|
8389
|
-
const span = merged[spanIndex];
|
|
8390
|
-
if (span?.startIndex === index) {
|
|
8391
|
-
result.push(span);
|
|
8392
|
-
index = span.endIndex + 1;
|
|
8393
|
-
continue;
|
|
8394
|
-
}
|
|
8395
|
-
result.push({ startIndex: index, endIndex: index });
|
|
8396
|
-
index++;
|
|
8397
|
-
}
|
|
8398
|
-
return result;
|
|
8399
|
-
}
|
|
8400
|
-
function buildAtomicUnits(messages, state) {
|
|
8401
|
-
const omissions = [];
|
|
8402
|
-
const spans = mergeOverlappingSpans(messages, collectToolSpans(messages));
|
|
8403
|
-
const units = [];
|
|
8404
|
-
for (const span of spans) {
|
|
8405
|
-
const source = messages.slice(span.startIndex, span.endIndex + 1);
|
|
8406
|
-
const refs = source.map((message) => state.messageIds.byRawId.get(message.info.id));
|
|
8407
|
-
const startRef = refs[0];
|
|
8408
|
-
const endRef = refs[refs.length - 1];
|
|
8409
|
-
if (!startRef || !endRef) {
|
|
8410
|
-
omissions.push({ kind: "micro", startRef, endRef, reason: "missing-reference" });
|
|
8411
|
-
continue;
|
|
8412
|
-
}
|
|
8413
|
-
const invalidShape = source.some(
|
|
8414
|
-
(message) => isSyntheticMessage(message) || isIgnoredUserMessage(message)
|
|
8415
|
-
);
|
|
8416
|
-
if (invalidShape) {
|
|
8417
|
-
omissions.push({ kind: "micro", startRef, endRef, reason: "synthetic-or-ignored" });
|
|
8418
|
-
continue;
|
|
8419
|
-
}
|
|
8420
|
-
const active = source.some((message) => {
|
|
8421
|
-
const entry = state.prune.messages.byMessageId.get(message.info.id);
|
|
8422
|
-
return entry !== void 0 && entry.activeBlockIds.length > 0;
|
|
8423
|
-
});
|
|
8424
|
-
if (active) {
|
|
8425
|
-
omissions.push({ kind: "micro", startRef, endRef, reason: "active-compression" });
|
|
8426
|
-
continue;
|
|
8427
|
-
}
|
|
8428
|
-
let isTool = false;
|
|
8429
|
-
const toolNames = /* @__PURE__ */ new Set();
|
|
8430
|
-
let retainedChars = 0;
|
|
8431
|
-
let toolMessageCount = 0;
|
|
8432
|
-
let textMessageCount = 0;
|
|
8433
|
-
for (const message of source) {
|
|
8434
|
-
retainedChars += countMessageCharacters(message);
|
|
8435
|
-
if (hasNonCompressTool(message)) {
|
|
8436
|
-
isTool = true;
|
|
8437
|
-
toolMessageCount++;
|
|
8438
|
-
} else {
|
|
8439
|
-
textMessageCount++;
|
|
8440
|
-
}
|
|
8441
|
-
for (const toolName of partToolNames(message)) toolNames.add(toolName);
|
|
8442
|
-
}
|
|
8443
|
-
units.push({
|
|
8444
|
-
startIndex: span.startIndex,
|
|
8445
|
-
endIndex: span.endIndex,
|
|
8446
|
-
messages: source,
|
|
8447
|
-
sourceMessageIds: source.map((message) => message.info.id),
|
|
8448
|
-
startRef,
|
|
8449
|
-
endRef,
|
|
8450
|
-
retainedChars,
|
|
8451
|
-
estimatedTokens: Math.ceil(retainedChars / 4),
|
|
8452
|
-
isTool,
|
|
8453
|
-
toolNames: [...toolNames],
|
|
8454
|
-
toolMessageCount,
|
|
8455
|
-
textMessageCount
|
|
8456
|
-
});
|
|
8457
|
-
}
|
|
8458
|
-
return { units, omissions };
|
|
8459
|
-
}
|
|
8460
|
-
function draftCandidateLabel(kind, units) {
|
|
8461
|
-
if (kind === "episode") return "historical conversation segment";
|
|
8462
|
-
const toolNames = [...new Set(units.flatMap((unit) => unit.toolNames))];
|
|
8463
|
-
if (toolNames.length > 0) {
|
|
8464
|
-
return `${toolNames.slice(0, 3).join("/")} transaction`;
|
|
8465
|
-
}
|
|
8466
|
-
return "large conversation message";
|
|
8467
|
-
}
|
|
8468
|
-
function mergeUnits(units) {
|
|
8469
|
-
const first = units[0];
|
|
8470
|
-
const last = units[units.length - 1];
|
|
8471
|
-
const toolNames = /* @__PURE__ */ new Set();
|
|
8472
|
-
for (const unit of units) {
|
|
8473
|
-
for (const toolName of unit.toolNames) toolNames.add(toolName);
|
|
8474
|
-
}
|
|
8475
|
-
return {
|
|
8476
|
-
startIndex: first.startIndex,
|
|
8477
|
-
endIndex: last.endIndex,
|
|
8478
|
-
messages: units.flatMap((unit) => unit.messages),
|
|
8479
|
-
sourceMessageIds: units.flatMap((unit) => unit.sourceMessageIds),
|
|
8480
|
-
startRef: first.startRef,
|
|
8481
|
-
endRef: last.endRef,
|
|
8482
|
-
retainedChars: units.reduce((total, unit) => total + unit.retainedChars, 0),
|
|
8483
|
-
estimatedTokens: units.reduce((total, unit) => total + unit.estimatedTokens, 0),
|
|
8484
|
-
isTool: units.some((unit) => unit.isTool),
|
|
8485
|
-
toolNames: [...toolNames],
|
|
8486
|
-
toolMessageCount: units.reduce((total, unit) => total + unit.toolMessageCount, 0),
|
|
8487
|
-
textMessageCount: units.reduce((total, unit) => total + unit.textMessageCount, 0)
|
|
8488
|
-
};
|
|
8489
|
-
}
|
|
8490
|
-
function buildDrafts(units, minChars, state, config, protectedRefs) {
|
|
8491
|
-
const drafts = [];
|
|
8492
|
-
const omissions = [];
|
|
8493
|
-
const residual = [];
|
|
8494
|
-
for (const unit of units) {
|
|
8495
|
-
const recentProtected = unit.sourceMessageIds.some(
|
|
8496
|
-
(id) => protectedRefs.has(state.messageIds.byRawId.get(id) ?? "")
|
|
8497
|
-
);
|
|
8498
|
-
const protectedToolOrFile = unit.messages.some(
|
|
8499
|
-
(message) => messageContainsProtectedTool(
|
|
8500
|
-
message,
|
|
8501
|
-
config.compress.protectedTools,
|
|
8502
|
-
config.protectedFilePatterns
|
|
8503
|
-
)
|
|
8504
|
-
);
|
|
8505
|
-
if (recentProtected || protectedToolOrFile) {
|
|
8506
|
-
if (residual.length > 0) {
|
|
8507
|
-
const merged = mergeUnits(residual);
|
|
8508
|
-
if (merged.retainedChars >= minChars) {
|
|
8509
|
-
drafts.push({ kind: "episode", units: [...residual] });
|
|
8510
|
-
}
|
|
8511
|
-
residual.length = 0;
|
|
8512
|
-
}
|
|
8513
|
-
omissions.push({
|
|
8514
|
-
kind: unit.retainedChars >= minChars ? "micro" : "episode",
|
|
8515
|
-
startRef: unit.startRef,
|
|
8516
|
-
endRef: unit.endRef,
|
|
8517
|
-
reason: recentProtected ? "recent-protection" : "protected-tool-or-file"
|
|
8518
|
-
});
|
|
8519
|
-
continue;
|
|
8520
|
-
}
|
|
8521
|
-
if (unit.retainedChars > 0 && (minChars <= 0 || unit.retainedChars >= minChars)) {
|
|
8522
|
-
drafts.push({ kind: "micro", units: [unit] });
|
|
8523
|
-
} else if (minChars > 0 && unit.retainedChars > 0) {
|
|
8524
|
-
residual.push(unit);
|
|
8525
|
-
}
|
|
8526
|
-
}
|
|
8527
|
-
let episode = [];
|
|
8528
|
-
const flushEpisode = () => {
|
|
8529
|
-
if (episode.length === 0) return;
|
|
8530
|
-
const merged = mergeUnits(episode);
|
|
8531
|
-
if (merged.retainedChars >= minChars) {
|
|
8532
|
-
drafts.push({ kind: "episode", units: [...episode] });
|
|
8533
|
-
}
|
|
8534
|
-
episode = [];
|
|
8535
|
-
};
|
|
8536
|
-
for (let index = 0; index < residual.length; index++) {
|
|
8537
|
-
const unit = residual[index];
|
|
8538
|
-
const previous = residual[index - 1];
|
|
8539
|
-
if (previous && unit.startIndex !== previous.endIndex + 1) flushEpisode();
|
|
8540
|
-
episode.push(unit);
|
|
8541
|
-
}
|
|
8542
|
-
flushEpisode();
|
|
8543
|
-
return { drafts, omissions };
|
|
8544
|
-
}
|
|
8545
|
-
function compareIds(left, right) {
|
|
8546
|
-
const leftNumber = Number.parseInt(left.slice(1), 10);
|
|
8547
|
-
const rightNumber = Number.parseInt(right.slice(1), 10);
|
|
8548
|
-
return leftNumber - rightNumber || left.localeCompare(right);
|
|
8549
|
-
}
|
|
8550
|
-
function candidateDraftRange(draft) {
|
|
8551
|
-
return mergeUnits(draft.units);
|
|
8552
|
-
}
|
|
8553
|
-
function selectionMatchesSource(result, sourceMessageIds, unit) {
|
|
8554
|
-
if (result.plans.length !== 1) return false;
|
|
8555
|
-
const plan = result.plans[0];
|
|
8556
|
-
if (!plan) return false;
|
|
8557
|
-
if (plan.selection.startReference.rawIndex !== unit.startIndex || plan.selection.endReference.rawIndex !== unit.endIndex) {
|
|
8558
|
-
return false;
|
|
8559
|
-
}
|
|
8560
|
-
if (plan.selection.messageIds.length !== sourceMessageIds.length) return false;
|
|
8561
|
-
return plan.selection.messageIds.every((id, index) => id === sourceMessageIds[index]);
|
|
8562
|
-
}
|
|
8563
|
-
function validateDraft(draft, unit, messages, state, config, protectedRefs, prepared) {
|
|
8564
|
-
const source = messages.slice(unit.startIndex, unit.endIndex + 1);
|
|
8565
|
-
if (source.some(
|
|
8566
|
-
(message) => protectedRefs.has(state.messageIds.byRawId.get(message.info.id) ?? "")
|
|
8567
|
-
)) {
|
|
8568
|
-
return {
|
|
8569
|
-
omission: {
|
|
8570
|
-
kind: draft.kind,
|
|
8571
|
-
startRef: unit.startRef,
|
|
8572
|
-
endRef: unit.endRef,
|
|
8573
|
-
reason: "recent-protection"
|
|
8574
|
-
}
|
|
8575
|
-
};
|
|
8576
|
-
}
|
|
8577
|
-
if (source.some(
|
|
8578
|
-
(message) => messageContainsProtectedTool(
|
|
8579
|
-
message,
|
|
8580
|
-
config.compress.protectedTools,
|
|
8581
|
-
config.protectedFilePatterns
|
|
8582
|
-
)
|
|
8583
|
-
)) {
|
|
8584
|
-
return {
|
|
8585
|
-
omission: {
|
|
8586
|
-
kind: draft.kind,
|
|
8587
|
-
startRef: unit.startRef,
|
|
8588
|
-
endRef: unit.endRef,
|
|
8589
|
-
reason: "protected-tool-or-file"
|
|
8590
|
-
}
|
|
8591
|
-
};
|
|
8592
|
-
}
|
|
8593
|
-
if (config.compress.minCompressRange > 0 && unit.retainedChars < config.compress.minCompressRange) {
|
|
8594
|
-
return {
|
|
8595
|
-
omission: {
|
|
8596
|
-
kind: draft.kind,
|
|
8597
|
-
startRef: unit.startRef,
|
|
8598
|
-
endRef: unit.endRef,
|
|
8599
|
-
reason: "below-minimum"
|
|
8600
|
-
}
|
|
8601
|
-
};
|
|
8602
|
-
}
|
|
8603
|
-
try {
|
|
8604
|
-
let result = prepared;
|
|
8605
|
-
if (!result) {
|
|
8606
|
-
const searchContext = buildSearchContext(state, messages);
|
|
8607
|
-
result = prepareExecutableRangePlans(
|
|
8608
|
-
{
|
|
8609
|
-
content: [
|
|
8610
|
-
{
|
|
8611
|
-
topic: draftCandidateLabel(draft.kind, draft.units),
|
|
8612
|
-
startId: unit.startRef,
|
|
8613
|
-
endId: unit.endRef,
|
|
8614
|
-
summary: "candidate"
|
|
8615
|
-
}
|
|
8616
|
-
]
|
|
8617
|
-
},
|
|
8618
|
-
searchContext,
|
|
8619
|
-
state,
|
|
8620
|
-
config
|
|
8621
|
-
);
|
|
8622
|
-
}
|
|
8623
|
-
if (!selectionMatchesSource(result, unit.sourceMessageIds, unit)) {
|
|
8624
|
-
return {
|
|
8625
|
-
omission: {
|
|
8626
|
-
kind: draft.kind,
|
|
8627
|
-
startRef: unit.startRef,
|
|
8628
|
-
endRef: unit.endRef,
|
|
8629
|
-
reason: "executor-selection-drift"
|
|
8630
|
-
}
|
|
8631
|
-
};
|
|
8632
|
-
}
|
|
8633
|
-
return {
|
|
8634
|
-
candidate: {
|
|
8635
|
-
kind: draft.kind,
|
|
8636
|
-
startRef: unit.startRef,
|
|
8637
|
-
endRef: unit.endRef,
|
|
8638
|
-
messageCount: unit.sourceMessageIds.length,
|
|
8639
|
-
retainedChars: unit.retainedChars,
|
|
8640
|
-
estimatedTokens: unit.estimatedTokens,
|
|
8641
|
-
toolPct: Math.round(unit.toolMessageCount / unit.sourceMessageIds.length * 100),
|
|
8642
|
-
textPct: Math.round(unit.textMessageCount / unit.sourceMessageIds.length * 100),
|
|
8643
|
-
label: draftCandidateLabel(draft.kind, draft.units),
|
|
8644
|
-
sourceMessageIds: [...unit.sourceMessageIds]
|
|
8645
|
-
}
|
|
8646
|
-
};
|
|
8647
|
-
} catch {
|
|
8648
|
-
return {
|
|
8649
|
-
omission: {
|
|
8650
|
-
kind: draft.kind,
|
|
8651
|
-
startRef: unit.startRef,
|
|
8652
|
-
endRef: unit.endRef,
|
|
8653
|
-
reason: "executor-rejected"
|
|
8654
|
-
}
|
|
8655
|
-
};
|
|
8656
|
-
}
|
|
8657
|
-
}
|
|
8658
|
-
function planCompressionCandidates(messages, state, config) {
|
|
8659
|
-
const protectedRefs = computeProtectedRefs(messages, state, config.compress);
|
|
8660
|
-
const { units, omissions } = buildAtomicUnits(messages, state);
|
|
8661
|
-
const minChars = config.compress.minCompressRange ?? 5e3;
|
|
8662
|
-
const draftResult = buildDrafts(units, minChars, state, config, protectedRefs);
|
|
8663
|
-
const drafts = draftResult.drafts;
|
|
8664
|
-
const candidates = [];
|
|
8665
|
-
const allOmissions = [...omissions, ...draftResult.omissions];
|
|
8666
|
-
let batchResult;
|
|
8667
|
-
try {
|
|
8668
|
-
const searchContext = buildSearchContext(state, messages);
|
|
8669
|
-
const entries = drafts.map((draft) => {
|
|
8670
|
-
const unit = candidateDraftRange(draft);
|
|
8671
|
-
return {
|
|
8672
|
-
topic: draftCandidateLabel(draft.kind, draft.units),
|
|
8673
|
-
startId: unit.startRef,
|
|
8674
|
-
endId: unit.endRef,
|
|
8675
|
-
summary: "candidate"
|
|
8676
|
-
};
|
|
8677
|
-
});
|
|
8678
|
-
if (entries.length > 0) {
|
|
8679
|
-
batchResult = prepareExecutableRangePlans(
|
|
8680
|
-
{ content: entries },
|
|
8681
|
-
searchContext,
|
|
8682
|
-
state,
|
|
8683
|
-
config,
|
|
8684
|
-
void 0,
|
|
8685
|
-
{ includeTokenAccounting: false }
|
|
8686
|
-
);
|
|
8687
|
-
}
|
|
8688
|
-
} catch {
|
|
8689
|
-
}
|
|
8690
|
-
const preparedPlansByIndex = new Map(batchResult?.plans.map((plan) => [plan.index, plan]));
|
|
8691
|
-
for (let draftIndex = 0; draftIndex < drafts.length; draftIndex++) {
|
|
8692
|
-
const draft = drafts[draftIndex];
|
|
8693
|
-
const unit = candidateDraftRange(draft);
|
|
8694
|
-
const preparedPlan = preparedPlansByIndex.get(draftIndex);
|
|
8695
|
-
const prepared = batchResult ? {
|
|
8696
|
-
plans: preparedPlan ? [preparedPlan] : [],
|
|
8697
|
-
totalChars: preparedPlan ? unit.retainedChars : 0
|
|
8698
|
-
} : void 0;
|
|
8699
|
-
const validated = validateDraft(
|
|
8700
|
-
draft,
|
|
8701
|
-
unit,
|
|
8702
|
-
messages,
|
|
8703
|
-
state,
|
|
8704
|
-
config,
|
|
8705
|
-
protectedRefs,
|
|
8706
|
-
prepared
|
|
8707
|
-
);
|
|
8708
|
-
if ("candidate" in validated) {
|
|
8709
|
-
candidates.push(validated.candidate);
|
|
8710
|
-
} else {
|
|
8711
|
-
allOmissions.push(validated.omission);
|
|
8712
|
-
}
|
|
8713
|
-
}
|
|
8714
|
-
candidates.sort((left, right) => {
|
|
8715
|
-
return right.estimatedTokens - left.estimatedTokens || (left.kind === "micro" ? -1 : 1) - (right.kind === "micro" ? -1 : 1) || compareIds(left.startRef, right.startRef) || compareIds(left.endRef, right.endRef);
|
|
8716
|
-
});
|
|
8717
|
-
const maxCandidates = 12;
|
|
8718
|
-
const bounded = candidates.slice(0, maxCandidates);
|
|
8719
|
-
return {
|
|
8720
|
-
candidates: bounded,
|
|
8721
|
-
omitted: allOmissions,
|
|
8722
|
-
truncatedCount: Math.max(0, candidates.length - bounded.length)
|
|
8723
|
-
};
|
|
8724
|
-
}
|
|
8725
|
-
function formatCompressionCandidates(plan) {
|
|
8726
|
-
if (plan.candidates.length === 0) return "";
|
|
8727
|
-
const fmt = (value) => value >= 1e3 ? `${(value / 1e3).toFixed(1)}K` : String(value);
|
|
8728
|
-
const lines = plan.candidates.map((candidate) => {
|
|
8729
|
-
const range = `${candidate.startRef}\u2013${candidate.endRef}`;
|
|
8730
|
-
return ` ${candidate.kind.toUpperCase().padEnd(7)} ${range} ${candidate.messageCount} msg${candidate.messageCount === 1 ? "" : "s"} ${fmt(candidate.estimatedTokens)} tokens ${candidate.label}`;
|
|
8731
|
-
});
|
|
8732
|
-
const suffix = plan.truncatedCount > 0 ? `
|
|
8733
|
-
...${plan.truncatedCount} additional candidate${plan.truncatedCount === 1 ? "" : "s"} omitted` : "";
|
|
8734
|
-
return `COMPRESSION CANDIDATES (independent; batchable)
|
|
8735
|
-
${lines.join("\n")}${suffix}`;
|
|
8736
|
-
}
|
|
8737
|
-
|
|
8738
8083
|
// lib/messages/inject/inject.ts
|
|
8739
8084
|
var ACP_SUFFIX_SEED = "acp-dynamic-guidance";
|
|
8740
8085
|
function createSuffixMessage(messages) {
|
|
@@ -8744,7 +8089,7 @@ function createSuffixMessage(messages) {
|
|
|
8744
8089
|
messages.push(synthetic);
|
|
8745
8090
|
return synthetic;
|
|
8746
8091
|
}
|
|
8747
|
-
var injectCompressNudges = (state, config, logger, messages, prompts, compressionPriorities, debugNotify, preCompressTokens
|
|
8092
|
+
var injectCompressNudges = (state, config, logger, messages, prompts, compressionPriorities, debugNotify, preCompressTokens) => {
|
|
8748
8093
|
if (compressPermission(state, config) === "deny") {
|
|
8749
8094
|
return;
|
|
8750
8095
|
}
|
|
@@ -8856,10 +8201,7 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
|
|
|
8856
8201
|
(message) => message.info.id === lastUserMessage.info.id
|
|
8857
8202
|
);
|
|
8858
8203
|
if (lastUserMessageIndex >= 0) {
|
|
8859
|
-
const messagesSinceUser = countMessagesAfterIndex(
|
|
8860
|
-
messages,
|
|
8861
|
-
lastUserMessageIndex
|
|
8862
|
-
);
|
|
8204
|
+
const messagesSinceUser = countMessagesAfterIndex(messages, lastUserMessageIndex);
|
|
8863
8205
|
const iterationThreshold = getIterationNudgeThreshold(config);
|
|
8864
8206
|
if (lastMessage.index > lastUserMessageIndex && messagesSinceUser >= iterationThreshold) {
|
|
8865
8207
|
const interval = getNudgeFrequency(config);
|
|
@@ -8934,69 +8276,24 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
|
|
|
8934
8276
|
config.protectedFilePatterns,
|
|
8935
8277
|
protectedRefs
|
|
8936
8278
|
) : { compressible: [], protected: [] };
|
|
8937
|
-
const unprotectedCompressible = excludeProtectedRanges(
|
|
8938
|
-
contextRanges.compressible,
|
|
8939
|
-
protectedRefs
|
|
8940
|
-
);
|
|
8279
|
+
const unprotectedCompressible = excludeProtectedRanges(contextRanges.compressible, protectedRefs);
|
|
8941
8280
|
const recommendedRanges = filterRecommendedRanges(
|
|
8942
8281
|
unprotectedCompressible,
|
|
8943
8282
|
contextRanges.protected,
|
|
8944
8283
|
{ logger, minEffectiveTokens: resolveEffectiveFloor(config) }
|
|
8945
8284
|
);
|
|
8946
|
-
|
|
8947
|
-
candidates: [],
|
|
8948
|
-
omitted: [],
|
|
8949
|
-
truncatedCount: 0
|
|
8950
|
-
};
|
|
8951
|
-
const candidatesEnabled = config.compress.candidates === true;
|
|
8952
|
-
if (nudgeAllowed && candidatesEnabled) {
|
|
8953
|
-
try {
|
|
8954
|
-
candidatePlan = planCompressionCandidates(candidateMessages ?? messages, state, config);
|
|
8955
|
-
} catch (error) {
|
|
8956
|
-
logger.warn("Compression candidate planning failed closed", {
|
|
8957
|
-
session: state.sessionId,
|
|
8958
|
-
error: error instanceof Error ? error.message : String(error)
|
|
8959
|
-
});
|
|
8960
|
-
}
|
|
8961
|
-
}
|
|
8962
|
-
const candidateText = candidatesEnabled ? formatCompressionCandidates(candidatePlan) || (candidateMessages === void 0 && recommendedRanges.length > 0 ? formatCompressibleRanges(recommendedRanges, contextRanges.protected) : "") : recommendedRanges.length > 0 ? formatCompressibleRanges(recommendedRanges, contextRanges.protected) : "";
|
|
8285
|
+
const hasRecommendations = recommendedRanges.length > 0;
|
|
8963
8286
|
const allProtected = contextRanges.compressible.length === 0 && contextRanges.protected.length > 0;
|
|
8964
8287
|
const allInProtectedZone = protectedRefs.size > 0 && unprotectedCompressible.length === 0;
|
|
8965
8288
|
const allBelowMin = contextRanges.compressible.length > 0 && recommendedRanges.length === 0;
|
|
8966
|
-
const
|
|
8967
|
-
const nothingToCompress = candidatesEnabled && candidateMessages !== void 0 ? noExecutableCandidates : allProtected || allInProtectedZone || allBelowMin;
|
|
8289
|
+
const nothingToCompress = allProtected || allInProtectedZone || allBelowMin;
|
|
8968
8290
|
const emergencyNoTargets = emergencyOverride && nothingToCompress;
|
|
8969
8291
|
const noticeCadenceMet = state.nudges.lastNudgeShownTokens === void 0 || growthSinceBaseline !== void 0 && growthSinceBaseline >= growthFloor;
|
|
8970
8292
|
const shouldInjectNudge = nudgeAllowed && !nothingToCompress;
|
|
8971
8293
|
const shouldInjectNotice = emergencyNoTargets && noticeCadenceMet;
|
|
8972
8294
|
let shouldInject = shouldInjectNudge || shouldInjectNotice;
|
|
8973
8295
|
if (shouldInjectNudge) {
|
|
8974
|
-
|
|
8975
|
-
...prompts,
|
|
8976
|
-
contextLimitNudge: prompts.contextLimitNudge ? `${prompts.contextLimitNudge}
|
|
8977
|
-
|
|
8978
|
-
${CANDIDATE_GUIDANCE}` : CANDIDATE_GUIDANCE,
|
|
8979
|
-
turnNudge: prompts.turnNudge ? `${prompts.turnNudge}
|
|
8980
|
-
|
|
8981
|
-
${TURN_CANDIDATE_GUIDANCE}` : TURN_CANDIDATE_GUIDANCE,
|
|
8982
|
-
iterationNudge: prompts.iterationNudge ? `${prompts.iterationNudge}
|
|
8983
|
-
|
|
8984
|
-
${ITERATION_CANDIDATE_GUIDANCE}` : ITERATION_CANDIDATE_GUIDANCE
|
|
8985
|
-
} : prompts;
|
|
8986
|
-
applyAnchoredNudges(
|
|
8987
|
-
state,
|
|
8988
|
-
config,
|
|
8989
|
-
messages,
|
|
8990
|
-
effectivePrompts,
|
|
8991
|
-
compressionPriorities,
|
|
8992
|
-
currentTokens,
|
|
8993
|
-
modelContextLimit,
|
|
8994
|
-
suffixMessage
|
|
8995
|
-
);
|
|
8996
|
-
if (candidatesEnabled && suffixMessage && candidateText && effectiveTipsVariant !== "maxLimit") {
|
|
8997
|
-
const actionHint = hasPendingNudge ? "\n\n\u26A0\uFE0F This compression nudge has already been shown without a compression. If candidates are clearly stale, call the `compress` tool for one clearly stale candidate before continuing. Do not compress active work or things needed to proceed well." : "\n\n\u{1F4A1} If one listed candidate is clearly complete and no longer needed, call the `compress` tool in this reply before continuing. Do not compress active work or every candidate.";
|
|
8998
|
-
appendToLastTextPart(suffixMessage, actionHint);
|
|
8999
|
-
}
|
|
8296
|
+
applyAnchoredNudges(state, config, messages, prompts, compressionPriorities, currentTokens, modelContextLimit, suffixMessage);
|
|
9000
8297
|
}
|
|
9001
8298
|
if (state.nudges.lastPerMessageNudgeTokens === void 0 && currentTokens !== void 0) {
|
|
9002
8299
|
state.nudges.lastPerMessageNudgeTokens = currentTokens;
|
|
@@ -9005,26 +8302,14 @@ ${ITERATION_CANDIDATE_GUIDANCE}` : ITERATION_CANDIDATE_GUIDANCE
|
|
|
9005
8302
|
if (suffixMessage && !shouldInject) {
|
|
9006
8303
|
const tierUsage = tierUsageEarly;
|
|
9007
8304
|
const tierChecks = [
|
|
9008
|
-
{
|
|
9009
|
-
|
|
9010
|
-
targetTier: 1,
|
|
9011
|
-
tokens: tierUsage.tier1Tokens,
|
|
9012
|
-
lastNudge: state.nudges.lastTier2NudgeTokens
|
|
9013
|
-
},
|
|
9014
|
-
{
|
|
9015
|
-
triggerTier: 3,
|
|
9016
|
-
targetTier: 2,
|
|
9017
|
-
tokens: tierUsage.tier2Tokens,
|
|
9018
|
-
lastNudge: state.nudges.lastTier3NudgeTokens
|
|
9019
|
-
}
|
|
8305
|
+
{ triggerTier: 2, targetTier: 1, tokens: tierUsage.tier1Tokens, lastNudge: state.nudges.lastTier2NudgeTokens },
|
|
8306
|
+
{ triggerTier: 3, targetTier: 2, tokens: tierUsage.tier2Tokens, lastNudge: state.nudges.lastTier3NudgeTokens }
|
|
9020
8307
|
];
|
|
9021
8308
|
for (const tc of tierChecks) {
|
|
9022
8309
|
if (tc.tokens < nudgeGrowthTokens) continue;
|
|
9023
8310
|
const cadenceMet = tc.lastNudge === void 0 || currentTokens !== void 0 && currentTokens - tc.lastNudge >= growthFloor;
|
|
9024
8311
|
if (!cadenceMet) continue;
|
|
9025
|
-
let candidates = [...state.prune.messages.activeBlockIds].map((id) => state.prune.messages.blocksById.get(id)).filter(
|
|
9026
|
-
(b) => b !== void 0 && b.active && (b.tier ?? 1) === tc.targetTier
|
|
9027
|
-
).sort((a, b) => a.blockId - b.blockId);
|
|
8312
|
+
let candidates = [...state.prune.messages.activeBlockIds].map((id) => state.prune.messages.blocksById.get(id)).filter((b) => b !== void 0 && b.active && (b.tier ?? 1) === tc.targetTier).sort((a, b) => a.blockId - b.blockId);
|
|
9028
8313
|
if (candidates.length >= 2) {
|
|
9029
8314
|
const firstId = candidates[0].blockId;
|
|
9030
8315
|
const lastId = candidates[candidates.length - 1].blockId;
|
|
@@ -9072,9 +8357,7 @@ ${ITERATION_CANDIDATE_GUIDANCE}` : ITERATION_CANDIDATE_GUIDANCE
|
|
|
9072
8357
|
const fmt = (n) => n >= 1e3 ? `${(n / 1e3).toFixed(1)}K` : String(n);
|
|
9073
8358
|
const sourceTier = tc.triggerTier === 2 ? "Tier 1" : "Tier 2";
|
|
9074
8359
|
const action = tc.triggerTier === 2 ? "Distill" : "Condense";
|
|
9075
|
-
const blockList = candidates.slice(0, 10).map(
|
|
9076
|
-
(b) => `b${b.blockId} (age=${b.survivedCount}, ${fmt(b.summaryTokens)}tok): "${b.topic}"`
|
|
9077
|
-
).join("\n");
|
|
8360
|
+
const blockList = candidates.slice(0, 10).map((b) => `b${b.blockId} (age=${b.survivedCount}, ${fmt(b.summaryTokens)}tok): "${b.topic}"`).join("\n");
|
|
9078
8361
|
const extraCount = candidates.length > 10 ? `
|
|
9079
8362
|
...and ${candidates.length - 10} more` : "";
|
|
9080
8363
|
const tierText = `
|
|
@@ -9115,19 +8398,7 @@ ${rules}`;
|
|
|
9115
8398
|
usagePct,
|
|
9116
8399
|
growthSinceBaseline,
|
|
9117
8400
|
growthFloor,
|
|
9118
|
-
|
|
9119
|
-
microCandidates: candidatePlan.candidates.filter(
|
|
9120
|
-
(candidate) => candidate.kind === "micro"
|
|
9121
|
-
).length,
|
|
9122
|
-
episodeCandidates: candidatePlan.candidates.filter(
|
|
9123
|
-
(candidate) => candidate.kind === "episode"
|
|
9124
|
-
).length,
|
|
9125
|
-
estimatedCandidateTokens: candidatePlan.candidates.reduce(
|
|
9126
|
-
(total, candidate) => total + candidate.estimatedTokens,
|
|
9127
|
-
0
|
|
9128
|
-
),
|
|
9129
|
-
omittedCandidates: candidatePlan.omitted.length,
|
|
9130
|
-
truncatedCandidates: candidatePlan.truncatedCount
|
|
8401
|
+
recommendedRanges: recommendedRanges.length
|
|
9131
8402
|
});
|
|
9132
8403
|
} else if (shouldInjectNotice) {
|
|
9133
8404
|
logger.info("Emergency /compact notice injected (no compressible targets)", {
|
|
@@ -9138,7 +8409,7 @@ ${rules}`;
|
|
|
9138
8409
|
} else if (nudgeAllowed && nothingToCompress) {
|
|
9139
8410
|
logger.info("Nudge suppressed: nothing to compress", {
|
|
9140
8411
|
session: state.sessionId,
|
|
9141
|
-
reason: allProtected ? "all_protected" : allInProtectedZone ? "in_protected_zone" :
|
|
8412
|
+
reason: allProtected ? "all_protected" : allInProtectedZone ? "in_protected_zone" : "below_effective_floor",
|
|
9142
8413
|
currentTokens,
|
|
9143
8414
|
usagePct,
|
|
9144
8415
|
compressibleRanges: contextRanges.compressible.length
|
|
@@ -9150,7 +8421,7 @@ ${rules}`;
|
|
|
9150
8421
|
const lines = [
|
|
9151
8422
|
`[ACP Debug] Recommendation filter:`,
|
|
9152
8423
|
` Input: ${compressible.length} range(s), ${fmt(compressible.reduce((s, r) => s + r.tokens, 0))} tokens`,
|
|
9153
|
-
|
|
8424
|
+
` Output: ${recommendedRanges.length} range(s) (last segment marked dangerous)`
|
|
9154
8425
|
];
|
|
9155
8426
|
logger.debug(lines.join("\n"));
|
|
9156
8427
|
}
|
|
@@ -9162,7 +8433,10 @@ ${rules}`;
|
|
|
9162
8433
|
const growth = currentTokens !== void 0 && (state.nudges.lastNudgeShownTokens ?? state.nudges.lastPerMessageNudgeTokens) !== void 0 ? currentTokens - (state.nudges.lastNudgeShownTokens ?? state.nudges.lastPerMessageNudgeTokens) : 0;
|
|
9163
8434
|
const growthStr = growth > 0 ? ` (+${fmt(growth)} since last nudge)` : "";
|
|
9164
8435
|
const plainTextTokens = composition.textTokens;
|
|
9165
|
-
const efficiencyNote = effectiveTipsVariant !== "maxLimit" ?
|
|
8436
|
+
const efficiencyNote = effectiveTipsVariant !== "maxLimit" ? `
|
|
8437
|
+
This is an efficiency nudge to compress early and keep context lean \u2014 not an overflow warning. A separate, stronger alert will appear if the context is actually full.
|
|
8438
|
+
|
|
8439
|
+
${COMPRESS_PHILOSOPHY}` : "";
|
|
9166
8440
|
const sysPart = composition.systemTokens > 0 ? `${fmt(composition.systemTokens)} system (${pct2(composition.systemTokens)}%) | ` : "";
|
|
9167
8441
|
let breakdown = `${efficiencyNote}
|
|
9168
8442
|
Breakdown: ${sysPart}${fmt(composition.toolTokens)} tool (${pct2(composition.toolTokens)}%) | ${fmt(composition.summaryTokens)} summaries (${pct2(composition.summaryTokens)}%) | ${fmt(composition.codeTokens)} code (${pct2(composition.codeTokens)}%) | ${fmt(plainTextTokens)} text (${pct2(plainTextTokens)}%) | ${fmt(composition.reasoningTokens)} reasoning (${pct2(composition.reasoningTokens)}%)${growthStr}`;
|
|
@@ -9171,20 +8445,21 @@ Breakdown: ${sysPart}${fmt(composition.toolTokens)} tool (${pct2(composition.too
|
|
|
9171
8445
|
breakdown += `
|
|
9172
8446
|
\u26A0\uFE0F ${fmt(composition.protectedTokens)} tokens are protected (environment-managed tools) \u2014 not compressible. Effective compressible: ~${fmt(compressibleTokens)}.`;
|
|
9173
8447
|
}
|
|
9174
|
-
if (
|
|
8448
|
+
if (recommendedRanges.length > 0) {
|
|
9175
8449
|
breakdown += `
|
|
9176
8450
|
|
|
9177
8451
|
${HOW_TO_COMPRESS_RULES}
|
|
9178
8452
|
|
|
9179
|
-
${
|
|
9180
|
-
breakdown +=
|
|
8453
|
+
${formatCompressibleRanges(recommendedRanges, contextRanges.protected)}`;
|
|
8454
|
+
breakdown += `
|
|
8455
|
+
\u{1F4A1} Compress all ranges in one call (pass multiple content entries: \`content: [{...}, {...}]\`).`;
|
|
9181
8456
|
}
|
|
9182
8457
|
breakdown += `
|
|
9183
8458
|
Use \`acp_status({scope:"uncompressed"})\` to re-fetch compressible ranges after compressing, or \`acp_status\` for compressed block details.`;
|
|
9184
8459
|
appendToLastTextPart(suffixMessage, breakdown);
|
|
9185
8460
|
}
|
|
9186
8461
|
if (effectiveTipsVariant === "maxLimit" && !emergencyNoTargets) {
|
|
9187
|
-
tipsText =
|
|
8462
|
+
tipsText = "\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.';
|
|
9188
8463
|
} else if (shouldInjectNotice) {
|
|
9189
8464
|
const emergencyPct = currentTokens !== void 0 && modelContextLimit !== void 0 && modelContextLimit > 0 ? Math.round(currentTokens / modelContextLimit * 100) : void 0;
|
|
9190
8465
|
tipsText = `
|
|
@@ -9199,7 +8474,9 @@ Then stop retrying and await the user's response.`;
|
|
|
9199
8474
|
}
|
|
9200
8475
|
state.nudges.lastNudgeShownTokens = currentTokens;
|
|
9201
8476
|
{
|
|
9202
|
-
const visibleMessageIds = new Set(
|
|
8477
|
+
const visibleMessageIds = new Set(
|
|
8478
|
+
messages.map((message) => message.info.id)
|
|
8479
|
+
);
|
|
9203
8480
|
const blockGuidance = buildCompressedBlockGuidance(state, {
|
|
9204
8481
|
currentTokens,
|
|
9205
8482
|
modelContextLimit,
|
|
@@ -9983,14 +9260,14 @@ function hideConsumedCompressCalls(state, messages) {
|
|
|
9983
9260
|
}
|
|
9984
9261
|
|
|
9985
9262
|
// lib/compress/status.ts
|
|
9986
|
-
var ACP_STATUS_TOOL_DESCRIPTION = `Show context status \u2014 overview includes compressible ranges
|
|
9263
|
+
var ACP_STATUS_TOOL_DESCRIPTION = `Show context status \u2014 overview includes compressible ranges by default.
|
|
9987
9264
|
|
|
9988
|
-
No args: Overview with totals, compressed blocks, and compressible ranges
|
|
9989
|
-
scope:"uncompressed": Compressible ranges
|
|
9265
|
+
No args: Overview with totals, compressed blocks, and compressible ranges.
|
|
9266
|
+
scope:"uncompressed": Compressible ranges only (default view:"ranges"). Add view:"messages" for per-message listing with tool/sort filters.
|
|
9990
9267
|
scope:"compressed": Drill into compressed blocks \u2014 list each with full details (age, generation, consumed lineage).
|
|
9991
9268
|
|
|
9992
9269
|
Use this tool to:
|
|
9993
|
-
- See what's consuming context + compressible
|
|
9270
|
+
- See what's consuming context + compressible ranges in one call (no args)
|
|
9994
9271
|
- Focus on ranges only (scope:"uncompressed")
|
|
9995
9272
|
- Find all messages of a specific tool type (scope:"uncompressed", view:"messages", tool:"bash")
|
|
9996
9273
|
- Check block details before decompressing (scope:"compressed")`;
|
|
@@ -10160,33 +9437,25 @@ function renderOverview(visibleMessages, summaryTokens, systemTokens, blocks, fe
|
|
|
10160
9437
|
const entry = pruneMap.get(msgId);
|
|
10161
9438
|
return !entry || entry.activeBlockIds.length === 0;
|
|
10162
9439
|
});
|
|
10163
|
-
|
|
10164
|
-
|
|
10165
|
-
|
|
10166
|
-
|
|
10167
|
-
|
|
10168
|
-
|
|
10169
|
-
|
|
10170
|
-
|
|
10171
|
-
|
|
10172
|
-
|
|
10173
|
-
|
|
10174
|
-
|
|
10175
|
-
ctx.config?.protectedFilePatterns ?? [],
|
|
10176
|
-
protectedRefs
|
|
9440
|
+
const protectedRefs = ctx.config?.compress ? computeProtectedRefs(visibleRaw, ctx.state, ctx.config.compress) : /* @__PURE__ */ new Set();
|
|
9441
|
+
const contextRanges = buildCompressibleRanges(
|
|
9442
|
+
visibleRaw,
|
|
9443
|
+
ctx.state,
|
|
9444
|
+
ctx.config?.compress?.protectedTools ?? [],
|
|
9445
|
+
ctx.config?.protectedFilePatterns ?? [],
|
|
9446
|
+
protectedRefs
|
|
9447
|
+
);
|
|
9448
|
+
if (contextRanges.compressible.length > 0 || contextRanges.protected.length > 0) {
|
|
9449
|
+
lines.push("");
|
|
9450
|
+
lines.push(
|
|
9451
|
+
formatCompressibleRanges(contextRanges.compressible, contextRanges.protected)
|
|
10177
9452
|
);
|
|
10178
|
-
if (contextRanges.compressible.length > 0 || contextRanges.protected.length > 0) {
|
|
10179
|
-
lines.push("");
|
|
10180
|
-
lines.push(
|
|
10181
|
-
formatCompressibleRanges(contextRanges.compressible, contextRanges.protected)
|
|
10182
|
-
);
|
|
10183
|
-
}
|
|
10184
9453
|
}
|
|
10185
9454
|
}
|
|
10186
9455
|
lines.push("");
|
|
10187
9456
|
const hintTool = topToolName || "bash";
|
|
10188
9457
|
lines.push(
|
|
10189
|
-
|
|
9458
|
+
`Tip: acp_status({scope:"uncompressed", view:"messages", tool:"${hintTool}"}) for per-message listing`
|
|
10190
9459
|
);
|
|
10191
9460
|
return lines;
|
|
10192
9461
|
}
|
|
@@ -10223,44 +9492,6 @@ function renderUncompressedRanges(rawMessages, ctx) {
|
|
|
10223
9492
|
lines.push(`Filter by tool: acp_status({scope:"uncompressed", view:"messages", tool:"bash"})`);
|
|
10224
9493
|
return lines;
|
|
10225
9494
|
}
|
|
10226
|
-
function renderCompressionCandidates(rawMessages, ctx) {
|
|
10227
|
-
const lines = ["COMPRESSION CANDIDATES"];
|
|
10228
|
-
if (!ctx.config?.compress || ctx.config.compress.candidates !== true) {
|
|
10229
|
-
return renderUncompressedRanges(rawMessages, ctx);
|
|
10230
|
-
}
|
|
10231
|
-
try {
|
|
10232
|
-
const plan = planCompressionCandidates(rawMessages, ctx.state, ctx.config);
|
|
10233
|
-
const visibleMessages = rawMessages.filter((message) => {
|
|
10234
|
-
const entry = ctx.state.prune.messages.byMessageId.get(message.info.id);
|
|
10235
|
-
return !entry || entry.activeBlockIds.length === 0;
|
|
10236
|
-
});
|
|
10237
|
-
const protectedRefs = computeProtectedRefs(visibleMessages, ctx.state, ctx.config.compress);
|
|
10238
|
-
const contextRanges = buildCompressibleRanges(
|
|
10239
|
-
visibleMessages,
|
|
10240
|
-
ctx.state,
|
|
10241
|
-
ctx.config.compress.protectedTools ?? [],
|
|
10242
|
-
ctx.config.protectedFilePatterns ?? [],
|
|
10243
|
-
protectedRefs
|
|
10244
|
-
);
|
|
10245
|
-
const protectedText = formatCompressibleRanges([], contextRanges.protected);
|
|
10246
|
-
if (plan.candidates.length === 0) {
|
|
10247
|
-
lines.push(" (no eligible candidates)");
|
|
10248
|
-
if (protectedText.includes("PROTECTED")) lines.push("", protectedText);
|
|
10249
|
-
return lines;
|
|
10250
|
-
}
|
|
10251
|
-
lines.length = 0;
|
|
10252
|
-
lines.push(formatCompressionCandidates(plan));
|
|
10253
|
-
if (protectedText.includes("PROTECTED")) lines.push("", protectedText);
|
|
10254
|
-
if (plan.omitted.length > 0) {
|
|
10255
|
-
lines.push(
|
|
10256
|
-
` ${plan.omitted.length} structurally unsafe or undersized candidate${plan.omitted.length === 1 ? "" : "s"} omitted`
|
|
10257
|
-
);
|
|
10258
|
-
}
|
|
10259
|
-
return lines;
|
|
10260
|
-
} catch {
|
|
10261
|
-
return ["COMPRESSION CANDIDATES", " (candidate planning unavailable)"];
|
|
10262
|
-
}
|
|
10263
|
-
}
|
|
10264
9495
|
function renderUncompressedDrilldown(visibleMessages, toolFilter, sort, limit) {
|
|
10265
9496
|
const lines = [];
|
|
10266
9497
|
let filtered = visibleMessages;
|
|
@@ -10363,12 +9594,14 @@ function renderCompressedDrilldown(blocks, sort, limit, blocksById) {
|
|
|
10363
9594
|
}
|
|
10364
9595
|
function buildStatusReport(renderCtx, rawMessages, options) {
|
|
10365
9596
|
const scope = options?.scope;
|
|
10366
|
-
const view = options?.view ?? "
|
|
9597
|
+
const view = options?.view ?? "ranges";
|
|
10367
9598
|
const toolFilter = options?.tool;
|
|
10368
9599
|
const sort = options?.sort ?? "size";
|
|
10369
9600
|
const limit = options?.limit ?? 30;
|
|
10370
9601
|
const msgState = renderCtx.state.prune.messages;
|
|
10371
|
-
const allBlocks = Array.from(msgState.blocksById.values()).sort(
|
|
9602
|
+
const allBlocks = Array.from(msgState.blocksById.values()).sort(
|
|
9603
|
+
(a, b) => a.blockId - b.blockId
|
|
9604
|
+
);
|
|
10372
9605
|
const activeBlocks = allBlocks.filter((b) => b.active);
|
|
10373
9606
|
const lines = [];
|
|
10374
9607
|
if (scope === "compressed") {
|
|
@@ -10382,10 +9615,8 @@ function buildStatusReport(renderCtx, rawMessages, options) {
|
|
|
10382
9615
|
if (scope === "uncompressed") {
|
|
10383
9616
|
if (view === "messages") {
|
|
10384
9617
|
lines.push(...renderUncompressedDrilldown(visibleMsgs, toolFilter, sort, limit));
|
|
10385
|
-
} else if (view === "ranges") {
|
|
10386
|
-
lines.push(...renderUncompressedRanges(rawMessages, renderCtx));
|
|
10387
9618
|
} else {
|
|
10388
|
-
lines.push(...
|
|
9619
|
+
lines.push(...renderUncompressedRanges(rawMessages, renderCtx));
|
|
10389
9620
|
}
|
|
10390
9621
|
} else {
|
|
10391
9622
|
lines.push(
|
|
@@ -10409,7 +9640,7 @@ function createAcpStatusTool(factoryCtx) {
|
|
|
10409
9640
|
args: {
|
|
10410
9641
|
scope: tool4.schema.string().optional().describe('Drill down: "compressed" or "uncompressed". No arg = overview of both.'),
|
|
10411
9642
|
view: tool4.schema.string().optional().describe(
|
|
10412
|
-
'Display format for scope:"uncompressed": "
|
|
9643
|
+
'Display format for scope:"uncompressed": "ranges" (default, grouped by turn \u2014 matches nudge format) or "messages" (per-message listing with sort/filter)'
|
|
10413
9644
|
),
|
|
10414
9645
|
tool: tool4.schema.string().optional().describe(
|
|
10415
9646
|
'Filter by tool type (only with scope:"uncompressed", view:"messages"). e.g., "bash", "todowrite", "write"'
|
|
@@ -10420,16 +9651,16 @@ function createAcpStatusTool(factoryCtx) {
|
|
|
10420
9651
|
async execute(args, toolCtx) {
|
|
10421
9652
|
const ctx = resolveToolContext(factoryCtx, toolCtx.sessionID);
|
|
10422
9653
|
const scope = args.scope === "compressed" || args.scope === "uncompressed" ? args.scope : void 0;
|
|
10423
|
-
const view = args.view === "messages"
|
|
9654
|
+
const view = args.view === "messages" ? "messages" : "ranges";
|
|
10424
9655
|
const toolFilter = typeof args.tool === "string" ? args.tool : void 0;
|
|
10425
9656
|
const sort = args.sort === "time" || args.sort === "tool" || args.sort === "age" ? args.sort : "size";
|
|
10426
9657
|
const limit = Number.isFinite(args.limit) && args.limit > 0 ? Math.min(args.limit, 200) : 30;
|
|
10427
9658
|
if (scope === "compressed") {
|
|
10428
|
-
return buildStatusReport(
|
|
10429
|
-
|
|
10430
|
-
|
|
10431
|
-
limit
|
|
10432
|
-
|
|
9659
|
+
return buildStatusReport(
|
|
9660
|
+
{ state: ctx.state, config: ctx.config },
|
|
9661
|
+
[],
|
|
9662
|
+
{ scope: "compressed", sort, limit }
|
|
9663
|
+
);
|
|
10433
9664
|
}
|
|
10434
9665
|
let rawMessages = [];
|
|
10435
9666
|
try {
|
|
@@ -10439,13 +9670,11 @@ function createAcpStatusTool(factoryCtx) {
|
|
|
10439
9670
|
rawMessages = [];
|
|
10440
9671
|
}
|
|
10441
9672
|
hideConsumedCompressCalls(ctx.state, rawMessages);
|
|
10442
|
-
return buildStatusReport(
|
|
10443
|
-
|
|
10444
|
-
|
|
10445
|
-
tool: toolFilter,
|
|
10446
|
-
|
|
10447
|
-
limit
|
|
10448
|
-
});
|
|
9673
|
+
return buildStatusReport(
|
|
9674
|
+
{ state: ctx.state, config: ctx.config },
|
|
9675
|
+
rawMessages,
|
|
9676
|
+
{ scope, view, tool: toolFilter, sort, limit }
|
|
9677
|
+
);
|
|
10449
9678
|
}
|
|
10450
9679
|
});
|
|
10451
9680
|
}
|
|
@@ -10553,7 +9782,7 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
|
10553
9782
|
import { join as join4 } from "path";
|
|
10554
9783
|
import { existsSync as existsSync4 } from "fs";
|
|
10555
9784
|
import { homedir as homedir3 } from "os";
|
|
10556
|
-
var LOG_VERSION = true ? "1.17.1
|
|
9785
|
+
var LOG_VERSION = true ? "1.17.1" : "dev";
|
|
10557
9786
|
var LEVEL_RANK = {
|
|
10558
9787
|
debug: 10,
|
|
10559
9788
|
info: 20,
|
|
@@ -10776,32 +10005,7 @@ import { join as join5, dirname as dirname2 } from "path";
|
|
|
10776
10005
|
import { homedir as homedir4 } from "os";
|
|
10777
10006
|
|
|
10778
10007
|
// lib/prompts/system.ts
|
|
10779
|
-
var
|
|
10780
|
-
var ACP_STATUS_TOOL_LINE_CANDIDATES = `- \`acp_status\` \u2014 Context status with compression candidates. No args = overview + candidates. \`scope:"uncompressed"\` defaults to independent candidates; use \`view:"ranges"\` for raw grouped ranges or \`view:"messages"\` for per-message listing with \`tool\`/\`sort\` filters. \`scope:"compressed"\` shows block details.`;
|
|
10781
|
-
var PHILOSOPHY_TAIL_RANGES = `All ranges listed in the context breakdown should be compressed to summary format \u2014 the only exceptions are protected content, content the current step is actively using, or critical content you cannot reconstruct.`;
|
|
10782
|
-
var PHILOSOPHY_TAIL_CANDIDATES = `Candidate guidance is advisory: a candidate is structurally safe to submit, not a command to compress. Preserve current intent and active work even when a candidate is displayed.`;
|
|
10783
|
-
var COMPRESSION_CANDIDATES_SECTION = `COMPRESSION CANDIDATES
|
|
10784
|
-
|
|
10785
|
-
ACP may append a bounded list headed \`COMPRESSION CANDIDATES\` below a nudge or status report:
|
|
10786
|
-
|
|
10787
|
-
- \`MICRO\` is one large plain message or one complete tool transaction, including every message needed to keep its tool call/result structure valid.
|
|
10788
|
-
- \`EPISODE\` is a contiguous historical segment made from smaller adjacent units.
|
|
10789
|
-
- Candidate ranges are independent, non-overlapping, and can be submitted together as separate \`content[]\` entries.
|
|
10790
|
-
- Choose candidates only when their content is no longer needed for the current task. Do not invent a target when no candidate is listed; call \`acp_status\` for a fresh view. If an arbitrary range is unavoidable, verify current visible IDs, protection boundaries, and complete tool-pair coverage first.
|
|
10791
|
-
- Keep summaries self-contained and use the existing \`compress\` tool. Candidate labels do not replace the semantic judgment to preserve useful context.
|
|
10792
|
-
- When a nudge lists a clearly stale candidate, call \`compress\` in that reply before continuing. A repeated nudge means compression was not completed; act on one clearly stale candidate rather than merely recommending compression.`;
|
|
10793
|
-
var BREAKDOWN_TAIL_RANGES = `Below the breakdown, the system lists compressible ranges grouped by conversation turn. All listed ranges should be compressed to summary format \u2014 the only exceptions are protected content, content the current step is actively using, or critical content you cannot reconstruct. Compress the largest ranges first when the current step no longer needs them.`;
|
|
10794
|
-
var BREAKDOWN_TAIL_CANDIDATES = `Below the breakdown, the system may list independent compression candidates. Prefer a large stale micro-range when it removes an isolated artifact; use an episode range when a completed historical phase is more coherent as one summary. Compress only content the current step no longer needs.`;
|
|
10795
|
-
function buildSystemPrompt(candidatesEnabled) {
|
|
10796
|
-
const acpStatusToolLine = candidatesEnabled ? ACP_STATUS_TOOL_LINE_CANDIDATES : ACP_STATUS_TOOL_LINE_RANGES;
|
|
10797
|
-
const philosophyTail = candidatesEnabled ? PHILOSOPHY_TAIL_CANDIDATES : PHILOSOPHY_TAIL_RANGES;
|
|
10798
|
-
const compressionCandidatesBlock = candidatesEnabled ? `
|
|
10799
|
-
|
|
10800
|
-
${COMPRESSION_CANDIDATES_SECTION}
|
|
10801
|
-
|
|
10802
|
-
` : "\n\n";
|
|
10803
|
-
const breakdownTail = candidatesEnabled ? BREAKDOWN_TAIL_CANDIDATES : BREAKDOWN_TAIL_RANGES;
|
|
10804
|
-
return `
|
|
10008
|
+
var SYSTEM = `
|
|
10805
10009
|
|
|
10806
10010
|
You operate in a context-constrained environment. All compression serves the primary task, but be frugal. Context management helps preserve retrieval quality, but your primary goal is completing the task at hand. Do not let context management distract from the actual work.
|
|
10807
10011
|
|
|
@@ -10827,7 +10031,7 @@ You have five context-management tools:
|
|
|
10827
10031
|
- \`compress\` \u2014 Replace a contiguous range of older conversation with a single detailed summary you write. Use when content is genuinely consumed (no longer needed for the current task step). Single range: \`compress({ topic: "API exploration", content: [{ startId: "m00150", endId: "m00220", summary: "..." }] })\`. Batch (multiple unrelated ranges, each with its own topic): \`compress({ content: [{ topic: "Auth", startId: "m00150", endId: "m00220", summary: "..." }, { topic: "Deploy", startId: "m00300", endId: "m00350", summary: "..." }] })\`.
|
|
10828
10032
|
- \`decompress\` \u2014 Restore a previously compressed block's content. By default restores one tier up (T2\u2192T1 summaries, not raw messages). Use \`full: true\` to restore all the way to original messages. Use \`toFile\` to write to file instead of inflating context. Example: \`decompress({ blockId: "b5" })\` or \`decompress({ blockId: "b5", toFile: "path" })\` or \`decompress({ blockId: "b5", full: true })\`.
|
|
10829
10033
|
- \`search_context\` \u2014 Search compressed block summaries (and optionally visible messages) by keyword. Use BEFORE decompressing to find the right block. Example: \`search_context({ query: "auth token refresh" })\`.
|
|
10830
|
-
|
|
10034
|
+
- \`acp_status\` \u2014 Context status with compressible ranges. No args = overview + ranges. \`scope:"uncompressed"\` for range view; add \`view:"messages"\` for per-message listing with \`tool\`/\`sort\` filters. \`scope:"compressed"\` for block details.
|
|
10831
10035
|
|
|
10832
10036
|
COMPRESSION PHILOSOPHY
|
|
10833
10037
|
|
|
@@ -10835,7 +10039,7 @@ Two failure modes to avoid:
|
|
|
10835
10039
|
- Over-compression: Compressing too aggressively loses critical details, decisions, and state needed for your task. This directly harms task quality.
|
|
10836
10040
|
- Under-compression: Failing to compress verbose outputs causes context overflow, reducing accuracy and eventually blocking your work.
|
|
10837
10041
|
|
|
10838
|
-
Balance is key. The single test for whether to compress is: "Is this content still needed by the current task step?" If yes, keep it. If no, compress it.
|
|
10042
|
+
Balance is key. The single test for whether to compress is: "Is this content still needed by the current task step?" If yes, keep it. If no, compress it. All ranges listed in the context breakdown should be compressed to summary format \u2014 the only exceptions are protected content, content the current step is actively using, or critical content you cannot reconstruct.
|
|
10839
10043
|
|
|
10840
10044
|
Be frugal with context. Compress obvious waste proactively \u2014 verbose outputs you have already used, duplicate reads, abandoned explorations. Do not wait until context is critically full; that harms retrieval quality and risks overflow. But never let the urge to compress distract from the actual task.
|
|
10841
10045
|
|
|
@@ -10856,7 +10060,9 @@ WHEN NOT TO COMPRESS
|
|
|
10856
10060
|
- Important user messages \u2014 preserve their exact intent, constraints, and acceptance criteria verbatim, not just the most recent one.
|
|
10857
10061
|
- Protected tool outputs (default: \`skill\` only) \u2014 hard-excluded from compression ranges, survive intact in visible context.
|
|
10858
10062
|
|
|
10859
|
-
${HOW_TO_COMPRESS_RULES}
|
|
10063
|
+
${HOW_TO_COMPRESS_RULES}
|
|
10064
|
+
|
|
10065
|
+
MULTI-TIER COMPRESSION
|
|
10860
10066
|
|
|
10861
10067
|
Summaries accumulate as the session grows. When tier-1 summaries pile up, the system injects a [Tier 2 Trigger] prompting you to DISTILL old blocks into a single tier-2 summary. If tier-2 summaries also accumulate, a [Tier 3 Trigger] asks you to CONDENSE them further.
|
|
10862
10068
|
|
|
@@ -10881,21 +10087,13 @@ Breakdown: 4.2K system (21%) | 8.0K tool (40%) | 2.0K summaries (10%) | 2.6K cod
|
|
|
10881
10087
|
- "text" = plain text messages
|
|
10882
10088
|
- "reasoning" = model thinking blocks (counted to match real API usage; freed when their message is compressed)
|
|
10883
10089
|
|
|
10884
|
-
|
|
10090
|
+
Below the breakdown, the system lists compressible ranges grouped by conversation turn. All listed ranges should be compressed to summary format \u2014 the only exceptions are protected content, content the current step is actively using, or critical content you cannot reconstruct. Compress the largest ranges first when the current step no longer needs them.
|
|
10885
10091
|
|
|
10886
10092
|
Each compression creates a reusable summary block you can decompress later if needed.
|
|
10887
10093
|
`;
|
|
10888
|
-
}
|
|
10889
|
-
var SYSTEM = buildSystemPrompt(true);
|
|
10890
10094
|
|
|
10891
10095
|
// lib/prompts/compress-range.ts
|
|
10892
|
-
var
|
|
10893
|
-
ACP may display a \`COMPRESSION CANDIDATES\` list in a nudge or \`acp_status\` report. A \`MICRO\` entry targets one large message or complete tool transaction; an \`EPISODE\` entry targets a contiguous historical segment. Displayed candidates are independent and non-overlapping, so they may be batched, but they are advisory: compress only entries whose content is no longer needed. When a nudge lists a clearly stale candidate, use its exact IDs and call \`compress\` before continuing. Keep current intent and active work visible, and use \`acp_status\` when the candidate list is stale.`;
|
|
10894
|
-
function buildCompressRangePrompt(candidatesEnabled) {
|
|
10895
|
-
const candidateGuidanceBlock = candidatesEnabled ? `${CANDIDATE_GUIDANCE_SECTION}
|
|
10896
|
-
|
|
10897
|
-
` : "";
|
|
10898
|
-
return `Collapse a range in the conversation into a detailed summary.
|
|
10096
|
+
var COMPRESS_RANGE = `Collapse a range in the conversation into a detailed summary.
|
|
10899
10097
|
|
|
10900
10098
|
COMPRESSED BLOCK PLACEHOLDERS
|
|
10901
10099
|
The system auto-detects any previously compressed blocks whose anchor messages fall inside your selected range. You do NOT need to manually list \`(bN)\` placeholders in your summary \u2014 every consumed block is tracked automatically.
|
|
@@ -10925,7 +10123,7 @@ Rules:
|
|
|
10925
10123
|
|
|
10926
10124
|
- Pick \`startId\` and \`endId\` directly from injected IDs in context.
|
|
10927
10125
|
- IDs must exist in the current visible context. If you cannot see an ID in the messages above, it is stale and will fail.
|
|
10928
|
-
-
|
|
10126
|
+
- \`startId\` must appear before \`endId\`.
|
|
10929
10127
|
- Do not invent IDs. Use only IDs that are present in context.
|
|
10930
10128
|
- NEVER use IDs from compressed block summaries, previous nudges, or your own memory \u2014 only IDs currently visible as XML metadata tags in the conversation.
|
|
10931
10129
|
|
|
@@ -10942,7 +10140,7 @@ compress({ content: [
|
|
|
10942
10140
|
]})
|
|
10943
10141
|
\`\`\`
|
|
10944
10142
|
|
|
10945
|
-
|
|
10143
|
+
KEEP AND REF MARKERS
|
|
10946
10144
|
When writing a summary, you may embed markers that reference specific messages in the compressed range. The system resolves them automatically:
|
|
10947
10145
|
|
|
10948
10146
|
- \`[[KEEP:mNNNNN]]\` \u2014 Expands to the original message content inline (truncated to a max length). Use for critical content you want preserved verbatim in the summary without re-typing it: key function definitions, important error messages, essential file contents.
|
|
@@ -10959,8 +10157,65 @@ The rest of the bash calls were repetitive export commands. See [[REF:m00078|tes
|
|
|
10959
10157
|
|
|
10960
10158
|
Use KEEP sparingly \u2014 each expansion adds to the summary length. Prefer REF for content that is important but not immediately critical.
|
|
10961
10159
|
`;
|
|
10160
|
+
|
|
10161
|
+
// lib/prompts/context-limit-nudge.ts
|
|
10162
|
+
var CONTEXT_LIMIT_NUDGE = `
|
|
10163
|
+
<system-reminder>
|
|
10164
|
+
\u26A0\uFE0F Context limit reached \u2014 time to compress the largest ranges you no longer need. Prioritize completed tool outputs and resolved work. You can decompress specific blocks later if you need details. Keeping context lean helps you stay accurate.
|
|
10165
|
+
|
|
10166
|
+
If mid-atomic-operation, finish that step first, then compress.
|
|
10167
|
+
|
|
10168
|
+
HOW TO CALL COMPRESS:
|
|
10169
|
+
{
|
|
10170
|
+
"topic": "Short Label",
|
|
10171
|
+
"content": [
|
|
10172
|
+
{
|
|
10173
|
+
"startId": "<ID from early in this conversation>",
|
|
10174
|
+
"endId": "<ID from later in this conversation>",
|
|
10175
|
+
"summary": "Complete technical summary of everything in the range"
|
|
10176
|
+
}
|
|
10177
|
+
]
|
|
10962
10178
|
}
|
|
10963
|
-
|
|
10179
|
+
|
|
10180
|
+
\u26A0\uFE0F ID RULES \u2014 MOST COMMON CAUSE OF ERRORS:
|
|
10181
|
+
- ONLY use IDs you can see in tags in the messages ABOVE.
|
|
10182
|
+
- Do NOT copy IDs from this example. Do NOT invent IDs.
|
|
10183
|
+
- Do NOT use IDs from compressed block summaries \u2014 they are stale.
|
|
10184
|
+
- startId must appear BEFORE endId in the conversation.
|
|
10185
|
+
|
|
10186
|
+
RANGE STRATEGY:
|
|
10187
|
+
- Prefer one large range over multiple small ones.
|
|
10188
|
+
- Compress OLDER resolved history first. Keep recent active work.
|
|
10189
|
+
</system-reminder>
|
|
10190
|
+
`;
|
|
10191
|
+
|
|
10192
|
+
// lib/prompts/turn-nudge.ts
|
|
10193
|
+
var TURN_NUDGE = `
|
|
10194
|
+
<system-reminder>
|
|
10195
|
+
Context is getting full. If you've finished reading tool outputs or exploration results, compress them \u2014 you can decompress later if needed. This keeps your focus on the current task and improves accuracy.
|
|
10196
|
+
|
|
10197
|
+
{
|
|
10198
|
+
"topic": "Short Label",
|
|
10199
|
+
"content": [{ "startId": "<visible message ID>", "endId": "<visible message ID>", "summary": "..." }]
|
|
10200
|
+
}
|
|
10201
|
+
|
|
10202
|
+
\u26A0\uFE0F ONLY use IDs from tags visible above. Do NOT invent or copy example IDs.
|
|
10203
|
+
</system-reminder>
|
|
10204
|
+
`;
|
|
10205
|
+
|
|
10206
|
+
// lib/prompts/iteration-nudge.ts
|
|
10207
|
+
var ITERATION_NUDGE = `
|
|
10208
|
+
<system-reminder>
|
|
10209
|
+
You've been iterating for a while. If any earlier work is closed and unlikely to be referenced, compress it now.
|
|
10210
|
+
|
|
10211
|
+
{
|
|
10212
|
+
"topic": "Short Label",
|
|
10213
|
+
"content": [{ "startId": "<visible message ID>", "endId": "<visible message ID>", "summary": "..." }]
|
|
10214
|
+
}
|
|
10215
|
+
|
|
10216
|
+
\u26A0\uFE0F ONLY use IDs from tags visible above. Do NOT invent or copy example IDs.
|
|
10217
|
+
</system-reminder>
|
|
10218
|
+
`;
|
|
10964
10219
|
|
|
10965
10220
|
// lib/prompts/extensions/system.ts
|
|
10966
10221
|
var SUBAGENT_SYSTEM_EXTENSION = `<dcp-system-reminder>
|
|
@@ -11052,27 +10307,24 @@ var HTML_COMMENT_REGEX = /<!--[\s\S]*?-->/g;
|
|
|
11052
10307
|
var LEGACY_INLINE_COMMENT_LINE_REGEX = /^[ \t]*\/\/.*?\/\/[ \t]*$/gm;
|
|
11053
10308
|
var DCP_SYSTEM_REMINDER_TAG_REGEX = /^\s*<dcp-system-reminder\b[^>]*>[\s\S]*<\/(?:dcp|acp)-system-reminder>\s*$/i;
|
|
11054
10309
|
var DEFAULTS_README_FILE = "README.md";
|
|
11055
|
-
|
|
11056
|
-
|
|
11057
|
-
|
|
11058
|
-
|
|
11059
|
-
|
|
11060
|
-
|
|
11061
|
-
|
|
11062
|
-
};
|
|
11063
|
-
}
|
|
10310
|
+
var BUNDLED_EDITABLE_PROMPTS = {
|
|
10311
|
+
system: SYSTEM,
|
|
10312
|
+
compressRange: COMPRESS_RANGE,
|
|
10313
|
+
contextLimitNudge: CONTEXT_LIMIT_NUDGE,
|
|
10314
|
+
turnNudge: TURN_NUDGE,
|
|
10315
|
+
iterationNudge: ITERATION_NUDGE
|
|
10316
|
+
};
|
|
11064
10317
|
var INTERNAL_PROMPT_EXTENSIONS = {
|
|
11065
10318
|
subagentExtension: SUBAGENT_SYSTEM_EXTENSION,
|
|
11066
10319
|
decompressExtension: DECOMPRESS_SYSTEM_EXTENSION
|
|
11067
10320
|
};
|
|
11068
|
-
function createBundledRuntimePrompts(
|
|
11069
|
-
const bundled = getBundledEditablePrompts(candidatesEnabled);
|
|
10321
|
+
function createBundledRuntimePrompts() {
|
|
11070
10322
|
return {
|
|
11071
|
-
system:
|
|
11072
|
-
compressRange:
|
|
11073
|
-
contextLimitNudge:
|
|
11074
|
-
turnNudge:
|
|
11075
|
-
iterationNudge:
|
|
10323
|
+
system: BUNDLED_EDITABLE_PROMPTS.system,
|
|
10324
|
+
compressRange: BUNDLED_EDITABLE_PROMPTS.compressRange,
|
|
10325
|
+
contextLimitNudge: BUNDLED_EDITABLE_PROMPTS.contextLimitNudge,
|
|
10326
|
+
turnNudge: BUNDLED_EDITABLE_PROMPTS.turnNudge,
|
|
10327
|
+
iterationNudge: BUNDLED_EDITABLE_PROMPTS.iterationNudge,
|
|
11076
10328
|
subagentExtension: INTERNAL_PROMPT_EXTENSIONS.subagentExtension,
|
|
11077
10329
|
decompressExtension: INTERNAL_PROMPT_EXTENSIONS.decompressExtension
|
|
11078
10330
|
};
|
|
@@ -11217,14 +10469,12 @@ var PromptStore = class {
|
|
|
11217
10469
|
logger;
|
|
11218
10470
|
paths;
|
|
11219
10471
|
customPromptsEnabled;
|
|
11220
|
-
candidatesEnabled;
|
|
11221
10472
|
runtimePrompts;
|
|
11222
|
-
constructor(logger, workingDirectory, customPromptsEnabled = false
|
|
10473
|
+
constructor(logger, workingDirectory, customPromptsEnabled = false) {
|
|
11223
10474
|
this.logger = logger;
|
|
11224
10475
|
this.paths = resolvePromptPaths(workingDirectory);
|
|
11225
10476
|
this.customPromptsEnabled = customPromptsEnabled;
|
|
11226
|
-
this.
|
|
11227
|
-
this.runtimePrompts = createBundledRuntimePrompts(this.candidatesEnabled);
|
|
10477
|
+
this.runtimePrompts = createBundledRuntimePrompts();
|
|
11228
10478
|
if (this.customPromptsEnabled) {
|
|
11229
10479
|
this.ensureDefaultFiles();
|
|
11230
10480
|
}
|
|
@@ -11234,13 +10484,13 @@ var PromptStore = class {
|
|
|
11234
10484
|
return { ...this.runtimePrompts };
|
|
11235
10485
|
}
|
|
11236
10486
|
reload() {
|
|
11237
|
-
const nextPrompts = createBundledRuntimePrompts(
|
|
10487
|
+
const nextPrompts = createBundledRuntimePrompts();
|
|
11238
10488
|
if (!this.customPromptsEnabled) {
|
|
11239
10489
|
this.runtimePrompts = nextPrompts;
|
|
11240
10490
|
return;
|
|
11241
10491
|
}
|
|
11242
10492
|
for (const definition of PROMPT_DEFINITIONS) {
|
|
11243
|
-
const bundledSource =
|
|
10493
|
+
const bundledSource = BUNDLED_EDITABLE_PROMPTS[definition.runtimeField];
|
|
11244
10494
|
const bundledEditable = toEditablePromptText(definition, bundledSource);
|
|
11245
10495
|
const bundledRuntime = wrapRuntimePromptContent(definition, bundledEditable);
|
|
11246
10496
|
const fallbackValue = bundledRuntime || bundledSource.trim();
|
|
@@ -11301,14 +10551,13 @@ var PromptStore = class {
|
|
|
11301
10551
|
});
|
|
11302
10552
|
return;
|
|
11303
10553
|
}
|
|
11304
|
-
const bundledPrompts = getBundledEditablePrompts(this.candidatesEnabled);
|
|
11305
10554
|
for (const definition of PROMPT_DEFINITIONS) {
|
|
11306
10555
|
const bundledEditable = toEditablePromptText(
|
|
11307
10556
|
definition,
|
|
11308
|
-
|
|
10557
|
+
BUNDLED_EDITABLE_PROMPTS[definition.runtimeField]
|
|
11309
10558
|
);
|
|
11310
10559
|
const managedContent = buildDefaultPromptFileContent(
|
|
11311
|
-
bundledEditable ||
|
|
10560
|
+
bundledEditable || BUNDLED_EDITABLE_PROMPTS[definition.runtimeField]
|
|
11312
10561
|
);
|
|
11313
10562
|
const filePath = join5(this.paths.defaultsDir, definition.fileName);
|
|
11314
10563
|
try {
|
|
@@ -12753,8 +12002,8 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
12753
12002
|
cacheSystemPromptTokens(state, output.messages);
|
|
12754
12003
|
assignMessageRefs(state, output.messages);
|
|
12755
12004
|
const activeBlockCountBefore = state.prune.messages.activeBlockIds.size;
|
|
12756
|
-
|
|
12757
|
-
if (
|
|
12005
|
+
syncCompressionBlocks(state, logger, output.messages);
|
|
12006
|
+
if (state.prune.messages.activeBlockIds.size !== activeBlockCountBefore) {
|
|
12758
12007
|
saveSessionState(state, logger).catch(() => {
|
|
12759
12008
|
});
|
|
12760
12009
|
}
|
|
@@ -12766,8 +12015,9 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
12766
12015
|
});
|
|
12767
12016
|
}
|
|
12768
12017
|
const prePruneTokens = getCurrentTokenUsage(state, output.messages);
|
|
12769
|
-
const candidateMessages = config.compress.candidates === true ? output.messages.slice() : void 0;
|
|
12770
12018
|
prune(state, logger, config, output.messages);
|
|
12019
|
+
truncateLargeToolOutputs(state, config, logger, output.messages);
|
|
12020
|
+
enforceContextBudget(state, config, logger, output.messages);
|
|
12771
12021
|
hideConsumedCompressCalls(state, output.messages);
|
|
12772
12022
|
assignMessageRefs(state, output.messages);
|
|
12773
12023
|
const compressionPriorities = buildPriorityMap(config, state, output.messages);
|
|
@@ -12792,16 +12042,8 @@ ${text}`);
|
|
|
12792
12042
|
}).catch(() => {
|
|
12793
12043
|
});
|
|
12794
12044
|
} : void 0,
|
|
12795
|
-
prePruneTokens
|
|
12796
|
-
candidateMessages
|
|
12797
|
-
);
|
|
12798
|
-
truncateLargeToolOutputs(
|
|
12799
|
-
state,
|
|
12800
|
-
config,
|
|
12801
|
-
logger,
|
|
12802
|
-
output.messages.filter((message) => !isSyntheticMessage(message))
|
|
12045
|
+
prePruneTokens
|
|
12803
12046
|
);
|
|
12804
|
-
enforceContextBudget(state, config, logger, output.messages);
|
|
12805
12047
|
injectMessageIds(state, config, output.messages, compressionPriorities);
|
|
12806
12048
|
hideFailedCompressCalls(output.messages);
|
|
12807
12049
|
stripStaleMetadata(output.messages);
|
|
@@ -13236,7 +12478,7 @@ var server = (async (ctx) => {
|
|
|
13236
12478
|
}
|
|
13237
12479
|
const logger = new Logger(config.debug, config.debug ? "debug" : config.logLevel);
|
|
13238
12480
|
logger.info("ACP plugin initialized", {
|
|
13239
|
-
version: true ? "1.17.1
|
|
12481
|
+
version: true ? "1.17.1" : "dev",
|
|
13240
12482
|
workspace: ctx.directory,
|
|
13241
12483
|
logLevel: logger.level,
|
|
13242
12484
|
debug: config.debug,
|
|
@@ -13244,12 +12486,7 @@ var server = (async (ctx) => {
|
|
|
13244
12486
|
secureMode: isSecureMode()
|
|
13245
12487
|
});
|
|
13246
12488
|
const registry4 = new SessionStateRegistry(logger, ctx.directory);
|
|
13247
|
-
const prompts = new PromptStore(
|
|
13248
|
-
logger,
|
|
13249
|
-
ctx.directory,
|
|
13250
|
-
config.experimental.customPrompts,
|
|
13251
|
-
config.compress.candidates === true
|
|
13252
|
-
);
|
|
12489
|
+
const prompts = new PromptStore(logger, ctx.directory, config.experimental.customPrompts);
|
|
13253
12490
|
const hostPermissions = {
|
|
13254
12491
|
global: void 0,
|
|
13255
12492
|
agents: {}
|