mirror of
https://github.com/wassname/pi-auto-compressor.git
synced 2026-06-27 18:05:33 +08:00
108 lines
3.6 KiB
TypeScript
108 lines
3.6 KiB
TypeScript
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"
|
|
import { loadConfig } from "./config.js"
|
|
import {
|
|
createState,
|
|
resetState,
|
|
createInputFingerprint,
|
|
} from "./state.js"
|
|
import { applyPruning } from "./pruner.js"
|
|
|
|
export default function (pi: ExtensionAPI) {
|
|
const config = loadConfig(process.cwd())
|
|
if (!config.enabled) return
|
|
|
|
const state = createState()
|
|
|
|
pi.on("tool_call", async (event, _ctx) => {
|
|
if (!state.toolCalls.has(event.toolCallId)) {
|
|
state.toolCalls.set(event.toolCallId, {
|
|
toolCallId: event.toolCallId,
|
|
toolName: event.toolName,
|
|
inputArgs: event.input as Record<string, unknown>,
|
|
inputFingerprint: createInputFingerprint(
|
|
event.toolName,
|
|
event.input as Record<string, unknown>,
|
|
),
|
|
isError: false,
|
|
turnIndex: state.currentTurn,
|
|
timestamp: 0,
|
|
tokenEstimate: 0,
|
|
})
|
|
}
|
|
})
|
|
|
|
pi.on("tool_result", async (event, _ctx) => {
|
|
const record = state.toolCalls.get(event.toolCallId)
|
|
const outputText = event.content
|
|
.map((c: any) => (c.type === "text" ? c.text : ""))
|
|
.join("")
|
|
const tokenEstimate = Math.round(outputText.length / 4)
|
|
|
|
if (record) {
|
|
record.isError = event.isError
|
|
record.timestamp = Date.now()
|
|
record.tokenEstimate = tokenEstimate
|
|
} else {
|
|
state.toolCalls.set(event.toolCallId, {
|
|
toolCallId: event.toolCallId,
|
|
toolName: event.toolName,
|
|
inputArgs: {},
|
|
inputFingerprint: createInputFingerprint(event.toolName, {}),
|
|
isError: event.isError,
|
|
turnIndex: state.currentTurn,
|
|
timestamp: Date.now(),
|
|
tokenEstimate,
|
|
})
|
|
}
|
|
})
|
|
|
|
pi.on("session_start", async (event, ctx) => {
|
|
resetState(state)
|
|
for (const entry of ctx.sessionManager.getBranch()) {
|
|
if (entry.type === "custom" && entry.customType === "dcp-state") {
|
|
const data = entry.data as any
|
|
if (data?.previousSummary) state.previousSummary = data.previousSummary
|
|
if (data?.compressionCount) state.compressionCount = data.compressionCount
|
|
if (data?.tokensSaved) state.tokensSaved = data.tokensSaved
|
|
if (data?.prunedToolIds) state.prunedToolIds = new Set(data.prunedToolIds)
|
|
}
|
|
}
|
|
})
|
|
|
|
pi.on("session_shutdown", async (_event, _ctx) => {
|
|
pi.appendEntry("dcp-state", {
|
|
previousSummary: state.previousSummary,
|
|
compressionCount: state.compressionCount,
|
|
tokensSaved: state.tokensSaved,
|
|
prunedToolIds: Array.from(state.prunedToolIds),
|
|
})
|
|
})
|
|
|
|
pi.on("context", async (event, ctx) => {
|
|
const prunedMessages = await applyPruning(event.messages, state, config, (ctx as any).apiClient)
|
|
return { messages: prunedMessages }
|
|
})
|
|
|
|
pi.registerCommand("acp", {
|
|
description: "Auto-Compressor stats",
|
|
async handler(args, ctx) {
|
|
const usage = ctx.getContextUsage ? ctx.getContextUsage() : null;
|
|
let tokenStr = "unavailable";
|
|
if (usage && usage.tokens !== null) {
|
|
tokenStr = `${usage.tokens.toLocaleString()} / ${usage.contextWindow.toLocaleString()}`;
|
|
}
|
|
|
|
const lines = [
|
|
"Auto-Compressor (Hermes) Stats:",
|
|
` Total Compressions: ${state.compressionCount}`,
|
|
` Estimated Tokens Saved: ${state.tokensSaved.toLocaleString()}`,
|
|
` Pruned Tool Outputs (Deduplication/Errors): ${state.prunedToolIds.size}`,
|
|
` Current User Turn: ${state.currentTurn}`,
|
|
` Summary Exists (Has Compressed): ${state.previousSummary !== null ? "Yes" : "No"}`,
|
|
` Current Context Tokens: ${tokenStr}`
|
|
];
|
|
ctx.ui.notify(lines.join("\n"), "info");
|
|
}
|
|
});
|
|
}
|