@vercel/board 0.16.0 → 0.18.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.
Files changed (130) hide show
  1. package/README.md +27 -27
  2. package/dist/{a2-C41hD8SF.mjs → a2-ChRLRupa.mjs} +969 -25
  3. package/dist/access.d.mts +1 -1
  4. package/dist/access.mjs +3 -3
  5. package/dist/{actors-DjMeZpnU.mjs → actors-BOamkEuz.mjs} +3 -73
  6. package/dist/attempts-CLG840Oj.mjs +20 -0
  7. package/dist/{auth-COzc09sn.mjs → auth-Drg9FiC2.mjs} +225 -2
  8. package/dist/backend-B-SJ7p6p.d.mts +680 -0
  9. package/dist/backend-a2/contract.d.mts +873 -2
  10. package/dist/backend-a2/contract.mjs +2 -2
  11. package/dist/backend-a2/scheduler-local.d.mts +1 -1
  12. package/dist/backend-a2/scheduler-local.mjs +1 -1
  13. package/dist/backend-a2/scheduler-qstash.d.mts +78 -1
  14. package/dist/backend-a2/scheduler-qstash.mjs +521 -1
  15. package/dist/backend-a2/scheduler-vercel.d.mts +37 -1
  16. package/dist/backend-a2/scheduler-vercel.mjs +203 -1
  17. package/dist/backend-a2/store-memory.d.mts +2 -2
  18. package/dist/backend-a2/store-memory.mjs +3 -3
  19. package/dist/backend-a2/store-postgres.d.mts +1 -1
  20. package/dist/backend-a2/store-postgres.mjs +2850 -2
  21. package/dist/backend-a2/store-redis-http.d.mts +1 -1
  22. package/dist/backend-a2/store-redis-http.mjs +490 -2
  23. package/dist/backend-a2/store-redis.d.mts +10 -2
  24. package/dist/backend-a2/store-redis.mjs +51 -2
  25. package/dist/backend-a2/store-sqlite.d.mts +1 -1
  26. package/dist/backend-a2/store-sqlite.mjs +3 -3
  27. package/dist/backend-a2.d.mts +2706 -3
  28. package/dist/backend-a2.mjs +1 -1
  29. package/dist/{backend-http-Bid7RIpC.d.mts → backend-http-7cNb8nJI.d.mts} +10 -3
  30. package/dist/{backend-http-0roEmjl0.mjs → backend-http-CMlL3yq3.mjs} +2 -2
  31. package/dist/{backend-http-BVRno-ca.mjs → backend-http-Ddzd5kTS.mjs} +32 -3
  32. package/dist/backend-http.d.mts +1 -1
  33. package/dist/backend-http.mjs +1 -1
  34. package/dist/backend-http.node.d.mts +1 -1
  35. package/dist/backend-http.node.mjs +1 -1
  36. package/dist/{chat-provider-XCnQlxq6.d.mts → chat-provider-DNJQyajS.d.mts} +16 -4
  37. package/dist/{chat-provider-jFSeyNmB.mjs → chat-provider-YHy-WbrB.mjs} +15 -9
  38. package/dist/cli.mjs +30 -10
  39. package/dist/{client-DGDPaN7U.mjs → client-BA-J7usH.mjs} +10 -2
  40. package/dist/{conformance-DRR23YNy.mjs → conformance-CT5EeHeC.mjs} +5 -2
  41. package/dist/conformance.d.mts +1 -1
  42. package/dist/conformance.mjs +1 -1
  43. package/dist/{engine-Bir5s8ts.mjs → engine-D0oBUBEK.mjs} +249 -163
  44. package/dist/events-CewD4kw7.mjs +75 -0
  45. package/dist/{exports-Dvc1o52I.mjs → exports-CgjfMrQ-.mjs} +35 -32
  46. package/dist/exports-ZsgjzEnM.d.mts +4 -0
  47. package/dist/external-BV_cUncs.mjs +151 -0
  48. package/dist/folds-CRYY14kc.d.mts +534 -0
  49. package/dist/{reducers-mUPFuFJV.mjs → folds-Dyjput8M.mjs} +6 -73
  50. package/dist/ids-C6AYo1bu.mjs +31 -0
  51. package/dist/index.d.mts +4 -4
  52. package/dist/{index.default-Bkg77Pxn.mjs → index.default-C5Cpz3sa.mjs} +1 -1
  53. package/dist/index.mjs +5 -5
  54. package/dist/index.node.d.mts +4 -4
  55. package/dist/index.node.mjs +3 -3
  56. package/dist/inspect/app.js +31 -31
  57. package/dist/inspect/engine.js +5 -5
  58. package/dist/internal-CvsrprnU-CRY89I-b.mjs +203 -0
  59. package/dist/{local-Cr_dSjvs.mjs → local-DhkrAqPP.mjs} +1 -1
  60. package/dist/mentions-CB6ShY4R.mjs +72 -0
  61. package/dist/{targets-yM5JBUgr.mjs → middleware-CqaCwucP.mjs} +1 -33
  62. package/dist/platform-B4TnJtWu-CwcTyKg2.mjs +32 -0
  63. package/dist/{project-CFiArraX.mjs → project-DMDST9kl.mjs} +1 -1
  64. package/dist/{provider-BGjz-mDa.d.mts → provider-B0b9Qxw4.d.mts} +170 -40
  65. package/dist/provider-B3DpYSDq.mjs +220 -0
  66. package/dist/redis-tables-DN9PfIDi.mjs +3897 -0
  67. package/dist/reducer-CYPHsSmd-BQIfozGi.d.mts +170 -0
  68. package/dist/reducer-CjmvZSAb-D_OSISmj.mjs +74 -0
  69. package/dist/{contract-CuJmlrhw.mjs → reducers-BFmIXilu.mjs} +260 -287
  70. package/dist/retryable-lazy-DZWmHpii-Bye-W8q7.mjs +19 -0
  71. package/dist/scheduler-task-X1SToDjP-BVoWuInI.mjs +69 -0
  72. package/dist/{serve-BsOOc-6_.mjs → serve-BGYw0uNL.mjs} +5 -5
  73. package/dist/{server-jwPY7_wi.mjs → server-DPxBSogx.mjs} +4 -4
  74. package/dist/server-DtFrWxi3-Boa6gdWO.mjs +3602 -0
  75. package/dist/server-qgez0Xny-D5mLfqFQ.d.mts +385 -0
  76. package/dist/{serving-BNbzc96L.mjs → serving-CNkgUPW1.mjs} +1 -1
  77. package/dist/session-clear-wHd5GCpZ-BnKSxReK.mjs +51 -0
  78. package/dist/{sql-DbiEnqM0.mjs → sql-U9WTxrwJ.mjs} +2 -2
  79. package/dist/{sqlite-db-Cbj03vmp.mjs → sqlite-db-Ds4majtT.mjs} +1 -1
  80. package/dist/store-D0MhBvg6-4Z2L0Kqd.d.mts +530 -0
  81. package/dist/store-N8PXxDAS-BWBgzBHp.mjs +5 -0
  82. package/dist/store-codec-DwrWlgQx-CYxGW0aD.mjs +61 -0
  83. package/dist/store-memory-Bas9Uq5C.mjs +872 -0
  84. package/dist/store-memory-ZLiZbH3R.mjs +2 -0
  85. package/dist/store-polling-BZt2Rf3D-BiEM6_HB.mjs +148 -0
  86. package/dist/store-presence-polling-JuAy2Ck2-CYpuK75X.mjs +109 -0
  87. package/dist/store-sqlite-BmwL3pUR.mjs +2 -0
  88. package/dist/store-sqlite-CxxPCcCT.mjs +1053 -0
  89. package/dist/stream-buffer-DrTyiIuo-BKy-vI14.mjs +53 -0
  90. package/dist/sync-github.d.mts +24 -17
  91. package/dist/sync-github.mjs +89 -22
  92. package/dist/sync-kapso.d.mts +15 -13
  93. package/dist/sync-kapso.mjs +17 -14
  94. package/dist/sync-linear.d.mts +219 -0
  95. package/dist/sync-linear.mjs +311 -0
  96. package/dist/sync-slack.d.mts +12 -17
  97. package/dist/sync-slack.mjs +54 -42
  98. package/dist/sync.chat.d.mts +1 -1
  99. package/dist/sync.chat.mjs +1 -1
  100. package/dist/sync.d.mts +3 -3
  101. package/dist/sync.mjs +5 -4
  102. package/dist/targets-C-wdR5wP.mjs +33 -0
  103. package/dist/{tokens-DKLn5P9B.mjs → tokens-DhuzKzAl.mjs} +1 -1
  104. package/dist/{types-BHCjTZdB.d.mts → types-8yq2VnKI.d.mts} +2 -2
  105. package/dist/{users-Dls7_ANV.mjs → users-yryHKFMo.mjs} +2 -2
  106. package/dist/{watch-spec-W0c7ypHJ.mjs → watchers-hash-RLtnSF-t.mjs} +233 -28
  107. package/docs/01-board/01-mounting.md +1 -1
  108. package/docs/02-sync/01-overview.md +72 -48
  109. package/docs/02-sync/02-functions.md +398 -0
  110. package/docs/02-sync/03-slack.md +30 -25
  111. package/docs/02-sync/04-github.md +62 -26
  112. package/docs/02-sync/05-whatsapp.md +23 -19
  113. package/docs/02-sync/06-providers.md +60 -27
  114. package/docs/02-sync/07-linear.md +129 -0
  115. package/docs/03-guides/04-triage.md +1 -1
  116. package/docs/04-reference/01-cli.md +26 -6
  117. package/docs/04-reference/02-board.md +18 -5
  118. package/docs/04-reference/03-http.md +5 -2
  119. package/docs/04-reference/05-conformance.md +1 -1
  120. package/docs/index.md +5 -10
  121. package/package.json +31 -6
  122. package/dist/a2-D24cvwpN.d.mts +0 -3359
  123. package/dist/access-CJU2-vaa.mjs +0 -226
  124. package/dist/attempts-Bxp9KgPf.mjs +0 -919
  125. package/dist/exports-DLiE7fLY.d.mts +0 -4
  126. package/dist/provider-CuewcDNZ.mjs +0 -205
  127. package/dist/redis-tables-B35vv4CZ.mjs +0 -842
  128. package/dist/reducers-B_vUGQRp.d.mts +0 -1172
  129. package/dist/watchers-hash-CLjsa6od.mjs +0 -225
  130. package/docs/02-sync/02-callbacks.md +0 -265
@@ -0,0 +1,530 @@
1
+ import { s as PresencePatch } from "./reducer-CYPHsSmd-BQIfozGi.mjs";
2
+ //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/store-D0MhBvg6.d.ts
3
+ //#region src/store.d.ts
4
+ /** A stored event, as the public API exposes it. */
5
+ type Event = {
6
+ id: string;
7
+ type: string;
8
+ payload: unknown;
9
+ /** Position in the session's event log, from 1. */
10
+ index: number;
11
+ sessionId: string;
12
+ createdAt: Date;
13
+ };
14
+ /** The consumer attempt whose append first persisted a child event. */
15
+ type EventCause = {
16
+ consumer: string;
17
+ /** The cursor's lane; null for a concurrent consumer's cursor of one event. */
18
+ lane: string | null;
19
+ index: number;
20
+ attempt: number;
21
+ /** Size of one named consumer append, used to reject truncated retries. */
22
+ batchSize?: number;
23
+ };
24
+ /** What the store persists: immutable event history and its causal edge. */
25
+ type StoredEvent = Event & {
26
+ /** Same-session consumer attempt that appended this event; null means root. */
27
+ cause: EventCause | null;
28
+ };
29
+ /**
30
+ * Where a consumer's cursor stands on its head event. A cursor is one record
31
+ * per (session, consumer, lane): a log cursor for a consumer with one string
32
+ * lane, a lane cursor per lane for a lane function, and a cursor per event
33
+ * (lane null) for a concurrent consumer. Its attempt and failure fields
34
+ * describe the current head and reset when the cursor moves past it.
35
+ */
36
+ type HeadDispatch = {
37
+ consumer: string;
38
+ lane: string | null;
39
+ /** Adapter clock time recorded by the first durable claim of this head. */
40
+ firstClaimedAt: Date | null;
41
+ /** Adapter clock time recorded by the most recent durable claim of this head. */
42
+ lastClaimedAt: Date | null;
43
+ /** Durable claims of this head, including claims abandoned by hard kills. */
44
+ attemptCount: number;
45
+ /** Current holder; null when the head is not claimed. */
46
+ claimHolder: string | null;
47
+ /**
48
+ * Adapter clock expiry for the current claim, or, with no holder, the end
49
+ * of a failed attempt's retry hold.
50
+ */
51
+ claimExpiresAt: Date | null;
52
+ /**
53
+ * Failed attempts on this head: caught failures, and lapsed claims a later
54
+ * claim took over. This alone drives dead-lettering.
55
+ */
56
+ failureCount: number;
57
+ /** Adapter clock time recorded by the most recent caught failure. */
58
+ lastFailedAt: Date | null;
59
+ /** Attempt that produced the most recent caught failure. */
60
+ lastFailedAttempt: number | null;
61
+ /** The last failure, stringified. */
62
+ lastError: string | null;
63
+ /** Adapter clock time recorded when dead-lettered; null otherwise. */
64
+ failedAt: Date | null;
65
+ };
66
+ /** Where one cursor stands: its position, its head, and the head's dispatch state. */
67
+ type StoredCursor = HeadDispatch & {
68
+ /** The last index this cursor finished; a log cursor counts from the latest clear marker. */
69
+ position: number;
70
+ /** The event it runs next; null when it has nothing to run. */
71
+ head: number | null;
72
+ };
73
+ /** A cursor's head event together with its dispatch state. */
74
+ type HeadEvent = StoredEvent & HeadDispatch & {
75
+ /** Latest clear marker, on claimed heads of a cleared session. */
76
+ clearIndex?: number;
77
+ };
78
+ /** Names one cursor head: the consumer, its lane, and the head's index. */
79
+ type HeadRef = {
80
+ consumer: string;
81
+ lane: string | null;
82
+ index: number;
83
+ };
84
+ /**
85
+ * A consumer the caller serves. Work for consumers it does not name is
86
+ * neither pending nor claimed, so a removed consumer's cursors wait for its
87
+ * name to return.
88
+ */
89
+ type StoreConsumer = {
90
+ name: string;
91
+ /**
92
+ * Set for a consumer with one string lane. Its cursor keeps one position
93
+ * over the log and runs the next event whose type is in `types` (null:
94
+ * every type). A missing cursor is created by the first append that
95
+ * carries one of those types: at the start of the log with `backfill`,
96
+ * otherwise just before that append.
97
+ */
98
+ log?: {
99
+ lane: string;
100
+ types: readonly string[] | null;
101
+ backfill: boolean;
102
+ };
103
+ };
104
+ /**
105
+ * One live presence value, as `A2Store.presence.read` returns it. The
106
+ * row is the LWW unit — one participant's one field. `at` is the
107
+ * sender's stamp, the LWW comparator. `expiresAt` is the storage's
108
+ * own clock at the applied set plus its `ttlMs` — never derived from
109
+ * the sender stamp; a row is live strictly before it.
110
+ */
111
+ type PresenceRow = {
112
+ participant: string;
113
+ field: string;
114
+ value: unknown;
115
+ seen: number;
116
+ at: Date;
117
+ expiresAt: Date;
118
+ };
119
+ /** One consistent cache-plus-tail read for a reducer fold. */
120
+ type StoreStateRead = {
121
+ /** The current head checkpoint, even when an older historical snapshot is selected. */
122
+ headIndex: number | null;
123
+ /** The greatest cached fold at or before the requested snapshot frontier. */
124
+ snapshot: {
125
+ index: number;
126
+ state: unknown;
127
+ } | null;
128
+ /** Immutable events strictly after `snapshot.index`, or the full log on a miss. */
129
+ events: Event[];
130
+ /** Latest clear marker; omitted when the session was never cleared. */
131
+ clearIndex?: number;
132
+ };
133
+ type StoreSnapshotWrite = {
134
+ index: number;
135
+ state: unknown;
136
+ /** Unfinished cursor heads that durably retain this exact checkpoint. */
137
+ pins?: readonly HeadRef[];
138
+ };
139
+ type StoreStateReadRequest = {
140
+ sessionId: string;
141
+ throughIndex?: number;
142
+ snapshotThroughIndex?: number;
143
+ };
144
+ /** The result of atomically claiming every currently eligible head. */
145
+ type StoreClaimAvailableResult = {
146
+ outcome: "claimed";
147
+ events: HeadEvent[];
148
+ /** The session's head when the claim was made: how far behind each event is. */
149
+ head?: number;
150
+ } | {
151
+ outcome: "busy";
152
+ retryAt: Date;
153
+ } | {
154
+ outcome: "settled";
155
+ };
156
+ /** A completion may lose to a newer claim or an earlier completion. */
157
+ type CompleteAttemptResult = {
158
+ outcome: "completed";
159
+ events: StoredEvent[];
160
+ } | {
161
+ outcome: "superseded";
162
+ };
163
+ /** The result of one claim-renewal heartbeat, both lists in head order. */
164
+ type RenewClaimsResult = {
165
+ /** Listed claims that remain owned by the holder. */
166
+ renewed: HeadRef[];
167
+ /** Listed claims a newer attempt has durably taken, or whose cursor moved on. */
168
+ superseded: HeadRef[];
169
+ };
170
+ /** The result of atomically recording a caught failure. */
171
+ type FailAttemptResult = {
172
+ outcome: "failed" | "dead_lettered" | "superseded";
173
+ failureCount: number;
174
+ };
175
+ /** A consumer an appended event starts work for, with its resolved lane. */
176
+ type EventTarget = {
177
+ consumer: string;
178
+ /** The lane a lane function resolved; null runs the event concurrently. */
179
+ lane: string | null;
180
+ };
181
+ /** Input to `A2Store.append` — already validated by the machine. */
182
+ type AppendEvent = {
183
+ type: string;
184
+ payload: unknown;
185
+ /** Caller-supplied idempotency key; generated when absent. */
186
+ id?: string;
187
+ /** Internal causal edge supplied atomically by consumer `session.append`. */
188
+ cause?: EventCause;
189
+ /**
190
+ * Lane-function and concurrent consumers this event starts work for,
191
+ * resolved before persistence. Log-cursor consumers are matched by type
192
+ * from `StoreConsumer.log` instead.
193
+ */
194
+ targets?: readonly EventTarget[];
195
+ };
196
+ /** A consumer-returned event with the deterministic id retries require. */
197
+ type ReturnedEvent = AppendEvent & {
198
+ id: string;
199
+ };
200
+ /** The rows written by an append and the session's pending state. */
201
+ type StoreAppendResult = {
202
+ events: StoredEvent[];
203
+ /**
204
+ * Whether a served consumer has a live head in this session: one that is
205
+ * not dead-lettered. An append whose own batch starts work for a served
206
+ * consumer may report true without checking that work is runnable.
207
+ */
208
+ hasPending: boolean;
209
+ };
210
+ type StoreClearOptions = {
211
+ sessionId: string;
212
+ ifLastIndex?: number;
213
+ /** The clearing consumer's attempt, fenced like a consumer append. */
214
+ cause?: EventCause;
215
+ };
216
+ type StoreClearResult = {
217
+ cleared: boolean;
218
+ /** The head after the operation. */
219
+ index: number;
220
+ /** The latest clear marker after the operation, or 0. */
221
+ clearIndex: number;
222
+ };
223
+ type StoreReclaimResult = {
224
+ deleted: number;
225
+ done: boolean;
226
+ };
227
+ type StoreRedriveOptions = {
228
+ sessionId: string;
229
+ consumer: string;
230
+ index: number;
231
+ /** `retry` clears the dead letter; `skip` moves the cursor past it. */
232
+ action: "retry" | "skip";
233
+ consumers?: readonly StoreConsumer[];
234
+ };
235
+ type StoreRedriveResult = {
236
+ /** Whether the head was dead-lettered and this operation resolved it. */
237
+ redriven: boolean;
238
+ /** Whether a served consumer has a live head in this session: one that is not dead-lettered. */
239
+ hasPending: boolean;
240
+ };
241
+ /**
242
+ * An injectable clock. Adapters take one so tests can drive claim
243
+ * expiry, failure timestamps, and (later) stuck-session detection
244
+ * deterministically — against real storage, no mocking.
245
+ */
246
+ type Clock = {
247
+ now(): Date;
248
+ };
249
+ /**
250
+ * Cursor rules every operation shares:
251
+ *
252
+ * - `consumers` names the consumers the caller serves. Omitted, every cursor
253
+ * counts and no log cursor is created or advanced by type.
254
+ * - A cursor's head is the next event it runs: the lowest unfinished event of
255
+ * its lane, the event itself for a concurrent cursor, or for a log cursor
256
+ * the next event after its position whose type it takes. The clear marker
257
+ * is never a head.
258
+ * - A head is eligible when no live claim or retry hold owns it, it is not
259
+ * dead-lettered, and it lies above the latest clear marker.
260
+ * - Moving a cursor past its head resets the head's attempt and failure
261
+ * fields and releases snapshot pins on it.
262
+ */
263
+ interface A2Store {
264
+ /**
265
+ * Accepts a batch; the batch is atomic — one transaction, consecutive
266
+ * `index`es, all-or-nothing. The idempotency key covers the whole
267
+ * operation, not each item: if *every* event's `id` already exists in
268
+ * this session, this is a retry of a committed batch whose ack was
269
+ * lost — return the existing rows as success. If only *some* ids
270
+ * exist, the caller mixed an already-sent batch with fresh events —
271
+ * always a caller bug — so throw `A2Error('PARTIAL_DUPLICATE_BATCH')`.
272
+ * Ids are unique per session: the same id in another session names a
273
+ * different event and plays no part in these checks.
274
+ *
275
+ * In the same atomic operation, each event's `targets` start cursor work:
276
+ * a lane target queues the event in that consumer's lane, a null lane
277
+ * creates a cursor for that event alone. Each log consumer in `consumers`
278
+ * whose types the batch carries gets its cursor created or, when idle, a
279
+ * head: the next event after its position that it takes, which may
280
+ * precede the batch when an appender that doesn't serve it wrote in
281
+ * between. `hasPending` reflects the whole session for the served consumers,
282
+ * including older work and idempotent retries.
283
+ *
284
+ * An event carrying `cause` is a consumer append, fenced by attempt
285
+ * currency: accept it only while the cause's cursor still has
286
+ * `cause.index` as its head, `cause.attempt` is that head's latest
287
+ * attempt, and the head is not dead-lettered; otherwise throw
288
+ * `A2Error('SUPERSEDED_ATTEMPT')` and write nothing. The check is part of
289
+ * this atomic operation and must serialize against a concurrent
290
+ * `claimAvailable` — an unlocked read of the cursor admits write skew. The
291
+ * idempotent-replay path runs first, so a batch whose ids all exist
292
+ * replays regardless of the current attempt.
293
+ *
294
+ * Clearing stores (a2-implementation.md §17.2) fence one level earlier:
295
+ * a `cause` at or below the latest clear marker throws
296
+ * `SUPERSEDED_ATTEMPT`, an `originIndex` there throws `SESSION_CLEARED`,
297
+ * and ids whose rows lie below the marker are free to reuse.
298
+ */
299
+ append(sessionId: string, events: AppendEvent[], options?: {
300
+ originIndex?: number;
301
+ consumers?: readonly StoreConsumer[];
302
+ }): Promise<StoreAppendResult>;
303
+ /**
304
+ * Optional with `reclaim`. Serialized with `append`: checks
305
+ * `ifLastIndex` against the head and the latest marker, then appends a
306
+ * clear marker at the next index without touching existing rows.
307
+ * Afterwards every event at or below the marker is superseded: no head
308
+ * lies there, and every log cursor's position counts from the marker.
309
+ */
310
+ clear?(options: StoreClearOptions): Promise<StoreClearResult>;
311
+ /**
312
+ * Deletes one bounded batch of rows below the latest clear marker, with
313
+ * their cursor records, id records, and cached folds. `done` once nothing
314
+ * remains below it. Never waits on a lock that other operations hold.
315
+ */
316
+ reclaim?(sessionId: string): Promise<StoreReclaimResult>;
317
+ /**
318
+ * Optional with `redrive`. The session's dead-lettered heads above the
319
+ * latest clear marker, in event order, then by consumer name.
320
+ */
321
+ deadLetters?(sessionId: string): Promise<HeadEvent[]>;
322
+ /**
323
+ * Optional with `deadLetters`. Atomically resolves the consumer's
324
+ * dead-lettered head at `index` above the latest clear marker; anything
325
+ * else is untouched and reports `redriven: false`. `retry` clears
326
+ * `failedAt` and `failureCount`, so the head is claimable again with a
327
+ * fresh failure budget, keeping its claim history and last failure. `skip`
328
+ * moves the cursor past the head with no completion. Both serialize with
329
+ * `claimAvailable` and the consumer-append fence. `hasPending` is read in
330
+ * the same step.
331
+ */
332
+ redrive?(options: StoreRedriveOptions): Promise<StoreRedriveResult>;
333
+ /**
334
+ * Brings one log consumer's cursor up to date without an append, for
335
+ * `session.consume()`. A missing cursor is created: with `backfill`, at
336
+ * the latest clear marker, taking the first event of its types after it;
337
+ * otherwise at the head, with nothing to run. When the session has nothing
338
+ * after its latest clear (or was never written), a missing cursor stays
339
+ * missing: nothing is written, and the cursor comes back idle at the
340
+ * marker, so a consume of an unknown session leaves no trace. That is
341
+ * exact with `backfill`; without it, the consumer starts at the first
342
+ * consume or serving append that finds events. An
343
+ * idle cursor takes the next event of its types after its position, so it
344
+ * finds events appended by deployments that don't serve it. A cursor with
345
+ * a head, claimed or not, is left as it is. Records the consumer's types,
346
+ * as an append would, and returns the cursor and the session's head.
347
+ */
348
+ wakeLog(options: {
349
+ sessionId: string;
350
+ consumer: StoreConsumer & {
351
+ log: NonNullable<StoreConsumer["log"]>;
352
+ };
353
+ }): Promise<{
354
+ cursor: StoredCursor;
355
+ head: number;
356
+ }>;
357
+ /**
358
+ * The session's cursors: every log and lane cursor, and every concurrent
359
+ * cursor that still has a head, by consumer, then lane (concurrent cursors
360
+ * last, by head). Lane and concurrent cursors whose work lies at or below
361
+ * the latest clear marker are not listed.
362
+ */
363
+ cursors(sessionId: string): Promise<StoredCursor[]>;
364
+ /** Events for one session, oldest first. Bounds form `(afterIndex, throughIndex]`. */
365
+ read(sessionId: string, opts?: {
366
+ afterIndex?: number;
367
+ throughIndex?: number;
368
+ }): Promise<StoredEvent[]>;
369
+ /** Public history without causal edges; core falls back to read when absent. */
370
+ readHistory?(sessionId: string, opts?: {
371
+ afterIndex?: number;
372
+ throughIndex?: number;
373
+ }): Promise<Event[]>;
374
+ /**
375
+ * Atomically claims every eligible head of the served consumers. A live
376
+ * claim or retry hold produces `busy` only when it is the sole remaining
377
+ * obstacle to actionable work. Claimed heads are returned in event order,
378
+ * then by consumer name. Excluded heads stay unclaimed and keep blocking
379
+ * their lane.
380
+ */
381
+ claimAvailable(options: {
382
+ sessionId: string;
383
+ holder: string;
384
+ ttlMs: number;
385
+ expiresAtMs?: number;
386
+ exclude?: readonly HeadRef[];
387
+ consumers?: readonly StoreConsumer[];
388
+ /**
389
+ * Taking over a lapsed claim (one whose holder is still recorded, never
390
+ * completed or failed) adds one to `failureCount`. When that reaches
391
+ * `maxFailures`, the head dead-letters instead of being claimed: it
392
+ * comes back in `events` with `failedAt` set and no claim. Its
393
+ * `attemptCount` still advances, fencing the lapsed attempt, and its
394
+ * `lastFailedAttempt` is unchanged.
395
+ */
396
+ maxFailures?: number;
397
+ /**
398
+ * Claims only heads at or below this index: a head past it is neither
399
+ * claimed nor reported `busy`, and stays claimable without it.
400
+ */
401
+ through?: number;
402
+ }): Promise<StoreClaimAvailableResult>;
403
+ /**
404
+ * Renews the listed live claims still owned by `holder`. Each listed claim
405
+ * carries the attempt the holder owns. `renewed` lists the claims that
406
+ * remain owned after the operation; `superseded` lists the claims whose
407
+ * head a newer attempt has durably taken, or whose cursor has moved past
408
+ * it. An expired claim no successor has taken appears in neither list — its
409
+ * attempt may still complete (`completeAttempt` is the fence), so it is
410
+ * not reported as lost. Renewal never revives an expired claim.
411
+ */
412
+ renewClaims(options: {
413
+ sessionId: string;
414
+ holder: string;
415
+ claims: readonly (HeadRef & {
416
+ attempt: number;
417
+ })[];
418
+ ttlMs: number;
419
+ expiresAtMs?: number;
420
+ }): Promise<RenewClaimsResult>;
421
+ /**
422
+ * Atomically completes one current attempt: appends its returned events
423
+ * (with their own targets, waking the served log consumers) and moves the
424
+ * cursor past its head. Retrying a committed completion with the same
425
+ * attempt and deterministic child ids returns the existing children. A
426
+ * stale attempt never appends.
427
+ */
428
+ completeAttempt(options: {
429
+ sessionId: string;
430
+ consumer: string;
431
+ lane: string | null;
432
+ index: number;
433
+ attempt: number;
434
+ events: ReturnedEvent[];
435
+ consumers?: readonly StoreConsumer[];
436
+ }): Promise<CompleteAttemptResult>;
437
+ /**
438
+ * Atomically records a caught failure for one claimed attempt. A stale
439
+ * attempt cannot poison a finished head or a newer attempt. Accepted
440
+ * failures record the operation's clock time. A failure that does not
441
+ * dead-letter releases the claim and, with `retryAfterMs`, keeps the head
442
+ * unclaimable for that long: its claim expiry is set with no holder, so
443
+ * `claimAvailable` reports it `busy` until then.
444
+ */
445
+ failAttempt(options: {
446
+ sessionId: string;
447
+ consumer: string;
448
+ lane: string | null;
449
+ index: number;
450
+ attempt: number;
451
+ error: string;
452
+ maxFailures: number;
453
+ retryAfterMs?: number;
454
+ }): Promise<FailAttemptResult>;
455
+ /**
456
+ * Reads a reducer snapshot and its event tail as one consistent adapter
457
+ * operation. On a cache miss, `snapshot` is null and `events` is the full
458
+ * log. The snapshot is untrusted; core may reject it and issue a full
459
+ * `read()` when its state schema no longer accepts the cached value.
460
+ * Operational failures propagate without falling back to a full-log read.
461
+ */
462
+ readState(sessionId: string, reducerName: string, options?: {
463
+ throughIndex?: number;
464
+ snapshotThroughIndex?: number;
465
+ }): Promise<StoreStateRead>;
466
+ /**
467
+ * Optional batched `readState` — one consistent snapshot-plus-tail read
468
+ * per session id, aligned positionally with the input (duplicates
469
+ * allowed). Each element has its own frontier; the batch makes no
470
+ * cross-session consistency claim. Core falls back to parallel
471
+ * `readState` calls when absent.
472
+ */
473
+ readStates?(requests: readonly StoreStateReadRequest[], reducerName: string): Promise<StoreStateRead[]>;
474
+ /**
475
+ * Atomically writes disposable reducer checkpoints. The greatest index
476
+ * advances the head cache. Older checkpoints survive only while at least
477
+ * one listed cursor head is still unfinished; moving that cursor past it
478
+ * or dead-lettering it releases the pin and collects unreferenced
479
+ * historical checkpoints.
480
+ */
481
+ putSnapshots(sessionId: string, reducerName: string, snapshots: readonly StoreSnapshotWrite[]): Promise<void>;
482
+ /**
483
+ * Optional ephemeral-plane capability (specs/a2-implementation.md
484
+ * §15.1) — optional like snapshots are. Values arrive already
485
+ * validated by core; adapters store them opaquely. Presence never
486
+ * touches the event log: no index, no history row, no recovery arm.
487
+ */
488
+ presence?: {
489
+ /**
490
+ * Field-wise last-writer-wins merge of one participant's values:
491
+ * a field whose unexpired entry has a strictly newer `at` (the
492
+ * sender's stamp) is left untouched. `null` deletes the value but
493
+ * keeps a tombstone with its `at`, which takes part in the merge
494
+ * like a value until it expires, so a set older than the delete
495
+ * still loses when it arrives later. Every applied write, value or
496
+ * tombstone, refreshes that field's expiry to the storage's own
497
+ * clock plus `ttlMs` — the sender stamp orders writes but never
498
+ * anchors their lifetime. `subscribe` delivers applied writes only,
499
+ * a delete as `null`.
500
+ */
501
+ set(ns: string, participant: string, values: Record<string, unknown | null>, meta: {
502
+ seen: number;
503
+ at: Date;
504
+ ttlMs: number;
505
+ }): Promise<void>;
506
+ /**
507
+ * The current map, pruned of rows at or past their `expiresAt`.
508
+ * Tombstones never appear.
509
+ */
510
+ read(ns: string): Promise<PresenceRow[]>;
511
+ /**
512
+ * Adapter-managed patch delivery. Without it, live feeds re-read
513
+ * presence on their poll cadence. HTTP Redis uses adaptive polling
514
+ * here when its endpoint does not support subscriptions.
515
+ */
516
+ subscribe?(ns: string, onPatch: (patch: PresencePatch) => void): () => void;
517
+ };
518
+ /**
519
+ * A live feed of one session's events, starting after `startAfter`
520
+ * (exclusive). Transport is the backend's choice — in-process pub/sub,
521
+ * polling, LISTEN/NOTIFY — callers never branch on which. The iterable
522
+ * ends when the consumer calls `return()` (e.g. a disconnecting SSE
523
+ * client) and must deliver events appended after subscription.
524
+ */
525
+ stream(sessionId: string, opts?: {
526
+ startAfter?: number;
527
+ }): AsyncIterable<Event>;
528
+ }
529
+ //#endregion
530
+ export { Clock as n, Event as r, A2Store as t };
@@ -0,0 +1,5 @@
1
+ //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/store-N8PXxDAS.js
2
+ const SYSTEM_CLOCK = { now: () => /* @__PURE__ */ new Date() };
3
+ const RANDOM_IDS = () => crypto.randomUUID();
4
+ //#endregion
5
+ export { SYSTEM_CLOCK as n, RANDOM_IDS as t };
@@ -0,0 +1,61 @@
1
+ import { t as A2Error } from "./session-clear-wHd5GCpZ-BnKSxReK.mjs";
2
+ //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/store-codec-DwrWlgQx.js
3
+ const canonicalJson = (value) => JSON.stringify(value, (_key, candidate) => {
4
+ if (candidate === null || typeof candidate !== "object" || Array.isArray(candidate)) return candidate;
5
+ return Object.fromEntries(Object.entries(candidate).toSorted(([left], [right]) => left < right ? -1 : left > right ? 1 : 0));
6
+ }) ?? "null";
7
+ const idempotentReplay = (events, existing) => {
8
+ const byId = new Map(existing.map((event) => [event.id, event]));
9
+ const ordered = events.map((event) => event.id === void 0 ? void 0 : byId.get(event.id));
10
+ const firstIndex = ordered[0]?.index;
11
+ const batchSize = events[0]?.cause?.batchSize;
12
+ if (firstIndex === void 0 || batchSize !== void 0 && batchSize !== events.length || ordered.some((stored, index) => {
13
+ const event = events[index];
14
+ return stored === void 0 || stored.index !== firstIndex + index || stored.type !== event.type || stored.cause?.batchSize !== event.cause?.batchSize || canonicalJson(stored.payload) !== canonicalJson(event.payload);
15
+ })) throw new A2Error("PARTIAL_DUPLICATE_BATCH", "already-appended events do not match the retried batch");
16
+ return ordered;
17
+ };
18
+ const decodeReturnedEventIds = (value) => {
19
+ const decoded = typeof value === "string" ? JSON.parse(value) : value;
20
+ if (!Array.isArray(decoded) || decoded.some((eventId) => typeof eventId !== "string")) throw new TypeError("stored event has invalid returned event ids");
21
+ return decoded;
22
+ };
23
+ const positive = (value) => Number.isInteger(value) && Number(value) >= 1;
24
+ /** A stored causal edge, from its JSON text or parsed value. */
25
+ const decodeCause = (value) => {
26
+ if (value === null || value === void 0) return null;
27
+ const decoded = typeof value === "string" ? JSON.parse(value) : value;
28
+ if (typeof decoded.consumer !== "string" || decoded.consumer.length === 0 || decoded.lane !== null && typeof decoded.lane !== "string" || !positive(decoded.index) || !positive(decoded.attempt) || decoded.batchSize !== void 0 && !positive(decoded.batchSize)) throw new TypeError("stored event has an invalid cause");
29
+ return {
30
+ consumer: decoded.consumer,
31
+ lane: decoded.lane,
32
+ index: Number(decoded.index),
33
+ attempt: Number(decoded.attempt),
34
+ ...decoded.batchSize === void 0 ? {} : { batchSize: Number(decoded.batchSize) }
35
+ };
36
+ };
37
+ /** The key of a cursor within its consumer: its lane, or its one event. */
38
+ const cursorKeyOf = (lane, index) => lane === null ? `#${index}` : `L${lane}`;
39
+ /**
40
+ * A log cursor a store doesn't hold, at `position` with nothing to run:
41
+ * what `wakeLog` returns for a session with nothing after its latest clear,
42
+ * where it writes nothing.
43
+ */
44
+ const idleLogCursor = (consumer, lane, position) => ({
45
+ consumer,
46
+ lane,
47
+ position,
48
+ head: null,
49
+ firstClaimedAt: null,
50
+ lastClaimedAt: null,
51
+ attemptCount: 0,
52
+ claimHolder: null,
53
+ claimExpiresAt: null,
54
+ failureCount: 0,
55
+ lastFailedAt: null,
56
+ lastFailedAttempt: null,
57
+ lastError: null,
58
+ failedAt: null
59
+ });
60
+ //#endregion
61
+ export { idleLogCursor as a, idempotentReplay as i, decodeCause as n, decodeReturnedEventIds as r, cursorKeyOf as t };