@soulcraft/sdk 2.1.0 → 2.3.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/namespaces.d.ts +33 -1
- package/dist/namespaces.d.ts.map +1 -1
- package/dist/server/handlers/chat/conversations.d.ts +19 -0
- package/dist/server/handlers/chat/conversations.d.ts.map +1 -1
- package/dist/server/handlers/chat/conversations.js +55 -0
- package/dist/server/handlers/chat/conversations.js.map +1 -1
- package/dist/server/handlers/chat/engine.d.ts.map +1 -1
- package/dist/server/handlers/chat/engine.js +67 -6
- package/dist/server/handlers/chat/engine.js.map +1 -1
- package/dist/server/handlers/chat/index.d.ts +3 -1
- package/dist/server/handlers/chat/index.d.ts.map +1 -1
- package/dist/server/handlers/chat/index.js +3 -1
- package/dist/server/handlers/chat/index.js.map +1 -1
- package/dist/server/handlers/chat/resolve-ai-client.d.ts +75 -0
- package/dist/server/handlers/chat/resolve-ai-client.d.ts.map +1 -0
- package/dist/server/handlers/chat/resolve-ai-client.js +183 -0
- package/dist/server/handlers/chat/resolve-ai-client.js.map +1 -0
- package/dist/server/handlers/chat/types.d.ts +14 -2
- package/dist/server/handlers/chat/types.d.ts.map +1 -1
- package/dist/server/handlers/index.d.ts +2 -2
- package/dist/server/handlers/index.d.ts.map +1 -1
- package/dist/server/handlers/index.js +1 -1
- package/dist/server/handlers/index.js.map +1 -1
- package/dist/server/index.d.ts +5 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/namespace-router.d.ts +21 -2
- package/dist/server/namespace-router.d.ts.map +1 -1
- package/dist/server/namespace-router.js +26 -13
- package/dist/server/namespace-router.js.map +1 -1
- package/dist/server/ws-handler.d.ts +167 -0
- package/dist/server/ws-handler.d.ts.map +1 -0
- package/dist/server/ws-handler.js +243 -0
- package/dist/server/ws-handler.js.map +1 -0
- package/dist/transports/ws.d.ts +29 -1
- package/dist/transports/ws.d.ts.map +1 -1
- package/dist/transports/ws.js +129 -3
- package/dist/transports/ws.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module server/ws-handler
|
|
3
|
+
* @description Namespace-aware WebSocket handler for the Soulcraft SDK.
|
|
4
|
+
*
|
|
5
|
+
* Provides `createNamespaceWsHandler()` — a server-side handler that processes
|
|
6
|
+
* WebSocket messages through the same namespace router used by HTTP RPC, plus
|
|
7
|
+
* Y.js collaborative editing and real-time change push.
|
|
8
|
+
*
|
|
9
|
+
* ## Wire protocol
|
|
10
|
+
*
|
|
11
|
+
* All frames are binary MessagePack. The protocol supports four message categories:
|
|
12
|
+
*
|
|
13
|
+
* 1. **Namespace RPC** — `{ id, ns, method, args }` dispatched to the namespace router
|
|
14
|
+
* 2. **Streaming RPC** — `{ id, ns, method, args, stream: true }` returns chunked responses
|
|
15
|
+
* 3. **Y.js collab** — `{ type: 'y-sync'|'y-update'|'y-awareness', ... }` for CRDT editing
|
|
16
|
+
* 4. **Change push** — `{ type: 'change', ... }` broadcast from server on data mutations
|
|
17
|
+
*
|
|
18
|
+
* ## Auth
|
|
19
|
+
*
|
|
20
|
+
* Authentication happens once during `handleUpgrade()`. The resulting `WsSession`
|
|
21
|
+
* carries the authenticated user context. Subsequent messages are dispatched with
|
|
22
|
+
* pre-authenticated context — no per-message auth overhead.
|
|
23
|
+
*
|
|
24
|
+
* ## Relationship to namespace router
|
|
25
|
+
*
|
|
26
|
+
* The WS handler is a thin transport adapter. All RPC dispatch logic lives in
|
|
27
|
+
* `namespace-router.ts`. This handler adds: token extraction, Y.js routing,
|
|
28
|
+
* peer tracking, streaming frame serialization, and change broadcasting.
|
|
29
|
+
*
|
|
30
|
+
* @example Bun server wiring
|
|
31
|
+
* ```typescript
|
|
32
|
+
* import { createNamespaceWsHandler, YDocManager } from '@soulcraft/sdk/server'
|
|
33
|
+
*
|
|
34
|
+
* const handler = createNamespaceWsHandler({
|
|
35
|
+
* router: routerConfig,
|
|
36
|
+
* ydocManager: new YDocManager(),
|
|
37
|
+
* })
|
|
38
|
+
*
|
|
39
|
+
* Bun.serve({
|
|
40
|
+
* async fetch(req, server) {
|
|
41
|
+
* if (new URL(req.url).pathname === '/api/brainy/ws') {
|
|
42
|
+
* const session = await handler.handleUpgrade(req)
|
|
43
|
+
* if (!session) return new Response('Unauthorized', { status: 401 })
|
|
44
|
+
* server.upgrade(req, { data: session })
|
|
45
|
+
* return undefined
|
|
46
|
+
* }
|
|
47
|
+
* },
|
|
48
|
+
* websocket: {
|
|
49
|
+
* open(ws) { ws.send(encode({ type: 'ready', scope: ws.data.scope })) },
|
|
50
|
+
* async message(ws, data) {
|
|
51
|
+
* await handler.handleMessage(ws.data, data, (msg) => ws.send(msg))
|
|
52
|
+
* },
|
|
53
|
+
* async close(ws) { await handler.handleClose(ws.data) },
|
|
54
|
+
* },
|
|
55
|
+
* })
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
import type { Brainy } from '@soulcraft/brainy';
|
|
59
|
+
import type { BrainyChangeEvent } from '../modules/brainy/events.js';
|
|
60
|
+
import type { NamespaceRouterConfig, UserContext } from './namespace-router.js';
|
|
61
|
+
import { YDocManager } from '../modules/brainy/ydoc-manager.js';
|
|
62
|
+
/**
|
|
63
|
+
* Configuration for {@link createNamespaceWsHandler}.
|
|
64
|
+
*
|
|
65
|
+
* Reuses the same `NamespaceRouterConfig` shape as `createSoulcraftRouter()`,
|
|
66
|
+
* so products can share a single config object between HTTP and WebSocket handlers.
|
|
67
|
+
*/
|
|
68
|
+
export interface NamespaceWsHandlerConfig {
|
|
69
|
+
/**
|
|
70
|
+
* Shared router config — `authenticate`, `resolveBrain`, `providers`, `authorize`.
|
|
71
|
+
*
|
|
72
|
+
* The `authenticate` callback receives a synthetic `RequestContext` built from
|
|
73
|
+
* the WebSocket upgrade request. The `resolveBrain` callback receives the same
|
|
74
|
+
* context with the authenticated user populated.
|
|
75
|
+
*/
|
|
76
|
+
router: NamespaceRouterConfig;
|
|
77
|
+
/**
|
|
78
|
+
* Optional Y.js document manager for real-time collaborative editing.
|
|
79
|
+
*
|
|
80
|
+
* When provided, the handler routes `y-sync`, `y-update`, and `y-awareness`
|
|
81
|
+
* messages through the `YDocManager`. Y.js update broadcasts are sent to all
|
|
82
|
+
* other peers via the `broadcast` callback on the session.
|
|
83
|
+
*/
|
|
84
|
+
ydocManager?: YDocManager;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Per-connection session state stored on the WebSocket's data field.
|
|
88
|
+
*
|
|
89
|
+
* Created by `handleUpgrade()` and passed to all subsequent message/close handlers.
|
|
90
|
+
*/
|
|
91
|
+
export interface WsSession {
|
|
92
|
+
/** The authenticated user context. */
|
|
93
|
+
user: UserContext;
|
|
94
|
+
/** Workspace ID extracted from the upgrade request. */
|
|
95
|
+
workspaceId: string;
|
|
96
|
+
/** The resolved Brainy instance for this session's scope. */
|
|
97
|
+
brain: Brainy;
|
|
98
|
+
/** The raw scope string from `?scope=` (preserved for broadcast key). */
|
|
99
|
+
scope: string;
|
|
100
|
+
/**
|
|
101
|
+
* Unique peer ID for this connection. Used by `YDocManager` to track per-file
|
|
102
|
+
* peer counts so it knows when the last peer has disconnected.
|
|
103
|
+
*/
|
|
104
|
+
peerId: string;
|
|
105
|
+
/**
|
|
106
|
+
* Broadcast callback set by the product server after upgrade.
|
|
107
|
+
*
|
|
108
|
+
* Called by the handler to fan out `y-update` and `y-awareness` messages to all
|
|
109
|
+
* other peers connected to this scope. The product server owns the connection map
|
|
110
|
+
* and provides this callback so the SDK does not manage WebSocket handles directly.
|
|
111
|
+
*
|
|
112
|
+
* @param msg - Encoded MessagePack frame to send to all OTHER peers in this scope.
|
|
113
|
+
* @param excludePeerId - The peer that sent the message — must be excluded.
|
|
114
|
+
*/
|
|
115
|
+
broadcast: (msg: Uint8Array, excludePeerId: string) => void;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* The object returned by {@link createNamespaceWsHandler}.
|
|
119
|
+
*/
|
|
120
|
+
export interface NamespaceWsHandler {
|
|
121
|
+
/**
|
|
122
|
+
* Handles a WebSocket upgrade request.
|
|
123
|
+
*
|
|
124
|
+
* Extracts the token and scope, authenticates via the router's `authenticate`
|
|
125
|
+
* callback, and resolves the Brainy instance. Returns `null` on auth failure.
|
|
126
|
+
*
|
|
127
|
+
* @param request - The HTTP upgrade request.
|
|
128
|
+
* @returns Session state on success, or `null` on auth failure.
|
|
129
|
+
*/
|
|
130
|
+
handleUpgrade(request: Request): Promise<WsSession | null>;
|
|
131
|
+
/**
|
|
132
|
+
* Processes an incoming WebSocket message.
|
|
133
|
+
*
|
|
134
|
+
* Routes to either the namespace RPC dispatcher or the Y.js handler based
|
|
135
|
+
* on the decoded message shape.
|
|
136
|
+
*
|
|
137
|
+
* @param session - Session from `handleUpgrade()`.
|
|
138
|
+
* @param data - Raw binary MessagePack frame.
|
|
139
|
+
* @param send - Callback to send a binary response to THIS client only.
|
|
140
|
+
*/
|
|
141
|
+
handleMessage(session: WsSession, data: ArrayBuffer | Uint8Array, send: (msg: Uint8Array) => void): Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* Called when a peer's WebSocket connection closes.
|
|
144
|
+
*
|
|
145
|
+
* Notifies the `YDocManager` so it can flush and discard Y.Docs with no
|
|
146
|
+
* active peers.
|
|
147
|
+
*
|
|
148
|
+
* @param session - The session of the disconnecting peer.
|
|
149
|
+
*/
|
|
150
|
+
handleClose(session: WsSession): Promise<void>;
|
|
151
|
+
/**
|
|
152
|
+
* Broadcasts a Brainy change event to a connected client.
|
|
153
|
+
*
|
|
154
|
+
* @param event - The change event to broadcast.
|
|
155
|
+
* @param send - Callback to send the encoded event to the target client.
|
|
156
|
+
*/
|
|
157
|
+
broadcastChange(event: BrainyChangeEvent, send: (msg: Uint8Array) => void): void;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Creates a namespace-aware WebSocket handler that dispatches RPC through the
|
|
161
|
+
* same namespace router used by HTTP, plus Y.js collaborative editing.
|
|
162
|
+
*
|
|
163
|
+
* @param config - Handler configuration.
|
|
164
|
+
* @returns A {@link NamespaceWsHandler} instance.
|
|
165
|
+
*/
|
|
166
|
+
export declare function createNamespaceWsHandler(config: NamespaceWsHandlerConfig): NamespaceWsHandler;
|
|
167
|
+
//# sourceMappingURL=ws-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-handler.d.ts","sourceRoot":"","sources":["../../src/server/ws-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AACpE,OAAO,KAAK,EACV,qBAAqB,EAErB,WAAW,EAEZ,MAAM,uBAAuB,CAAA;AAI9B,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAA;AAM/D;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;;;OAMG;IACH,MAAM,EAAE,qBAAqB,CAAA;IAE7B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAMD;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,sCAAsC;IACtC,IAAI,EAAE,WAAW,CAAA;IACjB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAA;IACnB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAA;IACd;;;;;;;;;OASG;IACH,SAAS,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5D;AAMD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;OAQG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAA;IAE1D;;;;;;;;;OASG;IACH,aAAa,CACX,OAAO,EAAE,SAAS,EAClB,IAAI,EAAE,WAAW,GAAG,UAAU,EAC9B,IAAI,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,GAC9B,OAAO,CAAC,IAAI,CAAC,CAAA;IAEhB;;;;;;;OAOG;IACH,WAAW,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE9C;;;;;OAKG;IACH,eAAe,CAAC,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAA;CACjF;AAiCD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,wBAAwB,GAAG,kBAAkB,CA0I7F"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module server/ws-handler
|
|
3
|
+
* @description Namespace-aware WebSocket handler for the Soulcraft SDK.
|
|
4
|
+
*
|
|
5
|
+
* Provides `createNamespaceWsHandler()` — a server-side handler that processes
|
|
6
|
+
* WebSocket messages through the same namespace router used by HTTP RPC, plus
|
|
7
|
+
* Y.js collaborative editing and real-time change push.
|
|
8
|
+
*
|
|
9
|
+
* ## Wire protocol
|
|
10
|
+
*
|
|
11
|
+
* All frames are binary MessagePack. The protocol supports four message categories:
|
|
12
|
+
*
|
|
13
|
+
* 1. **Namespace RPC** — `{ id, ns, method, args }` dispatched to the namespace router
|
|
14
|
+
* 2. **Streaming RPC** — `{ id, ns, method, args, stream: true }` returns chunked responses
|
|
15
|
+
* 3. **Y.js collab** — `{ type: 'y-sync'|'y-update'|'y-awareness', ... }` for CRDT editing
|
|
16
|
+
* 4. **Change push** — `{ type: 'change', ... }` broadcast from server on data mutations
|
|
17
|
+
*
|
|
18
|
+
* ## Auth
|
|
19
|
+
*
|
|
20
|
+
* Authentication happens once during `handleUpgrade()`. The resulting `WsSession`
|
|
21
|
+
* carries the authenticated user context. Subsequent messages are dispatched with
|
|
22
|
+
* pre-authenticated context — no per-message auth overhead.
|
|
23
|
+
*
|
|
24
|
+
* ## Relationship to namespace router
|
|
25
|
+
*
|
|
26
|
+
* The WS handler is a thin transport adapter. All RPC dispatch logic lives in
|
|
27
|
+
* `namespace-router.ts`. This handler adds: token extraction, Y.js routing,
|
|
28
|
+
* peer tracking, streaming frame serialization, and change broadcasting.
|
|
29
|
+
*
|
|
30
|
+
* @example Bun server wiring
|
|
31
|
+
* ```typescript
|
|
32
|
+
* import { createNamespaceWsHandler, YDocManager } from '@soulcraft/sdk/server'
|
|
33
|
+
*
|
|
34
|
+
* const handler = createNamespaceWsHandler({
|
|
35
|
+
* router: routerConfig,
|
|
36
|
+
* ydocManager: new YDocManager(),
|
|
37
|
+
* })
|
|
38
|
+
*
|
|
39
|
+
* Bun.serve({
|
|
40
|
+
* async fetch(req, server) {
|
|
41
|
+
* if (new URL(req.url).pathname === '/api/brainy/ws') {
|
|
42
|
+
* const session = await handler.handleUpgrade(req)
|
|
43
|
+
* if (!session) return new Response('Unauthorized', { status: 401 })
|
|
44
|
+
* server.upgrade(req, { data: session })
|
|
45
|
+
* return undefined
|
|
46
|
+
* }
|
|
47
|
+
* },
|
|
48
|
+
* websocket: {
|
|
49
|
+
* open(ws) { ws.send(encode({ type: 'ready', scope: ws.data.scope })) },
|
|
50
|
+
* async message(ws, data) {
|
|
51
|
+
* await handler.handleMessage(ws.data, data, (msg) => ws.send(msg))
|
|
52
|
+
* },
|
|
53
|
+
* async close(ws) { await handler.handleClose(ws.data) },
|
|
54
|
+
* },
|
|
55
|
+
* })
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
import { encode, decode } from '@msgpack/msgpack';
|
|
59
|
+
import { createNamespaceRouter } from './namespace-router.js';
|
|
60
|
+
import { YDocManager } from '../modules/brainy/ydoc-manager.js';
|
|
61
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
62
|
+
// Factory
|
|
63
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
64
|
+
/**
|
|
65
|
+
* Creates a namespace-aware WebSocket handler that dispatches RPC through the
|
|
66
|
+
* same namespace router used by HTTP, plus Y.js collaborative editing.
|
|
67
|
+
*
|
|
68
|
+
* @param config - Handler configuration.
|
|
69
|
+
* @returns A {@link NamespaceWsHandler} instance.
|
|
70
|
+
*/
|
|
71
|
+
export function createNamespaceWsHandler(config) {
|
|
72
|
+
const { router: routerConfig, ydocManager } = config;
|
|
73
|
+
const router = createNamespaceRouter(routerConfig);
|
|
74
|
+
return {
|
|
75
|
+
async handleUpgrade(request) {
|
|
76
|
+
const url = new URL(request.url);
|
|
77
|
+
const scope = url.searchParams.get('scope') ?? '';
|
|
78
|
+
// Extract auth token — Bun/Node uses Authorization header; browsers use ?token= query.
|
|
79
|
+
const authHeader = request.headers.get('authorization') ?? '';
|
|
80
|
+
const token = authHeader.startsWith('Bearer ')
|
|
81
|
+
? authHeader.slice(7)
|
|
82
|
+
: (url.searchParams.get('token') ?? '');
|
|
83
|
+
// Extract workspace ID from scope or header.
|
|
84
|
+
const workspaceId = request.headers.get('x-workspace-id') ??
|
|
85
|
+
url.searchParams.get('workspaceId') ??
|
|
86
|
+
scope;
|
|
87
|
+
// Build a synthetic RequestContext for the router's authenticate callback.
|
|
88
|
+
const ctx = {
|
|
89
|
+
request,
|
|
90
|
+
user: null,
|
|
91
|
+
workspaceId,
|
|
92
|
+
};
|
|
93
|
+
// Authenticate using the router's callback.
|
|
94
|
+
let user;
|
|
95
|
+
try {
|
|
96
|
+
user = await routerConfig.authenticate(ctx);
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
console.error('[SDK/ws] authenticate threw during upgrade:', err);
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
if (!user)
|
|
103
|
+
return null;
|
|
104
|
+
// Resolve brain with the authenticated context.
|
|
105
|
+
ctx.user = user;
|
|
106
|
+
let brain;
|
|
107
|
+
try {
|
|
108
|
+
brain = await routerConfig.resolveBrain(ctx);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
console.error('[SDK/ws] resolveBrain threw during upgrade:', err);
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
const peerId = crypto.randomUUID();
|
|
115
|
+
return {
|
|
116
|
+
user,
|
|
117
|
+
workspaceId,
|
|
118
|
+
brain,
|
|
119
|
+
scope,
|
|
120
|
+
peerId,
|
|
121
|
+
broadcast: () => { }, // No-op until product server sets it in websocket.open()
|
|
122
|
+
};
|
|
123
|
+
},
|
|
124
|
+
async handleMessage(session, data, send) {
|
|
125
|
+
let decoded;
|
|
126
|
+
try {
|
|
127
|
+
decoded = decode(data instanceof ArrayBuffer ? new Uint8Array(data) : data);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return; // Malformed frame — silently ignore
|
|
131
|
+
}
|
|
132
|
+
if (!decoded || typeof decoded !== 'object')
|
|
133
|
+
return;
|
|
134
|
+
const msg = decoded;
|
|
135
|
+
// ── Y.js messages ──────────────────────────────────────────────────
|
|
136
|
+
if (typeof msg['type'] === 'string' && msg['type'].startsWith('y-')) {
|
|
137
|
+
await _handleYjsMessage(msg, session, send, ydocManager);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// ── Namespace RPC ──────────────────────────────────────────────────
|
|
141
|
+
const id = msg['id'];
|
|
142
|
+
const ns = msg['ns'];
|
|
143
|
+
const method = msg['method'];
|
|
144
|
+
const args = msg['args'];
|
|
145
|
+
if (typeof id !== 'string' || typeof method !== 'string' || !Array.isArray(args)) {
|
|
146
|
+
return; // Not a valid RPC frame
|
|
147
|
+
}
|
|
148
|
+
// Default namespace to 'brainy' for backward compat with SDK 1.x clients
|
|
149
|
+
// that send { id, method, args } without an ns field.
|
|
150
|
+
const resolvedNs = typeof ns === 'string' ? ns : 'brainy';
|
|
151
|
+
const stream = msg['stream'] === true;
|
|
152
|
+
const rpc = { id, ns: resolvedNs, method, args, stream };
|
|
153
|
+
// Dispatch with pre-authenticated context — skips re-authentication.
|
|
154
|
+
// The user was already verified in handleUpgrade().
|
|
155
|
+
const preAuthCtx = {
|
|
156
|
+
user: session.user,
|
|
157
|
+
workspaceId: session.workspaceId,
|
|
158
|
+
request: new Request('http://localhost/api/rpc'),
|
|
159
|
+
};
|
|
160
|
+
const result = await router.dispatch(rpc, preAuthCtx);
|
|
161
|
+
if (result.type === 'response') {
|
|
162
|
+
send(encode(result.response));
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
// Streaming response — iterate the async iterable and send frames.
|
|
166
|
+
if (result.type === 'stream') {
|
|
167
|
+
try {
|
|
168
|
+
for await (const chunk of result.iterable) {
|
|
169
|
+
const frame = { id, chunk };
|
|
170
|
+
send(encode(frame));
|
|
171
|
+
}
|
|
172
|
+
send(encode({ id, done: true }));
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
176
|
+
send(encode({ id, error: message }));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
async handleClose(session) {
|
|
181
|
+
if (!ydocManager)
|
|
182
|
+
return;
|
|
183
|
+
await ydocManager.onPeerDisconnectAll(session.scope, session.peerId);
|
|
184
|
+
},
|
|
185
|
+
broadcastChange(event, send) {
|
|
186
|
+
send(encode(event));
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
191
|
+
// Y.js message handler
|
|
192
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
193
|
+
/**
|
|
194
|
+
* Routes a Y.js protocol message to the appropriate `YDocManager` method.
|
|
195
|
+
*
|
|
196
|
+
* ## Sync protocol (standard two-phase handshake):
|
|
197
|
+
* 1. Client sends `y-sync` with its state vector.
|
|
198
|
+
* 2. Server replies with `y-sync` diff (updates client is missing).
|
|
199
|
+
* 3. Client applies diff → sends `y-update` for pending local ops.
|
|
200
|
+
* 4. Steady state: all ops are `y-update` frames, broadcast to all other peers.
|
|
201
|
+
*
|
|
202
|
+
* ## Awareness:
|
|
203
|
+
* `y-awareness` frames carry cursor positions, user name/color. NOT persisted —
|
|
204
|
+
* forwarded to all other peers then discarded.
|
|
205
|
+
*
|
|
206
|
+
* @param msg - Decoded Y.js message frame.
|
|
207
|
+
* @param session - The WebSocket session for the sending peer.
|
|
208
|
+
* @param send - Sends a response to THIS peer only.
|
|
209
|
+
* @param ydocManager - The server-side Y.Doc pool (may be undefined if collab disabled).
|
|
210
|
+
*/
|
|
211
|
+
async function _handleYjsMessage(msg, session, send, ydocManager) {
|
|
212
|
+
if (!ydocManager)
|
|
213
|
+
return;
|
|
214
|
+
switch (msg.type) {
|
|
215
|
+
case 'y-sync': {
|
|
216
|
+
const clientSv = msg.stateVector instanceof Uint8Array
|
|
217
|
+
? msg.stateVector
|
|
218
|
+
: new Uint8Array(Object.values(msg.stateVector));
|
|
219
|
+
const diff = await ydocManager.getDiff(session.scope, msg.filePath, session.brain, clientSv);
|
|
220
|
+
send(encode({ type: 'y-sync', filePath: msg.filePath, diff }));
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
case 'y-update': {
|
|
224
|
+
const update = msg.update instanceof Uint8Array
|
|
225
|
+
? msg.update
|
|
226
|
+
: new Uint8Array(Object.values(msg.update));
|
|
227
|
+
await ydocManager.getOrCreate(session.scope, msg.filePath, session.brain, session.peerId);
|
|
228
|
+
await ydocManager.applyUpdate(session.scope, msg.filePath, update);
|
|
229
|
+
const frame = encode({ type: 'y-update', filePath: msg.filePath, update });
|
|
230
|
+
session.broadcast(frame, session.peerId);
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
case 'y-awareness': {
|
|
234
|
+
const update = msg.update instanceof Uint8Array
|
|
235
|
+
? msg.update
|
|
236
|
+
: new Uint8Array(Object.values(msg.update));
|
|
237
|
+
const frame = encode({ type: 'y-awareness', update });
|
|
238
|
+
session.broadcast(frame, session.peerId);
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=ws-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-handler.js","sourceRoot":"","sources":["../../src/server/ws-handler.ts"],"names":[],"mappings":"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"}
|
package/dist/transports/ws.d.ts
CHANGED
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
* ```
|
|
53
53
|
*/
|
|
54
54
|
import type { SDKTransport } from './transport.js';
|
|
55
|
+
import type { NamespaceTransport } from '../client/namespace-proxy.js';
|
|
55
56
|
import type { BrainyChangeEvent } from '../modules/brainy/events.js';
|
|
56
57
|
/**
|
|
57
58
|
* Transport that communicates via MessagePack-encoded WebSocket RPC.
|
|
@@ -63,7 +64,7 @@ import type { BrainyChangeEvent } from '../modules/brainy/events.js';
|
|
|
63
64
|
* `createSDK` client factory calls this automatically when `sdk.connect()` is
|
|
64
65
|
* invoked.
|
|
65
66
|
*/
|
|
66
|
-
export declare class WsTransport implements SDKTransport {
|
|
67
|
+
export declare class WsTransport implements SDKTransport, NamespaceTransport {
|
|
67
68
|
private ws;
|
|
68
69
|
private readonly wsUrl;
|
|
69
70
|
private readonly authToken;
|
|
@@ -71,6 +72,7 @@ export declare class WsTransport implements SDKTransport {
|
|
|
71
72
|
private readonly timeoutMs;
|
|
72
73
|
private readonly maxReconnectAttempts;
|
|
73
74
|
private readonly pending;
|
|
75
|
+
private readonly pendingStreams;
|
|
74
76
|
private nextId;
|
|
75
77
|
private connectionState;
|
|
76
78
|
private readonly changeListeners;
|
|
@@ -99,6 +101,9 @@ export declare class WsTransport implements SDKTransport {
|
|
|
99
101
|
/**
|
|
100
102
|
* Sends a MessagePack-encoded RPC request and awaits the response.
|
|
101
103
|
*
|
|
104
|
+
* Delegates to `callNs('brainy', method, args)` for backward compatibility
|
|
105
|
+
* with SDK 1.x callers that use the flat Brainy method namespace.
|
|
106
|
+
*
|
|
102
107
|
* @param method - Dot-separated Brainy method name (e.g. `'vfs.readdir'`).
|
|
103
108
|
* @param args - Positional arguments to forward.
|
|
104
109
|
* @returns Whatever the server's Brainy method returns.
|
|
@@ -107,6 +112,29 @@ export declare class WsTransport implements SDKTransport {
|
|
|
107
112
|
* @throws {@link SDKRpcError} if the server reports an error.
|
|
108
113
|
*/
|
|
109
114
|
call(method: string, args: unknown[]): Promise<unknown>;
|
|
115
|
+
/**
|
|
116
|
+
* Sends a namespace-aware RPC request and awaits the response.
|
|
117
|
+
*
|
|
118
|
+
* @param ns - Target namespace (e.g. `'chat'`, `'graph'`, `'brainy.vfs'`).
|
|
119
|
+
* @param method - Method within the namespace (e.g. `'send'`, `'getData'`).
|
|
120
|
+
* @param args - Positional arguments.
|
|
121
|
+
* @returns The handler's return value.
|
|
122
|
+
* @throws {@link SDKDisconnectedError} if not connected.
|
|
123
|
+
* @throws {@link SDKTimeoutError} after `timeoutMs` ms.
|
|
124
|
+
* @throws {@link SDKRpcError} if the server reports an error.
|
|
125
|
+
*/
|
|
126
|
+
callNs(ns: string, method: string, args: unknown[]): Promise<unknown>;
|
|
127
|
+
/**
|
|
128
|
+
* Sends a streaming namespace-aware RPC request and returns an async iterable
|
|
129
|
+
* that yields chunks as they arrive from the server.
|
|
130
|
+
*
|
|
131
|
+
* @param ns - Target namespace.
|
|
132
|
+
* @param method - Method within the namespace.
|
|
133
|
+
* @param args - Positional arguments.
|
|
134
|
+
* @returns An async iterable of response chunks.
|
|
135
|
+
* @throws {@link SDKDisconnectedError} if not connected.
|
|
136
|
+
*/
|
|
137
|
+
callNsStream(ns: string, method: string, args: unknown[]): AsyncIterable<unknown>;
|
|
110
138
|
/**
|
|
111
139
|
* Registers a listener for real-time change push events from the server.
|
|
112
140
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../src/transports/ws.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../src/transports/ws.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AA2EpE;;;;;;;;;GASG;AACH,qBAAa,WAAY,YAAW,YAAY,EAAE,kBAAkB;IAClE,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAQ;IAE7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgC;IACxD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAmC;IAClE,OAAO,CAAC,MAAM,CAAI;IAElB,OAAO,CAAC,eAAe,CAAkC;IACzD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgD;IAEhF,OAAO,CAAC,cAAc,CAA4B;IAClD,OAAO,CAAC,aAAa,CAAoC;IAEzD,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,cAAc,CAA6C;IAEnE;;;;;;OAMG;gBAED,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,SAAS,EAClB,oBAAoB,SAAK;IAW3B;;;;;;;;OAQG;IACH,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAO/B;;;;;;;;;;;;OAYG;IACG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAM7D;;;;;;;;;;OAUG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAoB3E;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC;IA+EjF;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI;IAI1D;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI;IAK3D;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;;;;OAKG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B;;;;;;;;;OASG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B9B,OAAO,CAAC,WAAW;IAuCnB,OAAO,CAAC,cAAc;IAyEtB,OAAO,CAAC,YAAY;IA2DpB,OAAO,CAAC,iBAAiB;CAa1B"}
|