@dsh-plus/notify-email 0.1.8 → 0.1.9

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/lib/index.js CHANGED
@@ -292,12 +292,19 @@ function createTurnEndTrigger(resolveConfig) {
292
292
  //#endregion
293
293
  //#region src/watchers/decision.ts
294
294
  function installDecisionWatcher(ctx, service) {
295
- const seen = /* @__PURE__ */ new Set();
295
+ const seen = /* @__PURE__ */ new Map();
296
+ const UNKNOWN_BUCKET_CAP = 1e3;
296
297
  const logger = ctx.logger("notify-email");
297
298
  ctx.on("tools/pre-execute", (exec, next) => {
298
- if (seen.has(exec.callId)) return next();
299
- seen.add(exec.callId);
300
299
  const sessionId = exec.agent?.id ?? "unknown";
300
+ let bucket = seen.get(sessionId);
301
+ if (bucket === void 0) {
302
+ bucket = /* @__PURE__ */ new Set();
303
+ seen.set(sessionId, bucket);
304
+ }
305
+ if (bucket.has(exec.callId)) return next();
306
+ if (sessionId === "unknown" && bucket.size >= UNKNOWN_BUCKET_CAP) bucket.clear();
307
+ bucket.add(exec.callId);
301
308
  service.dispatchDecision({
302
309
  callId: exec.callId,
303
310
  sessionId,
@@ -308,6 +315,9 @@ function installDecisionWatcher(ctx, service) {
308
315
  });
309
316
  return next();
310
317
  });
318
+ ctx.on("session/disposed", (session) => {
319
+ seen.delete(session.id);
320
+ });
311
321
  }
312
322
  //#endregion
313
323
  //#region src/watchers/turn-end.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-plus/notify-email",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "dsh-plus service+ui plugin: 任务结束/等待决策/出错时向指定邮箱发送邮件通知",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -9,12 +9,22 @@ import type { Context } from '@deepseek-ai/cordis'
9
9
  import type { NotifyEmailService } from '../service.ts'
10
10
 
11
11
  export function installDecisionWatcher(ctx: Context, service: NotifyEmailService): void {
12
- const seen = new Set<string>()
12
+ // 按 sessionId 分桶去重:callId 粒度的全局集合会随每个工具调用无限增长;
13
+ // 会话销毁即整桶释放。无 agent 归属的调用落到 unknown 桶(无生命周期可挂),
14
+ // 以有界环形覆盖兜底,保证任何路径都不产生无界内存。
15
+ const seen = new Map<string, Set<string>>()
16
+ const UNKNOWN_BUCKET_CAP = 1000
13
17
  const logger = ctx.logger('notify-email')
14
18
  ctx.on('tools/pre-execute', (exec, next) => {
15
- if (seen.has(exec.callId)) return next()
16
- seen.add(exec.callId)
17
19
  const sessionId = exec.agent?.id ?? 'unknown'
20
+ let bucket = seen.get(sessionId)
21
+ if (bucket === undefined) {
22
+ bucket = new Set()
23
+ seen.set(sessionId, bucket)
24
+ }
25
+ if (bucket.has(exec.callId)) return next()
26
+ if (sessionId === 'unknown' && bucket.size >= UNKNOWN_BUCKET_CAP) bucket.clear()
27
+ bucket.add(exec.callId)
18
28
  service
19
29
  .dispatchDecision({
20
30
  callId: exec.callId,
@@ -30,4 +40,7 @@ export function installDecisionWatcher(ctx: Context, service: NotifyEmailService
30
40
  })
31
41
  return next()
32
42
  })
43
+ ctx.on('session/disposed', (session) => {
44
+ seen.delete(session.id)
45
+ })
33
46
  }