fix: align pi-ai payload hooks

This commit is contained in:
Josh Lehman
2026-03-12 07:13:16 -07:00
parent 624a045822
commit 75d9204c86
4 changed files with 40 additions and 27 deletions

View File

@@ -276,7 +276,7 @@ describe("applyExtraParamsToAgent", () => {
const payloads: Record<string, unknown>[] = []; const payloads: Record<string, unknown>[] = [];
const baseStreamFn: StreamFn = (_model, _context, options) => { const baseStreamFn: StreamFn = (_model, _context, options) => {
const payload: Record<string, unknown> = { model: "deepseek/deepseek-r1" }; const payload: Record<string, unknown> = { model: "deepseek/deepseek-r1" };
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -308,7 +308,7 @@ describe("applyExtraParamsToAgent", () => {
const payloads: Record<string, unknown>[] = []; const payloads: Record<string, unknown>[] = [];
const baseStreamFn: StreamFn = (_model, _context, options) => { const baseStreamFn: StreamFn = (_model, _context, options) => {
const payload: Record<string, unknown> = {}; const payload: Record<string, unknown> = {};
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -332,7 +332,7 @@ describe("applyExtraParamsToAgent", () => {
const payloads: Record<string, unknown>[] = []; const payloads: Record<string, unknown>[] = [];
const baseStreamFn: StreamFn = (_model, _context, options) => { const baseStreamFn: StreamFn = (_model, _context, options) => {
const payload: Record<string, unknown> = { reasoning_effort: "high" }; const payload: Record<string, unknown> = { reasoning_effort: "high" };
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -357,7 +357,7 @@ describe("applyExtraParamsToAgent", () => {
const payloads: Record<string, unknown>[] = []; const payloads: Record<string, unknown>[] = [];
const baseStreamFn: StreamFn = (_model, _context, options) => { const baseStreamFn: StreamFn = (_model, _context, options) => {
const payload: Record<string, unknown> = { reasoning: { max_tokens: 256 } }; const payload: Record<string, unknown> = { reasoning: { max_tokens: 256 } };
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -381,7 +381,7 @@ describe("applyExtraParamsToAgent", () => {
const payloads: Record<string, unknown>[] = []; const payloads: Record<string, unknown>[] = [];
const baseStreamFn: StreamFn = (_model, _context, options) => { const baseStreamFn: StreamFn = (_model, _context, options) => {
const payload: Record<string, unknown> = { reasoning_effort: "medium" }; const payload: Record<string, unknown> = { reasoning_effort: "medium" };
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -588,7 +588,7 @@ describe("applyExtraParamsToAgent", () => {
const payloads: Record<string, unknown>[] = []; const payloads: Record<string, unknown>[] = [];
const baseStreamFn: StreamFn = (_model, _context, options) => { const baseStreamFn: StreamFn = (_model, _context, options) => {
const payload: Record<string, unknown> = { thinking: "off" }; const payload: Record<string, unknown> = { thinking: "off" };
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -619,7 +619,7 @@ describe("applyExtraParamsToAgent", () => {
const payloads: Record<string, unknown>[] = []; const payloads: Record<string, unknown>[] = [];
const baseStreamFn: StreamFn = (_model, _context, options) => { const baseStreamFn: StreamFn = (_model, _context, options) => {
const payload: Record<string, unknown> = { thinking: "off" }; const payload: Record<string, unknown> = { thinking: "off" };
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -650,7 +650,7 @@ describe("applyExtraParamsToAgent", () => {
const payloads: Record<string, unknown>[] = []; const payloads: Record<string, unknown>[] = [];
const baseStreamFn: StreamFn = (_model, _context, options) => { const baseStreamFn: StreamFn = (_model, _context, options) => {
const payload: Record<string, unknown> = {}; const payload: Record<string, unknown> = {};
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -674,7 +674,7 @@ describe("applyExtraParamsToAgent", () => {
const payloads: Record<string, unknown>[] = []; const payloads: Record<string, unknown>[] = [];
const baseStreamFn: StreamFn = (_model, _context, options) => { const baseStreamFn: StreamFn = (_model, _context, options) => {
const payload: Record<string, unknown> = { tool_choice: "required" }; const payload: Record<string, unknown> = { tool_choice: "required" };
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -699,7 +699,7 @@ describe("applyExtraParamsToAgent", () => {
const payloads: Record<string, unknown>[] = []; const payloads: Record<string, unknown>[] = [];
const baseStreamFn: StreamFn = (_model, _context, options) => { const baseStreamFn: StreamFn = (_model, _context, options) => {
const payload: Record<string, unknown> = {}; const payload: Record<string, unknown> = {};
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -749,7 +749,7 @@ describe("applyExtraParamsToAgent", () => {
], ],
tool_choice: { type: "tool", name: "read" }, tool_choice: { type: "tool", name: "read" },
}; };
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -793,7 +793,7 @@ describe("applyExtraParamsToAgent", () => {
}, },
], ],
}; };
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -832,7 +832,7 @@ describe("applyExtraParamsToAgent", () => {
}, },
], ],
}; };
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -896,7 +896,7 @@ describe("applyExtraParamsToAgent", () => {
}, },
}, },
}; };
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };
@@ -943,7 +943,7 @@ describe("applyExtraParamsToAgent", () => {
}, },
}, },
}; };
options?.onPayload?.(payload, model); options?.onPayload?.(payload, _model);
payloads.push(payload); payloads.push(payload);
return {} as ReturnType<StreamFn>; return {} as ReturnType<StreamFn>;
}; };

View File

@@ -7,11 +7,14 @@ vi.mock("@mariozechner/pi-ai", async (importOriginal) => {
const original = await importOriginal<typeof import("@mariozechner/pi-ai")>(); const original = await importOriginal<typeof import("@mariozechner/pi-ai")>();
return { return {
...original, ...original,
getOAuthApiKey: () => undefined,
getOAuthProviders: () => [],
}; };
}); });
vi.mock("@mariozechner/pi-ai/oauth", () => ({
getOAuthApiKey: () => undefined,
getOAuthProviders: () => [],
}));
import { createOpenClawCodingTools } from "./pi-tools.js"; import { createOpenClawCodingTools } from "./pi-tools.js";
describe("FS tools with workspaceOnly=false", () => { describe("FS tools with workspaceOnly=false", () => {

View File

@@ -69,7 +69,12 @@ export type TelegramBotOptions = {
export { getTelegramSequentialKey }; export { getTelegramSequentialKey };
function readRequestUrl(input: RequestInfo | URL): string | null { type TelegramFetchInput = Parameters<NonNullable<ApiClientOptions["fetch"]>>[0];
type TelegramFetchInit = Parameters<NonNullable<ApiClientOptions["fetch"]>>[1];
type GlobalFetchInput = Parameters<typeof globalThis.fetch>[0];
type GlobalFetchInit = Parameters<typeof globalThis.fetch>[1];
function readRequestUrl(input: TelegramFetchInput): string | null {
if (typeof input === "string") { if (typeof input === "string") {
return input; return input;
} }
@@ -83,7 +88,7 @@ function readRequestUrl(input: RequestInfo | URL): string | null {
return null; return null;
} }
function extractTelegramApiMethod(input: RequestInfo | URL): string | null { function extractTelegramApiMethod(input: TelegramFetchInput): string | null {
const url = readRequestUrl(input); const url = readRequestUrl(input);
if (!url) { if (!url) {
return null; return null;
@@ -150,7 +155,7 @@ export function createTelegramBot(opts: TelegramBotOptions) {
// Use manual event forwarding instead of AbortSignal.any() to avoid the cross-realm // Use manual event forwarding instead of AbortSignal.any() to avoid the cross-realm
// AbortSignal issue in Node.js (grammY's signal may come from a different module context, // AbortSignal issue in Node.js (grammY's signal may come from a different module context,
// causing "signals[0] must be an instance of AbortSignal" errors). // causing "signals[0] must be an instance of AbortSignal" errors).
finalFetch = ((input: RequestInfo | URL, init?: RequestInit) => { finalFetch = ((input: TelegramFetchInput, init?: TelegramFetchInit) => {
const controller = new AbortController(); const controller = new AbortController();
const abortWith = (signal: AbortSignal) => controller.abort(signal.reason); const abortWith = (signal: AbortSignal) => controller.abort(signal.reason);
const onShutdown = () => abortWith(shutdownSignal); const onShutdown = () => abortWith(shutdownSignal);
@@ -162,13 +167,16 @@ export function createTelegramBot(opts: TelegramBotOptions) {
} }
if (init?.signal) { if (init?.signal) {
if (init.signal.aborted) { if (init.signal.aborted) {
abortWith(init.signal); abortWith(init.signal as unknown as AbortSignal);
} else { } else {
onRequestAbort = () => abortWith(init.signal as AbortSignal); onRequestAbort = () => abortWith(init.signal as AbortSignal);
init.signal.addEventListener("abort", onRequestAbort, { once: true }); init.signal.addEventListener("abort", onRequestAbort);
} }
} }
return callFetch(input, { ...init, signal: controller.signal }).finally(() => { return callFetch(input as GlobalFetchInput, {
...(init as GlobalFetchInit),
signal: controller.signal,
}).finally(() => {
shutdownSignal.removeEventListener("abort", onShutdown); shutdownSignal.removeEventListener("abort", onShutdown);
if (init?.signal && onRequestAbort) { if (init?.signal && onRequestAbort) {
init.signal.removeEventListener("abort", onRequestAbort); init.signal.removeEventListener("abort", onRequestAbort);
@@ -178,7 +186,7 @@ export function createTelegramBot(opts: TelegramBotOptions) {
} }
if (finalFetch) { if (finalFetch) {
const baseFetch = finalFetch; const baseFetch = finalFetch;
finalFetch = ((input: RequestInfo | URL, init?: RequestInit) => { finalFetch = ((input: TelegramFetchInput, init?: TelegramFetchInit) => {
return Promise.resolve(baseFetch(input, init)).catch((err: unknown) => { return Promise.resolve(baseFetch(input, init)).catch((err: unknown) => {
try { try {
tagTelegramNetworkError(err, { tagTelegramNetworkError(err, {

View File

@@ -12,12 +12,14 @@ vi.mock("@mariozechner/pi-ai", async (importOriginal) => {
return { return {
...original, ...original,
completeSimple: vi.fn(), completeSimple: vi.fn(),
// Some auth helpers import oauth provider metadata at module load time.
getOAuthProviders: () => [],
getOAuthApiKey: vi.fn(async () => null),
}; };
}); });
vi.mock("@mariozechner/pi-ai/oauth", () => ({
getOAuthProviders: () => [],
getOAuthApiKey: vi.fn(async () => null),
}));
vi.mock("../agents/pi-embedded-runner/model.js", () => ({ vi.mock("../agents/pi-embedded-runner/model.js", () => ({
resolveModel: vi.fn((provider: string, modelId: string) => ({ resolveModel: vi.fn((provider: string, modelId: string) => ({
model: { model: {