1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
import type { StorageNamespace } from "@dispatch/kernel";
import { describe, expect, it } from "vitest";
import {
applyConfigUpdate,
createHeartbeatConfigStore,
DEFAULT_HEARTBEAT_CONFIG,
} from "./config-store.js";
function createMemoryStorage(): StorageNamespace {
const data = new Map<string, string>();
return {
get: async (key) => data.get(key) ?? null,
set: async (key, value) => {
data.set(key, value);
},
delete: async (key) => {
data.delete(key);
},
has: async (key) => data.has(key),
keys: async (prefix) => {
const all = [...data.keys()];
if (prefix === undefined) return all;
return all.filter((k) => k.startsWith(prefix));
},
};
}
describe("applyConfigUpdate (pure)", () => {
it("leaves omitted fields unchanged from the default", () => {
const next = applyConfigUpdate(DEFAULT_HEARTBEAT_CONFIG, {});
expect(next).toEqual(DEFAULT_HEARTBEAT_CONFIG);
});
it("applies provided fields", () => {
const next = applyConfigUpdate(DEFAULT_HEARTBEAT_CONFIG, {
enabled: true,
systemPrompt: "you are a monitor",
taskPrompt: "check for stuck chats",
model: "opencode/gpt-4o",
});
expect(next.enabled).toBe(true);
expect(next.systemPrompt).toBe("you are a monitor");
expect(next.taskPrompt).toBe("check for stuck chats");
expect(next.model).toBe("opencode/gpt-4o");
// Untouched fields keep defaults.
expect(next.intervalMinutes).toBe(30);
expect(next.reasoningEffort).toBeNull();
});
it("clamps intervalMinutes to a minimum of 1", () => {
expect(
applyConfigUpdate(DEFAULT_HEARTBEAT_CONFIG, { intervalMinutes: 0 }).intervalMinutes,
).toBe(1);
expect(
applyConfigUpdate(DEFAULT_HEARTBEAT_CONFIG, { intervalMinutes: -5 }).intervalMinutes,
).toBe(1);
expect(
applyConfigUpdate(DEFAULT_HEARTBEAT_CONFIG, { intervalMinutes: 7 }).intervalMinutes,
).toBe(7);
});
it("truncates a non-integer interval to an integer", () => {
expect(
applyConfigUpdate(DEFAULT_HEARTBEAT_CONFIG, { intervalMinutes: 12.9 }).intervalMinutes,
).toBe(12);
});
it("clears reasoningEffort when null is passed", () => {
const withEffort = applyConfigUpdate(DEFAULT_HEARTBEAT_CONFIG, { reasoningEffort: "high" });
expect(withEffort.reasoningEffort).toBe("high");
const cleared = applyConfigUpdate(withEffort, { reasoningEffort: null });
expect(cleared.reasoningEffort).toBeNull();
});
it("treats an absent reasoningEffort as unchanged (distinct from null)", () => {
const withEffort = applyConfigUpdate(DEFAULT_HEARTBEAT_CONFIG, { reasoningEffort: "low" });
const untouched = applyConfigUpdate(withEffort, { enabled: true });
expect(untouched.reasoningEffort).toBe("low");
});
});
describe("createHeartbeatConfigStore", () => {
it("returns the default config for an unknown workspace", async () => {
const store = createHeartbeatConfigStore(createMemoryStorage());
expect(await store.get("ws-1")).toEqual(DEFAULT_HEARTBEAT_CONFIG);
});
it("persists and round-trips an update", async () => {
const storage = createMemoryStorage();
const store = createHeartbeatConfigStore(storage);
const next = await store.update("ws-1", { enabled: true, intervalMinutes: 5 });
expect(next.enabled).toBe(true);
expect(next.intervalMinutes).toBe(5);
// A fresh store over the same storage reads the persisted value.
const store2 = createHeartbeatConfigStore(storage);
expect(await store2.get("ws-1")).toEqual(next);
});
it("applies a partial update on top of existing config", async () => {
const storage = createMemoryStorage();
const store = createHeartbeatConfigStore(storage);
await store.update("ws-1", { enabled: true, systemPrompt: "a", taskPrompt: "b" });
const next = await store.update("ws-1", { taskPrompt: "c" });
expect(next.enabled).toBe(true);
expect(next.systemPrompt).toBe("a");
expect(next.taskPrompt).toBe("c");
});
it("lists persisted workspace ids", async () => {
const store = createHeartbeatConfigStore(createMemoryStorage());
await store.update("ws-b", { enabled: true });
await store.update("ws-a", { enabled: false });
expect(await store.listWorkspaceIds()).toEqual(["ws-a", "ws-b"]);
});
});
|