stoops 0.1.0 → 0.2.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.
Potentially problematic release.
This version of stoops might be problematic. Click here for more details.
- package/README.md +208 -4
- package/dist/agent/index.d.ts +553 -0
- package/dist/agent/index.js +41 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/chunk-5ADJGMXQ.js +27 -0
- package/dist/chunk-5ADJGMXQ.js.map +1 -0
- package/dist/chunk-7PKT5MPI.js +115 -0
- package/dist/chunk-7PKT5MPI.js.map +1 -0
- package/dist/chunk-BLGV3QN4.js +692 -0
- package/dist/chunk-BLGV3QN4.js.map +1 -0
- package/dist/chunk-HQS7HBZR.js +25 -0
- package/dist/chunk-HQS7HBZR.js.map +1 -0
- package/dist/chunk-LC5WPWR2.js +690 -0
- package/dist/chunk-LC5WPWR2.js.map +1 -0
- package/dist/chunk-SS5NGUJM.js +968 -0
- package/dist/chunk-SS5NGUJM.js.map +1 -0
- package/dist/claude/index.d.ts +26 -0
- package/dist/claude/index.js +215 -0
- package/dist/claude/index.js.map +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +2468 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index-DlxJ95ki.d.ts +637 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +23 -2
- package/dist/index.js.map +1 -0
- package/dist/langgraph/index.d.ts +30 -0
- package/dist/langgraph/index.js +250 -0
- package/dist/langgraph/index.js.map +1 -0
- package/dist/sdk-YTUDDE6G.js +11945 -0
- package/dist/sdk-YTUDDE6G.js.map +1 -0
- package/dist/types-CzHDzfHA.d.ts +201 -0
- package/package.json +69 -11
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/** Core types for stoops — messages, participants, pagination. */
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The four top-level categories events are grouped under.
|
|
7
|
+
*
|
|
8
|
+
* Channels subscribe to one or more categories — they only receive events in
|
|
9
|
+
* their subscription set. Use this to filter what an agent or observer sees:
|
|
10
|
+
*
|
|
11
|
+
* - MESSAGE — chat messages and reactions (sent, edited, deleted, reacted)
|
|
12
|
+
* - PRESENCE — participants joining and leaving
|
|
13
|
+
* - ACTIVITY — agent activity (thinking, tool use, mode changes, compaction)
|
|
14
|
+
* - MENTION — direct @mentions delivered only to the mentioned participant
|
|
15
|
+
*/
|
|
16
|
+
declare const EventCategory: {
|
|
17
|
+
readonly MESSAGE: "MESSAGE";
|
|
18
|
+
readonly PRESENCE: "PRESENCE";
|
|
19
|
+
readonly ACTIVITY: "ACTIVITY";
|
|
20
|
+
readonly MENTION: "MENTION";
|
|
21
|
+
};
|
|
22
|
+
type EventCategory = (typeof EventCategory)[keyof typeof EventCategory];
|
|
23
|
+
/**
|
|
24
|
+
* A chat message. Immutable once stored — edits and deletes are separate events.
|
|
25
|
+
*
|
|
26
|
+
* - `id` — UUID, assigned by the room on creation
|
|
27
|
+
* - `room_id` — the room this message belongs to
|
|
28
|
+
* - `sender_id` — participant ID of the author
|
|
29
|
+
* - `sender_name` — display name at the time of sending (denormalized)
|
|
30
|
+
* - `content` — text body (may be empty if the message is image-only)
|
|
31
|
+
* - `reply_to_id` — if set, this message is a reply to that message ID
|
|
32
|
+
* - `image_url` — optional attached image URL
|
|
33
|
+
* - `image_mime_type` — MIME type of the attached image (e.g. "image/jpeg")
|
|
34
|
+
* - `image_size_bytes` — size of the image in bytes
|
|
35
|
+
* - `timestamp` — creation time (UTC)
|
|
36
|
+
*/
|
|
37
|
+
declare const MessageSchema: z.ZodObject<{
|
|
38
|
+
id: z.ZodDefault<z.ZodString>;
|
|
39
|
+
room_id: z.ZodString;
|
|
40
|
+
sender_id: z.ZodString;
|
|
41
|
+
sender_name: z.ZodString;
|
|
42
|
+
content: z.ZodString;
|
|
43
|
+
reply_to_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
44
|
+
image_url: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
45
|
+
image_mime_type: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
46
|
+
image_size_bytes: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
|
|
47
|
+
timestamp: z.ZodDefault<z.ZodDate>;
|
|
48
|
+
}, z.core.$strip>;
|
|
49
|
+
type Message = z.infer<typeof MessageSchema>;
|
|
50
|
+
/**
|
|
51
|
+
* Authority level — what a participant is allowed to do.
|
|
52
|
+
*
|
|
53
|
+
* - `admin` — full control: kick, set others' modes, generate share links
|
|
54
|
+
* - `participant` — can send messages, set own mode
|
|
55
|
+
* - `observer` — read-only: can catch up and search, but can't send or act
|
|
56
|
+
*
|
|
57
|
+
* Set on join, doesn't change during the session. Orthogonal to engagement mode.
|
|
58
|
+
*/
|
|
59
|
+
type AuthorityLevel = "admin" | "participant" | "observer";
|
|
60
|
+
/** Whether a participant is a human or an agent. */
|
|
61
|
+
type ParticipantType = "human" | "agent";
|
|
62
|
+
/**
|
|
63
|
+
* A participant in a room.
|
|
64
|
+
*
|
|
65
|
+
* - `id` — stable unique ID across all rooms and sessions
|
|
66
|
+
* - `name` — display name (mutable — participants can rename)
|
|
67
|
+
* - `status` — current presence status ("online", "offline", etc.)
|
|
68
|
+
* - `type` — "human" or "agent"
|
|
69
|
+
* - `identifier` — optional stable @-mention slug, e.g. "my-agent".
|
|
70
|
+
* Unlike `name`, this never changes on rename.
|
|
71
|
+
* Used for @-mention matching in addition to the display name.
|
|
72
|
+
* Not all participants have one — guests and anonymous users
|
|
73
|
+
* typically don't.
|
|
74
|
+
* - `authority` — optional authority level. Defaults to "participant" if unset.
|
|
75
|
+
*/
|
|
76
|
+
interface Participant {
|
|
77
|
+
id: string;
|
|
78
|
+
name: string;
|
|
79
|
+
status: string;
|
|
80
|
+
type: ParticipantType;
|
|
81
|
+
identifier?: string;
|
|
82
|
+
authority?: AuthorityLevel;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A page of results with a cursor for fetching the previous page.
|
|
86
|
+
*
|
|
87
|
+
* All paginated queries return results newest-first. Pass `next_cursor` back
|
|
88
|
+
* to the same query to continue paginating backwards through history.
|
|
89
|
+
*
|
|
90
|
+
* - `items` — results for this page (newest-first)
|
|
91
|
+
* - `next_cursor` — pass this to get the next (older) page; null when exhausted
|
|
92
|
+
* - `has_more` — true if there are older items beyond this page
|
|
93
|
+
*/
|
|
94
|
+
interface PaginatedResult<T> {
|
|
95
|
+
items: T[];
|
|
96
|
+
next_cursor: string | null;
|
|
97
|
+
has_more: boolean;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Typed events for rooms — a discriminated union on the `type` field.
|
|
102
|
+
*
|
|
103
|
+
* Every event has:
|
|
104
|
+
* id — UUID assigned at creation
|
|
105
|
+
* type — the discriminant (e.g. "MessageSent", "ParticipantJoined")
|
|
106
|
+
* category — the EventCategory for subscription filtering
|
|
107
|
+
* room_id — the room this event belongs to
|
|
108
|
+
* participant_id — the participant who caused the event
|
|
109
|
+
* timestamp — UTC creation time
|
|
110
|
+
*
|
|
111
|
+
* Use `createEvent()` to build events — it fills in `id` and `timestamp`.
|
|
112
|
+
* Use `EVENT_ROLE` to classify events by their semantic role.
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
interface BaseRoomEvent {
|
|
116
|
+
/** UUID assigned at creation. */
|
|
117
|
+
id: string;
|
|
118
|
+
}
|
|
119
|
+
/** Someone sent a message. `message` contains the full content including any image. */
|
|
120
|
+
interface MessageSentEvent extends BaseRoomEvent {
|
|
121
|
+
type: "MessageSent";
|
|
122
|
+
category: "MESSAGE";
|
|
123
|
+
room_id: string;
|
|
124
|
+
participant_id: string;
|
|
125
|
+
timestamp: Date;
|
|
126
|
+
message: Message;
|
|
127
|
+
}
|
|
128
|
+
/** A message's text content was changed. Does not update image attachments. */
|
|
129
|
+
interface MessageEditedEvent extends BaseRoomEvent {
|
|
130
|
+
type: "MessageEdited";
|
|
131
|
+
category: "MESSAGE";
|
|
132
|
+
room_id: string;
|
|
133
|
+
participant_id: string;
|
|
134
|
+
timestamp: Date;
|
|
135
|
+
message_id: string;
|
|
136
|
+
new_content: string;
|
|
137
|
+
old_content: string;
|
|
138
|
+
}
|
|
139
|
+
/** A message was removed. The message ID is preserved for reference but content is gone. */
|
|
140
|
+
interface MessageDeletedEvent extends BaseRoomEvent {
|
|
141
|
+
type: "MessageDeleted";
|
|
142
|
+
category: "MESSAGE";
|
|
143
|
+
room_id: string;
|
|
144
|
+
participant_id: string;
|
|
145
|
+
timestamp: Date;
|
|
146
|
+
message_id: string;
|
|
147
|
+
}
|
|
148
|
+
/** A participant added an emoji reaction to a message. */
|
|
149
|
+
interface ReactionAddedEvent extends BaseRoomEvent {
|
|
150
|
+
type: "ReactionAdded";
|
|
151
|
+
category: "MESSAGE";
|
|
152
|
+
room_id: string;
|
|
153
|
+
participant_id: string;
|
|
154
|
+
timestamp: Date;
|
|
155
|
+
message_id: string;
|
|
156
|
+
emoji: string;
|
|
157
|
+
}
|
|
158
|
+
/** A participant removed their emoji reaction from a message. */
|
|
159
|
+
interface ReactionRemovedEvent extends BaseRoomEvent {
|
|
160
|
+
type: "ReactionRemoved";
|
|
161
|
+
category: "MESSAGE";
|
|
162
|
+
room_id: string;
|
|
163
|
+
participant_id: string;
|
|
164
|
+
timestamp: Date;
|
|
165
|
+
message_id: string;
|
|
166
|
+
emoji: string;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* A participant connected to the room.
|
|
170
|
+
*
|
|
171
|
+
* Not emitted for silent connects (`Room.connect(..., silent: true)`).
|
|
172
|
+
* Agents connect silently to avoid polluting the chat with join noise.
|
|
173
|
+
*/
|
|
174
|
+
interface ParticipantJoinedEvent extends BaseRoomEvent {
|
|
175
|
+
type: "ParticipantJoined";
|
|
176
|
+
category: "PRESENCE";
|
|
177
|
+
room_id: string;
|
|
178
|
+
participant_id: string;
|
|
179
|
+
timestamp: Date;
|
|
180
|
+
/** Full participant snapshot at join time. */
|
|
181
|
+
participant: Participant;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* A participant disconnected from the room.
|
|
185
|
+
*
|
|
186
|
+
* Not emitted for silent disconnects (`channel.disconnect(true)`).
|
|
187
|
+
*/
|
|
188
|
+
interface ParticipantLeftEvent extends BaseRoomEvent {
|
|
189
|
+
type: "ParticipantLeft";
|
|
190
|
+
category: "PRESENCE";
|
|
191
|
+
room_id: string;
|
|
192
|
+
participant_id: string;
|
|
193
|
+
timestamp: Date;
|
|
194
|
+
/** Full participant snapshot at leave time. */
|
|
195
|
+
participant: Participant;
|
|
196
|
+
}
|
|
197
|
+
/** A participant's presence status changed (e.g. "online" → "away"). */
|
|
198
|
+
interface StatusChangedEvent extends BaseRoomEvent {
|
|
199
|
+
type: "StatusChanged";
|
|
200
|
+
category: "PRESENCE";
|
|
201
|
+
room_id: string;
|
|
202
|
+
participant_id: string;
|
|
203
|
+
timestamp: Date;
|
|
204
|
+
status: "online" | "offline" | "away";
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* An agent made an MCP tool call.
|
|
208
|
+
*
|
|
209
|
+
* Emitted twice per tool call: once with `status: "started"` (before the call)
|
|
210
|
+
* and once with `status: "completed"` (after). Useful for showing live tool
|
|
211
|
+
* progress in a UI.
|
|
212
|
+
*/
|
|
213
|
+
interface ToolUseEvent extends BaseRoomEvent {
|
|
214
|
+
type: "ToolUse";
|
|
215
|
+
category: "ACTIVITY";
|
|
216
|
+
room_id: string;
|
|
217
|
+
participant_id: string;
|
|
218
|
+
timestamp: Date;
|
|
219
|
+
tool_name: string;
|
|
220
|
+
/** "started" before the call, "completed" after. */
|
|
221
|
+
status: "started" | "completed";
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* A generic activity event for platform-specific actions.
|
|
225
|
+
*
|
|
226
|
+
* Used when no specific event type fits. The `action` field identifies the
|
|
227
|
+
* action (e.g. `"mode_changed"`), and `detail` carries structured metadata.
|
|
228
|
+
*
|
|
229
|
+
* Current usages:
|
|
230
|
+
* - action: "mode_changed", detail: { mode: EngagementMode }
|
|
231
|
+
* Emitted when an agent's engagement mode changes for a room.
|
|
232
|
+
*/
|
|
233
|
+
interface ActivityEvent extends BaseRoomEvent {
|
|
234
|
+
type: "Activity";
|
|
235
|
+
category: "ACTIVITY";
|
|
236
|
+
room_id: string;
|
|
237
|
+
participant_id: string;
|
|
238
|
+
timestamp: Date;
|
|
239
|
+
action: string;
|
|
240
|
+
detail: Record<string, unknown> | null;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* An agent's context window was compacted.
|
|
244
|
+
*
|
|
245
|
+
* Fired when the LLM backend summarizes and compresses the conversation history
|
|
246
|
+
* to free up context space. After compaction, the agent re-reads all rooms via
|
|
247
|
+
* `catch_up` to rebuild its working context.
|
|
248
|
+
*/
|
|
249
|
+
interface ContextCompactedEvent extends BaseRoomEvent {
|
|
250
|
+
type: "ContextCompacted";
|
|
251
|
+
category: "ACTIVITY";
|
|
252
|
+
room_id: string;
|
|
253
|
+
participant_id: string;
|
|
254
|
+
timestamp: Date;
|
|
255
|
+
/** Full participant snapshot (for display name). */
|
|
256
|
+
participant: Participant;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* A participant was @mentioned in a message.
|
|
260
|
+
*
|
|
261
|
+
* Delivered only to the mentioned participant's channel — not broadcast to the
|
|
262
|
+
* room. The `participant_id` is the **recipient** (the person mentioned), not
|
|
263
|
+
* the sender. The sender is in `message.sender_id`.
|
|
264
|
+
*
|
|
265
|
+
* @mention detection is case-insensitive and matches on both `identifier`
|
|
266
|
+
* (e.g. `@my-agent`) and display `name` (e.g. `@Alice`).
|
|
267
|
+
*
|
|
268
|
+
* Agents in standby modes wake up on this event type only.
|
|
269
|
+
*/
|
|
270
|
+
interface MentionedEvent extends BaseRoomEvent {
|
|
271
|
+
type: "Mentioned";
|
|
272
|
+
category: "MENTION";
|
|
273
|
+
room_id: string;
|
|
274
|
+
/** The mentioned participant (the recipient of the @mention). */
|
|
275
|
+
participant_id: string;
|
|
276
|
+
timestamp: Date;
|
|
277
|
+
/** The full message that contained the @mention. */
|
|
278
|
+
message: Message;
|
|
279
|
+
}
|
|
280
|
+
type RoomEvent = MessageSentEvent | MessageEditedEvent | MessageDeletedEvent | ReactionAddedEvent | ReactionRemovedEvent | ParticipantJoinedEvent | ParticipantLeftEvent | StatusChangedEvent | ToolUseEvent | ActivityEvent | MentionedEvent | ContextCompactedEvent;
|
|
281
|
+
/**
|
|
282
|
+
* Semantic role of an event, used by the engagement system to decide how to
|
|
283
|
+
* handle it relative to an agent.
|
|
284
|
+
*
|
|
285
|
+
* - "message" — a direct chat message; may trigger LLM evaluation
|
|
286
|
+
* - "mention" — an @mention directed at a specific participant
|
|
287
|
+
* - "ambient" — background activity (joins, leaves, reactions) — buffered as
|
|
288
|
+
* context but doesn't trigger evaluation on its own
|
|
289
|
+
* - "internal" — platform bookkeeping (edits, deletes, status changes, agent
|
|
290
|
+
* activity) — always dropped by the engagement system
|
|
291
|
+
*/
|
|
292
|
+
type EventRole = "message" | "mention" | "ambient" | "internal";
|
|
293
|
+
/** Maps each event type to its semantic role for the engagement system. */
|
|
294
|
+
declare const EVENT_ROLE: Record<RoomEvent["type"], EventRole>;
|
|
295
|
+
type EventData<T extends RoomEvent> = Omit<T, "id" | "timestamp"> & {
|
|
296
|
+
id?: string;
|
|
297
|
+
timestamp?: Date;
|
|
298
|
+
};
|
|
299
|
+
/**
|
|
300
|
+
* Create a typed room event, filling in `id` (UUID) and `timestamp` (now).
|
|
301
|
+
*
|
|
302
|
+
* @example
|
|
303
|
+
* const event = createEvent<MessageSentEvent>({
|
|
304
|
+
* type: "MessageSent",
|
|
305
|
+
* category: "MESSAGE",
|
|
306
|
+
* room_id: "room-1",
|
|
307
|
+
* participant_id: "user-1",
|
|
308
|
+
* message: { ... },
|
|
309
|
+
* });
|
|
310
|
+
*/
|
|
311
|
+
declare function createEvent<T extends RoomEvent>(data: EventData<T>): T;
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Storage protocol and reference implementations for stoops rooms.
|
|
315
|
+
*
|
|
316
|
+
* # Implementing StorageProtocol
|
|
317
|
+
*
|
|
318
|
+
* Provide your own implementation to persist messages and events to a real
|
|
319
|
+
* database. Pass it to `new Room(roomId, myStorage)`.
|
|
320
|
+
*
|
|
321
|
+
* Pagination contract (applies to all paginated methods):
|
|
322
|
+
* - Results are returned newest-first.
|
|
323
|
+
* - `cursor` is the ID of the last item on the previous page (exclusive).
|
|
324
|
+
* Pass `null` to start from the most recent.
|
|
325
|
+
* - `next_cursor` in the result is the cursor to pass for the next (older) page.
|
|
326
|
+
* - `has_more` is true if there are older items beyond the current page.
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* // Minimal Postgres implementation sketch:
|
|
330
|
+
* class PostgresStorage implements StorageProtocol {
|
|
331
|
+
* async addMessage(message) {
|
|
332
|
+
* await db.query("INSERT INTO messages ...", [message]);
|
|
333
|
+
* return message;
|
|
334
|
+
* }
|
|
335
|
+
* async getMessage(room_id, message_id) {
|
|
336
|
+
* return db.query("SELECT * FROM messages WHERE id = $1", [message_id]);
|
|
337
|
+
* }
|
|
338
|
+
* async getMessages(room_id, limit = 30, cursor = null) {
|
|
339
|
+
* // Fetch `limit` messages before `cursor`, newest-first
|
|
340
|
+
* const rows = await db.query("...");
|
|
341
|
+
* return { items: rows, next_cursor: ..., has_more: ... };
|
|
342
|
+
* }
|
|
343
|
+
* async searchMessages(room_id, query, limit = 10, cursor = null) {
|
|
344
|
+
* // Full-text search, newest-first
|
|
345
|
+
* }
|
|
346
|
+
* async addEvent(event) {
|
|
347
|
+
* await db.query("INSERT INTO events ...", [event]);
|
|
348
|
+
* }
|
|
349
|
+
* async getEvents(room_id, category = null, limit = 50, cursor = null) {
|
|
350
|
+
* // Optional category filter, newest-first
|
|
351
|
+
* }
|
|
352
|
+
* }
|
|
353
|
+
*/
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Persistence interface for a room's messages and events.
|
|
357
|
+
*
|
|
358
|
+
* Implement this to back rooms with a real database. The reference
|
|
359
|
+
* `InMemoryStorage` is suitable for testing and single-process local use.
|
|
360
|
+
*
|
|
361
|
+
* All methods operate on a single `room_id` — one storage instance is shared
|
|
362
|
+
* across all rooms (the `room_id` partitions the data).
|
|
363
|
+
*/
|
|
364
|
+
interface StorageProtocol {
|
|
365
|
+
/**
|
|
366
|
+
* Persist a message and return it (with any server-assigned fields set).
|
|
367
|
+
* Called automatically by `Channel.sendMessage()`.
|
|
368
|
+
*/
|
|
369
|
+
addMessage(message: Message): Promise<Message>;
|
|
370
|
+
/**
|
|
371
|
+
* Look up a single message by ID. Returns null if not found.
|
|
372
|
+
* Used by agents when resolving reply context and message refs.
|
|
373
|
+
*/
|
|
374
|
+
getMessage(room_id: string, message_id: string): Promise<Message | null>;
|
|
375
|
+
/**
|
|
376
|
+
* Paginate messages for a room, newest-first.
|
|
377
|
+
*
|
|
378
|
+
* `cursor` — the `id` of the last message on the previous page (exclusive).
|
|
379
|
+
* Pass null to start from the most recent message.
|
|
380
|
+
*/
|
|
381
|
+
getMessages(room_id: string, limit?: number, cursor?: string | null): Promise<PaginatedResult<Message>>;
|
|
382
|
+
/**
|
|
383
|
+
* Full-text search across message content, newest-first.
|
|
384
|
+
*
|
|
385
|
+
* `query` — keyword or phrase to search for (case-insensitive).
|
|
386
|
+
* `cursor` — pagination cursor (same semantics as `getMessages`).
|
|
387
|
+
*/
|
|
388
|
+
searchMessages(room_id: string, query: string, limit?: number, cursor?: string | null): Promise<PaginatedResult<Message>>;
|
|
389
|
+
/**
|
|
390
|
+
* Persist a room event. Called for every event that passes through the room.
|
|
391
|
+
* Events are append-only — never updated or deleted.
|
|
392
|
+
*/
|
|
393
|
+
addEvent(event: RoomEvent): Promise<void>;
|
|
394
|
+
/**
|
|
395
|
+
* Paginate events for a room, newest-first.
|
|
396
|
+
*
|
|
397
|
+
* `category` — optional filter (e.g. EventCategory.MESSAGE). Pass null for all.
|
|
398
|
+
* `cursor` — pagination cursor (index-based for events).
|
|
399
|
+
*/
|
|
400
|
+
getEvents(room_id: string, category?: EventCategory | null, limit?: number, cursor?: string | null): Promise<PaginatedResult<RoomEvent>>;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Reference in-memory implementation of `StorageProtocol`.
|
|
404
|
+
*
|
|
405
|
+
* Suitable for tests, development, and single-process local use. All data is
|
|
406
|
+
* lost on process restart — not for production.
|
|
407
|
+
*
|
|
408
|
+
* One instance can serve multiple rooms (data is partitioned by `room_id`).
|
|
409
|
+
*/
|
|
410
|
+
declare class InMemoryStorage implements StorageProtocol {
|
|
411
|
+
private _messages;
|
|
412
|
+
private _events;
|
|
413
|
+
addMessage(message: Message): Promise<Message>;
|
|
414
|
+
getMessage(room_id: string, message_id: string): Promise<Message | null>;
|
|
415
|
+
getMessages(room_id: string, limit?: number, cursor?: string | null): Promise<PaginatedResult<Message>>;
|
|
416
|
+
searchMessages(room_id: string, query: string, limit?: number, cursor?: string | null): Promise<PaginatedResult<Message>>;
|
|
417
|
+
addEvent(event: RoomEvent): Promise<void>;
|
|
418
|
+
getEvents(room_id: string, category?: EventCategory | null, limit?: number, cursor?: string | null): Promise<PaginatedResult<RoomEvent>>;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Room — a shared chat space where humans and agents are all just participants.
|
|
423
|
+
*
|
|
424
|
+
* Transport-agnostic: no WebSockets, no HTTP. The caller owns the transport
|
|
425
|
+
* and passes messages/events in via channels. This means the same Room works
|
|
426
|
+
* identically in a CLI, a web server, or a test.
|
|
427
|
+
*
|
|
428
|
+
* # Connecting
|
|
429
|
+
* Participants connect via `room.connect()`, which returns a `Channel`. The
|
|
430
|
+
* channel is their bidirectional connection: they send messages and receive
|
|
431
|
+
* events through it.
|
|
432
|
+
*
|
|
433
|
+
* # Observing
|
|
434
|
+
* Call `room.observe()` to get a read-only-style channel that receives every
|
|
435
|
+
* event in the room — including targeted @mention events directed at other
|
|
436
|
+
* participants. Observers are NOT participants: they don't appear in
|
|
437
|
+
* `listParticipants()` and don't trigger join/leave events.
|
|
438
|
+
*
|
|
439
|
+
* # @mention detection
|
|
440
|
+
* When a message is sent, the Room scans its content for `@token` patterns and
|
|
441
|
+
* fires a `MentionedEvent` for any participant whose `identifier` or display
|
|
442
|
+
* `name` matches the token (case-insensitive). The mention event is delivered
|
|
443
|
+
* to the mentioned participant AND to all observers.
|
|
444
|
+
*
|
|
445
|
+
* @example
|
|
446
|
+
* const storage = new InMemoryStorage();
|
|
447
|
+
* const room = new Room("room-1", storage);
|
|
448
|
+
*
|
|
449
|
+
* const aliceChannel = await room.connect("alice-id", "Alice");
|
|
450
|
+
* const agentChannel = await room.connect("agent-id", "Agent", "agent", "my-agent");
|
|
451
|
+
* const observer = room.observe();
|
|
452
|
+
*
|
|
453
|
+
* await aliceChannel.sendMessage("hey @my-agent what do you think?");
|
|
454
|
+
* // → MessageSentEvent broadcast to all participants + observer
|
|
455
|
+
* // → MentionedEvent delivered to agentChannel + observer
|
|
456
|
+
*/
|
|
457
|
+
|
|
458
|
+
declare class Room {
|
|
459
|
+
readonly roomId: string;
|
|
460
|
+
/** Direct access to the underlying storage. Useful for bulk reads. */
|
|
461
|
+
readonly storage: StorageProtocol;
|
|
462
|
+
private _channels;
|
|
463
|
+
private _participants;
|
|
464
|
+
private _observers;
|
|
465
|
+
private _nextObserverId;
|
|
466
|
+
/**
|
|
467
|
+
* @param roomId — stable identifier for this room (e.g. a UUID or slug)
|
|
468
|
+
* @param storage — storage backend; defaults to `InMemoryStorage`
|
|
469
|
+
*/
|
|
470
|
+
constructor(roomId: string, storage?: StorageProtocol);
|
|
471
|
+
/**
|
|
472
|
+
* Connect a participant and return their channel.
|
|
473
|
+
*/
|
|
474
|
+
connect(participantId: string, name: string, options?: {
|
|
475
|
+
type?: ParticipantType;
|
|
476
|
+
identifier?: string;
|
|
477
|
+
subscribe?: Set<EventCategory>;
|
|
478
|
+
silent?: boolean;
|
|
479
|
+
authority?: AuthorityLevel;
|
|
480
|
+
}): Promise<Channel>;
|
|
481
|
+
/**
|
|
482
|
+
* Observe all room events without being a participant.
|
|
483
|
+
*
|
|
484
|
+
* Returns a channel that receives every event — broadcasts AND targeted
|
|
485
|
+
* @mention events directed at other participants. Observers do NOT appear
|
|
486
|
+
* in `listParticipants()` and do not emit join/leave presence events,
|
|
487
|
+
* since they are not participants.
|
|
488
|
+
*
|
|
489
|
+
* Disconnect via `observer.disconnect()` when done.
|
|
490
|
+
*
|
|
491
|
+
* @example
|
|
492
|
+
* const observer = room.observe();
|
|
493
|
+
* for await (const event of observer) {
|
|
494
|
+
* // sees everything, including mentions for other participants
|
|
495
|
+
* }
|
|
496
|
+
*/
|
|
497
|
+
observe(): Channel;
|
|
498
|
+
/**
|
|
499
|
+
* Paginate messages, newest-first. Pass the returned `next_cursor` to get
|
|
500
|
+
* the next (older) page.
|
|
501
|
+
*/
|
|
502
|
+
listMessages(limit?: number, cursor?: string | null): Promise<PaginatedResult<Message>>;
|
|
503
|
+
/**
|
|
504
|
+
* Full-text search across message content, newest-first.
|
|
505
|
+
* `query` is matched case-insensitively against message content.
|
|
506
|
+
*/
|
|
507
|
+
searchMessages(query: string, limit?: number, cursor?: string | null): Promise<PaginatedResult<Message>>;
|
|
508
|
+
/** All currently connected participants (including agents). Observers excluded. */
|
|
509
|
+
listParticipants(): Participant[];
|
|
510
|
+
/**
|
|
511
|
+
* Paginate room events, newest-first.
|
|
512
|
+
* `category` optionally filters to one EventCategory.
|
|
513
|
+
*/
|
|
514
|
+
listEvents(category?: EventCategory | null, limit?: number, cursor?: string | null): Promise<PaginatedResult<RoomEvent>>;
|
|
515
|
+
/** Look up a single message by ID. Returns null if not found. */
|
|
516
|
+
getMessage(id: string): Promise<Message | null>;
|
|
517
|
+
/** Update a participant's authority level at runtime. */
|
|
518
|
+
setParticipantAuthority(participantId: string, authority: AuthorityLevel): boolean;
|
|
519
|
+
/**
|
|
520
|
+
* @internal
|
|
521
|
+
* Store a message, broadcast MessageSentEvent, and fire MentionedEvents.
|
|
522
|
+
*
|
|
523
|
+
* @mention scanning: looks for `@token` patterns in content and matches
|
|
524
|
+
* against each connected participant's `identifier` and display `name`
|
|
525
|
+
* (case-insensitive). Fires a `MentionedEvent` for each match, delivered
|
|
526
|
+
* to the mentioned participant AND all observers.
|
|
527
|
+
*/
|
|
528
|
+
_handleMessage(message: Message): Promise<void>;
|
|
529
|
+
/** @internal Store and broadcast an activity event. */
|
|
530
|
+
_handleEvent(event: RoomEvent): Promise<void>;
|
|
531
|
+
/** @internal Remove a channel and optionally broadcast ParticipantLeftEvent. */
|
|
532
|
+
_disconnectChannel(channel: Channel, silent?: boolean): Promise<void>;
|
|
533
|
+
private _storeAndBroadcast;
|
|
534
|
+
private _broadcast;
|
|
535
|
+
/**
|
|
536
|
+
* Scan message content for `@token` patterns and return matching participant IDs.
|
|
537
|
+
* Matches against both `identifier` (e.g. `@my-agent`) and display `name` (e.g. `@Alice`).
|
|
538
|
+
* Case-insensitive. Deduplicates — each participant appears at most once.
|
|
539
|
+
*/
|
|
540
|
+
private _detectMentions;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Channel — a participant's bidirectional connection to a room.
|
|
545
|
+
*
|
|
546
|
+
* Created by `Room.connect()`. Never instantiated directly.
|
|
547
|
+
*
|
|
548
|
+
* # Sending
|
|
549
|
+
* - `sendMessage()` — persist and broadcast a chat message
|
|
550
|
+
* - `emit()` — push non-message events (tool use, mode changes, etc.)
|
|
551
|
+
*
|
|
552
|
+
* # Receiving
|
|
553
|
+
* Channels are async-iterable — use `for await (const event of channel)` to
|
|
554
|
+
* consume events. Only events in the channel's `subscriptions` set are
|
|
555
|
+
* delivered. Alternatively, use `receive(timeoutMs)` for polling with a
|
|
556
|
+
* timeout (used by EventMultiplexer).
|
|
557
|
+
*
|
|
558
|
+
* # Lifecycle
|
|
559
|
+
* - `updateSubscriptions()` — change which EventCategories are delivered
|
|
560
|
+
* - `disconnect(silent?)` — leave the room; pass `true` to suppress the
|
|
561
|
+
* ParticipantLeft broadcast
|
|
562
|
+
*/
|
|
563
|
+
|
|
564
|
+
declare class Channel {
|
|
565
|
+
readonly participantId: string;
|
|
566
|
+
readonly participantName: string;
|
|
567
|
+
subscriptions: Set<EventCategory>;
|
|
568
|
+
private _room;
|
|
569
|
+
private _queue;
|
|
570
|
+
private _waiters;
|
|
571
|
+
private _disconnected;
|
|
572
|
+
constructor(room: Room, participantId: string, participantName: string, subscriptions: Set<EventCategory>);
|
|
573
|
+
get roomId(): string;
|
|
574
|
+
/**
|
|
575
|
+
* Send a chat message from this participant.
|
|
576
|
+
*
|
|
577
|
+
* Persists the message to storage, broadcasts a `MessageSentEvent` to all
|
|
578
|
+
* participants (including the sender), and fires `MentionedEvent` for any
|
|
579
|
+
* `@name` or `@identifier` patterns found in the content.
|
|
580
|
+
*
|
|
581
|
+
* @param content — message text (may be empty if image is provided)
|
|
582
|
+
* @param replyToId — ID of the message being replied to (optional)
|
|
583
|
+
* @param image — optional image attachment
|
|
584
|
+
*/
|
|
585
|
+
sendMessage(content: string, replyToId?: string | null, image?: {
|
|
586
|
+
url: string;
|
|
587
|
+
mimeType: string;
|
|
588
|
+
sizeBytes: number;
|
|
589
|
+
} | null): Promise<Message>;
|
|
590
|
+
/**
|
|
591
|
+
* Emit a non-message activity event to the room.
|
|
592
|
+
*
|
|
593
|
+
* Use this for platform events: tool use indicators, mode changes, compaction
|
|
594
|
+
* notices, etc. The event is persisted and broadcast to all subscribed
|
|
595
|
+
* participants.
|
|
596
|
+
*/
|
|
597
|
+
emit(event: RoomEvent): Promise<void>;
|
|
598
|
+
/**
|
|
599
|
+
* Change which event categories this channel receives.
|
|
600
|
+
* Takes effect immediately — buffered events from unsubscribed categories
|
|
601
|
+
* are not retroactively removed.
|
|
602
|
+
*/
|
|
603
|
+
updateSubscriptions(categories: Set<EventCategory>): void;
|
|
604
|
+
/**
|
|
605
|
+
* Leave the room.
|
|
606
|
+
*
|
|
607
|
+
* @param silent — if true, suppresses the `ParticipantLeft` broadcast.
|
|
608
|
+
* Agents disconnect silently to avoid chat noise.
|
|
609
|
+
*/
|
|
610
|
+
disconnect(silent?: boolean): Promise<void>;
|
|
611
|
+
/** @internal Called by Room to mark this channel as disconnected without removing from room maps. */
|
|
612
|
+
_markDisconnected(): void;
|
|
613
|
+
/** @internal Called by Room to deliver an incoming event. Filters by subscription. */
|
|
614
|
+
_deliver(event: RoomEvent): void;
|
|
615
|
+
/**
|
|
616
|
+
* Receive the next event, waiting up to `timeoutMs`.
|
|
617
|
+
*
|
|
618
|
+
* Returns null if no event arrives within the timeout. Drains buffered events
|
|
619
|
+
* before waiting. Used by `EventMultiplexer` to fan-in events from multiple
|
|
620
|
+
* rooms into a single stream.
|
|
621
|
+
*/
|
|
622
|
+
receive(timeoutMs: number): Promise<RoomEvent | null>;
|
|
623
|
+
/**
|
|
624
|
+
* Async iterator — yields events as they arrive.
|
|
625
|
+
*
|
|
626
|
+
* Used by `EventMultiplexer` to fan-in all room channels into a single stream.
|
|
627
|
+
* The iterator completes when the channel is disconnected.
|
|
628
|
+
*
|
|
629
|
+
* @example
|
|
630
|
+
* for await (const event of channel) {
|
|
631
|
+
* console.log(event.type);
|
|
632
|
+
* }
|
|
633
|
+
*/
|
|
634
|
+
[Symbol.asyncIterator](): AsyncIterator<RoomEvent>;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
export { type ActivityEvent as A, Channel as C, EventCategory as E, InMemoryStorage as I, type Message as M, type Participant as P, type RoomEvent as R, type StatusChangedEvent as S, type ToolUseEvent as T, type PaginatedResult as a, Room as b, type ParticipantType as c, type ContextCompactedEvent as d, EVENT_ROLE as e, type EventRole as f, type MentionedEvent as g, type MessageDeletedEvent as h, type MessageEditedEvent as i, MessageSchema as j, type MessageSentEvent as k, type ParticipantJoinedEvent as l, type ParticipantLeftEvent as m, type ReactionAddedEvent as n, type ReactionRemovedEvent as o, type StorageProtocol as p, createEvent as q };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { A as ActivityEvent, C as Channel, d as ContextCompactedEvent, e as EVENT_ROLE, E as EventCategory, f as EventRole, I as InMemoryStorage, g as MentionedEvent, M as Message, h as MessageDeletedEvent, i as MessageEditedEvent, j as MessageSchema, k as MessageSentEvent, a as PaginatedResult, P as Participant, l as ParticipantJoinedEvent, m as ParticipantLeftEvent, n as ReactionAddedEvent, o as ReactionRemovedEvent, b as Room, R as RoomEvent, S as StatusChangedEvent, p as StorageProtocol, T as ToolUseEvent, q as createEvent } from './index-DlxJ95ki.js';
|
|
2
|
+
import 'zod';
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
Channel,
|
|
3
|
+
InMemoryStorage,
|
|
4
|
+
Room
|
|
5
|
+
} from "./chunk-LC5WPWR2.js";
|
|
6
|
+
import {
|
|
7
|
+
EventCategory,
|
|
8
|
+
MessageSchema
|
|
9
|
+
} from "./chunk-5ADJGMXQ.js";
|
|
10
|
+
import {
|
|
11
|
+
EVENT_ROLE,
|
|
12
|
+
createEvent
|
|
13
|
+
} from "./chunk-HQS7HBZR.js";
|
|
14
|
+
export {
|
|
15
|
+
Channel,
|
|
16
|
+
EVENT_ROLE,
|
|
17
|
+
EventCategory,
|
|
18
|
+
InMemoryStorage,
|
|
19
|
+
MessageSchema,
|
|
20
|
+
Room,
|
|
21
|
+
createEvent
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|