@abloatai/ablo 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. package/CHANGELOG.md +208 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +12 -0
  4. package/README.md +230 -0
  5. package/dist/BaseSyncedStore.d.ts +709 -0
  6. package/dist/BaseSyncedStore.js +1843 -0
  7. package/dist/Database.d.ts +344 -0
  8. package/dist/Database.js +1259 -0
  9. package/dist/LazyReferenceCollection.d.ts +181 -0
  10. package/dist/LazyReferenceCollection.js +460 -0
  11. package/dist/Model.d.ts +339 -0
  12. package/dist/Model.js +715 -0
  13. package/dist/ModelRegistry.d.ts +200 -0
  14. package/dist/ModelRegistry.js +535 -0
  15. package/dist/NetworkMonitor.d.ts +27 -0
  16. package/dist/NetworkMonitor.js +73 -0
  17. package/dist/ObjectPool.d.ts +202 -0
  18. package/dist/ObjectPool.js +1106 -0
  19. package/dist/SyncClient.d.ts +489 -0
  20. package/dist/SyncClient.js +1555 -0
  21. package/dist/SyncEngineContext.d.ts +46 -0
  22. package/dist/SyncEngineContext.js +74 -0
  23. package/dist/adapters/alwaysOnline.d.ts +16 -0
  24. package/dist/adapters/alwaysOnline.js +19 -0
  25. package/dist/adapters/inMemoryStorage.d.ts +30 -0
  26. package/dist/adapters/inMemoryStorage.js +94 -0
  27. package/dist/agent/Agent.d.ts +358 -0
  28. package/dist/agent/Agent.js +500 -0
  29. package/dist/agent/index.d.ts +115 -0
  30. package/dist/agent/index.js +128 -0
  31. package/dist/agent/session.d.ts +90 -0
  32. package/dist/agent/session.js +156 -0
  33. package/dist/agent/types.d.ts +73 -0
  34. package/dist/agent/types.js +10 -0
  35. package/dist/ai-sdk/coordination-context.d.ts +51 -0
  36. package/dist/ai-sdk/coordination-context.js +107 -0
  37. package/dist/ai-sdk/index.d.ts +68 -0
  38. package/dist/ai-sdk/index.js +68 -0
  39. package/dist/ai-sdk/intent-broadcast.d.ts +77 -0
  40. package/dist/ai-sdk/intent-broadcast.js +72 -0
  41. package/dist/ai-sdk/wrap.d.ts +67 -0
  42. package/dist/ai-sdk/wrap.js +45 -0
  43. package/dist/api/index.d.ts +10 -0
  44. package/dist/api/index.js +9 -0
  45. package/dist/auth/index.d.ts +137 -0
  46. package/dist/auth/index.js +246 -0
  47. package/dist/client/Ablo.d.ts +835 -0
  48. package/dist/client/Ablo.js +1440 -0
  49. package/dist/client/ApiClient.d.ts +200 -0
  50. package/dist/client/ApiClient.js +659 -0
  51. package/dist/client/auth.d.ts +79 -0
  52. package/dist/client/auth.js +81 -0
  53. package/dist/client/createInternalComponents.d.ts +44 -0
  54. package/dist/client/createInternalComponents.js +88 -0
  55. package/dist/client/createModelProxy.d.ts +152 -0
  56. package/dist/client/createModelProxy.js +199 -0
  57. package/dist/client/identity.d.ts +63 -0
  58. package/dist/client/identity.js +156 -0
  59. package/dist/client/index.d.ts +36 -0
  60. package/dist/client/index.js +33 -0
  61. package/dist/client/persistence.d.ts +7 -0
  62. package/dist/client/persistence.js +11 -0
  63. package/dist/client/validateAbloOptions.d.ts +42 -0
  64. package/dist/client/validateAbloOptions.js +43 -0
  65. package/dist/config/index.d.ts +10 -0
  66. package/dist/config/index.js +12 -0
  67. package/dist/context.d.ts +27 -0
  68. package/dist/context.js +58 -0
  69. package/dist/core/DatabaseManager.d.ts +108 -0
  70. package/dist/core/DatabaseManager.js +361 -0
  71. package/dist/core/QueryProcessor.d.ts +77 -0
  72. package/dist/core/QueryProcessor.js +262 -0
  73. package/dist/core/QueryView.d.ts +64 -0
  74. package/dist/core/QueryView.js +219 -0
  75. package/dist/core/StoreManager.d.ts +131 -0
  76. package/dist/core/StoreManager.js +334 -0
  77. package/dist/core/ViewRegistry.d.ts +20 -0
  78. package/dist/core/ViewRegistry.js +55 -0
  79. package/dist/core/index.d.ts +34 -0
  80. package/dist/core/index.js +59 -0
  81. package/dist/core/openIDBWithTimeout.d.ts +27 -0
  82. package/dist/core/openIDBWithTimeout.js +63 -0
  83. package/dist/core/query-utils.d.ts +37 -0
  84. package/dist/core/query-utils.js +60 -0
  85. package/dist/errors.d.ts +235 -0
  86. package/dist/errors.js +243 -0
  87. package/dist/index.d.ts +41 -0
  88. package/dist/index.js +82 -0
  89. package/dist/interfaces/headless.d.ts +95 -0
  90. package/dist/interfaces/headless.js +41 -0
  91. package/dist/interfaces/index.d.ts +321 -0
  92. package/dist/interfaces/index.js +8 -0
  93. package/dist/mutators/RecordingTransaction.d.ts +36 -0
  94. package/dist/mutators/RecordingTransaction.js +216 -0
  95. package/dist/mutators/Transaction.d.ts +48 -0
  96. package/dist/mutators/Transaction.js +64 -0
  97. package/dist/mutators/UndoManager.d.ts +114 -0
  98. package/dist/mutators/UndoManager.js +143 -0
  99. package/dist/mutators/defineMutators.d.ts +55 -0
  100. package/dist/mutators/defineMutators.js +28 -0
  101. package/dist/policy/index.d.ts +19 -0
  102. package/dist/policy/index.js +18 -0
  103. package/dist/policy/types.d.ts +74 -0
  104. package/dist/policy/types.js +17 -0
  105. package/dist/principal.d.ts +44 -0
  106. package/dist/principal.js +49 -0
  107. package/dist/query/client.d.ts +43 -0
  108. package/dist/query/client.js +84 -0
  109. package/dist/query/index.d.ts +6 -0
  110. package/dist/query/index.js +5 -0
  111. package/dist/query/types.d.ts +143 -0
  112. package/dist/query/types.js +36 -0
  113. package/dist/react/AbloProvider.d.ts +205 -0
  114. package/dist/react/AbloProvider.js +398 -0
  115. package/dist/react/ClientSideSuspense.d.ts +36 -0
  116. package/dist/react/ClientSideSuspense.js +17 -0
  117. package/dist/react/DefaultFallback.d.ts +24 -0
  118. package/dist/react/DefaultFallback.js +43 -0
  119. package/dist/react/SyncGroupProvider.d.ts +19 -0
  120. package/dist/react/SyncGroupProvider.js +44 -0
  121. package/dist/react/context.d.ts +161 -0
  122. package/dist/react/context.js +35 -0
  123. package/dist/react/index.d.ts +64 -0
  124. package/dist/react/index.js +73 -0
  125. package/dist/react/internalContext.d.ts +35 -0
  126. package/dist/react/internalContext.js +3 -0
  127. package/dist/react/useAblo.d.ts +72 -0
  128. package/dist/react/useAblo.js +63 -0
  129. package/dist/react/useCurrentUserId.d.ts +21 -0
  130. package/dist/react/useCurrentUserId.js +33 -0
  131. package/dist/react/useErrorListener.d.ts +20 -0
  132. package/dist/react/useErrorListener.js +39 -0
  133. package/dist/react/useIntent.d.ts +29 -0
  134. package/dist/react/useIntent.js +42 -0
  135. package/dist/react/useMutate.d.ts +83 -0
  136. package/dist/react/useMutate.js +122 -0
  137. package/dist/react/useMutationFailureListener.d.ts +26 -0
  138. package/dist/react/useMutationFailureListener.js +38 -0
  139. package/dist/react/useMutators.d.ts +56 -0
  140. package/dist/react/useMutators.js +66 -0
  141. package/dist/react/usePresence.d.ts +32 -0
  142. package/dist/react/usePresence.js +41 -0
  143. package/dist/react/useQuery.d.ts +123 -0
  144. package/dist/react/useQuery.js +145 -0
  145. package/dist/react/useReactive.d.ts +35 -0
  146. package/dist/react/useReactive.js +111 -0
  147. package/dist/react/useReader.d.ts +69 -0
  148. package/dist/react/useReader.js +73 -0
  149. package/dist/react/useSyncStatus.d.ts +61 -0
  150. package/dist/react/useSyncStatus.js +76 -0
  151. package/dist/react/useUndoScope.d.ts +36 -0
  152. package/dist/react/useUndoScope.js +73 -0
  153. package/dist/realtime/index.d.ts +10 -0
  154. package/dist/realtime/index.js +9 -0
  155. package/dist/schema/field.d.ts +134 -0
  156. package/dist/schema/field.js +264 -0
  157. package/dist/schema/index.d.ts +29 -0
  158. package/dist/schema/index.js +38 -0
  159. package/dist/schema/model.d.ts +326 -0
  160. package/dist/schema/model.js +89 -0
  161. package/dist/schema/queries.d.ts +203 -0
  162. package/dist/schema/queries.js +145 -0
  163. package/dist/schema/relation.d.ts +172 -0
  164. package/dist/schema/relation.js +104 -0
  165. package/dist/schema/schema.d.ts +259 -0
  166. package/dist/schema/schema.js +188 -0
  167. package/dist/schema/sugar.d.ts +129 -0
  168. package/dist/schema/sugar.js +94 -0
  169. package/dist/source/index.d.ts +423 -0
  170. package/dist/source/index.js +320 -0
  171. package/dist/source/pushQueue.d.ts +112 -0
  172. package/dist/source/pushQueue.js +249 -0
  173. package/dist/stores/ObjectStore.d.ts +103 -0
  174. package/dist/stores/ObjectStore.js +371 -0
  175. package/dist/stores/ObjectStoreContract.d.ts +39 -0
  176. package/dist/stores/ObjectStoreContract.js +1 -0
  177. package/dist/stores/SyncActionStore.d.ts +101 -0
  178. package/dist/stores/SyncActionStore.js +481 -0
  179. package/dist/sync/BootstrapHelper.d.ts +127 -0
  180. package/dist/sync/BootstrapHelper.js +434 -0
  181. package/dist/sync/ConnectionManager.d.ts +136 -0
  182. package/dist/sync/ConnectionManager.js +465 -0
  183. package/dist/sync/HydrationCoordinator.d.ts +137 -0
  184. package/dist/sync/HydrationCoordinator.js +468 -0
  185. package/dist/sync/NetworkProbe.d.ts +43 -0
  186. package/dist/sync/NetworkProbe.js +113 -0
  187. package/dist/sync/OfflineFlush.d.ts +9 -0
  188. package/dist/sync/OfflineFlush.js +22 -0
  189. package/dist/sync/OfflineTransactionStore.d.ts +37 -0
  190. package/dist/sync/OfflineTransactionStore.js +263 -0
  191. package/dist/sync/SyncWebSocket.d.ts +663 -0
  192. package/dist/sync/SyncWebSocket.js +1336 -0
  193. package/dist/sync/createIntentStream.d.ts +33 -0
  194. package/dist/sync/createIntentStream.js +243 -0
  195. package/dist/sync/createPresenceStream.d.ts +46 -0
  196. package/dist/sync/createPresenceStream.js +192 -0
  197. package/dist/sync/createSnapshot.d.ts +33 -0
  198. package/dist/sync/createSnapshot.js +124 -0
  199. package/dist/sync/participants.d.ts +114 -0
  200. package/dist/sync/participants.js +336 -0
  201. package/dist/sync/schemas.d.ts +79 -0
  202. package/dist/sync/schemas.js +78 -0
  203. package/dist/testing/fixtures/bootstrap.d.ts +45 -0
  204. package/dist/testing/fixtures/bootstrap.js +53 -0
  205. package/dist/testing/fixtures/deltas.d.ts +86 -0
  206. package/dist/testing/fixtures/deltas.js +139 -0
  207. package/dist/testing/fixtures/models.d.ts +82 -0
  208. package/dist/testing/fixtures/models.js +270 -0
  209. package/dist/testing/helpers/react-wrapper.d.ts +66 -0
  210. package/dist/testing/helpers/react-wrapper.js +64 -0
  211. package/dist/testing/helpers/sync-engine-harness.d.ts +55 -0
  212. package/dist/testing/helpers/sync-engine-harness.js +70 -0
  213. package/dist/testing/helpers/wait.d.ts +25 -0
  214. package/dist/testing/helpers/wait.js +44 -0
  215. package/dist/testing/index.d.ts +21 -0
  216. package/dist/testing/index.js +32 -0
  217. package/dist/testing/mocks/MockMutationExecutor.d.ts +65 -0
  218. package/dist/testing/mocks/MockMutationExecutor.js +139 -0
  219. package/dist/testing/mocks/MockNetworkMonitor.d.ts +20 -0
  220. package/dist/testing/mocks/MockNetworkMonitor.js +46 -0
  221. package/dist/testing/mocks/MockSyncContext.d.ts +64 -0
  222. package/dist/testing/mocks/MockSyncContext.js +100 -0
  223. package/dist/testing/mocks/MockSyncStore.d.ts +88 -0
  224. package/dist/testing/mocks/MockSyncStore.js +171 -0
  225. package/dist/testing/mocks/MockWebSocket.d.ts +66 -0
  226. package/dist/testing/mocks/MockWebSocket.js +117 -0
  227. package/dist/transactions/OptimisticEchoTracker.d.ts +82 -0
  228. package/dist/transactions/OptimisticEchoTracker.js +104 -0
  229. package/dist/transactions/TransactionQueue.d.ts +499 -0
  230. package/dist/transactions/TransactionQueue.js +1895 -0
  231. package/dist/transactions/index.d.ts +16 -0
  232. package/dist/transactions/index.js +7 -0
  233. package/dist/transactions/mutation-error-handler.d.ts +5 -0
  234. package/dist/transactions/mutation-error-handler.js +39 -0
  235. package/dist/types/global.d.ts +107 -0
  236. package/dist/types/global.js +38 -0
  237. package/dist/types/index.d.ts +241 -0
  238. package/dist/types/index.js +70 -0
  239. package/dist/types/streams.d.ts +495 -0
  240. package/dist/types/streams.js +11 -0
  241. package/dist/utils/asyncIterator.d.ts +41 -0
  242. package/dist/utils/asyncIterator.js +142 -0
  243. package/dist/utils/duration.d.ts +28 -0
  244. package/dist/utils/duration.js +47 -0
  245. package/dist/utils/mobx-setup.d.ts +42 -0
  246. package/dist/utils/mobx-setup.js +381 -0
  247. package/docs/api-keys.md +24 -0
  248. package/docs/api.md +230 -0
  249. package/docs/audit.md +81 -0
  250. package/docs/capabilities.md +163 -0
  251. package/docs/client-behavior.md +202 -0
  252. package/docs/data-sources.md +214 -0
  253. package/docs/examples/agent-human.md +84 -0
  254. package/docs/examples/ai-sdk-tool.md +92 -0
  255. package/docs/examples/existing-python-backend.md +249 -0
  256. package/docs/examples/nextjs.md +88 -0
  257. package/docs/examples/server-agent.md +86 -0
  258. package/docs/guarantees.md +148 -0
  259. package/docs/index.md +97 -0
  260. package/docs/integration-guide.md +493 -0
  261. package/docs/interaction-model.md +140 -0
  262. package/docs/mcp/claude-code.md +43 -0
  263. package/docs/mcp/cursor.md +53 -0
  264. package/docs/mcp/windsurf.md +46 -0
  265. package/docs/mcp.md +59 -0
  266. package/docs/quickstart.md +152 -0
  267. package/docs/react.md +115 -0
  268. package/docs/roadmap.md +45 -0
  269. package/examples/README.md +54 -0
  270. package/examples/data-source/README.md +102 -0
  271. package/examples/data-source/ablo-driver.ts +89 -0
  272. package/examples/data-source/customer-server.ts +208 -0
  273. package/examples/data-source/run.ts +101 -0
  274. package/examples/data-source/schema.ts +25 -0
  275. package/examples/quickstart.ts +54 -0
  276. package/examples/tsconfig.json +16 -0
  277. package/llms.txt +143 -0
  278. package/package.json +147 -0
@@ -0,0 +1,88 @@
1
+ # Next.js Example
2
+
3
+ A production-shaped Next.js + Ablo Sync app. App Router, Server Actions, React
4
+ Server Components, and live client subscriptions.
5
+
6
+ ## Structure
7
+
8
+ ```txt
9
+ app/
10
+ tasks/
11
+ [id]/
12
+ page.tsx # RSC: retrieve + render
13
+ actions.ts # Server Action: schema update with stale-state check
14
+ TaskEditor.tsx # Client: live updates
15
+ lib/
16
+ ablo.ts # Schema-backed Ablo client for server actions
17
+ ```
18
+
19
+ ## RSC Initial Render
20
+
21
+ ```tsx
22
+ // app/tasks/[id]/page.tsx
23
+ import { ablo } from '@/lib/ablo';
24
+
25
+ export default async function TaskPage({
26
+ params,
27
+ }: { params: { id: string } }) {
28
+ await ablo.ready();
29
+ const [task] = await ablo.tasks.load({ where: { id: params.id } });
30
+ if (!task) return null;
31
+
32
+ return <TaskEditor task={task} />;
33
+ }
34
+ ```
35
+
36
+ ## Server Action Commit
37
+
38
+ ```ts
39
+ // app/tasks/[id]/actions.ts
40
+ 'use server';
41
+
42
+ import { ablo } from '@/lib/ablo';
43
+
44
+ export async function markDone(id: string) {
45
+ const busy = ablo.intents.list({ resource: 'tasks', id });
46
+ if (busy.length > 0) return { status: 'busy', intents: busy };
47
+
48
+ const snap = ablo.snapshot({ tasks: id });
49
+ const task = await ablo.tasks.update(
50
+ id,
51
+ { status: 'done' },
52
+ { readAt: snap.stamp, onStale: 'reject', wait: 'confirmed' },
53
+ );
54
+
55
+ return { status: 'done', task };
56
+ }
57
+ ```
58
+
59
+ If another participant commits between the read and the write, the commit
60
+ rejects. The action can re-fetch and ask the user to retry.
61
+
62
+ ## Live Client
63
+
64
+ ```tsx
65
+ 'use client';
66
+
67
+ import { useAblo } from '@ablo/sync-engine/react';
68
+
69
+ export function TaskEditor({ task: serverTask }: Props) {
70
+ const data = useAblo((ablo) => ablo.tasks.retrieve(serverTask.id)) ?? serverTask;
71
+ const intents = useAblo((ablo) =>
72
+ ablo.intents.list({ resource: 'tasks', id: serverTask.id }),
73
+ ) ?? [];
74
+ const busy = intents.length > 0;
75
+
76
+ return (
77
+ <button disabled={busy || data.status === 'done'}>
78
+ {busy ? 'Someone is editing' : 'Mark done'}
79
+ </button>
80
+ );
81
+ }
82
+ ```
83
+
84
+ ## More
85
+
86
+ - [Next.js landing](/nextjs) — the product overview.
87
+ - [React reference](/docs/react) — every option on `useAblo`.
88
+ - [API reference](/docs/api) — every option on the write path.
@@ -0,0 +1,86 @@
1
+ # Server Agent
2
+
3
+ Most server agents should import the app schema and use the same model methods
4
+ as the product UI.
5
+
6
+ ```ts
7
+ import Ablo from '@ablo/sync-engine';
8
+ import { defineSchema, model, z } from '@ablo/sync-engine/schema';
9
+
10
+ const schema = defineSchema({
11
+ tasks: model({
12
+ title: z.string(),
13
+ status: z.enum(['todo', 'doing', 'done']),
14
+ summary: z.string().optional(),
15
+ }),
16
+ });
17
+
18
+ const ablo = Ablo({
19
+ schema,
20
+ apiKey: process.env.ABLO_API_KEY,
21
+ });
22
+
23
+ export async function completeTask(taskId: string) {
24
+ await ablo.ready();
25
+
26
+ const [task] = await ablo.tasks.load({ where: { id: taskId } });
27
+ if (!task) return { status: 'not_found' };
28
+
29
+ const busy = ablo.intents.list({ resource: 'tasks', id: taskId });
30
+ if (busy.length > 0) {
31
+ return { status: 'busy', intents: busy };
32
+ }
33
+
34
+ const snap = ablo.snapshot({ tasks: taskId });
35
+ const updated = await ablo.tasks.update(
36
+ taskId,
37
+ { status: 'done' },
38
+ { readAt: snap.stamp, onStale: 'reject', wait: 'confirmed' },
39
+ );
40
+
41
+ return { status: 'done', task: updated };
42
+ }
43
+ ```
44
+
45
+ ## Advanced Schema-Less Run
46
+
47
+ Use `agent.run(...)` when the worker intentionally cannot import the app schema.
48
+ It creates the run envelope and returns `done`, `failed`, or `cancelled`.
49
+
50
+ ```ts
51
+ const api = Ablo({ apiKey: process.env.ABLO_API_KEY });
52
+
53
+ const result = await api.agent('task-writer', {
54
+ can: ['tasks.retrieve', 'tasks.update'],
55
+ syncGroups: ['workspace:acme'],
56
+ }).run(
57
+ {
58
+ prompt: 'Mark task_123 done.',
59
+ surface: 'agent_worker',
60
+ },
61
+ async ({ resource }) => {
62
+ const tasks = resource<{ title: string; status: string }>('tasks');
63
+
64
+ const { data, stamp, intents } = await tasks.retrieve('task_123', {
65
+ ifBusy: 'return',
66
+ });
67
+
68
+ if (intents.length > 0) {
69
+ return { skipped: true, reason: 'busy' };
70
+ }
71
+
72
+ return tasks.update(
73
+ 'task_123',
74
+ { status: 'done' },
75
+ { readAt: stamp, onStale: 'reject', wait: 'confirmed' },
76
+ );
77
+ },
78
+ );
79
+
80
+ if (result.status === 'failed') throw result.error;
81
+ if (result.status === 'cancelled') return;
82
+ ```
83
+
84
+ Use the schema-backed version first. The schema-less version is for generic
85
+ agent infrastructure, MCP routes, and platform code.
86
+
@@ -0,0 +1,148 @@
1
+ # Guarantees
2
+
3
+ This page is the short contract for what Ablo Sync guarantees at the state
4
+ boundary.
5
+
6
+ ## Confirmed Writes
7
+
8
+ `wait: 'confirmed'` resolves only after the server accepts the write and returns
9
+ the authoritative sync cursor.
10
+
11
+ ```ts
12
+ const updated = await ablo.tasks.update(
13
+ 'task_123',
14
+ { status: 'done' },
15
+ { wait: 'confirmed' },
16
+ );
17
+ ```
18
+
19
+ If the call resolves, the write was accepted by the server. If it rejects, the
20
+ error explains whether the write was rejected for auth, validation, stale state,
21
+ active intent conflict, idempotency, rate limit, or transport failure.
22
+
23
+ Schema model writes return the updated model row. Advanced resource writes and
24
+ `commits.create(...)` return a receipt with the commit status and sync cursor.
25
+
26
+ ## Optimistic Local State
27
+
28
+ Schema model writes update local state optimistically. This keeps UI and agent
29
+ tools responsive while the commit is sent to the server.
30
+
31
+ - With `wait: 'queued'` or omitted, the promise resolves after the local mutation
32
+ is queued.
33
+ - With `wait: 'confirmed'`, the promise waits for server confirmation.
34
+ - If the server rejects the write, the SDK rolls back the optimistic change and
35
+ raises a typed error.
36
+
37
+ The server remains the source of truth.
38
+
39
+ ## Stale-Write Protection
40
+
41
+ Use `snapshot(...)` and `readAt` when a write depends on state the agent already
42
+ read:
43
+
44
+ ```ts
45
+ const snap = ablo.snapshot({ tasks: 'task_123' });
46
+
47
+ await ablo.tasks.update(
48
+ 'task_123',
49
+ { status: 'done' },
50
+ { readAt: snap.stamp, onStale: 'reject', wait: 'confirmed' },
51
+ );
52
+ ```
53
+
54
+ `onStale: 'reject'` prevents lost updates. If the target changed after the
55
+ snapshot, the server rejects the write instead of applying stale reasoning.
56
+
57
+ Advanced policies exist for controlled product flows:
58
+
59
+ - `reject` fails the write when state moved.
60
+ - `force` applies the write without stale protection.
61
+ - `flag` accepts the write and marks it for product review.
62
+ - `merge` is reserved for server-defined merge behavior.
63
+
64
+ ## Intent Coordination
65
+
66
+ Intents are live coordination signals. They are not database locks.
67
+
68
+ When another human or agent is active on the same target, the caller chooses the
69
+ behavior:
70
+
71
+ - `ifBusy: 'return'` returns active intents immediately.
72
+ - `ifBusy: 'wait'` waits until the matching intent clears.
73
+ - `ifBusy: 'fail'` throws `AbloBusyError` with the active intents attached.
74
+
75
+ Schema clients wait from the realtime intent stream. Schema-less HTTP callers
76
+ must pass an explicit `busyPollInterval` if they choose `ifBusy: 'wait'`; Ablo
77
+ does not hide a hard-coded polling loop. `busyTimeout` is only a maximum wait.
78
+
79
+ ## Agent Runs
80
+
81
+ `agent.run(...)` is the advanced schema-less run envelope for workers that cannot
82
+ import the app schema. It returns one of three statuses:
83
+
84
+ - `done` — the handler returned successfully.
85
+ - `failed` — the handler threw or the commit failed.
86
+ - `cancelled` — the run signal aborted.
87
+
88
+ Normal schema-backed agents should import the same schema as the app and write
89
+ through `ablo.<model>.update(...)`. The lower-level run envelope exists for
90
+ platform runtimes that need capability and task management without app code.
91
+
92
+ ## Capabilities and Tasks
93
+
94
+ Capabilities scope what an agent is allowed to do. Tasks group a run for audit
95
+ and cost attribution.
96
+
97
+ Most users do not create either one manually. The SDK and hosted API manage the
98
+ common case. Manual capability and task APIs are for platform builders, custom
99
+ agent runtimes, and internal infrastructure.
100
+
101
+ Use `lease` as a crash cleanup window. A successful agent run still closes when
102
+ the handler returns, fails, or is cancelled.
103
+
104
+ ## Audit Trail
105
+
106
+ Accepted writes can be attributed to:
107
+
108
+ - the actor that wrote,
109
+ - the human or system the actor worked on behalf of,
110
+ - the capability that scoped the write,
111
+ - the task or run that caused it,
112
+ - the resource, operation, and state cursor.
113
+
114
+ For agent work, this is what lets an audit surface answer: "what changed, who
115
+ authorized it, which run did it, and what state was it based on?"
116
+
117
+ ## Persistence
118
+
119
+ Ablo defaults to volatile local persistence. That keeps the SDK focused on
120
+ coordination and audit instead of silently becoming a browser storage product.
121
+
122
+ Opt into durable browser cache and offline queueing when you need it:
123
+
124
+ ```ts
125
+ const ablo = Ablo({
126
+ schema,
127
+ apiKey: process.env.ABLO_API_KEY,
128
+ persistence: 'indexeddb',
129
+ });
130
+ ```
131
+
132
+ Node, SSR, tests, and agents use volatile in-memory persistence automatically.
133
+
134
+ ## Storage Boundary
135
+
136
+ Ablo does not need a customer database URL. When your own database is canonical,
137
+ Ablo calls a signed Data Source endpoint and records the coordination result for
138
+ receipts, realtime fanout, and audit. See [Connect Your Database](./data-sources.md).
139
+
140
+ ## Batches
141
+
142
+ Most apps should use `ablo.<model>.create/update/delete`. Use
143
+ `commits.create(...)` only when you need a low-level batch or a schema-less
144
+ runtime.
145
+
146
+ Each operation in the commit carries its own target, data, stale policy, and
147
+ idempotency context. The server validates authorization, stale state, active
148
+ intent conflicts, and idempotency before accepting the commit.
package/docs/index.md ADDED
@@ -0,0 +1,97 @@
1
+ # Ablo Docs
2
+
3
+ Ablo is a state control API for **humans and AI agents editing the same
4
+ typed state in real time, with attribution, conflict handling, and
5
+ fast cutoff**.
6
+
7
+ It gives agents a narrow way to write production state: declare models, load current state, coordinate active work, and write with stale-state checks. Capabilities, tasks, commits, and receipts are the protocol underneath, not first-integration ceremony.
8
+
9
+ Multiplayer is not a separate product mode. If humans, server actions, and agents
10
+ use the same `Ablo({ schema, apiKey })` client and write through
11
+ `ablo.<model>`, Ablo fans out confirmed deltas, exposes active intents, and
12
+ rejects stale writes for every participant.
13
+
14
+ ## What you get, in three commitments
15
+
16
+ These commitments drive every design choice in the rest of the docs; if
17
+ they don't match what you're building, the trade-offs land elsewhere
18
+ (Replicache, ElectricSQL, PowerSync for human-only real-time; Zero for
19
+ query-shaped sync).
20
+
21
+ - **One model API for every actor.** `ablo.<model>.update(...)` is the
22
+ call from React components, server actions, background workers, and
23
+ AI agents alike. No separate "agent SDK," no parallel mutation path.
24
+ Attribution comes from the credential, not the call site.
25
+ - **Server owns the scope convention.** Tenancy / per-entity scope
26
+ prefixes (`org:`, `deck:`, or your own `region:` / `customer:`) are
27
+ declared once on the schema's `identityRoles`. Consumer code never
28
+ composes group strings. Same boundary Liveblocks (`prepareSession`),
29
+ PowerSync (named streams), and Zero (synced queries) settled on.
30
+ - **Capabilities, not API keys, for agents.** Per-run, per-scope, leased
31
+ credentials with per-request signature verification and instant
32
+ revocation. The 2025-26 AI-agent auth consensus (OAuth 2.1 / MCP,
33
+ AWS STS, Vault leases, Auth0 Token Vault) converged on this shape;
34
+ capabilities are Ablo's instance. See
35
+ [Capabilities](./capabilities.md#why-capabilities-not-api-keys) for
36
+ the design rationale.
37
+
38
+ ## Start here
39
+
40
+ - [Quickstart](./quickstart.md) — Make your first schema-backed write.
41
+ - [Integration Guide](./integration-guide.md) — Choose Ablo-managed state, Data Source, React, multiplayer, and agent patterns.
42
+ - [Guarantees](./guarantees.md) — What confirmed writes, stale checks, and intents guarantee.
43
+ - [Interaction Model](./interaction-model.md) — The commit plane and control plane.
44
+ - [API Reference](./api.md) — Resource-by-resource method shape.
45
+ - [Client Behavior](./client-behavior.md) — Options, errors, retries, timeouts, and imports.
46
+ - [Connect Your Database](./data-sources.md) — Keep canonical rows in your app database without giving Ablo database credentials.
47
+ - [API Keys](./api-keys.md) — Bearer tokens for the public API.
48
+
49
+ ## API shape
50
+
51
+ | Plane | Primitives | Purpose |
52
+ |---|---|---|
53
+ | State | `Schema`, `Model`, `Intent`, `Receipt` | The product path. Load, coordinate, write, confirm. |
54
+ | Commit | `Resource`, `Commit` | Advanced protocol path for custom runtimes and batches. |
55
+ | Control | `Capability`, `Task`, `Usage` | The authority path. Scope, attribute, meter, audit. |
56
+ | Storage | `Managed State`, `Data Source` | Ablo stores declared models by default; existing app tables use a signed Data Source. |
57
+
58
+ ## Use cases
59
+
60
+ - **Let agents write to shared state** — Give an AI agent scoped, revocable write access to your typed data.
61
+ - **Coordinate multiple actors** — Use intents to broadcast pre-write declarations across humans and agents.
62
+ - **Audit every agent action** — Trace any write back to a human in one query.
63
+ - **Build collaborative editors** — Humans and agents on the same record, with realtime updates and stale-read protection.
64
+ - **Meter and gate API usage** — Per-key, per-team usage reports and quota enforcement.
65
+ - **Integrate with A2A and MCP** — Speak the same protocols as Claude, Cursor, Gemini.
66
+
67
+ ## Concepts
68
+
69
+ - [Model Methods](./api.md#model-methods) — Load and write typed state.
70
+ - [Integration Guide](./integration-guide.md) — The normal app path and optional pieces.
71
+ - [Guarantees](./guarantees.md) — Confirmed writes, optimistic state, stale-write protection, and agent lifecycle.
72
+ - [Intent](./api.md#intent) — Broadcast proposed work before committing.
73
+ - [Advanced Commit API](./api.md#advanced-commit-api) — Apply custom batch mutations.
74
+ - [Connect Your Database](./data-sources.md) — Where data lands when your app database is canonical.
75
+ - [Receipt](./api.md#receipt) — Confirm what landed.
76
+ - [Capability](./api.md#capability) — Signed credentials for a bounded actor, operation set, sync group, and lease.
77
+ - [Task](./api.md#task) — One agent run; the audit envelope for commits and cost.
78
+ - [Usage](./api.md#usage) — Metering and audit dimensions.
79
+
80
+ ## Examples
81
+
82
+ - [AI SDK Tool](./examples/ai-sdk-tool.md) — Put Ablo inside an AI SDK tool call.
83
+ - [Existing Python Backend](./examples/existing-python-backend.md) — Add multiplayer and future agent writes without replacing a Python API server.
84
+ - [Agent + Human](./examples/agent-human.md) — Yield when a human is editing the same task.
85
+ - [Server Agent](./examples/server-agent.md) — Schema-backed worker plus advanced schema-less run.
86
+ - [Next.js](./examples/nextjs.md) — App-router setup with React bindings.
87
+
88
+ ## Runtime builds
89
+
90
+ - `@ablo/sync-engine` — schema-powered sync client for typed model operations, realtime, intents, and receipts.
91
+ - `Ablo({ apiKey })` — advanced resource client for runtimes that intentionally cannot import a schema.
92
+
93
+ ## More
94
+
95
+ - [README](../README.md) — product overview and first example.
96
+ - [AGENTS.md](../AGENTS.md) — short installation guidance for coding assistants.
97
+ - [Changelog](../CHANGELOG.md) — what shipped recently.