fix: restore ci compatibility

This commit is contained in:
Peter Steinberger
2026-03-27 05:22:25 +00:00
parent c13d6dbf55
commit ee12f24760
5 changed files with 64 additions and 9 deletions

View File

@@ -20,9 +20,13 @@ vi.mock("./mattermost/accounts.js", async (importOriginal) => {
};
});
vi.mock("./mattermost/client.js", () => ({
normalizeMattermostBaseUrl,
}));
vi.mock("./mattermost/client.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("./mattermost/client.js")>();
return {
...actual,
normalizeMattermostBaseUrl,
};
});
vi.mock("./secret-input.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("./secret-input.js")>();

View File

@@ -69,6 +69,19 @@ export function buildCompactionSummarizationInstructions(
return `${identifierPreservation}\n\nAdditional focus:\n${custom}`;
}
type GenerateSummaryCompat = (
currentMessages: AgentMessage[],
model: NonNullable<ExtensionContext["model"]>,
reserveTokens: number,
apiKey: string,
headers?: Record<string, string>,
signal?: AbortSignal,
customInstructions?: string,
previousSummary?: string,
) => Promise<string>;
const generateSummaryCompat = generateSummary as unknown as GenerateSummaryCompat;
export function estimateMessagesTokens(messages: AgentMessage[]): number {
// SECURITY: toolResult.details can contain untrusted/verbose payloads; never include in LLM-facing compaction.
const safe = stripToolResultDetails(messages);
@@ -252,11 +265,12 @@ async function summarizeChunks(params: {
for (const chunk of chunks) {
summary = await retryAsync(
() =>
generateSummary(
generateSummaryCompat(
chunk,
model,
params.reserveTokens,
params.apiKey,
params.headers,
params.signal,
effectiveInstructions,
summary,

View File

@@ -1,6 +1,7 @@
import fs from "node:fs";
import path from "node:path";
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type { Api, Model } from "@mariozechner/pi-ai";
import type { ExtensionAPI, FileOperations } from "@mariozechner/pi-coding-agent";
import { extractSections } from "../../auto-reply/reply/post-compaction-context.js";
import { openBoundaryFile } from "../../infra/boundary-file-read.js";
@@ -63,6 +64,40 @@ const compactionSafeguardDeps = {
summarizeInStages,
};
type ModelApiKeyResolver = {
getApiKeyAndHeaders?: (model: Model<Api>) => Promise<{
ok: boolean;
apiKey?: string;
headers?: Record<string, string>;
}>;
getApiKey?: (model: Model<Api>) => Promise<string | undefined>;
getApiKeyForProvider?: (provider: string) => Promise<string | undefined>;
};
async function resolveModelAuth(
modelRegistry: unknown,
model: Model<Api>,
): Promise<{ apiKey?: string; headers?: Record<string, string> }> {
const registry = modelRegistry as ModelApiKeyResolver;
if (typeof registry.getApiKeyAndHeaders === "function") {
const resolved = await registry.getApiKeyAndHeaders(model);
if (resolved?.ok) {
return {
apiKey: resolved.apiKey,
headers: resolved.headers,
};
}
return {};
}
if (typeof registry.getApiKey === "function") {
return { apiKey: await registry.getApiKey(model) };
}
if (typeof registry.getApiKeyForProvider === "function") {
return { apiKey: await registry.getApiKeyForProvider(model.provider) };
}
return {};
}
type ToolFailure = {
toolCallId: string;
toolName: string;
@@ -618,8 +653,9 @@ export default function compactionSafeguardExtension(api: ExtensionAPI): void {
model.headers && typeof model.headers === "object" && !Array.isArray(model.headers)
? model.headers
: undefined;
const apiKey = (await ctx.modelRegistry.getApiKey(model)) ?? "";
const headers = fallbackHeaders;
const resolvedAuth = await resolveModelAuth(ctx.modelRegistry, model);
const apiKey = resolvedAuth.apiKey ?? "";
const headers = resolvedAuth.headers ?? fallbackHeaders;
if (!apiKey && !headers) {
log.warn(
"Compaction safeguard: no request auth available; cancelling compaction to preserve history.",

View File

@@ -1,5 +1,6 @@
import type { Skill } from "@mariozechner/pi-coding-agent";
export function resolveSkillSource(skill: Skill): string {
return skill.source;
const source = (skill as Skill & { source?: unknown }).source;
return typeof source === "string" ? source : "";
}

View File

@@ -89,8 +89,8 @@ describe("resolveGatewayConnection", () => {
"OPENCLAW_GATEWAY_TOKEN",
"OPENCLAW_GATEWAY_PASSWORD",
]);
loadConfig.mockClear();
resolveGatewayPort.mockClear();
loadConfig.mockReset();
resolveGatewayPort.mockReset();
resolveGatewayPort.mockReturnValue(18789);
delete process.env.OPENCLAW_GATEWAY_URL;
delete process.env.OPENCLAW_GATEWAY_TOKEN;