@dsh-plus/notify-email 0.1.7 → 0.1.8

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.d.ts CHANGED
@@ -1,9 +1,6 @@
1
- import "@deepseek-ai/dsh-settings";
2
1
  import z from "@deepseek-ai/schemastery";
3
2
  import { Context, Service } from "@deepseek-ai/cordis";
4
-
5
3
  //#region src/config.d.ts
6
-
7
4
  declare const Config: z<Schemastery.ObjectS<{
8
5
  enabled: z<boolean, boolean>;
9
6
  smtp: z<Schemastery.ObjectS<{
package/lib/index.js CHANGED
@@ -5,22 +5,16 @@ import { dshHomePath } from "@deepseek-ai/dsh-home-paths";
5
5
  import { appendFile, mkdir } from "node:fs/promises";
6
6
  import { dirname } from "node:path";
7
7
  import nodemailer from "nodemailer";
8
-
9
- //#region src/ns.ts
10
- /**
11
- * settings 命名空间字面量(纯常量,零依赖,浏览器半可安全引入)。
12
- * 服务端经 settingsNamespace() 品牌化后使用(config.ts),浏览器半将其作为
13
- * settings.plugin.item keyed 槽位的 key —— 同一字面量两处共用,防止漂移。
14
- * 契约:dsh rc7 起该槽位按「卡片编辑的 settings 命名空间」作 key 分发,
15
- * 官方配置页只渲染 key 命中 Host 已注册命名空间的卡片。
16
- * @module notify-email/ns
17
- */
18
- const SETTINGS_NS$1 = "dsh-plus-notify-email";
19
-
20
8
  //#endregion
21
9
  //#region src/config.ts
10
+ /**
11
+ * 配置单一事实源:cordis 行级 Config(组合默认值,dev/prod patch 层可覆盖)
12
+ * 与 settings namespace(用户层,经 dsh-settings-file 持久化到 $DSH_HOME/settings.yaml)
13
+ * 共用同一 schemastery schema。SMTP 密码标记 secret 角色,任何读取通道不得回传。
14
+ * @module notify-email/config
15
+ */
22
16
  /** settings 命名空间;webui 配置卡片与插件运行期读取同一份(字面量见 ./ns.ts)。 */
23
- const SETTINGS_NS = settingsNamespace(SETTINGS_NS$1);
17
+ const SETTINGS_NS = settingsNamespace("dsh-plus-notify-email");
24
18
  const SmtpSchema = z.object({
25
19
  host: z.string().description("SMTP 服务器主机名").default(""),
26
20
  port: z.natural().max(65535).description("SMTP 端口").default(465),
@@ -58,9 +52,14 @@ const Config = z.object({
58
52
  maxBodyChars: z.natural().min(200).description("邮件正文内容截断长度").default(4e3),
59
53
  dryRun: z.boolean().description("仅记录日志不真实发送(开发调试用)").default(false)
60
54
  });
61
-
62
55
  //#endregion
63
56
  //#region src/audit.ts
57
+ /**
58
+ * 通知投递审计:每次发送尝试追加一行 JSONL 到 $DSH_HOME/logs/notify-email.jsonl。
59
+ * 让 dry-run 可观测(dev 实例 logger 不落盘),也为生产排查「为什么没收到邮件」留痕。
60
+ * 记录正文截断 2000 字符;永远不含 SMTP 凭据。写失败只告警不阻断。
61
+ * @module notify-email/audit
62
+ */
64
63
  const BODY_EXCERPT_CHARS = 2e3;
65
64
  function buildAuditRecord(subject, text, to, result) {
66
65
  return {
@@ -80,7 +79,6 @@ function createJsonlAuditSink(path, onError) {
80
79
  });
81
80
  };
82
81
  }
83
-
84
82
  //#endregion
85
83
  //#region src/config-api.ts
86
84
  const ROUTE_TEST = "/dsh-plus/notify-email/test";
@@ -119,9 +117,13 @@ function registerTestApi(ctx, service) {
119
117
  })
120
118
  });
121
119
  }
122
-
123
120
  //#endregion
124
121
  //#region src/mailer.ts
122
+ /**
123
+ * 邮件发送:nodemailer 封装 + dry-run 兜底。
124
+ * Transport 抽象为函数注入,单元测试以假 transport 断言参数,零网络。
125
+ * @module notify-email/mailer
126
+ */
125
127
  /** nodemailer 连接/问候/套接字超时(毫秒),防 SMTP 不可达时挂住通知链路。 */
126
128
  const CONNECTION_TIMEOUT_MS = 1e4;
127
129
  const GREETING_TIMEOUT_MS = 1e4;
@@ -199,7 +201,6 @@ var Mailer = class {
199
201
  return result;
200
202
  }
201
203
  };
202
-
203
204
  //#endregion
204
205
  //#region src/triggers/render.ts
205
206
  function truncate(text, maxChars) {
@@ -264,7 +265,6 @@ function renderAbortedNotice(info) {
264
265
  text: header("任务被用户取消", info)
265
266
  };
266
267
  }
267
-
268
268
  //#endregion
269
269
  //#region src/triggers/builtin.ts
270
270
  /** 官方决策工具名 → 渲染函数 + 对应 toggle。 */
@@ -289,7 +289,6 @@ function createTurnEndTrigger(resolveConfig) {
289
289
  }
290
290
  };
291
291
  }
292
-
293
292
  //#endregion
294
293
  //#region src/watchers/decision.ts
295
294
  function installDecisionWatcher(ctx, service) {
@@ -310,11 +309,10 @@ function installDecisionWatcher(ctx, service) {
310
309
  return next();
311
310
  });
312
311
  }
313
-
314
312
  //#endregion
315
313
  //#region src/watchers/turn-end.ts
316
314
  /** 只有这三类 turn 结束对用户有可决策价值;blocked/max-tokens/interrupted 不通知。 */
317
- const NOTIFY_KINDS = new Set([
315
+ const NOTIFY_KINDS = /* @__PURE__ */ new Set([
318
316
  "completed",
319
317
  "error",
320
318
  "aborted"
@@ -397,9 +395,16 @@ function installTurnEndWatcher(ctx, service, resolveConfig) {
397
395
  watches.clear();
398
396
  }, "notify-email: turn-end timers");
399
397
  }
400
-
401
398
  //#endregion
402
399
  //#region src/service.ts
400
+ /**
401
+ * NotifyEmailService:通知编排中枢。
402
+ * - 配置:installSettingsSection 接入 settings 用户层($DSH_HOME/settings.yaml,热生效),
403
+ * 无 settings provider 时退化为 cordis 行级 config。
404
+ * - 触发器:registerTrigger 是第三方插件的扩展接口;内置官方适配器同路径注册。
405
+ * - 投递:首个非空 EmailNotice 经 Mailer 发送;单个触发器抛错不影响其余。
406
+ * @module @dsh-plus/notify-email
407
+ */
403
408
  var NotifyEmailService = class extends Service {
404
409
  static [Context.inject] = ["agents", "tools"];
405
410
  triggers = [];
@@ -415,7 +420,8 @@ var NotifyEmailService = class extends Service {
415
420
  onChange: () => {}
416
421
  });
417
422
  const logger = ctx.logger("notify-email");
418
- this.mailer = new Mailer(() => this.current(), logger, void 0, createJsonlAuditSink(dshHomePath("logs", "notify-email.jsonl"), (message) => logger.warn(`audit write failed: ${message}`)));
423
+ const audit = createJsonlAuditSink(dshHomePath("logs", "notify-email.jsonl"), (message) => logger.warn(`audit write failed: ${message}`));
424
+ this.mailer = new Mailer(() => this.current(), logger, void 0, audit);
419
425
  this.registerTrigger(createDecisionTrigger(() => this.current()));
420
426
  this.registerTrigger(createTurnEndTrigger(() => this.current()));
421
427
  installDecisionWatcher(ctx, this);
@@ -472,7 +478,6 @@ var NotifyEmailService = class extends Service {
472
478
  }
473
479
  }
474
480
  };
475
-
476
481
  //#endregion
477
482
  //#region src/index.ts
478
483
  const name = "dsh-plus-notify-email";
@@ -480,6 +485,5 @@ const inject = ["agents", "tools"];
480
485
  function apply(ctx, config) {
481
486
  ctx.plugin(NotifyEmailService, config);
482
487
  }
483
-
484
488
  //#endregion
485
- export { Config, NotifyEmailService, apply, inject, name };
489
+ export { Config, NotifyEmailService, apply, inject, name };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-plus/notify-email",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "dsh-plus service+ui plugin: 任务结束/等待决策/出错时向指定邮箱发送邮件通知",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -42,13 +42,13 @@
42
42
  },
43
43
  "devDependencies": {
44
44
  "@deepseek-ai/cordis": "4.0.1",
45
- "@deepseek-ai/dsh-agent": "0.1.0-rc.8",
46
- "@deepseek-ai/dsh-home-paths": "0.1.0-rc.8",
47
- "@deepseek-ai/dsh-host-webserver": "0.1.0-rc.8",
48
- "@deepseek-ai/dsh-llm": "0.1.0-rc.8",
49
- "@deepseek-ai/dsh-session": "0.1.0-rc.8",
50
- "@deepseek-ai/dsh-settings": "0.1.0-rc.8",
51
- "@deepseek-ai/dsh-tools": "0.1.0-rc.8",
45
+ "@deepseek-ai/dsh-agent": "0.1.1-rc.2",
46
+ "@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
47
+ "@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
48
+ "@deepseek-ai/dsh-llm": "0.1.1-rc.2",
49
+ "@deepseek-ai/dsh-session": "0.1.1-rc.2",
50
+ "@deepseek-ai/dsh-settings": "0.1.1-rc.2",
51
+ "@deepseek-ai/dsh-tools": "0.1.1-rc.2",
52
52
  "@deepseek-ai/schemastery": "3.18.1",
53
53
  "@types/nodemailer": "8.0.1",
54
54
  "@types/react": "~18.3.1",