@haikit/core 0.2.0 → 0.3.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/index.d.ts +159 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +172 -4
package/dist/index.d.ts
CHANGED
|
@@ -196,11 +196,46 @@ export interface Conversation {
|
|
|
196
196
|
id: string;
|
|
197
197
|
status: ConversationStatus;
|
|
198
198
|
messages: Message[];
|
|
199
|
+
/**
|
|
200
|
+
* Every handle this conversation's surviving history rendered.
|
|
201
|
+
*
|
|
202
|
+
* Load-bearing, not bookkeeping: an interaction is refused unless its handle
|
|
203
|
+
* appears here. A payload row alone is not proof, because a turn that was
|
|
204
|
+
* overtaken leaves its rows behind while its conversation save is discarded.
|
|
205
|
+
*/
|
|
199
206
|
handles: string[];
|
|
207
|
+
/**
|
|
208
|
+
* Handles whose elicit turn has been answered — resolved by a click, or closed
|
|
209
|
+
* out by a typed override. An interaction on one of these is refused.
|
|
210
|
+
*
|
|
211
|
+
* This lives on the conversation, not on the payload, because freezing is half
|
|
212
|
+
* of one transition: the other half is the history recording what the user
|
|
213
|
+
* chose. Split across two rows, a turn could freeze the payload while it still
|
|
214
|
+
* held the lease, lose the lease before saving, and leave the surviving history
|
|
215
|
+
* awaiting a surface that can never be clicked again. On one fenced row the two
|
|
216
|
+
* halves commit together or not at all.
|
|
217
|
+
*/
|
|
218
|
+
frozen: string[];
|
|
200
219
|
pending: Pending | null;
|
|
201
|
-
/** Turn lease. A dead process leaves this in the past. */
|
|
220
|
+
/** Turn lease expiry. A dead process leaves this in the past. */
|
|
202
221
|
leaseUntil: number | null;
|
|
222
|
+
/**
|
|
223
|
+
* Fencing token, reissued every time the lease is acquired.
|
|
224
|
+
*
|
|
225
|
+
* Expiry alone is not mutual exclusion. A request slower than the TTL loses
|
|
226
|
+
* the lease while still running; another process takes it and saves a newer
|
|
227
|
+
* turn; the first then finishes and writes its stale copy over the top. The
|
|
228
|
+
* token is what lets `saveConversation` tell those two apart — a holder whose
|
|
229
|
+
* token no longer matches the stored one has been superseded.
|
|
230
|
+
*/
|
|
231
|
+
leaseToken: string | null;
|
|
203
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* A rendered surface's data. **Immutable once written**: everything about a
|
|
235
|
+
* surface that changes over the conversation lives on the fenced conversation
|
|
236
|
+
* row instead (see `Conversation.frozen`), so no payload write can ever disagree
|
|
237
|
+
* with the history that references it.
|
|
238
|
+
*/
|
|
204
239
|
export interface PayloadRecord {
|
|
205
240
|
handle: string;
|
|
206
241
|
conversationId: string;
|
|
@@ -208,7 +243,6 @@ export interface PayloadRecord {
|
|
|
208
243
|
version: number;
|
|
209
244
|
props: unknown;
|
|
210
245
|
mode: "display" | "elicit";
|
|
211
|
-
state: "live" | "frozen";
|
|
212
246
|
createdAt: number;
|
|
213
247
|
}
|
|
214
248
|
export type Block = {
|
|
@@ -298,12 +332,133 @@ export interface ModelAdapter {
|
|
|
298
332
|
readonly id: string;
|
|
299
333
|
generate(request: ModelRequest): Promise<ModelResponse>;
|
|
300
334
|
}
|
|
335
|
+
/**
|
|
336
|
+
* Thrown by `loadConversation` when another request already holds the turn.
|
|
337
|
+
*
|
|
338
|
+
* Detected by `name` rather than `instanceof`: a duplicated install of this
|
|
339
|
+
* package would give two distinct classes, and the check must not silently
|
|
340
|
+
* start returning 500 for a case that is really a 409.
|
|
341
|
+
*/
|
|
342
|
+
export declare class ConversationBusy extends Error {
|
|
343
|
+
readonly name = "ConversationBusy";
|
|
344
|
+
constructor(id: string);
|
|
345
|
+
}
|
|
346
|
+
export declare const isConversationBusy: (err: unknown) => boolean;
|
|
347
|
+
/**
|
|
348
|
+
* Thrown by `saveConversation` when the caller's lease was superseded while its
|
|
349
|
+
* turn was still running. The write is rejected; the newer turn stands.
|
|
350
|
+
*/
|
|
351
|
+
export declare class StaleLease extends Error {
|
|
352
|
+
readonly name = "StaleLease";
|
|
353
|
+
constructor(id: string, detail?: string);
|
|
354
|
+
}
|
|
355
|
+
export declare const isStaleLease: (err: unknown) => boolean;
|
|
301
356
|
export interface StoreAdapter {
|
|
357
|
+
/**
|
|
358
|
+
* Load a conversation, creating one when `id` is undefined, and **acquire the
|
|
359
|
+
* turn lease**.
|
|
360
|
+
*
|
|
361
|
+
* A conversation may have exactly one turn in flight. Without that, two
|
|
362
|
+
* overlapping requests each load a copy, each mutate it, and the second
|
|
363
|
+
* `saveConversation` silently discards the first turn's messages. An
|
|
364
|
+
* in-process store hides this by handing back one shared object; anything
|
|
365
|
+
* networked does not.
|
|
366
|
+
*
|
|
367
|
+
* The lease must be checked here rather than at save time: a conflict
|
|
368
|
+
* discovered after the turn has run has already cost a model call.
|
|
369
|
+
*
|
|
370
|
+
* Throws `ConversationBusy` if a live lease is held. A lease older than its
|
|
371
|
+
* TTL is expired and may be taken — that is what releases a conversation
|
|
372
|
+
* stranded by a crashed process.
|
|
373
|
+
*
|
|
374
|
+
* **Acquisition must be atomic.** Reading the lease and then writing a new one
|
|
375
|
+
* is two operations, and two instances can both read "expired" before either
|
|
376
|
+
* writes — so both acquire, and the exclusion this method exists for is gone.
|
|
377
|
+
* Express it as one conditional statement, not a read followed by an update:
|
|
378
|
+
*
|
|
379
|
+
* ```sql
|
|
380
|
+
* UPDATE conversations
|
|
381
|
+
* SET lease_until = now() + $ttl, lease_token = gen_random_uuid()
|
|
382
|
+
* WHERE id = $1 AND (lease_until IS NULL OR lease_until < now())
|
|
383
|
+
* RETURNING *
|
|
384
|
+
* ```
|
|
385
|
+
*
|
|
386
|
+
* No row returned means the lease was live. Note that no conformance test can
|
|
387
|
+
* hold you to this: a single-process suite cannot interleave two acquisitions,
|
|
388
|
+
* so a read-then-write implementation passes everything and still races in
|
|
389
|
+
* production. It is a review item, not a testable one.
|
|
390
|
+
*/
|
|
302
391
|
loadConversation(id: string | undefined): Promise<Conversation>;
|
|
392
|
+
/**
|
|
393
|
+
* Persist a conversation, **rejecting a holder that has been superseded**.
|
|
394
|
+
*
|
|
395
|
+
* Throws `StaleLease` when `conversation.leaseToken` no longer matches the
|
|
396
|
+
* stored one. Without that check, expiry-based leasing still loses updates:
|
|
397
|
+
* a request slower than the TTL is overtaken, and its final write clobbers the
|
|
398
|
+
* turn that overtook it.
|
|
399
|
+
*
|
|
400
|
+
* The returned conversation must be independent of stored state. A store that
|
|
401
|
+
* hands back a live reference cannot detect staleness at all, because the
|
|
402
|
+
* caller's copy and the stored one are the same object.
|
|
403
|
+
*
|
|
404
|
+
* **The token check and the write must be one operation**, for the same reason
|
|
405
|
+
* as acquisition. Read-the-token-then-update lets a takeover land in between:
|
|
406
|
+
* the old holder sees its own token, the new holder writes, and the old update
|
|
407
|
+
* then clobbers it. Compare-and-set in a single statement and treat zero rows
|
|
408
|
+
* as stale:
|
|
409
|
+
*
|
|
410
|
+
* ```sql
|
|
411
|
+
* UPDATE conversations SET messages = $3, ...
|
|
412
|
+
* WHERE id = $1 AND lease_token = $2
|
|
413
|
+
* -- rowCount 0 → throw StaleLease
|
|
414
|
+
* ```
|
|
415
|
+
*
|
|
416
|
+
* That statement also rejects two cases a read-then-write check tends to wave
|
|
417
|
+
* through, and a store must reject them too: a conversation that does not
|
|
418
|
+
* exist (there is no row to match), and a null token (`NULL = x` is never
|
|
419
|
+
* true). Saving a conversation this store never issued a lease for is not an
|
|
420
|
+
* upsert — every conversation begins at `loadConversation`.
|
|
421
|
+
*
|
|
422
|
+
* Like acquisition, atomicity is a review item: a single-process suite cannot
|
|
423
|
+
* interleave the two halves to catch a read-then-write implementation.
|
|
424
|
+
*/
|
|
303
425
|
saveConversation(conversation: Conversation): Promise<void>;
|
|
304
|
-
|
|
426
|
+
/**
|
|
427
|
+
* Store a payload and return its handle.
|
|
428
|
+
*
|
|
429
|
+
* Fenced: throws `StaleLease` unless `leaseToken` is the conversation's
|
|
430
|
+
* current one. A superseded turn must stop writing rather than run to
|
|
431
|
+
* completion and be discarded at the end. As with `saveConversation`, check
|
|
432
|
+
* and insert in one statement:
|
|
433
|
+
*
|
|
434
|
+
* ```sql
|
|
435
|
+
* INSERT INTO payloads (conversation_id, handle, ...)
|
|
436
|
+
* SELECT $1, $2, ... WHERE EXISTS (
|
|
437
|
+
* SELECT 1 FROM conversations WHERE id = $1 AND lease_token = $3)
|
|
438
|
+
* -- rowCount 0 → throw StaleLease
|
|
439
|
+
* ```
|
|
440
|
+
*
|
|
441
|
+
* That shape rejects an unknown conversation and a null token for free, and a
|
|
442
|
+
* store must too — otherwise a caller holding no lease at all can create rows
|
|
443
|
+
* that no conversation owns.
|
|
444
|
+
*
|
|
445
|
+
* A row written *before* the lease was lost still outlives its turn — the
|
|
446
|
+
* conversation save is rejected but the row is not, so the winning history
|
|
447
|
+
* never references the handle. Those orphans are inert (see
|
|
448
|
+
* `Conversation.handles`); a durable store sweeps them by `createdAt`.
|
|
449
|
+
*/
|
|
450
|
+
putPayload(record: Omit<PayloadRecord, "handle" | "createdAt">, leaseToken: string | null): Promise<string>;
|
|
305
451
|
getPayload(handle: string, conversationId: string): Promise<PayloadRecord | null>;
|
|
306
|
-
|
|
452
|
+
/**
|
|
453
|
+
* Batch form of `getPayload`, scoped the same way. Missing or out-of-scope
|
|
454
|
+
* handles are omitted rather than returned as null, so the result may be
|
|
455
|
+
* shorter than the input.
|
|
456
|
+
*
|
|
457
|
+
* Exists because the context inspector reads every live payload on every
|
|
458
|
+
* turn. One call per handle is a map lookup in memory and a round trip over a
|
|
459
|
+
* network, so the loop is O(surfaces) queries per turn against a real store.
|
|
460
|
+
*/
|
|
461
|
+
getPayloads(handles: string[], conversationId: string): Promise<PayloadRecord[]>;
|
|
307
462
|
}
|
|
308
463
|
/** Rough token estimate. Only used to surface the economics in the UI. */
|
|
309
464
|
export declare const estTokens: (value: unknown) => number;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -72,6 +72,31 @@ export function defineSurface(def) {
|
|
|
72
72
|
export function defineTool(def) {
|
|
73
73
|
return { strict: true, ...def };
|
|
74
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Thrown by `loadConversation` when another request already holds the turn.
|
|
77
|
+
*
|
|
78
|
+
* Detected by `name` rather than `instanceof`: a duplicated install of this
|
|
79
|
+
* package would give two distinct classes, and the check must not silently
|
|
80
|
+
* start returning 500 for a case that is really a 409.
|
|
81
|
+
*/
|
|
82
|
+
export class ConversationBusy extends Error {
|
|
83
|
+
name = "ConversationBusy";
|
|
84
|
+
constructor(id) {
|
|
85
|
+
super(`conversation ${id} is busy — another turn is in flight`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export const isConversationBusy = (err) => err instanceof Error && err.name === "ConversationBusy";
|
|
89
|
+
/**
|
|
90
|
+
* Thrown by `saveConversation` when the caller's lease was superseded while its
|
|
91
|
+
* turn was still running. The write is rejected; the newer turn stands.
|
|
92
|
+
*/
|
|
93
|
+
export class StaleLease extends Error {
|
|
94
|
+
name = "StaleLease";
|
|
95
|
+
constructor(id, detail = "was taken over by a newer turn — this write was discarded") {
|
|
96
|
+
super(`conversation ${id} ${detail}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export const isStaleLease = (err) => err instanceof Error && err.name === "StaleLease";
|
|
75
100
|
/** Rough token estimate. Only used to surface the economics in the UI. */
|
|
76
101
|
export const estTokens = (value) => Math.ceil((typeof value === "string" ? value : JSON.stringify(value ?? "")).length / 4);
|
|
77
102
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAwCH;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,OAAO,SAAS,GAAG,CAAI,IAAS,EAAE,GAAuB,EAAE,OAAmB,EAAE;QAC9E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC;QAEvC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YACtB,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,QAAQ;gBAAE,MAAM;YAC1C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,KAAK,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAC3B,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC3C,MAAM,IAAI,GACR,IAAI,CAAC,MAAM,KAAK,CAAC;YACf,CAAC,CAAC,QAAQ,KAAK,SAAS;YACxB,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,OAAO,KAAK,WAAW,KAAK,CAAC,MAAM,QAAQ;gBACzD,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3C,GAAG,CAAC;QAEV,OAAO;YACL,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI;YAC1D,KAAK,EAAE,KAAK,CAAC,MAAM;YACnB,KAAK;SACI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC;AA8BD,0EAA0E;AAC1E,MAAM,CAAC,MAAM,OAAO,GAAG,CAAI,KAAgB,EAA4B,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;AAEvG,kEAAkE;AAClE,MAAM,CAAC,MAAM,MAAM,GAAG,CAAI,KAAgB,EAA2B,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;AAEpG,6EAA6E;AAC7E,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,KAAgB,EAChB,WAAoB,EACpB,cAA2B,EACb,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,CAAC;AAgD5D;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAuD,GAMnF;IACC,MAAM,OAAO,GAAqB;QAChC,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,OAAO,EAAE,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAM;QACjC,OAAO,EAAE,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAM;QACjC,SAAS,CAAC,IAAI;YACZ,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;KACF,CAAC;IACF,OAAO,OAAO,CAAC;AACjB,CAAC;AA6DD,MAAM,UAAU,UAAU,CAAI,GAQ7B;IACC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,EAAE,CAAC;AAClC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -295,12 +295,47 @@ export interface Conversation {
|
|
|
295
295
|
id: string;
|
|
296
296
|
status: ConversationStatus;
|
|
297
297
|
messages: Message[];
|
|
298
|
+
/**
|
|
299
|
+
* Every handle this conversation's surviving history rendered.
|
|
300
|
+
*
|
|
301
|
+
* Load-bearing, not bookkeeping: an interaction is refused unless its handle
|
|
302
|
+
* appears here. A payload row alone is not proof, because a turn that was
|
|
303
|
+
* overtaken leaves its rows behind while its conversation save is discarded.
|
|
304
|
+
*/
|
|
298
305
|
handles: string[];
|
|
306
|
+
/**
|
|
307
|
+
* Handles whose elicit turn has been answered — resolved by a click, or closed
|
|
308
|
+
* out by a typed override. An interaction on one of these is refused.
|
|
309
|
+
*
|
|
310
|
+
* This lives on the conversation, not on the payload, because freezing is half
|
|
311
|
+
* of one transition: the other half is the history recording what the user
|
|
312
|
+
* chose. Split across two rows, a turn could freeze the payload while it still
|
|
313
|
+
* held the lease, lose the lease before saving, and leave the surviving history
|
|
314
|
+
* awaiting a surface that can never be clicked again. On one fenced row the two
|
|
315
|
+
* halves commit together or not at all.
|
|
316
|
+
*/
|
|
317
|
+
frozen: string[];
|
|
299
318
|
pending: Pending | null;
|
|
300
|
-
/** Turn lease. A dead process leaves this in the past. */
|
|
319
|
+
/** Turn lease expiry. A dead process leaves this in the past. */
|
|
301
320
|
leaseUntil: number | null;
|
|
321
|
+
/**
|
|
322
|
+
* Fencing token, reissued every time the lease is acquired.
|
|
323
|
+
*
|
|
324
|
+
* Expiry alone is not mutual exclusion. A request slower than the TTL loses
|
|
325
|
+
* the lease while still running; another process takes it and saves a newer
|
|
326
|
+
* turn; the first then finishes and writes its stale copy over the top. The
|
|
327
|
+
* token is what lets `saveConversation` tell those two apart — a holder whose
|
|
328
|
+
* token no longer matches the stored one has been superseded.
|
|
329
|
+
*/
|
|
330
|
+
leaseToken: string | null;
|
|
302
331
|
}
|
|
303
332
|
|
|
333
|
+
/**
|
|
334
|
+
* A rendered surface's data. **Immutable once written**: everything about a
|
|
335
|
+
* surface that changes over the conversation lives on the fenced conversation
|
|
336
|
+
* row instead (see `Conversation.frozen`), so no payload write can ever disagree
|
|
337
|
+
* with the history that references it.
|
|
338
|
+
*/
|
|
304
339
|
export interface PayloadRecord {
|
|
305
340
|
handle: string;
|
|
306
341
|
conversationId: string;
|
|
@@ -308,7 +343,6 @@ export interface PayloadRecord {
|
|
|
308
343
|
version: number;
|
|
309
344
|
props: unknown;
|
|
310
345
|
mode: "display" | "elicit";
|
|
311
|
-
state: "live" | "frozen";
|
|
312
346
|
createdAt: number;
|
|
313
347
|
}
|
|
314
348
|
|
|
@@ -353,12 +387,146 @@ export interface ModelAdapter {
|
|
|
353
387
|
generate(request: ModelRequest): Promise<ModelResponse>;
|
|
354
388
|
}
|
|
355
389
|
|
|
390
|
+
/**
|
|
391
|
+
* Thrown by `loadConversation` when another request already holds the turn.
|
|
392
|
+
*
|
|
393
|
+
* Detected by `name` rather than `instanceof`: a duplicated install of this
|
|
394
|
+
* package would give two distinct classes, and the check must not silently
|
|
395
|
+
* start returning 500 for a case that is really a 409.
|
|
396
|
+
*/
|
|
397
|
+
export class ConversationBusy extends Error {
|
|
398
|
+
readonly name = "ConversationBusy";
|
|
399
|
+
constructor(id: string) {
|
|
400
|
+
super(`conversation ${id} is busy — another turn is in flight`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
export const isConversationBusy = (err: unknown): boolean =>
|
|
405
|
+
err instanceof Error && err.name === "ConversationBusy";
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Thrown by `saveConversation` when the caller's lease was superseded while its
|
|
409
|
+
* turn was still running. The write is rejected; the newer turn stands.
|
|
410
|
+
*/
|
|
411
|
+
export class StaleLease extends Error {
|
|
412
|
+
readonly name = "StaleLease";
|
|
413
|
+
constructor(id: string, detail = "was taken over by a newer turn — this write was discarded") {
|
|
414
|
+
super(`conversation ${id} ${detail}`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
export const isStaleLease = (err: unknown): boolean =>
|
|
419
|
+
err instanceof Error && err.name === "StaleLease";
|
|
420
|
+
|
|
356
421
|
export interface StoreAdapter {
|
|
422
|
+
/**
|
|
423
|
+
* Load a conversation, creating one when `id` is undefined, and **acquire the
|
|
424
|
+
* turn lease**.
|
|
425
|
+
*
|
|
426
|
+
* A conversation may have exactly one turn in flight. Without that, two
|
|
427
|
+
* overlapping requests each load a copy, each mutate it, and the second
|
|
428
|
+
* `saveConversation` silently discards the first turn's messages. An
|
|
429
|
+
* in-process store hides this by handing back one shared object; anything
|
|
430
|
+
* networked does not.
|
|
431
|
+
*
|
|
432
|
+
* The lease must be checked here rather than at save time: a conflict
|
|
433
|
+
* discovered after the turn has run has already cost a model call.
|
|
434
|
+
*
|
|
435
|
+
* Throws `ConversationBusy` if a live lease is held. A lease older than its
|
|
436
|
+
* TTL is expired and may be taken — that is what releases a conversation
|
|
437
|
+
* stranded by a crashed process.
|
|
438
|
+
*
|
|
439
|
+
* **Acquisition must be atomic.** Reading the lease and then writing a new one
|
|
440
|
+
* is two operations, and two instances can both read "expired" before either
|
|
441
|
+
* writes — so both acquire, and the exclusion this method exists for is gone.
|
|
442
|
+
* Express it as one conditional statement, not a read followed by an update:
|
|
443
|
+
*
|
|
444
|
+
* ```sql
|
|
445
|
+
* UPDATE conversations
|
|
446
|
+
* SET lease_until = now() + $ttl, lease_token = gen_random_uuid()
|
|
447
|
+
* WHERE id = $1 AND (lease_until IS NULL OR lease_until < now())
|
|
448
|
+
* RETURNING *
|
|
449
|
+
* ```
|
|
450
|
+
*
|
|
451
|
+
* No row returned means the lease was live. Note that no conformance test can
|
|
452
|
+
* hold you to this: a single-process suite cannot interleave two acquisitions,
|
|
453
|
+
* so a read-then-write implementation passes everything and still races in
|
|
454
|
+
* production. It is a review item, not a testable one.
|
|
455
|
+
*/
|
|
357
456
|
loadConversation(id: string | undefined): Promise<Conversation>;
|
|
457
|
+
/**
|
|
458
|
+
* Persist a conversation, **rejecting a holder that has been superseded**.
|
|
459
|
+
*
|
|
460
|
+
* Throws `StaleLease` when `conversation.leaseToken` no longer matches the
|
|
461
|
+
* stored one. Without that check, expiry-based leasing still loses updates:
|
|
462
|
+
* a request slower than the TTL is overtaken, and its final write clobbers the
|
|
463
|
+
* turn that overtook it.
|
|
464
|
+
*
|
|
465
|
+
* The returned conversation must be independent of stored state. A store that
|
|
466
|
+
* hands back a live reference cannot detect staleness at all, because the
|
|
467
|
+
* caller's copy and the stored one are the same object.
|
|
468
|
+
*
|
|
469
|
+
* **The token check and the write must be one operation**, for the same reason
|
|
470
|
+
* as acquisition. Read-the-token-then-update lets a takeover land in between:
|
|
471
|
+
* the old holder sees its own token, the new holder writes, and the old update
|
|
472
|
+
* then clobbers it. Compare-and-set in a single statement and treat zero rows
|
|
473
|
+
* as stale:
|
|
474
|
+
*
|
|
475
|
+
* ```sql
|
|
476
|
+
* UPDATE conversations SET messages = $3, ...
|
|
477
|
+
* WHERE id = $1 AND lease_token = $2
|
|
478
|
+
* -- rowCount 0 → throw StaleLease
|
|
479
|
+
* ```
|
|
480
|
+
*
|
|
481
|
+
* That statement also rejects two cases a read-then-write check tends to wave
|
|
482
|
+
* through, and a store must reject them too: a conversation that does not
|
|
483
|
+
* exist (there is no row to match), and a null token (`NULL = x` is never
|
|
484
|
+
* true). Saving a conversation this store never issued a lease for is not an
|
|
485
|
+
* upsert — every conversation begins at `loadConversation`.
|
|
486
|
+
*
|
|
487
|
+
* Like acquisition, atomicity is a review item: a single-process suite cannot
|
|
488
|
+
* interleave the two halves to catch a read-then-write implementation.
|
|
489
|
+
*/
|
|
358
490
|
saveConversation(conversation: Conversation): Promise<void>;
|
|
359
|
-
|
|
491
|
+
/**
|
|
492
|
+
* Store a payload and return its handle.
|
|
493
|
+
*
|
|
494
|
+
* Fenced: throws `StaleLease` unless `leaseToken` is the conversation's
|
|
495
|
+
* current one. A superseded turn must stop writing rather than run to
|
|
496
|
+
* completion and be discarded at the end. As with `saveConversation`, check
|
|
497
|
+
* and insert in one statement:
|
|
498
|
+
*
|
|
499
|
+
* ```sql
|
|
500
|
+
* INSERT INTO payloads (conversation_id, handle, ...)
|
|
501
|
+
* SELECT $1, $2, ... WHERE EXISTS (
|
|
502
|
+
* SELECT 1 FROM conversations WHERE id = $1 AND lease_token = $3)
|
|
503
|
+
* -- rowCount 0 → throw StaleLease
|
|
504
|
+
* ```
|
|
505
|
+
*
|
|
506
|
+
* That shape rejects an unknown conversation and a null token for free, and a
|
|
507
|
+
* store must too — otherwise a caller holding no lease at all can create rows
|
|
508
|
+
* that no conversation owns.
|
|
509
|
+
*
|
|
510
|
+
* A row written *before* the lease was lost still outlives its turn — the
|
|
511
|
+
* conversation save is rejected but the row is not, so the winning history
|
|
512
|
+
* never references the handle. Those orphans are inert (see
|
|
513
|
+
* `Conversation.handles`); a durable store sweeps them by `createdAt`.
|
|
514
|
+
*/
|
|
515
|
+
putPayload(
|
|
516
|
+
record: Omit<PayloadRecord, "handle" | "createdAt">,
|
|
517
|
+
leaseToken: string | null,
|
|
518
|
+
): Promise<string>;
|
|
360
519
|
getPayload(handle: string, conversationId: string): Promise<PayloadRecord | null>;
|
|
361
|
-
|
|
520
|
+
/**
|
|
521
|
+
* Batch form of `getPayload`, scoped the same way. Missing or out-of-scope
|
|
522
|
+
* handles are omitted rather than returned as null, so the result may be
|
|
523
|
+
* shorter than the input.
|
|
524
|
+
*
|
|
525
|
+
* Exists because the context inspector reads every live payload on every
|
|
526
|
+
* turn. One call per handle is a map lookup in memory and a round trip over a
|
|
527
|
+
* network, so the loop is O(surfaces) queries per turn against a real store.
|
|
528
|
+
*/
|
|
529
|
+
getPayloads(handles: string[], conversationId: string): Promise<PayloadRecord[]>;
|
|
362
530
|
}
|
|
363
531
|
|
|
364
532
|
/** Rough token estimate. Only used to surface the economics in the UI. */
|