feat(cron): add contextMessages param to control reminder context
This commit is contained in:
committed by
Peter Steinberger
parent
5fe8c4ab8c
commit
4642fae193
@@ -85,7 +85,7 @@ describe("cron tool", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("adds recent context for systemEvent reminders when session key is available", async () => {
|
it("adds recent context for systemEvent reminders when contextMessages > 0", async () => {
|
||||||
callGatewayMock
|
callGatewayMock
|
||||||
.mockResolvedValueOnce({
|
.mockResolvedValueOnce({
|
||||||
messages: [
|
messages: [
|
||||||
@@ -102,6 +102,7 @@ describe("cron tool", () => {
|
|||||||
const tool = createCronTool({ agentSessionKey: "main" });
|
const tool = createCronTool({ agentSessionKey: "main" });
|
||||||
await tool.execute("call3", {
|
await tool.execute("call3", {
|
||||||
action: "add",
|
action: "add",
|
||||||
|
contextMessages: 3,
|
||||||
job: {
|
job: {
|
||||||
name: "reminder",
|
name: "reminder",
|
||||||
schedule: { atMs: 123 },
|
schedule: { atMs: 123 },
|
||||||
@@ -127,4 +128,28 @@ describe("cron tool", () => {
|
|||||||
expect(text).toContain("Assistant: We agreed to review on Tuesday.");
|
expect(text).toContain("Assistant: We agreed to review on Tuesday.");
|
||||||
expect(text).toContain("User: Remind me about the thing at 2pm");
|
expect(text).toContain("User: Remind me about the thing at 2pm");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not add context when contextMessages is 0 (default)", async () => {
|
||||||
|
callGatewayMock.mockResolvedValueOnce({ ok: true });
|
||||||
|
|
||||||
|
const tool = createCronTool({ agentSessionKey: "main" });
|
||||||
|
await tool.execute("call4", {
|
||||||
|
action: "add",
|
||||||
|
job: {
|
||||||
|
name: "reminder",
|
||||||
|
schedule: { atMs: 123 },
|
||||||
|
payload: { text: "Reminder: the thing." },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Should only call cron.add, not chat.history
|
||||||
|
expect(callGatewayMock).toHaveBeenCalledTimes(1);
|
||||||
|
const cronCall = callGatewayMock.mock.calls[0]?.[0] as {
|
||||||
|
method?: string;
|
||||||
|
params?: { payload?: { text?: string } };
|
||||||
|
};
|
||||||
|
expect(cronCall.method).toBe("cron.add");
|
||||||
|
const text = cronCall.params?.payload?.text ?? "";
|
||||||
|
expect(text).not.toContain("Recent context:");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ const CRON_ACTIONS = ["status", "list", "add", "update", "remove", "run", "runs"
|
|||||||
|
|
||||||
const CRON_WAKE_MODES = ["now", "next-heartbeat"] as const;
|
const CRON_WAKE_MODES = ["now", "next-heartbeat"] as const;
|
||||||
|
|
||||||
const REMINDER_CONTEXT_MESSAGES = 3;
|
|
||||||
const REMINDER_CONTEXT_PER_MESSAGE_MAX = 220;
|
const REMINDER_CONTEXT_PER_MESSAGE_MAX = 220;
|
||||||
const REMINDER_CONTEXT_TOTAL_MAX = 700;
|
const REMINDER_CONTEXT_TOTAL_MAX = 700;
|
||||||
const REMINDER_CONTEXT_MARKER = "\n\nRecent context:\n";
|
const REMINDER_CONTEXT_MARKER = "\n\nRecent context:\n";
|
||||||
@@ -34,6 +33,7 @@ const CronToolSchema = Type.Object({
|
|||||||
patch: Type.Optional(Type.Object({}, { additionalProperties: true })),
|
patch: Type.Optional(Type.Object({}, { additionalProperties: true })),
|
||||||
text: Type.Optional(Type.String()),
|
text: Type.Optional(Type.String()),
|
||||||
mode: optionalStringEnum(CRON_WAKE_MODES),
|
mode: optionalStringEnum(CRON_WAKE_MODES),
|
||||||
|
contextMessages: Type.Optional(Type.Number()),
|
||||||
});
|
});
|
||||||
|
|
||||||
type CronToolOptions = {
|
type CronToolOptions = {
|
||||||
@@ -86,7 +86,9 @@ function extractMessageText(message: ChatMessage): { role: string; text: string
|
|||||||
async function buildReminderContextLines(params: {
|
async function buildReminderContextLines(params: {
|
||||||
agentSessionKey?: string;
|
agentSessionKey?: string;
|
||||||
gatewayOpts: GatewayCallOptions;
|
gatewayOpts: GatewayCallOptions;
|
||||||
|
contextMessages: number;
|
||||||
}) {
|
}) {
|
||||||
|
if (params.contextMessages <= 0) return [];
|
||||||
const sessionKey = params.agentSessionKey?.trim();
|
const sessionKey = params.agentSessionKey?.trim();
|
||||||
if (!sessionKey) return [];
|
if (!sessionKey) return [];
|
||||||
const cfg = loadConfig();
|
const cfg = loadConfig();
|
||||||
@@ -101,7 +103,7 @@ async function buildReminderContextLines(params: {
|
|||||||
const parsed = messages
|
const parsed = messages
|
||||||
.map((msg) => extractMessageText(msg as ChatMessage))
|
.map((msg) => extractMessageText(msg as ChatMessage))
|
||||||
.filter((msg): msg is { role: string; text: string } => Boolean(msg));
|
.filter((msg): msg is { role: string; text: string } => Boolean(msg));
|
||||||
const recent = parsed.slice(-REMINDER_CONTEXT_MESSAGES);
|
const recent = parsed.slice(-params.contextMessages);
|
||||||
if (recent.length === 0) return [];
|
if (recent.length === 0) return [];
|
||||||
const lines: string[] = [];
|
const lines: string[] = [];
|
||||||
let total = 0;
|
let total = 0;
|
||||||
@@ -149,6 +151,8 @@ export function createCronTool(opts?: CronToolOptions): AnyAgentTool {
|
|||||||
throw new Error("job required");
|
throw new Error("job required");
|
||||||
}
|
}
|
||||||
const job = normalizeCronJobCreate(params.job) ?? params.job;
|
const job = normalizeCronJobCreate(params.job) ?? params.job;
|
||||||
|
const contextMessages =
|
||||||
|
typeof params.contextMessages === "number" ? params.contextMessages : 0;
|
||||||
if (
|
if (
|
||||||
job &&
|
job &&
|
||||||
typeof job === "object" &&
|
typeof job === "object" &&
|
||||||
@@ -160,6 +164,7 @@ export function createCronTool(opts?: CronToolOptions): AnyAgentTool {
|
|||||||
const contextLines = await buildReminderContextLines({
|
const contextLines = await buildReminderContextLines({
|
||||||
agentSessionKey: opts?.agentSessionKey,
|
agentSessionKey: opts?.agentSessionKey,
|
||||||
gatewayOpts,
|
gatewayOpts,
|
||||||
|
contextMessages,
|
||||||
});
|
});
|
||||||
if (contextLines.length > 0) {
|
if (contextLines.length > 0) {
|
||||||
const baseText = stripExistingContext(payload.text);
|
const baseText = stripExistingContext(payload.text);
|
||||||
|
|||||||
Reference in New Issue
Block a user