@abloatai/transaction 0.37.1 → 0.39.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 (181) hide show
  1. package/dist/ai-sdk/index.d.ts +3 -1
  2. package/dist/ai-sdk/index.d.ts.map +1 -1
  3. package/dist/ai-sdk/index.js +2 -1
  4. package/dist/ai-sdk/index.js.map +1 -1
  5. package/dist/ai-sdk/modelTools.d.ts +67 -0
  6. package/dist/ai-sdk/modelTools.d.ts.map +1 -0
  7. package/dist/ai-sdk/modelTools.js +89 -0
  8. package/dist/ai-sdk/modelTools.js.map +1 -0
  9. package/dist/ai-sdk/toolOptions.d.ts +8 -0
  10. package/dist/ai-sdk/toolOptions.d.ts.map +1 -0
  11. package/dist/ai-sdk/toolOptions.js +2 -0
  12. package/dist/ai-sdk/toolOptions.js.map +1 -0
  13. package/dist/ai-sdk/{coordinatedTool.d.ts → updateTool.d.ts} +21 -28
  14. package/dist/ai-sdk/updateTool.d.ts.map +1 -0
  15. package/dist/ai-sdk/{coordinatedTool.js → updateTool.js} +39 -50
  16. package/dist/ai-sdk/updateTool.js.map +1 -0
  17. package/dist/auth/capability.d.ts +6 -0
  18. package/dist/auth/capability.d.ts.map +1 -1
  19. package/dist/auth/capability.js +4 -0
  20. package/dist/auth/capability.js.map +1 -1
  21. package/dist/auth/capabilityLifecycle.d.ts +3 -0
  22. package/dist/auth/capabilityLifecycle.d.ts.map +1 -1
  23. package/dist/auth/identity.d.ts +6 -4
  24. package/dist/auth/identity.d.ts.map +1 -1
  25. package/dist/auth/identity.js +7 -11
  26. package/dist/auth/identity.js.map +1 -1
  27. package/dist/auth/index.d.ts +16 -2
  28. package/dist/auth/index.d.ts.map +1 -1
  29. package/dist/auth/index.js +10 -1
  30. package/dist/auth/index.js.map +1 -1
  31. package/dist/auth/schemas.d.ts +5 -5
  32. package/dist/auth/schemas.d.ts.map +1 -1
  33. package/dist/auth/schemas.js +5 -2
  34. package/dist/auth/schemas.js.map +1 -1
  35. package/dist/auth/sessionMint.d.ts.map +1 -1
  36. package/dist/auth/sessionMint.js +3 -0
  37. package/dist/auth/sessionMint.js.map +1 -1
  38. package/dist/branches.d.ts +251 -0
  39. package/dist/branches.d.ts.map +1 -0
  40. package/dist/branches.js +108 -0
  41. package/dist/branches.js.map +1 -0
  42. package/dist/coordination/awaitClaimGrant.d.ts +2 -0
  43. package/dist/coordination/awaitClaimGrant.d.ts.map +1 -1
  44. package/dist/coordination/awaitClaimGrant.js +15 -2
  45. package/dist/coordination/awaitClaimGrant.js.map +1 -1
  46. package/dist/coordination/schema.d.ts +2 -0
  47. package/dist/coordination/schema.d.ts.map +1 -1
  48. package/dist/coordination/schema.js +2 -0
  49. package/dist/coordination/schema.js.map +1 -1
  50. package/dist/docs/catalog.d.ts +5 -5
  51. package/dist/docs/catalog.d.ts.map +1 -1
  52. package/dist/docs/catalog.js +12 -12
  53. package/dist/docs/catalog.js.map +1 -1
  54. package/dist/errorCodes.d.ts +1 -0
  55. package/dist/errorCodes.d.ts.map +1 -1
  56. package/dist/errorCodes.js +1 -0
  57. package/dist/errorCodes.js.map +1 -1
  58. package/dist/footprint.d.ts +3 -5
  59. package/dist/footprint.d.ts.map +1 -1
  60. package/dist/footprint.js +0 -0
  61. package/dist/footprint.js.map +1 -1
  62. package/dist/index.d.ts +1 -0
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +1 -0
  65. package/dist/index.js.map +1 -1
  66. package/dist/keys/index.d.ts +15 -7
  67. package/dist/keys/index.d.ts.map +1 -1
  68. package/dist/keys/index.js +45 -14
  69. package/dist/keys/index.js.map +1 -1
  70. package/dist/schema/index.d.ts +1 -1
  71. package/dist/schema/index.d.ts.map +1 -1
  72. package/dist/schema/index.js +1 -1
  73. package/dist/schema/index.js.map +1 -1
  74. package/dist/schema/openapi.d.ts +1 -1
  75. package/dist/schema/openapi.d.ts.map +1 -1
  76. package/dist/schema/openapi.js +308 -29
  77. package/dist/schema/openapi.js.map +1 -1
  78. package/dist/schema/schema.d.ts +12 -0
  79. package/dist/schema/schema.d.ts.map +1 -1
  80. package/dist/schema/schema.js.map +1 -1
  81. package/dist/schema/select.d.ts +13 -0
  82. package/dist/schema/select.d.ts.map +1 -1
  83. package/dist/schema/select.js +26 -0
  84. package/dist/schema/select.js.map +1 -1
  85. package/dist/server/commit.d.ts +2 -15
  86. package/dist/server/commit.d.ts.map +1 -1
  87. package/dist/source/adapter.d.ts +7 -2
  88. package/dist/source/adapter.d.ts.map +1 -1
  89. package/dist/source/adapter.js +4 -2
  90. package/dist/source/adapter.js.map +1 -1
  91. package/dist/source/adapterFactory.d.ts +10 -0
  92. package/dist/source/adapterFactory.d.ts.map +1 -0
  93. package/dist/source/adapterFactory.js +33 -0
  94. package/dist/source/adapterFactory.js.map +1 -0
  95. package/dist/source/adapterProfile.d.ts +55 -0
  96. package/dist/source/adapterProfile.d.ts.map +1 -0
  97. package/dist/source/adapterProfile.js +54 -0
  98. package/dist/source/adapterProfile.js.map +1 -0
  99. package/dist/source/adapters/drizzle.d.ts.map +1 -1
  100. package/dist/source/adapters/drizzle.js +5 -2
  101. package/dist/source/adapters/drizzle.js.map +1 -1
  102. package/dist/source/adapters/kysely.d.ts.map +1 -1
  103. package/dist/source/adapters/kysely.js +7 -4
  104. package/dist/source/adapters/kysely.js.map +1 -1
  105. package/dist/source/adapters/memory.d.ts.map +1 -1
  106. package/dist/source/adapters/memory.js +5 -2
  107. package/dist/source/adapters/memory.js.map +1 -1
  108. package/dist/source/adapters/prisma.d.ts.map +1 -1
  109. package/dist/source/adapters/prisma.js +5 -2
  110. package/dist/source/adapters/prisma.js.map +1 -1
  111. package/dist/source/conformance.d.ts.map +1 -1
  112. package/dist/source/conformance.js +18 -0
  113. package/dist/source/conformance.js.map +1 -1
  114. package/dist/source/index.d.ts +2 -0
  115. package/dist/source/index.d.ts.map +1 -1
  116. package/dist/source/index.js +2 -0
  117. package/dist/source/index.js.map +1 -1
  118. package/dist/source/types.d.ts +3 -14
  119. package/dist/source/types.d.ts.map +1 -1
  120. package/dist/source/types.js.map +1 -1
  121. package/dist/syncLog/contract.d.ts +1 -1
  122. package/dist/syncLog/contract.d.ts.map +1 -1
  123. package/dist/syncLog/contract.js +1 -2
  124. package/dist/syncLog/contract.js.map +1 -1
  125. package/dist/transport/httpClient.d.ts.map +1 -1
  126. package/dist/transport/httpClient.js +10 -1
  127. package/dist/transport/httpClient.js.map +1 -1
  128. package/dist/wire/accountResponses.d.ts +5 -9
  129. package/dist/wire/accountResponses.d.ts.map +1 -1
  130. package/dist/wire/accountResponses.js +5 -6
  131. package/dist/wire/accountResponses.js.map +1 -1
  132. package/dist/wire/auth.d.ts +7 -1
  133. package/dist/wire/auth.d.ts.map +1 -1
  134. package/dist/wire/auth.js +26 -3
  135. package/dist/wire/auth.js.map +1 -1
  136. package/dist/wire/delta.d.ts +11 -0
  137. package/dist/wire/delta.d.ts.map +1 -1
  138. package/dist/wire/delta.js +11 -0
  139. package/dist/wire/delta.js.map +1 -1
  140. package/dist/wire/inboundFrames.d.ts +2 -0
  141. package/dist/wire/inboundFrames.d.ts.map +1 -1
  142. package/package.json +8 -2
  143. package/src/ai-sdk/index.ts +19 -6
  144. package/src/ai-sdk/modelTools.ts +165 -0
  145. package/src/ai-sdk/toolOptions.ts +18 -0
  146. package/src/ai-sdk/{coordinatedTool.ts → updateTool.ts} +59 -69
  147. package/src/auth/capability.ts +4 -0
  148. package/src/auth/identity.ts +16 -16
  149. package/src/auth/index.ts +31 -3
  150. package/src/auth/schemas.ts +5 -2
  151. package/src/auth/sessionMint.ts +3 -0
  152. package/src/branches.ts +134 -0
  153. package/src/coordination/awaitClaimGrant.ts +18 -2
  154. package/src/coordination/schema.ts +2 -0
  155. package/src/docs/catalog.ts +24 -12
  156. package/src/errorCodes.ts +4 -0
  157. package/src/footprint.ts +0 -0
  158. package/src/index.ts +1 -0
  159. package/src/keys/index.ts +56 -17
  160. package/src/schema/index.ts +1 -1
  161. package/src/schema/openapi.ts +366 -38
  162. package/src/schema/schema.ts +13 -0
  163. package/src/schema/select.ts +30 -0
  164. package/src/server/commit.ts +2 -15
  165. package/src/source/adapter.ts +7 -2
  166. package/src/source/adapterFactory.ts +60 -0
  167. package/src/source/adapterProfile.ts +75 -0
  168. package/src/source/adapters/drizzle.ts +5 -2
  169. package/src/source/adapters/kysely.ts +10 -4
  170. package/src/source/adapters/memory.ts +5 -2
  171. package/src/source/adapters/prisma.ts +5 -2
  172. package/src/source/conformance.ts +18 -0
  173. package/src/source/index.ts +14 -0
  174. package/src/source/types.ts +3 -14
  175. package/src/syncLog/contract.ts +1 -2
  176. package/src/transport/httpClient.ts +8 -1
  177. package/src/wire/accountResponses.ts +5 -6
  178. package/src/wire/auth.ts +30 -3
  179. package/src/wire/delta.ts +11 -0
  180. package/dist/ai-sdk/coordinatedTool.d.ts.map +0 -1
  181. package/dist/ai-sdk/coordinatedTool.js.map +0 -1
package/dist/wire/auth.js CHANGED
@@ -10,7 +10,7 @@
10
10
  * `auth/schemas.ts`.
11
11
  */
12
12
  import { z } from 'zod';
13
- import { grantedOperationSchema } from '../auth/capability.js';
13
+ import { capabilityOperationSchema, grantedOperationSchema } from '../auth/capability.js';
14
14
  import { syncGroupInputSchema } from '../coordination/schema.js';
15
15
  /** The participant this session acts as. */
16
16
  export const ephemeralKeyUserSchema = z.object({
@@ -44,8 +44,25 @@ export const ephemeralKeyRequestSchema = z.object({
44
44
  schemaOwnerOrgId: z.string().min(1).optional(),
45
45
  /** Narrow the session to these sync groups. */
46
46
  syncGroups: z.array(syncGroupInputSchema).readonly().optional(),
47
- /** Required least-privilege allowlist. */
48
- operations: z.array(grantedOperationSchema).min(1),
47
+ /**
48
+ * Least-privilege allowlist, named model by model. For a caller that knows
49
+ * the schema the session will resolve. Exactly one of this and
50
+ * {@link ephemeralKeyRequestSchema.shape.activeSchemaOperations} is required.
51
+ */
52
+ operations: z.array(grantedOperationSchema).min(1).optional(),
53
+ /**
54
+ * The same allowlist expressed as verbs alone, for a caller that CANNOT know
55
+ * the models: an identity service minting sessions for organizations whose
56
+ * schemas it does not own has no way to name them, and a grant is checked
57
+ * against the session's schema at mint time, so naming another schema's
58
+ * models fails every time.
59
+ *
60
+ * The server expands these across the models in the session's active schema
61
+ * and stores the concrete result, so what lands on the credential is the same
62
+ * enumerated allowlist as the field above. A verb is granted only where the
63
+ * model admits it — an immutable model takes `read` and nothing else.
64
+ */
65
+ activeSchemaOperations: z.array(capabilityOperationSchema).min(1).optional(),
49
66
  /** Lifetime in seconds. Capped by the server's maximum. */
50
67
  ttlSeconds: z.number().int().positive().optional(),
51
68
  /** A human-readable tag recorded with the key, for debugging. */
@@ -54,6 +71,12 @@ export const ephemeralKeyRequestSchema = z.object({
54
71
  (request.schemaOwnerOrgId === undefined), {
55
72
  message: 'schemaProjectId and schemaOwnerOrgId must be provided together',
56
73
  path: ['schemaProjectId'],
74
+ }).refine((request) => (request.operations === undefined) !== (request.activeSchemaOperations === undefined), {
75
+ // Exactly one, never both and never neither. Neither would leave the
76
+ // credential with an empty allowlist, which reads as UNRESTRICTED at the
77
+ // gate rather than as nothing; both would leave two answers to one question.
78
+ message: 'provide either operations or activeSchemaOperations, not both',
79
+ path: ['operations'],
57
80
  });
58
81
  /**
59
82
  * The capability mint body lives with the rest of the capability vocabulary in
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/wire/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,4CAA4C;AAC5C,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACxC,CAAC,CAAC;AAGH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,4CAA4C;IAC5C,IAAI,EAAE,sBAAsB;IAC5B;;;;OAIG;IACH,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC5C;;;;OAIG;IACH,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC7C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC9C,+CAA+C;IAC/C,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC/D,0CAA0C;IAC1C,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAClD,2DAA2D;IAC3D,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAClD,iEAAiE;IACjE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC,MAAM,CACP,CAAC,OAAO,EAAE,EAAE,CACV,CAAC,OAAO,CAAC,eAAe,KAAK,SAAS,CAAC;IACvC,CAAC,OAAO,CAAC,gBAAgB,KAAK,SAAS,CAAC,EAC1C;IACE,OAAO,EACL,gEAAgE;IAClE,IAAI,EAAE,CAAC,iBAAiB,CAAC;CAC1B,CACF,CAAC;AAGF;;;;;;;;;;;GAWG;AACH,OAAO,EACL,uBAAuB,EACvB,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/wire/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,4CAA4C;AAC5C,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACxC,CAAC,CAAC;AAGH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,4CAA4C;IAC5C,IAAI,EAAE,sBAAsB;IAC5B;;;;OAIG;IACH,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC5C;;;;OAIG;IACH,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC7C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC9C,+CAA+C;IAC/C,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC/D;;;;OAIG;IACH,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC7D;;;;;;;;;;;OAWG;IACH,sBAAsB,EAAE,CAAC,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC5E,2DAA2D;IAC3D,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAClD,iEAAiE;IACjE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC,MAAM,CACP,CAAC,OAAO,EAAE,EAAE,CACV,CAAC,OAAO,CAAC,eAAe,KAAK,SAAS,CAAC;IACvC,CAAC,OAAO,CAAC,gBAAgB,KAAK,SAAS,CAAC,EAC1C;IACE,OAAO,EACL,gEAAgE;IAClE,IAAI,EAAE,CAAC,iBAAiB,CAAC;CAC1B,CACF,CAAC,MAAM,CACN,CAAC,OAAO,EAAE,EAAE,CACV,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,sBAAsB,KAAK,SAAS,CAAC,EACvF;IACE,qEAAqE;IACrE,yEAAyE;IACzE,6EAA6E;IAC7E,OAAO,EAAE,+DAA+D;IACxE,IAAI,EAAE,CAAC,YAAY,CAAC;CACrB,CACF,CAAC;AAGF;;;;;;;;;;;GAWG;AACH,OAAO,EACL,uBAAuB,EACvB,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC"}
@@ -62,6 +62,17 @@ export type SyncDeltaAction = z.infer<typeof syncDeltaActionSchema>;
62
62
  * serialized string (used by the group-change frames on `G` and `S` deltas), or
63
63
  * `null` on deletes. This is wider than the stored row's payload — which is only a
64
64
  * row or null — because the group-change frames encode their payload as a string.
65
+ *
66
+ * The record branch costs more than its contract suggests: it walks
67
+ * `Reflect.ownKeys` and rebuilds the payload into a fresh object on every parse,
68
+ * so client-side validation scales with a row's field count on a path that runs
69
+ * once per delta (2.7 microseconds at 23 fields, against 0.15 for a predicate).
70
+ * Replacing it was tried and reverted, because every faster spelling gives up
71
+ * something this contract owns: `z.custom` cannot be represented in JSON Schema
72
+ * and breaks the derived spec, and `z.unknown().refine` derives to an empty
73
+ * schema and infers `unknown`, which would widen {@link WireDeltaData}. A
74
+ * predicate must also match this schema's real acceptance, which is
75
+ * plain-object: `z.record` rejects `Date`, `Map`, and class instances.
65
76
  */
66
77
  export declare const wireDeltaDataSchema: z.ZodNullable<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodString]>>;
67
78
  export type WireDeltaData = z.infer<typeof wireDeltaDataSchema>;
@@ -1 +1 @@
1
- {"version":3,"file":"delta.d.ts","sourceRoot":"","sources":["../../src/wire/delta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB;;yCAEyC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,2EAA2E;AAC3E,eAAO,MAAM,uBAAuB;;;;;;EAMlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;EAAmD,CAAC;AACtF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,2FAEnB,CAAC;AACd,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;;;;;;iBAG/B,CAAC;AACH,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAO9D;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;iBAYlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;iBAQhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiBhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAWpB,CAAC;AACL,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC"}
1
+ {"version":3,"file":"delta.d.ts","sourceRoot":"","sources":["../../src/wire/delta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB;;yCAEyC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,2EAA2E;AAC3E,eAAO,MAAM,uBAAuB;;;;;;EAMlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;EAAmD,CAAC;AACtF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,mBAAmB,2FAEnB,CAAC;AACd,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;;;;;;iBAG/B,CAAC;AACH,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAO9D;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;iBAYlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;iBAQhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiBhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAWpB,CAAC;AACL,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC"}
@@ -54,6 +54,17 @@ export const syncDeltaActionSchema = z.enum(['I', 'U', 'D', 'A', 'V', 'C', 'G',
54
54
  * serialized string (used by the group-change frames on `G` and `S` deltas), or
55
55
  * `null` on deletes. This is wider than the stored row's payload — which is only a
56
56
  * row or null — because the group-change frames encode their payload as a string.
57
+ *
58
+ * The record branch costs more than its contract suggests: it walks
59
+ * `Reflect.ownKeys` and rebuilds the payload into a fresh object on every parse,
60
+ * so client-side validation scales with a row's field count on a path that runs
61
+ * once per delta (2.7 microseconds at 23 fields, against 0.15 for a predicate).
62
+ * Replacing it was tried and reverted, because every faster spelling gives up
63
+ * something this contract owns: `z.custom` cannot be represented in JSON Schema
64
+ * and breaks the derived spec, and `z.unknown().refine` derives to an empty
65
+ * schema and infers `unknown`, which would widen {@link WireDeltaData}. A
66
+ * predicate must also match this schema's real acceptance, which is
67
+ * plain-object: `z.record` rejects `Date`, `Map`, and class instances.
57
68
  */
58
69
  export const wireDeltaDataSchema = z
59
70
  .union([z.record(z.string(), z.unknown()), z.string()])
@@ -1 +1 @@
1
- {"version":3,"file":"delta.js","sourceRoot":"","sources":["../../src/wire/delta.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"delta.js","sourceRoot":"","sources":["../../src/wire/delta.ts"],"names":[],"mappings":"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"}
@@ -326,6 +326,7 @@ export declare const WS_INBOUND_FRAMES: {
326
326
  readonly payload: z.ZodObject<{
327
327
  claimId: z.ZodString;
328
328
  fenceToken: z.ZodOptional<z.ZodNumber>;
329
+ readAt: z.ZodOptional<z.ZodNumber>;
329
330
  target: z.ZodObject<{
330
331
  entityType: z.ZodString;
331
332
  entityId: z.ZodString;
@@ -389,6 +390,7 @@ export declare const WS_INBOUND_FRAMES: {
389
390
  readonly payload: z.ZodObject<{
390
391
  claimId: z.ZodString;
391
392
  fenceToken: z.ZodOptional<z.ZodNumber>;
393
+ readAt: z.ZodOptional<z.ZodNumber>;
392
394
  target: z.ZodObject<{
393
395
  entityType: z.ZodString;
394
396
  entityId: z.ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"inboundFrames.d.ts","sourceRoot":"","sources":["../../src/wire/inboundFrames.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgBxB;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;;kCAKZ,CAAC;AACzB,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,0CAA0C;AAC1C,MAAM,MAAM,oBAAoB;AAC9B,wDAAwD;AACtD;IAAE,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAA;CAAE;AAChE;;;;;;GAMG;GACD;IACE,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;CAChC,CAAC;AAEN;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+D2B,CAAC;AAE1D,8CAA8C;AAC9C,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,iBAAiB,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG;KAC/B,CAAC,IAAI,gBAAgB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS;QAC7D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC;KAC7C,GACG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GACV,KAAK;CACV,CAAC;AAEF,sEAAsE;AACtE,MAAM,MAAM,wBAAwB,GAAG;KACpC,CAAC,IAAI,gBAAgB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS;QAC7D,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;KAC/B,GACG,CAAC,GACD,KAAK;CACV,CAAC,gBAAgB,CAAC,CAAC;AAEpB,4DAA4D;AAC5D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,gBAAgB,CAE1E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,gBAAgB,GACrB,IAAI,IAAI,wBAAwB,CAElC"}
1
+ {"version":3,"file":"inboundFrames.d.ts","sourceRoot":"","sources":["../../src/wire/inboundFrames.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgBxB;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;;kCAKZ,CAAC;AACzB,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,0CAA0C;AAC1C,MAAM,MAAM,oBAAoB;AAC9B,wDAAwD;AACtD;IAAE,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAA;CAAE;AAChE;;;;;;GAMG;GACD;IACE,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;CAChC,CAAC;AAEN;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+D2B,CAAC;AAE1D,8CAA8C;AAC9C,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,iBAAiB,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG;KAC/B,CAAC,IAAI,gBAAgB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS;QAC7D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC;KAC7C,GACG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GACV,KAAK;CACV,CAAC;AAEF,sEAAsE;AACtE,MAAM,MAAM,wBAAwB,GAAG;KACpC,CAAC,IAAI,gBAAgB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS;QAC7D,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;KAC/B,GACG,CAAC,GACD,KAAK;CACV,CAAC,gBAAgB,CAAC,CAAC;AAEpB,4DAA4D;AAC5D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,gBAAgB,CAE1E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,gBAAgB,GACrB,IAAI,IAAI,wBAAwB,CAElC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abloatai/transaction",
3
- "version": "0.37.1",
3
+ "version": "0.39.0",
4
4
  "description": "The headless Ablo transaction client and canonical contracts for reads, commits, settlement, claims, and durable observation.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -22,6 +22,11 @@
22
22
  "import": "./dist/environment.js",
23
23
  "default": "./dist/environment.js"
24
24
  },
25
+ "./branches": {
26
+ "types": "./dist/branches.d.ts",
27
+ "import": "./dist/branches.js",
28
+ "default": "./dist/branches.js"
29
+ },
25
30
  "./coordination": {
26
31
  "types": "./dist/coordination/index.d.ts",
27
32
  "import": "./dist/coordination/index.js",
@@ -161,7 +166,7 @@
161
166
  "zod": "^4.4.3"
162
167
  },
163
168
  "peerDependencies": {
164
- "ai": "^6.0.0",
169
+ "ai": "^6.0.0 || ^7.0.0",
165
170
  "drizzle-orm": ">=0.44.0"
166
171
  },
167
172
  "peerDependenciesMeta": {
@@ -177,6 +182,7 @@
177
182
  "@jest/globals": "^30.2.0",
178
183
  "@types/jest": "^30.0.0",
179
184
  "ai": "^6.0.0",
185
+ "drizzle-orm": "^0.45.2",
180
186
  "jest": "^30.2.0",
181
187
  "jest-environment-node": "^30.2.0",
182
188
  "publint": "^0.3.17",
@@ -1,7 +1,20 @@
1
1
  export {
2
- coordinatedTool,
3
- type CoordinationStrategy,
4
- type CoordinatedModel,
5
- type CoordinatedToolOptions,
6
- type CoordinatedWriteResult,
7
- } from './coordinatedTool.js';
2
+ updateTool,
3
+ type UpdateStrategy,
4
+ type UpdateToolModel,
5
+ type UpdateToolOptions,
6
+ type UpdateToolResult,
7
+ } from './updateTool.js';
8
+ export {
9
+ createTool,
10
+ deleteTool,
11
+ readTool,
12
+ type CreateToolOptions,
13
+ type CreateToolResult,
14
+ type DeleteToolOptions,
15
+ type DeleteToolResult,
16
+ type ReadToolOptions,
17
+ type ReadToolResult,
18
+ type ToolModel,
19
+ } from './modelTools.js';
20
+ export type { ModelToolOptions } from './toolOptions.js';
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Small AI SDK adapters for Ablo model resources.
3
+ *
4
+ * The AI SDK owns the agent loop. These helpers only expose Ablo's
5
+ * authoritative model operations as tools, preserving the same credential,
6
+ * validation, idempotency, claims, and settlement behavior as direct SDK use.
7
+ */
8
+
9
+ import { tool, type ToolExecutionOptions } from 'ai';
10
+ import type { z } from 'zod';
11
+ import type {
12
+ ClaimParams,
13
+ ModelCreateParams,
14
+ ModelDeleteParams,
15
+ ModelRetrieveParams,
16
+ } from '../resources/modelOperations.js';
17
+ import type { HeldClaim } from '../types/streams.js';
18
+ import type { ModelToolOptions } from './toolOptions.js';
19
+
20
+ export interface ToolModel<T, CreateInput = Partial<T>, Fields = T> {
21
+ get(params: ModelRetrieveParams): Promise<T | undefined>;
22
+ create(params: ModelCreateParams<T, CreateInput>): Promise<T>;
23
+ delete(params: ModelDeleteParams<T, Fields>): Promise<void>;
24
+ claim(
25
+ params: ClaimParams<Fields> & { queue: false },
26
+ ): Promise<HeldClaim<T> | null>;
27
+ claim(params: ClaimParams<Fields>): Promise<HeldClaim<T>>;
28
+ }
29
+
30
+ export interface ReadToolOptions<TInput, T>
31
+ extends ModelToolOptions<TInput, ReadToolResult<T>> {
32
+ readonly description: string;
33
+ readonly inputSchema: z.ZodType<TInput>;
34
+ readonly id: (input: TInput) => string;
35
+ }
36
+
37
+ export type ReadToolResult<T> =
38
+ | { readonly status: 'found'; readonly row: T }
39
+ | { readonly status: 'not_found'; readonly message: string };
40
+
41
+ export function readTool<TInput, T>(
42
+ model: Pick<ToolModel<T>, 'get'>,
43
+ options: ReadToolOptions<TInput, T>,
44
+ ) {
45
+ return tool<TInput, ReadToolResult<T>>({
46
+ description: options.description,
47
+ title: options.title,
48
+ inputSchema: options.inputSchema,
49
+ inputExamples: options.inputExamples,
50
+ needsApproval: options.needsApproval,
51
+ strict: options.strict,
52
+ outputSchema: options.outputSchema,
53
+ toModelOutput: options.toModelOutput,
54
+ execute: async (input) => {
55
+ const id = options.id(input);
56
+ const row = await model.get({ id });
57
+ return row === undefined
58
+ ? {
59
+ status: 'not_found',
60
+ message: `No accessible row exists with id ${id}.`,
61
+ }
62
+ : { status: 'found', row };
63
+ },
64
+ });
65
+ }
66
+
67
+ export interface CreateToolOptions<TInput, CreateInput, T>
68
+ extends ModelToolOptions<TInput, CreateToolResult<T>> {
69
+ readonly description: string;
70
+ readonly inputSchema: z.ZodType<TInput>;
71
+ readonly data: (input: TInput) => CreateInput;
72
+ /**
73
+ * Stable ids make retries idempotent. Omit only when the model or server
74
+ * generates the id and duplicate creation is acceptable to the application.
75
+ */
76
+ readonly id?: (input: TInput) => string | undefined;
77
+ }
78
+
79
+ export interface CreateToolResult<T> {
80
+ readonly status: 'created';
81
+ readonly row: T;
82
+ }
83
+
84
+ export function createTool<TInput, T, CreateInput>(
85
+ model: Pick<ToolModel<T, CreateInput>, 'create'>,
86
+ options: CreateToolOptions<TInput, CreateInput, T>,
87
+ ) {
88
+ return tool<TInput, CreateToolResult<T>>({
89
+ description: options.description,
90
+ title: options.title,
91
+ inputSchema: options.inputSchema,
92
+ inputExamples: options.inputExamples,
93
+ needsApproval: options.needsApproval,
94
+ strict: options.strict,
95
+ outputSchema: options.outputSchema,
96
+ toModelOutput: options.toModelOutput,
97
+ execute: async (input) => {
98
+ const id = options.id?.(input);
99
+ const row = await model.create({
100
+ data: options.data(input),
101
+ ...(id !== undefined ? { id } : {}),
102
+ wait: 'confirmed',
103
+ });
104
+ return { status: 'created', row };
105
+ },
106
+ });
107
+ }
108
+
109
+ export interface DeleteToolOptions<TInput>
110
+ extends ModelToolOptions<TInput, DeleteToolResult> {
111
+ readonly description: string;
112
+ readonly inputSchema: z.ZodType<TInput>;
113
+ readonly id: (input: TInput) => string;
114
+ /** Defaults to waiting in the server-owned FIFO claim queue. */
115
+ readonly strategy?: 'claim' | 'queue';
116
+ readonly claim?: { readonly description?: string };
117
+ }
118
+
119
+ export type DeleteToolResult =
120
+ | { readonly status: 'deleted'; readonly id: string }
121
+ | { readonly status: 'claimed'; readonly message: string };
122
+
123
+ export function deleteTool<TInput, T, Fields = T>(
124
+ model: Pick<ToolModel<T, Partial<T>, Fields>, 'claim' | 'delete'>,
125
+ options: DeleteToolOptions<TInput>,
126
+ ) {
127
+ return tool<TInput, DeleteToolResult>({
128
+ description: options.description,
129
+ title: options.title,
130
+ inputSchema: options.inputSchema,
131
+ inputExamples: options.inputExamples,
132
+ // Destructive tools require approval unless an application deliberately
133
+ // opts into autonomous deletion.
134
+ needsApproval: options.needsApproval ?? true,
135
+ strict: options.strict,
136
+ outputSchema: options.outputSchema,
137
+ toModelOutput: options.toModelOutput,
138
+ execute: async (
139
+ input: TInput,
140
+ execution: ToolExecutionOptions,
141
+ ): Promise<DeleteToolResult> => {
142
+ const id = options.id(input);
143
+ const queue = options.strategy !== 'claim';
144
+ const claim = await model.claim({
145
+ id,
146
+ queue,
147
+ description: options.claim?.description,
148
+ signal: execution.abortSignal,
149
+ });
150
+ if (!claim) {
151
+ return {
152
+ status: 'claimed',
153
+ message:
154
+ 'Another participant holds this row right now — it was not deleted.',
155
+ };
156
+ }
157
+ try {
158
+ await model.delete({ id, claim, wait: 'confirmed' });
159
+ return { status: 'deleted', id };
160
+ } finally {
161
+ await claim.release();
162
+ }
163
+ },
164
+ });
165
+ }
@@ -0,0 +1,18 @@
1
+ import type { Tool } from 'ai';
2
+
3
+ /**
4
+ * AI SDK-native presentation and execution policy shared by Ablo model tools.
5
+ * Ablo owns the data operation; AI SDK owns how the tool is presented,
6
+ * validated, approved, and returned to the model.
7
+ */
8
+ export type ModelToolOptions<TInput, TResult> = Partial<
9
+ Pick<
10
+ Tool<TInput, TResult>,
11
+ | 'title'
12
+ | 'inputExamples'
13
+ | 'needsApproval'
14
+ | 'strict'
15
+ | 'outputSchema'
16
+ | 'toModelOutput'
17
+ >
18
+ >;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Turns a write to one of your models into a Vercel AI SDK tool that handles
2
+ * Turns a write to one of your models into an AI SDK tool that handles
3
3
  * multi-agent coordination for you, so an agent can contribute to shared state
4
4
  * without silently overwriting another writer's concurrent change.
5
5
  *
@@ -11,10 +11,10 @@
11
11
  * write:
12
12
  *
13
13
  * ```ts
14
- * import { coordinatedTool } from '@abloatai/transaction/ai-sdk';
14
+ * import { updateTool } from '@abloatai/ablo/ai-sdk';
15
15
  * import { z } from 'zod';
16
16
  *
17
- * const saveSection = coordinatedTool(ablo.documents, {
17
+ * const saveSection = updateTool(ablo.documents, {
18
18
  * description: 'Save your section into the shared document.',
19
19
  * inputSchema: z.object({ text: z.string() }),
20
20
  * id: () => DOC_ID,
@@ -25,7 +25,7 @@
25
25
  * await streamText({ model, messages, tools: { saveSection } });
26
26
  * ```
27
27
  *
28
- * The {@link CoordinatedToolOptions.apply} function is the whole API: a pure
28
+ * The {@link UpdateToolOptions.apply} function is the whole API: a pure
29
29
  * function from the freshest row and the tool input to a patch, in the same
30
30
  * spirit as a functional state update. Everything beneath it — reading the latest
31
31
  * row, the compare-and-swap, backing off between retries, and releasing claims —
@@ -52,42 +52,39 @@
52
52
  * than a hidden wait when it might spend its turn on something else. Works under
53
53
  * any conflict policy.
54
54
  *
55
- * - `'queue'` serializes writers over stateless HTTP. The tool polls to acquire
56
- * the claim until it is granted or `poll.timeoutMs` elapses, so the model calls
57
- * once and the tool waits its turn. Ordering is approximate rather than strict
58
- * first-in-first-out, which would require a persistent connection.
55
+ * - `'queue'` joins Ablo's server-owned FIFO queue. The model calls once and
56
+ * the tool waits for the canonical claim grant; it does not recreate queueing
57
+ * with client-side polling.
59
58
  */
60
59
 
61
- import { tool } from 'ai';
60
+ import { tool, type ToolExecutionOptions } from 'ai';
62
61
  import type { z } from 'zod';
63
- import { AbloClaimedError, AbloNotFoundError } from '@abloatai/transaction/errors';
64
62
  import type {
65
63
  ClaimParams,
66
- ModelRetrieveParams,
67
64
  ModelUpdateParams,
68
65
  } from '../resources/modelOperations.js';
69
66
  import type { ModelUpdater, ContentionOptions } from '../resources/functionalUpdate.js';
70
67
  import type { HeldClaim } from '../types/streams.js';
68
+ import type { ModelToolOptions } from './toolOptions.js';
71
69
 
72
- export type CoordinationStrategy = 'merge' | 'claim' | 'queue';
70
+ export type UpdateStrategy = 'merge' | 'claim' | 'queue';
73
71
 
74
72
  /** The structured result the tool hands back to the model (or the caller). */
75
- export interface CoordinatedWriteResult<T> {
73
+ export interface UpdateToolResult<T> {
76
74
  /**
77
75
  * `'written'` means the change was saved. `'claimed'` means another participant
78
76
  * holds the row, so nothing was saved and the model should try again.
79
- * `'timeout'` means the `'queue'` strategy could not acquire the row within
80
- * `poll.timeoutMs`.
81
77
  */
82
- status: 'written' | 'claimed' | 'timeout';
78
+ status: 'written' | 'claimed';
83
79
  /** The reconciled row, on `'written'`. */
84
80
  row?: T;
85
81
  message?: string;
86
- /** On `'written'` via the `queue` strategy, how long the tool waited in line. */
82
+ /** On `'written'` via the `queue` strategy, how long the tool waited. */
87
83
  waitedMs?: number;
88
84
  }
89
85
 
90
- export interface CoordinatedToolOptions<TInput, T> {
86
+ export interface UpdateToolOptions<TInput, T>
87
+ extends ModelToolOptions<TInput, UpdateToolResult<T>> {
91
88
  /** Tool description shown to the model. */
92
89
  description: string;
93
90
  /** The schema of what the model may send, as a standard AI SDK / Zod input schema. */
@@ -103,45 +100,50 @@ export interface CoordinatedToolOptions<TInput, T> {
103
100
  */
104
101
  apply: (current: T, input: TInput) => Partial<T>;
105
102
  /** How concurrent writers relate. Defaults to `'merge'`. */
106
- strategy?: CoordinationStrategy;
103
+ strategy?: UpdateStrategy;
107
104
  /** Human-readable coordination metadata attached to the claim, used by the `'claim'` and `'queue'` strategies. */
108
105
  claim?: { description?: string };
109
106
  /** How many reconcile rounds `'merge'` may take before it gives up with `AbloContentionError`. */
110
107
  retries?: number;
111
- /** Poll interval and overall timeout for `'queue'`. Defaults to 250ms and 30s. */
112
- poll?: { intervalMs?: number; timeoutMs?: number };
113
108
  }
114
109
 
115
- const sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));
116
-
117
110
  /**
118
111
  * The small model port this helper needs. Both typed transports implement this
119
112
  * exact contract; local-cache methods, wire receipts, and transport lifecycle
120
113
  * deliberately stay out of an AI tool's dependency surface.
121
114
  */
122
- export interface CoordinatedModel<T> {
123
- get(params: ModelRetrieveParams): Promise<T | undefined>;
124
- /** @deprecated Use `get({ id })`. */
125
- retrieve?(params: ModelRetrieveParams): Promise<T | undefined>;
115
+ export interface UpdateToolModel<T> {
126
116
  update(params: ModelUpdateParams<T>): Promise<T>;
127
117
  update(
128
118
  id: string,
129
119
  updater: ModelUpdater<T>,
130
120
  options?: ContentionOptions,
131
121
  ): Promise<T | undefined>;
122
+ claim(
123
+ params: ClaimParams<T> & { queue: false },
124
+ ): Promise<HeldClaim<T> | null>;
132
125
  claim(params: ClaimParams<T>): Promise<HeldClaim<T>>;
133
126
  }
134
127
 
135
- export function coordinatedTool<
128
+ export function updateTool<
136
129
  TInput,
137
130
  T = Record<string, unknown>,
138
- >(model: CoordinatedModel<T>, options: CoordinatedToolOptions<TInput, T>) {
131
+ >(model: UpdateToolModel<T>, options: UpdateToolOptions<TInput, T>) {
139
132
  const strategy = options.strategy ?? 'merge';
140
133
 
141
- return tool<TInput, CoordinatedWriteResult<T>>({
134
+ return tool<TInput, UpdateToolResult<T>>({
142
135
  description: options.description,
136
+ title: options.title,
143
137
  inputSchema: options.inputSchema,
144
- execute: async (input: TInput): Promise<CoordinatedWriteResult<T>> => {
138
+ inputExamples: options.inputExamples,
139
+ needsApproval: options.needsApproval,
140
+ strict: options.strict,
141
+ outputSchema: options.outputSchema,
142
+ toModelOutput: options.toModelOutput,
143
+ execute: async (
144
+ input: TInput,
145
+ execution: ToolExecutionOptions,
146
+ ): Promise<UpdateToolResult<T>> => {
145
147
  const id = options.id(input);
146
148
 
147
149
  if (strategy === 'merge') {
@@ -150,29 +152,39 @@ export function coordinatedTool<
150
152
  // backoff. The model never sees a conflict.
151
153
  const row = await model.update(id, (current) => options.apply(current, input), {
152
154
  retries: options.retries,
155
+ signal: execution.abortSignal,
153
156
  });
154
157
  return { status: 'written', row: row ?? undefined };
155
158
  }
156
159
 
157
160
  // The 'claim' and 'queue' strategies both acquire a claim, write under it,
158
161
  // and release it. They differ only in what they do when the row is already
159
- // held: 'claim' returns a signal to the model, while 'queue' waits and
160
- // retries by polling to acquire.
161
- const acquireWriteRelease = async (): Promise<CoordinatedWriteResult<T>> => {
162
+ // held: 'claim' returns a signal to the model, while 'queue' waits for
163
+ // the server-owned FIFO grant.
164
+ const acquireWriteRelease = async (
165
+ queue: boolean,
166
+ ): Promise<UpdateToolResult<T>> => {
162
167
  const claim = await model.claim({
163
168
  id,
164
- queue: false,
169
+ queue,
165
170
  description: options.claim?.description,
171
+ signal: execution.abortSignal,
166
172
  });
173
+ if (!claim) {
174
+ return {
175
+ status: 'claimed',
176
+ message:
177
+ 'Another participant holds this row right now — it was not saved.',
178
+ };
179
+ }
167
180
  try {
168
- const current = await model.get({ id });
169
- if (current === undefined) {
170
- throw new AbloNotFoundError(
171
- `Cannot write ${id}: it does not exist (or is outside this credential's scope).`,
172
- [id],
173
- );
174
- }
175
- const row = await model.update({ id, data: options.apply(current, input), claim, wait: 'confirmed' });
181
+ const current = claim.data;
182
+ const row = await model.update({
183
+ id,
184
+ data: options.apply(current, input),
185
+ claim,
186
+ wait: 'confirmed',
187
+ });
176
188
  return { status: 'written', row };
177
189
  } finally {
178
190
  await claim.release();
@@ -180,35 +192,13 @@ export function coordinatedTool<
180
192
  };
181
193
 
182
194
  if (strategy === 'claim') {
183
- try {
184
- return await acquireWriteRelease();
185
- } catch (e) {
186
- if (e instanceof AbloClaimedError) {
187
- return { status: 'claimed', message: 'Another participant holds this row right now — it was NOT saved. Wait briefly and try again.' };
188
- }
189
- throw e;
190
- }
195
+ return acquireWriteRelease(false);
191
196
  }
192
197
 
193
- // strategy === 'queue': poll to acquire the claim over stateless HTTP.
194
- const interval = options.poll?.intervalMs ?? 250;
195
- const timeout = options.poll?.timeoutMs ?? 30_000;
198
+ // The transaction client owns the server FIFO and resolves once granted.
196
199
  const start = Date.now();
197
- for (;;) {
198
- try {
199
- const result = await acquireWriteRelease();
200
- return { ...result, waitedMs: Date.now() - start };
201
- } catch (e) {
202
- if (e instanceof AbloClaimedError) {
203
- if (Date.now() - start >= timeout) {
204
- return { status: 'timeout', message: `Could not acquire the row within ${timeout}ms.` };
205
- }
206
- await sleep(interval);
207
- continue;
208
- }
209
- throw e;
210
- }
211
- }
200
+ const result = await acquireWriteRelease(true);
201
+ return { ...result, waitedMs: Date.now() - start };
212
202
  },
213
203
  });
214
204
  }
@@ -239,6 +239,10 @@ export function grantedOperations(
239
239
  */
240
240
  export const capabilityScopeSchema = z.object({
241
241
  organizationId: z.string().min(1),
242
+ /** Credential target. Branch id is authoritative; null supports self-hosted identities. */
243
+ projectId: z.string().min(1).nullable().default(null),
244
+ branchId: z.string().min(1).nullable().default(null),
245
+ branchRoot: z.boolean().default(false),
242
246
  /**
243
247
  * The ROW axis — which sync groups this credential may act within. Read back
244
248
  * as plain strings rather than the branded form the request enforces: this is