@vibevibes/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/index.js ADDED
@@ -0,0 +1,720 @@
1
+ // src/define.ts
2
+ function defineTool(config) {
3
+ return {
4
+ name: config.name,
5
+ description: config.description,
6
+ input_schema: config.input_schema,
7
+ risk: config.risk ?? "low",
8
+ capabilities_required: config.capabilities_required ?? [],
9
+ handler: config.handler
10
+ };
11
+ }
12
+ function defineTest(config) {
13
+ return { name: config.name, run: config.run };
14
+ }
15
+ function defineEphemeralAction(config) {
16
+ return {
17
+ name: config.name,
18
+ description: config.description,
19
+ input_schema: config.input_schema
20
+ };
21
+ }
22
+ function quickTool(name, description, input_schema, handler) {
23
+ return {
24
+ name,
25
+ description,
26
+ input_schema,
27
+ risk: "low",
28
+ capabilities_required: ["state.write"],
29
+ handler
30
+ };
31
+ }
32
+ function defineExperience(module) {
33
+ const m = module.manifest;
34
+ return {
35
+ ...module,
36
+ manifest: {
37
+ ...m,
38
+ version: m.version || "0.0.1",
39
+ requested_capabilities: m.requested_capabilities || ["state.write"]
40
+ }
41
+ };
42
+ }
43
+ function validateExperience(module) {
44
+ const errors = [];
45
+ if (!module.manifest?.id) {
46
+ errors.push("manifest.id is required");
47
+ }
48
+ if (!module.manifest?.version) {
49
+ errors.push("manifest.version is required");
50
+ }
51
+ if (!module.manifest?.title) {
52
+ errors.push("manifest.title is required");
53
+ }
54
+ if (!module.Canvas) {
55
+ errors.push("Canvas component is required");
56
+ }
57
+ if (!Array.isArray(module.tools)) {
58
+ errors.push("tools must be an array");
59
+ } else {
60
+ module.tools.forEach((tool, idx) => {
61
+ if (!tool.name) {
62
+ errors.push(`tools[${idx}].name is required`);
63
+ }
64
+ if (!tool.input_schema) {
65
+ errors.push(`tools[${idx}].input_schema is required`);
66
+ }
67
+ if (typeof tool.handler !== "function") {
68
+ errors.push(`tools[${idx}].handler must be a function`);
69
+ }
70
+ });
71
+ }
72
+ return {
73
+ valid: errors.length === 0,
74
+ errors
75
+ };
76
+ }
77
+
78
+ // src/hooks.ts
79
+ function getReact() {
80
+ const R = globalThis.React;
81
+ if (!R) throw new Error("React is not available. Hooks must be used inside a Canvas component.");
82
+ return R;
83
+ }
84
+ var React = new Proxy({}, {
85
+ get(_target, prop) {
86
+ return getReact()[prop];
87
+ }
88
+ });
89
+ function useToolCall(callTool) {
90
+ const [loading, setLoading] = React.useState(false);
91
+ const [error, setError] = React.useState(null);
92
+ const call = React.useCallback(
93
+ async (name, input) => {
94
+ setLoading(true);
95
+ setError(null);
96
+ try {
97
+ const result = await callTool(name, input);
98
+ return result;
99
+ } catch (err) {
100
+ const msg = err instanceof Error ? err.message : String(err);
101
+ setError(msg);
102
+ throw err;
103
+ } finally {
104
+ setLoading(false);
105
+ }
106
+ },
107
+ [callTool]
108
+ );
109
+ return { call, loading, error };
110
+ }
111
+ function useSharedState(sharedState, key, defaultValue) {
112
+ const value = sharedState[key];
113
+ if (value === void 0) return defaultValue;
114
+ return value;
115
+ }
116
+ function useOptimisticTool(callTool, sharedState) {
117
+ const [optimistic, setOptimistic] = React.useState(null);
118
+ const [pending, setPending] = React.useState(false);
119
+ const call = React.useCallback(
120
+ async (name, input, optimisticState) => {
121
+ setOptimistic(optimisticState);
122
+ setPending(true);
123
+ try {
124
+ const result = await callTool(name, input);
125
+ setOptimistic(null);
126
+ return result;
127
+ } catch (err) {
128
+ setOptimistic(null);
129
+ throw err;
130
+ } finally {
131
+ setPending(false);
132
+ }
133
+ },
134
+ [callTool]
135
+ );
136
+ const state = optimistic ? { ...sharedState, ...optimistic } : sharedState;
137
+ return { call, state, pending };
138
+ }
139
+ function useAnimationFrame(sharedState, interpolate) {
140
+ const prevStateRef = React.useRef(sharedState);
141
+ const targetStateRef = React.useRef(sharedState);
142
+ const displayStateRef = React.useRef(sharedState);
143
+ const [displayState, setDisplayState] = React.useState(sharedState);
144
+ const rafRef = React.useRef(null);
145
+ const transitionStartRef = React.useRef(0);
146
+ const TRANSITION_MS = 50;
147
+ React.useEffect(() => {
148
+ prevStateRef.current = displayStateRef.current;
149
+ targetStateRef.current = sharedState;
150
+ transitionStartRef.current = performance.now();
151
+ if (!rafRef.current) {
152
+ const tick = () => {
153
+ const now = performance.now();
154
+ const elapsed = now - transitionStartRef.current;
155
+ const t = Math.min(elapsed / TRANSITION_MS, 1);
156
+ let next;
157
+ if (interpolate && t < 1) {
158
+ next = interpolate(prevStateRef.current, targetStateRef.current, t);
159
+ } else {
160
+ next = targetStateRef.current;
161
+ }
162
+ displayStateRef.current = next;
163
+ setDisplayState(next);
164
+ if (t < 1 && interpolate) {
165
+ rafRef.current = requestAnimationFrame(tick);
166
+ } else {
167
+ rafRef.current = null;
168
+ }
169
+ };
170
+ rafRef.current = requestAnimationFrame(tick);
171
+ }
172
+ }, [sharedState, interpolate]);
173
+ React.useEffect(() => {
174
+ return () => {
175
+ if (rafRef.current) {
176
+ cancelAnimationFrame(rafRef.current);
177
+ rafRef.current = null;
178
+ }
179
+ };
180
+ }, []);
181
+ return displayState;
182
+ }
183
+ function useParticipants(participants) {
184
+ return React.useMemo(() => {
185
+ return participants.map((id) => {
186
+ const match = id.match(/^(.+)-(human|ai)-(\d+)$/);
187
+ if (match) {
188
+ return {
189
+ id,
190
+ username: match[1],
191
+ type: match[2],
192
+ index: parseInt(match[3], 10)
193
+ };
194
+ }
195
+ return { id, username: id, type: "unknown", index: 0 };
196
+ });
197
+ }, [participants]);
198
+ }
199
+ function useFollow(actorId, participants, ephemeralState, setEphemeral, _onEphemeralAction, dispatchEphemeralAction) {
200
+ const myEphemeral = ephemeralState[actorId];
201
+ const following = myEphemeral?._follow ?? null;
202
+ const followers = React.useMemo(() => {
203
+ const result = [];
204
+ for (const pid of participants) {
205
+ if (pid === actorId) continue;
206
+ const peerFollow = ephemeralState[pid]?._follow;
207
+ if (peerFollow && peerFollow.targetActorId === actorId) {
208
+ result.push({
209
+ actorId: pid,
210
+ mode: peerFollow.mode,
211
+ since: peerFollow.since
212
+ });
213
+ }
214
+ }
215
+ return result;
216
+ }, [participants, ephemeralState, actorId]);
217
+ const follow = React.useCallback(
218
+ (targetActorId, mode) => {
219
+ if (targetActorId === actorId) return;
220
+ const followData = {
221
+ targetActorId,
222
+ mode,
223
+ since: Date.now()
224
+ };
225
+ setEphemeral({ _follow: followData });
226
+ if (dispatchEphemeralAction) {
227
+ dispatchEphemeralAction("follow.started", {
228
+ follower: actorId,
229
+ target: targetActorId,
230
+ mode
231
+ });
232
+ }
233
+ },
234
+ [actorId, setEphemeral, dispatchEphemeralAction]
235
+ );
236
+ const unfollow = React.useCallback(() => {
237
+ const currentTarget = following?.targetActorId;
238
+ setEphemeral({ _follow: null });
239
+ if (dispatchEphemeralAction && currentTarget) {
240
+ dispatchEphemeralAction("follow.stopped", {
241
+ follower: actorId,
242
+ target: currentTarget
243
+ });
244
+ }
245
+ }, [actorId, following, setEphemeral, dispatchEphemeralAction]);
246
+ React.useEffect(() => {
247
+ if (!following) return;
248
+ if (!participants.includes(following.targetActorId)) {
249
+ setEphemeral({ _follow: null });
250
+ }
251
+ }, [following, participants, setEphemeral]);
252
+ return { follow, unfollow, following, followers };
253
+ }
254
+ function useTypingIndicator(actorId, ephemeralState, setEphemeral, timeoutMs = 3e3) {
255
+ const timerRef = React.useRef(null);
256
+ const setTyping = React.useCallback((isTyping) => {
257
+ setEphemeral({ _typing: isTyping ? Date.now() : null });
258
+ if (timerRef.current) clearTimeout(timerRef.current);
259
+ if (isTyping) {
260
+ timerRef.current = setTimeout(() => {
261
+ setEphemeral({ _typing: null });
262
+ }, timeoutMs);
263
+ }
264
+ }, [setEphemeral, timeoutMs]);
265
+ React.useEffect(() => {
266
+ return () => {
267
+ if (timerRef.current) clearTimeout(timerRef.current);
268
+ };
269
+ }, []);
270
+ const now = Date.now();
271
+ const typingUsers = Object.entries(ephemeralState).filter(([id, data]) => id !== actorId && data._typing && now - data._typing < timeoutMs + 2e3).map(([id]) => id);
272
+ return { setTyping, typingUsers };
273
+ }
274
+
275
+ // src/components.ts
276
+ function getReact2() {
277
+ const R = globalThis.React;
278
+ if (!R) throw new Error("React is not available.");
279
+ return R;
280
+ }
281
+ function h(type, props, ...children) {
282
+ return getReact2().createElement(type, props, ...children);
283
+ }
284
+ var buttonColors = {
285
+ primary: { bg: "#6366f1", text: "#fff", hover: "#4f46e5" },
286
+ secondary: { bg: "#f3f4f6", text: "#374151", hover: "#e5e7eb" },
287
+ danger: { bg: "#ef4444", text: "#fff", hover: "#dc2626" },
288
+ ghost: { bg: "transparent", text: "#6b7280", hover: "#f3f4f6" }
289
+ };
290
+ var buttonSizes = {
291
+ sm: { padding: "0.375rem 0.75rem", fontSize: "0.8125rem" },
292
+ md: { padding: "0.5rem 1rem", fontSize: "0.875rem" },
293
+ lg: { padding: "0.625rem 1.25rem", fontSize: "1rem" }
294
+ };
295
+ function Button({ children, onClick, disabled, variant = "primary", size = "md", style }) {
296
+ const colors = buttonColors[variant];
297
+ const sizeStyles = buttonSizes[size];
298
+ return h("button", {
299
+ onClick,
300
+ disabled,
301
+ style: {
302
+ ...sizeStyles,
303
+ backgroundColor: colors.bg,
304
+ color: colors.text,
305
+ border: "none",
306
+ borderRadius: "0.5rem",
307
+ fontWeight: 500,
308
+ cursor: disabled ? "not-allowed" : "pointer",
309
+ opacity: disabled ? 0.5 : 1,
310
+ transition: "background-color 0.15s, opacity 0.15s",
311
+ fontFamily: "system-ui, -apple-system, sans-serif",
312
+ lineHeight: 1.5,
313
+ ...style
314
+ }
315
+ }, children);
316
+ }
317
+ function Card({ children, title, style }) {
318
+ return h(
319
+ "div",
320
+ {
321
+ style: {
322
+ backgroundColor: "#fff",
323
+ border: "1px solid #e5e7eb",
324
+ borderRadius: "0.75rem",
325
+ padding: "1.25rem",
326
+ boxShadow: "0 1px 3px rgba(0,0,0,0.08)",
327
+ ...style
328
+ }
329
+ },
330
+ title ? h("h3", {
331
+ style: { margin: "0 0 0.75rem 0", fontSize: "1rem", fontWeight: 600, color: "#111827" }
332
+ }, title) : null,
333
+ children
334
+ );
335
+ }
336
+ function Input({ value, onChange, placeholder, type = "text", disabled, style }) {
337
+ return h("input", {
338
+ type,
339
+ value,
340
+ placeholder,
341
+ disabled,
342
+ onChange: onChange ? (e) => onChange(e.target.value) : void 0,
343
+ style: {
344
+ width: "100%",
345
+ padding: "0.5rem 0.75rem",
346
+ fontSize: "0.875rem",
347
+ border: "1px solid #d1d5db",
348
+ borderRadius: "0.5rem",
349
+ outline: "none",
350
+ backgroundColor: disabled ? "#f9fafb" : "#fff",
351
+ color: "#111827",
352
+ fontFamily: "system-ui, -apple-system, sans-serif",
353
+ lineHeight: 1.5,
354
+ boxSizing: "border-box",
355
+ ...style
356
+ }
357
+ });
358
+ }
359
+ var badgeColors = {
360
+ gray: { bg: "#f3f4f6", text: "#374151" },
361
+ blue: { bg: "#dbeafe", text: "#1d4ed8" },
362
+ green: { bg: "#dcfce7", text: "#15803d" },
363
+ red: { bg: "#fee2e2", text: "#b91c1c" },
364
+ yellow: { bg: "#fef9c3", text: "#a16207" },
365
+ purple: { bg: "#f3e8ff", text: "#7e22ce" }
366
+ };
367
+ function Badge({ children, color = "gray", style }) {
368
+ const colors = badgeColors[color];
369
+ return h("span", {
370
+ style: {
371
+ display: "inline-flex",
372
+ alignItems: "center",
373
+ padding: "0.125rem 0.625rem",
374
+ fontSize: "0.75rem",
375
+ fontWeight: 500,
376
+ borderRadius: "9999px",
377
+ backgroundColor: colors.bg,
378
+ color: colors.text,
379
+ fontFamily: "system-ui, -apple-system, sans-serif",
380
+ lineHeight: 1.5,
381
+ ...style
382
+ }
383
+ }, children);
384
+ }
385
+ function Stack({ children, direction = "column", gap = "0.5rem", align, justify, style }) {
386
+ return h("div", {
387
+ style: {
388
+ display: "flex",
389
+ flexDirection: direction,
390
+ gap,
391
+ alignItems: align,
392
+ justifyContent: justify,
393
+ ...style
394
+ }
395
+ }, children);
396
+ }
397
+ function Grid({ children, columns = 2, gap = "0.75rem", style }) {
398
+ return h("div", {
399
+ style: {
400
+ display: "grid",
401
+ gridTemplateColumns: typeof columns === "number" ? `repeat(${columns}, 1fr)` : columns,
402
+ gap,
403
+ ...style
404
+ }
405
+ }, children);
406
+ }
407
+
408
+ // src/agent-protocol.ts
409
+ function uid() {
410
+ return Math.random().toString(36).slice(2, 10) + Date.now().toString(36);
411
+ }
412
+ function capMessages(msgs, max = 100) {
413
+ return msgs.length > max ? msgs.slice(-max) : msgs;
414
+ }
415
+ function createAgentProtocolTools(namespace, z) {
416
+ return [
417
+ {
418
+ name: `${namespace}.agent.propose`,
419
+ description: "Propose an action for other agents to vote on",
420
+ input_schema: z.object({
421
+ proposal: z.string(),
422
+ data: z.any().optional(),
423
+ requiresVotes: z.number().optional()
424
+ }),
425
+ risk: "low",
426
+ capabilities_required: ["state.write"],
427
+ handler: async (ctx, input) => {
428
+ const id = uid();
429
+ const proposals = { ...ctx.state._agentProposals || {} };
430
+ proposals[id] = {
431
+ id,
432
+ from: ctx.actorId,
433
+ proposal: input.proposal,
434
+ data: input.data,
435
+ requiresVotes: input.requiresVotes || 1,
436
+ votes: [],
437
+ status: "pending",
438
+ ts: ctx.timestamp
439
+ };
440
+ const messages = capMessages([
441
+ ...ctx.state._agentMessages || [],
442
+ { id, from: ctx.actorId, to: "*", type: "proposal", content: input.proposal, data: input.data, ts: ctx.timestamp }
443
+ ]);
444
+ ctx.setState({ ...ctx.state, _agentProposals: proposals, _agentMessages: messages });
445
+ return { proposalId: id };
446
+ }
447
+ },
448
+ {
449
+ name: `${namespace}.agent.vote`,
450
+ description: "Vote on a pending proposal (approve or reject)",
451
+ input_schema: z.object({
452
+ proposalId: z.string(),
453
+ vote: z.enum(["approve", "reject"]),
454
+ reason: z.string().optional()
455
+ }),
456
+ risk: "low",
457
+ capabilities_required: ["state.write"],
458
+ handler: async (ctx, input) => {
459
+ const proposals = { ...ctx.state._agentProposals || {} };
460
+ const proposal = proposals[input.proposalId];
461
+ if (!proposal) throw new Error(`Proposal ${input.proposalId} not found`);
462
+ if (proposal.status !== "pending") throw new Error(`Proposal already ${proposal.status}`);
463
+ if (proposal.votes.some((v) => v.actorId === ctx.actorId)) throw new Error("Already voted");
464
+ const votes = [...proposal.votes, { actorId: ctx.actorId, vote: input.vote, reason: input.reason }];
465
+ const approves = votes.filter((v) => v.vote === "approve").length;
466
+ const rejects = votes.filter((v) => v.vote === "reject").length;
467
+ let status = "pending";
468
+ if (approves >= proposal.requiresVotes) status = "approved";
469
+ else if (rejects >= proposal.requiresVotes) status = "rejected";
470
+ proposals[input.proposalId] = { ...proposal, votes, status };
471
+ const messages = capMessages([
472
+ ...ctx.state._agentMessages || [],
473
+ { id: uid(), from: ctx.actorId, to: proposal.from, type: "vote", content: `${input.vote}: ${input.reason || ""}`, data: { proposalId: input.proposalId, vote: input.vote }, ts: ctx.timestamp }
474
+ ]);
475
+ ctx.setState({ ...ctx.state, _agentProposals: proposals, _agentMessages: messages });
476
+ return { status, voteCount: votes.length };
477
+ }
478
+ },
479
+ {
480
+ name: `${namespace}.agent.delegate`,
481
+ description: "Delegate a task to another agent",
482
+ input_schema: z.object({
483
+ targetActorId: z.string(),
484
+ task: z.string(),
485
+ data: z.any().optional()
486
+ }),
487
+ risk: "low",
488
+ capabilities_required: ["state.write"],
489
+ handler: async (ctx, input) => {
490
+ const id = uid();
491
+ const messages = capMessages([
492
+ ...ctx.state._agentMessages || [],
493
+ { id, from: ctx.actorId, to: input.targetActorId, type: "delegate", content: input.task, data: input.data, ts: ctx.timestamp }
494
+ ]);
495
+ ctx.setState({ ...ctx.state, _agentMessages: messages });
496
+ return { messageId: id };
497
+ }
498
+ },
499
+ {
500
+ name: `${namespace}.agent.inform`,
501
+ description: "Share information with other agents",
502
+ input_schema: z.object({
503
+ to: z.string(),
504
+ message: z.string(),
505
+ data: z.any().optional()
506
+ }),
507
+ risk: "low",
508
+ capabilities_required: ["state.write"],
509
+ handler: async (ctx, input) => {
510
+ const id = uid();
511
+ const messages = capMessages([
512
+ ...ctx.state._agentMessages || [],
513
+ { id, from: ctx.actorId, to: input.to, type: "inform", content: input.message, data: input.data, ts: ctx.timestamp }
514
+ ]);
515
+ ctx.setState({ ...ctx.state, _agentMessages: messages });
516
+ return { messageId: id };
517
+ }
518
+ },
519
+ {
520
+ name: `${namespace}.agent.request`,
521
+ description: "Request an action from another agent",
522
+ input_schema: z.object({
523
+ targetActorId: z.string(),
524
+ request: z.string(),
525
+ data: z.any().optional()
526
+ }),
527
+ risk: "low",
528
+ capabilities_required: ["state.write"],
529
+ handler: async (ctx, input) => {
530
+ const id = uid();
531
+ const messages = capMessages([
532
+ ...ctx.state._agentMessages || [],
533
+ { id, from: ctx.actorId, to: input.targetActorId, type: "request", content: input.request, data: input.data, ts: ctx.timestamp }
534
+ ]);
535
+ ctx.setState({ ...ctx.state, _agentMessages: messages });
536
+ return { messageId: id };
537
+ }
538
+ },
539
+ {
540
+ name: `${namespace}.agent.respond`,
541
+ description: "Respond to a message, request, or delegation from another agent",
542
+ input_schema: z.object({
543
+ messageId: z.string(),
544
+ response: z.string(),
545
+ data: z.any().optional()
546
+ }),
547
+ risk: "low",
548
+ capabilities_required: ["state.write"],
549
+ handler: async (ctx, input) => {
550
+ const id = uid();
551
+ const messages = capMessages([
552
+ ...ctx.state._agentMessages || [],
553
+ { id, from: ctx.actorId, to: "*", type: "inform", content: input.response, data: { ...input.data, inReplyTo: input.messageId }, ts: ctx.timestamp }
554
+ ]);
555
+ ctx.setState({ ...ctx.state, _agentMessages: messages });
556
+ return { messageId: id };
557
+ }
558
+ }
559
+ ];
560
+ }
561
+
562
+ // src/agent-hints.ts
563
+ function createAgentProtocolHints(namespace) {
564
+ return [
565
+ {
566
+ trigger: "A proposal is pending and you have not voted on it yet",
567
+ condition: `Object.values(state._agentProposals || {}).some(p => p.status === 'pending' && !p.votes.some(v => v.actorId === actorId))`,
568
+ suggestedTools: [`${namespace}.agent.vote`],
569
+ priority: "high",
570
+ cooldownMs: 2e3
571
+ },
572
+ {
573
+ trigger: "You received a delegation addressed to you",
574
+ condition: `(state._agentMessages || []).some(m => m.type === 'delegate' && m.to === actorId)`,
575
+ suggestedTools: [`${namespace}.agent.respond`],
576
+ priority: "high",
577
+ cooldownMs: 3e3
578
+ },
579
+ {
580
+ trigger: "You received a request addressed to you",
581
+ condition: `(state._agentMessages || []).some(m => m.type === 'request' && m.to === actorId)`,
582
+ suggestedTools: [`${namespace}.agent.respond`],
583
+ priority: "medium",
584
+ cooldownMs: 2e3
585
+ },
586
+ {
587
+ trigger: "You have useful information to share with other agents",
588
+ suggestedTools: [`${namespace}.agent.inform`],
589
+ priority: "low",
590
+ cooldownMs: 5e3
591
+ },
592
+ {
593
+ trigger: "You want to propose a collaborative action for the group",
594
+ suggestedTools: [`${namespace}.agent.propose`],
595
+ priority: "low",
596
+ cooldownMs: 1e4
597
+ }
598
+ ];
599
+ }
600
+
601
+ // src/migrations.ts
602
+ function getStateVersion(state) {
603
+ return typeof state._version === "string" ? state._version : "0.0.0";
604
+ }
605
+ function compareSemver(a, b) {
606
+ const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
607
+ const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
608
+ const len = Math.max(pa.length, pb.length);
609
+ for (let i = 0; i < len; i++) {
610
+ const va = pa[i] || 0;
611
+ const vb = pb[i] || 0;
612
+ if (va < vb) return -1;
613
+ if (va > vb) return 1;
614
+ }
615
+ return 0;
616
+ }
617
+ function migrateState(state, migrations, currentVersion) {
618
+ const fromVersion = getStateVersion(state);
619
+ if (compareSemver(fromVersion, currentVersion) >= 0) {
620
+ return {
621
+ migrated: false,
622
+ fromVersion,
623
+ toVersion: fromVersion,
624
+ state
625
+ };
626
+ }
627
+ if (!migrations || migrations.length === 0) {
628
+ return {
629
+ migrated: false,
630
+ fromVersion,
631
+ toVersion: currentVersion,
632
+ state: { ...state, _version: currentVersion }
633
+ };
634
+ }
635
+ const sorted = [...migrations].sort((a, b) => compareSemver(a.to, b.to));
636
+ const applicable = sorted.filter(
637
+ (m) => compareSemver(m.to, fromVersion) > 0 && compareSemver(m.to, currentVersion) <= 0
638
+ );
639
+ if (applicable.length === 0) {
640
+ return {
641
+ migrated: false,
642
+ fromVersion,
643
+ toVersion: currentVersion,
644
+ state: { ...state, _version: currentVersion }
645
+ };
646
+ }
647
+ let migratedState = { ...state };
648
+ for (const migration of applicable) {
649
+ migratedState = migration.migrate(migratedState);
650
+ }
651
+ migratedState._version = currentVersion;
652
+ return {
653
+ migrated: true,
654
+ fromVersion,
655
+ toVersion: currentVersion,
656
+ state: migratedState
657
+ };
658
+ }
659
+
660
+ // src/storage.ts
661
+ var InMemoryAdapter = class {
662
+ roomStates = /* @__PURE__ */ new Map();
663
+ events = /* @__PURE__ */ new Map();
664
+ profiles = /* @__PURE__ */ new Map();
665
+ async saveRoomState(roomId, state) {
666
+ this.roomStates.set(roomId, state);
667
+ }
668
+ async loadRoomState(roomId) {
669
+ return this.roomStates.get(roomId) || null;
670
+ }
671
+ async appendEvent(roomId, event) {
672
+ if (!this.events.has(roomId)) {
673
+ this.events.set(roomId, []);
674
+ }
675
+ this.events.get(roomId).push(event);
676
+ }
677
+ async loadEvents(roomId, limit) {
678
+ const events = this.events.get(roomId) || [];
679
+ if (limit) {
680
+ return events.slice(-limit);
681
+ }
682
+ return events;
683
+ }
684
+ async listExperiences(_userId) {
685
+ return [];
686
+ }
687
+ async saveUserProfile(userId, profile) {
688
+ this.profiles.set(userId, profile);
689
+ }
690
+ async loadUserProfile(userId) {
691
+ return this.profiles.get(userId) || null;
692
+ }
693
+ };
694
+ export {
695
+ Badge,
696
+ Button,
697
+ Card,
698
+ Grid,
699
+ InMemoryAdapter,
700
+ Input,
701
+ Stack,
702
+ compareSemver,
703
+ createAgentProtocolHints,
704
+ createAgentProtocolTools,
705
+ defineEphemeralAction,
706
+ defineExperience,
707
+ defineTest,
708
+ defineTool,
709
+ getStateVersion,
710
+ migrateState,
711
+ quickTool,
712
+ useAnimationFrame,
713
+ useFollow,
714
+ useOptimisticTool,
715
+ useParticipants,
716
+ useSharedState,
717
+ useToolCall,
718
+ useTypingIndicator,
719
+ validateExperience
720
+ };