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