@ziprack/sdk 0.1.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/dist/activity/index.d.ts +37 -0
- package/dist/ai/index.d.ts +41 -0
- package/dist/attempt/index.d.ts +27 -0
- package/dist/auth/index.d.ts +14 -0
- package/dist/broadcast/index.d.ts +81 -0
- package/dist/core/bridge.d.ts +39 -0
- package/dist/core/link.d.ts +14 -0
- package/dist/core/mock/MockRack.d.ts +141 -0
- package/dist/core/mock/MockTransport.d.ts +14 -0
- package/dist/core/mock/store.d.ts +23 -0
- package/dist/core/protocol.d.ts +15 -0
- package/dist/core/rack.d.ts +68 -0
- package/dist/core/types.d.ts +155 -0
- package/dist/db/index.d.ts +62 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +517 -0
- package/dist/index.js.map +1 -0
- package/dist/media/index.d.ts +14 -0
- package/dist/storage/index.d.ts +41 -0
- package/dist/store-DSV5q7C7.js +504 -0
- package/dist/store-DSV5q7C7.js.map +1 -0
- package/dist/testing.d.ts +30 -0
- package/dist/testing.js +42 -0
- package/dist/testing.js.map +1 -0
- package/dist/ziprack-sdk.iife.js +2 -0
- package/dist/ziprack-sdk.iife.js.map +1 -0
- package/package.json +30 -0
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
const b = "ziprack", S = 1, y = "ziprack/1";
|
|
2
|
+
let f = 0;
|
|
3
|
+
function _() {
|
|
4
|
+
const n = typeof globalThis.crypto < "u" ? globalThis.crypto : void 0;
|
|
5
|
+
return n && typeof n.randomUUID == "function" ? n.randomUUID() : (f += 1, `req-${Date.now().toString(36)}-${f.toString(36)}`);
|
|
6
|
+
}
|
|
7
|
+
function w(n, t, e) {
|
|
8
|
+
const s = { ns: b, v: 1, type: n, payload: t };
|
|
9
|
+
return e !== void 0 && (s.requestId = e), s;
|
|
10
|
+
}
|
|
11
|
+
function $(n) {
|
|
12
|
+
if (typeof n != "object" || n === null)
|
|
13
|
+
return !1;
|
|
14
|
+
const t = n;
|
|
15
|
+
return t.ns === b && t.v === 1 && typeof t.type == "string";
|
|
16
|
+
}
|
|
17
|
+
function v(n) {
|
|
18
|
+
const t = n.indexOf(":");
|
|
19
|
+
return t === -1 ? n : n.slice(0, t);
|
|
20
|
+
}
|
|
21
|
+
class O {
|
|
22
|
+
constructor(t, e, s = {}) {
|
|
23
|
+
this.manifest = t, this.store = e, this.options = s, this.statements = [], this.events = [], this.aiHandlers = /* @__PURE__ */ new Map(), this.chatHistory = /* @__PURE__ */ new Map(), this.blobs = /* @__PURE__ */ new Map(), this.eventListeners = /* @__PURE__ */ new Set(), this.roomMembers = /* @__PURE__ */ new Map(), this.roomState = {}, this.role = "participant", this.joinedAt = Date.now() + Math.random(), this.channel = null, this.heartbeat = null, this.participantId = s.participantId ?? Math.floor(Math.random() * 1e6) + 1, this.participantName = s.participantName ?? "Dev User";
|
|
24
|
+
}
|
|
25
|
+
get slug() {
|
|
26
|
+
return this.manifest?.slug ?? "applet";
|
|
27
|
+
}
|
|
28
|
+
key(...t) {
|
|
29
|
+
return `ziprack-mock:${this.slug}:${t.join(":")}`;
|
|
30
|
+
}
|
|
31
|
+
declares(t) {
|
|
32
|
+
return this.manifest ? (this.manifest.requires?.capabilities ?? []).some((e) => e.split("@")[0] === t) : !0;
|
|
33
|
+
}
|
|
34
|
+
onEvent(t) {
|
|
35
|
+
return this.eventListeners.add(t), () => {
|
|
36
|
+
this.eventListeners.delete(t);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
pushEvent(t) {
|
|
40
|
+
this.events.push(t), this.eventListeners.forEach((e) => e(t));
|
|
41
|
+
}
|
|
42
|
+
launchData(t) {
|
|
43
|
+
const e = this.manifest, s = {
|
|
44
|
+
schema: "ziprack/1",
|
|
45
|
+
actor: { id: this.participantId, name: this.participantName },
|
|
46
|
+
applet: { slug: this.slug, name: `${e?.name ?? t ?? "Applet"} (mock)`, version: e?.version ?? "dev" },
|
|
47
|
+
capabilities: e?.requires?.capabilities ?? [],
|
|
48
|
+
media: Object.fromEntries((e?.media ?? []).map((r) => [r.id, {
|
|
49
|
+
provider: r.provider,
|
|
50
|
+
embedUrl: r.provider === "vimeo" ? `https://player.vimeo.com/video/${r.key}?dnt=1` : `https://www.youtube-nocookie.com/embed/${r.key}?rel=0`,
|
|
51
|
+
meta: null
|
|
52
|
+
}]))
|
|
53
|
+
};
|
|
54
|
+
if (this.declares("auth")) {
|
|
55
|
+
const r = { user: { id: this.participantId, display_name: this.participantName } };
|
|
56
|
+
for (const i of e?.requires?.profile ?? [])
|
|
57
|
+
r.user[i] = r.user[i] ?? `mock-${i}`;
|
|
58
|
+
s.auth = r;
|
|
59
|
+
}
|
|
60
|
+
return this.declares("attempt") && (s.attempt = this.attempt()), this.declares("activity") && (s.activity = { activities: [...e?.activities ?? []].sort((r, i) => (r.sequence ?? 0) - (i.sequence ?? 0)) }), this.declares("db") && (s.db = { collections: (e?.collections ?? []).map((r) => ({ name: r.name, scope: r.scope })) }), this.declares("storage") && (s.storage = { uploads: (e?.uploads ?? []).map((r) => ({ name: r.name, scope: r.scope, mime: r.mime ?? [], max_bytes: r.max_bytes ?? 10 * 1024 * 1024 })) }), this.declares("ai") && (s.ai = { prompts: (e?.prompts ?? []).map((r) => ({ id: r.id, mode: r.mode })) }), this.declares("broadcast") && (this.joinRoom(), s.broadcast = {
|
|
61
|
+
room: { id: 1, code: "MOCK01", name: `${this.slug} room`, status: "open", mode: e?.broadcast?.mock_mode ?? "first_in" },
|
|
62
|
+
role: this.role,
|
|
63
|
+
members: this.members(),
|
|
64
|
+
state: this.stateSnapshot(),
|
|
65
|
+
channels: e?.broadcast?.channels ?? ["main"]
|
|
66
|
+
}), s;
|
|
67
|
+
}
|
|
68
|
+
mockAi(t, e) {
|
|
69
|
+
this.aiHandlers.set(t, e);
|
|
70
|
+
}
|
|
71
|
+
dispose() {
|
|
72
|
+
this.heartbeat && clearInterval(this.heartbeat), this.channel && (this.send({ t: "bye", from: this.member() }), this.channel.close());
|
|
73
|
+
}
|
|
74
|
+
// ---------------------------------------------------------------- dispatch
|
|
75
|
+
async handle(t, e) {
|
|
76
|
+
if (this.options.log?.(t, e), t === "rack:eject")
|
|
77
|
+
return { ok: !0 };
|
|
78
|
+
const s = v(t);
|
|
79
|
+
if ((this.options.strict ?? this.manifest !== null) && !this.declares(s))
|
|
80
|
+
return { ok: !1, error: "undeclared_capability", message: `The manifest does not declare the [${s}] capability.` };
|
|
81
|
+
switch (t) {
|
|
82
|
+
case "attempt:state":
|
|
83
|
+
return this.attemptState(e);
|
|
84
|
+
case "attempt:segment":
|
|
85
|
+
return this.attemptSegment(e);
|
|
86
|
+
case "attempt:complete":
|
|
87
|
+
return this.attemptComplete(e);
|
|
88
|
+
case "activity:statement":
|
|
89
|
+
return this.statement(e);
|
|
90
|
+
case "db:create":
|
|
91
|
+
return this.dbCreate(e);
|
|
92
|
+
case "db:get":
|
|
93
|
+
return this.dbGet(e);
|
|
94
|
+
case "db:update":
|
|
95
|
+
return this.dbUpdate(e);
|
|
96
|
+
case "db:delete":
|
|
97
|
+
return this.dbDelete(e);
|
|
98
|
+
case "db:list":
|
|
99
|
+
return this.dbList(e);
|
|
100
|
+
case "db:count":
|
|
101
|
+
return this.dbCount(e);
|
|
102
|
+
case "storage:put":
|
|
103
|
+
return this.storagePut(e);
|
|
104
|
+
case "storage:url":
|
|
105
|
+
return this.storageUrl(e);
|
|
106
|
+
case "storage:list":
|
|
107
|
+
return this.storageList(e);
|
|
108
|
+
case "storage:delete":
|
|
109
|
+
return this.storageDelete(e);
|
|
110
|
+
case "ai:ask":
|
|
111
|
+
return this.aiAsk(e);
|
|
112
|
+
case "ai:chat":
|
|
113
|
+
return this.aiChat(e);
|
|
114
|
+
case "ai:chat.reset":
|
|
115
|
+
return this.chatHistory.delete(String(e.prompt)), { ok: !0 };
|
|
116
|
+
case "broadcast:join":
|
|
117
|
+
return { ok: !0, data: { members: this.members(), state: this.stateSnapshot() } };
|
|
118
|
+
case "broadcast:leave":
|
|
119
|
+
return { ok: !0 };
|
|
120
|
+
case "broadcast:publish":
|
|
121
|
+
return this.publish(e);
|
|
122
|
+
case "broadcast:state.get":
|
|
123
|
+
return { ok: !0, data: { state: this.stateSnapshot(Array.isArray(e.keys) ? e.keys : void 0) } };
|
|
124
|
+
case "broadcast:state.set":
|
|
125
|
+
return this.stateSet(e);
|
|
126
|
+
case "broadcast:presence":
|
|
127
|
+
return { ok: !0, data: { members: this.members() } };
|
|
128
|
+
case "broadcast:claim":
|
|
129
|
+
return this.claim();
|
|
130
|
+
case "broadcast:transfer":
|
|
131
|
+
return this.transfer(e);
|
|
132
|
+
default:
|
|
133
|
+
return { ok: !1, error: "unknown_type", message: `Unknown message type [${t}].` };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// ---------------------------------------------------------------- attempt
|
|
137
|
+
attempt() {
|
|
138
|
+
return this.store.get(this.key("attempt")) ?? { id: 1, status: "in_progress", state: null, segment: null };
|
|
139
|
+
}
|
|
140
|
+
saveAttempt(t) {
|
|
141
|
+
this.store.set(this.key("attempt"), t);
|
|
142
|
+
}
|
|
143
|
+
attemptState(t) {
|
|
144
|
+
const e = this.attempt();
|
|
145
|
+
if (e.status === "completed")
|
|
146
|
+
return { ok: !1, error: "completed", message: "This attempt is already completed." };
|
|
147
|
+
const s = JSON.stringify(t.state ?? {}).length;
|
|
148
|
+
return s > 65536 ? { ok: !1, error: "validation", message: `State is ${s} bytes; the limit is 65536.` } : (this.saveAttempt({ ...e, state: t.state ?? null }), { ok: !0 });
|
|
149
|
+
}
|
|
150
|
+
attemptSegment(t) {
|
|
151
|
+
const e = this.attempt();
|
|
152
|
+
return e.status === "completed" ? { ok: !1, error: "completed" } : (this.saveAttempt({ ...e, segment: t.segment ?? null }), { ok: !0 });
|
|
153
|
+
}
|
|
154
|
+
attemptComplete(t) {
|
|
155
|
+
const e = this.attempt(), s = (/* @__PURE__ */ new Date()).toISOString();
|
|
156
|
+
return e.status !== "completed" && (this.saveAttempt({ ...e, status: "completed" }), this.declares("activity") && this.statement({ verb: "completed", activity: { id: "attempt", type: "attempt" }, result: t.summary ?? null, occurred_at: s })), { ok: !0, data: { status: "completed", completed_at: s } };
|
|
157
|
+
}
|
|
158
|
+
/** Clear a completed mock attempt so the experience can be run again. */
|
|
159
|
+
resetAttempt() {
|
|
160
|
+
this.store.remove(this.key("attempt"));
|
|
161
|
+
}
|
|
162
|
+
// ---------------------------------------------------------------- activity
|
|
163
|
+
statement(t) {
|
|
164
|
+
const e = String(t.verb ?? "");
|
|
165
|
+
if (!/^[a-z][a-z0-9_.:-]*$/.test(e) || e.length > 100)
|
|
166
|
+
return { ok: !1, error: "validation", message: `Invalid verb [${e}].` };
|
|
167
|
+
if (!t.activity?.id)
|
|
168
|
+
return { ok: !1, error: "validation", message: "activity.id is required." };
|
|
169
|
+
const r = `mock-${Date.now().toString(36)}-${this.statements.length + 1}`;
|
|
170
|
+
return this.statements.push({ id: r, ...t }), { ok: !0, data: { id: r } };
|
|
171
|
+
}
|
|
172
|
+
// ---------------------------------------------------------------- db
|
|
173
|
+
collectionKey(t) {
|
|
174
|
+
return this.key("db", t);
|
|
175
|
+
}
|
|
176
|
+
records(t) {
|
|
177
|
+
return this.store.get(this.collectionKey(t)) ?? [];
|
|
178
|
+
}
|
|
179
|
+
saveRecords(t, e) {
|
|
180
|
+
this.store.set(this.collectionKey(t), e);
|
|
181
|
+
}
|
|
182
|
+
collectionDeclared(t) {
|
|
183
|
+
return this.manifest && !(this.manifest.collections ?? []).some((s) => s.name === t) ? { ok: !1, error: "not_found", message: `Collection [${t}] is not declared in the manifest.` } : (this.manifest?.collections ?? []).find((s) => s.name === t)?.scope === "attempt" && this.attempt().status === "completed" ? { ok: !1, error: "completed", message: "Attempt-scoped records are frozen after completion." } : null;
|
|
184
|
+
}
|
|
185
|
+
dbCreate(t) {
|
|
186
|
+
const e = String(t.collection), s = this.collectionDeclared(e);
|
|
187
|
+
if (s)
|
|
188
|
+
return s;
|
|
189
|
+
const r = (/* @__PURE__ */ new Date()).toISOString(), i = {
|
|
190
|
+
id: `rec-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`,
|
|
191
|
+
data: t.data ?? {},
|
|
192
|
+
owner_id: this.participantId,
|
|
193
|
+
created_at: r,
|
|
194
|
+
updated_at: r
|
|
195
|
+
};
|
|
196
|
+
return this.saveRecords(e, [...this.records(e), i]), { ok: !0, data: { record: i } };
|
|
197
|
+
}
|
|
198
|
+
dbGet(t) {
|
|
199
|
+
const e = this.records(String(t.collection)).find((s) => s.id === t.id);
|
|
200
|
+
return e ? { ok: !0, data: { record: e } } : { ok: !1, error: "not_found" };
|
|
201
|
+
}
|
|
202
|
+
dbUpdate(t) {
|
|
203
|
+
const e = String(t.collection), s = this.collectionDeclared(e);
|
|
204
|
+
if (s && s.error === "completed")
|
|
205
|
+
return s;
|
|
206
|
+
const r = this.records(e), i = r.findIndex((c) => c.id === t.id);
|
|
207
|
+
if (i === -1)
|
|
208
|
+
return { ok: !1, error: "not_found" };
|
|
209
|
+
const o = t.merge !== !1, a = t.data ?? {};
|
|
210
|
+
return r[i] = { ...r[i], data: o ? { ...r[i].data, ...a } : a, updated_at: (/* @__PURE__ */ new Date()).toISOString() }, this.saveRecords(e, r), { ok: !0, data: { record: r[i] } };
|
|
211
|
+
}
|
|
212
|
+
dbDelete(t) {
|
|
213
|
+
const e = String(t.collection), s = this.records(e);
|
|
214
|
+
return s.some((r) => r.id === t.id) ? (this.saveRecords(e, s.filter((r) => r.id !== t.id)), { ok: !0, data: { id: t.id } }) : { ok: !1, error: "not_found" };
|
|
215
|
+
}
|
|
216
|
+
filter(t, e) {
|
|
217
|
+
return e ? t.filter((s) => e.every(([r, i, o]) => {
|
|
218
|
+
const a = r.split(".").reduce((c, l) => c?.[l], s.data);
|
|
219
|
+
switch (i) {
|
|
220
|
+
case "=":
|
|
221
|
+
return a === o;
|
|
222
|
+
case "!=":
|
|
223
|
+
return a !== o;
|
|
224
|
+
case "<":
|
|
225
|
+
return a < o;
|
|
226
|
+
case "<=":
|
|
227
|
+
return a <= o;
|
|
228
|
+
case ">":
|
|
229
|
+
return a > o;
|
|
230
|
+
case ">=":
|
|
231
|
+
return a >= o;
|
|
232
|
+
case "in":
|
|
233
|
+
return Array.isArray(o) && o.includes(a);
|
|
234
|
+
default:
|
|
235
|
+
return !1;
|
|
236
|
+
}
|
|
237
|
+
})) : t;
|
|
238
|
+
}
|
|
239
|
+
dbList(t) {
|
|
240
|
+
const e = String(t.collection);
|
|
241
|
+
if (this.manifest && !(this.manifest.collections ?? []).some((c) => c.name === e))
|
|
242
|
+
return { ok: !1, error: "not_found", message: `Collection [${e}] is not declared in the manifest.` };
|
|
243
|
+
let s = this.filter(this.records(e), t.where);
|
|
244
|
+
if (typeof t.orderBy == "string") {
|
|
245
|
+
const c = t.orderBy, l = t.direction === "desc" ? -1 : 1;
|
|
246
|
+
s = [...s].sort((g, k) => {
|
|
247
|
+
const d = c.split(".").reduce((h, m) => h?.[m], g.data), p = c.split(".").reduce((h, m) => h?.[m], k.data);
|
|
248
|
+
return d < p ? -l : d > p ? l : 0;
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
const r = Math.min(Number(t.limit ?? 50), 100), i = t.cursor ? Number(t.cursor) : 0, o = s.slice(i, i + r), a = i + r < s.length ? String(i + r) : null;
|
|
252
|
+
return { ok: !0, data: { records: o, nextCursor: a } };
|
|
253
|
+
}
|
|
254
|
+
dbCount(t) {
|
|
255
|
+
return { ok: !0, data: { count: this.filter(this.records(String(t.collection)), t.where).length } };
|
|
256
|
+
}
|
|
257
|
+
// ---------------------------------------------------------------- storage
|
|
258
|
+
files() {
|
|
259
|
+
return this.store.get(this.key("files")) ?? [];
|
|
260
|
+
}
|
|
261
|
+
storagePut(t) {
|
|
262
|
+
const e = String(t.upload), s = (this.manifest?.uploads ?? []).find((c) => c.name === e);
|
|
263
|
+
if (this.manifest && !s)
|
|
264
|
+
return { ok: !1, error: "not_found", message: `Upload [${e}] is not declared in the manifest.` };
|
|
265
|
+
const r = String(t.mime ?? "");
|
|
266
|
+
if (s?.mime && s.mime.length > 0 && !s.mime.some((c) => c === r || c.endsWith("/*") && r.startsWith(c.slice(0, -1))))
|
|
267
|
+
return { ok: !1, error: "validation", message: `MIME type [${r}] is not allowed for upload [${e}].` };
|
|
268
|
+
const i = Number(t.bytes ?? 0);
|
|
269
|
+
if (s?.max_bytes && i > s.max_bytes)
|
|
270
|
+
return { ok: !1, error: "quota_exceeded", message: `File is ${i} bytes; the limit is ${s.max_bytes}.` };
|
|
271
|
+
const o = {
|
|
272
|
+
id: `file-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`,
|
|
273
|
+
upload: e,
|
|
274
|
+
name: String(t.name ?? "blob"),
|
|
275
|
+
mime: r,
|
|
276
|
+
bytes: i,
|
|
277
|
+
status: "clean",
|
|
278
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
279
|
+
}, a = t.file;
|
|
280
|
+
return typeof URL < "u" && typeof URL.createObjectURL == "function" && a instanceof Blob && this.blobs.set(o.id, URL.createObjectURL(a)), this.store.set(this.key("files"), [...this.files(), o]), { ok: !0, data: { file: o } };
|
|
281
|
+
}
|
|
282
|
+
storageUrl(t) {
|
|
283
|
+
const e = this.files().find((s) => s.id === t.id);
|
|
284
|
+
return e ? { ok: !0, data: { url: this.blobs.get(e.id) ?? `mock://files/${e.id}`, expires_at: new Date(Date.now() + 6e5).toISOString() } } : { ok: !1, error: "not_found" };
|
|
285
|
+
}
|
|
286
|
+
storageList(t) {
|
|
287
|
+
return { ok: !0, data: { files: this.files().filter((s) => !t.upload || s.upload === t.upload) } };
|
|
288
|
+
}
|
|
289
|
+
storageDelete(t) {
|
|
290
|
+
return this.store.set(this.key("files"), this.files().filter((e) => e.id !== t.id)), { ok: !0, data: { id: t.id } };
|
|
291
|
+
}
|
|
292
|
+
// ---------------------------------------------------------------- ai
|
|
293
|
+
prompt(t) {
|
|
294
|
+
return (this.manifest?.prompts ?? []).find((e) => e.id === t) ?? (this.manifest ? null : { id: t, mode: "analysis" });
|
|
295
|
+
}
|
|
296
|
+
async aiAsk(t) {
|
|
297
|
+
const e = this.prompt(String(t.prompt));
|
|
298
|
+
if (!e)
|
|
299
|
+
return { ok: !1, error: "not_found", message: `Prompt [${t.prompt}] is not declared in the manifest.` };
|
|
300
|
+
const s = this.aiHandlers.get(e.id), r = t.vars ?? {};
|
|
301
|
+
return { ok: !0, data: { output: s ? await s(r, "analysis") : u(e.output_schema, r), usage: { input_tokens: 42, output_tokens: 17 } } };
|
|
302
|
+
}
|
|
303
|
+
async aiChat(t) {
|
|
304
|
+
const e = this.prompt(String(t.prompt));
|
|
305
|
+
if (!e)
|
|
306
|
+
return { ok: !1, error: "not_found", message: `Prompt [${t.prompt}] is not declared in the manifest.` };
|
|
307
|
+
const s = String(t.message ?? ""), r = this.chatHistory.get(e.id) ?? [];
|
|
308
|
+
r.push({ role: "user", content: s });
|
|
309
|
+
const i = this.aiHandlers.get(e.id), o = i ? String(await i({ history: r }, "chat", s)) : `[mock ${e.id}] You said: ${s}`;
|
|
310
|
+
r.push({ role: "assistant", content: o }), this.chatHistory.set(e.id, r);
|
|
311
|
+
const a = o.split(" "), c = `msg-${Date.now().toString(36)}`;
|
|
312
|
+
return {
|
|
313
|
+
stream: (async function* () {
|
|
314
|
+
for (let l = 0; l < a.length; l++)
|
|
315
|
+
yield { delta: (l === 0 ? "" : " ") + a[l] };
|
|
316
|
+
})(),
|
|
317
|
+
final: () => ({ message_id: c, text: o, usage: { input_tokens: s.length, output_tokens: o.length } })
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
// ---------------------------------------------------------------- broadcast (BroadcastChannel across tabs)
|
|
321
|
+
member() {
|
|
322
|
+
return { id: this.participantId, name: this.participantName, role: this.role, present: !0, joinedAt: this.joinedAt };
|
|
323
|
+
}
|
|
324
|
+
members() {
|
|
325
|
+
const t = Date.now(), e = [...this.roomMembers.values()].filter((i) => t - i.lastSeen < 15e3).map(({ lastSeen: i, joinedAt: o, ...a }) => a), { joinedAt: s, ...r } = this.member();
|
|
326
|
+
return [r, ...e].sort((i, o) => i.id - o.id);
|
|
327
|
+
}
|
|
328
|
+
stateSnapshot(t) {
|
|
329
|
+
const e = {};
|
|
330
|
+
for (const [s, r] of Object.entries(this.roomState))
|
|
331
|
+
(!t || t.includes(s)) && (e[s] = r.value);
|
|
332
|
+
return e;
|
|
333
|
+
}
|
|
334
|
+
send(t) {
|
|
335
|
+
this.channel?.postMessage({ ...t, sender: this.participantId });
|
|
336
|
+
}
|
|
337
|
+
joinRoom() {
|
|
338
|
+
if (this.channel)
|
|
339
|
+
return;
|
|
340
|
+
const t = this.manifest?.broadcast?.mock_mode ?? "first_in";
|
|
341
|
+
this.role = this.options.role ?? (t === "first_in" ? "facilitator" : "participant"), !(typeof BroadcastChannel > "u") && (this.channel = new BroadcastChannel(this.key("room")), this.channel.onmessage = (e) => this.onRoomMessage(e.data), this.send({ t: "hello", from: this.member() }), this.heartbeat = setInterval(() => this.send({ t: "here", from: this.member() }), 5e3));
|
|
342
|
+
}
|
|
343
|
+
/** An earlier facilitator wins; a later optimistic one steps down. */
|
|
344
|
+
reconcileFacilitator(t) {
|
|
345
|
+
t.role === "facilitator" && this.role === "facilitator" && (t.joinedAt ?? 0) < this.joinedAt && (this.role = "participant", this.pushEvent({ channel: "$room", event: "role", payload: { role: "participant", participant_id: this.participantId } }));
|
|
346
|
+
}
|
|
347
|
+
onRoomMessage(t) {
|
|
348
|
+
const e = t.from;
|
|
349
|
+
if (t.sender !== this.participantId)
|
|
350
|
+
switch (t.t) {
|
|
351
|
+
case "hello":
|
|
352
|
+
e && (this.roomMembers.set(e.id, { ...e, lastSeen: Date.now() }), this.reconcileFacilitator(e), this.send({ t: "here", from: this.member() }), this.send({ t: "state-sync", state: this.roomState }), this.pushEvent({ channel: "$room", event: "presence", payload: { members: this.members() } }));
|
|
353
|
+
break;
|
|
354
|
+
case "here":
|
|
355
|
+
if (e) {
|
|
356
|
+
const s = this.roomMembers.has(e.id);
|
|
357
|
+
this.roomMembers.set(e.id, { ...e, lastSeen: Date.now() }), this.reconcileFacilitator(e), s || this.pushEvent({ channel: "$room", event: "presence", payload: { members: this.members() } });
|
|
358
|
+
}
|
|
359
|
+
break;
|
|
360
|
+
case "bye":
|
|
361
|
+
e && (this.roomMembers.delete(e.id), this.pushEvent({ channel: "$room", event: "presence", payload: { members: this.members() } }));
|
|
362
|
+
break;
|
|
363
|
+
case "event":
|
|
364
|
+
this.pushEvent({ channel: String(t.channel), event: String(t.event), payload: t.payload, from: { participant_id: Number(t.sender), role: e?.role ?? "participant" } });
|
|
365
|
+
break;
|
|
366
|
+
case "state": {
|
|
367
|
+
const s = String(t.key), r = Number(t.version);
|
|
368
|
+
(this.roomState[s]?.version ?? 0) <= r && (this.roomState[s] = { value: t.value, version: r }, this.pushEvent({ channel: "$room", event: "state", payload: { key: s, value: t.value, version: r } }));
|
|
369
|
+
break;
|
|
370
|
+
}
|
|
371
|
+
case "state-sync":
|
|
372
|
+
for (const [s, r] of Object.entries(t.state))
|
|
373
|
+
(this.roomState[s]?.version ?? 0) < r.version && (this.roomState[s] = r);
|
|
374
|
+
break;
|
|
375
|
+
case "role":
|
|
376
|
+
e && (this.roomMembers.set(e.id, { ...e, lastSeen: Date.now() }), e.role === "facilitator" && this.role === "facilitator" && (this.role = "participant", this.pushEvent({ channel: "$room", event: "role", payload: { role: "participant", participant_id: this.participantId } })), this.pushEvent({ channel: "$room", event: "role", payload: { role: e.role, participant_id: e.id } }), this.pushEvent({ channel: "$room", event: "presence", payload: { members: this.members() } }));
|
|
377
|
+
break;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
setRole(t) {
|
|
381
|
+
this.role = t, this.send({ t: "role", from: this.member() }), this.pushEvent({ channel: "$room", event: "role", payload: { role: t, participant_id: this.participantId } });
|
|
382
|
+
}
|
|
383
|
+
publish(t) {
|
|
384
|
+
const e = String(t.event);
|
|
385
|
+
if ((this.manifest?.broadcast?.facilitator_events ?? []).includes(e) && this.role !== "facilitator")
|
|
386
|
+
return { ok: !1, error: "forbidden", message: `Event [${e}] may only be sent by the facilitator.` };
|
|
387
|
+
const r = { participant_id: this.participantId, role: this.role };
|
|
388
|
+
return this.send({ t: "event", channel: t.channel, event: e, payload: t.payload, from: this.member() }), this.pushEvent({ channel: String(t.channel ?? "main"), event: e, payload: t.payload, from: r }), { ok: !0 };
|
|
389
|
+
}
|
|
390
|
+
stateSet(t) {
|
|
391
|
+
const e = String(t.key), s = (this.roomState[e]?.version ?? 0) + 1;
|
|
392
|
+
return this.roomState[e] = { value: t.value, version: s }, this.send({ t: "state", key: e, value: t.value, version: s }), this.pushEvent({ channel: "$room", event: "state", payload: { key: e, value: t.value, version: s } }), { ok: !0, data: { version: s } };
|
|
393
|
+
}
|
|
394
|
+
claim() {
|
|
395
|
+
return this.setRole("facilitator"), { ok: !0, data: { role: "facilitator" } };
|
|
396
|
+
}
|
|
397
|
+
transfer(t) {
|
|
398
|
+
if (this.role !== "facilitator")
|
|
399
|
+
return { ok: !1, error: "forbidden", message: "Only the facilitator can transfer the role." };
|
|
400
|
+
const e = this.roomMembers.get(Number(t.to));
|
|
401
|
+
return e ? (this.role = "participant", e.role = "facilitator", this.send({ t: "role", from: { ...e } }), this.pushEvent({ channel: "$room", event: "role", payload: { role: "participant", participant_id: this.participantId } }), this.pushEvent({ channel: "$room", event: "role", payload: { role: "facilitator", participant_id: e.id } }), { ok: !0 }) : { ok: !1, error: "not_found" };
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
function u(n, t) {
|
|
405
|
+
if (!n)
|
|
406
|
+
return { summary: `Mock analysis of ${JSON.stringify(t).slice(0, 60)}` };
|
|
407
|
+
const e = n.type;
|
|
408
|
+
if (e === "object") {
|
|
409
|
+
const s = {};
|
|
410
|
+
for (const [r, i] of Object.entries(n.properties ?? {}))
|
|
411
|
+
s[r] = u(i, t);
|
|
412
|
+
return s;
|
|
413
|
+
}
|
|
414
|
+
return e === "array" ? [u(n.items, t)] : e === "number" || e === "integer" ? typeof n.minimum == "number" ? n.minimum : 3 : e === "boolean" ? !0 : Array.isArray(n.enum) ? n.enum[0] : "mock";
|
|
415
|
+
}
|
|
416
|
+
class I {
|
|
417
|
+
constructor(t) {
|
|
418
|
+
this.rack = t, this.kind = "mock";
|
|
419
|
+
}
|
|
420
|
+
async send(t, e, s = {}) {
|
|
421
|
+
const r = await this.rack.handle(t, e ?? {});
|
|
422
|
+
if ("stream" in r) {
|
|
423
|
+
for await (const i of r.stream)
|
|
424
|
+
s.onPartial?.(i);
|
|
425
|
+
return { ok: !0, data: r.final() };
|
|
426
|
+
}
|
|
427
|
+
return r;
|
|
428
|
+
}
|
|
429
|
+
fire(t, e = {}) {
|
|
430
|
+
this.rack.handle(t, e ?? {});
|
|
431
|
+
}
|
|
432
|
+
onEvent(t) {
|
|
433
|
+
return this.rack.onEvent(t);
|
|
434
|
+
}
|
|
435
|
+
dispose() {
|
|
436
|
+
this.rack.dispose();
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
class M {
|
|
440
|
+
constructor() {
|
|
441
|
+
this.data = /* @__PURE__ */ new Map();
|
|
442
|
+
}
|
|
443
|
+
get(t) {
|
|
444
|
+
const e = this.data.get(t);
|
|
445
|
+
return e === void 0 ? null : JSON.parse(e);
|
|
446
|
+
}
|
|
447
|
+
set(t, e) {
|
|
448
|
+
this.data.set(t, JSON.stringify(e));
|
|
449
|
+
}
|
|
450
|
+
remove(t) {
|
|
451
|
+
this.data.delete(t);
|
|
452
|
+
}
|
|
453
|
+
keys(t) {
|
|
454
|
+
return [...this.data.keys()].filter((e) => e.startsWith(t));
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
class E {
|
|
458
|
+
get(t) {
|
|
459
|
+
try {
|
|
460
|
+
const e = window.localStorage.getItem(t);
|
|
461
|
+
return e === null ? null : JSON.parse(e);
|
|
462
|
+
} catch {
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
set(t, e) {
|
|
467
|
+
try {
|
|
468
|
+
window.localStorage.setItem(t, JSON.stringify(e));
|
|
469
|
+
} catch {
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
remove(t) {
|
|
473
|
+
try {
|
|
474
|
+
window.localStorage.removeItem(t);
|
|
475
|
+
} catch {
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
keys(t) {
|
|
479
|
+
try {
|
|
480
|
+
const e = [];
|
|
481
|
+
for (let s = 0; s < window.localStorage.length; s++) {
|
|
482
|
+
const r = window.localStorage.key(s);
|
|
483
|
+
r && r.startsWith(t) && e.push(r);
|
|
484
|
+
}
|
|
485
|
+
return e;
|
|
486
|
+
} catch {
|
|
487
|
+
return [];
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
export {
|
|
492
|
+
y as F,
|
|
493
|
+
E as L,
|
|
494
|
+
I as M,
|
|
495
|
+
b as P,
|
|
496
|
+
v as a,
|
|
497
|
+
O as b,
|
|
498
|
+
w as c,
|
|
499
|
+
S as d,
|
|
500
|
+
M as e,
|
|
501
|
+
$ as i,
|
|
502
|
+
_ as n
|
|
503
|
+
};
|
|
504
|
+
//# sourceMappingURL=store-DSV5q7C7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-DSV5q7C7.js","sources":["../src/core/protocol.ts","../src/core/mock/MockRack.ts","../src/core/mock/MockTransport.ts","../src/core/mock/store.ts"],"sourcesContent":["export const PROTOCOL_NAMESPACE = 'ziprack' as const;\nexport const PROTOCOL_VERSION = 1 as const;\nexport const FORMAT = 'ziprack/1' as const;\n\nexport interface Envelope<T = unknown> {\n ns: typeof PROTOCOL_NAMESPACE;\n v: typeof PROTOCOL_VERSION;\n type: string;\n requestId?: string;\n payload?: T;\n}\n\nlet requestCounter = 0;\n\nexport function newRequestId(): string {\n const cryptoRef = typeof globalThis.crypto !== 'undefined' ? globalThis.crypto : undefined;\n if (cryptoRef && typeof cryptoRef.randomUUID === 'function') {\n return cryptoRef.randomUUID();\n }\n requestCounter += 1;\n\n return `req-${Date.now().toString(36)}-${requestCounter.toString(36)}`;\n}\n\nexport function createEnvelope<T>(type: string, payload?: T, requestId?: string): Envelope<T> {\n const envelope: Envelope<T> = { ns: PROTOCOL_NAMESPACE, v: PROTOCOL_VERSION, type, payload };\n if (requestId !== undefined) {\n envelope.requestId = requestId;\n }\n\n return envelope;\n}\n\nexport function isEnvelope(data: unknown): data is Envelope {\n if (typeof data !== 'object' || data === null) {\n return false;\n }\n const candidate = data as Partial<Envelope>;\n\n return candidate.ns === PROTOCOL_NAMESPACE && candidate.v === PROTOCOL_VERSION && typeof candidate.type === 'string';\n}\n\n/** Capability id from a message type (\"db:create\" -> \"db\"). */\nexport function capabilityOf(type: string): string {\n const index = type.indexOf(':');\n\n return index === -1 ? type : type.slice(0, index);\n}\n","import { capabilityOf } from '../protocol';\nimport type { AckResult, JsonObject, LaunchData, RackEvent, RoomMember, RoomRole } from '../types';\nimport type { RecordRow, WhereClause } from '../../db';\nimport type { StoredFile } from '../../storage';\nimport type { Store } from './store';\n\nexport interface MockManifest {\n schema?: string;\n slug: string;\n name: string;\n version: string;\n requires?: { capabilities?: string[]; profile?: string[] };\n media?: Array<{ id: string; provider: string; key: string }>;\n activities?: Array<{ id: string; type: string; label: string; scale?: unknown; segment?: string | null; sequence?: number }>;\n collections?: Array<{ name: string; scope: string; schema?: JsonObject }>;\n uploads?: Array<{ name: string; scope: string; mime?: string[]; max_bytes?: number }>;\n prompts?: Array<{ id: string; mode: 'analysis' | 'chat'; output_schema?: JsonObject }>;\n broadcast?: { facilitator_events?: string[]; channels?: string[]; mock_mode?: 'first_in' | 'opt_in' };\n [key: string]: unknown;\n}\n\nexport type AiMockHandler = (vars: JsonObject, mode: 'analysis' | 'chat', message?: string) => unknown | Promise<unknown>;\n\nexport interface MockRackOptions {\n /** Whether undeclared capabilities are refused, as a real Rack would. Default true when a manifest is present. */\n strict?: boolean;\n log?: (type: string, payload: unknown) => void;\n participantId?: number;\n participantName?: string;\n /** Force the mock room role instead of deriving it from the assignment mode. */\n role?: RoomRole;\n}\n\nexport type MockOutcome = AckResult | { stream: AsyncIterable<JsonObject>; final: () => JsonObject };\n\n/**\n * An in-memory Rack that services every capability so an applet can be built\n * and QA'd standalone. Shared by the browser mock transport (localStorage) and\n * the testing FakeHost (memory).\n */\nexport class MockRack {\n public readonly participantId: number;\n\n public readonly participantName: string;\n\n public readonly statements: Array<JsonObject & { id: string }> = [];\n\n public readonly events: RackEvent[] = [];\n\n private readonly aiHandlers = new Map<string, AiMockHandler>();\n\n private readonly chatHistory = new Map<string, Array<{ role: string; content: string }>>();\n\n private readonly blobs = new Map<string, string>();\n\n private readonly eventListeners = new Set<(event: RackEvent) => void>();\n\n private readonly roomMembers = new Map<number, RoomMember & { lastSeen: number; joinedAt?: number }>();\n\n private roomState: Record<string, { value: unknown; version: number }> = {};\n\n private role: RoomRole = 'participant';\n\n private readonly joinedAt = Date.now() + Math.random();\n\n private channel: BroadcastChannel | null = null;\n\n private heartbeat: ReturnType<typeof setInterval> | null = null;\n\n public constructor(\n public readonly manifest: MockManifest | null,\n private readonly store: Store,\n private readonly options: MockRackOptions = {},\n ) {\n this.participantId = options.participantId ?? Math.floor(Math.random() * 1_000_000) + 1;\n this.participantName = options.participantName ?? 'Dev User';\n }\n\n public get slug(): string {\n return this.manifest?.slug ?? 'applet';\n }\n\n private key(...parts: string[]): string {\n return `ziprack-mock:${this.slug}:${parts.join(':')}`;\n }\n\n public declares(capability: string): boolean {\n if (!this.manifest) {\n return true;\n }\n\n return (this.manifest.requires?.capabilities ?? []).some((ref) => ref.split('@')[0] === capability);\n }\n\n public onEvent(listener: (event: RackEvent) => void): () => void {\n this.eventListeners.add(listener);\n\n return () => {\n this.eventListeners.delete(listener);\n };\n }\n\n public pushEvent(event: RackEvent): void {\n this.events.push(event);\n this.eventListeners.forEach((l) => l(event));\n }\n\n public launchData(nameHint?: string): LaunchData {\n const m = this.manifest;\n const launch: LaunchData = {\n schema: 'ziprack/1',\n actor: { id: this.participantId, name: this.participantName },\n applet: { slug: this.slug, name: `${m?.name ?? nameHint ?? 'Applet'} (mock)`, version: m?.version ?? 'dev' },\n capabilities: m?.requires?.capabilities ?? [],\n media: Object.fromEntries((m?.media ?? []).map((item) => [item.id, {\n provider: item.provider,\n embedUrl: item.provider === 'vimeo' ? `https://player.vimeo.com/video/${item.key}?dnt=1` : `https://www.youtube-nocookie.com/embed/${item.key}?rel=0`,\n meta: null,\n }])),\n };\n\n if (this.declares('auth')) {\n const user: LaunchData['auth'] = { user: { id: this.participantId, display_name: this.participantName } };\n for (const attribute of m?.requires?.profile ?? []) {\n user.user[attribute] = user.user[attribute] ?? `mock-${attribute}`;\n }\n launch.auth = user;\n }\n if (this.declares('attempt')) {\n launch.attempt = this.attempt();\n }\n if (this.declares('activity')) {\n launch.activity = { activities: [...(m?.activities ?? [])].sort((a, b) => (a.sequence ?? 0) - (b.sequence ?? 0)) };\n }\n if (this.declares('db')) {\n launch.db = { collections: (m?.collections ?? []).map((c) => ({ name: c.name, scope: c.scope })) };\n }\n if (this.declares('storage')) {\n launch.storage = { uploads: (m?.uploads ?? []).map((u) => ({ name: u.name, scope: u.scope, mime: u.mime ?? [], max_bytes: u.max_bytes ?? 10 * 1024 * 1024 })) };\n }\n if (this.declares('ai')) {\n launch.ai = { prompts: (m?.prompts ?? []).map((p) => ({ id: p.id, mode: p.mode })) };\n }\n if (this.declares('broadcast')) {\n this.joinRoom();\n launch.broadcast = {\n room: { id: 1, code: 'MOCK01', name: `${this.slug} room`, status: 'open', mode: m?.broadcast?.mock_mode ?? 'first_in' },\n role: this.role,\n members: this.members(),\n state: this.stateSnapshot(),\n channels: m?.broadcast?.channels ?? ['main'],\n };\n }\n\n return launch;\n }\n\n public mockAi(promptId: string, handler: AiMockHandler): void {\n this.aiHandlers.set(promptId, handler);\n }\n\n public dispose(): void {\n if (this.heartbeat) {\n clearInterval(this.heartbeat);\n }\n if (this.channel) {\n this.send({ t: 'bye', from: this.member() });\n this.channel.close();\n }\n }\n\n // ---------------------------------------------------------------- dispatch\n\n public async handle(type: string, payload: JsonObject): Promise<MockOutcome> {\n this.options.log?.(type, payload);\n\n if (type === 'rack:eject') {\n return { ok: true };\n }\n\n const capability = capabilityOf(type);\n if ((this.options.strict ?? this.manifest !== null) && !this.declares(capability)) {\n return { ok: false, error: 'undeclared_capability', message: `The manifest does not declare the [${capability}] capability.` };\n }\n\n switch (type) {\n case 'attempt:state': return this.attemptState(payload);\n case 'attempt:segment': return this.attemptSegment(payload);\n case 'attempt:complete': return this.attemptComplete(payload);\n case 'activity:statement': return this.statement(payload);\n case 'db:create': return this.dbCreate(payload);\n case 'db:get': return this.dbGet(payload);\n case 'db:update': return this.dbUpdate(payload);\n case 'db:delete': return this.dbDelete(payload);\n case 'db:list': return this.dbList(payload);\n case 'db:count': return this.dbCount(payload);\n case 'storage:put': return this.storagePut(payload);\n case 'storage:url': return this.storageUrl(payload);\n case 'storage:list': return this.storageList(payload);\n case 'storage:delete': return this.storageDelete(payload);\n case 'ai:ask': return this.aiAsk(payload);\n case 'ai:chat': return this.aiChat(payload);\n case 'ai:chat.reset': this.chatHistory.delete(String(payload.prompt)); return { ok: true };\n case 'broadcast:join': return { ok: true, data: { members: this.members(), state: this.stateSnapshot() } };\n case 'broadcast:leave': return { ok: true };\n case 'broadcast:publish': return this.publish(payload);\n case 'broadcast:state.get': return { ok: true, data: { state: this.stateSnapshot(Array.isArray(payload.keys) ? (payload.keys as string[]) : undefined) } };\n case 'broadcast:state.set': return this.stateSet(payload);\n case 'broadcast:presence': return { ok: true, data: { members: this.members() } };\n case 'broadcast:claim': return this.claim();\n case 'broadcast:transfer': return this.transfer(payload);\n default:\n return { ok: false, error: 'unknown_type', message: `Unknown message type [${type}].` };\n }\n }\n\n // ---------------------------------------------------------------- attempt\n\n public attempt(): NonNullable<LaunchData['attempt']> {\n return this.store.get(this.key('attempt')) ?? { id: 1, status: 'in_progress', state: null, segment: null };\n }\n\n private saveAttempt(attempt: NonNullable<LaunchData['attempt']>): void {\n this.store.set(this.key('attempt'), attempt);\n }\n\n private attemptState(payload: JsonObject): AckResult {\n const attempt = this.attempt();\n if (attempt.status === 'completed') {\n return { ok: false, error: 'completed', message: 'This attempt is already completed.' };\n }\n const size = JSON.stringify(payload.state ?? {}).length;\n if (size > 65536) {\n return { ok: false, error: 'validation', message: `State is ${size} bytes; the limit is 65536.` };\n }\n this.saveAttempt({ ...attempt, state: (payload.state as JsonObject) ?? null });\n\n return { ok: true };\n }\n\n private attemptSegment(payload: JsonObject): AckResult {\n const attempt = this.attempt();\n if (attempt.status === 'completed') {\n return { ok: false, error: 'completed' };\n }\n this.saveAttempt({ ...attempt, segment: (payload.segment as Record<string, string>) ?? null });\n\n return { ok: true };\n }\n\n private attemptComplete(payload: JsonObject): AckResult {\n const attempt = this.attempt();\n const completedAt = new Date().toISOString();\n if (attempt.status !== 'completed') {\n this.saveAttempt({ ...attempt, status: 'completed' });\n if (this.declares('activity')) {\n this.statement({ verb: 'completed', activity: { id: 'attempt', type: 'attempt' }, result: payload.summary ?? null, occurred_at: completedAt });\n }\n }\n\n return { ok: true, data: { status: 'completed', completed_at: completedAt } };\n }\n\n /** Clear a completed mock attempt so the experience can be run again. */\n public resetAttempt(): void {\n this.store.remove(this.key('attempt'));\n }\n\n // ---------------------------------------------------------------- activity\n\n private statement(payload: JsonObject): AckResult<{ id: string }> {\n const verb = String(payload.verb ?? '');\n if (!/^[a-z][a-z0-9_.:-]*$/.test(verb) || verb.length > 100) {\n return { ok: false, error: 'validation', message: `Invalid verb [${verb}].` };\n }\n const activity = payload.activity as { id?: string } | undefined;\n if (!activity?.id) {\n return { ok: false, error: 'validation', message: 'activity.id is required.' };\n }\n const id = `mock-${Date.now().toString(36)}-${this.statements.length + 1}`;\n this.statements.push({ id, ...payload });\n\n return { ok: true, data: { id } };\n }\n\n // ---------------------------------------------------------------- db\n\n private collectionKey(name: string): string {\n return this.key('db', name);\n }\n\n public records(collection: string): RecordRow[] {\n return this.store.get<RecordRow[]>(this.collectionKey(collection)) ?? [];\n }\n\n private saveRecords(collection: string, records: RecordRow[]): void {\n this.store.set(this.collectionKey(collection), records);\n }\n\n private collectionDeclared(name: string): AckResult | null {\n if (this.manifest && !(this.manifest.collections ?? []).some((c) => c.name === name)) {\n return { ok: false, error: 'not_found', message: `Collection [${name}] is not declared in the manifest.` };\n }\n const scope = (this.manifest?.collections ?? []).find((c) => c.name === name)?.scope;\n if (scope === 'attempt' && this.attempt().status === 'completed') {\n return { ok: false, error: 'completed', message: 'Attempt-scoped records are frozen after completion.' };\n }\n\n return null;\n }\n\n private dbCreate(payload: JsonObject): AckResult {\n const name = String(payload.collection);\n const declared = this.collectionDeclared(name);\n if (declared) {\n return declared;\n }\n const now = new Date().toISOString();\n const record: RecordRow = {\n id: `rec-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`,\n data: (payload.data as JsonObject) ?? {},\n owner_id: this.participantId,\n created_at: now,\n updated_at: now,\n };\n this.saveRecords(name, [...this.records(name), record]);\n\n return { ok: true, data: { record } };\n }\n\n private dbGet(payload: JsonObject): AckResult {\n const record = this.records(String(payload.collection)).find((r) => r.id === payload.id);\n\n return record ? { ok: true, data: { record } } : { ok: false, error: 'not_found' };\n }\n\n private dbUpdate(payload: JsonObject): AckResult {\n const name = String(payload.collection);\n const frozen = this.collectionDeclared(name);\n if (frozen && frozen.error === 'completed') {\n return frozen;\n }\n const records = this.records(name);\n const index = records.findIndex((r) => r.id === payload.id);\n if (index === -1) {\n return { ok: false, error: 'not_found' };\n }\n const merge = payload.merge !== false;\n const data = (payload.data as JsonObject) ?? {};\n records[index] = { ...records[index], data: merge ? { ...records[index].data, ...data } : data, updated_at: new Date().toISOString() };\n this.saveRecords(name, records);\n\n return { ok: true, data: { record: records[index] } };\n }\n\n private dbDelete(payload: JsonObject): AckResult {\n const name = String(payload.collection);\n const records = this.records(name);\n if (!records.some((r) => r.id === payload.id)) {\n return { ok: false, error: 'not_found' };\n }\n this.saveRecords(name, records.filter((r) => r.id !== payload.id));\n\n return { ok: true, data: { id: payload.id } };\n }\n\n private filter(records: RecordRow[], where: WhereClause[] | undefined): RecordRow[] {\n if (!where) {\n return records;\n }\n\n return records.filter((record) => where.every(([path, op, value]) => {\n const actual = path.split('.').reduce<unknown>((acc, part) => (acc as JsonObject | undefined)?.[part], record.data);\n switch (op) {\n case '=': return actual === value;\n case '!=': return actual !== value;\n case '<': return (actual as number) < (value as number);\n case '<=': return (actual as number) <= (value as number);\n case '>': return (actual as number) > (value as number);\n case '>=': return (actual as number) >= (value as number);\n case 'in': return Array.isArray(value) && value.includes(actual);\n default: return false;\n }\n }));\n }\n\n private dbList(payload: JsonObject): AckResult {\n const name = String(payload.collection);\n if (this.manifest && !(this.manifest.collections ?? []).some((c) => c.name === name)) {\n return { ok: false, error: 'not_found', message: `Collection [${name}] is not declared in the manifest.` };\n }\n let records = this.filter(this.records(name), payload.where as WhereClause[] | undefined);\n if (typeof payload.orderBy === 'string') {\n const path = payload.orderBy;\n const dir = payload.direction === 'desc' ? -1 : 1;\n records = [...records].sort((a, b) => {\n const av = path.split('.').reduce<unknown>((acc, p) => (acc as JsonObject | undefined)?.[p], a.data) as number | string;\n const bv = path.split('.').reduce<unknown>((acc, p) => (acc as JsonObject | undefined)?.[p], b.data) as number | string;\n\n return av < bv ? -dir : av > bv ? dir : 0;\n });\n }\n const limit = Math.min(Number(payload.limit ?? 50), 100);\n const offset = payload.cursor ? Number(payload.cursor) : 0;\n const page = records.slice(offset, offset + limit);\n const nextCursor = offset + limit < records.length ? String(offset + limit) : null;\n\n return { ok: true, data: { records: page, nextCursor } };\n }\n\n private dbCount(payload: JsonObject): AckResult {\n return { ok: true, data: { count: this.filter(this.records(String(payload.collection)), payload.where as WhereClause[] | undefined).length } };\n }\n\n // ---------------------------------------------------------------- storage\n\n public files(): StoredFile[] {\n return this.store.get<StoredFile[]>(this.key('files')) ?? [];\n }\n\n private storagePut(payload: JsonObject): AckResult {\n const upload = String(payload.upload);\n const slot = (this.manifest?.uploads ?? []).find((u) => u.name === upload);\n if (this.manifest && !slot) {\n return { ok: false, error: 'not_found', message: `Upload [${upload}] is not declared in the manifest.` };\n }\n const mime = String(payload.mime ?? '');\n if (slot?.mime && slot.mime.length > 0 && !slot.mime.some((m) => m === mime || (m.endsWith('/*') && mime.startsWith(m.slice(0, -1))))) {\n return { ok: false, error: 'validation', message: `MIME type [${mime}] is not allowed for upload [${upload}].` };\n }\n const bytes = Number(payload.bytes ?? 0);\n if (slot?.max_bytes && bytes > slot.max_bytes) {\n return { ok: false, error: 'quota_exceeded', message: `File is ${bytes} bytes; the limit is ${slot.max_bytes}.` };\n }\n const file: StoredFile = {\n id: `file-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`,\n upload,\n name: String(payload.name ?? 'blob'),\n mime,\n bytes,\n status: 'clean',\n created_at: new Date().toISOString(),\n };\n const blob = payload.file;\n if (typeof URL !== 'undefined' && typeof URL.createObjectURL === 'function' && blob instanceof Blob) {\n this.blobs.set(file.id, URL.createObjectURL(blob));\n }\n this.store.set(this.key('files'), [...this.files(), file]);\n\n return { ok: true, data: { file } };\n }\n\n private storageUrl(payload: JsonObject): AckResult {\n const file = this.files().find((f) => f.id === payload.id);\n if (!file) {\n return { ok: false, error: 'not_found' };\n }\n\n return { ok: true, data: { url: this.blobs.get(file.id) ?? `mock://files/${file.id}`, expires_at: new Date(Date.now() + 600_000).toISOString() } };\n }\n\n private storageList(payload: JsonObject): AckResult {\n const files = this.files().filter((f) => !payload.upload || f.upload === payload.upload);\n\n return { ok: true, data: { files } };\n }\n\n private storageDelete(payload: JsonObject): AckResult {\n this.store.set(this.key('files'), this.files().filter((f) => f.id !== payload.id));\n\n return { ok: true, data: { id: payload.id } };\n }\n\n // ---------------------------------------------------------------- ai\n\n private prompt(id: string): { id: string; mode: 'analysis' | 'chat'; output_schema?: JsonObject } | null {\n return (this.manifest?.prompts ?? []).find((p) => p.id === id) ?? (this.manifest ? null : { id, mode: 'analysis' });\n }\n\n private async aiAsk(payload: JsonObject): Promise<AckResult> {\n const prompt = this.prompt(String(payload.prompt));\n if (!prompt) {\n return { ok: false, error: 'not_found', message: `Prompt [${payload.prompt}] is not declared in the manifest.` };\n }\n const handler = this.aiHandlers.get(prompt.id);\n const vars = (payload.vars as JsonObject) ?? {};\n const output = handler ? await handler(vars, 'analysis') : stubFromSchema(prompt.output_schema, vars);\n\n return { ok: true, data: { output, usage: { input_tokens: 42, output_tokens: 17 } } };\n }\n\n private async aiChat(payload: JsonObject): Promise<MockOutcome> {\n const prompt = this.prompt(String(payload.prompt));\n if (!prompt) {\n return { ok: false, error: 'not_found', message: `Prompt [${payload.prompt}] is not declared in the manifest.` };\n }\n const message = String(payload.message ?? '');\n const history = this.chatHistory.get(prompt.id) ?? [];\n history.push({ role: 'user', content: message });\n const handler = this.aiHandlers.get(prompt.id);\n const reply = handler ? String(await handler({ history }, 'chat', message)) : `[mock ${prompt.id}] You said: ${message}`;\n history.push({ role: 'assistant', content: reply });\n this.chatHistory.set(prompt.id, history);\n\n const words = reply.split(' ');\n const messageId = `msg-${Date.now().toString(36)}`;\n\n return {\n stream: (async function* () {\n for (let i = 0; i < words.length; i++) {\n yield { delta: (i === 0 ? '' : ' ') + words[i] };\n }\n })(),\n final: () => ({ message_id: messageId, text: reply, usage: { input_tokens: message.length, output_tokens: reply.length } }),\n };\n }\n\n // ---------------------------------------------------------------- broadcast (BroadcastChannel across tabs)\n\n private member(): RoomMember & { joinedAt: number } {\n return { id: this.participantId, name: this.participantName, role: this.role, present: true, joinedAt: this.joinedAt };\n }\n\n public members(): RoomMember[] {\n const now = Date.now();\n const others = [...this.roomMembers.values()].filter((m) => now - m.lastSeen < 15_000).map(({ lastSeen: _l, joinedAt: _j, ...m }) => m);\n const { joinedAt: _joined, ...self } = this.member();\n\n return [self, ...others].sort((a, b) => a.id - b.id);\n }\n\n private stateSnapshot(keys?: string[]): JsonObject {\n const snapshot: JsonObject = {};\n for (const [key, entry] of Object.entries(this.roomState)) {\n if (!keys || keys.includes(key)) {\n snapshot[key] = entry.value;\n }\n }\n\n return snapshot;\n }\n\n private send(message: JsonObject): void {\n this.channel?.postMessage({ ...message, sender: this.participantId });\n }\n\n private joinRoom(): void {\n if (this.channel) {\n return;\n }\n const mode = this.manifest?.broadcast?.mock_mode ?? 'first_in';\n // Optimistic first_in: this tab takes the role until an earlier facilitator answers.\n this.role = this.options.role ?? (mode === 'first_in' ? 'facilitator' : 'participant');\n\n if (typeof BroadcastChannel === 'undefined') {\n return;\n }\n this.channel = new BroadcastChannel(this.key('room'));\n this.channel.onmessage = (event: MessageEvent<JsonObject>) => this.onRoomMessage(event.data);\n this.send({ t: 'hello', from: this.member() });\n this.heartbeat = setInterval(() => this.send({ t: 'here', from: this.member() }), 5000);\n }\n\n /** An earlier facilitator wins; a later optimistic one steps down. */\n private reconcileFacilitator(from: RoomMember & { joinedAt?: number }): void {\n if (from.role === 'facilitator' && this.role === 'facilitator' && (from.joinedAt ?? 0) < this.joinedAt) {\n this.role = 'participant';\n this.pushEvent({ channel: '$room', event: 'role', payload: { role: 'participant', participant_id: this.participantId } });\n }\n }\n\n private onRoomMessage(data: JsonObject): void {\n const from = data.from as (RoomMember & { joinedAt?: number }) | undefined;\n if (data.sender === this.participantId) {\n return;\n }\n switch (data.t) {\n case 'hello':\n if (from) {\n this.roomMembers.set(from.id, { ...from, lastSeen: Date.now() });\n this.reconcileFacilitator(from);\n this.send({ t: 'here', from: this.member() });\n this.send({ t: 'state-sync', state: this.roomState });\n this.pushEvent({ channel: '$room', event: 'presence', payload: { members: this.members() } });\n }\n break;\n case 'here':\n if (from) {\n const known = this.roomMembers.has(from.id);\n this.roomMembers.set(from.id, { ...from, lastSeen: Date.now() });\n this.reconcileFacilitator(from);\n if (!known) {\n this.pushEvent({ channel: '$room', event: 'presence', payload: { members: this.members() } });\n }\n }\n break;\n case 'bye':\n if (from) {\n this.roomMembers.delete(from.id);\n this.pushEvent({ channel: '$room', event: 'presence', payload: { members: this.members() } });\n }\n break;\n case 'event':\n this.pushEvent({ channel: String(data.channel), event: String(data.event), payload: data.payload, from: { participant_id: Number(data.sender), role: (from?.role ?? 'participant') as RoomRole } });\n break;\n case 'state': {\n const key = String(data.key);\n const version = Number(data.version);\n if ((this.roomState[key]?.version ?? 0) <= version) {\n this.roomState[key] = { value: data.value, version };\n this.pushEvent({ channel: '$room', event: 'state', payload: { key, value: data.value, version } });\n }\n break;\n }\n case 'state-sync':\n for (const [key, entry] of Object.entries(data.state as Record<string, { value: unknown; version: number }>)) {\n if ((this.roomState[key]?.version ?? 0) < entry.version) {\n this.roomState[key] = entry;\n }\n }\n break;\n case 'role':\n if (from) {\n this.roomMembers.set(from.id, { ...from, lastSeen: Date.now() });\n if (from.role === 'facilitator' && this.role === 'facilitator') {\n this.role = 'participant';\n this.pushEvent({ channel: '$room', event: 'role', payload: { role: 'participant', participant_id: this.participantId } });\n }\n this.pushEvent({ channel: '$room', event: 'role', payload: { role: from.role, participant_id: from.id } });\n this.pushEvent({ channel: '$room', event: 'presence', payload: { members: this.members() } });\n }\n break;\n default:\n break;\n }\n }\n\n private setRole(role: RoomRole): void {\n this.role = role;\n this.send({ t: 'role', from: this.member() });\n this.pushEvent({ channel: '$room', event: 'role', payload: { role, participant_id: this.participantId } });\n }\n\n private publish(payload: JsonObject): AckResult {\n const event = String(payload.event);\n const facilitatorOnly = this.manifest?.broadcast?.facilitator_events ?? [];\n if (facilitatorOnly.includes(event) && this.role !== 'facilitator') {\n return { ok: false, error: 'forbidden', message: `Event [${event}] may only be sent by the facilitator.` };\n }\n const from = { participant_id: this.participantId, role: this.role };\n this.send({ t: 'event', channel: payload.channel, event, payload: payload.payload, from: this.member() });\n this.pushEvent({ channel: String(payload.channel ?? 'main'), event, payload: payload.payload, from });\n\n return { ok: true };\n }\n\n private stateSet(payload: JsonObject): AckResult {\n const key = String(payload.key);\n const version = (this.roomState[key]?.version ?? 0) + 1;\n this.roomState[key] = { value: payload.value, version };\n this.send({ t: 'state', key, value: payload.value, version });\n this.pushEvent({ channel: '$room', event: 'state', payload: { key, value: payload.value, version } });\n\n return { ok: true, data: { version } };\n }\n\n private claim(): AckResult {\n this.setRole('facilitator');\n\n return { ok: true, data: { role: 'facilitator' } };\n }\n\n private transfer(payload: JsonObject): AckResult {\n if (this.role !== 'facilitator') {\n return { ok: false, error: 'forbidden', message: 'Only the facilitator can transfer the role.' };\n }\n const target = this.roomMembers.get(Number(payload.to));\n if (!target) {\n return { ok: false, error: 'not_found' };\n }\n this.role = 'participant';\n target.role = 'facilitator';\n this.send({ t: 'role', from: { ...target } });\n this.pushEvent({ channel: '$room', event: 'role', payload: { role: 'participant', participant_id: this.participantId } });\n this.pushEvent({ channel: '$room', event: 'role', payload: { role: 'facilitator', participant_id: target.id } });\n\n return { ok: true };\n }\n}\n\n/** A plausible object for an analysis prompt's output_schema, so UIs render in mock mode. */\nexport function stubFromSchema(schema: JsonObject | undefined, vars: JsonObject): unknown {\n if (!schema) {\n return { summary: `Mock analysis of ${JSON.stringify(vars).slice(0, 60)}` };\n }\n const type = schema.type;\n if (type === 'object') {\n const out: JsonObject = {};\n for (const [key, prop] of Object.entries((schema.properties as Record<string, JsonObject>) ?? {})) {\n out[key] = stubFromSchema(prop, vars);\n }\n\n return out;\n }\n if (type === 'array') {\n return [stubFromSchema(schema.items as JsonObject, vars)];\n }\n if (type === 'number' || type === 'integer') {\n return typeof schema.minimum === 'number' ? schema.minimum : 3;\n }\n if (type === 'boolean') {\n return true;\n }\n if (Array.isArray(schema.enum)) {\n return schema.enum[0];\n }\n\n return 'mock';\n}\n","import type { AckResult, JsonObject, RackEvent, SendOptions, Transport } from '../types';\nimport type { MockRack } from './MockRack';\n\n/**\n * Transport that fulfils every message locally through a MockRack.\n */\nexport class MockTransport implements Transport {\n public readonly kind = 'mock' as const;\n\n public constructor(public readonly rack: MockRack) {}\n\n public async send<T = JsonObject>(type: string, payload: unknown, options: SendOptions = {}): Promise<AckResult<T>> {\n const outcome = await this.rack.handle(type, (payload as JsonObject) ?? {});\n\n if ('stream' in outcome) {\n for await (const chunk of outcome.stream) {\n options.onPartial?.(chunk);\n }\n\n return { ok: true, data: outcome.final() as T };\n }\n\n return outcome as AckResult<T>;\n }\n\n public fire(type: string, payload: unknown = {}): void {\n void this.rack.handle(type, (payload as JsonObject) ?? {});\n }\n\n public onEvent(listener: (event: RackEvent) => void): () => void {\n return this.rack.onEvent(listener);\n }\n\n public dispose(): void {\n this.rack.dispose();\n }\n}\n","/**\n * Key/value persistence for the mock Rack. localStorage in the browser so a\n * standalone session survives a refresh; memory in tests.\n */\nexport interface Store {\n get<T>(key: string): T | null;\n set(key: string, value: unknown): void;\n remove(key: string): void;\n keys(prefix: string): string[];\n}\n\nexport class MemoryStore implements Store {\n private readonly data = new Map<string, string>();\n\n public get<T>(key: string): T | null {\n const raw = this.data.get(key);\n\n return raw === undefined ? null : (JSON.parse(raw) as T);\n }\n\n public set(key: string, value: unknown): void {\n this.data.set(key, JSON.stringify(value));\n }\n\n public remove(key: string): void {\n this.data.delete(key);\n }\n\n public keys(prefix: string): string[] {\n return [...this.data.keys()].filter((k) => k.startsWith(prefix));\n }\n}\n\nexport class LocalStore implements Store {\n public get<T>(key: string): T | null {\n try {\n const raw = window.localStorage.getItem(key);\n\n return raw === null ? null : (JSON.parse(raw) as T);\n } catch {\n return null;\n }\n }\n\n public set(key: string, value: unknown): void {\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch {\n // Storage may be unavailable; mock mode tolerates that silently.\n }\n }\n\n public remove(key: string): void {\n try {\n window.localStorage.removeItem(key);\n } catch {\n // ignore\n }\n }\n\n public keys(prefix: string): string[] {\n try {\n const keys: string[] = [];\n for (let i = 0; i < window.localStorage.length; i++) {\n const key = window.localStorage.key(i);\n if (key && key.startsWith(prefix)) {\n keys.push(key);\n }\n }\n\n return keys;\n } catch {\n return [];\n }\n }\n}\n"],"names":["PROTOCOL_NAMESPACE","PROTOCOL_VERSION","FORMAT","requestCounter","newRequestId","cryptoRef","createEnvelope","type","payload","requestId","envelope","isEnvelope","data","candidate","capabilityOf","index","MockRack","manifest","store","options","parts","capability","ref","listener","event","l","nameHint","m","launch","item","user","attribute","a","b","c","u","p","promptId","handler","attempt","size","completedAt","verb","id","name","collection","records","declared","now","record","r","frozen","merge","where","path","op","value","actual","acc","part","dir","av","bv","limit","offset","page","nextCursor","upload","slot","mime","bytes","file","blob","f","prompt","vars","stubFromSchema","message","history","reply","words","messageId","i","others","_l","_j","_joined","self","keys","snapshot","key","entry","mode","from","known","version","role","target","schema","out","prop","MockTransport","rack","outcome","chunk","MemoryStore","raw","prefix","k","LocalStore"],"mappings":"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"}
|