@abloatai/ablo 0.27.0 → 0.28.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/CHANGELOG.md +29 -3
- package/README.md +1 -1
- package/dist/BaseSyncedStore.js +8 -9
- package/dist/Database.d.ts +14 -1
- package/dist/Database.js +225 -28
- package/dist/Model.d.ts +17 -0
- package/dist/Model.js +32 -1
- package/dist/SyncClient.d.ts +10 -6
- package/dist/SyncClient.js +379 -76
- package/dist/adapters/inMemoryStorage.d.ts +1 -0
- package/dist/adapters/inMemoryStorage.js +12 -0
- package/dist/cli.cjs +6 -2
- package/dist/client/Ablo.d.ts +24 -1
- package/dist/client/Ablo.js +4 -3
- package/dist/client/ApiClient.js +309 -43
- package/dist/client/createInternalComponents.d.ts +2 -0
- package/dist/client/createInternalComponents.js +1 -1
- package/dist/client/httpClient.d.ts +2 -0
- package/dist/client/modelRegistration.js +11 -0
- package/dist/client/options.d.ts +23 -0
- package/dist/client/wsMutationExecutor.d.ts +3 -2
- package/dist/client/wsMutationExecutor.js +3 -2
- package/dist/commit/contract.d.ts +493 -0
- package/dist/commit/contract.js +187 -0
- package/dist/commit/index.d.ts +6 -0
- package/dist/commit/index.js +5 -0
- package/dist/core/StoreManager.d.ts +2 -0
- package/dist/core/StoreManager.js +12 -0
- package/dist/errorCodes.js +6 -2
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2 -0
- package/dist/interfaces/index.d.ts +2 -2
- package/dist/mutators/UndoManager.d.ts +2 -0
- package/dist/mutators/UndoManager.js +32 -0
- package/dist/react/useAblo.d.ts +6 -4
- package/dist/react/useAblo.js +25 -3
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/schema.d.ts +31 -1
- package/dist/stores/ObjectStore.d.ts +14 -1
- package/dist/stores/ObjectStore.js +27 -4
- package/dist/stores/ObjectStoreContract.d.ts +2 -0
- package/dist/surface.d.ts +1 -1
- package/dist/surface.js +2 -0
- package/dist/sync/SyncWebSocket.d.ts +2 -1
- package/dist/sync/persistedPrefix.d.ts +12 -0
- package/dist/sync/persistedPrefix.js +22 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +1 -0
- package/dist/testing/mocks/FakeDatabase.d.ts +18 -0
- package/dist/testing/mocks/FakeDatabase.js +10 -0
- package/dist/testing/mocks/MockWebSocket.d.ts +2 -1
- package/dist/transactions/TransactionQueue.d.ts +66 -8
- package/dist/transactions/TransactionQueue.js +607 -89
- package/dist/transactions/commitEnvelope.d.ts +132 -0
- package/dist/transactions/commitEnvelope.js +139 -0
- package/dist/transactions/commitOutboxStore.d.ts +32 -0
- package/dist/transactions/commitOutboxStore.js +26 -0
- package/dist/transactions/commitPayload.d.ts +15 -0
- package/dist/transactions/commitPayload.js +6 -0
- package/dist/transactions/httpCommitEnvelope.d.ts +43 -0
- package/dist/transactions/httpCommitEnvelope.js +179 -0
- package/dist/transactions/replayValidation.d.ts +83 -0
- package/dist/transactions/replayValidation.js +46 -1
- package/dist/wire/bootstrapReason.d.ts +9 -0
- package/dist/wire/bootstrapReason.js +8 -0
- package/dist/wire/frames.d.ts +236 -0
- package/dist/wire/frames.js +21 -0
- package/dist/wire/index.d.ts +4 -2
- package/dist/wire/index.js +2 -1
- package/docs/api.md +10 -10
- package/docs/coordination.md +2 -2
- package/docs/mcp.md +1 -1
- package/package.json +7 -2
|
@@ -45,6 +45,14 @@ export declare const persistedTransactionSchema: z.ZodObject<{
|
|
|
45
45
|
}, z.core.$strip>;
|
|
46
46
|
createdAt: z.ZodOptional<z.ZodNumber>;
|
|
47
47
|
batchId: z.ZodOptional<z.ZodString>;
|
|
48
|
+
commitEnvelope: z.ZodOptional<z.ZodObject<{
|
|
49
|
+
idempotencyKey: z.core.$ZodBranded<z.ZodString, "IdempotencyKey", "out">;
|
|
50
|
+
operationIndex: z.ZodNumber;
|
|
51
|
+
operationCount: z.ZodNumber;
|
|
52
|
+
sealedAt: z.ZodOptional<z.ZodNumber>;
|
|
53
|
+
sequence: z.ZodOptional<z.ZodNumber>;
|
|
54
|
+
}, z.core.$strict>>;
|
|
55
|
+
sourceMutationIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
48
56
|
writeOptions: z.ZodOptional<z.ZodObject<{
|
|
49
57
|
readAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
50
58
|
onStale: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
@@ -76,6 +84,7 @@ export declare function deserializePersistedTransaction(row: unknown): Transacti
|
|
|
76
84
|
* queue is restored on reconnect.
|
|
77
85
|
*/
|
|
78
86
|
export declare const persistedMutationSchema: z.ZodObject<{
|
|
87
|
+
mutationId: z.ZodOptional<z.ZodString>;
|
|
79
88
|
type: z.ZodEnum<{
|
|
80
89
|
update: "update";
|
|
81
90
|
create: "create";
|
|
@@ -85,6 +94,7 @@ export declare const persistedMutationSchema: z.ZodObject<{
|
|
|
85
94
|
modelData: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
86
95
|
modelName: z.ZodString;
|
|
87
96
|
timestamp: z.ZodString;
|
|
97
|
+
capturedChanges: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
88
98
|
writeOptions: z.ZodOptional<z.ZodObject<{
|
|
89
99
|
readAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
90
100
|
onStale: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
@@ -97,3 +107,76 @@ export declare const persistedMutationSchema: z.ZodObject<{
|
|
|
97
107
|
}, z.core.$loose>>;
|
|
98
108
|
}, z.core.$loose>;
|
|
99
109
|
export type PersistedQueuedMutation = z.infer<typeof persistedMutationSchema>;
|
|
110
|
+
export declare const PENDING_MUTATION_RECORD_PREFIX = "pending-mutation:";
|
|
111
|
+
/**
|
|
112
|
+
* Stay one hour inside the server's 24-hour idempotency retention window.
|
|
113
|
+
* A journaled write older than this can no longer be deduplicated by the
|
|
114
|
+
* server, so restore holds it for review instead of replaying it.
|
|
115
|
+
*/
|
|
116
|
+
export declare const PENDING_MUTATION_REPLAY_WINDOW_MS: number;
|
|
117
|
+
/** Scope-less records written by the first aggregate-journal release. */
|
|
118
|
+
export declare const legacyPendingMutationRecordSchema: z.ZodObject<{
|
|
119
|
+
storageVersion: z.ZodLiteral<1>;
|
|
120
|
+
id: z.ZodString;
|
|
121
|
+
type: z.ZodLiteral<"pending_mutation">;
|
|
122
|
+
mutation: z.ZodObject<{
|
|
123
|
+
type: z.ZodEnum<{
|
|
124
|
+
update: "update";
|
|
125
|
+
create: "create";
|
|
126
|
+
delete: "delete";
|
|
127
|
+
archive: "archive";
|
|
128
|
+
}>;
|
|
129
|
+
modelData: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
130
|
+
modelName: z.ZodString;
|
|
131
|
+
timestamp: z.ZodString;
|
|
132
|
+
capturedChanges: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
133
|
+
writeOptions: z.ZodOptional<z.ZodObject<{
|
|
134
|
+
readAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
135
|
+
onStale: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
136
|
+
reject: "reject";
|
|
137
|
+
overwrite: "overwrite";
|
|
138
|
+
notify: "notify";
|
|
139
|
+
}>>>;
|
|
140
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
141
|
+
label: z.ZodOptional<z.ZodString>;
|
|
142
|
+
}, z.core.$loose>>;
|
|
143
|
+
mutationId: z.ZodString;
|
|
144
|
+
}, z.core.$loose>;
|
|
145
|
+
timestamp: z.ZodNumber;
|
|
146
|
+
}, z.core.$strict>;
|
|
147
|
+
export declare const pendingMutationRecordSchema: z.ZodObject<{
|
|
148
|
+
storageVersion: z.ZodLiteral<2>;
|
|
149
|
+
scope: z.ZodObject<{
|
|
150
|
+
organizationId: z.ZodString;
|
|
151
|
+
participantId: z.ZodString;
|
|
152
|
+
namespace: z.ZodString;
|
|
153
|
+
}, z.core.$strict>;
|
|
154
|
+
id: z.ZodString;
|
|
155
|
+
type: z.ZodLiteral<"pending_mutation">;
|
|
156
|
+
mutation: z.ZodObject<{
|
|
157
|
+
type: z.ZodEnum<{
|
|
158
|
+
update: "update";
|
|
159
|
+
create: "create";
|
|
160
|
+
delete: "delete";
|
|
161
|
+
archive: "archive";
|
|
162
|
+
}>;
|
|
163
|
+
modelData: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
164
|
+
modelName: z.ZodString;
|
|
165
|
+
timestamp: z.ZodString;
|
|
166
|
+
capturedChanges: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
167
|
+
writeOptions: z.ZodOptional<z.ZodObject<{
|
|
168
|
+
readAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
169
|
+
onStale: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
170
|
+
reject: "reject";
|
|
171
|
+
overwrite: "overwrite";
|
|
172
|
+
notify: "notify";
|
|
173
|
+
}>>>;
|
|
174
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
175
|
+
label: z.ZodOptional<z.ZodString>;
|
|
176
|
+
}, z.core.$loose>>;
|
|
177
|
+
mutationId: z.ZodString;
|
|
178
|
+
}, z.core.$loose>;
|
|
179
|
+
timestamp: z.ZodNumber;
|
|
180
|
+
}, z.core.$strict>;
|
|
181
|
+
export type PendingMutationRecord = z.infer<typeof pendingMutationRecordSchema>;
|
|
182
|
+
export declare function pendingMutationRecordId(mutationId: string): string;
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { z } from 'zod';
|
|
18
18
|
import { computePriorityScore, normalizeModelKey } from './commitPayload.js';
|
|
19
|
+
import { commitEnvelopeMemberSchema, commitOutboxScopeSchema, } from './commitEnvelope.js';
|
|
19
20
|
/** The subset of a write's options that is stored with each transaction or queued mutation. */
|
|
20
21
|
const persistedWriteOptionsSchema = z
|
|
21
22
|
.object({
|
|
@@ -49,12 +50,20 @@ export const persistedTransactionSchema = z
|
|
|
49
50
|
}),
|
|
50
51
|
createdAt: z.number().optional(),
|
|
51
52
|
batchId: z.string().optional(),
|
|
53
|
+
commitEnvelope: commitEnvelopeMemberSchema.optional(),
|
|
54
|
+
sourceMutationIds: z.array(z.string().min(1)).optional(),
|
|
52
55
|
writeOptions: persistedWriteOptionsSchema.optional(),
|
|
53
56
|
localOnly: z.boolean().optional(),
|
|
54
57
|
})
|
|
55
58
|
.loose();
|
|
56
59
|
/** The `type` values of stored rows that belong to other parts of the client and are not replayable transactions. */
|
|
57
|
-
const NON_REPLAYABLE_TYPES = new Set([
|
|
60
|
+
const NON_REPLAYABLE_TYPES = new Set([
|
|
61
|
+
'queue',
|
|
62
|
+
'awaiting_delta',
|
|
63
|
+
'pending_mutation',
|
|
64
|
+
'commit_envelope',
|
|
65
|
+
'http_commit_envelope',
|
|
66
|
+
]);
|
|
58
67
|
/**
|
|
59
68
|
* Reports whether a stored row is one of the non-transaction kinds, so callers
|
|
60
69
|
* skip it instead of treating it as a corrupt transaction.
|
|
@@ -91,6 +100,12 @@ export function deserializePersistedTransaction(row) {
|
|
|
91
100
|
priority: 'normal',
|
|
92
101
|
priorityScore: computePriorityScore(tx.type, tx.modelName),
|
|
93
102
|
...(tx.batchId !== undefined ? { batchId: tx.batchId } : {}),
|
|
103
|
+
...(tx.commitEnvelope !== undefined
|
|
104
|
+
? { commitEnvelope: tx.commitEnvelope }
|
|
105
|
+
: {}),
|
|
106
|
+
...(tx.sourceMutationIds !== undefined
|
|
107
|
+
? { sourceMutationIds: tx.sourceMutationIds }
|
|
108
|
+
: {}),
|
|
94
109
|
...(tx.writeOptions !== undefined ? { writeOptions: tx.writeOptions } : {}),
|
|
95
110
|
...(tx.localOnly !== undefined ? { localOnly: tx.localOnly } : {}),
|
|
96
111
|
};
|
|
@@ -102,10 +117,40 @@ export function deserializePersistedTransaction(row) {
|
|
|
102
117
|
*/
|
|
103
118
|
export const persistedMutationSchema = z
|
|
104
119
|
.object({
|
|
120
|
+
mutationId: z.string().min(1).optional(),
|
|
105
121
|
type: z.enum(['create', 'update', 'delete', 'archive']),
|
|
106
122
|
modelData: z.record(z.string(), z.unknown()),
|
|
107
123
|
modelName: z.string().min(1),
|
|
108
124
|
timestamp: z.string(),
|
|
125
|
+
capturedChanges: z.record(z.string(), z.unknown()).optional(),
|
|
109
126
|
writeOptions: persistedWriteOptionsSchema.optional(),
|
|
110
127
|
})
|
|
111
128
|
.loose();
|
|
129
|
+
export const PENDING_MUTATION_RECORD_PREFIX = 'pending-mutation:';
|
|
130
|
+
/**
|
|
131
|
+
* Stay one hour inside the server's 24-hour idempotency retention window.
|
|
132
|
+
* A journaled write older than this can no longer be deduplicated by the
|
|
133
|
+
* server, so restore holds it for review instead of replaying it.
|
|
134
|
+
*/
|
|
135
|
+
export const PENDING_MUTATION_REPLAY_WINDOW_MS = 23 * 60 * 60 * 1000;
|
|
136
|
+
const pendingMutationRecordBaseShape = {
|
|
137
|
+
id: z.string().startsWith(PENDING_MUTATION_RECORD_PREFIX),
|
|
138
|
+
type: z.literal('pending_mutation'),
|
|
139
|
+
mutation: persistedMutationSchema.extend({
|
|
140
|
+
mutationId: z.string().min(1),
|
|
141
|
+
}),
|
|
142
|
+
timestamp: z.number().int().nonnegative(),
|
|
143
|
+
};
|
|
144
|
+
/** Scope-less records written by the first aggregate-journal release. */
|
|
145
|
+
export const legacyPendingMutationRecordSchema = z.strictObject({
|
|
146
|
+
...pendingMutationRecordBaseShape,
|
|
147
|
+
storageVersion: z.literal(1),
|
|
148
|
+
});
|
|
149
|
+
export const pendingMutationRecordSchema = z.strictObject({
|
|
150
|
+
...pendingMutationRecordBaseShape,
|
|
151
|
+
storageVersion: z.literal(2),
|
|
152
|
+
scope: commitOutboxScopeSchema,
|
|
153
|
+
});
|
|
154
|
+
export function pendingMutationRecordId(mutationId) {
|
|
155
|
+
return `${PENDING_MUTATION_RECORD_PREFIX}${mutationId}`;
|
|
156
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** Machine-readable reasons a live delta stream must resume via catch-up. */
|
|
3
|
+
export declare const bootstrapReasonSchema: z.ZodEnum<{
|
|
4
|
+
too_far_behind: "too_far_behind";
|
|
5
|
+
too_many_deltas: "too_many_deltas";
|
|
6
|
+
missing_entities: "missing_entities";
|
|
7
|
+
stream_gap: "stream_gap";
|
|
8
|
+
}>;
|
|
9
|
+
export type BootstrapReason = z.infer<typeof bootstrapReasonSchema>;
|
package/dist/wire/frames.d.ts
CHANGED
|
@@ -222,3 +222,239 @@ export interface MutationResultMessage {
|
|
|
222
222
|
};
|
|
223
223
|
};
|
|
224
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* A transport frame carrying the Zod-first v2 commit request. The payload's
|
|
227
|
+
* `schemaVersion` distinguishes it from the legacy `commit` payload during the
|
|
228
|
+
* migration window; the transport does not duplicate the commit contract.
|
|
229
|
+
*/
|
|
230
|
+
export declare const commitRequestMessageSchema: z.ZodObject<{
|
|
231
|
+
type: z.ZodLiteral<"commit">;
|
|
232
|
+
payload: z.ZodObject<{
|
|
233
|
+
idempotencyKey: z.core.$ZodBranded<z.ZodString, "IdempotencyKey", "out">;
|
|
234
|
+
schemaVersion: z.ZodLiteral<2>;
|
|
235
|
+
operations: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
236
|
+
type: z.ZodLiteral<"create">;
|
|
237
|
+
value: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
|
|
238
|
+
operationId: z.core.$ZodBranded<z.ZodString, "OperationId", "out">;
|
|
239
|
+
target: z.ZodObject<{
|
|
240
|
+
model: z.ZodString;
|
|
241
|
+
id: z.ZodString;
|
|
242
|
+
}, z.core.$strict>;
|
|
243
|
+
preconditions: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
244
|
+
type: z.ZodLiteral<"unchanged_since">;
|
|
245
|
+
cursor: z.core.$ZodBranded<z.ZodString, "SyncOffset", "out">;
|
|
246
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
247
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
248
|
+
type: z.ZodLiteral<"version_matches">;
|
|
249
|
+
version: z.ZodNumber;
|
|
250
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
251
|
+
type: z.ZodLiteral<"claim_fence">;
|
|
252
|
+
claimId: z.core.$ZodBranded<z.ZodString, "ClaimId", "out">;
|
|
253
|
+
generation: z.ZodNumber;
|
|
254
|
+
}, z.core.$strict>], "type">>>;
|
|
255
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
256
|
+
type: z.ZodLiteral<"patch">;
|
|
257
|
+
changes: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
|
|
258
|
+
operationId: z.core.$ZodBranded<z.ZodString, "OperationId", "out">;
|
|
259
|
+
target: z.ZodObject<{
|
|
260
|
+
model: z.ZodString;
|
|
261
|
+
id: z.ZodString;
|
|
262
|
+
}, z.core.$strict>;
|
|
263
|
+
preconditions: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
264
|
+
type: z.ZodLiteral<"unchanged_since">;
|
|
265
|
+
cursor: z.core.$ZodBranded<z.ZodString, "SyncOffset", "out">;
|
|
266
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
267
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
268
|
+
type: z.ZodLiteral<"version_matches">;
|
|
269
|
+
version: z.ZodNumber;
|
|
270
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
271
|
+
type: z.ZodLiteral<"claim_fence">;
|
|
272
|
+
claimId: z.core.$ZodBranded<z.ZodString, "ClaimId", "out">;
|
|
273
|
+
generation: z.ZodNumber;
|
|
274
|
+
}, z.core.$strict>], "type">>>;
|
|
275
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
276
|
+
type: z.ZodLiteral<"delete">;
|
|
277
|
+
operationId: z.core.$ZodBranded<z.ZodString, "OperationId", "out">;
|
|
278
|
+
target: z.ZodObject<{
|
|
279
|
+
model: z.ZodString;
|
|
280
|
+
id: z.ZodString;
|
|
281
|
+
}, z.core.$strict>;
|
|
282
|
+
preconditions: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
283
|
+
type: z.ZodLiteral<"unchanged_since">;
|
|
284
|
+
cursor: z.core.$ZodBranded<z.ZodString, "SyncOffset", "out">;
|
|
285
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
286
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
287
|
+
type: z.ZodLiteral<"version_matches">;
|
|
288
|
+
version: z.ZodNumber;
|
|
289
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
290
|
+
type: z.ZodLiteral<"claim_fence">;
|
|
291
|
+
claimId: z.core.$ZodBranded<z.ZodString, "ClaimId", "out">;
|
|
292
|
+
generation: z.ZodNumber;
|
|
293
|
+
}, z.core.$strict>], "type">>>;
|
|
294
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
295
|
+
type: z.ZodLiteral<"archive">;
|
|
296
|
+
operationId: z.core.$ZodBranded<z.ZodString, "OperationId", "out">;
|
|
297
|
+
target: z.ZodObject<{
|
|
298
|
+
model: z.ZodString;
|
|
299
|
+
id: z.ZodString;
|
|
300
|
+
}, z.core.$strict>;
|
|
301
|
+
preconditions: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
302
|
+
type: z.ZodLiteral<"unchanged_since">;
|
|
303
|
+
cursor: z.core.$ZodBranded<z.ZodString, "SyncOffset", "out">;
|
|
304
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
305
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
306
|
+
type: z.ZodLiteral<"version_matches">;
|
|
307
|
+
version: z.ZodNumber;
|
|
308
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
309
|
+
type: z.ZodLiteral<"claim_fence">;
|
|
310
|
+
claimId: z.core.$ZodBranded<z.ZodString, "ClaimId", "out">;
|
|
311
|
+
generation: z.ZodNumber;
|
|
312
|
+
}, z.core.$strict>], "type">>>;
|
|
313
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
314
|
+
type: z.ZodLiteral<"unarchive">;
|
|
315
|
+
operationId: z.core.$ZodBranded<z.ZodString, "OperationId", "out">;
|
|
316
|
+
target: z.ZodObject<{
|
|
317
|
+
model: z.ZodString;
|
|
318
|
+
id: z.ZodString;
|
|
319
|
+
}, z.core.$strict>;
|
|
320
|
+
preconditions: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
321
|
+
type: z.ZodLiteral<"unchanged_since">;
|
|
322
|
+
cursor: z.core.$ZodBranded<z.ZodString, "SyncOffset", "out">;
|
|
323
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
324
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
325
|
+
type: z.ZodLiteral<"version_matches">;
|
|
326
|
+
version: z.ZodNumber;
|
|
327
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
328
|
+
type: z.ZodLiteral<"claim_fence">;
|
|
329
|
+
claimId: z.core.$ZodBranded<z.ZodString, "ClaimId", "out">;
|
|
330
|
+
generation: z.ZodNumber;
|
|
331
|
+
}, z.core.$strict>], "type">>>;
|
|
332
|
+
}, z.core.$strict>], "type">>;
|
|
333
|
+
metadata: z.ZodOptional<z.ZodObject<{
|
|
334
|
+
label: z.ZodOptional<z.ZodString>;
|
|
335
|
+
causedByTaskId: z.ZodOptional<z.ZodString>;
|
|
336
|
+
}, z.core.$strict>>;
|
|
337
|
+
}, z.core.$strict>;
|
|
338
|
+
}, z.core.$strict>;
|
|
339
|
+
export type CommitRequestMessage = z.output<typeof commitRequestMessageSchema>;
|
|
340
|
+
/** A transport frame carrying one terminal, status-discriminated v2 receipt. */
|
|
341
|
+
export declare const commitResultMessageSchema: z.ZodObject<{
|
|
342
|
+
type: z.ZodLiteral<"commit_result">;
|
|
343
|
+
payload: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
344
|
+
status: z.ZodLiteral<"committed">;
|
|
345
|
+
syncCursor: z.core.$ZodBranded<z.ZodString, "SyncCursor", "out">;
|
|
346
|
+
operationCount: z.ZodNumber;
|
|
347
|
+
object: z.ZodLiteral<"commit_receipt">;
|
|
348
|
+
schemaVersion: z.ZodLiteral<2>;
|
|
349
|
+
idempotencyKey: z.core.$ZodBranded<z.ZodString, "IdempotencyKey", "out">;
|
|
350
|
+
commitId: z.core.$ZodBranded<z.ZodUUID, "CommitId", "out">;
|
|
351
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
352
|
+
status: z.ZodLiteral<"conflicted">;
|
|
353
|
+
syncCursor: z.core.$ZodBranded<z.ZodString, "SyncCursor", "out">;
|
|
354
|
+
conflicts: z.ZodArray<z.ZodObject<{
|
|
355
|
+
operationId: z.core.$ZodBranded<z.ZodString, "OperationId", "out">;
|
|
356
|
+
target: z.ZodObject<{
|
|
357
|
+
model: z.ZodString;
|
|
358
|
+
id: z.ZodString;
|
|
359
|
+
}, z.core.$strict>;
|
|
360
|
+
fields: z.ZodArray<z.ZodString>;
|
|
361
|
+
currentValues: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
|
|
362
|
+
observedAt: z.core.$ZodBranded<z.ZodString, "SyncOffset", "out">;
|
|
363
|
+
}, z.core.$strict>>;
|
|
364
|
+
object: z.ZodLiteral<"commit_receipt">;
|
|
365
|
+
schemaVersion: z.ZodLiteral<2>;
|
|
366
|
+
idempotencyKey: z.core.$ZodBranded<z.ZodString, "IdempotencyKey", "out">;
|
|
367
|
+
commitId: z.core.$ZodBranded<z.ZodUUID, "CommitId", "out">;
|
|
368
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
369
|
+
status: z.ZodLiteral<"rejected">;
|
|
370
|
+
error: z.ZodObject<{
|
|
371
|
+
code: z.ZodUnion<readonly [z.ZodEnum<{}>, z.ZodCustom<`policy:${string}`, `policy:${string}`>]>;
|
|
372
|
+
message: z.ZodString;
|
|
373
|
+
field: z.ZodOptional<z.ZodString>;
|
|
374
|
+
requiredCapability: z.ZodOptional<z.ZodObject<{
|
|
375
|
+
scope: z.ZodString;
|
|
376
|
+
constraints: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
|
|
377
|
+
issuer: z.ZodOptional<z.ZodString>;
|
|
378
|
+
ttlSeconds: z.ZodOptional<z.ZodNumber>;
|
|
379
|
+
nonce: z.ZodOptional<z.ZodString>;
|
|
380
|
+
}, z.core.$strict>>;
|
|
381
|
+
details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>;
|
|
382
|
+
}, z.core.$strict>;
|
|
383
|
+
object: z.ZodLiteral<"commit_receipt">;
|
|
384
|
+
schemaVersion: z.ZodLiteral<2>;
|
|
385
|
+
idempotencyKey: z.core.$ZodBranded<z.ZodString, "IdempotencyKey", "out">;
|
|
386
|
+
commitId: z.core.$ZodBranded<z.ZodUUID, "CommitId", "out">;
|
|
387
|
+
}, z.core.$strict>], "status">;
|
|
388
|
+
}, z.core.$strict>;
|
|
389
|
+
export type CommitResultMessage = z.output<typeof commitResultMessageSchema>;
|
|
390
|
+
/** Explicit compatibility name for the v1 uppercase operation schema. */
|
|
391
|
+
export declare const legacyCommitOperationSchema: z.ZodObject<{
|
|
392
|
+
readAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
393
|
+
onStale: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
394
|
+
reject: "reject";
|
|
395
|
+
overwrite: "overwrite";
|
|
396
|
+
notify: "notify";
|
|
397
|
+
}>>>;
|
|
398
|
+
type: z.ZodEnum<{
|
|
399
|
+
CREATE: "CREATE";
|
|
400
|
+
UPDATE: "UPDATE";
|
|
401
|
+
DELETE: "DELETE";
|
|
402
|
+
ARCHIVE: "ARCHIVE";
|
|
403
|
+
UNARCHIVE: "UNARCHIVE";
|
|
404
|
+
}>;
|
|
405
|
+
model: z.ZodString;
|
|
406
|
+
id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
407
|
+
input: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
408
|
+
transactionId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
409
|
+
bypass: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
410
|
+
}, z.core.$strip>;
|
|
411
|
+
/** Explicit compatibility name for the v1 `clientTxId` payload schema. */
|
|
412
|
+
export declare const legacyCommitPayloadSchema: z.ZodObject<{
|
|
413
|
+
operations: z.ZodArray<z.ZodObject<{
|
|
414
|
+
readAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
415
|
+
onStale: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
416
|
+
reject: "reject";
|
|
417
|
+
overwrite: "overwrite";
|
|
418
|
+
notify: "notify";
|
|
419
|
+
}>>>;
|
|
420
|
+
type: z.ZodEnum<{
|
|
421
|
+
CREATE: "CREATE";
|
|
422
|
+
UPDATE: "UPDATE";
|
|
423
|
+
DELETE: "DELETE";
|
|
424
|
+
ARCHIVE: "ARCHIVE";
|
|
425
|
+
UNARCHIVE: "UNARCHIVE";
|
|
426
|
+
}>;
|
|
427
|
+
model: z.ZodString;
|
|
428
|
+
id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
429
|
+
input: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
430
|
+
transactionId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
431
|
+
bypass: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
432
|
+
}, z.core.$strip>>;
|
|
433
|
+
clientTxId: z.ZodString;
|
|
434
|
+
causedByTaskId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
435
|
+
reads: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
436
|
+
model: z.ZodString;
|
|
437
|
+
id: z.ZodString;
|
|
438
|
+
readAt: z.ZodNumber;
|
|
439
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
440
|
+
onStale: z.ZodOptional<z.ZodEnum<{
|
|
441
|
+
reject: "reject";
|
|
442
|
+
overwrite: "overwrite";
|
|
443
|
+
notify: "notify";
|
|
444
|
+
}>>;
|
|
445
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
446
|
+
group: z.ZodString;
|
|
447
|
+
readAt: z.ZodNumber;
|
|
448
|
+
onStale: z.ZodOptional<z.ZodEnum<{
|
|
449
|
+
reject: "reject";
|
|
450
|
+
overwrite: "overwrite";
|
|
451
|
+
notify: "notify";
|
|
452
|
+
}>>;
|
|
453
|
+
}, z.core.$strip>]>>>>;
|
|
454
|
+
}, z.core.$strip>;
|
|
455
|
+
/** Explicit compatibility alias for the v1 uppercase operation shape. */
|
|
456
|
+
export type LegacyCommitOperation = CommitOperation;
|
|
457
|
+
/** Explicit compatibility alias for the v1 `clientTxId` commit frame. */
|
|
458
|
+
export type LegacyCommitMessage = CommitMessage;
|
|
459
|
+
/** Explicit compatibility alias for the v1 boolean-style mutation receipt. */
|
|
460
|
+
export type LegacyMutationResultMessage = MutationResultMessage;
|
package/dist/wire/frames.js
CHANGED
|
@@ -16,6 +16,7 @@ import { z } from 'zod';
|
|
|
16
16
|
// The runtime schema primitives are imported straight from the coordination
|
|
17
17
|
// schema module to keep this file's runtime dependencies limited to Zod.
|
|
18
18
|
import { commitOperationSchema as coordinationCommitOperationSchema, readDependencySchema, } from '../coordination/schema.js';
|
|
19
|
+
import { commitReceiptSchema as commitReceiptV2Schema, commitRequestSchema as commitRequestV2Schema, } from '../commit/contract.js';
|
|
19
20
|
/**
|
|
20
21
|
* Runtime validator for {@link CommitOperation}. Both commit transports — the
|
|
21
22
|
* WebSocket `commit` frame and the HTTP `/v1/commits` endpoint — run this check
|
|
@@ -46,3 +47,23 @@ export const commitPayloadSchema = z.object({
|
|
|
46
47
|
// Pins the schema to the payload type: fails to compile if either side drifts.
|
|
47
48
|
const _commitPayloadContract = true;
|
|
48
49
|
void _commitPayloadContract;
|
|
50
|
+
// ── Commit contract v2 ───────────────────────────────────────────────────
|
|
51
|
+
/**
|
|
52
|
+
* A transport frame carrying the Zod-first v2 commit request. The payload's
|
|
53
|
+
* `schemaVersion` distinguishes it from the legacy `commit` payload during the
|
|
54
|
+
* migration window; the transport does not duplicate the commit contract.
|
|
55
|
+
*/
|
|
56
|
+
export const commitRequestMessageSchema = z.strictObject({
|
|
57
|
+
type: z.literal('commit'),
|
|
58
|
+
payload: commitRequestV2Schema,
|
|
59
|
+
});
|
|
60
|
+
/** A transport frame carrying one terminal, status-discriminated v2 receipt. */
|
|
61
|
+
export const commitResultMessageSchema = z.strictObject({
|
|
62
|
+
type: z.literal('commit_result'),
|
|
63
|
+
payload: commitReceiptV2Schema,
|
|
64
|
+
});
|
|
65
|
+
// ── Explicit v1 compatibility names ─────────────────────────────────────
|
|
66
|
+
/** Explicit compatibility name for the v1 uppercase operation schema. */
|
|
67
|
+
export const legacyCommitOperationSchema = commitOperationSchema;
|
|
68
|
+
/** Explicit compatibility name for the v1 `clientTxId` payload schema. */
|
|
69
|
+
export const legacyCommitPayloadSchema = commitPayloadSchema;
|
package/dist/wire/index.d.ts
CHANGED
|
@@ -19,9 +19,11 @@ export { errorEnvelope, statusForType } from './errorEnvelope.js';
|
|
|
19
19
|
export type { ErrorEnvelope } from './errorEnvelope.js';
|
|
20
20
|
export { listEnvelope } from './listEnvelope.js';
|
|
21
21
|
export type { ListEnvelope } from './listEnvelope.js';
|
|
22
|
-
export {
|
|
22
|
+
export { bootstrapReasonSchema } from './bootstrapReason.js';
|
|
23
|
+
export type { BootstrapReason } from './bootstrapReason.js';
|
|
24
|
+
export { commitOperationSchema, commitPayloadSchema, commitRequestMessageSchema, commitResultMessageSchema, legacyCommitOperationSchema, legacyCommitPayloadSchema, } from './frames.js';
|
|
23
25
|
export { PROTOCOL_VERSION, MIN_SUPPORTED_PROTOCOL_VERSION, WS_CLOSE_PROTOCOL_VERSION, PROTOCOL_VERSION_HEADER, protocolVersionProblem, } from './protocolVersion.js';
|
|
24
|
-
export type { CommitOperation, MutationMessage, CommitMessage, MutationResultMessage, } from './frames.js';
|
|
26
|
+
export type { CommitOperation, MutationMessage, CommitMessage, MutationResultMessage, CommitRequestMessage, CommitResultMessage, LegacyCommitOperation, LegacyCommitMessage, LegacyMutationResultMessage, } from './frames.js';
|
|
25
27
|
export { participantKindSchema, confirmationStateSchema, syncDeltaActionSchema, wireDeltaDataSchema, participantRefSchema, syncDeltaWireCoreSchema, clientSyncDeltaSchema, serverSyncDeltaSchema, } from './delta.js';
|
|
26
28
|
export type { ParticipantKind, ConfirmationState, SyncDeltaAction, WireDeltaData, ParticipantRef, SyncDeltaWireCore, ClientSyncDelta, ServerSyncDelta, } from './delta.js';
|
|
27
29
|
export { AbloError, AbloAuthenticationError, AbloPermissionError, AbloValidationError, AbloRateLimitError, AbloIdempotencyError, AbloConnectionError, AbloServerError, AbloStaleContextError, AbloClaimedError, CapabilityError, SyncSessionError, docUrlForCode, translateHttpError, errorFromWire, toAbloError, ERROR_CONTRACT_VERSION, errorCodeSpec, } from '../errors.js';
|
package/dist/wire/index.js
CHANGED
|
@@ -17,11 +17,12 @@
|
|
|
17
17
|
*/
|
|
18
18
|
export { errorEnvelope, statusForType } from './errorEnvelope.js';
|
|
19
19
|
export { listEnvelope } from './listEnvelope.js';
|
|
20
|
+
export { bootstrapReasonSchema } from './bootstrapReason.js';
|
|
20
21
|
// The write-path frame contract: the message shapes shared by the client and
|
|
21
22
|
// the server. The runtime Zod validators sit beside the interfaces and are
|
|
22
23
|
// pinned to them, and they gate every operation and payload on both commit
|
|
23
24
|
// transports.
|
|
24
|
-
export { commitOperationSchema, commitPayloadSchema } from './frames.js';
|
|
25
|
+
export { commitOperationSchema, commitPayloadSchema, commitRequestMessageSchema, commitResultMessageSchema, legacyCommitOperationSchema, legacyCommitPayloadSchema, } from './frames.js';
|
|
25
26
|
// Protocol versioning: the single integer the client and server compare to
|
|
26
27
|
// confirm they can speak to each other, plus the WebSocket close code used to
|
|
27
28
|
// reject a mismatch. See protocolVersion.ts for the changelog and deploy rules.
|
package/docs/api.md
CHANGED
|
@@ -206,27 +206,27 @@ The SDK is a convenience wrapper over a model-scoped HTTP surface — the same
|
|
|
206
206
|
noun (`model`) and verbs as `ablo.<model>.…`. Non-JS callers (or curl) use it
|
|
207
207
|
directly. The table below shows the shape with `{model}` as a placeholder; the
|
|
208
208
|
[OpenAPI spec](./openapi.json) expands it into one **typed** path per model
|
|
209
|
-
(`/v1/models/task`, `/v1/models/deck`, …, generated from your schema) so each
|
|
209
|
+
(`/api/v1/models/task`, `/api/v1/models/deck`, …, generated from your schema) so each
|
|
210
210
|
endpoint documents that model's real field contract instead of a generic blob.
|
|
211
211
|
|
|
212
212
|
| SDK call | HTTP |
|
|
213
213
|
|---|---|
|
|
214
|
-
| `ablo.<model>.create({ data })` | `POST /v1/models/{model}` |
|
|
215
|
-
| `ablo.<model>.list({ where })` | `GET /v1/models/{model}` |
|
|
216
|
-
| `ablo.<model>.retrieve({ id })` | `GET /v1/models/{model}/{id}` |
|
|
217
|
-
| `ablo.<model>.update({ id, data })` | `PATCH /v1/models/{model}/{id}` |
|
|
218
|
-
| `ablo.<model>.delete({ id })` | `DELETE /v1/models/{model}/{id}` |
|
|
219
|
-
| `ablo.<model>.claim({ id })` | `POST /v1/models/{model}/{id}/claim` |
|
|
220
|
-
| (release a claim) | `DELETE /v1/models/{model}/{id}/claim` |
|
|
214
|
+
| `ablo.<model>.create({ data })` | `POST /api/v1/models/{model}` |
|
|
215
|
+
| `ablo.<model>.list({ where })` | `GET /api/v1/models/{model}` |
|
|
216
|
+
| `ablo.<model>.retrieve({ id })` | `GET /api/v1/models/{model}/{id}` |
|
|
217
|
+
| `ablo.<model>.update({ id, data })` | `PATCH /api/v1/models/{model}/{id}` |
|
|
218
|
+
| `ablo.<model>.delete({ id })` | `DELETE /api/v1/models/{model}/{id}` |
|
|
219
|
+
| `ablo.<model>.claim({ id })` | `POST /api/v1/models/{model}/{id}/claim` |
|
|
220
|
+
| (release a claim) | `DELETE /api/v1/models/{model}/{id}/claim` |
|
|
221
221
|
|
|
222
222
|
Auth is a bearer API key: `Authorization: Bearer sk_…`. Mutations take an
|
|
223
223
|
`Idempotency-Key` header — derive it from the business event, not a random
|
|
224
224
|
value, so a retry never double-writes. Writes return a `CommitReceipt`; a
|
|
225
225
|
rejected write carries an error `code` (e.g. `stale_context`, `intent_conflict`)
|
|
226
|
-
to act on. `GET /v1/models/{model}` is cursor-paginated (`limit`, `order`,
|
|
226
|
+
to act on. `GET /api/v1/models/{model}` is cursor-paginated (`limit`, `order`,
|
|
227
227
|
`order_by`, `starting_after`) and returns `{ data, has_more, next_cursor }`.
|
|
228
228
|
|
|
229
|
-
`POST /v1/commits` remains the path for **atomic multi-op** writes (several
|
|
229
|
+
`POST /api/v1/commits` remains the path for **atomic multi-op** writes (several
|
|
230
230
|
operations across rows/models that must commit together) — the per-model routes
|
|
231
231
|
above are the one-record path. Both run the identical guarded-write engine.
|
|
232
232
|
|
package/docs/coordination.md
CHANGED
|
@@ -465,13 +465,13 @@ Each beat's answer carries two more things:
|
|
|
465
465
|
|
|
466
466
|
Works identically on both transports: the realtime client sends a
|
|
467
467
|
`claim_heartbeat` frame; the HTTP client posts
|
|
468
|
-
`POST /v1/models/{model}/{id}/claim/heartbeat` (`{ ttl?, claimId?, details? }`).
|
|
468
|
+
`POST /api/v1/models/{model}/{id}/claim/heartbeat` (`{ ttl?, claimId?, details? }`).
|
|
469
469
|
Over HTTP, a **queued** claim can heartbeat too — it refreshes the waiter's
|
|
470
470
|
slot in the line (a queued slot is TTL'd like a lease) and reports
|
|
471
471
|
`{ status: 'queued', position }`.
|
|
472
472
|
|
|
473
473
|
A stateless worker holding **many** rows beats them all in one round trip:
|
|
474
|
-
`ablo.claims.heartbeatAll({ ttl: '5m' })` → `POST /v1/claims/heartbeat`, one
|
|
474
|
+
`ablo.claims.heartbeatAll({ ttl: '5m' })` → `POST /api/v1/claims/heartbeat`, one
|
|
475
475
|
entry per extended lease. This is the socketless twin of the realtime
|
|
476
476
|
keepalive, which already renews every held lease on each ping.
|
|
477
477
|
|
package/docs/mcp.md
CHANGED
|
@@ -16,7 +16,7 @@ edits rows → coordination; teaching your IDE assistant the SDK → helper.
|
|
|
16
16
|
## Coordination server (`@ablo/mcp`)
|
|
17
17
|
|
|
18
18
|
The coordination server is the MCP projection of the model-scoped API
|
|
19
|
-
(`/v1/models/...`) — the same surface as `ablo.<model>.create/update/claim` and
|
|
19
|
+
(`/api/v1/models/...`) — the same surface as `ablo.<model>.create/update/claim` and
|
|
20
20
|
the REST routes, rendered as tools. An agent connects with your API key and
|
|
21
21
|
gets one safe loop: **claim → read → commit → release.**
|
|
22
22
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abloatai/ablo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "The Collaboration Layer For AI Agents",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -28,6 +28,11 @@
|
|
|
28
28
|
"import": "./dist/coordination/index.js",
|
|
29
29
|
"default": "./dist/coordination/index.js"
|
|
30
30
|
},
|
|
31
|
+
"./commit": {
|
|
32
|
+
"types": "./dist/commit/index.d.ts",
|
|
33
|
+
"import": "./dist/commit/index.js",
|
|
34
|
+
"default": "./dist/commit/index.js"
|
|
35
|
+
},
|
|
31
36
|
"./react": {
|
|
32
37
|
"types": "./dist/react/index.d.ts",
|
|
33
38
|
"import": "./dist/react/index.js",
|
|
@@ -207,7 +212,7 @@
|
|
|
207
212
|
"mobx": "^6.13.7",
|
|
208
213
|
"mobx-react-lite": "^4.0.0",
|
|
209
214
|
"uuid": "^11.1.0",
|
|
210
|
-
"zod": "^4.
|
|
215
|
+
"zod": "^4.1.11"
|
|
211
216
|
},
|
|
212
217
|
"devDependencies": {
|
|
213
218
|
"@ai-sdk/provider": "^3.0.0",
|