@zhin.js/adapter-sandbox 3.0.1 → 3.0.3
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/CHANGELOG.md +28 -0
- package/README.md +16 -2
- package/client/Sandbox.tsx +111 -31
- package/client/sandboxTransport.ts +61 -0
- package/dist/index.js +7 -7
- package/lib/fetch-sse.d.ts +11 -0
- package/lib/fetch-sse.d.ts.map +1 -0
- package/lib/fetch-sse.js +76 -0
- package/lib/fetch-sse.js.map +1 -0
- package/lib/fetch-ws.d.ts +11 -0
- package/lib/fetch-ws.d.ts.map +1 -0
- package/lib/fetch-ws.js +13 -0
- package/lib/fetch-ws.js.map +1 -0
- package/lib/index.d.ts +16 -48
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +25 -132
- package/lib/index.js.map +1 -1
- package/lib/sandbox-sse-hub.d.ts +10 -0
- package/lib/sandbox-sse-hub.d.ts.map +1 -0
- package/lib/sandbox-sse-hub.js +101 -0
- package/lib/sandbox-sse-hub.js.map +1 -0
- package/lib/sandbox-ws.d.ts +91 -0
- package/lib/sandbox-ws.d.ts.map +1 -0
- package/lib/sandbox-ws.js +337 -0
- package/lib/sandbox-ws.js.map +1 -0
- package/package.json +14 -9
- package/src/fetch-sse.ts +87 -0
- package/src/fetch-ws.ts +23 -0
- package/src/index.ts +57 -181
- package/src/sandbox-sse-hub.ts +118 -0
- package/src/sandbox-ws.ts +462 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sandbox 传输 — Node WebSocket;Edge HTTP+SSE(见 sandbox-sse-hub / fetch-sse)。
|
|
3
|
+
*/
|
|
4
|
+
import { EventEmitter } from "node:events";
|
|
5
|
+
import { broadcastSandboxSse, closeSandboxSseSession } from "./sandbox-sse-hub.js";
|
|
6
|
+
import { Adapter, Message, segment, } from "zhin.js";
|
|
7
|
+
/** 无 WS 时的占位 socket(仅用于 bot:list,不可收发) */
|
|
8
|
+
export function createOfflineSandboxWs() {
|
|
9
|
+
return { send: () => { }, close: () => { } };
|
|
10
|
+
}
|
|
11
|
+
export function createSandboxSseTransport(sessionId, onClose) {
|
|
12
|
+
return {
|
|
13
|
+
sessionId,
|
|
14
|
+
send(data) {
|
|
15
|
+
broadcastSandboxSse(sessionId, data);
|
|
16
|
+
},
|
|
17
|
+
close() {
|
|
18
|
+
closeSandboxSseSession(sessionId);
|
|
19
|
+
onClose?.();
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function envVar(key) {
|
|
24
|
+
const g = globalThis;
|
|
25
|
+
return g.Deno?.env.get(key) ?? g.process?.env[key];
|
|
26
|
+
}
|
|
27
|
+
export function resolveSandboxBot(appConfig) {
|
|
28
|
+
const bots = appConfig.bots;
|
|
29
|
+
const entry = bots?.find((b) => b.context === "sandbox");
|
|
30
|
+
const fixedName = typeof entry?.name === "string" ? entry.name : undefined;
|
|
31
|
+
const name = fixedName ||
|
|
32
|
+
envVar("SANDBOX_BOT_NAME") ||
|
|
33
|
+
"sandbox-bot";
|
|
34
|
+
const owner = (typeof entry?.owner === "string" && entry.owner) ||
|
|
35
|
+
envVar("SANDBOX_BOT_OWNER") ||
|
|
36
|
+
"sandbox-user";
|
|
37
|
+
const transportRaw = (typeof entry?.transport === "string" && entry.transport) ||
|
|
38
|
+
envVar("SANDBOX_TRANSPORT") ||
|
|
39
|
+
"websocket";
|
|
40
|
+
const transport = transportRaw === "http-sse" || transportRaw === "sse" ? "http-sse" : "websocket";
|
|
41
|
+
return {
|
|
42
|
+
context: "sandbox",
|
|
43
|
+
name,
|
|
44
|
+
owner,
|
|
45
|
+
randomNamePerConnection: !fixedName,
|
|
46
|
+
transport,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** 标准 WebSocket 在 upgrade 后可能尚未 OPEN;Node `ws` 在 connection 回调里通常已可 send */
|
|
50
|
+
function whenWsOpen(ws, fn) {
|
|
51
|
+
const std = ws;
|
|
52
|
+
if (typeof std.readyState === "number") {
|
|
53
|
+
if (std.readyState === WebSocket.OPEN) {
|
|
54
|
+
fn();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
std.addEventListener("open", fn, { once: true });
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
fn();
|
|
61
|
+
}
|
|
62
|
+
export function bindSandboxWsSocket(ws, handlers) {
|
|
63
|
+
if (typeof ws.on === "function") {
|
|
64
|
+
const onMessage = (...args) => {
|
|
65
|
+
const data = args[0];
|
|
66
|
+
const raw = typeof data === "string"
|
|
67
|
+
? data
|
|
68
|
+
: data instanceof ArrayBuffer
|
|
69
|
+
? new TextDecoder().decode(data)
|
|
70
|
+
: Buffer.isBuffer(data)
|
|
71
|
+
? data.toString()
|
|
72
|
+
: String(data ?? "");
|
|
73
|
+
handlers.onMessage(raw);
|
|
74
|
+
};
|
|
75
|
+
ws.on("message", onMessage);
|
|
76
|
+
ws.on("close", handlers.onClose);
|
|
77
|
+
if (handlers.onError)
|
|
78
|
+
ws.on("error", handlers.onError);
|
|
79
|
+
return () => {
|
|
80
|
+
ws.off?.("message", onMessage);
|
|
81
|
+
ws.off?.("close", handlers.onClose);
|
|
82
|
+
if (handlers.onError)
|
|
83
|
+
ws.off?.("error", handlers.onError);
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const onMessage = (ev) => {
|
|
87
|
+
const data = ev.data;
|
|
88
|
+
handlers.onMessage(typeof data === "string" ? data : "");
|
|
89
|
+
};
|
|
90
|
+
const onClose = () => handlers.onClose();
|
|
91
|
+
const onError = handlers.onError
|
|
92
|
+
? () => handlers.onError?.(new Error("WebSocket error"))
|
|
93
|
+
: undefined;
|
|
94
|
+
ws.addEventListener("message", onMessage);
|
|
95
|
+
ws.addEventListener("close", onClose);
|
|
96
|
+
if (onError)
|
|
97
|
+
ws.addEventListener("error", onError);
|
|
98
|
+
return () => {
|
|
99
|
+
ws.removeEventListener("message", onMessage);
|
|
100
|
+
ws.removeEventListener("close", onClose);
|
|
101
|
+
if (onError)
|
|
102
|
+
ws.removeEventListener("error", onError);
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export function parseSandboxWsPayload(raw) {
|
|
106
|
+
let payload;
|
|
107
|
+
try {
|
|
108
|
+
payload = JSON.parse(raw);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
payload = { text: raw };
|
|
112
|
+
}
|
|
113
|
+
const type = payload.type ?? "private";
|
|
114
|
+
const id = payload.id ?? "sandbox-user";
|
|
115
|
+
const content = typeof payload.content === "string"
|
|
116
|
+
? [{ type: "text", data: { text: payload.content } }]
|
|
117
|
+
: Array.isArray(payload.content)
|
|
118
|
+
? payload.content
|
|
119
|
+
: [{ type: "text", data: { text: payload.text ?? raw } }];
|
|
120
|
+
return { type, id, content, timestamp: payload.timestamp ?? Date.now() };
|
|
121
|
+
}
|
|
122
|
+
export class SandboxWsBot extends EventEmitter {
|
|
123
|
+
adapter;
|
|
124
|
+
$config;
|
|
125
|
+
$connected = false;
|
|
126
|
+
#unbind = null;
|
|
127
|
+
get $id() {
|
|
128
|
+
return this.$config.name;
|
|
129
|
+
}
|
|
130
|
+
constructor(adapter, $config) {
|
|
131
|
+
super();
|
|
132
|
+
this.adapter = adapter;
|
|
133
|
+
this.$config = $config;
|
|
134
|
+
}
|
|
135
|
+
async $connect() {
|
|
136
|
+
if (this.$config.offline || !this.$config.ws)
|
|
137
|
+
return;
|
|
138
|
+
const ws = this.$config.ws;
|
|
139
|
+
if (typeof ws.on !== "function" && typeof ws.addEventListener !== "function") {
|
|
140
|
+
this.$connected = true;
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
this.#unbind = bindSandboxWsSocket(ws, {
|
|
144
|
+
onMessage: (raw) => {
|
|
145
|
+
const { type, id, content, timestamp } = parseSandboxWsPayload(raw);
|
|
146
|
+
this.adapter.emit("message.receive", this.$formatMessage({ content, type, id, ts: timestamp }));
|
|
147
|
+
},
|
|
148
|
+
onClose: () => {
|
|
149
|
+
this.$connected = false;
|
|
150
|
+
if (!this.$config.offline) {
|
|
151
|
+
this.adapter.bots.delete(this.$id);
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
onError: (err) => {
|
|
155
|
+
this.adapter.logger.warn(`sandbox ws error (${this.$config.name}): ${err instanceof Error ? err.message : String(err)}`);
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
this.$connected = true;
|
|
159
|
+
}
|
|
160
|
+
async $disconnect() {
|
|
161
|
+
this.#unbind?.();
|
|
162
|
+
this.#unbind = null;
|
|
163
|
+
this.$config.ws?.close();
|
|
164
|
+
this.$connected = false;
|
|
165
|
+
}
|
|
166
|
+
$formatMessage({ content, type, id, ts }) {
|
|
167
|
+
if (!this.$config.owner)
|
|
168
|
+
this.$config.owner = id;
|
|
169
|
+
const message = Message.from({ content, type, id, ts }, {
|
|
170
|
+
$id: `${ts}`,
|
|
171
|
+
$adapter: "sandbox",
|
|
172
|
+
$bot: this.$config.name,
|
|
173
|
+
$sender: { id, name: "mock" },
|
|
174
|
+
$channel: { id, type },
|
|
175
|
+
$content: content,
|
|
176
|
+
$raw: segment.raw(content),
|
|
177
|
+
$timestamp: ts,
|
|
178
|
+
$recall: async () => { },
|
|
179
|
+
$reply: async (replyContent, quote) => {
|
|
180
|
+
const normalized = Array.isArray(replyContent) ? replyContent : [replyContent];
|
|
181
|
+
if (quote) {
|
|
182
|
+
normalized.unshift({
|
|
183
|
+
type: "reply",
|
|
184
|
+
data: {
|
|
185
|
+
id: typeof quote === "boolean" ? message.$id : quote,
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
return await this.adapter.sendMessage({
|
|
190
|
+
context: "sandbox",
|
|
191
|
+
bot: this.$config.name,
|
|
192
|
+
content: normalized,
|
|
193
|
+
id,
|
|
194
|
+
type,
|
|
195
|
+
});
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
return message;
|
|
199
|
+
}
|
|
200
|
+
async $sendMessage(options) {
|
|
201
|
+
if (!this.$connected)
|
|
202
|
+
return "";
|
|
203
|
+
const ws = this.$config.ws;
|
|
204
|
+
if (!ws)
|
|
205
|
+
return "";
|
|
206
|
+
ws.send(JSON.stringify({
|
|
207
|
+
...options,
|
|
208
|
+
content: options.content,
|
|
209
|
+
timestamp: Date.now(),
|
|
210
|
+
}));
|
|
211
|
+
return "";
|
|
212
|
+
}
|
|
213
|
+
async $recallMessage(_id) { }
|
|
214
|
+
}
|
|
215
|
+
export class SandboxWsHostAdapter extends Adapter {
|
|
216
|
+
defaults;
|
|
217
|
+
#sseSessions = new Map();
|
|
218
|
+
constructor(plugin, defaults) {
|
|
219
|
+
super(plugin, "sandbox", []);
|
|
220
|
+
this.defaults = defaults;
|
|
221
|
+
}
|
|
222
|
+
get transport() {
|
|
223
|
+
return this.defaults.transport;
|
|
224
|
+
}
|
|
225
|
+
hasSseSession(sessionId) {
|
|
226
|
+
return this.#sseSessions.has(sessionId);
|
|
227
|
+
}
|
|
228
|
+
getBotBySseSession(sessionId) {
|
|
229
|
+
const name = this.#sseSessions.get(sessionId);
|
|
230
|
+
return name ? this.bots.get(name) : undefined;
|
|
231
|
+
}
|
|
232
|
+
createBot(config) {
|
|
233
|
+
const bot = new SandboxWsBot(this, config);
|
|
234
|
+
this.bots.set(bot.$id, bot);
|
|
235
|
+
return bot;
|
|
236
|
+
}
|
|
237
|
+
/** `zhin.config.yml` 中 `context: sandbox` + 固定 `name` 时,启动即出现在 bot:list(离线) */
|
|
238
|
+
registerConfiguredPlaceholder() {
|
|
239
|
+
if (this.defaults.randomNamePerConnection)
|
|
240
|
+
return;
|
|
241
|
+
if (this.bots.has(this.defaults.name))
|
|
242
|
+
return;
|
|
243
|
+
this.createBot({
|
|
244
|
+
context: "sandbox",
|
|
245
|
+
name: this.defaults.name,
|
|
246
|
+
owner: this.defaults.owner,
|
|
247
|
+
ws: createOfflineSandboxWs(),
|
|
248
|
+
offline: true,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
/** Edge / 外部 upgrade:注入已建立的 WebSocket */
|
|
252
|
+
acceptWebSocket(ws, overrides) {
|
|
253
|
+
const name = overrides?.name ??
|
|
254
|
+
(this.defaults.randomNamePerConnection
|
|
255
|
+
? `sandbox-${crypto.randomUUID().slice(0, 8)}`
|
|
256
|
+
: this.defaults.name);
|
|
257
|
+
const owner = overrides?.owner ?? this.defaults.owner;
|
|
258
|
+
const existing = this.bots.get(name);
|
|
259
|
+
if (existing) {
|
|
260
|
+
void existing.$disconnect();
|
|
261
|
+
this.bots.delete(name);
|
|
262
|
+
}
|
|
263
|
+
const bot = this.createBot({ context: "sandbox", ws, name, owner, offline: false });
|
|
264
|
+
void bot.$connect();
|
|
265
|
+
if (!this.defaults.randomNamePerConnection) {
|
|
266
|
+
const readyPayload = JSON.stringify({
|
|
267
|
+
type: "ready",
|
|
268
|
+
id: owner,
|
|
269
|
+
bot: name,
|
|
270
|
+
content: [
|
|
271
|
+
{
|
|
272
|
+
type: "text",
|
|
273
|
+
data: {
|
|
274
|
+
text: [
|
|
275
|
+
`已连接 Sandbox「${name}」`,
|
|
276
|
+
"与 Node Host 控制台沙盒协议一致(/sandbox)",
|
|
277
|
+
"命令: help · ping · zt · status",
|
|
278
|
+
].join("\n"),
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
timestamp: Date.now(),
|
|
283
|
+
});
|
|
284
|
+
whenWsOpen(ws, () => ws.send(readyPayload));
|
|
285
|
+
}
|
|
286
|
+
return bot;
|
|
287
|
+
}
|
|
288
|
+
/** Edge SSE:建立会话并绑定固定 bot */
|
|
289
|
+
acceptSseSession(sessionId, overrides) {
|
|
290
|
+
const name = overrides?.name ?? this.defaults.name;
|
|
291
|
+
const owner = overrides?.owner ?? this.defaults.owner;
|
|
292
|
+
const existing = this.bots.get(name);
|
|
293
|
+
if (existing) {
|
|
294
|
+
void existing.$disconnect();
|
|
295
|
+
this.bots.delete(name);
|
|
296
|
+
}
|
|
297
|
+
const ws = createSandboxSseTransport(sessionId, () => {
|
|
298
|
+
this.#sseSessions.delete(sessionId);
|
|
299
|
+
this.bots.delete(name);
|
|
300
|
+
});
|
|
301
|
+
const bot = this.createBot({ context: "sandbox", ws, name, owner, offline: false });
|
|
302
|
+
this.#sseSessions.set(sessionId, name);
|
|
303
|
+
void bot.$connect();
|
|
304
|
+
if (!this.defaults.randomNamePerConnection) {
|
|
305
|
+
const readyPayload = JSON.stringify({
|
|
306
|
+
type: "ready",
|
|
307
|
+
id: owner,
|
|
308
|
+
bot: name,
|
|
309
|
+
content: [
|
|
310
|
+
{
|
|
311
|
+
type: "text",
|
|
312
|
+
data: {
|
|
313
|
+
text: [
|
|
314
|
+
`已连接 Sandbox「${name}」`,
|
|
315
|
+
"传输: HTTP + SSE(Edge)",
|
|
316
|
+
"命令: help · ping · zt · status",
|
|
317
|
+
].join("\n"),
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
timestamp: Date.now(),
|
|
322
|
+
});
|
|
323
|
+
ws.send(readyPayload);
|
|
324
|
+
}
|
|
325
|
+
return bot;
|
|
326
|
+
}
|
|
327
|
+
/** POST /sandbox/message — 与 WebSocket 帧同格式的 JSON 字符串 */
|
|
328
|
+
ingestSseClientMessage(sessionId, raw) {
|
|
329
|
+
const bot = this.getBotBySseSession(sessionId);
|
|
330
|
+
if (!bot || !bot.$connected) {
|
|
331
|
+
throw new Error(`sandbox session not connected: ${sessionId}`);
|
|
332
|
+
}
|
|
333
|
+
const { type, id, content, timestamp } = parseSandboxWsPayload(raw);
|
|
334
|
+
this.emit("message.receive", bot.$formatMessage({ content, type, id, ts: timestamp }));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
//# sourceMappingURL=sandbox-ws.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-ws.js","sourceRoot":"","sources":["../src/sandbox-ws.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EACL,OAAO,EAEP,OAAO,EACP,OAAO,GAMR,MAAM,SAAS,CAAC;AAWjB,0CAA0C;AAC1C,MAAM,UAAU,sBAAsB;IACpC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,SAAiB,EACjB,OAAoB;IAEpB,OAAO;QACL,SAAS;QACT,IAAI,CAAC,IAAY;YACf,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACvC,CAAC;QACD,KAAK;YACH,sBAAsB,CAAC,SAAS,CAAC,CAAC;YAClC,OAAO,EAAE,EAAE,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC;AAsCD,SAAS,MAAM,CAAC,GAAW;IACzB,MAAM,CAAC,GAAG,UAGT,CAAC;IACF,OAAO,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,SAAkC;IAElC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAkD,CAAC;IAC1E,MAAM,KAAK,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC;IACzD,MAAM,SAAS,GAAG,OAAO,KAAK,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3E,MAAM,IAAI,GACR,SAAS;QACT,MAAM,CAAC,kBAAkB,CAAC;QAC1B,aAAa,CAAC;IAChB,MAAM,KAAK,GACT,CAAC,OAAO,KAAK,EAAE,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC;QACjD,MAAM,CAAC,mBAAmB,CAAC;QAC3B,cAAc,CAAC;IACjB,MAAM,YAAY,GAChB,CAAC,OAAO,KAAK,EAAE,SAAS,KAAK,QAAQ,IAAI,KAAK,CAAC,SAAS,CAAC;QACzD,MAAM,CAAC,mBAAmB,CAAC;QAC3B,WAAW,CAAC;IACd,MAAM,SAAS,GACb,YAAY,KAAK,UAAU,IAAI,YAAY,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC;IACnF,OAAO;QACL,OAAO,EAAE,SAAS;QAClB,IAAI;QACJ,KAAK;QACL,uBAAuB,EAAE,CAAC,SAAS;QACnC,SAAS;KACV,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,SAAS,UAAU,CAAC,EAAmB,EAAE,EAAc;IACrD,MAAM,GAAG,GAAG,EAAe,CAAC;IAC5B,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QACvC,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YACtC,EAAE,EAAE,CAAC;YACL,OAAO;QACT,CAAC;QACD,GAAG,CAAC,gBAAgB,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,OAAO;IACT,CAAC;IACD,EAAE,EAAE,CAAC;AACP,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,EAAmB,EACnB,QAIC;IAED,IAAI,OAAO,EAAE,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE;YACvC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ;gBAClC,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,IAAI,YAAY,WAAW;oBAC7B,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC;oBAChC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;wBACvB,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE;wBACjB,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YACvB,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC,CAAC;QACF,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC5B,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjC,IAAI,QAAQ,CAAC,OAAO;YAAE,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;QACvD,OAAO,GAAG,EAAE;YACV,EAAE,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YAC/B,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;YACpC,IAAI,QAAQ,CAAC,OAAO;gBAAE,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC5D,CAAC,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG,CAAC,EAAS,EAAE,EAAE;QAC9B,MAAM,IAAI,GAAI,EAAmB,CAAC,IAAI,CAAC;QACvC,QAAQ,CAAC,SAAS,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC3D,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO;QAC9B,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACxD,CAAC,CAAC,SAAS,CAAC;IACd,EAAE,CAAC,gBAAiB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC3C,EAAE,CAAC,gBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACvC,IAAI,OAAO;QAAE,EAAE,CAAC,gBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACpD,OAAO,GAAG,EAAE;QACV,EAAE,CAAC,mBAAoB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC9C,EAAE,CAAC,mBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1C,IAAI,OAAO;YAAE,EAAE,CAAC,mBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACzD,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAM/C,IAAI,OAMH,CAAC;IACF,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;IAC1B,CAAC;IACD,MAAM,IAAI,GAAI,OAAO,CAAC,IAAoB,IAAI,SAAS,CAAC;IACxD,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,cAAc,CAAC;IACxC,MAAM,OAAO,GAAqB,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ;QACnE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;QACrD,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;YAChC,CAAC,CAAC,OAAO,CAAC,OAAO;YACjB,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5D,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;AAC3E,CAAC;AASD,MAAM,OAAO,YAAa,SAAQ,YAAY;IASnC;IACA;IATT,UAAU,GAAG,KAAK,CAAC;IACnB,OAAO,GAAwB,IAAI,CAAC;IAEpC,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,YACS,OAA6B,EAC7B,OAAwB;QAE/B,KAAK,EAAE,CAAC;QAHD,YAAO,GAAP,OAAO,CAAsB;QAC7B,YAAO,GAAP,OAAO,CAAiB;IAGjC,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;YAAE,OAAO;QACrD,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,IAAI,OAAO,EAAE,CAAC,EAAE,KAAK,UAAU,IAAI,OAAO,EAAE,CAAC,gBAAgB,KAAK,UAAU,EAAE,CAAC;YAC7E,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,mBAAmB,CAAC,EAAE,EAAE;YACrC,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE;gBACjB,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;gBACpE,IAAI,CAAC,OAAO,CAAC,IAAI,CACf,iBAAiB,EACjB,IAAI,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAC1D,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,GAAG,EAAE;gBACZ,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;gBACxB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;oBAC1B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACrC,CAAC;YACH,CAAC;YACD,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACf,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CACtB,qBAAqB,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC/F,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;QACH,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAY;QAChD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC;QACjD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAC1B,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EACzB;YACE,GAAG,EAAE,GAAG,EAAE,EAAE;YACZ,QAAQ,EAAE,SAAkB;YAC5B,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;YACvB,OAAO,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;YAC7B,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE;YACtB,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;YAC1B,UAAU,EAAE,EAAE;YACd,OAAO,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;YACvB,MAAM,EAAE,KAAK,EAAE,YAAyB,EAAE,KAAwB,EAAE,EAAE;gBACpE,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;gBAC/E,IAAI,KAAK,EAAE,CAAC;oBACV,UAAU,CAAC,OAAO,CAAC;wBACjB,IAAI,EAAE,OAAO;wBACb,IAAI,EAAE;4BACJ,EAAE,EAAE,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK;yBACrD;qBACF,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;oBACpC,OAAO,EAAE,SAAS;oBAClB,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;oBACtB,OAAO,EAAE,UAAU;oBACnB,EAAE;oBACF,IAAI;iBACL,CAAC,CAAC;YACL,CAAC;SACF,CACF,CAAC;QACF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,OAAoB;QACrC,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAChC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QACnB,EAAE,CAAC,IAAI,CACL,IAAI,CAAC,SAAS,CAAC;YACb,GAAG,OAAO;YACV,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CACH,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,GAAW,IAAkB,CAAC;CACpD;AAED,MAAM,OAAO,oBAAqB,SAAQ,OAAqB;IAKxC;IAJZ,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAElD,YACE,MAAc,EACK,QAA4B;QAE/C,KAAK,CAAC,MAAM,EAAE,SAAkC,EAAE,EAAE,CAAC,CAAC;QAFnC,aAAQ,GAAR,QAAQ,CAAoB;IAGjD,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;IACjC,CAAC;IAED,aAAa,CAAC,SAAiB;QAC7B,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IAED,kBAAkB,CAAC,SAAiB;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAChD,CAAC;IAED,SAAS,CAAC,MAAuB;QAC/B,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC5B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,+EAA+E;IAC/E,6BAA6B;QAC3B,IAAI,IAAI,CAAC,QAAQ,CAAC,uBAAuB;YAAE,OAAO;QAClD,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO;QAC9C,IAAI,CAAC,SAAS,CAAC;YACb,OAAO,EAAE,SAAS;YAClB,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI;YACxB,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK;YAC1B,EAAE,EAAE,sBAAsB,EAAE;YAC5B,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAED,yCAAyC;IACzC,eAAe,CACb,EAAmB,EACnB,SAA4D;QAE5D,MAAM,IAAI,GAAG,SAAS,EAAE,IAAI;YAC1B,CAAC,IAAI,CAAC,QAAQ,CAAC,uBAAuB;gBACpC,CAAC,CAAC,WAAW,MAAM,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;gBAC9C,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,KAAK,GAAG,SAAS,EAAE,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,QAAQ,CAAC,WAAW,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACpF,KAAK,GAAG,CAAC,QAAQ,EAAE,CAAC;QACpB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,uBAAuB,EAAE,CAAC;YAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC;gBAClC,IAAI,EAAE,OAAO;gBACb,EAAE,EAAE,KAAK;gBACT,GAAG,EAAE,IAAI;gBACT,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;4BACJ,IAAI,EAAE;gCACJ,eAAe,IAAI,GAAG;gCACtB,iCAAiC;gCACjC,+BAA+B;6BAChC,CAAC,IAAI,CAAC,IAAI,CAAC;yBACb;qBACF;iBACF;gBACD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB,CAAC,CAAC;YACH,UAAU,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,6BAA6B;IAC7B,gBAAgB,CACd,SAAiB,EACjB,SAA4D;QAE5D,MAAM,IAAI,GAAG,SAAS,EAAE,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QACnD,MAAM,KAAK,GAAG,SAAS,EAAE,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,QAAQ,CAAC,WAAW,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;QACD,MAAM,EAAE,GAAG,yBAAyB,CAAC,SAAS,EAAE,GAAG,EAAE;YACnD,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACpF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACvC,KAAK,GAAG,CAAC,QAAQ,EAAE,CAAC;QACpB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,uBAAuB,EAAE,CAAC;YAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC;gBAClC,IAAI,EAAE,OAAO;gBACb,EAAE,EAAE,KAAK;gBACT,GAAG,EAAE,IAAI;gBACT,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;4BACJ,IAAI,EAAE;gCACJ,eAAe,IAAI,GAAG;gCACtB,sBAAsB;gCACtB,+BAA+B;6BAChC,CAAC,IAAI,CAAC,IAAI,CAAC;yBACb;qBACF;iBACF;gBACD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB,CAAC,CAAC;YACH,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,yDAAyD;IACzD,sBAAsB,CAAC,SAAiB,EAAE,GAAW;QACnD,MAAM,GAAG,GAAG,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAC/C,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,kCAAkC,SAAS,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;QACpE,IAAI,CAAC,IAAI,CACP,iBAAiB,EACjB,GAAG,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CACzD,CAAC;IACJ,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-sandbox",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "Zhin.js adapter for local testing and development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -43,25 +43,30 @@
|
|
|
43
43
|
"directory": "plugins/adapters/sandbox"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@types/react": "^19.2.
|
|
46
|
+
"@types/react": "^19.2.15",
|
|
47
47
|
"@types/react-dom": "^19.2.3",
|
|
48
48
|
"radix-ui": "^1.4.3",
|
|
49
49
|
"lucide-react": "^1.16.0",
|
|
50
50
|
"typescript": "^6.0.3",
|
|
51
|
-
"@zhin.js/
|
|
52
|
-
"zhin.js": "1.0.
|
|
51
|
+
"@zhin.js/http-host": "0.1.3",
|
|
52
|
+
"@zhin.js/cli": "1.0.80",
|
|
53
|
+
"zhin.js": "1.0.84"
|
|
53
54
|
},
|
|
54
55
|
"peerDependencies": {
|
|
55
|
-
"@zhin.js/core": "1.1.
|
|
56
|
-
"@zhin.js/client": "1.1.
|
|
57
|
-
"@zhin.js/http": "1.0.
|
|
58
|
-
"@zhin.js/
|
|
59
|
-
"zhin.js": "
|
|
56
|
+
"@zhin.js/core": "1.1.26",
|
|
57
|
+
"@zhin.js/client": "1.1.3",
|
|
58
|
+
"@zhin.js/http": "1.0.77",
|
|
59
|
+
"@zhin.js/http-host": "0.1.3",
|
|
60
|
+
"@zhin.js/console": "3.0.3",
|
|
61
|
+
"zhin.js": "1.0.84"
|
|
60
62
|
},
|
|
61
63
|
"peerDependenciesMeta": {
|
|
62
64
|
"@zhin.js/http": {
|
|
63
65
|
"optional": true
|
|
64
66
|
},
|
|
67
|
+
"@zhin.js/http-host": {
|
|
68
|
+
"optional": true
|
|
69
|
+
},
|
|
65
70
|
"@zhin.js/console": {
|
|
66
71
|
"optional": true
|
|
67
72
|
},
|
package/src/fetch-sse.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { registerFetchRoute, type RouteTable } from "@zhin.js/http-host/edge";
|
|
2
|
+
import type { RouterContext } from "@zhin.js/http-host/edge";
|
|
3
|
+
import type { SandboxWsHostAdapter } from "./sandbox-ws.js";
|
|
4
|
+
import { subscribeSandboxSse } from "./sandbox-sse-hub.js";
|
|
5
|
+
|
|
6
|
+
export type RegisterSandboxSseOptions = {
|
|
7
|
+
eventsPath?: string;
|
|
8
|
+
messagePath?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function resolveSessionId(ctx: RouterContext): string | undefined {
|
|
12
|
+
const q = ctx.query.session?.trim();
|
|
13
|
+
if (q) return q;
|
|
14
|
+
const h = ctx.get("x-sandbox-session")?.trim();
|
|
15
|
+
if (h) return h;
|
|
16
|
+
const body = ctx.request.body as { session?: string } | undefined;
|
|
17
|
+
if (body && typeof body.session === "string" && body.session.trim()) {
|
|
18
|
+
return body.session.trim();
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Edge / Vercel 等:Sandbox 使用 HTTP POST 上行 + SSE 下行(无 WebSocket upgrade)。
|
|
25
|
+
*/
|
|
26
|
+
export function registerSandboxSseRoutes(
|
|
27
|
+
table: RouteTable,
|
|
28
|
+
getAdapter: () => SandboxWsHostAdapter,
|
|
29
|
+
options: RegisterSandboxSseOptions = {},
|
|
30
|
+
): void {
|
|
31
|
+
const eventsPath = options.eventsPath ?? "/sandbox/events";
|
|
32
|
+
const messagePath = options.messagePath ?? "/sandbox/message";
|
|
33
|
+
|
|
34
|
+
registerFetchRoute(table, "GET", eventsPath, (ctx: RouterContext) => {
|
|
35
|
+
const sessionId = resolveSessionId(ctx);
|
|
36
|
+
if (!sessionId) {
|
|
37
|
+
ctx.status = 400;
|
|
38
|
+
ctx.body = { success: false, error: "Missing session (query ?session= or X-Sandbox-Session)" };
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const adapter = getAdapter();
|
|
42
|
+
if (!adapter.hasSseSession(sessionId)) {
|
|
43
|
+
adapter.acceptSseSession(sessionId);
|
|
44
|
+
}
|
|
45
|
+
const lastEventId = ctx.query["last-event-id"] ?? ctx.query.lastEventId;
|
|
46
|
+
const stream = subscribeSandboxSse(sessionId, lastEventId);
|
|
47
|
+
ctx.status = 200;
|
|
48
|
+
ctx.set("Content-Type", "text/event-stream; charset=utf-8");
|
|
49
|
+
ctx.set("Cache-Control", "no-cache, no-transform");
|
|
50
|
+
ctx.set("Connection", "keep-alive");
|
|
51
|
+
ctx.set("X-Accel-Buffering", "no");
|
|
52
|
+
ctx.body = stream;
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
registerFetchRoute(table, "POST", messagePath, async (ctx: RouterContext) => {
|
|
56
|
+
const sessionId = resolveSessionId(ctx);
|
|
57
|
+
if (!sessionId) {
|
|
58
|
+
ctx.status = 400;
|
|
59
|
+
ctx.body = { success: false, error: "Missing session (X-Sandbox-Session or body.session)" };
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const adapter = getAdapter();
|
|
63
|
+
if (!adapter.hasSseSession(sessionId)) {
|
|
64
|
+
ctx.status = 404;
|
|
65
|
+
ctx.body = { success: false, error: "No sandbox session; open GET /sandbox/events first" };
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const body = ctx.request.body;
|
|
69
|
+
const raw = typeof body === "string"
|
|
70
|
+
? body
|
|
71
|
+
: body === undefined || body === null
|
|
72
|
+
? ""
|
|
73
|
+
: JSON.stringify(body);
|
|
74
|
+
if (!raw) {
|
|
75
|
+
ctx.status = 400;
|
|
76
|
+
ctx.body = { success: false, error: "Empty message body" };
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
adapter.ingestSseClientMessage(sessionId, raw);
|
|
81
|
+
ctx.body = { success: true };
|
|
82
|
+
} catch (err) {
|
|
83
|
+
ctx.status = 500;
|
|
84
|
+
ctx.body = { success: false, error: (err as Error).message };
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
package/src/fetch-ws.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { registerWebSocketRoute, type RouteTable } from "@zhin.js/http-host/edge";
|
|
2
|
+
import type { SandboxWsHostAdapter, SandboxWsSocket } from "./sandbox-ws.js";
|
|
3
|
+
|
|
4
|
+
export type RegisterSandboxWsOptions = {
|
|
5
|
+
/** 兼容旧路径,默认 `/ws` */
|
|
6
|
+
legacyPaths?: string[];
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Deno / Edge:在 {@link RouteTable} 上注册 `/sandbox` WebSocket(http-host Fetch upgrade)。
|
|
11
|
+
*/
|
|
12
|
+
export function registerSandboxWebSocketRoutes(
|
|
13
|
+
table: RouteTable,
|
|
14
|
+
getAdapter: () => SandboxWsHostAdapter,
|
|
15
|
+
options: RegisterSandboxWsOptions = {},
|
|
16
|
+
): void {
|
|
17
|
+
const paths = ["/sandbox", ...(options.legacyPaths ?? ["/ws"])];
|
|
18
|
+
for (const path of paths) {
|
|
19
|
+
registerWebSocketRoute(table, path, (ws: unknown) => {
|
|
20
|
+
getAdapter().acceptWebSocket(ws as SandboxWsSocket);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|