luckytri 1.0.1 → 1.0.2
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/guide.md +10 -0
- package/docs/zh/guide.md +10 -0
- package/package.json +3 -2
- package/public/app/assets/{ChatsPage-B9Odvzfz.js → ChatsPage-BhlJHseG.js} +1 -1
- package/public/app/assets/{Empty-SkA8PyMo.js → Empty-DP6WMGHi.js} +1 -1
- package/public/app/assets/{Field-BjLhi8pL.js → Field-CtbdqaiB.js} +1 -1
- package/public/app/assets/{HeartPage-CscKqMsr.js → HeartPage-32BeTPn2.js} +1 -1
- package/public/app/assets/{LifePage-BHCmBHlH.js → LifePage-CxSm0XKI.js} +1 -1
- package/public/app/assets/{MemoryPage-Bhs2xa1k.js → MemoryPage-BeKBcPCY.js} +1 -1
- package/public/app/assets/{NaturePage-CaPIar_5.js → NaturePage-NEPYl2HS.js} +1 -1
- package/public/app/assets/{PeoplePage-CuwSSVeX.js → PeoplePage-DxtpekwM.js} +1 -1
- package/public/app/assets/{PluginsPage-BhVm1SUi.js → PluginsPage-DksEZbUU.js} +1 -1
- package/public/app/assets/{SystemPage-5yYqyUgR.css → SystemPage-BkRu0Rvx.css} +1 -1
- package/public/app/assets/SystemPage-BvzJlHuY.js +1 -0
- package/public/app/assets/{TimePage-BUm4eUzB.js → TimePage-7-awH5XL.js} +1 -1
- package/public/app/assets/{index-BIAdfObg.js → index-4rItIkD-.js} +3 -3
- package/public/app/assets/{knowledge-DNDLyN9m.js → knowledge-C6_HvoyB.js} +1 -1
- package/public/app/assets/{media-CKVAvML2.js → media-SMfTT-yc.js} +1 -1
- package/public/app/index.html +2 -2
- package/public/guide.en.html +43 -3
- package/public/guide.html +26 -3
- package/public/tutorial.en.md +10 -0
- package/public/tutorial.md +10 -0
- package/scripts/import-data.js +128 -0
- package/server/app.js +3 -1
- package/server/i18n/errors.js +36 -0
- package/server/index.js +46 -2
- package/server/knowledge/schema.js +12 -8
- package/server/storage/archive.js +5 -4
- package/server/storage/backup-cleanup.js +1 -0
- package/server/storage/data-package.js +298 -0
- package/server/storage/data-transfer-api.js +50 -0
- package/server/storage/data-transfer-worker.js +18 -0
- package/server/storage/data-transfer.js +415 -0
- package/server/storage/store.js +5 -2
- package/public/app/assets/SystemPage-Chm5fiGP.js +0 -1
package/docs/en/guide.md
CHANGED
|
@@ -170,6 +170,16 @@ Cleanup verifies a retained automatic backup of this instance from the last 72 h
|
|
|
170
170
|
|
|
171
171
|
To restore, stop the service, move the current `data/friend.db` and its `-wal` and `-shm` files away, then copy the chosen backup to `data/friend.db`. When `DB_PATH` is set, work on that path. Never keep an old WAL file next to a restored database. The safer way is `npm run recovery`, which verifies a backup and restores it into a brand new file; see `docs/en/recovery.md`.
|
|
172
172
|
|
|
173
|
+
### Import and export from the studio
|
|
174
|
+
|
|
175
|
+
"System → Data and backups" provides "Export data package" and "Choose import file". A `.luckytri` package contains chats, memories, relationships, personal state, diaries, tasks, work versions, knowledge text and settings stored in the database, including saved credentials. Management passwords and login sessions are not migrated. Plugin programs, original knowledge files and the local `.env` are outside the package. Export uses a consistent snapshot while the instance continues running and streams large downloads.
|
|
176
|
+
|
|
177
|
+
Imports accept `.luckytri` packages and existing `.db` / SQLite backups. The default upload limit is 10 GiB; adjust `DATA_TRANSFER_MAX_GB` (1–100) in `.env`. Uploads are checked for package SHA-256, database integrity, references and supported structures. Older versions are upgraded only in staging. The preview shows the name, version and record counts before current data changes, so it can be cancelled.
|
|
178
|
+
|
|
179
|
+
Confirming "Import and restart" stops the instance, retains a complete `luckytri-before-import-*.db` snapshot, replaces the data and restarts automatically. The local management password, current logins, QQ connection settings and backup cleanup rules are preserved. Automatic replies are turned off and plugin execution grants reset. Review connections, models and tasks before enabling replies; reinstall plugins or review their permissions. Import replaces the whole database rather than merging records. Pre-import snapshots can be managed manually and are excluded from scheduled full-backup cleanup.
|
|
180
|
+
|
|
181
|
+
The server removes the export copy after download. Cancelled, expired and interrupted staging files are reclaimed; unused previews expire after one hour. Failed imports retain or restore the original database rather than starting with a partial file.
|
|
182
|
+
|
|
173
183
|
## 9. Troubleshooting
|
|
174
184
|
|
|
175
185
|
| Symptom | Check first |
|
package/docs/zh/guide.md
CHANGED
|
@@ -170,6 +170,16 @@ TA 的一切都存在这一个数据库里,所以服务运行时会自动备
|
|
|
170
170
|
|
|
171
171
|
恢复时先停止服务,把当前 `data/friend.db` 及同名 `-wal`、`-shm` 移开,再把选中的备份复制为 `data/friend.db`。设置了 `DB_PATH` 时操作该路径。不要把旧的 WAL 文件和恢复后的数据库放在一起。更稳妥的做法是用 `npm run recovery` 校验并恢复到一个全新的文件,见 `docs/zh/recovery.md`。
|
|
172
172
|
|
|
173
|
+
### 从管理台导入与导出
|
|
174
|
+
|
|
175
|
+
「系统 → 数据与备份」提供「导出数据包」和「选择导入文件」。导出的 `.luckytri` 文件包含数据库内的聊天、记忆、关系、个人状态、日记、待办、作品版本、知识文本和设置,也包含保存在设置中的密钥。管理密码和登录会话不随数据包迁移;插件程序、知识库原始文件及本机 `.env` 不在其中。导出读取一致快照,实例可以继续运行,大文件通过流式传输下载。
|
|
176
|
+
|
|
177
|
+
导入支持 `.luckytri` 数据包及已有 `.db` / SQLite 备份。默认单个文件最多 10 GiB,可用 `.env` 中的 `DATA_TRANSFER_MAX_GB`(1–100)调整。上传后先校验数据包 SHA-256、数据库完整性、引用和结构,旧版本只在暂存副本上升级,界面会显示姓名、版本和记录数量。此时尚未改变当前数据,可以取消。
|
|
178
|
+
|
|
179
|
+
确认「导入并重启」后,程序停止实例,保留一份完整的 `luckytri-before-import-*.db` 快照,再替换数据并自动重启。本机管理密码、当前登录、QQ 连接配置和备份整理规则保留。导入后的自动回复关闭,插件执行权限重置;检查连接、模型和待办后可重新开启,插件需重新安装或确认权限。导入是替换整份数据,不与当前记录合并;原有快照可在备份列表手动管理,定时清理完整备份不会删除它。
|
|
180
|
+
|
|
181
|
+
下载完成后删除服务器导出副本;取消、失效或中断的暂存文件会回收,未使用的预览默认一小时失效。导入失败时保留或恢复原数据,不会把不完整的文件交给实例运行。
|
|
182
|
+
|
|
173
183
|
## 9. 常见问题
|
|
174
184
|
|
|
175
185
|
| 现象 | 先检查 |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "luckytri",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "让由技术诞生的她,在时间、记忆、相遇与选择中逐渐形成自己的方向",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"scripts/proxy-config.js",
|
|
31
31
|
"scripts/backup.js",
|
|
32
32
|
"scripts/recover.js",
|
|
33
|
+
"scripts/import-data.js",
|
|
33
34
|
"scripts/plugin.js",
|
|
34
35
|
"public/app/index.html",
|
|
35
36
|
"public/app/assets/*.js",
|
|
@@ -76,7 +77,7 @@
|
|
|
76
77
|
"test": "node --import ./tests/helpers/awake.mjs --test tests/*.test.js",
|
|
77
78
|
"test:clock": "node scripts/dev/test-clock.js",
|
|
78
79
|
"audit:sent": "node --env-file-if-exists=.env scripts/dev/audit-sent.js",
|
|
79
|
-
"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/i18n.mjs",
|
|
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",
|
|
80
81
|
"setup": "node scripts/setup.js",
|
|
81
82
|
"stop": "node scripts/stop.js",
|
|
82
83
|
"backup": "node scripts/backup.js",
|
|
@@ -1,3 +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-SkA8PyMo.js";import{t as V}from"./formatters-ZmW_xFHw.js";import{F as ee,c as H,f as te,h as U,j as W,m as G,n as K,o as ne,p as q,u as J}from"./index-BIAdfObg.js";import{t as re}from"./media-CKVAvML2.js";import{t as Y}from"./Field-BjLhi8pL.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(te)(e.id)})},r(e.kind===`private`?t(a)(`私`):t(a)(`群`)),5),o(`span`,ye,[o(`b`,null,r(t(U)(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(U)(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(U)(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(ne,{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 U(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 W(){await C(),O.value?.focus()}function G(){E.value.trim()&&!b.sending&&(x(`simulate`,{userId:T.value,text:E.value,mentioned:D.value}),E.value=``)}return g({focusComposer:W}),(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(te)(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:W},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(te)(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=>U(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(G,[`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(G,[`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(`
|
|
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-DP6WMGHi.js";import{t as V}from"./formatters-ZmW_xFHw.js";import{F as ee,c as H,f as te,h as U,j as W,m as G,n as K,o as ne,p as q,u as J}from"./index-4rItIkD-.js";import{t as re}from"./media-SMfTT-yc.js";import{t as Y}from"./Field-CtbdqaiB.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(te)(e.id)})},r(e.kind===`private`?t(a)(`私`):t(a)(`群`)),5),o(`span`,ye,[o(`b`,null,r(t(U)(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(U)(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(U)(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(ne,{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 U(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 W(){await C(),O.value?.focus()}function G(){E.value.trim()&&!b.sending&&(x(`simulate`,{userId:T.value,text:E.value,mentioned:D.value}),E.value=``)}return g({focusComposer:W}),(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(te)(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:W},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(te)(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=>U(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(G,[`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(G,[`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
2
|
|
|
3
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(ne,{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||[]),te=A(()=>w.value.find(e=>e.session===u.value)||null),U=!1,G=!1,K=!1,q=``,J=0,Y=null,X=0;async function Z(e=!1){if(!u.value)return;if(U){G=!0,K||=e;return}let t=u.value,n=e||q!==t;U=!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(U=!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([W.bonds(),W.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=``;ee(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:te.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(ne,{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};
|