@goodandready/dsh-goal 0.2.2 → 0.2.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/README.md +12 -0
- package/README.ru.md +12 -0
- package/README.zh.md +12 -0
- package/lib/client.js +4418 -4498
- package/lib/command-handler.js +242 -276
- package/lib/engine-prompt.js +57 -0
- package/lib/engine-reports.js +114 -0
- package/lib/engine-store.js +142 -0
- package/lib/goal-engine-constants.js +100 -0
- package/lib/goal-engine.js +579 -2018
- package/lib/index.js +452 -1960
- package/lib/routes.js +294 -0
- package/lib/tools.js +294 -0
- package/lib/updater.js +317 -0
- package/package.json +62 -63
package/lib/command-handler.js
CHANGED
|
@@ -1,276 +1,242 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { GoalState, detectLanguage } from './goal-engine.js';
|
|
3
|
-
|
|
4
|
-
export const USAGE_EN = 'Usage: /goal [<goal>|clear|pause|resume]';
|
|
5
|
-
export const USAGE_ZH = '用法: /goal [<目标描述>|clear|pause|resume]';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (lower === '
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
*
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
*
|
|
44
|
-
* @
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
`
|
|
54
|
-
`
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
: (
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
case 'start': {
|
|
244
|
-
const maxIterations = config.maxIterations ?? snap.maxIterations ?? 25;
|
|
245
|
-
const cwd = config.cwd;
|
|
246
|
-
const newSnap = engine.startGoal(parsed.text, { maxIterations, lang, cwd }, sid);
|
|
247
|
-
|
|
248
|
-
if (agent && typeof agent.followup === 'function') {
|
|
249
|
-
try {
|
|
250
|
-
const userMsg = createGoalUserMessage(formatGoalStartPrompt(parsed.text, lang));
|
|
251
|
-
agent.followup(userMsg);
|
|
252
|
-
} catch (err) {
|
|
253
|
-
console.warn('[dsh-goal] Failed to dispatch goal to agent followup:', err);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
return {
|
|
258
|
-
kind: 'success',
|
|
259
|
-
text: isZh
|
|
260
|
-
? `🎯 目标已激活: "${newSnap.title}" (上限 ${newSnap.maxIterations} 轮迭代)。\n` +
|
|
261
|
-
`暂停: /goal pause | 清除: /goal clear`
|
|
262
|
-
: (isRu
|
|
263
|
-
? `🎯 Активирована цель: «${newSnap.title}» (макс. ${newSnap.maxIterations} итераций).\n` +
|
|
264
|
-
`Для паузы: /goal pause | Для сброса: /goal clear`
|
|
265
|
-
: `🎯 Goal activated: "${newSnap.title}" (max ${newSnap.maxIterations} iterations).\n` +
|
|
266
|
-
`To pause: /goal pause | To clear: /goal clear`),
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
default:
|
|
271
|
-
return {
|
|
272
|
-
kind: 'error',
|
|
273
|
-
text: isZh ? `未知指令。${usage}` : (isRu ? `Неизвестная команда. ${usage}` : `Unknown command. ${usage}`),
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
}
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { GoalState, detectLanguage } from './goal-engine.js';
|
|
3
|
+
|
|
4
|
+
export const USAGE_EN = 'Usage: /goal [<goal>|clear|pause|resume]';
|
|
5
|
+
export const USAGE_ZH = '用法: /goal [<目标描述>|clear|pause|resume]';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Parse input string for /goal command
|
|
9
|
+
* @param {string} rawInput
|
|
10
|
+
* @returns {{ action: string, text?: string }}
|
|
11
|
+
*/
|
|
12
|
+
export function parseGoalInput(rawInput = '') {
|
|
13
|
+
const input = String(rawInput || '').trim();
|
|
14
|
+
if (!input) {
|
|
15
|
+
return { action: 'show' };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const lower = input.toLowerCase();
|
|
19
|
+
if (lower === 'clear') return { action: 'clear' };
|
|
20
|
+
if (lower === 'pause') return { action: 'pause' };
|
|
21
|
+
if (lower === 'resume') return { action: 'resume' };
|
|
22
|
+
|
|
23
|
+
return { action: 'start', text: input };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Create a valid identified user message for agent followup
|
|
28
|
+
* @param {string} text
|
|
29
|
+
* @returns {Object}
|
|
30
|
+
*/
|
|
31
|
+
export function createGoalUserMessage(text) {
|
|
32
|
+
return {
|
|
33
|
+
id: randomUUID(),
|
|
34
|
+
role: 'user',
|
|
35
|
+
content: [{ type: 'text', text }],
|
|
36
|
+
source: { kind: 'user' },
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Format goal start prompt with mandatory milestone contract
|
|
42
|
+
* @param {string} goalText
|
|
43
|
+
* @param {string} [explicitLang]
|
|
44
|
+
* @returns {string}
|
|
45
|
+
*/
|
|
46
|
+
export function formatGoalStartPrompt(goalText, explicitLang) {
|
|
47
|
+
const lang = explicitLang || detectLanguage(goalText);
|
|
48
|
+
if (lang === 'zh') {
|
|
49
|
+
return `🎯 目标模式已激活 (Goal Mode): "${goalText}"\n\n` +
|
|
50
|
+
`自主执行契约:\n` +
|
|
51
|
+
`1. 第一步必选动作:在开展任何工作或回复之前,你的第一个动作必须是调用 goal_set_milestones 工具,提交包含 3-7 个具体连续步骤的工作计划。用户将在界面中实时查看此计划。\n` +
|
|
52
|
+
`2. 第二步:计划确立后开始执行任务。在开始每个步骤前,通过 goal_update_progress(milestone_id, "in_progress") 标记其为进行中。\n` +
|
|
53
|
+
`3. 第三步:完成某一步骤后,通过 goal_update_progress(milestone_id, "completed", "阶段简要成果") 标记为已完成。\n` +
|
|
54
|
+
`4. 第四步:当所有里程碑全部完成后,调用 goal_finish(summary) 工具并附带详尽的最终成果总结。`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return `🎯 Goal Mode activated: "${goalText}"\n\n` +
|
|
58
|
+
`STRICT AUTONOMOUS CONTRACT:\n` +
|
|
59
|
+
`1. MANDATORY STEP 1: Your FIRST action BEFORE doing any other work or reply MUST be calling tool goal_set_milestones with an array of 3-7 concrete, sequential milestones. The user sees this plan in real time.\n` +
|
|
60
|
+
`2. STEP 2: After establishing the plan, proceed to execute milestones. Before starting each milestone, mark it as in_progress via goal_update_progress(milestone_id, "in_progress").\n` +
|
|
61
|
+
`3. STEP 3: Upon completing a milestone, mark it as completed via goal_update_progress(milestone_id, "completed", "brief milestone outcome").\n` +
|
|
62
|
+
`4. STEP 4: When all milestones are completed, call tool goal_finish(summary) with a comprehensive summary of achieved results.`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Format response for UI and manage agent task execution
|
|
67
|
+
* @param {import('./goal-engine.js').GoalEngine} engine
|
|
68
|
+
* @param {{ action: string, text?: string }} parsed
|
|
69
|
+
* @param {Object} [config]
|
|
70
|
+
* @param {Object} [agent]
|
|
71
|
+
* @param {string} [sessionId='default']
|
|
72
|
+
* @returns {{ kind: string, text: string }}
|
|
73
|
+
*/
|
|
74
|
+
export function executeGoalSlashCommand(engine, parsed, config = {}, agent = null, sessionId = 'default') {
|
|
75
|
+
const sid = sessionId || 'default';
|
|
76
|
+
const snap = engine.getGoalSnapshot(sid);
|
|
77
|
+
const lang = snap.lang || (parsed.text ? detectLanguage(parsed.text) : 'en');
|
|
78
|
+
const isZh = lang === 'zh';
|
|
79
|
+
const usage = isZh ? USAGE_ZH : USAGE_EN;
|
|
80
|
+
|
|
81
|
+
switch (parsed.action) {
|
|
82
|
+
case 'show': {
|
|
83
|
+
if (!snap.hasActiveGoal) {
|
|
84
|
+
return {
|
|
85
|
+
kind: 'success',
|
|
86
|
+
text: isZh ? `目标模式: 当前未设置活动目标。\n${usage}` : `Goal Mode: no active goal set.\n${usage}`,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const milestonesInfo = snap.milestones && snap.milestones.length > 0
|
|
91
|
+
? `\n\n${isZh ? '工作计划' : 'Work Plan'}:\n` +
|
|
92
|
+
snap.milestones
|
|
93
|
+
.map((m, i) => ` ${i + 1}. [${m.status.toUpperCase()}] ${m.title}${m.notes ? ` (${m.notes})` : ''}`)
|
|
94
|
+
.join('\n')
|
|
95
|
+
: '';
|
|
96
|
+
|
|
97
|
+
const etaText = snap.formattedETA ? ` (ETA: ${snap.formattedETA})` : '';
|
|
98
|
+
const tokensInfo = (snap.tokensUsage && snap.tokensUsage.totalTokens > 0)
|
|
99
|
+
? (isZh
|
|
100
|
+
? `\nToken: ${snap.tokensUsage.totalTokens.toLocaleString()} (输入: ${snap.tokensUsage.promptTokens.toLocaleString()}, 输出: ${snap.tokensUsage.completionTokens.toLocaleString()})`
|
|
101
|
+
: `\nTokens: ${snap.tokensUsage.totalTokens.toLocaleString()} (in: ${snap.tokensUsage.promptTokens.toLocaleString()}, out: ${snap.tokensUsage.completionTokens.toLocaleString()})`)
|
|
102
|
+
: '';
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
kind: 'success',
|
|
106
|
+
text: isZh
|
|
107
|
+
? `🎯 目标: "${snap.title}"\n` +
|
|
108
|
+
`状态: ${snap.state}\n` +
|
|
109
|
+
`耗时: ${snap.formattedElapsed}${etaText}\n` +
|
|
110
|
+
`迭代轮次: ${snap.iterationsCount}/${snap.maxIterations}` +
|
|
111
|
+
tokensInfo +
|
|
112
|
+
milestonesInfo +
|
|
113
|
+
`\n\n快捷指令: /goal pause, /goal resume, /goal clear, /goal <新目标>`
|
|
114
|
+
: `🎯 Goal: "${snap.title}"\n` +
|
|
115
|
+
`Status: ${snap.state}\n` +
|
|
116
|
+
`Duration: ${snap.formattedElapsed}${etaText}\n` +
|
|
117
|
+
`Iterations: ${snap.iterationsCount}/${snap.maxIterations}` +
|
|
118
|
+
tokensInfo +
|
|
119
|
+
milestonesInfo +
|
|
120
|
+
`\n\nCommands: /goal pause, /goal resume, /goal clear, /goal <new goal>`,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
case 'clear': {
|
|
125
|
+
if (!snap.hasActiveGoal) {
|
|
126
|
+
return {
|
|
127
|
+
kind: 'success',
|
|
128
|
+
text: isZh ? '当前未设置目标。' : 'No active goal set.',
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
engine.clear(sid);
|
|
132
|
+
if (agent && typeof agent.cancel === 'function') {
|
|
133
|
+
try {
|
|
134
|
+
agent.cancel({ kind: 'user', reason: 'Goal cleared by user' });
|
|
135
|
+
} catch (err) {
|
|
136
|
+
// agent cancellation error handled defensively
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
kind: 'success',
|
|
141
|
+
text: isZh ? '🎯 目标已清除。' : '🎯 Goal cleared.',
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
case 'pause': {
|
|
146
|
+
if (!snap.hasActiveGoal) {
|
|
147
|
+
return {
|
|
148
|
+
kind: 'error',
|
|
149
|
+
text: isZh
|
|
150
|
+
? `无法暂停:未设置活动目标。\n${usage}`
|
|
151
|
+
: `Cannot pause: no active goal.\n${usage}`,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (snap.state === GoalState.PAUSED) {
|
|
155
|
+
return {
|
|
156
|
+
kind: 'success',
|
|
157
|
+
text: isZh ? '⏸ 目标当前已处于暂停状态。' : '⏸ Goal is already paused.',
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
engine.pause(isZh ? '用户命令暂停 (/goal pause)' : 'Paused by user command (/goal pause)', sid);
|
|
161
|
+
if (agent && typeof agent.cancel === 'function') {
|
|
162
|
+
try {
|
|
163
|
+
agent.cancel({ kind: 'user', reason: 'Goal paused by user' });
|
|
164
|
+
} catch (err) {
|
|
165
|
+
// agent cancellation error handled defensively
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
kind: 'success',
|
|
170
|
+
text: isZh
|
|
171
|
+
? `⏸ 目标已暂停: "${snap.title}"。智能体已停止,使用 /goal resume 或 ▶️ 按钮继续。`
|
|
172
|
+
: `⏸ Goal paused: "${snap.title}". Agent stopped. Use /goal resume or ▶️ button to continue.`,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
case 'resume': {
|
|
177
|
+
if (!snap.hasActiveGoal) {
|
|
178
|
+
return {
|
|
179
|
+
kind: 'error',
|
|
180
|
+
text: isZh
|
|
181
|
+
? `无法恢复:未设置活动目标。\n${usage}`
|
|
182
|
+
: `Cannot resume: no active goal.\n${usage}`,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
if (snap.state === GoalState.RUNNING) {
|
|
186
|
+
return {
|
|
187
|
+
kind: 'success',
|
|
188
|
+
text: isZh ? '▶️ 目标已在运行中。' : '▶️ Goal is already running.',
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
engine.resume(sid);
|
|
192
|
+
if (agent && typeof agent.followup === 'function') {
|
|
193
|
+
try {
|
|
194
|
+
const resumePrompt = isZh
|
|
195
|
+
? `▶️ 用户已恢复目标运行。请继续推进工作计划中尚未完成的步骤。通过 goal_update_progress 实时更新进度。`
|
|
196
|
+
: `▶️ Goal resumed by user. Continue executing the work plan from where you stopped. Update steps via goal_update_progress.`;
|
|
197
|
+
agent.followup(createGoalUserMessage(resumePrompt));
|
|
198
|
+
} catch (err) {
|
|
199
|
+
// agent followup error handled defensively
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
kind: 'success',
|
|
204
|
+
text: isZh
|
|
205
|
+
? `▶️ 目标已恢复: "${snap.title}"。智能体继续工作中。`
|
|
206
|
+
: `▶️ Goal resumed: "${snap.title}". Agent continues working.`,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
case 'start': {
|
|
211
|
+
const goalLang = detectLanguage(parsed.text);
|
|
212
|
+
const isZhStart = goalLang === 'zh';
|
|
213
|
+
const maxIterations = config.maxIterations ?? snap.maxIterations ?? 25;
|
|
214
|
+
const cwd = config.cwd;
|
|
215
|
+
const newSnap = engine.startGoal(parsed.text, { maxIterations, lang: goalLang, cwd }, sid);
|
|
216
|
+
|
|
217
|
+
if (agent && typeof agent.followup === 'function') {
|
|
218
|
+
try {
|
|
219
|
+
const userMsg = createGoalUserMessage(formatGoalStartPrompt(parsed.text, goalLang));
|
|
220
|
+
agent.followup(userMsg);
|
|
221
|
+
} catch (err) {
|
|
222
|
+
// agent dispatch error handled defensively
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
kind: 'success',
|
|
228
|
+
text: isZhStart
|
|
229
|
+
? `🎯 目标已激活: "${newSnap.title}" (上限 ${newSnap.maxIterations} 轮迭代)。\n` +
|
|
230
|
+
`暂停: /goal pause | 清除: /goal clear`
|
|
231
|
+
: `🎯 Goal activated: "${newSnap.title}" (max ${newSnap.maxIterations} iterations).\n` +
|
|
232
|
+
`To pause: /goal pause | To clear: /goal clear`,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
default:
|
|
237
|
+
return {
|
|
238
|
+
kind: 'error',
|
|
239
|
+
text: isZh ? `未知指令。${usage}` : `Unknown command. ${usage}`,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt generation for DSH Goal Mode
|
|
3
|
+
*/
|
|
4
|
+
export function buildStatePromptInjection(snapshot, pendingNudge) {
|
|
5
|
+
const lang = snapshot.lang || 'en';
|
|
6
|
+
const hasMilestones = snapshot.milestones && snapshot.milestones.length > 0;
|
|
7
|
+
const etaText = snapshot.formattedETA ? ` (ETA: ${snapshot.formattedETA})` : '';
|
|
8
|
+
|
|
9
|
+
let nudgeText = '';
|
|
10
|
+
if (pendingNudge) {
|
|
11
|
+
if (lang === 'zh') {
|
|
12
|
+
nudgeText = `\n\n🚨 用户紧急补充说明 / 调整方向:\n"${pendingNudge}"\n你必须根据此说明调整近期的具体执行步骤!\n`;
|
|
13
|
+
} else {
|
|
14
|
+
nudgeText = `\n\n🚨 URGENT USER CLARIFICATION / STEERING:\n"${pendingNudge}"\nYou must adjust your immediate actions according to this guidance!\n`;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (lang === 'zh') {
|
|
19
|
+
const milestonesText = hasMilestones
|
|
20
|
+
? snapshot.milestones
|
|
21
|
+
.map((m, i) => ` ${i + 1}. [${m.status.toUpperCase()}] ${m.title}${m.notes ? ` (${m.notes})` : ''}`)
|
|
22
|
+
.join('\n')
|
|
23
|
+
: ' (工作计划尚未建立 — 请立即调用 goal_set_milestones 设定初始里程碑!)';
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
nudgeText +
|
|
27
|
+
`\n\n[DSH GOAL MODE ACTIVE]\n` +
|
|
28
|
+
`目标: "${snapshot.title}"\n` +
|
|
29
|
+
`运行时间: ${snapshot.formattedElapsed}${etaText} | 迭代轮次: ${snapshot.iterationsCount}/${snapshot.maxIterations}\n` +
|
|
30
|
+
`工作计划:\n` +
|
|
31
|
+
`${milestonesText}\n\n` +
|
|
32
|
+
`Goal Mode 执行契约 (必须严格遵循):\n` +
|
|
33
|
+
`1. ${hasMilestones ? '按部就班推进当前进行中的里程碑。' : '第一步核心指令: 立即调用 goal_set_milestones 制定 3-7 个具体里程碑。在完成此工具调用前严禁执行其他操作!'}\n` +
|
|
34
|
+
`2. 推进里程碑时,必须通过 goal_update_progress 工具更新状态(开始前标为 in_progress,完成后标为 completed 并附简要说明)。\n` +
|
|
35
|
+
`3. 当所有里程碑全部完成后,调用 goal_finish 工具提交详细成果总结。`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const milestonesText = hasMilestones
|
|
40
|
+
? snapshot.milestones
|
|
41
|
+
.map((m, i) => ` ${i + 1}. [${m.status.toUpperCase()}] ${m.title}${m.notes ? ` (${m.notes})` : ''}`)
|
|
42
|
+
.join('\n')
|
|
43
|
+
: ' (Work plan is not yet established — call goal_set_milestones immediately with initial steps!)';
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
nudgeText +
|
|
47
|
+
`\n\n[DSH GOAL MODE ACTIVE]\n` +
|
|
48
|
+
`Goal: "${snapshot.title}"\n` +
|
|
49
|
+
`Elapsed Time: ${snapshot.formattedElapsed}${etaText} | Iteration: ${snapshot.iterationsCount}/${snapshot.maxIterations}\n` +
|
|
50
|
+
`Work Plan:\n` +
|
|
51
|
+
`${milestonesText}\n\n` +
|
|
52
|
+
`Goal Mode Instructions (MANDATORY TO FOLLOW):\n` +
|
|
53
|
+
`1. ${hasMilestones ? 'Execute the current active milestone from the work plan.' : 'YOUR FIRST STEP: Immediately call tool goal_set_milestones with the list of milestones (3-7 concrete steps). You must not execute work or finish turn without calling goal_set_milestones!'}\n` +
|
|
54
|
+
`2. As each milestone progresses, update its status via tool goal_update_progress (status: "in_progress" before starting, status: "completed" upon completion with brief notes).\n` +
|
|
55
|
+
`3. When all milestones are completed, call tool goal_finish with a detailed summary of achieved results.`
|
|
56
|
+
);
|
|
57
|
+
}
|