@abloatai/ablo 0.10.1 → 0.11.1

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 (105) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +63 -23
  3. package/dist/BaseSyncedStore.d.ts +75 -0
  4. package/dist/BaseSyncedStore.js +193 -8
  5. package/dist/Database.d.ts +10 -2
  6. package/dist/Database.js +15 -1
  7. package/dist/SyncClient.d.ts +12 -1
  8. package/dist/SyncClient.js +110 -26
  9. package/dist/agent/Agent.d.ts +9 -9
  10. package/dist/agent/Agent.js +16 -16
  11. package/dist/agent/index.d.ts +1 -1
  12. package/dist/agent/index.js +2 -2
  13. package/dist/agent/types.d.ts +1 -1
  14. package/dist/agent/types.js +1 -1
  15. package/dist/ai-sdk/{intent-broadcast.d.ts → claim-broadcast.d.ts} +10 -10
  16. package/dist/ai-sdk/{intent-broadcast.js → claim-broadcast.js} +6 -6
  17. package/dist/ai-sdk/coordination-context.d.ts +9 -9
  18. package/dist/ai-sdk/coordination-context.js +8 -8
  19. package/dist/ai-sdk/index.d.ts +1 -1
  20. package/dist/ai-sdk/index.js +1 -1
  21. package/dist/ai-sdk/wrap.d.ts +4 -4
  22. package/dist/ai-sdk/wrap.js +4 -4
  23. package/dist/api/index.d.ts +2 -2
  24. package/dist/cli.cjs +369 -67
  25. package/dist/client/Ablo.d.ts +30 -63
  26. package/dist/client/Ablo.js +124 -103
  27. package/dist/client/ApiClient.d.ts +6 -5
  28. package/dist/client/ApiClient.js +86 -62
  29. package/dist/client/auth.d.ts +9 -4
  30. package/dist/client/auth.js +40 -5
  31. package/dist/client/createModelProxy.d.ts +41 -54
  32. package/dist/client/createModelProxy.js +123 -20
  33. package/dist/client/httpClient.d.ts +2 -0
  34. package/dist/client/httpClient.js +1 -1
  35. package/dist/client/index.d.ts +3 -3
  36. package/dist/client/writeOptionsSchema.d.ts +4 -4
  37. package/dist/client/writeOptionsSchema.js +4 -4
  38. package/dist/coordination/schema.d.ts +249 -38
  39. package/dist/coordination/schema.js +172 -39
  40. package/dist/core/index.d.ts +2 -2
  41. package/dist/core/index.js +4 -4
  42. package/dist/errorCodes.d.ts +9 -9
  43. package/dist/errorCodes.js +16 -16
  44. package/dist/errors.d.ts +51 -2
  45. package/dist/errors.js +94 -5
  46. package/dist/interfaces/index.d.ts +8 -4
  47. package/dist/policy/index.d.ts +1 -1
  48. package/dist/policy/types.d.ts +13 -13
  49. package/dist/policy/types.js +8 -8
  50. package/dist/react/AbloProvider.d.ts +51 -4
  51. package/dist/react/AbloProvider.js +95 -11
  52. package/dist/react/context.d.ts +26 -9
  53. package/dist/react/context.js +2 -2
  54. package/dist/react/index.d.ts +4 -4
  55. package/dist/react/index.js +4 -4
  56. package/dist/react/useAblo.js +5 -5
  57. package/dist/react/{useIntent.d.ts → useClaim.d.ts} +9 -9
  58. package/dist/react/useClaim.js +42 -0
  59. package/dist/schema/index.js +1 -1
  60. package/dist/schema/schema.d.ts +3 -3
  61. package/dist/schema/sugar.d.ts +3 -3
  62. package/dist/schema/sugar.js +3 -3
  63. package/dist/schema/sync-delta-wire.d.ts +8 -8
  64. package/dist/server/commit.d.ts +2 -2
  65. package/dist/sync/AreaOfInterestManager.d.ts +162 -0
  66. package/dist/sync/AreaOfInterestManager.js +233 -0
  67. package/dist/sync/BootstrapHelper.d.ts +9 -1
  68. package/dist/sync/BootstrapHelper.js +15 -5
  69. package/dist/sync/NetworkProbe.d.ts +1 -1
  70. package/dist/sync/NetworkProbe.js +1 -1
  71. package/dist/sync/SyncWebSocket.d.ts +59 -25
  72. package/dist/sync/SyncWebSocket.js +123 -26
  73. package/dist/sync/awaitClaimGrant.d.ts +40 -0
  74. package/dist/sync/awaitClaimGrant.js +86 -0
  75. package/dist/sync/createClaimStream.d.ts +34 -0
  76. package/dist/sync/{createIntentStream.js → createClaimStream.js} +92 -81
  77. package/dist/sync/createPresenceStream.js +3 -2
  78. package/dist/sync/participants.d.ts +10 -10
  79. package/dist/sync/participants.js +17 -10
  80. package/dist/sync/schemas.d.ts +8 -8
  81. package/dist/transactions/TransactionQueue.d.ts +23 -0
  82. package/dist/transactions/TransactionQueue.js +186 -12
  83. package/dist/types/global.d.ts +18 -13
  84. package/dist/types/global.js +11 -6
  85. package/dist/types/index.d.ts +9 -7
  86. package/dist/types/index.js +2 -2
  87. package/dist/types/streams.d.ts +114 -98
  88. package/dist/types/streams.js +1 -1
  89. package/dist/utils/asyncIterator.d.ts +1 -1
  90. package/dist/utils/asyncIterator.js +1 -1
  91. package/dist/wire/frames.d.ts +2 -2
  92. package/docs/api.md +3 -3
  93. package/docs/client-behavior.md +6 -3
  94. package/docs/coordination.md +13 -3
  95. package/docs/data-sources.md +29 -9
  96. package/docs/migration.md +40 -0
  97. package/docs/quickstart.md +61 -33
  98. package/docs/react.md +46 -0
  99. package/llms-full.txt +25 -8
  100. package/llms.txt +11 -9
  101. package/package.json +3 -2
  102. package/dist/react/useIntent.js +0 -42
  103. package/dist/sync/awaitIntentGrant.d.ts +0 -40
  104. package/dist/sync/awaitIntentGrant.js +0 -62
  105. package/dist/sync/createIntentStream.d.ts +0 -34
@@ -15,8 +15,10 @@
15
15
  * client assembles the `ablo.<model>` lookup table from these.
16
16
  */
17
17
  import { autorun } from 'mobx';
18
- import { AbloClaimedError, AbloValidationError, toAbloError, } from '../errors.js';
18
+ import { AbloClaimedError, AbloValidationError, formatClaimedErrorMessage, toAbloError, } from '../errors.js';
19
+ import { descriptionFromMeta } from '../coordination/schema.js';
19
20
  import { Model, modelAsRow } from '../Model.js';
21
+ import { toMs } from '../utils/duration.js';
20
22
  import { assertWriteOptions } from './writeOptionsSchema.js';
21
23
  import { ModelScope } from '../types/index.js';
22
24
  const modelClientMeta = new WeakMap();
@@ -31,9 +33,9 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
31
33
  throw new AbloValidationError(`Ablo: schema model "${schemaKey}" resolved to "${registeredModelName}", ` +
32
34
  'but no matching constructor was registered.', { code: 'model_not_registered' });
33
35
  }
34
- // The coordination plane (claims/intents) must speak the SAME wire dialect
36
+ // The coordination plane (claims/claims) must speak the SAME wire dialect
35
37
  // as the commit plane: the lowercased TYPENAME (`task`), not the schema key
36
- // (`tasks`). The server's commit-time intent guard probes the lease store
38
+ // (`tasks`). The server's commit-time claim guard probes the lease store
37
39
  // with the commit op's model name; a lease recorded under the schema key
38
40
  // never collides with it — which silently disarmed the guard for every
39
41
  // model whose schema key differs from its typename (i.e. nearly all of
@@ -74,7 +76,17 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
74
76
  // Claims this proxy currently holds, keyed by entity id. Lets the flat
75
77
  // `release({ id })` and `update({ id, data })` find the lease + snapshot a `claim({ id })`
76
78
  // took — no per-call handle. Released on dispose, explicit release, or TTL.
79
+ //
80
+ // `target` / `action` / `expiresAt` are kept alongside the lease so
81
+ // `claim.state` can synthesize a self-claim: the server excludes a holder's
82
+ // own presence frames, so the local proxy is the ONLY place that knows "I
83
+ // hold this." `expiresAt` is the client's best estimate from the requested
84
+ // TTL (a genuine epoch-ms expiry, not a fabricated watermark), defaulting to
85
+ // the server's keepalive lease window when no TTL was requested.
77
86
  const activeClaims = new Map();
87
+ // Server keepalive lease window (Hub `LEASE_RENEW_TTL_MS`). The fallback
88
+ // expiry estimate when a claim is taken without an explicit TTL.
89
+ const DEFAULT_LEASE_TTL_MS = 90_000;
78
90
  const isClaimHandle = (value) => typeof value === 'object' &&
79
91
  value !== null &&
80
92
  value.object === 'claim' &&
@@ -85,6 +97,27 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
85
97
  return options?.meta;
86
98
  return { ...(options.meta ?? {}), description: options.description };
87
99
  };
100
+ const claimContextFromClaim = (claim) => {
101
+ const description = claim.description ?? descriptionFromMeta(claim.target.meta);
102
+ return {
103
+ id: claim.id,
104
+ actor: claim.heldBy,
105
+ participantKind: claim.participantKind,
106
+ action: claim.action,
107
+ ...(description ? { description } : {}),
108
+ field: claim.target.field,
109
+ status: claim.status,
110
+ expiresAt: claim.expiresAt,
111
+ target: {
112
+ model: claim.target.type,
113
+ id: claim.target.id,
114
+ path: claim.target.path,
115
+ range: claim.target.range,
116
+ field: claim.target.field,
117
+ meta: claim.target.meta,
118
+ },
119
+ };
120
+ };
88
121
  const mutationOptions = (params) => {
89
122
  const { id: _id, data: _data, claim: _claim, ...rest } = params;
90
123
  // THE write-options schema — runtime twin of the compile-time params.
@@ -102,7 +135,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
102
135
  };
103
136
  const takeClaim = async (params) => {
104
137
  if (!collaboration) {
105
- throw new AbloValidationError(`Model "${schemaKey}" cannot claim a row without collaboration wiring.`, { code: 'model_claim_not_configured' });
138
+ throw new AbloValidationError(`Model "${schemaKey}" was built without the collaboration runtime, so claim() is unavailable here. Claiming needs no per-model config — use the standard Ablo({ schema, apiKey }) client and every model is claimable.`, { code: 'model_claim_not_configured' });
106
139
  }
107
140
  const { id, ...options } = params;
108
141
  // Is someone ELSE already on this target? Read the local coordination
@@ -114,11 +147,17 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
114
147
  // Fail-fast (`wait: false`): if another participant already holds it,
115
148
  // reject now instead of queuing. Best-effort at the client (a racing
116
149
  // claim not yet synced into our snapshot slips through here) — the
117
- // commit-time intent guard is the authoritative backstop that rejects
150
+ // commit-time claim guard is the authoritative backstop that rejects
118
151
  // the loser's first write. For work-distribution dedup that's exactly
119
152
  // right: don't wait (that would double-process), skip.
120
153
  if (failFast && contended) {
121
- throw new AbloClaimedError(`${registeredModelName}/${id} is held by ${held?.heldBy ?? 'another participant'}.`, { code: 'entity_claimed' });
154
+ const claim = held ? claimContextFromClaim(held) : undefined;
155
+ throw new AbloClaimedError(formatClaimedErrorMessage({
156
+ targetLabel: `${registeredModelName}/${id}`,
157
+ heldBy: held?.heldBy,
158
+ claim,
159
+ fallback: `${registeredModelName}/${id} is held by ${held?.heldBy ?? 'another participant'}.`,
160
+ }), { code: 'entity_claimed', claims: claim ? [claim] : undefined });
122
161
  }
123
162
  // Ensure the row exists locally before claiming.
124
163
  let model = objectPool.get(id);
@@ -129,12 +168,20 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
129
168
  if (!model) {
130
169
  throw new AbloValidationError(`Entity not found: ${registeredModelName}/${id}`, { code: 'entity_not_found' });
131
170
  }
171
+ // Write-intent: enter the entity scope BEFORE acquiring the lease so the
172
+ // holder's claim presence broadcasts to whoever is in this entity group —
173
+ // including a peer that subscribed just before us. Pinning before the
174
+ // lease (rather than after) closes the subscribe-vs-broadcast race: the
175
+ // server fans `broadcastPresenceChange` out at claim time, so we must be
176
+ // in the group when `createClaim` lands. Awaited because the broadcast
177
+ // ordering depends on it; still soft (the store swallows reconcile errors).
178
+ await collaboration.pinScope?.({ [schemaKey]: id });
132
179
  // Acquire the lease. Default (`wait` !== false) goes through the server's
133
180
  // fair FIFO queue — `queue: true` resolves only once the lease is genuinely
134
181
  // ours, blocking behind any current holder, with no TOCTOU gap (the server
135
182
  // orders contenders). Fail-fast skips the queue: we already rejected an
136
183
  // observed conflict above, so this just records our lease.
137
- const lease = await collaboration.createIntent({
184
+ const lease = await collaboration.createClaim({
138
185
  target: {
139
186
  model: wireModel,
140
187
  id,
@@ -151,9 +198,9 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
151
198
  // Only when we actually waited behind another holder can the row have
152
199
  // changed underneath us — re-read so the claimed snapshot reflects what
153
200
  // they committed before releasing. Two signals, either suffices:
154
- // - `lease.waited` — the server granted via `intent_granted`, i.e. we
201
+ // - `lease.waited` — the server granted via `claim_granted`, i.e. we
155
202
  // provably queued behind a holder. Authoritative; works even when
156
- // the local snapshot is blind (intent fan-out is entity-scoped, so
203
+ // the local snapshot is blind (claim fan-out is entity-scoped, so
157
204
  // org-wide-subscribed clients never observe peers' claims).
158
205
  // - `contended` — the local snapshot saw a holder up front. Kept for
159
206
  // the no-queue paths where no grant frame exists.
@@ -166,7 +213,27 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
166
213
  model = objectPool.get(id) ?? model;
167
214
  }
168
215
  const snapshot = collaboration.createSnapshot(schemaKey, id);
169
- activeClaims.set(id, { lease, snapshot });
216
+ const action = options?.action ?? 'editing';
217
+ // The self-claim's `EntityRef` mirrors what a peer's `claim.state` would
218
+ // report (`observe` maps `held.target.model` → `type`), so a holder and a
219
+ // peer see the SAME target.type for one row — the wire model token.
220
+ const selfTarget = {
221
+ type: wireModel,
222
+ id,
223
+ ...(options?.field ? { field: options.field } : {}),
224
+ ...(options?.path ? { path: options.path } : {}),
225
+ ...(options?.range ? { range: options.range } : {}),
226
+ ...(claimMeta(options) ? { meta: claimMeta(options) } : {}),
227
+ };
228
+ const expiresAt = Date.now() +
229
+ (options?.ttl !== undefined ? toMs(options.ttl) : DEFAULT_LEASE_TTL_MS);
230
+ activeClaims.set(id, {
231
+ lease,
232
+ snapshot,
233
+ target: selfTarget,
234
+ action,
235
+ expiresAt,
236
+ });
170
237
  const target = {
171
238
  model: schemaKey,
172
239
  id,
@@ -178,10 +245,10 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
178
245
  const release = () => releaseClaim(id);
179
246
  return {
180
247
  object: 'claim',
181
- claimId: lease.id,
248
+ claimId: lease.claimId,
182
249
  readAt: snapshot.stamp,
183
250
  target,
184
- action: options?.action ?? 'editing',
251
+ action,
185
252
  ...(options?.description ? { description: options.description } : {}),
186
253
  data: modelAsRow(model),
187
254
  release,
@@ -198,6 +265,28 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
198
265
  // are the same object.
199
266
  const claimApi = Object.assign(guard(claim), {
200
267
  state(params) {
268
+ // Read-interest: a passive observer subscribing to a row's claim state
269
+ // must enter that row's entity scope, or it sits on `org:`/`user:`
270
+ // groups only and never receives the holder's entity-scoped claim
271
+ // presence. Soft + fire-and-forget — never blocks or rejects the read.
272
+ void collaboration?.enterScope?.({ [schemaKey]: params.id });
273
+ // Self-awareness: the server excludes a holder's OWN presence frames and
274
+ // the client skips them, so `observe` returns null for a row WE hold.
275
+ // Synthesize the active claim for self from the stored lease so the
276
+ // holder sees its own claim (the JSDoc contract on `claim.state`).
277
+ const own = activeClaims.get(params.id);
278
+ if (own) {
279
+ return {
280
+ object: 'claim',
281
+ id: own.lease.claimId,
282
+ status: 'active',
283
+ target: own.target,
284
+ action: own.action,
285
+ heldBy: collaboration?.selfParticipantId ?? '',
286
+ participantKind: collaboration?.selfParticipantKind ?? 'user',
287
+ expiresAt: own.expiresAt,
288
+ };
289
+ }
201
290
  return collaboration?.observe({ model: wireModel, id: params.id }) ?? null;
202
291
  },
203
292
  queue(params) {
@@ -213,6 +302,11 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
213
302
  });
214
303
  const operations = {
215
304
  retrieve: guard(async (params) => {
305
+ // Read-interest enrolment: READ a row → enter its entity scope, so a
306
+ // Node/agent client lands in the same group the holder's claim presence
307
+ // fans out on and `claim.state`/`claim.queue` report peers. Soft +
308
+ // fire-and-forget — never make the read reject or slower.
309
+ void collaboration?.enterScope?.({ [schemaKey]: params.id });
216
310
  const rows = await load({
217
311
  ...params,
218
312
  where: [['id', params.id]],
@@ -220,6 +314,9 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
220
314
  });
221
315
  return rows[0];
222
316
  }),
317
+ // NB: no auto scope enrolment on bulk `list`/`getAll` — that would
318
+ // subscribe to an unbounded set of rows' entity groups. Bulk-list scope
319
+ // enrolment is a deliberate follow-up (a bounded, opt-in policy).
223
320
  list: guard(load),
224
321
  get(id) {
225
322
  return objectPool.get(id);
@@ -267,9 +364,15 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
267
364
  let autoLease;
268
365
  if (claim && !isClaimHandle(claim)) {
269
366
  if (!collaboration) {
270
- throw new AbloValidationError(`Model "${schemaKey}" cannot claim a row without collaboration wiring.`, { code: 'model_claim_not_configured' });
367
+ throw new AbloValidationError(`Model "${schemaKey}" was built without the collaboration runtime, so claim() is unavailable here. Claiming needs no per-model config — use the standard Ablo({ schema, apiKey }) client and every model is claimable.`, { code: 'model_claim_not_configured' });
271
368
  }
272
- autoLease = await collaboration.createIntent({
369
+ // Write-intent: enter the new row's entity scope BEFORE acquiring the
370
+ // create-claim so the holder's claim presence broadcasts to whoever is
371
+ // already in this entity group (closing the subscribe-vs-broadcast
372
+ // race — see `takeClaim`). Released with the lease in the `finally`
373
+ // below. Awaited for broadcast ordering; still soft.
374
+ await collaboration.pinScope?.({ [schemaKey]: id });
375
+ autoLease = await collaboration.createClaim({
273
376
  target: {
274
377
  model: wireModel,
275
378
  id,
@@ -299,8 +402,8 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
299
402
  });
300
403
  const effective = {
301
404
  ...opts,
302
- ...(autoLease ? { intent: autoLease } : {}),
303
- ...(isClaimHandle(claim) ? { intent: { id: claim.claimId } } : {}),
405
+ ...(autoLease ? { claim: autoLease } : {}),
406
+ ...(isClaimHandle(claim) ? { claim: { id: claim.claimId } } : {}),
304
407
  };
305
408
  try {
306
409
  syncClient.add(model, effective);
@@ -336,7 +439,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
336
439
  wait: 'confirmed',
337
440
  readAt: claimed.snapshot.stamp,
338
441
  onStale: 'reject',
339
- intent: claimed.lease,
442
+ claimRef: { id: claimed.lease.claimId },
340
443
  ...opts,
341
444
  }
342
445
  : {
@@ -351,7 +454,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
351
454
  }
352
455
  : {}),
353
456
  ...opts,
354
- ...(handle ? { intent: { id: handle.claimId } } : {}),
457
+ ...(handle ? { claim: { id: handle.claimId } } : {}),
355
458
  };
356
459
  // Local user update: `applyChanges` keeps change tracking ON so
357
460
  // the edited fields land in `modifiedProperties` and actually get
@@ -386,7 +489,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
386
489
  wait: 'confirmed',
387
490
  readAt: claimed.snapshot.stamp,
388
491
  onStale: 'reject',
389
- intent: claimed.lease,
492
+ claimRef: { id: claimed.lease.claimId },
390
493
  ...opts,
391
494
  }
392
495
  : {
@@ -398,7 +501,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
398
501
  }
399
502
  : {}),
400
503
  ...opts,
401
- ...(handle ? { intent: { id: handle.claimId } } : {}),
504
+ ...(handle ? { claim: { id: handle.claimId } } : {}),
402
505
  };
403
506
  syncClient.delete(model, effective);
404
507
  await waitForMutation(model, effective);
@@ -55,6 +55,8 @@ export interface HttpModelClient<T, C = T> {
55
55
  export type AbloHttpClient<S extends SchemaRecord> = {
56
56
  readonly [K in keyof S & string]: HttpModelClient<InferModel<Schema<S>, K>, InferCreate<Schema<S>, K>>;
57
57
  } & {
58
+ /** Register `databaseUrl` when configured. Also runs lazily before the first request. */
59
+ ready(): Promise<void>;
58
60
  readonly commits: CommitResource;
59
61
  dispose(): Promise<void>;
60
62
  /** Resolve the bearer credential this client authenticates with (see `AbloApi.getAuthToken`). */
@@ -26,7 +26,7 @@ import { createProtocolClient, } from './ApiClient.js';
26
26
  /**
27
27
  * Members of the underlying `AbloApi` that pass straight through the facade.
28
28
  * Deliberately EXCLUDES the resource names that collide with common schema model
29
- * names — `tasks`, `intents`, `capabilities`, `agent` — so `client.tasks` resolves
29
+ * names — `tasks`, `claims`, `capabilities`, `agent` — so `client.tasks` resolves
30
30
  * to the schema model `tasks`, not the protocol `TaskResource`. Only lifecycle +
31
31
  * the genuinely-protocol methods an agent uses pass through.
32
32
  */
@@ -29,8 +29,8 @@
29
29
  * });
30
30
  * ```
31
31
  */
32
- export { Ablo, computeFKDepthPriority, type AbloOptions, type InternalAbloOptions, type ClaimedOptions, type IfClaimedPolicy, type IntentWaitOptions, type ModelCountOptions, type ModelListOptions, type ModelListScope, type ModelLoadOptions, type ModelOperations, type ModelReadOptions, } from './Ablo.js';
32
+ export { Ablo, computeFKDepthPriority, type AbloOptions, type InternalAbloOptions, type ClaimedOptions, type IfClaimedPolicy, type ClaimWaitOptions, type ModelCountOptions, type ModelListOptions, type ModelListScope, type ModelLoadOptions, type ModelOperations, type ModelReadOptions, } from './Ablo.js';
33
33
  export { ABLO_DEFAULT_BASE_URL, ABLO_HOSTED_API_DOMAIN, ABLO_HOSTED_HTTP_BASE_URL, normalizeAbloHostedBaseUrl, } from './auth.js';
34
34
  export type { AbloPersistence } from './persistence.js';
35
- export type { AbloApi, AbloApiClientOptions, AbloApiIntents, Capability, CapabilityCreateOptions, CapabilityParticipantKind, CapabilityRecord, CapabilityResource, CapabilityRevocation, CapabilityScope, } from './ApiClient.js';
36
- export type { EngineParticipant, JoinedParticipant, ParticipantJoinOptions, ParticipantManager, ParticipantScope, ParticipantStatus, ScopedIntents, ScopedPresence, } from '../sync/participants.js';
35
+ export type { AbloApi, AbloApiClientOptions, AbloApiClaims, Capability, CapabilityCreateOptions, CapabilityParticipantKind, CapabilityRecord, CapabilityResource, CapabilityRevocation, CapabilityScope, } from './ApiClient.js';
36
+ export type { EngineParticipant, JoinedParticipant, ParticipantJoinOptions, ParticipantManager, ParticipantScope, ParticipantStatus, ScopedClaims, ScopedPresence, } from '../sync/participants.js';
@@ -10,8 +10,8 @@
10
10
  * bottom so the two can never silently diverge.
11
11
  *
12
12
  * Validation-only by design: callers keep their ORIGINAL options object.
13
- * Zod's parse output strips unknown keys, and the `intent` slot legally
14
- * carries live handles (`IntentLeaseHandle` / claim leases) whose
13
+ * Zod's parse output strips unknown keys, and the `claim` slot legally
14
+ * carries live handles (`ClaimHandle` / claim leases) whose
15
15
  * `release`/`revoke` functions must survive — so we assert, never replace.
16
16
  */
17
17
  import { z } from 'zod';
@@ -25,8 +25,8 @@ export declare const writeOptionsSchema: z.ZodObject<{
25
25
  idempotencyKey: z.ZodOptional<z.ZodNullable<z.ZodString>>;
26
26
  label: z.ZodOptional<z.ZodString>;
27
27
  wait: z.ZodOptional<z.ZodEnum<{
28
- confirmed: "confirmed";
29
28
  queued: "queued";
29
+ confirmed: "confirmed";
30
30
  }>>;
31
31
  readAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
32
32
  onStale: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
@@ -35,7 +35,7 @@ export declare const writeOptionsSchema: z.ZodObject<{
35
35
  flag: "flag";
36
36
  merge: "merge";
37
37
  }>>>;
38
- intent: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
38
+ claim: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
39
39
  id: z.ZodString;
40
40
  }, z.core.$loose>]>>>;
41
41
  causedByTaskId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -10,8 +10,8 @@
10
10
  * bottom so the two can never silently diverge.
11
11
  *
12
12
  * Validation-only by design: callers keep their ORIGINAL options object.
13
- * Zod's parse output strips unknown keys, and the `intent` slot legally
14
- * carries live handles (`IntentLeaseHandle` / claim leases) whose
13
+ * Zod's parse output strips unknown keys, and the `claim` slot legally
14
+ * carries live handles (`ClaimHandle` / claim leases) whose
15
15
  * `release`/`revoke` functions must survive — so we assert, never replace.
16
16
  */
17
17
  import { z } from 'zod';
@@ -28,9 +28,9 @@ export const writeOptionsSchema = z.object({
28
28
  readAt: z.number().int().nonnegative().nullish(),
29
29
  /** What the server does when the target moved past `readAt`. */
30
30
  onStale: onStaleModeSchema.nullish(),
31
- /** Claim/intent attribution — an id, or a live lease handle (loose: the
31
+ /** Claim/claim attribution — an id, or a live lease handle (loose: the
32
32
  * handle's `release`/`revoke` functions ride along untouched). */
33
- intent: z.union([z.string(), z.looseObject({ id: z.string() })]).nullish(),
33
+ claim: z.union([z.string(), z.looseObject({ id: z.string() })]).nullish(),
34
34
  /** Dormant wire-compat field; always `null` from current clients. */
35
35
  causedByTaskId: z.string().nullish(),
36
36
  });