@vibes.diy/prompts 2.6.2 → 2.6.4
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/use-viewer.md +1 -1
- package/llms/web-audio.md +49 -7
- package/package.json +4 -4
package/llms/use-viewer.md
CHANGED
|
@@ -36,7 +36,7 @@ export default function App() {
|
|
|
36
36
|
|
|
37
37
|
- `viewer` — `{ userHandle, displayName? }` or `null` for anonymous visitors. Avatars are not on the payload — render them with `<ViewerTag userHandle={...} />`, which resolves the avatar from the handle. Don't build avatar URLs yourself.
|
|
38
38
|
- `isViewerPending` — `true` while the platform is still resolving the viewer identity (e.g. on first render before the parent shell has pushed the identity update). **Gate any auth-dependent UI on `!isViewerPending`** to avoid flashing the wrong state. Once it becomes `false`, `viewer` is either populated or definitively `null`.
|
|
39
|
-
- `can(action
|
|
39
|
+
- `can(action)` — membership boolean for `"read"`/`"write"`/`"delete"`: is the viewer through the door? Access functions enforce per-document and per-database rules server-side. Prefer `useVibe(dbName).can.create/edit/delete` for write gating; it runs the app's access function and returns a `reason`.
|
|
40
40
|
- `ViewerTag` — ready-made user pill; see the ViewerTag section below.
|
|
41
41
|
|
|
42
42
|
## Gating UI
|
package/llms/web-audio.md
CHANGED
|
@@ -4,6 +4,18 @@ Authoritative source: Issue #228 research threads — comments 3192681700, 31926
|
|
|
4
4
|
|
|
5
5
|
> **Web Audio is a browser built-in.** Use `window.AudioContext` (with the
|
|
6
6
|
> `window.webkitAudioContext` fallback) directly, gated on a user gesture as shown below.
|
|
7
|
+
>
|
|
8
|
+
> **iOS Safari: unlock audio synchronously inside the gesture.** WebKit requires
|
|
9
|
+
> playback to *directly result* from a trusted handler (`pointerdown`, `touchend`,
|
|
10
|
+
> `click`, `keydown`). Inside that handler you must, synchronously and before any
|
|
11
|
+
> async work: create-or-resume the `AudioContext` **and start at least one real
|
|
12
|
+
> sound** (a ~10ms blip at `gain ≈ 0.0001` is enough). A resume/start that runs
|
|
13
|
+
> from a downstream `setTimeout`, `Promise.then`, `await`, `requestAnimationFrame`,
|
|
14
|
+
> a React state-update→effect, a worker/scheduler task, or a media
|
|
15
|
+
> `canplay`/`canplaythrough` callback **does not count** and will stay silent on
|
|
16
|
+
> iOS. Once the context is `running`, all of those are fine for scheduling. iOS
|
|
17
|
+
> also suspends audio after backgrounding/lock, so **re-check `audioCtx.state` on
|
|
18
|
+
> every gesture** and resume again if needed. See the `unlockAudio()` gate in §1.
|
|
7
19
|
|
|
8
20
|
## 1) Fundamentals and Core Nodes
|
|
9
21
|
|
|
@@ -17,15 +29,40 @@ Authoritative source: Issue #228 research threads — comments 3192681700, 31926
|
|
|
17
29
|
Examples
|
|
18
30
|
|
|
19
31
|
```js
|
|
20
|
-
// 1) Context
|
|
21
|
-
|
|
32
|
+
// 1) Context + iOS-safe unlock gate.
|
|
33
|
+
let audioCtx;
|
|
34
|
+
function unlockAudio() {
|
|
35
|
+
audioCtx ||= new (window.AudioContext || window.webkitAudioContext)();
|
|
36
|
+
// Re-check every gesture — iOS suspends audio after backgrounding/lock.
|
|
37
|
+
if (audioCtx.state !== "running") {
|
|
38
|
+
audioCtx.resume();
|
|
39
|
+
// Start one real (silent) sound synchronously, inside the gesture, so WebKit
|
|
40
|
+
// actually unlocks output. This is the part a resume()-alone often misses.
|
|
41
|
+
const osc = audioCtx.createOscillator();
|
|
42
|
+
const gain = audioCtx.createGain();
|
|
43
|
+
gain.gain.value = 0.0001;
|
|
44
|
+
osc.connect(gain).connect(audioCtx.destination);
|
|
45
|
+
osc.start();
|
|
46
|
+
osc.stop(audioCtx.currentTime + 0.01);
|
|
47
|
+
}
|
|
48
|
+
return audioCtx;
|
|
49
|
+
}
|
|
22
50
|
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
51
|
+
// Call unlockAudio() FIRST, synchronously, in a trusted gesture — before any
|
|
52
|
+
// app/audio logic. After it returns, the context is running and timers,
|
|
53
|
+
// requestAnimationFrame, sequencers, and workers are all safe to schedule with.
|
|
54
|
+
document.querySelector("#start-audio")?.addEventListener("pointerdown", () => {
|
|
55
|
+
unlockAudio();
|
|
56
|
+
// now safe to create/start nodes, kick off the transport, etc.
|
|
27
57
|
});
|
|
28
58
|
|
|
59
|
+
// ✗ What breaks on iOS — the unlock does NOT count if audio first starts from a
|
|
60
|
+
// downstream callback, because it no longer "directly results" from the gesture:
|
|
61
|
+
// el.addEventListener("click", () => requestAnimationFrame(() => audioCtx.resume())); // risky
|
|
62
|
+
// setTimeout(...), Promise.then(...), await fetch(...), await import(...),
|
|
63
|
+
// a React state update then effect, a scheduler/task-queue callback, or a
|
|
64
|
+
// media canplay/canplaythrough callback — all too late. Unlock in the handler.
|
|
65
|
+
|
|
29
66
|
// 2) Simple tone
|
|
30
67
|
const osc = audioCtx.createOscillator();
|
|
31
68
|
osc.type = "sine";
|
|
@@ -225,7 +262,12 @@ External sync and drift
|
|
|
225
262
|
|
|
226
263
|
## 5) Practical Notes
|
|
227
264
|
|
|
228
|
-
- User gesture required to start/resume `AudioContext` and to access the mic.
|
|
265
|
+
- User gesture required to start/resume `AudioContext` and to access the mic. On
|
|
266
|
+
iOS Safari the unlock must be **synchronous inside the gesture and start one
|
|
267
|
+
real sound** (the `unlockAudio()` gate in §1); a resume from a downstream
|
|
268
|
+
timer/promise/`await`/rAF/effect/media callback is too late. Re-check
|
|
269
|
+
`audioCtx.state` on every gesture, since iOS suspends audio after
|
|
270
|
+
backgrounding/lock.
|
|
229
271
|
- Convolver IRs: host with CORS if cross‑origin; decode before use.
|
|
230
272
|
- Latency budget: device `baseLatency` + your lookahead + any Worklet buffering.
|
|
231
273
|
- Headphones recommended for monitoring to avoid acoustic feedback.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibes.diy/prompts",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"description": "",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"@fireproof/core-types-base": "~0.24.19",
|
|
31
31
|
"@fireproof/core-types-protocols-cloud": "~0.24.19",
|
|
32
32
|
"@fireproof/use-fireproof": "~0.24.19",
|
|
33
|
-
"@vibes.diy/call-ai-v2": "^2.6.
|
|
34
|
-
"@vibes.diy/identity": "^2.6.
|
|
35
|
-
"@vibes.diy/use-vibes-types": "^2.6.
|
|
33
|
+
"@vibes.diy/call-ai-v2": "^2.6.4",
|
|
34
|
+
"@vibes.diy/identity": "^2.6.4",
|
|
35
|
+
"@vibes.diy/use-vibes-types": "^2.6.4",
|
|
36
36
|
"arktype": "~2.2.1",
|
|
37
37
|
"json-schema-faker": "~0.6.2"
|
|
38
38
|
},
|