dsh-messager 0.1.4
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 -0
- package/README.en.md +86 -0
- package/README.md +241 -0
- package/assets/icon.png +0 -0
- package/cordis.patch.yml +11 -0
- package/lib/channels/feishu.d.ts +58 -0
- package/lib/channels/feishu.d.ts.map +1 -0
- package/lib/channels/feishu.js +77 -0
- package/lib/channels/feishu.js.map +1 -0
- package/lib/channels/system.d.ts +26 -0
- package/lib/channels/system.d.ts.map +1 -0
- package/lib/channels/system.js +73 -0
- package/lib/channels/system.js.map +1 -0
- package/lib/client.js +2001 -0
- package/lib/client.js.map +1 -0
- package/lib/config-route.d.ts +55 -0
- package/lib/config-route.d.ts.map +1 -0
- package/lib/config-route.js +170 -0
- package/lib/config-route.js.map +1 -0
- package/lib/config-shared.d.ts +28 -0
- package/lib/config-shared.d.ts.map +1 -0
- package/lib/config-shared.js +7 -0
- package/lib/config-shared.js.map +1 -0
- package/lib/config.d.ts +82 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +59 -0
- package/lib/config.js.map +1 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +152 -0
- package/lib/index.js.map +1 -0
- package/lib/notify.d.ts +75 -0
- package/lib/notify.d.ts.map +1 -0
- package/lib/notify.js +157 -0
- package/lib/notify.js.map +1 -0
- package/lib/settings.d.ts +23 -0
- package/lib/settings.d.ts.map +1 -0
- package/lib/settings.js +23 -0
- package/lib/settings.js.map +1 -0
- package/lib/signals.d.ts +57 -0
- package/lib/signals.d.ts.map +1 -0
- package/lib/signals.js +52 -0
- package/lib/signals.js.map +1 -0
- package/lib/templates.d.ts +40 -0
- package/lib/templates.d.ts.map +1 -0
- package/lib/templates.js +107 -0
- package/lib/templates.js.map +1 -0
- package/lib/types/client/card-controller.d.ts +171 -0
- package/lib/types/client/card-controller.d.ts.map +1 -0
- package/lib/types/client/config.d.ts +20 -0
- package/lib/types/client/config.d.ts.map +1 -0
- package/lib/types/client/diff.d.ts +26 -0
- package/lib/types/client/diff.d.ts.map +1 -0
- package/lib/types/client/fetch-scope.d.ts +29 -0
- package/lib/types/client/fetch-scope.d.ts.map +1 -0
- package/lib/types/client/index.d.ts +24 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/lib/types/client/locales.d.ts +92 -0
- package/lib/types/client/locales.d.ts.map +1 -0
- package/lib/types/client/section.d.ts +16 -0
- package/lib/types/client/section.d.ts.map +1 -0
- package/lib/types/client/settings-form.d.ts +22 -0
- package/lib/types/client/settings-form.d.ts.map +1 -0
- package/lib/types/config-shared.d.ts +28 -0
- package/lib/types/config-shared.d.ts.map +1 -0
- package/lib/types/config.d.ts +82 -0
- package/lib/types/config.d.ts.map +1 -0
- package/package.json +96 -0
package/lib/signals.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 信号层:把 DSH 事件(session/event、agent/status、agent/error)翻译为
|
|
3
|
+
* 统一的通知信号(Signal)。提取逻辑为纯函数,便于单元测试。
|
|
4
|
+
*/
|
|
5
|
+
import type { SessionEvent, TurnEndReason } from '@deepseek-ai/dsh-session';
|
|
6
|
+
export type { TurnEndReason } from '@deepseek-ai/dsh-session';
|
|
7
|
+
/** 触发类型(对应配置 triggers.*)。 */
|
|
8
|
+
export type TriggerKind = 'interaction' | 'completed' | 'error';
|
|
9
|
+
/** 交互类型:审批(approval/asked)或提问/计划待审(ask_user_question 工具)。 */
|
|
10
|
+
export type InteractionKind = 'approval' | 'question';
|
|
11
|
+
/** 统一内部信号(调度层输入)。 */
|
|
12
|
+
export type Signal = {
|
|
13
|
+
kind: 'interaction';
|
|
14
|
+
sessionId: string;
|
|
15
|
+
interaction: InteractionKind;
|
|
16
|
+
toolName?: string;
|
|
17
|
+
reason?: string;
|
|
18
|
+
turn?: number;
|
|
19
|
+
step?: number;
|
|
20
|
+
seq: number;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'completed';
|
|
23
|
+
sessionId: string;
|
|
24
|
+
/** 最近一次 turn/end 的原因(由调度层合并)。 */
|
|
25
|
+
reason?: TurnEndReason;
|
|
26
|
+
turn?: number;
|
|
27
|
+
step?: number;
|
|
28
|
+
seq: number;
|
|
29
|
+
} | {
|
|
30
|
+
kind: 'error';
|
|
31
|
+
sessionId: string;
|
|
32
|
+
message: string;
|
|
33
|
+
turn?: number;
|
|
34
|
+
step?: number;
|
|
35
|
+
seq: number;
|
|
36
|
+
};
|
|
37
|
+
/** ask_user_question 工具的稳定名称(提问/计划待审均经由该工具发起)。 */
|
|
38
|
+
export declare const ASK_USER_QUESTION_TOOL = "ask_user_question";
|
|
39
|
+
/**
|
|
40
|
+
* 从一条会话事件中提取“需要交互”信号:
|
|
41
|
+
* - `approval/asked`(落库审计事件)→ 审批
|
|
42
|
+
* - `tool/call` 且工具名为 ask_user_question → 提问/计划待审
|
|
43
|
+
*
|
|
44
|
+
* @returns 交互信号;该事件与交互无关时返回 undefined。
|
|
45
|
+
*/
|
|
46
|
+
export declare function interactionSignalOf(sessionId: string, event: SessionEvent): Signal | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* 从一条会话事件中提取 turn/end 的结束原因。
|
|
49
|
+
* @returns { turn, reason };非 turn/end 事件返回 undefined。
|
|
50
|
+
*/
|
|
51
|
+
export declare function turnEndReasonOf(event: SessionEvent): {
|
|
52
|
+
turn: number;
|
|
53
|
+
reason: TurnEndReason;
|
|
54
|
+
} | undefined;
|
|
55
|
+
/** 把未知错误归一化为可展示的字符串(截断防刷屏)。 */
|
|
56
|
+
export declare function errorMessageOf(error: unknown, maxLength?: number): string;
|
|
57
|
+
//# sourceMappingURL=signals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../src/signals.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAG3E,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAE7D,6BAA6B;AAC7B,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,WAAW,GAAG,OAAO,CAAA;AAE/D,6DAA6D;AAC7D,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,UAAU,CAAA;AAErD,qBAAqB;AACrB,MAAM,MAAM,MAAM,GACd;IACA,IAAI,EAAE,aAAa,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,eAAe,CAAA;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;CACZ,GACC;IACA,IAAI,EAAE,WAAW,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,iCAAiC;IACjC,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;CACZ,GACC;IACA,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAEH,kDAAkD;AAClD,eAAO,MAAM,sBAAsB,sBAAsB,CAAA;AAEzD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAuB9F;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GAAG,SAAS,CAGxG;AACD,+BAA+B;AAC/B,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,SAAM,GAAG,MAAM,CAGtE"}
|
package/lib/signals.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 信号层:把 DSH 事件(session/event、agent/status、agent/error)翻译为
|
|
3
|
+
* 统一的通知信号(Signal)。提取逻辑为纯函数,便于单元测试。
|
|
4
|
+
*/
|
|
5
|
+
/** ask_user_question 工具的稳定名称(提问/计划待审均经由该工具发起)。 */
|
|
6
|
+
export const ASK_USER_QUESTION_TOOL = 'ask_user_question';
|
|
7
|
+
/**
|
|
8
|
+
* 从一条会话事件中提取“需要交互”信号:
|
|
9
|
+
* - `approval/asked`(落库审计事件)→ 审批
|
|
10
|
+
* - `tool/call` 且工具名为 ask_user_question → 提问/计划待审
|
|
11
|
+
*
|
|
12
|
+
* @returns 交互信号;该事件与交互无关时返回 undefined。
|
|
13
|
+
*/
|
|
14
|
+
export function interactionSignalOf(sessionId, event) {
|
|
15
|
+
if (event.type === 'approval/asked') {
|
|
16
|
+
return {
|
|
17
|
+
kind: 'interaction',
|
|
18
|
+
sessionId,
|
|
19
|
+
interaction: 'approval',
|
|
20
|
+
...(event.data.toolName === undefined ? {} : { toolName: event.data.toolName }),
|
|
21
|
+
...(event.data.reason === undefined ? {} : { reason: event.data.reason }),
|
|
22
|
+
seq: event.seq,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (event.type === 'tool/call' && event.data.name === ASK_USER_QUESTION_TOOL) {
|
|
26
|
+
return {
|
|
27
|
+
kind: 'interaction',
|
|
28
|
+
sessionId,
|
|
29
|
+
interaction: 'question',
|
|
30
|
+
toolName: event.data.name,
|
|
31
|
+
turn: event.data.turn,
|
|
32
|
+
step: event.data.step,
|
|
33
|
+
seq: event.seq,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 从一条会话事件中提取 turn/end 的结束原因。
|
|
40
|
+
* @returns { turn, reason };非 turn/end 事件返回 undefined。
|
|
41
|
+
*/
|
|
42
|
+
export function turnEndReasonOf(event) {
|
|
43
|
+
if (event.type !== 'turn/end')
|
|
44
|
+
return undefined;
|
|
45
|
+
return { turn: event.data.turn, reason: event.data.reason };
|
|
46
|
+
}
|
|
47
|
+
/** 把未知错误归一化为可展示的字符串(截断防刷屏)。 */
|
|
48
|
+
export function errorMessageOf(error, maxLength = 300) {
|
|
49
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
50
|
+
return message.length > maxLength ? `${message.slice(0, maxLength)}…` : message;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=signals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signals.js","sourceRoot":"","sources":["../src/signals.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA2CH,kDAAkD;AAClD,MAAM,CAAC,MAAM,sBAAsB,GAAG,mBAAmB,CAAA;AAEzD;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAAiB,EAAE,KAAmB;IACxE,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;QACpC,OAAO;YACL,IAAI,EAAE,aAAa;YACnB,SAAS;YACT,WAAW,EAAE,UAAU;YACvB,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC/E,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACzE,GAAG,EAAE,KAAK,CAAC,GAAG;SACf,CAAA;IACH,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,sBAAsB,EAAE,CAAC;QAC7E,OAAO;YACL,IAAI,EAAE,aAAa;YACnB,SAAS;YACT,WAAW,EAAE,UAAU;YACvB,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI;YACzB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI;YACrB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI;YACrB,GAAG,EAAE,KAAK,CAAC,GAAG;SACf,CAAA;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAmB;IACjD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,SAAS,CAAA;IAC/C,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAA;AAC7D,CAAC;AACD,+BAA+B;AAC/B,MAAM,UAAU,cAAc,CAAC,KAAc,EAAE,SAAS,GAAG,GAAG;IAC5D,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACtE,OAAO,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAA;AACjF,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 消息模板层:把 Signal 渲染为各通道的最终载荷(NotificationPayload)。
|
|
3
|
+
* 纯函数;verbosity(内容繁复度)按通道取值:
|
|
4
|
+
* - minimal:只有标题
|
|
5
|
+
* - normal:+ 会话标题 / 工具名 / 结束原因 / 错误摘要
|
|
6
|
+
* - detailed:+ turn/step 与 GUI 链接
|
|
7
|
+
*/
|
|
8
|
+
import type { Config, Verbosity } from './config.ts';
|
|
9
|
+
import type { Signal, TurnEndReason } from './signals.ts';
|
|
10
|
+
/** 投递给通道的最终通知载荷(已渲染)。 */
|
|
11
|
+
export interface NotificationPayload {
|
|
12
|
+
kind: Signal['kind'];
|
|
13
|
+
sessionId: string;
|
|
14
|
+
title: string;
|
|
15
|
+
body: string;
|
|
16
|
+
/** 打开 DSH 的地址(system 通道点击 / 飞书卡片按钮)。 */
|
|
17
|
+
url: string;
|
|
18
|
+
}
|
|
19
|
+
/** 渲染上下文。 */
|
|
20
|
+
export interface RenderContext {
|
|
21
|
+
signal: Signal;
|
|
22
|
+
config: Config;
|
|
23
|
+
/** 会话标题(来自 session/title 事件),可为空。 */
|
|
24
|
+
sessionTitle?: string;
|
|
25
|
+
verbosity: Verbosity;
|
|
26
|
+
}
|
|
27
|
+
/** 完成原因 → 标题与正文细节(DSH 的 TurnEndReason 为可扩展 sum 类型)。 */
|
|
28
|
+
export declare function completionLabelOf(reason: TurnEndReason): {
|
|
29
|
+
title: string;
|
|
30
|
+
detail?: string;
|
|
31
|
+
};
|
|
32
|
+
/** 标题(不含前缀):completed 依据结束原因细分。 */
|
|
33
|
+
export declare function baseTitleOf(signal: Signal): string;
|
|
34
|
+
/** 完整标题(含可选前缀)。 */
|
|
35
|
+
export declare function titleOf(ctx: RenderContext): string;
|
|
36
|
+
/** 正文(verbosity 决定繁复度)。 */
|
|
37
|
+
export declare function bodyOf(ctx: RenderContext): string;
|
|
38
|
+
/** 渲染完整载荷。 */
|
|
39
|
+
export declare function renderPayload(ctx: RenderContext): NotificationPayload;
|
|
40
|
+
//# sourceMappingURL=templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEzD,yBAAyB;AACzB,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,aAAa;AACb,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,qCAAqC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,SAAS,CAAA;CACrB;AAaD,uDAAuD;AACvD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAU3F;AAED,mCAAmC;AACnC,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED,mBAAmB;AACnB,wBAAgB,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAIlD;AAeD,2BAA2B;AAC3B,wBAAgB,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAgCjD;AAED,cAAc;AACd,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,mBAAmB,CAQrE"}
|
package/lib/templates.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 消息模板层:把 Signal 渲染为各通道的最终载荷(NotificationPayload)。
|
|
3
|
+
* 纯函数;verbosity(内容繁复度)按通道取值:
|
|
4
|
+
* - minimal:只有标题
|
|
5
|
+
* - normal:+ 会话标题 / 工具名 / 结束原因 / 错误摘要
|
|
6
|
+
* - detailed:+ turn/step 与 GUI 链接
|
|
7
|
+
*/
|
|
8
|
+
const KIND_TITLES = {
|
|
9
|
+
interaction: '需要交互',
|
|
10
|
+
completed: '任务完成',
|
|
11
|
+
error: '任务出错',
|
|
12
|
+
};
|
|
13
|
+
/** 交互类型的细分标题。 */
|
|
14
|
+
function interactionTitle(kind) {
|
|
15
|
+
return kind === 'approval' ? '需要交互:等待审批' : '需要交互:等待回答';
|
|
16
|
+
}
|
|
17
|
+
/** 完成原因 → 标题与正文细节(DSH 的 TurnEndReason 为可扩展 sum 类型)。 */
|
|
18
|
+
export function completionLabelOf(reason) {
|
|
19
|
+
switch (reason.kind) {
|
|
20
|
+
case 'completed': return { title: '任务完成' };
|
|
21
|
+
case 'aborted': return { title: '任务中止', detail: '任务被中止' };
|
|
22
|
+
case 'blocked': return { title: '任务受阻', detail: '任务被阻塞' };
|
|
23
|
+
case 'error': return { title: '任务失败', detail: '任务执行出错' };
|
|
24
|
+
case 'max-tokens': return { title: '输出达上限', detail: '达到输出 token 上限' };
|
|
25
|
+
case 'interrupted': return { title: '任务中断', detail: '任务被中断' };
|
|
26
|
+
default: return { title: '任务完成' };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** 标题(不含前缀):completed 依据结束原因细分。 */
|
|
30
|
+
export function baseTitleOf(signal) {
|
|
31
|
+
if (signal.kind === 'interaction')
|
|
32
|
+
return interactionTitle(signal.interaction);
|
|
33
|
+
if (signal.kind === 'completed') {
|
|
34
|
+
return signal.reason === undefined ? '任务完成' : completionLabelOf(signal.reason).title;
|
|
35
|
+
}
|
|
36
|
+
return KIND_TITLES.error;
|
|
37
|
+
}
|
|
38
|
+
/** 完整标题(含可选前缀)。 */
|
|
39
|
+
export function titleOf(ctx) {
|
|
40
|
+
const base = baseTitleOf(ctx.signal);
|
|
41
|
+
const prefix = ctx.config.message.titlePrefix;
|
|
42
|
+
return prefix === undefined || prefix === '' ? base : `${prefix} ${base}`;
|
|
43
|
+
}
|
|
44
|
+
function sessionTitleLine(ctx) {
|
|
45
|
+
if (!ctx.config.message.includeSessionTitle)
|
|
46
|
+
return undefined;
|
|
47
|
+
const title = ctx.sessionTitle;
|
|
48
|
+
if (title === undefined || title === '')
|
|
49
|
+
return undefined;
|
|
50
|
+
return `会话:${title}`;
|
|
51
|
+
}
|
|
52
|
+
function turnLine(ctx) {
|
|
53
|
+
const { turn, step } = ctx.signal;
|
|
54
|
+
if (turn === undefined)
|
|
55
|
+
return undefined;
|
|
56
|
+
return step === undefined ? `turn ${turn}` : `turn ${turn} / step ${step}`;
|
|
57
|
+
}
|
|
58
|
+
/** 正文(verbosity 决定繁复度)。 */
|
|
59
|
+
export function bodyOf(ctx) {
|
|
60
|
+
const lines = [];
|
|
61
|
+
const { signal } = ctx;
|
|
62
|
+
if (ctx.verbosity === 'minimal')
|
|
63
|
+
return '';
|
|
64
|
+
// normal 与 detailed 共有的内容
|
|
65
|
+
if (signal.kind === 'interaction') {
|
|
66
|
+
if (signal.interaction === 'approval') {
|
|
67
|
+
lines.push(`等待审批:${signal.toolName ?? '未知工具'}`);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
lines.push('等待回答(提问/计划待审)');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else if (signal.kind === 'completed') {
|
|
74
|
+
if (signal.reason !== undefined) {
|
|
75
|
+
const detail = completionLabelOf(signal.reason).detail;
|
|
76
|
+
if (detail !== undefined)
|
|
77
|
+
lines.push(detail);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
lines.push(`错误:${signal.message}`);
|
|
82
|
+
}
|
|
83
|
+
const sessionLine = sessionTitleLine(ctx);
|
|
84
|
+
if (sessionLine !== undefined)
|
|
85
|
+
lines.push(sessionLine);
|
|
86
|
+
if (ctx.verbosity === 'detailed') {
|
|
87
|
+
const turn = turnLine(ctx);
|
|
88
|
+
if (turn !== undefined)
|
|
89
|
+
lines.push(turn);
|
|
90
|
+
if (signal.kind === 'interaction' && signal.reason !== undefined) {
|
|
91
|
+
lines.push(`原因:${signal.reason}`);
|
|
92
|
+
}
|
|
93
|
+
lines.push(`打开:${ctx.config.message.guiUrl}`);
|
|
94
|
+
}
|
|
95
|
+
return lines.join('\n');
|
|
96
|
+
}
|
|
97
|
+
/** 渲染完整载荷。 */
|
|
98
|
+
export function renderPayload(ctx) {
|
|
99
|
+
return {
|
|
100
|
+
kind: ctx.signal.kind,
|
|
101
|
+
sessionId: ctx.signal.sessionId,
|
|
102
|
+
title: titleOf(ctx),
|
|
103
|
+
body: bodyOf(ctx),
|
|
104
|
+
url: ctx.config.message.guiUrl,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 设置页卡片:字段清单与表单控制器(纯逻辑,可单测)。
|
|
3
|
+
*
|
|
4
|
+
* 配置为嵌套结构,而客户端 SettingsScope 的 set/unset 只支持单层路径写,
|
|
5
|
+
* 因此保存走 scope.writeOps:把每个草稿翻译为一条「嵌套路径」写操作
|
|
6
|
+
* (set/unset path: ['group', 'field']),由适配层直连 settings RPC。
|
|
7
|
+
*
|
|
8
|
+
* 为什么不用「整组合并 set」:mutate 的 set 是**整组替换**语义——
|
|
9
|
+
* 1) 服务端回显脱敏(write-only 密钥永不回显),写后校验必然误报失败;
|
|
10
|
+
* 2) 合并对象不含密钥时,已存的密钥会被静默抹掉。
|
|
11
|
+
* 逐字段路径写则只在显式填写/重置密钥时才触碰它,其余字段互不牵连。
|
|
12
|
+
*
|
|
13
|
+
* feishu.secret 为 write-only(服务端会脱敏,响应永不携带其值):
|
|
14
|
+
* - 输入框留空 = 不修改;填入并保存 = 写入;
|
|
15
|
+
* - 点「重置」= 发出 unset 清除已存密钥。
|
|
16
|
+
*/
|
|
17
|
+
/** 字段控件类型。 */
|
|
18
|
+
export type CardFieldKind = 'toggle' | 'text' | 'number' | 'select';
|
|
19
|
+
/** 门控:仅当指定组内开关字段生效值为 true 时,该字段才可编辑/可见。 */
|
|
20
|
+
export interface FieldHiddenUnless {
|
|
21
|
+
group: string;
|
|
22
|
+
field: string;
|
|
23
|
+
}
|
|
24
|
+
/** 一个可编辑字段(位于某个顶层配置组内)。 */
|
|
25
|
+
export interface CardFieldSpec {
|
|
26
|
+
/** 顶层组:config 的一级键,同时是 scope 的标量字段名。 */
|
|
27
|
+
group: string;
|
|
28
|
+
/** 组内字段名。 */
|
|
29
|
+
field: string;
|
|
30
|
+
kind: CardFieldKind;
|
|
31
|
+
label: string;
|
|
32
|
+
hint?: string;
|
|
33
|
+
/** select 的选项。 */
|
|
34
|
+
options?: readonly string[];
|
|
35
|
+
/** write-only 字段(secret):响应永不携带其值。 */
|
|
36
|
+
secret?: boolean;
|
|
37
|
+
/** 门控开关:开关关闭时该字段不可见且保存计划跳过(如第三方通道的子配置)。 */
|
|
38
|
+
hiddenUnless?: FieldHiddenUnless;
|
|
39
|
+
}
|
|
40
|
+
/** 字段渲染状态。 */
|
|
41
|
+
export interface CardFieldState {
|
|
42
|
+
/** 草稿文本 / 选中值。 */
|
|
43
|
+
text: string;
|
|
44
|
+
/** 保存后是否会产生用户层覆盖。 */
|
|
45
|
+
overridden: boolean;
|
|
46
|
+
/** 草稿非法(数字格式错误等),阻止保存。 */
|
|
47
|
+
invalid: boolean;
|
|
48
|
+
}
|
|
49
|
+
/** 卡片状态快照(槽位 hook 的载荷)。 */
|
|
50
|
+
export interface MessagerCardState {
|
|
51
|
+
/** 命名空间是否可用(ready)。 */
|
|
52
|
+
available: boolean;
|
|
53
|
+
/** 原始 scope 状态(loading/unavailable/ready),供提示区分原因。 */
|
|
54
|
+
status: string;
|
|
55
|
+
/** 连接模式(host/memory);memory = 非 loopback 访问,设置页不可用。 */
|
|
56
|
+
mode: string;
|
|
57
|
+
/** 设置文档是否可写。 */
|
|
58
|
+
writable: boolean;
|
|
59
|
+
/** 是否存在待保存的编辑。 */
|
|
60
|
+
dirty: boolean;
|
|
61
|
+
/** 是否有非法草稿。 */
|
|
62
|
+
invalid: boolean;
|
|
63
|
+
saving: boolean;
|
|
64
|
+
failed: boolean;
|
|
65
|
+
fields: Readonly<Record<string, CardFieldState>>;
|
|
66
|
+
}
|
|
67
|
+
/** 卡片动作(组件直接调用)。 */
|
|
68
|
+
export interface MessagerCardActions {
|
|
69
|
+
edit(group: string, field: string, text: string): void;
|
|
70
|
+
reset(group: string, field: string): void;
|
|
71
|
+
save(): void;
|
|
72
|
+
discard(): void;
|
|
73
|
+
}
|
|
74
|
+
/** 槽位注入面:hooks 中的 messagerCard 会变成 useMessagerCard 选择器;动作平铺为组件 props。 */
|
|
75
|
+
export interface MessagerCardFace {
|
|
76
|
+
hooks: {
|
|
77
|
+
messagerCard: {
|
|
78
|
+
getSnapshot(): MessagerCardState;
|
|
79
|
+
subscribe(listener: () => void): () => void;
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
edit(group: string, field: string, text: string): void;
|
|
83
|
+
reset(group: string, field: string): void;
|
|
84
|
+
save(): void;
|
|
85
|
+
discard(): void;
|
|
86
|
+
/** 翻译函数(键 → 当前语言文案);未接入 locale 时原样返回键。 */
|
|
87
|
+
t(key: string): string;
|
|
88
|
+
}
|
|
89
|
+
/** 一条嵌套路径写操作(与 settings.mutate 的 SettingsPathOpView 同构)。 */
|
|
90
|
+
export type ScopeWriteOp = {
|
|
91
|
+
op: 'set';
|
|
92
|
+
path: string[];
|
|
93
|
+
value: unknown;
|
|
94
|
+
} | {
|
|
95
|
+
op: 'unset';
|
|
96
|
+
path: string[];
|
|
97
|
+
};
|
|
98
|
+
/** 控制器依赖的 scope 窄接口(便于测试替身)。 */
|
|
99
|
+
export interface ScopeLike {
|
|
100
|
+
getSnapshot(): {
|
|
101
|
+
status: string;
|
|
102
|
+
value: unknown;
|
|
103
|
+
user: unknown;
|
|
104
|
+
base: unknown;
|
|
105
|
+
writable: boolean;
|
|
106
|
+
mode?: string;
|
|
107
|
+
/** 命名空间修订号(直连 api 写时作为 expectedRevision 回传)。 */
|
|
108
|
+
revision?: number;
|
|
109
|
+
};
|
|
110
|
+
subscribe(listener: () => void): () => void;
|
|
111
|
+
set(field: string, value: unknown): Promise<void>;
|
|
112
|
+
unset(field: string): Promise<void>;
|
|
113
|
+
/** 一次批量嵌套路径写;返回是否落库成功。memory 模式下应静默成功(与 scope 一致)。 */
|
|
114
|
+
writeOps(ops: readonly ScopeWriteOp[]): Promise<boolean>;
|
|
115
|
+
}
|
|
116
|
+
/** 字段键:`group.field`。 */
|
|
117
|
+
export declare function fieldKey(group: string, field: string): string;
|
|
118
|
+
/**
|
|
119
|
+
* 渲染层门控判断(与控制器 gatedOff 语义一致):
|
|
120
|
+
* hiddenUnless 指定的开关字段当前(含草稿)不为 true 时,该字段不渲染。
|
|
121
|
+
*/
|
|
122
|
+
export declare function isFieldGated(spec: CardFieldSpec, fields: Readonly<Record<string, CardFieldState>>): boolean;
|
|
123
|
+
export declare class MessagerCardController {
|
|
124
|
+
private readonly scope;
|
|
125
|
+
private readonly fields;
|
|
126
|
+
private readonly staged;
|
|
127
|
+
private readonly listeners;
|
|
128
|
+
private saving;
|
|
129
|
+
private failed;
|
|
130
|
+
private cache;
|
|
131
|
+
constructor(scope: ScopeLike, fields: readonly CardFieldSpec[]);
|
|
132
|
+
/** 槽位注入面。 */
|
|
133
|
+
inject(): MessagerCardFace;
|
|
134
|
+
/**
|
|
135
|
+
* 读取缓存的快照。
|
|
136
|
+
* 注意:useSyncExternalStore 要求 getSnapshot 在状态未变化时返回**同一引用**,
|
|
137
|
+
* 否则 React 会以 #185(最大更新深度)崩溃 —— 因此快照按变更点惰性计算并缓存,
|
|
138
|
+
* 只有 invalidate() 之后才重建。
|
|
139
|
+
*/
|
|
140
|
+
getSnapshot(): MessagerCardState;
|
|
141
|
+
private compute;
|
|
142
|
+
private effectiveValue;
|
|
143
|
+
private groupValue;
|
|
144
|
+
private baseValue;
|
|
145
|
+
private userHas;
|
|
146
|
+
private stage;
|
|
147
|
+
private spec;
|
|
148
|
+
/**
|
|
149
|
+
* 计算保存计划:把每个有效草稿翻译为一条嵌套路径写操作。
|
|
150
|
+
* 逐字段而非整组合并:密钥字段只有被显式填写/重置时才生成 op,
|
|
151
|
+
* 其余字段互不牵连(mutate 的 set 是整组替换,合并写会抹掉未回显的密钥)。
|
|
152
|
+
*/
|
|
153
|
+
private plan;
|
|
154
|
+
/**
|
|
155
|
+
* 门控判断:hiddenUnless 指定的开关字段当前(含草稿覆盖)不为 true 时,
|
|
156
|
+
* 该字段不可见、草稿不参与保存。
|
|
157
|
+
*/
|
|
158
|
+
gatedOff(spec: CardFieldSpec): boolean;
|
|
159
|
+
private save;
|
|
160
|
+
/** 失效缓存并通知订阅者(getSnapshot 下一次调用时重建)。 */
|
|
161
|
+
private invalidate;
|
|
162
|
+
}
|
|
163
|
+
/** 深比较 JSON 形状数据(组对象比较)。 */
|
|
164
|
+
export declare function deepEqualJson(a: unknown, b: unknown): boolean;
|
|
165
|
+
/**
|
|
166
|
+
* 设置分区展示的字段清单。
|
|
167
|
+
* label/hint 为**翻译键**(见 src/client/locales.ts),渲染层经 t() 取当前语言;
|
|
168
|
+
* 键名与字典一致,缺键时 t() 原样返回键名(fail loud)。
|
|
169
|
+
*/
|
|
170
|
+
export declare const CARD_FIELDS: readonly CardFieldSpec[];
|
|
171
|
+
//# sourceMappingURL=card-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card-controller.d.ts","sourceRoot":"","sources":["../../../src/client/card-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 客户端配置读取:经 host 配置路由(GET /dsh-messager/config)拉取 messager
|
|
3
|
+
* 命名空间有效值,并通过 `settings/document-updated` 失效后重拉。
|
|
4
|
+
* 路由不受 Web 设置白名单门控,发行版同样可用;拉取失败回退 schema 默认值。
|
|
5
|
+
*/
|
|
6
|
+
import { type Config } from '../config.js';
|
|
7
|
+
export interface ClientConfigHandle {
|
|
8
|
+
get(): Config;
|
|
9
|
+
subscribe(listener: () => void): () => void;
|
|
10
|
+
refresh(): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare class ClientConfig implements ClientConfigHandle {
|
|
13
|
+
private current;
|
|
14
|
+
private readonly listeners;
|
|
15
|
+
get(): Config;
|
|
16
|
+
subscribe(listener: () => void): () => void;
|
|
17
|
+
/** 拉取 host 配置视图(首次与收到 document-updated 后调用)。 */
|
|
18
|
+
refresh(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/client/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAA;AAGzD,MAAM,WAAW,kBAAkB;IACjC,GAAG,IAAI,MAAM,CAAA;IACb,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAA;IAC3C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAED,qBAAa,YAAa,YAAW,kBAAkB;IACrD,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAElD,GAAG,IAAI,MAAM;IAIb,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAO3C,gDAAgD;IAC1C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAY/B"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 客户端会话摘要 diff(纯函数,可单测):
|
|
3
|
+
* 对比两次会话列表快照,产出需要浏览器通知的变化。
|
|
4
|
+
* 语义与 Web UI 状态圆点完全一致:
|
|
5
|
+
* - pendingInteraction 从无到有 → 需要交互(橙点)
|
|
6
|
+
* - running true→false 且会话非当前选中 → 任务完成(绿点)
|
|
7
|
+
*/
|
|
8
|
+
import type { SessionId, SessionSummary } from '@deepseek-ai/dsh-client-runtime/client';
|
|
9
|
+
export type ClientNoticeKind = 'interaction' | 'completed';
|
|
10
|
+
export interface ClientNotice {
|
|
11
|
+
kind: ClientNoticeKind;
|
|
12
|
+
sessionId: SessionId;
|
|
13
|
+
/** interaction 细分(与 PendingInteractionStatus 一致)。 */
|
|
14
|
+
interaction?: 'approval' | 'plan-review' | 'question';
|
|
15
|
+
/** 会话显示标题(displayTitle)。 */
|
|
16
|
+
title?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 对比两次列表快照。
|
|
20
|
+
* 首次出现的会话只建立基线、不通知;被移除的会话不通知。
|
|
21
|
+
* @param previous - 上一次快照的 byId。
|
|
22
|
+
* @param next - 本次快照的 byId。
|
|
23
|
+
* @param current - 本次快照的当前选中会话(选中会话的完成不打扰)。
|
|
24
|
+
*/
|
|
25
|
+
export declare function diffSessionSummaries(previous: Readonly<Record<SessionId, SessionSummary>>, next: Readonly<Record<SessionId, SessionSummary>>, current: SessionId | undefined): ClientNotice[];
|
|
26
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/client/diff.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAA;AAEvF,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,WAAW,CAAA;AAE1D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,qDAAqD;IACrD,WAAW,CAAC,EAAE,UAAU,GAAG,aAAa,GAAG,UAAU,CAAA;IACrD,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,EACrD,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,EACjD,OAAO,EAAE,SAAS,GAAG,SAAS,GAC7B,YAAY,EAAE,CAoBhB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fetch 版 ScopeLike:浏览器经 /dsh-messager/config 路由读写配置。
|
|
3
|
+
* 替代 settingsScope(受 Web 设置白名单门控)—— 本通道不受门控,发行版可用。
|
|
4
|
+
*
|
|
5
|
+
* - getSnapshot:缓存视图(初始 loading;无变化时返回同一引用,满足
|
|
6
|
+
* useSyncExternalStore 契约);
|
|
7
|
+
* - subscribe:document-updated 事件或显式 refresh 时重新 GET 并通知;
|
|
8
|
+
* - writeOps:POST 逐字段 ops,成功后重新 GET。
|
|
9
|
+
*
|
|
10
|
+
* fetcher 可注入,便于单测。
|
|
11
|
+
*/
|
|
12
|
+
import type { ConfigView, ConfigWriteBody } from '../config-shared.js';
|
|
13
|
+
import type { ScopeLike } from './card-controller.js';
|
|
14
|
+
/** 路由访问器(浏览器 fetch 实现见 client/index.ts;测试注入替身)。 */
|
|
15
|
+
export interface ConfigFetcher {
|
|
16
|
+
get(): Promise<ConfigView>;
|
|
17
|
+
write(body: ConfigWriteBody): Promise<{
|
|
18
|
+
ok: boolean;
|
|
19
|
+
error?: string;
|
|
20
|
+
}>;
|
|
21
|
+
}
|
|
22
|
+
export interface FetchScope {
|
|
23
|
+
scope: ScopeLike;
|
|
24
|
+
/** 重新拉取配置视图(document-updated 或手动触发)。 */
|
|
25
|
+
refresh(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
/** 创建 fetch 版 scope。 */
|
|
28
|
+
export declare function createFetchScope(fetcher: ConfigFetcher): FetchScope;
|
|
29
|
+
//# sourceMappingURL=fetch-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-scope.d.ts","sourceRoot":"","sources":["../../../src/client/fetch-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAgB,MAAM,sBAAsB,CAAA;AAEnE,mDAAmD;AACnD,MAAM,WAAW,aAAa;IAC5B,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC,CAAA;IAC1B,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACvE;AAaD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,SAAS,CAAA;IAChB,wCAAwC;IACxC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAED,wBAAwB;AACxB,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,UAAU,CA0DnE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-messager —— DeepSeek Harness 通知插件(浏览器 client 端)。
|
|
3
|
+
*
|
|
4
|
+
* 功能:
|
|
5
|
+
* 1. 浏览器通知:基于客户端会话摘要(ctx.sessions.list)投递,语义与 Web UI
|
|
6
|
+
* 状态圆点一致(橙点=需要交互、绿点=任务完成)。
|
|
7
|
+
* 2. 设置页分区「通知&信使」:注册到 settings.section(Agent预设下方,动态
|
|
8
|
+
* order),经 host 配置路由(/dsh-messager/config,webServer 通道)读写
|
|
9
|
+
* `messager` 命名空间 —— 不受 Web 设置白名单门控,发行版同样可用。
|
|
10
|
+
*
|
|
11
|
+
* 行为要点:
|
|
12
|
+
* - 配置与 host 端同源(settings 命名空间 `messager`,document-updated 失效重拉);
|
|
13
|
+
* - `onlyWhenHidden`(默认 true):页面可见时不弹,避免看着界面还被打扰;
|
|
14
|
+
* - tag 去重 + localStorage 跨标签页冷却,多开标签不重复弹;
|
|
15
|
+
* - 点击通知聚焦窗口;权限未授予时在插件加载时请求一次。
|
|
16
|
+
*/
|
|
17
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
18
|
+
export declare const name = "dsh-messager";
|
|
19
|
+
/** locale 字典命名空间(与 section 的 locale 声明一致)。 */
|
|
20
|
+
export declare const LOCALE_NS = "dsh-messager";
|
|
21
|
+
/** 依赖的客户端服务:会话列表、远程事件(document-updated)、槽位、locale。 */
|
|
22
|
+
export declare const inject: string[];
|
|
23
|
+
export declare function apply(ctx: Context): void;
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAgBlD,eAAO,MAAM,IAAI,iBAAiB,CAAA;AAElC,8CAA8C;AAC9C,eAAO,MAAM,SAAS,iBAAiB,CAAA;AAEvC,sDAAsD;AACtD,eAAO,MAAM,MAAM,UAA4C,CAAA;AA4F/D,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAiFxC"}
|