ec-web 0.0.20 → 0.0.22
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/dist/ipc-client.js +7 -1
- package/dist/paths.js +18 -1
- package/dist/server.js +159 -28
- package/dist/sources/aid.js +69 -49
- package/dist/sources/baseagent-detector.js +60 -6
- package/dist/sources/basic-settings.js +818 -0
- package/dist/sources/gateway.js +5 -4
- package/dist/sources/monitor.js +22 -5
- package/dist/sources/msg.js +4 -96
- package/dist/sources/relation-roles.js +216 -207
- package/dist/sources/role-definitions.js +162 -331
- package/dist/sources/session-codex.js +207 -84
- package/dist/sources/system.js +10 -9
- package/dist/sources/triggers.js +82 -13
- package/dist/sources/types.js +20 -1
- package/dist/static/app.js +175 -15
- package/dist/static/basic-settings.js +1576 -0
- package/dist/static/index.html +43 -1
- package/dist/static/style.css +586 -2
- package/ecweb-wrapper.cjs +5 -1
- package/package.json +1 -1
package/dist/sources/gateway.js
CHANGED
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { resolvePaths } from '../paths.js';
|
|
12
12
|
import { ipcQuery } from '../ipc-client.js';
|
|
13
|
-
|
|
13
|
+
import { watchMenuRequestAuth } from './types.js';
|
|
14
|
+
async function getSnapshot(params = {}) {
|
|
14
15
|
const sock = resolvePaths().socket;
|
|
15
|
-
const resp = await ipcQuery(sock, { type: 'menu.exec', payload: { type: 'menu.query', name: 'gateway', id: 'ecw-gateway-snap' }, auth:
|
|
16
|
+
const resp = await ipcQuery(sock, { type: 'menu.exec', payload: { type: 'menu.query', name: 'gateway', id: 'ecw-gateway-snap' }, auth: watchMenuRequestAuth(params) }, 5000);
|
|
16
17
|
if (!resp) {
|
|
17
18
|
return { gateways: [], scopes: [], types: [], error: 'evolcore 未运行或 socket 不可达' };
|
|
18
19
|
}
|
|
@@ -34,8 +35,8 @@ async function getSnapshot() {
|
|
|
34
35
|
}
|
|
35
36
|
export const gatewaySource = {
|
|
36
37
|
kind: 'gateway',
|
|
37
|
-
async snapshot() {
|
|
38
|
-
return getSnapshot();
|
|
38
|
+
async snapshot(params = {}) {
|
|
39
|
+
return getSnapshot(params);
|
|
39
40
|
},
|
|
40
41
|
subscribe(_params, _push) {
|
|
41
42
|
// 网关配置变更不频繁,无文件监听;前端通过操作后主动 re-subscribe 刷新。
|
package/dist/sources/monitor.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import fs from 'node:fs';
|
|
15
15
|
import { resolvePaths } from '../paths.js';
|
|
16
16
|
import { ipcQuery } from '../ipc-client.js';
|
|
17
|
+
import crypto from 'node:crypto';
|
|
17
18
|
function processGroupKey(process) {
|
|
18
19
|
return `${process.kind}\u0000${process.name}`;
|
|
19
20
|
}
|
|
@@ -192,9 +193,9 @@ function sampleNetworkRate(ts) {
|
|
|
192
193
|
previousNetworkSample = { ...totals, ts };
|
|
193
194
|
return latestNetworkRate;
|
|
194
195
|
}
|
|
195
|
-
async function fetchSnapshot() {
|
|
196
|
+
async function fetchSnapshot(leaseId) {
|
|
196
197
|
const p = resolvePaths();
|
|
197
|
-
const resp = await ipcQuery(p.socket, { type: 'monitor-snapshot' }, 3000);
|
|
198
|
+
const resp = await ipcQuery(p.socket, { type: 'monitor-snapshot', ...(leaseId ? { leaseId } : {}) }, 3000);
|
|
198
199
|
// resp === null → daemon 离线或 socket 不可达;resp.ok === false → 命令不受支持(旧 daemon)
|
|
199
200
|
if (!resp?.ok) {
|
|
200
201
|
return { daemonRunning: resp !== null, snapshot: null, history: { fine: [], mid: [], coarse: [] } };
|
|
@@ -237,8 +238,24 @@ async function fetchSnapshot() {
|
|
|
237
238
|
}
|
|
238
239
|
export const monitorSource = {
|
|
239
240
|
kind: 'monitor',
|
|
240
|
-
async
|
|
241
|
-
|
|
241
|
+
async activate(params) {
|
|
242
|
+
const leaseId = crypto.randomUUID();
|
|
243
|
+
const p = resolvePaths();
|
|
244
|
+
const response = await ipcQuery(p.socket, { type: 'monitor-subscribe', leaseId }, 3000);
|
|
245
|
+
if (!response?.ok)
|
|
246
|
+
throw new Error('daemon rejected monitor subscription');
|
|
247
|
+
params.__monitorLeaseId = leaseId;
|
|
248
|
+
let released = false;
|
|
249
|
+
return () => {
|
|
250
|
+
if (released)
|
|
251
|
+
return;
|
|
252
|
+
released = true;
|
|
253
|
+
delete params.__monitorLeaseId;
|
|
254
|
+
void ipcQuery(p.socket, { type: 'monitor-unsubscribe', leaseId }, 3000);
|
|
255
|
+
};
|
|
256
|
+
},
|
|
257
|
+
async snapshot(params) {
|
|
258
|
+
return fetchSnapshot(params?.__monitorLeaseId);
|
|
242
259
|
},
|
|
243
260
|
subscribe(_params, push) {
|
|
244
261
|
let lastJson = '';
|
|
@@ -247,7 +264,7 @@ export const monitorSource = {
|
|
|
247
264
|
if (stopped)
|
|
248
265
|
return;
|
|
249
266
|
try {
|
|
250
|
-
const snap = await fetchSnapshot();
|
|
267
|
+
const snap = await fetchSnapshot(_params.__monitorLeaseId);
|
|
251
268
|
const json = JSON.stringify(snap);
|
|
252
269
|
if (json !== lastJson) {
|
|
253
270
|
lastJson = json;
|
package/dist/sources/msg.js
CHANGED
|
@@ -13,8 +13,6 @@ import { decodeDirSegment, isTransientProtocolMessage, readAllJsonlLines, readJs
|
|
|
13
13
|
let contextModulesPromise = null;
|
|
14
14
|
const sessionAdapterPromises = new Map();
|
|
15
15
|
let peerDisplayResolverPromise = null;
|
|
16
|
-
const aunGroupNameCache = new Map();
|
|
17
|
-
const aunGroupNameRequests = new Map();
|
|
18
16
|
let agentDisplayNamesCache = null;
|
|
19
17
|
const messageFileCache = new Map();
|
|
20
18
|
function getContextModules() {
|
|
@@ -67,94 +65,10 @@ export function resolveAunGroupName(names, groupId, fallback) {
|
|
|
67
65
|
}
|
|
68
66
|
return fallback;
|
|
69
67
|
}
|
|
70
|
-
async function fetchAunGroupNames(aid) {
|
|
71
|
-
const names = new Map();
|
|
72
|
-
let cursor = null;
|
|
73
|
-
let page = 0;
|
|
74
|
-
do {
|
|
75
|
-
page += 1;
|
|
76
|
-
const response = await ipcQuery(resolvePaths().socket, {
|
|
77
|
-
type: 'menu.exec',
|
|
78
|
-
payload: {
|
|
79
|
-
type: 'menu.query',
|
|
80
|
-
name: 'connect',
|
|
81
|
-
cmd: '/connect',
|
|
82
|
-
agent: aid,
|
|
83
|
-
id: `ecweb-msg-groups-${Date.now()}-${page}`,
|
|
84
|
-
args: { self: aid, view: 'groups', limit: 200, ...(cursor ? { cursor } : {}) },
|
|
85
|
-
},
|
|
86
|
-
auth: { source: 'ecweb', localDirect: true },
|
|
87
|
-
}, 10_000);
|
|
88
|
-
const data = response?.ok && !response.response?.error ? response.response?.data : null;
|
|
89
|
-
if (!data || !Array.isArray(data.items))
|
|
90
|
-
break;
|
|
91
|
-
for (const item of data.items) {
|
|
92
|
-
const groupId = String(item?.groupId || '').trim();
|
|
93
|
-
const displayName = String(item?.displayName || '').trim();
|
|
94
|
-
if (!groupId || !displayName)
|
|
95
|
-
continue;
|
|
96
|
-
for (const variant of aunGroupIdVariants(groupId))
|
|
97
|
-
names.set(variant, displayName);
|
|
98
|
-
}
|
|
99
|
-
cursor = typeof data.nextCursor === 'string' && data.nextCursor ? data.nextCursor : null;
|
|
100
|
-
} while (cursor && page < 20);
|
|
101
|
-
return names;
|
|
102
|
-
}
|
|
103
|
-
function getAunGroupNames(aid) {
|
|
104
|
-
const cached = aunGroupNameCache.get(aid);
|
|
105
|
-
if (cached && cached.expiresAt > Date.now())
|
|
106
|
-
return Promise.resolve(cached.names);
|
|
107
|
-
const pending = aunGroupNameRequests.get(aid);
|
|
108
|
-
if (pending)
|
|
109
|
-
return pending;
|
|
110
|
-
const request = fetchAunGroupNames(aid)
|
|
111
|
-
.then(names => {
|
|
112
|
-
aunGroupNameCache.set(aid, {
|
|
113
|
-
names,
|
|
114
|
-
expiresAt: Date.now() + (names.size ? 5 * 60_000 : 15_000),
|
|
115
|
-
});
|
|
116
|
-
return names;
|
|
117
|
-
})
|
|
118
|
-
.catch(() => new Map())
|
|
119
|
-
.finally(() => aunGroupNameRequests.delete(aid));
|
|
120
|
-
aunGroupNameRequests.set(aid, request);
|
|
121
|
-
return request;
|
|
122
|
-
}
|
|
123
|
-
async function hydrateAunGroupNames(chats, waitForRefresh = false) {
|
|
124
|
-
const aids = [...new Set(chats
|
|
125
|
-
.filter(chat => chat.channelType === 'aun' && chat.chatType === 'group')
|
|
126
|
-
.map(chat => chat.selfAID))];
|
|
127
|
-
if (!aids.length)
|
|
128
|
-
return;
|
|
129
|
-
const directories = new Map();
|
|
130
|
-
if (waitForRefresh) {
|
|
131
|
-
for (const [aid, names] of await Promise.all(aids.map(async (aid) => [aid, await getAunGroupNames(aid)]))) {
|
|
132
|
-
directories.set(aid, names);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
for (const aid of aids) {
|
|
137
|
-
const cached = aunGroupNameCache.get(aid);
|
|
138
|
-
if (cached)
|
|
139
|
-
directories.set(aid, cached.names);
|
|
140
|
-
if (!cached || cached.expiresAt <= Date.now())
|
|
141
|
-
void getAunGroupNames(aid);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
for (const chat of chats) {
|
|
145
|
-
if (chat.channelType !== 'aun' || chat.chatType !== 'group')
|
|
146
|
-
continue;
|
|
147
|
-
const groupName = resolveAunGroupName(directories.get(chat.selfAID) || new Map(), chat.groupId, chat.groupName);
|
|
148
|
-
if (!groupName)
|
|
149
|
-
continue;
|
|
150
|
-
chat.groupName = groupName;
|
|
151
|
-
chat.peerName = groupName;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
68
|
export function resolveSessionBindDisplayName(bind, resolver, aunGroupNames = new Map()) {
|
|
155
69
|
const isGroup = bind.chatType === 'group' || !!bind.groupId;
|
|
156
70
|
if (bind.channelType === 'aun' && isGroup) {
|
|
157
|
-
return
|
|
71
|
+
return bind.groupName || bind.groupId || bind.channelId || null;
|
|
158
72
|
}
|
|
159
73
|
if (isGroup)
|
|
160
74
|
return bind.groupName || null;
|
|
@@ -166,18 +80,14 @@ export function resolveSessionBindDisplayName(bind, resolver, aunGroupNames = ne
|
|
|
166
80
|
}, bind.peerId || bind.channelId, bind.peerName);
|
|
167
81
|
}
|
|
168
82
|
/** 为会话页绑定标签补齐联系人名或 AUN 群名,不改变原始 channelId。 */
|
|
169
|
-
export async function hydrateSessionBindDisplayNames(binds) {
|
|
83
|
+
export async function hydrateSessionBindDisplayNames(binds, params = {}) {
|
|
84
|
+
void params;
|
|
170
85
|
const items = [...binds];
|
|
171
86
|
if (!items.length)
|
|
172
87
|
return;
|
|
173
88
|
const resolver = await getPeerDisplayResolver();
|
|
174
|
-
const groupAids = [...new Set(items
|
|
175
|
-
.filter(bind => bind.channelType === 'aun' && (bind.chatType === 'group' || !!bind.groupId))
|
|
176
|
-
.map(bind => bind.selfAID)
|
|
177
|
-
.filter(Boolean))];
|
|
178
|
-
const groupDirectories = new Map(await Promise.all(groupAids.map(async (aid) => [aid, await getAunGroupNames(aid)])));
|
|
179
89
|
for (const bind of items) {
|
|
180
|
-
bind.displayName = resolveSessionBindDisplayName(bind, resolver,
|
|
90
|
+
bind.displayName = resolveSessionBindDisplayName(bind, resolver, new Map());
|
|
181
91
|
}
|
|
182
92
|
}
|
|
183
93
|
function getSessionAdapter(baseagent) {
|
|
@@ -943,8 +853,6 @@ async function buildSnapshot(params) {
|
|
|
943
853
|
: requestedScope;
|
|
944
854
|
const peer = params.peer || null;
|
|
945
855
|
const inScope = selectedChats(chats, scope);
|
|
946
|
-
if (scope)
|
|
947
|
-
await hydrateAunGroupNames(inScope);
|
|
948
856
|
const peers = scope ? mergePeerInfo(inScope) : [];
|
|
949
857
|
const requestedLimit = Number(params.limit);
|
|
950
858
|
const limit = Number.isFinite(requestedLimit) ? Math.min(Math.max(Math.trunc(requestedLimit), 20), 200) : 100;
|