chore: Enable `typescript/no-explicit-any` rule.
parent
baa1e95b9d
commit
935a0e5708
|
|
@ -14,6 +14,7 @@
|
|||
"oxc/no-accumulating-spread": "off",
|
||||
"oxc/no-async-endpoint-handlers": "off",
|
||||
"oxc/no-map-spread": "off",
|
||||
"typescript/no-explicit-any": "error",
|
||||
"typescript/no-extraneous-class": "off",
|
||||
"typescript/no-unsafe-type-assertion": "off",
|
||||
"unicorn/consistent-function-scoping": "off",
|
||||
|
|
|
|||
|
|
@ -1216,7 +1216,9 @@ describe("BlueBubbles webhook monitor", () => {
|
|||
const core = createMockRuntime();
|
||||
|
||||
// Use a timing-aware debouncer test double that respects debounceMs/buildKey/shouldDebounce.
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
core.channel.debounce.createInboundDebouncer = vi.fn((params: any) => {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
type Item = any;
|
||||
const buckets = new Map<
|
||||
string,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ function createRuntime(): { runtime: PluginRuntime; mocks: LineRuntimeMocks } {
|
|||
? (lineConfig.accounts?.[accountId] ?? {})
|
||||
: lineConfig;
|
||||
const hasToken =
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
Boolean((entry as any).channelAccessToken) || Boolean((entry as any).tokenFile);
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const hasSecret = Boolean((entry as any).channelSecret) || Boolean((entry as any).secretFile);
|
||||
return { tokenSource: hasToken && hasSecret ? "config" : "none" };
|
||||
},
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ vi.mock("../../../src/agents/pi-embedded-runner.js", () => {
|
|||
import { runEmbeddedPiAgent } from "../../../src/agents/pi-embedded-runner.js";
|
||||
import { createLlmTaskTool } from "./llm-task-tool.js";
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
function fakeApi(overrides: any = {}) {
|
||||
return {
|
||||
id: "llm-task",
|
||||
|
|
@ -32,26 +33,31 @@ describe("llm-task tool (json-only)", () => {
|
|||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it("returns parsed json", async () => {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
(runEmbeddedPiAgent as any).mockResolvedValueOnce({
|
||||
meta: {},
|
||||
payloads: [{ text: JSON.stringify({ foo: "bar" }) }],
|
||||
});
|
||||
const tool = createLlmTaskTool(fakeApi());
|
||||
const res = await tool.execute("id", { prompt: "return foo" });
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect((res as any).details.json).toEqual({ foo: "bar" });
|
||||
});
|
||||
|
||||
it("strips fenced json", async () => {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
(runEmbeddedPiAgent as any).mockResolvedValueOnce({
|
||||
meta: {},
|
||||
payloads: [{ text: '```json\n{"ok":true}\n```' }],
|
||||
});
|
||||
const tool = createLlmTaskTool(fakeApi());
|
||||
const res = await tool.execute("id", { prompt: "return ok" });
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect((res as any).details.json).toEqual({ ok: true });
|
||||
});
|
||||
|
||||
it("validates schema", async () => {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
(runEmbeddedPiAgent as any).mockResolvedValueOnce({
|
||||
meta: {},
|
||||
payloads: [{ text: JSON.stringify({ foo: "bar" }) }],
|
||||
|
|
@ -64,10 +70,12 @@ describe("llm-task tool (json-only)", () => {
|
|||
additionalProperties: false,
|
||||
};
|
||||
const res = await tool.execute("id", { prompt: "return foo", schema });
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect((res as any).details.json).toEqual({ foo: "bar" });
|
||||
});
|
||||
|
||||
it("throws on invalid json", async () => {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
(runEmbeddedPiAgent as any).mockResolvedValueOnce({
|
||||
meta: {},
|
||||
payloads: [{ text: "not-json" }],
|
||||
|
|
@ -77,6 +85,7 @@ describe("llm-task tool (json-only)", () => {
|
|||
});
|
||||
|
||||
it("throws on schema mismatch", async () => {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
(runEmbeddedPiAgent as any).mockResolvedValueOnce({
|
||||
meta: {},
|
||||
payloads: [{ text: JSON.stringify({ foo: 1 }) }],
|
||||
|
|
@ -87,18 +96,21 @@ describe("llm-task tool (json-only)", () => {
|
|||
});
|
||||
|
||||
it("passes provider/model overrides to embedded runner", async () => {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
(runEmbeddedPiAgent as any).mockResolvedValueOnce({
|
||||
meta: {},
|
||||
payloads: [{ text: JSON.stringify({ ok: true }) }],
|
||||
});
|
||||
const tool = createLlmTaskTool(fakeApi());
|
||||
await tool.execute("id", { prompt: "x", provider: "anthropic", model: "claude-4-sonnet" });
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const call = (runEmbeddedPiAgent as any).mock.calls[0]?.[0];
|
||||
expect(call.provider).toBe("anthropic");
|
||||
expect(call.model).toBe("claude-4-sonnet");
|
||||
});
|
||||
|
||||
it("enforces allowedModels", async () => {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
(runEmbeddedPiAgent as any).mockResolvedValueOnce({
|
||||
meta: {},
|
||||
payloads: [{ text: JSON.stringify({ ok: true }) }],
|
||||
|
|
@ -112,12 +124,14 @@ describe("llm-task tool (json-only)", () => {
|
|||
});
|
||||
|
||||
it("disables tools for embedded run", async () => {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
(runEmbeddedPiAgent as any).mockResolvedValueOnce({
|
||||
meta: {},
|
||||
payloads: [{ text: JSON.stringify({ ok: true }) }],
|
||||
});
|
||||
const tool = createLlmTaskTool(fakeApi());
|
||||
await tool.execute("id", { prompt: "x" });
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const call = (runEmbeddedPiAgent as any).mock.calls[0]?.[0];
|
||||
expect(call.disableTools).toBe(true);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ async function loadRunEmbeddedPiAgent(): Promise<RunEmbeddedPiAgentFn> {
|
|||
// Source checkout (tests/dev)
|
||||
try {
|
||||
const mod = await import("../../../src/agents/pi-embedded-runner.js");
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
if (typeof (mod as any).runEmbeddedPiAgent === "function") {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
return (mod as any).runEmbeddedPiAgent;
|
||||
}
|
||||
} catch {
|
||||
|
|
@ -111,7 +113,9 @@ export function createLlmTaskTool(api: OpenClawPluginApi) {
|
|||
undefined;
|
||||
|
||||
const authProfileId =
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
(typeof (params as any).authProfileId === "string" &&
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
(params as any).authProfileId.trim()) ||
|
||||
(typeof pluginCfg.defaultAuthProfileId === "string" &&
|
||||
pluginCfg.defaultAuthProfileId.trim()) ||
|
||||
|
|
@ -150,6 +154,7 @@ export function createLlmTaskTool(api: OpenClawPluginApi) {
|
|||
: undefined,
|
||||
};
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const input = (params as any).input as unknown;
|
||||
let inputJson: string;
|
||||
try {
|
||||
|
|
@ -192,6 +197,7 @@ export function createLlmTaskTool(api: OpenClawPluginApi) {
|
|||
disableTools: true,
|
||||
});
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const text = collectText((result as any).payloads);
|
||||
if (!text) {
|
||||
throw new Error("LLM returned empty output");
|
||||
|
|
@ -205,9 +211,11 @@ export function createLlmTaskTool(api: OpenClawPluginApi) {
|
|||
throw new Error("LLM returned invalid JSON");
|
||||
}
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const schema = (params as any).schema as unknown;
|
||||
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
||||
const ajv = new Ajv({ allErrors: true, strict: false });
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const validate = ajv.compile(schema as any);
|
||||
const ok = validate(parsed);
|
||||
if (!ok) {
|
||||
|
|
|
|||
|
|
@ -36,8 +36,9 @@ function fakeApi(overrides: Partial<OpenClawPluginApi> = {}): OpenClawPluginApi
|
|||
id: "lobster",
|
||||
name: "lobster",
|
||||
source: "test",
|
||||
config: {} as any,
|
||||
config: {},
|
||||
pluginConfig: {},
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
runtime: { version: "test" } as any,
|
||||
logger: { info() {}, warn() {}, error() {}, debug() {} },
|
||||
registerTool() {},
|
||||
|
|
@ -58,7 +59,7 @@ function fakeApi(overrides: Partial<OpenClawPluginApi> = {}): OpenClawPluginApi
|
|||
|
||||
function fakeCtx(overrides: Partial<OpenClawPluginToolContext> = {}): OpenClawPluginToolContext {
|
||||
return {
|
||||
config: {} as any,
|
||||
config: {},
|
||||
workspaceDir: "/tmp",
|
||||
agentDir: "/tmp",
|
||||
agentId: "main",
|
||||
|
|
|
|||
|
|
@ -180,9 +180,13 @@ describeLive("memory plugin live tests", () => {
|
|||
const liveApiKey = process.env.OPENAI_API_KEY ?? "";
|
||||
|
||||
// Mock plugin API
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const registeredTools: any[] = [];
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const registeredClis: any[] = [];
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const registeredServices: any[] = [];
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const registeredHooks: Record<string, any[]> = {};
|
||||
const logs: string[] = [];
|
||||
|
||||
|
|
@ -207,15 +211,19 @@ describeLive("memory plugin live tests", () => {
|
|||
error: (msg: string) => logs.push(`[error] ${msg}`),
|
||||
debug: (msg: string) => logs.push(`[debug] ${msg}`),
|
||||
},
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
registerTool: (tool: any, opts: any) => {
|
||||
registeredTools.push({ tool, opts });
|
||||
},
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
registerCli: (registrar: any, opts: any) => {
|
||||
registeredClis.push({ registrar, opts });
|
||||
},
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
registerService: (service: any) => {
|
||||
registeredServices.push(service);
|
||||
},
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
on: (hookName: string, handler: any) => {
|
||||
if (!registeredHooks[hookName]) {
|
||||
registeredHooks[hookName] = [];
|
||||
|
|
@ -226,6 +234,7 @@ describeLive("memory plugin live tests", () => {
|
|||
};
|
||||
|
||||
// Register plugin
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
memoryPlugin.register(mockApi as any);
|
||||
|
||||
// Check registration
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ export const tlonPlugin: ChannelPlugin = {
|
|||
} finally {
|
||||
await api.delete();
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
return { ok: false, error: error?.message ?? String(error) };
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export async function fetchGroupChanges(
|
|||
return changes;
|
||||
}
|
||||
return null;
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
runtime.log?.(
|
||||
`[tlon] Failed to fetch changes (falling back to full init): ${error?.message ?? String(error)}`,
|
||||
);
|
||||
|
|
@ -31,6 +31,7 @@ export async function fetchAllChannels(
|
|||
runtime.log?.("[tlon] Attempting auto-discovery of group channels...");
|
||||
const changes = await fetchGroupChanges(api, runtime, 5);
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
let initData: any;
|
||||
if (changes) {
|
||||
runtime.log?.("[tlon] Changes data received, using full init for channel extraction");
|
||||
|
|
@ -41,6 +42,7 @@ export async function fetchAllChannels(
|
|||
|
||||
const channels: string[] = [];
|
||||
if (initData && initData.groups) {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
for (const groupData of Object.values(initData.groups as Record<string, any>)) {
|
||||
if (groupData && typeof groupData === "object" && groupData.channels) {
|
||||
for (const channelNest of Object.keys(groupData.channels)) {
|
||||
|
|
@ -63,7 +65,7 @@ export async function fetchAllChannels(
|
|||
}
|
||||
|
||||
return channels;
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
runtime.log?.(`[tlon] Auto-discovery failed: ${error?.message ?? String(error)}`);
|
||||
runtime.log?.(
|
||||
"[tlon] To monitor group channels, add them to config: channels.tlon.groupChannels",
|
||||
|
|
|
|||
|
|
@ -35,11 +35,13 @@ export async function fetchChannelHistory(
|
|||
const scryPath = `/channels/v4/${channelNest}/posts/newest/${count}/outline.json`;
|
||||
runtime?.log?.(`[tlon] Fetching history: ${scryPath}`);
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const data: any = await api.scry(scryPath);
|
||||
if (!data) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
let posts: any[] = [];
|
||||
if (Array.isArray(data)) {
|
||||
posts = data;
|
||||
|
|
@ -65,7 +67,7 @@ export async function fetchChannelHistory(
|
|||
|
||||
runtime?.log?.(`[tlon] Extracted ${messages.length} messages from history`);
|
||||
return messages;
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
runtime?.log?.(`[tlon] Error fetching channel history: ${error?.message ?? String(error)}`);
|
||||
return [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v
|
|||
error: (message) => runtime.error?.(message),
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
runtime.error?.(`[tlon] Failed to authenticate: ${error?.message ?? String(error)}`);
|
||||
throw error;
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v
|
|||
if (discoveredChannels.length > 0) {
|
||||
groupChannels = discoveredChannels;
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
runtime.error?.(`[tlon] Auto-discovery failed: ${error?.message ?? String(error)}`);
|
||||
}
|
||||
}
|
||||
|
|
@ -120,6 +120,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v
|
|||
runtime.log?.("[tlon] No group channels to monitor (DMs only)");
|
||||
}
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const handleIncomingDM = async (update: any) => {
|
||||
try {
|
||||
const memo = update?.response?.add?.memo;
|
||||
|
|
@ -154,11 +155,12 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v
|
|||
isGroup: false,
|
||||
timestamp: memo.sent || Date.now(),
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
runtime.error?.(`[tlon] Error handling DM: ${error?.message ?? String(error)}`);
|
||||
}
|
||||
};
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const handleIncomingGroupMessage = (channelNest: string) => async (update: any) => {
|
||||
try {
|
||||
const parsed = parseChannelNest(channelNest);
|
||||
|
|
@ -235,7 +237,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v
|
|||
timestamp: content.sent || Date.now(),
|
||||
parentId,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
runtime.error?.(`[tlon] Error handling group message: ${error?.message ?? String(error)}`);
|
||||
}
|
||||
};
|
||||
|
|
@ -294,7 +296,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v
|
|||
"2. Key decisions or conclusions\n" +
|
||||
"3. Action items if any\n" +
|
||||
"4. Notable participants";
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
const errorMsg = `Sorry, I encountered an error while fetching the channel history: ${error?.message ?? String(error)}`;
|
||||
if (isGroup && groupChannel) {
|
||||
const parsed = parseChannelNest(groupChannel);
|
||||
|
|
@ -437,7 +439,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v
|
|||
});
|
||||
subscribedChannels.add(channelNest);
|
||||
runtime.log?.(`[tlon] Subscribed to group channel: ${channelNest}`);
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
runtime.error?.(
|
||||
`[tlon] Failed to subscribe to ${channelNest}: ${error?.message ?? String(error)}`,
|
||||
);
|
||||
|
|
@ -463,7 +465,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v
|
|||
});
|
||||
subscribedDMs.add(dmShip);
|
||||
runtime.log?.(`[tlon] Subscribed to DM with ${dmShip}`);
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
runtime.error?.(
|
||||
`[tlon] Failed to subscribe to DM with ${dmShip}: ${error?.message ?? String(error)}`,
|
||||
);
|
||||
|
|
@ -485,7 +487,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v
|
|||
await subscribeToChannel(channelNest);
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
runtime.error?.(`[tlon] Channel refresh failed: ${error?.message ?? String(error)}`);
|
||||
}
|
||||
}
|
||||
|
|
@ -500,7 +502,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v
|
|||
dmShips = dmList;
|
||||
runtime.log?.(`[tlon] Found ${dmShips.length} DM conversation(s)`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
runtime.error?.(`[tlon] Failed to fetch DM list: ${error?.message ?? String(error)}`);
|
||||
}
|
||||
|
||||
|
|
@ -544,7 +546,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v
|
|||
} finally {
|
||||
try {
|
||||
await api?.close();
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
runtime.error?.(`[tlon] Cleanup error: ${error?.message ?? String(error)}`);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,10 +49,14 @@ export function extractMessageText(content: unknown): string {
|
|||
return "";
|
||||
}
|
||||
|
||||
return content
|
||||
return (
|
||||
content
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
.map((block: any) => {
|
||||
if (block.inline && Array.isArray(block.inline)) {
|
||||
return block.inline
|
||||
return (
|
||||
block.inline
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
.map((item: any) => {
|
||||
if (typeof item === "string") {
|
||||
return item;
|
||||
|
|
@ -70,12 +74,14 @@ export function extractMessageText(content: unknown): string {
|
|||
}
|
||||
return "";
|
||||
})
|
||||
.join("");
|
||||
.join("")
|
||||
);
|
||||
}
|
||||
return "";
|
||||
})
|
||||
.join("\n")
|
||||
.trim();
|
||||
.trim()
|
||||
);
|
||||
}
|
||||
|
||||
export function isSummarizationRequest(messageText: string): boolean {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ const plugin = {
|
|||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setTwitchRuntime(api.runtime);
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
api.registerChannel({ plugin: twitchPlugin as any });
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -155,7 +155,6 @@ export function extractMentions(message: string): string[] {
|
|||
const mentions: string[] = [];
|
||||
let match: RegExpExecArray | null;
|
||||
|
||||
// biome-ignore lint/suspicious/noAssignInExpressions: Standard regex iteration pattern
|
||||
while ((match = mentionRegex.exec(message)) !== null) {
|
||||
const username = match[1];
|
||||
if (username) {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ export const twitchOutbound: ChannelOutboundAdapter = {
|
|||
return { ok: true, to: normalizedTo };
|
||||
}
|
||||
// Fallback to first allowFrom entry
|
||||
// biome-ignore lint/style/noNonNullAssertion: length > 0 check ensures element exists
|
||||
return { ok: true, to: allowList[0] };
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +73,6 @@ export const twitchOutbound: ChannelOutboundAdapter = {
|
|||
|
||||
// No target provided, use allowFrom fallback
|
||||
if (allowList.length > 0) {
|
||||
// biome-ignore lint/style/noNonNullAssertion: length > 0 check ensures element exists
|
||||
return { ok: true, to: allowList[0] };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,10 +21,12 @@ const mockQuit = vi.fn();
|
|||
const mockUnbind = vi.fn();
|
||||
|
||||
// Event handler storage for testing
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const messageHandlers: Array<(channel: string, user: string, message: string, msg: any) => void> =
|
||||
[];
|
||||
|
||||
// Mock functions that track handlers and return unbind objects
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const mockOnMessage = vi.fn((handler: any) => {
|
||||
messageHandlers.push(handler);
|
||||
return { unbind: mockUnbind };
|
||||
|
|
@ -269,6 +271,7 @@ describe("TwitchClientManager", () => {
|
|||
|
||||
// Check the stored handler is handler2
|
||||
const key = manager.getAccountKey(testAccount);
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect((manager as any).messageHandlers.get(key)).toBe(handler2);
|
||||
});
|
||||
});
|
||||
|
|
@ -290,7 +293,9 @@ describe("TwitchClientManager", () => {
|
|||
await manager.disconnect(testAccount);
|
||||
|
||||
const key = manager.getAccountKey(testAccount);
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect((manager as any).clients.has(key)).toBe(false);
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect((manager as any).messageHandlers.has(key)).toBe(false);
|
||||
});
|
||||
|
||||
|
|
@ -309,6 +314,7 @@ describe("TwitchClientManager", () => {
|
|||
expect(mockQuit).toHaveBeenCalledTimes(1);
|
||||
|
||||
const key2 = manager.getAccountKey(testAccount2);
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect((manager as any).clients.has(key2)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
@ -321,7 +327,9 @@ describe("TwitchClientManager", () => {
|
|||
await manager.disconnectAll();
|
||||
|
||||
expect(mockQuit).toHaveBeenCalledTimes(2);
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect((manager as any).clients.size).toBe(0);
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect((manager as any).messageHandlers.size).toBe(0);
|
||||
});
|
||||
|
||||
|
|
@ -387,6 +395,7 @@ describe("TwitchClientManager", () => {
|
|||
|
||||
it("should create client if not already connected", async () => {
|
||||
// Clear the existing client
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
(manager as any).clients.clear();
|
||||
|
||||
// Reset connect call count for this specific test
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ function median(values: number[]): number {
|
|||
|
||||
async function runModel(opts: {
|
||||
label: string;
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
model: Model<any>;
|
||||
apiKey: string;
|
||||
runs: number;
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ for (const [login, lines] of linesByLogin.entries()) {
|
|||
}
|
||||
let user = apiByLogin.get(login);
|
||||
if (!user) {
|
||||
user = fetchUser(login);
|
||||
user = fetchUser(login) || undefined;
|
||||
}
|
||||
if (user) {
|
||||
const contributions = contributionsByLogin.get(login) ?? 0;
|
||||
|
|
@ -256,7 +256,9 @@ function run(cmd: string): string {
|
|||
}).trim();
|
||||
}
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
function parsePaginatedJson(raw: string): any[] {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const items: any[] = [];
|
||||
for (const line of raw.split("\n")) {
|
||||
if (!line.trim()) {
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ const applyPatchSchema = Type.Object({
|
|||
|
||||
export function createApplyPatchTool(
|
||||
options: { cwd?: string; sandboxRoot?: string } = {},
|
||||
// biome-ignore lint/suspicious/noExplicitAny: TypeBox schema type from pi-agent-core uses a different module instance.
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
): AgentTool<any, ApplyPatchToolDetails> {
|
||||
const cwd = options.cwd ?? process.cwd();
|
||||
const sandboxRoot = options.sandboxRoot;
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ const OAUTH_PROVIDER_IDS = new Set<OAuthProvider>(
|
|||
);
|
||||
|
||||
function isOAuthProvider(provider: string): provider is OAuthProvider {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: type guard needs runtime check
|
||||
return OAUTH_PROVIDER_IDS.has(provider as any);
|
||||
return OAUTH_PROVIDER_IDS.has(provider);
|
||||
}
|
||||
|
||||
const resolveOAuthProvider = (provider: string): OAuthProvider | null =>
|
||||
|
|
|
|||
|
|
@ -799,7 +799,7 @@ async function runExecProcess(opts: {
|
|||
|
||||
export function createExecTool(
|
||||
defaults?: ExecToolDefaults,
|
||||
// biome-ignore lint/suspicious/noExplicitAny: TypeBox schema type from pi-agent-core uses a different module instance.
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
): AgentTool<any, ExecToolDetails> {
|
||||
const defaultBackgroundMs = clampNumber(
|
||||
defaults?.backgroundMs ?? readEnvInt("PI_BASH_YIELD_MS"),
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ const processSchema = Type.Object({
|
|||
|
||||
export function createProcessTool(
|
||||
defaults?: ProcessToolDefaults,
|
||||
// biome-ignore lint/suspicious/noExplicitAny: TypeBox schema type from pi-agent-core uses a different module instance.
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
): AgentTool<any> {
|
||||
if (defaults?.cleanupMs !== undefined) {
|
||||
setJobTtlMs(defaults.cleanupMs);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ describe("downgradeOpenAIReasoningBlocks", () => {
|
|||
},
|
||||
];
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect(downgradeOpenAIReasoningBlocks(input as any)).toEqual(input);
|
||||
});
|
||||
|
||||
|
|
@ -34,6 +35,7 @@ describe("downgradeOpenAIReasoningBlocks", () => {
|
|||
{ role: "user", content: "next" },
|
||||
];
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect(downgradeOpenAIReasoningBlocks(input as any)).toEqual([
|
||||
{ role: "user", content: "next" },
|
||||
]);
|
||||
|
|
@ -52,6 +54,7 @@ describe("downgradeOpenAIReasoningBlocks", () => {
|
|||
},
|
||||
];
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect(downgradeOpenAIReasoningBlocks(input as any)).toEqual([]);
|
||||
});
|
||||
|
||||
|
|
@ -69,6 +72,7 @@ describe("downgradeOpenAIReasoningBlocks", () => {
|
|||
},
|
||||
];
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect(downgradeOpenAIReasoningBlocks(input as any)).toEqual(input);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { runBeforeToolCallHook } from "./pi-tools.before-tool-call.js";
|
|||
import { normalizeToolName } from "./tool-policy.js";
|
||||
import { jsonResult } from "./tools/common.js";
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: TypeBox schema type from pi-agent-core uses a different module instance.
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
type AnyAgentTool = AgentTool<any, unknown>;
|
||||
|
||||
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
||||
|
|
@ -36,7 +36,6 @@ export function toToolDefinitions(tools: AnyAgentTool[]): ToolDefinition[] {
|
|||
name,
|
||||
label: tool.label ?? name,
|
||||
description: tool.description ?? "",
|
||||
// biome-ignore lint/suspicious/noExplicitAny: TypeBox schema from pi-agent-core uses a different module instance.
|
||||
parameters: tool.parameters,
|
||||
execute: async (
|
||||
toolCallId,
|
||||
|
|
@ -87,6 +86,7 @@ export function toClientToolDefinitions(
|
|||
name: func.name,
|
||||
label: func.name,
|
||||
description: func.description ?? "",
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
parameters: func.parameters as any,
|
||||
execute: async (
|
||||
toolCallId,
|
||||
|
|
|
|||
|
|
@ -18,12 +18,14 @@ describe("before_tool_call hook integration", () => {
|
|||
hasHooks: vi.fn(),
|
||||
runBeforeToolCall: vi.fn(),
|
||||
};
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
mockGetGlobalHookRunner.mockReturnValue(hookRunner as any);
|
||||
});
|
||||
|
||||
it("executes tool normally when no hook is registered", async () => {
|
||||
hookRunner.hasHooks.mockReturnValue(false);
|
||||
const execute = vi.fn().mockResolvedValue({ content: [], details: { ok: true } });
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const tool = wrapToolWithBeforeToolCallHook({ name: "Read", execute } as any, {
|
||||
agentId: "main",
|
||||
sessionKey: "main",
|
||||
|
|
@ -39,6 +41,7 @@ describe("before_tool_call hook integration", () => {
|
|||
hookRunner.hasHooks.mockReturnValue(true);
|
||||
hookRunner.runBeforeToolCall.mockResolvedValue({ params: { mode: "safe" } });
|
||||
const execute = vi.fn().mockResolvedValue({ content: [], details: { ok: true } });
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const tool = wrapToolWithBeforeToolCallHook({ name: "exec", execute } as any);
|
||||
|
||||
await tool.execute("call-2", { cmd: "ls" }, undefined, undefined);
|
||||
|
|
@ -58,6 +61,7 @@ describe("before_tool_call hook integration", () => {
|
|||
blockReason: "blocked",
|
||||
});
|
||||
const execute = vi.fn().mockResolvedValue({ content: [], details: { ok: true } });
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const tool = wrapToolWithBeforeToolCallHook({ name: "exec", execute } as any);
|
||||
|
||||
await expect(tool.execute("call-3", { cmd: "rm -rf /" }, undefined, undefined)).rejects.toThrow(
|
||||
|
|
@ -70,6 +74,7 @@ describe("before_tool_call hook integration", () => {
|
|||
hookRunner.hasHooks.mockReturnValue(true);
|
||||
hookRunner.runBeforeToolCall.mockRejectedValue(new Error("boom"));
|
||||
const execute = vi.fn().mockResolvedValue({ content: [], details: { ok: true } });
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const tool = wrapToolWithBeforeToolCallHook({ name: "read", execute } as any);
|
||||
|
||||
await tool.execute("call-4", { path: "/tmp/file" }, undefined, undefined);
|
||||
|
|
@ -81,6 +86,7 @@ describe("before_tool_call hook integration", () => {
|
|||
hookRunner.hasHooks.mockReturnValue(true);
|
||||
hookRunner.runBeforeToolCall.mockResolvedValue(undefined);
|
||||
const execute = vi.fn().mockResolvedValue({ content: [], details: { ok: true } });
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const tool = wrapToolWithBeforeToolCallHook({ name: "ReAd", execute } as any, {
|
||||
agentId: "main",
|
||||
sessionKey: "main",
|
||||
|
|
@ -113,6 +119,7 @@ describe("before_tool_call hook integration for client tools", () => {
|
|||
hasHooks: vi.fn(),
|
||||
runBeforeToolCall: vi.fn(),
|
||||
};
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
mockGetGlobalHookRunner.mockReturnValue(hookRunner as any);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { AgentTool } from "@mariozechner/pi-agent-core";
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: TypeBox schema type from pi-agent-core uses a different module instance.
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
export type AnyAgentTool = AgentTool<any, unknown>;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ export function guardSessionManager(
|
|||
|
||||
const hookRunner = getGlobalHookRunner();
|
||||
const transform = hookRunner?.hasHooks("tool_result_persist")
|
||||
? (message: any, meta: { toolCallId?: string; toolName?: string; isSynthetic?: boolean }) => {
|
||||
? // oxlint-disable-next-line typescript/no-explicit-any
|
||||
(message: any, meta: { toolCallId?: string; toolName?: string; isSynthetic?: boolean }) => {
|
||||
const out = hookRunner.runToolResultPersist(
|
||||
{
|
||||
toolName: meta.toolName,
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ describe("tool_result_persist hook", () => {
|
|||
isError: false,
|
||||
content: [{ type: "text", text: "ok" }],
|
||||
details: { big: "x".repeat(10_000) },
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any);
|
||||
|
||||
const messages = sm
|
||||
|
|
@ -59,6 +60,7 @@ describe("tool_result_persist hook", () => {
|
|||
.filter((e) => e.type === "message")
|
||||
.map((e) => (e as { message: AgentMessage }).message);
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const toolResult = messages.find((m) => (m as any).role === "toolResult") as any;
|
||||
expect(toolResult).toBeTruthy();
|
||||
expect(toolResult.details).toBeTruthy();
|
||||
|
|
@ -121,6 +123,7 @@ describe("tool_result_persist hook", () => {
|
|||
isError: false,
|
||||
content: [{ type: "text", text: "ok" }],
|
||||
details: { big: "x".repeat(10_000) },
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any);
|
||||
|
||||
const messages = sm
|
||||
|
|
@ -128,6 +131,7 @@ describe("tool_result_persist hook", () => {
|
|||
.filter((e) => e.type === "message")
|
||||
.map((e) => (e as { message: AgentMessage }).message);
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const toolResult = messages.find((m) => (m as any).role === "toolResult") as any;
|
||||
expect(toolResult).toBeTruthy();
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import fs from "node:fs/promises";
|
|||
import { detectMime } from "../../media/mime.js";
|
||||
import { sanitizeToolResultImages } from "../tool-images.js";
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: TypeBox schema type from pi-agent-core uses a different module instance.
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
export type AnyAgentTool = AgentTool<any, unknown>;
|
||||
|
||||
export type StringParamOptions = {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ export async function handleCommands(params: HandleCommandsParams): Promise<Comm
|
|||
// Send hook messages immediately if present
|
||||
if (hookEvent.messages.length > 0) {
|
||||
// Use OriginatingChannel/To if available, otherwise fall back to command channel/from
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const channel = params.ctx.OriginatingChannel || (params.command.channel as any);
|
||||
// For replies, use 'from' (the sender) not 'to' (which might be the bot itself)
|
||||
const to = params.ctx.OriginatingTo || params.command.from || params.command.to;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ export type InlineActionResult =
|
|||
abortedLastRun: boolean;
|
||||
};
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
function extractTextFromToolResult(result: any): string | null {
|
||||
if (!result || typeof result !== "object") {
|
||||
return null;
|
||||
|
|
@ -193,6 +194,7 @@ export async function handleInlineActions(params: {
|
|||
command: rawArgs,
|
||||
commandName: skillInvocation.command.name,
|
||||
skillName: skillInvocation.command.skillName,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any);
|
||||
const text = extractTextFromToolResult(result) ?? "✅ Done.";
|
||||
typing.cleanup();
|
||||
|
|
|
|||
|
|
@ -285,6 +285,7 @@ export async function runPreparedReply(
|
|||
}
|
||||
}
|
||||
if (resetTriggered && command.isAuthorizedSender) {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const channel = ctx.OriginatingChannel || (command.channel as any);
|
||||
const to = ctx.OriginatingTo || command.from || command.to;
|
||||
if (channel && to) {
|
||||
|
|
|
|||
|
|
@ -181,18 +181,14 @@ describe("color allocation", () => {
|
|||
});
|
||||
|
||||
it("allocates next unused color from palette", () => {
|
||||
// biome-ignore lint/style/noNonNullAssertion: Test file with known array
|
||||
const usedColors = new Set([PROFILE_COLORS[0].toUpperCase()]);
|
||||
expect(allocateColor(usedColors)).toBe(PROFILE_COLORS[1]);
|
||||
});
|
||||
|
||||
it("skips multiple used colors", () => {
|
||||
const usedColors = new Set([
|
||||
// biome-ignore lint/style/noNonNullAssertion: Test file with known array
|
||||
PROFILE_COLORS[0].toUpperCase(),
|
||||
// biome-ignore lint/style/noNonNullAssertion: Test file with known array
|
||||
PROFILE_COLORS[1].toUpperCase(),
|
||||
// biome-ignore lint/style/noNonNullAssertion: Test file with known array
|
||||
PROFILE_COLORS[2].toUpperCase(),
|
||||
]);
|
||||
expect(allocateColor(usedColors)).toBe(PROFILE_COLORS[3]);
|
||||
|
|
|
|||
|
|
@ -100,7 +100,6 @@ export function allocateColor(usedColors: Set<string>): string {
|
|||
}
|
||||
// All colors used, cycle based on count
|
||||
const index = usedColors.size % PROFILE_COLORS.length;
|
||||
// biome-ignore lint/style/noNonNullAssertion: Array is non-empty constant
|
||||
return PROFILE_COLORS[index] ?? PROFILE_COLORS[0];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,12 +51,11 @@ describe("browser server-context ensureTabAvailable", () => {
|
|||
} as unknown as Response;
|
||||
});
|
||||
|
||||
// @ts-expect-error test override
|
||||
global.fetch = fetchMock;
|
||||
|
||||
const state: BrowserServerState = {
|
||||
// unused in these tests
|
||||
// biome-ignore lint/suspicious/noExplicitAny: test stub
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
server: null as any,
|
||||
port: 0,
|
||||
resolved: {
|
||||
|
|
@ -113,11 +112,10 @@ describe("browser server-context ensureTabAvailable", () => {
|
|||
return { ok: true, json: async () => next } as unknown as Response;
|
||||
});
|
||||
|
||||
// @ts-expect-error test override
|
||||
global.fetch = fetchMock;
|
||||
|
||||
const state: BrowserServerState = {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: test stub
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
server: null as any,
|
||||
port: 0,
|
||||
resolved: {
|
||||
|
|
@ -164,11 +162,11 @@ describe("browser server-context ensureTabAvailable", () => {
|
|||
}
|
||||
return { ok: true, json: async () => next } as unknown as Response;
|
||||
});
|
||||
// @ts-expect-error test override
|
||||
|
||||
global.fetch = fetchMock;
|
||||
|
||||
const state: BrowserServerState = {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: test stub
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
server: null as any,
|
||||
port: 0,
|
||||
resolved: {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ function makeState(
|
|||
profile: "remote" | "openclaw",
|
||||
): BrowserServerState & { profiles: Map<string, { lastTargetId?: string | null }> } {
|
||||
return {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: test stub
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
server: null as any,
|
||||
port: 0,
|
||||
resolved: {
|
||||
|
|
@ -67,7 +67,7 @@ describe("browser server-context remote profile tab operations", () => {
|
|||
const fetchMock = vi.fn(async () => {
|
||||
throw new Error("unexpected fetch");
|
||||
});
|
||||
// @ts-expect-error test override
|
||||
|
||||
global.fetch = fetchMock;
|
||||
|
||||
const { createBrowserRouteContext } = await import("./server-context.js");
|
||||
|
|
@ -134,7 +134,7 @@ describe("browser server-context remote profile tab operations", () => {
|
|||
const fetchMock = vi.fn(async () => {
|
||||
throw new Error("unexpected fetch");
|
||||
});
|
||||
// @ts-expect-error test override
|
||||
|
||||
global.fetch = fetchMock;
|
||||
|
||||
const { createBrowserRouteContext } = await import("./server-context.js");
|
||||
|
|
@ -163,7 +163,7 @@ describe("browser server-context remote profile tab operations", () => {
|
|||
const fetchMock = vi.fn(async () => {
|
||||
throw new Error("unexpected fetch");
|
||||
});
|
||||
// @ts-expect-error test override
|
||||
|
||||
global.fetch = fetchMock;
|
||||
|
||||
const { createBrowserRouteContext } = await import("./server-context.js");
|
||||
|
|
@ -191,7 +191,7 @@ describe("browser server-context remote profile tab operations", () => {
|
|||
const fetchMock = vi.fn(async () => {
|
||||
throw new Error("unexpected fetch");
|
||||
});
|
||||
// @ts-expect-error test override
|
||||
|
||||
global.fetch = fetchMock;
|
||||
|
||||
const { createBrowserRouteContext } = await import("./server-context.js");
|
||||
|
|
@ -229,7 +229,7 @@ describe("browser server-context remote profile tab operations", () => {
|
|||
],
|
||||
} as unknown as Response;
|
||||
});
|
||||
// @ts-expect-error test override
|
||||
|
||||
global.fetch = fetchMock;
|
||||
|
||||
const { createBrowserRouteContext } = await import("./server-context.js");
|
||||
|
|
@ -273,7 +273,7 @@ describe("browser server-context tab selection state", () => {
|
|||
],
|
||||
} as unknown as Response;
|
||||
});
|
||||
// @ts-expect-error test override
|
||||
|
||||
global.fetch = fetchMock;
|
||||
|
||||
const { createBrowserRouteContext } = await import("./server-context.js");
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ describe("directory (config-backed)", () => {
|
|||
channels: { C111: { users: ["U777"] } },
|
||||
},
|
||||
},
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
|
||||
const peers = await listSlackDirectoryPeersFromConfig({
|
||||
|
|
@ -65,6 +66,7 @@ describe("directory (config-backed)", () => {
|
|||
},
|
||||
},
|
||||
},
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
|
||||
const peers = await listDiscordDirectoryPeersFromConfig({
|
||||
|
|
@ -94,6 +96,7 @@ describe("directory (config-backed)", () => {
|
|||
groups: { "-1001": {}, "*": {} },
|
||||
},
|
||||
},
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
|
||||
const peers = await listTelegramDirectoryPeersFromConfig({
|
||||
|
|
@ -121,6 +124,7 @@ describe("directory (config-backed)", () => {
|
|||
groups: { "999@g.us": { requireMention: true }, "*": {} },
|
||||
},
|
||||
},
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
|
||||
const peers = await listWhatsAppDirectoryPeersFromConfig({
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ import type {
|
|||
} from "./types.core.js";
|
||||
|
||||
// Channel docking: implement this contract in src/channels/plugins/<id>.ts.
|
||||
// biome-ignore lint/suspicious/noExplicitAny: registry aggregates heterogeneous account types.
|
||||
export type ChannelConfigUiHint = {
|
||||
label?: string;
|
||||
help?: string;
|
||||
|
|
@ -45,6 +44,7 @@ export type ChannelConfigSchema = {
|
|||
uiHints?: Record<string, ChannelConfigUiHint>;
|
||||
};
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
export type ChannelPlugin<ResolvedAccount = any> = {
|
||||
id: ChannelId;
|
||||
meta: ChannelMeta;
|
||||
|
|
|
|||
|
|
@ -77,8 +77,11 @@ async function dockerImageExists(image: string): Promise<boolean> {
|
|||
try {
|
||||
await runExec("docker", ["image", "inspect", image], { timeoutMs: 5_000 });
|
||||
return true;
|
||||
} catch (error: any) {
|
||||
const stderr = error?.stderr || error?.message || "";
|
||||
} catch (error) {
|
||||
const stderr =
|
||||
(error as { stderr: string } | undefined)?.stderr ||
|
||||
(error as { message: string } | undefined)?.message ||
|
||||
"";
|
||||
if (String(stderr).includes("No such image")) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,9 @@ describe("parseExecApprovalData", () => {
|
|||
});
|
||||
|
||||
it("rejects null/undefined input", () => {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect(parseExecApprovalData(null as any)).toBeNull();
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expect(parseExecApprovalData(undefined as any)).toBeNull();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -31,10 +31,13 @@ describe("discord processDiscordMessage inbound contract", () => {
|
|||
const storePath = path.join(dir, "sessions.json");
|
||||
|
||||
await processDiscordMessage({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
cfg: { messages: {}, session: { store: storePath } } as any,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
discordConfig: {} as any,
|
||||
accountId: "default",
|
||||
token: "token",
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
runtime: { log: () => {}, error: () => {} } as any,
|
||||
guildHistories: new Map(),
|
||||
historyLimit: 0,
|
||||
|
|
@ -44,19 +47,23 @@ describe("discord processDiscordMessage inbound contract", () => {
|
|||
replyToMode: "off",
|
||||
ackReactionScope: "direct",
|
||||
groupPolicy: "open",
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
data: { guild: null } as any,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
client: { rest: {} } as any,
|
||||
message: {
|
||||
id: "m1",
|
||||
channelId: "c1",
|
||||
timestamp: new Date().toISOString(),
|
||||
attachments: [],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any,
|
||||
author: {
|
||||
id: "U1",
|
||||
username: "alice",
|
||||
discriminator: "0",
|
||||
globalName: "Alice",
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any,
|
||||
channelInfo: null,
|
||||
channelName: undefined,
|
||||
|
|
@ -86,7 +93,9 @@ describe("discord processDiscordMessage inbound contract", () => {
|
|||
accountId: "default",
|
||||
sessionKey: "agent:main:discord:dm:u1",
|
||||
mainSessionKey: "agent:main:main",
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any);
|
||||
|
||||
expect(capturedCtx).toBeTruthy();
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ describe("processDiscordMessage ack reactions", () => {
|
|||
sender: { label: "user" },
|
||||
});
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await processDiscordMessage(ctx as any);
|
||||
|
||||
expect(reactMessageDiscord).not.toHaveBeenCalled();
|
||||
|
|
@ -117,6 +118,7 @@ describe("processDiscordMessage ack reactions", () => {
|
|||
sender: { label: "user" },
|
||||
});
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await processDiscordMessage(ctx as any);
|
||||
|
||||
expect(reactMessageDiscord).toHaveBeenCalledWith("c1", "m1", "👀", { rest: {} });
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ export function resolveDiscordWebhookId(message: DiscordWebhookMessageLike): str
|
|||
|
||||
export function resolveDiscordSenderIdentity(params: {
|
||||
author: User;
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
member?: any;
|
||||
pluralkitInfo?: PluralKitMessageInfo | null;
|
||||
}): DiscordSenderIdentity {
|
||||
|
|
@ -73,6 +74,7 @@ export function resolveDiscordSenderIdentity(params: {
|
|||
|
||||
export function resolveDiscordSenderLabel(params: {
|
||||
author: User;
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
member?: any;
|
||||
pluralkitInfo?: PluralKitMessageInfo | null;
|
||||
}): string {
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ export class GatewayClient {
|
|||
return new Error("gateway tls fingerprint mismatch");
|
||||
}
|
||||
return undefined;
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
}) as any;
|
||||
}
|
||||
this.ws = new WebSocket(url, wsOptions);
|
||||
|
|
|
|||
|
|
@ -128,12 +128,14 @@ describe("timestampOptsFromConfig", () => {
|
|||
userTimezone: "America/Chicago",
|
||||
},
|
||||
},
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any);
|
||||
|
||||
expect(opts.timezone).toBe("America/Chicago");
|
||||
});
|
||||
|
||||
it("falls back gracefully with empty config", () => {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const opts = timestampOptsFromConfig({} as any);
|
||||
|
||||
expect(opts.timezone).toBeDefined(); // resolveUserTimezone provides a default
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@ describe("gateway server auth/connect", () => {
|
|||
gateway: {
|
||||
trustedProxies: ["127.0.0.1"],
|
||||
},
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any);
|
||||
const prevToken = process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
process.env.OPENCLAW_GATEWAY_TOKEN = "secret";
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ describe("POST /tools/invoke", () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
|
||||
const port = await getFreePort();
|
||||
|
|
@ -60,12 +61,14 @@ describe("POST /tools/invoke", () => {
|
|||
// No explicit tool allowlist; rely on profile + alsoAllow.
|
||||
testState.agentsConfig = {
|
||||
list: [{ id: "main" }],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
|
||||
// minimal profile does NOT include agents_list, but alsoAllow should.
|
||||
const { writeConfigFile } = await import("../config/config.js");
|
||||
await writeConfigFile({
|
||||
tools: { profile: "minimal", alsoAllow: ["agents_list"] },
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any);
|
||||
|
||||
const port = await getFreePort();
|
||||
|
|
@ -88,6 +91,7 @@ describe("POST /tools/invoke", () => {
|
|||
it("supports tools.alsoAllow without allow/profile (implicit allow-all)", async () => {
|
||||
testState.agentsConfig = {
|
||||
list: [{ id: "main" }],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
|
||||
const { CONFIG_PATH } = await import("../config/config.js");
|
||||
|
|
@ -125,6 +129,7 @@ describe("POST /tools/invoke", () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
|
||||
const port = await getFreePort();
|
||||
|
|
@ -175,6 +180,7 @@ describe("POST /tools/invoke", () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
|
||||
const port = await getFreePort();
|
||||
|
|
@ -210,6 +216,7 @@ describe("POST /tools/invoke", () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
|
||||
const port = await getFreePort();
|
||||
|
|
@ -239,6 +246,7 @@ describe("POST /tools/invoke", () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
|
||||
const port = await getFreePort();
|
||||
|
|
@ -266,11 +274,13 @@ describe("POST /tools/invoke", () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
|
||||
const { writeConfigFile } = await import("../config/config.js");
|
||||
await writeConfigFile({
|
||||
tools: { profile: "minimal" },
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any);
|
||||
|
||||
const port = await getFreePort();
|
||||
|
|
@ -305,6 +315,7 @@ describe("POST /tools/invoke", () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
testState.sessionConfig = { mainKey: "primary" };
|
||||
|
||||
|
|
|
|||
|
|
@ -230,12 +230,14 @@ export async function handleToolsInvokeHttpRequest(
|
|||
|
||||
const coreToolNames = new Set(
|
||||
allTools
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
.filter((tool) => !getPluginToolMeta(tool as any))
|
||||
.map((tool) => normalizeToolName(tool.name))
|
||||
.filter(Boolean),
|
||||
);
|
||||
const pluginGroups = buildPluginToolGroups({
|
||||
tools: allTools,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
toolMeta: (tool) => getPluginToolMeta(tool as any),
|
||||
});
|
||||
const resolvePolicy = (policy: typeof profilePolicy, label: string) => {
|
||||
|
|
@ -306,10 +308,12 @@ export async function handleToolsInvokeHttpRequest(
|
|||
|
||||
try {
|
||||
const toolArgs = mergeActionIntoArgsIfSupported({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
toolSchema: (tool as any).parameters,
|
||||
action,
|
||||
args,
|
||||
});
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const result = await (tool as any).execute?.(`http-${Date.now()}`, toolArgs);
|
||||
sendJson(res, 200, { ok: true, result });
|
||||
} catch (err) {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ async function getRecentSessionContent(
|
|||
if ((role === "user" || role === "assistant") && msg.content) {
|
||||
// Extract text content
|
||||
const text = Array.isArray(msg.content)
|
||||
? msg.content.find((c: any) => c.type === "text")?.text
|
||||
? // oxlint-disable-next-line typescript/no-explicit-any
|
||||
msg.content.find((c: any) => c.type === "text")?.text
|
||||
: msg.content;
|
||||
if (text && !text.startsWith("/")) {
|
||||
allMessages.push(`${role}: ${text}`);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ const createRes = () => {
|
|||
status: vi.fn(),
|
||||
json: vi.fn(),
|
||||
headersSent: false,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
res.status.mockReturnValue(res);
|
||||
res.json.mockReturnValue(res);
|
||||
|
|
@ -26,9 +27,11 @@ describe("createLineWebhookMiddleware", () => {
|
|||
const req = {
|
||||
headers: { "x-line-signature": sign(rawBody, secret) },
|
||||
body: rawBody,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
const res = createRes();
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await middleware(req, res, {} as any);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(200);
|
||||
|
|
@ -44,9 +47,11 @@ describe("createLineWebhookMiddleware", () => {
|
|||
const req = {
|
||||
headers: { "x-line-signature": sign(rawBody, secret) },
|
||||
body: Buffer.from(rawBody, "utf-8"),
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
const res = createRes();
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await middleware(req, res, {} as any);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(200);
|
||||
|
|
@ -62,9 +67,11 @@ describe("createLineWebhookMiddleware", () => {
|
|||
const req = {
|
||||
headers: { "x-line-signature": sign(rawBody, secret) },
|
||||
body: rawBody,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
const res = createRes();
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await middleware(req, res, {} as any);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(400);
|
||||
|
|
@ -80,9 +87,11 @@ describe("createLineWebhookMiddleware", () => {
|
|||
const req = {
|
||||
headers: { "x-line-signature": "invalid-signature" },
|
||||
body: rawBody,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
const res = createRes();
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await middleware(req, res, {} as any);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(401);
|
||||
|
|
@ -99,9 +108,11 @@ describe("createLineWebhookMiddleware", () => {
|
|||
const req = {
|
||||
headers: { "x-line-signature": sign(rawBody, wrongSecret) },
|
||||
body: rawBody,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
const res = createRes();
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await middleware(req, res, {} as any);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(401);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ describe("registerPluginCliCommands", () => {
|
|||
const program = new Command();
|
||||
program.command("memory");
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
registerPluginCliCommands(program, {} as any);
|
||||
|
||||
expect(mocks.memoryRegister).not.toHaveBeenCalled();
|
||||
|
|
|
|||
|
|
@ -335,12 +335,14 @@ export function createHookRunner(registry: PluginRegistry, options: HookRunnerOp
|
|||
|
||||
for (const hook of hooks) {
|
||||
try {
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const out = (hook.handler as any)({ ...event, message: current }, ctx) as
|
||||
| PluginHookToolResultPersistResult
|
||||
| void
|
||||
| Promise<unknown>;
|
||||
|
||||
// Guard against accidental async handlers (this hook is sync-only).
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
if (out && typeof (out as any).then === "function") {
|
||||
const msg =
|
||||
`[hooks] tool_result_persist handler from ${hook.pluginId} returned a Promise; ` +
|
||||
|
|
|
|||
|
|
@ -826,6 +826,7 @@ async function collectChannelSecurityFindings(params: {
|
|||
|
||||
if (!hasAnySenderAllowlist) {
|
||||
const providerSetting = (telegramCfg.commands as { nativeSkills?: unknown } | undefined)
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
?.nativeSkills as any;
|
||||
const skillsEnabled = resolveNativeSkillsEnabled({
|
||||
providerId: "telegram",
|
||||
|
|
|
|||
|
|
@ -41,10 +41,12 @@ describe("signal event handler typing + read receipts", () => {
|
|||
vi.resetModules();
|
||||
const { createSignalEventHandler } = await import("./monitor/event-handler.js");
|
||||
const handler = createSignalEventHandler({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
runtime: { log: () => {}, error: () => {} } as any,
|
||||
cfg: {
|
||||
messages: { inbound: { debounceMs: 0 } },
|
||||
channels: { signal: { dmPolicy: "open", allowFrom: ["*"] } },
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any,
|
||||
baseUrl: "http://localhost",
|
||||
account: "+15550009999",
|
||||
|
|
@ -66,6 +68,7 @@ describe("signal event handler typing + read receipts", () => {
|
|||
fetchAttachment: async () => null,
|
||||
deliverReplies: async () => {},
|
||||
resolveSignalReactionTargets: () => [],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
isSignalReactionMessage: () => false as any,
|
||||
shouldEmitSignalReactionNotification: () => false,
|
||||
buildSignalReactionSystemEventText: () => "reaction",
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ describe("signal createSignalEventHandler inbound contract", () => {
|
|||
capturedCtx = undefined;
|
||||
|
||||
const handler = createSignalEventHandler({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
runtime: { log: () => {}, error: () => {} } as any,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
cfg: { messages: { inbound: { debounceMs: 0 } } } as any,
|
||||
baseUrl: "http://localhost",
|
||||
accountId: "default",
|
||||
|
|
@ -45,6 +47,7 @@ describe("signal createSignalEventHandler inbound contract", () => {
|
|||
fetchAttachment: async () => null,
|
||||
deliverReplies: async () => {},
|
||||
resolveSignalReactionTargets: () => [],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
isSignalReactionMessage: () => false as any,
|
||||
shouldEmitSignalReactionNotification: () => false,
|
||||
buildSignalReactionSystemEventText: () => "reaction",
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ describe("slack prepareSlackMessage inbound contract", () => {
|
|||
mediaMaxBytes: 1024,
|
||||
removeAckAfterReply: false,
|
||||
});
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
slackCtx.resolveUserName = async () => ({ name: "Alice" }) as any;
|
||||
|
||||
const account: ResolvedSlackAccount = {
|
||||
|
|
@ -74,6 +75,7 @@ describe("slack prepareSlackMessage inbound contract", () => {
|
|||
});
|
||||
|
||||
expect(prepared).toBeTruthy();
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expectInboundContextContract(prepared!.ctxPayload as any);
|
||||
});
|
||||
|
||||
|
|
@ -116,6 +118,7 @@ describe("slack prepareSlackMessage inbound contract", () => {
|
|||
mediaMaxBytes: 1024,
|
||||
removeAckAfterReply: false,
|
||||
});
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
slackCtx.resolveUserName = async () => ({ name: "Alice" }) as any;
|
||||
|
||||
const account: ResolvedSlackAccount = {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ describe("createSlackThreadTsResolver", () => {
|
|||
messages: [{ ts: "1", thread_ts: "9" }],
|
||||
});
|
||||
const resolver = createSlackThreadTsResolver({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
client: { conversations: { history: historyMock } } as any,
|
||||
cacheTtlMs: 60_000,
|
||||
maxSize: 5,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ export const dispatchTelegramMessage = async ({
|
|||
telegramCfg,
|
||||
opts,
|
||||
resolveBotTopicsEnabled,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
}: any) => {
|
||||
const {
|
||||
ctxPayload,
|
||||
|
|
|
|||
|
|
@ -446,7 +446,9 @@ export function createTelegramBot(opts: TelegramBotOptions) {
|
|||
senderLabel = senderLabel || "unknown";
|
||||
|
||||
// Extract forum thread info (similar to message processing)
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const messageThreadId = (reaction as any).message_thread_id;
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
const isForum = (reaction.chat as any).is_forum === true;
|
||||
const resolvedThreadId = resolveTelegramForumThreadId({
|
||||
isForum,
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ describe("normalizeForwardedContext", () => {
|
|||
sender_user: { first_name: "Ada", last_name: "Lovelace", username: "ada", id: 42 },
|
||||
date: 123,
|
||||
},
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any);
|
||||
expect(ctx).not.toBeNull();
|
||||
expect(ctx?.from).toBe("Ada Lovelace (@ada)");
|
||||
|
|
@ -91,6 +92,7 @@ describe("normalizeForwardedContext", () => {
|
|||
it("handles hidden forward_origin names", () => {
|
||||
const ctx = normalizeForwardedContext({
|
||||
forward_origin: { type: "hidden_user", sender_user_name: "Hidden Name", date: 456 },
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any);
|
||||
expect(ctx).not.toBeNull();
|
||||
expect(ctx?.from).toBe("Hidden Name");
|
||||
|
|
@ -109,6 +111,7 @@ describe("normalizeForwardedContext", () => {
|
|||
},
|
||||
forward_signature: "Stan",
|
||||
forward_date: 789,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any);
|
||||
expect(ctx).not.toBeNull();
|
||||
expect(ctx?.from).toBe("OpenClaw Updates (Stan)");
|
||||
|
|
@ -124,6 +127,7 @@ describe("normalizeForwardedContext", () => {
|
|||
const ctx = normalizeForwardedContext({
|
||||
forward_sender_name: "Legacy Hidden",
|
||||
forward_date: 111,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any);
|
||||
expect(ctx).not.toBeNull();
|
||||
expect(ctx?.from).toBe("Legacy Hidden");
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ describe("createTelegramDraftStream", () => {
|
|||
it("passes message_thread_id when provided", () => {
|
||||
const api = { sendMessageDraft: vi.fn().mockResolvedValue(true) };
|
||||
const stream = createTelegramDraftStream({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
api: api as any,
|
||||
chatId: 123,
|
||||
draftId: 42,
|
||||
|
|
@ -21,6 +22,7 @@ describe("createTelegramDraftStream", () => {
|
|||
it("omits message_thread_id for general topic id", () => {
|
||||
const api = { sendMessageDraft: vi.fn().mockResolvedValue(true) };
|
||||
const stream = createTelegramDraftStream({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
api: api as any,
|
||||
chatId: 123,
|
||||
draftId: 42,
|
||||
|
|
@ -35,6 +37,7 @@ describe("createTelegramDraftStream", () => {
|
|||
it("keeps message_thread_id for dm threads", () => {
|
||||
const api = { sendMessageDraft: vi.fn().mockResolvedValue(true) };
|
||||
const stream = createTelegramDraftStream({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
api: api as any,
|
||||
chatId: 123,
|
||||
draftId: 42,
|
||||
|
|
|
|||
|
|
@ -53,7 +53,9 @@ describe("tui-event-handlers: handleAgentEvent", () => {
|
|||
const { chatLog, tui, setActivityStatus } = makeContext(state);
|
||||
const { handleAgentEvent } = createEventHandlers({
|
||||
// Casts are fine here: TUI runtime shape is larger than we need in unit tests.
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
chatLog: chatLog as any,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
tui: tui as any,
|
||||
state,
|
||||
setActivityStatus,
|
||||
|
|
@ -80,7 +82,9 @@ describe("tui-event-handlers: handleAgentEvent", () => {
|
|||
const state = makeState({ activeChatRunId: "run-1" });
|
||||
const { chatLog, tui, setActivityStatus } = makeContext(state);
|
||||
const { handleAgentEvent } = createEventHandlers({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
chatLog: chatLog as any,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
tui: tui as any,
|
||||
state,
|
||||
setActivityStatus,
|
||||
|
|
@ -103,7 +107,9 @@ describe("tui-event-handlers: handleAgentEvent", () => {
|
|||
const state = makeState({ activeChatRunId: "run-9" });
|
||||
const { tui, setActivityStatus } = makeContext(state);
|
||||
const { handleAgentEvent } = createEventHandlers({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
chatLog: { startTool: vi.fn(), updateToolResult: vi.fn() } as any,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
tui: tui as any,
|
||||
state,
|
||||
setActivityStatus,
|
||||
|
|
@ -125,7 +131,9 @@ describe("tui-event-handlers: handleAgentEvent", () => {
|
|||
const state = makeState({ activeChatRunId: null });
|
||||
const { chatLog, tui, setActivityStatus } = makeContext(state);
|
||||
const { handleChatEvent, handleAgentEvent } = createEventHandlers({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
chatLog: chatLog as any,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
tui: tui as any,
|
||||
state,
|
||||
setActivityStatus,
|
||||
|
|
@ -157,7 +165,9 @@ describe("tui-event-handlers: handleAgentEvent", () => {
|
|||
const state = makeState({ activeChatRunId: null });
|
||||
const { chatLog, tui, setActivityStatus } = makeContext(state);
|
||||
const { handleChatEvent, handleAgentEvent } = createEventHandlers({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
chatLog: chatLog as any,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
tui: tui as any,
|
||||
state,
|
||||
setActivityStatus,
|
||||
|
|
@ -188,7 +198,9 @@ describe("tui-event-handlers: handleAgentEvent", () => {
|
|||
const state = makeState({ activeChatRunId: "run-active" });
|
||||
const { chatLog, tui, setActivityStatus } = makeContext(state);
|
||||
const { handleChatEvent, handleAgentEvent } = createEventHandlers({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
chatLog: chatLog as any,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
tui: tui as any,
|
||||
state,
|
||||
setActivityStatus,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ const theme = {
|
|||
dim: (s: string) => `<d>${s}</d>`,
|
||||
bold: (s: string) => `<b>${s}</b>`,
|
||||
accentSoft: (s: string) => `<a>${s}</a>`,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
|
||||
describe("tui-waiting", () => {
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ describe("jidToE164", () => {
|
|||
const original = fs.readFileSync;
|
||||
const spy = vi
|
||||
.spyOn(fs, "readFileSync")
|
||||
// biome-ignore lint/suspicious/noExplicitAny: forwarding to native signature
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
.mockImplementation((path: any, encoding?: any) => {
|
||||
if (path === mappingPath) {
|
||||
return `"5551234"`;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ describe("web processMessage inbound contract", () => {
|
|||
capturedCtx = undefined;
|
||||
|
||||
await processMessage({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
cfg: { messages: {} } as any,
|
||||
msg: {
|
||||
id: "msg1",
|
||||
|
|
@ -29,11 +30,13 @@ describe("web processMessage inbound contract", () => {
|
|||
senderE164: "+15550002222",
|
||||
groupSubject: "Test Group",
|
||||
groupParticipants: [],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any,
|
||||
route: {
|
||||
agentId: "main",
|
||||
accountId: "default",
|
||||
sessionKey: "agent:main:whatsapp:group:123",
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any,
|
||||
groupHistoryKey: "123@g.us",
|
||||
groupHistories: new Map(),
|
||||
|
|
@ -41,7 +44,9 @@ describe("web processMessage inbound contract", () => {
|
|||
connectionId: "conn",
|
||||
verbose: false,
|
||||
maxMediaBytes: 1,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
replyResolver: (async () => undefined) as any,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
replyLogger: { info: () => {}, warn: () => {}, error: () => {}, debug: () => {} } as any,
|
||||
backgroundTasks: new Set(),
|
||||
rememberSentText: (_text: string | undefined, _opts: unknown) => {},
|
||||
|
|
@ -49,9 +54,11 @@ describe("web processMessage inbound contract", () => {
|
|||
echoForget: () => {},
|
||||
buildCombinedEchoKey: () => "echo",
|
||||
groupHistory: [],
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any);
|
||||
|
||||
expect(capturedCtx).toBeTruthy();
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
expectInboundContextContract(capturedCtx as any);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue