dsh-messager 0.3.1 → 0.3.3

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.
@@ -16,8 +16,15 @@ import type { IncomingMessage } from 'node:http';
16
16
  import type { WebRoute } from '@deepseek-ai/dsh-host-webserver';
17
17
  import type { SettingsPathOp } from '@deepseek-ai/dsh-settings';
18
18
  import type { ConfigView, ConfigWriteBody } from './config-shared.js';
19
- /** 命名空间(与 host 注册一致)。 */
20
- export declare const CONFIG_NAMESPACE: "messager";
19
+ /**
20
+ * 命名空间(= 本插件在 profile 中的条目 id)。
21
+ *
22
+ * ⚠️ 0.1.7 起 settings 命名空间就是 profile 条目 id,**不是**固定字符串。
23
+ * 不同装载方式(bundle 的 cordis.patch.yml / dev 的 cordis.yml / marketplace)
24
+ * 可能给出不同的 id,因此默认值只作兜底,真实值由调用方经
25
+ * `resolveNamespace(ctx)` 反查后传入。
26
+ */
27
+ export declare const CONFIG_NAMESPACE = "messager";
21
28
  export type { ConfigView, ConfigWriteBody } from './config-shared.js';
22
29
  /** 路由依赖的 settings 服务窄接口(便于测试替身)。 */
23
30
  export interface SettingsServiceLike {
@@ -38,7 +45,7 @@ export interface WebServerLike {
38
45
  register(route: WebRoute): () => void;
39
46
  }
40
47
  /** 把 settings 描述符映射为 client 视图;命名空间缺失 → unavailable。 */
41
- export declare function configViewOf(settings: SettingsServiceLike): ConfigView;
48
+ export declare function configViewOf(settings: SettingsServiceLike, namespace?: string): ConfigView;
42
49
  /** 校验并规范化写请求体;非法 → undefined。 */
43
50
  export declare function parseConfigWriteBody(raw: unknown): ConfigWriteBody | undefined;
44
51
  /**
@@ -48,7 +55,10 @@ export declare function parseConfigWriteBody(raw: unknown): ConfigWriteBody | un
48
55
  export declare function sameOrigin(request: IncomingMessage, requireOrigin: boolean): boolean;
49
56
  /**
50
57
  * 挂载配置路由(webServer 服务可用时调用)。
58
+ * @param webServer - webServer 服务(窄接口)。
59
+ * @param settings - settings 服务(窄接口)。
60
+ * @param namespace - 本插件在 profile 中的条目 id(settings 命名空间)。
51
61
  * @returns 卸载函数。
52
62
  */
53
- export declare function mountConfigRoutes(webServer: WebServerLike, settings: SettingsServiceLike): () => void;
63
+ export declare function mountConfigRoutes(webServer: WebServerLike, settings: SettingsServiceLike, namespace?: string): () => void;
54
64
  //# sourceMappingURL=config-route.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-route.d.ts","sourceRoot":"","sources":["../src/config-route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAErE,yBAAyB;AACzB,eAAO,MAAM,gBAAgB,EAAG,UAAmB,CAAA;AAEnD,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAErE,oCAAoC;AACpC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,aAAa,CAAC;QAC7D,EAAE,EAAE,MAAM,CAAA;QACV,KAAK,EAAE,OAAO,CAAA;QACd,QAAQ,EAAE,MAAM,CAAA;QAChB,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,IAAI,CAAC,EAAE,OAAO,CAAA;KACf,CAAC,CAAA;IACF,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,cAAc,EAAE,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7F;AAED,gCAAgC;AAChC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,IAAI,CAAA;CACtC;AAID,wDAAwD;AACxD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,mBAAmB,GAAG,UAAU,CActE;AAED,iCAAiC;AACjC,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAwB9E;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,GAAG,OAAO,CAWpF;AAiED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,mBAAmB,GAAG,MAAM,IAAI,CAsBrG"}
1
+ {"version":3,"file":"config-route.d.ts","sourceRoot":"","sources":["../src/config-route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGrE;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,aAAoB,CAAA;AAEjD,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAErE,oCAAoC;AACpC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,aAAa,CAAC;QAC7D,EAAE,EAAE,MAAM,CAAA;QACV,KAAK,EAAE,OAAO,CAAA;QACd,QAAQ,EAAE,MAAM,CAAA;QAChB,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,IAAI,CAAC,EAAE,OAAO,CAAA;KACf,CAAC,CAAA;IACF,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,cAAc,EAAE,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7F;AAED,gCAAgC;AAChC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,IAAI,CAAA;CACtC;AAID,wDAAwD;AACxD,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,GAAE,MAAyB,GACnC,UAAU,CAcZ;AAED,iCAAiC;AACjC,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAwB9E;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,GAAG,OAAO,CAWpF;AAkED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,aAAa,EACxB,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,GAAE,MAAyB,GACnC,MAAM,IAAI,CAsBZ"}
@@ -12,12 +12,20 @@
12
12
  * 跨站 JS 无法读取;GET 只读无副作用。
13
13
  * 密钥:describe({ redactSecrets: true }) 自动脱敏,写入方向与设置页一致。
14
14
  */
15
- /** 命名空间(与 host 注册一致)。 */
16
- export const CONFIG_NAMESPACE = 'messager';
15
+ import { FALLBACK_ENTRY_ID } from './settings.js';
16
+ /**
17
+ * 命名空间(= 本插件在 profile 中的条目 id)。
18
+ *
19
+ * ⚠️ 0.1.7 起 settings 命名空间就是 profile 条目 id,**不是**固定字符串。
20
+ * 不同装载方式(bundle 的 cordis.patch.yml / dev 的 cordis.yml / marketplace)
21
+ * 可能给出不同的 id,因此默认值只作兜底,真实值由调用方经
22
+ * `resolveNamespace(ctx)` 反查后传入。
23
+ */
24
+ export const CONFIG_NAMESPACE = FALLBACK_ENTRY_ID;
17
25
  // ---- 纯逻辑(可单测) ----
18
26
  /** 把 settings 描述符映射为 client 视图;命名空间缺失 → unavailable。 */
19
- export function configViewOf(settings) {
20
- const descriptor = settings.describe({ redactSecrets: true }).find(candidate => candidate.ns === CONFIG_NAMESPACE);
27
+ export function configViewOf(settings, namespace = CONFIG_NAMESPACE) {
28
+ const descriptor = settings.describe({ redactSecrets: true }).find(candidate => candidate.ns === namespace);
21
29
  if (descriptor === undefined) {
22
30
  return { status: 'unavailable', value: undefined, user: undefined, base: undefined, writable: settings.writable, mode: 'host' };
23
31
  }
@@ -106,10 +114,10 @@ function readBody(request, limit = 64 * 1024) {
106
114
  request.on('error', reject);
107
115
  });
108
116
  }
109
- function handleGet(settings, res) {
110
- sendJson(res, 200, configViewOf(settings));
117
+ function handleGet(settings, res, namespace) {
118
+ sendJson(res, 200, configViewOf(settings, namespace));
111
119
  }
112
- async function handlePost(settings, request, res) {
120
+ async function handlePost(settings, request, res, namespace) {
113
121
  if (!sameOrigin(request, true)) {
114
122
  sendJson(res, 403, { ok: false, error: 'untrusted origin' });
115
123
  return;
@@ -128,7 +136,7 @@ async function handlePost(settings, request, res) {
128
136
  return;
129
137
  }
130
138
  try {
131
- await settings.mutate(CONFIG_NAMESPACE, body.ops, body.expectedRevision);
139
+ await settings.mutate(namespace, body.ops, body.expectedRevision);
132
140
  sendJson(res, 200, { ok: true });
133
141
  }
134
142
  catch (error) {
@@ -140,20 +148,23 @@ async function handlePost(settings, request, res) {
140
148
  }
141
149
  /**
142
150
  * 挂载配置路由(webServer 服务可用时调用)。
151
+ * @param webServer - webServer 服务(窄接口)。
152
+ * @param settings - settings 服务(窄接口)。
153
+ * @param namespace - 本插件在 profile 中的条目 id(settings 命名空间)。
143
154
  * @returns 卸载函数。
144
155
  */
145
- export function mountConfigRoutes(webServer, settings) {
156
+ export function mountConfigRoutes(webServer, settings, namespace = CONFIG_NAMESPACE) {
146
157
  const routes = [
147
158
  {
148
159
  kind: 'exact',
149
160
  path: '/dsh-messager/config',
150
161
  handler: (request, response) => {
151
162
  if (request.method === 'GET') {
152
- handleGet(settings, response);
163
+ handleGet(settings, response, namespace);
153
164
  return;
154
165
  }
155
166
  if (request.method === 'POST') {
156
- return handlePost(settings, request, response);
167
+ return handlePost(settings, request, response, namespace);
157
168
  }
158
169
  response.writeHead(405, { allow: 'GET, POST' });
159
170
  response.end();
@@ -1 +1 @@
1
- {"version":3,"file":"config-route.js","sourceRoot":"","sources":["../src/config-route.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config-route.js","sourceRoot":"","sources":["../src/config-route.ts"],"names":[],"mappings":"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"}
package/lib/config.d.ts CHANGED
@@ -1,14 +1,21 @@
1
1
  /**
2
2
  * dsh-messager 配置模型。
3
3
  *
4
- * 本 schema 同时承担两个角色:
5
- * - host 端的 Loader config(cordis.yml 中该插件行的 `config:`,成为 settings 命名空间的 base 层);
6
- * - `ctx.settings.register('messager', Config, { base })` 的命名空间 schema,
7
- * 因此 Web 设置页会自动渲染配置表单,用户层可覆盖 base。
4
+ * DSH 0.1.7 起,本 schema 由 **Loader 自动接管**:插件模块导出的 `Config` 即
5
+ * settings 表单的 schema,命名空间 = profile 中该插件条目的 id(本仓库的
6
+ * `cordis.patch.yml` / `cordis.yml` 都声明为 `messager`)。
7
+ * 因此**不再有** `ctx.settings.register(...)` 这一步。
8
8
  *
9
- * 有效值优先级:schema 默认值 → base(cordis.yml)→ 用户层(设置页)。
9
+ * ⚠️ 所有可编辑字段必须标记 `.volatile()`:DSH 用 `isVolatilePath` 门控写入,
10
+ * 非 volatile 路径一律被 `settings.mutate` 拒绝("Config field ... is not volatile"),
11
+ * 且没有任何 volatile 字段时整个命名空间会被 `volatileForm` 判为不可配置
12
+ * ("Plugin entry ... has no volatile fields"),设置页直接报废。
13
+ * 这是 0.1.7 的硬契约,不是可选项。
14
+ *
15
+ * 有效值优先级:schema 默认值 → base(Loader config)→ 用户层(设置页)。
10
16
  */
11
17
  import Schema from '@deepseek-ai/schemastery';
18
+ import { type Volatile } from '@deepseek-ai/cosmokit';
12
19
  /** 通知内容繁复度。 */
13
20
  export type Verbosity = 'minimal' | 'normal' | 'detailed';
14
21
  /** 触发时机开关(需求 1:什么时候通知)。 */
@@ -119,10 +126,246 @@ export interface Config {
119
126
  dedup: DedupConfig;
120
127
  message: MessageConfig;
121
128
  }
122
- export declare const Config: Schema<Config>;
129
+ export declare const Config: Schema<Schemastery.ObjectS<NoInfer<{
130
+ triggers: Schema<Schemastery.ObjectS<NoInfer<{
131
+ interaction: Schema<boolean, boolean, "volatile-defined">;
132
+ completed: Schema<boolean, boolean, "volatile-defined">;
133
+ error: Schema<boolean, boolean, "volatile-defined">;
134
+ }>>, Schemastery.ObjectT<NoInfer<{
135
+ interaction: Schema<boolean, boolean, "volatile-defined">;
136
+ completed: Schema<boolean, boolean, "volatile-defined">;
137
+ error: Schema<boolean, boolean, "volatile-defined">;
138
+ }>>, "plain">;
139
+ system: Schema<Schemastery.ObjectS<NoInfer<{
140
+ enabled: Schema<boolean, boolean, "volatile-defined">;
141
+ icon: Schema<string, string, "volatile">;
142
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
143
+ }>>, Schemastery.ObjectT<NoInfer<{
144
+ enabled: Schema<boolean, boolean, "volatile-defined">;
145
+ icon: Schema<string, string, "volatile">;
146
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
147
+ }>>, "plain">;
148
+ browser: Schema<Schemastery.ObjectS<NoInfer<{
149
+ enabled: Schema<boolean, boolean, "volatile-defined">;
150
+ icon: Schema<string, string, "volatile">;
151
+ onlyWhenHidden: Schema<boolean, boolean, "volatile-defined">;
152
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
153
+ }>>, Schemastery.ObjectT<NoInfer<{
154
+ enabled: Schema<boolean, boolean, "volatile-defined">;
155
+ icon: Schema<string, string, "volatile">;
156
+ onlyWhenHidden: Schema<boolean, boolean, "volatile-defined">;
157
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
158
+ }>>, "plain">;
159
+ feishu: Schema<Schemastery.ObjectS<NoInfer<{
160
+ enabled: Schema<boolean, boolean, "volatile-defined">;
161
+ webhookUrl: Schema<string, string, "volatile">;
162
+ secret: Schema<string, string, "volatile">;
163
+ timeoutMs: Schema<number, number, "volatile-defined">;
164
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
165
+ }>>, Schemastery.ObjectT<NoInfer<{
166
+ enabled: Schema<boolean, boolean, "volatile-defined">;
167
+ webhookUrl: Schema<string, string, "volatile">;
168
+ secret: Schema<string, string, "volatile">;
169
+ timeoutMs: Schema<number, number, "volatile-defined">;
170
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
171
+ }>>, "plain">;
172
+ wecom: Schema<Schemastery.ObjectS<NoInfer<{
173
+ enabled: Schema<boolean, boolean, "volatile-defined">;
174
+ webhookUrl: Schema<string, string, "volatile">;
175
+ secret: Schema<string, string, "volatile">;
176
+ timeoutMs: Schema<number, number, "volatile-defined">;
177
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
178
+ }>>, Schemastery.ObjectT<NoInfer<{
179
+ enabled: Schema<boolean, boolean, "volatile-defined">;
180
+ webhookUrl: Schema<string, string, "volatile">;
181
+ secret: Schema<string, string, "volatile">;
182
+ timeoutMs: Schema<number, number, "volatile-defined">;
183
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
184
+ }>>, "plain">;
185
+ discord: Schema<Schemastery.ObjectS<NoInfer<{
186
+ enabled: Schema<boolean, boolean, "volatile-defined">;
187
+ webhookUrl: Schema<string, string, "volatile">;
188
+ timeoutMs: Schema<number, number, "volatile-defined">;
189
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
190
+ }>>, Schemastery.ObjectT<NoInfer<{
191
+ enabled: Schema<boolean, boolean, "volatile-defined">;
192
+ webhookUrl: Schema<string, string, "volatile">;
193
+ timeoutMs: Schema<number, number, "volatile-defined">;
194
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
195
+ }>>, "plain">;
196
+ dingtalk: Schema<Schemastery.ObjectS<NoInfer<{
197
+ enabled: Schema<boolean, boolean, "volatile-defined">;
198
+ webhookUrl: Schema<string, string, "volatile">;
199
+ secret: Schema<string, string, "volatile">;
200
+ timeoutMs: Schema<number, number, "volatile-defined">;
201
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
202
+ }>>, Schemastery.ObjectT<NoInfer<{
203
+ enabled: Schema<boolean, boolean, "volatile-defined">;
204
+ webhookUrl: Schema<string, string, "volatile">;
205
+ secret: Schema<string, string, "volatile">;
206
+ timeoutMs: Schema<number, number, "volatile-defined">;
207
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
208
+ }>>, "plain">;
209
+ telegram: Schema<Schemastery.ObjectS<NoInfer<{
210
+ enabled: Schema<boolean, boolean, "volatile-defined">;
211
+ botToken: Schema<string, string, "volatile">;
212
+ chatId: Schema<string, string, "volatile">;
213
+ timeoutMs: Schema<number, number, "volatile-defined">;
214
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
215
+ }>>, Schemastery.ObjectT<NoInfer<{
216
+ enabled: Schema<boolean, boolean, "volatile-defined">;
217
+ botToken: Schema<string, string, "volatile">;
218
+ chatId: Schema<string, string, "volatile">;
219
+ timeoutMs: Schema<number, number, "volatile-defined">;
220
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
221
+ }>>, "plain">;
222
+ dedup: Schema<Schemastery.ObjectS<NoInfer<{
223
+ interactionCooldownMs: Schema<number, number, "volatile-defined">;
224
+ completedDebounceMs: Schema<number, number, "volatile-defined">;
225
+ perChannelPerMinute: Schema<number, number, "volatile-defined">;
226
+ }>>, Schemastery.ObjectT<NoInfer<{
227
+ interactionCooldownMs: Schema<number, number, "volatile-defined">;
228
+ completedDebounceMs: Schema<number, number, "volatile-defined">;
229
+ perChannelPerMinute: Schema<number, number, "volatile-defined">;
230
+ }>>, "plain">;
231
+ message: Schema<Schemastery.ObjectS<NoInfer<{
232
+ titlePrefix: Schema<string, string, "volatile">;
233
+ includeSessionTitle: Schema<boolean, boolean, "volatile-defined">;
234
+ guiUrl: Schema<string, string, "volatile-defined">;
235
+ }>>, Schemastery.ObjectT<NoInfer<{
236
+ titlePrefix: Schema<string, string, "volatile">;
237
+ includeSessionTitle: Schema<boolean, boolean, "volatile-defined">;
238
+ guiUrl: Schema<string, string, "volatile-defined">;
239
+ }>>, "plain">;
240
+ }>>, Schemastery.ObjectT<NoInfer<{
241
+ triggers: Schema<Schemastery.ObjectS<NoInfer<{
242
+ interaction: Schema<boolean, boolean, "volatile-defined">;
243
+ completed: Schema<boolean, boolean, "volatile-defined">;
244
+ error: Schema<boolean, boolean, "volatile-defined">;
245
+ }>>, Schemastery.ObjectT<NoInfer<{
246
+ interaction: Schema<boolean, boolean, "volatile-defined">;
247
+ completed: Schema<boolean, boolean, "volatile-defined">;
248
+ error: Schema<boolean, boolean, "volatile-defined">;
249
+ }>>, "plain">;
250
+ system: Schema<Schemastery.ObjectS<NoInfer<{
251
+ enabled: Schema<boolean, boolean, "volatile-defined">;
252
+ icon: Schema<string, string, "volatile">;
253
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
254
+ }>>, Schemastery.ObjectT<NoInfer<{
255
+ enabled: Schema<boolean, boolean, "volatile-defined">;
256
+ icon: Schema<string, string, "volatile">;
257
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
258
+ }>>, "plain">;
259
+ browser: Schema<Schemastery.ObjectS<NoInfer<{
260
+ enabled: Schema<boolean, boolean, "volatile-defined">;
261
+ icon: Schema<string, string, "volatile">;
262
+ onlyWhenHidden: Schema<boolean, boolean, "volatile-defined">;
263
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
264
+ }>>, Schemastery.ObjectT<NoInfer<{
265
+ enabled: Schema<boolean, boolean, "volatile-defined">;
266
+ icon: Schema<string, string, "volatile">;
267
+ onlyWhenHidden: Schema<boolean, boolean, "volatile-defined">;
268
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
269
+ }>>, "plain">;
270
+ feishu: Schema<Schemastery.ObjectS<NoInfer<{
271
+ enabled: Schema<boolean, boolean, "volatile-defined">;
272
+ webhookUrl: Schema<string, string, "volatile">;
273
+ secret: Schema<string, string, "volatile">;
274
+ timeoutMs: Schema<number, number, "volatile-defined">;
275
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
276
+ }>>, Schemastery.ObjectT<NoInfer<{
277
+ enabled: Schema<boolean, boolean, "volatile-defined">;
278
+ webhookUrl: Schema<string, string, "volatile">;
279
+ secret: Schema<string, string, "volatile">;
280
+ timeoutMs: Schema<number, number, "volatile-defined">;
281
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
282
+ }>>, "plain">;
283
+ wecom: Schema<Schemastery.ObjectS<NoInfer<{
284
+ enabled: Schema<boolean, boolean, "volatile-defined">;
285
+ webhookUrl: Schema<string, string, "volatile">;
286
+ secret: Schema<string, string, "volatile">;
287
+ timeoutMs: Schema<number, number, "volatile-defined">;
288
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
289
+ }>>, Schemastery.ObjectT<NoInfer<{
290
+ enabled: Schema<boolean, boolean, "volatile-defined">;
291
+ webhookUrl: Schema<string, string, "volatile">;
292
+ secret: Schema<string, string, "volatile">;
293
+ timeoutMs: Schema<number, number, "volatile-defined">;
294
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
295
+ }>>, "plain">;
296
+ discord: Schema<Schemastery.ObjectS<NoInfer<{
297
+ enabled: Schema<boolean, boolean, "volatile-defined">;
298
+ webhookUrl: Schema<string, string, "volatile">;
299
+ timeoutMs: Schema<number, number, "volatile-defined">;
300
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
301
+ }>>, Schemastery.ObjectT<NoInfer<{
302
+ enabled: Schema<boolean, boolean, "volatile-defined">;
303
+ webhookUrl: Schema<string, string, "volatile">;
304
+ timeoutMs: Schema<number, number, "volatile-defined">;
305
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
306
+ }>>, "plain">;
307
+ dingtalk: Schema<Schemastery.ObjectS<NoInfer<{
308
+ enabled: Schema<boolean, boolean, "volatile-defined">;
309
+ webhookUrl: Schema<string, string, "volatile">;
310
+ secret: Schema<string, string, "volatile">;
311
+ timeoutMs: Schema<number, number, "volatile-defined">;
312
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
313
+ }>>, Schemastery.ObjectT<NoInfer<{
314
+ enabled: Schema<boolean, boolean, "volatile-defined">;
315
+ webhookUrl: Schema<string, string, "volatile">;
316
+ secret: Schema<string, string, "volatile">;
317
+ timeoutMs: Schema<number, number, "volatile-defined">;
318
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
319
+ }>>, "plain">;
320
+ telegram: Schema<Schemastery.ObjectS<NoInfer<{
321
+ enabled: Schema<boolean, boolean, "volatile-defined">;
322
+ botToken: Schema<string, string, "volatile">;
323
+ chatId: Schema<string, string, "volatile">;
324
+ timeoutMs: Schema<number, number, "volatile-defined">;
325
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
326
+ }>>, Schemastery.ObjectT<NoInfer<{
327
+ enabled: Schema<boolean, boolean, "volatile-defined">;
328
+ botToken: Schema<string, string, "volatile">;
329
+ chatId: Schema<string, string, "volatile">;
330
+ timeoutMs: Schema<number, number, "volatile-defined">;
331
+ verbosity: Schema<"minimal" | "normal" | "detailed", "minimal" | "normal" | "detailed", "volatile-defined">;
332
+ }>>, "plain">;
333
+ dedup: Schema<Schemastery.ObjectS<NoInfer<{
334
+ interactionCooldownMs: Schema<number, number, "volatile-defined">;
335
+ completedDebounceMs: Schema<number, number, "volatile-defined">;
336
+ perChannelPerMinute: Schema<number, number, "volatile-defined">;
337
+ }>>, Schemastery.ObjectT<NoInfer<{
338
+ interactionCooldownMs: Schema<number, number, "volatile-defined">;
339
+ completedDebounceMs: Schema<number, number, "volatile-defined">;
340
+ perChannelPerMinute: Schema<number, number, "volatile-defined">;
341
+ }>>, "plain">;
342
+ message: Schema<Schemastery.ObjectS<NoInfer<{
343
+ titlePrefix: Schema<string, string, "volatile">;
344
+ includeSessionTitle: Schema<boolean, boolean, "volatile-defined">;
345
+ guiUrl: Schema<string, string, "volatile-defined">;
346
+ }>>, Schemastery.ObjectT<NoInfer<{
347
+ titlePrefix: Schema<string, string, "volatile">;
348
+ includeSessionTitle: Schema<boolean, boolean, "volatile-defined">;
349
+ guiUrl: Schema<string, string, "volatile-defined">;
350
+ }>>, "plain">;
351
+ }>>, "plain">;
352
+ /**
353
+ * 递归把纯值形态映射为 volatile 引用形态。
354
+ *
355
+ * `.volatile()` 只标在**叶子**上(分组对象本身不标),因此推导结果与
356
+ * schemastery 的实际输出一致:分组是普通对象,叶子是 `Volatile<T>` 引用。
357
+ * 这就是 Loader 传给 `apply(ctx, config)` 的运行时配置形态。
358
+ */
359
+ export type VolatileShape<T> = {
360
+ [K in keyof T]: T[K] extends object ? VolatileShape<T[K]> : Volatile<T[K]>;
361
+ };
362
+ /** Loader 传入 `apply()` 的运行时配置(可编辑字段是 volatile 引用)。 */
363
+ export type RuntimeConfig = VolatileShape<Config>;
123
364
  /**
124
365
  * 用 schema 默认值解析一份配置(输入可省略任意字段)。
125
- * 与 cordis Loader 的校验同源,保证“默认值 → base → 用户层”的解析一致。
366
+ *
367
+ * 输入既可以是纯值(Loader config / settings 视图),也可以是 Loader 传入的
368
+ * volatile 形态 —— 两者都先解包再校验,保证「默认值 → base → 用户层」解析一致。
126
369
  */
127
- export declare function resolveConfig(input?: Partial<Config>): Config;
370
+ export declare function resolveConfig(input?: unknown): Config;
128
371
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAE7C,eAAe;AACf,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAA;AAEzD,2BAA2B;AAC3B,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,WAAW,EAAE,OAAO,CAAA;IACpB,iBAAiB;IACjB,SAAS,EAAE,OAAO,CAAA;IAClB,eAAe;IACf,KAAK,EAAE,OAAO,CAAA;CACf;AAED,mDAAmD;AACnD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAA;IAChB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,yBAAyB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kCAAkC;IAClC,cAAc,EAAE,OAAO,CAAA;IACvB,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,mDAAmD;AACnD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAA;IAChB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,oCAAoC;AACpC,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAA;IAChB,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,oCAAoC;AACpC,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,oCAAoC;AACpC,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAA;IAChB,mFAAmF;IACnF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,qCAAqC;AACrC,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAA;IAChB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,iBAAiB;AACjB,MAAM,WAAW,WAAW;IAC1B,0BAA0B;IAC1B,qBAAqB,EAAE,MAAM,CAAA;IAC7B,+CAA+C;IAC/C,mBAAmB,EAAE,MAAM,CAAA;IAC3B,gCAAgC;IAChC,mBAAmB,EAAE,MAAM,CAAA;CAC5B;AAED,cAAc;AACd,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kBAAkB;IAClB,mBAAmB,EAAE,OAAO,CAAA;IAC5B,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,EAAE,aAAa,CAAA;IACvB,MAAM,EAAE,mBAAmB,CAAA;IAC3B,OAAO,EAAE,oBAAoB,CAAA;IAC7B,MAAM,EAAE,mBAAmB,CAAA;IAC3B,KAAK,EAAE,kBAAkB,CAAA;IACzB,OAAO,EAAE,oBAAoB,CAAA;IAC7B,QAAQ,EAAE,qBAAqB,CAAA;IAC/B,QAAQ,EAAE,qBAAqB,CAAA;IAC/B,KAAK,EAAE,WAAW,CAAA;IAClB,OAAO,EAAE,aAAa,CAAA;CACvB;AAID,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,CAiEhC,CAAA;AAEF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,GAAE,OAAO,CAAC,MAAM,CAAM,GAAG,MAAM,CAEjE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/lib/config.js CHANGED
@@ -1,86 +1,117 @@
1
1
  /**
2
2
  * dsh-messager 配置模型。
3
3
  *
4
- * 本 schema 同时承担两个角色:
5
- * - host 端的 Loader config(cordis.yml 中该插件行的 `config:`,成为 settings 命名空间的 base 层);
6
- * - `ctx.settings.register('messager', Config, { base })` 的命名空间 schema,
7
- * 因此 Web 设置页会自动渲染配置表单,用户层可覆盖 base。
4
+ * DSH 0.1.7 起,本 schema 由 **Loader 自动接管**:插件模块导出的 `Config` 即
5
+ * settings 表单的 schema,命名空间 = profile 中该插件条目的 id(本仓库的
6
+ * `cordis.patch.yml` / `cordis.yml` 都声明为 `messager`)。
7
+ * 因此**不再有** `ctx.settings.register(...)` 这一步。
8
8
  *
9
- * 有效值优先级:schema 默认值 → base(cordis.yml)→ 用户层(设置页)。
9
+ * ⚠️ 所有可编辑字段必须标记 `.volatile()`:DSH 用 `isVolatilePath` 门控写入,
10
+ * 非 volatile 路径一律被 `settings.mutate` 拒绝("Config field ... is not volatile"),
11
+ * 且没有任何 volatile 字段时整个命名空间会被 `volatileForm` 判为不可配置
12
+ * ("Plugin entry ... has no volatile fields"),设置页直接报废。
13
+ * 这是 0.1.7 的硬契约,不是可选项。
14
+ *
15
+ * 有效值优先级:schema 默认值 → base(Loader config)→ 用户层(设置页)。
10
16
  */
11
17
  import Schema from '@deepseek-ai/schemastery';
18
+ import { isVolatile } from '@deepseek-ai/cosmokit';
12
19
  const verbosity = Schema.union(['minimal', 'normal', 'detailed']);
20
+ // 全部叶子字段 .volatile() —— 见文件头说明,0.1.7 用 volatile 门控设置页写入。
21
+ //
22
+ // 这里**不写** `: Schema<Config>` 标注(DSH 官方插件同样不标注):`.volatile()`
23
+ // 让 schema 的输出形态变成 `RuntimeConfig`,而 `Schema<T>` 的 `meta.default` 用的是
24
+ // *输入*(纯值)形态,两种标注都对不上,交给 schemastery 推导即可。
13
25
  export const Config = Schema.object({
14
26
  triggers: Schema.object({
15
- interaction: Schema.boolean().default(true),
16
- completed: Schema.boolean().default(true),
17
- error: Schema.boolean().default(true),
27
+ interaction: Schema.boolean().default(true).volatile(),
28
+ completed: Schema.boolean().default(true).volatile(),
29
+ error: Schema.boolean().default(true).volatile(),
18
30
  }),
19
31
  system: Schema.object({
20
- enabled: Schema.boolean().default(true),
32
+ enabled: Schema.boolean().default(true).volatile(),
21
33
  // 无 default 的字段即可选(undefined 允许)
22
34
  // 注意:node-notifier 需要文件路径且该文件必须存在;Linux(notify-send)与
23
35
  // macOS(terminal-notifier)对缺失路径可能直接失败而非像 Windows 那样降级,
24
36
  // 通道层虽已做存在性校验,仍建议配置有效的绝对路径。
25
- icon: Schema.string(),
26
- verbosity: verbosity.default('normal'),
37
+ icon: Schema.string().volatile(),
38
+ verbosity: verbosity.default('normal').volatile(),
27
39
  }),
28
40
  browser: Schema.object({
29
- enabled: Schema.boolean().default(true),
30
- icon: Schema.string(),
31
- onlyWhenHidden: Schema.boolean().default(true),
32
- verbosity: verbosity.default('normal'),
41
+ enabled: Schema.boolean().default(true).volatile(),
42
+ icon: Schema.string().volatile(),
43
+ onlyWhenHidden: Schema.boolean().default(true).volatile(),
44
+ verbosity: verbosity.default('normal').volatile(),
33
45
  }),
34
46
  feishu: Schema.object({
35
- enabled: Schema.boolean().default(false),
36
- webhookUrl: Schema.string(),
37
- secret: Schema.string().role('secret'),
38
- timeoutMs: Schema.number().default(5000),
39
- verbosity: verbosity.default('normal'),
47
+ enabled: Schema.boolean().default(false).volatile(),
48
+ webhookUrl: Schema.string().volatile(),
49
+ secret: Schema.string().role('secret').volatile(),
50
+ timeoutMs: Schema.number().default(5000).volatile(),
51
+ verbosity: verbosity.default('normal').volatile(),
40
52
  }),
41
53
  wecom: Schema.object({
42
- enabled: Schema.boolean().default(false),
43
- webhookUrl: Schema.string(),
44
- secret: Schema.string().role('secret'),
45
- timeoutMs: Schema.number().default(5000),
46
- verbosity: verbosity.default('normal'),
54
+ enabled: Schema.boolean().default(false).volatile(),
55
+ webhookUrl: Schema.string().volatile(),
56
+ secret: Schema.string().role('secret').volatile(),
57
+ timeoutMs: Schema.number().default(5000).volatile(),
58
+ verbosity: verbosity.default('normal').volatile(),
47
59
  }),
48
60
  discord: Schema.object({
49
- enabled: Schema.boolean().default(false),
50
- webhookUrl: Schema.string(),
51
- timeoutMs: Schema.number().default(5000),
52
- verbosity: verbosity.default('normal'),
61
+ enabled: Schema.boolean().default(false).volatile(),
62
+ webhookUrl: Schema.string().volatile(),
63
+ timeoutMs: Schema.number().default(5000).volatile(),
64
+ verbosity: verbosity.default('normal').volatile(),
53
65
  }),
54
66
  dingtalk: Schema.object({
55
- enabled: Schema.boolean().default(false),
56
- webhookUrl: Schema.string(),
57
- secret: Schema.string().role('secret'),
58
- timeoutMs: Schema.number().default(5000),
59
- verbosity: verbosity.default('normal'),
67
+ enabled: Schema.boolean().default(false).volatile(),
68
+ webhookUrl: Schema.string().volatile(),
69
+ secret: Schema.string().role('secret').volatile(),
70
+ timeoutMs: Schema.number().default(5000).volatile(),
71
+ verbosity: verbosity.default('normal').volatile(),
60
72
  }),
61
73
  telegram: Schema.object({
62
- enabled: Schema.boolean().default(false),
63
- botToken: Schema.string().role('secret'),
64
- chatId: Schema.string(),
65
- timeoutMs: Schema.number().default(5000),
66
- verbosity: verbosity.default('normal'),
74
+ enabled: Schema.boolean().default(false).volatile(),
75
+ botToken: Schema.string().role('secret').volatile(),
76
+ chatId: Schema.string().volatile(),
77
+ timeoutMs: Schema.number().default(5000).volatile(),
78
+ verbosity: verbosity.default('normal').volatile(),
67
79
  }),
68
80
  dedup: Schema.object({
69
- interactionCooldownMs: Schema.number().default(10000),
70
- completedDebounceMs: Schema.number().default(1000),
71
- perChannelPerMinute: Schema.number().default(20),
81
+ interactionCooldownMs: Schema.number().default(10000).volatile(),
82
+ completedDebounceMs: Schema.number().default(1000).volatile(),
83
+ perChannelPerMinute: Schema.number().default(20).volatile(),
72
84
  }),
73
85
  message: Schema.object({
74
- titlePrefix: Schema.string(),
75
- includeSessionTitle: Schema.boolean().default(true),
76
- guiUrl: Schema.string().default('http://127.0.0.1:3080'),
86
+ titlePrefix: Schema.string().volatile(),
87
+ includeSessionTitle: Schema.boolean().default(true).volatile(),
88
+ guiUrl: Schema.string().default('http://127.0.0.1:3080').volatile(),
77
89
  }),
78
90
  });
91
+ /**
92
+ * 递归解开 volatile 引用,得到纯值。
93
+ *
94
+ * volatile 引用在配置热更新时**原地变更**(这正是无需重挂载的原因),
95
+ * 所以引用本身要保留;本插件的内部逻辑(通道构建/调度/模板)只需要某一时刻的
96
+ * 纯值,因此在边界处统一取值。
97
+ */
98
+ function unwrapVolatile(value) {
99
+ if (isVolatile(value))
100
+ return unwrapVolatile(value.get());
101
+ if (Array.isArray(value))
102
+ return value.map(unwrapVolatile);
103
+ if (value !== null && typeof value === 'object') {
104
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, unwrapVolatile(child)]));
105
+ }
106
+ return value;
107
+ }
79
108
  /**
80
109
  * 用 schema 默认值解析一份配置(输入可省略任意字段)。
81
- * 与 cordis Loader 的校验同源,保证“默认值 → base → 用户层”的解析一致。
110
+ *
111
+ * 输入既可以是纯值(Loader config / settings 视图),也可以是 Loader 传入的
112
+ * volatile 形态 —— 两者都先解包再校验,保证「默认值 → base → 用户层」解析一致。
82
113
  */
83
114
  export function resolveConfig(input = {}) {
84
- return Config(input);
115
+ return unwrapVolatile(Config(unwrapVolatile(input)));
85
116
  }
86
117
  //# sourceMappingURL=config.js.map