feat(hooks): add cleanup fields to HookMappingResolved, HookAction, HookTransformResult and propagate through mapping
This commit is contained in:
parent
bfde8e1213
commit
fa5e8481ab
@ -3,6 +3,7 @@ import os from "node:os";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import type { HookAction, HookMappingResolved } from "./hooks-mapping.js";
|
||||||
import { applyHookMappings, resolveHookMappings } from "./hooks-mapping.js";
|
import { applyHookMappings, resolveHookMappings } from "./hooks-mapping.js";
|
||||||
|
|
||||||
const baseUrl = new URL("http://127.0.0.1:18789/hooks/gmail");
|
const baseUrl = new URL("http://127.0.0.1:18789/hooks/gmail");
|
||||||
@ -32,8 +33,7 @@ describe("hooks mapping", () => {
|
|||||||
path: "gmail",
|
path: "gmail",
|
||||||
});
|
});
|
||||||
expect(result?.ok).toBe(true);
|
expect(result?.ok).toBe(true);
|
||||||
if (result?.ok) {
|
if (result?.ok && result.action?.kind === "agent") {
|
||||||
expect(result.action.kind).toBe("agent");
|
|
||||||
expect(result.action.message).toBe("Subject: Hello");
|
expect(result.action.message).toBe("Subject: Hello");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -57,7 +57,7 @@ describe("hooks mapping", () => {
|
|||||||
path: "gmail",
|
path: "gmail",
|
||||||
});
|
});
|
||||||
expect(result?.ok).toBe(true);
|
expect(result?.ok).toBe(true);
|
||||||
if (result?.ok && result.action.kind === "agent") {
|
if (result?.ok && result.action?.kind === "agent") {
|
||||||
expect(result.action.model).toBe("openai/gpt-4.1-mini");
|
expect(result.action.model).toBe("openai/gpt-4.1-mini");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -90,11 +90,8 @@ describe("hooks mapping", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(result?.ok).toBe(true);
|
expect(result?.ok).toBe(true);
|
||||||
if (result?.ok) {
|
if (result?.ok && result.action?.kind === "wake") {
|
||||||
expect(result.action.kind).toBe("wake");
|
expect(result.action.text).toBe("Ping Ada");
|
||||||
if (result.action.kind === "wake") {
|
|
||||||
expect(result.action.text).toBe("Ping Ada");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -147,8 +144,7 @@ describe("hooks mapping", () => {
|
|||||||
path: "gmail",
|
path: "gmail",
|
||||||
});
|
});
|
||||||
expect(result?.ok).toBe(true);
|
expect(result?.ok).toBe(true);
|
||||||
if (result?.ok) {
|
if (result?.ok && result.action?.kind === "agent") {
|
||||||
expect(result.action.kind).toBe("agent");
|
|
||||||
expect(result.action.message).toBe("Override subject: Hello");
|
expect(result.action.message).toBe("Override subject: Hello");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -166,3 +162,89 @@ describe("hooks mapping", () => {
|
|||||||
expect(result?.ok).toBe(false);
|
expect(result?.ok).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("HookMappingResolved", () => {
|
||||||
|
it("includes cleanup fields", () => {
|
||||||
|
const resolved: HookMappingResolved = {
|
||||||
|
id: "test",
|
||||||
|
matchPath: "test",
|
||||||
|
action: "agent",
|
||||||
|
cleanup: "delete",
|
||||||
|
cleanupDelayMinutes: 5,
|
||||||
|
};
|
||||||
|
expect(resolved.cleanup).toBe("delete");
|
||||||
|
expect(resolved.cleanupDelayMinutes).toBe(5);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("HookAction", () => {
|
||||||
|
it("agent action includes cleanup fields", () => {
|
||||||
|
const action: HookAction = {
|
||||||
|
kind: "agent",
|
||||||
|
message: "test",
|
||||||
|
wakeMode: "now",
|
||||||
|
cleanup: "delete",
|
||||||
|
cleanupDelayMinutes: 5,
|
||||||
|
};
|
||||||
|
expect(action.kind).toBe("agent");
|
||||||
|
if (action.kind === "agent") {
|
||||||
|
expect(action.cleanup).toBe("delete");
|
||||||
|
expect(action.cleanupDelayMinutes).toBe(5);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("applyHookMappings cleanup propagation", () => {
|
||||||
|
it("propagates cleanup option from config to action", async () => {
|
||||||
|
const mappings = resolveHookMappings({
|
||||||
|
mappings: [
|
||||||
|
{
|
||||||
|
id: "test",
|
||||||
|
match: { path: "test" },
|
||||||
|
action: "agent",
|
||||||
|
messageTemplate: "hello",
|
||||||
|
cleanup: "delete",
|
||||||
|
cleanupDelayMinutes: 5,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await applyHookMappings(mappings, {
|
||||||
|
payload: {},
|
||||||
|
headers: {},
|
||||||
|
url: new URL("http://localhost/hooks/test"),
|
||||||
|
path: "test",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result?.ok).toBe(true);
|
||||||
|
if (result?.ok && result.action?.kind === "agent") {
|
||||||
|
expect(result.action.cleanup).toBe("delete");
|
||||||
|
expect(result.action.cleanupDelayMinutes).toBe(5);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("defaults cleanup to undefined when not specified", async () => {
|
||||||
|
const mappings = resolveHookMappings({
|
||||||
|
mappings: [
|
||||||
|
{
|
||||||
|
id: "test",
|
||||||
|
match: { path: "test" },
|
||||||
|
action: "agent",
|
||||||
|
messageTemplate: "hello",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await applyHookMappings(mappings, {
|
||||||
|
payload: {},
|
||||||
|
headers: {},
|
||||||
|
url: new URL("http://localhost/hooks/test"),
|
||||||
|
path: "test",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result?.ok).toBe(true);
|
||||||
|
if (result?.ok && result.action?.kind === "agent") {
|
||||||
|
expect(result.action.cleanup).toBeUndefined();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@ -21,6 +21,8 @@ export type HookMappingResolved = {
|
|||||||
model?: string;
|
model?: string;
|
||||||
thinking?: string;
|
thinking?: string;
|
||||||
timeoutSeconds?: number;
|
timeoutSeconds?: number;
|
||||||
|
cleanup?: "delete" | "keep";
|
||||||
|
cleanupDelayMinutes?: number;
|
||||||
transform?: HookMappingTransformResolved;
|
transform?: HookMappingTransformResolved;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -55,6 +57,8 @@ export type HookAction =
|
|||||||
model?: string;
|
model?: string;
|
||||||
thinking?: string;
|
thinking?: string;
|
||||||
timeoutSeconds?: number;
|
timeoutSeconds?: number;
|
||||||
|
cleanup?: "delete" | "keep";
|
||||||
|
cleanupDelayMinutes?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type HookMappingResult =
|
export type HookMappingResult =
|
||||||
@ -94,6 +98,8 @@ type HookTransformResult = Partial<{
|
|||||||
model: string;
|
model: string;
|
||||||
thinking: string;
|
thinking: string;
|
||||||
timeoutSeconds: number;
|
timeoutSeconds: number;
|
||||||
|
cleanup: "delete" | "keep";
|
||||||
|
cleanupDelayMinutes: number;
|
||||||
}> | null;
|
}> | null;
|
||||||
|
|
||||||
type HookTransformFn = (
|
type HookTransformFn = (
|
||||||
@ -191,6 +197,8 @@ function normalizeHookMapping(
|
|||||||
model: mapping.model,
|
model: mapping.model,
|
||||||
thinking: mapping.thinking,
|
thinking: mapping.thinking,
|
||||||
timeoutSeconds: mapping.timeoutSeconds,
|
timeoutSeconds: mapping.timeoutSeconds,
|
||||||
|
cleanup: mapping.cleanup,
|
||||||
|
cleanupDelayMinutes: mapping.cleanupDelayMinutes,
|
||||||
transform,
|
transform,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -237,6 +245,8 @@ function buildActionFromMapping(
|
|||||||
model: renderOptional(mapping.model, ctx),
|
model: renderOptional(mapping.model, ctx),
|
||||||
thinking: renderOptional(mapping.thinking, ctx),
|
thinking: renderOptional(mapping.thinking, ctx),
|
||||||
timeoutSeconds: mapping.timeoutSeconds,
|
timeoutSeconds: mapping.timeoutSeconds,
|
||||||
|
cleanup: mapping.cleanup,
|
||||||
|
cleanupDelayMinutes: mapping.cleanupDelayMinutes,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -277,6 +287,8 @@ function mergeAction(
|
|||||||
model: override.model ?? baseAgent?.model,
|
model: override.model ?? baseAgent?.model,
|
||||||
thinking: override.thinking ?? baseAgent?.thinking,
|
thinking: override.thinking ?? baseAgent?.thinking,
|
||||||
timeoutSeconds: override.timeoutSeconds ?? baseAgent?.timeoutSeconds,
|
timeoutSeconds: override.timeoutSeconds ?? baseAgent?.timeoutSeconds,
|
||||||
|
cleanup: override.cleanup ?? baseAgent?.cleanup,
|
||||||
|
cleanupDelayMinutes: override.cleanupDelayMinutes ?? baseAgent?.cleanupDelayMinutes,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user