@bastani/atomic 0.8.30-alpha.1 → 0.8.30-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -0
- package/dist/builtin/cursor/package.json +2 -2
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/core/compaction/context-compaction.d.ts.map +1 -1
- package/dist/core/compaction/context-compaction.js +56 -13
- package/dist/core/compaction/context-compaction.js.map +1 -1
- package/docs/compaction.md +6 -5
- package/package.json +2 -2
|
@@ -150,7 +150,7 @@ What Survives:
|
|
|
150
150
|
- User instructions: The original task and any clarifications.
|
|
151
151
|
|
|
152
152
|
Conditionally Deleted:
|
|
153
|
-
- Old Reasoning decisions: If there is nothing else to remove and the target reduction is not met, you can remove
|
|
153
|
+
- Old Reasoning decisions: If there is nothing else to remove and the target reduction is not met, you can remove reasoning steps, EXCEPT do not delete any content block from the latest assistant message when that message contains thinking or redacted_thinking blocks.
|
|
154
154
|
|
|
155
155
|
<output_format>
|
|
156
156
|
Call the context_delete tool one or more times with deletion targets in this shape:
|
|
@@ -535,29 +535,44 @@ function assertNoRecentContextDeletionTargets(transcript, targets) {
|
|
|
535
535
|
}
|
|
536
536
|
}
|
|
537
537
|
}
|
|
538
|
-
function latestAssistantEntry(transcript) {
|
|
538
|
+
function latestAssistantEntry(transcript, deletedEntryIds = new Set()) {
|
|
539
539
|
for (let index = transcript.entries.length - 1; index >= 0; index--) {
|
|
540
540
|
const entry = transcript.entries[index];
|
|
541
|
-
if (entry.role === "assistant")
|
|
541
|
+
if (entry.role === "assistant" && !deletedEntryIds.has(entry.entryId))
|
|
542
542
|
return entry;
|
|
543
543
|
}
|
|
544
544
|
return undefined;
|
|
545
545
|
}
|
|
546
|
-
function
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
return;
|
|
546
|
+
function findLatestAssistantThinkingDeletionViolation(transcript, targets) {
|
|
547
|
+
const deletedEntryIds = getDeletedEntryIds(targets);
|
|
548
|
+
const latestRetainedAssistant = latestAssistantEntry(transcript, deletedEntryIds);
|
|
550
549
|
for (const target of targets) {
|
|
551
|
-
if (target.entryId !== latestAssistant.entryId)
|
|
552
|
-
continue;
|
|
553
550
|
if (target.kind === "entry") {
|
|
554
|
-
|
|
551
|
+
const entry = findTranscriptEntry(transcript, target.entryId);
|
|
552
|
+
if (!entry || !assistantEntryHasThinkingContentBlock(entry))
|
|
553
|
+
continue;
|
|
554
|
+
const deletedEntryIdsIfTargetWereKept = new Set(deletedEntryIds);
|
|
555
|
+
deletedEntryIdsIfTargetWereKept.delete(target.entryId);
|
|
556
|
+
if (latestAssistantEntry(transcript, deletedEntryIdsIfTargetWereKept)?.entryId === target.entryId) {
|
|
557
|
+
return target;
|
|
558
|
+
}
|
|
559
|
+
continue;
|
|
555
560
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
561
|
+
if (latestRetainedAssistant?.entryId === target.entryId &&
|
|
562
|
+
assistantEntryHasThinkingContentBlock(latestRetainedAssistant)) {
|
|
563
|
+
return target;
|
|
559
564
|
}
|
|
560
565
|
}
|
|
566
|
+
return undefined;
|
|
567
|
+
}
|
|
568
|
+
function assertNoLatestAssistantThinkingDeletionTargets(transcript, targets) {
|
|
569
|
+
const violation = findLatestAssistantThinkingDeletionViolation(transcript, targets);
|
|
570
|
+
if (!violation)
|
|
571
|
+
return;
|
|
572
|
+
if (violation.kind === "entry") {
|
|
573
|
+
throw new Error(`Cannot delete assistant entry ${violation.entryId} because it is the latest assistant message retained after other deletions and contains thinking/redacted_thinking content blocks`);
|
|
574
|
+
}
|
|
575
|
+
throw new Error(`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in the latest assistant message must remain unmodified; the latest retained assistant message contains thinking/redacted_thinking content blocks`);
|
|
561
576
|
}
|
|
562
577
|
function isToolCallBlockDeleted(entry, callId, deletedEntryIds, deletedContentBlocks) {
|
|
563
578
|
if (deletedEntryIds.has(entry.entryId))
|
|
@@ -1075,6 +1090,34 @@ function filterProtectedGrepCandidates(candidates, matches, currentTargets, tran
|
|
|
1075
1090
|
eligibleMatches.push(match);
|
|
1076
1091
|
}
|
|
1077
1092
|
}
|
|
1093
|
+
// Some latest-assistant thinking violations only become visible after a grep batch also
|
|
1094
|
+
// deletes newer assistant entries. Classify the newly-unsafe grep candidates as
|
|
1095
|
+
// protected/skipped before maxMatches, expectedMatchCount, stats, or removals are computed.
|
|
1096
|
+
let changed = true;
|
|
1097
|
+
while (changed) {
|
|
1098
|
+
changed = false;
|
|
1099
|
+
const mergedTargets = mergeContextDeletionTargets(currentTargets, eligibleCandidates);
|
|
1100
|
+
const violation = findLatestAssistantThinkingDeletionViolation(transcript, mergedTargets);
|
|
1101
|
+
if (!violation)
|
|
1102
|
+
continue;
|
|
1103
|
+
const violationKey = targetKey(violation);
|
|
1104
|
+
let violationIndex = eligibleCandidates.findIndex((candidate) => targetKey(candidate) === violationKey);
|
|
1105
|
+
if (violationIndex < 0) {
|
|
1106
|
+
violationIndex = eligibleCandidates.findIndex((_candidate, candidateIndex) => {
|
|
1107
|
+
const remainingCandidates = eligibleCandidates.filter((_candidateToKeep, index) => index !== candidateIndex);
|
|
1108
|
+
const remainingTargets = mergeContextDeletionTargets(currentTargets, remainingCandidates);
|
|
1109
|
+
const remainingViolation = findLatestAssistantThinkingDeletionViolation(transcript, remainingTargets);
|
|
1110
|
+
return !remainingViolation || targetKey(remainingViolation) !== violationKey;
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
if (violationIndex < 0)
|
|
1114
|
+
continue;
|
|
1115
|
+
const [skippedMatch] = eligibleMatches.splice(violationIndex, 1);
|
|
1116
|
+
eligibleCandidates.splice(violationIndex, 1);
|
|
1117
|
+
if (skippedMatch)
|
|
1118
|
+
pushProtectedGrepSkip(skipped, skippedMatch);
|
|
1119
|
+
changed = true;
|
|
1120
|
+
}
|
|
1078
1121
|
return { candidates: eligibleCandidates, matches: eligibleMatches };
|
|
1079
1122
|
}
|
|
1080
1123
|
function copyDeletionTarget(target) {
|