@haikit/core 0.1.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 CHANGED
@@ -52,6 +52,17 @@ export interface ActionSpec<K extends ActionKind = ActionKind, V = unknown> {
52
52
  export interface QuerySpec<A = unknown> {
53
53
  input: Schema<A>;
54
54
  description?: string;
55
+ /**
56
+ * JSON Schema for this query's arguments, spliced into the derived `query_ui`
57
+ * tool so the model can see the parameter names.
58
+ *
59
+ * Omit it and the model is shown an opaque `args: {}`. It will then call the
60
+ * query with no arguments, every filter will be a no-op, and it will get the
61
+ * whole collection back — the exact outcome `cap()` and the digest exist to
62
+ * prevent. `input` cannot supply this: schemas are accepted structurally, so
63
+ * the runtime has a `.parse()` and no way to introspect it.
64
+ */
65
+ argsJsonSchema?: JsonSchema;
55
66
  }
56
67
  export type ActionMap = Record<string, ActionSpec<ActionKind, any>>;
57
68
  export type QueryMap = Record<string, QuerySpec<any>>;
@@ -60,7 +71,7 @@ export declare const resolve: <V>(input: Schema<V>) => ActionSpec<"resolve", V>;
60
71
  /** Adds context to the conversation without having blocked it. */
61
72
  export declare const inform: <V>(input: Schema<V>) => ActionSpec<"inform", V>;
62
73
  /** A named accessor over the stored payload. There is no raw dereference. */
63
- export declare const query: <A>(input: Schema<A>, description?: string) => QuerySpec<A>;
74
+ export declare const query: <A>(input: Schema<A>, description?: string, argsJsonSchema?: JsonSchema) => QuerySpec<A>;
64
75
  export interface DigestCtx {
65
76
  handle: string;
66
77
  }
@@ -185,11 +196,46 @@ export interface Conversation {
185
196
  id: string;
186
197
  status: ConversationStatus;
187
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
+ */
188
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[];
189
219
  pending: Pending | null;
190
- /** Turn lease. A dead process leaves this in the past. */
220
+ /** Turn lease expiry. A dead process leaves this in the past. */
191
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;
192
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
+ */
193
239
  export interface PayloadRecord {
194
240
  handle: string;
195
241
  conversationId: string;
@@ -197,7 +243,6 @@ export interface PayloadRecord {
197
243
  version: number;
198
244
  props: unknown;
199
245
  mode: "display" | "elicit";
200
- state: "live" | "frozen";
201
246
  createdAt: number;
202
247
  }
203
248
  export type Block = {
@@ -287,12 +332,133 @@ export interface ModelAdapter {
287
332
  readonly id: string;
288
333
  generate(request: ModelRequest): Promise<ModelResponse>;
289
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;
290
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
+ */
291
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
+ */
292
425
  saveConversation(conversation: Conversation): Promise<void>;
293
- putPayload(record: Omit<PayloadRecord, "handle" | "createdAt">): Promise<string>;
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>;
294
451
  getPayload(handle: string, conversationId: string): Promise<PayloadRecord | null>;
295
- freezePayload(handle: string): Promise<void>;
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[]>;
296
462
  }
297
463
  /** Rough token estimate. Only used to surface the economics in the UI. */
298
464
  export declare const estTokens: (value: unknown) => number;
@@ -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
@@ -47,7 +47,7 @@ export const resolve = (input) => ({ kind: "resolve", input });
47
47
  /** Adds context to the conversation without having blocked it. */
48
48
  export const inform = (input) => ({ kind: "inform", input });
49
49
  /** A named accessor over the stored payload. There is no raw dereference. */
50
- export const query = (input, description) => ({ input, description });
50
+ export const query = (input, description, argsJsonSchema) => ({ input, description, argsJsonSchema });
51
51
  /**
52
52
  * Declare a surface contract. Import this module from BOTH halves: the server
53
53
  * calls `.implement()`, the client renders against the same prop type.
@@ -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":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haikit/core",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "The haikit contract layer: declare a UI surface once, implement it on the server and in the browser. Isomorphic, zero runtime dependencies.",
5
5
  "keywords": [
6
6
  "haikit",
package/src/index.ts CHANGED
@@ -97,6 +97,17 @@ export interface ActionSpec<K extends ActionKind = ActionKind, V = unknown> {
97
97
  export interface QuerySpec<A = unknown> {
98
98
  input: Schema<A>;
99
99
  description?: string;
100
+ /**
101
+ * JSON Schema for this query's arguments, spliced into the derived `query_ui`
102
+ * tool so the model can see the parameter names.
103
+ *
104
+ * Omit it and the model is shown an opaque `args: {}`. It will then call the
105
+ * query with no arguments, every filter will be a no-op, and it will get the
106
+ * whole collection back — the exact outcome `cap()` and the digest exist to
107
+ * prevent. `input` cannot supply this: schemas are accepted structurally, so
108
+ * the runtime has a `.parse()` and no way to introspect it.
109
+ */
110
+ argsJsonSchema?: JsonSchema;
100
111
  }
101
112
 
102
113
  export type ActionMap = Record<string, ActionSpec<ActionKind, any>>;
@@ -109,7 +120,11 @@ export const resolve = <V>(input: Schema<V>): ActionSpec<"resolve", V> => ({ kin
109
120
  export const inform = <V>(input: Schema<V>): ActionSpec<"inform", V> => ({ kind: "inform", input });
110
121
 
111
122
  /** A named accessor over the stored payload. There is no raw dereference. */
112
- export const query = <A>(input: Schema<A>, description?: string): QuerySpec<A> => ({ input, description });
123
+ export const query = <A>(
124
+ input: Schema<A>,
125
+ description?: string,
126
+ argsJsonSchema?: JsonSchema,
127
+ ): QuerySpec<A> => ({ input, description, argsJsonSchema });
113
128
 
114
129
  // ──────────────────────────────────────────────────────── surfaces
115
130
 
@@ -280,12 +295,47 @@ export interface Conversation {
280
295
  id: string;
281
296
  status: ConversationStatus;
282
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
+ */
283
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[];
284
318
  pending: Pending | null;
285
- /** Turn lease. A dead process leaves this in the past. */
319
+ /** Turn lease expiry. A dead process leaves this in the past. */
286
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;
287
331
  }
288
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
+ */
289
339
  export interface PayloadRecord {
290
340
  handle: string;
291
341
  conversationId: string;
@@ -293,7 +343,6 @@ export interface PayloadRecord {
293
343
  version: number;
294
344
  props: unknown;
295
345
  mode: "display" | "elicit";
296
- state: "live" | "frozen";
297
346
  createdAt: number;
298
347
  }
299
348
 
@@ -338,12 +387,146 @@ export interface ModelAdapter {
338
387
  generate(request: ModelRequest): Promise<ModelResponse>;
339
388
  }
340
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
+
341
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
+ */
342
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
+ */
343
490
  saveConversation(conversation: Conversation): Promise<void>;
344
- putPayload(record: Omit<PayloadRecord, "handle" | "createdAt">): Promise<string>;
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>;
345
519
  getPayload(handle: string, conversationId: string): Promise<PayloadRecord | null>;
346
- freezePayload(handle: string): Promise<void>;
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[]>;
347
530
  }
348
531
 
349
532
  /** Rough token estimate. Only used to surface the economics in the UI. */