@abloatai/ablo 0.3.1 → 0.5.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 +54 -1
- package/NOTICE +2 -2
- package/README.md +99 -78
- package/dist/BaseSyncedStore.d.ts +3 -2
- package/dist/agent/Agent.d.ts +1 -1
- package/dist/agent/Agent.js +1 -1
- package/dist/agent/index.d.ts +4 -4
- package/dist/agent/index.js +6 -6
- package/dist/agent/types.d.ts +1 -1
- package/dist/ai-sdk/index.d.ts +3 -3
- package/dist/ai-sdk/index.js +3 -3
- package/dist/ai-sdk/intent-broadcast.d.ts +1 -1
- package/dist/ai-sdk/intent-broadcast.js +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/client/Ablo.d.ts +53 -27
- package/dist/client/Ablo.js +32 -1
- package/dist/client/auth.d.ts +3 -3
- package/dist/client/auth.js +5 -5
- package/dist/client/createModelProxy.d.ts +118 -32
- package/dist/client/createModelProxy.js +87 -44
- package/dist/client/index.d.ts +3 -3
- package/dist/client/index.js +3 -3
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.js +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +2 -2
- package/dist/errors.d.ts +9 -7
- package/dist/errors.js +9 -7
- package/dist/index.d.ts +20 -6
- package/dist/index.js +41 -22
- package/dist/interfaces/headless.d.ts +1 -1
- package/dist/interfaces/headless.js +2 -2
- package/dist/policy/index.d.ts +2 -2
- package/dist/policy/index.js +2 -2
- package/dist/policy/types.d.ts +10 -0
- package/dist/principal.d.ts +3 -3
- package/dist/principal.js +3 -3
- package/dist/query/client.d.ts +7 -6
- package/dist/react/AbloProvider.d.ts +44 -1
- package/dist/react/AbloProvider.js +3 -1
- package/dist/react/ClientSideSuspense.d.ts +1 -1
- package/dist/react/SyncGroupProvider.js +1 -1
- package/dist/react/context.d.ts +1 -1
- package/dist/react/context.js +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/useCurrentUserId.js +1 -1
- package/dist/react/useErrorListener.js +1 -1
- package/dist/react/useMutate.d.ts +1 -1
- package/dist/react/useMutationFailureListener.js +1 -1
- package/dist/react/useReader.d.ts +1 -1
- package/dist/schema/field.d.ts +1 -1
- package/dist/schema/field.js +1 -1
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.js +2 -2
- package/dist/schema/model.d.ts +2 -2
- package/dist/schema/model.js +2 -2
- package/dist/schema/queries.d.ts +1 -1
- package/dist/schema/queries.js +1 -1
- package/dist/schema/relation.d.ts +1 -1
- package/dist/schema/relation.js +1 -1
- package/dist/schema/schema.d.ts +1 -1
- package/dist/schema/schema.js +1 -1
- package/dist/source/index.d.ts +22 -28
- package/dist/source/index.js +23 -20
- package/dist/source/pushQueue.d.ts +1 -1
- package/dist/source/pushQueue.js +2 -2
- package/dist/sync/SyncWebSocket.d.ts +20 -5
- package/dist/sync/createIntentStream.js +7 -0
- package/dist/testing/fixtures/models.d.ts +1 -1
- package/dist/testing/fixtures/models.js +1 -1
- package/dist/testing/helpers/react-wrapper.d.ts +2 -2
- package/dist/testing/helpers/react-wrapper.js +2 -2
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +1 -1
- package/dist/types/streams.d.ts +41 -1
- package/docs/api.md +78 -20
- package/docs/data-sources.md +50 -16
- package/docs/examples/ai-sdk-tool.md +14 -31
- package/docs/examples/existing-python-backend.md +6 -6
- package/docs/integration-guide.md +8 -7
- package/docs/interaction-model.md +16 -4
- package/docs/mcp.md +1 -1
- package/docs/quickstart.md +20 -18
- package/examples/data-source/README.md +1 -1
- package/examples/data-source/ablo-driver.ts +5 -5
- package/examples/data-source/customer-server.ts +10 -10
- package/examples/data-source/run.ts +9 -11
- package/examples/data-source/schema.ts +1 -1
- package/examples/quickstart.ts +2 -2
- package/llms.txt +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,65 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 9154c1b: Rename intent handle methods to a clearer claim vocabulary; add `AbloProvider` `bootstrapMode`.
|
|
8
|
+
|
|
9
|
+
BREAKING — on the model intent handle (`ablo.<model>.intent(id)`):
|
|
10
|
+
`acquire`→`claim`, `acquireOrAwait`→`claimOrWait`, `settled`→`whenFree`,
|
|
11
|
+
`release`→`finish`, `revoke`→`cancel`. The lower-level `IntentHandle` /
|
|
12
|
+
`IntentLeaseHandle` (`ablo.intents.*`) are unchanged.
|
|
13
|
+
|
|
14
|
+
Also: `AbloProvider` gains a `bootstrapMode` prop (`'full' | 'none'`) to skip the
|
|
15
|
+
baseline pull on read-light pages; `StaleContextConflict` gains an optional
|
|
16
|
+
`conflictingFields`; README + JSDoc clarity pass and a new HTTP API section.
|
|
17
|
+
|
|
18
|
+
## 0.4.0
|
|
19
|
+
|
|
20
|
+
### Minor Changes
|
|
21
|
+
|
|
22
|
+
- Per-entity coordination intents on the model accessor.
|
|
23
|
+
|
|
24
|
+
Coordinate writes to an entity through the same accessor you read it with —
|
|
25
|
+
`ablo.<model>.intent(id)`, returning a `ModelIntentHandle`. Intent state is one
|
|
26
|
+
self-describing object (`{ object: 'intent', id, status, target, action, heldBy,
|
|
27
|
+
participantKind, createdAt?, expiresAt? }`) with a single lifecycle:
|
|
28
|
+
`status: 'active' | 'committed' | 'expired' | 'canceled'`. An `active` intent is
|
|
29
|
+
the lock.
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
- `ablo.<model>.intent(id)` → `ModelIntentHandle<T>`, beside `create` / `update`
|
|
33
|
+
/ `retrieve` / `load` on every model.
|
|
34
|
+
- Read side (any participant, synchronous + reactive): `current` (the holder's
|
|
35
|
+
intent, or `null`), `status` (`'idle'` when free), `settled()`.
|
|
36
|
+
- Write side (the holder): `acquire()`, `acquireOrAwait()`, lease-guarded
|
|
37
|
+
`update()`, `release()`, `revoke()`.
|
|
38
|
+
- `AsyncDisposable`: `await using lock = ablo.<model>.intent(id)` auto-releases
|
|
39
|
+
on scope exit.
|
|
40
|
+
- `acquireOrAwait()` — serialize-on-contention: take the lease, or wait out the
|
|
41
|
+
current holder, re-read the changed row, then take it. The caller never branches
|
|
42
|
+
on who holds the target — it just gets the target safely. Bind it to an agent's
|
|
43
|
+
write-tool boundary so agents never reason about coordination.
|
|
44
|
+
- New exports: `ModelIntentHandle`, `ModelIntentAcquireOptions`.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
- `acquire()` is fire-and-forget over the socket — it does not throw on conflict.
|
|
48
|
+
Resolve contention with `acquireOrAwait()` (wait) or read `current` for a
|
|
49
|
+
reactive "who's editing" badge, rather than catching a rejection.
|
|
50
|
+
|
|
51
|
+
### Deprecated
|
|
52
|
+
- Participant-level `intents.claim()` / `onRejected()` and the `intent_rejected`
|
|
53
|
+
wire frame still work but are superseded by the per-model handle. Their removal
|
|
54
|
+
is a future breaking change.
|
|
55
|
+
|
|
3
56
|
## Unreleased
|
|
4
57
|
|
|
5
58
|
Schema-driven identity sync-group composition, plus a terser capability surface.
|
|
6
59
|
|
|
7
60
|
The convention for deriving a participant's allowed sync-groups from its identity is now declared on the consumer's schema as an open registration. Consumers with a `{ regionId, customerId }` identity shape declare their own roles instead of receiving any built-in prefixes from the SDK.
|
|
8
61
|
|
|
9
|
-
Capability fields shed their redundant `allowed` prefix to match the surrounding vocabulary — capability inputs always describe what the bearer
|
|
62
|
+
Capability fields shed their redundant `allowed` prefix to match the surrounding vocabulary — capability inputs always describe what the bearer _can_ touch, so the prefix was doing no disambiguation work for the consumer.
|
|
10
63
|
|
|
11
64
|
### Added
|
|
12
65
|
|
package/NOTICE
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
@ablo
|
|
1
|
+
@abloatai/ablo
|
|
2
2
|
Copyright 2025-2026 Fablo Innovation AB
|
|
3
3
|
|
|
4
4
|
This product includes software developed by Fablo Innovation AB
|
|
@@ -7,6 +7,6 @@ This product includes software developed by Fablo Innovation AB
|
|
|
7
7
|
"Ablo" is a trademark of Fablo Innovation AB. This license does not grant
|
|
8
8
|
permission to use the Ablo name, logo, or trademarks. Third parties
|
|
9
9
|
may describe their use of or compatibility with Ablo factually (e.g.,
|
|
10
|
-
"built with @ablo
|
|
10
|
+
"built with @abloatai/ablo") but may not use the Ablo name in a way
|
|
11
11
|
that suggests endorsement, affiliation, or origin without written
|
|
12
12
|
permission.
|
package/README.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# Ablo
|
|
2
2
|
|
|
3
|
-
Ablo Sync is a
|
|
3
|
+
Ablo Sync is a typed sync engine for shared app state — the kind that humans,
|
|
4
|
+
server code, and AI agents all edit at once.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
Reach for it when those edits need to show up everywhere in real time, not
|
|
7
|
+
silently overwrite each other, expose who's working on what, and leave a record
|
|
8
|
+
of who changed what.
|
|
8
9
|
|
|
9
10
|
```txt
|
|
10
|
-
schema -> ablo.<model>.create/load/
|
|
11
|
+
schema -> ablo.<model>.create/load/update(...)
|
|
11
12
|
```
|
|
12
13
|
|
|
13
14
|
## Install
|
|
@@ -27,8 +28,9 @@ server runtimes only.
|
|
|
27
28
|
export ABLO_API_KEY=sk_test_...
|
|
28
29
|
```
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
In the browser, connect through the React provider (`<AbloProvider>`), which
|
|
32
|
+
authenticates with the signed-in user's session — never the raw API key. Do not
|
|
33
|
+
ship `ABLO_API_KEY` in a browser bundle.
|
|
32
34
|
|
|
33
35
|
## Quick Start
|
|
34
36
|
|
|
@@ -72,8 +74,9 @@ Expected output:
|
|
|
72
74
|
{ id: '...', status: 'ready' }
|
|
73
75
|
```
|
|
74
76
|
|
|
75
|
-
Pass `schema`
|
|
76
|
-
|
|
77
|
+
Pass `schema` to get typed models like `ablo.weatherReports.update(...)`. Omit it
|
|
78
|
+
only for the lower-level client used by custom agents and MCP routes that can't
|
|
79
|
+
import your app's schema.
|
|
77
80
|
|
|
78
81
|
Run the package example from this directory:
|
|
79
82
|
|
|
@@ -87,100 +90,113 @@ future agents, read [Integration Guide](./docs/integration-guide.md).
|
|
|
87
90
|
|
|
88
91
|
## AI Activity on Existing State
|
|
89
92
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
When AI or background work will spend real time on an existing row — not just a
|
|
94
|
+
one-shot write — coordinate through `ablo.<model>.intent(id)`, the coordination
|
|
95
|
+
accessor that sits beside `create`/`update`/`retrieve`. It takes the row's `id` (the same
|
|
96
|
+
id you pass to `retrieve(id)` / `update(id, …)`) and returns a handle
|
|
97
|
+
synchronously, so you can see who's already working on a row before you start.
|
|
94
98
|
|
|
95
99
|
```ts
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
// `report_stockholm` is this weather report's id — set at create time, or the
|
|
101
|
+
// `created.id` returned above.
|
|
102
|
+
const report = ablo.weatherReports.intent('report_stockholm');
|
|
103
|
+
|
|
104
|
+
// Read side: is someone already on it? Wait for them to finish.
|
|
105
|
+
if (report.current) {
|
|
106
|
+
report.current.heldBy; // 'agent:forecaster'
|
|
107
|
+
await report.whenFree();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Write side: claim so other participants yield while we work.
|
|
111
|
+
await report.claim({ action: 'checking_weather', field: 'forecast', ttl: '2m' });
|
|
101
112
|
|
|
102
113
|
// Your existing weather tool or agent call. While this runs, other clients see
|
|
103
|
-
// that
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
});
|
|
114
|
+
// that report_stockholm is being checked.
|
|
115
|
+
const row = ablo.weatherReports.retrieve('report_stockholm');
|
|
116
|
+
const weather = await weatherAgent.getWeather(row.location);
|
|
107
117
|
|
|
108
|
-
await
|
|
118
|
+
await report.update({
|
|
109
119
|
status: 'ready',
|
|
110
120
|
forecast: weather.summary,
|
|
111
121
|
});
|
|
112
122
|
```
|
|
113
123
|
|
|
114
|
-
Ablo does not fetch the weather. It keeps the activity visible
|
|
115
|
-
|
|
116
|
-
|
|
124
|
+
Ablo does not fetch the weather. It keeps the activity visible while the work
|
|
125
|
+
runs, rejects `report.update(...)` with `AbloStaleContextError` if the row
|
|
126
|
+
changed under you, and finishes the claim automatically once the write lands.
|
|
117
127
|
|
|
118
128
|
## Multiplayer
|
|
119
129
|
|
|
120
130
|
There is no separate multiplayer mode. When human UI, server actions, and agent
|
|
121
|
-
workers
|
|
122
|
-
the
|
|
131
|
+
workers share the same schema and write through `ablo.<model>`, they all see
|
|
132
|
+
each other's changes in real time — that's the default, not a feature you turn on.
|
|
123
133
|
|
|
124
134
|
- `ablo.<model>.create/update/delete` fan out confirmed deltas to subscribers.
|
|
125
135
|
- `useAblo(...)` gives React clients the live row plus active intents.
|
|
126
|
-
- `ablo.<model>.
|
|
127
|
-
- `ablo.intents` remains available for custom lower-level coordination.
|
|
136
|
+
- `ablo.<model>.intent(id)` lets humans and agents see and coordinate active work before a write lands.
|
|
128
137
|
|
|
129
|
-
|
|
130
|
-
|
|
138
|
+
Always write through Ablo — the SDK (`ablo.<model>.create/update/delete`) or the
|
|
139
|
+
HTTP API (`POST /v1/commits`). If you write straight to your own database
|
|
140
|
+
instead, those changes won't reach connected clients. Use Ablo's endpoints and
|
|
141
|
+
the fan-out is automatic.
|
|
131
142
|
|
|
132
143
|
Under the hood, capabilities, tasks, leases, intents, commits, and receipts are
|
|
133
144
|
real protocol primitives. They exist so agent work is scoped, coordinated,
|
|
134
|
-
attributable, and cleaned up if a runtime disappears
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
##
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
145
|
+
attributable, and cleaned up if a runtime disappears — but you don't touch them
|
|
146
|
+
in a first integration. The default path above is enough.
|
|
147
|
+
|
|
148
|
+
## HTTP API
|
|
149
|
+
|
|
150
|
+
The SDK is a typed wrapper over a signed HTTP API, the same way `stripe-node`
|
|
151
|
+
wraps Stripe's REST API. Everything you do through `ablo.<model>` is reachable
|
|
152
|
+
over HTTP, so backends in other languages and server-to-server callers work
|
|
153
|
+
without the SDK.
|
|
154
|
+
|
|
155
|
+
Writes — create, update, and delete — all go through one endpoint as a batch of
|
|
156
|
+
operations:
|
|
157
|
+
|
|
158
|
+
```http
|
|
159
|
+
POST /v1/commits
|
|
160
|
+
Authorization: Bearer sk_live_...
|
|
161
|
+
Idempotency-Key: <your-unique-id>
|
|
162
|
+
|
|
163
|
+
{
|
|
164
|
+
"operations": [
|
|
165
|
+
{
|
|
166
|
+
"type": "UPDATE",
|
|
167
|
+
"model": "weatherReports",
|
|
168
|
+
"id": "report_stockholm",
|
|
169
|
+
"input": { "status": "ready" },
|
|
170
|
+
"readAt": 1042,
|
|
171
|
+
"onStale": "reject"
|
|
172
|
+
}
|
|
173
|
+
]
|
|
163
174
|
}
|
|
164
|
-
|
|
165
|
-
await ablo.intents.waitFor(
|
|
166
|
-
{ resource: 'weatherReports', id: 'weather_stockholm' },
|
|
167
|
-
);
|
|
168
175
|
```
|
|
169
176
|
|
|
170
|
-
|
|
177
|
+
Each operation is one `CREATE` / `UPDATE` / `DELETE` (plus `ARCHIVE` /
|
|
178
|
+
`UNARCHIVE`). Reads fetch a single row with `GET /v1/resources/{model}/{id}`.
|
|
179
|
+
The same API key, scope, idempotency, and stale-write rules apply as in the SDK
|
|
180
|
+
— the SDK just removes the boilerplate.
|
|
171
181
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
182
|
+
## Load vs Retrieve
|
|
183
|
+
|
|
184
|
+
Most reads are `retrieve` — it's the everyday path, especially inside `useAblo(...)`:
|
|
185
|
+
|
|
186
|
+
- `ablo.weatherReports.retrieve(id)` is sync. It returns the already-loaded row from
|
|
187
|
+
the local pool (or `undefined` if it isn't loaded yet). In React,
|
|
188
|
+
`useAblo((ablo) => ablo.weatherReports.retrieve(id))` keeps that read live.
|
|
189
|
+
- `ablo.weatherReports.load({ where })` is async. Reach for it when you need to
|
|
190
|
+
guarantee a row is hydrated before you read it — initial fetch, SSR, scripts, or
|
|
191
|
+
any non-reactive runtime.
|
|
176
192
|
|
|
177
193
|
## Persistence
|
|
178
194
|
|
|
179
|
-
Ablo
|
|
180
|
-
state
|
|
181
|
-
|
|
195
|
+
Ablo keeps local state in memory by default. That keeps the SDK focused on
|
|
196
|
+
coordinating shared state, rather than silently turning every browser app into
|
|
197
|
+
an offline database it didn't ask for.
|
|
182
198
|
|
|
183
|
-
Opt into
|
|
199
|
+
Opt into a durable browser cache and offline write queue when you want it:
|
|
184
200
|
|
|
185
201
|
```ts
|
|
186
202
|
const ablo = Ablo({
|
|
@@ -198,12 +214,17 @@ Every schema model has a backing store. By default, Ablo stores rows for the
|
|
|
198
214
|
models you declare, so `ablo.weatherReports.create(...)` and `ablo.weatherReports.update(...)`
|
|
199
215
|
write to Ablo-managed state.
|
|
200
216
|
|
|
201
|
-
If your existing database
|
|
202
|
-
|
|
203
|
-
|
|
217
|
+
If your existing database stays the source of truth, connect it as a Data
|
|
218
|
+
Source: Ablo sends signed commit requests to an endpoint you host, and your app
|
|
219
|
+
writes its own database. Ablo never sees your database credentials — only the
|
|
220
|
+
API key:
|
|
204
221
|
|
|
205
222
|
```bash
|
|
206
|
-
|
|
223
|
+
# stays in your app — Ablo never receives this
|
|
224
|
+
DATABASE_URL=postgres://...
|
|
225
|
+
|
|
226
|
+
# the only Ablo credential your app needs
|
|
227
|
+
ABLO_API_KEY=sk_live_...
|
|
207
228
|
```
|
|
208
229
|
|
|
209
230
|
See [Connect Your Database](./docs/data-sources.md) for the route and commit shape.
|
|
@@ -123,8 +123,9 @@ export interface UserContext {
|
|
|
123
123
|
* store routes this to SyncWebSocket so the WS URL carries
|
|
124
124
|
* `kind=agent` and the server applies capability-token auth. */
|
|
125
125
|
kind?: 'user' | 'agent' | 'system';
|
|
126
|
-
/**
|
|
127
|
-
* `?authorization=Bearer <token>` on the
|
|
126
|
+
/** Restricted (`rk_`) API key for `kind: 'agent'` — the agent's
|
|
127
|
+
* bearer credential. Sent as `?authorization=Bearer <token>` on the
|
|
128
|
+
* WS upgrade. (Field name predates the Biscuit→opaque-key migration.) */
|
|
128
129
|
capabilityToken?: string;
|
|
129
130
|
/** Server-authoritative sync groups, supplied by auth/capability
|
|
130
131
|
* exchange. The SDK does not invent org/user/default groups; app
|
package/dist/agent/Agent.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* ```ts
|
|
11
11
|
* import { generateText, tool, stepCountIs } from 'ai';
|
|
12
|
-
* import { Agent } from '@ablo/
|
|
12
|
+
* import { Agent } from '@abloatai/ablo/agent';
|
|
13
13
|
*
|
|
14
14
|
* const perception = new Agent({
|
|
15
15
|
* syncServerUrl: 'http://localhost:8080',
|
package/dist/agent/Agent.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* ```ts
|
|
11
11
|
* import { generateText, tool, stepCountIs } from 'ai';
|
|
12
|
-
* import { Agent } from '@ablo/
|
|
12
|
+
* import { Agent } from '@abloatai/ablo/agent';
|
|
13
13
|
*
|
|
14
14
|
* const perception = new Agent({
|
|
15
15
|
* syncServerUrl: 'http://localhost:8080',
|
package/dist/agent/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @ablo/
|
|
2
|
+
* @abloatai/ablo/agent — Agent SDK helpers
|
|
3
3
|
*
|
|
4
4
|
* Two entry points depending on agent lifetime:
|
|
5
5
|
*
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* server-issued capability token instead of session cookies.
|
|
13
13
|
*
|
|
14
14
|
* ```ts
|
|
15
|
-
* import Ablo from '@ablo
|
|
15
|
+
* import Ablo from '@abloatai/ablo';
|
|
16
16
|
*
|
|
17
17
|
* const ablo = Ablo({
|
|
18
18
|
* schema,
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
*
|
|
45
45
|
* ```ts
|
|
46
46
|
* import { generateText, tool, stepCountIs } from 'ai';
|
|
47
|
-
* import { Agent } from '@ablo/
|
|
47
|
+
* import { Agent } from '@abloatai/ablo/agent';
|
|
48
48
|
*
|
|
49
49
|
* const perception = new Agent({
|
|
50
50
|
* syncServerUrl: 'http://localhost:8080',
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
* ```ts
|
|
79
79
|
* import { tool } from 'ai';
|
|
80
80
|
* import { z } from 'zod';
|
|
81
|
-
* import { Agent, type AgentContext } from '@ablo/
|
|
81
|
+
* import { Agent, type AgentContext } from '@abloatai/ablo/agent';
|
|
82
82
|
*
|
|
83
83
|
* export const updateSlideTool = () => tool({
|
|
84
84
|
* description: 'Update a slide title',
|
package/dist/agent/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @ablo/
|
|
2
|
+
* @abloatai/ablo/agent — Agent SDK helpers
|
|
3
3
|
*
|
|
4
4
|
* Two entry points depending on agent lifetime:
|
|
5
5
|
*
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* server-issued capability token instead of session cookies.
|
|
13
13
|
*
|
|
14
14
|
* ```ts
|
|
15
|
-
* import Ablo from '@ablo
|
|
15
|
+
* import Ablo from '@abloatai/ablo';
|
|
16
16
|
*
|
|
17
17
|
* const ablo = Ablo({
|
|
18
18
|
* schema,
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
*
|
|
45
45
|
* ```ts
|
|
46
46
|
* import { generateText, tool, stepCountIs } from 'ai';
|
|
47
|
-
* import { Agent } from '@ablo/
|
|
47
|
+
* import { Agent } from '@abloatai/ablo/agent';
|
|
48
48
|
*
|
|
49
49
|
* const perception = new Agent({
|
|
50
50
|
* syncServerUrl: 'http://localhost:8080',
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
* ```ts
|
|
79
79
|
* import { tool } from 'ai';
|
|
80
80
|
* import { z } from 'zod';
|
|
81
|
-
* import { Agent, type AgentContext } from '@ablo/
|
|
81
|
+
* import { Agent, type AgentContext } from '@abloatai/ablo/agent';
|
|
82
82
|
*
|
|
83
83
|
* export const updateSlideTool = () => tool({
|
|
84
84
|
* description: 'Update a slide title',
|
|
@@ -117,12 +117,12 @@
|
|
|
117
117
|
// `Agent` is the class AND the namespace for its types. Reach for
|
|
118
118
|
// options, context, and session options via dot access:
|
|
119
119
|
//
|
|
120
|
-
// import { Agent } from '@ablo/
|
|
120
|
+
// import { Agent } from '@abloatai/ablo/agent';
|
|
121
121
|
// const opts: Agent.Options = { ... };
|
|
122
122
|
// const ctx: Agent.Context = { perception };
|
|
123
123
|
// const s: Agent.SessionOptions = { ... };
|
|
124
124
|
//
|
|
125
125
|
// Everything else (Activity, Claim, Turn, Peer, ActiveIntent, ...)
|
|
126
126
|
// lives on the `Ablo.*` namespace via
|
|
127
|
-
// `import type { Ablo } from '@ablo
|
|
127
|
+
// `import type { Ablo } from '@abloatai/ablo'`.
|
|
128
128
|
export { Agent } from './Agent.js';
|
package/dist/agent/types.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export interface PresenceAnnouncer {
|
|
|
35
35
|
*
|
|
36
36
|
* ```ts
|
|
37
37
|
* import { generateText, tool } from 'ai';
|
|
38
|
-
* import { Agent, type AgentContext } from '@ablo/
|
|
38
|
+
* import { Agent, type AgentContext } from '@abloatai/ablo/agent';
|
|
39
39
|
*
|
|
40
40
|
* const updateSlideTool = () => tool({
|
|
41
41
|
* inputSchema: z.object({ id: z.string(), title: z.string() }),
|
package/dist/ai-sdk/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@ablo/
|
|
2
|
+
* `@abloatai/ablo/ai-sdk` — multiplayer-with-AI as language model
|
|
3
3
|
* middleware.
|
|
4
4
|
*
|
|
5
5
|
* Two cross-cutting middlewares for any AI SDK consumer using
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* import {
|
|
25
25
|
* intentBroadcastMiddleware,
|
|
26
26
|
* coordinationContextMiddleware,
|
|
27
|
-
* } from '@ablo/
|
|
27
|
+
* } from '@abloatai/ablo/ai-sdk';
|
|
28
28
|
*
|
|
29
29
|
* const target = { entityType: 'SlideDeck', entityId: 'deck-abc' };
|
|
30
30
|
*
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
* Or use the convenience composition for the common case:
|
|
49
49
|
*
|
|
50
50
|
* ```ts
|
|
51
|
-
* import { wrapWithMultiplayer } from '@ablo/
|
|
51
|
+
* import { wrapWithMultiplayer } from '@abloatai/ablo/ai-sdk';
|
|
52
52
|
*
|
|
53
53
|
* const wrappedModel = wrapWithMultiplayer({
|
|
54
54
|
* model: anthropic('claude-opus-4-7'),
|
package/dist/ai-sdk/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@ablo/
|
|
2
|
+
* `@abloatai/ablo/ai-sdk` — multiplayer-with-AI as language model
|
|
3
3
|
* middleware.
|
|
4
4
|
*
|
|
5
5
|
* Two cross-cutting middlewares for any AI SDK consumer using
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* import {
|
|
25
25
|
* intentBroadcastMiddleware,
|
|
26
26
|
* coordinationContextMiddleware,
|
|
27
|
-
* } from '@ablo/
|
|
27
|
+
* } from '@abloatai/ablo/ai-sdk';
|
|
28
28
|
*
|
|
29
29
|
* const target = { entityType: 'SlideDeck', entityId: 'deck-abc' };
|
|
30
30
|
*
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
* Or use the convenience composition for the common case:
|
|
49
49
|
*
|
|
50
50
|
* ```ts
|
|
51
|
-
* import { wrapWithMultiplayer } from '@ablo/
|
|
51
|
+
* import { wrapWithMultiplayer } from '@abloatai/ablo/ai-sdk';
|
|
52
52
|
*
|
|
53
53
|
* const wrappedModel = wrapWithMultiplayer({
|
|
54
54
|
* model: anthropic('claude-opus-4-7'),
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Open-source-clean: depends only on `@ai-sdk/provider` types and
|
|
13
13
|
* the package's own `SyncAgent`. No app-specific assumptions —
|
|
14
|
-
* Ablo's web app uses this, but so can any consumer of `@ablo
|
|
14
|
+
* Ablo's web app uses this, but so can any consumer of `@abloatai/ablo`.
|
|
15
15
|
*
|
|
16
16
|
* Cost: one WS frame at stream start (`intent_begin`), one at end
|
|
17
17
|
* (`intent_abandon`). No DB I/O, no extra LLM tokens.
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Open-source-clean: depends only on `@ai-sdk/provider` types and
|
|
13
13
|
* the package's own `SyncAgent`. No app-specific assumptions —
|
|
14
|
-
* Ablo's web app uses this, but so can any consumer of `@ablo
|
|
14
|
+
* Ablo's web app uses this, but so can any consumer of `@abloatai/ablo`.
|
|
15
15
|
*
|
|
16
16
|
* Cost: one WS frame at stream start (`intent_begin`), one at end
|
|
17
17
|
* (`intent_abandon`). No DB I/O, no extra LLM tokens.
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -63,7 +63,7 @@ export declare function resolveIdentity(options: ResolveIdentityRequest): Promis
|
|
|
63
63
|
/**
|
|
64
64
|
* Capability-token refresh scheduler.
|
|
65
65
|
*
|
|
66
|
-
* Long-lived `@ablo
|
|
66
|
+
* Long-lived `@abloatai/ablo` clients hold a server-issued capability
|
|
67
67
|
* token whose TTL (1h default) is shorter than typical browser sessions.
|
|
68
68
|
* Without proactive refresh, the WebSocket would either be force-closed
|
|
69
69
|
* by the server at expiry (code 1008) or fail its next reconnect with
|