@zhin.js/adapter-sandbox 3.0.11 → 4.0.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/CHANGELOG.md +19 -4
- package/README.md +4 -4
- package/client/Sandbox.tsx +10 -12
- package/client/sandboxTransport.ts +19 -3
- package/dist/index.js +7 -8
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +9 -9
- package/lib/index.js.map +1 -1
- package/lib/sandbox-ws.d.ts +12 -11
- package/lib/sandbox-ws.d.ts.map +1 -1
- package/lib/sandbox-ws.js +22 -21
- package/lib/sandbox-ws.js.map +1 -1
- package/package.json +12 -6
- package/src/index.ts +10 -10
- package/src/sandbox-ws.ts +30 -28
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
# @zhin.js/adapter-process
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 4.0.1
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
- d8def69: fix: 性能优化
|
|
8
|
+
- 2ef4896: fix: 更新概念 Bot=>Endpoint,已适配后续更多的业务场景;统一角色权限
|
|
9
|
+
- Updated dependencies [d8def69]
|
|
10
|
+
- Updated dependencies [2ef4896]
|
|
11
|
+
- @zhin.js/host-router@1.0.1
|
|
12
|
+
- @zhin.js/host-api@1.0.1
|
|
13
|
+
- @zhin.js/core@1.2.1
|
|
14
|
+
- @zhin.js/client@2.0.3
|
|
15
|
+
|
|
16
|
+
## 4.0.0
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies [65f4b0a]
|
|
21
|
+
- Updated dependencies [e62c23a]
|
|
22
|
+
- @zhin.js/core@1.2.0
|
|
23
|
+
- @zhin.js/host-api@1.0.0
|
|
24
|
+
- @zhin.js/host-router@1.0.0
|
|
10
25
|
|
|
11
26
|
## 3.0.10
|
|
12
27
|
|
package/README.md
CHANGED
|
@@ -26,11 +26,11 @@ Sandbox 适配器需要以下服务插件:
|
|
|
26
26
|
|
|
27
27
|
## 配置
|
|
28
28
|
|
|
29
|
-
**推荐(与 [minimal-bot](../../../examples/minimal-bot/) 一致)**:`
|
|
29
|
+
**推荐(与 [minimal-bot](../../../examples/minimal-bot/) 一致)**:`endpoints: []`,在 Remote Console 打开「沙盒」页时经 `/sandbox` WebSocket **自动创建** bot(如 `sandbox-xxxx`),无需在 yaml 里写 `context: sandbox`。
|
|
30
30
|
|
|
31
31
|
```yaml
|
|
32
32
|
# zhin.config.yml
|
|
33
|
-
|
|
33
|
+
endpoints: []
|
|
34
34
|
|
|
35
35
|
plugins:
|
|
36
36
|
- "@zhin.js/adapter-sandbox"
|
|
@@ -41,14 +41,14 @@ plugins:
|
|
|
41
41
|
可选:若需在启动时即在 bot 列表显示**固定名称**的离线占位 bot,可显式配置:
|
|
42
42
|
|
|
43
43
|
```yaml
|
|
44
|
-
|
|
44
|
+
endpoints:
|
|
45
45
|
- context: sandbox
|
|
46
46
|
name: sandbox-bot
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
## 使用方式
|
|
50
50
|
|
|
51
|
-
1.
|
|
51
|
+
1. 启动 Zhin 实例:`pnpm dev`(终端会打印 Host 地址,一般为 `http://127.0.0.1:8086`)
|
|
52
52
|
2. 打开 **[Remote Console](https://console.zhin.dev)**,API Base 与 Host 地址一致,Token 与 `http.token` / `HTTP_TOKEN` 一致
|
|
53
53
|
3. 在 Console **沙盒** 页连接后发送消息进行测试
|
|
54
54
|
|
package/client/Sandbox.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React, { useState, useEffect, useRef } from 'react';
|
|
2
2
|
import { MessageSegment, cn, resolveMediaSrc, pickMediaRawUrl } from '@zhin.js/client';
|
|
3
3
|
import {
|
|
4
|
-
|
|
4
|
+
buildSandboxWebSocketUrl,
|
|
5
5
|
} from './sandboxTransport';
|
|
6
|
-
import { User, Users, Trash2, Send, Hash, MessageSquare, Wifi, WifiOff, Smile, Image, X, Check, Info, Search,
|
|
6
|
+
import { User, Users, Trash2, Send, Hash, MessageSquare, Wifi, WifiOff, Smile, Image, X, Check, Info, Search, Endpoint, UserPlus, Bell, Video, Music } from 'lucide-react';
|
|
7
7
|
import RichTextEditor, { RichTextEditorRef } from './RichTextEditor';
|
|
8
8
|
|
|
9
9
|
interface Message {
|
|
@@ -25,7 +25,7 @@ export default function Sandbox() {
|
|
|
25
25
|
const [faceList, setFaceList] = useState<Face[]>([])
|
|
26
26
|
const [activeChannel, setActiveChannel] = useState<Channel>(channels[0])
|
|
27
27
|
const [inputText, setInputText] = useState('')
|
|
28
|
-
const [
|
|
28
|
+
const [endpointName, setBotName] = useState('ProcessEndpoint')
|
|
29
29
|
const [connected, setConnected] = useState(false)
|
|
30
30
|
const [showFacePicker, setShowFacePicker] = useState(false)
|
|
31
31
|
/** 输入区:插入图片 / 视频 / 音频 URL */
|
|
@@ -56,14 +56,14 @@ export default function Sandbox() {
|
|
|
56
56
|
useEffect(() => { fetchFaceList() }, [])
|
|
57
57
|
|
|
58
58
|
const handleInboundPayload = (data: {
|
|
59
|
-
type: string; id: string; content?: unknown;
|
|
59
|
+
type: string; id: string; content?: unknown; endpoint?: string; timestamp: number
|
|
60
60
|
}) => {
|
|
61
61
|
const content: MessageSegment[] = typeof data.content === 'string'
|
|
62
62
|
? parseTextToSegments(data.content)
|
|
63
63
|
: Array.isArray(data.content) ? data.content as MessageSegment[] : parseTextToSegments(String(data.content ?? ''))
|
|
64
64
|
|
|
65
65
|
const channelName = data.type === 'private'
|
|
66
|
-
? `私聊-${data.bot ||
|
|
66
|
+
? `私聊-${data.bot || endpointName}`
|
|
67
67
|
: data.type === 'group'
|
|
68
68
|
? `群组-${data.id}`
|
|
69
69
|
: `频道-${data.id}`
|
|
@@ -78,16 +78,14 @@ export default function Sandbox() {
|
|
|
78
78
|
|
|
79
79
|
setMessages((prev) => [...prev, {
|
|
80
80
|
id: `bot_${data.timestamp}`, type: 'received', channelType,
|
|
81
|
-
channelId: data.id, channelName, senderId: '
|
|
82
|
-
senderName: data.bot ||
|
|
81
|
+
channelId: data.id, channelName, senderId: 'endpoint',
|
|
82
|
+
senderName: data.bot || endpointName, content, timestamp: data.timestamp,
|
|
83
83
|
}])
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
useEffect(() => {
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
wsUrl.protocol = wsUrl.protocol === 'https:' ? 'wss:' : 'ws:'
|
|
90
|
-
wsRef.current = new WebSocket(wsUrl.href)
|
|
87
|
+
const wsUrl = buildSandboxWebSocketUrl()
|
|
88
|
+
wsRef.current = new WebSocket(wsUrl)
|
|
91
89
|
wsRef.current.onopen = () => setConnected(true)
|
|
92
90
|
wsRef.current.onmessage = (event) => {
|
|
93
91
|
try { handleInboundPayload(JSON.parse(event.data)) }
|
|
@@ -350,7 +348,7 @@ export default function Sandbox() {
|
|
|
350
348
|
</span>
|
|
351
349
|
</div>
|
|
352
350
|
<div className="flex items-center gap-2">
|
|
353
|
-
<input value={
|
|
351
|
+
<input value={endpointName} onChange={(e) => setBotName(e.target.value)} placeholder="机器人名称"
|
|
354
352
|
className="h-8 w-28 rounded-md border bg-transparent px-2 text-sm" />
|
|
355
353
|
<button className="inline-flex items-center gap-1 h-8 px-3 rounded-md bg-secondary text-secondary-foreground text-sm hover:bg-secondary/80" onClick={clearMessages}>
|
|
356
354
|
<Trash2 size={14} /> 清空
|
|
@@ -3,10 +3,26 @@ export function getSandboxApiBase(): string {
|
|
|
3
3
|
return (stored ? stored.replace(/\/$/, "") : null) ?? window.location.origin;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
export function
|
|
7
|
-
|
|
6
|
+
export function getSandboxBearerToken(): string {
|
|
7
|
+
return (
|
|
8
|
+
localStorage.getItem("zhin_api_token")?.trim() ||
|
|
8
9
|
localStorage.getItem("HTTP_TOKEN")?.trim() ||
|
|
9
10
|
localStorage.getItem("zhin_http_token")?.trim() ||
|
|
10
|
-
""
|
|
11
|
+
""
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getSandboxAuthHeaders(): Record<string, string> {
|
|
16
|
+
const token = getSandboxBearerToken();
|
|
11
17
|
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
12
18
|
}
|
|
19
|
+
|
|
20
|
+
/** Browser WebSocket cannot set Authorization reliably; pass token in query when needed. */
|
|
21
|
+
export function buildSandboxWebSocketUrl(base?: string): string {
|
|
22
|
+
const apiBase = (base ?? getSandboxApiBase()).replace(/\/$/, "");
|
|
23
|
+
const wsUrl = new URL("/sandbox", `${apiBase}/`);
|
|
24
|
+
wsUrl.protocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
|
|
25
|
+
const token = getSandboxBearerToken();
|
|
26
|
+
if (token) wsUrl.searchParams.set("token", token);
|
|
27
|
+
return wsUrl.href;
|
|
28
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
`)}return{text:d,segments:t}},U=d=>{if(!
|
|
3
|
-
`)){
|
|
4
|
-
`).map((F,P)=>o(
|
|
5
|
-
`).length-1&&a("br",{})]},P))},
|
|
6
|
-
`).map((F,P)=>o(
|
|
7
|
-
`).length-1&&a("br",{})]},P))},f);case"at":return o("span",{className:"inline-flex items-center px-1.5 py-0.5 rounded bg-accent text-accent-foreground text-xs mx-0.5",children:["@",String(h.name??h.qq??"")]},f);case"face":return a("img",{src:`https://face.viki.moe/apng/${h.id}.png`,alt:"",className:"w-6 h-6 inline-block align-middle mx-0.5"},f);case"image":{let F=ye(h),P=Pe(F,"image");return P?a("a",{href:P,target:"_blank",rel:"noreferrer",className:"block my-1",children:a("img",{src:P,alt:"",className:A("max-w-[min(320px,88vw)] rounded-lg block",L,"ring-offset-0"),onError:aa=>{aa.target.style.display="none"}})},f):a("span",{className:"text-xs opacity-70",children:"[\u56FE\u7247]"},f)}case"video":{let F=ye(h),P=Pe(F,"video");return P?a("video",{src:P,controls:!0,playsInline:!0,preload:"metadata",className:A("max-w-[min(360px,92vw)] max-h-72 rounded-lg my-1 bg-black/10",L)},f):a("span",{className:"text-xs opacity-70",children:"[\u89C6\u9891\u65E0\u5730\u5740]"},f)}case"audio":case"record":{let F=ye(h),P=Pe(F,"audio");return P?a("audio",{src:P,controls:!0,preload:"metadata",className:A("w-full max-w-sm my-2 h-10",r&&"opacity-95")},f):a("span",{className:"text-xs opacity-70",children:"[\u97F3\u9891\u65E0\u5730\u5740]"},f)}case"file":return o("span",{className:"inline-flex items-center px-1.5 py-0.5 rounded border text-xs mx-0.5",children:["\u{1F4CE} ",String(h.name||"\u6587\u4EF6")]},f);default:return o("span",{className:"text-xs opacity-70",children:["[",x.type,"]"]},f)}})},Fe=(e,r)=>{if(!Be(r))return;let L={id:`msg_${Date.now()}`,type:"sent",channelType:g.type,channelId:g.id,channelName:g.name,senderId:"test_user",senderName:"\u6D4B\u8BD5\u7528\u6237",content:r,timestamp:Date.now()};m(f=>[...f,L]),B(""),v([]),q.current?.clear();let x=JSON.stringify({type:g.type,id:g.id,content:r,timestamp:Date.now()});z.current?.send(x)},_e=()=>{confirm("\u786E\u5B9A\u6E05\u7A7A\u6240\u6709\u6D88\u606F\u8BB0\u5F55\uFF1F")&&m([])},Qe=e=>{ge("chat"),p(e),I(r=>r.map(L=>L.id===e.id?{...L,unread:0}:L)),window.innerWidth<768&&T(!1)},Je=()=>{let e=["private","group","channel"],r=e[Math.floor(Math.random()*e.length)],L=prompt("\u8BF7\u8F93\u5165\u9891\u9053\u540D\u79F0\uFF1A");if(L){let x={id:`${r}_${Date.now()}`,name:L,type:r,unread:0};I(f=>[...f,x]),p(x)}},De=e=>{switch(e){case"private":return a(Z,{size:16});case"group":return a(fe,{size:16});case"channel":return a(te,{size:16});default:return a(O,{size:16})}},je=e=>{q.current?.insertFace(e),M(!1)},be=()=>{let e=$.trim();!e||!k||(k==="image"?q.current?.insertImage(e):k==="video"?q.current?.insertVideo(e):q.current?.insertAudio(e),me(""),W(null))},ba=()=>{l.trim()&&(q.current?.insertAt(l.trim()),n(""),Ce(!1))},$e=e=>{q.current?.replaceAtTrigger(e.name,e.id),Q(null),t("")},Ye=(e,r,L)=>{if(g.type==="private"){Q(null),t("");return}e&&L?(Q(L),t(r)):(Q(null),t(""))},Re=y.filter(e=>{if(!d.trim())return!0;let r=d.toLowerCase();return e.name.toLowerCase().includes(r)||e.id.toLowerCase().includes(r)}),ea=(e,r)=>{B(e),v(r)},ve=N.filter(e=>e.name.toLowerCase().includes(u.toLowerCase())||e.describe.toLowerCase().includes(u.toLowerCase())),Se=i.filter(e=>e.channelId===g.id);return o("div",{className:"sandbox-container rounded-xl border border-border/70 bg-card/30 shadow-sm",children:[o("button",{className:"mobile-channel-toggle md:hidden",onClick:()=>T(!b),children:[a(O,{size:20})," \u9891\u9053\u5217\u8868"]}),o("div",{className:A("channel-sidebar rounded-lg border bg-card",b&&"show"),children:[a("div",{className:"p-3 border-b",children:o("div",{className:"flex justify-between items-center",children:[o("div",{className:"flex items-center gap-2",children:[a("div",{className:"p-1 rounded-md bg-secondary",children:a(O,{size:16,className:"text-muted-foreground"})}),a("h3",{className:"font-semibold",children:"\u9891\u9053\u5217\u8868"})]}),o("span",{className:A("inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium border",E?"bg-emerald-100 text-emerald-800 border-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400 dark:border-emerald-800":"bg-muted text-muted-foreground"),children:[E?a(ne,{size:12}):a(ce,{size:12}),E?"\u5DF2\u8FDE\u63A5":"\u672A\u8FDE\u63A5"]})]})}),o("div",{className:"flex-1 overflow-y-auto p-2 space-y-1",children:[w.map(e=>{let r=J==="chat"&&g.id===e.id;return o("div",{className:A("menu-item",r&&"active"),onClick:()=>Qe(e),children:[a("span",{className:"shrink-0",children:De(e.type)}),o("div",{className:"flex-1 min-w-0",children:[a("div",{className:"text-sm font-medium truncate",children:e.name}),a("div",{className:"text-xs text-muted-foreground",children:e.type==="private"?"\u79C1\u804A":e.type==="group"?"\u7FA4\u804A":"\u9891\u9053"})]}),e.unread>0&&a("span",{className:"inline-flex items-center justify-center h-5 min-w-5 rounded-full bg-destructive text-destructive-foreground text-[10px] font-medium px-1",children:e.unread})]},e.id)}),o("div",{className:"pt-2 mt-2 border-t space-y-1",children:[o("div",{className:A("menu-item",J==="requests"&&"active"),onClick:()=>{ge("requests"),window.innerWidth<768&&T(!1)},children:[a(K,{size:16,className:"shrink-0"}),o("div",{className:"flex-1 min-w-0",children:[a("div",{className:"text-sm font-medium",children:"\u8BF7\u6C42"}),a("div",{className:"text-xs text-muted-foreground",children:"\u597D\u53CB/\u7FA4\u9080\u8BF7\u7B49"})]})]}),o("div",{className:A("menu-item",J==="notices"&&"active"),onClick:()=>{ge("notices"),window.innerWidth<768&&T(!1)},children:[a(X,{size:16,className:"shrink-0"}),o("div",{className:"flex-1 min-w-0",children:[a("div",{className:"text-sm font-medium",children:"\u901A\u77E5"}),a("div",{className:"text-xs text-muted-foreground",children:"\u7FA4\u7BA1/\u64A4\u56DE\u7B49"})]})]})]})]}),a("div",{className:"p-2 border-t",children:a("button",{className:"w-full py-2 px-3 rounded-md border border-dashed text-sm text-muted-foreground hover:bg-accent transition-colors",onClick:Je,children:"+ \u6DFB\u52A0\u9891\u9053"})})]}),b&&a("div",{className:"channel-overlay md:hidden",onClick:()=>T(!1)}),o("div",{className:"chat-area",children:[J==="requests"&&o("div",{className:"rounded-lg border bg-card flex-1 flex flex-col min-h-0 overflow-hidden",children:[a("div",{className:"p-3 border-b flex-shrink-0",children:o("h2",{className:"text-lg font-bold flex items-center gap-2",children:[a(K,{size:20})," \u8BF7\u6C42"]})}),o("div",{className:"flex-1 overflow-y-auto p-4 flex flex-col items-center justify-center gap-3 text-muted-foreground text-center",children:[a(K,{size:48,className:"opacity-30"}),a("span",{children:"\u6C99\u76D2\u4E3A\u6A21\u62DF\u73AF\u5883\uFF0C\u6682\u65E0\u8BF7\u6C42\u6570\u636E"}),o("span",{className:"text-sm",children:["\u5B9E\u9645\u597D\u53CB/\u7FA4\u9080\u8BF7\u7B49\u8BF7\u6C42\u8BF7\u5230\u4FA7\u8FB9\u680F ",a("strong",{children:"\u673A\u5668\u4EBA"})," \u9875\u9762\u8FDB\u5165\u5BF9\u5E94\u673A\u5668\u4EBA\u7BA1\u7406\u67E5\u770B"]})]})]}),J==="notices"&&o("div",{className:"rounded-lg border bg-card flex-1 flex flex-col min-h-0 overflow-hidden",children:[a("div",{className:"p-3 border-b flex-shrink-0",children:o("h2",{className:"text-lg font-bold flex items-center gap-2",children:[a(X,{size:20})," \u901A\u77E5"]})}),o("div",{className:"flex-1 overflow-y-auto p-4 flex flex-col items-center justify-center gap-3 text-muted-foreground text-center",children:[a(X,{size:48,className:"opacity-30"}),a("span",{children:"\u6C99\u76D2\u4E3A\u6A21\u62DF\u73AF\u5883\uFF0C\u6682\u65E0\u901A\u77E5\u6570\u636E"}),o("span",{className:"text-sm",children:["\u5B9E\u9645\u7FA4\u7BA1\u3001\u64A4\u56DE\u7B49\u901A\u77E5\u8BF7\u5230\u4FA7\u8FB9\u680F ",a("strong",{children:"\u673A\u5668\u4EBA"})," \u9875\u9762\u8FDB\u5165\u5BF9\u5E94\u673A\u5668\u4EBA\u7BA1\u7406\u67E5\u770B"]})]})]}),J==="chat"&&o(Da,{children:[a("div",{className:"rounded-lg border bg-card p-3 flex-shrink-0",children:o("div",{className:"flex justify-between items-center flex-wrap gap-2",children:[o("div",{className:"flex items-center gap-3",children:[a("div",{className:"p-2 rounded-lg bg-secondary",children:De(g.type)}),o("div",{children:[a("h2",{className:"text-lg font-bold",children:g.name}),o("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[a("span",{children:g.id}),a("span",{className:"inline-flex items-center px-1.5 py-0.5 rounded border text-[10px]",children:Se.length}),a("span",{children:"\u6761\u6D88\u606F"})]})]}),a("span",{className:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-secondary text-secondary-foreground",children:g.type==="private"?"\u79C1\u804A":g.type==="group"?"\u7FA4\u804A":"\u9891\u9053"})]}),o("div",{className:"flex items-center gap-2",children:[a("input",{value:U,onChange:e=>_(e.target.value),placeholder:"\u673A\u5668\u4EBA\u540D\u79F0",className:"h-8 w-28 rounded-md border bg-transparent px-2 text-sm"}),o("button",{className:"inline-flex items-center gap-1 h-8 px-3 rounded-md bg-secondary text-secondary-foreground text-sm hover:bg-secondary/80",onClick:_e,children:[a(se,{size:14})," \u6E05\u7A7A"]})]})]})}),a("div",{className:"rounded-lg border bg-card flex-1 flex flex-col min-h-0",children:a("div",{className:"flex-1 overflow-y-auto p-4",children:Se.length===0?o("div",{className:"flex flex-col items-center justify-center h-full gap-3",children:[a(O,{size:64,className:"text-muted-foreground/20"}),a("span",{className:"text-muted-foreground",children:"\u6682\u65E0\u6D88\u606F\uFF0C\u5F00\u59CB\u5BF9\u8BDD\u5427\uFF01"})]}):o("div",{className:"space-y-2",children:[Se.map(e=>a("div",{className:A("flex",e.type==="sent"?"justify-end":"justify-start"),children:o("div",{className:A("max-w-[70%] p-3 rounded-2xl",e.type==="sent"?"bg-primary text-primary-foreground":"bg-muted"),children:[o("div",{className:"flex items-center gap-2 mb-1",children:[e.type==="received"&&a(ee,{size:14}),e.type==="sent"&&a(Z,{size:14}),a("span",{className:"text-xs font-medium opacity-90",children:e.senderName}),a("span",{className:"text-xs opacity-70",children:new Date(e.timestamp).toLocaleTimeString()})]}),a("div",{className:"text-sm space-y-1",children:Ze(e.content,e.type==="sent")})]})},e.id)),a("div",{ref:Me})]})})}),o("div",{className:"rounded-lg border bg-card p-3 flex-shrink-0 space-y-3",children:[o("div",{className:"flex gap-2 items-center flex-wrap",children:[a("button",{type:"button",className:A("h-8 w-8 rounded-md flex items-center justify-center border transition-colors",H?"bg-primary text-primary-foreground":"hover:bg-accent"),onClick:()=>{M(!H),W(null)},title:"\u63D2\u5165\u8868\u60C5",children:a(re,{size:16})}),a("button",{type:"button",className:A("h-8 w-8 rounded-md flex items-center justify-center border transition-colors",k==="image"?"bg-primary text-primary-foreground":"hover:bg-accent"),onClick:()=>{W(e=>e==="image"?null:"image"),M(!1)},title:"\u63D2\u5165\u56FE\u7247 URL",children:a(oe,{size:16})}),a("button",{type:"button",className:A("h-8 w-8 rounded-md flex items-center justify-center border transition-colors",k==="video"?"bg-primary text-primary-foreground":"hover:bg-accent"),onClick:()=>{W(e=>e==="video"?null:"video"),M(!1)},title:"\u63D2\u5165\u89C6\u9891 URL",children:a(ie,{size:16})}),a("button",{type:"button",className:A("h-8 w-8 rounded-md flex items-center justify-center border transition-colors",k==="audio"?"bg-primary text-primary-foreground":"hover:bg-accent"),onClick:()=>{W(e=>e==="audio"?null:"audio"),M(!1)},title:"\u63D2\u5165\u97F3\u9891 URL",children:a(ue,{size:16})}),a("div",{className:"flex-1 min-w-[1rem]"}),S&&a("button",{className:"h-8 w-8 rounded-md flex items-center justify-center hover:bg-accent transition-colors",onClick:()=>{B(""),v([])},children:a(pe,{size:16})})]}),H&&o("div",{className:"p-3 rounded-md border bg-muted/30 max-h-64 overflow-y-auto space-y-2",children:[a("input",{value:u,onChange:e=>c(e.target.value),placeholder:"\u641C\u7D22\u8868\u60C5...",className:"w-full h-8 rounded-md border bg-transparent px-2 text-sm"}),a("div",{className:"grid grid-cols-8 gap-1",children:ve.slice(0,80).map(e=>a("button",{onClick:()=>je(e.id),title:e.name,className:"w-10 h-10 rounded-md border flex items-center justify-center hover:bg-accent transition-colors",children:a("img",{src:`https://face.viki.moe/apng/${e.id}.png`,alt:e.name,className:"w-8 h-8"})},e.id))}),ve.length===0&&o("div",{className:"flex flex-col items-center gap-2 py-4",children:[a(j,{size:32,className:"text-muted-foreground/30"}),a("span",{className:"text-sm text-muted-foreground",children:"\u672A\u627E\u5230\u5339\u914D\u7684\u8868\u60C5"})]})]}),k&&o("div",{className:"p-3 rounded-md border bg-muted/30 space-y-2",children:[o("p",{className:"text-xs text-muted-foreground",children:[k==="image"&&"\u652F\u6301 http(s) \u56FE\u7247\u94FE\u63A5\u6216 data URL",k==="video"&&"\u652F\u6301\u6D4F\u89C8\u5668\u53EF\u89E3\u7801\u7684\u89C6\u9891\u76F4\u94FE\uFF08\u5982 .mp4\u3001.webm\uFF09",k==="audio"&&"\u652F\u6301 .mp3\u3001.ogg\u3001.wav \u7B49\u97F3\u9891\u76F4\u94FE"]}),a("input",{value:$,onChange:e=>me(e.target.value),placeholder:k==="image"?"\u56FE\u7247 URL\u2026":k==="video"?"\u89C6\u9891 URL\u2026":"\u97F3\u9891 URL\u2026",className:"w-full h-8 rounded-md border border-input bg-background px-2 text-sm",onKeyDown:e=>{e.key==="Enter"&&(e.preventDefault(),be())}}),o("button",{type:"button",className:"inline-flex items-center gap-1 h-8 px-3 rounded-md bg-primary text-primary-foreground text-sm disabled:opacity-50",onClick:be,disabled:!$.trim(),children:[a(ae,{size:14})," \u63D2\u5165\u5230\u8F93\u5165\u6846"]})]}),o("div",{className:"flex gap-2 items-start",children:[o("div",{className:"flex-1 relative",children:[a(Ve,{ref:q,placeholder:`\u5411 ${g.name} \u53D1\u9001\u6D88\u606F...`,onSend:Fe,onChange:ea,onAtTrigger:Ye,minHeight:"44px",maxHeight:"200px"}),Y&&a("div",{className:"absolute z-50 rounded-lg border bg-popover shadow-md min-w-60 max-h-72 overflow-y-auto p-1",style:{top:`${Y.top}px`,left:`${Y.left}px`},children:Re.length>0?Re.map(e=>o("div",{className:"flex items-center gap-2 p-2 rounded-md cursor-pointer hover:bg-accent transition-colors",onClick:()=>$e(e),children:[a(Z,{size:16,className:"text-muted-foreground"}),o("div",{className:"flex-1",children:[a("div",{className:"text-sm font-medium",children:e.name}),o("div",{className:"text-xs text-muted-foreground",children:["ID: ",e.id]})]})]},e.id)):o("div",{className:"flex flex-col items-center gap-2 p-4",children:[a(j,{size:20,className:"text-muted-foreground/50"}),a("span",{className:"text-xs text-muted-foreground",children:"\u672A\u627E\u5230\u5339\u914D\u7684\u7528\u6237"})]})})]}),o("button",{className:"inline-flex items-center gap-1.5 h-10 px-4 rounded-md bg-primary text-primary-foreground text-sm font-medium disabled:opacity-50 transition-colors hover:bg-primary/90",onClick:()=>{let e=q.current?.getContent();e&&Fe(e.text,e.segments)},disabled:!Be(V),children:[a(le,{size:16})," \u53D1\u9001"]})]}),o("div",{className:"flex items-center gap-2 flex-wrap text-xs text-muted-foreground",children:[a(de,{size:12})," \u5FEB\u6377\u64CD\u4F5C:",a("span",{className:"px-1 py-0.5 rounded border text-[10px]",children:"Enter"})," \u53D1\u9001",a("span",{className:"px-1 py-0.5 rounded border text-[10px]",children:"Shift+Enter"})," \u6362\u884C",a("span",{className:"px-1 py-0.5 rounded border text-[10px]",children:"[@\u540D\u79F0]"})," @\u67D0\u4EBA",a("span",{className:"px-1 py-0.5 rounded border text-[10px]",children:"[video:URL]"}),a("span",{className:"px-1 py-0.5 rounded border text-[10px]",children:"[audio:URL]"})]})]})]})]})]})}function So(i){i.addRoute({path:"/console/sandbox",name:"\u6C99\u76D2",element:i.React.createElement(Ae,{hostReact:i.React})}),i.addTool({id:"sandbox",name:"\u6C99\u76D2",path:"/console/sandbox"})}export{So as register};
|
|
1
|
+
import Ve,{useState as g,useEffect as xe,useRef as ke}from"react";import{cn as A,resolveMediaSrc as we,pickMediaRawUrl as Pe}from"@zhin.js/client";function aa(){let i=localStorage.getItem("zhin_api_base")?.trim();return(i?i.replace(/\/$/,""):null)??window.location.origin}function ta(){return localStorage.getItem("zhin_api_token")?.trim()||localStorage.getItem("HTTP_TOKEN")?.trim()||localStorage.getItem("zhin_http_token")?.trim()||""}function ve(i){let p=(i??aa()).replace(/\/$/,""),I=new URL("/sandbox",`${p}/`);I.protocol=I.protocol==="https:"?"wss:":"ws:";let L=ta();return L&&I.searchParams.set("token",L),I.href}import{forwardRef as ra,createElement as sa}from"react";var me=(...i)=>i.filter((p,I,L)=>!!p&&p.trim()!==""&&L.indexOf(p)===I).join(" ").trim();var Te=i=>i.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();var qe=i=>i.replace(/^([A-Z])|[\s-_]+(\w)/g,(p,I,L)=>L?L.toUpperCase():I.toLowerCase());var Se=i=>{let p=qe(i);return p.charAt(0).toUpperCase()+p.slice(1)};import{forwardRef as la,createElement as Oe}from"react";var Le={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};var Ue=i=>{for(let p in i)if(p.startsWith("aria-")||p==="role"||p==="title")return!0;return!1};import{createContext as oa,useContext as da,useMemo as Ga,createElement as Wa}from"react";var ua=oa({});var He=()=>da(ua);var Ne=la(({color:i,size:p,strokeWidth:I,absoluteStrokeWidth:L,className:N="",children:D,iconNode:h,...m},k)=>{let{size:B=24,strokeWidth:U=2,absoluteStrokeWidth:_=!1,color:E="currentColor",className:G=""}=He()??{},H=L??_?Number(I??U)*24/Number(p??B):I??U;return Oe("svg",{ref:k,...Le,width:p??B??Le.width,height:p??B??Le.height,stroke:i??E,strokeWidth:H,className:me("lucide",G,N),...!D&&!Ue(m)&&{"aria-hidden":"true"},...m},[...h.map(([M,w])=>Oe(M,w)),...Array.isArray(D)?D:[D]])});var f=(i,p)=>{let I=ra(({className:L,...N},D)=>sa(Ne,{ref:D,iconNode:p,className:me(`lucide-${Te(Se(i))}`,`lucide-${i}`,L),...N}));return I.displayName=Se(i),I};var fa=[["path",{d:"M10.268 21a2 2 0 0 0 3.464 0",key:"vwvbt9"}],["path",{d:"M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326",key:"11g9vi"}]],X=f("bell",fa);var ia=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],ee=f("check",ia);var ca=[["line",{x1:"4",x2:"20",y1:"9",y2:"9",key:"4lhtct"}],["line",{x1:"4",x2:"20",y1:"15",y2:"15",key:"vyu0kd"}],["line",{x1:"10",x2:"8",y1:"3",y2:"21",key:"1ggp8o"}],["line",{x1:"16",x2:"14",y1:"3",y2:"21",key:"weycgp"}]],ae=f("hash",ca);var na=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2",key:"1m3agn"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}]],te=f("image",na);var pa=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]],oe=f("info",pa);var ma=[["path",{d:"M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z",key:"18887p"}]],O=f("message-square",ma);var La=[["path",{d:"M9 18V5l12-2v13",key:"1jmyc2"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}],["circle",{cx:"18",cy:"16",r:"3",key:"1hluhg"}]],de=f("music",La);var xa=[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]],j=f("search",xa);var Ia=[["path",{d:"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z",key:"1ffxy3"}],["path",{d:"m21.854 2.147-10.94 10.939",key:"12cjpa"}]],ue=f("send",Ia);var Ca=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M8 14s1.5 2 4 2 4-2 4-2",key:"1y1vjs"}],["line",{x1:"9",x2:"9.01",y1:"9",y2:"9",key:"yxxnd0"}],["line",{x1:"15",x2:"15.01",y1:"9",y2:"9",key:"1p4y9e"}]],le=f("smile",Ca);var ga=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],re=f("trash-2",ga);var ha=[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["line",{x1:"19",x2:"19",y1:"8",y2:"14",key:"1bvyxn"}],["line",{x1:"22",x2:"16",y1:"11",y2:"11",key:"1shjgl"}]],K=f("user-plus",ha);var Sa=[["path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2",key:"975kel"}],["circle",{cx:"12",cy:"7",r:"4",key:"17ys0d"}]],Z=f("user",Sa);var ka=[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["path",{d:"M16 3.128a4 4 0 0 1 0 7.744",key:"16gr8j"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}]],se=f("users",ka);var wa=[["path",{d:"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5",key:"ftymec"}],["rect",{x:"2",y:"6",width:"14",height:"12",rx:"2",key:"158x01"}]],fe=f("video",wa);var Pa=[["path",{d:"M12 20h.01",key:"zekei9"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0",key:"1bycff"}],["path",{d:"M5 12.859a10 10 0 0 1 5.17-2.69",key:"1dl1wf"}],["path",{d:"M19 12.859a10 10 0 0 0-2.007-1.523",key:"4k23kn"}],["path",{d:"M2 8.82a15 15 0 0 1 4.177-2.643",key:"1grhjp"}],["path",{d:"M22 8.82a15 15 0 0 0-11.288-3.764",key:"z3jwby"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]],ie=f("wifi-off",Pa);var ya=[["path",{d:"M12 20h.01",key:"zekei9"}],["path",{d:"M2 8.82a15 15 0 0 1 20 0",key:"dnpr2z"}],["path",{d:"M5 12.859a10 10 0 0 1 14 0",key:"1x1e6c"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0",key:"1bycff"}]],ce=f("wifi",ya);var Aa=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],ne=f("x",Aa);import{useRef as Ee,forwardRef as Ma,useImperativeHandle as Ba}from"react";import{jsx as Fa}from"react/jsx-runtime";var Ge=Ma(({placeholder:i="\u8F93\u5165\u6D88\u606F...",onSend:p,onChange:I,onAtTrigger:L,minHeight:N="44px",maxHeight:D="200px"},h)=>{let m=Ee(null),k=Ee(null),B=()=>{if(!m.current)return{text:"",segments:[]};let d="",t=[],u=Array.from(m.current.childNodes);for(let c of u)if(c.nodeType===Node.TEXT_NODE){let l=c.textContent||"";l&&(d+=l,t.push({type:"text",data:{text:l}}))}else if(c.nodeType===Node.ELEMENT_NODE){let l=c;if(l.classList.contains("editor-face")){let n=l.dataset.id;d+=`[face:${n}]`,t.push({type:"face",data:{id:Number(n)}})}else if(l.classList.contains("editor-image")){let n=l.dataset.url;d+=`[image:${n}]`,t.push({type:"image",data:{url:n}})}else if(l.classList.contains("editor-video")){let n=l.dataset.url||"";d+=`[video:${n}]`,t.push({type:"video",data:{url:n}})}else if(l.classList.contains("editor-audio")){let n=l.dataset.url||"";d+=`[audio:${n}]`,t.push({type:"audio",data:{url:n}})}else if(l.classList.contains("editor-at")){let n=l.dataset.name,y=l.dataset.id;d+=`[@${n}]`,t.push({type:"at",data:{name:n,qq:y}})}else l.tagName==="BR"&&(d+=`
|
|
2
|
+
`)}return{text:d,segments:t}},U=d=>{if(!m.current)return;let t=document.createElement("img");t.src=`https://face.viki.moe/apng/${d}.png`,t.alt=`[face:${d}]`,t.dataset.type="face",t.dataset.id=String(d),t.className="editor-face",M(t),R()},_=d=>{if(!m.current||!d.trim())return;let t=document.createElement("img");t.src=d.trim(),t.alt=`[image:${d.trim()}]`,t.dataset.type="image",t.dataset.url=d.trim(),t.className="editor-image",M(t),R()},E=d=>{if(!m.current||!d.trim())return;let t=d.trim(),u=document.createElement("span");u.className="editor-video",u.dataset.url=t,u.contentEditable="false",u.textContent="\u{1F4F9} \u89C6\u9891",M(u),R()},G=d=>{if(!m.current||!d.trim())return;let t=d.trim(),u=document.createElement("span");u.className="editor-audio",u.dataset.url=t,u.contentEditable="false",u.textContent="\u{1F3B5} \u97F3\u9891",M(u),R()},H=(d,t)=>{if(!m.current||!d.trim())return;let u=document.createElement("span");u.dataset.type="at",u.dataset.name=d,t&&(u.dataset.id=t),u.className="editor-at",u.contentEditable="false";let c=document.createElement("span");c.textContent="@",c.className="editor-at-symbol";let l=document.createElement("span");l.textContent=d,l.className="editor-at-name",u.appendChild(c),u.appendChild(l),M(u),R()},M=d=>{if(!m.current)return;m.current.focus();let t=window.getSelection();if(t&&t.rangeCount>0){let u=t.getRangeAt(0);if(m.current.contains(u.commonAncestorContainer))u.deleteContents(),u.insertNode(d),u.collapse(!1),t.removeAllRanges(),t.addRange(u);else{m.current.appendChild(d);let l=document.createRange();l.setStartAfter(d),l.collapse(!0),t.removeAllRanges(),t.addRange(l)}}else{m.current.appendChild(d);let u=window.getSelection();if(u){let c=document.createRange();c.setStartAfter(d),c.collapse(!0),u.removeAllRanges(),u.addRange(c)}}},w=()=>{m.current&&(m.current.innerHTML="",R())},W=()=>{m.current?.focus()},$=()=>B(),pe=()=>{if(!m.current||!L)return;let d=window.getSelection();if(!d||d.rangeCount===0){L(!1,""),k.current=null;return}let t=d.getRangeAt(0);if(!m.current.contains(t.commonAncestorContainer)){L(!1,""),k.current=null;return}let u=t.startContainer;if(u.nodeType!==Node.TEXT_NODE){L(!1,""),k.current=null;return}let c=u,l=c.textContent?.substring(0,t.startOffset)||"",n=l.lastIndexOf("@");if(n!==-1){let y=l.substring(n+1);if(y.includes(" ")||y.includes(`
|
|
3
|
+
`)){L(!1,""),k.current=null;return}k.current=c;let V=document.createRange();V.setStart(c,n),V.setEnd(c,n+1);let v=V.getBoundingClientRect(),b=m.current.getBoundingClientRect();L(!0,y,{top:v.bottom-b.top,left:v.left-b.left})}else L(!1,""),k.current=null},R=()=>{if(pe(),I){let{text:d,segments:t}=B();I(d,t)}},Ie=(d,t)=>{if(!k.current)return;let u=k.current,c=u.textContent||"",l=c.lastIndexOf("@");if(l!==-1){let n=c.substring(l+1),y=l+1+n.split(/[\s\n]/)[0].length,V=c.substring(0,l),v=c.substring(y);u.textContent=V+v;let b=window.getSelection();if(b){let T=document.createRange();T.setStart(u,l),T.collapse(!0),b.removeAllRanges(),b.addRange(T)}}k.current=null,H(d,t)},Y=d=>{d.preventDefault();let t=d.clipboardData,c=Array.from(t.items).find(n=>n.type.startsWith("image/"));if(c){let n=c.getAsFile();if(n){let y=new FileReader;y.onload=()=>{typeof y.result=="string"&&_(y.result)},y.readAsDataURL(n)}return}let l=t.getData("text/plain");l&&(document.execCommand("insertText",!1,l),R())},Q=d=>{if(d.key==="Enter"&&!d.shiftKey&&(d.preventDefault(),p)){let{text:t,segments:u}=B();p(t,u)}};return Ba(h,()=>({focus:W,clear:w,insertFace:U,insertImage:_,insertVideo:E,insertAudio:G,insertAt:H,replaceAtTrigger:Ie,getContent:$})),Fa("div",{ref:m,contentEditable:!0,suppressContentEditableWarning:!0,onInput:R,onKeyDown:Q,onPaste:Y,"data-placeholder":i,className:"rich-text-editor",style:{width:"100%",minHeight:N,maxHeight:D,padding:"0.5rem 0.75rem",border:"1px solid var(--gray-6)",borderRadius:"6px",backgroundColor:"var(--gray-1)",fontSize:"var(--font-size-2)",outline:"none",overflowY:"auto",lineHeight:"1.5",wordWrap:"break-word",color:"var(--gray-12)"}})});Ge.displayName="RichTextEditor";var We=Ge;import{Fragment as Da,jsx as a,jsxs as o}from"react/jsx-runtime";function ye(){let[i,p]=g([]),[I,L]=g([{id:"user_1001",name:"\u6D4B\u8BD5\u7528\u6237",type:"private",unread:0},{id:"group_2001",name:"\u6D4B\u8BD5\u7FA4\u7EC4",type:"group",unread:0},{id:"channel_3001",name:"\u6D4B\u8BD5\u9891\u9053",type:"channel",unread:0}]),[N,D]=g([]),[h,m]=g(I[0]),[k,B]=g(""),[U,_]=g("ProcessEndpoint"),[E,G]=g(!1),[H,M]=g(!1),[w,W]=g(null),[$,pe]=g(""),[R,Ie]=g(!1),[Y,Q]=g(null),[d,t]=g(""),[u,c]=g(""),[l,n]=g(""),[y]=g([{id:"10001",name:"\u5F20\u4E09"},{id:"10002",name:"\u674E\u56DB"},{id:"10003",name:"\u738B\u4E94"},{id:"10004",name:"\u8D75\u516D"},{id:"10005",name:"\u6D4B\u8BD5\u7528\u6237"},{id:"10086",name:"Admin"},{id:"10010",name:"Test User"}]),[V,v]=g([]),[b,T]=g(!1),[J,Ce]=g("chat"),Ae=ke(null),z=ke(null),q=ke(null),ze=async()=>{try{let e=await fetch("https://face.viki.moe/metadata.json");D(await e.json())}catch(e){console.error("[Sandbox] Failed to fetch face list:",e)}};xe(()=>{ze()},[]);let Xe=e=>{let r=typeof e.content=="string"?ge(e.content):Array.isArray(e.content)?e.content:ge(String(e.content??"")),x=e.type==="private"?`\u79C1\u804A-${e.bot||U}`:e.type==="group"?`\u7FA4\u7EC4-${e.id}`:`\u9891\u9053-${e.id}`,C=e.type;L(s=>{if(s.some(F=>F.id===e.id))return s;let S={id:e.id,name:x,type:C,unread:0};return m(S),[...s,S]}),p(s=>[...s,{id:`bot_${e.timestamp}`,type:"received",channelType:C,channelId:e.id,channelName:x,senderId:"endpoint",senderName:e.bot||U,content:r,timestamp:e.timestamp}])};xe(()=>{let e=ve();return z.current=new WebSocket(e),z.current.onopen=()=>G(!0),z.current.onmessage=r=>{try{Xe(JSON.parse(r.data))}catch(x){console.error("[Sandbox] Failed to parse message:",x)}},z.current.onclose=()=>G(!1),()=>{z.current?.close(),z.current=null,G(!1)}},[]),xe(()=>{Ae.current?.scrollIntoView({behavior:"smooth"})},[i]),xe(()=>{v(k.trim()?ge(k):[])},[k]);let ge=e=>{let r=[],x=/\[@([^\]]+)\]|\[face:(\d+)\]|\[image:([^\]]+)\]|\[video:([^\]]+)\]|\[audio:([^\]]+)\]/g,C=0,s;for(;(s=x.exec(e))!==null;){if(s.index>C){let S=e.substring(C,s.index);S&&r.push({type:"text",data:{text:S}})}s[1]?r.push({type:"at",data:{qq:s[1],name:s[1]}}):s[2]?r.push({type:"face",data:{id:parseInt(s[2],10)}}):s[3]?r.push({type:"image",data:{url:s[3]}}):s[4]?r.push({type:"video",data:{url:s[4]}}):s[5]&&r.push({type:"audio",data:{url:s[5]}}),C=x.lastIndex}if(C<e.length){let S=e.substring(C);S&&r.push({type:"text",data:{text:S}})}return r.length>0?r:[{type:"text",data:{text:e}}]},Me=e=>e.length===0?!1:e.some(r=>r.type==="text"?!!String(r.data?.text??"").trim():!0),Ke=(e,r)=>{let x=r?"ring-1 ring-primary-foreground/25":"ring-1 ring-border/60";return e.map((C,s)=>{if(typeof C=="string")return a("span",{children:C.split(`
|
|
4
|
+
`).map((F,P)=>o(Ve.Fragment,{children:[F,P<C.split(`
|
|
5
|
+
`).length-1&&a("br",{})]},P))},s);let S=C.data;switch(C.type){case"text":return a("span",{children:String(S.text??"").split(`
|
|
6
|
+
`).map((F,P)=>o(Ve.Fragment,{children:[F,P<String(S.text??"").split(`
|
|
7
|
+
`).length-1&&a("br",{})]},P))},s);case"at":return o("span",{className:"inline-flex items-center px-1.5 py-0.5 rounded bg-accent text-accent-foreground text-xs mx-0.5",children:["@",String(S.name??S.qq??"")]},s);case"face":return a("img",{src:`https://face.viki.moe/apng/${S.id}.png`,alt:"",className:"w-6 h-6 inline-block align-middle mx-0.5"},s);case"image":{let F=Pe(S),P=we(F,"image");return P?a("a",{href:P,target:"_blank",rel:"noreferrer",className:"block my-1",children:a("img",{src:P,alt:"",className:A("max-w-[min(320px,88vw)] rounded-lg block",x,"ring-offset-0"),onError:ea=>{ea.target.style.display="none"}})},s):a("span",{className:"text-xs opacity-70",children:"[\u56FE\u7247]"},s)}case"video":{let F=Pe(S),P=we(F,"video");return P?a("video",{src:P,controls:!0,playsInline:!0,preload:"metadata",className:A("max-w-[min(360px,92vw)] max-h-72 rounded-lg my-1 bg-black/10",x)},s):a("span",{className:"text-xs opacity-70",children:"[\u89C6\u9891\u65E0\u5730\u5740]"},s)}case"audio":case"record":{let F=Pe(S),P=we(F,"audio");return P?a("audio",{src:P,controls:!0,preload:"metadata",className:A("w-full max-w-sm my-2 h-10",r&&"opacity-95")},s):a("span",{className:"text-xs opacity-70",children:"[\u97F3\u9891\u65E0\u5730\u5740]"},s)}case"file":return o("span",{className:"inline-flex items-center px-1.5 py-0.5 rounded border text-xs mx-0.5",children:["\u{1F4CE} ",String(S.name||"\u6587\u4EF6")]},s);default:return o("span",{className:"text-xs opacity-70",children:["[",C.type,"]"]},s)}})},Be=(e,r)=>{if(!Me(r))return;let x={id:`msg_${Date.now()}`,type:"sent",channelType:h.type,channelId:h.id,channelName:h.name,senderId:"test_user",senderName:"\u6D4B\u8BD5\u7528\u6237",content:r,timestamp:Date.now()};p(s=>[...s,x]),B(""),v([]),q.current?.clear();let C=JSON.stringify({type:h.type,id:h.id,content:r,timestamp:Date.now()});z.current?.send(C)},Ze=()=>{confirm("\u786E\u5B9A\u6E05\u7A7A\u6240\u6709\u6D88\u606F\u8BB0\u5F55\uFF1F")&&p([])},_e=e=>{Ce("chat"),m(e),L(r=>r.map(x=>x.id===e.id?{...x,unread:0}:x)),window.innerWidth<768&&T(!1)},Qe=()=>{let e=["private","group","channel"],r=e[Math.floor(Math.random()*e.length)],x=prompt("\u8BF7\u8F93\u5165\u9891\u9053\u540D\u79F0\uFF1A");if(x){let C={id:`${r}_${Date.now()}`,name:x,type:r,unread:0};L(s=>[...s,C]),m(C)}},Fe=e=>{switch(e){case"private":return a(Z,{size:16});case"group":return a(se,{size:16});case"channel":return a(ae,{size:16});default:return a(O,{size:16})}},Je=e=>{q.current?.insertFace(e),M(!1)},De=()=>{let e=$.trim();!e||!w||(w==="image"?q.current?.insertImage(e):w==="video"?q.current?.insertVideo(e):q.current?.insertAudio(e),pe(""),W(null))},ba=()=>{l.trim()&&(q.current?.insertAt(l.trim()),n(""),Ie(!1))},je=e=>{q.current?.replaceAtTrigger(e.name,e.id),Q(null),t("")},$e=(e,r,x)=>{if(h.type==="private"){Q(null),t("");return}e&&x?(Q(x),t(r)):(Q(null),t(""))},be=y.filter(e=>{if(!d.trim())return!0;let r=d.toLowerCase();return e.name.toLowerCase().includes(r)||e.id.toLowerCase().includes(r)}),Ye=(e,r)=>{B(e),v(r)},Re=N.filter(e=>e.name.toLowerCase().includes(u.toLowerCase())||e.describe.toLowerCase().includes(u.toLowerCase())),he=i.filter(e=>e.channelId===h.id);return o("div",{className:"sandbox-container rounded-xl border border-border/70 bg-card/30 shadow-sm",children:[o("button",{className:"mobile-channel-toggle md:hidden",onClick:()=>T(!b),children:[a(O,{size:20})," \u9891\u9053\u5217\u8868"]}),o("div",{className:A("channel-sidebar rounded-lg border bg-card",b&&"show"),children:[a("div",{className:"p-3 border-b",children:o("div",{className:"flex justify-between items-center",children:[o("div",{className:"flex items-center gap-2",children:[a("div",{className:"p-1 rounded-md bg-secondary",children:a(O,{size:16,className:"text-muted-foreground"})}),a("h3",{className:"font-semibold",children:"\u9891\u9053\u5217\u8868"})]}),o("span",{className:A("inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium border",E?"bg-emerald-100 text-emerald-800 border-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400 dark:border-emerald-800":"bg-muted text-muted-foreground"),children:[E?a(ce,{size:12}):a(ie,{size:12}),E?"\u5DF2\u8FDE\u63A5":"\u672A\u8FDE\u63A5"]})]})}),o("div",{className:"flex-1 overflow-y-auto p-2 space-y-1",children:[I.map(e=>{let r=J==="chat"&&h.id===e.id;return o("div",{className:A("menu-item",r&&"active"),onClick:()=>_e(e),children:[a("span",{className:"shrink-0",children:Fe(e.type)}),o("div",{className:"flex-1 min-w-0",children:[a("div",{className:"text-sm font-medium truncate",children:e.name}),a("div",{className:"text-xs text-muted-foreground",children:e.type==="private"?"\u79C1\u804A":e.type==="group"?"\u7FA4\u804A":"\u9891\u9053"})]}),e.unread>0&&a("span",{className:"inline-flex items-center justify-center h-5 min-w-5 rounded-full bg-destructive text-destructive-foreground text-[10px] font-medium px-1",children:e.unread})]},e.id)}),o("div",{className:"pt-2 mt-2 border-t space-y-1",children:[o("div",{className:A("menu-item",J==="requests"&&"active"),onClick:()=>{Ce("requests"),window.innerWidth<768&&T(!1)},children:[a(K,{size:16,className:"shrink-0"}),o("div",{className:"flex-1 min-w-0",children:[a("div",{className:"text-sm font-medium",children:"\u8BF7\u6C42"}),a("div",{className:"text-xs text-muted-foreground",children:"\u597D\u53CB/\u7FA4\u9080\u8BF7\u7B49"})]})]}),o("div",{className:A("menu-item",J==="notices"&&"active"),onClick:()=>{Ce("notices"),window.innerWidth<768&&T(!1)},children:[a(X,{size:16,className:"shrink-0"}),o("div",{className:"flex-1 min-w-0",children:[a("div",{className:"text-sm font-medium",children:"\u901A\u77E5"}),a("div",{className:"text-xs text-muted-foreground",children:"\u7FA4\u7BA1/\u64A4\u56DE\u7B49"})]})]})]})]}),a("div",{className:"p-2 border-t",children:a("button",{className:"w-full py-2 px-3 rounded-md border border-dashed text-sm text-muted-foreground hover:bg-accent transition-colors",onClick:Qe,children:"+ \u6DFB\u52A0\u9891\u9053"})})]}),b&&a("div",{className:"channel-overlay md:hidden",onClick:()=>T(!1)}),o("div",{className:"chat-area",children:[J==="requests"&&o("div",{className:"rounded-lg border bg-card flex-1 flex flex-col min-h-0 overflow-hidden",children:[a("div",{className:"p-3 border-b flex-shrink-0",children:o("h2",{className:"text-lg font-bold flex items-center gap-2",children:[a(K,{size:20})," \u8BF7\u6C42"]})}),o("div",{className:"flex-1 overflow-y-auto p-4 flex flex-col items-center justify-center gap-3 text-muted-foreground text-center",children:[a(K,{size:48,className:"opacity-30"}),a("span",{children:"\u6C99\u76D2\u4E3A\u6A21\u62DF\u73AF\u5883\uFF0C\u6682\u65E0\u8BF7\u6C42\u6570\u636E"}),o("span",{className:"text-sm",children:["\u5B9E\u9645\u597D\u53CB/\u7FA4\u9080\u8BF7\u7B49\u8BF7\u6C42\u8BF7\u5230\u4FA7\u8FB9\u680F ",a("strong",{children:"\u673A\u5668\u4EBA"})," \u9875\u9762\u8FDB\u5165\u5BF9\u5E94\u673A\u5668\u4EBA\u7BA1\u7406\u67E5\u770B"]})]})]}),J==="notices"&&o("div",{className:"rounded-lg border bg-card flex-1 flex flex-col min-h-0 overflow-hidden",children:[a("div",{className:"p-3 border-b flex-shrink-0",children:o("h2",{className:"text-lg font-bold flex items-center gap-2",children:[a(X,{size:20})," \u901A\u77E5"]})}),o("div",{className:"flex-1 overflow-y-auto p-4 flex flex-col items-center justify-center gap-3 text-muted-foreground text-center",children:[a(X,{size:48,className:"opacity-30"}),a("span",{children:"\u6C99\u76D2\u4E3A\u6A21\u62DF\u73AF\u5883\uFF0C\u6682\u65E0\u901A\u77E5\u6570\u636E"}),o("span",{className:"text-sm",children:["\u5B9E\u9645\u7FA4\u7BA1\u3001\u64A4\u56DE\u7B49\u901A\u77E5\u8BF7\u5230\u4FA7\u8FB9\u680F ",a("strong",{children:"\u673A\u5668\u4EBA"})," \u9875\u9762\u8FDB\u5165\u5BF9\u5E94\u673A\u5668\u4EBA\u7BA1\u7406\u67E5\u770B"]})]})]}),J==="chat"&&o(Da,{children:[a("div",{className:"rounded-lg border bg-card p-3 flex-shrink-0",children:o("div",{className:"flex justify-between items-center flex-wrap gap-2",children:[o("div",{className:"flex items-center gap-3",children:[a("div",{className:"p-2 rounded-lg bg-secondary",children:Fe(h.type)}),o("div",{children:[a("h2",{className:"text-lg font-bold",children:h.name}),o("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[a("span",{children:h.id}),a("span",{className:"inline-flex items-center px-1.5 py-0.5 rounded border text-[10px]",children:he.length}),a("span",{children:"\u6761\u6D88\u606F"})]})]}),a("span",{className:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-secondary text-secondary-foreground",children:h.type==="private"?"\u79C1\u804A":h.type==="group"?"\u7FA4\u804A":"\u9891\u9053"})]}),o("div",{className:"flex items-center gap-2",children:[a("input",{value:U,onChange:e=>_(e.target.value),placeholder:"\u673A\u5668\u4EBA\u540D\u79F0",className:"h-8 w-28 rounded-md border bg-transparent px-2 text-sm"}),o("button",{className:"inline-flex items-center gap-1 h-8 px-3 rounded-md bg-secondary text-secondary-foreground text-sm hover:bg-secondary/80",onClick:Ze,children:[a(re,{size:14})," \u6E05\u7A7A"]})]})]})}),a("div",{className:"rounded-lg border bg-card flex-1 flex flex-col min-h-0",children:a("div",{className:"flex-1 overflow-y-auto p-4",children:he.length===0?o("div",{className:"flex flex-col items-center justify-center h-full gap-3",children:[a(O,{size:64,className:"text-muted-foreground/20"}),a("span",{className:"text-muted-foreground",children:"\u6682\u65E0\u6D88\u606F\uFF0C\u5F00\u59CB\u5BF9\u8BDD\u5427\uFF01"})]}):o("div",{className:"space-y-2",children:[he.map(e=>a("div",{className:A("flex",e.type==="sent"?"justify-end":"justify-start"),children:o("div",{className:A("max-w-[70%] p-3 rounded-2xl",e.type==="sent"?"bg-primary text-primary-foreground":"bg-muted"),children:[o("div",{className:"flex items-center gap-2 mb-1",children:[e.type==="received"&&a(Bot,{size:14}),e.type==="sent"&&a(Z,{size:14}),a("span",{className:"text-xs font-medium opacity-90",children:e.senderName}),a("span",{className:"text-xs opacity-70",children:new Date(e.timestamp).toLocaleTimeString()})]}),a("div",{className:"text-sm space-y-1",children:Ke(e.content,e.type==="sent")})]})},e.id)),a("div",{ref:Ae})]})})}),o("div",{className:"rounded-lg border bg-card p-3 flex-shrink-0 space-y-3",children:[o("div",{className:"flex gap-2 items-center flex-wrap",children:[a("button",{type:"button",className:A("h-8 w-8 rounded-md flex items-center justify-center border transition-colors",H?"bg-primary text-primary-foreground":"hover:bg-accent"),onClick:()=>{M(!H),W(null)},title:"\u63D2\u5165\u8868\u60C5",children:a(le,{size:16})}),a("button",{type:"button",className:A("h-8 w-8 rounded-md flex items-center justify-center border transition-colors",w==="image"?"bg-primary text-primary-foreground":"hover:bg-accent"),onClick:()=>{W(e=>e==="image"?null:"image"),M(!1)},title:"\u63D2\u5165\u56FE\u7247 URL",children:a(te,{size:16})}),a("button",{type:"button",className:A("h-8 w-8 rounded-md flex items-center justify-center border transition-colors",w==="video"?"bg-primary text-primary-foreground":"hover:bg-accent"),onClick:()=>{W(e=>e==="video"?null:"video"),M(!1)},title:"\u63D2\u5165\u89C6\u9891 URL",children:a(fe,{size:16})}),a("button",{type:"button",className:A("h-8 w-8 rounded-md flex items-center justify-center border transition-colors",w==="audio"?"bg-primary text-primary-foreground":"hover:bg-accent"),onClick:()=>{W(e=>e==="audio"?null:"audio"),M(!1)},title:"\u63D2\u5165\u97F3\u9891 URL",children:a(de,{size:16})}),a("div",{className:"flex-1 min-w-[1rem]"}),k&&a("button",{className:"h-8 w-8 rounded-md flex items-center justify-center hover:bg-accent transition-colors",onClick:()=>{B(""),v([])},children:a(ne,{size:16})})]}),H&&o("div",{className:"p-3 rounded-md border bg-muted/30 max-h-64 overflow-y-auto space-y-2",children:[a("input",{value:u,onChange:e=>c(e.target.value),placeholder:"\u641C\u7D22\u8868\u60C5...",className:"w-full h-8 rounded-md border bg-transparent px-2 text-sm"}),a("div",{className:"grid grid-cols-8 gap-1",children:Re.slice(0,80).map(e=>a("button",{onClick:()=>Je(e.id),title:e.name,className:"w-10 h-10 rounded-md border flex items-center justify-center hover:bg-accent transition-colors",children:a("img",{src:`https://face.viki.moe/apng/${e.id}.png`,alt:e.name,className:"w-8 h-8"})},e.id))}),Re.length===0&&o("div",{className:"flex flex-col items-center gap-2 py-4",children:[a(j,{size:32,className:"text-muted-foreground/30"}),a("span",{className:"text-sm text-muted-foreground",children:"\u672A\u627E\u5230\u5339\u914D\u7684\u8868\u60C5"})]})]}),w&&o("div",{className:"p-3 rounded-md border bg-muted/30 space-y-2",children:[o("p",{className:"text-xs text-muted-foreground",children:[w==="image"&&"\u652F\u6301 http(s) \u56FE\u7247\u94FE\u63A5\u6216 data URL",w==="video"&&"\u652F\u6301\u6D4F\u89C8\u5668\u53EF\u89E3\u7801\u7684\u89C6\u9891\u76F4\u94FE\uFF08\u5982 .mp4\u3001.webm\uFF09",w==="audio"&&"\u652F\u6301 .mp3\u3001.ogg\u3001.wav \u7B49\u97F3\u9891\u76F4\u94FE"]}),a("input",{value:$,onChange:e=>pe(e.target.value),placeholder:w==="image"?"\u56FE\u7247 URL\u2026":w==="video"?"\u89C6\u9891 URL\u2026":"\u97F3\u9891 URL\u2026",className:"w-full h-8 rounded-md border border-input bg-background px-2 text-sm",onKeyDown:e=>{e.key==="Enter"&&(e.preventDefault(),De())}}),o("button",{type:"button",className:"inline-flex items-center gap-1 h-8 px-3 rounded-md bg-primary text-primary-foreground text-sm disabled:opacity-50",onClick:De,disabled:!$.trim(),children:[a(ee,{size:14})," \u63D2\u5165\u5230\u8F93\u5165\u6846"]})]}),o("div",{className:"flex gap-2 items-start",children:[o("div",{className:"flex-1 relative",children:[a(We,{ref:q,placeholder:`\u5411 ${h.name} \u53D1\u9001\u6D88\u606F...`,onSend:Be,onChange:Ye,onAtTrigger:$e,minHeight:"44px",maxHeight:"200px"}),Y&&a("div",{className:"absolute z-50 rounded-lg border bg-popover shadow-md min-w-60 max-h-72 overflow-y-auto p-1",style:{top:`${Y.top}px`,left:`${Y.left}px`},children:be.length>0?be.map(e=>o("div",{className:"flex items-center gap-2 p-2 rounded-md cursor-pointer hover:bg-accent transition-colors",onClick:()=>je(e),children:[a(Z,{size:16,className:"text-muted-foreground"}),o("div",{className:"flex-1",children:[a("div",{className:"text-sm font-medium",children:e.name}),o("div",{className:"text-xs text-muted-foreground",children:["ID: ",e.id]})]})]},e.id)):o("div",{className:"flex flex-col items-center gap-2 p-4",children:[a(j,{size:20,className:"text-muted-foreground/50"}),a("span",{className:"text-xs text-muted-foreground",children:"\u672A\u627E\u5230\u5339\u914D\u7684\u7528\u6237"})]})})]}),o("button",{className:"inline-flex items-center gap-1.5 h-10 px-4 rounded-md bg-primary text-primary-foreground text-sm font-medium disabled:opacity-50 transition-colors hover:bg-primary/90",onClick:()=>{let e=q.current?.getContent();e&&Be(e.text,e.segments)},disabled:!Me(V),children:[a(ue,{size:16})," \u53D1\u9001"]})]}),o("div",{className:"flex items-center gap-2 flex-wrap text-xs text-muted-foreground",children:[a(oe,{size:12})," \u5FEB\u6377\u64CD\u4F5C:",a("span",{className:"px-1 py-0.5 rounded border text-[10px]",children:"Enter"})," \u53D1\u9001",a("span",{className:"px-1 py-0.5 rounded border text-[10px]",children:"Shift+Enter"})," \u6362\u884C",a("span",{className:"px-1 py-0.5 rounded border text-[10px]",children:"[@\u540D\u79F0]"})," @\u67D0\u4EBA",a("span",{className:"px-1 py-0.5 rounded border text-[10px]",children:"[video:URL]"}),a("span",{className:"px-1 py-0.5 rounded border text-[10px]",children:"[audio:URL]"})]})]})]})]})]})}function go(i){i.addRoute({path:"/console/sandbox",name:"\u6C99\u76D2",element:i.React.createElement(ye,{hostReact:i.React})}),i.addTool({id:"sandbox",name:"\u6C99\u76D2",path:"/console/sandbox"})}export{go as register};
|
|
8
8
|
/*! Bundled license information:
|
|
9
9
|
|
|
10
10
|
lucide-react/dist/esm/shared/src/utils/mergeClasses.mjs:
|
|
@@ -17,7 +17,6 @@ lucide-react/dist/esm/context.mjs:
|
|
|
17
17
|
lucide-react/dist/esm/Icon.mjs:
|
|
18
18
|
lucide-react/dist/esm/createLucideIcon.mjs:
|
|
19
19
|
lucide-react/dist/esm/icons/bell.mjs:
|
|
20
|
-
lucide-react/dist/esm/icons/bot.mjs:
|
|
21
20
|
lucide-react/dist/esm/icons/check.mjs:
|
|
22
21
|
lucide-react/dist/esm/icons/hash.mjs:
|
|
23
22
|
lucide-react/dist/esm/icons/image.mjs:
|
package/lib/index.d.ts
CHANGED
|
@@ -18,5 +18,5 @@ export declare class SandboxAdapter extends SandboxWsHostAdapter {
|
|
|
18
18
|
start(): Promise<void>;
|
|
19
19
|
setupWebSocket(router: SandboxRouter): Promise<void>;
|
|
20
20
|
}
|
|
21
|
-
export {
|
|
21
|
+
export { SandboxWsEndpoint, SandboxWsHostAdapter, resolveSandboxEndpoint, bindSandboxWsSocket, parseSandboxWsPayload, type ResolvedSandboxBot, type SandboxWsConfig, type SandboxWsSocket, } from "./sandbox-ws.js";
|
|
22
22
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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,uBAAuB;AACvB,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,
|
|
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,uBAAuB;AACvB,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,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,eAAe,GACrB,MAAM,iBAAiB,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { usePlugin } from "zhin.js";
|
|
3
|
-
import { SandboxWsHostAdapter,
|
|
3
|
+
import { SandboxWsHostAdapter, resolveSandboxEndpoint, } from "./sandbox-ws.js";
|
|
4
4
|
const plugin = usePlugin();
|
|
5
5
|
const logger = plugin.logger;
|
|
6
6
|
/** Node:`Router.ws` */
|
|
@@ -8,7 +8,7 @@ export class SandboxAdapter extends SandboxWsHostAdapter {
|
|
|
8
8
|
wss;
|
|
9
9
|
constructor(plugin) {
|
|
10
10
|
const appConfig = (plugin.inject("config")?.getPrimary() ?? {});
|
|
11
|
-
super(plugin,
|
|
11
|
+
super(plugin, resolveSandboxEndpoint(appConfig));
|
|
12
12
|
}
|
|
13
13
|
async start() {
|
|
14
14
|
await super.start();
|
|
@@ -23,13 +23,13 @@ export class SandboxAdapter extends SandboxWsHostAdapter {
|
|
|
23
23
|
const ws = args[0];
|
|
24
24
|
const req = args[1];
|
|
25
25
|
logger.debug(`New sandbox connection from ${req.socket?.remoteAddress ?? "unknown"}`);
|
|
26
|
-
const
|
|
26
|
+
const endpoint = this.acceptWebSocket(ws);
|
|
27
27
|
ws.on("close", () => {
|
|
28
|
-
logger.debug(`Sandbox connection closed: ${
|
|
29
|
-
this.
|
|
28
|
+
logger.debug(`Sandbox connection closed: ${endpoint.$config.name}`);
|
|
29
|
+
this.endpoints.delete(endpoint.$id);
|
|
30
30
|
});
|
|
31
31
|
ws.on("error", (error) => {
|
|
32
|
-
logger.error(`Sandbox WebSocket error for ${
|
|
32
|
+
logger.error(`Sandbox WebSocket error for ${endpoint.$config.name}:`, error);
|
|
33
33
|
});
|
|
34
34
|
});
|
|
35
35
|
logger.debug("Sandbox WebSocket server started at /sandbox (Node Router.ws)");
|
|
@@ -45,8 +45,8 @@ provide({
|
|
|
45
45
|
return adapter;
|
|
46
46
|
},
|
|
47
47
|
dispose: async (adapter) => {
|
|
48
|
-
for (const
|
|
49
|
-
await
|
|
48
|
+
for (const endpoint of adapter.endpoints.values()) {
|
|
49
|
+
await endpoint.$disconnect();
|
|
50
50
|
}
|
|
51
51
|
adapter.wss?.close();
|
|
52
52
|
await adapter.stop();
|
|
@@ -63,5 +63,5 @@ plugin.useContext("web", (pageManager) => {
|
|
|
63
63
|
meta: { name: "Sandbox" },
|
|
64
64
|
});
|
|
65
65
|
});
|
|
66
|
-
export {
|
|
66
|
+
export { SandboxWsEndpoint, SandboxWsHostAdapter, resolveSandboxEndpoint, bindSandboxWsSocket, parseSandboxWsPayload, } from "./sandbox-ws.js";
|
|
67
67
|
//# 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":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAe,MAAM,SAAS,CAAC;AAEjD,OAAO,EACL,oBAAoB,EACpB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/sandbox-ws.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/** Sandbox 传输 — Node WebSocket。 */
|
|
2
2
|
import { EventEmitter } from "node:events";
|
|
3
|
-
import { Adapter,
|
|
3
|
+
import { Adapter, Endpoint, Message, type MessageElement, type MessageType, type Plugin, type SendOptions } from "zhin.js";
|
|
4
4
|
export interface SandboxWsConfig {
|
|
5
5
|
context: "sandbox";
|
|
6
6
|
ws?: SandboxWsSocket;
|
|
7
7
|
name: string;
|
|
8
8
|
owner?: string;
|
|
9
|
-
/** yaml 预置名:启动时占位,WS 连接前在
|
|
9
|
+
/** yaml 预置名:启动时占位,WS 连接前在 endpoint:list 显示为离线 */
|
|
10
10
|
offline?: boolean;
|
|
11
11
|
}
|
|
12
|
-
/** 无 WS 时的占位 socket(仅用于
|
|
12
|
+
/** 无 WS 时的占位 socket(仅用于 endpoint:list,不可收发) */
|
|
13
13
|
export declare function createOfflineSandboxWs(): SandboxWsSocket;
|
|
14
14
|
/** 兼容 `ws` 包与标准 WebSocket */
|
|
15
15
|
export type SandboxWsSocket = {
|
|
@@ -32,7 +32,7 @@ export type ResolvedSandboxBot = {
|
|
|
32
32
|
owner: string;
|
|
33
33
|
randomNamePerConnection: boolean;
|
|
34
34
|
};
|
|
35
|
-
export declare function
|
|
35
|
+
export declare function resolveSandboxEndpoint(appConfig: Record<string, unknown>): ResolvedSandboxBot;
|
|
36
36
|
export declare function bindSandboxWsSocket(ws: SandboxWsSocket, handlers: {
|
|
37
37
|
onMessage: (raw: string) => void;
|
|
38
38
|
onClose: () => void;
|
|
@@ -44,13 +44,13 @@ export declare function parseSandboxWsPayload(raw: string): {
|
|
|
44
44
|
content: MessageElement[];
|
|
45
45
|
timestamp: number;
|
|
46
46
|
};
|
|
47
|
-
type
|
|
47
|
+
type EndpointEvent = {
|
|
48
48
|
content: MessageElement[];
|
|
49
49
|
type: MessageType;
|
|
50
50
|
id: string;
|
|
51
51
|
ts: number;
|
|
52
52
|
};
|
|
53
|
-
export declare class
|
|
53
|
+
export declare class SandboxWsEndpoint extends EventEmitter implements Endpoint<SandboxWsConfig, EndpointEvent> {
|
|
54
54
|
#private;
|
|
55
55
|
adapter: SandboxWsHostAdapter;
|
|
56
56
|
$config: SandboxWsConfig;
|
|
@@ -59,12 +59,13 @@ export declare class SandboxWsBot extends EventEmitter implements Bot<SandboxWsC
|
|
|
59
59
|
constructor(adapter: SandboxWsHostAdapter, $config: SandboxWsConfig);
|
|
60
60
|
$connect(): Promise<void>;
|
|
61
61
|
$disconnect(): Promise<void>;
|
|
62
|
-
$formatMessage({ content, type, id, ts }:
|
|
62
|
+
$formatMessage({ content, type, id, ts }: EndpointEvent): Message<EndpointEvent>;
|
|
63
63
|
$sendMessage(options: SendOptions): Promise<string>;
|
|
64
64
|
$recallMessage(_id: string): Promise<void>;
|
|
65
65
|
}
|
|
66
|
-
export declare class SandboxWsHostAdapter extends Adapter<
|
|
66
|
+
export declare class SandboxWsHostAdapter extends Adapter<SandboxWsEndpoint> {
|
|
67
67
|
protected readonly defaults: ResolvedSandboxBot;
|
|
68
|
+
static readonly capabilities: readonly ["inbound", "outbound"];
|
|
68
69
|
constructor(plugin: Plugin, defaults: ResolvedSandboxBot);
|
|
69
70
|
getOutboundMediaCapabilities(): {
|
|
70
71
|
image: boolean;
|
|
@@ -73,11 +74,11 @@ export declare class SandboxWsHostAdapter extends Adapter<SandboxWsBot> {
|
|
|
73
74
|
file: boolean;
|
|
74
75
|
maxAttachmentBytes: number;
|
|
75
76
|
};
|
|
76
|
-
|
|
77
|
-
/** `zhin.config.yml` 中 `context: sandbox` + 固定 `name` 时,启动即出现在
|
|
77
|
+
createEndpoint(config: SandboxWsConfig): SandboxWsEndpoint;
|
|
78
|
+
/** `zhin.config.yml` 中 `context: sandbox` + 固定 `name` 时,启动即出现在 endpoint:list(离线) */
|
|
78
79
|
registerConfiguredPlaceholder(): void;
|
|
79
80
|
/** 外部 upgrade:注入已建立的 WebSocket */
|
|
80
|
-
acceptWebSocket(ws: SandboxWsSocket, overrides?: Partial<Pick<SandboxWsConfig, "name" | "owner">>):
|
|
81
|
+
acceptWebSocket(ws: SandboxWsSocket, overrides?: Partial<Pick<SandboxWsConfig, "name" | "owner">>): SandboxWsEndpoint;
|
|
81
82
|
}
|
|
82
83
|
export {};
|
|
83
84
|
//# sourceMappingURL=sandbox-ws.d.ts.map
|
package/lib/sandbox-ws.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-ws.d.ts","sourceRoot":"","sources":["../src/sandbox-ws.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,OAAO,EACP,
|
|
1
|
+
{"version":3,"file":"sandbox-ws.d.ts","sourceRoot":"","sources":["../src/sandbox-ws.ts"],"names":[],"mappings":"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"}
|
package/lib/sandbox-ws.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Sandbox 传输 — Node WebSocket。 */
|
|
2
2
|
import { EventEmitter } from "node:events";
|
|
3
3
|
import { Adapter, Message, segment, } from "zhin.js";
|
|
4
|
-
/** 无 WS 时的占位 socket(仅用于
|
|
4
|
+
/** 无 WS 时的占位 socket(仅用于 endpoint:list,不可收发) */
|
|
5
5
|
export function createOfflineSandboxWs() {
|
|
6
6
|
return { send: () => { }, close: () => { } };
|
|
7
7
|
}
|
|
@@ -9,9 +9,9 @@ function envVar(key) {
|
|
|
9
9
|
const g = globalThis;
|
|
10
10
|
return g.Deno?.env.get(key) ?? g.process?.env[key];
|
|
11
11
|
}
|
|
12
|
-
export function
|
|
13
|
-
const
|
|
14
|
-
const entry =
|
|
12
|
+
export function resolveSandboxEndpoint(appConfig) {
|
|
13
|
+
const endpoints = appConfig.endpoints;
|
|
14
|
+
const entry = endpoints?.find((b) => b.context === "sandbox");
|
|
15
15
|
const fixedName = typeof entry?.name === "string" ? entry.name : undefined;
|
|
16
16
|
const name = fixedName ||
|
|
17
17
|
envVar("SANDBOX_BOT_NAME") ||
|
|
@@ -99,7 +99,7 @@ export function parseSandboxWsPayload(raw) {
|
|
|
99
99
|
: [{ type: "text", data: { text: payload.text ?? raw } }];
|
|
100
100
|
return { type, id, content, timestamp: payload.timestamp ?? Date.now() };
|
|
101
101
|
}
|
|
102
|
-
export class
|
|
102
|
+
export class SandboxWsEndpoint extends EventEmitter {
|
|
103
103
|
adapter;
|
|
104
104
|
$config;
|
|
105
105
|
$connected = false;
|
|
@@ -128,7 +128,7 @@ export class SandboxWsBot extends EventEmitter {
|
|
|
128
128
|
onClose: () => {
|
|
129
129
|
this.$connected = false;
|
|
130
130
|
if (!this.$config.offline) {
|
|
131
|
-
this.adapter.
|
|
131
|
+
this.adapter.endpoints.delete(this.$id);
|
|
132
132
|
}
|
|
133
133
|
},
|
|
134
134
|
onError: (err) => {
|
|
@@ -149,7 +149,7 @@ export class SandboxWsBot extends EventEmitter {
|
|
|
149
149
|
const message = Message.from({ content, type, id, ts }, {
|
|
150
150
|
$id: `${ts}`,
|
|
151
151
|
$adapter: "sandbox",
|
|
152
|
-
$
|
|
152
|
+
$endpoint: this.$config.name,
|
|
153
153
|
$sender: { id, name: "mock" },
|
|
154
154
|
$channel: { id, type },
|
|
155
155
|
$content: content,
|
|
@@ -168,7 +168,7 @@ export class SandboxWsBot extends EventEmitter {
|
|
|
168
168
|
}
|
|
169
169
|
return await this.adapter.sendMessage({
|
|
170
170
|
context: "sandbox",
|
|
171
|
-
|
|
171
|
+
endpoint: this.$config.name,
|
|
172
172
|
content: normalized,
|
|
173
173
|
id,
|
|
174
174
|
type,
|
|
@@ -194,6 +194,7 @@ export class SandboxWsBot extends EventEmitter {
|
|
|
194
194
|
}
|
|
195
195
|
export class SandboxWsHostAdapter extends Adapter {
|
|
196
196
|
defaults;
|
|
197
|
+
static capabilities = ['inbound', 'outbound'];
|
|
197
198
|
constructor(plugin, defaults) {
|
|
198
199
|
super(plugin, "sandbox", []);
|
|
199
200
|
this.defaults = defaults;
|
|
@@ -207,18 +208,18 @@ export class SandboxWsHostAdapter extends Adapter {
|
|
|
207
208
|
maxAttachmentBytes: 26_214_400,
|
|
208
209
|
};
|
|
209
210
|
}
|
|
210
|
-
|
|
211
|
-
const
|
|
212
|
-
this.
|
|
213
|
-
return
|
|
211
|
+
createEndpoint(config) {
|
|
212
|
+
const endpoint = new SandboxWsEndpoint(this, config);
|
|
213
|
+
this.endpoints.set(endpoint.$id, endpoint);
|
|
214
|
+
return endpoint;
|
|
214
215
|
}
|
|
215
|
-
/** `zhin.config.yml` 中 `context: sandbox` + 固定 `name` 时,启动即出现在
|
|
216
|
+
/** `zhin.config.yml` 中 `context: sandbox` + 固定 `name` 时,启动即出现在 endpoint:list(离线) */
|
|
216
217
|
registerConfiguredPlaceholder() {
|
|
217
218
|
if (this.defaults.randomNamePerConnection)
|
|
218
219
|
return;
|
|
219
|
-
if (this.
|
|
220
|
+
if (this.endpoints.has(this.defaults.name))
|
|
220
221
|
return;
|
|
221
|
-
this.
|
|
222
|
+
this.createEndpoint({
|
|
222
223
|
context: "sandbox",
|
|
223
224
|
name: this.defaults.name,
|
|
224
225
|
owner: this.defaults.owner,
|
|
@@ -233,18 +234,18 @@ export class SandboxWsHostAdapter extends Adapter {
|
|
|
233
234
|
? `sandbox-${crypto.randomUUID().slice(0, 8)}`
|
|
234
235
|
: this.defaults.name);
|
|
235
236
|
const owner = overrides?.owner ?? this.defaults.owner;
|
|
236
|
-
const existing = this.
|
|
237
|
+
const existing = this.endpoints.get(name);
|
|
237
238
|
if (existing) {
|
|
238
239
|
void existing.$disconnect();
|
|
239
|
-
this.
|
|
240
|
+
this.endpoints.delete(name);
|
|
240
241
|
}
|
|
241
|
-
const
|
|
242
|
-
void
|
|
242
|
+
const endpoint = this.createEndpoint({ context: "sandbox", ws, name, owner, offline: false });
|
|
243
|
+
void endpoint.$connect();
|
|
243
244
|
if (!this.defaults.randomNamePerConnection) {
|
|
244
245
|
const readyPayload = JSON.stringify({
|
|
245
246
|
type: "ready",
|
|
246
247
|
id: owner,
|
|
247
|
-
|
|
248
|
+
endpoint: name,
|
|
248
249
|
content: [
|
|
249
250
|
{
|
|
250
251
|
type: "text",
|
|
@@ -261,7 +262,7 @@ export class SandboxWsHostAdapter extends Adapter {
|
|
|
261
262
|
});
|
|
262
263
|
whenWsOpen(ws, () => ws.send(readyPayload));
|
|
263
264
|
}
|
|
264
|
-
return
|
|
265
|
+
return endpoint;
|
|
265
266
|
}
|
|
266
267
|
}
|
|
267
268
|
//# sourceMappingURL=sandbox-ws.js.map
|
package/lib/sandbox-ws.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-ws.js","sourceRoot":"","sources":["../src/sandbox-ws.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,OAAO,EAEP,OAAO,EACP,OAAO,GAMR,MAAM,SAAS,CAAC;AAWjB
|
|
1
|
+
{"version":3,"file":"sandbox-ws.js","sourceRoot":"","sources":["../src/sandbox-ws.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,OAAO,EAEP,OAAO,EACP,OAAO,GAMR,MAAM,SAAS,CAAC;AAWjB,+CAA+C;AAC/C,MAAM,UAAU,sBAAsB;IACpC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;AAC7C,CAAC;AAmCD,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,sBAAsB,CACpC,SAAkC;IAElC,MAAM,SAAS,GAAG,SAAS,CAAC,SAAuD,CAAC;IACpF,MAAM,KAAK,GAAG,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC;IAC9D,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,OAAO;QACL,OAAO,EAAE,SAAS;QAClB,IAAI;QACJ,KAAK;QACL,uBAAuB,EAAE,CAAC,SAAS;KACpC,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,iBAAkB,SAAQ,YAAY;IASxC;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,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC1C,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,EAAiB;QACrD,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,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;YAC5B,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,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;oBAC3B,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,OAA0B;IAK7C;IAJrB,MAAM,CAAmB,YAAY,GAAG,CAAC,SAAS,EAAE,UAAU,CAAU,CAAC;IAEzE,YACE,MAAc,EACK,QAA4B;QAE/C,KAAK,CAAC,MAAM,EAAE,SAAkC,EAAE,EAAE,CAAC,CAAC;QAFnC,aAAQ,GAAR,QAAQ,CAAoB;IAGjD,CAAC;IAED,4BAA4B;QAC1B,OAAO;YACL,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,IAAI;YACX,IAAI,EAAE,IAAI;YACV,kBAAkB,EAAE,UAAU;SAC/B,CAAC;IACJ,CAAC;IAED,cAAc,CAAC,MAAuB;QACpC,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACrD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC3C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,oFAAoF;IACpF,6BAA6B;QAC3B,IAAI,IAAI,CAAC,QAAQ,CAAC,uBAAuB;YAAE,OAAO;QAClD,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO;QACnD,IAAI,CAAC,cAAc,CAAC;YAClB,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,kCAAkC;IAClC,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,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,QAAQ,CAAC,WAAW,EAAE,CAAC;YAC5B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9F,KAAK,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACzB,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,QAAQ,EAAE,IAAI;gBACd,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,QAAQ,CAAC;IAClB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-sandbox",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Zhin.js adapter for local testing and development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -49,13 +49,19 @@
|
|
|
49
49
|
"@types/react": "^19.2.15",
|
|
50
50
|
"@types/react-dom": "^19.2.3",
|
|
51
51
|
"typescript": "^6.0.3",
|
|
52
|
-
"@zhin.js/cli": "1.0.
|
|
52
|
+
"@zhin.js/cli": "1.0.89",
|
|
53
|
+
"@zhin.js/contract": "1.0.1",
|
|
54
|
+
"@zhin.js/core": "1.2.1",
|
|
55
|
+
"@zhin.js/host-api": "1.0.1",
|
|
56
|
+
"@zhin.js/host-router": "1.0.1",
|
|
57
|
+
"zhin.js": "2.0.1",
|
|
58
|
+
"@zhin.js/client": "2.0.3"
|
|
53
59
|
},
|
|
54
60
|
"peerDependencies": {
|
|
55
|
-
"@zhin.js/core": "1.1
|
|
56
|
-
"@zhin.js/host-router": "
|
|
57
|
-
"@zhin.js/host-api": "
|
|
58
|
-
"@zhin.js/client": "2.0.
|
|
61
|
+
"@zhin.js/core": "1.2.1",
|
|
62
|
+
"@zhin.js/host-router": "1.0.1",
|
|
63
|
+
"@zhin.js/host-api": "1.0.1",
|
|
64
|
+
"@zhin.js/client": "2.0.3",
|
|
59
65
|
"@zhin.js/contract": "1.0.1"
|
|
60
66
|
},
|
|
61
67
|
"peerDependenciesMeta": {
|
package/src/index.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { usePlugin, type Plugin } from "zhin.js";
|
|
|
3
3
|
import type { WebSocket } from "ws";
|
|
4
4
|
import {
|
|
5
5
|
SandboxWsHostAdapter,
|
|
6
|
-
|
|
6
|
+
resolveSandboxEndpoint,
|
|
7
7
|
type SandboxWsSocket,
|
|
8
8
|
} from "./sandbox-ws.js";
|
|
9
9
|
import { PageManager } from "@zhin.js/host-api";
|
|
@@ -27,7 +27,7 @@ export class SandboxAdapter extends SandboxWsHostAdapter {
|
|
|
27
27
|
|
|
28
28
|
constructor(plugin: ReturnType<typeof usePlugin>) {
|
|
29
29
|
const appConfig = (plugin.inject("config")?.getPrimary() ?? {}) as Record<string, unknown>;
|
|
30
|
-
super(plugin,
|
|
30
|
+
super(plugin, resolveSandboxEndpoint(appConfig));
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
override async start(): Promise<void> {
|
|
@@ -48,13 +48,13 @@ export class SandboxAdapter extends SandboxWsHostAdapter {
|
|
|
48
48
|
logger.debug(
|
|
49
49
|
`New sandbox connection from ${req.socket?.remoteAddress ?? "unknown"}`,
|
|
50
50
|
);
|
|
51
|
-
const
|
|
51
|
+
const endpoint = this.acceptWebSocket(ws as SandboxWsSocket);
|
|
52
52
|
ws.on("close", () => {
|
|
53
|
-
logger.debug(`Sandbox connection closed: ${
|
|
54
|
-
this.
|
|
53
|
+
logger.debug(`Sandbox connection closed: ${endpoint.$config.name}`);
|
|
54
|
+
this.endpoints.delete(endpoint.$id);
|
|
55
55
|
});
|
|
56
56
|
ws.on("error", (error) => {
|
|
57
|
-
logger.error(`Sandbox WebSocket error for ${
|
|
57
|
+
logger.error(`Sandbox WebSocket error for ${endpoint.$config.name}:`, error);
|
|
58
58
|
});
|
|
59
59
|
});
|
|
60
60
|
|
|
@@ -73,8 +73,8 @@ provide({
|
|
|
73
73
|
return adapter;
|
|
74
74
|
},
|
|
75
75
|
dispose: async (adapter: SandboxAdapter) => {
|
|
76
|
-
for (const
|
|
77
|
-
await
|
|
76
|
+
for (const endpoint of adapter.endpoints.values()) {
|
|
77
|
+
await endpoint.$disconnect();
|
|
78
78
|
}
|
|
79
79
|
adapter.wss?.close();
|
|
80
80
|
await adapter.stop();
|
|
@@ -95,9 +95,9 @@ plugin.useContext("web", (pageManager) => {
|
|
|
95
95
|
});
|
|
96
96
|
|
|
97
97
|
export {
|
|
98
|
-
|
|
98
|
+
SandboxWsEndpoint,
|
|
99
99
|
SandboxWsHostAdapter,
|
|
100
|
-
|
|
100
|
+
resolveSandboxEndpoint,
|
|
101
101
|
bindSandboxWsSocket,
|
|
102
102
|
parseSandboxWsPayload,
|
|
103
103
|
type ResolvedSandboxBot,
|
package/src/sandbox-ws.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { EventEmitter } from "node:events";
|
|
3
3
|
import {
|
|
4
4
|
Adapter,
|
|
5
|
-
|
|
5
|
+
Endpoint,
|
|
6
6
|
Message,
|
|
7
7
|
segment,
|
|
8
8
|
type MessageElement,
|
|
@@ -17,11 +17,11 @@ export interface SandboxWsConfig {
|
|
|
17
17
|
ws?: SandboxWsSocket;
|
|
18
18
|
name: string;
|
|
19
19
|
owner?: string;
|
|
20
|
-
/** yaml 预置名:启动时占位,WS 连接前在
|
|
20
|
+
/** yaml 预置名:启动时占位,WS 连接前在 endpoint:list 显示为离线 */
|
|
21
21
|
offline?: boolean;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/** 无 WS 时的占位 socket(仅用于
|
|
24
|
+
/** 无 WS 时的占位 socket(仅用于 endpoint:list,不可收发) */
|
|
25
25
|
export function createOfflineSandboxWs(): SandboxWsSocket {
|
|
26
26
|
return { send: () => {}, close: () => {} };
|
|
27
27
|
}
|
|
@@ -67,11 +67,11 @@ function envVar(key: string): string | undefined {
|
|
|
67
67
|
return g.Deno?.env.get(key) ?? g.process?.env[key];
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
export function
|
|
70
|
+
export function resolveSandboxEndpoint(
|
|
71
71
|
appConfig: Record<string, unknown>,
|
|
72
72
|
): ResolvedSandboxBot {
|
|
73
|
-
const
|
|
74
|
-
const entry =
|
|
73
|
+
const endpoints = appConfig.endpoints as Array<Record<string, unknown>> | undefined;
|
|
74
|
+
const entry = endpoints?.find((b) => b.context === "sandbox");
|
|
75
75
|
const fixedName = typeof entry?.name === "string" ? entry.name : undefined;
|
|
76
76
|
const name =
|
|
77
77
|
fixedName ||
|
|
@@ -178,14 +178,14 @@ export function parseSandboxWsPayload(raw: string): {
|
|
|
178
178
|
return { type, id, content, timestamp: payload.timestamp ?? Date.now() };
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
type
|
|
181
|
+
type EndpointEvent = {
|
|
182
182
|
content: MessageElement[];
|
|
183
183
|
type: MessageType;
|
|
184
184
|
id: string;
|
|
185
185
|
ts: number;
|
|
186
186
|
};
|
|
187
187
|
|
|
188
|
-
export class
|
|
188
|
+
export class SandboxWsEndpoint extends EventEmitter implements Endpoint<SandboxWsConfig, EndpointEvent> {
|
|
189
189
|
$connected = false;
|
|
190
190
|
#unbind: (() => void) | null = null;
|
|
191
191
|
|
|
@@ -218,7 +218,7 @@ export class SandboxWsBot extends EventEmitter implements Bot<SandboxWsConfig, B
|
|
|
218
218
|
onClose: () => {
|
|
219
219
|
this.$connected = false;
|
|
220
220
|
if (!this.$config.offline) {
|
|
221
|
-
this.adapter.
|
|
221
|
+
this.adapter.endpoints.delete(this.$id);
|
|
222
222
|
}
|
|
223
223
|
},
|
|
224
224
|
onError: (err) => {
|
|
@@ -237,14 +237,14 @@ export class SandboxWsBot extends EventEmitter implements Bot<SandboxWsConfig, B
|
|
|
237
237
|
this.$connected = false;
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
-
$formatMessage({ content, type, id, ts }:
|
|
240
|
+
$formatMessage({ content, type, id, ts }: EndpointEvent) {
|
|
241
241
|
if (!this.$config.owner) this.$config.owner = id;
|
|
242
|
-
const message = Message.from<
|
|
242
|
+
const message = Message.from<EndpointEvent>(
|
|
243
243
|
{ content, type, id, ts },
|
|
244
244
|
{
|
|
245
245
|
$id: `${ts}`,
|
|
246
246
|
$adapter: "sandbox" as const,
|
|
247
|
-
$
|
|
247
|
+
$endpoint: this.$config.name,
|
|
248
248
|
$sender: { id, name: "mock" },
|
|
249
249
|
$channel: { id, type },
|
|
250
250
|
$content: content,
|
|
@@ -263,7 +263,7 @@ export class SandboxWsBot extends EventEmitter implements Bot<SandboxWsConfig, B
|
|
|
263
263
|
}
|
|
264
264
|
return await this.adapter.sendMessage({
|
|
265
265
|
context: "sandbox",
|
|
266
|
-
|
|
266
|
+
endpoint: this.$config.name,
|
|
267
267
|
content: normalized,
|
|
268
268
|
id,
|
|
269
269
|
type,
|
|
@@ -291,7 +291,9 @@ export class SandboxWsBot extends EventEmitter implements Bot<SandboxWsConfig, B
|
|
|
291
291
|
async $recallMessage(_id: string): Promise<void> {}
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
-
export class SandboxWsHostAdapter extends Adapter<
|
|
294
|
+
export class SandboxWsHostAdapter extends Adapter<SandboxWsEndpoint> {
|
|
295
|
+
static override readonly capabilities = ['inbound', 'outbound'] as const;
|
|
296
|
+
|
|
295
297
|
constructor(
|
|
296
298
|
plugin: Plugin,
|
|
297
299
|
protected readonly defaults: ResolvedSandboxBot,
|
|
@@ -309,17 +311,17 @@ export class SandboxWsHostAdapter extends Adapter<SandboxWsBot> {
|
|
|
309
311
|
};
|
|
310
312
|
}
|
|
311
313
|
|
|
312
|
-
|
|
313
|
-
const
|
|
314
|
-
this.
|
|
315
|
-
return
|
|
314
|
+
createEndpoint(config: SandboxWsConfig): SandboxWsEndpoint {
|
|
315
|
+
const endpoint = new SandboxWsEndpoint(this, config);
|
|
316
|
+
this.endpoints.set(endpoint.$id, endpoint);
|
|
317
|
+
return endpoint;
|
|
316
318
|
}
|
|
317
319
|
|
|
318
|
-
/** `zhin.config.yml` 中 `context: sandbox` + 固定 `name` 时,启动即出现在
|
|
320
|
+
/** `zhin.config.yml` 中 `context: sandbox` + 固定 `name` 时,启动即出现在 endpoint:list(离线) */
|
|
319
321
|
registerConfiguredPlaceholder(): void {
|
|
320
322
|
if (this.defaults.randomNamePerConnection) return;
|
|
321
|
-
if (this.
|
|
322
|
-
this.
|
|
323
|
+
if (this.endpoints.has(this.defaults.name)) return;
|
|
324
|
+
this.createEndpoint({
|
|
323
325
|
context: "sandbox",
|
|
324
326
|
name: this.defaults.name,
|
|
325
327
|
owner: this.defaults.owner,
|
|
@@ -332,24 +334,24 @@ export class SandboxWsHostAdapter extends Adapter<SandboxWsBot> {
|
|
|
332
334
|
acceptWebSocket(
|
|
333
335
|
ws: SandboxWsSocket,
|
|
334
336
|
overrides?: Partial<Pick<SandboxWsConfig, "name" | "owner">>,
|
|
335
|
-
):
|
|
337
|
+
): SandboxWsEndpoint {
|
|
336
338
|
const name = overrides?.name ??
|
|
337
339
|
(this.defaults.randomNamePerConnection
|
|
338
340
|
? `sandbox-${crypto.randomUUID().slice(0, 8)}`
|
|
339
341
|
: this.defaults.name);
|
|
340
342
|
const owner = overrides?.owner ?? this.defaults.owner;
|
|
341
|
-
const existing = this.
|
|
343
|
+
const existing = this.endpoints.get(name);
|
|
342
344
|
if (existing) {
|
|
343
345
|
void existing.$disconnect();
|
|
344
|
-
this.
|
|
346
|
+
this.endpoints.delete(name);
|
|
345
347
|
}
|
|
346
|
-
const
|
|
347
|
-
void
|
|
348
|
+
const endpoint = this.createEndpoint({ context: "sandbox", ws, name, owner, offline: false });
|
|
349
|
+
void endpoint.$connect();
|
|
348
350
|
if (!this.defaults.randomNamePerConnection) {
|
|
349
351
|
const readyPayload = JSON.stringify({
|
|
350
352
|
type: "ready",
|
|
351
353
|
id: owner,
|
|
352
|
-
|
|
354
|
+
endpoint: name,
|
|
353
355
|
content: [
|
|
354
356
|
{
|
|
355
357
|
type: "text",
|
|
@@ -366,7 +368,7 @@ export class SandboxWsHostAdapter extends Adapter<SandboxWsBot> {
|
|
|
366
368
|
});
|
|
367
369
|
whenWsOpen(ws, () => ws.send(readyPayload));
|
|
368
370
|
}
|
|
369
|
-
return
|
|
371
|
+
return endpoint;
|
|
370
372
|
}
|
|
371
373
|
}
|
|
372
374
|
|