@poncho-ai/harness 0.31.2 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +5 -5
- package/.turbo/turbo-lint.log +6 -0
- package/.turbo/turbo-test.log +34 -0
- package/CHANGELOG.md +14 -0
- package/dist/index.d.ts +37 -1
- package/dist/index.js +502 -90
- package/package.json +1 -1
- package/src/config.ts +6 -0
- package/src/harness.ts +34 -9
- package/src/index.ts +2 -0
- package/src/reminder-store.ts +334 -0
- package/src/reminder-tools.ts +168 -0
- package/test/reminder-store.test.ts +159 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { createReminderStore } from "../src/reminder-store.js";
|
|
3
|
+
import { createReminderTools } from "../src/reminder-tools.js";
|
|
4
|
+
import type { ToolContext } from "@poncho-ai/sdk";
|
|
5
|
+
|
|
6
|
+
describe("reminder store", () => {
|
|
7
|
+
it("creates with memory provider by default", () => {
|
|
8
|
+
const store = createReminderStore("agent-test", { provider: "memory" });
|
|
9
|
+
expect(store).toBeDefined();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("creates and lists reminders", async () => {
|
|
13
|
+
const store = createReminderStore("agent-list", { provider: "memory" });
|
|
14
|
+
const reminder = await store.create({
|
|
15
|
+
task: "Check the report",
|
|
16
|
+
scheduledAt: Date.now() + 60_000,
|
|
17
|
+
conversationId: "conv-1",
|
|
18
|
+
});
|
|
19
|
+
expect(reminder.id).toBeTruthy();
|
|
20
|
+
expect(reminder.status).toBe("pending");
|
|
21
|
+
expect(reminder.task).toBe("Check the report");
|
|
22
|
+
|
|
23
|
+
const all = await store.list();
|
|
24
|
+
expect(all).toHaveLength(1);
|
|
25
|
+
expect(all[0].id).toBe(reminder.id);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("cancels a pending reminder", async () => {
|
|
29
|
+
const store = createReminderStore("agent-cancel", { provider: "memory" });
|
|
30
|
+
const reminder = await store.create({
|
|
31
|
+
task: "Send email",
|
|
32
|
+
scheduledAt: Date.now() + 60_000,
|
|
33
|
+
conversationId: "conv-2",
|
|
34
|
+
});
|
|
35
|
+
const cancelled = await store.cancel(reminder.id);
|
|
36
|
+
expect(cancelled.status).toBe("cancelled");
|
|
37
|
+
|
|
38
|
+
const all = await store.list();
|
|
39
|
+
expect(all[0].status).toBe("cancelled");
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("throws when cancelling a non-existent (deleted) reminder", async () => {
|
|
43
|
+
const store = createReminderStore("agent-cancel-err", { provider: "memory" });
|
|
44
|
+
const reminder = await store.create({
|
|
45
|
+
task: "Task",
|
|
46
|
+
scheduledAt: Date.now() + 60_000,
|
|
47
|
+
conversationId: "conv-3",
|
|
48
|
+
});
|
|
49
|
+
await store.delete(reminder.id);
|
|
50
|
+
await expect(store.cancel(reminder.id)).rejects.toThrow("not found");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("deletes a reminder from the store", async () => {
|
|
54
|
+
const store = createReminderStore("agent-fire", { provider: "memory" });
|
|
55
|
+
const reminder = await store.create({
|
|
56
|
+
task: "Do the thing",
|
|
57
|
+
scheduledAt: Date.now() + 60_000,
|
|
58
|
+
conversationId: "conv-4",
|
|
59
|
+
});
|
|
60
|
+
await store.delete(reminder.id);
|
|
61
|
+
const all = await store.list();
|
|
62
|
+
expect(all).toHaveLength(0);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("throws when cancelling a nonexistent reminder", async () => {
|
|
66
|
+
const store = createReminderStore("agent-noexist", { provider: "memory" });
|
|
67
|
+
await expect(store.cancel("does-not-exist")).rejects.toThrow("not found");
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe("reminder tools", () => {
|
|
72
|
+
it("creates three tool definitions", () => {
|
|
73
|
+
const store = createReminderStore("agent-tools", { provider: "memory" });
|
|
74
|
+
const tools = createReminderTools(store);
|
|
75
|
+
expect(tools.map((t) => t.name)).toEqual([
|
|
76
|
+
"set_reminder",
|
|
77
|
+
"list_reminders",
|
|
78
|
+
"cancel_reminder",
|
|
79
|
+
]);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const makeContext = (overrides?: Partial<ToolContext>): ToolContext => ({
|
|
83
|
+
runId: "run-1",
|
|
84
|
+
agentId: "agent-1",
|
|
85
|
+
step: 1,
|
|
86
|
+
workingDir: "/tmp",
|
|
87
|
+
parameters: {},
|
|
88
|
+
conversationId: "conv-ctx",
|
|
89
|
+
...overrides,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("set_reminder creates a future reminder", async () => {
|
|
93
|
+
const store = createReminderStore("agent-tool-set", { provider: "memory" });
|
|
94
|
+
const tools = createReminderTools(store);
|
|
95
|
+
const setTool = tools.find((t) => t.name === "set_reminder")!;
|
|
96
|
+
const future = new Date(Date.now() + 3600_000).toISOString();
|
|
97
|
+
const result = (await setTool.handler({ task: "Buy milk", datetime: future }, makeContext())) as {
|
|
98
|
+
ok: boolean;
|
|
99
|
+
reminder: { id: string; status: string };
|
|
100
|
+
};
|
|
101
|
+
expect(result.ok).toBe(true);
|
|
102
|
+
expect(result.reminder.status).toBe("pending");
|
|
103
|
+
|
|
104
|
+
const all = await store.list();
|
|
105
|
+
expect(all).toHaveLength(1);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("set_reminder rejects past datetimes", async () => {
|
|
109
|
+
const store = createReminderStore("agent-tool-past", { provider: "memory" });
|
|
110
|
+
const tools = createReminderTools(store);
|
|
111
|
+
const setTool = tools.find((t) => t.name === "set_reminder")!;
|
|
112
|
+
const past = new Date(Date.now() - 60_000).toISOString();
|
|
113
|
+
await expect(setTool.handler({ task: "Too late", datetime: past }, makeContext())).rejects.toThrow("future");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("list_reminders returns all reminders", async () => {
|
|
117
|
+
const store = createReminderStore("agent-tool-list", { provider: "memory" });
|
|
118
|
+
await store.create({ task: "A", scheduledAt: Date.now() + 60_000, conversationId: "c1" });
|
|
119
|
+
await store.create({ task: "B", scheduledAt: Date.now() + 120_000, conversationId: "c2" });
|
|
120
|
+
|
|
121
|
+
const tools = createReminderTools(store);
|
|
122
|
+
const listTool = tools.find((t) => t.name === "list_reminders")!;
|
|
123
|
+
const result = (await listTool.handler({}, makeContext())) as {
|
|
124
|
+
reminders: Array<{ task: string }>;
|
|
125
|
+
count: number;
|
|
126
|
+
};
|
|
127
|
+
expect(result.count).toBe(2);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("list_reminders filters by status", async () => {
|
|
131
|
+
const store = createReminderStore("agent-tool-filter", { provider: "memory" });
|
|
132
|
+
const r = await store.create({ task: "A", scheduledAt: Date.now() + 60_000, conversationId: "c1" });
|
|
133
|
+
await store.create({ task: "B", scheduledAt: Date.now() + 120_000, conversationId: "c2" });
|
|
134
|
+
await store.cancel(r.id);
|
|
135
|
+
|
|
136
|
+
const tools = createReminderTools(store);
|
|
137
|
+
const listTool = tools.find((t) => t.name === "list_reminders")!;
|
|
138
|
+
const result = (await listTool.handler({ status: "pending" }, makeContext())) as {
|
|
139
|
+
reminders: Array<{ task: string }>;
|
|
140
|
+
count: number;
|
|
141
|
+
};
|
|
142
|
+
expect(result.count).toBe(1);
|
|
143
|
+
expect(result.reminders[0].task).toBe("B");
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("cancel_reminder cancels by ID", async () => {
|
|
147
|
+
const store = createReminderStore("agent-tool-cancel", { provider: "memory" });
|
|
148
|
+
const r = await store.create({ task: "Cancel me", scheduledAt: Date.now() + 60_000, conversationId: "c1" });
|
|
149
|
+
|
|
150
|
+
const tools = createReminderTools(store);
|
|
151
|
+
const cancelTool = tools.find((t) => t.name === "cancel_reminder")!;
|
|
152
|
+
const result = (await cancelTool.handler({ id: r.id }, makeContext())) as {
|
|
153
|
+
ok: boolean;
|
|
154
|
+
reminder: { status: string };
|
|
155
|
+
};
|
|
156
|
+
expect(result.ok).toBe(true);
|
|
157
|
+
expect(result.reminder.status).toBe("cancelled");
|
|
158
|
+
});
|
|
159
|
+
});
|