@vibevibes/sdk 0.3.0 → 0.4.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/README.md +39 -69
- package/dist/index.cjs +0 -50
- package/dist/index.d.cts +1 -23
- package/dist/index.d.ts +1 -23
- package/dist/index.js +0 -49
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# @vibevibes/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Primitives for building shared human-AI experiences — interactive apps where humans and AI agents collaborate in real-time through shared state, shared tools, and a shared canvas.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@vibevibes/sdk)
|
|
6
|
+
[](./LICENSE)
|
|
4
7
|
|
|
5
8
|
## Install
|
|
6
9
|
|
|
@@ -21,7 +24,7 @@ const tools = [
|
|
|
21
24
|
name: "counter.increment",
|
|
22
25
|
description: "Add to the counter",
|
|
23
26
|
input_schema: z.object({
|
|
24
|
-
amount: z.number().default(1)
|
|
27
|
+
amount: z.number().default(1),
|
|
25
28
|
}),
|
|
26
29
|
handler: async (ctx, input) => {
|
|
27
30
|
const count = (ctx.state.count || 0) + input.amount;
|
|
@@ -59,44 +62,24 @@ That's a complete experience. Humans click the button. Agents call the same tool
|
|
|
59
62
|
|
|
60
63
|
## Core Concepts
|
|
61
64
|
|
|
62
|
-
**Tools are the only way to mutate state.** Every tool has a Zod schema
|
|
65
|
+
**Tools are the only way to mutate state.** Every tool has a Zod schema and a handler that calls `ctx.setState()`. Humans use tools via the Canvas. Agents use the same tools via MCP. No backdoors.
|
|
63
66
|
|
|
64
|
-
**Canvas is a React component.** It receives
|
|
67
|
+
**Canvas is a React component.** It receives current shared state and a `callTool` function. Re-renders on every state change.
|
|
65
68
|
|
|
66
69
|
**Agents are actors, not assistants.** They join rooms, watch for events, react with tools, and persist memory. Same participation model as humans.
|
|
67
70
|
|
|
68
|
-
##
|
|
69
|
-
|
|
70
|
-
```tsx
|
|
71
|
-
defineTool({
|
|
72
|
-
name: "board.place",
|
|
73
|
-
description: "Place a piece on the board",
|
|
74
|
-
input_schema: z.object({
|
|
75
|
-
x: z.number(),
|
|
76
|
-
y: z.number(),
|
|
77
|
-
piece: z.string(),
|
|
78
|
-
}),
|
|
79
|
-
handler: async (ctx, input) => {
|
|
80
|
-
const board = { ...ctx.state.board };
|
|
81
|
-
board[`${input.x},${input.y}`] = input.piece;
|
|
82
|
-
ctx.setState({ ...ctx.state, board });
|
|
83
|
-
return { placed: true };
|
|
84
|
-
},
|
|
85
|
-
});
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Tool Handler Context
|
|
71
|
+
## Tool Handler Context
|
|
89
72
|
|
|
90
73
|
```tsx
|
|
91
74
|
type ToolCtx = {
|
|
92
75
|
roomId: string;
|
|
93
|
-
actorId: string;
|
|
94
|
-
owner?: string;
|
|
95
|
-
state: Record<string, any>;
|
|
96
|
-
setState: (s
|
|
76
|
+
actorId: string; // Who called this tool
|
|
77
|
+
owner?: string; // Owner extracted from actorId
|
|
78
|
+
state: Record<string, any>; // Current shared state (read)
|
|
79
|
+
setState: (s) => void; // Set new state (write)
|
|
97
80
|
timestamp: number;
|
|
98
|
-
memory: Record<string, any>;
|
|
99
|
-
setMemory: (updates
|
|
81
|
+
memory: Record<string, any>; // Agent's persistent memory
|
|
82
|
+
setMemory: (updates) => void;
|
|
100
83
|
};
|
|
101
84
|
```
|
|
102
85
|
|
|
@@ -116,28 +99,36 @@ type CanvasProps = {
|
|
|
116
99
|
};
|
|
117
100
|
```
|
|
118
101
|
|
|
119
|
-
##
|
|
102
|
+
## Hooks
|
|
103
|
+
|
|
104
|
+
| Hook | Returns | Purpose |
|
|
105
|
+
|------|---------|---------|
|
|
106
|
+
| `useToolCall(callTool)` | `{ call, loading, error }` | Loading/error tracking |
|
|
107
|
+
| `useSharedState(state, key, default?)` | `value` | Typed state accessor |
|
|
108
|
+
| `useOptimisticTool(callTool, state)` | `{ call, state, pending }` | Optimistic updates with rollback |
|
|
109
|
+
| `useParticipants(participants)` | `ParsedParticipant[]` | Parse actor IDs |
|
|
110
|
+
| `useAnimationFrame(state, interpolate?)` | `displayState` | Frame-rate buffering |
|
|
111
|
+
|
|
112
|
+
## Components
|
|
120
113
|
|
|
121
|
-
|
|
114
|
+
Inline-styled (no Tailwind needed): `Button`, `Card`, `Input`, `Badge`, `Stack`, `Grid`
|
|
115
|
+
|
|
116
|
+
## Agent Slots
|
|
122
117
|
|
|
123
118
|
```tsx
|
|
124
119
|
manifest: {
|
|
125
|
-
agentSlots: [
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
},
|
|
133
|
-
],
|
|
120
|
+
agentSlots: [{
|
|
121
|
+
role: "game-master",
|
|
122
|
+
systemPrompt: "You are the game master.",
|
|
123
|
+
allowedTools: ["world.narrate"],
|
|
124
|
+
autoSpawn: true,
|
|
125
|
+
maxInstances: 1,
|
|
126
|
+
}],
|
|
134
127
|
}
|
|
135
128
|
```
|
|
136
129
|
|
|
137
130
|
## Tests
|
|
138
131
|
|
|
139
|
-
Inline tests for tool handlers:
|
|
140
|
-
|
|
141
132
|
```tsx
|
|
142
133
|
import { defineTest } from "@vibevibes/sdk";
|
|
143
134
|
|
|
@@ -154,26 +145,7 @@ tests: [
|
|
|
154
145
|
]
|
|
155
146
|
```
|
|
156
147
|
|
|
157
|
-
##
|
|
158
|
-
|
|
159
|
-
```tsx
|
|
160
|
-
type ExperienceManifest = {
|
|
161
|
-
id: string;
|
|
162
|
-
version: string;
|
|
163
|
-
title: string;
|
|
164
|
-
description: string;
|
|
165
|
-
requested_capabilities: string[];
|
|
166
|
-
agentSlots?: AgentSlot[];
|
|
167
|
-
participantSlots?: ParticipantSlot[];
|
|
168
|
-
category?: string;
|
|
169
|
-
tags?: string[];
|
|
170
|
-
netcode?: "default" | "tick" | "p2p-ephemeral";
|
|
171
|
-
tickRateMs?: number;
|
|
172
|
-
hotKeys?: string[];
|
|
173
|
-
};
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
## How It Works
|
|
148
|
+
## Architecture
|
|
177
149
|
|
|
178
150
|
```
|
|
179
151
|
Browser (Canvas) <--WebSocket--> Server <--HTTP--> MCP (Agent)
|
|
@@ -184,15 +156,13 @@ Browser (Canvas) <--WebSocket--> Server <--HTTP--> MCP (Agent)
|
|
|
184
156
|
broadcasts to all clients
|
|
185
157
|
```
|
|
186
158
|
|
|
187
|
-
All state lives on the server. The Canvas renders it. Tools are the only mutation path. Both humans and agents use the same tools.
|
|
188
|
-
|
|
189
159
|
## Ecosystem
|
|
190
160
|
|
|
191
161
|
| Package | Description |
|
|
192
162
|
|---------|-------------|
|
|
193
|
-
| **@vibevibes/sdk**
|
|
194
|
-
| [@vibevibes/mcp](https://github.com/vibevibes/mcp) | Runtime
|
|
195
|
-
| [create
|
|
163
|
+
| **@vibevibes/sdk** | Define experiences — tools, canvas, state |
|
|
164
|
+
| [@vibevibes/mcp](https://github.com/vibevibes/mcp) | Runtime engine — MCP server + WebSocket + viewer |
|
|
165
|
+
| [@vibevibes/create](https://github.com/vibevibes/create) | `npx @vibevibes/create` — scaffold in seconds |
|
|
196
166
|
| [experiences](https://github.com/vibevibes/experiences) | Example experiences — fork and remix |
|
|
197
167
|
|
|
198
168
|
## License
|
package/dist/index.cjs
CHANGED
|
@@ -20,7 +20,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
createChatTools: () => createChatTools,
|
|
24
23
|
defineExperience: () => defineExperience,
|
|
25
24
|
defineStream: () => defineStream,
|
|
26
25
|
defineTest: () => defineTest,
|
|
@@ -92,57 +91,8 @@ function defineExperience(module2) {
|
|
|
92
91
|
}
|
|
93
92
|
};
|
|
94
93
|
}
|
|
95
|
-
|
|
96
|
-
// src/chat.ts
|
|
97
|
-
function uid() {
|
|
98
|
-
return Math.random().toString(36).slice(2, 10) + Date.now().toString(36);
|
|
99
|
-
}
|
|
100
|
-
function capMessages(msgs, max = 200) {
|
|
101
|
-
return msgs.length > max ? msgs.slice(-max) : msgs;
|
|
102
|
-
}
|
|
103
|
-
function createChatTools(z) {
|
|
104
|
-
return [
|
|
105
|
-
{
|
|
106
|
-
name: "_chat.send",
|
|
107
|
-
description: "Send a chat message",
|
|
108
|
-
input_schema: z.object({
|
|
109
|
-
message: z.string().min(1).max(2e3),
|
|
110
|
-
replyTo: z.string().optional()
|
|
111
|
-
}),
|
|
112
|
-
risk: "low",
|
|
113
|
-
capabilities_required: ["state.write"],
|
|
114
|
-
handler: async (ctx, input) => {
|
|
115
|
-
const cleanMessage = input.message.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
|
|
116
|
-
const messages = capMessages([
|
|
117
|
-
...ctx.state._chat || [],
|
|
118
|
-
{
|
|
119
|
-
id: uid(),
|
|
120
|
-
actorId: ctx.actorId,
|
|
121
|
-
message: cleanMessage,
|
|
122
|
-
replyTo: input.replyTo,
|
|
123
|
-
ts: ctx.timestamp
|
|
124
|
-
}
|
|
125
|
-
]);
|
|
126
|
-
ctx.setState({ ...ctx.state, _chat: messages });
|
|
127
|
-
return { sent: true, messageCount: messages.length };
|
|
128
|
-
}
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
name: "_chat.clear",
|
|
132
|
-
description: "Clear all chat messages",
|
|
133
|
-
input_schema: z.object({}),
|
|
134
|
-
risk: "medium",
|
|
135
|
-
capabilities_required: ["state.write"],
|
|
136
|
-
handler: async (ctx) => {
|
|
137
|
-
ctx.setState({ ...ctx.state, _chat: [] });
|
|
138
|
-
return { cleared: true };
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
];
|
|
142
|
-
}
|
|
143
94
|
// Annotate the CommonJS export names for ESM import in node:
|
|
144
95
|
0 && (module.exports = {
|
|
145
|
-
createChatTools,
|
|
146
96
|
defineExperience,
|
|
147
97
|
defineStream,
|
|
148
98
|
defineTest,
|
package/dist/index.d.cts
CHANGED
|
@@ -181,26 +181,4 @@ declare function defineExperience(module: ExperienceModule & {
|
|
|
181
181
|
initialState?: Record<string, any>;
|
|
182
182
|
};
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
* Chat tool factory for experiences.
|
|
186
|
-
*
|
|
187
|
-
* Messages are stored in shared state under `_chat` so agents
|
|
188
|
-
* see them via the stop hook's /agent-context endpoint.
|
|
189
|
-
*
|
|
190
|
-
* Usage:
|
|
191
|
-
* import { createChatTools } from "@vibevibes/sdk";
|
|
192
|
-
* const tools = [...myTools, ...createChatTools(z)];
|
|
193
|
-
*
|
|
194
|
-
* // In Canvas: read sharedState._chat, send via callTool('_chat.send', { message })
|
|
195
|
-
*/
|
|
196
|
-
|
|
197
|
-
type ChatMessage = {
|
|
198
|
-
id: string;
|
|
199
|
-
actorId: string;
|
|
200
|
-
message: string;
|
|
201
|
-
replyTo?: string;
|
|
202
|
-
ts: number;
|
|
203
|
-
};
|
|
204
|
-
declare function createChatTools(z: ZodFactory): ToolDef[];
|
|
205
|
-
|
|
206
|
-
export { type AgentSlot, type CallToolFn, type CanvasProps, type ChatMessage, type ExpectChain, type ExperienceManifest, type ExperienceModule, type ExperienceRegistry, type ParticipantDetail, type ParticipantSlot, type RegistryEntry, type StreamDef, type TestDef, type TestHelpers, type ToolCtx, type ToolDef, type ToolEvent, type ToolRisk, type ZodFactory, createChatTools, defineExperience, defineStream, defineTest, defineTool };
|
|
184
|
+
export { type AgentSlot, type CallToolFn, type CanvasProps, type ExpectChain, type ExperienceManifest, type ExperienceModule, type ExperienceRegistry, type ParticipantDetail, type ParticipantSlot, type RegistryEntry, type StreamDef, type TestDef, type TestHelpers, type ToolCtx, type ToolDef, type ToolEvent, type ToolRisk, type ZodFactory, defineExperience, defineStream, defineTest, defineTool };
|
package/dist/index.d.ts
CHANGED
|
@@ -181,26 +181,4 @@ declare function defineExperience(module: ExperienceModule & {
|
|
|
181
181
|
initialState?: Record<string, any>;
|
|
182
182
|
};
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
* Chat tool factory for experiences.
|
|
186
|
-
*
|
|
187
|
-
* Messages are stored in shared state under `_chat` so agents
|
|
188
|
-
* see them via the stop hook's /agent-context endpoint.
|
|
189
|
-
*
|
|
190
|
-
* Usage:
|
|
191
|
-
* import { createChatTools } from "@vibevibes/sdk";
|
|
192
|
-
* const tools = [...myTools, ...createChatTools(z)];
|
|
193
|
-
*
|
|
194
|
-
* // In Canvas: read sharedState._chat, send via callTool('_chat.send', { message })
|
|
195
|
-
*/
|
|
196
|
-
|
|
197
|
-
type ChatMessage = {
|
|
198
|
-
id: string;
|
|
199
|
-
actorId: string;
|
|
200
|
-
message: string;
|
|
201
|
-
replyTo?: string;
|
|
202
|
-
ts: number;
|
|
203
|
-
};
|
|
204
|
-
declare function createChatTools(z: ZodFactory): ToolDef[];
|
|
205
|
-
|
|
206
|
-
export { type AgentSlot, type CallToolFn, type CanvasProps, type ChatMessage, type ExpectChain, type ExperienceManifest, type ExperienceModule, type ExperienceRegistry, type ParticipantDetail, type ParticipantSlot, type RegistryEntry, type StreamDef, type TestDef, type TestHelpers, type ToolCtx, type ToolDef, type ToolEvent, type ToolRisk, type ZodFactory, createChatTools, defineExperience, defineStream, defineTest, defineTool };
|
|
184
|
+
export { type AgentSlot, type CallToolFn, type CanvasProps, type ExpectChain, type ExperienceManifest, type ExperienceModule, type ExperienceRegistry, type ParticipantDetail, type ParticipantSlot, type RegistryEntry, type StreamDef, type TestDef, type TestHelpers, type ToolCtx, type ToolDef, type ToolEvent, type ToolRisk, type ZodFactory, defineExperience, defineStream, defineTest, defineTool };
|
package/dist/index.js
CHANGED
|
@@ -62,56 +62,7 @@ function defineExperience(module) {
|
|
|
62
62
|
}
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
-
|
|
66
|
-
// src/chat.ts
|
|
67
|
-
function uid() {
|
|
68
|
-
return Math.random().toString(36).slice(2, 10) + Date.now().toString(36);
|
|
69
|
-
}
|
|
70
|
-
function capMessages(msgs, max = 200) {
|
|
71
|
-
return msgs.length > max ? msgs.slice(-max) : msgs;
|
|
72
|
-
}
|
|
73
|
-
function createChatTools(z) {
|
|
74
|
-
return [
|
|
75
|
-
{
|
|
76
|
-
name: "_chat.send",
|
|
77
|
-
description: "Send a chat message",
|
|
78
|
-
input_schema: z.object({
|
|
79
|
-
message: z.string().min(1).max(2e3),
|
|
80
|
-
replyTo: z.string().optional()
|
|
81
|
-
}),
|
|
82
|
-
risk: "low",
|
|
83
|
-
capabilities_required: ["state.write"],
|
|
84
|
-
handler: async (ctx, input) => {
|
|
85
|
-
const cleanMessage = input.message.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
|
|
86
|
-
const messages = capMessages([
|
|
87
|
-
...ctx.state._chat || [],
|
|
88
|
-
{
|
|
89
|
-
id: uid(),
|
|
90
|
-
actorId: ctx.actorId,
|
|
91
|
-
message: cleanMessage,
|
|
92
|
-
replyTo: input.replyTo,
|
|
93
|
-
ts: ctx.timestamp
|
|
94
|
-
}
|
|
95
|
-
]);
|
|
96
|
-
ctx.setState({ ...ctx.state, _chat: messages });
|
|
97
|
-
return { sent: true, messageCount: messages.length };
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
name: "_chat.clear",
|
|
102
|
-
description: "Clear all chat messages",
|
|
103
|
-
input_schema: z.object({}),
|
|
104
|
-
risk: "medium",
|
|
105
|
-
capabilities_required: ["state.write"],
|
|
106
|
-
handler: async (ctx) => {
|
|
107
|
-
ctx.setState({ ...ctx.state, _chat: [] });
|
|
108
|
-
return { cleared: true };
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
];
|
|
112
|
-
}
|
|
113
65
|
export {
|
|
114
|
-
createChatTools,
|
|
115
66
|
defineExperience,
|
|
116
67
|
defineStream,
|
|
117
68
|
defineTest,
|