geo-ai-search-optimization 1.2.9 → 1.2.10
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 +30 -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-executor/SKILL.md +24 -0
- package/resources/geo-ai-search-optimization-agent-executor/agents/openai.yaml +4 -0
- package/resources/geo-ai-search-optimization-usage/SKILL.md +19 -14
- package/src/agent-executor.js +319 -0
- package/src/agent-session.js +10 -0
- package/src/auto-flow.js +48 -19
- package/src/cli.js +34 -0
- package/src/index.js +1 -0
- package/src/skills.js +3 -0
package/README.md
CHANGED
|
@@ -103,6 +103,27 @@ geo-ai-search-optimization agent-runbook ./reports/apply-plan.json --json
|
|
|
103
103
|
- 回报清单
|
|
104
104
|
- 可直接复制给 agent 的 runbook prompt
|
|
105
105
|
|
|
106
|
+
## Agent Executor 命令
|
|
107
|
+
|
|
108
|
+
如果你希望 agent 不只是拿到 runbook,而是直接得到“这一轮先执行哪 1 个任务”的入口,可以直接用 `agent-executor`:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
geo-ai-search-optimization agent-executor ./your-site
|
|
112
|
+
geo-ai-search-optimization agent-executor ./reports/apply-plan.json
|
|
113
|
+
geo-ai-search-optimization agent-executor ./reports/apply-plan.json --task fix-02 --json
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
它会输出:
|
|
117
|
+
|
|
118
|
+
- 当前先做哪一包
|
|
119
|
+
- 为什么先做这一包
|
|
120
|
+
- do-now checklist
|
|
121
|
+
- stop checklist
|
|
122
|
+
- success checklist
|
|
123
|
+
- 验证命令
|
|
124
|
+
- 给用户的回报模板
|
|
125
|
+
- 可直接复制给 agent 的 executor prompt
|
|
126
|
+
|
|
106
127
|
## Quick Start
|
|
107
128
|
|
|
108
129
|
如果你要从 0 到 1 启动一个 GEO 项目,建议照这个顺序做。
|
|
@@ -499,6 +520,7 @@ geo-ai-search-optimization install --target ./tmp/custom-skills --json
|
|
|
499
520
|
geo-ai-search-optimization auto-flow "audit this site and tell me the next skill"
|
|
500
521
|
geo-ai-search-optimization agent-session ./your-site
|
|
501
522
|
geo-ai-search-optimization agent-runbook ./your-site
|
|
523
|
+
geo-ai-search-optimization agent-executor ./your-site
|
|
502
524
|
geo-ai-search-optimization skills
|
|
503
525
|
geo-ai-search-optimization where
|
|
504
526
|
geo-ai-search-optimization doctor
|
|
@@ -562,6 +584,13 @@ geo-ai-search-optimization help
|
|
|
562
584
|
- 输出开始前检查、工作规则、停止条件、验证清单、回报清单
|
|
563
585
|
- 新增 `geo-ai-search-optimization-agent-runbook` skill
|
|
564
586
|
|
|
587
|
+
## New in 1.2.10
|
|
588
|
+
|
|
589
|
+
- 新增 `agent-executor` 命令
|
|
590
|
+
- 把 runbook 再收敛成“这一轮先做哪 1 包”的单任务入口
|
|
591
|
+
- 输出 do-now checklist、stop checklist、success checklist、验证命令和回报模板
|
|
592
|
+
- 新增 `geo-ai-search-optimization-agent-executor` skill
|
|
593
|
+
|
|
565
594
|
## New in 1.2.5
|
|
566
595
|
|
|
567
596
|
- 新增 `publish-pack`
|
|
@@ -751,6 +780,7 @@ The installed package now includes a bundled GEO skill pack, including:
|
|
|
751
780
|
- `geo-ai-search-optimization-auto-flow`
|
|
752
781
|
- `geo-ai-search-optimization-agent-session`
|
|
753
782
|
- `geo-ai-search-optimization-agent-runbook`
|
|
783
|
+
- `geo-ai-search-optimization-agent-executor`
|
|
754
784
|
- `geo-ai-search-optimization-usage`
|
|
755
785
|
- `geo-ai-search-optimization-agent-handoff`
|
|
756
786
|
- `geo-ai-search-optimization-repair-loop`
|
package/package.json
CHANGED
|
@@ -52,6 +52,16 @@ Best for:
|
|
|
52
52
|
- telling the next agent what to check before acting
|
|
53
53
|
- defining stop conditions, validation checklist, and reporting checklist
|
|
54
54
|
|
|
55
|
+
### `geo-ai-search-optimization-agent-executor`
|
|
56
|
+
|
|
57
|
+
Use this when the next agent should stop planning and start one concrete execution packet.
|
|
58
|
+
|
|
59
|
+
Best for:
|
|
60
|
+
|
|
61
|
+
- selecting the first packet to execute now
|
|
62
|
+
- reducing a runbook into one actionable task
|
|
63
|
+
- giving the next agent a single-task prompt, validation commands, and reply template
|
|
64
|
+
|
|
55
65
|
## Usage guide
|
|
56
66
|
|
|
57
67
|
### `geo-ai-search-optimization-usage`
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: geo-ai-search-optimization-agent-executor
|
|
3
|
+
description: Turn a GEO input into a single-task execution entrypoint for the next agent. Use when an agent should stop planning and start one concrete GEO packet now, with a selected task, do-now checklist, validation commands, success criteria, and a reply template.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GEO Agent Executor
|
|
7
|
+
|
|
8
|
+
Use this skill when the next agent should execute one packet now, not keep expanding the plan.
|
|
9
|
+
|
|
10
|
+
`GEO = Generative Engine Optimization`
|
|
11
|
+
|
|
12
|
+
## What it does
|
|
13
|
+
|
|
14
|
+
- select the first or requested execution packet
|
|
15
|
+
- compress the runbook into one task entrypoint
|
|
16
|
+
- define do-now, stop, and success checklists
|
|
17
|
+
- provide validation commands and a reply template
|
|
18
|
+
- make the next agent focus on one packet at a time
|
|
19
|
+
|
|
20
|
+
## Best use
|
|
21
|
+
|
|
22
|
+
- when `agent-runbook` is still too broad
|
|
23
|
+
- when a PM or another agent asks “this round, what should we do first?”
|
|
24
|
+
- when execution should start from one concrete packet
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "GEO Agent Executor"
|
|
3
|
+
short_description: "Start one GEO execution packet right now"
|
|
4
|
+
default_prompt: "Use $geo-ai-search-optimization-agent-executor to choose the first GEO packet to execute now, with a do-now checklist, validation commands, and a reply template."
|
|
@@ -13,24 +13,25 @@ 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 seventeen 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
|
-
4. `
|
|
22
|
-
5. `
|
|
23
|
-
6. `
|
|
24
|
-
7. `
|
|
25
|
-
8. `
|
|
26
|
-
9. `
|
|
27
|
-
10. `
|
|
28
|
-
11. `
|
|
29
|
-
12. `
|
|
30
|
-
13. `
|
|
31
|
-
14. `
|
|
32
|
-
15. `
|
|
33
|
-
16. `
|
|
21
|
+
4. `agent-executor`: choose one packet to execute right now
|
|
22
|
+
5. `skills`: inspect the bundled skill package
|
|
23
|
+
6. `onboard-url` / `onboard`: first look
|
|
24
|
+
7. `scan`: raw signal check
|
|
25
|
+
8. `audit` / `report`: diagnosis
|
|
26
|
+
9. `fix-plan` / `owner-board`: execution planning
|
|
27
|
+
10. `agent-handoff`: agent takeover package
|
|
28
|
+
11. `apply-plan`: execution loop
|
|
29
|
+
12. `completion-report`: closeout
|
|
30
|
+
13. `handoff-bundle`: all-in-one package
|
|
31
|
+
14. `share-pack`: audience-ready delivery
|
|
32
|
+
15. `export-pack`: folder export
|
|
33
|
+
16. `html-pack` / `publish-pack`: browsable and final delivery output
|
|
34
|
+
17. `pm-brief` / `roadmap`: stakeholder alignment
|
|
34
35
|
|
|
35
36
|
## Recommended command order
|
|
36
37
|
|
|
@@ -40,6 +41,7 @@ If the user only has a website URL:
|
|
|
40
41
|
npx geo-ai-search-optimization auto-flow https://example.com
|
|
41
42
|
npx geo-ai-search-optimization agent-session https://example.com
|
|
42
43
|
npx geo-ai-search-optimization agent-runbook https://example.com
|
|
44
|
+
npx geo-ai-search-optimization agent-executor https://example.com
|
|
43
45
|
npx geo-ai-search-optimization onboard-url https://example.com
|
|
44
46
|
npx geo-ai-search-optimization pm-brief https://example.com
|
|
45
47
|
npx geo-ai-search-optimization roadmap https://example.com
|
|
@@ -51,6 +53,7 @@ If the user has the website codebase:
|
|
|
51
53
|
npx geo-ai-search-optimization auto-flow ./your-site
|
|
52
54
|
npx geo-ai-search-optimization agent-session ./your-site
|
|
53
55
|
npx geo-ai-search-optimization agent-runbook ./your-site
|
|
56
|
+
npx geo-ai-search-optimization agent-executor ./your-site
|
|
54
57
|
npx geo-ai-search-optimization scan ./your-site
|
|
55
58
|
npx geo-ai-search-optimization audit ./your-site
|
|
56
59
|
npx geo-ai-search-optimization fix-plan ./your-site
|
|
@@ -71,6 +74,7 @@ npx geo-ai-search-optimization roadmap ./your-site
|
|
|
71
74
|
- `auto-flow`: auto-select the next skill and command order from a task brief, URL, project path, or GEO artifact
|
|
72
75
|
- `agent-session`: build a step-by-step session packet for the next agent from the same kinds of inputs
|
|
73
76
|
- `agent-runbook`: build a checklist-driven runbook with preflight, validation, and reporting rules
|
|
77
|
+
- `agent-executor`: select one packet to execute now and package it into a single-task entrypoint
|
|
74
78
|
- `onboard-url`: first-time website check from a live URL
|
|
75
79
|
- `onboard`: interactive first-time onboarding
|
|
76
80
|
- `skills`: list the bundled skills and decide which skill or command chain fits the task
|
|
@@ -98,6 +102,7 @@ When explaining the tool to a user:
|
|
|
98
102
|
- if the user or the next agent is unsure where to start, move them to `auto-flow` first
|
|
99
103
|
- if the user wants something the next agent can follow step by step, move them to `agent-session`
|
|
100
104
|
- if the user wants the next agent to follow a checklist and execution manual, move them to `agent-runbook`
|
|
105
|
+
- if the user wants the next agent to start one concrete task now, move them to `agent-executor`
|
|
101
106
|
- explain the result in PM language, not implementation jargon
|
|
102
107
|
- if the user sounds new, start with `onboard-url` or `quick-start`
|
|
103
108
|
- if the user wants another agent to take over, move them to `agent-handoff`
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { createApplyPlan } from "./apply-plan.js";
|
|
3
|
+
import { createAgentRunbook } from "./agent-runbook.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-executor 格式:${format}。可选值:${Array.from(VALID_FORMATS).join(", ")}`);
|
|
12
|
+
}
|
|
13
|
+
return resolved;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function loadJsonArtifact(input) {
|
|
17
|
+
const raw = await readFile(input, "utf8");
|
|
18
|
+
return JSON.parse(raw);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function resolveRunbookAndPlan(input, options = {}) {
|
|
22
|
+
const runbook = await createAgentRunbook(input, {
|
|
23
|
+
format: "json",
|
|
24
|
+
intent: options.intent,
|
|
25
|
+
taskId: options.taskId
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (runbook.applyPlan?.kind === "geo-apply-plan") {
|
|
29
|
+
return {
|
|
30
|
+
runbook,
|
|
31
|
+
applyPlan: runbook.applyPlan
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (runbook.sourceType === "json") {
|
|
36
|
+
const parsed = await loadJsonArtifact(input).catch(() => null);
|
|
37
|
+
if (parsed?.kind === "geo-apply-plan") {
|
|
38
|
+
return {
|
|
39
|
+
runbook,
|
|
40
|
+
applyPlan: parsed
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (parsed?.kind === "geo-agent-runbook" && parsed.applyPlan?.kind === "geo-apply-plan") {
|
|
44
|
+
return {
|
|
45
|
+
runbook,
|
|
46
|
+
applyPlan: parsed.applyPlan
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const applyPlan = await createApplyPlan(input, {
|
|
53
|
+
format: "json",
|
|
54
|
+
taskId: options.taskId
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
runbook,
|
|
58
|
+
applyPlan
|
|
59
|
+
};
|
|
60
|
+
} catch {
|
|
61
|
+
return {
|
|
62
|
+
runbook,
|
|
63
|
+
applyPlan: null
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function inferExecutorMode(runbook, applyPlan) {
|
|
69
|
+
if (!applyPlan?.packets?.length) {
|
|
70
|
+
if (runbook.contextNeeded?.length) {
|
|
71
|
+
return "needs-context";
|
|
72
|
+
}
|
|
73
|
+
return "planning-only";
|
|
74
|
+
}
|
|
75
|
+
return applyPlan.executionType || "guided-planning";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function selectPacket(applyPlan, taskId) {
|
|
79
|
+
if (!applyPlan?.packets?.length) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (taskId) {
|
|
84
|
+
const selected = applyPlan.packets.find((packet) => packet.id === taskId);
|
|
85
|
+
if (!selected) {
|
|
86
|
+
throw new Error(`找不到执行包:${taskId}`);
|
|
87
|
+
}
|
|
88
|
+
return selected;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return applyPlan.packets[0];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function buildSelectionReason(packet, applyPlan, taskId) {
|
|
95
|
+
if (!packet) {
|
|
96
|
+
return "当前还没有可执行任务包,说明需要先补上下文或先生成 apply-plan。";
|
|
97
|
+
}
|
|
98
|
+
if (taskId) {
|
|
99
|
+
return `已按指定任务 ID 选中:${taskId}。`;
|
|
100
|
+
}
|
|
101
|
+
if (applyPlan?.selectedTaskCount > 1) {
|
|
102
|
+
return "默认选择第一包,代表当前优先级最高、最适合立刻开始的一项任务。";
|
|
103
|
+
}
|
|
104
|
+
return "当前只有一个任务包,因此直接将它作为本轮执行入口。";
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function buildDoNowChecklist(packet, executorMode) {
|
|
108
|
+
if (!packet) {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const items = [
|
|
113
|
+
`先锁定任务范围:${packet.title}`,
|
|
114
|
+
...packet.inspectTargets.slice(0, 3).map((item) => `先检查:${item}`),
|
|
115
|
+
...packet.editPlan.slice(0, 3).map((item) => `执行动作:${item}`)
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
if (executorMode === "direct-fix") {
|
|
119
|
+
items.push("开始修改前先确认会影响整类页面的复用层,而不是只 patch 单页。");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return items;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function buildStopChecklist(runbook, packet, executorMode) {
|
|
126
|
+
const items = [...(runbook.stopConditions || [])];
|
|
127
|
+
|
|
128
|
+
if (!packet) {
|
|
129
|
+
items.push("还没有拿到执行包时,不要假装已经进入真正修复阶段。");
|
|
130
|
+
return items;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (executorMode === "recommendation-only") {
|
|
134
|
+
items.push("如果当前只有网址或建议上下文,不要输出伪造的代码修改结果。");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
items.push("如果执行中发现这不是最高优先级任务,应先说明原因,再决定是否切换。");
|
|
138
|
+
return items;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function buildSuccessChecklist(packet) {
|
|
142
|
+
if (!packet) {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return [
|
|
147
|
+
...packet.doneWhen,
|
|
148
|
+
"你已经能用 PM 可读的方式说明:改了什么、为什么改、验证结果是什么。"
|
|
149
|
+
];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function buildNextCommands(runbook, packet, input) {
|
|
153
|
+
if (!packet) {
|
|
154
|
+
return runbook.nextCommands || [`geo-ai-search-optimization agent-runbook ${input}`];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const source = runbook.source;
|
|
158
|
+
return [
|
|
159
|
+
`geo-ai-search-optimization completion-report ${source}`,
|
|
160
|
+
`geo-ai-search-optimization handoff-bundle ${source}`
|
|
161
|
+
];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function buildUserReplyTemplate(packet, executorMode) {
|
|
165
|
+
if (!packet) {
|
|
166
|
+
return [
|
|
167
|
+
"结论:我还不能直接执行,因为当前缺少足够上下文。",
|
|
168
|
+
"我目前确认到的情况:",
|
|
169
|
+
"- ",
|
|
170
|
+
"我还需要你补充:",
|
|
171
|
+
"- ",
|
|
172
|
+
"拿到这些之后,我会先执行:",
|
|
173
|
+
"- "
|
|
174
|
+
].join("\n");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const closingLine =
|
|
178
|
+
executorMode === "direct-fix"
|
|
179
|
+
? "我已经完成这一包可直接落地的部分,并附上复测结果。"
|
|
180
|
+
: executorMode === "recommendation-only"
|
|
181
|
+
? "我已经完成这一包的建议版执行,但还需要更多上下文才能继续实际修改。"
|
|
182
|
+
: "我已经把这一包的执行顺序和阻塞项整理好,下一步可以继续推进。";
|
|
183
|
+
|
|
184
|
+
return [
|
|
185
|
+
`任务:${packet.title}`,
|
|
186
|
+
`结论:${closingLine}`,
|
|
187
|
+
"这次我先做了什么:",
|
|
188
|
+
"- ",
|
|
189
|
+
"我检查了哪些文件 / 页面 / 模板:",
|
|
190
|
+
"- ",
|
|
191
|
+
"我实际修改或建议了什么:",
|
|
192
|
+
"- ",
|
|
193
|
+
"验证结果:",
|
|
194
|
+
"- ",
|
|
195
|
+
"剩余风险或下一步:",
|
|
196
|
+
"- "
|
|
197
|
+
].join("\n");
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function buildExecutorPrompt(runbook, packet, executorMode, selectionReason) {
|
|
201
|
+
const lines = [
|
|
202
|
+
"你现在进入 GEO 单任务执行模式。",
|
|
203
|
+
`当前输入:${runbook.source}`,
|
|
204
|
+
`当前阶段:${runbook.stage}`,
|
|
205
|
+
`执行模式:${executorMode}`,
|
|
206
|
+
`任务选择原因:${selectionReason}`
|
|
207
|
+
];
|
|
208
|
+
|
|
209
|
+
if (packet) {
|
|
210
|
+
lines.push(`本轮只做这一包:${packet.title}`);
|
|
211
|
+
lines.push("请你按这个顺序输出:");
|
|
212
|
+
lines.push("1. 先检查什么");
|
|
213
|
+
lines.push("2. 你准备如何执行这一包");
|
|
214
|
+
lines.push("3. 你会如何验证");
|
|
215
|
+
lines.push("4. 完成后如何向用户回报");
|
|
216
|
+
} else {
|
|
217
|
+
lines.push("当前还不能执行具体任务。请先明确缺什么上下文,再告诉用户下一步要补什么。");
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
lines.push("一次只推进一包,不要在同一轮同时展开多个任务。");
|
|
221
|
+
return lines.join("\n");
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export async function createAgentExecutor(input, options = {}) {
|
|
225
|
+
const format = normalizeFormat(options.format);
|
|
226
|
+
const { runbook, applyPlan } = await resolveRunbookAndPlan(input, options);
|
|
227
|
+
const executorMode = inferExecutorMode(runbook, applyPlan);
|
|
228
|
+
const packet = selectPacket(applyPlan, options.taskId);
|
|
229
|
+
const selectionReason = buildSelectionReason(packet, applyPlan, options.taskId);
|
|
230
|
+
|
|
231
|
+
return {
|
|
232
|
+
kind: "geo-agent-executor",
|
|
233
|
+
input,
|
|
234
|
+
source: runbook.source,
|
|
235
|
+
sourceType: runbook.sourceType,
|
|
236
|
+
artifactKind: runbook.artifactKind,
|
|
237
|
+
format,
|
|
238
|
+
intent: runbook.intent,
|
|
239
|
+
stage: runbook.stage,
|
|
240
|
+
executorMode,
|
|
241
|
+
goal: packet ? `先完成这一包:${packet.title}` : runbook.goal,
|
|
242
|
+
selectionReason,
|
|
243
|
+
selectedSkill: {
|
|
244
|
+
name: "geo-ai-search-optimization-agent-executor",
|
|
245
|
+
displayName: "GEO Agent Executor",
|
|
246
|
+
shortDescription: "Start one GEO execution packet right now"
|
|
247
|
+
},
|
|
248
|
+
selectedPacket: packet,
|
|
249
|
+
doNowChecklist: buildDoNowChecklist(packet, executorMode),
|
|
250
|
+
stopChecklist: buildStopChecklist(runbook, packet, executorMode),
|
|
251
|
+
successChecklist: buildSuccessChecklist(packet),
|
|
252
|
+
validationCommands: packet?.validationCommands || runbook.validationChecklist || [],
|
|
253
|
+
userReplyTemplate: buildUserReplyTemplate(packet, executorMode),
|
|
254
|
+
nextCommands: buildNextCommands(runbook, packet, input),
|
|
255
|
+
executorPrompt: buildExecutorPrompt(runbook, packet, executorMode, selectionReason),
|
|
256
|
+
agentRunbook: runbook,
|
|
257
|
+
applyPlan
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export function renderAgentExecutorMarkdown(executor) {
|
|
262
|
+
const lines = [
|
|
263
|
+
"# GEO Agent Executor",
|
|
264
|
+
"",
|
|
265
|
+
`- 输入:\`${executor.source}\``,
|
|
266
|
+
`- 输入类型:\`${executor.sourceType}\``,
|
|
267
|
+
`- 工件类型:\`${executor.artifactKind}\``,
|
|
268
|
+
`- 当前阶段:${executor.stage}`,
|
|
269
|
+
`- 执行模式:\`${executor.executorMode}\``,
|
|
270
|
+
`- 本轮目标:${executor.goal}`,
|
|
271
|
+
`- 任务选择原因:${executor.selectionReason}`,
|
|
272
|
+
"",
|
|
273
|
+
"## 现在先做什么",
|
|
274
|
+
""
|
|
275
|
+
];
|
|
276
|
+
|
|
277
|
+
for (const item of executor.doNowChecklist) {
|
|
278
|
+
lines.push(`- [ ] ${item}`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (executor.selectedPacket) {
|
|
282
|
+
lines.push("", "## 当前任务包", "");
|
|
283
|
+
lines.push(`- ID:\`${executor.selectedPacket.id}\``);
|
|
284
|
+
lines.push(`- 标题:${executor.selectedPacket.title}`);
|
|
285
|
+
lines.push(`- 优先级:${executor.selectedPacket.priority}`);
|
|
286
|
+
lines.push(`- Owner:${executor.selectedPacket.owner}`);
|
|
287
|
+
lines.push(`- 执行类型:\`${executor.selectedPacket.executionType}\``);
|
|
288
|
+
lines.push("");
|
|
289
|
+
lines.push("### 验证命令", "");
|
|
290
|
+
for (const command of executor.validationCommands) {
|
|
291
|
+
lines.push(`- \`${command}\``);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
lines.push("", "## 需要停下来的情况", "");
|
|
296
|
+
for (const item of executor.stopChecklist) {
|
|
297
|
+
lines.push(`- [ ] ${item}`);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
lines.push("", "## 完成标准", "");
|
|
301
|
+
for (const item of executor.successChecklist) {
|
|
302
|
+
lines.push(`- [ ] ${item}`);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
lines.push("", "## 完成后怎么回报用户", "", "```text", executor.userReplyTemplate, "```");
|
|
306
|
+
|
|
307
|
+
lines.push("", "## 下一步推荐命令", "");
|
|
308
|
+
for (const command of executor.nextCommands) {
|
|
309
|
+
lines.push(`- \`${command}\``);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
lines.push("", "## 可直接复制给 Agent 的 Executor Prompt", "", "```text", executor.executorPrompt, "```");
|
|
313
|
+
|
|
314
|
+
return `${lines.join("\n")}\n`;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export async function writeAgentExecutorOutput(outputPath, content) {
|
|
318
|
+
return writeScanOutput(outputPath, content);
|
|
319
|
+
}
|
package/src/agent-session.js
CHANGED
|
@@ -49,6 +49,9 @@ function inferSkillForCommand(commandName, flow) {
|
|
|
49
49
|
if (commandName === "agent-runbook") {
|
|
50
50
|
return "geo-ai-search-optimization-agent-runbook";
|
|
51
51
|
}
|
|
52
|
+
if (commandName === "agent-executor") {
|
|
53
|
+
return "geo-ai-search-optimization-agent-executor";
|
|
54
|
+
}
|
|
52
55
|
if (commandName === "skills" || commandName === "quick-start") {
|
|
53
56
|
return "geo-ai-search-optimization-usage";
|
|
54
57
|
}
|
|
@@ -111,6 +114,8 @@ function inferStepPurpose(commandName, flow) {
|
|
|
111
114
|
return "把当前结果交接成 agent 可继续执行的工件。";
|
|
112
115
|
case "agent-runbook":
|
|
113
116
|
return "把当前链路整理成 agent 可照着执行的手册和检查表。";
|
|
117
|
+
case "agent-executor":
|
|
118
|
+
return "把这一轮先做哪一个任务包压成单任务执行入口。";
|
|
114
119
|
case "apply-plan":
|
|
115
120
|
return "把交接结果推进到具体执行包。";
|
|
116
121
|
case "completion-report":
|
|
@@ -153,6 +158,8 @@ function inferExpectedArtifact(commandName) {
|
|
|
153
158
|
return "agent 交接工件";
|
|
154
159
|
case "agent-runbook":
|
|
155
160
|
return "agent 执行手册";
|
|
161
|
+
case "agent-executor":
|
|
162
|
+
return "agent 单任务执行包";
|
|
156
163
|
case "apply-plan":
|
|
157
164
|
return "执行包";
|
|
158
165
|
case "completion-report":
|
|
@@ -188,6 +195,9 @@ function buildStepInstructions(parsedCommand, flow) {
|
|
|
188
195
|
if (parsedCommand.commandName === "agent-runbook") {
|
|
189
196
|
lines.push("先用 runbook 稳定顺序、检查项和回报方式,再开始真正执行。");
|
|
190
197
|
}
|
|
198
|
+
if (parsedCommand.commandName === "agent-executor") {
|
|
199
|
+
lines.push("这一轮只推进一包任务,不要把多个修复包混在同一次执行里。");
|
|
200
|
+
}
|
|
191
201
|
if (parsedCommand.commandName === "agent-handoff" && flow.intent === "execute") {
|
|
192
202
|
lines.push("如果还是 advice-only,说明还缺仓库或本地项目上下文。");
|
|
193
203
|
}
|
package/src/auto-flow.js
CHANGED
|
@@ -44,6 +44,9 @@ function inferTaskTextMode(text) {
|
|
|
44
44
|
if (/(share-pack|export-pack|html-pack|publish-pack|分享|导出|交付|外发|报告包)/i.test(normalized)) {
|
|
45
45
|
return "share";
|
|
46
46
|
}
|
|
47
|
+
if (/(executor|先做哪一个|先做哪一包|single task|执行第一包|先执行一个任务)/i.test(normalized)) {
|
|
48
|
+
return "execute";
|
|
49
|
+
}
|
|
47
50
|
if (/(runbook|checklist|playbook|执行手册|检查清单|操作手册)/i.test(normalized)) {
|
|
48
51
|
return "execute";
|
|
49
52
|
}
|
|
@@ -150,9 +153,14 @@ function resolveEffectiveIntent(intent, detected) {
|
|
|
150
153
|
return "share";
|
|
151
154
|
}
|
|
152
155
|
if (
|
|
153
|
-
[
|
|
154
|
-
|
|
155
|
-
|
|
156
|
+
[
|
|
157
|
+
"geo-agent-handoff",
|
|
158
|
+
"geo-agent-runbook",
|
|
159
|
+
"geo-agent-executor",
|
|
160
|
+
"geo-apply-plan",
|
|
161
|
+
"geo-handoff-bundle",
|
|
162
|
+
"geo-fix-plan"
|
|
163
|
+
].includes(detected.artifactKind)
|
|
156
164
|
) {
|
|
157
165
|
return "execute";
|
|
158
166
|
}
|
|
@@ -203,7 +211,8 @@ function buildCommandChain(detected, intent) {
|
|
|
203
211
|
`geo-ai-search-optimization onboard-url ${source}`,
|
|
204
212
|
`geo-ai-search-optimization fix-plan ${source}`,
|
|
205
213
|
`geo-ai-search-optimization agent-handoff ${source}`,
|
|
206
|
-
`geo-ai-search-optimization agent-runbook ${source}
|
|
214
|
+
`geo-ai-search-optimization agent-runbook ${source}`,
|
|
215
|
+
`geo-ai-search-optimization agent-executor ${source}`
|
|
207
216
|
];
|
|
208
217
|
}
|
|
209
218
|
return [
|
|
@@ -220,6 +229,7 @@ function buildCommandChain(detected, intent) {
|
|
|
220
229
|
`geo-ai-search-optimization fix-plan ${source}`,
|
|
221
230
|
`geo-ai-search-optimization agent-handoff ${source}`,
|
|
222
231
|
`geo-ai-search-optimization agent-runbook ${source}`,
|
|
232
|
+
`geo-ai-search-optimization agent-executor ${source}`,
|
|
223
233
|
`geo-ai-search-optimization apply-plan ${source}`
|
|
224
234
|
];
|
|
225
235
|
}
|
|
@@ -238,6 +248,7 @@ function buildCommandChain(detected, intent) {
|
|
|
238
248
|
`geo-ai-search-optimization fix-plan ${source}`,
|
|
239
249
|
`geo-ai-search-optimization agent-handoff ${source}`,
|
|
240
250
|
`geo-ai-search-optimization agent-runbook ${source}`,
|
|
251
|
+
`geo-ai-search-optimization agent-executor ${source}`,
|
|
241
252
|
`geo-ai-search-optimization apply-plan ${source}`
|
|
242
253
|
]
|
|
243
254
|
: [`geo-ai-search-optimization fix-plan ${source}`, `geo-ai-search-optimization owner-board ${source}`];
|
|
@@ -250,26 +261,31 @@ function buildCommandChain(detected, intent) {
|
|
|
250
261
|
];
|
|
251
262
|
case "geo-fix-plan":
|
|
252
263
|
return [
|
|
253
|
-
`geo-ai-search-optimization agent-handoff ${source}`,
|
|
254
264
|
`geo-ai-search-optimization agent-runbook ${source}`,
|
|
255
|
-
`geo-ai-search-optimization
|
|
265
|
+
`geo-ai-search-optimization agent-executor ${source}`,
|
|
266
|
+
`geo-ai-search-optimization completion-report ${source}`
|
|
256
267
|
];
|
|
257
268
|
case "geo-agent-handoff":
|
|
258
269
|
return [
|
|
259
270
|
`geo-ai-search-optimization agent-runbook ${source}`,
|
|
260
|
-
`geo-ai-search-optimization
|
|
271
|
+
`geo-ai-search-optimization agent-executor ${source}`,
|
|
261
272
|
`geo-ai-search-optimization completion-report ${source}`
|
|
262
273
|
];
|
|
263
274
|
case "geo-agent-runbook":
|
|
264
275
|
return [
|
|
265
|
-
`geo-ai-search-optimization
|
|
276
|
+
`geo-ai-search-optimization agent-executor ${source}`,
|
|
266
277
|
`geo-ai-search-optimization completion-report ${source}`,
|
|
267
278
|
`geo-ai-search-optimization handoff-bundle ${source}`
|
|
268
279
|
];
|
|
280
|
+
case "geo-agent-executor":
|
|
281
|
+
return [
|
|
282
|
+
`geo-ai-search-optimization completion-report ${source}`,
|
|
283
|
+
`geo-ai-search-optimization handoff-bundle ${source}`,
|
|
284
|
+
`geo-ai-search-optimization publish-pack ${source}`
|
|
285
|
+
];
|
|
269
286
|
case "geo-apply-plan":
|
|
270
287
|
return [
|
|
271
|
-
`geo-ai-search-optimization agent-
|
|
272
|
-
`geo-ai-search-optimization apply-plan ${source}`,
|
|
288
|
+
`geo-ai-search-optimization agent-executor ${source}`,
|
|
273
289
|
`geo-ai-search-optimization completion-report ${source}`,
|
|
274
290
|
`geo-ai-search-optimization handoff-bundle ${source}`
|
|
275
291
|
];
|
|
@@ -330,11 +346,11 @@ function pickSkillName(detected, intent) {
|
|
|
330
346
|
case "geo-report:onboarding":
|
|
331
347
|
return intent === "execute" ? "geo-ai-search-optimization-agent-handoff" : "geo-ai-search-optimization";
|
|
332
348
|
case "geo-fix-plan":
|
|
333
|
-
return "geo-ai-search-optimization-agent-handoff";
|
|
334
349
|
case "geo-agent-handoff":
|
|
335
350
|
case "geo-agent-runbook":
|
|
351
|
+
case "geo-agent-executor":
|
|
336
352
|
case "geo-apply-plan":
|
|
337
|
-
return "geo-ai-search-optimization-agent-
|
|
353
|
+
return "geo-ai-search-optimization-agent-executor";
|
|
338
354
|
case "geo-completion-report":
|
|
339
355
|
return "geo-ai-search-optimization-completion-report";
|
|
340
356
|
case "geo-handoff-bundle":
|
|
@@ -366,8 +382,11 @@ function buildSecondarySkillNames(primarySkill, intent, detected) {
|
|
|
366
382
|
}
|
|
367
383
|
if (
|
|
368
384
|
intent === "execute" ||
|
|
369
|
-
["geo-fix-plan", "geo-agent-handoff", "geo-agent-runbook", "geo-apply-plan"].includes(
|
|
385
|
+
["geo-fix-plan", "geo-agent-handoff", "geo-agent-runbook", "geo-agent-executor", "geo-apply-plan"].includes(
|
|
386
|
+
detected.artifactKind
|
|
387
|
+
)
|
|
370
388
|
) {
|
|
389
|
+
names.add("geo-ai-search-optimization-agent-executor");
|
|
371
390
|
names.add("geo-ai-search-optimization-agent-runbook");
|
|
372
391
|
names.add("geo-ai-search-optimization-agent-handoff");
|
|
373
392
|
names.add("geo-ai-search-optimization-repair-loop");
|
|
@@ -391,16 +410,26 @@ function buildStage(intent, detected) {
|
|
|
391
410
|
return "执行复盘";
|
|
392
411
|
}
|
|
393
412
|
if (intent === "execute") {
|
|
394
|
-
return [
|
|
395
|
-
|
|
396
|
-
|
|
413
|
+
return [
|
|
414
|
+
"geo-fix-plan",
|
|
415
|
+
"geo-agent-handoff",
|
|
416
|
+
"geo-agent-runbook",
|
|
417
|
+
"geo-agent-executor",
|
|
418
|
+
"geo-apply-plan",
|
|
419
|
+
"geo-handoff-bundle"
|
|
420
|
+
].includes(detected.artifactKind)
|
|
397
421
|
? "Agent 执行"
|
|
398
422
|
: "执行准备";
|
|
399
423
|
}
|
|
400
424
|
if (
|
|
401
|
-
[
|
|
402
|
-
|
|
403
|
-
|
|
425
|
+
[
|
|
426
|
+
"geo-fix-plan",
|
|
427
|
+
"geo-agent-handoff",
|
|
428
|
+
"geo-agent-runbook",
|
|
429
|
+
"geo-agent-executor",
|
|
430
|
+
"geo-apply-plan",
|
|
431
|
+
"geo-handoff-bundle"
|
|
432
|
+
].includes(detected.artifactKind)
|
|
404
433
|
) {
|
|
405
434
|
return "Agent 执行";
|
|
406
435
|
}
|
package/src/cli.js
CHANGED
|
@@ -2,6 +2,7 @@ import { fileURLToPath } from "node:url";
|
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { createApplyPlan, renderApplyPlanMarkdown, writeApplyPlanOutput } from "./apply-plan.js";
|
|
5
|
+
import { createAgentExecutor, renderAgentExecutorMarkdown, writeAgentExecutorOutput } from "./agent-executor.js";
|
|
5
6
|
import { createAgentHandoff, renderAgentHandoffMarkdown, writeAgentHandoffOutput } from "./agent-handoff.js";
|
|
6
7
|
import { createAgentRunbook, renderAgentRunbookMarkdown, writeAgentRunbookOutput } from "./agent-runbook.js";
|
|
7
8
|
import { createAgentSession, renderAgentSessionMarkdown, writeAgentSessionOutput } from "./agent-session.js";
|
|
@@ -63,6 +64,7 @@ function printHelp() {
|
|
|
63
64
|
" geo-ai-search-optimization auto-flow <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--json] [--out <file>]",
|
|
64
65
|
" geo-ai-search-optimization agent-session <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--json] [--out <file>]",
|
|
65
66
|
" geo-ai-search-optimization agent-runbook <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--task <id>] [--format <markdown|json>] [--out <file>]",
|
|
67
|
+
" geo-ai-search-optimization agent-executor <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--task <id>] [--format <markdown|json>] [--out <file>]",
|
|
66
68
|
" geo-ai-search-optimization skills [--json]",
|
|
67
69
|
" geo-ai-search-optimization where",
|
|
68
70
|
" geo-ai-search-optimization doctor [--json]",
|
|
@@ -206,6 +208,33 @@ async function handleAgentRunbook(args) {
|
|
|
206
208
|
process.stdout.write(renderedOutput);
|
|
207
209
|
}
|
|
208
210
|
|
|
211
|
+
async function handleAgentExecutor(args) {
|
|
212
|
+
const input = args.find((value) => !value.startsWith("-"));
|
|
213
|
+
if (!input) {
|
|
214
|
+
throw new Error("agent-executor 需要一个输入值,可以是任务描述、项目路径、网站网址或已导出的工件");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const format = getFlagValue(args, "--format");
|
|
218
|
+
const executor = await createAgentExecutor(input, {
|
|
219
|
+
intent: getFlagValue(args, "--intent"),
|
|
220
|
+
format,
|
|
221
|
+
taskId: getFlagValue(args, "--task")
|
|
222
|
+
});
|
|
223
|
+
const outputJson = format === "json";
|
|
224
|
+
const renderedOutput = outputJson
|
|
225
|
+
? `${JSON.stringify(executor, null, 2)}\n`
|
|
226
|
+
: renderAgentExecutorMarkdown(executor);
|
|
227
|
+
|
|
228
|
+
const outputPath = getFlagValue(args, "--out");
|
|
229
|
+
if (outputPath) {
|
|
230
|
+
const resolvedOutputPath = await writeAgentExecutorOutput(outputPath, renderedOutput);
|
|
231
|
+
process.stdout.write(`已保存 agent executor:${resolvedOutputPath}\n`);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
process.stdout.write(renderedOutput);
|
|
236
|
+
}
|
|
237
|
+
|
|
209
238
|
function handleWhere() {
|
|
210
239
|
process.stdout.write(
|
|
211
240
|
[
|
|
@@ -761,6 +790,11 @@ export async function runCli(args = []) {
|
|
|
761
790
|
return;
|
|
762
791
|
}
|
|
763
792
|
|
|
793
|
+
if (command === "agent-executor") {
|
|
794
|
+
await handleAgentExecutor(rest);
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
|
|
764
798
|
if (command === "skills") {
|
|
765
799
|
await handleSkills(rest);
|
|
766
800
|
return;
|
package/src/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export {
|
|
|
8
8
|
export { createAutoFlow, renderAutoFlowMarkdown, writeAutoFlowOutput } from "./auto-flow.js";
|
|
9
9
|
export { createApplyPlan, renderApplyPlanMarkdown, writeApplyPlanOutput } from "./apply-plan.js";
|
|
10
10
|
export { createAgentHandoff, renderAgentHandoffMarkdown, writeAgentHandoffOutput } from "./agent-handoff.js";
|
|
11
|
+
export { createAgentExecutor, renderAgentExecutorMarkdown, writeAgentExecutorOutput } from "./agent-executor.js";
|
|
11
12
|
export { createAgentRunbook, renderAgentRunbookMarkdown, writeAgentRunbookOutput } from "./agent-runbook.js";
|
|
12
13
|
export { createAgentSession, renderAgentSessionMarkdown, writeAgentSessionOutput } from "./agent-session.js";
|
|
13
14
|
export { createCompletionReport, renderCompletionReportMarkdown, writeCompletionReportOutput } from "./completion-report.js";
|
package/src/skills.js
CHANGED
|
@@ -7,6 +7,7 @@ const SKILL_ORDER = [
|
|
|
7
7
|
"geo-ai-search-optimization-auto-flow",
|
|
8
8
|
"geo-ai-search-optimization-agent-session",
|
|
9
9
|
"geo-ai-search-optimization-agent-runbook",
|
|
10
|
+
"geo-ai-search-optimization-agent-executor",
|
|
10
11
|
"geo-ai-search-optimization-usage",
|
|
11
12
|
"geo-ai-search-optimization-agent-handoff",
|
|
12
13
|
"geo-ai-search-optimization-repair-loop",
|
|
@@ -23,6 +24,7 @@ const SKILL_CATEGORY = {
|
|
|
23
24
|
"geo-ai-search-optimization-auto-flow": "routing",
|
|
24
25
|
"geo-ai-search-optimization-agent-session": "routing",
|
|
25
26
|
"geo-ai-search-optimization-agent-runbook": "execution",
|
|
27
|
+
"geo-ai-search-optimization-agent-executor": "execution",
|
|
26
28
|
"geo-ai-search-optimization-usage": "guidance",
|
|
27
29
|
"geo-ai-search-optimization-agent-handoff": "execution",
|
|
28
30
|
"geo-ai-search-optimization-repair-loop": "execution",
|
|
@@ -158,6 +160,7 @@ export function renderBundledSkillsMarkdown(bundle) {
|
|
|
158
160
|
"- 如果 agent 需要自动选 skill,先跑 auto-flow。",
|
|
159
161
|
"- 如果要给 agent 明确步骤,继续进入 agent-session。",
|
|
160
162
|
"- 如果要给 agent 一份执行手册和检查表,再进入 agent-runbook。",
|
|
163
|
+
"- 如果要直接告诉 agent 这轮先做哪 1 包,再进入 agent-executor。",
|
|
161
164
|
"- 再看 usage skill,知道什么时候该跑哪个命令。",
|
|
162
165
|
"- 如果要交给 agent 执行,再进入 handoff / apply / completion 这一条执行链。",
|
|
163
166
|
"- 如果要产出给团队分发,再进入 share / export / html / publish 这一条交付链。",
|