@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.
- package/dist/ai-sdk/index.d.ts +3 -1
- package/dist/ai-sdk/index.d.ts.map +1 -1
- package/dist/ai-sdk/index.js +2 -1
- package/dist/ai-sdk/index.js.map +1 -1
- package/dist/ai-sdk/modelTools.d.ts +67 -0
- package/dist/ai-sdk/modelTools.d.ts.map +1 -0
- package/dist/ai-sdk/modelTools.js +89 -0
- package/dist/ai-sdk/modelTools.js.map +1 -0
- package/dist/ai-sdk/toolOptions.d.ts +8 -0
- package/dist/ai-sdk/toolOptions.d.ts.map +1 -0
- package/dist/ai-sdk/toolOptions.js +2 -0
- package/dist/ai-sdk/toolOptions.js.map +1 -0
- package/dist/ai-sdk/{coordinatedTool.d.ts → updateTool.d.ts} +21 -28
- package/dist/ai-sdk/updateTool.d.ts.map +1 -0
- package/dist/ai-sdk/{coordinatedTool.js → updateTool.js} +39 -50
- package/dist/ai-sdk/updateTool.js.map +1 -0
- package/dist/auth/capability.d.ts +6 -0
- package/dist/auth/capability.d.ts.map +1 -1
- package/dist/auth/capability.js +4 -0
- package/dist/auth/capability.js.map +1 -1
- package/dist/auth/capabilityLifecycle.d.ts +3 -0
- package/dist/auth/capabilityLifecycle.d.ts.map +1 -1
- package/dist/auth/identity.d.ts +6 -4
- package/dist/auth/identity.d.ts.map +1 -1
- package/dist/auth/identity.js +7 -11
- package/dist/auth/identity.js.map +1 -1
- package/dist/auth/index.d.ts +16 -2
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +10 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/schemas.d.ts +5 -5
- package/dist/auth/schemas.d.ts.map +1 -1
- package/dist/auth/schemas.js +5 -2
- package/dist/auth/schemas.js.map +1 -1
- package/dist/auth/sessionMint.d.ts.map +1 -1
- package/dist/auth/sessionMint.js +3 -0
- package/dist/auth/sessionMint.js.map +1 -1
- package/dist/branches.d.ts +251 -0
- package/dist/branches.d.ts.map +1 -0
- package/dist/branches.js +108 -0
- package/dist/branches.js.map +1 -0
- package/dist/coordination/awaitClaimGrant.d.ts +2 -0
- package/dist/coordination/awaitClaimGrant.d.ts.map +1 -1
- package/dist/coordination/awaitClaimGrant.js +15 -2
- package/dist/coordination/awaitClaimGrant.js.map +1 -1
- package/dist/coordination/schema.d.ts +2 -0
- package/dist/coordination/schema.d.ts.map +1 -1
- package/dist/coordination/schema.js +2 -0
- package/dist/coordination/schema.js.map +1 -1
- package/dist/docs/catalog.d.ts +5 -5
- package/dist/docs/catalog.d.ts.map +1 -1
- package/dist/docs/catalog.js +12 -12
- package/dist/docs/catalog.js.map +1 -1
- package/dist/errorCodes.d.ts +1 -0
- package/dist/errorCodes.d.ts.map +1 -1
- package/dist/errorCodes.js +1 -0
- package/dist/errorCodes.js.map +1 -1
- package/dist/footprint.d.ts +3 -5
- package/dist/footprint.d.ts.map +1 -1
- package/dist/footprint.js +0 -0
- package/dist/footprint.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/keys/index.d.ts +15 -7
- package/dist/keys/index.d.ts.map +1 -1
- package/dist/keys/index.js +45 -14
- package/dist/keys/index.js.map +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +1 -1
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/openapi.d.ts +1 -1
- package/dist/schema/openapi.d.ts.map +1 -1
- package/dist/schema/openapi.js +308 -29
- package/dist/schema/openapi.js.map +1 -1
- package/dist/schema/schema.d.ts +12 -0
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/select.d.ts +13 -0
- package/dist/schema/select.d.ts.map +1 -1
- package/dist/schema/select.js +26 -0
- package/dist/schema/select.js.map +1 -1
- package/dist/server/commit.d.ts +2 -15
- package/dist/server/commit.d.ts.map +1 -1
- package/dist/source/adapter.d.ts +7 -2
- package/dist/source/adapter.d.ts.map +1 -1
- package/dist/source/adapter.js +4 -2
- package/dist/source/adapter.js.map +1 -1
- package/dist/source/adapterFactory.d.ts +10 -0
- package/dist/source/adapterFactory.d.ts.map +1 -0
- package/dist/source/adapterFactory.js +33 -0
- package/dist/source/adapterFactory.js.map +1 -0
- package/dist/source/adapterProfile.d.ts +55 -0
- package/dist/source/adapterProfile.d.ts.map +1 -0
- package/dist/source/adapterProfile.js +54 -0
- package/dist/source/adapterProfile.js.map +1 -0
- package/dist/source/adapters/drizzle.d.ts.map +1 -1
- package/dist/source/adapters/drizzle.js +5 -2
- package/dist/source/adapters/drizzle.js.map +1 -1
- package/dist/source/adapters/kysely.d.ts.map +1 -1
- package/dist/source/adapters/kysely.js +7 -4
- package/dist/source/adapters/kysely.js.map +1 -1
- package/dist/source/adapters/memory.d.ts.map +1 -1
- package/dist/source/adapters/memory.js +5 -2
- package/dist/source/adapters/memory.js.map +1 -1
- package/dist/source/adapters/prisma.d.ts.map +1 -1
- package/dist/source/adapters/prisma.js +5 -2
- package/dist/source/adapters/prisma.js.map +1 -1
- package/dist/source/conformance.d.ts.map +1 -1
- package/dist/source/conformance.js +18 -0
- package/dist/source/conformance.js.map +1 -1
- package/dist/source/index.d.ts +2 -0
- package/dist/source/index.d.ts.map +1 -1
- package/dist/source/index.js +2 -0
- package/dist/source/index.js.map +1 -1
- package/dist/source/types.d.ts +3 -14
- package/dist/source/types.d.ts.map +1 -1
- package/dist/source/types.js.map +1 -1
- package/dist/syncLog/contract.d.ts +1 -1
- package/dist/syncLog/contract.d.ts.map +1 -1
- package/dist/syncLog/contract.js +1 -2
- package/dist/syncLog/contract.js.map +1 -1
- package/dist/transport/httpClient.d.ts.map +1 -1
- package/dist/transport/httpClient.js +10 -1
- package/dist/transport/httpClient.js.map +1 -1
- package/dist/wire/accountResponses.d.ts +5 -9
- package/dist/wire/accountResponses.d.ts.map +1 -1
- package/dist/wire/accountResponses.js +5 -6
- package/dist/wire/accountResponses.js.map +1 -1
- package/dist/wire/auth.d.ts +7 -1
- package/dist/wire/auth.d.ts.map +1 -1
- package/dist/wire/auth.js +26 -3
- package/dist/wire/auth.js.map +1 -1
- package/dist/wire/delta.d.ts +11 -0
- package/dist/wire/delta.d.ts.map +1 -1
- package/dist/wire/delta.js +11 -0
- package/dist/wire/delta.js.map +1 -1
- package/dist/wire/inboundFrames.d.ts +2 -0
- package/dist/wire/inboundFrames.d.ts.map +1 -1
- package/package.json +8 -2
- package/src/ai-sdk/index.ts +19 -6
- package/src/ai-sdk/modelTools.ts +165 -0
- package/src/ai-sdk/toolOptions.ts +18 -0
- package/src/ai-sdk/{coordinatedTool.ts → updateTool.ts} +59 -69
- package/src/auth/capability.ts +4 -0
- package/src/auth/identity.ts +16 -16
- package/src/auth/index.ts +31 -3
- package/src/auth/schemas.ts +5 -2
- package/src/auth/sessionMint.ts +3 -0
- package/src/branches.ts +134 -0
- package/src/coordination/awaitClaimGrant.ts +18 -2
- package/src/coordination/schema.ts +2 -0
- package/src/docs/catalog.ts +24 -12
- package/src/errorCodes.ts +4 -0
- package/src/footprint.ts +0 -0
- package/src/index.ts +1 -0
- package/src/keys/index.ts +56 -17
- package/src/schema/index.ts +1 -1
- package/src/schema/openapi.ts +366 -38
- package/src/schema/schema.ts +13 -0
- package/src/schema/select.ts +30 -0
- package/src/server/commit.ts +2 -15
- package/src/source/adapter.ts +7 -2
- package/src/source/adapterFactory.ts +60 -0
- package/src/source/adapterProfile.ts +75 -0
- package/src/source/adapters/drizzle.ts +5 -2
- package/src/source/adapters/kysely.ts +10 -4
- package/src/source/adapters/memory.ts +5 -2
- package/src/source/adapters/prisma.ts +5 -2
- package/src/source/conformance.ts +18 -0
- package/src/source/index.ts +14 -0
- package/src/source/types.ts +3 -14
- package/src/syncLog/contract.ts +1 -2
- package/src/transport/httpClient.ts +8 -1
- package/src/wire/accountResponses.ts +5 -6
- package/src/wire/auth.ts +30 -3
- package/src/wire/delta.ts +11 -0
- package/dist/ai-sdk/coordinatedTool.d.ts.map +0 -1
- 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
|
-
/**
|
|
48
|
-
|
|
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
|
package/dist/wire/auth.js.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/wire/delta.d.ts
CHANGED
|
@@ -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>;
|
package/dist/wire/delta.d.ts.map
CHANGED
|
@@ -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
|
|
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"}
|
package/dist/wire/delta.js
CHANGED
|
@@ -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()])
|
package/dist/wire/delta.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delta.js","sourceRoot":"","sources":["../../src/wire/delta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAIlE,iFAAiF;AAEjF;;yCAEyC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,2EAA2E;AAC3E,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC5C,MAAM;IACN,WAAW;IACX,UAAU;IACV,yBAAyB;IACzB,iBAAiB;CAClB,CAAC,CAAC;AAGH,iFAAiF;AAEjF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAGtF
|
|
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
|
|
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.
|
|
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",
|
package/src/ai-sdk/index.ts
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
export {
|
|
2
|
-
|
|
3
|
-
type
|
|
4
|
-
type
|
|
5
|
-
type
|
|
6
|
-
type
|
|
7
|
-
} from './
|
|
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
|
|
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 {
|
|
14
|
+
* import { updateTool } from '@abloatai/ablo/ai-sdk';
|
|
15
15
|
* import { z } from 'zod';
|
|
16
16
|
*
|
|
17
|
-
* const saveSection =
|
|
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
|
|
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'`
|
|
56
|
-
* the
|
|
57
|
-
*
|
|
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
|
|
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
|
|
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'
|
|
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
|
|
82
|
+
/** On `'written'` via the `queue` strategy, how long the tool waited. */
|
|
87
83
|
waitedMs?: number;
|
|
88
84
|
}
|
|
89
85
|
|
|
90
|
-
export interface
|
|
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?:
|
|
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
|
|
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
|
|
128
|
+
export function updateTool<
|
|
136
129
|
TInput,
|
|
137
130
|
T = Record<string, unknown>,
|
|
138
|
-
>(model:
|
|
131
|
+
>(model: UpdateToolModel<T>, options: UpdateToolOptions<TInput, T>) {
|
|
139
132
|
const strategy = options.strategy ?? 'merge';
|
|
140
133
|
|
|
141
|
-
return tool<TInput,
|
|
134
|
+
return tool<TInput, UpdateToolResult<T>>({
|
|
142
135
|
description: options.description,
|
|
136
|
+
title: options.title,
|
|
143
137
|
inputSchema: options.inputSchema,
|
|
144
|
-
|
|
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
|
|
160
|
-
//
|
|
161
|
-
const acquireWriteRelease = async (
|
|
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
|
|
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 =
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
198
|
-
|
|
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
|
}
|
package/src/auth/capability.ts
CHANGED
|
@@ -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
|