@mzzsfy/dsh-rs-workflow 1.0.2 → 1.1.0

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.
@@ -1,161 +1,172 @@
1
- // template-tool — rs_workflow_template 模型工具:AI 按用户口述逻辑生成/修改流程模板
2
- // 激活于已创建组合行(template-tool 行);落盘走自有文件存储与 release 模块,不直接触碰预设目录(v5)
3
- import { defineTool } from '@deepseek-ai/dsh-tools'
4
- import { parseTemplate, validateTemplate, validateTemplateSet } from './template.mjs'
5
- import { SPEC_TEXT } from './spec.mjs'
6
- import { loadJson, saveJson } from './storage.mjs'
7
- import { releaseFlowTemplate, unreleaseFlowTemplate } from './release.mjs'
8
-
9
- const ACTIONS = ['spec', 'list', 'save', 'remove']
10
-
11
- function normalizeTemplates(value) {
12
- if (!Array.isArray(value)) return []
13
- return value
14
- .filter((t) => t && typeof t === 'object')
15
- .map((t) => ({
16
- id: typeof t.id === 'string' ? t.id : '',
17
- label: typeof t.label === 'string' ? t.label : '',
18
- description: typeof t.description === 'string' ? t.description : '',
19
- enabled: t.enabled !== false,
20
- json: typeof t.json === 'string' ? t.json : '',
21
- }))
22
- .filter((t) => t.id !== '')
23
- }
24
-
25
- export function createTemplateTool({ getTemplates, setTemplates, removeTemplate, releaseTemplate, unreleaseTemplate, logger }) {
26
- return defineTool({
27
- name: 'rs_workflow_template',
28
- description: [
29
- '若水工作流流程模板的 AI 编辑入口:用户口述流程逻辑,你据此生成/修改流程模板(严格 JSON)。',
30
- '先调 {action:"spec"} 获取 DSL v5 规范与示例,再 {action:"save", template:{...}, release:true} 保存并创建为可选模式。',
31
- 'list 列出现有模板;remove 按 id 移除并撤下其模式。',
32
- '每步以 outputs 声明结构化产出契约(子代理以结构化工具提交,引擎强制校验);人工审校用 type:"approve" 原语;',
33
- '流程入参用 inputs;禁止把「希望模型怎么做」写成口头约定。',
34
- ].join(''),
35
- parameters: {
36
- action: { type: 'string', required: true, enum: ACTIONS, description: 'spec=获取 DSL 规范;list=列模板;save=保存模板(可同时创建);remove=移除模板' },
37
- template: {
38
- type: 'object',
39
- additionalProperties: true,
40
- description: 'save:模板对象 {id,label,description,enabled,json};json 为流程定义严格 JSON 文本(先调 spec 按规范写)',
41
- },
42
- id: { type: 'string', description: 'remove:要移除的模板 id' },
43
- release: { type: 'boolean', description: 'save:true=保存后立即创建为可选模式(rs-<id>)' },
44
- dryRun: { type: 'boolean', description: 'save:true=仅校验不落盘(编辑器「校验」同源通道)' },
45
- },
46
- output: {
47
- schema: {
48
- type: 'object',
49
- additionalProperties: false,
50
- properties: {
51
- ok: { type: 'boolean', required: true },
52
- action: { type: 'string' },
53
- spec: { type: 'string' },
54
- templates: { type: 'array', items: { type: 'object', additionalProperties: true } },
55
- released: { type: 'boolean' },
56
- presetId: { type: 'string' },
57
- errors: { type: 'array', items: { type: 'string' } },
58
- error: { type: 'string' },
59
- },
60
- },
61
- render: (_args, value) => [{
62
- type: 'text',
63
- text: value.spec !== undefined ? value.spec : JSON.stringify(value, null, 2),
64
- }],
65
- },
66
- async execute(args) {
67
- const action = args.action
68
- if (action === 'spec') {
69
- return { ok: true, action, spec: SPEC_TEXT }
70
- }
71
- if (action === 'list') {
72
- const templates = normalizeTemplates(await getTemplates())
73
- return { ok: true, action, templates }
74
- }
75
- if (action === 'save') {
76
- const t = args.template && typeof args.template === 'object' ? args.template : null
77
- if (!t) return { ok: false, action, error: '缺少 template 对象 {id,label,description,json}' }
78
- const id = typeof t.id === 'string' ? t.id.trim() : ''
79
- const json = typeof t.json === 'string' ? t.json : ''
80
- if (id === '' || json.trim() === '') return { ok: false, action, error: 'template.id 与 template.json 均为必填' }
81
- let parsed
82
- try {
83
- parsed = parseTemplate(json)
84
- } catch (error) {
85
- return { ok: false, action, errors: ['JSON 解析失败: ' + String(error?.message ?? error)] }
86
- }
87
- if (parsed && typeof parsed.id === 'string' && parsed.id !== id) {
88
- return { ok: false, action, errors: [`template.id("${id}") 与流程定义内 id("${parsed.id}") 不一致`] }
89
- }
90
- // 单模板校验 + 与既有模板并集跨流程校验(动态路由目标存在性;损坏既有模板跳过)
91
- const single = validateTemplate(parsed)
92
- if (single.length > 0) return { ok: false, action, errors: single.map((e) => `${e.target}: ${e.message}`) }
93
- const others = normalizeTemplates(await getTemplates()).filter((item) => item.id !== id)
94
- const otherFlows = []
95
- for (const item of others) {
96
- try {
97
- otherFlows.push(parseTemplate(item.json))
98
- } catch { /* 既有模板损坏不阻塞新模板保存 */ }
99
- }
100
- const cross = validateTemplateSet([parsed, ...otherFlows].filter(Boolean))
101
- if (cross.length > 0) return { ok: false, action, errors: cross.map((e) => `${e.target}: ${e.message}`) }
102
- const entry = {
103
- id,
104
- label: typeof t.label === 'string' && t.label.trim() !== '' ? t.label.trim() : (parsed && parsed.label) || id,
105
- description: typeof t.description === 'string' && t.description.trim() !== '' ? t.description.trim() : (parsed && parsed.description) || '',
106
- enabled: t.enabled !== false,
107
- json,
108
- }
109
- if (args.dryRun === true) {
110
- return { ok: true, action, templates: normalizeTemplates([...others, entry]) }
111
- }
112
- await setTemplates([...others, entry])
113
- let released = false
114
- let presetId = ''
115
- if (args.release === true) {
116
- released = (await releaseTemplate(entry)) === true
117
- presetId = 'rs-' + id
118
- }
119
- logger?.info?.(`rs-workflow 模板已保存: ${id}${released ? `(已创建为模式 ${presetId})` : ''}`)
120
- return { ok: true, action, released, presetId, templates: normalizeTemplates([...others, entry]) }
121
- }
122
- if (action === 'remove') {
123
- const id = typeof args.id === 'string' ? args.id.trim() : ''
124
- if (id === '') return { ok: false, action, error: '缺少 id' }
125
- const outcome = await removeTemplate(id)
126
- if (!outcome.ok) return { ok: false, action, error: outcome.error }
127
- return { ok: true, action, presetId: 'rs-' + id, templates: outcome.templates }
128
- }
129
- return { ok: false, action, error: '未知 action: ' + action }
130
- },
131
- presentCall: () => ({ card: 'generic', title: '编辑若水工作流模板', kind: 'other', rawInput: {} }),
132
- })
133
- }
134
-
135
- // 模式行激活入口:自有文件存储读写 + release 落盘(ctx = agent realm 组合行上下文)
136
- export function registerTemplateTool(ctx) {
137
- ctx.inject(['tools'], (tctx) => {
138
- tctx.effect(() => tctx.tools.register(createTemplateTool({
139
- getTemplates: () => loadJson('templates.json', []),
140
- setTemplates: (templates) => saveJson('templates.json', templates),
141
- removeTemplate: (id) => {
142
- const raw = loadJson('templates.json', [])
143
- const next = raw.filter((t) => t.id !== id)
144
- if (next.length === raw.length) return { ok: false, error: '模板不存在: ' + id }
145
- saveJson('templates.json', next)
146
- const outcome = unreleaseFlowTemplate(id)
147
- return { ok: true, templates: next, outcome }
148
- },
149
- releaseTemplate: (entry) => {
150
- try {
151
- return releaseFlowTemplate(entry) !== 'foreign'
152
- } catch (error) {
153
- ctx.logger?.warn?.(`rs-workflow 模板释放失败: ${error?.message ?? error}`)
154
- return false
155
- }
156
- },
157
- unreleaseTemplate: (id) => unreleaseFlowTemplate(id),
158
- logger: ctx.logger,
159
- })), 'rs-workflow template tool')
160
- })
161
- }
1
+ // template-tool — rs_workflow_template 模型工具:AI 按用户口述逻辑生成/修改流程模板
2
+ // 激活于已创建组合行(template-tool 行);落盘走自有文件存储与释放分派,不直接触碰预设目录(v5)
3
+ import { defineTool } from '@deepseek-ai/dsh-tools'
4
+ import { parseTemplate, validateTemplate, validateTemplateSet } from './template.mjs'
5
+ import { SPEC_TEXT } from './spec.mjs'
6
+ import { loadJson, saveJson } from './storage.mjs'
7
+ import { currentAgentPresets, markReleased, releaseTemplateVia, unreleaseTemplateVia } from './release-registry.mjs'
8
+
9
+ const ACTIONS = ['spec', 'list', 'save', 'remove']
10
+
11
+ function normalizeTemplates(value) {
12
+ if (!Array.isArray(value)) return []
13
+ return value
14
+ .filter((t) => t && typeof t === 'object')
15
+ .map((t) => ({
16
+ id: typeof t.id === 'string' ? t.id : '',
17
+ label: typeof t.label === 'string' ? t.label : '',
18
+ description: typeof t.description === 'string' ? t.description : '',
19
+ enabled: t.enabled !== false,
20
+ json: typeof t.json === 'string' ? t.json : '',
21
+ // released 是注册形态的释放事实源(templates.json),归一化不得剥离
22
+ ...(t.released === true ? { released: true } : {}),
23
+ }))
24
+ .filter((t) => t.id !== '')
25
+ }
26
+
27
+ export function createTemplateTool({ getTemplates, setTemplates, removeTemplate, releaseTemplate, logger }) {
28
+ return defineTool({
29
+ name: 'rs_workflow_template',
30
+ description: [
31
+ '若水工作流流程模板的 AI 编辑入口:用户口述流程逻辑,你据此生成/修改流程模板(严格 JSON)。',
32
+ '先调 {action:"spec"} 获取 DSL v5 规范与示例,再 {action:"save", template:{...}, release:true} 保存并创建为可选模式。',
33
+ 'list 列出现有模板;remove 按 id 移除并撤下其模式。',
34
+ '每步以 outputs 声明结构化产出契约(子代理以结构化工具提交,引擎强制校验);人工审校用 type:"approve" 原语;',
35
+ '流程入参用 inputs;禁止把「希望模型怎么做」写成口头约定。',
36
+ ].join(''),
37
+ parameters: {
38
+ action: { type: 'string', required: true, enum: ACTIONS, description: 'spec=获取 DSL 规范;list=列模板;save=保存模板(可同时创建);remove=移除模板' },
39
+ template: {
40
+ type: 'object',
41
+ additionalProperties: true,
42
+ description: 'save:模板对象 {id,label,description,enabled,json};json 为流程定义严格 JSON 文本(先调 spec 按规范写)',
43
+ },
44
+ id: { type: 'string', description: 'remove:要移除的模板 id' },
45
+ release: { type: 'boolean', description: 'save:true=保存后立即创建为可选模式(rs-<id>)' },
46
+ dryRun: { type: 'boolean', description: 'save:true=仅校验不落盘(编辑器「校验」同源通道)' },
47
+ },
48
+ output: {
49
+ schema: {
50
+ type: 'object',
51
+ additionalProperties: false,
52
+ properties: {
53
+ ok: { type: 'boolean', required: true },
54
+ action: { type: 'string' },
55
+ spec: { type: 'string' },
56
+ templates: { type: 'array', items: { type: 'object', additionalProperties: true } },
57
+ released: { type: 'boolean' },
58
+ presetId: { type: 'string' },
59
+ errors: { type: 'array', items: { type: 'string' } },
60
+ error: { type: 'string' },
61
+ },
62
+ },
63
+ render: (_args, value) => [{
64
+ type: 'text',
65
+ text: value.spec !== undefined ? value.spec : JSON.stringify(value, null, 2),
66
+ }],
67
+ },
68
+ async execute(args) {
69
+ const action = args.action
70
+ if (action === 'spec') {
71
+ return { ok: true, action, spec: SPEC_TEXT }
72
+ }
73
+ if (action === 'list') {
74
+ const templates = normalizeTemplates(await getTemplates())
75
+ return { ok: true, action, templates }
76
+ }
77
+ if (action === 'save') {
78
+ const t = args.template && typeof args.template === 'object' ? args.template : null
79
+ if (!t) return { ok: false, action, error: '缺少 template 对象 {id,label,description,json}' }
80
+ const id = typeof t.id === 'string' ? t.id.trim() : ''
81
+ const json = typeof t.json === 'string' ? t.json : ''
82
+ if (id === '' || json.trim() === '') return { ok: false, action, error: 'template.id 与 template.json 均为必填' }
83
+ let parsed
84
+ try {
85
+ parsed = parseTemplate(json)
86
+ } catch (error) {
87
+ return { ok: false, action, errors: ['JSON 解析失败: ' + String(error?.message ?? error)] }
88
+ }
89
+ if (parsed && typeof parsed.id === 'string' && parsed.id !== id) {
90
+ return { ok: false, action, errors: [`template.id("${id}") 与流程定义内 id("${parsed.id}") 不一致`] }
91
+ }
92
+ // 单模板校验 + 与既有模板并集跨流程校验(动态路由目标存在性;损坏既有模板跳过)
93
+ const single = validateTemplate(parsed)
94
+ if (single.length > 0) return { ok: false, action, errors: single.map((e) => `${e.target}: ${e.message}`) }
95
+ const all = normalizeTemplates(await getTemplates())
96
+ const others = all.filter((item) => item.id !== id)
97
+ const otherFlows = []
98
+ for (const item of others) {
99
+ try {
100
+ otherFlows.push(parseTemplate(item.json))
101
+ } catch { /* 既有模板损坏不阻塞新模板保存 */ }
102
+ }
103
+ const cross = validateTemplateSet([parsed, ...otherFlows].filter(Boolean))
104
+ if (cross.length > 0) return { ok: false, action, errors: cross.map((e) => `${e.target}: ${e.message}`) }
105
+ const entry = {
106
+ id,
107
+ label: typeof t.label === 'string' && t.label.trim() !== '' ? t.label.trim() : (parsed && parsed.label) || id,
108
+ description: typeof t.description === 'string' && t.description.trim() !== '' ? t.description.trim() : (parsed && parsed.description) || '',
109
+ enabled: t.enabled !== false,
110
+ json,
111
+ // 编辑性重存不改变释放态(注销走 remove/unrelease 显式动作)
112
+ ...(all.find((item) => item.id === id)?.released === true ? { released: true } : {}),
113
+ }
114
+ if (args.dryRun === true) {
115
+ return { ok: true, action, templates: normalizeTemplates([...others, entry]) }
116
+ }
117
+ await setTemplates([...others, entry])
118
+ let released = false
119
+ let presetId = ''
120
+ if (args.release === true) {
121
+ released = (await releaseTemplate(entry)) === true
122
+ presetId = 'rs-' + id
123
+ }
124
+ logger?.info?.(`rs-workflow 模板已保存: ${id}${released ? `(已创建为模式 ${presetId})` : ''}`)
125
+ return { ok: true, action, released, presetId, templates: normalizeTemplates([...others, entry]) }
126
+ }
127
+ if (action === 'remove') {
128
+ const id = typeof args.id === 'string' ? args.id.trim() : ''
129
+ if (id === '') return { ok: false, action, error: '缺少 id' }
130
+ const outcome = await removeTemplate(id)
131
+ if (!outcome.ok) return { ok: false, action, error: outcome.error }
132
+ return { ok: true, action, presetId: 'rs-' + id, templates: outcome.templates }
133
+ }
134
+ return { ok: false, action, error: '未知 action: ' + action }
135
+ },
136
+ presentCall: () => ({ card: 'generic', title: '编辑若水工作流模板', kind: 'other', rawInput: {} }),
137
+ })
138
+ }
139
+
140
+ // 模式行激活入口:自有文件存储读写 + 释放分派(注册/目录形态,与 board 同源
141
+ // 服务当值;ctx = agent realm 组合行上下文)
142
+ export function registerTemplateTool(ctx) {
143
+ ctx.inject(['tools'], (tctx) => {
144
+ tctx.effect(() => tctx.tools.register(createTemplateTool({
145
+ getTemplates: () => loadJson('templates.json', []),
146
+ setTemplates: (templates) => saveJson('templates.json', templates),
147
+ removeTemplate: async (id) => {
148
+ const raw = loadJson('templates.json', [])
149
+ const next = raw.filter((t) => t.id !== id)
150
+ if (next.length === raw.length) return { ok: false, error: '模板不存在: ' + id }
151
+ saveJson('templates.json', next)
152
+ const result = await unreleaseTemplateVia(currentAgentPresets(), id)
153
+ return { ok: true, templates: next, outcome: result.outcome }
154
+ },
155
+ releaseTemplate: async (entry) => {
156
+ try {
157
+ const result = await releaseTemplateVia(currentAgentPresets(), entry)
158
+ if (result.outcome === 'failed') {
159
+ ctx.logger?.warn?.(`rs-workflow 模板释放失败: ${result.broken ?? '未知原因'}`)
160
+ return false
161
+ }
162
+ markReleased(entry.id, true)
163
+ return true
164
+ } catch (error) {
165
+ ctx.logger?.warn?.(`rs-workflow 模板释放失败: ${error?.message ?? error}`)
166
+ return false
167
+ }
168
+ },
169
+ logger: ctx.logger,
170
+ })), 'rs-workflow template tool')
171
+ })
172
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mzzsfy/dsh-rs-workflow",
3
3
  "description": "若水工作流设置面:流程模板管理与工作位/预算配置(模板编辑/校验/配置读写)。编排运行时按 v5 设计(docs/rsww-v5/)另行实现。",
4
- "version": "1.0.2",
4
+ "version": "1.1.0",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "exports": {
@@ -1,15 +1,4 @@
1
- # The `rs-workflow` agent preset: 若水工作流(v5,主循环协作编排)。
2
- #
3
- # 本文件是释放骨架源:release 生成器把它作为唯一源生成 rs-<id> 模式组合
4
- # (运行时仅改写 orchestrator 行的 templateId 锚定),不在包内被宿主装载。
5
- #
6
- # 基底是 `standard` 全功能编码代理行集,差异:
7
- # 1. persona 换成流程模式纪律 v5(人机接口+受约束规划者,任务交付由编排子代理承担);
8
- # 2. delegation 组内 rs-workflow-orchestrator 工具行与 template-tool 行;
9
- # 3. 无 report 行(trace 事件 + run-store 取代);plan-mode 组移除(规划在编排内)。
10
-
11
- # ── identity ────────────────────────────────────────────────────────────────
12
-
1
+ # 由 lib/skeleton.mjs emitRows 规范化生成,勿手改;漂移对拍见 test/skeleton.test.mjs。
13
2
  - id: persona
14
3
  name: '@deepseek-ai/dsh-persona'
15
4
  config:
@@ -33,64 +22,35 @@
33
22
  5. 引擎不可用或编排启动失败时,不得自行完成文件类请求——向用户说明故障与已尝试的调用,
34
23
  等待用户处置;文件交付只有 rs_workflow_ 通道,没有自行兜底。
35
24
  suffix: Your working directory is {{cwd}}.
36
-
37
25
  - id: agent-instructions
38
26
  name: '@deepseek-ai/dsh-agent-instructions'
39
27
  config:
40
28
  maxBytes: 65536
41
-
42
- # ── shell ───────────────────────────────────────────────────────────────────
43
-
44
- # 注:不可禁本组合 shell/fs 工具行——宿主 workflow worker 的段子代理继承组合行集,
45
- # 禁行使段子代理无法落盘交付物(实测证实)。主循环不写文件由 persona 判据约束,
46
- # 物理隔离需宿主提供 worker 行集覆写能力(外部依赖)。
47
-
48
29
  - id: tool-bash
49
30
  name: '@deepseek-ai/dsh-tool-bash'
50
31
  disabled: !!js process.platform === 'win32'
51
-
52
32
  - id: tool-pwsh
53
33
  name: '@deepseek-ai/dsh-tool-pwsh'
54
34
  disabled: !!js process.platform !== 'win32'
55
-
56
- # ── filesystem ──────────────────────────────────────────────────────────────
57
-
58
35
  - id: tool-fs
59
36
  name: '@deepseek-ai/dsh-tool-fs'
60
-
61
37
  - id: tool-fs-search
62
38
  name: '@deepseek-ai/dsh-tool-fs-search'
63
39
  config:
64
40
  sampleOverCapGlobResults: false
65
-
66
- # ── background jobs ────────────────────────────────────────────────────────
67
-
68
41
  - id: tool-jobs
69
42
  name: '@deepseek-ai/dsh-tool-jobs'
70
- # 缺省连续唤醒预算 3 次且仅用户消息重置:纯自主编排每段 settle 耗 1 次,第 4 段起降级 inject 不唤醒,
71
- # 编排静默停滞;放宽到 64 段(覆盖 spec 建议的 3~12 步多实例流程上限)
72
43
  config:
73
44
  maxConsecutiveWakes: 64
74
-
75
- # ── skills ──────────────────────────────────────────────────────────────────
76
-
77
45
  - id: skill-filesystem
78
46
  name: '@deepseek-ai/dsh-skill-filesystem'
79
-
80
47
  - id: tool-skill
81
48
  name: '@deepseek-ai/dsh-tool-skill'
82
-
83
- # ── web ─────────────────────────────────────────────────────────────────────
84
-
85
49
  - id: tool-web
86
50
  name: '@deepseek-ai/dsh-tool-web'
87
51
  config:
88
52
  fetch: false
89
53
  searchTimeoutMs: 60000
90
-
91
- # ── compaction ──────────────────────────────────────────────────────────────
92
-
93
- # 编排子代理上下文较长,保留 standard 的压缩组。
94
54
  - id: compaction
95
55
  name: cordis:group
96
56
  group: true
@@ -100,23 +60,14 @@
100
60
  config:
101
61
  - id: compaction-basic
102
62
  name: '@deepseek-ai/dsh-compaction-basic'
103
-
104
63
  - id: command-compact
105
64
  name: '@deepseek-ai/dsh-command-compact'
106
-
107
65
  - id: tool-result-pruner
108
66
  name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
109
67
  config:
110
68
  thresholdChars: 8192
111
69
  headChars: 4096
112
70
  tailChars: 1024
113
-
114
- # ── delegation and workflows ────────────────────────────────────────────────
115
-
116
- # workflowEngine 是预设私有服务(preset 组合发布全局服务会被宿主拒绝 mount),
117
- # 所有触达它的行共享一个 entry-local isolate realm。
118
- # orchestrator 行注册 rs_workflow_* 六工具(含裁决回写 rs_workflow_verdict)并经 jobs 服务拉起分段 continuable job;
119
- # 控制队列与 store 为普通模块单例,host/agent 行经同一 realpath 解析共享实例。
120
71
  - id: delegation
121
72
  name: cordis:group
122
73
  group: true
@@ -125,56 +76,42 @@
125
76
  config:
126
77
  - id: tool-subagent-control
127
78
  name: '@deepseek-ai/dsh-tool-subagent-control'
128
-
129
79
  - id: tool-subagent-list-agents
130
80
  name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
131
-
132
81
  - id: tool-subagent
133
82
  name: '@deepseek-ai/dsh-tool-subagent'
134
83
  config:
135
84
  provider: spawn
136
85
  toolName: subagent
137
86
  backgroundMode: continuable
138
-
139
87
  - id: tool-subagent-fork
140
88
  name: '@deepseek-ai/dsh-tool-subagent'
141
89
  config:
142
90
  provider: fork
143
91
  toolName: subagent_fork
144
92
  backgroundMode: continuable
145
-
146
- - id: workflow-worker-thread
147
- name: '@deepseek-ai/dsh-workflow-worker-thread'
93
+ - id: workflow-ptc
94
+ name: '@deepseek-ai/dsh-workflow-ptc'
148
95
  config:
149
96
  provider: spawn
150
-
151
97
  - id: tool-workflow
152
98
  name: '@deepseek-ai/dsh-tool-workflow'
153
-
154
99
  - id: tool-ralph
155
100
  name: '@deepseek-ai/dsh-tool-ralph'
156
101
  config:
157
102
  subagentProvider: spawn
158
103
  maxRounds: 64
159
-
160
- # orchestrator 工具行:模板 id 由组合名承载(rs-<id> → <id>),释放生成器按组合名写入
161
104
  - id: rs-workflow-orchestrator
162
105
  name: '@mzzsfy/dsh-rs-workflow'
163
106
  config:
164
107
  role: orchestrator
165
108
  templateId: TPL_ANCHOR
166
-
167
- # 模板编辑工具行:rs_workflow_template(AI 按口述逻辑生成/修改流程模板)
168
109
  - id: rs-workflow-template-tool
169
110
  name: '@mzzsfy/dsh-rs-workflow'
170
111
  config:
171
112
  role: template-tool
172
-
173
- # ── remaining model-facing rows ─────────────────────────────────────────────
174
-
175
113
  - id: tool-ask-user
176
114
  name: '@deepseek-ai/dsh-tool-ask-user'
177
-
178
115
  - id: tool-todo
179
116
  name: '@deepseek-ai/dsh-tool-todo'
180
117
  config: