@agimon-ai/po-autocompact 0.0.0-alpha.3 → 0.0.0-alpha.4
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/README.md +1 -1
- package/dist/{compactionPolicy-BIJJHcBP.cjs → compactionPolicy-BH0jiFUR.cjs} +14 -14
- package/dist/compactionPolicy-BH0jiFUR.cjs.map +1 -0
- package/dist/{compactionPolicy-CDCYTj2b.mjs → compactionPolicy-BwT6SX7k.mjs} +14 -14
- package/dist/compactionPolicy-BwT6SX7k.mjs.map +1 -0
- package/dist/extensions/server.cjs +37 -37
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.mts +1 -1
- package/dist/extensions/server.mjs +41 -41
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/extensions/web.mjs +1 -1
- package/dist/extensions/web.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +8 -8
- package/dist/compactionPolicy-BIJJHcBP.cjs.map +0 -1
- package/dist/compactionPolicy-CDCYTj2b.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ asynchronous checkpoints and combines each checkpoint with subsequent messages.
|
|
|
17
17
|
|
|
18
18
|
## Install
|
|
19
19
|
|
|
20
|
-
`po init`
|
|
20
|
+
`po init` include Autocompact in `default.packages` in `.po/modes.yaml`.
|
|
21
21
|
Remove it or move it to a named layer to change which major modes load it.
|
|
22
22
|
The native session facet is `@agimon-ai/po-autocompact/extensions/server`.
|
|
23
23
|
This package does not provide a Pi extension or terminal UI.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
let _earendil_works_pi_coding_agent = require("@earendil-works/pi-coding-agent");
|
|
2
2
|
//#region src/constants/autocompact.ts
|
|
3
|
-
const STATE_CUSTOM_TYPE = "
|
|
4
|
-
const CHECKPOINT_MESSAGE_TYPE = "
|
|
5
|
-
const CONTEXT_MESSAGE_TYPE = "
|
|
6
|
-
const RESUME_MESSAGE_TYPE = "
|
|
7
|
-
const RUNTIME_STATE_MESSAGE_TYPE = "
|
|
3
|
+
const STATE_CUSTOM_TYPE = "po-autocompact-state";
|
|
4
|
+
const CHECKPOINT_MESSAGE_TYPE = "po-autocompact-checkpoint";
|
|
5
|
+
const CONTEXT_MESSAGE_TYPE = "po-autocompact-context";
|
|
6
|
+
const RESUME_MESSAGE_TYPE = "po-autocompact-resume";
|
|
7
|
+
const RUNTIME_STATE_MESSAGE_TYPE = "po-autocompact-runtime-state";
|
|
8
8
|
const COMPACTION_THRESHOLDS = {
|
|
9
9
|
1: {
|
|
10
10
|
ratio: .5,
|
|
@@ -57,14 +57,14 @@ function isAutocompactMessage(value) {
|
|
|
57
57
|
function contextDetailsFromUnknown(value) {
|
|
58
58
|
if (!isRecord(value) || !isStringArray(value.readFiles) || !isStringArray(value.modifiedFiles)) return void 0;
|
|
59
59
|
if (!Array.isArray(value.retainedMessages) || !value.retainedMessages.every(isAutocompactMessage)) return void 0;
|
|
60
|
-
if (!isRecord(value.
|
|
61
|
-
const marker = value.
|
|
60
|
+
if (!isRecord(value.poAutocompact)) return void 0;
|
|
61
|
+
const marker = value.poAutocompact;
|
|
62
62
|
if (marker.version !== 2 || marker.pass !== 2 && marker.pass !== 3 || typeof marker.cycle !== "number" || typeof marker.requestId !== "string" || typeof marker.snapshotLeafId !== "string" || typeof marker.tokensBefore !== "number") return void 0;
|
|
63
63
|
return {
|
|
64
64
|
readFiles: [...value.readFiles],
|
|
65
65
|
modifiedFiles: [...value.modifiedFiles],
|
|
66
66
|
retainedMessages: [...value.retainedMessages],
|
|
67
|
-
|
|
67
|
+
poAutocompact: {
|
|
68
68
|
version: 2,
|
|
69
69
|
cycle: marker.cycle,
|
|
70
70
|
pass: marker.pass,
|
|
@@ -150,10 +150,10 @@ function effectiveThresholds(contextWindow, baselineTokens = 0, configured = {},
|
|
|
150
150
|
return thresholds;
|
|
151
151
|
}
|
|
152
152
|
function latestCheckpointArtifactEntry(branchEntries) {
|
|
153
|
-
return branchEntries.findLast((entry) => entry.type === "compaction" || entry.type === "custom" && entry.customType === "
|
|
153
|
+
return branchEntries.findLast((entry) => entry.type === "compaction" || entry.type === "custom" && entry.customType === "po-autocompact-checkpoint" || customMessage(entry)?.customType === "po-autocompact-checkpoint" || customMessage(entry)?.customType === "po-autocompact-context");
|
|
154
154
|
}
|
|
155
155
|
function baselineUsageIsSettled(branchEntries) {
|
|
156
|
-
const boundaryIndex = branchEntries.findLastIndex((entry) => entry.type === "compaction" || customMessage(entry)?.customType === "
|
|
156
|
+
const boundaryIndex = branchEntries.findLastIndex((entry) => entry.type === "compaction" || customMessage(entry)?.customType === "po-autocompact-context");
|
|
157
157
|
return branchEntries.slice(boundaryIndex + 1).some((entry) => {
|
|
158
158
|
if (entry.type !== "message" || entry.message.role !== "assistant") return false;
|
|
159
159
|
const { stopReason, usage } = entry.message;
|
|
@@ -176,7 +176,7 @@ function projectContextMessages(messages, branchEntries) {
|
|
|
176
176
|
invalidMarker: true,
|
|
177
177
|
retainedMessageCount: 0
|
|
178
178
|
};
|
|
179
|
-
const markerMessageIndex = messages.findLastIndex((message) => message.role === "custom" && message.customType === "
|
|
179
|
+
const markerMessageIndex = messages.findLastIndex((message) => message.role === "custom" && message.customType === "po-autocompact-context" && contextDetailsFromUnknown(message.details)?.poAutocompact.requestId === details.poAutocompact.requestId);
|
|
180
180
|
if (markerMessageIndex === -1) return {
|
|
181
181
|
messages,
|
|
182
182
|
invalidMarker: true,
|
|
@@ -187,13 +187,13 @@ function projectContextMessages(messages, branchEntries) {
|
|
|
187
187
|
{
|
|
188
188
|
role: "compactionSummary",
|
|
189
189
|
summary,
|
|
190
|
-
tokensBefore: details.
|
|
190
|
+
tokensBefore: details.poAutocompact.tokensBefore,
|
|
191
191
|
timestamp: messages[markerMessageIndex]?.timestamp ?? Date.now()
|
|
192
192
|
},
|
|
193
193
|
...details.retainedMessages,
|
|
194
194
|
...messages.slice(markerMessageIndex + 1)
|
|
195
195
|
],
|
|
196
|
-
marker: details.
|
|
196
|
+
marker: details.poAutocompact,
|
|
197
197
|
retainedMessageCount: details.retainedMessages.length
|
|
198
198
|
};
|
|
199
199
|
}
|
|
@@ -456,4 +456,4 @@ Object.defineProperty(exports, "withCanonicalFileSections", {
|
|
|
456
456
|
}
|
|
457
457
|
});
|
|
458
458
|
|
|
459
|
-
//# sourceMappingURL=compactionPolicy-
|
|
459
|
+
//# sourceMappingURL=compactionPolicy-BH0jiFUR.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compactionPolicy-BH0jiFUR.cjs","names":["DEFAULT_COMPACTION_SETTINGS"],"sources":["../src/constants/autocompact.ts","../src/services/compactionPolicy/index.ts"],"sourcesContent":["export const STATE_CUSTOM_TYPE = 'po-autocompact-state';\nexport const CHECKPOINT_MESSAGE_TYPE = 'po-autocompact-checkpoint';\nexport const CONTEXT_MESSAGE_TYPE = 'po-autocompact-context';\nexport const RESUME_MESSAGE_TYPE = 'po-autocompact-resume';\nexport const RUNTIME_STATE_MESSAGE_TYPE = 'po-autocompact-runtime-state';\nexport const STATE_VERSION = 2;\n/** Retrying a malformed checkpoint costs a full summarization call per turn, so a pass that\n * keeps failing is abandoned instead of retried for the rest of the session. */\nexport const MAX_INVALID_CHECKPOINT_ATTEMPTS = 3;\n\nexport const COMPACTION_THRESHOLDS = {\n 1: { ratio: 0.5, capTokens: 200_000 },\n 2: { ratio: 0.75, capTokens: 500_000 },\n 3: { ratio: 0.95, capTokens: 800_000 },\n} as const;\n\nexport const CHECKPOINT_HEADINGS = [\n '## Goal',\n '## Constraints & Preferences',\n '## Progress',\n '### Done',\n '### In Progress',\n '### Blocked',\n '## Key Decisions',\n '## Next Steps',\n '## Critical Context',\n] as const;\n","import {\n DEFAULT_COMPACTION_SETTINGS,\n type FileOperations,\n type SessionEntry,\n sessionEntryToContextMessages,\n} from '@earendil-works/pi-coding-agent';\n\nimport {\n CHECKPOINT_HEADINGS,\n CHECKPOINT_MESSAGE_TYPE,\n COMPACTION_THRESHOLDS,\n CONTEXT_MESSAGE_TYPE,\n STATE_VERSION,\n} from '../../constants/autocompact';\nimport type {\n AutocompactContextDetails,\n AutocompactFileDetails,\n AutocompactRatioOverrides,\n AutocompactTokenOverrides,\n AutocompactMessage,\n AutocompactPass,\n AutocompactState,\n CheckpointDecision,\n CheckpointRequestDetails,\n ContextProjection,\n} from '../../types/autocompact';\n\n/** V4 projections have numeric timestamps and store custom messages as message entries. */\nexport type NativePolicyEntry = { id: string; timestamp: number } & (\n | { type: 'message'; message: AutocompactMessage }\n | { type: 'custom'; customType: string; data?: unknown }\n | { type: 'compaction'; summary: string; tokensBefore: number; retainedTail: AutocompactMessage[] }\n | { type: 'branch_summary'; summary: string; fromId?: string | null }\n);\nexport type CompactionPolicyEntry = SessionEntry | NativePolicyEntry;\n\nfunction customMessage(entry: CompactionPolicyEntry) {\n if (entry.type === 'custom_message') return entry;\n if (entry.type === 'message' && entry.message.role === 'custom') return entry.message;\n return undefined;\n}\n\n/** Native entries are already projected messages, not Pi journal entries. */\nexport function policyEntryMessages(entry: CompactionPolicyEntry): AutocompactMessage[] {\n if (typeof entry.timestamp === 'string') return sessionEntryToContextMessages(entry as SessionEntry);\n if (entry.type === 'message') return [entry.message];\n if (entry.type === 'compaction' && 'retainedTail' in entry) {\n return [\n {\n role: 'compactionSummary',\n summary: entry.summary,\n tokensBefore: entry.tokensBefore,\n timestamp: entry.timestamp,\n },\n ...entry.retainedTail,\n ];\n }\n if (entry.type === 'branch_summary') {\n return [{ role: 'branchSummary', summary: entry.summary, fromId: entry.fromId ?? '', timestamp: entry.timestamp }];\n }\n return [];\n}\n\nconst SHOULD_COMPACT_PATTERN = /<shouldCompact>\\s*(true|false)\\s*<\\/shouldCompact>/i;\nconst FILE_SECTION_PATTERN = /\\n*<(?:read-files|modified-files)>[\\s\\S]*?<\\/(?:read-files|modified-files)>/g;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((item) => typeof item === 'string');\n}\n\nfunction isPass(value: unknown): value is AutocompactPass {\n return value === 1 || value === 2 || value === 3;\n}\n\nfunction assistantText(entry: CompactionPolicyEntry): string | undefined {\n if (entry.type !== 'message' || entry.message.role !== 'assistant') return undefined;\n const text = entry.message.content\n .filter((block) => block.type === 'text')\n .map((block) => block.text)\n .join('\\n')\n .trim();\n return text || undefined;\n}\n\nfunction isAutocompactMessage(value: unknown): value is AutocompactMessage {\n return isRecord(value) && typeof value.role === 'string';\n}\n\nexport function contextDetailsFromUnknown(value: unknown): AutocompactContextDetails | undefined {\n if (!isRecord(value) || !isStringArray(value.readFiles) || !isStringArray(value.modifiedFiles)) return undefined;\n if (!Array.isArray(value.retainedMessages) || !value.retainedMessages.every(isAutocompactMessage)) return undefined;\n if (!isRecord(value.poAutocompact)) return undefined;\n const marker = value.poAutocompact;\n if (\n marker.version !== STATE_VERSION ||\n (marker.pass !== 2 && marker.pass !== 3) ||\n typeof marker.cycle !== 'number' ||\n typeof marker.requestId !== 'string' ||\n typeof marker.snapshotLeafId !== 'string' ||\n typeof marker.tokensBefore !== 'number'\n )\n return undefined;\n return {\n readFiles: [...value.readFiles],\n modifiedFiles: [...value.modifiedFiles],\n retainedMessages: [...value.retainedMessages],\n poAutocompact: {\n version: STATE_VERSION,\n cycle: marker.cycle,\n pass: marker.pass,\n requestId: marker.requestId,\n snapshotLeafId: marker.snapshotLeafId,\n tokensBefore: marker.tokensBefore,\n },\n };\n}\n\nexport function createInitialState(): AutocompactState {\n return {\n version: STATE_VERSION,\n cycle: 1,\n pass: 1,\n phase: 'waiting',\n checkpointQueue: [],\n exhaustedPasses: [],\n invalidAttempts: 0,\n baselineTokens: 0,\n baselinePending: false,\n readFiles: [],\n modifiedFiles: [],\n };\n}\n\n/**\n * The ratios each pass fires at, with configured values folded in.\n *\n * The ladder only works if it climbs, so a configured pass never sits below the\n * one before it: a file that says pass 2 fires earlier than pass 1 gets pass 1's\n * ratio for pass 2 rather than a pass that can never contribute.\n */\nexport function compactionRatios(configured: AutocompactRatioOverrides = {}): Record<AutocompactPass, number> {\n let previous = 0;\n const ratios = {} as Record<AutocompactPass, number>;\n for (const pass of [1, 2, 3] as const) {\n const ratio = Math.max(configured[pass] ?? COMPACTION_THRESHOLDS[pass].ratio, previous);\n ratios[pass] = ratio;\n previous = ratio;\n }\n return ratios;\n}\n\nexport function thresholdTokens(\n pass: AutocompactPass,\n contextWindow: number,\n baselineTokens = 0,\n configured: AutocompactRatioOverrides = {},\n): number {\n const threshold = COMPACTION_THRESHOLDS[pass];\n const ratio = compactionRatios(configured)[pass];\n const baseline = Math.max(0, Math.min(baselineTokens, contextWindow));\n const remaining = contextWindow - baseline;\n const staged = baseline + Math.min(Math.floor(remaining * ratio), threshold.capTokens);\n // Pi compacts natively above `contextWindow - reserveTokens`. A staged threshold above that\n // point can never fire, so the ladder would silently degrade into native compaction: on a\n // 200k window the raw pass 3 ratio lands at 190_000, while Pi already compacted at 183_616.\n const nativeTrigger = contextWindow - DEFAULT_COMPACTION_SETTINGS.reserveTokens;\n return nativeTrigger > baseline ? Math.min(staged, nativeTrigger) : staged;\n}\n\n/**\n * Where every pass fires, with a matching model's absolute token checkpoints folded in.\n *\n * A configured token count replaces the ratio only when it fires earlier, so an\n * override can bring a checkpoint forward on a very large window without ever\n * pushing one past the point Pi compacts natively.\n *\n * Two rules keep the ladder usable. A token count at or below the baseline is\n * ignored, because a compaction that lands above it would otherwise satisfy that\n * pass the moment the next cycle opens and re-fire it every turn. And a pass never\n * sits below the one before it, for the same reason {@link compactionRatios}\n * climbs: `evaluateUsage` skips any pass below the one already reached, so a later\n * pass that fires first does not merely reorder the ladder, it locks the earlier\n * passes out of the cycle and forces compaction with no summary ever written.\n */\nexport function effectiveThresholds(\n contextWindow: number,\n baselineTokens = 0,\n configured: AutocompactRatioOverrides = {},\n tokenOverrides: AutocompactTokenOverrides = {},\n): Record<AutocompactPass, number> {\n let previous = 0;\n const thresholds = {} as Record<AutocompactPass, number>;\n for (const pass of [1, 2, 3] as const) {\n const ratioTokens = thresholdTokens(pass, contextWindow, baselineTokens, configured);\n const absolute = tokenOverrides[pass];\n const staged = absolute !== undefined && absolute > baselineTokens ? Math.min(ratioTokens, absolute) : ratioTokens;\n thresholds[pass] = Math.max(staged, previous);\n previous = thresholds[pass];\n }\n return thresholds;\n}\nexport function latestCheckpointArtifactEntry(\n branchEntries: readonly CompactionPolicyEntry[],\n): CompactionPolicyEntry | undefined {\n return branchEntries.findLast(\n (entry) =>\n entry.type === 'compaction' ||\n // Staged checkpoints are plain entries so they stay out of the agent's LLM context.\n (entry.type === 'custom' && entry.customType === CHECKPOINT_MESSAGE_TYPE) ||\n // Legacy sessions staged checkpoints as custom messages; committed markers still are.\n customMessage(entry)?.customType === CHECKPOINT_MESSAGE_TYPE ||\n customMessage(entry)?.customType === CONTEXT_MESSAGE_TYPE,\n );\n}\n\nexport function baselineUsageIsSettled(branchEntries: readonly CompactionPolicyEntry[]): boolean {\n const boundaryIndex = branchEntries.findLastIndex(\n (entry) => entry.type === 'compaction' || customMessage(entry)?.customType === CONTEXT_MESSAGE_TYPE,\n );\n return branchEntries.slice(boundaryIndex + 1).some((entry) => {\n if (entry.type !== 'message' || entry.message.role !== 'assistant') return false;\n const { stopReason, usage } = entry.message;\n if (stopReason === 'aborted' || stopReason === 'error' || !usage) return false;\n return (usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite) > 0;\n });\n}\n\nexport function retainedMessagesAfterSnapshot(\n branchEntries: readonly CompactionPolicyEntry[],\n snapshotLeafId: string,\n): AutocompactMessage[] {\n const snapshotIndex = branchEntries.findIndex((entry) => entry.id === snapshotLeafId);\n if (snapshotIndex === -1) return [];\n return branchEntries\n .slice(snapshotIndex + 1)\n .filter((entry) => customMessage(entry)?.customType !== CHECKPOINT_MESSAGE_TYPE)\n .flatMap(policyEntryMessages);\n}\n\nexport function projectContextMessages(\n messages: AutocompactMessage[],\n branchEntries: readonly CompactionPolicyEntry[],\n): ContextProjection {\n const nativeCompactionIndex = branchEntries.findLastIndex((entry) => entry.type === 'compaction');\n const markerEntry = branchEntries\n .slice(nativeCompactionIndex + 1)\n .findLast((entry) => customMessage(entry)?.customType === CONTEXT_MESSAGE_TYPE);\n const markerMessage = markerEntry && customMessage(markerEntry);\n if (!markerEntry || !markerMessage) {\n return { messages, retainedMessageCount: 0 };\n }\n\n const details = contextDetailsFromUnknown(markerMessage.details);\n const summary = checkpointSummaryFromEntry(markerEntry);\n if (!details || !summary) return { messages, invalidMarker: true, retainedMessageCount: 0 };\n\n const markerMessageIndex = messages.findLastIndex(\n (message) =>\n message.role === 'custom' &&\n message.customType === CONTEXT_MESSAGE_TYPE &&\n contextDetailsFromUnknown(message.details)?.poAutocompact.requestId === details.poAutocompact.requestId,\n );\n if (markerMessageIndex === -1) return { messages, invalidMarker: true, retainedMessageCount: 0 };\n\n const summaryMessage: AutocompactMessage = {\n role: 'compactionSummary',\n summary,\n tokensBefore: details.poAutocompact.tokensBefore,\n timestamp: messages[markerMessageIndex]?.timestamp ?? Date.now(),\n };\n return {\n messages: [summaryMessage, ...details.retainedMessages, ...messages.slice(markerMessageIndex + 1)],\n marker: details.poAutocompact,\n retainedMessageCount: details.retainedMessages.length,\n };\n}\n\nexport function fileOperationsFromMessages(messages: AutocompactMessage[]): FileOperations {\n const fileOps: FileOperations = { read: new Set(), written: new Set(), edited: new Set() };\n for (const message of messages) {\n if (message.role !== 'assistant') continue;\n for (const block of message.content) {\n if (block.type !== 'toolCall') continue;\n const path = typeof block.arguments.path === 'string' ? block.arguments.path : undefined;\n if (!path) continue;\n if (block.name === 'read') fileOps.read.add(path);\n else if (block.name === 'write') fileOps.written.add(path);\n else if (block.name === 'edit') fileOps.edited.add(path);\n }\n }\n return fileOps;\n}\n\nexport function parseState(value: unknown): AutocompactState | undefined {\n if (!isRecord(value)) return undefined;\n if (value.version !== STATE_VERSION || typeof value.cycle !== 'number' || !isPass(value.pass)) return undefined;\n if (\n value.phase !== 'waiting' &&\n value.phase !== 'checkpoint_pending' &&\n value.phase !== 'checkpoint_ready' &&\n value.phase !== 'compacting'\n )\n return undefined;\n const baselineTokens = value.baselineTokens ?? 0;\n if (typeof baselineTokens !== 'number' || baselineTokens < 0) return undefined;\n const baselinePending = value.baselinePending ?? false;\n if (typeof baselinePending !== 'boolean') return undefined;\n const checkpointQueue = value.checkpointQueue ?? [];\n if (\n !Array.isArray(checkpointQueue) ||\n !checkpointQueue.every(isPass) ||\n checkpointQueue.some((pass, index) => index > 0 && pass <= checkpointQueue[index - 1]!)\n )\n return undefined;\n // Sessions persisted before bounded retry landed simply have no attempt history to restore.\n const exhaustedPasses = value.exhaustedPasses ?? [];\n if (!Array.isArray(exhaustedPasses) || !exhaustedPasses.every(isPass)) return undefined;\n const invalidAttempts = value.invalidAttempts ?? 0;\n if (typeof invalidAttempts !== 'number' || invalidAttempts < 0) return undefined;\n if (!isStringArray(value.readFiles) || !isStringArray(value.modifiedFiles)) return undefined;\n if (value.requestId !== undefined && typeof value.requestId !== 'string') return undefined;\n if (value.compactionPass !== undefined && value.compactionPass !== 2 && value.compactionPass !== 3) return undefined;\n if ('latestCheckpointEntryId' in value) return undefined;\n if (value.latestCheckpointSnapshotLeafId !== undefined && typeof value.latestCheckpointSnapshotLeafId !== 'string')\n return undefined;\n if (value.lastAttemptLeafId !== undefined && typeof value.lastAttemptLeafId !== 'string') return undefined;\n if (value.snapshotLeafId !== undefined && typeof value.snapshotLeafId !== 'string') return undefined;\n if (value.snapshotTokens !== undefined && (typeof value.snapshotTokens !== 'number' || value.snapshotTokens < 0))\n return undefined;\n if (value.pendingCheckpoint !== undefined && typeof value.pendingCheckpoint !== 'string') return undefined;\n\n return {\n version: STATE_VERSION,\n cycle: value.cycle,\n pass: value.pass,\n phase: value.phase,\n checkpointQueue: [...checkpointQueue],\n exhaustedPasses: [...exhaustedPasses],\n invalidAttempts,\n baselineTokens,\n baselinePending,\n readFiles: [...value.readFiles],\n modifiedFiles: [...value.modifiedFiles],\n ...(value.requestId ? { requestId: value.requestId } : {}),\n ...(value.compactionPass ? { compactionPass: value.compactionPass } : {}),\n ...(value.latestCheckpointSnapshotLeafId\n ? { latestCheckpointSnapshotLeafId: value.latestCheckpointSnapshotLeafId }\n : {}),\n ...(value.lastAttemptLeafId ? { lastAttemptLeafId: value.lastAttemptLeafId } : {}),\n ...(value.snapshotLeafId ? { snapshotLeafId: value.snapshotLeafId } : {}),\n ...(value.snapshotTokens !== undefined ? { snapshotTokens: value.snapshotTokens } : {}),\n ...(value.pendingCheckpoint ? { pendingCheckpoint: value.pendingCheckpoint } : {}),\n };\n}\n\nexport function checkpointSummaryFromEntry(entry: CompactionPolicyEntry | undefined): string | undefined {\n if (!entry) return undefined;\n if (entry.type === 'compaction') return entry.summary.trim() || undefined;\n if (entry.type === 'custom') {\n return isRecord(entry.data) && typeof entry.data.summary === 'string'\n ? entry.data.summary.trim() || undefined\n : undefined;\n }\n const marker = customMessage(entry);\n if (marker) {\n const content =\n typeof marker.content === 'string'\n ? marker.content\n : marker.content\n .filter((block) => block.type === 'text')\n .map((block) => block.text)\n .join('\\n');\n return content.trim() || undefined;\n }\n return assistantText(entry);\n}\n\nexport function parseCheckpointDecision(response: string): CheckpointDecision {\n const match = response.match(SHOULD_COMPACT_PATTERN);\n const summary = response.replace(SHOULD_COMPACT_PATTERN, '').trim();\n if (!match) return { summary };\n return { summary, shouldCompact: match[1]?.toLowerCase() === 'true' };\n}\n\nexport function isStructuredCheckpoint(summary: string): boolean {\n return CHECKPOINT_HEADINGS.every((heading) => summary.includes(heading));\n}\n\nexport function createRequestId(\n sessionId: string,\n cycle: number,\n pass: AutocompactPass,\n leafId: string | null,\n): string {\n return `${sessionId}:${cycle}:${pass}:${leafId ?? 'root'}`;\n}\n\nexport function checkpointRequestDetails(\n cycle: number,\n pass: AutocompactPass,\n requestId: string,\n): CheckpointRequestDetails {\n return { version: STATE_VERSION, cycle, pass, requestId };\n}\n\nexport function mergeFileDetails(\n current: AutocompactFileDetails,\n fileOps?: FileOperations,\n additional?: AutocompactFileDetails,\n): AutocompactFileDetails {\n const modified = new Set([\n ...current.modifiedFiles,\n ...(additional?.modifiedFiles ?? []),\n ...(fileOps ? [...fileOps.edited, ...fileOps.written] : []),\n ]);\n const read = new Set([...current.readFiles, ...(additional?.readFiles ?? []), ...(fileOps ? [...fileOps.read] : [])]);\n for (const path of modified) read.delete(path);\n return { readFiles: [...read].sort(), modifiedFiles: [...modified].sort() };\n}\n\nexport function fileDetailsFromUnknown(value: unknown): AutocompactFileDetails | undefined {\n if (!isRecord(value) || !isStringArray(value.readFiles) || !isStringArray(value.modifiedFiles)) return undefined;\n return { readFiles: value.readFiles, modifiedFiles: value.modifiedFiles };\n}\n\nexport function withCanonicalFileSections(summary: string, details: AutocompactFileDetails): string {\n const sections: string[] = [];\n if (details.readFiles.length > 0) sections.push(`<read-files>\\n${details.readFiles.join('\\n')}\\n</read-files>`);\n if (details.modifiedFiles.length > 0) {\n sections.push(`<modified-files>\\n${details.modifiedFiles.join('\\n')}\\n</modified-files>`);\n }\n const normalized = summary.replace(FILE_SECTION_PATTERN, '').trim();\n return sections.length > 0 ? `${normalized}\\n\\n${sections.join('\\n\\n')}` : normalized;\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { DEFAULT_COMPACTION_SETTINGS } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
//#region src/constants/autocompact.ts
|
|
3
|
-
const STATE_CUSTOM_TYPE = "
|
|
4
|
-
const CHECKPOINT_MESSAGE_TYPE = "
|
|
5
|
-
const CONTEXT_MESSAGE_TYPE = "
|
|
6
|
-
const RESUME_MESSAGE_TYPE = "
|
|
7
|
-
const RUNTIME_STATE_MESSAGE_TYPE = "
|
|
3
|
+
const STATE_CUSTOM_TYPE = "po-autocompact-state";
|
|
4
|
+
const CHECKPOINT_MESSAGE_TYPE = "po-autocompact-checkpoint";
|
|
5
|
+
const CONTEXT_MESSAGE_TYPE = "po-autocompact-context";
|
|
6
|
+
const RESUME_MESSAGE_TYPE = "po-autocompact-resume";
|
|
7
|
+
const RUNTIME_STATE_MESSAGE_TYPE = "po-autocompact-runtime-state";
|
|
8
8
|
const COMPACTION_THRESHOLDS = {
|
|
9
9
|
1: {
|
|
10
10
|
ratio: .5,
|
|
@@ -57,14 +57,14 @@ function isAutocompactMessage(value) {
|
|
|
57
57
|
function contextDetailsFromUnknown(value) {
|
|
58
58
|
if (!isRecord(value) || !isStringArray(value.readFiles) || !isStringArray(value.modifiedFiles)) return void 0;
|
|
59
59
|
if (!Array.isArray(value.retainedMessages) || !value.retainedMessages.every(isAutocompactMessage)) return void 0;
|
|
60
|
-
if (!isRecord(value.
|
|
61
|
-
const marker = value.
|
|
60
|
+
if (!isRecord(value.poAutocompact)) return void 0;
|
|
61
|
+
const marker = value.poAutocompact;
|
|
62
62
|
if (marker.version !== 2 || marker.pass !== 2 && marker.pass !== 3 || typeof marker.cycle !== "number" || typeof marker.requestId !== "string" || typeof marker.snapshotLeafId !== "string" || typeof marker.tokensBefore !== "number") return void 0;
|
|
63
63
|
return {
|
|
64
64
|
readFiles: [...value.readFiles],
|
|
65
65
|
modifiedFiles: [...value.modifiedFiles],
|
|
66
66
|
retainedMessages: [...value.retainedMessages],
|
|
67
|
-
|
|
67
|
+
poAutocompact: {
|
|
68
68
|
version: 2,
|
|
69
69
|
cycle: marker.cycle,
|
|
70
70
|
pass: marker.pass,
|
|
@@ -150,10 +150,10 @@ function effectiveThresholds(contextWindow, baselineTokens = 0, configured = {},
|
|
|
150
150
|
return thresholds;
|
|
151
151
|
}
|
|
152
152
|
function latestCheckpointArtifactEntry(branchEntries) {
|
|
153
|
-
return branchEntries.findLast((entry) => entry.type === "compaction" || entry.type === "custom" && entry.customType === "
|
|
153
|
+
return branchEntries.findLast((entry) => entry.type === "compaction" || entry.type === "custom" && entry.customType === "po-autocompact-checkpoint" || customMessage(entry)?.customType === "po-autocompact-checkpoint" || customMessage(entry)?.customType === "po-autocompact-context");
|
|
154
154
|
}
|
|
155
155
|
function baselineUsageIsSettled(branchEntries) {
|
|
156
|
-
const boundaryIndex = branchEntries.findLastIndex((entry) => entry.type === "compaction" || customMessage(entry)?.customType === "
|
|
156
|
+
const boundaryIndex = branchEntries.findLastIndex((entry) => entry.type === "compaction" || customMessage(entry)?.customType === "po-autocompact-context");
|
|
157
157
|
return branchEntries.slice(boundaryIndex + 1).some((entry) => {
|
|
158
158
|
if (entry.type !== "message" || entry.message.role !== "assistant") return false;
|
|
159
159
|
const { stopReason, usage } = entry.message;
|
|
@@ -176,7 +176,7 @@ function projectContextMessages(messages, branchEntries) {
|
|
|
176
176
|
invalidMarker: true,
|
|
177
177
|
retainedMessageCount: 0
|
|
178
178
|
};
|
|
179
|
-
const markerMessageIndex = messages.findLastIndex((message) => message.role === "custom" && message.customType === "
|
|
179
|
+
const markerMessageIndex = messages.findLastIndex((message) => message.role === "custom" && message.customType === "po-autocompact-context" && contextDetailsFromUnknown(message.details)?.poAutocompact.requestId === details.poAutocompact.requestId);
|
|
180
180
|
if (markerMessageIndex === -1) return {
|
|
181
181
|
messages,
|
|
182
182
|
invalidMarker: true,
|
|
@@ -187,13 +187,13 @@ function projectContextMessages(messages, branchEntries) {
|
|
|
187
187
|
{
|
|
188
188
|
role: "compactionSummary",
|
|
189
189
|
summary,
|
|
190
|
-
tokensBefore: details.
|
|
190
|
+
tokensBefore: details.poAutocompact.tokensBefore,
|
|
191
191
|
timestamp: messages[markerMessageIndex]?.timestamp ?? Date.now()
|
|
192
192
|
},
|
|
193
193
|
...details.retainedMessages,
|
|
194
194
|
...messages.slice(markerMessageIndex + 1)
|
|
195
195
|
],
|
|
196
|
-
marker: details.
|
|
196
|
+
marker: details.poAutocompact,
|
|
197
197
|
retainedMessageCount: details.retainedMessages.length
|
|
198
198
|
};
|
|
199
199
|
}
|
|
@@ -325,4 +325,4 @@ function withCanonicalFileSections(summary, details) {
|
|
|
325
325
|
//#endregion
|
|
326
326
|
export { STATE_CUSTOM_TYPE as S, withCanonicalFileSections as _, createInitialState as a, RESUME_MESSAGE_TYPE as b, fileDetailsFromUnknown as c, latestCheckpointArtifactEntry as d, mergeFileDetails as f, thresholdTokens as g, projectContextMessages as h, contextDetailsFromUnknown as i, fileOperationsFromMessages as l, parseState as m, checkpointRequestDetails as n, createRequestId as o, parseCheckpointDecision as p, checkpointSummaryFromEntry as r, effectiveThresholds as s, baselineUsageIsSettled as t, isStructuredCheckpoint as u, CHECKPOINT_MESSAGE_TYPE as v, RUNTIME_STATE_MESSAGE_TYPE as x, CONTEXT_MESSAGE_TYPE as y };
|
|
327
327
|
|
|
328
|
-
//# sourceMappingURL=compactionPolicy-
|
|
328
|
+
//# sourceMappingURL=compactionPolicy-BwT6SX7k.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compactionPolicy-BwT6SX7k.mjs","names":[],"sources":["../src/constants/autocompact.ts","../src/services/compactionPolicy/index.ts"],"sourcesContent":["export const STATE_CUSTOM_TYPE = 'po-autocompact-state';\nexport const CHECKPOINT_MESSAGE_TYPE = 'po-autocompact-checkpoint';\nexport const CONTEXT_MESSAGE_TYPE = 'po-autocompact-context';\nexport const RESUME_MESSAGE_TYPE = 'po-autocompact-resume';\nexport const RUNTIME_STATE_MESSAGE_TYPE = 'po-autocompact-runtime-state';\nexport const STATE_VERSION = 2;\n/** Retrying a malformed checkpoint costs a full summarization call per turn, so a pass that\n * keeps failing is abandoned instead of retried for the rest of the session. */\nexport const MAX_INVALID_CHECKPOINT_ATTEMPTS = 3;\n\nexport const COMPACTION_THRESHOLDS = {\n 1: { ratio: 0.5, capTokens: 200_000 },\n 2: { ratio: 0.75, capTokens: 500_000 },\n 3: { ratio: 0.95, capTokens: 800_000 },\n} as const;\n\nexport const CHECKPOINT_HEADINGS = [\n '## Goal',\n '## Constraints & Preferences',\n '## Progress',\n '### Done',\n '### In Progress',\n '### Blocked',\n '## Key Decisions',\n '## Next Steps',\n '## Critical Context',\n] as const;\n","import {\n DEFAULT_COMPACTION_SETTINGS,\n type FileOperations,\n type SessionEntry,\n sessionEntryToContextMessages,\n} from '@earendil-works/pi-coding-agent';\n\nimport {\n CHECKPOINT_HEADINGS,\n CHECKPOINT_MESSAGE_TYPE,\n COMPACTION_THRESHOLDS,\n CONTEXT_MESSAGE_TYPE,\n STATE_VERSION,\n} from '../../constants/autocompact';\nimport type {\n AutocompactContextDetails,\n AutocompactFileDetails,\n AutocompactRatioOverrides,\n AutocompactTokenOverrides,\n AutocompactMessage,\n AutocompactPass,\n AutocompactState,\n CheckpointDecision,\n CheckpointRequestDetails,\n ContextProjection,\n} from '../../types/autocompact';\n\n/** V4 projections have numeric timestamps and store custom messages as message entries. */\nexport type NativePolicyEntry = { id: string; timestamp: number } & (\n | { type: 'message'; message: AutocompactMessage }\n | { type: 'custom'; customType: string; data?: unknown }\n | { type: 'compaction'; summary: string; tokensBefore: number; retainedTail: AutocompactMessage[] }\n | { type: 'branch_summary'; summary: string; fromId?: string | null }\n);\nexport type CompactionPolicyEntry = SessionEntry | NativePolicyEntry;\n\nfunction customMessage(entry: CompactionPolicyEntry) {\n if (entry.type === 'custom_message') return entry;\n if (entry.type === 'message' && entry.message.role === 'custom') return entry.message;\n return undefined;\n}\n\n/** Native entries are already projected messages, not Pi journal entries. */\nexport function policyEntryMessages(entry: CompactionPolicyEntry): AutocompactMessage[] {\n if (typeof entry.timestamp === 'string') return sessionEntryToContextMessages(entry as SessionEntry);\n if (entry.type === 'message') return [entry.message];\n if (entry.type === 'compaction' && 'retainedTail' in entry) {\n return [\n {\n role: 'compactionSummary',\n summary: entry.summary,\n tokensBefore: entry.tokensBefore,\n timestamp: entry.timestamp,\n },\n ...entry.retainedTail,\n ];\n }\n if (entry.type === 'branch_summary') {\n return [{ role: 'branchSummary', summary: entry.summary, fromId: entry.fromId ?? '', timestamp: entry.timestamp }];\n }\n return [];\n}\n\nconst SHOULD_COMPACT_PATTERN = /<shouldCompact>\\s*(true|false)\\s*<\\/shouldCompact>/i;\nconst FILE_SECTION_PATTERN = /\\n*<(?:read-files|modified-files)>[\\s\\S]*?<\\/(?:read-files|modified-files)>/g;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((item) => typeof item === 'string');\n}\n\nfunction isPass(value: unknown): value is AutocompactPass {\n return value === 1 || value === 2 || value === 3;\n}\n\nfunction assistantText(entry: CompactionPolicyEntry): string | undefined {\n if (entry.type !== 'message' || entry.message.role !== 'assistant') return undefined;\n const text = entry.message.content\n .filter((block) => block.type === 'text')\n .map((block) => block.text)\n .join('\\n')\n .trim();\n return text || undefined;\n}\n\nfunction isAutocompactMessage(value: unknown): value is AutocompactMessage {\n return isRecord(value) && typeof value.role === 'string';\n}\n\nexport function contextDetailsFromUnknown(value: unknown): AutocompactContextDetails | undefined {\n if (!isRecord(value) || !isStringArray(value.readFiles) || !isStringArray(value.modifiedFiles)) return undefined;\n if (!Array.isArray(value.retainedMessages) || !value.retainedMessages.every(isAutocompactMessage)) return undefined;\n if (!isRecord(value.poAutocompact)) return undefined;\n const marker = value.poAutocompact;\n if (\n marker.version !== STATE_VERSION ||\n (marker.pass !== 2 && marker.pass !== 3) ||\n typeof marker.cycle !== 'number' ||\n typeof marker.requestId !== 'string' ||\n typeof marker.snapshotLeafId !== 'string' ||\n typeof marker.tokensBefore !== 'number'\n )\n return undefined;\n return {\n readFiles: [...value.readFiles],\n modifiedFiles: [...value.modifiedFiles],\n retainedMessages: [...value.retainedMessages],\n poAutocompact: {\n version: STATE_VERSION,\n cycle: marker.cycle,\n pass: marker.pass,\n requestId: marker.requestId,\n snapshotLeafId: marker.snapshotLeafId,\n tokensBefore: marker.tokensBefore,\n },\n };\n}\n\nexport function createInitialState(): AutocompactState {\n return {\n version: STATE_VERSION,\n cycle: 1,\n pass: 1,\n phase: 'waiting',\n checkpointQueue: [],\n exhaustedPasses: [],\n invalidAttempts: 0,\n baselineTokens: 0,\n baselinePending: false,\n readFiles: [],\n modifiedFiles: [],\n };\n}\n\n/**\n * The ratios each pass fires at, with configured values folded in.\n *\n * The ladder only works if it climbs, so a configured pass never sits below the\n * one before it: a file that says pass 2 fires earlier than pass 1 gets pass 1's\n * ratio for pass 2 rather than a pass that can never contribute.\n */\nexport function compactionRatios(configured: AutocompactRatioOverrides = {}): Record<AutocompactPass, number> {\n let previous = 0;\n const ratios = {} as Record<AutocompactPass, number>;\n for (const pass of [1, 2, 3] as const) {\n const ratio = Math.max(configured[pass] ?? COMPACTION_THRESHOLDS[pass].ratio, previous);\n ratios[pass] = ratio;\n previous = ratio;\n }\n return ratios;\n}\n\nexport function thresholdTokens(\n pass: AutocompactPass,\n contextWindow: number,\n baselineTokens = 0,\n configured: AutocompactRatioOverrides = {},\n): number {\n const threshold = COMPACTION_THRESHOLDS[pass];\n const ratio = compactionRatios(configured)[pass];\n const baseline = Math.max(0, Math.min(baselineTokens, contextWindow));\n const remaining = contextWindow - baseline;\n const staged = baseline + Math.min(Math.floor(remaining * ratio), threshold.capTokens);\n // Pi compacts natively above `contextWindow - reserveTokens`. A staged threshold above that\n // point can never fire, so the ladder would silently degrade into native compaction: on a\n // 200k window the raw pass 3 ratio lands at 190_000, while Pi already compacted at 183_616.\n const nativeTrigger = contextWindow - DEFAULT_COMPACTION_SETTINGS.reserveTokens;\n return nativeTrigger > baseline ? Math.min(staged, nativeTrigger) : staged;\n}\n\n/**\n * Where every pass fires, with a matching model's absolute token checkpoints folded in.\n *\n * A configured token count replaces the ratio only when it fires earlier, so an\n * override can bring a checkpoint forward on a very large window without ever\n * pushing one past the point Pi compacts natively.\n *\n * Two rules keep the ladder usable. A token count at or below the baseline is\n * ignored, because a compaction that lands above it would otherwise satisfy that\n * pass the moment the next cycle opens and re-fire it every turn. And a pass never\n * sits below the one before it, for the same reason {@link compactionRatios}\n * climbs: `evaluateUsage` skips any pass below the one already reached, so a later\n * pass that fires first does not merely reorder the ladder, it locks the earlier\n * passes out of the cycle and forces compaction with no summary ever written.\n */\nexport function effectiveThresholds(\n contextWindow: number,\n baselineTokens = 0,\n configured: AutocompactRatioOverrides = {},\n tokenOverrides: AutocompactTokenOverrides = {},\n): Record<AutocompactPass, number> {\n let previous = 0;\n const thresholds = {} as Record<AutocompactPass, number>;\n for (const pass of [1, 2, 3] as const) {\n const ratioTokens = thresholdTokens(pass, contextWindow, baselineTokens, configured);\n const absolute = tokenOverrides[pass];\n const staged = absolute !== undefined && absolute > baselineTokens ? Math.min(ratioTokens, absolute) : ratioTokens;\n thresholds[pass] = Math.max(staged, previous);\n previous = thresholds[pass];\n }\n return thresholds;\n}\nexport function latestCheckpointArtifactEntry(\n branchEntries: readonly CompactionPolicyEntry[],\n): CompactionPolicyEntry | undefined {\n return branchEntries.findLast(\n (entry) =>\n entry.type === 'compaction' ||\n // Staged checkpoints are plain entries so they stay out of the agent's LLM context.\n (entry.type === 'custom' && entry.customType === CHECKPOINT_MESSAGE_TYPE) ||\n // Legacy sessions staged checkpoints as custom messages; committed markers still are.\n customMessage(entry)?.customType === CHECKPOINT_MESSAGE_TYPE ||\n customMessage(entry)?.customType === CONTEXT_MESSAGE_TYPE,\n );\n}\n\nexport function baselineUsageIsSettled(branchEntries: readonly CompactionPolicyEntry[]): boolean {\n const boundaryIndex = branchEntries.findLastIndex(\n (entry) => entry.type === 'compaction' || customMessage(entry)?.customType === CONTEXT_MESSAGE_TYPE,\n );\n return branchEntries.slice(boundaryIndex + 1).some((entry) => {\n if (entry.type !== 'message' || entry.message.role !== 'assistant') return false;\n const { stopReason, usage } = entry.message;\n if (stopReason === 'aborted' || stopReason === 'error' || !usage) return false;\n return (usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite) > 0;\n });\n}\n\nexport function retainedMessagesAfterSnapshot(\n branchEntries: readonly CompactionPolicyEntry[],\n snapshotLeafId: string,\n): AutocompactMessage[] {\n const snapshotIndex = branchEntries.findIndex((entry) => entry.id === snapshotLeafId);\n if (snapshotIndex === -1) return [];\n return branchEntries\n .slice(snapshotIndex + 1)\n .filter((entry) => customMessage(entry)?.customType !== CHECKPOINT_MESSAGE_TYPE)\n .flatMap(policyEntryMessages);\n}\n\nexport function projectContextMessages(\n messages: AutocompactMessage[],\n branchEntries: readonly CompactionPolicyEntry[],\n): ContextProjection {\n const nativeCompactionIndex = branchEntries.findLastIndex((entry) => entry.type === 'compaction');\n const markerEntry = branchEntries\n .slice(nativeCompactionIndex + 1)\n .findLast((entry) => customMessage(entry)?.customType === CONTEXT_MESSAGE_TYPE);\n const markerMessage = markerEntry && customMessage(markerEntry);\n if (!markerEntry || !markerMessage) {\n return { messages, retainedMessageCount: 0 };\n }\n\n const details = contextDetailsFromUnknown(markerMessage.details);\n const summary = checkpointSummaryFromEntry(markerEntry);\n if (!details || !summary) return { messages, invalidMarker: true, retainedMessageCount: 0 };\n\n const markerMessageIndex = messages.findLastIndex(\n (message) =>\n message.role === 'custom' &&\n message.customType === CONTEXT_MESSAGE_TYPE &&\n contextDetailsFromUnknown(message.details)?.poAutocompact.requestId === details.poAutocompact.requestId,\n );\n if (markerMessageIndex === -1) return { messages, invalidMarker: true, retainedMessageCount: 0 };\n\n const summaryMessage: AutocompactMessage = {\n role: 'compactionSummary',\n summary,\n tokensBefore: details.poAutocompact.tokensBefore,\n timestamp: messages[markerMessageIndex]?.timestamp ?? Date.now(),\n };\n return {\n messages: [summaryMessage, ...details.retainedMessages, ...messages.slice(markerMessageIndex + 1)],\n marker: details.poAutocompact,\n retainedMessageCount: details.retainedMessages.length,\n };\n}\n\nexport function fileOperationsFromMessages(messages: AutocompactMessage[]): FileOperations {\n const fileOps: FileOperations = { read: new Set(), written: new Set(), edited: new Set() };\n for (const message of messages) {\n if (message.role !== 'assistant') continue;\n for (const block of message.content) {\n if (block.type !== 'toolCall') continue;\n const path = typeof block.arguments.path === 'string' ? block.arguments.path : undefined;\n if (!path) continue;\n if (block.name === 'read') fileOps.read.add(path);\n else if (block.name === 'write') fileOps.written.add(path);\n else if (block.name === 'edit') fileOps.edited.add(path);\n }\n }\n return fileOps;\n}\n\nexport function parseState(value: unknown): AutocompactState | undefined {\n if (!isRecord(value)) return undefined;\n if (value.version !== STATE_VERSION || typeof value.cycle !== 'number' || !isPass(value.pass)) return undefined;\n if (\n value.phase !== 'waiting' &&\n value.phase !== 'checkpoint_pending' &&\n value.phase !== 'checkpoint_ready' &&\n value.phase !== 'compacting'\n )\n return undefined;\n const baselineTokens = value.baselineTokens ?? 0;\n if (typeof baselineTokens !== 'number' || baselineTokens < 0) return undefined;\n const baselinePending = value.baselinePending ?? false;\n if (typeof baselinePending !== 'boolean') return undefined;\n const checkpointQueue = value.checkpointQueue ?? [];\n if (\n !Array.isArray(checkpointQueue) ||\n !checkpointQueue.every(isPass) ||\n checkpointQueue.some((pass, index) => index > 0 && pass <= checkpointQueue[index - 1]!)\n )\n return undefined;\n // Sessions persisted before bounded retry landed simply have no attempt history to restore.\n const exhaustedPasses = value.exhaustedPasses ?? [];\n if (!Array.isArray(exhaustedPasses) || !exhaustedPasses.every(isPass)) return undefined;\n const invalidAttempts = value.invalidAttempts ?? 0;\n if (typeof invalidAttempts !== 'number' || invalidAttempts < 0) return undefined;\n if (!isStringArray(value.readFiles) || !isStringArray(value.modifiedFiles)) return undefined;\n if (value.requestId !== undefined && typeof value.requestId !== 'string') return undefined;\n if (value.compactionPass !== undefined && value.compactionPass !== 2 && value.compactionPass !== 3) return undefined;\n if ('latestCheckpointEntryId' in value) return undefined;\n if (value.latestCheckpointSnapshotLeafId !== undefined && typeof value.latestCheckpointSnapshotLeafId !== 'string')\n return undefined;\n if (value.lastAttemptLeafId !== undefined && typeof value.lastAttemptLeafId !== 'string') return undefined;\n if (value.snapshotLeafId !== undefined && typeof value.snapshotLeafId !== 'string') return undefined;\n if (value.snapshotTokens !== undefined && (typeof value.snapshotTokens !== 'number' || value.snapshotTokens < 0))\n return undefined;\n if (value.pendingCheckpoint !== undefined && typeof value.pendingCheckpoint !== 'string') return undefined;\n\n return {\n version: STATE_VERSION,\n cycle: value.cycle,\n pass: value.pass,\n phase: value.phase,\n checkpointQueue: [...checkpointQueue],\n exhaustedPasses: [...exhaustedPasses],\n invalidAttempts,\n baselineTokens,\n baselinePending,\n readFiles: [...value.readFiles],\n modifiedFiles: [...value.modifiedFiles],\n ...(value.requestId ? { requestId: value.requestId } : {}),\n ...(value.compactionPass ? { compactionPass: value.compactionPass } : {}),\n ...(value.latestCheckpointSnapshotLeafId\n ? { latestCheckpointSnapshotLeafId: value.latestCheckpointSnapshotLeafId }\n : {}),\n ...(value.lastAttemptLeafId ? { lastAttemptLeafId: value.lastAttemptLeafId } : {}),\n ...(value.snapshotLeafId ? { snapshotLeafId: value.snapshotLeafId } : {}),\n ...(value.snapshotTokens !== undefined ? { snapshotTokens: value.snapshotTokens } : {}),\n ...(value.pendingCheckpoint ? { pendingCheckpoint: value.pendingCheckpoint } : {}),\n };\n}\n\nexport function checkpointSummaryFromEntry(entry: CompactionPolicyEntry | undefined): string | undefined {\n if (!entry) return undefined;\n if (entry.type === 'compaction') return entry.summary.trim() || undefined;\n if (entry.type === 'custom') {\n return isRecord(entry.data) && typeof entry.data.summary === 'string'\n ? entry.data.summary.trim() || undefined\n : undefined;\n }\n const marker = customMessage(entry);\n if (marker) {\n const content =\n typeof marker.content === 'string'\n ? marker.content\n : marker.content\n .filter((block) => block.type === 'text')\n .map((block) => block.text)\n .join('\\n');\n return content.trim() || undefined;\n }\n return assistantText(entry);\n}\n\nexport function parseCheckpointDecision(response: string): CheckpointDecision {\n const match = response.match(SHOULD_COMPACT_PATTERN);\n const summary = response.replace(SHOULD_COMPACT_PATTERN, '').trim();\n if (!match) return { summary };\n return { summary, shouldCompact: match[1]?.toLowerCase() === 'true' };\n}\n\nexport function isStructuredCheckpoint(summary: string): boolean {\n return CHECKPOINT_HEADINGS.every((heading) => summary.includes(heading));\n}\n\nexport function createRequestId(\n sessionId: string,\n cycle: number,\n pass: AutocompactPass,\n leafId: string | null,\n): string {\n return `${sessionId}:${cycle}:${pass}:${leafId ?? 'root'}`;\n}\n\nexport function checkpointRequestDetails(\n cycle: number,\n pass: AutocompactPass,\n requestId: string,\n): CheckpointRequestDetails {\n return { version: STATE_VERSION, cycle, pass, requestId };\n}\n\nexport function mergeFileDetails(\n current: AutocompactFileDetails,\n fileOps?: FileOperations,\n additional?: AutocompactFileDetails,\n): AutocompactFileDetails {\n const modified = new Set([\n ...current.modifiedFiles,\n ...(additional?.modifiedFiles ?? []),\n ...(fileOps ? [...fileOps.edited, ...fileOps.written] : []),\n ]);\n const read = new Set([...current.readFiles, ...(additional?.readFiles ?? []), ...(fileOps ? [...fileOps.read] : [])]);\n for (const path of modified) read.delete(path);\n return { readFiles: [...read].sort(), modifiedFiles: [...modified].sort() };\n}\n\nexport function fileDetailsFromUnknown(value: unknown): AutocompactFileDetails | undefined {\n if (!isRecord(value) || !isStringArray(value.readFiles) || !isStringArray(value.modifiedFiles)) return undefined;\n return { readFiles: value.readFiles, modifiedFiles: value.modifiedFiles };\n}\n\nexport function withCanonicalFileSections(summary: string, details: AutocompactFileDetails): string {\n const sections: string[] = [];\n if (details.readFiles.length > 0) sections.push(`<read-files>\\n${details.readFiles.join('\\n')}\\n</read-files>`);\n if (details.modifiedFiles.length > 0) {\n sections.push(`<modified-files>\\n${details.modifiedFiles.join('\\n')}\\n</modified-files>`);\n }\n const normalized = summary.replace(FILE_SECTION_PATTERN, '').trim();\n return sections.length > 0 ? `${normalized}\\n\\n${sections.join('\\n\\n')}` : normalized;\n}\n"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_compactionPolicy = require("../compactionPolicy-
|
|
5
|
+
const require_compactionPolicy = require("../compactionPolicy-BH0jiFUR.cjs");
|
|
6
6
|
let _agimon_ai_po_core_serverFacet = require("@agimon-ai/po-core/serverFacet");
|
|
7
7
|
let _agimon_ai_po_core_extensionFile = require("@agimon-ai/po-core/extensionFile");
|
|
8
8
|
let _agimon_ai_po_core_contextContributions = require("@agimon-ai/po-core/contextContributions");
|
|
@@ -10,8 +10,8 @@ let _agimon_ai_po_core_uiHub = require("@agimon-ai/po-core/uiHub");
|
|
|
10
10
|
let _agimon_ai_po_config = require("@agimon-ai/po-config");
|
|
11
11
|
let _agimon_ai_po_telemetry = require("@agimon-ai/po-telemetry");
|
|
12
12
|
let minimatch = require("minimatch");
|
|
13
|
-
const FOOTER_SOURCE = "
|
|
14
|
-
const STATUS_KEY = "
|
|
13
|
+
const FOOTER_SOURCE = "po-autocompact";
|
|
14
|
+
const STATUS_KEY = "po-autocompact";
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/services/autocompactRuntime/index.ts
|
|
17
17
|
function errorMessage(error) {
|
|
@@ -41,7 +41,7 @@ function readContextContributionsSnapshot(service) {
|
|
|
41
41
|
return {
|
|
42
42
|
entries: [],
|
|
43
43
|
errors: [{
|
|
44
|
-
source: _agimon_ai_po_core_contextContributions.
|
|
44
|
+
source: _agimon_ai_po_core_contextContributions.PO_CONTEXT_CONTRIBUTIONS_SERVICE,
|
|
45
45
|
id: "service-snapshot",
|
|
46
46
|
label: "Context contributions",
|
|
47
47
|
order: 0,
|
|
@@ -67,7 +67,7 @@ function formatRuntimeState(snapshot) {
|
|
|
67
67
|
return `<compaction-runtime-state>
|
|
68
68
|
Authoritative runtime state captured when compaction committed. Use it to resume coordination without reconstructing state from the summary.
|
|
69
69
|
<active-plan>
|
|
70
|
-
${snapshot.planPath ? `Source: ${snapshot.planPath}\nExact plan content is restored separately by
|
|
70
|
+
${snapshot.planPath ? `Source: ${snapshot.planPath}\nExact plan content is restored separately by Po Plan.` : "(no active plan document)"}
|
|
71
71
|
</active-plan>
|
|
72
72
|
<context-contributions>
|
|
73
73
|
${formatContextContributions({
|
|
@@ -97,7 +97,7 @@ ${importantContext.length > 0 ? importantContext.join("\n") : "(none recorded ou
|
|
|
97
97
|
}
|
|
98
98
|
function checkpointInstructions(pass, steering) {
|
|
99
99
|
const decision = pass === 2 ? "Start with exactly <shouldCompact>true</shouldCompact> or <shouldCompact>false</shouldCompact>. Use true when the staged summary safely retains the important parent context. Use false only when it is not yet sufficient for safe compaction.\n\n" : "";
|
|
100
|
-
return `Create
|
|
100
|
+
return `Create Po autocompact checkpoint pass ${pass}.
|
|
101
101
|
|
|
102
102
|
${steeringEnvelope(steering)}
|
|
103
103
|
|
|
@@ -121,7 +121,7 @@ const DEFAULT_RUNTIME_CONFIG = {
|
|
|
121
121
|
overrides: []
|
|
122
122
|
};
|
|
123
123
|
/**
|
|
124
|
-
* What the
|
|
124
|
+
* What the Po config says about this package.
|
|
125
125
|
*
|
|
126
126
|
* `modes.autocompact` is read first and `modes.planning.subagents` is the
|
|
127
127
|
* fallback, because summarization borrowed the planning subagent model before
|
|
@@ -130,9 +130,9 @@ const DEFAULT_RUNTIME_CONFIG = {
|
|
|
130
130
|
function autocompactRuntimeConfig(root, onLoadFailure) {
|
|
131
131
|
let modes;
|
|
132
132
|
try {
|
|
133
|
-
modes = (0, _agimon_ai_po_config.
|
|
133
|
+
modes = (0, _agimon_ai_po_config.loadPoConfig)(root).modes;
|
|
134
134
|
} catch (error) {
|
|
135
|
-
process.emitWarning("
|
|
135
|
+
process.emitWarning("Po autocompact configuration could not be loaded; using the active session model instead.");
|
|
136
136
|
onLoadFailure?.(error);
|
|
137
137
|
return DEFAULT_RUNTIME_CONFIG;
|
|
138
138
|
}
|
|
@@ -155,23 +155,23 @@ function autocompactRuntimeConfig(root, onLoadFailure) {
|
|
|
155
155
|
}
|
|
156
156
|
//#endregion
|
|
157
157
|
//#region src/services/autocompactTelemetry/index.ts
|
|
158
|
-
const SERVICE_NAME = "
|
|
158
|
+
const SERVICE_NAME = "po-autocompact";
|
|
159
159
|
const PACKAGE_NAME = "@agimon-ai/po-autocompact";
|
|
160
160
|
const AUTOCOMPACT_EVENT = {
|
|
161
|
-
checkpointStarted: "
|
|
162
|
-
checkpointCompleted: "
|
|
163
|
-
checkpointFailed: "
|
|
164
|
-
checkpointInvalid: "
|
|
165
|
-
configurationLoadFailed: "
|
|
166
|
-
contextContributionDegraded: "
|
|
167
|
-
contextCommitted: "
|
|
168
|
-
contextApplied: "
|
|
169
|
-
contextMarkerInvalid: "
|
|
170
|
-
contextHookSlow: "
|
|
171
|
-
nativeCompactionCompleted: "
|
|
161
|
+
checkpointStarted: "po_autocompact.checkpoint_started",
|
|
162
|
+
checkpointCompleted: "po_autocompact.checkpoint_completed",
|
|
163
|
+
checkpointFailed: "po_autocompact.checkpoint_failed",
|
|
164
|
+
checkpointInvalid: "po_autocompact.checkpoint_invalid",
|
|
165
|
+
configurationLoadFailed: "po_autocompact.configuration_load_failed",
|
|
166
|
+
contextContributionDegraded: "po_autocompact.context_contribution_degraded",
|
|
167
|
+
contextCommitted: "po_autocompact.context_committed",
|
|
168
|
+
contextApplied: "po_autocompact.context_applied",
|
|
169
|
+
contextMarkerInvalid: "po_autocompact.context_marker_invalid",
|
|
170
|
+
contextHookSlow: "po_autocompact.context_hook_slow",
|
|
171
|
+
nativeCompactionCompleted: "po_autocompact.native_compaction_completed"
|
|
172
172
|
};
|
|
173
173
|
function createAutocompactTelemetry(options = {}) {
|
|
174
|
-
const telemetry = (0, _agimon_ai_po_telemetry.
|
|
174
|
+
const telemetry = (0, _agimon_ai_po_telemetry.createPoTelemetry)({
|
|
175
175
|
serviceName: SERVICE_NAME,
|
|
176
176
|
packageName: PACKAGE_NAME,
|
|
177
177
|
cwd: options.cwd,
|
|
@@ -237,7 +237,7 @@ function tailAfter(snapshot, current) {
|
|
|
237
237
|
return current.slice(snapshot.length);
|
|
238
238
|
}
|
|
239
239
|
function leaf(entries) {
|
|
240
|
-
return entries.findLast((entry) => entry.type !== "custom" || entry.customType !== "
|
|
240
|
+
return entries.findLast((entry) => entry.type !== "custom" || entry.customType !== "po-autocompact-state" && entry.customType !== "po-autocompact-checkpoint")?.id ?? "root";
|
|
241
241
|
}
|
|
242
242
|
function createNativeAutocompact(dependencies = {}) {
|
|
243
243
|
const telemetry = dependencies.telemetry ?? createAutocompactTelemetry();
|
|
@@ -325,7 +325,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
325
325
|
await persist(execution, version);
|
|
326
326
|
if (!alive(version)) return;
|
|
327
327
|
await execution.client.notify({
|
|
328
|
-
body: `
|
|
328
|
+
body: `Po autocompact summarization pass ${pass} failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
329
329
|
level: "error"
|
|
330
330
|
});
|
|
331
331
|
await telemetry.recordError(malformed ? AUTOCOMPACT_EVENT.checkpointInvalid : AUTOCOMPACT_EVENT.checkpointFailed, error, {
|
|
@@ -343,7 +343,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
343
343
|
const result = readContextContributionsSnapshot(contributions);
|
|
344
344
|
for (const error of result.errors) {
|
|
345
345
|
await execution.client.notify({
|
|
346
|
-
body: `
|
|
346
|
+
body: `Po autocompact context contribution degraded (${error.source}/${error.id}): ${error.message}`,
|
|
347
347
|
level: "warning"
|
|
348
348
|
});
|
|
349
349
|
await telemetry.recordWarning(AUTOCOMPACT_EVENT.contextContributionDegraded, new Error(error.message), {
|
|
@@ -422,7 +422,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
422
422
|
const files = require_compactionPolicy.mergeFileDetails(state, require_compactionPolicy.fileOperationsFromMessages(messages));
|
|
423
423
|
const details = {
|
|
424
424
|
...files,
|
|
425
|
-
|
|
425
|
+
poAutocompact: {
|
|
426
426
|
version: 2,
|
|
427
427
|
cycle: state.cycle,
|
|
428
428
|
pass,
|
|
@@ -458,7 +458,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
458
458
|
"autocompact.apply_mode": idle ? "idle" : "turn_end",
|
|
459
459
|
...runtimeAttributes
|
|
460
460
|
});
|
|
461
|
-
if (idle && alive(version)) await execution.session.admitPrompt?.("Asynchronous compaction completed. Continue from the compacted checkpoint's immediate next action without repeating completed work.", "steer", void 0, `${require_compactionPolicy.RESUME_MESSAGE_TYPE}:${details.
|
|
461
|
+
if (idle && alive(version)) await execution.session.admitPrompt?.("Asynchronous compaction completed. Continue from the compacted checkpoint's immediate next action without repeating completed work.", "steer", void 0, `${require_compactionPolicy.RESUME_MESSAGE_TYPE}:${details.poAutocompact.requestId}`);
|
|
462
462
|
return true;
|
|
463
463
|
};
|
|
464
464
|
const progress = async (execution, allowBusy = false, appendMessage = checkpointBoundary?.appendMessage.bind(checkpointBoundary)) => {
|
|
@@ -527,7 +527,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
527
527
|
"autocompact.message_count.before": messages.length
|
|
528
528
|
};
|
|
529
529
|
const delta = previousSnapshot ? tailAfter(previousSnapshot, messages) : void 0;
|
|
530
|
-
const completion = telemetry.runInSpan("
|
|
530
|
+
const completion = telemetry.runInSpan("po_autocompact.checkpoint", requestAttributes, async () => {
|
|
531
531
|
await telemetry.recordEvent(AUTOCOMPACT_EVENT.checkpointStarted, requestAttributes);
|
|
532
532
|
return execution.textCompletion.summarize(reference, {
|
|
533
533
|
messages: pass > 1 && delta ? delta : messages,
|
|
@@ -586,7 +586,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
586
586
|
invalid.clear();
|
|
587
587
|
const entries = await branch(execution);
|
|
588
588
|
if (!alive(version)) return;
|
|
589
|
-
const entry = entries.findLast((item) => item.type === "custom" && item.customType === "
|
|
589
|
+
const entry = entries.findLast((item) => item.type === "custom" && item.customType === "po-autocompact-state");
|
|
590
590
|
const data = entry?.type === "custom" && entry.data && typeof entry.data === "object" ? entry.data : void 0;
|
|
591
591
|
state = require_compactionPolicy.parseState(data) ?? require_compactionPolicy.createInitialState();
|
|
592
592
|
lastNativeCompactionId = typeof data?.nativeLastCompactionId === "string" ? data.nativeLastCompactionId : void 0;
|
|
@@ -597,9 +597,9 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
597
597
|
const artifacts = entries.slice(entry ? entries.indexOf(entry) + 1 : 0);
|
|
598
598
|
const committed = artifacts.findLast((item) => {
|
|
599
599
|
const message = item.type === "message" ? item.message : void 0;
|
|
600
|
-
if (message?.role !== "custom" || message.customType !== "
|
|
600
|
+
if (message?.role !== "custom" || message.customType !== "po-autocompact-context") return false;
|
|
601
601
|
const details = require_compactionPolicy.contextDetailsFromUnknown(message.details);
|
|
602
|
-
return details !== void 0 && details.
|
|
602
|
+
return details !== void 0 && details.poAutocompact.requestId === state.requestId && details.poAutocompact.cycle === state.cycle && details.poAutocompact.pass === state.pass && details.poAutocompact.snapshotLeafId === state.snapshotLeafId && require_compactionPolicy.isStructuredCheckpoint(require_compactionPolicy.checkpointSummaryFromEntry(item) ?? "");
|
|
603
603
|
});
|
|
604
604
|
if (committed?.type === "message" && committed.message.role === "custom") {
|
|
605
605
|
const details = require_compactionPolicy.contextDetailsFromUnknown(committed.message.details);
|
|
@@ -608,7 +608,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
608
608
|
resetCycle();
|
|
609
609
|
await persist(execution, version);
|
|
610
610
|
} else if (artifacts.findLast((item) => {
|
|
611
|
-
if (item.type !== "custom" || item.customType !== "
|
|
611
|
+
if (item.type !== "custom" || item.customType !== "po-autocompact-checkpoint") return false;
|
|
612
612
|
const details = item.data;
|
|
613
613
|
return details?.version === 2 && details.requestId === state.requestId && details.cycle === state.cycle && details.pass === state.pass && require_compactionPolicy.isStructuredCheckpoint(require_compactionPolicy.checkpointSummaryFromEntry(item) ?? "");
|
|
614
614
|
}) && (state.pass === 1 || state.pass === 2)) {
|
|
@@ -674,7 +674,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
674
674
|
const id = leaf(entries);
|
|
675
675
|
if (!invalid.has(id)) {
|
|
676
676
|
invalid.add(id);
|
|
677
|
-
await telemetry.recordError(AUTOCOMPACT_EVENT.contextMarkerInvalid, /* @__PURE__ */ new Error("
|
|
677
|
+
await telemetry.recordError(AUTOCOMPACT_EVENT.contextMarkerInvalid, /* @__PURE__ */ new Error("Po autocompact context marker is malformed."), {
|
|
678
678
|
...attributes(),
|
|
679
679
|
"autocompact.leaf_id": id
|
|
680
680
|
});
|
|
@@ -743,8 +743,8 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
743
743
|
}
|
|
744
744
|
],
|
|
745
745
|
plugin(cordis) {
|
|
746
|
-
cordis.inject([_agimon_ai_po_core_uiHub.
|
|
747
|
-
const contribution = (0, _agimon_ai_po_core_uiHub.
|
|
746
|
+
cordis.inject([_agimon_ai_po_core_uiHub.PO_UI_HUB_SERVICE], (injected) => {
|
|
747
|
+
const contribution = (0, _agimon_ai_po_core_uiHub.requirePoUiHub)(injected).registerFooter({
|
|
748
748
|
source: FOOTER_SOURCE,
|
|
749
749
|
id: "autocompact",
|
|
750
750
|
order: 20
|
|
@@ -756,8 +756,8 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
756
756
|
if (footer === contribution) footer = void 0;
|
|
757
757
|
};
|
|
758
758
|
});
|
|
759
|
-
cordis.inject([_agimon_ai_po_core_contextContributions.
|
|
760
|
-
const service = (0, _agimon_ai_po_core_contextContributions.
|
|
759
|
+
cordis.inject([_agimon_ai_po_core_contextContributions.PO_CONTEXT_CONTRIBUTIONS_SERVICE], (injected) => {
|
|
760
|
+
const service = (0, _agimon_ai_po_core_contextContributions.requirePoContextContributions)(injected);
|
|
761
761
|
contributions = service;
|
|
762
762
|
return () => {
|
|
763
763
|
if (contributions === service) contributions = void 0;
|