ec-web 0.0.25 → 0.0.27
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/LICENSE +21 -21
- package/README.md +17 -17
- package/dist/index.js +1 -1
- package/dist/paths.js +12 -1
- package/dist/server.js +42 -25
- package/dist/sources/aid.js +28 -13
- package/dist/sources/basic-settings.js +7 -27
- package/dist/sources/msg.js +21 -4
- package/dist/sources/relation-roles.js +23 -9
- package/dist/sources/role-definitions.js +59 -34
- package/dist/sources/session-codex.js +34 -16
- package/dist/sources/session-ecagent.js +665 -0
- package/dist/sources/session-origin.js +16 -0
- package/dist/sources/session.js +69 -165
- package/dist/sources/stats.js +92 -92
- package/dist/sources/system.js +1 -33
- package/dist/sources/triggers.js +1 -1
- package/dist/sources/types.js +1 -0
- package/dist/static/app.js +11931 -11691
- package/dist/static/basic-settings.js +3 -3
- package/dist/static/index.html +427 -427
- package/dist/static/style.css +4936 -4899
- package/dist/static/vendor/echarts-5.6.0.min.js +45 -45
- package/ecweb-wrapper.cjs +67 -67
- package/package.json +35 -35
|
@@ -29,6 +29,7 @@ async function getRolesModule() {
|
|
|
29
29
|
const resolverMod = await import(toFileUrl(resolverPath));
|
|
30
30
|
const roleServiceMod = await import(toFileUrl(roleServicePath));
|
|
31
31
|
const authMod = await import(toFileUrl(authPath));
|
|
32
|
+
const schemaMod = await import(toFileUrl(resolveParentDistModule('config', 'role-schema.js')));
|
|
32
33
|
if (!rolesMod.readRolesConfig)
|
|
33
34
|
throw new Error('readRolesConfig not found in roles.js');
|
|
34
35
|
if (!rolesMod.roleExists)
|
|
@@ -54,6 +55,8 @@ async function getRolesModule() {
|
|
|
54
55
|
read: cmMod.read,
|
|
55
56
|
write: cmMod.write,
|
|
56
57
|
ConfigTarget: cmMod.ConfigTarget,
|
|
58
|
+
resolveEffective: cmMod.resolveEffective,
|
|
59
|
+
rolePermissionFields: schemaMod.rolePermissionFields,
|
|
57
60
|
resolver: resolverMod,
|
|
58
61
|
buildAuthSubject: authMod.buildAuthSubject,
|
|
59
62
|
authorizeOperation: authMod.authorizeOperation,
|
|
@@ -66,10 +69,10 @@ async function getRolesModule() {
|
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
71
|
async function getRoleConstraintsModule() {
|
|
69
|
-
const constraintsPath = resolveParentDistModule('
|
|
72
|
+
const constraintsPath = resolveParentDistModule('core', 'model', 'model-permission.js');
|
|
70
73
|
const mod = await import(toFileUrl(constraintsPath));
|
|
71
74
|
if (!mod.isModelAllowedByPatterns)
|
|
72
|
-
throw new Error('isModelAllowedByPatterns not found in
|
|
75
|
+
throw new Error('isModelAllowedByPatterns not found in model-permission.js');
|
|
73
76
|
return {
|
|
74
77
|
isModelAllowedByPatterns: mod.isModelAllowedByPatterns,
|
|
75
78
|
};
|
|
@@ -105,8 +108,8 @@ function isReadMethod(method) {
|
|
|
105
108
|
async function authorizeRolePolicyOperation(modules, processConfig, auth, aid, operation, args) {
|
|
106
109
|
const actor = auth.actorAid || '';
|
|
107
110
|
const processOwners = Array.isArray(processConfig?.owners) ? processConfig.owners.map(String) : [];
|
|
108
|
-
const syntheticOwner =
|
|
109
|
-
const actorId = auth.localDirect ? 'local-direct' : actor || undefined;
|
|
111
|
+
const syntheticOwner = isDaemonOwnerAuth(processConfig, auth);
|
|
112
|
+
const actorId = auth.localDirect ? 'local-direct' : actor || (syntheticOwner ? 'ecweb-remote' : undefined);
|
|
110
113
|
const subject = modules.buildAuthSubject({
|
|
111
114
|
selfAid: aid,
|
|
112
115
|
actorId,
|
|
@@ -116,6 +119,7 @@ async function authorizeRolePolicyOperation(modules, processConfig, auth, aid, o
|
|
|
116
119
|
chatType: 'private',
|
|
117
120
|
conversationId: actor || 'ecweb',
|
|
118
121
|
processOwners,
|
|
122
|
+
trustedProcessRole: syntheticOwner ? 'daemon-owner' : undefined,
|
|
119
123
|
...(syntheticOwner ? {
|
|
120
124
|
roleDetail: {
|
|
121
125
|
effectiveRole: 'owner',
|
|
@@ -123,8 +127,8 @@ async function authorizeRolePolicyOperation(modules, processConfig, auth, aid, o
|
|
|
123
127
|
isAuthenticated: true,
|
|
124
128
|
allowAccess: true,
|
|
125
129
|
roleExists: true,
|
|
126
|
-
//
|
|
127
|
-
//
|
|
130
|
+
// Keep the token's actor provenance separate from the management
|
|
131
|
+
// authority established by the ECWeb authentication gate.
|
|
128
132
|
actor: {
|
|
129
133
|
operatorId: actorId || 'ecweb',
|
|
130
134
|
operatorChannelKey: `ecweb#${aid}`,
|
|
@@ -155,7 +159,7 @@ async function authorizeRolePolicyOperation(modules, processConfig, auth, aid, o
|
|
|
155
159
|
});
|
|
156
160
|
}
|
|
157
161
|
function isDaemonOwnerAuth(processConfig, auth) {
|
|
158
|
-
if (auth.localDirect)
|
|
162
|
+
if (auth.daemonOwner === true || auth.localDirect)
|
|
159
163
|
return true;
|
|
160
164
|
const actor = typeof auth.actorAid === 'string' ? auth.actorAid.trim() : '';
|
|
161
165
|
const processOwners = Array.isArray(processConfig?.owners)
|
|
@@ -163,8 +167,16 @@ function isDaemonOwnerAuth(processConfig, auth) {
|
|
|
163
167
|
: [];
|
|
164
168
|
return !!actor && processOwners.includes(actor);
|
|
165
169
|
}
|
|
166
|
-
|
|
167
|
-
const
|
|
170
|
+
function roleModelContext(modules, aid, requested) {
|
|
171
|
+
const effective = modules.resolveEffective({ self: aid });
|
|
172
|
+
const baseagent = requested ?? effective.active_baseagent;
|
|
173
|
+
const field = `baseagents.${baseagent}.model`;
|
|
174
|
+
const descriptor = modules.rolePermissionFields().find((item) => item.value === field);
|
|
175
|
+
if (!descriptor) {
|
|
176
|
+
throw Object.assign(new Error(`Unsupported role model backend: ${String(baseagent)}`), { statusCode: 400 });
|
|
177
|
+
}
|
|
178
|
+
return { baseagent, field, patternOptions: descriptor.patterns?.map((item) => item.value) ?? ['*'] };
|
|
179
|
+
}
|
|
168
180
|
const COMMAND_PERMISSION_SCOPES = new Set(['relation', 'role', 'agent', 'process', 'filesystem', 'control', 'raw-cli']);
|
|
169
181
|
const COMMAND_CONSTRAINT_KEYS = new Set([
|
|
170
182
|
'ownPeerOnly',
|
|
@@ -494,11 +506,11 @@ function normalizeRoleDefinitionForSave(roleDef) {
|
|
|
494
506
|
return roleDef;
|
|
495
507
|
return { ...roleDef, usageLimits: normalizeRoleUsageLimits(roleDef.usageLimits) };
|
|
496
508
|
}
|
|
497
|
-
function getModelPermission(roleDef) {
|
|
509
|
+
function getModelPermission(roleDef, field) {
|
|
498
510
|
const permissions = roleDef?.permissions;
|
|
499
511
|
if (!permissions || typeof permissions !== 'object')
|
|
500
512
|
return {};
|
|
501
|
-
const perm = permissions[
|
|
513
|
+
const perm = permissions[field];
|
|
502
514
|
return perm && typeof perm === 'object' ? perm : {};
|
|
503
515
|
}
|
|
504
516
|
function stripSelectionModeFromPermission(perm) {
|
|
@@ -543,38 +555,42 @@ async function validateRoleModelPermission(roleDef) {
|
|
|
543
555
|
const permissions = roleDef?.permissions;
|
|
544
556
|
if (!permissions || typeof permissions !== 'object')
|
|
545
557
|
return { ok: true, errors: [] };
|
|
546
|
-
const
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
558
|
+
const errors = [];
|
|
559
|
+
for (const [field, perm] of Object.entries(permissions)) {
|
|
560
|
+
if (!/^baseagents\.[a-z0-9_-]+\.model$/.test(field))
|
|
561
|
+
continue;
|
|
562
|
+
permissions[field] = stripSelectionModeFromPermission(perm);
|
|
563
|
+
const result = await validateModelPermissionInput({
|
|
564
|
+
defaultModel: permissions[field]?.default,
|
|
565
|
+
allowOverride: permissions[field]?.allowOverride,
|
|
566
|
+
allowedModels: permissions[field]?.allowedModels,
|
|
567
|
+
});
|
|
568
|
+
errors.push(...result.errors.map(error => `${field}: ${error}`));
|
|
569
|
+
}
|
|
570
|
+
return { ok: errors.length === 0, errors };
|
|
556
571
|
}
|
|
557
572
|
async function filterAllowedCatalogModels(models, allowedModels) {
|
|
558
573
|
const { isModelAllowedByPatterns } = await getRoleConstraintsModule();
|
|
559
574
|
return models.filter(model => !model.isAlias && isModelAllowedByPatterns(model.id, allowedModels));
|
|
560
575
|
}
|
|
561
|
-
async function buildModelPermissionResponse(roleName, roleDef, override, aid) {
|
|
562
|
-
const currentPerm = getModelPermission(roleDef);
|
|
576
|
+
async function buildModelPermissionResponse(roleName, roleDef, modelContext, override, aid) {
|
|
577
|
+
const currentPerm = getModelPermission(roleDef, modelContext.field);
|
|
563
578
|
const defaultModel = override?.defaultModel ?? currentPerm.default ?? '';
|
|
564
579
|
const allowOverride = override?.allowOverride ?? currentPerm.allowOverride ?? false;
|
|
565
580
|
const allowedModels = override?.allowedModels ?? (Array.isArray(currentPerm.allowedModels) ? currentPerm.allowedModels : []);
|
|
566
|
-
const catalog = await getModelCatalogSnapshot(
|
|
581
|
+
const catalog = await getModelCatalogSnapshot(modelContext.baseagent, aid);
|
|
567
582
|
const matchingModels = await filterAllowedCatalogModels(catalog.models, allowedModels);
|
|
568
583
|
return {
|
|
569
584
|
role: roleName,
|
|
570
|
-
|
|
585
|
+
baseagent: modelContext.baseagent,
|
|
586
|
+
field: modelContext.field,
|
|
571
587
|
permission: {
|
|
572
588
|
default: defaultModel,
|
|
573
589
|
allowOverride,
|
|
574
590
|
allowedModels,
|
|
575
591
|
},
|
|
576
592
|
selectionMode: inferSelectionMode(allowedModels),
|
|
577
|
-
patternOptions:
|
|
593
|
+
patternOptions: modelContext.patternOptions,
|
|
578
594
|
catalog,
|
|
579
595
|
matchingModels,
|
|
580
596
|
stats: {
|
|
@@ -612,10 +628,16 @@ async function buildSnapshot(params = {}, auth = {}) {
|
|
|
612
628
|
};
|
|
613
629
|
}
|
|
614
630
|
const config = modules.readRolesConfig(aid);
|
|
631
|
+
const activeBaseagent = modules.resolveEffective({ self: aid }).active_baseagent;
|
|
632
|
+
const modelContext = activeBaseagent ? roleModelContext(modules, aid, activeBaseagent) : undefined;
|
|
615
633
|
return {
|
|
616
634
|
$schema_version: 1,
|
|
617
635
|
aid,
|
|
618
636
|
self: aid,
|
|
637
|
+
baseagent: modelContext?.baseagent ?? null,
|
|
638
|
+
modelPermissionField: modelContext?.field ?? null,
|
|
639
|
+
modelPatternOptions: modelContext?.patternOptions ?? [],
|
|
640
|
+
permissionFields: modules.rolePermissionFields(),
|
|
619
641
|
agents: summarizeAgents(agents),
|
|
620
642
|
defaultRoles: config.defaultRoles ?? { private: null, group: null },
|
|
621
643
|
policyRevision: JSON.stringify(config),
|
|
@@ -865,7 +887,8 @@ export async function handleRoleDefinitionsApi(req, res, auth = {}) {
|
|
|
865
887
|
sendJson(res, 404, { success: false, error: 'Role not found' });
|
|
866
888
|
return;
|
|
867
889
|
}
|
|
868
|
-
const
|
|
890
|
+
const modelContext = roleModelContext(modules, aid, parsedUrl.query.baseagent);
|
|
891
|
+
const data = await buildModelPermissionResponse(roleName, roleDef, modelContext, undefined, aid || undefined);
|
|
869
892
|
sendJson(res, 200, { success: true, data });
|
|
870
893
|
return;
|
|
871
894
|
}
|
|
@@ -878,13 +901,14 @@ export async function handleRoleDefinitionsApi(req, res, auth = {}) {
|
|
|
878
901
|
return;
|
|
879
902
|
}
|
|
880
903
|
const payload = await readJsonBody(req);
|
|
881
|
-
const
|
|
904
|
+
const modelContext = roleModelContext(modules, aid, parsedUrl.query.baseagent);
|
|
905
|
+
const currentPerm = getModelPermission(roleDef, modelContext.field);
|
|
882
906
|
const validation = await validateModelPermissionInput(extractModelPermissionPayload(payload, currentPerm));
|
|
883
907
|
if (!validation.ok || !validation.value) {
|
|
884
908
|
sendJson(res, 400, { success: false, error: 'Invalid model permissions', errors: validation.errors });
|
|
885
909
|
return;
|
|
886
910
|
}
|
|
887
|
-
const data = await buildModelPermissionResponse(roleName, roleDef, validation.value, aid || undefined);
|
|
911
|
+
const data = await buildModelPermissionResponse(roleName, roleDef, modelContext, validation.value, aid || undefined);
|
|
888
912
|
sendJson(res, 200, { success: true, data });
|
|
889
913
|
return;
|
|
890
914
|
}
|
|
@@ -897,7 +921,8 @@ export async function handleRoleDefinitionsApi(req, res, auth = {}) {
|
|
|
897
921
|
return;
|
|
898
922
|
}
|
|
899
923
|
const payload = await readJsonBody(req);
|
|
900
|
-
const
|
|
924
|
+
const modelContext = roleModelContext(modules, aid, parsedUrl.query.baseagent);
|
|
925
|
+
const currentPerm = getModelPermission(roleDef, modelContext.field);
|
|
901
926
|
const validation = await validateModelPermissionInput(extractModelPermissionPayload(payload, currentPerm));
|
|
902
927
|
if (!validation.ok || !validation.value) {
|
|
903
928
|
sendJson(res, 400, { success: false, error: 'Invalid model permissions', errors: validation.errors });
|
|
@@ -906,15 +931,15 @@ export async function handleRoleDefinitionsApi(req, res, auth = {}) {
|
|
|
906
931
|
roleDef.permissions = roleDef.permissions && typeof roleDef.permissions === 'object'
|
|
907
932
|
? roleDef.permissions
|
|
908
933
|
: {};
|
|
909
|
-
const existingPerm = stripSelectionModeFromPermission(getModelPermission(roleDef));
|
|
910
|
-
roleDef.permissions[
|
|
934
|
+
const existingPerm = stripSelectionModeFromPermission(getModelPermission(roleDef, modelContext.field));
|
|
935
|
+
roleDef.permissions[modelContext.field] = {
|
|
911
936
|
...existingPerm,
|
|
912
937
|
default: validation.value.defaultModel,
|
|
913
938
|
allowOverride: validation.value.allowOverride,
|
|
914
939
|
allowedModels: validation.value.allowedModels,
|
|
915
940
|
};
|
|
916
941
|
modules.roleService.writeRoleDefinition(aid, roleName, roleDef);
|
|
917
|
-
const data = await buildModelPermissionResponse(roleName, roleDef, validation.value, aid || undefined);
|
|
942
|
+
const data = await buildModelPermissionResponse(roleName, roleDef, modelContext, validation.value, aid || undefined);
|
|
918
943
|
sendJson(res, 200, { success: true, data });
|
|
919
944
|
return;
|
|
920
945
|
}
|
|
@@ -1028,6 +1053,6 @@ export async function handleRoleDefinitionsApi(req, res, auth = {}) {
|
|
|
1028
1053
|
}
|
|
1029
1054
|
catch (err) {
|
|
1030
1055
|
console.error('[role-definitions] API error:', err);
|
|
1031
|
-
sendJson(res, 500, { error: err.message });
|
|
1056
|
+
sendJson(res, err.statusCode ?? 500, { error: err.message });
|
|
1032
1057
|
}
|
|
1033
1058
|
}
|
|
@@ -15,7 +15,7 @@ import { resolvePaths } from '../paths.js';
|
|
|
15
15
|
import { encodePath } from '../fs-utils.js';
|
|
16
16
|
import { getAgentSelfNames } from './msg.js';
|
|
17
17
|
import { parseTranscriptResultKey, previewLargeToolResults, windowTranscriptTurns } from './transcript-window.js';
|
|
18
|
-
import { buildSessionBindMap, classifyTranscriptSource, isEvolcoreRoutedMessage, isSyntheticCliPrompt, resolveSessionBindSelfName, } from './session-origin.js';
|
|
18
|
+
import { buildSessionBindMap, readRunnerTaskTurns, classifyTranscriptSource, isEvolcoreRoutedMessage, isSyntheticCliPrompt, resolveSessionBindSelfName, } from './session-origin.js';
|
|
19
19
|
const requireFromHere = createRequire(import.meta.url);
|
|
20
20
|
let _dlog = null;
|
|
21
21
|
export function setDebugLog(log) { _dlog = log; }
|
|
@@ -205,12 +205,12 @@ function listProjects() {
|
|
|
205
205
|
if (!db)
|
|
206
206
|
return [];
|
|
207
207
|
try {
|
|
208
|
-
const rows = db.prepare(`
|
|
209
|
-
SELECT cwd, COUNT(*) as count, MAX(updated_at) as lastActivity
|
|
210
|
-
FROM threads
|
|
211
|
-
WHERE archived = 0
|
|
212
|
-
GROUP BY cwd
|
|
213
|
-
ORDER BY lastActivity DESC
|
|
208
|
+
const rows = db.prepare(`
|
|
209
|
+
SELECT cwd, COUNT(*) as count, MAX(updated_at) as lastActivity
|
|
210
|
+
FROM threads
|
|
211
|
+
WHERE archived = 0
|
|
212
|
+
GROUP BY cwd
|
|
213
|
+
ORDER BY lastActivity DESC
|
|
214
214
|
`).all();
|
|
215
215
|
const projects = rows.map(r => {
|
|
216
216
|
const cwd = r.cwd || '';
|
|
@@ -382,11 +382,11 @@ function listTranscripts(encoded, cwd) {
|
|
|
382
382
|
if (!db)
|
|
383
383
|
return [];
|
|
384
384
|
try {
|
|
385
|
-
const rows = db.prepare(`
|
|
386
|
-
SELECT id, title, first_user_message, updated_at, rollout_path, source, thread_source
|
|
387
|
-
FROM threads
|
|
388
|
-
WHERE cwd = ? AND archived = 0
|
|
389
|
-
ORDER BY updated_at DESC
|
|
385
|
+
const rows = db.prepare(`
|
|
386
|
+
SELECT id, title, first_user_message, updated_at, rollout_path, source, thread_source
|
|
387
|
+
FROM threads
|
|
388
|
+
WHERE cwd = ? AND archived = 0
|
|
389
|
+
ORDER BY updated_at DESC
|
|
390
390
|
`).all(cwd);
|
|
391
391
|
const out = [];
|
|
392
392
|
let parsed = 0, hitMem = 0, hitDisk = 0;
|
|
@@ -817,7 +817,7 @@ function readTranscriptFile(threadId, cwd, readStats) {
|
|
|
817
817
|
cacheTranscriptDetail(rolloutPath, stat.mtimeMs, stat.size, detail);
|
|
818
818
|
return detail;
|
|
819
819
|
}
|
|
820
|
-
export function readCodexSessionResult(params) {
|
|
820
|
+
export async function readCodexSessionResult(params) {
|
|
821
821
|
const projects = listProjects();
|
|
822
822
|
const project = resolveProject(params, projects);
|
|
823
823
|
const sessionId = typeof params.sessionId === 'string' ? params.sessionId : '';
|
|
@@ -825,7 +825,10 @@ export function readCodexSessionResult(params) {
|
|
|
825
825
|
if (!project || !sessionId || !key || !/^[A-Za-z0-9-]+$/.test(sessionId))
|
|
826
826
|
return null;
|
|
827
827
|
const detail = readTranscriptFile(sessionId, project.cwd);
|
|
828
|
-
const
|
|
828
|
+
const bind = buildBindMap().get(sessionId);
|
|
829
|
+
const taskTurns = bind?.evolSessionId ? await readRunnerTaskTurns(resolvePaths().logs, bind.evolSessionId) : [];
|
|
830
|
+
const turns = detail.turns.concat(taskTurns).sort((a, b) => (a.ts || 0) - (b.ts || 0));
|
|
831
|
+
const block = turns[key[0]]?.blocks?.[key[1]];
|
|
829
832
|
return block?.kind === 'tool_result' && typeof block.text === 'string' ? block.text : null;
|
|
830
833
|
}
|
|
831
834
|
// ── Snapshot ──
|
|
@@ -899,8 +902,11 @@ async function buildSnapshot(params) {
|
|
|
899
902
|
const detailStartedAt = Date.now();
|
|
900
903
|
const detail = readTranscriptFile(sessionId, project.cwd, metrics);
|
|
901
904
|
metrics.detailMs = Date.now() - detailStartedAt;
|
|
902
|
-
const page = windowTranscriptTurns(detail.turns, params.turnLimit, params.turnBefore);
|
|
903
905
|
const bind = bindMap.get(sessionId);
|
|
906
|
+
const taskTurns = bind?.evolSessionId ? await readRunnerTaskTurns(resolvePaths().logs, bind.evolSessionId) : [];
|
|
907
|
+
const turns = detail.turns.concat(taskTurns).sort((a, b) => (a.ts || 0) - (b.ts || 0));
|
|
908
|
+
const page = windowTranscriptTurns(turns, params.turnLimit, params.turnBefore);
|
|
909
|
+
const counts = { ...detail.counts, subtask: taskTurns.length };
|
|
904
910
|
const transcript = metas.find(meta => meta.id === sessionId);
|
|
905
911
|
const header = {
|
|
906
912
|
sessionId,
|
|
@@ -912,7 +918,7 @@ async function buildSnapshot(params) {
|
|
|
912
918
|
totalTurns: detail.totalTurns,
|
|
913
919
|
userMsgs: detail.userMsgs,
|
|
914
920
|
totalMsgs: detail.totalMsgs,
|
|
915
|
-
counts
|
|
921
|
+
counts,
|
|
916
922
|
inputTokens: detail.inputTokens,
|
|
917
923
|
outputTokens: detail.outputTokens,
|
|
918
924
|
contextTokens: detail.contextTokens,
|
|
@@ -944,6 +950,7 @@ export function subscribeCodex(params, push) {
|
|
|
944
950
|
const p = resolvePaths();
|
|
945
951
|
let dbWatcher = null;
|
|
946
952
|
let sessionWatcher = null;
|
|
953
|
+
let logWatcher = null;
|
|
947
954
|
let debounce = null;
|
|
948
955
|
const fire = () => {
|
|
949
956
|
if (debounce)
|
|
@@ -971,11 +978,22 @@ export function subscribeCodex(params, push) {
|
|
|
971
978
|
});
|
|
972
979
|
}
|
|
973
980
|
catch { }
|
|
981
|
+
if (params.sessionId) {
|
|
982
|
+
try {
|
|
983
|
+
logWatcher = fs.watch(p.logs, (_evt, filename) => {
|
|
984
|
+
if (!filename || /^events(?:-.+)?\.log$/.test(String(filename)))
|
|
985
|
+
fire();
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
catch { }
|
|
989
|
+
}
|
|
974
990
|
return () => {
|
|
975
991
|
if (dbWatcher)
|
|
976
992
|
dbWatcher.close();
|
|
977
993
|
if (sessionWatcher)
|
|
978
994
|
sessionWatcher.close();
|
|
995
|
+
if (logWatcher)
|
|
996
|
+
logWatcher.close();
|
|
979
997
|
if (debounce)
|
|
980
998
|
clearTimeout(debounce);
|
|
981
999
|
};
|