chore: migrate to oxlint and oxfmt

Co-authored-by: Christoph Nakazawa <christoph.pojer@gmail.com>
This commit is contained in:
Peter Steinberger
2026-01-14 14:31:43 +00:00
parent 912ebffc63
commit c379191f80
1480 changed files with 28608 additions and 43547 deletions

View File

@@ -1,9 +1,5 @@
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type {
ExtensionAPI,
ExtensionContext,
FileOperations,
} from "@mariozechner/pi-coding-agent";
import type { ExtensionAPI, ExtensionContext, FileOperations } from "@mariozechner/pi-coding-agent";
import { estimateTokens, generateSummary } from "@mariozechner/pi-coding-agent";
import { DEFAULT_CONTEXT_TOKENS } from "../defaults.js";
@@ -25,27 +21,19 @@ function computeFileLists(fileOps: FileOperations): {
return { readFiles, modifiedFiles };
}
function formatFileOperations(
readFiles: string[],
modifiedFiles: string[],
): string {
function formatFileOperations(readFiles: string[], modifiedFiles: string[]): string {
const sections: string[] = [];
if (readFiles.length > 0) {
sections.push(`<read-files>\n${readFiles.join("\n")}\n</read-files>`);
}
if (modifiedFiles.length > 0) {
sections.push(
`<modified-files>\n${modifiedFiles.join("\n")}\n</modified-files>`,
);
sections.push(`<modified-files>\n${modifiedFiles.join("\n")}\n</modified-files>`);
}
if (sections.length === 0) return "";
return `\n\n${sections.join("\n\n")}`;
}
function chunkMessages(
messages: AgentMessage[],
maxTokens: number,
): AgentMessage[][] {
function chunkMessages(messages: AgentMessage[], maxTokens: number): AgentMessage[][] {
if (messages.length === 0) return [];
const chunks: AgentMessage[][] = [];
@@ -146,14 +134,8 @@ export default function compactionSafeguardExtension(api: ExtensionAPI): void {
1,
Math.floor(model.contextWindow ?? DEFAULT_CONTEXT_TOKENS),
);
const maxChunkTokens = Math.max(
1,
Math.floor(contextWindowTokens * MAX_CHUNK_RATIO),
);
const reserveTokens = Math.max(
1,
Math.floor(preparation.settings.reserveTokens),
);
const maxChunkTokens = Math.max(1, Math.floor(contextWindowTokens * MAX_CHUNK_RATIO));
const reserveTokens = Math.max(1, Math.floor(preparation.settings.reserveTokens));
const historySummary = await summarizeChunks({
messages: preparation.messagesToSummarize,
@@ -167,10 +149,7 @@ export default function compactionSafeguardExtension(api: ExtensionAPI): void {
});
let summary = historySummary;
if (
preparation.isSplitTurn &&
preparation.turnPrefixMessages.length > 0
) {
if (preparation.isSplitTurn && preparation.turnPrefixMessages.length > 0) {
const prefixSummary = await summarizeChunks({
messages: preparation.turnPrefixMessages,
model,

View File

@@ -1,8 +1,5 @@
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type {
ExtensionAPI,
ExtensionContext,
} from "@mariozechner/pi-coding-agent";
import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
import { describe, expect, it } from "vitest";
import { setContextPruningRuntime } from "./context-pruning/runtime.js";
@@ -21,13 +18,8 @@ function toolText(msg: AgentMessage): string {
return first.text;
}
function findToolResult(
messages: AgentMessage[],
toolCallId: string,
): AgentMessage {
const msg = messages.find(
(m) => m.role === "toolResult" && m.toolCallId === toolCallId,
);
function findToolResult(messages: AgentMessage[], toolCallId: string): AgentMessage {
const msg = messages.find((m) => m.role === "toolResult" && m.toolCallId === toolCallId);
if (!msg) throw new Error(`missing toolResult: ${toolCallId}`);
return msg;
}

View File

@@ -1,9 +1,5 @@
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type {
ContextEvent,
ExtensionAPI,
ExtensionContext,
} from "@mariozechner/pi-coding-agent";
import type { ContextEvent, ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
import { pruneContextMessages } from "./pruner.js";
import { getContextPruningRuntime } from "./runtime.js";

View File

@@ -1,9 +1,5 @@
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type {
ImageContent,
TextContent,
ToolResultMessage,
} from "@mariozechner/pi-ai";
import type { ImageContent, TextContent, ToolResultMessage } from "@mariozechner/pi-ai";
import type { ExtensionContext } from "@mariozechner/pi-coding-agent";
import type { EffectiveContextPruningSettings } from "./settings.js";
@@ -18,9 +14,7 @@ function asText(text: string): TextContent {
return { type: "text", text };
}
function collectTextSegments(
content: ReadonlyArray<TextContent | ImageContent>,
): string[] {
function collectTextSegments(content: ReadonlyArray<TextContent | ImageContent>): string[] {
const parts: string[] = [];
for (const block of content) {
if (block.type === "text") parts.push(block.text);
@@ -82,9 +76,7 @@ function takeTailFromJoinedText(parts: string[], maxChars: number): string {
return out.join("");
}
function hasImageBlocks(
content: ReadonlyArray<TextContent | ImageContent>,
): boolean {
function hasImageBlocks(content: ReadonlyArray<TextContent | ImageContent>): boolean {
for (const block of content) {
if (block.type === "image") return true;
}
@@ -208,21 +200,16 @@ export function pruneContextMessages(params: {
const charWindow = contextWindowTokens * CHARS_PER_TOKEN_ESTIMATE;
if (charWindow <= 0) return messages;
const cutoffIndex = findAssistantCutoffIndex(
messages,
settings.keepLastAssistants,
);
const cutoffIndex = findAssistantCutoffIndex(messages, settings.keepLastAssistants);
if (cutoffIndex === null) return messages;
// Bootstrap safety: never prune anything before the first user message. This protects initial
// "identity" reads (SOUL.md, USER.md, etc.) which typically happen before the first inbound user
// message exists in the session transcript.
const firstUserIndex = findFirstUserIndex(messages);
const pruneStartIndex =
firstUserIndex === null ? messages.length : firstUserIndex;
const pruneStartIndex = firstUserIndex === null ? messages.length : firstUserIndex;
const isToolPrunable =
params.isToolPrunable ?? makeToolPrunablePredicate(settings.tools);
const isToolPrunable = params.isToolPrunable ?? makeToolPrunablePredicate(settings.tools);
if (settings.mode === "aggressive") {
let next: AgentMessage[] | null = null;

View File

@@ -41,81 +41,55 @@ export type EffectiveContextPruningSettings = {
};
};
export const DEFAULT_CONTEXT_PRUNING_SETTINGS: EffectiveContextPruningSettings =
{
mode: "adaptive",
keepLastAssistants: 3,
softTrimRatio: 0.3,
hardClearRatio: 0.5,
minPrunableToolChars: 50_000,
tools: {},
softTrim: {
maxChars: 4_000,
headChars: 1_500,
tailChars: 1_500,
},
hardClear: {
enabled: true,
placeholder: "[Old tool result content cleared]",
},
};
export const DEFAULT_CONTEXT_PRUNING_SETTINGS: EffectiveContextPruningSettings = {
mode: "adaptive",
keepLastAssistants: 3,
softTrimRatio: 0.3,
hardClearRatio: 0.5,
minPrunableToolChars: 50_000,
tools: {},
softTrim: {
maxChars: 4_000,
headChars: 1_500,
tailChars: 1_500,
},
hardClear: {
enabled: true,
placeholder: "[Old tool result content cleared]",
},
};
export function computeEffectiveSettings(
raw: unknown,
): EffectiveContextPruningSettings | null {
export function computeEffectiveSettings(raw: unknown): EffectiveContextPruningSettings | null {
if (!raw || typeof raw !== "object") return null;
const cfg = raw as ContextPruningConfig;
if (cfg.mode !== "adaptive" && cfg.mode !== "aggressive") return null;
const s: EffectiveContextPruningSettings = structuredClone(
DEFAULT_CONTEXT_PRUNING_SETTINGS,
);
const s: EffectiveContextPruningSettings = structuredClone(DEFAULT_CONTEXT_PRUNING_SETTINGS);
s.mode = cfg.mode;
if (
typeof cfg.keepLastAssistants === "number" &&
Number.isFinite(cfg.keepLastAssistants)
) {
if (typeof cfg.keepLastAssistants === "number" && Number.isFinite(cfg.keepLastAssistants)) {
s.keepLastAssistants = Math.max(0, Math.floor(cfg.keepLastAssistants));
}
if (
typeof cfg.softTrimRatio === "number" &&
Number.isFinite(cfg.softTrimRatio)
) {
if (typeof cfg.softTrimRatio === "number" && Number.isFinite(cfg.softTrimRatio)) {
s.softTrimRatio = Math.min(1, Math.max(0, cfg.softTrimRatio));
}
if (
typeof cfg.hardClearRatio === "number" &&
Number.isFinite(cfg.hardClearRatio)
) {
if (typeof cfg.hardClearRatio === "number" && Number.isFinite(cfg.hardClearRatio)) {
s.hardClearRatio = Math.min(1, Math.max(0, cfg.hardClearRatio));
}
if (
typeof cfg.minPrunableToolChars === "number" &&
Number.isFinite(cfg.minPrunableToolChars)
) {
if (typeof cfg.minPrunableToolChars === "number" && Number.isFinite(cfg.minPrunableToolChars)) {
s.minPrunableToolChars = Math.max(0, Math.floor(cfg.minPrunableToolChars));
}
if (cfg.tools) {
s.tools = cfg.tools;
}
if (cfg.softTrim) {
if (
typeof cfg.softTrim.maxChars === "number" &&
Number.isFinite(cfg.softTrim.maxChars)
) {
if (typeof cfg.softTrim.maxChars === "number" && Number.isFinite(cfg.softTrim.maxChars)) {
s.softTrim.maxChars = Math.max(0, Math.floor(cfg.softTrim.maxChars));
}
if (
typeof cfg.softTrim.headChars === "number" &&
Number.isFinite(cfg.softTrim.headChars)
) {
if (typeof cfg.softTrim.headChars === "number" && Number.isFinite(cfg.softTrim.headChars)) {
s.softTrim.headChars = Math.max(0, Math.floor(cfg.softTrim.headChars));
}
if (
typeof cfg.softTrim.tailChars === "number" &&
Number.isFinite(cfg.softTrim.tailChars)
) {
if (typeof cfg.softTrim.tailChars === "number" && Number.isFinite(cfg.softTrim.tailChars)) {
s.softTrim.tailChars = Math.max(0, Math.floor(cfg.softTrim.tailChars));
}
}
@@ -123,10 +97,7 @@ export function computeEffectiveSettings(
if (s.mode === "adaptive" && typeof cfg.hardClear.enabled === "boolean") {
s.hardClear.enabled = cfg.hardClear.enabled;
}
if (
typeof cfg.hardClear.placeholder === "string" &&
cfg.hardClear.placeholder.trim()
) {
if (typeof cfg.hardClear.placeholder === "string" && cfg.hardClear.placeholder.trim()) {
s.hardClear.placeholder = cfg.hardClear.placeholder.trim();
}
}

View File

@@ -7,11 +7,7 @@
*/
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type {
ContextEvent,
ExtensionAPI,
ExtensionContext,
} from "@mariozechner/pi-coding-agent";
import type { ContextEvent, ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
import { isGoogleModelApi } from "../pi-embedded-helpers.js";
import { repairToolUseResultPairing } from "../session-transcript-repair.js";