geo-ai-search-optimization 1.2.11 → 1.2.12
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 +29 -0
- package/package.json +1 -1
- package/resources/geo-ai-search-optimization/references/skill-bundle-map.md +10 -0
- package/resources/geo-ai-search-optimization-agent-progress-tracker/SKILL.md +23 -0
- package/resources/geo-ai-search-optimization-agent-progress-tracker/agents/openai.yaml +4 -0
- package/resources/geo-ai-search-optimization-usage/SKILL.md +19 -14
- package/src/agent-progress-tracker.js +482 -0
- package/src/agent-session.js +10 -0
- package/src/auto-flow.js +40 -1
- package/src/cli.js +39 -0
- package/src/index.js +5 -0
- package/src/skills.js +3 -0
package/README.md
CHANGED
|
@@ -145,6 +145,26 @@ geo-ai-search-optimization agent-batch-executor ./reports/apply-plan.json --task
|
|
|
145
145
|
- 批次收尾命令
|
|
146
146
|
- 可直接复制给 agent 的 batch prompt
|
|
147
147
|
|
|
148
|
+
## Agent Progress Tracker 命令
|
|
149
|
+
|
|
150
|
+
如果你希望 agent 不是只拿到执行队列,而是能够明确回答“现在做到第几包、当前卡在哪、下一包是什么”,可以直接用 `agent-progress-tracker`:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
geo-ai-search-optimization agent-progress-tracker ./your-site
|
|
154
|
+
geo-ai-search-optimization agent-progress-tracker ./reports/apply-plan.json --completed fix-01,fix-02 --current fix-03
|
|
155
|
+
geo-ai-search-optimization agent-progress-tracker ./reports/agent-batch-executor.json --blocked "缺少仓库权限,缺少模板文件" --format json --out ./reports/agent-progress-tracker.json
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`agent-progress-tracker` 会输出:
|
|
159
|
+
|
|
160
|
+
- 当前状态是未开始、进行中、阻塞还是已完成
|
|
161
|
+
- 已完成到哪几包
|
|
162
|
+
- 当前正在推进哪一包
|
|
163
|
+
- 下一包是什么
|
|
164
|
+
- 当前阻塞项
|
|
165
|
+
- 建议下一步命令
|
|
166
|
+
- 可直接复制给 agent 的 progress prompt
|
|
167
|
+
|
|
148
168
|
## Quick Start
|
|
149
169
|
|
|
150
170
|
如果你要从 0 到 1 启动一个 GEO 项目,建议照这个顺序做。
|
|
@@ -543,6 +563,7 @@ geo-ai-search-optimization agent-session ./your-site
|
|
|
543
563
|
geo-ai-search-optimization agent-runbook ./your-site
|
|
544
564
|
geo-ai-search-optimization agent-executor ./your-site
|
|
545
565
|
geo-ai-search-optimization agent-batch-executor ./your-site
|
|
566
|
+
geo-ai-search-optimization agent-progress-tracker ./your-site
|
|
546
567
|
geo-ai-search-optimization skills
|
|
547
568
|
geo-ai-search-optimization where
|
|
548
569
|
geo-ai-search-optimization doctor
|
|
@@ -613,6 +634,13 @@ geo-ai-search-optimization help
|
|
|
613
634
|
- 输出 do-now checklist、stop checklist、success checklist、验证命令和回报模板
|
|
614
635
|
- 新增 `geo-ai-search-optimization-agent-executor` skill
|
|
615
636
|
|
|
637
|
+
## New in 1.2.12
|
|
638
|
+
|
|
639
|
+
- 新增 `agent-progress-tracker` 命令
|
|
640
|
+
- 可以从 `apply-plan`、`agent-executor`、`agent-batch-executor` 等工件推导当前执行进度
|
|
641
|
+
- 输出已完成任务、当前包、下一包、阻塞项和建议下一步命令
|
|
642
|
+
- 新增 `geo-ai-search-optimization-agent-progress-tracker` skill
|
|
643
|
+
|
|
616
644
|
## New in 1.2.11
|
|
617
645
|
|
|
618
646
|
- 新增 `agent-batch-executor` 命令
|
|
@@ -811,6 +839,7 @@ The installed package now includes a bundled GEO skill pack, including:
|
|
|
811
839
|
- `geo-ai-search-optimization-agent-runbook`
|
|
812
840
|
- `geo-ai-search-optimization-agent-executor`
|
|
813
841
|
- `geo-ai-search-optimization-agent-batch-executor`
|
|
842
|
+
- `geo-ai-search-optimization-agent-progress-tracker`
|
|
814
843
|
- `geo-ai-search-optimization-usage`
|
|
815
844
|
- `geo-ai-search-optimization-agent-handoff`
|
|
816
845
|
- `geo-ai-search-optimization-repair-loop`
|
package/package.json
CHANGED
|
@@ -72,6 +72,16 @@ Best for:
|
|
|
72
72
|
- making the next agent finish packet 1 before packet 2 starts
|
|
73
73
|
- giving the next agent a batch-level prompt, per-packet checklists, and final closeout commands
|
|
74
74
|
|
|
75
|
+
### `geo-ai-search-optimization-agent-progress-tracker`
|
|
76
|
+
|
|
77
|
+
Use this when the next agent should explain current execution status, not just produce the next queue.
|
|
78
|
+
|
|
79
|
+
Best for:
|
|
80
|
+
|
|
81
|
+
- showing which packet is already done
|
|
82
|
+
- clarifying the current active packet and the next packet
|
|
83
|
+
- surfacing blockers before the team moves into closeout or the next batch
|
|
84
|
+
|
|
75
85
|
## Usage guide
|
|
76
86
|
|
|
77
87
|
### `geo-ai-search-optimization-usage`
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: geo-ai-search-optimization-agent-progress-tracker
|
|
3
|
+
description: Track GEO execution progress from apply-plan, agent-executor, agent-batch-executor, completion-report, or related artifacts. Use when an agent should explain which GEO packet is already done, which one is active, what is blocked, and what command should run next.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GEO Agent Progress Tracker
|
|
7
|
+
|
|
8
|
+
Use this skill when the next agent should stop guessing current status and make the execution state explicit.
|
|
9
|
+
|
|
10
|
+
`GEO = Generative Engine Optimization`
|
|
11
|
+
|
|
12
|
+
## What it does
|
|
13
|
+
|
|
14
|
+
- reads GEO execution artifacts and infers the current packet state
|
|
15
|
+
- shows completed packets, the active packet, the next packet, and blockers
|
|
16
|
+
- recommends the next command for continuing or closing out the work
|
|
17
|
+
- gives the next agent a progress-tracking prompt instead of another open-ended plan
|
|
18
|
+
|
|
19
|
+
## Best use
|
|
20
|
+
|
|
21
|
+
- when a PM asks “现在做到哪了?”
|
|
22
|
+
- when the next agent should explain status before touching the next packet
|
|
23
|
+
- when batch execution is underway and the team needs a stable progress checkpoint
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "GEO Agent Progress Tracker"
|
|
3
|
+
short_description: "Track which GEO packet is done, active, or blocked"
|
|
4
|
+
default_prompt: "Use $geo-ai-search-optimization-agent-progress-tracker to explain GEO execution progress, blockers, the current packet, and the next command."
|
|
@@ -13,26 +13,27 @@ Treat this tool as a PM-friendly GEO workflow for websites.
|
|
|
13
13
|
|
|
14
14
|
`GEO = Generative Engine Optimization`
|
|
15
15
|
|
|
16
|
-
The package is best explained as
|
|
16
|
+
The package is best explained as nineteen layers:
|
|
17
17
|
|
|
18
18
|
1. `auto-flow`: auto-select the next skill and command chain
|
|
19
19
|
2. `agent-session`: build a runnable session for the next agent
|
|
20
20
|
3. `agent-runbook`: execution manual and checklist for the next agent
|
|
21
21
|
4. `agent-executor`: choose one packet to execute right now
|
|
22
22
|
5. `agent-batch-executor`: queue the first few packets, but still advance one packet at a time
|
|
23
|
-
6. `
|
|
24
|
-
7. `
|
|
25
|
-
8. `
|
|
26
|
-
9. `
|
|
27
|
-
10. `
|
|
28
|
-
11. `
|
|
29
|
-
12. `
|
|
30
|
-
13. `
|
|
31
|
-
14. `
|
|
32
|
-
15. `
|
|
33
|
-
16. `
|
|
34
|
-
17. `
|
|
35
|
-
18. `
|
|
23
|
+
6. `agent-progress-tracker`: track which packet is done, which one is active, and what comes next
|
|
24
|
+
7. `skills`: inspect the bundled skill package
|
|
25
|
+
8. `onboard-url` / `onboard`: first look
|
|
26
|
+
9. `scan`: raw signal check
|
|
27
|
+
10. `audit` / `report`: diagnosis
|
|
28
|
+
11. `fix-plan` / `owner-board`: execution planning
|
|
29
|
+
12. `agent-handoff`: agent takeover package
|
|
30
|
+
13. `apply-plan`: execution loop
|
|
31
|
+
14. `completion-report`: closeout
|
|
32
|
+
15. `handoff-bundle`: all-in-one package
|
|
33
|
+
16. `share-pack`: audience-ready delivery
|
|
34
|
+
17. `export-pack`: folder export
|
|
35
|
+
18. `html-pack` / `publish-pack`: browsable and final delivery output
|
|
36
|
+
19. `pm-brief` / `roadmap`: stakeholder alignment
|
|
36
37
|
|
|
37
38
|
## Recommended command order
|
|
38
39
|
|
|
@@ -44,6 +45,7 @@ npx geo-ai-search-optimization agent-session https://example.com
|
|
|
44
45
|
npx geo-ai-search-optimization agent-runbook https://example.com
|
|
45
46
|
npx geo-ai-search-optimization agent-executor https://example.com
|
|
46
47
|
npx geo-ai-search-optimization agent-batch-executor https://example.com
|
|
48
|
+
npx geo-ai-search-optimization agent-progress-tracker https://example.com
|
|
47
49
|
npx geo-ai-search-optimization onboard-url https://example.com
|
|
48
50
|
npx geo-ai-search-optimization pm-brief https://example.com
|
|
49
51
|
npx geo-ai-search-optimization roadmap https://example.com
|
|
@@ -57,6 +59,7 @@ npx geo-ai-search-optimization agent-session ./your-site
|
|
|
57
59
|
npx geo-ai-search-optimization agent-runbook ./your-site
|
|
58
60
|
npx geo-ai-search-optimization agent-executor ./your-site
|
|
59
61
|
npx geo-ai-search-optimization agent-batch-executor ./your-site
|
|
62
|
+
npx geo-ai-search-optimization agent-progress-tracker ./your-site
|
|
60
63
|
npx geo-ai-search-optimization scan ./your-site
|
|
61
64
|
npx geo-ai-search-optimization audit ./your-site
|
|
62
65
|
npx geo-ai-search-optimization fix-plan ./your-site
|
|
@@ -79,6 +82,7 @@ npx geo-ai-search-optimization roadmap ./your-site
|
|
|
79
82
|
- `agent-runbook`: build a checklist-driven runbook with preflight, validation, and reporting rules
|
|
80
83
|
- `agent-executor`: select one packet to execute now and package it into a single-task entrypoint
|
|
81
84
|
- `agent-batch-executor`: line up the first few packets in execution order while preserving one-packet-at-a-time discipline
|
|
85
|
+
- `agent-progress-tracker`: show execution progress, current packet, blockers, and the next packet to advance
|
|
82
86
|
- `onboard-url`: first-time website check from a live URL
|
|
83
87
|
- `onboard`: interactive first-time onboarding
|
|
84
88
|
- `skills`: list the bundled skills and decide which skill or command chain fits the task
|
|
@@ -108,6 +112,7 @@ When explaining the tool to a user:
|
|
|
108
112
|
- if the user wants the next agent to follow a checklist and execution manual, move them to `agent-runbook`
|
|
109
113
|
- if the user wants the next agent to start one concrete task now, move them to `agent-executor`
|
|
110
114
|
- if the user wants the next agent to continuously advance the first 2 to 3 packets in order, move them to `agent-batch-executor`
|
|
115
|
+
- if the user wants the next agent to explain current progress, blockers, and the next packet, move them to `agent-progress-tracker`
|
|
111
116
|
- explain the result in PM language, not implementation jargon
|
|
112
117
|
- if the user sounds new, start with `onboard-url` or `quick-start`
|
|
113
118
|
- if the user wants another agent to take over, move them to `agent-handoff`
|
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createApplyPlan } from "./apply-plan.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-progress-tracker 格式:${format}。可选值:${Array.from(VALID_FORMATS).join(", ")}`);
|
|
12
|
+
}
|
|
13
|
+
return resolved;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function parseCommaList(value) {
|
|
17
|
+
if (!value) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return String(value)
|
|
22
|
+
.split(",")
|
|
23
|
+
.map((item) => item.trim())
|
|
24
|
+
.filter(Boolean);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function pathExists(targetPath) {
|
|
28
|
+
try {
|
|
29
|
+
await fs.access(targetPath);
|
|
30
|
+
return true;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function isUrlInput(input) {
|
|
37
|
+
return /^https?:\/\//i.test(input);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function buildPseudoApplyPlanFromCompletionReport(report) {
|
|
41
|
+
return {
|
|
42
|
+
kind: "geo-apply-plan",
|
|
43
|
+
source: report.source,
|
|
44
|
+
sourceType: report.sourceType || "json",
|
|
45
|
+
executionType: report.executionType || "guided-planning",
|
|
46
|
+
executionMode: report.executionMode || "mixed",
|
|
47
|
+
selectedTaskCount: Array.isArray(report.nextRoundTasks) ? report.nextRoundTasks.length : 0,
|
|
48
|
+
packets: (report.nextRoundTasks || []).map((task) => {
|
|
49
|
+
const template = (report.completionTemplates || []).find((item) => item.id === task.id);
|
|
50
|
+
return {
|
|
51
|
+
id: task.id,
|
|
52
|
+
title: task.title,
|
|
53
|
+
owner: task.owner,
|
|
54
|
+
priority: "P1",
|
|
55
|
+
executionType: report.executionType || "guided-planning",
|
|
56
|
+
doneWhen: task.doneWhen || [],
|
|
57
|
+
validationCommands: report.validationChecklist || [],
|
|
58
|
+
completionTemplate: template?.template || ""
|
|
59
|
+
};
|
|
60
|
+
})
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function buildExecutionContextFromParsedArtifact(parsed, input) {
|
|
65
|
+
if (parsed?.kind === "geo-apply-plan") {
|
|
66
|
+
return {
|
|
67
|
+
source: parsed.source || input,
|
|
68
|
+
sourceType: parsed.sourceType || "json",
|
|
69
|
+
artifactKind: parsed.kind,
|
|
70
|
+
applyPlan: parsed,
|
|
71
|
+
trackerState: {}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (parsed?.kind === "geo-agent-runbook" && parsed.applyPlan?.kind === "geo-apply-plan") {
|
|
76
|
+
return {
|
|
77
|
+
source: parsed.source || parsed.applyPlan.source || input,
|
|
78
|
+
sourceType: parsed.sourceType || parsed.applyPlan.sourceType || "json",
|
|
79
|
+
artifactKind: parsed.kind,
|
|
80
|
+
applyPlan: parsed.applyPlan,
|
|
81
|
+
trackerState: {}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (parsed?.kind === "geo-agent-executor" && parsed.applyPlan?.kind === "geo-apply-plan") {
|
|
86
|
+
return {
|
|
87
|
+
source: parsed.source || parsed.applyPlan.source || input,
|
|
88
|
+
sourceType: parsed.sourceType || parsed.applyPlan.sourceType || "json",
|
|
89
|
+
artifactKind: parsed.kind,
|
|
90
|
+
applyPlan: parsed.applyPlan,
|
|
91
|
+
trackerState: {
|
|
92
|
+
currentTaskId: parsed.selectedPacket?.id || null
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (parsed?.kind === "geo-agent-batch-executor" && parsed.applyPlan?.kind === "geo-apply-plan") {
|
|
98
|
+
return {
|
|
99
|
+
source: parsed.source || parsed.applyPlan.source || input,
|
|
100
|
+
sourceType: parsed.sourceType || parsed.applyPlan.sourceType || "json",
|
|
101
|
+
artifactKind: parsed.kind,
|
|
102
|
+
applyPlan: parsed.applyPlan,
|
|
103
|
+
trackerState: {
|
|
104
|
+
currentTaskId: parsed.packetExecutors?.[0]?.id || null
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (parsed?.kind === "geo-agent-progress-tracker" && parsed.applyPlan?.kind === "geo-apply-plan") {
|
|
110
|
+
return {
|
|
111
|
+
source: parsed.source || parsed.applyPlan.source || input,
|
|
112
|
+
sourceType: parsed.sourceType || parsed.applyPlan.sourceType || "json",
|
|
113
|
+
artifactKind: parsed.kind,
|
|
114
|
+
applyPlan: parsed.applyPlan,
|
|
115
|
+
trackerState: {
|
|
116
|
+
currentTaskId: parsed.currentTaskId || parsed.activePacket?.id || null,
|
|
117
|
+
completedPacketIds: parsed.completedPacketIds || [],
|
|
118
|
+
blockedReasons: parsed.blockedReasons || []
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (parsed?.kind === "geo-completion-report") {
|
|
124
|
+
return {
|
|
125
|
+
source: parsed.source || input,
|
|
126
|
+
sourceType: parsed.sourceType || "json",
|
|
127
|
+
artifactKind: parsed.kind,
|
|
128
|
+
applyPlan: buildPseudoApplyPlanFromCompletionReport(parsed),
|
|
129
|
+
trackerState: {}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function resolveExecutionContext(input) {
|
|
137
|
+
if (!input) {
|
|
138
|
+
throw new Error("agent-progress-tracker 需要一个输入值,可以是项目路径、网站网址或已导出的 JSON 工件。");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (isUrlInput(input)) {
|
|
142
|
+
const applyPlan = await createApplyPlan(input, { format: "json" });
|
|
143
|
+
return {
|
|
144
|
+
source: applyPlan.source,
|
|
145
|
+
sourceType: applyPlan.sourceType,
|
|
146
|
+
artifactKind: applyPlan.kind,
|
|
147
|
+
applyPlan,
|
|
148
|
+
trackerState: {}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const resolvedPath = path.resolve(input);
|
|
153
|
+
if (!(await pathExists(resolvedPath))) {
|
|
154
|
+
const applyPlan = await createApplyPlan(input, { format: "json" });
|
|
155
|
+
return {
|
|
156
|
+
source: applyPlan.source,
|
|
157
|
+
sourceType: applyPlan.sourceType,
|
|
158
|
+
artifactKind: applyPlan.kind,
|
|
159
|
+
applyPlan,
|
|
160
|
+
trackerState: {}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const stat = await fs.stat(resolvedPath);
|
|
165
|
+
if (stat.isDirectory()) {
|
|
166
|
+
const applyPlan = await createApplyPlan(resolvedPath, { format: "json" });
|
|
167
|
+
return {
|
|
168
|
+
source: applyPlan.source,
|
|
169
|
+
sourceType: applyPlan.sourceType,
|
|
170
|
+
artifactKind: applyPlan.kind,
|
|
171
|
+
applyPlan,
|
|
172
|
+
trackerState: {}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (path.extname(resolvedPath).toLowerCase() === ".json") {
|
|
177
|
+
const raw = await fs.readFile(resolvedPath, "utf8");
|
|
178
|
+
const parsed = JSON.parse(raw);
|
|
179
|
+
const resolved = buildExecutionContextFromParsedArtifact(parsed, resolvedPath);
|
|
180
|
+
if (resolved) {
|
|
181
|
+
return resolved;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const applyPlan = await createApplyPlan(resolvedPath, { format: "json" });
|
|
186
|
+
return {
|
|
187
|
+
source: applyPlan.source,
|
|
188
|
+
sourceType: applyPlan.sourceType,
|
|
189
|
+
artifactKind: applyPlan.kind,
|
|
190
|
+
applyPlan,
|
|
191
|
+
trackerState: {}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function pickCompletedIds(packets, options, trackerState) {
|
|
196
|
+
const packetIds = new Set((packets || []).map((packet) => packet.id));
|
|
197
|
+
const requestedIds =
|
|
198
|
+
options.completedPacketIds != null ? parseCommaList(options.completedPacketIds) : trackerState.completedPacketIds || [];
|
|
199
|
+
|
|
200
|
+
return requestedIds.filter((id) => packetIds.has(id));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function pickCurrentTaskId(packets, completedIds, options, trackerState) {
|
|
204
|
+
const packetIds = new Set((packets || []).map((packet) => packet.id));
|
|
205
|
+
const completedSet = new Set(completedIds);
|
|
206
|
+
const requested = options.currentTaskId || trackerState.currentTaskId;
|
|
207
|
+
if (requested && packetIds.has(requested) && !completedSet.has(requested)) {
|
|
208
|
+
return requested;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const remaining = (packets || []).filter((packet) => !completedSet.has(packet.id));
|
|
212
|
+
return remaining[0]?.id || null;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function pickBlockedReasons(options, trackerState) {
|
|
216
|
+
if (options.blockedReasons != null) {
|
|
217
|
+
return parseCommaList(options.blockedReasons);
|
|
218
|
+
}
|
|
219
|
+
return trackerState.blockedReasons || [];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function inferTrackerStatus(totalPackets, completedCount, blockedReasons) {
|
|
223
|
+
if (blockedReasons.length > 0) {
|
|
224
|
+
return "blocked";
|
|
225
|
+
}
|
|
226
|
+
if (totalPackets === 0) {
|
|
227
|
+
return "needs-context";
|
|
228
|
+
}
|
|
229
|
+
if (completedCount === 0) {
|
|
230
|
+
return "not-started";
|
|
231
|
+
}
|
|
232
|
+
if (completedCount >= totalPackets) {
|
|
233
|
+
return "completed";
|
|
234
|
+
}
|
|
235
|
+
return "in-progress";
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function buildStatusSummary(status, activePacket, nextPacket, blockedReasons) {
|
|
239
|
+
switch (status) {
|
|
240
|
+
case "blocked":
|
|
241
|
+
return `当前已识别到阻塞,先处理这些问题再继续:${blockedReasons.join(";")}`;
|
|
242
|
+
case "needs-context":
|
|
243
|
+
return "当前还没有足够的执行包,说明需要先补上下文或重新生成 apply-plan。";
|
|
244
|
+
case "completed":
|
|
245
|
+
return "当前批次已全部完成,可以进入 completion-report 与交付收尾。";
|
|
246
|
+
case "in-progress":
|
|
247
|
+
return activePacket
|
|
248
|
+
? `当前正推进 ${activePacket.id},完成后继续 ${nextPacket?.id || "进入收尾阶段"}。`
|
|
249
|
+
: "当前已经开始执行,但还没有明确当前包,请先校准执行顺序。";
|
|
250
|
+
default:
|
|
251
|
+
return activePacket
|
|
252
|
+
? `当前尚未开始,建议先从 ${activePacket.id} 开始。`
|
|
253
|
+
: "当前尚未开始,先确认执行包和优先级。";
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function buildSuggestedNextCommand(source, status, activePacket, remainingPackets, blockedReasons) {
|
|
258
|
+
if (status === "blocked") {
|
|
259
|
+
if (activePacket) {
|
|
260
|
+
return `geo-ai-search-optimization agent-runbook ${source} --task ${activePacket.id}`;
|
|
261
|
+
}
|
|
262
|
+
return `geo-ai-search-optimization agent-session ${source}`;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (status === "completed") {
|
|
266
|
+
return `geo-ai-search-optimization completion-report ${source}`;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (activePacket) {
|
|
270
|
+
return `geo-ai-search-optimization agent-executor ${source} --task ${activePacket.id}`;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (remainingPackets.length > 1) {
|
|
274
|
+
return `geo-ai-search-optimization agent-batch-executor ${source}`;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (blockedReasons.length > 0) {
|
|
278
|
+
return `geo-ai-search-optimization agent-session ${source}`;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return `geo-ai-search-optimization apply-plan ${source}`;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function buildFollowupCommands(source, status, activePacket, nextPacket, remainingPackets) {
|
|
285
|
+
if (status === "completed") {
|
|
286
|
+
return [
|
|
287
|
+
`geo-ai-search-optimization handoff-bundle ${source}`,
|
|
288
|
+
`geo-ai-search-optimization publish-pack ${source}`
|
|
289
|
+
];
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const commands = [];
|
|
293
|
+
|
|
294
|
+
if (nextPacket) {
|
|
295
|
+
commands.push(`geo-ai-search-optimization agent-batch-executor ${source} --task ${nextPacket.id}`);
|
|
296
|
+
} else if (remainingPackets.length > 1) {
|
|
297
|
+
commands.push(`geo-ai-search-optimization agent-batch-executor ${source}`);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (activePacket) {
|
|
301
|
+
commands.push(`geo-ai-search-optimization agent-progress-tracker ${source} --current ${activePacket.id}`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
commands.push(`geo-ai-search-optimization completion-report ${source}`);
|
|
305
|
+
commands.push(`geo-ai-search-optimization handoff-bundle ${source}`);
|
|
306
|
+
return commands;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function buildTrackerPrompt(tracker) {
|
|
310
|
+
const lines = [
|
|
311
|
+
"你现在进入 GEO 执行进度追踪模式。",
|
|
312
|
+
`当前输入:${tracker.source}`,
|
|
313
|
+
`当前状态:${tracker.status}`,
|
|
314
|
+
`当前总结:${tracker.statusSummary}`,
|
|
315
|
+
`总任务包:${tracker.totalPackets}`,
|
|
316
|
+
`已完成:${tracker.completedCount}`,
|
|
317
|
+
`剩余:${tracker.remainingCount}`
|
|
318
|
+
];
|
|
319
|
+
|
|
320
|
+
if (tracker.activePacket) {
|
|
321
|
+
lines.push(`当前执行包:${tracker.activePacket.id}|${tracker.activePacket.title}`);
|
|
322
|
+
}
|
|
323
|
+
if (tracker.nextPacket) {
|
|
324
|
+
lines.push(`下一包:${tracker.nextPacket.id}|${tracker.nextPacket.title}`);
|
|
325
|
+
}
|
|
326
|
+
if (tracker.blockedReasons.length > 0) {
|
|
327
|
+
lines.push(`阻塞原因:${tracker.blockedReasons.join(";")}`);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
lines.push("请输出:");
|
|
331
|
+
lines.push("1. 当前已完成到哪");
|
|
332
|
+
lines.push("2. 当前卡点是什么");
|
|
333
|
+
lines.push("3. 现在该继续哪一包");
|
|
334
|
+
lines.push("4. 完成这一包后下一步是什么");
|
|
335
|
+
return lines.join("\n");
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function summarizePacket(packet) {
|
|
339
|
+
if (!packet) {
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return {
|
|
344
|
+
id: packet.id,
|
|
345
|
+
title: packet.title,
|
|
346
|
+
owner: packet.owner,
|
|
347
|
+
priority: packet.priority || "P1",
|
|
348
|
+
doneWhen: packet.doneWhen || [],
|
|
349
|
+
validationCommands: packet.validationCommands || []
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export async function createAgentProgressTracker(input, options = {}) {
|
|
354
|
+
const format = normalizeFormat(options.format);
|
|
355
|
+
const context = await resolveExecutionContext(input);
|
|
356
|
+
const packets = context.applyPlan?.packets || [];
|
|
357
|
+
const completedPacketIds = pickCompletedIds(packets, options, context.trackerState);
|
|
358
|
+
const completedSet = new Set(completedPacketIds);
|
|
359
|
+
const currentTaskId = pickCurrentTaskId(packets, completedPacketIds, options, context.trackerState);
|
|
360
|
+
const blockedReasons = pickBlockedReasons(options, context.trackerState);
|
|
361
|
+
const completedPackets = packets.filter((packet) => completedSet.has(packet.id));
|
|
362
|
+
const remainingPackets = packets.filter((packet) => !completedSet.has(packet.id));
|
|
363
|
+
const activePacket = summarizePacket(remainingPackets.find((packet) => packet.id === currentTaskId) || remainingPackets[0]);
|
|
364
|
+
const nextPacket = summarizePacket(
|
|
365
|
+
activePacket ? remainingPackets.find((packet) => packet.id !== activePacket.id) : remainingPackets[0]
|
|
366
|
+
);
|
|
367
|
+
const totalPackets = packets.length;
|
|
368
|
+
const completedCount = completedPackets.length;
|
|
369
|
+
const remainingCount = Math.max(totalPackets - completedCount, 0);
|
|
370
|
+
const progressPercent = totalPackets > 0 ? Math.round((completedCount / totalPackets) * 100) : 0;
|
|
371
|
+
const status = inferTrackerStatus(totalPackets, completedCount, blockedReasons);
|
|
372
|
+
const statusSummary = buildStatusSummary(status, activePacket, nextPacket, blockedReasons);
|
|
373
|
+
const suggestedNextCommand = buildSuggestedNextCommand(
|
|
374
|
+
context.source,
|
|
375
|
+
status,
|
|
376
|
+
activePacket,
|
|
377
|
+
remainingPackets,
|
|
378
|
+
blockedReasons
|
|
379
|
+
);
|
|
380
|
+
const followupCommands = buildFollowupCommands(context.source, status, activePacket, nextPacket, remainingPackets);
|
|
381
|
+
|
|
382
|
+
const tracker = {
|
|
383
|
+
kind: "geo-agent-progress-tracker",
|
|
384
|
+
input,
|
|
385
|
+
source: context.source,
|
|
386
|
+
sourceType: context.sourceType,
|
|
387
|
+
artifactKind: context.artifactKind,
|
|
388
|
+
format,
|
|
389
|
+
executionType: context.applyPlan?.executionType || "guided-planning",
|
|
390
|
+
status,
|
|
391
|
+
statusSummary,
|
|
392
|
+
totalPackets,
|
|
393
|
+
completedCount,
|
|
394
|
+
remainingCount,
|
|
395
|
+
progressPercent,
|
|
396
|
+
currentTaskId: activePacket?.id || null,
|
|
397
|
+
completedPacketIds,
|
|
398
|
+
blockedReasons,
|
|
399
|
+
completedPackets: completedPackets.map(summarizePacket),
|
|
400
|
+
activePacket,
|
|
401
|
+
nextPacket,
|
|
402
|
+
remainingPackets: remainingPackets.map(summarizePacket),
|
|
403
|
+
suggestedNextCommand,
|
|
404
|
+
followupCommands,
|
|
405
|
+
trackerPrompt: "",
|
|
406
|
+
applyPlan: context.applyPlan
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
tracker.trackerPrompt = buildTrackerPrompt(tracker);
|
|
410
|
+
return tracker;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export function renderAgentProgressTrackerMarkdown(tracker) {
|
|
414
|
+
const lines = [
|
|
415
|
+
"# GEO Agent Progress Tracker",
|
|
416
|
+
"",
|
|
417
|
+
`- 输入:\`${tracker.source}\``,
|
|
418
|
+
`- 来源类型:\`${tracker.sourceType}\``,
|
|
419
|
+
`- 工件类型:\`${tracker.artifactKind}\``,
|
|
420
|
+
`- 当前状态:\`${tracker.status}\``,
|
|
421
|
+
`- 执行类型:\`${tracker.executionType}\``,
|
|
422
|
+
`- 进度:\`${tracker.progressPercent}%\``,
|
|
423
|
+
`- 已完成:\`${tracker.completedCount}/${tracker.totalPackets}\``,
|
|
424
|
+
`- 当前总结:${tracker.statusSummary}`,
|
|
425
|
+
""
|
|
426
|
+
];
|
|
427
|
+
|
|
428
|
+
lines.push("## 已完成任务包", "");
|
|
429
|
+
if (tracker.completedPackets.length === 0) {
|
|
430
|
+
lines.push("- 当前还没有标记为已完成的任务包。", "");
|
|
431
|
+
} else {
|
|
432
|
+
for (const packet of tracker.completedPackets) {
|
|
433
|
+
lines.push(`- ${packet.id}|${packet.title}`);
|
|
434
|
+
}
|
|
435
|
+
lines.push("");
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
lines.push("## 当前任务包", "");
|
|
439
|
+
if (!tracker.activePacket) {
|
|
440
|
+
lines.push("- 当前还没有可推进的任务包。", "");
|
|
441
|
+
} else {
|
|
442
|
+
lines.push(`- ID:\`${tracker.activePacket.id}\``);
|
|
443
|
+
lines.push(`- 标题:${tracker.activePacket.title}`);
|
|
444
|
+
lines.push(`- Owner:${tracker.activePacket.owner}`);
|
|
445
|
+
lines.push(`- 优先级:${tracker.activePacket.priority}`);
|
|
446
|
+
lines.push("");
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
lines.push("## 下一包", "");
|
|
450
|
+
if (!tracker.nextPacket) {
|
|
451
|
+
lines.push("- 当前没有下一包,完成后可进入收尾。", "");
|
|
452
|
+
} else {
|
|
453
|
+
lines.push(`- ID:\`${tracker.nextPacket.id}\``);
|
|
454
|
+
lines.push(`- 标题:${tracker.nextPacket.title}`);
|
|
455
|
+
lines.push(`- Owner:${tracker.nextPacket.owner}`);
|
|
456
|
+
lines.push("");
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
lines.push("## 阻塞项", "");
|
|
460
|
+
if (tracker.blockedReasons.length === 0) {
|
|
461
|
+
lines.push("- 当前没有手动标记的阻塞项。", "");
|
|
462
|
+
} else {
|
|
463
|
+
for (const reason of tracker.blockedReasons) {
|
|
464
|
+
lines.push(`- ${reason}`);
|
|
465
|
+
}
|
|
466
|
+
lines.push("");
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
lines.push("## 建议下一步命令", "");
|
|
470
|
+
lines.push(`- \`${tracker.suggestedNextCommand}\``);
|
|
471
|
+
lines.push("", "## 后续命令", "");
|
|
472
|
+
for (const command of tracker.followupCommands) {
|
|
473
|
+
lines.push(`- \`${command}\``);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
lines.push("", "## 可直接复制给 Agent 的 Progress Prompt", "", "```text", tracker.trackerPrompt, "```");
|
|
477
|
+
return `${lines.join("\n")}\n`;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
export async function writeAgentProgressTrackerOutput(outputPath, content) {
|
|
481
|
+
return writeScanOutput(outputPath, content);
|
|
482
|
+
}
|
package/src/agent-session.js
CHANGED
|
@@ -55,6 +55,9 @@ function inferSkillForCommand(commandName, flow) {
|
|
|
55
55
|
if (commandName === "agent-batch-executor") {
|
|
56
56
|
return "geo-ai-search-optimization-agent-batch-executor";
|
|
57
57
|
}
|
|
58
|
+
if (commandName === "agent-progress-tracker") {
|
|
59
|
+
return "geo-ai-search-optimization-agent-progress-tracker";
|
|
60
|
+
}
|
|
58
61
|
if (commandName === "skills" || commandName === "quick-start") {
|
|
59
62
|
return "geo-ai-search-optimization-usage";
|
|
60
63
|
}
|
|
@@ -121,6 +124,8 @@ function inferStepPurpose(commandName, flow) {
|
|
|
121
124
|
return "把这一轮先做哪一个任务包压成单任务执行入口。";
|
|
122
125
|
case "agent-batch-executor":
|
|
123
126
|
return "把前几包任务排成连续执行顺序,但保持一次只推进一包。";
|
|
127
|
+
case "agent-progress-tracker":
|
|
128
|
+
return "追踪当前做到第几包、卡点在哪里,以及下一包该推进什么。";
|
|
124
129
|
case "apply-plan":
|
|
125
130
|
return "把交接结果推进到具体执行包。";
|
|
126
131
|
case "completion-report":
|
|
@@ -167,6 +172,8 @@ function inferExpectedArtifact(commandName) {
|
|
|
167
172
|
return "agent 单任务执行包";
|
|
168
173
|
case "agent-batch-executor":
|
|
169
174
|
return "agent 多任务批次执行包";
|
|
175
|
+
case "agent-progress-tracker":
|
|
176
|
+
return "agent 执行进度追踪工件";
|
|
170
177
|
case "apply-plan":
|
|
171
178
|
return "执行包";
|
|
172
179
|
case "completion-report":
|
|
@@ -208,6 +215,9 @@ function buildStepInstructions(parsedCommand, flow) {
|
|
|
208
215
|
if (parsedCommand.commandName === "agent-batch-executor") {
|
|
209
216
|
lines.push("批次模式下也要一次只做一包,上一包通过验证后再进入下一包。");
|
|
210
217
|
}
|
|
218
|
+
if (parsedCommand.commandName === "agent-progress-tracker") {
|
|
219
|
+
lines.push("这一步用于校准当前做到哪、当前卡点和下一包,不要跳过状态确认直接进入收尾。");
|
|
220
|
+
}
|
|
211
221
|
if (parsedCommand.commandName === "agent-handoff" && flow.intent === "execute") {
|
|
212
222
|
lines.push("如果还是 advice-only,说明还缺仓库或本地项目上下文。");
|
|
213
223
|
}
|
package/src/auto-flow.js
CHANGED
|
@@ -47,6 +47,9 @@ function inferTaskTextMode(text) {
|
|
|
47
47
|
if (/(batch-executor|batch executor|多包|前3包|批次执行|连续推进前几包)/i.test(normalized)) {
|
|
48
48
|
return "execute";
|
|
49
49
|
}
|
|
50
|
+
if (/(progress-tracker|progress tracker|进度追踪|做到第几包|卡在哪|下一包是什么)/i.test(normalized)) {
|
|
51
|
+
return "execute";
|
|
52
|
+
}
|
|
50
53
|
if (/(executor|先做哪一个|先做哪一包|single task|执行第一包|先执行一个任务)/i.test(normalized)) {
|
|
51
54
|
return "execute";
|
|
52
55
|
}
|
|
@@ -165,6 +168,7 @@ function resolveEffectiveIntent(intent, detected) {
|
|
|
165
168
|
"geo-agent-runbook",
|
|
166
169
|
"geo-agent-executor",
|
|
167
170
|
"geo-agent-batch-executor",
|
|
171
|
+
"geo-agent-progress-tracker",
|
|
168
172
|
"geo-apply-plan",
|
|
169
173
|
"geo-handoff-bundle",
|
|
170
174
|
"geo-fix-plan"
|
|
@@ -257,7 +261,9 @@ function buildCommandChain(detected, intent) {
|
|
|
257
261
|
`geo-ai-search-optimization agent-handoff ${source}`,
|
|
258
262
|
`geo-ai-search-optimization agent-runbook ${source}`,
|
|
259
263
|
`geo-ai-search-optimization agent-executor ${source}`,
|
|
260
|
-
`geo-ai-search-optimization apply-plan ${source}
|
|
264
|
+
`geo-ai-search-optimization apply-plan ${source}`,
|
|
265
|
+
`geo-ai-search-optimization agent-batch-executor ${source}`,
|
|
266
|
+
`geo-ai-search-optimization agent-progress-tracker ${source}`
|
|
261
267
|
]
|
|
262
268
|
: [`geo-ai-search-optimization fix-plan ${source}`, `geo-ai-search-optimization owner-board ${source}`];
|
|
263
269
|
case "geo-url-onboarding":
|
|
@@ -272,6 +278,7 @@ function buildCommandChain(detected, intent) {
|
|
|
272
278
|
`geo-ai-search-optimization agent-runbook ${source}`,
|
|
273
279
|
`geo-ai-search-optimization agent-executor ${source}`,
|
|
274
280
|
`geo-ai-search-optimization agent-batch-executor ${source}`,
|
|
281
|
+
`geo-ai-search-optimization agent-progress-tracker ${source}`,
|
|
275
282
|
`geo-ai-search-optimization completion-report ${source}`
|
|
276
283
|
];
|
|
277
284
|
case "geo-agent-handoff":
|
|
@@ -279,31 +286,54 @@ function buildCommandChain(detected, intent) {
|
|
|
279
286
|
`geo-ai-search-optimization agent-runbook ${source}`,
|
|
280
287
|
`geo-ai-search-optimization agent-executor ${source}`,
|
|
281
288
|
`geo-ai-search-optimization agent-batch-executor ${source}`,
|
|
289
|
+
`geo-ai-search-optimization agent-progress-tracker ${source}`,
|
|
282
290
|
`geo-ai-search-optimization completion-report ${source}`
|
|
283
291
|
];
|
|
284
292
|
case "geo-agent-runbook":
|
|
285
293
|
return [
|
|
286
294
|
`geo-ai-search-optimization agent-executor ${source}`,
|
|
287
295
|
`geo-ai-search-optimization agent-batch-executor ${source}`,
|
|
296
|
+
`geo-ai-search-optimization agent-progress-tracker ${source}`,
|
|
288
297
|
`geo-ai-search-optimization completion-report ${source}`,
|
|
289
298
|
`geo-ai-search-optimization handoff-bundle ${source}`
|
|
290
299
|
];
|
|
291
300
|
case "geo-agent-executor":
|
|
292
301
|
return [
|
|
302
|
+
`geo-ai-search-optimization agent-progress-tracker ${source}`,
|
|
293
303
|
`geo-ai-search-optimization completion-report ${source}`,
|
|
294
304
|
`geo-ai-search-optimization handoff-bundle ${source}`,
|
|
295
305
|
`geo-ai-search-optimization publish-pack ${source}`
|
|
296
306
|
];
|
|
297
307
|
case "geo-agent-batch-executor":
|
|
298
308
|
return [
|
|
309
|
+
`geo-ai-search-optimization agent-progress-tracker ${source}`,
|
|
299
310
|
`geo-ai-search-optimization completion-report ${source}`,
|
|
300
311
|
`geo-ai-search-optimization handoff-bundle ${source}`,
|
|
301
312
|
`geo-ai-search-optimization publish-pack ${source}`
|
|
302
313
|
];
|
|
314
|
+
case "geo-agent-progress-tracker":
|
|
315
|
+
return detected.parsed?.status === "completed"
|
|
316
|
+
? [
|
|
317
|
+
`geo-ai-search-optimization completion-report ${source}`,
|
|
318
|
+
`geo-ai-search-optimization handoff-bundle ${source}`,
|
|
319
|
+
`geo-ai-search-optimization publish-pack ${source}`
|
|
320
|
+
]
|
|
321
|
+
: detected.parsed?.currentTaskId
|
|
322
|
+
? [
|
|
323
|
+
`geo-ai-search-optimization agent-executor ${source} --task ${detected.parsed.currentTaskId}`,
|
|
324
|
+
`geo-ai-search-optimization completion-report ${source}`,
|
|
325
|
+
`geo-ai-search-optimization handoff-bundle ${source}`
|
|
326
|
+
]
|
|
327
|
+
: [
|
|
328
|
+
`geo-ai-search-optimization agent-batch-executor ${source}`,
|
|
329
|
+
`geo-ai-search-optimization completion-report ${source}`,
|
|
330
|
+
`geo-ai-search-optimization handoff-bundle ${source}`
|
|
331
|
+
];
|
|
303
332
|
case "geo-apply-plan":
|
|
304
333
|
return [
|
|
305
334
|
`geo-ai-search-optimization agent-executor ${source}`,
|
|
306
335
|
`geo-ai-search-optimization agent-batch-executor ${source}`,
|
|
336
|
+
`geo-ai-search-optimization agent-progress-tracker ${source}`,
|
|
307
337
|
`geo-ai-search-optimization completion-report ${source}`,
|
|
308
338
|
`geo-ai-search-optimization handoff-bundle ${source}`
|
|
309
339
|
];
|
|
@@ -374,6 +404,8 @@ function pickSkillName(detected, intent) {
|
|
|
374
404
|
return "geo-ai-search-optimization-agent-executor";
|
|
375
405
|
case "geo-agent-batch-executor":
|
|
376
406
|
return "geo-ai-search-optimization-agent-batch-executor";
|
|
407
|
+
case "geo-agent-progress-tracker":
|
|
408
|
+
return "geo-ai-search-optimization-agent-progress-tracker";
|
|
377
409
|
case "geo-completion-report":
|
|
378
410
|
return "geo-ai-search-optimization-completion-report";
|
|
379
411
|
case "geo-handoff-bundle":
|
|
@@ -411,12 +443,14 @@ function buildSecondarySkillNames(primarySkill, intent, detected) {
|
|
|
411
443
|
"geo-agent-runbook",
|
|
412
444
|
"geo-agent-executor",
|
|
413
445
|
"geo-agent-batch-executor",
|
|
446
|
+
"geo-agent-progress-tracker",
|
|
414
447
|
"geo-apply-plan"
|
|
415
448
|
].includes(
|
|
416
449
|
detected.artifactKind
|
|
417
450
|
)
|
|
418
451
|
) {
|
|
419
452
|
names.add("geo-ai-search-optimization-agent-batch-executor");
|
|
453
|
+
names.add("geo-ai-search-optimization-agent-progress-tracker");
|
|
420
454
|
names.add("geo-ai-search-optimization-agent-executor");
|
|
421
455
|
names.add("geo-ai-search-optimization-agent-runbook");
|
|
422
456
|
names.add("geo-ai-search-optimization-agent-handoff");
|
|
@@ -447,6 +481,7 @@ function buildStage(intent, detected) {
|
|
|
447
481
|
"geo-agent-runbook",
|
|
448
482
|
"geo-agent-executor",
|
|
449
483
|
"geo-agent-batch-executor",
|
|
484
|
+
"geo-agent-progress-tracker",
|
|
450
485
|
"geo-apply-plan",
|
|
451
486
|
"geo-handoff-bundle"
|
|
452
487
|
].includes(detected.artifactKind)
|
|
@@ -460,6 +495,7 @@ function buildStage(intent, detected) {
|
|
|
460
495
|
"geo-agent-runbook",
|
|
461
496
|
"geo-agent-executor",
|
|
462
497
|
"geo-agent-batch-executor",
|
|
498
|
+
"geo-agent-progress-tracker",
|
|
463
499
|
"geo-apply-plan",
|
|
464
500
|
"geo-handoff-bundle"
|
|
465
501
|
].includes(detected.artifactKind)
|
|
@@ -546,6 +582,9 @@ function buildNextAction(detected, intent, commands) {
|
|
|
546
582
|
return `先运行 \`${commands[0]}\` 生成适合外发或交接的结果。`;
|
|
547
583
|
}
|
|
548
584
|
if (intent === "execute") {
|
|
585
|
+
if (detected.artifactKind === "geo-agent-progress-tracker") {
|
|
586
|
+
return `先运行 \`${commands[0]}\`,继续当前执行包或校准下一包。`;
|
|
587
|
+
}
|
|
549
588
|
return `先运行 \`${commands[0]}\`,把当前输入推进到 agent 可执行状态。`;
|
|
550
589
|
}
|
|
551
590
|
if (intent === "closeout") {
|
package/src/cli.js
CHANGED
|
@@ -9,6 +9,11 @@ import {
|
|
|
9
9
|
} from "./agent-batch-executor.js";
|
|
10
10
|
import { createAgentExecutor, renderAgentExecutorMarkdown, writeAgentExecutorOutput } from "./agent-executor.js";
|
|
11
11
|
import { createAgentHandoff, renderAgentHandoffMarkdown, writeAgentHandoffOutput } from "./agent-handoff.js";
|
|
12
|
+
import {
|
|
13
|
+
createAgentProgressTracker,
|
|
14
|
+
renderAgentProgressTrackerMarkdown,
|
|
15
|
+
writeAgentProgressTrackerOutput
|
|
16
|
+
} from "./agent-progress-tracker.js";
|
|
12
17
|
import { createAgentRunbook, renderAgentRunbookMarkdown, writeAgentRunbookOutput } from "./agent-runbook.js";
|
|
13
18
|
import { createAgentSession, renderAgentSessionMarkdown, writeAgentSessionOutput } from "./agent-session.js";
|
|
14
19
|
import { createAutoFlow, renderAutoFlowMarkdown, writeAutoFlowOutput } from "./auto-flow.js";
|
|
@@ -71,6 +76,7 @@ function printHelp() {
|
|
|
71
76
|
" geo-ai-search-optimization agent-runbook <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--task <id>] [--format <markdown|json>] [--out <file>]",
|
|
72
77
|
" geo-ai-search-optimization agent-executor <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--task <id>] [--format <markdown|json>] [--out <file>]",
|
|
73
78
|
" geo-ai-search-optimization agent-batch-executor <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--task <id>] [--count <count>] [--format <markdown|json>] [--out <file>]",
|
|
79
|
+
" geo-ai-search-optimization agent-progress-tracker <input> [--current <id>] [--completed <id,id>] [--blocked <reason,reason>] [--format <markdown|json>] [--out <file>]",
|
|
74
80
|
" geo-ai-search-optimization skills [--json]",
|
|
75
81
|
" geo-ai-search-optimization where",
|
|
76
82
|
" geo-ai-search-optimization doctor [--json]",
|
|
@@ -269,6 +275,34 @@ async function handleAgentBatchExecutor(args) {
|
|
|
269
275
|
process.stdout.write(renderedOutput);
|
|
270
276
|
}
|
|
271
277
|
|
|
278
|
+
async function handleAgentProgressTracker(args) {
|
|
279
|
+
const input = args.find((value) => !value.startsWith("-"));
|
|
280
|
+
if (!input) {
|
|
281
|
+
throw new Error("agent-progress-tracker 需要一个输入值,可以是项目路径、网站网址或已导出的工件");
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const format = getFlagValue(args, "--format") || (hasFlag(args, "--json") ? "json" : undefined);
|
|
285
|
+
const tracker = await createAgentProgressTracker(input, {
|
|
286
|
+
format,
|
|
287
|
+
currentTaskId: getFlagValue(args, "--current"),
|
|
288
|
+
completedPacketIds: getFlagValue(args, "--completed"),
|
|
289
|
+
blockedReasons: getFlagValue(args, "--blocked")
|
|
290
|
+
});
|
|
291
|
+
const outputJson = tracker.format === "json";
|
|
292
|
+
const renderedOutput = outputJson
|
|
293
|
+
? `${JSON.stringify(tracker, null, 2)}\n`
|
|
294
|
+
: renderAgentProgressTrackerMarkdown(tracker);
|
|
295
|
+
|
|
296
|
+
const outputPath = getFlagValue(args, "--out");
|
|
297
|
+
if (outputPath) {
|
|
298
|
+
const resolvedOutputPath = await writeAgentProgressTrackerOutput(outputPath, renderedOutput);
|
|
299
|
+
process.stdout.write(`已保存 agent progress tracker:${resolvedOutputPath}\n`);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
process.stdout.write(renderedOutput);
|
|
304
|
+
}
|
|
305
|
+
|
|
272
306
|
function handleWhere() {
|
|
273
307
|
process.stdout.write(
|
|
274
308
|
[
|
|
@@ -834,6 +868,11 @@ export async function runCli(args = []) {
|
|
|
834
868
|
return;
|
|
835
869
|
}
|
|
836
870
|
|
|
871
|
+
if (command === "agent-progress-tracker") {
|
|
872
|
+
await handleAgentProgressTracker(rest);
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
|
|
837
876
|
if (command === "skills") {
|
|
838
877
|
await handleSkills(rest);
|
|
839
878
|
return;
|
package/src/index.js
CHANGED
|
@@ -10,6 +10,11 @@ export { createApplyPlan, renderApplyPlanMarkdown, writeApplyPlanOutput } from "
|
|
|
10
10
|
export { createAgentBatchExecutor, renderAgentBatchExecutorMarkdown, writeAgentBatchExecutorOutput } from "./agent-batch-executor.js";
|
|
11
11
|
export { createAgentHandoff, renderAgentHandoffMarkdown, writeAgentHandoffOutput } from "./agent-handoff.js";
|
|
12
12
|
export { createAgentExecutor, renderAgentExecutorMarkdown, writeAgentExecutorOutput } from "./agent-executor.js";
|
|
13
|
+
export {
|
|
14
|
+
createAgentProgressTracker,
|
|
15
|
+
renderAgentProgressTrackerMarkdown,
|
|
16
|
+
writeAgentProgressTrackerOutput
|
|
17
|
+
} from "./agent-progress-tracker.js";
|
|
13
18
|
export { createAgentRunbook, renderAgentRunbookMarkdown, writeAgentRunbookOutput } from "./agent-runbook.js";
|
|
14
19
|
export { createAgentSession, renderAgentSessionMarkdown, writeAgentSessionOutput } from "./agent-session.js";
|
|
15
20
|
export { createCompletionReport, renderCompletionReportMarkdown, writeCompletionReportOutput } from "./completion-report.js";
|
package/src/skills.js
CHANGED
|
@@ -9,6 +9,7 @@ const SKILL_ORDER = [
|
|
|
9
9
|
"geo-ai-search-optimization-agent-runbook",
|
|
10
10
|
"geo-ai-search-optimization-agent-executor",
|
|
11
11
|
"geo-ai-search-optimization-agent-batch-executor",
|
|
12
|
+
"geo-ai-search-optimization-agent-progress-tracker",
|
|
12
13
|
"geo-ai-search-optimization-usage",
|
|
13
14
|
"geo-ai-search-optimization-agent-handoff",
|
|
14
15
|
"geo-ai-search-optimization-repair-loop",
|
|
@@ -27,6 +28,7 @@ const SKILL_CATEGORY = {
|
|
|
27
28
|
"geo-ai-search-optimization-agent-runbook": "execution",
|
|
28
29
|
"geo-ai-search-optimization-agent-executor": "execution",
|
|
29
30
|
"geo-ai-search-optimization-agent-batch-executor": "execution",
|
|
31
|
+
"geo-ai-search-optimization-agent-progress-tracker": "execution",
|
|
30
32
|
"geo-ai-search-optimization-usage": "guidance",
|
|
31
33
|
"geo-ai-search-optimization-agent-handoff": "execution",
|
|
32
34
|
"geo-ai-search-optimization-repair-loop": "execution",
|
|
@@ -164,6 +166,7 @@ export function renderBundledSkillsMarkdown(bundle) {
|
|
|
164
166
|
"- 如果要给 agent 一份执行手册和检查表,再进入 agent-runbook。",
|
|
165
167
|
"- 如果要直接告诉 agent 这轮先做哪 1 包,再进入 agent-executor。",
|
|
166
168
|
"- 如果要连续推进前 2 到 3 包,但仍然一次只做一包,再进入 agent-batch-executor。",
|
|
169
|
+
"- 如果要追踪目前做到第几包、卡在哪、下一包是什么,再进入 agent-progress-tracker。",
|
|
167
170
|
"- 再看 usage skill,知道什么时候该跑哪个命令。",
|
|
168
171
|
"- 如果要交给 agent 执行,再进入 handoff / apply / completion 这一条执行链。",
|
|
169
172
|
"- 如果要产出给团队分发,再进入 share / export / html / publish 这一条交付链。",
|