fix(heartbeat): telegram accountId + cron jobId compat (#516, thanks @YuriNachos)
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
- Heartbeat: resolve Telegram account IDs from config-only tokens; cron tool accepts canonical `jobId` and legacy `id` for job actions. (#516) — thanks @YuriNachos
|
||||||
- Discord: stop provider when gateway reconnects are exhausted and surface errors. (#514) — thanks @joshp123
|
- Discord: stop provider when gateway reconnects are exhausted and surface errors. (#514) — thanks @joshp123
|
||||||
- Auto-reply: preserve block reply ordering with timeout fallback for streaming. (#503) — thanks @joshp123
|
- Auto-reply: preserve block reply ordering with timeout fallback for streaming. (#503) — thanks @joshp123
|
||||||
- Auto-reply: avoid splitting outbound chunks inside parentheses. (#499) — thanks @philipp-spiess
|
- Auto-reply: avoid splitting outbound chunks inside parentheses. (#499) — thanks @philipp-spiess
|
||||||
|
|||||||
@@ -19,9 +19,17 @@ describe("cron tool", () => {
|
|||||||
{ action: "update", jobId: "job-1", patch: { foo: "bar" } },
|
{ action: "update", jobId: "job-1", patch: { foo: "bar" } },
|
||||||
{ id: "job-1", patch: { foo: "bar" } },
|
{ id: "job-1", patch: { foo: "bar" } },
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"update",
|
||||||
|
{ action: "update", id: "job-2", patch: { foo: "bar" } },
|
||||||
|
{ id: "job-2", patch: { foo: "bar" } },
|
||||||
|
],
|
||||||
["remove", { action: "remove", jobId: "job-1" }, { id: "job-1" }],
|
["remove", { action: "remove", jobId: "job-1" }, { id: "job-1" }],
|
||||||
|
["remove", { action: "remove", id: "job-2" }, { id: "job-2" }],
|
||||||
["run", { action: "run", jobId: "job-1" }, { id: "job-1" }],
|
["run", { action: "run", jobId: "job-1" }, { id: "job-1" }],
|
||||||
|
["run", { action: "run", id: "job-2" }, { id: "job-2" }],
|
||||||
["runs", { action: "runs", jobId: "job-1" }, { id: "job-1" }],
|
["runs", { action: "runs", jobId: "job-1" }, { id: "job-1" }],
|
||||||
|
["runs", { action: "runs", id: "job-2" }, { id: "job-2" }],
|
||||||
])("%s sends id to gateway", async (action, args, expectedParams) => {
|
])("%s sends id to gateway", async (action, args, expectedParams) => {
|
||||||
const tool = createCronTool();
|
const tool = createCronTool();
|
||||||
await tool.execute("call1", args);
|
await tool.execute("call1", args);
|
||||||
@@ -35,6 +43,20 @@ describe("cron tool", () => {
|
|||||||
expect(call.params).toEqual(expectedParams);
|
expect(call.params).toEqual(expectedParams);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("prefers jobId over id when both are provided", async () => {
|
||||||
|
const tool = createCronTool();
|
||||||
|
await tool.execute("call1", {
|
||||||
|
action: "run",
|
||||||
|
jobId: "job-primary",
|
||||||
|
id: "job-legacy",
|
||||||
|
});
|
||||||
|
|
||||||
|
const call = callGatewayMock.mock.calls[0]?.[0] as {
|
||||||
|
params?: unknown;
|
||||||
|
};
|
||||||
|
expect(call?.params).toEqual({ id: "job-primary" });
|
||||||
|
});
|
||||||
|
|
||||||
it("normalizes cron.add job payloads", async () => {
|
it("normalizes cron.add job payloads", async () => {
|
||||||
const tool = createCronTool();
|
const tool = createCronTool();
|
||||||
await tool.execute("call2", {
|
await tool.execute("call2", {
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ const CronToolSchema = Type.Union([
|
|||||||
gatewayUrl: Type.Optional(Type.String()),
|
gatewayUrl: Type.Optional(Type.String()),
|
||||||
gatewayToken: Type.Optional(Type.String()),
|
gatewayToken: Type.Optional(Type.String()),
|
||||||
timeoutMs: Type.Optional(Type.Number()),
|
timeoutMs: Type.Optional(Type.Number()),
|
||||||
jobId: Type.String(),
|
jobId: Type.Optional(Type.String()),
|
||||||
|
id: Type.Optional(Type.String()),
|
||||||
patch: Type.Object({}, { additionalProperties: true }),
|
patch: Type.Object({}, { additionalProperties: true }),
|
||||||
}),
|
}),
|
||||||
Type.Object({
|
Type.Object({
|
||||||
@@ -55,21 +56,24 @@ const CronToolSchema = Type.Union([
|
|||||||
gatewayUrl: Type.Optional(Type.String()),
|
gatewayUrl: Type.Optional(Type.String()),
|
||||||
gatewayToken: Type.Optional(Type.String()),
|
gatewayToken: Type.Optional(Type.String()),
|
||||||
timeoutMs: Type.Optional(Type.Number()),
|
timeoutMs: Type.Optional(Type.Number()),
|
||||||
jobId: Type.String(),
|
jobId: Type.Optional(Type.String()),
|
||||||
|
id: Type.Optional(Type.String()),
|
||||||
}),
|
}),
|
||||||
Type.Object({
|
Type.Object({
|
||||||
action: Type.Literal("run"),
|
action: Type.Literal("run"),
|
||||||
gatewayUrl: Type.Optional(Type.String()),
|
gatewayUrl: Type.Optional(Type.String()),
|
||||||
gatewayToken: Type.Optional(Type.String()),
|
gatewayToken: Type.Optional(Type.String()),
|
||||||
timeoutMs: Type.Optional(Type.Number()),
|
timeoutMs: Type.Optional(Type.Number()),
|
||||||
jobId: Type.String(),
|
jobId: Type.Optional(Type.String()),
|
||||||
|
id: Type.Optional(Type.String()),
|
||||||
}),
|
}),
|
||||||
Type.Object({
|
Type.Object({
|
||||||
action: Type.Literal("runs"),
|
action: Type.Literal("runs"),
|
||||||
gatewayUrl: Type.Optional(Type.String()),
|
gatewayUrl: Type.Optional(Type.String()),
|
||||||
gatewayToken: Type.Optional(Type.String()),
|
gatewayToken: Type.Optional(Type.String()),
|
||||||
timeoutMs: Type.Optional(Type.Number()),
|
timeoutMs: Type.Optional(Type.Number()),
|
||||||
jobId: Type.String(),
|
jobId: Type.Optional(Type.String()),
|
||||||
|
id: Type.Optional(Type.String()),
|
||||||
}),
|
}),
|
||||||
Type.Object({
|
Type.Object({
|
||||||
action: Type.Literal("wake"),
|
action: Type.Literal("wake"),
|
||||||
@@ -88,7 +92,7 @@ export function createCronTool(): AnyAgentTool {
|
|||||||
label: "Cron",
|
label: "Cron",
|
||||||
name: "cron",
|
name: "cron",
|
||||||
description:
|
description:
|
||||||
"Manage Gateway cron jobs (status/list/add/update/remove/run/runs) and send wake events.",
|
"Manage Gateway cron jobs (status/list/add/update/remove/run/runs) and send wake events. Use `jobId` as the canonical identifier; `id` is accepted for compatibility.",
|
||||||
parameters: CronToolSchema,
|
parameters: CronToolSchema,
|
||||||
execute: async (_toolCallId, args) => {
|
execute: async (_toolCallId, args) => {
|
||||||
const params = args as Record<string, unknown>;
|
const params = args as Record<string, unknown>;
|
||||||
@@ -121,7 +125,13 @@ export function createCronTool(): AnyAgentTool {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
case "update": {
|
case "update": {
|
||||||
const id = readStringParam(params, "jobId", { required: true });
|
const id =
|
||||||
|
readStringParam(params, "jobId") ?? readStringParam(params, "id");
|
||||||
|
if (!id) {
|
||||||
|
throw new Error(
|
||||||
|
"jobId required (id accepted for backward compatibility)",
|
||||||
|
);
|
||||||
|
}
|
||||||
if (!params.patch || typeof params.patch !== "object") {
|
if (!params.patch || typeof params.patch !== "object") {
|
||||||
throw new Error("patch required");
|
throw new Error("patch required");
|
||||||
}
|
}
|
||||||
@@ -134,19 +144,37 @@ export function createCronTool(): AnyAgentTool {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
case "remove": {
|
case "remove": {
|
||||||
const id = readStringParam(params, "jobId", { required: true });
|
const id =
|
||||||
|
readStringParam(params, "jobId") ?? readStringParam(params, "id");
|
||||||
|
if (!id) {
|
||||||
|
throw new Error(
|
||||||
|
"jobId required (id accepted for backward compatibility)",
|
||||||
|
);
|
||||||
|
}
|
||||||
return jsonResult(
|
return jsonResult(
|
||||||
await callGatewayTool("cron.remove", gatewayOpts, { id }),
|
await callGatewayTool("cron.remove", gatewayOpts, { id }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case "run": {
|
case "run": {
|
||||||
const id = readStringParam(params, "jobId", { required: true });
|
const id =
|
||||||
|
readStringParam(params, "jobId") ?? readStringParam(params, "id");
|
||||||
|
if (!id) {
|
||||||
|
throw new Error(
|
||||||
|
"jobId required (id accepted for backward compatibility)",
|
||||||
|
);
|
||||||
|
}
|
||||||
return jsonResult(
|
return jsonResult(
|
||||||
await callGatewayTool("cron.run", gatewayOpts, { id }),
|
await callGatewayTool("cron.run", gatewayOpts, { id }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case "runs": {
|
case "runs": {
|
||||||
const id = readStringParam(params, "jobId", { required: true });
|
const id =
|
||||||
|
readStringParam(params, "jobId") ?? readStringParam(params, "id");
|
||||||
|
if (!id) {
|
||||||
|
throw new Error(
|
||||||
|
"jobId required (id accepted for backward compatibility)",
|
||||||
|
);
|
||||||
|
}
|
||||||
return jsonResult(
|
return jsonResult(
|
||||||
await callGatewayTool("cron.runs", gatewayOpts, { id }),
|
await callGatewayTool("cron.runs", gatewayOpts, { id }),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user