🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@archships/dim-plugin-auto-compact

Package Overview
Dependencies
Maintainers
3
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@archships/dim-plugin-auto-compact - npm Package Compare versions

Comparing version
0.0.12
to
0.0.13
+55
-28
dist/index.js

@@ -14,2 +14,3 @@ //#region src/index.ts

const CONTINUATION_SUMMARY_BLOCK_PATTERN = /<continuation_summary>([\s\S]*?)<\/continuation_summary>/g;
const CONTINUATION_SUMMARY_TAG_FRAGMENT_PATTERN = /<\/?continuation_summary>?/g;
const SUMMARY_PROMPT_VERSION = "continuation-summary-v2";

@@ -133,2 +134,3 @@ const COMPACTION_INJECTION_METADATA_KEY = "_dimCompactionInjection";

summaryPrompt: normalized.summaryPrompt,
existingSummary: payload.systemSegments[0],
systemSegments: payload.systemSegments,

@@ -142,2 +144,18 @@ compactedMessages: plan.compactedMessages,

});
if (summaryResult.status === "empty_body_preserve_previous") {
await persistPluginState(context.sessionId, context, {
strategy: "handoff-v1",
summaryModel,
entries: previous.entries,
lastAttempt: finalizeAttemptDiagnostics(baseAttempt, {
status: "skipped",
reasonCode: "empty_summary_preserved_previous",
reasonMessage: "Auto compact summary normalized to an empty body and preserved the previous continuation summary",
compactedMessageCount: plan.compactedMessages.length,
retainedMessageCount: plan.retainedMessages.length
})
});
return;
}
if (summaryResult.status === "invalid_summary_contract") throw createCodedError("invalid_summary_contract", "Auto compact summary body cannot be empty");
const plannedAttempt = finalizeAttemptDiagnostics(baseAttempt, {

@@ -332,17 +350,24 @@ status: "planned",

const summaryInputBudget = Math.max(256, input.summaryInputMaxTokens - DEFAULT_SUMMARY_INPUT_SAFETY_MARGIN);
const summarized = await summarizeRenderedSections({
stage: "source",
remainingLevels: MAX_SUMMARY_RECURSION_PASSES,
prefixSections: renderedInput.prefixSections,
messageSections: renderedInput.messageSections,
summaryInputBudget,
sessionId: input.sessionId,
summaryModel: input.summaryModel,
maxSummaryTokens: input.maxSummaryTokens,
summaryPrompt: input.summaryPrompt,
usageKind: input.usageKind,
model: input.model,
logger: input.logger
});
let summarized;
try {
summarized = await summarizeRenderedSections({
stage: "source",
remainingLevels: MAX_SUMMARY_RECURSION_PASSES,
prefixSections: renderedInput.prefixSections,
messageSections: renderedInput.messageSections,
summaryInputBudget,
sessionId: input.sessionId,
summaryModel: input.summaryModel,
maxSummaryTokens: input.maxSummaryTokens,
summaryPrompt: input.summaryPrompt,
usageKind: input.usageKind,
model: input.model,
logger: input.logger
});
} catch (error) {
if (readErrorCode(error) === "empty_summary_body") return input.existingSummary?.trim() ? { status: "empty_body_preserve_previous" } : { status: "invalid_summary_contract" };
throw error;
}
return {
status: "normalized",
summary: summarized.summary,

@@ -463,4 +488,5 @@ summaryNormalization: summarized.summaryNormalization,

}
if (!text.trim()) throw createCodedError("invalid_summary_contract", "Auto compact summary body cannot be empty");
if (!text.trim()) throw createCodedError("empty_summary_body", "Auto compact summary body cannot be empty");
const normalizedSummary = normalizeContinuationSummary(text);
if (normalizedSummary.status === "empty_body") throw createCodedError("empty_summary_body", "Auto compact summary body cannot be empty");
if (normalizedSummary.normalization !== "plain_text") input.logger.emit({

@@ -657,21 +683,19 @@ level: "warn",

const trimmed = summary.trim();
const openCount = trimmed.split(CONTINUATION_SUMMARY_OPEN_TAG).length - 1;
const closeCount = trimmed.split(CONTINUATION_SUMMARY_CLOSE_TAG).length - 1;
if (!trimmed) return { status: "empty_body" };
const blockMatches = [...trimmed.matchAll(CONTINUATION_SUMMARY_BLOCK_PATTERN)];
if (blockMatches.length > 1) throw createCodedError("invalid_summary_contract", "Auto compact summary must be plain text or contain exactly one <continuation_summary>...</continuation_summary> block");
if (blockMatches.length === 1) {
if (openCount !== 1 || closeCount !== 1) throw createCodedError("invalid_summary_contract", "Auto compact summary must be plain text or contain exactly one <continuation_summary>...</continuation_summary> block");
const blockBodies = blockMatches.map((match) => match?.[1]?.trim() ?? "").filter((body) => body.length > 0);
if (blockBodies.length > 0) {
const [match] = blockMatches;
const body = match?.[1]?.trim();
if (!body) throw createCodedError("invalid_summary_contract", "Auto compact summary body cannot be empty");
return {
summary: renderCanonicalContinuationSummary(body),
normalization: match.index === 0 && match[0].length === trimmed.length ? "wrapped_block" : "extracted_block"
status: "normalized",
summary: renderCanonicalContinuationSummary(blockBodies.join("\n\n")),
normalization: blockMatches.length === 1 && match?.index === 0 && match[0].length === trimmed.length ? "wrapped_block" : "extracted_block"
};
}
if (openCount > 0 || closeCount > 0) throw createCodedError("invalid_summary_contract", "Auto compact summary must be plain text or contain exactly one <continuation_summary>...</continuation_summary> block");
if (!trimmed) throw createCodedError("invalid_summary_contract", "Auto compact summary body cannot be empty");
const stripped = stripContinuationSummaryTagFragments(trimmed).trim();
if (!stripped) return { status: "empty_body" };
return {
summary: renderCanonicalContinuationSummary(trimmed),
normalization: "plain_text"
status: "normalized",
summary: renderCanonicalContinuationSummary(stripped),
normalization: stripped === trimmed ? "plain_text" : "extracted_block"
};

@@ -682,2 +706,5 @@ }

}
function stripContinuationSummaryTagFragments(text) {
return text.replace(CONTINUATION_SUMMARY_TAG_FRAGMENT_PATTERN, "\n");
}
function combineSummaryNormalizationModes(left, right) {

@@ -684,0 +711,0 @@ const rank = {

{
"name": "@archships/dim-plugin-auto-compact",
"version": "0.0.12",
"version": "0.0.13",
"description": "Official auto compaction plugin for dim-agent-sdk.",

@@ -5,0 +5,0 @@ "homepage": "https://dimcode.dev/",

@@ -55,5 +55,5 @@ # @archships/dim-plugin-auto-compact

- summary model calls now opt into the SDK usage ledger with semantic request kinds: threshold-triggered passes record `auto_compaction`, and `session.compact()` summary calls record `manual_compaction`
- the default summary prompt asks the model for plain-text summary body only; runtime wraps accepted output back into one canonical `<continuation_summary>...</continuation_summary>` block, and it continues to accept a single wrapped block with or without surrounding noise for backward compatibility
- multiple wrapper blocks, empty bodies, or malformed wrapper tags still fail with `invalid_summary_contract`
- `lastAttempt` is updated on every threshold-triggered compaction pass with `planned` / `skipped` / `compacted` / `failed`, budget metadata, estimator-based `estimatedInputTokensAfter` / `estimatedSavedTokens`, reason codes such as `missing_summary_model`, `nothing_to_compact`, `summary_generation_failed`, or `compaction_owner_required`, and optional `summaryNormalization` values (`plain_text`, `wrapped_block`, `extracted_block`) when the summary output was inspected
- the default summary prompt asks the model for plain-text summary body only; runtime normalizes accepted output back into one canonical `<continuation_summary>...</continuation_summary>` block before replay, including wrapped blocks, merged multi-block outputs, and malformed-tag fragments that still yield a non-empty semantic body
- when normalization yields an empty body, runtime preserves the previous saved continuation summary when one already exists; only empty output without a previous summary fails with `invalid_summary_contract`
- `lastAttempt` is updated on every threshold-triggered compaction pass with `planned` / `skipped` / `compacted` / `failed`, budget metadata, estimator-based `estimatedInputTokensAfter` / `estimatedSavedTokens`, reason codes such as `missing_summary_model`, `nothing_to_compact`, `empty_summary_preserved_previous`, `summary_generation_failed`, or `compaction_owner_required`, and optional `summaryNormalization` values (`plain_text`, `wrapped_block`, `extracted_block`) when the summary output was inspected
- persisted plugin state keeps only semantic provenance fields; summary-call counters and per-message id arrays stay out of `pluginState`

@@ -60,0 +60,0 @@ - `context.compacted` notifications now include compacted / retained message counts plus estimator-based before / after / saved token fields when budgeting is enabled

Sorry, the diff of this file is too big to display