@morlay/dsh-session-mode 0.0.1-alpha.4 → 0.0.1-alpha.5

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/src/rows.ts ADDED
@@ -0,0 +1,57 @@
1
+ /**
2
+ * 本包作为能力包发布的**装配数据**:`session-mode` 行的 config(各模式的会话级扩展)由这里渲染,
3
+ * 装配入口在 `packages/bundles/session-mode-profile`(它同时装注入通道、工具说明与 subagent 那几行)。
4
+ */
5
+
6
+ import { DEFAULT_MODE, MODE_SOURCES, type ModeSource } from "./mode-sources.ts";
7
+
8
+ // 装配入口要拿这个 id 声明 preset 行(`preset-<id>` 的行 id 与 `config.id` 都用它):与模式里的 `preset`
9
+ // 是同一个事实,所以只有一份。
10
+ export { MODE_PRESET_ID } from "./mode-sources.ts";
11
+
12
+ /** 一行装配条目:与 `cordis.patch.yml` 的顶层结构同形。 */
13
+ export interface PatchRow {
14
+ readonly insert?: readonly RowEntry[];
15
+ }
16
+
17
+ /** `insert` 里的一个条目。 */
18
+ export interface RowEntry {
19
+ readonly id: string;
20
+ readonly name: string;
21
+ readonly config?: Readonly<Record<string, unknown>>;
22
+ }
23
+
24
+ /** 一个模式的源定义 → 行 config(schema 的输入形状:可省的字段就省)。 */
25
+ function modeConfig(source: ModeSource): Record<string, unknown> {
26
+ return {
27
+ preset: source.preset,
28
+ name: source.name,
29
+ description: source.description,
30
+ ...(source.role === undefined ? {} : { role: [...source.role] }),
31
+ ...(source.persona === undefined ? {} : { persona: { ...source.persona } }),
32
+ allowTools: [...source.allowTools],
33
+ ...(source.instructions === undefined ? {} : { instructions: source.instructions }),
34
+ ...(source.runtimeContext === undefined ? {} : { runtimeContext: source.runtimeContext }),
35
+ ...(source.defaultModel === undefined ? {} : { defaultModel: { ...source.defaultModel } }),
36
+ };
37
+ }
38
+
39
+ /** `session-mode` 行的装配:默认模式与各模式的扩展定义。 */
40
+ export function sessionModeRows(): readonly PatchRow[] {
41
+ return [
42
+ {
43
+ insert: [
44
+ {
45
+ id: "session-mode",
46
+ name: "@morlay/dsh-session-mode",
47
+ config: {
48
+ default: DEFAULT_MODE,
49
+ modes: Object.fromEntries(
50
+ MODE_SOURCES.map((source) => [source.id, modeConfig(source)]),
51
+ ),
52
+ },
53
+ },
54
+ ],
55
+ },
56
+ ];
57
+ }
package/cordis.patch.yml DELETED
@@ -1,69 +0,0 @@
1
- # 本文件由 packages/profile/dsh-session-mode/tool/patch.ts 生成,请勿手工编辑
2
- - insert:
3
- - id: session-mode
4
- name: "@morlay/dsh-session-mode"
5
- config:
6
- default: coding
7
- modes:
8
- coding:
9
- name: 编码模式
10
- description: 功能完整的编码 Agent:文件、Shell、检索、联网等工具常驻,其余用法说明按需加载。
11
- role:
12
- - main
13
- - subagent
14
- persona:
15
- prefix: |-
16
- 你是一个经验丰富的编程专家,YAGNI 是你的编程哲学,PDCA 是你的行为规范。
17
- 全程用中文(专有名词除外),包括但不限于思考,回答,工具描述,subagent 提示词;思考不要陷入重复循环,一旦循环立即退出;思考聚焦需求理解与方案设计,不预演具体代码实现,正确性由验证环节确认。
18
- suffix: 你的工作目录在 `{{cwd}}`
19
- allowTools:
20
- - ask_user_question
21
- - subagent
22
- - subagent_fork
23
- - list_subagent_models
24
- - workflow
25
- - todo_write
26
- - exit_plan_mode
27
- - get_goal
28
- - create_goal
29
- - update_goal
30
- - present
31
- - read
32
- - write
33
- - edit
34
- - glob
35
- - grep
36
- - read_image
37
- - bash
38
- - pwsh
39
- - job_output
40
- - job_list
41
- - job_kill
42
- - skill
43
- - spawn_teammate
44
- - send_message
45
- - list_agents
46
- - wait_agent
47
- - interrupt_agent
48
- - team_task_create
49
- - team_task_list
50
- - team_task_get
51
- - team_task_update
52
- - web_fetch
53
- - web_search
54
- chat:
55
- name: 对话模式
56
- description: 只做对话:提问与联网(搜索、抓取)三件工具,不注入系统提示词、工作区指令与技能目录。
57
- role:
58
- - main
59
- persona:
60
- prefix: 你是一个助手。全程用中文(专有名词除外),包括但不限于思考,回答,工具描述;思考不要陷入重复循环,一旦循环立即退出。
61
- allowTools:
62
- - ask_user_question
63
- - web_search
64
- - web_fetch
65
- instructions: false
66
- runtimeContext: false
67
- models: {}
68
- - id: context-assembler-scope
69
- name: "@morlay/dsh-context-assembler/scope"
@@ -1,106 +0,0 @@
1
- import { Volatile } from "@deepseek-ai/cordis";
2
- import z from "@deepseek-ai/schemastery";
3
- //#region src/modes.d.ts
4
- /** 一个模式的提示词:两段文本,注册成 agent 作用域的 `deployment:persona-prefix` / `-suffix` section。 */
5
- interface SessionModePersona {
6
- /** 系统提示词最前的一段;空串表示不遮蔽部署级那层。 */
7
- readonly prefix: string;
8
- /** 系统提示词最后的一段;空串表示不写。 */
9
- readonly suffix: string;
10
- }
11
- /**
12
- * 一个模式对谁可见:`main` 进用户选择器(会话级选择),`subagent` 表示它**可以**作为子代理的 mode。
13
- * 两个角色可以同时声明;不写默认 `["main"]`——没写角色的模式不该悄悄变成子代理候选。
14
- *
15
- * `subagent` 目前只是候选集的声明:子代理默认继承父 mode(不看角色),"按角色指派 mode" 还没做。
16
- */
17
- type SessionModeRole = "main" | "subagent";
18
- /** 一个模式的默认模型;省略的字段跟着 provider 默认走(与全局 `agent-default-model` 同形状)。 */
19
- interface SessionModeModel {
20
- readonly provider: string;
21
- readonly model: string;
22
- readonly reasoningEffort?: string;
23
- }
24
- /** 各模式的默认模型:模式 id → 模型;键必须在 `modes` 里(装配期校验)。 */
25
- type SessionModeModels = Readonly<Record<string, SessionModeModel>>;
26
- /**
27
- * 一个模式:提示词 + 能力开关。
28
- *
29
- * 这份形状是 **schema 归一化之后**的:每个字段都有值(写配置时可以不写,schema 用默认补上——`description`
30
- * 补空串、`persona` 补两段空文本、两个布尔开关补 `true`)。配置里能省略哪些字段看 `modeSchema` 的 default,
31
- * 不看这里。
32
- */
33
- interface SessionMode {
34
- /** 选择器里的展示名。 */
35
- readonly name: string;
36
- /** 一句话说明这个模式干什么;空串表示没写。 */
37
- readonly description: string;
38
- /** 这个模式归谁用:`main`(用户选择器)/ `subagent`(可作子代理 mode)。至少一个。 */
39
- readonly role: SessionModeRole[];
40
- /** 该模式的提示词。 */
41
- readonly persona: SessionModePersona;
42
- /**
43
- * 这个模式能用哪些工具;其余工具既不进模型目录、调用也被执行层拒绝,它们自己的说明 section
44
- * (`tool:<工具名>`)也不留在提示词里。**至少给一个**——想要"全都要"就列出全部,别留空。
45
- */
46
- readonly allowTools: string[];
47
- /**
48
- * 是否要 instruction 类注入(工作区指令、技能目录、用法正文)。缺省要;`false` 表示这个模式一条都不要
49
- * ——对话模式就是它。开关由 `@morlay/dsh-context-assembler/scope` 落到通道上。
50
- */
51
- readonly instructions: boolean;
52
- /**
53
- * 是否要 runtime context(文件沙箱策略、审批策略那两条动态快照)。缺省要;`false` 表示这个模式不要它们
54
- * ——对话模式没有文件与 shell 工具,"能改工作区哪些文件、要不要走审批"对它全是噪音。
55
- */
56
- readonly runtimeContext: boolean;
57
- }
58
- /** 本包 config 的**源码形状**:装配层与设置页写的那个形状(`models` 是普通对象,可以整块省略)。 */
59
- interface Config {
60
- /** 新会话(还没选过模式的会话)用哪个模式。必须是 `modes` 里的一个 id。 */
61
- readonly default: string;
62
- /** 模式清单:id → 定义。顺序即选择器里的顺序(`Object.entries` 的插入序)。 */
63
- readonly modes: Record<string, SessionMode>;
64
- /**
65
- * 各模式的默认模型:模式 id → 模型。省略的模式跟着全局 `agent-default-model` 走。
66
- *
67
- * 它是 config 的**顶层 volatile 字段**:设置面(`ctx.configForms` → 我们那张卡片)编辑的就是它。挪进
68
- * `modes.<id>` 会让设置面看不见它——`schemastery` 的 `validateVolatileSchema` 把 dict 内部一律当成
69
- * blocked,而 settings 只挑得出固定路径上的 volatile 字段。
70
- */
71
- readonly models?: SessionModeModels;
72
- }
73
- /** schema 解析之后的形状:volatile 字段被换成**稳定引用**,读它要过 `.get()`(设置页改的就是同一份)。 */
74
- interface ResolvedConfig {
75
- readonly default: string;
76
- readonly modes: Record<string, SessionMode>;
77
- /** 各模式的默认模型;一个都没配时是空对象(schema 的 default)。 */
78
- readonly models: Volatile<SessionModeModels>;
79
- }
80
- declare const Config: z<Config, ResolvedConfig>;
81
- //#endregion
82
- //#region src/shared.d.ts
83
- /**
84
- * host 半与 client 半共用的接口面:一条 HTTP 路径、模式行的对外形状、请求与响应体。
85
- *
86
- * 为什么不是 Typert Remote:客户端的 remote 清单(`@deepseek-ai/dsh-api-remotes/client`)由上游硬编码,
87
- * 我们的服务不在里面,`ctx.remote.sessionModes` 解析不到。仓库既有的跨半通路是 HTTP 路由
88
- * (见 `@morlay/ui-conversation-message-actions` 的 `/session-editor`),这里沿用同一种。
89
- *
90
- * 会话当前模式不走这条通路:它是一条 session 投影(`sessionMode`),随会话列表一起到页面。
91
- */
92
- /** 模式清单与切换的路由路径:宿主(web 与桌面)在同一张路由表上服务它。 */
93
- declare const SESSION_MODE_PATH = "/session-mode";
94
- /** 一个模式对外的那部分:选择器要的名字与说明。 */
95
- interface SessionModeRow {
96
- readonly id: string;
97
- readonly name: string;
98
- readonly description?: string;
99
- }
100
- /** `GET` 的响应体:清单与默认模式。 */
101
- interface SessionModeRoster {
102
- readonly default: string;
103
- readonly modes: readonly SessionModeRow[];
104
- }
105
- //#endregion
106
- export { ResolvedConfig as a, SessionModeModels as c, Config as i, SessionModePersona as l, SessionModeRoster as n, SessionMode as o, SessionModeRow as r, SessionModeModel as s, SESSION_MODE_PATH as t, SessionModeRole as u };
@@ -1,106 +0,0 @@
1
- import { Volatile } from "@deepseek-ai/cordis";
2
- import z from "@deepseek-ai/schemastery";
3
- //#region src/modes.d.ts
4
- /** 一个模式的提示词:两段文本,注册成 agent 作用域的 `deployment:persona-prefix` / `-suffix` section。 */
5
- interface SessionModePersona {
6
- /** 系统提示词最前的一段;空串表示不遮蔽部署级那层。 */
7
- readonly prefix: string;
8
- /** 系统提示词最后的一段;空串表示不写。 */
9
- readonly suffix: string;
10
- }
11
- /**
12
- * 一个模式对谁可见:`main` 进用户选择器(会话级选择),`subagent` 表示它**可以**作为子代理的 mode。
13
- * 两个角色可以同时声明;不写默认 `["main"]`——没写角色的模式不该悄悄变成子代理候选。
14
- *
15
- * `subagent` 目前只是候选集的声明:子代理默认继承父 mode(不看角色),"按角色指派 mode" 还没做。
16
- */
17
- type SessionModeRole = "main" | "subagent";
18
- /** 一个模式的默认模型;省略的字段跟着 provider 默认走(与全局 `agent-default-model` 同形状)。 */
19
- interface SessionModeModel {
20
- readonly provider: string;
21
- readonly model: string;
22
- readonly reasoningEffort?: string;
23
- }
24
- /** 各模式的默认模型:模式 id → 模型;键必须在 `modes` 里(装配期校验)。 */
25
- type SessionModeModels = Readonly<Record<string, SessionModeModel>>;
26
- /**
27
- * 一个模式:提示词 + 能力开关。
28
- *
29
- * 这份形状是 **schema 归一化之后**的:每个字段都有值(写配置时可以不写,schema 用默认补上——`description`
30
- * 补空串、`persona` 补两段空文本、两个布尔开关补 `true`)。配置里能省略哪些字段看 `modeSchema` 的 default,
31
- * 不看这里。
32
- */
33
- interface SessionMode {
34
- /** 选择器里的展示名。 */
35
- readonly name: string;
36
- /** 一句话说明这个模式干什么;空串表示没写。 */
37
- readonly description: string;
38
- /** 这个模式归谁用:`main`(用户选择器)/ `subagent`(可作子代理 mode)。至少一个。 */
39
- readonly role: SessionModeRole[];
40
- /** 该模式的提示词。 */
41
- readonly persona: SessionModePersona;
42
- /**
43
- * 这个模式能用哪些工具;其余工具既不进模型目录、调用也被执行层拒绝,它们自己的说明 section
44
- * (`tool:<工具名>`)也不留在提示词里。**至少给一个**——想要"全都要"就列出全部,别留空。
45
- */
46
- readonly allowTools: string[];
47
- /**
48
- * 是否要 instruction 类注入(工作区指令、技能目录、用法正文)。缺省要;`false` 表示这个模式一条都不要
49
- * ——对话模式就是它。开关由 `@morlay/dsh-context-assembler/scope` 落到通道上。
50
- */
51
- readonly instructions: boolean;
52
- /**
53
- * 是否要 runtime context(文件沙箱策略、审批策略那两条动态快照)。缺省要;`false` 表示这个模式不要它们
54
- * ——对话模式没有文件与 shell 工具,"能改工作区哪些文件、要不要走审批"对它全是噪音。
55
- */
56
- readonly runtimeContext: boolean;
57
- }
58
- /** 本包 config 的**源码形状**:装配层与设置页写的那个形状(`models` 是普通对象,可以整块省略)。 */
59
- interface Config {
60
- /** 新会话(还没选过模式的会话)用哪个模式。必须是 `modes` 里的一个 id。 */
61
- readonly default: string;
62
- /** 模式清单:id → 定义。顺序即选择器里的顺序(`Object.entries` 的插入序)。 */
63
- readonly modes: Record<string, SessionMode>;
64
- /**
65
- * 各模式的默认模型:模式 id → 模型。省略的模式跟着全局 `agent-default-model` 走。
66
- *
67
- * 它是 config 的**顶层 volatile 字段**:设置面(`ctx.configForms` → 我们那张卡片)编辑的就是它。挪进
68
- * `modes.<id>` 会让设置面看不见它——`schemastery` 的 `validateVolatileSchema` 把 dict 内部一律当成
69
- * blocked,而 settings 只挑得出固定路径上的 volatile 字段。
70
- */
71
- readonly models?: SessionModeModels;
72
- }
73
- /** schema 解析之后的形状:volatile 字段被换成**稳定引用**,读它要过 `.get()`(设置页改的就是同一份)。 */
74
- interface ResolvedConfig {
75
- readonly default: string;
76
- readonly modes: Record<string, SessionMode>;
77
- /** 各模式的默认模型;一个都没配时是空对象(schema 的 default)。 */
78
- readonly models: Volatile<SessionModeModels>;
79
- }
80
- declare const Config: z<Config, ResolvedConfig>;
81
- //#endregion
82
- //#region src/shared.d.ts
83
- /**
84
- * host 半与 client 半共用的接口面:一条 HTTP 路径、模式行的对外形状、请求与响应体。
85
- *
86
- * 为什么不是 Typert Remote:客户端的 remote 清单(`@deepseek-ai/dsh-api-remotes/client`)由上游硬编码,
87
- * 我们的服务不在里面,`ctx.remote.sessionModes` 解析不到。仓库既有的跨半通路是 HTTP 路由
88
- * (见 `@morlay/ui-conversation-message-actions` 的 `/session-editor`),这里沿用同一种。
89
- *
90
- * 会话当前模式不走这条通路:它是一条 session 投影(`sessionMode`),随会话列表一起到页面。
91
- */
92
- /** 模式清单与切换的路由路径:宿主(web 与桌面)在同一张路由表上服务它。 */
93
- declare const SESSION_MODE_PATH = "/session-mode";
94
- /** 一个模式对外的那部分:选择器要的名字与说明。 */
95
- interface SessionModeRow {
96
- readonly id: string;
97
- readonly name: string;
98
- readonly description?: string;
99
- }
100
- /** `GET` 的响应体:清单与默认模式。 */
101
- interface SessionModeRoster {
102
- readonly default: string;
103
- readonly modes: readonly SessionModeRow[];
104
- }
105
- //#endregion
106
- export { ResolvedConfig as a, SessionModeModels as c, Config as i, SessionModePersona as l, SessionModeRoster as n, SessionMode as o, SessionModeRow as r, SessionModeModel as s, SESSION_MODE_PATH as t, SessionModeRole as u };
@@ -1,134 +0,0 @@
1
- /**
2
- * 卡片样式:只管布局与那几个控件,颜色 / 圆角 / 焦点环跟共享原语(`SettingsForm` / `SettingsValueField`)
3
- * 同源——用官方的 `--dsw-*` token(`dsw` 助手给出变量名,写错名字是类型错误),这样它跟别的插件卡片长得一样。
4
- */
5
-
6
- import type { CSSProps } from "@morlay/dsh-client-ui-primitives/client";
7
- import { dsw } from "@morlay/dsh-client-ui-primitives/client";
8
-
9
- export const styles = {
10
- section: {
11
- display: "flex",
12
- flexDirection: "column",
13
- gap: "12px",
14
- },
15
- heading: {
16
- margin: "0",
17
- fontSize: "14px",
18
- lineHeight: "20px",
19
- fontWeight: "600",
20
- color: dsw.alias.label.primary,
21
- },
22
- hint: {
23
- margin: "0",
24
- fontSize: "12px",
25
- lineHeight: "1.5",
26
- color: dsw.alias.label.tertiary,
27
- },
28
- // 两条提示都不是错:读不到目录只影响"能不能改",当前值与恢复默认仍然可用。
29
- notice: {
30
- margin: "0",
31
- fontSize: "12px",
32
- lineHeight: "1.5",
33
- color: dsw.alias.state.warn.label,
34
- },
35
- rows: {
36
- display: "flex",
37
- flexDirection: "column",
38
- gap: "12px",
39
- },
40
- // 一个模式一行:窄到放不下时那几个选择器各自占一行。
41
- row: {
42
- display: "flex",
43
- flexDirection: "column",
44
- gap: "8px",
45
- padding: "10px 12px",
46
- border: `0.5px solid ${String(dsw.alias.border.l2)}`,
47
- borderRadius: "8px",
48
- },
49
- rowHead: {
50
- display: "flex",
51
- alignItems: "center",
52
- gap: "8px",
53
- },
54
- rowName: {
55
- fontSize: "13px",
56
- lineHeight: "1.5",
57
- fontWeight: "500",
58
- color: dsw.alias.label.primary,
59
- },
60
- badge: {
61
- display: "inline-flex",
62
- alignItems: "center",
63
- borderRadius: "999px",
64
- padding: "1px 8px",
65
- fontSize: "11px",
66
- lineHeight: "17px",
67
- background: dsw.alias.bg.module.platform,
68
- color: dsw.alias.label.secondary,
69
- },
70
- // "恢复默认"推到最后:它属于整行,不属于某个选择器。
71
- reset: {
72
- marginLeft: "auto",
73
- border: "none",
74
- background: "none",
75
- padding: 0,
76
- font: "inherit",
77
- fontSize: "12px",
78
- lineHeight: "1.5",
79
- color: dsw.alias.label.secondary,
80
- cursor: "pointer",
81
- "&:hover:not(:disabled)": {
82
- color: dsw.alias.label.primary,
83
- },
84
- "&:disabled": {
85
- cursor: "default",
86
- },
87
- },
88
- rowHint: {
89
- margin: "0",
90
- fontSize: "12px",
91
- lineHeight: "1.5",
92
- color: dsw.alias.label.tertiary,
93
- },
94
- fields: {
95
- display: "grid",
96
- gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))",
97
- gap: "12px",
98
- },
99
- field: {
100
- display: "flex",
101
- flexDirection: "column",
102
- gap: "4px",
103
- minWidth: 0,
104
- },
105
- fieldLabel: {
106
- fontSize: "12px",
107
- lineHeight: "1.5",
108
- color: dsw.alias.label.secondary,
109
- },
110
- select: {
111
- height: "30px",
112
- padding: "0 8px",
113
- border: `0.5px solid ${String(dsw.alias.border.l4)}`,
114
- borderRadius: "8px",
115
- background: dsw.alias.bg.layer["3"],
116
- font: "inherit",
117
- fontSize: "13px",
118
- lineHeight: "1.5",
119
- color: dsw.alias.label.primary,
120
- "&:focus-visible": {
121
- outline: "none",
122
- borderColor: dsw.alias.brand.primary,
123
- },
124
- "&:disabled": {
125
- color: dsw.alias.label.tertiary,
126
- cursor: "default",
127
- },
128
- },
129
- invalid: {
130
- fontSize: "12px",
131
- lineHeight: "1.5",
132
- color: dsw.alias.state.error.primary,
133
- },
134
- } satisfies Record<string, CSSProps>;