@abloatai/ablo 0.9.3 → 0.9.5
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 +12 -0
- package/README.md +8 -6
- package/dist/BaseSyncedStore.d.ts +5 -2
- package/dist/BaseSyncedStore.js +15 -14
- package/dist/Database.js +7 -1
- package/dist/SyncClient.d.ts +8 -0
- package/dist/SyncClient.js +9 -0
- package/dist/cli.cjs +9474 -29723
- package/dist/client/Ablo.js +8 -1
- package/dist/client/auth.d.ts +1 -1
- package/dist/client/auth.js +14 -5
- package/dist/errorCodes.d.ts +1 -0
- package/dist/errorCodes.js +1 -0
- package/dist/schema/ddl.js +10 -2
- package/dist/schema/model.d.ts +9 -7
- package/dist/schema/model.js +1 -1
- package/dist/schema/schema.js +7 -1
- package/dist/sync/syncPosition.d.ts +78 -0
- package/dist/sync/syncPosition.js +111 -0
- package/dist/transactions/TransactionQueue.d.ts +16 -1
- package/dist/transactions/TransactionQueue.js +43 -25
- package/docs/api-keys.md +4 -4
- package/docs/cli.md +6 -6
- package/docs/quickstart.md +21 -2
- package/llms-full.txt +19 -5
- package/llms.txt +5 -3
- package/package.json +5 -3
package/llms-full.txt
CHANGED
|
@@ -142,10 +142,22 @@ This applies to any API-backed app: Python, Rails, Go, or Node. The backend keep
|
|
|
142
142
|
its service layer and DB credentials. Ablo gets a Data Source endpoint and uses
|
|
143
143
|
`ABLO_API_KEY`, not a database URL.
|
|
144
144
|
|
|
145
|
+
When the user DOES use the connection-string path (`Ablo({ databaseUrl })` /
|
|
146
|
+
`DATABASE_URL` at init): the role must be NON-superuser and NON-BYPASSRLS —
|
|
147
|
+
Ablo enforces row-level security and rejects owner roles with
|
|
148
|
+
`database_role_cannot_enforce_rls`. Neon's and Supabase's default dashboard
|
|
149
|
+
strings use the database OWNER (e.g. `neondb_owner`) and ARE rejected. EASIEST: have the user run `npx ablo migrate` — it detects the unsafe role and creates the scoped one automatically from their machine (owner credential never reaches Ablo; new DATABASE_URL written to the env file). Manual alternative — create a scoped role first (`CREATE ROLE ablo_app LOGIN PASSWORD '...'
|
|
150
|
+
NOSUPERUSER NOBYPASSRLS; GRANT CREATE, CONNECT ON DATABASE <db> TO ablo_app;
|
|
151
|
+
GRANT CREATE, USAGE ON SCHEMA public TO ablo_app;`), then swap user/password
|
|
152
|
+
into the same host/db string.
|
|
153
|
+
|
|
145
154
|
## Client Behavior
|
|
146
155
|
|
|
147
|
-
|
|
148
|
-
`
|
|
156
|
+
The options that matter: `schema` and `apiKey`. Everything else
|
|
157
|
+
(`persistence`, `logger`, transport tuning) has correct defaults — do NOT set
|
|
158
|
+
`baseURL`; the default already routes to the hosted API, and overriding it
|
|
159
|
+
breaks the connection. It exists only for self-hosted/proxy setups the human
|
|
160
|
+
explicitly asks for.
|
|
149
161
|
|
|
150
162
|
There is intentionally no `databaseURL` option on `Ablo(...)`. Application and
|
|
151
163
|
agent code use `ABLO_API_KEY`. Customer-owned app databases stay private behind
|
|
@@ -171,7 +183,7 @@ There are two sandbox surfaces:
|
|
|
171
183
|
making real Ablo calls. It is agent-first: it should expose a prompt that can
|
|
172
184
|
be pasted into Claude Code or Codex to wire one real model through Ablo.
|
|
173
185
|
- Authenticated org sandboxes are real test environments. The default sandbox is
|
|
174
|
-
the Stripe-style
|
|
186
|
+
the Stripe-style sandbox for an org. It has an isolated sync group prefix,
|
|
175
187
|
can mint `sk_test_*` keys, and can be reset without touching live state.
|
|
176
188
|
|
|
177
189
|
Additional org sandboxes can start blank or copy live configuration. Keep
|
|
@@ -190,8 +202,10 @@ Use these public environment names:
|
|
|
190
202
|
- `ABLO_API_KEY` — SDK authentication for app and agent code. Where it comes
|
|
191
203
|
from: the human runs `npx ablo login` once (browser; an agent must not run
|
|
192
204
|
it), and `npx ablo dev` then writes `ABLO_API_KEY=sk_test_…` into
|
|
193
|
-
`.env.local` automatically. Check the environment and
|
|
194
|
-
|
|
205
|
+
`.env.local` automatically (and gitignores it). Check the environment and
|
|
206
|
+
`.env.local` for PRESENCE only (`grep -cq '^ABLO_API_KEY=' .env.local`)
|
|
207
|
+
before asking the human for a key — never print or echo the key value; a
|
|
208
|
+
secret in agent output lives in the conversation history forever.
|
|
195
209
|
|
|
196
210
|
Do not ask customers to paste their app database URL into Ablo. If their app
|
|
197
211
|
database is canonical, they expose a Data Source endpoint and keep database
|
package/llms.txt
CHANGED
|
@@ -10,9 +10,9 @@ Use AI SDK for the agent loop. Use Ablo when agent reads and writes must persist
|
|
|
10
10
|
|
|
11
11
|
First action when integrating into an app: run `npx ablo init --yes --framework <nextjs|vite|remix|vanilla> --storage datasource`. Agents have no TTY — `--yes` is REQUIRED or it HANGS. It scaffolds `ablo/schema.ts`, the client, the Data Source endpoint, and (for Next.js) the browser provider + session route, all on the current API. Edit the generated files rather than hand-writing from this doc.
|
|
12
12
|
|
|
13
|
-
Second: make sure a key exists. Check `ABLO_API_KEY`
|
|
13
|
+
Second: make sure a key exists — WITHOUT printing it. The key is a secret; it must never appear in your output, your reasoning, or a file you echo (it would live in the conversation history forever). Check PRESENCE only: `[ -n "$ABLO_API_KEY" ] && echo set` and `grep -cq '^ABLO_API_KEY=' .env.local && echo wired` — never `cat .env.local`, never `echo $ABLO_API_KEY`. If neither check passes, ask the HUMAN to run `npx ablo login` once — it opens a browser and saves a `sk_test_` key locally; an agent must NOT run it. You never copy the key by hand: the next step writes it into `.env.local` (and gitignores it) for you.
|
|
14
14
|
|
|
15
|
-
Then PUSH — this is the step everything depends on. The server keeps its OWN copy of the schema. Run `npx ablo dev --no-watch`: it pushes `ablo/schema.ts` (
|
|
15
|
+
Then PUSH — this is the step everything depends on. The server keeps its OWN copy of the schema. Run `npx ablo dev --no-watch`: it pushes `ablo/schema.ts` (sandbox) AND writes `ABLO_API_KEY` into `.env.local` from the stored login. Until the schema is pushed, EVERY write to a new or changed model fails with `server_execute_unknown_model`. Re-run it after schema changes (`npx ablo push` also works once the key is wired; bare `npx ablo dev` watches forever — don't, you have no TTY).
|
|
16
16
|
|
|
17
17
|
## Use this API
|
|
18
18
|
|
|
@@ -120,6 +120,8 @@ Do not add `databaseURL` to `Ablo(...)`. Application and agent code use `ABLO_AP
|
|
|
120
120
|
|
|
121
121
|
Every schema model is backed by a database, and the default is YOUR OWN. Keep your rows in your Postgres and expose a Data Source endpoint that hands Ablo an ORM `adapter` (Drizzle is the default; Prisma and Kysely are also supported) — it owns the transaction, exactly-once idempotency, and outbox in ONE pass (no hand-written `commit`/`events`). Your `DATABASE_URL` lives in your app, never in `Ablo(...)`; run `npx ablo migrate` to provision the synced-model tables in your DB.
|
|
122
122
|
|
|
123
|
+
GOTCHA the user WILL hit: `DATABASE_URL` must use a NON-superuser, NON-BYPASSRLS role (Ablo enforces row-level security; owner roles are rejected with `database_role_cannot_enforce_rls`). Neon's and Supabase's default dashboard connection strings use the database OWNER (e.g. `neondb_owner`) and are rejected. EASIEST: `npx ablo migrate` detects the unsafe role and creates the scoped one automatically from the user's machine (owner credential never reaches Ablo; new DATABASE_URL written to the env file). Manual alternative — create a scoped role first: `CREATE ROLE ablo_app LOGIN PASSWORD '...' NOSUPERUSER NOBYPASSRLS; GRANT CREATE, CONNECT ON DATABASE <db> TO ablo_app; GRANT CREATE, USAGE ON SCHEMA public TO ablo_app;` — then swap user/password into the same host/db string.
|
|
124
|
+
|
|
123
125
|
```ts
|
|
124
126
|
// app/api/ablo/source/route.ts
|
|
125
127
|
import { dataSourceNext } from '@abloatai/ablo/source/next';
|
|
@@ -179,6 +181,6 @@ Do not teach `/api`, `/agent`, `/ai-sdk`, `/core`, `/realtime`, or internal subp
|
|
|
179
181
|
- `npx ablo init --yes` (flags: `--framework`, `--auth`, `--storage`, `--no-agent`, `--no-pull`, `--no-install`, `--no-login`). Generates `ablo/schema.ts` + the `ablo/data-source.ts` endpoint above.
|
|
180
182
|
- Key: see "Start here" — env → `.env.local` → ask the human to `npx ablo login`; never run `login` yourself, never copy keys by hand (`ablo dev` writes `.env.local`).
|
|
181
183
|
- Adopt an existing DB: `npx ablo pull prisma [path]` / `npx ablo pull drizzle <module>`.
|
|
182
|
-
- `npx ablo dev --no-watch` pushes the schema (
|
|
184
|
+
- `npx ablo dev --no-watch` pushes the schema (sandbox) AND writes `ABLO_API_KEY` to `.env.local` (default watches forever); `npx ablo logs --no-follow` (default tails forever); `npx ablo mode sandbox|production` (always pass the arg). `npx ablo push`/`status`/`pull`/`check`/`generate` are one-shot.
|
|
183
185
|
|
|
184
186
|
Canonical docs to read before integrating: `quickstart`, `schema-contract`, `integration-guide`, `guarantees`, `client-behavior`, `data-sources`, `examples/existing-python-backend`, `api`, `examples/ai-sdk-tool`, and `examples/server-agent`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abloatai/ablo",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.5",
|
|
4
4
|
"description": "State control API for AI agents and collaborative apps.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -134,6 +134,7 @@
|
|
|
134
134
|
"check:dist": "node scripts/check-dist-fresh.mjs",
|
|
135
135
|
"pretest": "node scripts/check-dist-fresh.mjs",
|
|
136
136
|
"test": "jest",
|
|
137
|
+
"test:quickstart": "node scripts/test-quickstart.mjs",
|
|
137
138
|
"test:unit": "jest --testPathPattern=__tests__/unit",
|
|
138
139
|
"test:integration": "jest --testPathPattern=__tests__/integration",
|
|
139
140
|
"test:contract": "jest --testPathPattern=__tests__/contract",
|
|
@@ -183,10 +184,11 @@
|
|
|
183
184
|
}
|
|
184
185
|
},
|
|
185
186
|
"dependencies": {
|
|
187
|
+
"jiti": "^2.7.0",
|
|
186
188
|
"mobx": "^6.13.7",
|
|
187
189
|
"mobx-react-lite": "^4.0.0",
|
|
188
|
-
"
|
|
189
|
-
"
|
|
190
|
+
"uuid": "^11.1.0",
|
|
191
|
+
"zod": "^4.0.17"
|
|
190
192
|
},
|
|
191
193
|
"devDependencies": {
|
|
192
194
|
"@ai-sdk/provider": "^3.0.0",
|