@lynn123411/dsh-ask-user-grilling 0.1.1 → 0.2.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.
- package/README.md +6 -5
- package/lib/index.js +35 -55
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
# @lynn123411/dsh-ask-user-grilling
|
|
2
2
|
|
|
3
|
-
DSH 侧的 grilling 适配层(输送机制):把 Matt Pocock 的 grilling 流程在 DSH
|
|
3
|
+
DSH 侧的 grilling 适配层(输送机制):把 Matt Pocock 的 grilling 流程在 DSH 里的提问环节做成工具级硬约束。本插件只提供 `ask_user_grilling`,不提供任何 plan-mode 工具——共识达成后不自动进入 plan mode,交还用户决定下一步。分工:本插件负责「在 DSH 里怎么问」的工具与报错层;grilling 纪律文案(强制走 `ask_user_grilling`、子代理停轮)写在工具描述与 matt-* 预设 vendor 的 `skills/grilling/SKILL.md` 本地适配旁注(DSH delivery、Sub-agent rounds,重同步上游技能时需保留)里,preset persona 保持原厂逐字不做任何修改。
|
|
4
4
|
|
|
5
5
|
## 特性
|
|
6
6
|
|
|
7
7
|
- **ask_user_grilling**:grilling 轮次专用提问工具。
|
|
8
8
|
- **子代理闸门**:后台有子代理运行时会拒绝提问,返回「阻塞 + 运行中名单」——agent 应**结束当前回合**,子代理结算通知自动唤醒后再调用,不在回合内反复重试;
|
|
9
|
-
- **强制多选**:所有问题一律多选(schema
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
9
|
+
- **强制多选**:所有问题一律多选(schema 不提供关闭开关;此行为刻意**不写入工具描述**——模型若知道只能多选,会为避免互斥选项而影响出题质量,见「描述即纪律」);
|
|
10
|
+
- **补充机制**:每题末尾的补充输入框由 UI 自动渲染、轮末补充题由代码自动追加,两者都不依赖模型也不写入描述(模型自加补充项只会与它们重复);仅当轮末补充输入非空时才应再开一轮;
|
|
11
|
+
- **题干引导**:要求题干只含问题本身、不重复选项文本(仅模型侧引导,不做硬校验——避免误伤自然提及选项名称的题干);
|
|
12
|
+
- **描述即纪律**:工具描述保持精简,只承载「grilling 轮次专用(其余用 ask_user_question)、先散文预告同一轮、再以一次调用投递表单、字段映射、勿自加收尾题、子代理运行中返回 blocked」等工具必知项;投递协议细节(散文预告与表单一一对应、PTC 形态)由技能旁注(DSH delivery / Sub-agent rounds)承载,不与工具描述重复。
|
|
13
|
+
- 轮次收尾不自动进入 plan mode:grilling 达成共识后由用户决定继续方式(直接执行、或需要方案时自行 `/plan on`)。
|
|
13
14
|
|
|
14
15
|
## 安装
|
|
15
16
|
|
package/lib/index.js
CHANGED
|
@@ -9,28 +9,22 @@ import "@deepseek-ai/dsh-user-questions";
|
|
|
9
9
|
* ask_user_grilling:
|
|
10
10
|
* - gate: refuses while background subagents are running (R1)
|
|
11
11
|
* - forces multi-select on every question (R2)
|
|
12
|
-
* - appends a
|
|
12
|
+
* - appends a round-end supplement question (R3) — per-question supplement is
|
|
13
|
+
* via the built-in custom input ("Type your answer" / "输入你的答案"), no
|
|
14
|
+
* extra per-question "Supplement" option to avoid duplication with that
|
|
15
|
+
* field (see image.png issue: checkbox + input were redundant)
|
|
13
16
|
* - stem/option separation is guidance only — never rejects stems (R4
|
|
14
17
|
* relaxed: substring checks false-positive on legitimate stems)
|
|
15
|
-
*
|
|
16
|
-
* enter_plan_mode:
|
|
17
|
-
* - activates DSH plan mode for the current agent (planMode.set)
|
|
18
18
|
*/
|
|
19
19
|
const name = "tool-ask-user-grilling";
|
|
20
20
|
const inject = ["tools", "userQuestions"];
|
|
21
21
|
|
|
22
|
-
const SUPPLEMENT_OPTION = {
|
|
23
|
-
label: "Supplement",
|
|
24
|
-
description: "Select this and write your supplement for this question in your reply.",
|
|
25
|
-
};
|
|
26
|
-
|
|
27
22
|
const ROUND_END_QUESTION = {
|
|
28
23
|
id: "__grill_round_supplement__",
|
|
29
|
-
question: "
|
|
30
|
-
header: "
|
|
24
|
+
question: "这轮还有什么要补充或调整的吗?",
|
|
25
|
+
header: "轮末补充",
|
|
31
26
|
options: [
|
|
32
|
-
{ label: "
|
|
33
|
-
{ label: "I have something to add (write it in my reply)", description: "Select this and write any additions or adjustments for this round in your reply." },
|
|
27
|
+
{ label: "无需补充" },
|
|
34
28
|
],
|
|
35
29
|
multiSelect: true,
|
|
36
30
|
};
|
|
@@ -42,12 +36,12 @@ function displayName(entry) {
|
|
|
42
36
|
function apply(ctx) {
|
|
43
37
|
ctx.tools.register(defineTool({
|
|
44
38
|
name: "ask_user_grilling",
|
|
45
|
-
description: "
|
|
39
|
+
description: "Deliver one ROUND of grilling questions as a form. Use it only when the grilling skill (grill-me / grill-with-docs, or the grilling phases of triage / wayfinder / improve-codebase-architecture) directs a round: first announce the whole round in the message text (title, options and your recommendation, per the skill's template), then deliver the SAME round as ONE call here — the prose and the form must match one-to-one. Map each question to the fields below (title → header, body → question, the A/B/C choices → options; put your recommendation first in options with \"(Recommended)\"; if your recommendation is not an option, state it briefly in the question text). Each question needs a stable id that does not start with __grill_ (reserved for the auto-appended round-end supplement question — never add your own catch-all/\"anything else?\" question; a non-empty supplement input reshapes the tree: ask a further round, and stop asking once the user confirms shared understanding). If background subagents are still running, this tool returns blocked: end your turn and wait for the settlement notice, do not retry within the same turn. For any non-grilling question use the plain ask_user_question tool.",
|
|
46
40
|
parameters: {
|
|
47
41
|
questions: {
|
|
48
42
|
type: "array",
|
|
49
43
|
required: true,
|
|
50
|
-
description: "
|
|
44
|
+
description: "The current round's questions (round/frontier protocol: see the grilling skill). Each needs a stable id, a stem and options.",
|
|
51
45
|
items: {
|
|
52
46
|
type: "object",
|
|
53
47
|
additionalProperties: true,
|
|
@@ -60,15 +54,15 @@ function apply(ctx) {
|
|
|
60
54
|
question: {
|
|
61
55
|
type: "string",
|
|
62
56
|
required: true,
|
|
63
|
-
description: "The question stem only
|
|
57
|
+
description: "The question stem — write only the question. The A/B/C choices belong in options, never in the stem.",
|
|
64
58
|
},
|
|
65
59
|
header: {
|
|
66
60
|
type: "string",
|
|
67
|
-
description: "Optional short heading
|
|
61
|
+
description: "Optional short heading, e.g. \"Q2 — Deadline\".",
|
|
68
62
|
},
|
|
69
63
|
options: {
|
|
70
64
|
type: "array",
|
|
71
|
-
description: "Choices to show the user.
|
|
65
|
+
description: "Choices to show the user. Put your recommended option first and append \"(Recommended)\" to its label.",
|
|
72
66
|
items: {
|
|
73
67
|
type: "object",
|
|
74
68
|
additionalProperties: true,
|
|
@@ -112,16 +106,32 @@ function apply(ctx) {
|
|
|
112
106
|
items: { type: "string" },
|
|
113
107
|
description: "Validation violations when rejected (reserved id prefix only).",
|
|
114
108
|
},
|
|
115
|
-
error: {
|
|
109
|
+
error: {
|
|
110
|
+
type: "string",
|
|
111
|
+
description: "Human-readable error when blocked or rejected.",
|
|
112
|
+
},
|
|
116
113
|
answers: {
|
|
117
114
|
type: "array",
|
|
115
|
+
description: "One entry per question, in the order asked.",
|
|
118
116
|
items: {
|
|
119
117
|
type: "object",
|
|
120
118
|
additionalProperties: false,
|
|
121
119
|
properties: {
|
|
122
|
-
id: {
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
id: {
|
|
121
|
+
type: "string",
|
|
122
|
+
required: true,
|
|
123
|
+
description: "The question id you supplied.",
|
|
124
|
+
},
|
|
125
|
+
selected: {
|
|
126
|
+
type: "array",
|
|
127
|
+
required: true,
|
|
128
|
+
items: { type: "string" },
|
|
129
|
+
description: "Labels of the options the user picked (may be empty if skipped).",
|
|
130
|
+
},
|
|
131
|
+
custom: {
|
|
132
|
+
type: "string",
|
|
133
|
+
description: "User-typed free text for this question, if any.",
|
|
134
|
+
},
|
|
125
135
|
},
|
|
126
136
|
},
|
|
127
137
|
},
|
|
@@ -149,7 +159,7 @@ function apply(ctx) {
|
|
|
149
159
|
return {
|
|
150
160
|
blocked: true,
|
|
151
161
|
waiting: [],
|
|
152
|
-
error: "Cannot confirm background subagent status (subagents query failed).
|
|
162
|
+
error: "Cannot confirm background subagent status (subagents query failed). End your turn and wait; call this tool again in a later turn.",
|
|
153
163
|
};
|
|
154
164
|
}
|
|
155
165
|
}
|
|
@@ -180,7 +190,7 @@ function apply(ctx) {
|
|
|
180
190
|
};
|
|
181
191
|
}
|
|
182
192
|
|
|
183
|
-
// 3. transform: force multi-select (R2)
|
|
193
|
+
// 3. transform: force multi-select (R2); per-question supplement is via the built-in custom input ("Type your answer"/"输入你的答案") — no extra option is added to avoid duplication with that field
|
|
184
194
|
const questions = args.questions.map((question) => ({
|
|
185
195
|
id: question.id,
|
|
186
196
|
question: question.question,
|
|
@@ -190,12 +200,11 @@ function apply(ctx) {
|
|
|
190
200
|
label: option.label,
|
|
191
201
|
...(option.description !== undefined ? { description: option.description } : {}),
|
|
192
202
|
})),
|
|
193
|
-
SUPPLEMENT_OPTION,
|
|
194
203
|
],
|
|
195
204
|
multiSelect: true,
|
|
196
205
|
}));
|
|
197
206
|
|
|
198
|
-
// 4. round-end supplement question (R3)
|
|
207
|
+
// 4. round-end supplement question (R3) — single "无需补充" option; supplement is via custom input, so no "I have something to add" option (duplicates that field)
|
|
199
208
|
questions.push(ROUND_END_QUESTION);
|
|
200
209
|
|
|
201
210
|
// 5. ask through the userQuestions seam (UI renders from the service)
|
|
@@ -213,35 +222,6 @@ function apply(ctx) {
|
|
|
213
222
|
};
|
|
214
223
|
},
|
|
215
224
|
}));
|
|
216
|
-
|
|
217
|
-
ctx.tools.register(defineTool({
|
|
218
|
-
name: "enter_plan_mode",
|
|
219
|
-
description: "Enter plan mode for the current agent. Call it after the final round of a grilling session once the user has confirmed shared understanding, so a plan is written for review instead of executing directly. Plan mode ends via exit_plan_mode or the /plan off command.",
|
|
220
|
-
parameters: {},
|
|
221
|
-
output: {
|
|
222
|
-
schema: {
|
|
223
|
-
type: "object",
|
|
224
|
-
additionalProperties: false,
|
|
225
|
-
properties: {
|
|
226
|
-
ok: { type: "boolean" },
|
|
227
|
-
result: { type: "string" },
|
|
228
|
-
error: { type: "string" },
|
|
229
|
-
},
|
|
230
|
-
},
|
|
231
|
-
render: (_args, value) => [{ type: "text", text: JSON.stringify(value) }],
|
|
232
|
-
},
|
|
233
|
-
async execute(_args, exec) {
|
|
234
|
-
const planMode = ctx.get("planMode");
|
|
235
|
-
if (planMode === undefined) return { ok: false, error: "planMode service unavailable" };
|
|
236
|
-
const agent = exec.agent;
|
|
237
|
-
if (agent === undefined) return { ok: false, error: "current agent unavailable" };
|
|
238
|
-
const outcome = planMode.set(agent, true);
|
|
239
|
-
// cancelled = an opposite pending selection was cleared and the logged
|
|
240
|
-
// state already matches the requested active state — plan mode IS active.
|
|
241
|
-
const ok = outcome === "committed" || outcome === "queued" || outcome === "cancelled" || outcome === "noop";
|
|
242
|
-
return { ok, result: `plan mode ${outcome}` };
|
|
243
|
-
},
|
|
244
|
-
}));
|
|
245
225
|
}
|
|
246
226
|
|
|
247
227
|
export { apply, inject, name };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lynn123411/dsh-ask-user-grilling",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "DSH delivery adaptations for grilling rounds: ask_user_grilling (subagent gate / forced multi-select / supplement
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "DSH delivery adaptations for grilling rounds: ask_user_grilling (subagent gate / forced multi-select / round-end supplement / stem guidance). Does not modify any skill file.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|