@intentface/latch-core 0.13.2 → 0.14.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/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +145 -52
- package/dist/runtime.js.map +1 -1
- package/dist/storage.d.ts +54 -3
- package/dist/storage.d.ts.map +1 -1
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +2 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/storage-conformance.d.ts +49 -0
- package/dist/testing/storage-conformance.d.ts.map +1 -0
- package/dist/testing/storage-conformance.js +285 -0
- package/dist/testing/storage-conformance.js.map +1 -0
- package/package.json +7 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,GAIzB,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type StorageAdapter } from "../storage.js";
|
|
2
|
+
/**
|
|
3
|
+
* The `StorageAdapter` guarantees the runtime relies on, as runnable checks:
|
|
4
|
+
* tenant scoping, message ordering and upserts, one active run per chat, and
|
|
5
|
+
* the lease / heartbeat / reaper / fencing rules that make a run continue on
|
|
6
|
+
* exactly one node. An adapter that passes these can back a multi-node,
|
|
7
|
+
* durable deployment; one that only "works" in normal use can still let a
|
|
8
|
+
* crashed run resume twice, or a zombie node write into a chat it lost.
|
|
9
|
+
*
|
|
10
|
+
* Runner-agnostic: pass your runner's `describe` and `it` (Vitest, Jest,
|
|
11
|
+
* `node:test`):
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { describe, it } from "vitest";
|
|
15
|
+
* import { registerStorageConformance } from "@intentface/latch-core/testing";
|
|
16
|
+
*
|
|
17
|
+
* registerStorageConformance({ describe, it }, "my adapter", async () => {
|
|
18
|
+
* const db = await openTestDatabase();
|
|
19
|
+
* return {
|
|
20
|
+
* store: createMyAdapter(db, { owner: (p) => [p.org] }),
|
|
21
|
+
* principals: [{ org: "a" }, { org: "b" }],
|
|
22
|
+
* close: () => db.close(),
|
|
23
|
+
* };
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* Every check opens a fresh target, so they may run in any order.
|
|
28
|
+
*/
|
|
29
|
+
export interface ConformanceRunner {
|
|
30
|
+
describe: (name: string, fn: () => void) => void;
|
|
31
|
+
it: (name: string, fn: () => Promise<void>, timeoutMs?: number) => void;
|
|
32
|
+
}
|
|
33
|
+
export interface ConformanceTarget<P> {
|
|
34
|
+
store: StorageAdapter<P>;
|
|
35
|
+
/** Two principals the adapter maps to DIFFERENT owners. */
|
|
36
|
+
principals: [P, P];
|
|
37
|
+
close?: () => Promise<void> | void;
|
|
38
|
+
}
|
|
39
|
+
export interface ConformanceCheck<P> {
|
|
40
|
+
name: string;
|
|
41
|
+
run: (t: ConformanceTarget<P>) => Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
/** The checks as a plain list, for runners `registerStorageConformance` doesn't fit. */
|
|
44
|
+
export declare function storageConformanceChecks<P>(): ReadonlyArray<ConformanceCheck<P>>;
|
|
45
|
+
/** Register every check as one test under `describe(name)`. */
|
|
46
|
+
export declare function registerStorageConformance<P>(runner: ConformanceRunner, name: string, open: () => Promise<ConformanceTarget<P>>, opts?: {
|
|
47
|
+
timeoutMs?: number;
|
|
48
|
+
}): void;
|
|
49
|
+
//# sourceMappingURL=storage-conformance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-conformance.d.ts","sourceRoot":"","sources":["../../src/testing/storage-conformance.ts"],"names":[],"mappings":"AACA,OAAO,EAAkD,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpG;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACjD,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACzE;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IACzB,2DAA2D;IAC3D,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AA4RD,wFAAwF;AACxF,wBAAgB,wBAAwB,CAAC,CAAC,KAAK,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAEhF;AAED,+DAA+D;AAC/D,wBAAgB,0BAA0B,CAAC,CAAC,EAC1C,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,EACzC,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5B,IAAI,CAiBN"}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { isChatBusyError } from "../storage.js";
|
|
2
|
+
class ConformanceError extends Error {
|
|
3
|
+
}
|
|
4
|
+
function check(cond, msg) {
|
|
5
|
+
if (!cond)
|
|
6
|
+
throw new ConformanceError(msg);
|
|
7
|
+
}
|
|
8
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
9
|
+
/** Long enough past a 1 ms lease for any clock to agree it expired. */
|
|
10
|
+
const EXPIRE = 25;
|
|
11
|
+
const msg = (id, text = id, role = "user") => ({
|
|
12
|
+
id,
|
|
13
|
+
role,
|
|
14
|
+
parts: [{ type: "text", text }],
|
|
15
|
+
metadata: { visibility: "user", createdAt: Date.now() },
|
|
16
|
+
});
|
|
17
|
+
const textOf = (m) => m?.parts[0]?.text;
|
|
18
|
+
async function busy(fn) {
|
|
19
|
+
try {
|
|
20
|
+
await fn();
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
if (isChatBusyError(e))
|
|
25
|
+
return e.retryAfterMs;
|
|
26
|
+
throw e;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const fenceOf = (run, owner) => ({
|
|
30
|
+
runId: run.id,
|
|
31
|
+
owner,
|
|
32
|
+
fencingToken: run.fencingToken ?? 1,
|
|
33
|
+
});
|
|
34
|
+
function checks() {
|
|
35
|
+
return [
|
|
36
|
+
// ── messages ──────────────────────────────────────────────────────────
|
|
37
|
+
{
|
|
38
|
+
name: "messages load in append order and upsert by id in place",
|
|
39
|
+
async run({ store, principals: [me] }) {
|
|
40
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
41
|
+
await store.appendMessages(chat.id, [msg("m1"), msg("m2", "m2", "assistant")]);
|
|
42
|
+
await store.appendMessages(chat.id, [msg("m3")]);
|
|
43
|
+
await store.appendMessages(chat.id, [msg("m2", "edited", "assistant")]);
|
|
44
|
+
const loaded = await store.loadMessages(me, chat.id);
|
|
45
|
+
check(loaded.map((m) => m.id).join() === "m1,m2,m3", `order: ${loaded.map((m) => m.id).join()}`);
|
|
46
|
+
check(textOf(loaded[1]) === "edited", "an upsert updates the message in place");
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: "the same message id in two chats is two messages",
|
|
51
|
+
async run({ store, principals: [me] }) {
|
|
52
|
+
const a = await store.createChat(me, { agent: "a" });
|
|
53
|
+
const b = await store.createChat(me, { agent: "a" });
|
|
54
|
+
await store.appendMessages(a.id, [msg("same", "in a")]);
|
|
55
|
+
await store.appendMessages(b.id, [msg("same", "in b")]);
|
|
56
|
+
check(textOf((await store.loadMessages(me, a.id))[0]) === "in a", "chat a keeps its own message");
|
|
57
|
+
check(textOf((await store.loadMessages(me, b.id))[0]) === "in b", "chat b keeps its own message");
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "concurrent appends to one chat all land, each with its own position",
|
|
62
|
+
async run({ store, principals: [me] }) {
|
|
63
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
64
|
+
const ids = Array.from({ length: 8 }, (_, i) => `c${i}`);
|
|
65
|
+
await Promise.all(ids.map((id) => store.appendMessages(chat.id, [msg(id)])));
|
|
66
|
+
const loaded = await store.loadMessages(me, chat.id);
|
|
67
|
+
check(loaded.length === ids.length, `all appends landed (${loaded.length}/${ids.length})`);
|
|
68
|
+
check(new Set(loaded.map((m) => m.id)).size === ids.length, "no message lost or duplicated");
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
// ── tenancy ───────────────────────────────────────────────────────────
|
|
72
|
+
{
|
|
73
|
+
name: "another owner can't see a chat, its messages, or it in a list",
|
|
74
|
+
async run({ store, principals: [me, other] }) {
|
|
75
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
76
|
+
await store.appendMessages(chat.id, [msg("secret")]);
|
|
77
|
+
check((await store.getChat(other, chat.id)) === null, "getChat is scoped");
|
|
78
|
+
check((await store.loadMessages(other, chat.id)).length === 0, "loadMessages is scoped");
|
|
79
|
+
check(!(await store.listChats(other)).some((c) => c.id === chat.id), "listChats is scoped");
|
|
80
|
+
check((await store.getChat(me, chat.id))?.id === chat.id, "the owner still sees it");
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
// ── one active run per chat ──────────────────────────────────────────
|
|
84
|
+
{
|
|
85
|
+
name: "a live run refuses a second run in its chat, with the time left",
|
|
86
|
+
async run({ store, principals: [me] }) {
|
|
87
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
88
|
+
await store.claimRun({ principal: me, chatId: chat.id, agent: "a", owner: "n1", ttlMs: 60_000 });
|
|
89
|
+
const retry = await busy(() => store.claimRun({ principal: me, chatId: chat.id, agent: "a", owner: "n2", ttlMs: 60_000 }));
|
|
90
|
+
check(retry !== null && retry > 0 && retry <= 60_000, `second claim refused with retryAfterMs (${retry})`);
|
|
91
|
+
check((await busy(() => store.createRun(me, { chatId: chat.id, agent: "a" }))) !== null, "a non-durable run is refused too");
|
|
92
|
+
const other = await store.createChat(me, { agent: "a" });
|
|
93
|
+
check((await busy(() => store.createRun(me, { chatId: other.id, agent: "a" }))) === null, "other chats are unaffected");
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "racing claims on one chat: exactly one wins",
|
|
98
|
+
async run({ store, principals: [me] }) {
|
|
99
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
100
|
+
const race = await Promise.allSettled(["n1", "n2", "n3", "n4"].map((owner) => store.claimRun({ principal: me, chatId: chat.id, agent: "a", owner, ttlMs: 60_000 })));
|
|
101
|
+
const won = race.filter((r) => r.status === "fulfilled").length;
|
|
102
|
+
check(won === 1, `exactly one claim wins (${won})`);
|
|
103
|
+
for (const r of race)
|
|
104
|
+
if (r.status === "rejected")
|
|
105
|
+
check(isChatBusyError(r.reason), `losers get ChatBusyError (${r.reason})`);
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "a run paused for a human doesn't block the chat",
|
|
110
|
+
async run({ store, principals: [me] }) {
|
|
111
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
112
|
+
const paused = await store.claimRun({ principal: me, chatId: chat.id, agent: "a", owner: "n1", ttlMs: 60_000 });
|
|
113
|
+
await store.updateRun(paused.id, { status: "awaiting_input" });
|
|
114
|
+
const next = await store.claimRun({ principal: me, chatId: chat.id, agent: "a", owner: "n1", ttlMs: 60_000 });
|
|
115
|
+
check(next.id !== paused.id, "a decision opens a new run");
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: "an expired lease is superseded by the next turn, and can't be reclaimed",
|
|
120
|
+
async run({ store, principals: [me] }) {
|
|
121
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
122
|
+
const crashed = await store.claimRun({ principal: me, chatId: chat.id, agent: "a", owner: "n1", ttlMs: 1 });
|
|
123
|
+
await sleep(EXPIRE);
|
|
124
|
+
await store.claimRun({ principal: me, chatId: chat.id, agent: "a", owner: "n2", ttlMs: 60_000 });
|
|
125
|
+
const old = await store.getRun(crashed.id);
|
|
126
|
+
check(old?.status === "errored", `the crashed run is settled (${old?.status})`);
|
|
127
|
+
check((old?.fencingToken ?? 0) > (crashed.fencingToken ?? 0), "its fencing token is bumped");
|
|
128
|
+
check((await store.reclaimRun(crashed.id, "n3", 60_000)) === null, "a superseded run is not reclaimable");
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: "openTurn opens the run and its message together, or neither",
|
|
133
|
+
async run({ store, principals: [me] }) {
|
|
134
|
+
if (!store.openTurn)
|
|
135
|
+
return;
|
|
136
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
137
|
+
const run = await store.openTurn(me, {
|
|
138
|
+
chatId: chat.id,
|
|
139
|
+
agent: "a",
|
|
140
|
+
messages: [msg("u1")],
|
|
141
|
+
lease: { owner: "n1", ttlMs: 60_000 },
|
|
142
|
+
});
|
|
143
|
+
check(run.status === "active" && run.leaseOwner === "n1", "opens a leased run");
|
|
144
|
+
check((await busy(() => store.openTurn(me, { chatId: chat.id, agent: "a", messages: [msg("u2")] }))) !== null, "a busy chat is refused");
|
|
145
|
+
const ids = (await store.loadMessages(me, chat.id)).map((m) => m.id);
|
|
146
|
+
check(ids.join() === "u1", `a refused turn persists nothing (${ids.join()})`);
|
|
147
|
+
const racy = await store.createChat(me, { agent: "a" });
|
|
148
|
+
const race = await Promise.allSettled(["a", "b", "c"].map((id) => store.openTurn(me, { chatId: racy.id, agent: "a", messages: [msg(id)] })));
|
|
149
|
+
const won = race.filter((r) => r.status === "fulfilled").length;
|
|
150
|
+
const persisted = (await store.loadMessages(me, racy.id)).length;
|
|
151
|
+
check(won === 1 && persisted === 1, `one of three racing turns wins, one message lands (${won}/${persisted})`);
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
// ── leases, heartbeats, the reaper ───────────────────────────────────
|
|
155
|
+
{
|
|
156
|
+
name: "a heartbeat renews only the current holder's lease",
|
|
157
|
+
async run({ store, principals: [me] }) {
|
|
158
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
159
|
+
const run = await store.claimRun({ principal: me, chatId: chat.id, agent: "a", owner: "n1", ttlMs: 60_000 });
|
|
160
|
+
const token = run.fencingToken ?? 1;
|
|
161
|
+
check(await store.heartbeatRun(run.id, "n1", 60_000, token), "the holder renews");
|
|
162
|
+
check(!(await store.heartbeatRun(run.id, "n2", 60_000, token)), "another owner can't");
|
|
163
|
+
check(!(await store.heartbeatRun(run.id, "n1", 60_000, token + 1)), "a wrong token can't");
|
|
164
|
+
await store.updateRun(run.id, { status: "completed" });
|
|
165
|
+
check(!(await store.heartbeatRun(run.id, "n1", 60_000, token)), "a finished run can't be renewed");
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "the reaper settles expired leases once and fences out their holder",
|
|
170
|
+
async run({ store, principals: [me] }) {
|
|
171
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
172
|
+
const live = await store.claimRun({ principal: me, chatId: chat.id, agent: "a", owner: "n1", ttlMs: 60_000 });
|
|
173
|
+
const other = await store.createChat(me, { agent: "a" });
|
|
174
|
+
const dead = await store.claimRun({ principal: me, chatId: other.id, agent: "a", owner: "n2", ttlMs: 1 });
|
|
175
|
+
await sleep(EXPIRE);
|
|
176
|
+
// No `now`: the adapter's own clock decides.
|
|
177
|
+
const reaped = await store.reapExpiredRuns();
|
|
178
|
+
check(reaped.some((r) => r.id === dead.id), "an expired lease is reaped");
|
|
179
|
+
check(!reaped.some((r) => r.id === live.id), "a live lease is not");
|
|
180
|
+
check(!(await store.reapExpiredRuns()).some((r) => r.id === dead.id), "a reaped run isn't reaped twice");
|
|
181
|
+
const zombie = { owner: "n2", fencingToken: dead.fencingToken ?? 1 };
|
|
182
|
+
check(!(await store.heartbeatRun(dead.id, zombie.owner, 60_000, zombie.fencingToken)), "its holder can't renew");
|
|
183
|
+
check(!(await store.updateRun(dead.id, { status: "completed" }, zombie)), "its holder can't settle it");
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: "racing reclaims of a dead run: exactly one wins",
|
|
188
|
+
async run({ store, principals: [me] }) {
|
|
189
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
190
|
+
const dead = await store.claimRun({ principal: me, chatId: chat.id, agent: "a", owner: "n1", ttlMs: 1 });
|
|
191
|
+
await sleep(EXPIRE);
|
|
192
|
+
await store.reapExpiredRuns();
|
|
193
|
+
const race = await Promise.all(["n2", "n3", "n4"].map((owner) => store.reclaimRun(dead.id, owner, 60_000)));
|
|
194
|
+
const winners = race.filter((r) => r !== null);
|
|
195
|
+
check(winners.length === 1, `exactly one reclaim wins (${winners.length})`);
|
|
196
|
+
check((winners[0].fencingToken ?? 0) > (dead.fencingToken ?? 0), "the winner holds a newer token");
|
|
197
|
+
check(winners[0].status === "active", "the reclaimed run is active again");
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
name: "reclaim refuses live, finished and never-leased runs",
|
|
202
|
+
async run({ store, principals: [me] }) {
|
|
203
|
+
const a = await store.createChat(me, { agent: "a" });
|
|
204
|
+
const live = await store.claimRun({ principal: me, chatId: a.id, agent: "a", owner: "n1", ttlMs: 60_000 });
|
|
205
|
+
check((await store.reclaimRun(live.id, "n2", 60_000)) === null, "a live lease is not taken over");
|
|
206
|
+
const b = await store.createChat(me, { agent: "a" });
|
|
207
|
+
const done = await store.claimRun({ principal: me, chatId: b.id, agent: "a", owner: "n1", ttlMs: 1 });
|
|
208
|
+
await store.updateRun(done.id, { status: "completed" });
|
|
209
|
+
await sleep(EXPIRE);
|
|
210
|
+
check((await store.reclaimRun(done.id, "n2", 60_000)) === null, "a completed run is not resumed");
|
|
211
|
+
const c = await store.createChat(me, { agent: "a" });
|
|
212
|
+
const t1 = await store.createRun(me, { chatId: c.id, agent: "a" });
|
|
213
|
+
check((await store.reclaimRun(t1.id, "n2", 60_000)) === null, "a never-leased run is not seized");
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: "a guarded run update applies only for the current holder",
|
|
218
|
+
async run({ store, principals: [me] }) {
|
|
219
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
220
|
+
const run = await store.claimRun({ principal: me, chatId: chat.id, agent: "a", owner: "n1", ttlMs: 1 });
|
|
221
|
+
await sleep(EXPIRE);
|
|
222
|
+
await store.reapExpiredRuns();
|
|
223
|
+
const back = (await store.reclaimRun(run.id, "n2", 60_000));
|
|
224
|
+
check(!(await store.updateRun(run.id, { status: "completed" }, { owner: "n1", fencingToken: run.fencingToken ?? 1 })), "the old holder is refused");
|
|
225
|
+
check(await store.updateRun(run.id, { status: "completed" }, { owner: "n2", fencingToken: back.fencingToken ?? 1 }), "the new holder applies");
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
// ── fenced message writes ────────────────────────────────────────────
|
|
229
|
+
{
|
|
230
|
+
name: "fenced message writes land for the holder and are refused for a zombie",
|
|
231
|
+
async run({ store, principals: [me] }) {
|
|
232
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
233
|
+
const run = await store.claimRun({ principal: me, chatId: chat.id, agent: "a", owner: "n1", ttlMs: 60_000 });
|
|
234
|
+
const first = fenceOf(run, "n1");
|
|
235
|
+
check((await store.appendMessages(chat.id, [msg("a1", "draft", "assistant")], first)) === true, "the holder's write lands (returns true)");
|
|
236
|
+
// Only now let the lease run out: the first write must not depend on
|
|
237
|
+
// whether an adapter's fence also checks expiry.
|
|
238
|
+
check(await store.heartbeatRun(run.id, "n1", 1, first.fencingToken), "the holder shortens its lease");
|
|
239
|
+
await sleep(EXPIRE);
|
|
240
|
+
await store.reapExpiredRuns();
|
|
241
|
+
const back = (await store.reclaimRun(run.id, "n2", 60_000));
|
|
242
|
+
// The zombie wakes up: a new message and an edit of an existing one.
|
|
243
|
+
const refused = await store.appendMessages(chat.id, [msg("a1", "zombie edit", "assistant"), msg("z1", "zombie")], first);
|
|
244
|
+
check(refused === false, `the zombie's write is refused (returned ${String(refused)})`);
|
|
245
|
+
const after = await store.loadMessages(me, chat.id);
|
|
246
|
+
check(after.map((m) => m.id).join() === "a1", `nothing of the refused write landed (${after.map((m) => m.id).join()})`);
|
|
247
|
+
check(textOf(after[0]) === "draft", "an existing message is not overwritten by the zombie");
|
|
248
|
+
check((await store.appendMessages(chat.id, [msg("a2", "new owner", "assistant")], fenceOf(back, "n2"))) === true, "the new holder writes");
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: "a fenced write still lands after its run is settled by its holder",
|
|
253
|
+
async run({ store, principals: [me] }) {
|
|
254
|
+
// The runtime settles the run row FIRST, then writes the final message
|
|
255
|
+
// with the same lease: settling must not invalidate the holder's fence.
|
|
256
|
+
const chat = await store.createChat(me, { agent: "a" });
|
|
257
|
+
const run = await store.claimRun({ principal: me, chatId: chat.id, agent: "a", owner: "n1", ttlMs: 60_000 });
|
|
258
|
+
const fence = fenceOf(run, "n1");
|
|
259
|
+
check(await store.updateRun(run.id, { status: "completed", endedAt: Date.now() }, fence), "the holder settles");
|
|
260
|
+
check((await store.appendMessages(chat.id, [msg("final", "answer", "assistant")], fence)) === true, "the final message lands");
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
];
|
|
264
|
+
}
|
|
265
|
+
/** The checks as a plain list, for runners `registerStorageConformance` doesn't fit. */
|
|
266
|
+
export function storageConformanceChecks() {
|
|
267
|
+
return checks();
|
|
268
|
+
}
|
|
269
|
+
/** Register every check as one test under `describe(name)`. */
|
|
270
|
+
export function registerStorageConformance(runner, name, open, opts) {
|
|
271
|
+
runner.describe(`${name}: storage conformance`, () => {
|
|
272
|
+
for (const c of checks()) {
|
|
273
|
+
runner.it(c.name, async () => {
|
|
274
|
+
const target = await open();
|
|
275
|
+
try {
|
|
276
|
+
await c.run(target);
|
|
277
|
+
}
|
|
278
|
+
finally {
|
|
279
|
+
await target.close?.();
|
|
280
|
+
}
|
|
281
|
+
}, opts?.timeoutMs ?? 30_000);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=storage-conformance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-conformance.js","sourceRoot":"","sources":["../../src/testing/storage-conformance.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentface/latch-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Latch core — runtime, types, and seams for building agents on the AI SDK. Subpaths: /models (models.dev catalog + provider hooks) and /harness (default sandbox/app tools); their extra deps are optional peers, loaded lazily.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
"./harness": {
|
|
33
33
|
"types": "./dist/harness/index.d.ts",
|
|
34
34
|
"import": "./dist/harness/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./testing": {
|
|
37
|
+
"types": "./dist/testing/index.d.ts",
|
|
38
|
+
"import": "./dist/testing/index.js"
|
|
35
39
|
}
|
|
36
40
|
},
|
|
37
41
|
"files": [
|
|
@@ -51,7 +55,7 @@
|
|
|
51
55
|
"@ai-sdk/openai": ">=4.0.0",
|
|
52
56
|
"ai": ">=7.0.0",
|
|
53
57
|
"turndown": ">=7.0.0",
|
|
54
|
-
"@intentface/latch-net": "^0.
|
|
58
|
+
"@intentface/latch-net": "^0.14.0"
|
|
55
59
|
},
|
|
56
60
|
"devDependencies": {
|
|
57
61
|
"@ai-sdk/anthropic": "^4.0.57",
|
|
@@ -63,7 +67,7 @@
|
|
|
63
67
|
"turndown": "^7.2.4",
|
|
64
68
|
"typescript": "^5.7.0",
|
|
65
69
|
"vitest": "^4",
|
|
66
|
-
"@intentface/latch-net": "^0.
|
|
70
|
+
"@intentface/latch-net": "^0.14.0"
|
|
67
71
|
},
|
|
68
72
|
"repository": {
|
|
69
73
|
"type": "git",
|