@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.
@@ -0,0 +1,11 @@
1
+ import { type RouteTable } from "@zhin.js/http-host/edge";
2
+ import type { SandboxWsHostAdapter } from "./sandbox-ws.js";
3
+ export type RegisterSandboxWsOptions = {
4
+ /** 兼容旧路径,默认 `/ws` */
5
+ legacyPaths?: string[];
6
+ };
7
+ /**
8
+ * Deno / Edge:在 {@link RouteTable} 上注册 `/sandbox` WebSocket(http-host Fetch upgrade)。
9
+ */
10
+ export declare function registerSandboxWebSocketRoutes(table: RouteTable, getAdapter: () => SandboxWsHostAdapter, options?: RegisterSandboxWsOptions): void;
11
+ //# sourceMappingURL=fetch-ws.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-ws.d.ts","sourceRoot":"","sources":["../src/fetch-ws.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,KAAK,EAAE,oBAAoB,EAAmB,MAAM,iBAAiB,CAAC;AAE7E,MAAM,MAAM,wBAAwB,GAAG;IACrC,qBAAqB;IACrB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AAEF;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,MAAM,oBAAoB,EACtC,OAAO,GAAE,wBAA6B,GACrC,IAAI,CAON"}
@@ -0,0 +1,13 @@
1
+ import { registerWebSocketRoute } from "@zhin.js/http-host/edge";
2
+ /**
3
+ * Deno / Edge:在 {@link RouteTable} 上注册 `/sandbox` WebSocket(http-host Fetch upgrade)。
4
+ */
5
+ export function registerSandboxWebSocketRoutes(table, getAdapter, options = {}) {
6
+ const paths = ["/sandbox", ...(options.legacyPaths ?? ["/ws"])];
7
+ for (const path of paths) {
8
+ registerWebSocketRoute(table, path, (ws) => {
9
+ getAdapter().acceptWebSocket(ws);
10
+ });
11
+ }
12
+ }
13
+ //# sourceMappingURL=fetch-ws.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-ws.js","sourceRoot":"","sources":["../src/fetch-ws.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAmB,MAAM,yBAAyB,CAAC;AAQlF;;GAEG;AACH,MAAM,UAAU,8BAA8B,CAC5C,KAAiB,EACjB,UAAsC,EACtC,UAAoC,EAAE;IAEtC,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,sBAAsB,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,EAAW,EAAE,EAAE;YAClD,UAAU,EAAE,CAAC,eAAe,CAAC,EAAqB,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
package/lib/index.d.ts CHANGED
@@ -1,56 +1,24 @@
1
- import { EventEmitter } from "events";
2
- import { Bot, Adapter, Message, SendOptions, MessageType, MessageElement, Plugin } from "zhin.js";
3
- import type { WebSocket } from "ws";
4
- import { Router } from "@zhin.js/http";
5
- import { PageManager } from "@zhin.js/console";
6
- export interface SandboxConfig {
7
- context: "sandbox";
8
- ws: WebSocket;
9
- name: string;
10
- /** 发言者即为 owner(沙箱模式) */
11
- owner?: string;
12
- }
1
+ import { usePlugin } from "zhin.js";
2
+ import { SandboxWsHostAdapter } from "./sandbox-ws.js";
3
+ type SandboxRouter = {
4
+ ws: (path: string) => NonNullable<SandboxAdapter["wss"]>;
5
+ };
13
6
  declare module "zhin.js" {
14
- namespace Plugin {
15
- interface Contexts {
16
- router: Router;
17
- web: PageManager;
18
- }
19
- }
20
7
  interface Adapters {
21
8
  sandbox: SandboxAdapter;
22
9
  }
23
10
  }
24
- export declare class SandboxBot extends EventEmitter implements Bot<SandboxConfig, {
25
- content: MessageElement[];
26
- ts: number;
27
- }> {
28
- adapter: SandboxAdapter;
29
- $config: SandboxConfig;
30
- $connected: boolean;
31
- get $id(): string;
32
- private logger;
33
- constructor(adapter: SandboxAdapter, $config: SandboxConfig);
34
- $connect(): Promise<void>;
35
- $disconnect(): Promise<void>;
36
- $formatMessage({ content, type, id, ts }: {
37
- content: MessageElement[];
38
- id: string;
39
- type: MessageType;
40
- ts: number;
41
- }): Message<{
42
- content: MessageElement[];
43
- ts: number;
44
- }>;
45
- $sendMessage(options: SendOptions): Promise<string>;
46
- $recallMessage(id: string): Promise<void>;
47
- }
48
- declare class SandboxAdapter extends Adapter<SandboxBot> {
49
- wss?: ReturnType<Router["ws"]>;
50
- constructor(plugin: Plugin);
51
- createBot(config: SandboxConfig): SandboxBot;
11
+ /** Node:`Router.ws`;Deno/Edge:`registerSandboxWebSocketRoutes`(http-host) */
12
+ export declare class SandboxAdapter extends SandboxWsHostAdapter {
13
+ wss?: {
14
+ on: (ev: string, fn: (...args: unknown[]) => void) => void;
15
+ close: () => void;
16
+ };
17
+ constructor(plugin: ReturnType<typeof usePlugin>);
52
18
  start(): Promise<void>;
53
- setupWebSocket(router: Router): Promise<void>;
19
+ setupWebSocket(router: SandboxRouter): Promise<void>;
54
20
  }
55
- export {};
21
+ export { registerSandboxWebSocketRoutes, type RegisterSandboxWsOptions, } from "./fetch-ws.js";
22
+ export { registerSandboxSseRoutes, type RegisterSandboxSseOptions, } from "./fetch-sse.js";
23
+ export { SandboxWsBot, SandboxWsHostAdapter, resolveSandboxBot, bindSandboxWsSocket, parseSandboxWsPayload, type ResolvedSandboxBot, type SandboxTransport, type SandboxWsConfig, type SandboxWsSocket, } from "./sandbox-ws.js";
56
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EACL,GAAG,EACH,OAAO,EAEP,OAAO,EACP,WAAW,EAGX,WAAW,EACX,cAAc,EACd,MAAM,EACP,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,SAAS,CAAC;IACnB,EAAE,EAAE,SAAS,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,MAAM,CAAC;QACf,UAAU,QAAQ;YAChB,MAAM,EAAE,MAAM,CAAC;YACf,GAAG,EAAE,WAAW,CAAC;SAClB;KACF;IAED,UAAU,QAAQ;QAChB,OAAO,EAAE,cAAc,CAAC;KACzB;CACF;AAYD,qBAAa,UAAW,SAAQ,YAAa,YAAW,GAAG,CAAC,aAAa,EAAE;IAAE,OAAO,EAAE,cAAc,EAAE,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;IAShG,OAAO,EAAE,cAAc;IAAS,OAAO,EAAE,aAAa;IARzE,UAAU,EAAE,OAAO,CAAS;IAE5B,IAAI,GAAG,WAEN;IAED,OAAO,CAAC,MAAM,CAAU;gBAEL,OAAO,EAAE,cAAc,EAAS,OAAO,EAAE,aAAa;IAqBnE,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAKlC,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;QAAE,OAAO,EAAE,cAAc,EAAE,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE;;;;IAsC5G,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAenD,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGhD;AAED,cAAM,cAAe,SAAQ,OAAO,CAAC,UAAU,CAAC;IAC9C,GAAG,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;gBAEnB,MAAM,EAAE,MAAM;IAI1B,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU;IAOtC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAkCpD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAe,MAAM,SAAS,CAAC;AAEjD,OAAO,EACL,oBAAoB,EAGrB,MAAM,iBAAiB,CAAC;AAGzB,KAAK,aAAa,GAAG;IACnB,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;CAC1D,CAAC;AAEF,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,QAAQ;QAChB,OAAO,EAAE,cAAc,CAAC;KACzB;CACF;AAKD,6EAA6E;AAC7E,qBAAa,cAAe,SAAQ,oBAAoB;IACtD,GAAG,CAAC,EAAE;QAAE,EAAE,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;gBAE5E,MAAM,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC;IAKjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ/B,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CAsB3D;AAkCD,OAAO,EACL,8BAA8B,EAC9B,KAAK,wBAAwB,GAC9B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,wBAAwB,EACxB,KAAK,yBAAyB,GAC/B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,GACrB,MAAM,iBAAiB,CAAC"}
package/lib/index.js CHANGED
@@ -1,170 +1,60 @@
1
- import { EventEmitter } from "events";
2
- import { Adapter, usePlugin, Message, segment, } from "zhin.js";
3
- import path from "path";
1
+ import path from "node:path";
2
+ import { usePlugin } from "zhin.js";
3
+ import { SandboxWsHostAdapter, resolveSandboxBot, } from "./sandbox-ws.js";
4
4
  const plugin = usePlugin();
5
5
  const logger = plugin.logger;
6
- export class SandboxBot extends EventEmitter {
7
- adapter;
8
- $config;
9
- $connected = false;
10
- get $id() {
11
- return this.$config.name;
12
- }
13
- logger = logger;
14
- constructor(adapter, $config) {
15
- super();
16
- this.adapter = adapter;
17
- this.$config = $config;
18
- this.$config.ws.on("message", (data) => {
19
- const message = JSON.parse(data.toString());
20
- // 确保 content 是 MessageElement[] 格式
21
- const content = typeof message.content === 'string'
22
- ? [{ type: 'text', data: { text: message.content } }]
23
- : message.content;
24
- this.logger.debug(`${this.$config.name} recv ${message.type}(${message.id}):${segment.raw(content)}`);
25
- const formattedMessage = this.$formatMessage({ content: content, type: message.type, id: message.id, ts: message.timestamp });
26
- this.adapter.emit("message.receive", formattedMessage);
27
- });
28
- this.$config.ws.on("close", () => {
29
- this.logger.debug(`Sandbox bot ${this.$config.name} disconnected`);
30
- this.$connected = false;
31
- // 从 adapter 中移除 bot
32
- this.adapter.bots.delete(this.$id);
33
- });
34
- }
35
- async $connect() {
36
- this.$connected = true;
37
- }
38
- async $disconnect() {
39
- this.$config.ws.close();
40
- this.$connected = false;
41
- }
42
- $formatMessage({ content, type, id, ts }) {
43
- // 沙箱模式:发言者即为 owner
44
- if (!this.$config.owner)
45
- this.$config.owner = id;
46
- const message = Message.from({ content, ts }, {
47
- $id: `${ts}`,
48
- $adapter: "sandbox",
49
- $bot: `${this.$config.name}`,
50
- $sender: {
51
- id: `${id}`,
52
- name: `mock`,
53
- },
54
- $channel: {
55
- id: `${id}`,
56
- type: type,
57
- },
58
- $content: content,
59
- $raw: segment.raw(content),
60
- $timestamp: ts,
61
- $recall: async () => {
62
- await this.$recallMessage(message.$id);
63
- },
64
- $reply: async (content, quote) => {
65
- if (!Array.isArray(content))
66
- content = [content];
67
- if (quote)
68
- content.unshift({ type: "reply", data: { id: typeof quote === "boolean" ? message.$id : quote } });
69
- return await this.adapter.sendMessage({
70
- ...message.$channel,
71
- context: "sandbox",
72
- bot: `${this.$config.name}`,
73
- content,
74
- });
75
- },
76
- });
77
- return message;
78
- }
79
- async $sendMessage(options) {
80
- if (!this.$connected)
81
- return "";
82
- this.logger.debug(`${this.$config.name} send ${options.type}(${options.id}):${segment.raw(options.content)}`);
83
- options.bot = this.$config.name;
84
- options.context = "sandbox";
85
- this.$config.ws.send(JSON.stringify({
86
- ...options,
87
- content: options.content, // 发送消息段数组
88
- timestamp: Date.now(),
89
- }));
90
- return "";
91
- }
92
- async $recallMessage(id) {
93
- // 沙盒不支持撤回消息
94
- }
95
- }
96
- class SandboxAdapter extends Adapter {
6
+ /** Node:`Router.ws`;Deno/Edge:`registerSandboxWebSocketRoutes`(http-host) */
7
+ export class SandboxAdapter extends SandboxWsHostAdapter {
97
8
  wss;
98
9
  constructor(plugin) {
99
- super(plugin, "sandbox", []);
100
- }
101
- createBot(config) {
102
- const bot = new SandboxBot(this, config);
103
- // 将 bot 添加到 bots Map 中
104
- this.bots.set(bot.$id, bot);
105
- return bot;
10
+ const appConfig = (plugin.inject("config")?.getPrimary() ?? {});
11
+ super(plugin, resolveSandboxBot(appConfig));
106
12
  }
107
13
  async start() {
108
- // start 方法会在 mounted 时被调用
109
- // WebSocket server 的创建在 useContext("router") 中处理
14
+ await super.start();
15
+ this.registerConfiguredPlaceholder();
16
+ logger.debug(`Sandbox placeholder: ${this.defaults.name} (offline until /sandbox WS)`);
110
17
  }
111
18
  async setupWebSocket(router) {
112
19
  if (this.wss)
113
- return; // 已经设置过了
114
- // 创建 WebSocket server
20
+ return;
115
21
  this.wss = router.ws("/sandbox");
116
- this.wss.on("connection", (ws, req) => {
117
- // 为每个连接创建一个唯一的 bot 名称
118
- const botName = `sandbox-${Math.random().toString(36).slice(2, 9)}`;
119
- logger.debug(`New sandbox connection: ${botName} from ${req.socket.remoteAddress}`);
120
- // 创建 bot 配置
121
- const config = {
122
- context: "sandbox",
123
- ws,
124
- name: botName,
125
- };
126
- // 创建并连接 bot
127
- const bot = this.createBot(config);
128
- bot.$connect();
129
- // WebSocket 关闭时清理
22
+ this.wss.on("connection", (...args) => {
23
+ const ws = args[0];
24
+ const req = args[1];
25
+ logger.debug(`New sandbox connection from ${req.socket?.remoteAddress ?? "unknown"}`);
26
+ const bot = this.acceptWebSocket(ws);
130
27
  ws.on("close", () => {
131
- logger.debug(`Sandbox connection closed: ${botName}`);
28
+ logger.debug(`Sandbox connection closed: ${bot.$config.name}`);
132
29
  this.bots.delete(bot.$id);
133
30
  });
134
31
  ws.on("error", (error) => {
135
- logger.error(`Sandbox WebSocket error for ${botName}:`, error);
32
+ logger.error(`Sandbox WebSocket error for ${bot.$config.name}:`, error);
136
33
  });
137
34
  });
138
- logger.debug("Sandbox WebSocket server started at /sandbox");
35
+ logger.debug("Sandbox WebSocket server started at /sandbox (Node Router.ws)");
139
36
  }
140
37
  }
141
38
  const { provide } = usePlugin();
142
39
  provide({
143
40
  name: "sandbox",
144
- description: "Sandbox Adapter",
41
+ description: "Sandbox Adapter — Node Router.ws + Deno http-host WebSocket",
145
42
  mounted: async (p) => {
146
43
  const adapter = new SandboxAdapter(p);
147
44
  await adapter.start();
148
45
  return adapter;
149
46
  },
150
47
  dispose: async (adapter) => {
151
- // 关闭所有 bot 连接
152
48
  for (const bot of adapter.bots.values()) {
153
49
  await bot.$disconnect();
154
50
  }
155
- // 关闭 WebSocket server
156
51
  adapter.wss?.close();
157
52
  await adapter.stop();
158
53
  },
159
54
  });
160
- // 使用 router 上下文创建 WebSocket server
161
- plugin.useContext("router", async (router) => {
162
- // 等待 sandbox adapter 就绪
163
- plugin.useContext("sandbox", async (adapter) => {
164
- await adapter.setupWebSocket(router);
165
- });
55
+ plugin.useContext("router", 'sandbox', async (router, adapter) => {
56
+ await adapter.setupWebSocket(router);
166
57
  });
167
- // 使用 web 上下文注册客户端入口
168
58
  plugin.useContext("web", (pageManager) => {
169
59
  pageManager.addEntry({
170
60
  id: "sandbox",
@@ -173,4 +63,7 @@ plugin.useContext("web", (pageManager) => {
173
63
  meta: { name: "Sandbox" },
174
64
  });
175
65
  });
66
+ export { registerSandboxWebSocketRoutes, } from "./fetch-ws.js";
67
+ export { registerSandboxSseRoutes, } from "./fetch-sse.js";
68
+ export { SandboxWsBot, SandboxWsHostAdapter, resolveSandboxBot, bindSandboxWsSocket, parseSandboxWsPayload, } from "./sandbox-ws.js";
176
69
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 按 session 隔离的 Sandbox SSE 推送(Edge / Vercel 等无 WebSocket 入站时使用)。
3
+ * SSE `data` 字段为与 WebSocket 相同的 JSON 字符串。
4
+ */
5
+ export declare function broadcastSandboxSse(sessionId: string, jsonPayload: string): void;
6
+ export declare function subscribeSandboxSse(sessionId: string, lastEventId?: string): ReadableStream<Uint8Array>;
7
+ export declare function closeSandboxSseSession(sessionId: string): void;
8
+ /** @internal */
9
+ export declare function resetSandboxSseHubForTests(): void;
10
+ //# sourceMappingURL=sandbox-sse-hub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-sse-hub.d.ts","sourceRoot":"","sources":["../src/sandbox-sse-hub.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAqCH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAYhF;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,MAAM,GACnB,cAAc,CAAC,UAAU,CAAC,CA8C5B;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAM9D;AAED,gBAAgB;AAChB,wBAAgB,0BAA0B,IAAI,IAAI,CAGjD"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * 按 session 隔离的 Sandbox SSE 推送(Edge / Vercel 等无 WebSocket 入站时使用)。
3
+ * SSE `data` 字段为与 WebSocket 相同的 JSON 字符串。
4
+ */
5
+ const MAX_REPLAY = 100;
6
+ const sessions = new Map();
7
+ function getSession(sessionId) {
8
+ let s = sessions.get(sessionId);
9
+ if (!s) {
10
+ s = { subscribers: new Map(), history: [], nextSubId: 0, nextEventId: 0 };
11
+ sessions.set(sessionId, s);
12
+ }
13
+ return s;
14
+ }
15
+ function formatSse(data, id) {
16
+ const lines = [];
17
+ if (id)
18
+ lines.push(`id: ${id}`);
19
+ lines.push(`data: ${data}`);
20
+ lines.push("");
21
+ return lines.join("\n") + "\n";
22
+ }
23
+ export function broadcastSandboxSse(sessionId, jsonPayload) {
24
+ const session = getSession(sessionId);
25
+ const stored = {
26
+ id: String(++session.nextEventId),
27
+ data: jsonPayload,
28
+ };
29
+ session.history.push(stored);
30
+ if (session.history.length > MAX_REPLAY)
31
+ session.history.shift();
32
+ const chunk = formatSse(stored.data, stored.id);
33
+ for (const sub of session.subscribers.values()) {
34
+ sub.enqueue(chunk);
35
+ }
36
+ }
37
+ export function subscribeSandboxSse(sessionId, lastEventId) {
38
+ const session = getSession(sessionId);
39
+ const encoder = new TextEncoder();
40
+ const replayFrom = lastEventId ? Number.parseInt(lastEventId, 10) : 0;
41
+ const subId = `sse-${++session.nextSubId}`;
42
+ return new ReadableStream({
43
+ start(controller) {
44
+ for (const ev of session.history) {
45
+ if (Number(ev.id) > replayFrom) {
46
+ controller.enqueue(encoder.encode(formatSse(ev.data, ev.id)));
47
+ }
48
+ }
49
+ const interval = setInterval(() => {
50
+ try {
51
+ controller.enqueue(encoder.encode(": heartbeat\n\n"));
52
+ }
53
+ catch {
54
+ clearInterval(interval);
55
+ }
56
+ }, 15000);
57
+ session.subscribers.set(subId, {
58
+ id: subId,
59
+ enqueue: (chunk) => {
60
+ try {
61
+ controller.enqueue(encoder.encode(chunk));
62
+ }
63
+ catch {
64
+ /* closed */
65
+ }
66
+ },
67
+ close: () => {
68
+ clearInterval(interval);
69
+ try {
70
+ controller.close();
71
+ }
72
+ catch {
73
+ /* */
74
+ }
75
+ },
76
+ });
77
+ },
78
+ cancel() {
79
+ const s = sessions.get(sessionId);
80
+ const sub = s?.subscribers.get(subId);
81
+ sub?.close();
82
+ s?.subscribers.delete(subId);
83
+ },
84
+ });
85
+ }
86
+ export function closeSandboxSseSession(sessionId) {
87
+ const session = sessions.get(sessionId);
88
+ if (!session)
89
+ return;
90
+ for (const sub of session.subscribers.values())
91
+ sub.close();
92
+ session.subscribers.clear();
93
+ sessions.delete(sessionId);
94
+ }
95
+ /** @internal */
96
+ export function resetSandboxSseHubForTests() {
97
+ for (const id of [...sessions.keys()])
98
+ closeSandboxSseSession(id);
99
+ sessions.clear();
100
+ }
101
+ //# sourceMappingURL=sandbox-sse-hub.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-sse-hub.js","sourceRoot":"","sources":["../src/sandbox-sse-hub.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Sandbox 传输 — Node WebSocket;Edge HTTP+SSE(见 sandbox-sse-hub / fetch-sse)。
3
+ */
4
+ import { EventEmitter } from "node:events";
5
+ import { Adapter, Bot, Message, type MessageElement, type MessageType, type Plugin, type SendOptions } from "zhin.js";
6
+ export interface SandboxWsConfig {
7
+ context: "sandbox";
8
+ ws?: SandboxWsSocket;
9
+ name: string;
10
+ owner?: string;
11
+ /** yaml 预置名:启动时占位,WS 连接前在 bot:list 显示为离线 */
12
+ offline?: boolean;
13
+ }
14
+ /** 无 WS 时的占位 socket(仅用于 bot:list,不可收发) */
15
+ export declare function createOfflineSandboxWs(): SandboxWsSocket;
16
+ export declare function createSandboxSseTransport(sessionId: string, onClose?: () => void): SandboxWsSocket & {
17
+ sessionId: string;
18
+ };
19
+ /** 兼容 `ws` 包与标准 WebSocket */
20
+ export type SandboxWsSocket = {
21
+ send(data: string): void;
22
+ close(code?: number, reason?: string): void;
23
+ on?(event: "message" | "close" | "error", listener: (...args: unknown[]) => void): void;
24
+ off?(event: "message" | "close" | "error", listener: (...args: unknown[]) => void): void;
25
+ addEventListener?(type: "message" | "close" | "error", listener: (ev: Event | MessageEvent | CloseEvent) => void): void;
26
+ removeEventListener?(type: "message" | "close" | "error", listener: (ev: Event | MessageEvent | CloseEvent) => void): void;
27
+ };
28
+ export type SandboxBotDefaults = {
29
+ name: string;
30
+ owner: string;
31
+ /** true:每连接随机 bot 名(Node 本地默认);false:固定 name(Edge 单实例) */
32
+ randomNamePerConnection?: boolean;
33
+ };
34
+ export type SandboxTransport = "websocket" | "http-sse";
35
+ export type ResolvedSandboxBot = {
36
+ context: "sandbox";
37
+ name: string;
38
+ owner: string;
39
+ randomNamePerConnection: boolean;
40
+ transport: SandboxTransport;
41
+ };
42
+ export declare function resolveSandboxBot(appConfig: Record<string, unknown>): ResolvedSandboxBot;
43
+ export declare function bindSandboxWsSocket(ws: SandboxWsSocket, handlers: {
44
+ onMessage: (raw: string) => void;
45
+ onClose: () => void;
46
+ onError?: (err: unknown) => void;
47
+ }): () => void;
48
+ export declare function parseSandboxWsPayload(raw: string): {
49
+ type: MessageType;
50
+ id: string;
51
+ content: MessageElement[];
52
+ timestamp: number;
53
+ };
54
+ type BotEvent = {
55
+ content: MessageElement[];
56
+ type: MessageType;
57
+ id: string;
58
+ ts: number;
59
+ };
60
+ export declare class SandboxWsBot extends EventEmitter implements Bot<SandboxWsConfig, BotEvent> {
61
+ #private;
62
+ adapter: SandboxWsHostAdapter;
63
+ $config: SandboxWsConfig;
64
+ $connected: boolean;
65
+ get $id(): string;
66
+ constructor(adapter: SandboxWsHostAdapter, $config: SandboxWsConfig);
67
+ $connect(): Promise<void>;
68
+ $disconnect(): Promise<void>;
69
+ $formatMessage({ content, type, id, ts }: BotEvent): Message<BotEvent>;
70
+ $sendMessage(options: SendOptions): Promise<string>;
71
+ $recallMessage(_id: string): Promise<void>;
72
+ }
73
+ export declare class SandboxWsHostAdapter extends Adapter<SandboxWsBot> {
74
+ #private;
75
+ protected readonly defaults: ResolvedSandboxBot;
76
+ constructor(plugin: Plugin, defaults: ResolvedSandboxBot);
77
+ get transport(): SandboxTransport;
78
+ hasSseSession(sessionId: string): boolean;
79
+ getBotBySseSession(sessionId: string): SandboxWsBot | undefined;
80
+ createBot(config: SandboxWsConfig): SandboxWsBot;
81
+ /** `zhin.config.yml` 中 `context: sandbox` + 固定 `name` 时,启动即出现在 bot:list(离线) */
82
+ registerConfiguredPlaceholder(): void;
83
+ /** Edge / 外部 upgrade:注入已建立的 WebSocket */
84
+ acceptWebSocket(ws: SandboxWsSocket, overrides?: Partial<Pick<SandboxWsConfig, "name" | "owner">>): SandboxWsBot;
85
+ /** Edge SSE:建立会话并绑定固定 bot */
86
+ acceptSseSession(sessionId: string, overrides?: Partial<Pick<SandboxWsConfig, "name" | "owner">>): SandboxWsBot;
87
+ /** POST /sandbox/message — 与 WebSocket 帧同格式的 JSON 字符串 */
88
+ ingestSseClientMessage(sessionId: string, raw: string): void;
89
+ }
90
+ export {};
91
+ //# sourceMappingURL=sandbox-ws.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-ws.d.ts","sourceRoot":"","sources":["../src/sandbox-ws.ts"],"names":[],"mappings":"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"}