@shadowob/sdk 0.3.4 → 0.4.1

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/src/constants.ts DELETED
@@ -1,15 +0,0 @@
1
- // Re-export shared event constants for convenience
2
-
3
- export type { ClientEvent, ServerEvent } from '@shadowob/shared'
4
- export { CLIENT_EVENTS, SERVER_EVENTS } from '@shadowob/shared'
5
-
6
- // ─── Room helpers ───────────────────────────────────────────────────────────
7
-
8
- /** Build a Socket.IO room name for a channel */
9
- export const channelRoom = (channelId: string) => `channel:${channelId}` as const
10
-
11
- /** Build a Socket.IO room name for a thread */
12
- export const threadRoom = (threadId: string) => `thread:${threadId}` as const
13
-
14
- /** Build a Socket.IO room name for user-level notifications */
15
- export const userRoom = (userId: string) => `user:${userId}` as const
package/src/index.ts DELETED
@@ -1,64 +0,0 @@
1
- // Client
2
- export { ShadowClient } from './client'
3
- export type { ClientEvent, ServerEvent } from './constants'
4
- // Constants & room helpers
5
- export {
6
- CLIENT_EVENTS,
7
- channelRoom,
8
- SERVER_EVENTS,
9
- threadRoom,
10
- userRoom,
11
- } from './constants'
12
- export type { ShadowSocketOptions } from './socket'
13
- // Socket
14
- export { ShadowSocket } from './socket'
15
-
16
- // Types
17
- export type {
18
- ChannelCreatedPayload,
19
- ChannelMemberAddedPayload,
20
- ChannelMemberRemovedPayload,
21
- ClientEventMap,
22
- DmMessage,
23
- MemberJoinPayload,
24
- MemberLeavePayload,
25
- MessageDeletedPayload,
26
- PolicyChangedPayload,
27
- PresenceActivityPayload,
28
- PresenceChangePayload,
29
- ReactionPayload,
30
- ServerEventMap,
31
- ServerJoinedPayload,
32
- ShadowApp,
33
- ShadowAttachment,
34
- ShadowCartItem,
35
- ShadowCategory,
36
- ShadowChannel,
37
- ShadowChannelPolicy,
38
- ShadowContract,
39
- ShadowDmChannel,
40
- ShadowFriendship,
41
- ShadowInviteCode,
42
- ShadowListing,
43
- ShadowMember,
44
- ShadowMessage,
45
- ShadowNotification,
46
- ShadowNotificationPreferences,
47
- ShadowOAuthApp,
48
- ShadowOAuthConsent,
49
- ShadowOAuthToken,
50
- ShadowOrder,
51
- ShadowProduct,
52
- ShadowRemoteChannel,
53
- ShadowRemoteConfig,
54
- ShadowRemoteServer,
55
- ShadowReview,
56
- ShadowServer,
57
- ShadowShop,
58
- ShadowTask,
59
- ShadowThread,
60
- ShadowTransaction,
61
- ShadowUser,
62
- ShadowWallet,
63
- TypingPayload,
64
- } from './types'
package/src/socket.ts DELETED
@@ -1,202 +0,0 @@
1
- import { io, type Socket } from 'socket.io-client'
2
- import type { ClientEventMap, ServerEventMap } from './types'
3
-
4
- export interface ShadowSocketOptions {
5
- /** Shadow server base URL (e.g. "https://shadowob.shadowob.com") */
6
- serverUrl: string
7
- /** JWT token for authentication */
8
- token: string
9
- /** Socket.IO transports (default: ['websocket']) */
10
- transports?: string[]
11
- /** Auto-reconnect on disconnect (default: true) */
12
- autoReconnect?: boolean
13
- /** Reconnection delay in ms (default: 1000) */
14
- reconnectionDelay?: number
15
- }
16
-
17
- type ServerEventName = keyof ServerEventMap
18
- type ServerEventHandler<E extends ServerEventName> = ServerEventMap[E]
19
-
20
- /**
21
- * Shadow real-time event listener.
22
- *
23
- * Wraps Socket.IO with strongly-typed events that match the Shadow server
24
- * gateway broadcasts. Provides channel/thread room management and
25
- * convenience methods for sending messages and typing indicators.
26
- */
27
- export class ShadowSocket {
28
- private socket: Socket
29
- private _connected = false
30
-
31
- constructor(options: ShadowSocketOptions) {
32
- this.socket = io(options.serverUrl, {
33
- auth: { token: options.token },
34
- transports: options.transports ?? ['websocket'],
35
- autoConnect: false,
36
- reconnection: options.autoReconnect ?? true,
37
- reconnectionDelay: options.reconnectionDelay ?? 1000,
38
- })
39
-
40
- this.socket.on('connect', () => {
41
- this._connected = true
42
- })
43
- this.socket.on('disconnect', () => {
44
- this._connected = false
45
- })
46
- }
47
-
48
- /** Whether the socket is currently connected */
49
- get connected(): boolean {
50
- return this._connected
51
- }
52
-
53
- /** The underlying Socket.IO socket instance */
54
- get raw(): Socket {
55
- return this.socket
56
- }
57
-
58
- // ── Connection lifecycle ──────────────────────────────────────────────
59
-
60
- /** Connect to the Shadow server */
61
- connect(): void {
62
- if (!this.socket.connected) {
63
- this.socket.connect()
64
- }
65
- }
66
-
67
- /** Disconnect from the Shadow server */
68
- disconnect(): void {
69
- this.socket.disconnect()
70
- }
71
-
72
- /** Wait until the socket is connected (resolves immediately if already connected) */
73
- waitForConnect(timeoutMs = 5000): Promise<void> {
74
- if (this.socket.connected) return Promise.resolve()
75
- return new Promise<void>((resolve, reject) => {
76
- const timer = setTimeout(() => {
77
- reject(new Error(`Socket connect timeout after ${timeoutMs}ms`))
78
- }, timeoutMs)
79
- this.socket.once('connect', () => {
80
- clearTimeout(timer)
81
- resolve()
82
- })
83
- })
84
- }
85
-
86
- // ── Typed event listeners ─────────────────────────────────────────────
87
-
88
- /** Listen for a server event */
89
- on<E extends ServerEventName>(event: E, handler: ServerEventHandler<E>): this {
90
- this.socket.on(event as string, handler as (...args: unknown[]) => void)
91
- return this
92
- }
93
-
94
- /** Listen for a server event (one-time) */
95
- once<E extends ServerEventName>(event: E, handler: ServerEventHandler<E>): this {
96
- this.socket.once(event as string, handler as (...args: unknown[]) => void)
97
- return this
98
- }
99
-
100
- /** Remove a specific event listener */
101
- off<E extends ServerEventName>(event: E, handler: ServerEventHandler<E>): this {
102
- this.socket.off(event as string, handler as (...args: unknown[]) => void)
103
- return this
104
- }
105
-
106
- /** Remove all listeners for an event or all events */
107
- removeAllListeners(event?: ServerEventName): this {
108
- if (event) {
109
- this.socket.removeAllListeners(event)
110
- } else {
111
- this.socket.removeAllListeners()
112
- }
113
- return this
114
- }
115
-
116
- // ── Connection event listeners ────────────────────────────────────────
117
-
118
- /** Listen for raw connection events (connect, disconnect, connect_error) */
119
- onConnect(handler: () => void): this {
120
- this.socket.on('connect', handler)
121
- return this
122
- }
123
-
124
- onDisconnect(handler: (reason: string) => void): this {
125
- this.socket.on('disconnect', handler)
126
- return this
127
- }
128
-
129
- onConnectError(handler: (error: Error) => void): this {
130
- this.socket.on('connect_error', handler)
131
- return this
132
- }
133
-
134
- // ── Room management ───────────────────────────────────────────────────
135
-
136
- /** Join a channel room to receive its messages and events */
137
- joinChannel(channelId: string): Promise<{ ok: boolean }> {
138
- return new Promise((resolve) => {
139
- this.socket.emit(
140
- 'channel:join' satisfies keyof ClientEventMap,
141
- { channelId },
142
- (res: { ok: boolean }) => {
143
- resolve(res ?? { ok: true })
144
- },
145
- )
146
- })
147
- }
148
-
149
- /** Leave a channel room */
150
- leaveChannel(channelId: string): void {
151
- this.socket.emit('channel:leave' satisfies keyof ClientEventMap, { channelId })
152
- }
153
-
154
- // ── Client actions ────────────────────────────────────────────────────
155
-
156
- /** Send a message via WebSocket (text-only; for file attachments use REST) */
157
- sendMessage(data: {
158
- channelId: string
159
- content: string
160
- threadId?: string
161
- replyToId?: string
162
- }): void {
163
- this.socket.emit('message:send' satisfies keyof ClientEventMap, data)
164
- }
165
-
166
- /** Send a typing indicator */
167
- sendTyping(channelId: string): void {
168
- this.socket.emit('message:typing' satisfies keyof ClientEventMap, { channelId })
169
- }
170
-
171
- /** Update user presence status */
172
- updatePresence(status: 'online' | 'idle' | 'dnd' | 'offline'): void {
173
- this.socket.emit('presence:update' satisfies keyof ClientEventMap, { status })
174
- }
175
-
176
- /** Update activity status in a channel (e.g. 'thinking', 'working', null) */
177
- updateActivity(channelId: string, activity: string | null): void {
178
- this.socket.emit('presence:activity' satisfies keyof ClientEventMap, { channelId, activity })
179
- }
180
-
181
- // ── DM actions ────────────────────────────────────────────────────────
182
-
183
- /** Join a DM channel room */
184
- joinDmChannel(dmChannelId: string): void {
185
- this.socket.emit('dm:join' as string, { dmChannelId })
186
- }
187
-
188
- /** Leave a DM channel room */
189
- leaveDmChannel(dmChannelId: string): void {
190
- this.socket.emit('dm:leave' as string, { dmChannelId })
191
- }
192
-
193
- /** Send a DM message via WebSocket */
194
- sendDmMessage(data: { dmChannelId: string; content: string; replyToId?: string }): void {
195
- this.socket.emit('dm:send' as string, data)
196
- }
197
-
198
- /** Send a DM typing indicator */
199
- sendDmTyping(dmChannelId: string): void {
200
- this.socket.emit('dm:typing' as string, { dmChannelId })
201
- }
202
- }
package/src/types.ts DELETED
@@ -1,438 +0,0 @@
1
- // ─── Shadow SDK Types ───────────────────────────────────────────────────────
2
-
3
- /** Message returned by the Shadow REST API and Socket.IO broadcasts */
4
- export interface ShadowMessage {
5
- id: string
6
- content: string
7
- channelId: string
8
- authorId: string
9
- threadId?: string | null
10
- replyToId?: string | null
11
- isPinned?: boolean
12
- createdAt: string
13
- updatedAt: string
14
- author?: {
15
- id: string
16
- username: string
17
- displayName?: string | null
18
- avatarUrl?: string | null
19
- isBot?: boolean
20
- }
21
- attachments?: ShadowAttachment[]
22
- }
23
-
24
- export interface ShadowAttachment {
25
- id: string
26
- filename: string
27
- url: string
28
- contentType: string
29
- size: number
30
- width?: number | null
31
- height?: number | null
32
- }
33
-
34
- export interface ShadowChannel {
35
- id: string
36
- name: string
37
- type: string
38
- serverId: string
39
- description?: string | null
40
- position?: number
41
- }
42
-
43
- export interface ShadowDmChannel {
44
- id: string
45
- user1Id: string
46
- user2Id: string
47
- createdAt: string
48
- }
49
-
50
- export interface ShadowThread {
51
- id: string
52
- name: string
53
- channelId: string
54
- parentMessageId: string
55
- createdAt: string
56
- }
57
-
58
- export interface ShadowMember {
59
- userId: string
60
- serverId: string
61
- role: string
62
- user?: ShadowUser
63
- }
64
-
65
- export interface ShadowInviteCode {
66
- id: string
67
- code: string
68
- createdBy: string
69
- usedBy?: string | null
70
- usedAt?: string | null
71
- isActive: boolean
72
- note?: string | null
73
- createdAt: string
74
- }
75
-
76
- export interface ShadowServer {
77
- id: string
78
- name: string
79
- slug: string
80
- description: string | null
81
- iconUrl: string | null
82
- bannerUrl: string | null
83
- homepageHtml: string | null
84
- isPublic: boolean
85
- }
86
-
87
- export interface ShadowUser {
88
- id: string
89
- username: string
90
- displayName?: string
91
- avatarUrl?: string
92
- isBot?: boolean
93
- agentId?: string
94
- }
95
-
96
- export interface ShadowNotification {
97
- id: string
98
- userId: string
99
- type: string
100
- title: string
101
- body: string
102
- referenceId?: string
103
- referenceType?: string
104
- isRead: boolean
105
- createdAt: string
106
- }
107
-
108
- // ─── Channel Policy Types ───────────────────────────────────────────────────
109
-
110
- export interface ShadowChannelPolicy {
111
- listen: boolean
112
- reply: boolean
113
- mentionOnly: boolean
114
- config: Record<string, unknown>
115
- }
116
-
117
- export interface ShadowRemoteChannel {
118
- id: string
119
- name: string
120
- type: string
121
- policy: ShadowChannelPolicy
122
- }
123
-
124
- export interface ShadowRemoteServer {
125
- id: string
126
- name: string
127
- slug?: string
128
- iconUrl?: string | null
129
- defaultPolicy: ShadowChannelPolicy
130
- channels: ShadowRemoteChannel[]
131
- }
132
-
133
- export interface ShadowRemoteConfig {
134
- agentId: string
135
- botUserId: string
136
- servers: ShadowRemoteServer[]
137
- }
138
-
139
- // ─── Socket Event Payloads ──────────────────────────────────────────────────
140
-
141
- export interface TypingPayload {
142
- channelId: string
143
- userId: string
144
- username: string
145
- }
146
-
147
- export interface PresenceChangePayload {
148
- userId: string
149
- status: 'online' | 'idle' | 'dnd' | 'offline'
150
- }
151
-
152
- export interface PresenceActivityPayload {
153
- userId: string
154
- activity: string | null
155
- channelId: string
156
- }
157
-
158
- export interface MemberJoinPayload {
159
- channelId: string
160
- userId: string
161
- }
162
-
163
- export interface MemberLeavePayload {
164
- channelId: string
165
- userId: string
166
- }
167
-
168
- export interface ReactionPayload {
169
- messageId: string
170
- userId: string
171
- emoji: string
172
- }
173
-
174
- export interface MessageDeletedPayload {
175
- id: string
176
- channelId: string
177
- }
178
-
179
- export interface ChannelCreatedPayload {
180
- id: string
181
- name: string
182
- type: string
183
- serverId: string
184
- }
185
-
186
- export interface ChannelMemberAddedPayload {
187
- channelId: string
188
- userId: string
189
- }
190
-
191
- export interface ChannelMemberRemovedPayload {
192
- channelId: string
193
- userId: string
194
- }
195
-
196
- export interface ServerJoinedPayload {
197
- serverId: string
198
- serverName: string
199
- }
200
-
201
- export interface PolicyChangedPayload {
202
- agentId: string
203
- serverId: string
204
- channelId?: string | null
205
- }
206
-
207
- export interface DmMessage {
208
- id: string
209
- content: string
210
- senderId: string
211
- receiverId: string
212
- dmChannelId: string
213
- channelId: string
214
- authorId: string
215
- author?: {
216
- id: string
217
- username: string
218
- displayName?: string
219
- avatarUrl?: string
220
- isBot?: boolean
221
- }
222
- createdAt: string
223
- }
224
-
225
- // ─── Friendship Types ───────────────────────────────────────────────────────
226
-
227
- export interface ShadowFriendship {
228
- id: string
229
- userId: string
230
- friendId: string
231
- status: 'pending' | 'accepted' | 'rejected'
232
- createdAt: string
233
- user?: ShadowUser
234
- friend?: ShadowUser
235
- }
236
-
237
- // ─── OAuth App Types ────────────────────────────────────────────────────────
238
-
239
- export interface ShadowOAuthApp {
240
- id: string
241
- name: string
242
- clientId: string
243
- clientSecret?: string
244
- redirectUris: string[]
245
- scopes: string[]
246
- createdAt: string
247
- }
248
-
249
- export interface ShadowOAuthConsent {
250
- id: string
251
- appId: string
252
- appName: string
253
- scopes: string[]
254
- createdAt: string
255
- }
256
-
257
- export interface ShadowOAuthToken {
258
- access_token: string
259
- token_type: string
260
- expires_in: number
261
- refresh_token?: string
262
- scope: string
263
- }
264
-
265
- // ─── Marketplace / Rental Types ─────────────────────────────────────────────
266
-
267
- export interface ShadowListing {
268
- id: string
269
- agentId: string
270
- title: string
271
- description: string
272
- pricePerHour: number
273
- currency: string
274
- tags: string[]
275
- isActive: boolean
276
- createdAt: string
277
- agent?: { id: string; name: string; status: string }
278
- }
279
-
280
- export interface ShadowContract {
281
- id: string
282
- listingId: string
283
- tenantId: string
284
- ownerId: string
285
- status: string
286
- startedAt: string
287
- expiresAt: string
288
- totalCost: number
289
- createdAt: string
290
- }
291
-
292
- // ─── Shop Types ─────────────────────────────────────────────────────────────
293
-
294
- export interface ShadowShop {
295
- id: string
296
- serverId: string
297
- name: string
298
- description?: string | null
299
- isEnabled: boolean
300
- }
301
-
302
- export interface ShadowCategory {
303
- id: string
304
- shopId: string
305
- name: string
306
- description?: string | null
307
- position: number
308
- }
309
-
310
- export interface ShadowProduct {
311
- id: string
312
- shopId: string
313
- categoryId?: string | null
314
- name: string
315
- description?: string | null
316
- price: number
317
- currency: string
318
- stock: number
319
- status: string
320
- images: string[]
321
- createdAt: string
322
- }
323
-
324
- export interface ShadowCartItem {
325
- id: string
326
- productId: string
327
- quantity: number
328
- product?: ShadowProduct
329
- }
330
-
331
- export interface ShadowOrder {
332
- id: string
333
- shopId: string
334
- buyerId: string
335
- status: string
336
- totalAmount: number
337
- currency: string
338
- items: { productId: string; quantity: number; price: number }[]
339
- createdAt: string
340
- }
341
-
342
- export interface ShadowReview {
343
- id: string
344
- orderId: string
345
- productId: string
346
- userId: string
347
- rating: number
348
- content: string
349
- reply?: string | null
350
- createdAt: string
351
- }
352
-
353
- export interface ShadowWallet {
354
- id: string
355
- userId: string
356
- balance: number
357
- currency: string
358
- }
359
-
360
- export interface ShadowTransaction {
361
- id: string
362
- walletId: string
363
- type: string
364
- amount: number
365
- description?: string | null
366
- createdAt: string
367
- }
368
-
369
- // ─── Task Center Types ──────────────────────────────────────────────────────
370
-
371
- export interface ShadowTask {
372
- key: string
373
- title: string
374
- description: string
375
- reward: number
376
- status: string
377
- claimedAt?: string | null
378
- }
379
-
380
- // ─── App Types ──────────────────────────────────────────────────────────────
381
-
382
- export interface ShadowApp {
383
- id: string
384
- serverId: string
385
- name: string
386
- slug: string
387
- type: string
388
- url?: string | null
389
- status: string
390
- createdAt: string
391
- }
392
-
393
- // ─── Notification Preferences ───────────────────────────────────────────────
394
-
395
- export interface ShadowNotificationPreferences {
396
- strategy: 'all' | 'mention_only' | 'none'
397
- mutedServerIds: string[]
398
- mutedChannelIds: string[]
399
- }
400
-
401
- // ─── Socket Event Map ───────────────────────────────────────────────────────
402
-
403
- /** Events the server pushes to the client */
404
- export interface ServerEventMap {
405
- 'message:new': (message: ShadowMessage) => void
406
- 'message:updated': (message: ShadowMessage) => void
407
- 'message:deleted': (payload: MessageDeletedPayload) => void
408
- 'member:typing': (payload: TypingPayload) => void
409
- 'member:join': (payload: MemberJoinPayload) => void
410
- 'member:leave': (payload: MemberLeavePayload) => void
411
- 'presence:change': (payload: PresenceChangePayload) => void
412
- 'presence:activity': (payload: PresenceActivityPayload) => void
413
- 'reaction:add': (payload: ReactionPayload) => void
414
- 'reaction:remove': (payload: ReactionPayload) => void
415
- 'notification:new': (notification: ShadowNotification) => void
416
- 'dm:message:new': (message: DmMessage) => void
417
- 'channel:created': (payload: ChannelCreatedPayload) => void
418
- 'channel:member-added': (payload: ChannelMemberAddedPayload) => void
419
- 'channel:member-removed': (payload: ChannelMemberRemovedPayload) => void
420
- 'server:joined': (payload: ServerJoinedPayload) => void
421
- 'agent:policy-changed': (payload: PolicyChangedPayload) => void
422
- error: (payload: { message: string }) => void
423
- }
424
-
425
- /** Events the client sends to the server */
426
- export interface ClientEventMap {
427
- 'channel:join': (data: { channelId: string }, ack?: (res: { ok: boolean }) => void) => void
428
- 'channel:leave': (data: { channelId: string }) => void
429
- 'message:send': (data: {
430
- channelId: string
431
- content: string
432
- threadId?: string
433
- replyToId?: string
434
- }) => void
435
- 'message:typing': (data: { channelId: string }) => void
436
- 'presence:update': (data: { status: 'online' | 'idle' | 'dnd' | 'offline' }) => void
437
- 'presence:activity': (data: { channelId: string; activity: string | null }) => void
438
- }