geo-ai-search-optimization 1.2.13 → 1.2.15
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 +58 -0
- package/package.json +1 -1
- package/resources/geo-ai-search-optimization/references/skill-bundle-map.md +20 -0
- package/resources/geo-ai-search-optimization-agent-checkpoint/SKILL.md +23 -0
- package/resources/geo-ai-search-optimization-agent-checkpoint/agents/openai.yaml +4 -0
- package/resources/geo-ai-search-optimization-agent-decision-log/SKILL.md +23 -0
- package/resources/geo-ai-search-optimization-agent-decision-log/agents/openai.yaml +4 -0
- package/resources/geo-ai-search-optimization-usage/SKILL.md +24 -14
- package/src/agent-checkpoint.js +378 -0
- package/src/agent-decision-log.js +368 -0
- package/src/agent-progress-tracker.js +70 -0
- package/src/agent-session.js +20 -0
- package/src/agent-status-board.js +35 -0
- package/src/auto-flow.js +67 -0
- package/src/cli.js +72 -0
- package/src/index.js +2 -0
- package/src/skills.js +6 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createAgentCheckpoint } from "./agent-checkpoint.js";
|
|
4
|
+
import { writeScanOutput } from "./scan.js";
|
|
5
|
+
|
|
6
|
+
const VALID_FORMATS = new Set(["markdown", "json"]);
|
|
7
|
+
|
|
8
|
+
function normalizeFormat(format) {
|
|
9
|
+
const resolved = (format || "markdown").toLowerCase();
|
|
10
|
+
if (!VALID_FORMATS.has(resolved)) {
|
|
11
|
+
throw new Error(`不支持的 agent-decision-log 格式:${format}。可选值:${Array.from(VALID_FORMATS).join(", ")}`);
|
|
12
|
+
}
|
|
13
|
+
return resolved;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function pathExists(targetPath) {
|
|
17
|
+
try {
|
|
18
|
+
await fs.access(targetPath);
|
|
19
|
+
return true;
|
|
20
|
+
} catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function cloneForFormat(record, format) {
|
|
26
|
+
if (!record || typeof record !== "object") {
|
|
27
|
+
return record;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
...record,
|
|
32
|
+
format
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function buildEntryId(index) {
|
|
37
|
+
return `decision-${String(index).padStart(2, "0")}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function buildDecisionNote(options) {
|
|
41
|
+
return options.note || options.decisionNote || null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function buildRecommendedFocus(checkpoint) {
|
|
45
|
+
switch (checkpoint.decision) {
|
|
46
|
+
case "resolve-blockers":
|
|
47
|
+
return `先解除 ${checkpoint.blockedItems.length || 1} 个阻塞项,再继续当前包。`;
|
|
48
|
+
case "move-to-closeout":
|
|
49
|
+
return "进入复盘、交接和交付,不要再扩展新任务。";
|
|
50
|
+
case "continue-current-packet":
|
|
51
|
+
return `继续推进当前包 ${checkpoint.currentPacket?.id || ""},不要切换任务。`.trim();
|
|
52
|
+
case "start-first-packet":
|
|
53
|
+
return `启动第一包 ${checkpoint.currentPacket?.id || ""},建立第一轮执行节奏。`.trim();
|
|
54
|
+
default:
|
|
55
|
+
return "先补执行上下文,再进入下一轮。";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function buildLogSummary(entries, checkpoint) {
|
|
60
|
+
if (entries.length === 1) {
|
|
61
|
+
return `目前已有 1 次阶段决策,最新结论是 ${checkpoint.decision}。`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return `目前已累计 ${entries.length} 次阶段决策,最新结论是 ${checkpoint.decision},当前重点是:${buildRecommendedFocus(checkpoint)}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function buildEntry(checkpoint, note, index) {
|
|
68
|
+
return {
|
|
69
|
+
id: buildEntryId(index),
|
|
70
|
+
createdAt: new Date().toISOString(),
|
|
71
|
+
checkpointType: checkpoint.checkpointType,
|
|
72
|
+
decision: checkpoint.decision,
|
|
73
|
+
boardStatus: checkpoint.boardStatus,
|
|
74
|
+
progressPercent: checkpoint.progressPercent,
|
|
75
|
+
decisionReason: checkpoint.decisionReason,
|
|
76
|
+
currentPacket: checkpoint.currentPacket
|
|
77
|
+
? {
|
|
78
|
+
id: checkpoint.currentPacket.id,
|
|
79
|
+
title: checkpoint.currentPacket.title,
|
|
80
|
+
owner: checkpoint.currentPacket.owner,
|
|
81
|
+
priority: checkpoint.currentPacket.priority
|
|
82
|
+
}
|
|
83
|
+
: null,
|
|
84
|
+
nextPacket: checkpoint.nextPacket
|
|
85
|
+
? {
|
|
86
|
+
id: checkpoint.nextPacket.id,
|
|
87
|
+
title: checkpoint.nextPacket.title,
|
|
88
|
+
owner: checkpoint.nextPacket.owner,
|
|
89
|
+
priority: checkpoint.nextPacket.priority
|
|
90
|
+
}
|
|
91
|
+
: null,
|
|
92
|
+
blockedItems: checkpoint.blockedItems.map((item) => ({
|
|
93
|
+
id: item.id,
|
|
94
|
+
title: item.title,
|
|
95
|
+
owner: item.owner,
|
|
96
|
+
priority: item.priority
|
|
97
|
+
})),
|
|
98
|
+
suggestedNextCommand: checkpoint.suggestedNextCommand,
|
|
99
|
+
alternateCommands: checkpoint.alternateCommands,
|
|
100
|
+
handoffNote: checkpoint.handoffNote,
|
|
101
|
+
note: note || null
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function buildLogPrompt(log) {
|
|
106
|
+
const latest = log.latestCheckpoint;
|
|
107
|
+
const lines = [
|
|
108
|
+
"你现在进入 GEO 决策历史模式。",
|
|
109
|
+
`当前输入:${log.source}`,
|
|
110
|
+
`已累计决策次数:${log.totalEntries}`,
|
|
111
|
+
`最新检查点类型:${latest.checkpointType}`,
|
|
112
|
+
`最新决策:${latest.decision}`,
|
|
113
|
+
`最新决策原因:${latest.decisionReason}`,
|
|
114
|
+
`当前重点:${log.recommendedFocus}`
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
if (latest.currentPacket) {
|
|
118
|
+
lines.push(`当前包:${latest.currentPacket.id}|${latest.currentPacket.title}`);
|
|
119
|
+
}
|
|
120
|
+
if (latest.nextPacket) {
|
|
121
|
+
lines.push(`下一包:${latest.nextPacket.id}|${latest.nextPacket.title}`);
|
|
122
|
+
}
|
|
123
|
+
if (latest.blockedItems.length > 0) {
|
|
124
|
+
lines.push(`当前阻塞:${latest.blockedItems.map((item) => item.title).join(";")}`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
lines.push("请先说明最近几轮是如何决策的,再给出这一轮应该继续、解阻还是收尾。");
|
|
128
|
+
lines.push("最后输出下一步命令、交接说明,以及是否需要追加一条新的决策记录。");
|
|
129
|
+
return lines.join("\n");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function readJsonIfExists(targetPath) {
|
|
133
|
+
if (!(await pathExists(targetPath))) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const raw = await fs.readFile(targetPath, "utf8");
|
|
138
|
+
return JSON.parse(raw);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function resolveExistingLog(options = {}) {
|
|
142
|
+
const appendFrom = options.appendFrom || options.appendPath;
|
|
143
|
+
if (!appendFrom) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const resolvedPath = path.resolve(appendFrom);
|
|
148
|
+
const parsed = await readJsonIfExists(resolvedPath);
|
|
149
|
+
if (!parsed || parsed.kind !== "geo-agent-decision-log") {
|
|
150
|
+
throw new Error(`append-from 需要指向一个 geo-agent-decision-log JSON 工件:${resolvedPath}`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
path: resolvedPath,
|
|
155
|
+
log: parsed
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function shouldReuseDecisionLog(parsed, options = {}) {
|
|
160
|
+
return (
|
|
161
|
+
parsed?.kind === "geo-agent-decision-log" &&
|
|
162
|
+
!options.appendFrom &&
|
|
163
|
+
!options.appendPath &&
|
|
164
|
+
!options.currentTaskId &&
|
|
165
|
+
!options.completedPacketIds &&
|
|
166
|
+
!options.blockedReasons &&
|
|
167
|
+
!buildDecisionNote(options)
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function getCheckpointSourceFromLog(parsed, fallbackInput) {
|
|
172
|
+
return (
|
|
173
|
+
parsed?.latestCheckpoint?.source ||
|
|
174
|
+
parsed?.latestCheckpoint?.statusBoard?.source ||
|
|
175
|
+
parsed?.source ||
|
|
176
|
+
fallbackInput
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async function resolveCheckpoint(input, options = {}) {
|
|
181
|
+
const resolvedInput = path.resolve(input);
|
|
182
|
+
if (await pathExists(resolvedInput)) {
|
|
183
|
+
try {
|
|
184
|
+
const raw = await fs.readFile(resolvedInput, "utf8");
|
|
185
|
+
const parsed = JSON.parse(raw);
|
|
186
|
+
|
|
187
|
+
if (shouldReuseDecisionLog(parsed, options)) {
|
|
188
|
+
return {
|
|
189
|
+
reuseLog: cloneForFormat(parsed, normalizeFormat(options.format)),
|
|
190
|
+
checkpoint: parsed.latestCheckpoint || null
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (parsed?.kind === "geo-agent-decision-log" && parsed.latestCheckpoint?.kind === "geo-agent-checkpoint") {
|
|
195
|
+
const checkpointSource = getCheckpointSourceFromLog(parsed, resolvedInput);
|
|
196
|
+
const checkpoint = await createAgentCheckpoint(checkpointSource, {
|
|
197
|
+
format: "json",
|
|
198
|
+
currentTaskId: options.currentTaskId || parsed.latestCheckpoint.currentPacket?.id,
|
|
199
|
+
completedPacketIds:
|
|
200
|
+
options.completedPacketIds != null
|
|
201
|
+
? options.completedPacketIds
|
|
202
|
+
: (parsed.latestCheckpoint.completedPackets || []).map((packet) => packet.id).join(","),
|
|
203
|
+
blockedReasons:
|
|
204
|
+
options.blockedReasons != null
|
|
205
|
+
? options.blockedReasons
|
|
206
|
+
: (parsed.latestCheckpoint.blockedItems || []).map((item) => item.title).join(",")
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
reuseLog: null,
|
|
211
|
+
checkpoint
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
} catch {
|
|
215
|
+
// Fall through to checkpoint generation.
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
reuseLog: null,
|
|
221
|
+
checkpoint: await createAgentCheckpoint(input, {
|
|
222
|
+
format: "json",
|
|
223
|
+
currentTaskId: options.currentTaskId,
|
|
224
|
+
completedPacketIds: options.completedPacketIds,
|
|
225
|
+
blockedReasons: options.blockedReasons
|
|
226
|
+
})
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export async function createAgentDecisionLog(input, options = {}) {
|
|
231
|
+
const format = normalizeFormat(options.format);
|
|
232
|
+
const existing = await resolveExistingLog(options);
|
|
233
|
+
const { reuseLog, checkpoint } = await resolveCheckpoint(input, {
|
|
234
|
+
...options,
|
|
235
|
+
format: "json"
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
if (reuseLog) {
|
|
239
|
+
return reuseLog;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (!checkpoint) {
|
|
243
|
+
throw new Error("无法从当前输入生成 agent checkpoint,因此不能创建 decision log。");
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const note = buildDecisionNote(options);
|
|
247
|
+
const previousEntries = existing?.log?.entries || [];
|
|
248
|
+
const entries = [
|
|
249
|
+
...previousEntries,
|
|
250
|
+
buildEntry(checkpoint, note, previousEntries.length + 1)
|
|
251
|
+
];
|
|
252
|
+
|
|
253
|
+
const log = {
|
|
254
|
+
kind: "geo-agent-decision-log",
|
|
255
|
+
input,
|
|
256
|
+
source: checkpoint.source,
|
|
257
|
+
sourceType: checkpoint.sourceType,
|
|
258
|
+
artifactKind: checkpoint.kind,
|
|
259
|
+
format,
|
|
260
|
+
updatedAt: new Date().toISOString(),
|
|
261
|
+
totalEntries: entries.length,
|
|
262
|
+
latestDecision: checkpoint.decision,
|
|
263
|
+
latestDecisionReason: checkpoint.decisionReason,
|
|
264
|
+
latestCheckpointType: checkpoint.checkpointType,
|
|
265
|
+
latestBoardStatus: checkpoint.boardStatus,
|
|
266
|
+
currentPacket: checkpoint.currentPacket,
|
|
267
|
+
nextPacket: checkpoint.nextPacket,
|
|
268
|
+
openBlockers: checkpoint.blockedItems,
|
|
269
|
+
recommendedFocus: buildRecommendedFocus(checkpoint),
|
|
270
|
+
logSummary: buildLogSummary(entries, checkpoint),
|
|
271
|
+
suggestedNextCommand: checkpoint.suggestedNextCommand,
|
|
272
|
+
alternateCommands: checkpoint.alternateCommands,
|
|
273
|
+
entries,
|
|
274
|
+
latestCheckpoint: checkpoint,
|
|
275
|
+
logPrompt: ""
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
log.logPrompt = buildLogPrompt(log);
|
|
279
|
+
return log;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export function renderAgentDecisionLogMarkdown(log) {
|
|
283
|
+
const lines = [
|
|
284
|
+
"# GEO Agent Decision Log",
|
|
285
|
+
"",
|
|
286
|
+
`- 输入:\`${log.source}\``,
|
|
287
|
+
`- 来源类型:\`${log.sourceType}\``,
|
|
288
|
+
`- 最新工件类型:\`${log.artifactKind}\``,
|
|
289
|
+
`- 决策次数:\`${log.totalEntries}\``,
|
|
290
|
+
`- 最新检查点类型:\`${log.latestCheckpointType}\``,
|
|
291
|
+
`- 最新状态:\`${log.latestBoardStatus}\``,
|
|
292
|
+
`- 最新决策:\`${log.latestDecision}\``,
|
|
293
|
+
`- 当前重点:${log.recommendedFocus}`,
|
|
294
|
+
`- 总结:${log.logSummary}`,
|
|
295
|
+
""
|
|
296
|
+
];
|
|
297
|
+
|
|
298
|
+
if (log.currentPacket) {
|
|
299
|
+
lines.push("## 当前包", "", `- ${log.currentPacket.id}|${log.currentPacket.title}`);
|
|
300
|
+
lines.push(`- Owner:${log.currentPacket.owner}`);
|
|
301
|
+
lines.push(`- 优先级:${log.currentPacket.priority}`);
|
|
302
|
+
lines.push("");
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (log.nextPacket) {
|
|
306
|
+
lines.push("## 下一包", "", `- ${log.nextPacket.id}|${log.nextPacket.title}`);
|
|
307
|
+
lines.push(`- Owner:${log.nextPacket.owner}`);
|
|
308
|
+
lines.push(`- 优先级:${log.nextPacket.priority}`);
|
|
309
|
+
lines.push("");
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
lines.push("## 当前阻塞", "");
|
|
313
|
+
if (log.openBlockers.length === 0) {
|
|
314
|
+
lines.push("- 当前没有阻塞。", "");
|
|
315
|
+
} else {
|
|
316
|
+
for (const blocker of log.openBlockers) {
|
|
317
|
+
lines.push(`- ${blocker.id}|${blocker.title}`);
|
|
318
|
+
lines.push(` - Owner:${blocker.owner}`);
|
|
319
|
+
lines.push(` - 优先级:${blocker.priority}`);
|
|
320
|
+
}
|
|
321
|
+
lines.push("");
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
lines.push("## 决策时间线", "");
|
|
325
|
+
for (const entry of [...log.entries].reverse()) {
|
|
326
|
+
lines.push(`### ${entry.id}`);
|
|
327
|
+
lines.push("");
|
|
328
|
+
lines.push(`- 时间:\`${entry.createdAt}\``);
|
|
329
|
+
lines.push(`- 检查点类型:\`${entry.checkpointType}\``);
|
|
330
|
+
lines.push(`- 决策:\`${entry.decision}\``);
|
|
331
|
+
lines.push(`- 状态:\`${entry.boardStatus}\``);
|
|
332
|
+
lines.push(`- 进度:\`${entry.progressPercent}%\``);
|
|
333
|
+
lines.push(`- 原因:${entry.decisionReason}`);
|
|
334
|
+
if (entry.currentPacket) {
|
|
335
|
+
lines.push(`- 当前包:${entry.currentPacket.id}|${entry.currentPacket.title}`);
|
|
336
|
+
}
|
|
337
|
+
if (entry.nextPacket) {
|
|
338
|
+
lines.push(`- 下一包:${entry.nextPacket.id}|${entry.nextPacket.title}`);
|
|
339
|
+
}
|
|
340
|
+
if (entry.blockedItems.length > 0) {
|
|
341
|
+
lines.push(`- 阻塞:${entry.blockedItems.map((item) => item.title).join(";")}`);
|
|
342
|
+
}
|
|
343
|
+
if (entry.note) {
|
|
344
|
+
lines.push(`- 备注:${entry.note}`);
|
|
345
|
+
}
|
|
346
|
+
lines.push(`- 建议命令:\`${entry.suggestedNextCommand}\``);
|
|
347
|
+
lines.push(`- 交接说明:${entry.handoffNote}`);
|
|
348
|
+
lines.push("");
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
lines.push("## 建议下一步命令", "", `- \`${log.suggestedNextCommand}\``);
|
|
352
|
+
|
|
353
|
+
if (log.alternateCommands.length > 0) {
|
|
354
|
+
lines.push("", "## 备选命令", "");
|
|
355
|
+
for (const command of log.alternateCommands) {
|
|
356
|
+
lines.push(`- \`${command}\``);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
lines.push("", "## 最新检查点", "", "```text", log.latestCheckpoint.checkpointPrompt, "```");
|
|
361
|
+
lines.push("", "## 可直接复制给 Agent 的 Decision Log Prompt", "", "```text", log.logPrompt, "```");
|
|
362
|
+
|
|
363
|
+
return `${lines.join("\n")}\n`;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export async function writeAgentDecisionLogOutput(outputPath, content) {
|
|
367
|
+
return writeScanOutput(outputPath, content);
|
|
368
|
+
}
|
|
@@ -134,6 +134,76 @@ function buildExecutionContextFromParsedArtifact(parsed, input) {
|
|
|
134
134
|
};
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
if (parsed?.kind === "geo-agent-checkpoint" && parsed.statusBoard?.tracker?.applyPlan?.kind === "geo-apply-plan") {
|
|
138
|
+
return {
|
|
139
|
+
source:
|
|
140
|
+
parsed.source ||
|
|
141
|
+
parsed.statusBoard.source ||
|
|
142
|
+
parsed.statusBoard.tracker.source ||
|
|
143
|
+
parsed.statusBoard.tracker.applyPlan.source ||
|
|
144
|
+
input,
|
|
145
|
+
sourceType:
|
|
146
|
+
parsed.sourceType ||
|
|
147
|
+
parsed.statusBoard.sourceType ||
|
|
148
|
+
parsed.statusBoard.tracker.sourceType ||
|
|
149
|
+
parsed.statusBoard.tracker.applyPlan.sourceType ||
|
|
150
|
+
"json",
|
|
151
|
+
artifactKind: parsed.kind,
|
|
152
|
+
applyPlan: parsed.statusBoard.tracker.applyPlan,
|
|
153
|
+
trackerState: {
|
|
154
|
+
currentTaskId:
|
|
155
|
+
parsed.currentPacket?.id ||
|
|
156
|
+
parsed.statusBoard.tracker.currentTaskId ||
|
|
157
|
+
parsed.statusBoard.tracker.activePacket?.id ||
|
|
158
|
+
null,
|
|
159
|
+
completedPacketIds:
|
|
160
|
+
parsed.statusBoard.tracker.completedPacketIds ||
|
|
161
|
+
parsed.completedPackets?.map((packet) => packet.id) ||
|
|
162
|
+
[],
|
|
163
|
+
blockedReasons:
|
|
164
|
+
parsed.statusBoard.tracker.blockedReasons ||
|
|
165
|
+
parsed.blockedItems?.map((item) => item.title) ||
|
|
166
|
+
[]
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (parsed?.kind === "geo-agent-decision-log" && parsed.latestCheckpoint?.statusBoard?.tracker?.applyPlan?.kind === "geo-apply-plan") {
|
|
172
|
+
return {
|
|
173
|
+
source:
|
|
174
|
+
parsed.source ||
|
|
175
|
+
parsed.latestCheckpoint.source ||
|
|
176
|
+
parsed.latestCheckpoint.statusBoard.source ||
|
|
177
|
+
parsed.latestCheckpoint.statusBoard.tracker.source ||
|
|
178
|
+
parsed.latestCheckpoint.statusBoard.tracker.applyPlan.source ||
|
|
179
|
+
input,
|
|
180
|
+
sourceType:
|
|
181
|
+
parsed.sourceType ||
|
|
182
|
+
parsed.latestCheckpoint.sourceType ||
|
|
183
|
+
parsed.latestCheckpoint.statusBoard.sourceType ||
|
|
184
|
+
parsed.latestCheckpoint.statusBoard.tracker.sourceType ||
|
|
185
|
+
parsed.latestCheckpoint.statusBoard.tracker.applyPlan.sourceType ||
|
|
186
|
+
"json",
|
|
187
|
+
artifactKind: parsed.kind,
|
|
188
|
+
applyPlan: parsed.latestCheckpoint.statusBoard.tracker.applyPlan,
|
|
189
|
+
trackerState: {
|
|
190
|
+
currentTaskId:
|
|
191
|
+
parsed.latestCheckpoint.currentPacket?.id ||
|
|
192
|
+
parsed.latestCheckpoint.statusBoard.tracker.currentTaskId ||
|
|
193
|
+
parsed.latestCheckpoint.statusBoard.tracker.activePacket?.id ||
|
|
194
|
+
null,
|
|
195
|
+
completedPacketIds:
|
|
196
|
+
parsed.latestCheckpoint.statusBoard.tracker.completedPacketIds ||
|
|
197
|
+
parsed.latestCheckpoint.completedPackets?.map((packet) => packet.id) ||
|
|
198
|
+
[],
|
|
199
|
+
blockedReasons:
|
|
200
|
+
parsed.latestCheckpoint.statusBoard.tracker.blockedReasons ||
|
|
201
|
+
parsed.latestCheckpoint.blockedItems?.map((item) => item.title) ||
|
|
202
|
+
[]
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
137
207
|
if (parsed?.kind === "geo-completion-report") {
|
|
138
208
|
return {
|
|
139
209
|
source: parsed.source || input,
|
package/src/agent-session.js
CHANGED
|
@@ -61,6 +61,12 @@ function inferSkillForCommand(commandName, flow) {
|
|
|
61
61
|
if (commandName === "agent-status-board") {
|
|
62
62
|
return "geo-ai-search-optimization-agent-status-board";
|
|
63
63
|
}
|
|
64
|
+
if (commandName === "agent-checkpoint") {
|
|
65
|
+
return "geo-ai-search-optimization-agent-checkpoint";
|
|
66
|
+
}
|
|
67
|
+
if (commandName === "agent-decision-log") {
|
|
68
|
+
return "geo-ai-search-optimization-agent-decision-log";
|
|
69
|
+
}
|
|
64
70
|
if (commandName === "skills" || commandName === "quick-start") {
|
|
65
71
|
return "geo-ai-search-optimization-usage";
|
|
66
72
|
}
|
|
@@ -131,6 +137,10 @@ function inferStepPurpose(commandName, flow) {
|
|
|
131
137
|
return "追踪当前做到第几包、卡点在哪里,以及下一包该推进什么。";
|
|
132
138
|
case "agent-status-board":
|
|
133
139
|
return "把当前执行状态整理成 PM 和 agent 都能直接消费的分栏看板。";
|
|
140
|
+
case "agent-checkpoint":
|
|
141
|
+
return "把当前阶段压成继续 / 阻塞 / 收尾的决策检查点。";
|
|
142
|
+
case "agent-decision-log":
|
|
143
|
+
return "把每一轮 checkpoint 沉淀成可继承的决策历史。";
|
|
134
144
|
case "apply-plan":
|
|
135
145
|
return "把交接结果推进到具体执行包。";
|
|
136
146
|
case "completion-report":
|
|
@@ -181,6 +191,10 @@ function inferExpectedArtifact(commandName) {
|
|
|
181
191
|
return "agent 执行进度追踪工件";
|
|
182
192
|
case "agent-status-board":
|
|
183
193
|
return "agent 执行状态看板";
|
|
194
|
+
case "agent-checkpoint":
|
|
195
|
+
return "agent 阶段检查点工件";
|
|
196
|
+
case "agent-decision-log":
|
|
197
|
+
return "agent 决策历史工件";
|
|
184
198
|
case "apply-plan":
|
|
185
199
|
return "执行包";
|
|
186
200
|
case "completion-report":
|
|
@@ -228,6 +242,12 @@ function buildStepInstructions(parsedCommand, flow) {
|
|
|
228
242
|
if (parsedCommand.commandName === "agent-status-board") {
|
|
229
243
|
lines.push("这一步用于把当前执行状态转成看板视图,方便 PM 和 agent 对齐当前阶段。");
|
|
230
244
|
}
|
|
245
|
+
if (parsedCommand.commandName === "agent-checkpoint") {
|
|
246
|
+
lines.push("这一步用于明确此刻应该继续、先解除阻塞,还是进入收尾。");
|
|
247
|
+
}
|
|
248
|
+
if (parsedCommand.commandName === "agent-decision-log") {
|
|
249
|
+
lines.push("这一步用于保留跨轮决策历史,方便下一位 agent 直接承接上一次判断。");
|
|
250
|
+
}
|
|
231
251
|
if (parsedCommand.commandName === "agent-handoff" && flow.intent === "execute") {
|
|
232
252
|
lines.push("如果还是 advice-only,说明还缺仓库或本地项目上下文。");
|
|
233
253
|
}
|
|
@@ -139,6 +139,41 @@ async function resolveTracker(input, options = {}) {
|
|
|
139
139
|
options.blockedReasons != null ? options.blockedReasons : (parsed.tracker.blockedReasons || []).join(",")
|
|
140
140
|
});
|
|
141
141
|
}
|
|
142
|
+
if (parsed?.kind === "geo-agent-checkpoint" && parsed.statusBoard?.tracker?.kind === "geo-agent-progress-tracker") {
|
|
143
|
+
return createAgentProgressTracker(parsed.statusBoard.tracker.source || input, {
|
|
144
|
+
format: "json",
|
|
145
|
+
currentTaskId:
|
|
146
|
+
options.currentTaskId || parsed.currentPacket?.id || parsed.statusBoard.tracker.currentTaskId,
|
|
147
|
+
completedPacketIds:
|
|
148
|
+
options.completedPacketIds != null
|
|
149
|
+
? options.completedPacketIds
|
|
150
|
+
: (parsed.statusBoard.tracker.completedPacketIds || []).join(","),
|
|
151
|
+
blockedReasons:
|
|
152
|
+
options.blockedReasons != null
|
|
153
|
+
? options.blockedReasons
|
|
154
|
+
: (parsed.statusBoard.tracker.blockedReasons || []).join(",")
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (parsed?.kind === "geo-agent-decision-log" && parsed.latestCheckpoint?.statusBoard?.tracker?.kind === "geo-agent-progress-tracker") {
|
|
158
|
+
return createAgentProgressTracker(
|
|
159
|
+
parsed.latestCheckpoint.statusBoard.tracker.source || parsed.latestCheckpoint.source || input,
|
|
160
|
+
{
|
|
161
|
+
format: "json",
|
|
162
|
+
currentTaskId:
|
|
163
|
+
options.currentTaskId ||
|
|
164
|
+
parsed.latestCheckpoint.currentPacket?.id ||
|
|
165
|
+
parsed.latestCheckpoint.statusBoard.tracker.currentTaskId,
|
|
166
|
+
completedPacketIds:
|
|
167
|
+
options.completedPacketIds != null
|
|
168
|
+
? options.completedPacketIds
|
|
169
|
+
: (parsed.latestCheckpoint.statusBoard.tracker.completedPacketIds || []).join(","),
|
|
170
|
+
blockedReasons:
|
|
171
|
+
options.blockedReasons != null
|
|
172
|
+
? options.blockedReasons
|
|
173
|
+
: (parsed.latestCheckpoint.statusBoard.tracker.blockedReasons || []).join(",")
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
}
|
|
142
177
|
} catch {
|
|
143
178
|
// Fall through to tracker generation
|
|
144
179
|
}
|
package/src/auto-flow.js
CHANGED
|
@@ -53,6 +53,12 @@ function inferTaskTextMode(text) {
|
|
|
53
53
|
if (/(status-board|status board|状态看板|执行看板|看板视图|board 视图)/i.test(normalized)) {
|
|
54
54
|
return "execute";
|
|
55
55
|
}
|
|
56
|
+
if (/(checkpoint|检查点|阶段检查点|继续还是收尾|解除阻塞还是继续)/i.test(normalized)) {
|
|
57
|
+
return "execute";
|
|
58
|
+
}
|
|
59
|
+
if (/(decision-log|decision log|决策历史|决策日志|为什么这样决定|历史决策)/i.test(normalized)) {
|
|
60
|
+
return "execute";
|
|
61
|
+
}
|
|
56
62
|
if (/(executor|先做哪一个|先做哪一包|single task|执行第一包|先执行一个任务)/i.test(normalized)) {
|
|
57
63
|
return "execute";
|
|
58
64
|
}
|
|
@@ -173,6 +179,8 @@ function resolveEffectiveIntent(intent, detected) {
|
|
|
173
179
|
"geo-agent-batch-executor",
|
|
174
180
|
"geo-agent-progress-tracker",
|
|
175
181
|
"geo-agent-status-board",
|
|
182
|
+
"geo-agent-checkpoint",
|
|
183
|
+
"geo-agent-decision-log",
|
|
176
184
|
"geo-apply-plan",
|
|
177
185
|
"geo-handoff-bundle",
|
|
178
186
|
"geo-fix-plan"
|
|
@@ -351,6 +359,50 @@ function buildCommandChain(detected, intent) {
|
|
|
351
359
|
`geo-ai-search-optimization completion-report ${source}`,
|
|
352
360
|
`geo-ai-search-optimization handoff-bundle ${source}`
|
|
353
361
|
];
|
|
362
|
+
case "geo-agent-checkpoint":
|
|
363
|
+
return detected.parsed?.decision === "move-to-closeout"
|
|
364
|
+
? [
|
|
365
|
+
`geo-ai-search-optimization completion-report ${source}`,
|
|
366
|
+
`geo-ai-search-optimization handoff-bundle ${source}`,
|
|
367
|
+
`geo-ai-search-optimization publish-pack ${source}`
|
|
368
|
+
]
|
|
369
|
+
: detected.parsed?.decision === "resolve-blockers"
|
|
370
|
+
? [
|
|
371
|
+
detected.parsed.suggestedNextCommand || `geo-ai-search-optimization agent-runbook ${source}`,
|
|
372
|
+
`geo-ai-search-optimization agent-status-board ${source}`,
|
|
373
|
+
`geo-ai-search-optimization agent-progress-tracker ${source}`
|
|
374
|
+
]
|
|
375
|
+
: [
|
|
376
|
+
detected.parsed?.suggestedNextCommand || `geo-ai-search-optimization agent-executor ${source}`,
|
|
377
|
+
`geo-ai-search-optimization agent-progress-tracker ${source}`,
|
|
378
|
+
`geo-ai-search-optimization completion-report ${source}`
|
|
379
|
+
];
|
|
380
|
+
case "geo-agent-decision-log": {
|
|
381
|
+
const baseSource = detected.parsed?.latestCheckpoint?.source || detected.parsed?.source || source;
|
|
382
|
+
const latestDecision = detected.parsed?.latestDecision;
|
|
383
|
+
const suggestedNext =
|
|
384
|
+
detected.parsed?.suggestedNextCommand ||
|
|
385
|
+
detected.parsed?.latestCheckpoint?.suggestedNextCommand ||
|
|
386
|
+
`geo-ai-search-optimization agent-executor ${baseSource}`;
|
|
387
|
+
|
|
388
|
+
return latestDecision === "move-to-closeout"
|
|
389
|
+
? [
|
|
390
|
+
`geo-ai-search-optimization completion-report ${baseSource}`,
|
|
391
|
+
`geo-ai-search-optimization handoff-bundle ${baseSource}`,
|
|
392
|
+
`geo-ai-search-optimization publish-pack ${baseSource}`
|
|
393
|
+
]
|
|
394
|
+
: latestDecision === "resolve-blockers"
|
|
395
|
+
? [
|
|
396
|
+
suggestedNext,
|
|
397
|
+
`geo-ai-search-optimization agent-status-board ${source}`,
|
|
398
|
+
`geo-ai-search-optimization agent-decision-log ${baseSource} --append-from ${source}`
|
|
399
|
+
]
|
|
400
|
+
: [
|
|
401
|
+
suggestedNext,
|
|
402
|
+
`geo-ai-search-optimization agent-progress-tracker ${source}`,
|
|
403
|
+
`geo-ai-search-optimization agent-decision-log ${baseSource} --append-from ${source}`
|
|
404
|
+
];
|
|
405
|
+
}
|
|
354
406
|
case "geo-apply-plan":
|
|
355
407
|
return [
|
|
356
408
|
`geo-ai-search-optimization agent-executor ${source}`,
|
|
@@ -430,6 +482,10 @@ function pickSkillName(detected, intent) {
|
|
|
430
482
|
return "geo-ai-search-optimization-agent-progress-tracker";
|
|
431
483
|
case "geo-agent-status-board":
|
|
432
484
|
return "geo-ai-search-optimization-agent-status-board";
|
|
485
|
+
case "geo-agent-checkpoint":
|
|
486
|
+
return "geo-ai-search-optimization-agent-checkpoint";
|
|
487
|
+
case "geo-agent-decision-log":
|
|
488
|
+
return "geo-ai-search-optimization-agent-decision-log";
|
|
433
489
|
case "geo-completion-report":
|
|
434
490
|
return "geo-ai-search-optimization-completion-report";
|
|
435
491
|
case "geo-handoff-bundle":
|
|
@@ -469,6 +525,8 @@ function buildSecondarySkillNames(primarySkill, intent, detected) {
|
|
|
469
525
|
"geo-agent-batch-executor",
|
|
470
526
|
"geo-agent-progress-tracker",
|
|
471
527
|
"geo-agent-status-board",
|
|
528
|
+
"geo-agent-checkpoint",
|
|
529
|
+
"geo-agent-decision-log",
|
|
472
530
|
"geo-apply-plan"
|
|
473
531
|
].includes(
|
|
474
532
|
detected.artifactKind
|
|
@@ -477,6 +535,8 @@ function buildSecondarySkillNames(primarySkill, intent, detected) {
|
|
|
477
535
|
names.add("geo-ai-search-optimization-agent-batch-executor");
|
|
478
536
|
names.add("geo-ai-search-optimization-agent-progress-tracker");
|
|
479
537
|
names.add("geo-ai-search-optimization-agent-status-board");
|
|
538
|
+
names.add("geo-ai-search-optimization-agent-checkpoint");
|
|
539
|
+
names.add("geo-ai-search-optimization-agent-decision-log");
|
|
480
540
|
names.add("geo-ai-search-optimization-agent-executor");
|
|
481
541
|
names.add("geo-ai-search-optimization-agent-runbook");
|
|
482
542
|
names.add("geo-ai-search-optimization-agent-handoff");
|
|
@@ -509,6 +569,8 @@ function buildStage(intent, detected) {
|
|
|
509
569
|
"geo-agent-batch-executor",
|
|
510
570
|
"geo-agent-progress-tracker",
|
|
511
571
|
"geo-agent-status-board",
|
|
572
|
+
"geo-agent-checkpoint",
|
|
573
|
+
"geo-agent-decision-log",
|
|
512
574
|
"geo-apply-plan",
|
|
513
575
|
"geo-handoff-bundle"
|
|
514
576
|
].includes(detected.artifactKind)
|
|
@@ -524,6 +586,8 @@ function buildStage(intent, detected) {
|
|
|
524
586
|
"geo-agent-batch-executor",
|
|
525
587
|
"geo-agent-progress-tracker",
|
|
526
588
|
"geo-agent-status-board",
|
|
589
|
+
"geo-agent-checkpoint",
|
|
590
|
+
"geo-agent-decision-log",
|
|
527
591
|
"geo-apply-plan",
|
|
528
592
|
"geo-handoff-bundle"
|
|
529
593
|
].includes(detected.artifactKind)
|
|
@@ -613,6 +677,9 @@ function buildNextAction(detected, intent, commands) {
|
|
|
613
677
|
if (detected.artifactKind === "geo-agent-progress-tracker") {
|
|
614
678
|
return `先运行 \`${commands[0]}\`,继续当前执行包或校准下一包。`;
|
|
615
679
|
}
|
|
680
|
+
if (detected.artifactKind === "geo-agent-decision-log") {
|
|
681
|
+
return `先运行 \`${commands[0]}\`,沿着最近一次阶段决策继续推进,而不是重新判断整条链。`;
|
|
682
|
+
}
|
|
616
683
|
return `先运行 \`${commands[0]}\`,把当前输入推进到 agent 可执行状态。`;
|
|
617
684
|
}
|
|
618
685
|
if (intent === "closeout") {
|