@vibes.diy/prompts 14.3.8 → 14.3.9

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/llms/backend.md CHANGED
@@ -675,10 +675,24 @@ upstream that can be down, input that can be malformed — catches it and answer
675
675
  `{ ok: false, reason }` with a status the app can show, and the platform's 500
676
676
  stays the signal for a bug to fix.
677
677
 
678
+ `/_api` opens to every caller once the app is published. Before its first
679
+ publish, and after the owner unpublishes it, the routes answer the app's own
680
+ people — its owner, its developers, and anyone it is shared with — and
681
+ everyone else gets `404 backend.js _api: not found` without the handler
682
+ running. The page reaches its own routes in every state through `apiFetch`
683
+ (below), which arrives as the signed-in visitor. `call_own_api`, `onChange`
684
+ and `scheduled` keep running, and a connected GitHub webhook runs until the
685
+ owner unpublishes.
686
+
678
687
  ### Who is calling: `ctx.userInfo` comes from the request, never a cookie
679
688
 
680
- Cookies are not read. `ctx.userInfo` is filled in two ways:
689
+ Cookies are not read. `ctx.userInfo` is filled in three ways:
681
690
 
691
+ - **The app's own page, through `apiFetch`** from `use-vibes`. The platform
692
+ makes the call for the signed-in visitor, so the handler runs as them:
693
+ `ctx.userInfo` is that visitor, their `ctx.db` writes pass `access.js` as
694
+ them, and `ctx.connections` spends their connection. A visitor who is not
695
+ signed in arrives as `ctx.userInfo === null`.
682
696
  - **A caller outside the app** — a script, another agent, a server — sends the
683
697
  person's vibes.diy token as `Authorization: Bearer <token>`. A missing,
684
698
  expired or unrecognised token is not an error: the handler runs with
@@ -686,13 +700,29 @@ Cookies are not read. `ctx.userInfo` is filled in two ways:
686
700
  - **The builder's own `call_own_api` check** (see the debugging skill) arrives
687
701
  already verified, as the app's owner, with no bearer header.
688
702
 
689
- A plain `fetch("/_api/...")` from `App.jsx` sends neither, so for that call the
690
- handler sees `ctx.userInfo === null`. That is exactly right for the routes the
691
- app calls for server work — reading a page, calling a service with a secret —
692
- which should not depend on who is asking. For anything that depends on the
693
- signed-in person (their own records, their permissions), build the screen on
694
- the database hooks, which already know who is signed in; a button that "tests
695
- the API" from inside the app is testing the anonymous path.
703
+ A plain `fetch("/_api/...")` from `App.jsx` carries no visitor, so the handler
704
+ sees `ctx.userInfo === null`. That suits routes that should not depend on who
705
+ is asking — reading a page, calling a service with a secret. **When a route
706
+ needs to know the visitor — their own records, their connection, their
707
+ permissions — the page calls it with `apiFetch`.** The path is the route under
708
+ `/_api`, and the answer reads like a `Response`:
709
+
710
+ ```jsx file=App.jsx partial
711
+ import { apiFetch } from "use-vibes";
712
+
713
+ const res = await apiFetch("/my-rsvp", {
714
+ method: "POST",
715
+ headers: { "content-type": "application/json" },
716
+ body: JSON.stringify({ going: true }),
717
+ });
718
+ const mine = res.ok ? await res.json() : null;
719
+ ```
720
+
721
+ A route's own error status resolves with `ok: false`; `apiFetch` rejects only
722
+ when the route could not be reached. Bodies are strings, and answers are for
723
+ JSON-sized results rather than exports. Screens that simply list the visitor's
724
+ own records still read best from the database hooks, which already know who is
725
+ signed in.
696
726
 
697
727
  Writes a handler makes with `ctx.db.put` still pass through `access.js` as the
698
728
  caller, so the app's rules hold for API writes too.
@@ -88,7 +88,7 @@ function TaskCard({ task, database, can, onCorrect, onSaved, disabled }) {
88
88
  }
89
89
 
90
90
  export default function App() {
91
- const { database, useLiveQuery } = useFireproof("tasks");
91
+ const { database, useLiveQuery, writeRejection, clearWriteRejection } = useFireproof("tasks");
92
92
  const { me, can, ready } = useVibe("tasks");
93
93
  const { docs } = useLiveQuery("type", { key: "task" });
94
94
  const [sentence, setSentence] = useState("");
@@ -170,6 +170,7 @@ export default function App() {
170
170
  </form>
171
171
  <p>{answer}</p>
172
172
  <p role="status">{message}</p>
173
+ {writeRejection && <p role="status">{writeRejection.message} <button type="button" onClick={clearWriteRejection}>Dismiss</button></p>}
173
174
  {lastWrite !== undefined && <button type="button" disabled={busy} onClick={undoLast}>Undo</button>}
174
175
  {pending !== undefined && !busy && <button type="button" onClick={() => { setPending(undefined); setSentence(""); setCurrent(undefined); }}>Discard unsaved tasks</button>}
175
176
  {docs.map((task) => <TaskCard key={task._id} task={task} database={database} can={can} disabled={busy || pending !== undefined} onSaved={(previous) => setLastWrite({ created: [], replaced: previous })} onCorrect={(doc) => { if (busy || pending !== undefined) return; setCurrent(doc); setSentence(""); }} />)}
package/llms/callai.md CHANGED
@@ -88,7 +88,7 @@ function TaskCard({ task, database, can, onCorrect, onSaved, disabled }) {
88
88
  }
89
89
 
90
90
  export default function App() {
91
- const { database, useLiveQuery } = useFireproof("tasks");
91
+ const { database, useLiveQuery, writeRejection, clearWriteRejection } = useFireproof("tasks");
92
92
  const { me, can, ready } = useVibe("tasks");
93
93
  const { docs } = useLiveQuery("type", { key: "task" });
94
94
  const [sentence, setSentence] = useState("");
@@ -170,6 +170,7 @@ export default function App() {
170
170
  </form>
171
171
  <p>{answer}</p>
172
172
  <p role="status">{message}</p>
173
+ {writeRejection && <p role="status">{writeRejection.message} <button type="button" onClick={clearWriteRejection}>Dismiss</button></p>}
173
174
  {lastWrite !== undefined && <button type="button" disabled={busy} onClick={undoLast}>Undo</button>}
174
175
  {pending !== undefined && !busy && <button type="button" onClick={() => { setPending(undefined); setSentence(""); setCurrent(undefined); }}>Discard unsaved tasks</button>}
175
176
  {docs.map((task) => <TaskCard key={task._id} task={task} database={database} can={can} disabled={busy || pending !== undefined} onSaved={(previous) => setLastWrite({ created: [], replaced: previous })} onCorrect={(doc) => { if (busy || pending !== undefined) return; setCurrent(doc); setSentence(""); }} />)}
@@ -27,7 +27,8 @@ a public profile) is an ordinary `ctx.fetch` and needs no connection.
27
27
 
28
28
  **Declare the provider in `config.connections`, render the Connect button from
29
29
  `useConnection`, and read the account through `@vibes.diy/social` or
30
- `ctx.connections` in `backend.js`.** All three, every time.
30
+ `ctx.connections` in `backend.js`.** All three, every time — and the page
31
+ reaches the third with `apiFetch` (section 4), so it runs as the visitor.
31
32
 
32
33
  ### 1. Declare it — `backend.js`
33
34
 
@@ -172,10 +173,63 @@ with the credential attached by the platform, and
172
173
  `await ctx.connections.status(provider)` returns
173
174
  `{ state, consented, expiresAt?, accountLabel? }` without spending a call.
174
175
 
175
- **Whose account?** In a `fetch` handler it is the signed-in visitor who called
176
- the route; in `scheduled` it is the app owner's. A `scheduled` tick can only
177
- ever read the owner's connection — an app that ranks _each visitor's_ posts
178
- does that work in `fetch`, when they are there.
176
+ **Whose account?** In a `fetch` handler it is the signed-in visitor the page
177
+ called the route for with `apiFetch` (section 4); in `scheduled` it is the app
178
+ owner's. A `scheduled` tick can only ever read the owner's connection — an app
179
+ that ranks _each visitor's_ posts does that work in `fetch`, when they are there.
180
+
181
+ ### 4. Call it from the page — `apiFetch`
182
+
183
+ **The page calls its connection-backed routes with `apiFetch` from `use-vibes`, so the
184
+ backend runs as the visitor who connected.** `apiFetch` asks the platform to make
185
+ the call for the signed-in visitor: the handler's `ctx.userInfo` is that
186
+ visitor, and `ctx.connections` and `@vibes.diy/social` spend _their_
187
+ connection. The path is the route under `/_api`, so `apiFetch("/top-posts")`
188
+ reaches the `/top-posts` branch above. Wait for the connection before calling,
189
+ so the first answer is the real one.
190
+
191
+ ```jsx file=App.jsx app=instagram-connection
192
+ import React, { useEffect, useState } from "react";
193
+ import { useConnection, apiFetch } from "use-vibes";
194
+
195
+ function TopPosts() {
196
+ const { state, consented } = useConnection("instagram");
197
+ const connected = consented && (state === "live" || state === "expiring");
198
+ const [posts, setPosts] = useState([]);
199
+ const [problem, setProblem] = useState(null);
200
+ useEffect(() => {
201
+ if (!connected) return;
202
+ apiFetch("/top-posts")
203
+ .then(async (res) => {
204
+ const data = await res.json();
205
+ if (res.ok) setPosts(data.posts);
206
+ else setProblem(`Instagram is ${data.connection ?? "not ready"} — try again in a moment.`);
207
+ })
208
+ .catch(() => setProblem("Could not reach the app just now."));
209
+ }, [connected]);
210
+ if (!connected) return null;
211
+ if (problem) return <p>{problem}</p>;
212
+ return (
213
+ <ol>
214
+ {posts.map((p) => (
215
+ <li key={p.id}>
216
+ <a href={p.permalink}>{p.caption}</a> — {p.likeCount ?? "hidden"} likes
217
+ </li>
218
+ ))}
219
+ </ol>
220
+ );
221
+ }
222
+ ```
223
+
224
+ `apiFetch(path, { method, headers, body })` answers like `fetch`: `status`,
225
+ `ok`, `headers`, `text()` and `json()`. The route's own status comes back as
226
+ an answer — a `409` with `{ connection: "needs_consent" }` resolves with
227
+ `ok: false` — and the promise rejects only when the route could not be reached.
228
+ Send JSON as `body: JSON.stringify(data)` with a `content-type:
229
+ application/json` header. A visitor who is not signed in still reaches the
230
+ route, with `ctx.userInfo` set to `null`. The platform keeps the visitor's
231
+ sign-in to itself: `apiFetch` carries who they are, and your code never handles
232
+ a token.
179
233
 
180
234
  ## Ticks that have nothing to do
181
235
 
@@ -21,7 +21,25 @@ Each document has an `_id`, which can be auto-generated or set explicitly. Auto-
21
21
 
22
22
  Use granular documents, e.g. one document per user action, so saving a form or clicking a button should typically create or update a single document, or just a few documents. Avoid patterns that require a single document to grow without bound.
23
23
 
24
- `useLiveQuery` populates and refreshes the UI reactively as data arrives, so you usually render empty states rather than loading spinners. Writes are optimistic and local: `put()`/`save()`/`del()` land in the local replica instantly, and transport or offline failures queue and retry automatically. If the server rejects a synced write, the local optimistic revision converges **server-wins** (it is overwritten by the server's version) — and the **platform** surfaces the reason in a write-fail toast only when it has one; a reason-less rejection converges silently. So do **not** wrap plain writes in `try/catch` to show denial errors to the user (a save carrying `_files` is the one exception, covered with the image uploader below); keep the UI reactive to the store (`useLiveQuery`/`useDocument`) so the converged state is the feedback, and gate write surfaces up front with `useVibe(dbName).can.create/edit/delete` so a disallowed action never renders in the first place.
24
+ `useLiveQuery` populates and refreshes the UI reactively as data arrives, so you usually render empty states rather than loading spinners. Writes are optimistic and local: `put()`/`save()`/`del()` land in the local replica instantly, and transport or offline failures queue and retry automatically. If the server rejects a synced write, the local optimistic revision converges **server-wins** (it is overwritten by the server's version) — and the **platform** surfaces the reason in a write-fail toast whenever it has one: the app's own `forbidden("…")` text, or the platform's message when a signed-in visitor has no write access to the app (both also reach the app as `writeRejection`, below); a reason-less rejection converges silently. So do **not** wrap plain writes in `try/catch` to show denial errors to the user (a save carrying `_files` is the one exception, covered with the image uploader below); keep the UI reactive to the store (`useLiveQuery`/`useDocument`) so the converged state is the feedback, and gate write surfaces up front with `useVibe(dbName).can.create/edit/delete` so a disallowed action never renders in the first place.
25
+
26
+ When the server later refuses a write the visitor can act on — a signed-in visitor saving to a private app, say — the platform shows a notice and `useFireproof` hands the app the same reason as `writeRejection` (`{ docId, message }`, or `null` until a save is refused). Render `writeRejection.message` beside the form it came from and call `clearWriteRejection()` when the visitor dismisses it:
27
+
28
+ ```jsx
29
+ function NoteForm({ text }) {
30
+ const { database, writeRejection, clearWriteRejection } = useFireproof("notes");
31
+ return (
32
+ <div>
33
+ <button onClick={() => database.put({ type: "note", text })}>Save</button>
34
+ {writeRejection && (
35
+ <p role="status">
36
+ {writeRejection.message} <button onClick={clearWriteRejection}>Dismiss</button>
37
+ </p>
38
+ )}
39
+ </div>
40
+ );
41
+ }
42
+ ```
25
43
 
26
44
  ### Basic Example
27
45
 
@@ -97,7 +115,7 @@ function TaskCard({ task, database, can, onCorrect, onSaved, disabled }) {
97
115
  }
98
116
 
99
117
  export default function App() {
100
- const { database, useLiveQuery } = useFireproof("tasks");
118
+ const { database, useLiveQuery, writeRejection, clearWriteRejection } = useFireproof("tasks");
101
119
  const { me, can, ready } = useVibe("tasks");
102
120
  const { docs } = useLiveQuery("type", { key: "task" });
103
121
  const [sentence, setSentence] = useState("");
@@ -179,6 +197,7 @@ export default function App() {
179
197
  </form>
180
198
  <p>{answer}</p>
181
199
  <p role="status">{message}</p>
200
+ {writeRejection && <p role="status">{writeRejection.message} <button type="button" onClick={clearWriteRejection}>Dismiss</button></p>}
182
201
  {lastWrite !== undefined && <button type="button" disabled={busy} onClick={undoLast}>Undo</button>}
183
202
  {pending !== undefined && !busy && <button type="button" onClick={() => { setPending(undefined); setSentence(""); setCurrent(undefined); }}>Discard unsaved tasks</button>}
184
203
  {docs.map((task) => <TaskCard key={task._id} task={task} database={database} can={can} disabled={busy || pending !== undefined} onSaved={(previous) => setLastWrite({ created: [], replaced: previous })} onCorrect={(doc) => { if (busy || pending !== undefined) return; setCurrent(doc); setSentence(""); }} />)}
package/llms/fireproof.md CHANGED
@@ -5,7 +5,7 @@ Fireproof is a document database with live sync, designed to make browser apps e
5
5
  ## Key Features
6
6
 
7
7
  - **Apps run anywhere:** Bundle UI, data, and logic together.
8
- - **Real-Time, local-first:** Writes land in the local replica instantly and sync in the background; the server validates each on ingest and streams the accepted ones live to every viewer. `useLiveQuery` keeps the UI in sync as data arrives, so you render empty states rather than loading spinners — but a synced write can still be rejected on ingest (access denied, conflicts): the local optimistic revision converges **server-wins** — and the platform surfaces the reason **only when the app's access rules provide one**; a reason-less rejection converges silently. Keep the UI reactive to the store rather than depending on a toast; don't assume every write lands, but don't hand-roll denial errors either.
8
+ - **Real-Time, local-first:** Writes land in the local replica instantly and sync in the background; the server validates each on ingest and streams the accepted ones live to every viewer. `useLiveQuery` keeps the UI in sync as data arrives, so you render empty states rather than loading spinners — but a synced write can still be rejected on ingest (access denied, conflicts): the local optimistic revision converges **server-wins** — and the platform surfaces the reason whenever there is one (an access-rule `forbidden("…")`, or no write access for a signed-in visitor); a reason-less rejection converges silently. Keep the UI reactive to the store rather than depending on a toast; don't assume every write lands, but don't hand-roll denial errors either.
9
9
  - **Unified API:** TypeScript works with Deno, Bun, Node.js, and the browser.
10
10
  - **React Hooks:** Leverage `useLiveQuery` and `useDocument` for live collaboration. Note: these are NOT top-level exports — they are returned by the `useFireproof()` hook. Always destructure from `const { useLiveQuery, useDocument, database } = useFireproof("dbName")`. A child component that was handed `database` may call `useFireproof(database)` instead of repeating the name; it is the same database.
11
11
 
@@ -21,7 +21,25 @@ Each document has an `_id`, which can be auto-generated or set explicitly. Auto-
21
21
 
22
22
  Use granular documents, e.g. one document per user action, so saving a form or clicking a button should typically create or update a single document, or just a few documents. Avoid patterns that require a single document to grow without bound.
23
23
 
24
- `useLiveQuery` populates and refreshes the UI reactively as data arrives, so you usually render empty states rather than loading spinners. Writes are optimistic and local: `put()`/`save()`/`del()` land in the local replica instantly, and transport or offline failures queue and retry automatically. If the server's access rules reject a synced write, the local optimistic revision converges **server-wins** (it is overwritten by the server's version) — and the **platform** surfaces the reason in a write-fail toast **only when the app's access rules provide one** (`forbidden("…")`); a reason-less rejection converges silently. So do **not** wrap plain writes in `try/catch` to show denial errors to the user (a save carrying `_files` is the one exception, covered with the image uploader below); keep the UI reactive to the store (`useLiveQuery`/`useDocument`) so the converged state is the feedback, and gate write surfaces up front with `useVibe(dbName).can.create/edit/delete` so a disallowed action never renders in the first place.
24
+ `useLiveQuery` populates and refreshes the UI reactively as data arrives, so you usually render empty states rather than loading spinners. Writes are optimistic and local: `put()`/`save()`/`del()` land in the local replica instantly, and transport or offline failures queue and retry automatically. If the server's access rules reject a synced write, the local optimistic revision converges **server-wins** (it is overwritten by the server's version) — and the **platform** surfaces the reason in a write-fail toast whenever there is one: the app's own `forbidden("…")` text, or the platform's message when a signed-in visitor has no write access to the app (both also reach the app as `writeRejection`, below); a reason-less rejection converges silently. So do **not** wrap plain writes in `try/catch` to show denial errors to the user (a save carrying `_files` is the one exception, covered with the image uploader below); keep the UI reactive to the store (`useLiveQuery`/`useDocument`) so the converged state is the feedback, and gate write surfaces up front with `useVibe(dbName).can.create/edit/delete` so a disallowed action never renders in the first place.
25
+
26
+ When the server later refuses a write the visitor can act on — a signed-in visitor saving to a private app, say — the platform shows a notice and `useFireproof` hands the app the same reason as `writeRejection` (`{ docId, message }`, or `null` until a save is refused). Render `writeRejection.message` beside the form it came from and call `clearWriteRejection()` when the visitor dismisses it:
27
+
28
+ ```jsx
29
+ function NoteForm({ text }) {
30
+ const { database, writeRejection, clearWriteRejection } = useFireproof("notes");
31
+ return (
32
+ <div>
33
+ <button onClick={() => database.put({ type: "note", text })}>Save</button>
34
+ {writeRejection && (
35
+ <p role="status">
36
+ {writeRejection.message} <button onClick={clearWriteRejection}>Dismiss</button>
37
+ </p>
38
+ )}
39
+ </div>
40
+ );
41
+ }
42
+ ```
25
43
 
26
44
  ### Basic Example
27
45
 
@@ -97,7 +115,7 @@ function TaskCard({ task, database, can, onCorrect, onSaved, disabled }) {
97
115
  }
98
116
 
99
117
  export default function App() {
100
- const { database, useLiveQuery } = useFireproof("tasks");
118
+ const { database, useLiveQuery, writeRejection, clearWriteRejection } = useFireproof("tasks");
101
119
  const { me, can, ready } = useVibe("tasks");
102
120
  const { docs } = useLiveQuery("type", { key: "task" });
103
121
  const [sentence, setSentence] = useState("");
@@ -179,6 +197,7 @@ export default function App() {
179
197
  </form>
180
198
  <p>{answer}</p>
181
199
  <p role="status">{message}</p>
200
+ {writeRejection && <p role="status">{writeRejection.message} <button type="button" onClick={clearWriteRejection}>Dismiss</button></p>}
182
201
  {lastWrite !== undefined && <button type="button" disabled={busy} onClick={undoLast}>Undo</button>}
183
202
  {pending !== undefined && !busy && <button type="button" onClick={() => { setPending(undefined); setSentence(""); setCurrent(undefined); }}>Discard unsaved tasks</button>}
184
203
  {docs.map((task) => <TaskCard key={task._id} task={task} database={database} can={can} disabled={busy || pending !== undefined} onSaved={(previous) => setLastWrite({ created: [], replaced: previous })} onCorrect={(doc) => { if (busy || pending !== undefined) return; setCurrent(doc); setSentence(""); }} />)}
@@ -506,7 +525,7 @@ App.jsx
506
525
 
507
526
  ## Offline writes are on by default (`offlineQueue`)
508
527
 
509
- For signed-in users, writes are **local-first by default**: a `put`/`del` that fails on the network is durably queued on the device (it resolves, stays visible, and syncs to the cloud when you're back online) instead of rolling back. You don't opt in — every signed-in vibe gets this. An access-denied/validation rejection is **not** queued: it converges **server-wins** (the local optimistic revision is overwritten by the server's version); the platform surfaces the reason only when the app's access rules provide one, and a reason-less rejection converges silently — so keep the UI reactive to the store rather than depending on a toast. Only transport failures queue and retry.
528
+ For signed-in users, writes are **local-first by default**: a `put`/`del` that fails on the network is durably queued on the device (it resolves, stays visible, and syncs to the cloud when you're back online) instead of rolling back. You don't opt in — every signed-in vibe gets this. An access-denied/validation rejection is **not** queued: it converges **server-wins** (the local optimistic revision is overwritten by the server's version); the platform surfaces the reason whenever there is one, and a reason-less rejection converges silently — so keep the UI reactive to the store rather than depending on a toast. Only transport failures queue and retry.
510
529
 
511
530
  Pass `{ offlineQueue: false }` for **server-first, fail-fast** writes: a `put` resolves only when the server accepts it, and a network failure rejects immediately with nothing queued. Choose this for **collaborative multi-writer apps** where two people may edit the same doc — sync is blind last-arrival-wins (Firefly has no `_rev`), so a stale write replayed on reconnect can silently overwrite a newer one. When a lost write is safer than a surprise overwrite, opt out.
512
531
 
@@ -532,7 +551,7 @@ The old `{ anonymousLocal: true }` option (and its `migrate` hook) is **deprecat
532
551
 
533
552
  ## Architecture: Where's My Data?
534
553
 
535
- Data lives in a local replica (IndexedDB) that the app reads and writes instantly; that replica syncs to the Firefly server in the background. The server is the authority on acceptance — each synced write is validated by the app's access rules on ingest, persisted, and then synced to all users who have read access. A write that fails validation or hits a conflict is rejected on ingest: the local optimistic revision converges **server-wins**, and the platform surfaces the reason **only when the app's access rules provide one** — a reason-less rejection converges silently, so keep the UI reactive to the store rather than depending on a toast. Don't assume the write always lands, but don't hand-roll your own denial error UI — let it converge.
554
+ Data lives in a local replica (IndexedDB) that the app reads and writes instantly; that replica syncs to the Firefly server in the background. The server is the authority on acceptance — each synced write is validated by the app's access rules on ingest, persisted, and then synced to all users who have read access. A write that fails validation or hits a conflict is rejected on ingest: the local optimistic revision converges **server-wins**, and the platform surfaces the reason whenever there is one — a reason-less rejection converges silently, so keep the UI reactive to the store rather than depending on a toast. Don't assume the write always lands, but don't hand-roll your own denial error UI — let it converge.
536
555
 
537
556
  ## Using Fireproof in JavaScript
538
557
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibes.diy/prompts",
3
- "version": "14.3.8",
3
+ "version": "14.3.9",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "exports": {
@@ -37,9 +37,9 @@
37
37
  "license": "Apache-2.0",
38
38
  "dependencies": {
39
39
  "@adviser/cement": "~0.5.34",
40
- "@vibes.diy/call-ai-v2": "14.3.8",
41
- "@vibes.diy/identity": "14.3.8",
42
- "@vibes.diy/use-vibes-types": "14.3.8",
40
+ "@vibes.diy/call-ai-v2": "14.3.9",
41
+ "@vibes.diy/identity": "14.3.9",
42
+ "@vibes.diy/use-vibes-types": "14.3.9",
43
43
  "arktype": "~2.2.3",
44
44
  "json-schema-faker": "~0.6.3"
45
45
  },