mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 08:41:23 +00:00
refactor(runtime): split runtime builders and stabilize cron tool seam
This commit is contained in:
@@ -1,11 +1,7 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const { callGatewayMock } = vi.hoisted(() => ({
|
||||
callGatewayMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../gateway/call.js", () => ({
|
||||
callGateway: (opts: unknown) => callGatewayMock(opts),
|
||||
const { callGatewayToolMock } = vi.hoisted(() => ({
|
||||
callGatewayToolMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../agent-scope.js", () => ({
|
||||
@@ -16,12 +12,15 @@ import { createCronTool } from "./cron-tool.js";
|
||||
|
||||
describe("cron tool flat-params", () => {
|
||||
beforeEach(() => {
|
||||
callGatewayMock.mockReset();
|
||||
callGatewayMock.mockResolvedValue({ ok: true });
|
||||
callGatewayToolMock.mockReset();
|
||||
callGatewayToolMock.mockResolvedValue({ ok: true });
|
||||
});
|
||||
|
||||
it("preserves explicit top-level sessionKey during flat-params recovery", async () => {
|
||||
const tool = createCronTool({ agentSessionKey: "agent:main:discord:channel:ops" });
|
||||
const tool = createCronTool(
|
||||
{ agentSessionKey: "agent:main:discord:channel:ops" },
|
||||
{ callGatewayTool: callGatewayToolMock },
|
||||
);
|
||||
await tool.execute("call-flat-session-key", {
|
||||
action: "add",
|
||||
sessionKey: "agent:main:telegram:group:-100123:topic:99",
|
||||
@@ -29,11 +28,12 @@ describe("cron tool flat-params", () => {
|
||||
message: "do stuff",
|
||||
});
|
||||
|
||||
const call = callGatewayMock.mock.calls[0]?.[0] as {
|
||||
method?: string;
|
||||
params?: { sessionKey?: string };
|
||||
};
|
||||
expect(call.method).toBe("cron.add");
|
||||
expect(call.params?.sessionKey).toBe("agent:main:telegram:group:-100123:topic:99");
|
||||
const [method, _gatewayOpts, params] = callGatewayToolMock.mock.calls[0] as [
|
||||
string,
|
||||
unknown,
|
||||
{ sessionKey?: string },
|
||||
];
|
||||
expect(method).toBe("cron.add");
|
||||
expect(params.sessionKey).toBe("agent:main:telegram:group:-100123:topic:99");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import type { CronDelivery, CronMessageChannel } from "../../cron/types.js";
|
||||
import { loadConfig } from "../../config/config.js";
|
||||
import { normalizeCronJobCreate, normalizeCronJobPatch } from "../../cron/normalize.js";
|
||||
import type { CronDelivery, CronMessageChannel } from "../../cron/types.js";
|
||||
import { normalizeHttpWebhookUrl } from "../../cron/webhook-url.js";
|
||||
import { parseAgentSessionKey } from "../../sessions/session-key-utils.js";
|
||||
import { extractTextFromChatContent } from "../../shared/chat-content.js";
|
||||
@@ -50,6 +50,12 @@ type CronToolOptions = {
|
||||
agentSessionKey?: string;
|
||||
};
|
||||
|
||||
type GatewayToolCaller = typeof callGatewayTool;
|
||||
|
||||
type CronToolDeps = {
|
||||
callGatewayTool?: GatewayToolCaller;
|
||||
};
|
||||
|
||||
type ChatMessage = {
|
||||
role?: unknown;
|
||||
content?: unknown;
|
||||
@@ -84,6 +90,7 @@ async function buildReminderContextLines(params: {
|
||||
agentSessionKey?: string;
|
||||
gatewayOpts: GatewayCallOptions;
|
||||
contextMessages: number;
|
||||
callGatewayTool: GatewayToolCaller;
|
||||
}) {
|
||||
const maxMessages = Math.min(
|
||||
REMINDER_CONTEXT_MESSAGES_MAX,
|
||||
@@ -100,7 +107,7 @@ async function buildReminderContextLines(params: {
|
||||
const { mainKey, alias } = resolveMainSessionAlias(cfg);
|
||||
const resolvedKey = resolveInternalSessionKey({ key: sessionKey, alias, mainKey });
|
||||
try {
|
||||
const res = await callGatewayTool<{ messages: Array<unknown> }>(
|
||||
const res = await params.callGatewayTool<{ messages: Array<unknown> }>(
|
||||
"chat.history",
|
||||
params.gatewayOpts,
|
||||
{
|
||||
@@ -197,7 +204,8 @@ function inferDeliveryFromSessionKey(agentSessionKey?: string): CronDelivery | n
|
||||
return delivery;
|
||||
}
|
||||
|
||||
export function createCronTool(opts?: CronToolOptions): AnyAgentTool {
|
||||
export function createCronTool(opts?: CronToolOptions, deps?: CronToolDeps): AnyAgentTool {
|
||||
const callGateway = deps?.callGatewayTool ?? callGatewayTool;
|
||||
return {
|
||||
label: "Cron",
|
||||
name: "cron",
|
||||
@@ -272,10 +280,10 @@ Use jobId as the canonical identifier; id is accepted for compatibility. Use con
|
||||
|
||||
switch (action) {
|
||||
case "status":
|
||||
return jsonResult(await callGatewayTool("cron.status", gatewayOpts, {}));
|
||||
return jsonResult(await callGateway("cron.status", gatewayOpts, {}));
|
||||
case "list":
|
||||
return jsonResult(
|
||||
await callGatewayTool("cron.list", gatewayOpts, {
|
||||
await callGateway("cron.list", gatewayOpts, {
|
||||
includeDisabled: Boolean(params.includeDisabled),
|
||||
}),
|
||||
);
|
||||
@@ -412,6 +420,7 @@ Use jobId as the canonical identifier; id is accepted for compatibility. Use con
|
||||
agentSessionKey: opts?.agentSessionKey,
|
||||
gatewayOpts,
|
||||
contextMessages,
|
||||
callGatewayTool: callGateway,
|
||||
});
|
||||
if (contextLines.length > 0) {
|
||||
const baseText = stripExistingContext(payload.text);
|
||||
@@ -419,7 +428,7 @@ Use jobId as the canonical identifier; id is accepted for compatibility. Use con
|
||||
}
|
||||
}
|
||||
}
|
||||
return jsonResult(await callGatewayTool("cron.add", gatewayOpts, job));
|
||||
return jsonResult(await callGateway("cron.add", gatewayOpts, job));
|
||||
}
|
||||
case "update": {
|
||||
const id = readStringParam(params, "jobId") ?? readStringParam(params, "id");
|
||||
@@ -431,7 +440,7 @@ Use jobId as the canonical identifier; id is accepted for compatibility. Use con
|
||||
}
|
||||
const patch = normalizeCronJobPatch(params.patch) ?? params.patch;
|
||||
return jsonResult(
|
||||
await callGatewayTool("cron.update", gatewayOpts, {
|
||||
await callGateway("cron.update", gatewayOpts, {
|
||||
id,
|
||||
patch,
|
||||
}),
|
||||
@@ -442,7 +451,7 @@ Use jobId as the canonical identifier; id is accepted for compatibility. Use con
|
||||
if (!id) {
|
||||
throw new Error("jobId required (id accepted for backward compatibility)");
|
||||
}
|
||||
return jsonResult(await callGatewayTool("cron.remove", gatewayOpts, { id }));
|
||||
return jsonResult(await callGateway("cron.remove", gatewayOpts, { id }));
|
||||
}
|
||||
case "run": {
|
||||
const id = readStringParam(params, "jobId") ?? readStringParam(params, "id");
|
||||
@@ -451,14 +460,14 @@ Use jobId as the canonical identifier; id is accepted for compatibility. Use con
|
||||
}
|
||||
const runMode =
|
||||
params.runMode === "due" || params.runMode === "force" ? params.runMode : "force";
|
||||
return jsonResult(await callGatewayTool("cron.run", gatewayOpts, { id, mode: runMode }));
|
||||
return jsonResult(await callGateway("cron.run", gatewayOpts, { id, mode: runMode }));
|
||||
}
|
||||
case "runs": {
|
||||
const id = readStringParam(params, "jobId") ?? readStringParam(params, "id");
|
||||
if (!id) {
|
||||
throw new Error("jobId required (id accepted for backward compatibility)");
|
||||
}
|
||||
return jsonResult(await callGatewayTool("cron.runs", gatewayOpts, { id }));
|
||||
return jsonResult(await callGateway("cron.runs", gatewayOpts, { id }));
|
||||
}
|
||||
case "wake": {
|
||||
const text = readStringParam(params, "text", { required: true });
|
||||
@@ -467,7 +476,7 @@ Use jobId as the canonical identifier; id is accepted for compatibility. Use con
|
||||
? params.mode
|
||||
: "next-heartbeat";
|
||||
return jsonResult(
|
||||
await callGatewayTool("wake", gatewayOpts, { mode, text }, { expectFinal: false }),
|
||||
await callGateway("wake", gatewayOpts, { mode, text }, { expectFinal: false }),
|
||||
);
|
||||
}
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user