@abloatai/ablo 0.5.1 → 0.7.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 +61 -0
- package/README.md +248 -124
- package/dist/BaseSyncedStore.d.ts +3 -3
- package/dist/BaseSyncedStore.js +3 -3
- package/dist/api/index.d.ts +3 -3
- package/dist/api/index.js +1 -1
- package/dist/client/Ablo.d.ts +91 -93
- package/dist/client/Ablo.js +122 -60
- package/dist/client/ApiClient.d.ts +14 -14
- package/dist/client/ApiClient.js +81 -55
- package/dist/client/createInternalComponents.d.ts +2 -3
- package/dist/client/createInternalComponents.js +2 -3
- package/dist/client/createModelProxy.d.ts +116 -90
- package/dist/client/createModelProxy.js +128 -128
- package/dist/client/index.d.ts +6 -7
- package/dist/client/index.js +4 -5
- package/dist/client/validateAbloOptions.js +5 -5
- package/dist/coordination/index.d.ts +6 -0
- package/dist/coordination/index.js +6 -0
- package/dist/coordination/schema.d.ts +329 -0
- package/dist/coordination/schema.js +209 -0
- package/dist/core/QueryView.d.ts +4 -1
- package/dist/core/QueryView.js +1 -1
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +7 -0
- package/dist/core/query-utils.d.ts +7 -10
- package/dist/core/query-utils.js +2 -3
- package/dist/errorCodes.d.ts +264 -0
- package/dist/errorCodes.js +251 -0
- package/dist/errors.d.ts +59 -14
- package/dist/errors.js +73 -12
- package/dist/index.d.ts +11 -9
- package/dist/index.js +8 -12
- package/dist/interfaces/index.d.ts +2 -10
- package/dist/mutators/Transaction.d.ts +2 -2
- package/dist/mutators/Transaction.js +2 -2
- package/dist/mutators/mutateActions.d.ts +44 -0
- package/dist/{react/useMutate.js → mutators/mutateActions.js} +11 -28
- package/dist/mutators/readerActions.d.ts +32 -0
- package/dist/{react/useReader.js → mutators/readerActions.js} +2 -18
- package/dist/policy/index.d.ts +1 -1
- package/dist/policy/index.js +1 -1
- package/dist/policy/types.d.ts +31 -0
- package/dist/policy/types.js +15 -0
- package/dist/query/types.d.ts +1 -1
- package/dist/react/AbloProvider.d.ts +13 -1
- package/dist/react/AbloProvider.js +14 -6
- package/dist/react/context.d.ts +4 -4
- package/dist/react/index.d.ts +4 -5
- package/dist/react/index.js +3 -7
- package/dist/react/useAblo.d.ts +14 -14
- package/dist/react/useAblo.js +26 -26
- package/dist/react/useIntent.d.ts +2 -2
- package/dist/react/useIntent.js +2 -2
- package/dist/react/useMutators.d.ts +1 -1
- package/dist/react/usePresence.d.ts +3 -3
- package/dist/react/usePresence.js +4 -4
- package/dist/react/useUndoScope.d.ts +1 -1
- package/dist/schema/ddl.d.ts +62 -0
- package/dist/schema/ddl.js +317 -0
- package/dist/schema/diff.d.ts +167 -0
- package/dist/schema/diff.js +280 -0
- package/dist/schema/field.d.ts +16 -19
- package/dist/schema/field.js +30 -17
- package/dist/schema/generate.d.ts +19 -0
- package/dist/schema/generate.js +87 -0
- package/dist/schema/index.d.ts +9 -3
- package/dist/schema/index.js +14 -2
- package/dist/schema/model.d.ts +87 -25
- package/dist/schema/model.js +33 -3
- package/dist/schema/relation.d.ts +17 -0
- package/dist/schema/roles.d.ts +148 -0
- package/dist/schema/roles.js +149 -0
- package/dist/schema/schema.d.ts +10 -69
- package/dist/schema/schema.js +58 -24
- package/dist/schema/select.d.ts +25 -0
- package/dist/schema/select.js +55 -0
- package/dist/schema/serialize.d.ts +96 -0
- package/dist/schema/serialize.js +231 -0
- package/dist/schema/sugar.d.ts +20 -3
- package/dist/schema/sugar.js +5 -1
- package/dist/schema/tenancy.d.ts +66 -0
- package/dist/schema/tenancy.js +58 -0
- package/dist/sync/HydrationCoordinator.d.ts +2 -0
- package/dist/sync/HydrationCoordinator.js +23 -17
- package/dist/sync/SyncWebSocket.d.ts +17 -0
- package/dist/sync/SyncWebSocket.js +46 -1
- package/dist/sync/awaitIntentGrant.d.ts +26 -0
- package/dist/sync/awaitIntentGrant.js +60 -0
- package/dist/sync/createIntentStream.d.ts +2 -1
- package/dist/sync/createIntentStream.js +89 -5
- package/dist/sync/createPresenceStream.js +1 -1
- package/dist/sync/participants.d.ts +2 -2
- package/dist/sync/participants.js +9 -18
- package/dist/types/global.d.ts +43 -52
- package/dist/types/global.js +16 -18
- package/dist/types/streams.d.ts +90 -42
- package/docs/api-keys.md +44 -0
- package/docs/api.md +72 -173
- package/docs/audit.md +5 -5
- package/docs/cli.md +212 -0
- package/docs/client-behavior.md +42 -43
- package/docs/coordination.md +343 -0
- package/docs/data-sources.md +16 -16
- package/docs/examples/agent-human.md +30 -32
- package/docs/examples/ai-sdk-tool.md +32 -33
- package/docs/examples/existing-python-backend.md +38 -36
- package/docs/examples/nextjs.md +24 -25
- package/docs/examples/scoped-agent.md +78 -0
- package/docs/examples/server-agent.md +20 -61
- package/docs/guarantees.md +34 -56
- package/docs/identity.md +529 -0
- package/docs/index.md +18 -24
- package/docs/integration-guide.md +130 -144
- package/docs/interaction-model.md +32 -95
- package/docs/mcp/claude-code.md +3 -3
- package/docs/mcp/cursor.md +1 -1
- package/docs/mcp/windsurf.md +1 -1
- package/docs/mcp.md +11 -26
- package/docs/quickstart.md +43 -49
- package/docs/react.md +74 -24
- package/docs/roadmap.md +17 -7
- package/llms.txt +34 -39
- package/package.json +8 -1
- package/dist/react/useMutate.d.ts +0 -83
- package/dist/react/useQuery.d.ts +0 -123
- package/dist/react/useQuery.js +0 -145
- package/dist/react/useReader.d.ts +0 -69
- package/docs/capabilities.md +0 -163
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Per-model
|
|
2
|
+
* Per-model client factory.
|
|
3
3
|
*
|
|
4
|
-
* Mirrors Anthropic SDK's
|
|
5
|
-
*
|
|
4
|
+
* Mirrors Anthropic SDK's per-endpoint module pattern: each model client
|
|
5
|
+
* has its own file, and the root client just instantiates
|
|
6
6
|
* one per model. Extracted from `Ablo.ts` so the proxy logic is
|
|
7
7
|
* testable in isolation and the constructor doesn't carry it.
|
|
8
8
|
*
|
|
9
9
|
* Each schema model gets one `ModelOperations<T, CreateInput>` —
|
|
10
10
|
* exposes `retrieve`, `list`, `count`, `create`, `update`, `delete`,
|
|
11
|
-
* `
|
|
12
|
-
* factory returns a plain object; the client assembles the
|
|
11
|
+
* `claim`, `claimState`, `queue`, `release`, `subscribe`, and `load`.
|
|
12
|
+
* The factory returns a plain object; the client assembles the
|
|
13
13
|
* `ablo.<model>` lookup table from these.
|
|
14
14
|
*/
|
|
15
15
|
import { autorun } from 'mobx';
|
|
16
|
-
import {
|
|
16
|
+
import { AbloClaimedError, AbloValidationError } from '../errors.js';
|
|
17
17
|
import { Model, modelAsRow } from '../Model.js';
|
|
18
18
|
import { ModelScope } from '../types/index.js';
|
|
19
|
-
const
|
|
20
|
-
export function
|
|
21
|
-
if (typeof
|
|
19
|
+
const modelClientMeta = new WeakMap();
|
|
20
|
+
export function getModelClientMeta(modelClient) {
|
|
21
|
+
if (typeof modelClient !== 'object' || modelClient === null)
|
|
22
22
|
return undefined;
|
|
23
|
-
return
|
|
23
|
+
return modelClientMeta.get(modelClient);
|
|
24
24
|
}
|
|
25
25
|
export function createModelProxy(schemaKey, registeredModelName, objectPool, syncClient, registry, hydration, collaboration) {
|
|
26
26
|
const ModelClass = registry.getModelByName(registeredModelName);
|
|
@@ -42,12 +42,99 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
42
42
|
await syncClient.syncNow();
|
|
43
43
|
await syncClient.waitForConfirmation(model.getModelName(), model.id);
|
|
44
44
|
};
|
|
45
|
+
// Claims this proxy currently holds, keyed by entity id. Lets the flat
|
|
46
|
+
// `release(id)` and `update(id)` find the lease + snapshot a `claim(id)`
|
|
47
|
+
// took — no per-call handle. Released on dispose, explicit release, or TTL.
|
|
48
|
+
const activeClaims = new Map();
|
|
49
|
+
const releaseClaim = async (id) => {
|
|
50
|
+
const held = activeClaims.get(id);
|
|
51
|
+
if (!held)
|
|
52
|
+
return;
|
|
53
|
+
activeClaims.delete(id);
|
|
54
|
+
await held.lease.release();
|
|
55
|
+
};
|
|
56
|
+
const takeClaim = async (id, options) => {
|
|
57
|
+
if (!collaboration) {
|
|
58
|
+
throw new AbloValidationError(`Model "${schemaKey}" cannot claim a row without collaboration wiring.`, { code: 'model_claim_not_configured' });
|
|
59
|
+
}
|
|
60
|
+
// Is someone ELSE already on this target? Read the local coordination
|
|
61
|
+
// snapshot up front — it decides whether we'll need to re-read after the
|
|
62
|
+
// claim (a free / already-mine target can't have changed under us).
|
|
63
|
+
const held = collaboration.observe({ model: schemaKey, id });
|
|
64
|
+
const contended = !!held && held.heldBy !== collaboration.selfParticipantId;
|
|
65
|
+
const failFast = options?.wait === false;
|
|
66
|
+
// Fail-fast (`wait: false`): if another participant already holds it,
|
|
67
|
+
// reject now instead of queuing. Best-effort at the client (a racing
|
|
68
|
+
// claim not yet synced into our snapshot slips through here) — the
|
|
69
|
+
// commit-time intent guard is the authoritative backstop that rejects
|
|
70
|
+
// the loser's first write. For work-distribution dedup that's exactly
|
|
71
|
+
// right: don't wait (that would double-process), skip.
|
|
72
|
+
if (failFast && contended) {
|
|
73
|
+
throw new AbloClaimedError(`${registeredModelName}/${id} is held by ${held?.heldBy ?? 'another participant'}.`, { code: 'entity_claimed' });
|
|
74
|
+
}
|
|
75
|
+
// Ensure the row exists locally before claiming.
|
|
76
|
+
let model = objectPool.get(id);
|
|
77
|
+
if (!model) {
|
|
78
|
+
await load({ where: { id } });
|
|
79
|
+
model = objectPool.get(id);
|
|
80
|
+
}
|
|
81
|
+
if (!model) {
|
|
82
|
+
throw new AbloValidationError(`Entity not found: ${registeredModelName}/${id}`, { code: 'entity_not_found' });
|
|
83
|
+
}
|
|
84
|
+
// Acquire the lease. Default (`wait` !== false) goes through the server's
|
|
85
|
+
// fair FIFO queue — `queue: true` resolves only once the lease is genuinely
|
|
86
|
+
// ours, blocking behind any current holder, with no TOCTOU gap (the server
|
|
87
|
+
// orders contenders). Fail-fast skips the queue: we already rejected an
|
|
88
|
+
// observed conflict above, so this just records our lease.
|
|
89
|
+
const lease = await collaboration.createIntent({
|
|
90
|
+
target: {
|
|
91
|
+
model: schemaKey,
|
|
92
|
+
id,
|
|
93
|
+
...(options?.field ? { field: options.field } : {}),
|
|
94
|
+
},
|
|
95
|
+
action: options?.action ?? 'editing',
|
|
96
|
+
ttl: options?.ttl,
|
|
97
|
+
queue: !failFast,
|
|
98
|
+
maxQueueDepth: options?.maxQueueDepth,
|
|
99
|
+
});
|
|
100
|
+
// Only when we actually waited behind another holder can the row have
|
|
101
|
+
// changed underneath us — re-read so the claimed snapshot reflects what
|
|
102
|
+
// they committed before releasing.
|
|
103
|
+
if (contended && !failFast) {
|
|
104
|
+
await load({ where: { id } });
|
|
105
|
+
model = objectPool.get(id) ?? model;
|
|
106
|
+
}
|
|
107
|
+
const snapshot = collaboration.createSnapshot(schemaKey, id);
|
|
108
|
+
activeClaims.set(id, { lease, snapshot });
|
|
109
|
+
const row = modelAsRow(model);
|
|
110
|
+
// `await using` calls this on scope exit; releases the claim.
|
|
111
|
+
Object.defineProperty(row, Symbol.asyncDispose, {
|
|
112
|
+
value: () => releaseClaim(id),
|
|
113
|
+
enumerable: false,
|
|
114
|
+
configurable: true,
|
|
115
|
+
});
|
|
116
|
+
return row;
|
|
117
|
+
};
|
|
118
|
+
function claim(id, a, b) {
|
|
119
|
+
if (typeof a === 'function') {
|
|
120
|
+
return (async () => {
|
|
121
|
+
const row = await takeClaim(id, b);
|
|
122
|
+
try {
|
|
123
|
+
return await a(row);
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
await releaseClaim(id);
|
|
127
|
+
}
|
|
128
|
+
})();
|
|
129
|
+
}
|
|
130
|
+
return takeClaim(id, a);
|
|
131
|
+
}
|
|
45
132
|
const operations = {
|
|
46
133
|
retrieve(id) {
|
|
47
134
|
return objectPool.get(id);
|
|
48
135
|
},
|
|
49
136
|
list(options) {
|
|
50
|
-
const all = objectPool.getByType(ModelClass, (options?.
|
|
137
|
+
const all = objectPool.getByType(ModelClass, (options?.state ?? ModelScope.live));
|
|
51
138
|
let result = all;
|
|
52
139
|
if (options?.where) {
|
|
53
140
|
const where = options.where;
|
|
@@ -99,9 +186,21 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
99
186
|
const model = objectPool.get(id);
|
|
100
187
|
if (!model)
|
|
101
188
|
throw new AbloValidationError(`Entity not found: ${registeredModelName}/${id}`, { code: 'entity_not_found' });
|
|
189
|
+
// If we hold a claim on this row, guard the write with its snapshot
|
|
190
|
+
// watermark + lease so it's stale-rejected and attributed to the claim.
|
|
191
|
+
const claimed = activeClaims.get(id);
|
|
192
|
+
const effective = claimed
|
|
193
|
+
? {
|
|
194
|
+
wait: 'confirmed',
|
|
195
|
+
readAt: claimed.snapshot.stamp,
|
|
196
|
+
onStale: 'reject',
|
|
197
|
+
intent: claimed.lease,
|
|
198
|
+
...options,
|
|
199
|
+
}
|
|
200
|
+
: options;
|
|
102
201
|
model.updateFromData(data);
|
|
103
|
-
syncClient.update(model,
|
|
104
|
-
await waitForMutation(model,
|
|
202
|
+
syncClient.update(model, effective);
|
|
203
|
+
await waitForMutation(model, effective);
|
|
105
204
|
return modelAsRow(model);
|
|
106
205
|
},
|
|
107
206
|
async delete(id, options) {
|
|
@@ -111,122 +210,23 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
111
210
|
syncClient.delete(model, options);
|
|
112
211
|
await waitForMutation(model, options);
|
|
113
212
|
},
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const cancel = () => {
|
|
123
|
-
if (released)
|
|
124
|
-
return;
|
|
125
|
-
released = true;
|
|
126
|
-
if (snapshot)
|
|
127
|
-
snapshot.signal.removeEventListener('abort', cancel);
|
|
128
|
-
acquired?.revoke();
|
|
129
|
-
};
|
|
130
|
-
// Public `finish()` — give the claim back after committing. Calls the
|
|
131
|
-
// lower-level lease handle's `release()` (a different API; leave it).
|
|
132
|
-
const finish = async () => {
|
|
133
|
-
if (released)
|
|
134
|
-
return;
|
|
135
|
-
released = true;
|
|
136
|
-
if (snapshot)
|
|
137
|
-
snapshot.signal.removeEventListener('abort', cancel);
|
|
138
|
-
await acquired?.release();
|
|
139
|
-
};
|
|
140
|
-
const whenFree = async (options) => {
|
|
141
|
-
if (!collaboration)
|
|
142
|
-
return;
|
|
143
|
-
await collaboration.waitFor(target, options);
|
|
144
|
-
};
|
|
145
|
-
const claim = async (options) => {
|
|
146
|
-
if (!collaboration) {
|
|
147
|
-
throw new AbloValidationError(`Model "${schemaKey}" cannot claim an intent without collaboration wiring.`, { code: 'model_intent_not_configured' });
|
|
148
|
-
}
|
|
149
|
-
if (acquired)
|
|
150
|
-
return;
|
|
151
|
-
acquireWait = options?.wait;
|
|
152
|
-
// Load the row so update() has a snapshot to guard against.
|
|
153
|
-
let model = objectPool.get(id);
|
|
154
|
-
if (!model) {
|
|
155
|
-
await load({ where: { id } });
|
|
156
|
-
model = objectPool.get(id);
|
|
157
|
-
}
|
|
158
|
-
if (!model) {
|
|
159
|
-
throw new AbloValidationError(`Entity not found: ${registeredModelName}/${id}`, { code: 'entity_not_found' });
|
|
160
|
-
}
|
|
161
|
-
const snap = collaboration.createSnapshot(schemaKey, id);
|
|
162
|
-
snap.signal.addEventListener('abort', cancel, { once: true });
|
|
163
|
-
snapshot = snap;
|
|
164
|
-
released = false;
|
|
165
|
-
acquired = await collaboration.createIntent({
|
|
166
|
-
target: {
|
|
167
|
-
resource: schemaKey,
|
|
168
|
-
id,
|
|
169
|
-
...(options?.field ? { field: options.field } : {}),
|
|
170
|
-
},
|
|
171
|
-
action: options?.action ?? 'editing',
|
|
172
|
-
ttl: options?.ttl,
|
|
173
|
-
});
|
|
174
|
-
};
|
|
175
|
-
const claimOrWait = async (options) => {
|
|
176
|
-
if (!collaboration) {
|
|
177
|
-
throw new AbloValidationError(`Model "${schemaKey}" cannot claim an intent without collaboration wiring.`, { code: 'model_intent_not_configured' });
|
|
178
|
-
}
|
|
179
|
-
const held = collaboration.observe(target);
|
|
180
|
-
// A foreign holder: wait for them to finish, then re-read before
|
|
181
|
-
// claiming. Our own claim (or a free target) goes straight to claim.
|
|
182
|
-
if (held && held.heldBy !== collaboration.selfParticipantId) {
|
|
183
|
-
await whenFree();
|
|
184
|
-
await load({ where: { id } });
|
|
185
|
-
}
|
|
186
|
-
await claim(options);
|
|
187
|
-
};
|
|
188
|
-
const handle = {
|
|
189
|
-
id,
|
|
190
|
-
get current() {
|
|
191
|
-
return collaboration?.observe(target) ?? null;
|
|
192
|
-
},
|
|
193
|
-
get status() {
|
|
194
|
-
return collaboration?.observe(target)?.status ?? 'idle';
|
|
195
|
-
},
|
|
196
|
-
claim,
|
|
197
|
-
claimOrWait,
|
|
198
|
-
async update(data, updateOptions) {
|
|
199
|
-
if (!acquired || !snapshot) {
|
|
200
|
-
throw new AbloValidationError(`Call claim() before update() on ablo.${schemaKey}.intent(${id}).`, { code: 'intent_not_acquired' });
|
|
201
|
-
}
|
|
202
|
-
if (snapshot.signal.aborted) {
|
|
203
|
-
throw new AbloStaleContextError(`Intent context is stale for ${schemaKey}/${id}. Re-read the row and retry.`, {
|
|
204
|
-
code: 'edit_context_stale',
|
|
205
|
-
readAt: snapshot.stamp,
|
|
206
|
-
cause: snapshot.signal.reason,
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
try {
|
|
210
|
-
return await operations.update(id, data, {
|
|
211
|
-
wait: acquireWait ?? 'confirmed',
|
|
212
|
-
readAt: snapshot.stamp,
|
|
213
|
-
onStale: 'reject',
|
|
214
|
-
...updateOptions,
|
|
215
|
-
intent: acquired,
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
finally {
|
|
219
|
-
await finish();
|
|
220
|
-
}
|
|
221
|
-
},
|
|
222
|
-
finish,
|
|
223
|
-
whenFree,
|
|
224
|
-
cancel,
|
|
225
|
-
[Symbol.asyncDispose]: finish,
|
|
213
|
+
claim,
|
|
214
|
+
claimState(id) {
|
|
215
|
+
return collaboration?.observe({ model: schemaKey, id }) ?? null;
|
|
216
|
+
},
|
|
217
|
+
queue(id) {
|
|
218
|
+
return {
|
|
219
|
+
object: 'list',
|
|
220
|
+
data: collaboration?.queue({ model: schemaKey, id }) ?? [],
|
|
226
221
|
};
|
|
227
|
-
return handle;
|
|
228
222
|
},
|
|
229
|
-
|
|
223
|
+
reorder(id, order) {
|
|
224
|
+
collaboration?.reorder({ model: schemaKey, id }, order);
|
|
225
|
+
},
|
|
226
|
+
release(id) {
|
|
227
|
+
return releaseClaim(id);
|
|
228
|
+
},
|
|
229
|
+
onChange(callback, options) {
|
|
230
230
|
return autorun(() => {
|
|
231
231
|
const entities = this.list(options);
|
|
232
232
|
callback(entities);
|
|
@@ -234,7 +234,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
234
234
|
},
|
|
235
235
|
load,
|
|
236
236
|
};
|
|
237
|
-
|
|
237
|
+
modelClientMeta.set(operations, {
|
|
238
238
|
key: schemaKey,
|
|
239
239
|
typename: registeredModelName,
|
|
240
240
|
});
|
package/dist/client/index.d.ts
CHANGED
|
@@ -15,22 +15,21 @@
|
|
|
15
15
|
* apiKey: process.env.ABLO_API_KEY,
|
|
16
16
|
* });
|
|
17
17
|
*
|
|
18
|
-
* const
|
|
19
|
-
* await ablo.
|
|
18
|
+
* const reports = ablo.weatherReports.list({ where: { status: 'pending' } });
|
|
19
|
+
* await ablo.weatherReports.create({ location: 'Stockholm', status: 'pending' });
|
|
20
20
|
* ```
|
|
21
21
|
*
|
|
22
|
-
* For headless agents (workers, bots), pass
|
|
23
|
-
*
|
|
22
|
+
* For headless agents (workers, bots), pass the same schema and an API key
|
|
23
|
+
* scoped for that server runtime:
|
|
24
24
|
*
|
|
25
25
|
* ```ts
|
|
26
26
|
* const bot = Ablo({
|
|
27
27
|
* schema,
|
|
28
28
|
* apiKey: process.env.ABLO_API_KEY,
|
|
29
|
-
* kind: 'agent',
|
|
30
29
|
* });
|
|
31
30
|
* ```
|
|
32
31
|
*/
|
|
33
|
-
export { Ablo, computeFKDepthPriority, type AbloOptions, type InternalAbloOptions, type
|
|
32
|
+
export { Ablo, computeFKDepthPriority, type AbloOptions, type InternalAbloOptions, type ClaimedOptions, type IfClaimedPolicy, type IntentWaitOptions, type ModelCountOptions, type ModelListOptions, type ModelListScope, type ModelLoadOptions, type ModelOperations, type ModelReadOptions, } from './Ablo.js';
|
|
34
33
|
export type { AbloPersistence } from './persistence.js';
|
|
35
|
-
export type { AbloApi, AbloApiClientOptions, AbloApiIntents, Agent, AgentIntentInput, AgentIntentOptions, AgentOptions,
|
|
34
|
+
export type { AbloApi, AbloApiClientOptions, AbloApiIntents, Agent, AgentIntentInput, AgentIntentOptions, AgentOptions, AgentModelClient, AgentModelReadOptions, AgentModelMutationOptions, AgentRunContext, AgentRunDone, AgentRunFailed, AgentRunCancelled, AgentRunOptions, AgentRunResult, AgentRunStatus, Capability, CapabilityCreateOptions, CapabilityParticipantKind, CapabilityRecord, CapabilityResource, CapabilityRevocation, CapabilityScope, Task, TaskCloseOptions, TaskCloseResult, TaskCreateOptions, TaskResource, } from './ApiClient.js';
|
|
36
35
|
export type { EngineParticipant, JoinedParticipant, ParticipantJoinOptions, ParticipantManager, ParticipantScope, ParticipantStatus, ScopedIntents, ScopedPresence, } from '../sync/participants.js';
|
package/dist/client/index.js
CHANGED
|
@@ -15,18 +15,17 @@
|
|
|
15
15
|
* apiKey: process.env.ABLO_API_KEY,
|
|
16
16
|
* });
|
|
17
17
|
*
|
|
18
|
-
* const
|
|
19
|
-
* await ablo.
|
|
18
|
+
* const reports = ablo.weatherReports.list({ where: { status: 'pending' } });
|
|
19
|
+
* await ablo.weatherReports.create({ location: 'Stockholm', status: 'pending' });
|
|
20
20
|
* ```
|
|
21
21
|
*
|
|
22
|
-
* For headless agents (workers, bots), pass
|
|
23
|
-
*
|
|
22
|
+
* For headless agents (workers, bots), pass the same schema and an API key
|
|
23
|
+
* scoped for that server runtime:
|
|
24
24
|
*
|
|
25
25
|
* ```ts
|
|
26
26
|
* const bot = Ablo({
|
|
27
27
|
* schema,
|
|
28
28
|
* apiKey: process.env.ABLO_API_KEY,
|
|
29
|
-
* kind: 'agent',
|
|
30
29
|
* });
|
|
31
30
|
* ```
|
|
32
31
|
*/
|
|
@@ -15,11 +15,11 @@ export function validateAbloOptions(input) {
|
|
|
15
15
|
const kind = options.kind ?? 'user';
|
|
16
16
|
if (!url) {
|
|
17
17
|
return new Error('Ablo: `url` is required. Pass the sync server URL, e.g. ' +
|
|
18
|
-
`Ablo({ baseURL: 'wss://sync.
|
|
18
|
+
`Ablo({ baseURL: 'wss://sync.abloatai.com', schema, user })`);
|
|
19
19
|
}
|
|
20
|
-
// Schema is optional for the
|
|
21
|
-
// Ablo({ apiKey }).
|
|
22
|
-
// Passing a schema only enables typed model sugar (`ablo.
|
|
20
|
+
// Schema is optional for the model-first API:
|
|
21
|
+
// Ablo({ apiKey }).model('clauses').retrieve(...)
|
|
22
|
+
// Passing a schema only enables typed model sugar (`ablo.weatherReports.update(...)`).
|
|
23
23
|
if (!configuredApiKey &&
|
|
24
24
|
!configuredAuthToken &&
|
|
25
25
|
!options.capabilityToken &&
|
|
@@ -37,7 +37,7 @@ export function validateAbloOptions(input) {
|
|
|
37
37
|
if (!configuredApiKey && !configuredAuthToken && kind === 'agent' && !options.capabilityToken) {
|
|
38
38
|
return new Error('Ablo: provide either `apiKey` (hosted cloud — SDK exchanges internally) ' +
|
|
39
39
|
'or `capabilityToken` (self-hosted — your auth layer mints + hands in). ' +
|
|
40
|
-
'See https://
|
|
40
|
+
'See https://abloatai.com/docs/api-keys for the full pattern.');
|
|
41
41
|
}
|
|
42
42
|
return null;
|
|
43
43
|
}
|