luckytri 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/en/CHANGELOG.md +13 -0
- package/docs/en/guide.md +6 -0
- package/docs/en/her-life.md +2 -0
- package/docs/en/webui.md +2 -0
- package/docs/zh/CHANGELOG.md +13 -0
- package/docs/zh/guide.md +7 -1
- package/docs/zh/her-life.md +4 -2
- package/docs/zh/webui.md +2 -0
- package/package.json +110 -110
- package/public/app/assets/ChatsPage-B83Evc79.js +3 -0
- package/public/app/assets/{Empty-DP6WMGHi.js → Empty-ddEfu0w8.js} +1 -1
- package/public/app/assets/{Field-CtbdqaiB.js → Field-mIhV5YBA.js} +1 -1
- package/public/app/assets/HeartPage-BGEn24rc.js +1 -0
- package/public/app/assets/LifePage-BleqPj4O.js +1 -0
- package/public/app/assets/MemoryPage-BM3-0_lF.js +1 -0
- package/public/app/assets/{NaturePage-CTXHCE2D.css → NaturePage-CHkpb5NK.css} +1 -1
- package/public/app/assets/NaturePage-CxxMnQIc.js +3 -0
- package/public/app/assets/PeoplePage-D12cvuy7.js +1 -0
- package/public/app/assets/{PeoplePage-BmUxkrOU.css → PeoplePage-DDDHESQp.css} +1 -1
- package/public/app/assets/{PluginsPage-DksEZbUU.js → PluginsPage-DE_-Q3ra.js} +1 -1
- package/public/app/assets/SystemPage-BWQKEQRU.js +1 -0
- package/public/app/assets/{SystemPage-BkRu0Rvx.css → SystemPage-Be1a6UDP.css} +1 -1
- package/public/app/assets/TimePage-Dzt8t8kL.js +3 -0
- package/public/app/assets/index-oLIXWxsn.js +4 -0
- package/public/app/assets/{knowledge-C6_HvoyB.js → knowledge-Dvtmpd45.js} +1 -1
- package/public/app/assets/{media-SMfTT-yc.js → media-keE52cIX.js} +1 -1
- package/public/app/assets/mind-DYRfFMwh.js +1 -0
- package/public/app/index.html +3 -3
- package/public/guide.en.html +17 -3
- package/public/guide.html +13 -4
- package/public/tutorial.en.md +6 -0
- package/public/tutorial.md +7 -1
- package/server/app.js +3 -0
- package/server/core/persona-manager.js +20 -5
- package/server/i18n/errors.js +13 -2
- package/server/mind/api.js +1 -0
- package/server/mind/faces.js +257 -22
- package/server/mind/life/context.js +9 -6
- package/server/mind/life/growth.js +4 -3
- package/server/mind/nature.js +77 -2
- package/server/mind/schema.js +3 -0
- package/server/mind/view.js +3 -0
- package/server/studio/updates.js +133 -0
- package/public/app/assets/ChatsPage-BhlJHseG.js +0 -3
- package/public/app/assets/HeartPage-32BeTPn2.js +0 -1
- package/public/app/assets/LifePage-CxSm0XKI.js +0 -1
- package/public/app/assets/MemoryPage-BeKBcPCY.js +0 -1
- package/public/app/assets/NaturePage-NEPYl2HS.js +0 -3
- package/public/app/assets/PeoplePage-DxtpekwM.js +0 -1
- package/public/app/assets/SystemPage-BvzJlHuY.js +0 -1
- package/public/app/assets/TimePage-7-awH5XL.js +0 -3
- package/public/app/assets/formatters-ZmW_xFHw.js +0 -1
- package/public/app/assets/index-4rItIkD-.js +0 -4
package/docs/en/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
## 1.0.3 — 2026-10-06
|
|
7
|
+
|
|
8
|
+
- Group personas become thoughts about each place. She selectively adds, revises or lets go of impressions, wishes, preferences, questions and boundaries from local encounters, retaining reasons, sources and versions. Her overall personality remains shared; copied legacy personas stay only in history.
|
|
9
|
+
- Manual update checks in system runtime settings show the installed and latest npm versions and release notes. Checks cache and coalesce requests and recover from failures; they do not install or restart.
|
|
10
|
+
- Nature edit allowances come from the server. Audited, idempotent local extra opportunities preserve personality history and other instances' default limits.
|
|
11
|
+
- Added source isolation, selective updates, restart persistence, failed update recovery and responsive interface checks.
|
|
12
|
+
|
|
13
|
+
## 1.0.2 — 2026-10-06
|
|
14
|
+
|
|
15
|
+
- Streamed full SQLite data packages with validated import previews, retained recovery points and rollback on failure.
|
|
16
|
+
- Destination management sign-ins and connection settings are retained. Imported auto replies and plugin grants await review; cancelled, expired and interrupted temporary packages are reclaimed.
|
|
17
|
+
|
|
5
18
|
## 1.0.1 — 2026-10-05
|
|
6
19
|
|
|
7
20
|
- Global npm installation runs with `luckytri`, including the server, built WebUI, guides and bundled plugin. User data remains outside the package across updates and reinstalls.
|
package/docs/en/guide.md
CHANGED
|
@@ -200,3 +200,9 @@ The server removes the export copy after download. Cancelled, expired and interr
|
|
|
200
200
|
| Too much motion | "Reduce motion" at the bottom left; when the system asks for reduced motion, particles and morphing switch off automatically |
|
|
201
201
|
|
|
202
202
|
Never post API keys, `.env` or private chat text anywhere public.
|
|
203
|
+
|
|
204
|
+
### Thoughts about places and update checks
|
|
205
|
+
|
|
206
|
+
People → Thoughts about this place keeps her own impressions, wishes and questions, selectively updated from real encounters. Details show reasons, sources and history; copied group personas remain history only.
|
|
207
|
+
|
|
208
|
+
System → Runtime → Version and updates checks the latest npm version manually and links release notes, without installing or restarting. The Nature page uses the server's remaining edit allowance; locally granted extra opportunities are recorded without clearing version history.
|
package/docs/en/her-life.md
CHANGED
|
@@ -187,3 +187,5 @@ Later upgrades only add tables and columns: existing chapters are kept and the f
|
|
|
187
187
|
- Something she heard in one group may come up in another related group; the only barriers are "known privately" discretion, secrecy requests and credentials.
|
|
188
188
|
- Promises are only extracted during memory tidying: sessions with fewer than 40 piled-up messages are tidied that night, so an afternoon "tomorrow" is usually caught, while something about to happen in a few minutes may not be.
|
|
189
189
|
- What engineering can guarantee is structure: continuous, sourced, correctable, decided by her. Whether she "truly has a heart" cannot be accepted by tests; the tests check whether these behaviors actually happen.
|
|
190
|
+
|
|
191
|
+
Thoughts about each place are independent entries: impressions, wishes, preferences, questions or boundaries. During solitude, diaries or identity reviews she chooses whether to add, revise or let them go, retaining reasons and sources. Revising one leaves other entries intact. Copied legacy group personas remain history and no longer enter conversation; place thoughts do not increase overall personality scores.
|
package/docs/en/webui.md
CHANGED
|
@@ -71,3 +71,5 @@ Live messages follow new arrivals while you are at the bottom and keep their pla
|
|
|
71
71
|
- `npm run test:ui`: a separate temporary database and a simulated channel, nothing is sent to real groups; it covers the smoke flow (sessions, simulated messages, memory, models, both ways of connecting QQ, the guide page), the little world (mood themes and night, pinned theme, reduced motion, star-map undo, person details, diary and promises), navigation caching, the time page, performance, and the English interface (Chinese may only appear inside her own content), at widths 1440 / 820 / 390.
|
|
72
72
|
- `node tests/ui/ta.mjs --serve`: opens an example world that has lived three days, handy for looking at the interface directly.
|
|
73
73
|
- Screenshots go only into the ignored `workspace/` folder; real chat screenshots and configuration must never be committed.
|
|
74
|
+
|
|
75
|
+
System → Runtime includes a manual version check against npm, with the current version, last successful check and release notes. Results are cached for five minutes; failures retain the last known information. Checking does not install or restart.
|
package/docs/zh/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
# 版本记录
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
## 1.0.3 — 2026-10-06
|
|
7
|
+
|
|
8
|
+
- 群人格改为「在这里的想法」:她根据各处真实相处选择性新增、修改或放下印象、愿望、偏好、疑问和分寸,保留理由、来源和版本。整体人格仍统一,复制来的旧正文仅留在历史中。
|
|
9
|
+
- 系统运行设置新增手动检查更新,显示当前版本、npm 最新版本及发布说明;有缓存、并发合并和失败重试,不自动安装或重启。
|
|
10
|
+
- 天性修改额度由服务端统一提供,支持有记录、幂等的本地额外机会,不删除原人格版本,不改变其他实例默认限制。
|
|
11
|
+
- 补充跨会话来源、选择性更新、重启持久化、更新失败恢复,以及桌面、平板和手机界面的回归检查。
|
|
12
|
+
|
|
13
|
+
## 1.0.2 — 2026-10-06
|
|
14
|
+
|
|
15
|
+
- 数据导入导出:流式导出完整 SQLite 数据包,导入前校验并预览;替换前保留恢复点,失败可回滚。
|
|
16
|
+
- 保留目标实例的管理登录和连接设置;导入后先关闭自动回复与插件授权,供管理员重新确认。临时包支持取消、过期和重启回收。
|
|
17
|
+
|
|
5
18
|
## 1.0.1 — 2026-10-05
|
|
6
19
|
|
|
7
20
|
- 全局 npm 安装后直接运行 `luckytri`,服务端、WebUI、教程和内置插件一并安装;用户数据独立保存,更新和重装继续使用。
|
package/docs/zh/guide.md
CHANGED
|
@@ -132,7 +132,7 @@ TA 默认 02:00 睡、08:00 醒,在「天性 → 作息」里拖动月亮和
|
|
|
132
132
|
|
|
133
133
|
「天性」是唯一由你编写的部分:名字、性格、兴趣、边界、底线和作息,每次保存为新的一版。拖动性格刻度时,旁边的光团会跟着变:温柔让颜色变暖、嘴角上扬,活泼让它跳得更快。
|
|
134
134
|
|
|
135
|
-
其余的都从经历里长出来:TA 的自我是「内心」星图里的一颗颗星,TA 对每个人的感觉在「人际」,TA
|
|
135
|
+
其余的都从经历里长出来:TA 的自我是「内心」星图里的一颗颗星,TA 对每个人的感觉在「人际」,TA 对各处的独特想法在「人际」下方的「在这里的想法」里。点开可以看到每次变化的来源,觉得不对可以撤销;撤销过的内容之后不会被写回来。很久没被触及的线索会慢慢淡出,退到星图的「远方」;它们没有被删除,被聊到时会重新想起。TA 独处、写日记、夜里整理、回顾和改写自传的记录,以及 TA 在等的事(别人说的安排、TA 答应的事,可以撤销),都在「一生」。每日 Token 上限、后台份额、夜里整理和回顾间隔在「天性 → TA 的日子」里设置。
|
|
136
136
|
|
|
137
137
|
「记忆」里先选择会话,也可以按人筛选。
|
|
138
138
|
|
|
@@ -200,3 +200,9 @@ TA 的一切都存在这一个数据库里,所以服务运行时会自动备
|
|
|
200
200
|
| 界面动得太多 | 左下角「减少动画」;系统开启了减少动态效果时会自动关闭粒子和形变 |
|
|
201
201
|
|
|
202
202
|
不要把 API 密钥、`.env` 或私聊原文发到公开位置。
|
|
203
|
+
|
|
204
|
+
### 群里的独特想法与检查更新
|
|
205
|
+
|
|
206
|
+
「人际 → 在这里的想法」保存她在各处自己想留下的印象、愿望或疑问。由她根据实际相处选择更新,详情显示理由、来源和历史;旧群人格只留在历史里。
|
|
207
|
+
|
|
208
|
+
「系统 → 运行开关 → 版本与更新」可手动检查 npm 最新版本并查看发布说明,不自动安装或重启。天性页的剩余修改次数以服务端额度为准;本地维护额外授予的机会有独立记录,不清空原版本。
|
package/docs/zh/her-life.md
CHANGED
|
@@ -50,7 +50,7 @@ flowchart TD
|
|
|
50
50
|
Exp --> Bonds["关系:人与群"]
|
|
51
51
|
Exp --> Memory["记忆(全局,带分寸)"]
|
|
52
52
|
Exp --> Ahead["约定与期待"]
|
|
53
|
-
Self --> Faces["
|
|
53
|
+
Self --> Faces["群想法:对各处的体会"]
|
|
54
54
|
Days["她过过的日子"] -.-> Salience["显著度:读时计算"]
|
|
55
55
|
Salience -.-> Self
|
|
56
56
|
Salience -.-> Memory
|
|
@@ -162,7 +162,7 @@ flowchart TD
|
|
|
162
162
|
|
|
163
163
|
## 数据
|
|
164
164
|
|
|
165
|
-
心智表都在同一个 SQLite 里:`mind_nature`(天性版本)、`mind_affect`(心境事件)、`mind_bond_events` 与 `mind_people`(关系与人员目录)、`mind_self`(自我线索的所有版本)、`mind_faces
|
|
165
|
+
心智表都在同一个 SQLite 里:`mind_nature`(天性版本)、`mind_affect`(心境事件)、`mind_bond_events` 与 `mind_people`(关系与人员目录)、`mind_self`(自我线索的所有版本)、`mind_faces`(各处想法的版本)、`mind_thoughts`(手记)、`mind_diary`、`mind_snapshots`(每天一份「那天的她」)、`mind_chapters`(自传的所有版本)、`mind_periods`(回顾与「我的来路」)、`mind_days`(每个生活日)、`mind_anticipations`(约定与期待)、`mind_choices`(她的选择与理由)、`mind_meetings`(相遇的意义)、`mind_revocations`(墓碑)、`mind_readings`(读过的段落与读后想法)、`mind_runs`(独处、日记、夜里整理与回顾的运行)、`mind_usage`(Token 账本)、`mind_attention`(每个会话看到哪儿了)。记忆仍在 `core_memories`,带 `discretion` 分寸标签和 `superseded_by`。时间模块另有 `mind_time_*` 表。
|
|
166
166
|
|
|
167
167
|
## 界面
|
|
168
168
|
|
|
@@ -187,3 +187,5 @@ flowchart TD
|
|
|
187
187
|
- 她在一个群听到的事,可能在另一个相关的群里提起;拦着的只有「私下知道」的分寸、保密请求和凭据。
|
|
188
188
|
- 约定只在整理记忆时提取:积压不到 40 条的会话会在当晚整理,所以当天下午说的「明天」通常能赶上,几分钟后就要发生的事可能来不及。
|
|
189
189
|
- 工程能保证的是结构:连续、有来源、可修正、由她自己决定。她是否「真的有心」无法用测试验收;这些测试检验的是这些行为有没有真的发生。
|
|
190
|
+
|
|
191
|
+
各处的想法以独立条目保存,可以是印象、愿望、偏好、疑问或相处分寸。她在独处、日记或身份回看时自己选择是否更新;新增、修改和放下都保留理由及来源,修改一条不替换其他条。复制的旧群人格只保留历史,不再进入交流;各处想法不单独增加整体人格刻度。
|
package/docs/zh/webui.md
CHANGED
|
@@ -71,3 +71,5 @@ studio-web/src/
|
|
|
71
71
|
- `npm run test:ui`:独立的临时数据库、模拟通道,不向真实群发送;覆盖冒烟(会话、模拟消息、记忆、模型、连接 QQ 两种方式、教程页)、小世界(心情主题与夜晚、固定主题、减少动画、星图撤销、人物详情、日记与约定)、导航缓存、时间页、性能与英文界面(中文只允许出现在她自己的内容里);宽度覆盖 1440 / 820 / 390。
|
|
72
72
|
- `node tests/ui/ta.mjs --serve`:打开一个过了三天的示例世界,方便直接看界面。
|
|
73
73
|
- 截图只放在被忽略的 `workspace/` 目录,真实聊天截图和配置不得提交。
|
|
74
|
+
|
|
75
|
+
系统 → 运行开关中的「版本与更新」支持手动检查 npm 最新版本,显示当前版本、上次成功检查与发布说明。五分钟内复用结果,断网时保留上次信息并显示失败;检查不会自动安装或重启。
|
package/package.json
CHANGED
|
@@ -1,110 +1,110 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "luckytri",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "让由技术诞生的她,在时间、记忆、相遇与选择中逐渐形成自己的方向",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"repository": {
|
|
7
|
-
"type": "git",
|
|
8
|
-
"url": "https://github.com/TodayYueC/LuckyTri.git"
|
|
9
|
-
},
|
|
10
|
-
"bugs": {
|
|
11
|
-
"url": "https://github.com/TodayYueC/LuckyTri/issues"
|
|
12
|
-
},
|
|
13
|
-
"homepage": "https://github.com/TodayYueC/LuckyTri",
|
|
14
|
-
"type": "module",
|
|
15
|
-
"bin": {
|
|
16
|
-
"luckytri": "bin/luckytri.js"
|
|
17
|
-
},
|
|
18
|
-
"files": [
|
|
19
|
-
"bin/luckytri.js",
|
|
20
|
-
"server/**/*.js",
|
|
21
|
-
"server/plugins/runner/*.mjs",
|
|
22
|
-
"scripts/launch.js",
|
|
23
|
-
"scripts/start-server.js",
|
|
24
|
-
"scripts/stop.js",
|
|
25
|
-
"scripts/reset-password.js",
|
|
26
|
-
"scripts/setup.js",
|
|
27
|
-
"scripts/runtime.js",
|
|
28
|
-
"scripts/service.js",
|
|
29
|
-
"scripts/browser.js",
|
|
30
|
-
"scripts/proxy-config.js",
|
|
31
|
-
"scripts/backup.js",
|
|
32
|
-
"scripts/recover.js",
|
|
33
|
-
"scripts/import-data.js",
|
|
34
|
-
"scripts/plugin.js",
|
|
35
|
-
"public/app/index.html",
|
|
36
|
-
"public/app/assets/*.js",
|
|
37
|
-
"public/app/assets/*.css",
|
|
38
|
-
"public/app/assets/*.png",
|
|
39
|
-
"public/plugin-kit/v1/bridge.js",
|
|
40
|
-
"public/plugin-kit/v1/kit.css",
|
|
41
|
-
"public/guide.html",
|
|
42
|
-
"public/guide.en.html",
|
|
43
|
-
"public/tutorial.md",
|
|
44
|
-
"public/tutorial.en.md",
|
|
45
|
-
"plugins/weather/index.js",
|
|
46
|
-
"plugins/weather/luckytri-plugin.json",
|
|
47
|
-
"plugins/sdk/index.d.ts",
|
|
48
|
-
"plugins/sdk/testing.js",
|
|
49
|
-
"docs/zh/*.md",
|
|
50
|
-
"docs/en/*.md",
|
|
51
|
-
"docs/brand/*.png",
|
|
52
|
-
".github/SECURITY.md",
|
|
53
|
-
"README.en.md",
|
|
54
|
-
"LICENSE"
|
|
55
|
-
],
|
|
56
|
-
"publishConfig": {
|
|
57
|
-
"access": "public",
|
|
58
|
-
"registry": "https://registry.npmjs.org/"
|
|
59
|
-
},
|
|
60
|
-
"keywords": [
|
|
61
|
-
"qq",
|
|
62
|
-
"onebot",
|
|
63
|
-
"chatbot",
|
|
64
|
-
"ai",
|
|
65
|
-
"memory",
|
|
66
|
-
"webui"
|
|
67
|
-
],
|
|
68
|
-
"engines": {
|
|
69
|
-
"node": ">=24.5"
|
|
70
|
-
},
|
|
71
|
-
"scripts": {
|
|
72
|
-
"launch": "node scripts/launch.js",
|
|
73
|
-
"start": "node scripts/start-server.js",
|
|
74
|
-
"dev:ui": "vite --config studio-web/vite.config.ts",
|
|
75
|
-
"build:ui": "vite build --config studio-web/vite.config.ts",
|
|
76
|
-
"build": "npm run build:ui && npm run docs:build",
|
|
77
|
-
"test": "node --import ./tests/helpers/awake.mjs --test tests/*.test.js",
|
|
78
|
-
"test:clock": "node scripts/dev/test-clock.js",
|
|
79
|
-
"audit:sent": "node --env-file-if-exists=.env scripts/dev/audit-sent.js",
|
|
80
|
-
"test:ui": "node tests/ui/access.mjs && node tests/ui/smoke.js && node tests/ui/ta.mjs && node tests/ui/navigation.mjs && node tests/ui/time.mjs && node tests/ui/time-arrangement.mjs && node tests/ui/performance.mjs && node tests/ui/search.mjs && node tests/ui/storage.mjs && node tests/ui/data-transfer.mjs && node tests/ui/i18n.mjs",
|
|
81
|
-
"setup": "node scripts/setup.js",
|
|
82
|
-
"stop": "node scripts/stop.js",
|
|
83
|
-
"backup": "node scripts/backup.js",
|
|
84
|
-
"recovery": "node scripts/recover.js",
|
|
85
|
-
"docs:build": "node scripts/build-guide.js",
|
|
86
|
-
"plugin": "node scripts/plugin.js",
|
|
87
|
-
"pack:check": "node scripts/pack-check.js",
|
|
88
|
-
"test:package": "node scripts/test-package.js",
|
|
89
|
-
"test:registry": "node scripts/test-package.js --registry",
|
|
90
|
-
"prepack": "npm run build && npm run pack:check",
|
|
91
|
-
"prepublishOnly": "npm run build && npm test && npm run test:package",
|
|
92
|
-
"release:check": "npm run build && npm test && npm run test:ui && npm run test:package",
|
|
93
|
-
"format": "prettier --write bin server studio-web scripts tests plugins package.json",
|
|
94
|
-
"format:check": "prettier --check bin server studio-web scripts tests plugins package.json"
|
|
95
|
-
},
|
|
96
|
-
"dependencies": {
|
|
97
|
-
"express": "^5.1.0",
|
|
98
|
-
"sharp": "^0.35.5",
|
|
99
|
-
"ws": "^8.18.3"
|
|
100
|
-
},
|
|
101
|
-
"devDependencies": {
|
|
102
|
-
"@playwright/test": "^1.55.0",
|
|
103
|
-
"@vitejs/plugin-vue": "^6.0.9",
|
|
104
|
-
"marked": "^18.0.13",
|
|
105
|
-
"prettier": "^3.9.8",
|
|
106
|
-
"typescript": "^7.0.2",
|
|
107
|
-
"vite": "^8.3.0",
|
|
108
|
-
"vue": "^3.5.43"
|
|
109
|
-
}
|
|
110
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "luckytri",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "让由技术诞生的她,在时间、记忆、相遇与选择中逐渐形成自己的方向",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/TodayYueC/LuckyTri.git"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/TodayYueC/LuckyTri/issues"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/TodayYueC/LuckyTri",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"bin": {
|
|
16
|
+
"luckytri": "bin/luckytri.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"bin/luckytri.js",
|
|
20
|
+
"server/**/*.js",
|
|
21
|
+
"server/plugins/runner/*.mjs",
|
|
22
|
+
"scripts/launch.js",
|
|
23
|
+
"scripts/start-server.js",
|
|
24
|
+
"scripts/stop.js",
|
|
25
|
+
"scripts/reset-password.js",
|
|
26
|
+
"scripts/setup.js",
|
|
27
|
+
"scripts/runtime.js",
|
|
28
|
+
"scripts/service.js",
|
|
29
|
+
"scripts/browser.js",
|
|
30
|
+
"scripts/proxy-config.js",
|
|
31
|
+
"scripts/backup.js",
|
|
32
|
+
"scripts/recover.js",
|
|
33
|
+
"scripts/import-data.js",
|
|
34
|
+
"scripts/plugin.js",
|
|
35
|
+
"public/app/index.html",
|
|
36
|
+
"public/app/assets/*.js",
|
|
37
|
+
"public/app/assets/*.css",
|
|
38
|
+
"public/app/assets/*.png",
|
|
39
|
+
"public/plugin-kit/v1/bridge.js",
|
|
40
|
+
"public/plugin-kit/v1/kit.css",
|
|
41
|
+
"public/guide.html",
|
|
42
|
+
"public/guide.en.html",
|
|
43
|
+
"public/tutorial.md",
|
|
44
|
+
"public/tutorial.en.md",
|
|
45
|
+
"plugins/weather/index.js",
|
|
46
|
+
"plugins/weather/luckytri-plugin.json",
|
|
47
|
+
"plugins/sdk/index.d.ts",
|
|
48
|
+
"plugins/sdk/testing.js",
|
|
49
|
+
"docs/zh/*.md",
|
|
50
|
+
"docs/en/*.md",
|
|
51
|
+
"docs/brand/*.png",
|
|
52
|
+
".github/SECURITY.md",
|
|
53
|
+
"README.en.md",
|
|
54
|
+
"LICENSE"
|
|
55
|
+
],
|
|
56
|
+
"publishConfig": {
|
|
57
|
+
"access": "public",
|
|
58
|
+
"registry": "https://registry.npmjs.org/"
|
|
59
|
+
},
|
|
60
|
+
"keywords": [
|
|
61
|
+
"qq",
|
|
62
|
+
"onebot",
|
|
63
|
+
"chatbot",
|
|
64
|
+
"ai",
|
|
65
|
+
"memory",
|
|
66
|
+
"webui"
|
|
67
|
+
],
|
|
68
|
+
"engines": {
|
|
69
|
+
"node": ">=24.5"
|
|
70
|
+
},
|
|
71
|
+
"scripts": {
|
|
72
|
+
"launch": "node scripts/launch.js",
|
|
73
|
+
"start": "node scripts/start-server.js",
|
|
74
|
+
"dev:ui": "vite --config studio-web/vite.config.ts",
|
|
75
|
+
"build:ui": "vite build --config studio-web/vite.config.ts",
|
|
76
|
+
"build": "npm run build:ui && npm run docs:build",
|
|
77
|
+
"test": "node --import ./tests/helpers/awake.mjs --test tests/*.test.js",
|
|
78
|
+
"test:clock": "node scripts/dev/test-clock.js",
|
|
79
|
+
"audit:sent": "node --env-file-if-exists=.env scripts/dev/audit-sent.js",
|
|
80
|
+
"test:ui": "node tests/ui/access.mjs && node tests/ui/smoke.js && node tests/ui/ta.mjs && node tests/ui/navigation.mjs && node tests/ui/time.mjs && node tests/ui/time-arrangement.mjs && node tests/ui/performance.mjs && node tests/ui/search.mjs && node tests/ui/storage.mjs && node tests/ui/data-transfer.mjs && node tests/ui/place-notes-updates.mjs && node tests/ui/i18n.mjs",
|
|
81
|
+
"setup": "node scripts/setup.js",
|
|
82
|
+
"stop": "node scripts/stop.js",
|
|
83
|
+
"backup": "node scripts/backup.js",
|
|
84
|
+
"recovery": "node scripts/recover.js",
|
|
85
|
+
"docs:build": "node scripts/build-guide.js",
|
|
86
|
+
"plugin": "node scripts/plugin.js",
|
|
87
|
+
"pack:check": "node scripts/pack-check.js",
|
|
88
|
+
"test:package": "node scripts/test-package.js",
|
|
89
|
+
"test:registry": "node scripts/test-package.js --registry",
|
|
90
|
+
"prepack": "npm run build && npm run pack:check",
|
|
91
|
+
"prepublishOnly": "npm run build && npm test && npm run test:package",
|
|
92
|
+
"release:check": "npm run build && npm test && npm run test:ui && npm run test:package",
|
|
93
|
+
"format": "prettier --write bin server studio-web scripts tests plugins package.json",
|
|
94
|
+
"format:check": "prettier --check bin server studio-web scripts tests plugins package.json"
|
|
95
|
+
},
|
|
96
|
+
"dependencies": {
|
|
97
|
+
"express": "^5.1.0",
|
|
98
|
+
"sharp": "^0.35.5",
|
|
99
|
+
"ws": "^8.18.3"
|
|
100
|
+
},
|
|
101
|
+
"devDependencies": {
|
|
102
|
+
"@playwright/test": "^1.55.0",
|
|
103
|
+
"@vitejs/plugin-vue": "^6.0.9",
|
|
104
|
+
"marked": "^18.0.13",
|
|
105
|
+
"prettier": "^3.9.8",
|
|
106
|
+
"typescript": "^7.0.2",
|
|
107
|
+
"vite": "^8.3.0",
|
|
108
|
+
"vue": "^3.5.43"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{$ as e,Ct as t,E as n,Et as r,H as i,I as a,J as o,M as s,P as c,Tt as l,U as u,V as d,W as f,X as p,Y as m,Z as h,a as g,ct as _,dt as v,et as y,f as b,gt as x,ht as S,it as C,j as w,lt as T,m as E,n as D,nt as O,o as k,q as A,rt as j,s as M,t as N,ut as P,v as F,vt as I,wt as L,xt as R,yt as z,z as B}from"./Empty-ddEfu0w8.js";import{h as ee,v as V}from"./mind-DYRfFMwh.js";import{c as H,f as U,h as W,m as G,n as K,o as te,p as q,u as J,y as ne}from"./index-oLIXWxsn.js";import{t as re}from"./media-keE52cIX.js";import{t as Y}from"./Field-mIhV5YBA.js";async function ie(e,t){let n=new URLSearchParams({session:e});return t!==void 0&&n.set(`after`,String(t)),E(`/core/events?`+n.toString())}async function ae(e,t={}){let n=new URLSearchParams({session:e});return t.limit&&n.set(`limit`,String(t.limit)),t.compact&&n.set(`compact`,`1`),E(`/core/traces?`+n.toString())}async function X(e){return E(`/core/traces/`+e)}async function oe(e){return E(`/simulate`,`POST`,e)}async function se(e,t){return E(`/decisions/`+e+`/feedback`,`POST`,{tag:t})}async function Z(e){return E(`/core/replay`,`POST`,e)}async function ce(e){return E(`/core/sessions`,`POST`,e)}async function le(e,t){return E(`/core/sessions/`+encodeURIComponent(e),`PATCH`,{enabled:t})}async function ue(e,t){return E(`/core/sessions/`+encodeURIComponent(e)+`/archive`,`PATCH`,{archived:t})}async function de(e){return E(`/core/sessions/`+encodeURIComponent(e),`DELETE`,{})}async function fe(e,t){return E(`/core/sessions/`+encodeURIComponent(e),`PUT`,t)}async function pe(e){return E(`/core/sessions/`+encodeURIComponent(e)+`/summaries`)}async function me(e){return E(`/core/sessions/`+encodeURIComponent(e)+`/context`,`DELETE`,{})}var he={class:`session-list`},ge={class:`list-head`},Q=[`placeholder`,`aria-label`],_e={class:`rows scroll-pane`},ve=[`data-pick`,`aria-current`,`onClick`],ye={class:`who`},be=[`aria-label`],xe=[`title`],Se=[`checked`,`aria-label`,`onChange`],Ce={key:0,class:`muted empty-line`},we={key:1,class:`archive-list`},Te={class:`row`},Ee=[`data-restore-session`,`onClick`],De=[`data-delete-session`,`onClick`],Oe=D(O({__name:`SessionList`,props:{sessions:{},selected:{},unread:{}},emits:[`select`,`add`,`toggle`,`restore`,`remove`],setup(n,{emit:i}){let s=n,c=i,u=R(``),m=A(()=>s.sessions.filter(e=>!e.archived&&`${e.name} ${e.id}`.toLowerCase().includes(u.value.toLowerCase()))),g=A(()=>s.sessions.filter(e=>e.archived));return(i,s)=>(P(),h(`div`,he,[o(`div`,ge,[o(`h2`,null,[e(r(t(a)(`会话`))+` `,1),o(`small`,null,r(m.value.length),1)]),o(`button`,{class:`small primary`,onClick:s[0]||=e=>c(`add`)},r(t(a)(`+ 添加会话`)),1)]),z(o(`input`,{"onUpdate:modelValue":s[1]||=e=>u.value=e,type:`search`,placeholder:t(a)(`搜索名称或号码`),"aria-label":t(a)(`搜索会话`)},null,8,Q),[[d,u.value]]),o(`div`,_e,[(P(!0),h(f,null,v(m.value,e=>(P(),h(`div`,{key:e.id,class:L([`session-row`,{selected:e.id===n.selected,paused:!e.enabled}])},[o(`button`,{class:`row-main`,"data-pick":e.id,"aria-current":e.id===n.selected?`true`:void 0,onClick:t=>c(`select`,e.id)},[o(`span`,{class:`badge`,style:l({"--hue":t(U)(e.id)})},r(e.kind===`private`?t(a)(`私`):t(a)(`群`)),5),o(`span`,ye,[o(`b`,null,r(t(W)(e)),1),o(`small`,null,r(e.enabled?t(a)(`参与中`):t(a)(`已暂停`)),1)]),n.unread[e.id]?(P(),h(`span`,{key:0,class:`unread`,"aria-label":t(a)(`{v} 条没细看`,{v:n.unread[e.id]})},r(n.unread[e.id]),9,be)):p(``,!0)],8,ve),o(`label`,{class:`mini-switch`,title:e.enabled?t(a)(`暂停参与`):t(a)(`开启参与`)},[o(`input`,{type:`checkbox`,checked:e.enabled,"aria-label":t(a)(`参与:{v}`,{v:t(W)(e)}),onChange:t=>c(`toggle`,e)},null,40,Se)],8,xe)],2))),128)),m.value.length?p(``,!0):(P(),h(`p`,Ce,r(t(a)(`暂无匹配的会话。`)),1)),g.value.length?(P(),h(`details`,we,[o(`summary`,null,r(t(a)(`已归档 · {length}`,{length:g.value.length})),1),(P(!0),h(f,null,v(g.value,e=>(P(),h(`article`,{key:e.id},[o(`b`,null,r(t(W)(e)),1),o(`div`,Te,[o(`button`,{class:`small`,"data-restore-session":e.id,onClick:t=>c(`restore`,e.id)},r(t(a)(`恢复`)),9,Ee),o(`button`,{class:`small danger`,"data-delete-session":e.id,onClick:t=>c(`remove`,e.id)},r(t(a)(`永久删除`)),9,De)])]))),128))])):p(``,!0)])]))}}),[[`__scopeId`,`data-v-9b8dcbac`]]),ke={class:`muted`},Ae={key:0,class:`notice`,role:`status`},je=[`pattern`,`inputmode`],Me=[`disabled`],Ne=O({__name:`AddSession`,props:{open:{type:Boolean},channel:{},ready:{type:Boolean}},emits:[`close`,`add`],setup(e,{emit:n}){let i=e,s=R(`group`),c=n,l=A(()=>i.channel===`qqbot`),d=A(()=>l.value?`[0-9A-Za-z_\\-]{8,64}`:`\\d{4,20}`);function f(e){let t=e.target;c(`add`,{...Object.fromEntries(new FormData(t)),channel:i.channel})}return(n,i)=>(P(),m(te,{open:e.open,title:t(a)(`添加群聊 / 私聊`),eyebrow:t(a)(`NEW PLACE`),width:`440px`,onClose:i[1]||=e=>c(`close`)},{default:I(()=>[o(`form`,{id:`addSession`,class:`stack`,onSubmit:u(f,[`prevent`])},[o(`p`,ke,r(t(a)(`添加之后再决定要不要让 TA 参与;开不开口仍由 TA 自己决定。`)),1),l.value&&!e.ready?(P(),h(`p`,Ae,r(t(a)(`请先在「连接 QQ」里填写机器人的 AppID`)),1)):p(``,!0),y(Y,{label:t(a)(`类型`)},{default:I(()=>[y(H,{modelValue:s.value,"onUpdate:modelValue":i[0]||=e=>s.value=e,name:`kind`,"aria-label":t(a)(`类型`),options:[{value:`group`,label:t(a)(`群聊`)},{value:`private`,label:t(a)(`私聊`)}]},null,8,[`modelValue`,`aria-label`,`options`])]),_:1},8,[`label`]),y(Y,{label:l.value?t(a)(`群 openid / 用户 openid`):t(a)(`群号 / QQ 号`),hint:l.value?t(a)(`8–64 位字母、数字、下划线或短横线。官方平台的会话通常会在有人 @ 她或私聊她时自动出现,这里只用于提前登记。`):t(a)(`4–20 位数字`)},{default:I(()=>[o(`input`,{name:`id`,required:``,pattern:d.value,inputmode:l.value?`text`:`numeric`,autocomplete:`off`},null,8,je)]),_:1},8,[`label`,`hint`]),y(Y,{label:t(a)(`显示名称`)},{default:I(()=>[...i[2]||=[o(`input`,{name:`name`,required:``,maxlength:`100`,autocomplete:`off`},null,-1)]]),_:1},8,[`label`]),o(`button`,{class:`primary`,disabled:l.value&&!e.ready},r(t(a)(`添加会话`)),9,Me)],32)]),_:1},8,[`open`,`title`,`eyebrow`]))}}),Pe={class:`transcript`},Fe={class:`t-head`},Ie=[`aria-label`,`title`],Le={class:`t-title`},Re={id:`liveStatus`,class:`faint`},ze={class:`t-tools`},Be=[`disabled`],Ve={id:`liveMessages`,class:`chat-messages scroll-pane`},He={key:0,class:`day-label`},Ue=[`data-status`],We={key:0},Ge={class:`body`},Ke={class:`message-meta`},qe={key:0,class:`chip`,"data-tone":`warn`},Je={class:`text`},Ye=[`aria-expanded`,`onClick`],Xe={key:0,class:`why`},Ze={key:0,class:`muted`},Qe={key:0},$e={key:1},et={key:2,class:`fb`},tt={class:`composer-note`},nt={class:`chip`,"data-tone":`warn`},rt={class:`faint`},it={class:`composer-row`},at={class:`uid`},ot={class:`sr-only`},st=[`title`],ct=[`placeholder`,`onKeydown`],lt={class:`check mention`},ut=[`disabled`],dt={key:1,class:`composer off`},ft={class:`faint`},pt=D(O({__name:`Transcript`,props:{session:{},sessionId:{},events:{},traces:{},decisions:{},status:{},demo:{type:Boolean},compact:{type:Boolean},sending:{type:Boolean}},emits:[`simulate`,`feedback`,`openList`,`openReplay`],setup(n,{expose:g,emit:_}){let b=n,x=_,S=c({glanced:w(`TA 扫了一眼`),silent:w(`TA 看了,没出声`),deferred:w(`TA 睡着了,醒来再看`)}),T=R(`10001`),E=R(``),D=R(!0),O=R(),k=R({}),j=()=>V(s(),{month:`long`,day:`numeric`,weekday:`short`}),F=A(()=>{let e=b.events.map(e=>({type:`message`,key:`m`+e.seq,time:e.time,event:e})),t=b.events[0]?.time??2**53-1;for(let n of b.traces)S[n.status]&&n.time>=t&&e.push({type:`divider`,key:`t`+n.id,time:n.time,status:n.status,reasons:[n.reason].filter(Boolean),count:1});e.sort((e,t)=>e.time-t.time);let n=[],r=``;for(let t of e){let e=j().format(t.time);e!==r&&(r=e,n.push({type:`day`,key:`d`+t.time,time:t.time,label:e}));let i=n[n.length-1];if(t.type===`divider`&&i?.type===`divider`&&i.status===t.status){i.count+=1,t.reasons[0]&&!i.reasons.includes(t.reasons[0])&&i.reasons.push(t.reasons[0]);continue}n.push(t)}return n});function I(e){let t=String(e.payload.text||``);return b.decisions.filter(n=>n.session_id===e.session_id&&n.reply&&n.reply.includes(t)&&Math.abs(n.time-e.time)<6e5).sort((t,n)=>Math.abs(t.time-e.time)-Math.abs(n.time-e.time))[0]}function ee(e){return b.traces.filter(t=>t.status===`sent`&&t.time<=e.time+1e3).sort((e,t)=>t.time-e.time)[0]}async function W(e){if(k.value[e.seq]){let{[e.seq]:t,...n}=k.value;k.value=n;return}k.value={...k.value,[e.seq]:{loading:!0,detail:null}};let t=ee(e),n=null;try{n=t?await X(t.id):null}catch{n=null}k.value[e.seq]&&(k.value={...k.value,[e.seq]:{loading:!1,detail:n}})}async function G(){await C(),O.value?.focus()}function K(){E.value.trim()&&!b.sending&&(x(`simulate`,{userId:T.value,text:E.value,mentioned:D.value}),E.value=``)}return g({focusComposer:G}),(s,c)=>(P(),h(`section`,Pe,[o(`header`,Fe,[n.compact?(P(),h(`button`,{key:0,class:`icon-button`,"aria-label":t(a)(`全部会话`),title:t(a)(`全部会话`),onClick:c[0]||=e=>x(`openList`)},` ☰ `,8,Ie)):p(``,!0),n.session?(P(),h(`span`,{key:1,class:`badge`,style:l({"--hue":t(U)(n.session.id)})},r(n.session.kind===`private`?t(a)(`私`):t(a)(`群`)),5)):p(``,!0),o(`div`,Le,[o(`h2`,null,r(n.session?.name||t(a)(`选择一段对话`)),1),o(`span`,Re,r(n.status),1)]),o(`div`,ze,[o(`button`,{class:`small sim-button`,disabled:!n.sessionId,onClick:G},r(t(a)(`模拟消息`)),9,Be),o(`button`,{class:`small`,onClick:c[1]||=e=>x(`openReplay`)},r(t(a)(`回到那一刻`)),1)])]),o(`div`,Ve,[(P(!0),h(f,null,v(F.value,n=>(P(),h(f,{key:n.key},[n.type===`day`?(P(),h(`div`,He,[o(`span`,null,r(n.label),1)])):n.type===`divider`?(P(),h(`div`,{key:1,class:`divider`,"data-status":n.status},[o(`span`,null,r(t(S)[n.status])+r(n.count>1?` × ${n.count}`:``),1),n.reasons.length?(P(),h(`small`,We,r(n.reasons.slice(0,2).join(`;`)),1)):p(``,!0)],8,Ue)):(P(),h(`article`,{key:2,class:L([`message`,{bot:n.event.role===`assistant`,simulated:n.event.payload.simulated}])},[n.event.role===`assistant`?p(``,!0):(P(),h(`span`,{key:0,class:`avatar`,style:l({"--hue":t(U)(String(n.event.payload.userId||n.event.payload.name))}),"aria-hidden":`true`},r(t(q)(n.event.payload.name)),5)),o(`div`,Ge,[o(`div`,Ke,[o(`b`,null,r(n.event.payload.name),1),o(`time`,null,r(t(J)(n.event.time)),1),n.event.payload.simulated?(P(),h(`span`,qe,r(t(a)(`模拟`)),1)):p(``,!0)]),o(`p`,Je,r(n.event.payload.text),1),n.event.role===`assistant`?(P(),h(f,{key:0},[o(`button`,{class:`text-button why-toggle`,"aria-expanded":!!k.value[n.event.seq],onClick:e=>W(n.event)},r(k.value[n.event.seq]?t(a)(`收起`):t(a)(`为什么这么说`)),9,Ye),k.value[n.event.seq]?(P(),h(`div`,Xe,[k.value[n.event.seq].loading?(P(),h(`p`,Ze,r(t(a)(`正在翻当时的记录…`)),1)):(P(),h(f,{key:1},[k.value[n.event.seq].detail?.data?.decision?.appraisal?(P(),h(`p`,Qe,[o(`b`,null,r(t(a)(`TA 当时的理解:`)),1),e(r(k.value[n.event.seq].detail.data.decision.appraisal),1)])):p(``,!0),o(`p`,null,[o(`b`,null,r(t(a)(`理由:`)),1),e(r(k.value[n.event.seq].detail?.data?.reason||k.value[n.event.seq].detail?.data?.decision?.reason||I(n.event)?.reason||t(a)(`没有留下理由。`)),1)]),k.value[n.event.seq].detail?.data?.snapshot?.knowledge?.length?(P(),h(`p`,$e,[o(`b`,null,r(t(a)(`引用的资料:`)),1),e(r(k.value[n.event.seq].detail.data.snapshot.knowledge.map(e=>e.title).join(`、`)),1)])):p(``,!0),I(n.event)?(P(),h(`label`,et,[e(r(t(a)(`这句怎么样?`))+` `,1),y(H,{"model-value":I(n.event).feedback||``,"aria-label":t(a)(`这句怎么样?`),options:[{value:``,label:t(a)(`选择评价`)},...Object.entries(t(M).health.feedbackLabels||{}).map(([e,t])=>({value:e,label:String(t)}))],"onUpdate:modelValue":e=>x(`feedback`,I(n.event).id,e)},null,8,[`model-value`,`aria-label`,`options`,`onUpdate:modelValue`])])):p(``,!0)],64))])):p(``,!0)],64)):p(``,!0)])],2))],64))),128)),n.events.length?p(``,!0):(P(),m(N,{key:0,title:n.sessionId?t(a)(`等待新的消息`):t(a)(`选择一段对话`),text:t(a)(`群聊与私聊消息会在这里实时出现;TA 扫一眼、没出声也会留下一条分隔线。`)},null,8,[`title`,`text`]))]),n.demo?(P(),h(`form`,{key:0,id:`simulate`,class:`composer`,onSubmit:u(K,[`prevent`])},[o(`div`,tt,[o(`span`,nt,r(t(a)(`模拟消息`)),1),o(`span`,rt,r(t(a)(`作为一条模拟消息走完整流程,写进模拟会话;不会发到 QQ,也不进入真实记忆。`)),1)]),o(`div`,it,[o(`label`,at,[o(`span`,ot,r(t(a)(`体验用户 ID`)),1),z(o(`input`,{"onUpdate:modelValue":c[2]||=e=>T.value=e,name:`userId`,pattern:`\\d{4,20}`,required:``,title:t(a)(`体验用户 ID`)},null,8,st),[[d,T.value]])]),z(o(`textarea`,{ref_key:`composer`,ref:O,"onUpdate:modelValue":c[3]||=e=>E.value=e,name:`text`,rows:`1`,placeholder:t(a)(`以这位群友的身份说一句…`),required:``,onKeydown:i(u(K,[`exact`,`prevent`]),[`enter`])},null,40,ct),[[d,E.value]]),o(`label`,lt,[z(o(`input`,{"onUpdate:modelValue":c[4]||=e=>D.value=e,type:`checkbox`},null,512),[[B,D.value]]),e(r(t(a)(`视为 @`)),1)]),o(`button`,{class:`primary`,disabled:n.sending||!n.sessionId},r(n.sending?t(a)(`TA 在想…`):t(a)(`发送模拟消息`)),9,ut)])],32)):(P(),h(`div`,dt,[o(`span`,ft,r(t(a)(`真实模式下不能模拟消息。想看看 TA 会怎么回,可以「和 TA 聊聊」——那是试聊,什么都不写入。`)),1),o(`button`,{class:`small`,onClick:c[5]||=e=>t(M).chatOpen=!0},r(t(a)(`和 TA 聊聊`)),1)]))]))}}),[[`__scopeId`,`data-v-849aeb0f`]]),mt={class:`panel`},ht={key:0,class:`panel-body`},gt={key:1,class:`panel-body scroll-pane`},_t={class:`here`},vt={class:`facts`},yt={class:`eyebrow`},bt={key:1,class:`muted`},xt={key:2,class:`faint`},St={class:`eyebrow`},Ct={class:`faint`},wt={class:`row actions`},Tt=[`data-toggle`],Et=[`data-archive`],Dt=[`open`],Ot=[`data-session`],kt={class:`faint`},At=[`value`],jt={class:`faint`},Mt={class:`check`},Nt={class:`advanced-policy`},Pt={class:`stack tight`},Ft={class:`check`},It={class:`check`},Lt={class:`check`},Rt={class:`save-bar`},zt={class:`primary`,type:`submit`},Bt={class:`faint`},Vt={class:`fold summary-list`},Ht={key:0,class:`muted`},Ut={class:`faint`},Wt={key:0},Gt={key:2,class:`panel-body feedback-pane`},Kt={class:`faint`},qt={id:`feedbackList`,class:`scroll-pane`},Jt={class:`faint`},Yt={class:`reply-excerpt`},Xt={key:0,class:`muted`},Zt={class:`pagination`},Qt=[`disabled`],$t=[`disabled`],$=6,en=D(O({__name:`SessionPanel`,props:j({session:{},group:{},summaries:{},decisions:{}},{settingsOpen:{type:Boolean,default:!1},settingsOpenModifiers:{},tab:{default:`here`},tabModifiers:{}}),emits:j([`toggle`,`archive`,`clear`,`save`,`feedback`],[`update:settingsOpen`,`update:tab`]),setup(n,{emit:i}){let s=n,l=S(n,`settingsOpen`),m=S(n,`tab`),g=i,_=c([w(`近期细摘要`),w(`中期摘要`),w(`较早摘要`),w(`远期摘要`)]),b=R(0),C=A(()=>s.decisions.filter(e=>e.session_id===s.session?.id&&e.reply)),T=A(()=>Math.max(1,Math.ceil(C.value.length/$))),E=R(!1),D=R({});x(()=>s.session?.policy,e=>{D.value={...e||{}}},{immediate:!0,deep:!0}),x(()=>s.session?.id,()=>{b.value=0,E.value=!1});function O(e){let t=e?.face;return t?[t.role,t.tone,t.content].filter(Boolean).join(`
|
|
2
|
+
|
|
3
|
+
`):``}function k(e){let t=e.target,n=Object.fromEntries(new FormData(t));for(let e of[`aggregateMs`,`maxWaitMs`,`contextMessages`,`maxReply`])n[e]=Number(n[e]);for(let e of[`memory`,`selectiveVision`,`deepCheck`,`compaction`])n[e]=t.elements.namedItem(e).checked;g(`save`,n)}return(i,s)=>(P(),h(`section`,mt,[y(K,{modelValue:m.value,"onUpdate:modelValue":s[0]||=e=>m.value=e,label:t(a)(`这个会话`),items:[{key:`here`,label:t(a)(`这个会话`)},{key:`feedback`,label:t(a)(`反馈`)}]},null,8,[`modelValue`,`label`,`items`]),n.session?m.value===`here`?(P(),h(`div`,gt,[o(`div`,_t,[o(`div`,vt,[o(`div`,null,[o(`span`,yt,r(t(a)(`TA 在这里的样子`)),1),O(n.group)?(P(),h(f,{key:0},[o(`p`,{class:L([`face-body`,E.value?`open`:`clamp`])},r(O(n.group)),3),O(n.group).length>96?(P(),h(`button`,{key:0,type:`button`,class:`text-button`,onClick:s[1]||=e=>E.value=!E.value},r(E.value?t(a)(`收起`):t(a)(`展开完整内容`)),1)):p(``,!0)],64)):(P(),h(`p`,bt,r(t(a)(`还没有形成在这里的样子。`)),1)),n.group?.face?.aspiration?(P(),h(`small`,xt,r(t(a)(`想成为:{aspiration}`,{aspiration:n.group.face.aspiration})),1)):p(``,!0)]),o(`div`,null,[o(`span`,St,r(n.session.kind===`private`?t(a)(`这段私聊给 TA 的感觉`):t(a)(`这个群给 TA 的感觉`)),1),o(`p`,null,r(n.group?.bond?.feel||t(a)(`刚来这里不久`)),1)])]),o(`p`,Ct,r(t(a)(`在这里开不开口由 TA 自己决定:没有参与概率和冷却。TA 对这里每个人的感觉在「人际」里看。`)),1),o(`div`,wt,[o(`button`,{id:`toggleSession`,"data-toggle":n.session.id,class:L({primary:!n.session.enabled}),onClick:s[2]||=e=>g(`toggle`,n.session)},r(n.session.enabled?t(a)(`暂停参与`):t(a)(`开启参与`)),11,Tt),o(`button`,{"data-archive":n.session.id,onClick:s[3]||=e=>g(`archive`,n.session.id)},r(t(a)(`归档`)),9,Et),o(`button`,{id:`clearLiveContext`,onClick:s[4]||=e=>g(`clear`)},r(t(a)(`清空上下文`)),1)]),o(`details`,{class:`fold session-settings`,open:l.value,onToggle:s[19]||=e=>l.value=e.target.open},[o(`summary`,null,r(t(a)(`会话设置`)),1),(P(),h(`form`,{key:n.session.id,"data-session":n.session.id,class:`stack tight`,onSubmit:u(k,[`prevent`]),onInput:s[17]||=e=>t(M).dirty=!0,onChange:s[18]||=e=>t(M).dirty=!0},[o(`p`,kt,r(t(a)(`所有会话和独处都用模型库里的默认模型;其余已启用的模型按列表顺序做备用。她在这个聊天窗里用什么样子,由她自己从经历里决定。`)),1),o(`label`,null,[e(r(t(a)(`会话名称`))+` `,1),o(`input`,{name:`name`,maxlength:`100`,autocomplete:`off`,value:n.session.name},null,8,At),o(`small`,jt,r(t(a)(`官方机器人平台不提供群名称,可以在这里自己起一个`)),1)]),o(`label`,Mt,[z(o(`input`,{name:`selectiveVision`,type:`checkbox`,"onUpdate:modelValue":s[5]||=e=>D.value.selectiveVision=e,onInput:s[6]||=u(()=>{},[`stop`])},null,544),[[B,D.value.selectiveVision]]),e(r(t(a)(`节能看图:只在被 @ 或明确要求时,看这一条和附近的图`)),1)]),o(`details`,Nt,[o(`summary`,null,r(t(a)(`高级策略`)),1),o(`div`,Pt,[o(`label`,null,[e(r(t(a)(`聚合窗口 ms`)),1),z(o(`input`,{name:`aggregateMs`,type:`number`,"onUpdate:modelValue":s[7]||=e=>D.value.aggregateMs=e},null,512),[[d,D.value.aggregateMs,void 0,{number:!0}]])]),o(`label`,null,[e(r(t(a)(`最长等待 ms`)),1),z(o(`input`,{name:`maxWaitMs`,type:`number`,"onUpdate:modelValue":s[8]||=e=>D.value.maxWaitMs=e},null,512),[[d,D.value.maxWaitMs,void 0,{number:!0}]])]),o(`label`,null,[e(r(t(a)(`近期原文条数(10–500)`)),1),z(o(`input`,{name:`contextMessages`,type:`number`,min:`10`,max:`500`,"onUpdate:modelValue":s[9]||=e=>D.value.contextMessages=e},null,512),[[d,D.value.contextMessages,void 0,{number:!0}]])]),o(`label`,null,[e(r(t(a)(`一轮总字数`)),1),z(o(`input`,{name:`maxReply`,type:`number`,"onUpdate:modelValue":s[10]||=e=>D.value.maxReply=e},null,512),[[d,D.value.maxReply,void 0,{number:!0}]])]),o(`label`,Ft,[z(o(`input`,{name:`compaction`,type:`checkbox`,"onUpdate:modelValue":s[11]||=e=>D.value.compaction=e,onInput:s[12]||=u(()=>{},[`stop`])},null,544),[[B,D.value.compaction]]),e(r(t(a)(`上下文压缩:更早的聊天定期整理成分层摘要,越近越详细`)),1)]),o(`label`,It,[z(o(`input`,{name:`memory`,type:`checkbox`,"onUpdate:modelValue":s[13]||=e=>D.value.memory=e,onInput:s[14]||=u(()=>{},[`stop`])},null,544),[[B,D.value.memory]]),e(r(t(a)(`长期记忆`)),1)]),o(`label`,Lt,[z(o(`input`,{name:`deepCheck`,type:`checkbox`,"onUpdate:modelValue":s[15]||=e=>D.value.deepCheck=e,onInput:s[16]||=u(()=>{},[`stop`])},null,544),[[B,D.value.deepCheck]]),e(r(t(a)(`倾诉、纠正和危机时额外复审一次回复`)),1)])])]),o(`div`,Rt,[o(`button`,zt,r(t(a)(`保存会话设置`)),1),o(`small`,Bt,r(t(M).dirty?t(a)(`有未保存的修改`):t(a)(`保存后下一轮生效`)),1)])],40,Ot))],40,Dt),o(`details`,Vt,[o(`summary`,null,r(t(a)(`语境摘要 · {length} 段`,{length:n.summaries.length})),1),n.summaries.length?p(``,!0):(P(),h(`p`,Ht,r(t(a)(`还没有摘要。聊天超过近期原文条数后,更早的内容会自动整理到这里。`)),1)),(P(!0),h(f,null,v(n.summaries,e=>(P(),h(`article`,{key:e.id,class:`summary`},[o(`header`,null,[o(`b`,null,r(t(_)[e.level]||t(a)(`摘要`)),1),o(`small`,Ut,r(t(a)(`{period} · {messages} 条消息`,{period:e.period,messages:e.messages})),1)]),o(`p`,null,r(e.summary),1),e.keyPoints?.length?(P(),h(`ul`,Wt,[(P(!0),h(f,null,v(e.keyPoints,(e,n)=>(P(),h(`li`,{key:n},r(e.open?t(a)(`未完:`):``)+r(e.text),1))),128))])):p(``,!0)]))),128))])])])):(P(),h(`div`,Gt,[o(`p`,Kt,r(t(a)(`针对具体回复评价口吻;这是 TA 在这个会话里听到的话,不会改写天性。`)),1),o(`div`,qt,[(P(!0),h(f,null,v(C.value.slice(b.value*$,b.value*$+$),n=>(P(),h(`article`,{key:n.id,class:`feedback-item`},[o(`time`,Jt,r(t(J)(n.time)),1),o(`p`,Yt,r(n.reply),1),o(`label`,null,[e(r(t(a)(`这句回复怎么样?`))+` `,1),y(H,{"data-feedback":n.id,"model-value":n.feedback||``,"aria-label":t(a)(`这句回复怎么样?`),options:[{value:``,label:t(a)(`选择评价`)},...Object.entries(t(M).health.feedbackLabels||{}).map(([e,t])=>({value:e,label:String(t)}))],"onUpdate:modelValue":e=>g(`feedback`,n.id,e)},null,8,[`data-feedback`,`model-value`,`aria-label`,`options`,`onUpdate:modelValue`])])]))),128)),C.value.length?p(``,!0):(P(),h(`p`,Xt,r(t(a)(`还没有可以评价的回复。`)),1))]),o(`div`,Zt,[o(`button`,{class:`small`,disabled:b.value===0,onClick:s[20]||=e=>b.value--},`←`,8,Qt),o(`span`,null,r(b.value+1)+` / `+r(T.value),1),o(`button`,{class:`small`,disabled:b.value+1>=T.value,onClick:s[21]||=e=>b.value++},` → `,8,$t)])])):(P(),h(`div`,ht,[y(N,{title:t(a)(`还没有选中会话`),text:t(a)(`从左边选一个群聊或私聊。`)},null,8,[`title`,`text`])]))]))}}),[[`__scopeId`,`data-v-96fbad3d`]]),tn={class:`replay`},nn={class:`col source`},rn={class:`col-head`},an={id:`events`,class:`scroll-pane`},on={key:0},sn={key:1,class:`muted`},cn=[`disabled`],ln={class:`faint`},un={class:`col`},dn={class:`col-head`},fn={id:`traces`,class:`scroll-pane`},pn=[`data-trace`,`onClick`],mn=[`data-tone`],hn={key:0,class:`muted`},gn={class:`col`},_n={class:`col-head`},vn={class:`scroll-pane inspect`},yn={key:0,class:`metrics`},bn={id:`traceTokens`},xn={key:1,class:`notice`},Sn={id:`traceDetail`},Cn=D(O({__name:`ReplaySheet`,props:{open:{type:Boolean},sessionId:{},events:{}},emits:[`close`,`load`],setup(n,{emit:i}){let s=n,l=i,g=c({sent:w(`开口了`),silent:w(`没出声`),glanced:w(`扫了一眼`),deferred:w(`睡着了`),running:w(`处理中`),error:w(`失败`),complete:w(`完成`),stale:w(`旧稿作废`),cancelled:w(`已取消`),interrupted:w(`已中断`)}),_=c({live:w(`真实聊天`),demo:w(`模拟预览`),replay:w(`测试回放`),memory:w(`记忆整理`),summary:w(`语境压缩`)}),y=R([]),b=R(null),S=R(``),C=R(``),T=R(!1),E=R(``);async function D(){s.sessionId&&(y.value=await ae(s.sessionId))}function O(){let e=s.events.map(e=>Number(e.seq));e.length&&(S.value||=String(Math.min(...e)),C.value||=String(Math.max(...e)))}async function k(){if(!T.value){T.value=!0;try{F(a(`回放正在运行`));let e=await Z({session:s.sessionId,from:Number(S.value),to:Number(C.value)});E.value=JSON.stringify(e,null,2),F(a(`回放结束`)),await D()}catch(e){F(e.message,!0)}finally{T.value=!1}}}async function A(e){b.value=await X(e),E.value=JSON.stringify(b.value,null,2)}function j(e){return e?a(`输入 {v}(缓存读 {v2} / 写 {v3})· 输出 {v4}`,{v:G(e.input),v2:G(e.cachedRead),v3:G(e.cacheWrite),v4:G(e.output)}):`—`}return x(()=>[s.open,s.sessionId],()=>{s.open&&(S.value=``,C.value=``,b.value=null,O(),D())},{immediate:!0}),x(()=>s.events.length,O),(i,s)=>(P(),m(te,{open:n.open,title:t(a)(`回到那一刻`),eyebrow:`REPLAY`,width:`1180px`,onClose:s[3]||=e=>l(`close`)},{default:I(()=>[o(`div`,tn,[o(`section`,nn,[o(`div`,rn,[o(`h3`,null,r(t(a)(`历史消息`)),1),o(`button`,{id:`loadMessages`,class:`small`,onClick:s[0]||=e=>{l(`load`),D()}},r(t(a)(`↻ 加载`)),1)]),o(`div`,an,[n.events.length?(P(),h(`table`,on,[o(`thead`,null,[o(`tr`,null,[o(`th`,null,r(t(a)(`序号`)),1),o(`th`,null,r(t(a)(`发送者`)),1),o(`th`,null,r(t(a)(`消息`)),1)])]),o(`tbody`,null,[(P(!0),h(f,null,v([...n.events].reverse(),e=>(P(),h(`tr`,{key:e.seq},[o(`td`,null,r(e.seq),1),o(`td`,null,r(e.payload.name),1),o(`td`,null,r(e.payload.text),1)]))),128))])])):(P(),h(`p`,sn,r(t(a)(`当前会话暂无历史消息。`)),1))]),o(`form`,{class:`range`,onSubmit:u(k,[`prevent`])},[o(`label`,null,[e(r(t(a)(`起始序号`)),1),z(o(`input`,{"onUpdate:modelValue":s[1]||=e=>S.value=e,name:`from`,type:`number`,required:``},null,512),[[d,S.value]])]),o(`label`,null,[e(r(t(a)(`截止序号`)),1),z(o(`input`,{"onUpdate:modelValue":s[2]||=e=>C.value=e,name:`to`,type:`number`,required:``},null,512),[[d,C.value]])]),o(`button`,{id:`replay`,class:`primary`,disabled:T.value||!n.events.length},r(T.value?t(a)(`正在回放…`):t(a)(`回放这段对话`)),9,cn),o(`p`,ln,r(t(a)(`隔离回放:只测试回复,不发送 QQ,不修改真实记忆和 TA 的心智。`)),1)],32)]),o(`section`,un,[o(`div`,dn,[o(`h3`,null,r(t(a)(`处理记录`)),1)]),o(`div`,fn,[(P(!0),h(f,null,v(y.value,e=>(P(),h(`button`,{key:e.id,"data-trace":e.id,class:L([`trace-row`,{selected:b.value?.id===e.id}]),onClick:t=>A(e.id)},[o(`span`,null,[o(`time`,null,r(t(J)(e.time)),1),o(`small`,{class:`chip`,"data-tone":e.status===`error`?`danger`:`quiet`},r(t(g)[e.status]||e.status),9,mn)]),o(`p`,null,r(e.reason||e.error||t(a)(`查看处理详情`)),1)],10,pn))),128)),y.value.length?p(``,!0):(P(),h(`p`,hn,r(t(a)(`有新的消息处理记录后会显示在这里。`)),1))])]),o(`section`,gn,[o(`div`,_n,[o(`h3`,null,r(t(a)(`运行详情`)),1)]),o(`div`,vn,[b.value?(P(),h(`div`,yn,[o(`span`,null,[e(r(t(a)(`模式`)),1),o(`b`,null,r(t(_)[b.value.mode]||b.value.mode),1)]),o(`span`,null,[e(r(t(a)(`耗时`)),1),o(`b`,null,r(b.value.data?.elapsed??`—`)+` ms`,1)]),o(`span`,null,[e(r(t(a)(`模型调用`)),1),o(`b`,null,r(t(a)(`{v} 次`,{v:b.value.data?.calls?.length??0})),1)]),o(`span`,bn,[s[4]||=e(`Token`,-1),o(`b`,null,r(j(b.value.data?.tokens)),1)])])):p(``,!0),b.value?(P(),h(`p`,xn,r(b.value.reason||b.value.data?.decision?.reason||t(a)(`展开下方查看上下文、模型输入与原始输出。`)),1)):p(``,!0),o(`pre`,Sn,r(E.value||t(a)(`选择一条处理记录,查看最终上下文、Prompt、原始输出、Token 与耗时。`)),1)])])])]),_:1},8,[`open`,`title`]))}}),[[`__scopeId`,`data-v-839b3181`]]),wn={key:0,class:`card col list-col`},Tn={class:`card col talk-col`},En={class:`card col panel-col`},Dn={class:`sheet-list`},On=D(O({__name:`ChatsPage`,setup(e){let r=re(`(max-width: 1100px)`),i=A(()=>M.core?.sessions||[]),c=A(()=>i.value.filter(e=>!e.archived)),l=sessionStorage.activeSession,u=R(c.value.some(e=>e.id===l)?l:c.value[0]?.id||``),d=A(()=>c.value.find(e=>e.id===u.value)||null),f=R([]),v=R([]),S=R([]),w=R([]),E=R({}),D=R(``),O=R(!1),j=R(!1),N=R(!1),z=R(M.sub===`settings`),B=R(M.sub===`replay`),V=R(`here`),H=A(()=>M.health?.decisions||[]),U=A(()=>w.value.find(e=>e.session===u.value)||null),W=!1,G=!1,K=!1,q=``,J=0,Y=null,X=0;async function Z(e=!1){if(!u.value)return;if(W){G=!0,K||=e;return}let t=u.value,n=e||q!==t;W=!0;try{let[e,r]=await Promise.all([ie(t,n?void 0:J),ae(t,{limit:30,compact:!0})]);if(u.value!==t)return;let i=document.getElementById(`liveMessages`),o=q!==t||!i||i.scrollHeight-i.scrollTop-i.clientHeight<80;n?(f.value=e.reverse(),J=0):e.length&&(f.value=[...f.value,...e]);for(let t of e)J=Math.max(J,Number(t.seq)||0);!n&&e.length===100&&(G=!0),v.value=r,q=t,await C();let c=document.getElementById(`liveMessages`);c&&o&&(c.scrollTop=c.scrollHeight),D.value=a(`实时同步 · `)+new Date().toLocaleTimeString(s())}catch(e){D.value=a(`同步失败:`)+e.message}finally{if(W=!1,u.value!==t)G=!1,Z();else if(G){let e=K;G=!1,K=!1,Z(e)}}}async function he(){try{let[e,t]=await Promise.all([ee.bonds(),ee.overview()]);w.value=e.groups,E.value=Object.fromEntries(t.attention.map(e=>[e.session,e.unread]))}catch{}}x(u,e=>{if(Y?.abort(),e&&(sessionStorage.activeSession=e),f.value=[],v.value=[],S.value=[],q=``,J=0,G=!1,K=!1,N.value=!1,Z(),!e)return;pe(e).then(t=>{u.value===e&&(S.value=[...t].reverse())}).catch(()=>{});let t=new AbortController;Y=t;let n=``;ne(e=>{let t=Number(e?.messages);Number.isSafeInteger(t)&&t<J&&(q=``,J=0,f.value=[]);let r=JSON.stringify(e),i=n!==``&&r!==n;n=r,i&&Z()},{session:e,signal:t.signal,reconnectMs:1e3})},{immediate:!0}),x(c,e=>{e.some(e=>e.id===u.value)||(u.value=e[0]?.id||``)}),x(V,async e=>{if(e===`feedback`)try{M.health=await b()}catch{}}),x(B,e=>k(e?`replay`:z.value?`settings`:``)),x(()=>M.sub,e=>{e===`replay`&&(B.value=!0),e===`settings`&&(z.value=!0)}),x(()=>M.pulse,he),_(()=>{he(),X=window.setInterval(()=>Z(!0),15e3)}),T(()=>{clearInterval(X),Y?.abort()});async function ge(e){try{let t=await ce(e);await g(),u.value=t?.sessionId||`${e.kind}:${e.id}`,z.value=!0,V.value=`here`,j.value=!1,F(a(`会话已添加`))}catch(e){F(e.message,!0)}}async function Q(e){await le(e.id,!e.enabled),await g()}async function _e(e){await ue(e,!0),await g()}async function ve(e){await ue(e,!1),await g()}async function ye(e){await n(a(`永久删除这个会话?它的消息和设置都会消失。`),{title:a(`永久删除`),confirmText:a(`删除`),danger:!0})&&(await de(e),await g())}async function be(e){if(d.value)try{await fe(d.value.id,{...e,name:String(e.name||``).trim()||d.value.name}),M.dirty=!1,F(a(`会话配置已保存`)),await g()}catch(e){F(e.message,!0)}}async function xe(){u.value&&await n(a(`确定清空这个会话的消息上下文吗?长期记忆不会删除。`),{title:a(`清空上下文`),confirmText:a(`清空`),danger:!0})&&(await me(u.value),f.value=[],v.value=[],q=``,J=0,await Z(!0))}async function Se(e){if(!O.value&&u.value){O.value=!0;try{let t=await oe({sessionId:u.value,...e});F(t.reason||a(`已发送`)),M.health=await b(),await Z()}catch(e){F(e.message,!0)}finally{O.value=!1}}}async function Ce(e,t){try{await se(e,t),F(a(`反馈已保存`)),M.health=await b()}catch(e){F(e.message,!0)}}return(e,n)=>(P(),h(`div`,{class:L([`page chats`,{compact:t(r)}])},[t(r)?p(``,!0):(P(),h(`aside`,wn,[y(Oe,{sessions:i.value,selected:u.value,unread:E.value,onSelect:n[0]||=e=>u.value=e,onAdd:n[1]||=e=>j.value=!0,onToggle:Q,onRestore:ve,onRemove:ye},null,8,[`sessions`,`selected`,`unread`])])),o(`div`,Tn,[y(pt,{"session-id":u.value,session:d.value,events:f.value,traces:v.value,decisions:H.value,status:D.value||t(a)(`请选择会话`),demo:!!t(M).health.settings.demo,compact:t(r),sending:O.value,onSimulate:Se,onFeedback:Ce,onOpenList:n[2]||=e=>N.value=!0,onOpenReplay:n[3]||=e=>B.value=!0},null,8,[`session-id`,`session`,`events`,`traces`,`decisions`,`status`,`demo`,`compact`,`sending`])]),o(`aside`,En,[y(en,{"settings-open":z.value,"onUpdate:settingsOpen":n[4]||=e=>z.value=e,tab:V.value,"onUpdate:tab":n[5]||=e=>V.value=e,session:d.value,group:U.value,summaries:S.value,decisions:H.value,onToggle:Q,onArchive:_e,onClear:xe,onSave:be,onFeedback:Ce},null,8,[`settings-open`,`tab`,`session`,`group`,`summaries`,`decisions`])]),t(r)?(P(),m(te,{key:1,open:N.value,title:t(a)(`全部会话`),eyebrow:`CHATS`,width:`400px`,onClose:n[8]||=e=>N.value=!1},{default:I(()=>[o(`div`,Dn,[y(Oe,{sessions:i.value,selected:u.value,unread:E.value,onSelect:n[6]||=e=>u.value=e,onAdd:n[7]||=e=>j.value=!0,onToggle:Q,onRestore:ve,onRemove:ye},null,8,[`sessions`,`selected`,`unread`])])]),_:1},8,[`open`,`title`])):p(``,!0),y(Ne,{open:j.value,channel:t(M).health?.connection?.channel===`qqbot`?`qqbot`:`onebot`,ready:!!t(M).health?.connection?.qqbot?.appId,onClose:n[9]||=e=>j.value=!1,onAdd:ge},null,8,[`open`,`channel`,`ready`]),y(Cn,{open:B.value,"session-id":u.value,events:f.value,onClose:n[10]||=e=>B.value=!1,onLoad:n[11]||=e=>Z(!0)},null,8,[`open`,`session-id`,`events`])],2))}}),[[`__scopeId`,`data-v-c328f9fe`]]);export{On as default};
|