geo-ai-search-optimization 1.2.7 → 1.2.9
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 +70 -1
- 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-runbook/SKILL.md +24 -0
- package/resources/geo-ai-search-optimization-agent-runbook/agents/openai.yaml +4 -0
- package/resources/geo-ai-search-optimization-agent-session/SKILL.md +24 -0
- package/resources/geo-ai-search-optimization-agent-session/agents/openai.yaml +4 -0
- package/resources/geo-ai-search-optimization-usage/SKILL.md +24 -14
- package/src/agent-runbook.js +438 -0
- package/src/agent-session.js +307 -0
- package/src/auto-flow.js +35 -7
- package/src/cli.js +65 -0
- package/src/index.js +2 -0
- package/src/skills.js +6 -0
package/README.md
CHANGED
|
@@ -61,6 +61,48 @@ geo-ai-search-optimization auto-flow ./reports/apply-plan.json --json
|
|
|
61
61
|
- 建议命令顺序
|
|
62
62
|
- 可直接复制给 agent 的 prompt
|
|
63
63
|
|
|
64
|
+
## Agent Session 命令
|
|
65
|
+
|
|
66
|
+
如果你希望不只是“选 skill”,而是直接产出一份给 agent 跟着执行的会话包,可以用 `agent-session`:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
geo-ai-search-optimization agent-session "我想把这份 GEO 结果交给下一个 agent 继续修"
|
|
70
|
+
geo-ai-search-optimization agent-session https://example.com
|
|
71
|
+
geo-ai-search-optimization agent-session ./your-site
|
|
72
|
+
geo-ai-search-optimization agent-session ./reports/apply-plan.json --json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
它会输出:
|
|
76
|
+
|
|
77
|
+
- 当前阶段与会话状态
|
|
78
|
+
- 会话目标
|
|
79
|
+
- 自动选择的 skill
|
|
80
|
+
- 一步步该跑什么命令
|
|
81
|
+
- 每一步的目的与预期产物
|
|
82
|
+
- 可直接复制给 agent 的 session prompt
|
|
83
|
+
|
|
84
|
+
## Agent Runbook 命令
|
|
85
|
+
|
|
86
|
+
如果你希望 agent 拿到的不只是会话步骤,而是一份更稳定的执行手册和检查清单,可以直接用 `agent-runbook`:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
geo-ai-search-optimization agent-runbook "我想把这份 GEO 结果交给下一个 agent 继续修"
|
|
90
|
+
geo-ai-search-optimization agent-runbook https://example.com
|
|
91
|
+
geo-ai-search-optimization agent-runbook ./your-site
|
|
92
|
+
geo-ai-search-optimization agent-runbook ./reports/apply-plan.json --json
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
它会输出:
|
|
96
|
+
|
|
97
|
+
- 开始前检查
|
|
98
|
+
- 工作规则
|
|
99
|
+
- 需要停下来的情况
|
|
100
|
+
- 命令执行清单
|
|
101
|
+
- 重点执行包
|
|
102
|
+
- 验证清单
|
|
103
|
+
- 回报清单
|
|
104
|
+
- 可直接复制给 agent 的 runbook prompt
|
|
105
|
+
|
|
64
106
|
## Quick Start
|
|
65
107
|
|
|
66
108
|
如果你要从 0 到 1 启动一个 GEO 项目,建议照这个顺序做。
|
|
@@ -455,6 +497,8 @@ geo-ai-search-optimization
|
|
|
455
497
|
geo-ai-search-optimization install
|
|
456
498
|
geo-ai-search-optimization install --target ./tmp/custom-skills --json
|
|
457
499
|
geo-ai-search-optimization auto-flow "audit this site and tell me the next skill"
|
|
500
|
+
geo-ai-search-optimization agent-session ./your-site
|
|
501
|
+
geo-ai-search-optimization agent-runbook ./your-site
|
|
458
502
|
geo-ai-search-optimization skills
|
|
459
503
|
geo-ai-search-optimization where
|
|
460
504
|
geo-ai-search-optimization doctor
|
|
@@ -504,6 +548,20 @@ geo-ai-search-optimization help
|
|
|
504
548
|
- 输出推荐 skill、命令顺序与可直接复制给 agent 的 prompt
|
|
505
549
|
- 新增 `geo-ai-search-optimization-auto-flow` skill,作为 agent 的自动路由入口
|
|
506
550
|
|
|
551
|
+
## New in 1.2.8
|
|
552
|
+
|
|
553
|
+
- 新增 `agent-session` 命令,生成给 agent 跟着执行的会话包
|
|
554
|
+
- 在 `auto-flow` 之上补上步骤级说明、预期产物和 session prompt
|
|
555
|
+
- 新增 `geo-ai-search-optimization-agent-session` skill
|
|
556
|
+
- 更适合把 GEO 任务直接交给下一个 agent 连续推进
|
|
557
|
+
|
|
558
|
+
## New in 1.2.9
|
|
559
|
+
|
|
560
|
+
- 新增 `agent-runbook` 命令
|
|
561
|
+
- 把 `agent-session` 继续推进成给 agent 使用的执行手册和检查清单
|
|
562
|
+
- 输出开始前检查、工作规则、停止条件、验证清单、回报清单
|
|
563
|
+
- 新增 `geo-ai-search-optimization-agent-runbook` skill
|
|
564
|
+
|
|
507
565
|
## New in 1.2.5
|
|
508
566
|
|
|
509
567
|
- 新增 `publish-pack`
|
|
@@ -687,10 +745,21 @@ Override with:
|
|
|
687
745
|
|
|
688
746
|
## Resource contents
|
|
689
747
|
|
|
690
|
-
The installed package now includes
|
|
748
|
+
The installed package now includes a bundled GEO skill pack, including:
|
|
691
749
|
|
|
692
750
|
- `geo-ai-search-optimization`
|
|
751
|
+
- `geo-ai-search-optimization-auto-flow`
|
|
752
|
+
- `geo-ai-search-optimization-agent-session`
|
|
753
|
+
- `geo-ai-search-optimization-agent-runbook`
|
|
693
754
|
- `geo-ai-search-optimization-usage`
|
|
755
|
+
- `geo-ai-search-optimization-agent-handoff`
|
|
756
|
+
- `geo-ai-search-optimization-repair-loop`
|
|
757
|
+
- `geo-ai-search-optimization-completion-report`
|
|
758
|
+
- `geo-ai-search-optimization-handoff-bundle`
|
|
759
|
+
- `geo-ai-search-optimization-share-pack`
|
|
760
|
+
- `geo-ai-search-optimization-export-pack`
|
|
761
|
+
- `geo-ai-search-optimization-html-pack`
|
|
762
|
+
- `geo-ai-search-optimization-publish-pack`
|
|
694
763
|
|
|
695
764
|
## License
|
|
696
765
|
|
package/package.json
CHANGED
|
@@ -32,6 +32,26 @@ Best for:
|
|
|
32
32
|
- turning one-line task briefs into a concrete command sequence
|
|
33
33
|
- deciding whether the work should move into diagnosis, execution, closeout, or delivery
|
|
34
34
|
|
|
35
|
+
### `geo-ai-search-optimization-agent-session`
|
|
36
|
+
|
|
37
|
+
Use this when the next agent needs a runnable session plan, not just a routing answer.
|
|
38
|
+
|
|
39
|
+
Best for:
|
|
40
|
+
|
|
41
|
+
- turning `auto-flow` output into a step-by-step execution sequence
|
|
42
|
+
- giving the next agent a first command, second command, and expected artifact list
|
|
43
|
+
- reducing ambiguity at handoff time
|
|
44
|
+
|
|
45
|
+
### `geo-ai-search-optimization-agent-runbook`
|
|
46
|
+
|
|
47
|
+
Use this when the next agent needs an execution manual, not just a session sequence.
|
|
48
|
+
|
|
49
|
+
Best for:
|
|
50
|
+
|
|
51
|
+
- turning a GEO session into a checklist-driven runbook
|
|
52
|
+
- telling the next agent what to check before acting
|
|
53
|
+
- defining stop conditions, validation checklist, and reporting checklist
|
|
54
|
+
|
|
35
55
|
## Usage guide
|
|
36
56
|
|
|
37
57
|
### `geo-ai-search-optimization-usage`
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: geo-ai-search-optimization-agent-runbook
|
|
3
|
+
description: Turn a GEO input into an execution runbook for the next agent. Use when an agent needs more than routing or a session plan, and should receive a checklist-driven manual with preflight checks, stop conditions, validation steps, reporting expectations, and optional execution packets.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GEO Agent Runbook
|
|
7
|
+
|
|
8
|
+
Use this skill when the next agent should receive a practical runbook, not just a list of commands.
|
|
9
|
+
|
|
10
|
+
`GEO = Generative Engine Optimization`
|
|
11
|
+
|
|
12
|
+
## What it does
|
|
13
|
+
|
|
14
|
+
- turn a GEO input into a checklist-driven execution manual
|
|
15
|
+
- define what to check before acting
|
|
16
|
+
- define what should stop execution
|
|
17
|
+
- define how validation and reporting should work
|
|
18
|
+
- carry the next agent from session planning into disciplined execution
|
|
19
|
+
|
|
20
|
+
## Best use
|
|
21
|
+
|
|
22
|
+
- when `agent-session` is still too light and the next agent needs a more operational checklist
|
|
23
|
+
- when a PM or another agent wants a stable “follow this runbook” artifact
|
|
24
|
+
- when execution needs preflight, validation, and reporting rules
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "GEO Agent Runbook"
|
|
3
|
+
short_description: "Build a checklist-driven GEO execution manual"
|
|
4
|
+
default_prompt: "Use $geo-ai-search-optimization-agent-runbook to turn this input into a GEO runbook with preflight checks, execution checklist, validation steps, and reporting guidance."
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: geo-ai-search-optimization-agent-session
|
|
3
|
+
description: Turn a GEO input into a step-by-step agent session plan. Use when an agent should not only pick the next GEO skill, but also receive a runnable session sequence with step goals, expected artifacts, and a copyable session prompt.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GEO Agent Session
|
|
7
|
+
|
|
8
|
+
Use this skill when the next agent should receive a full GEO session plan instead of only a routing recommendation.
|
|
9
|
+
|
|
10
|
+
`GEO = Generative Engine Optimization`
|
|
11
|
+
|
|
12
|
+
## What it does
|
|
13
|
+
|
|
14
|
+
- choose the current GEO stage
|
|
15
|
+
- choose the right next skill
|
|
16
|
+
- build a step-by-step command sequence
|
|
17
|
+
- explain what each step should produce
|
|
18
|
+
- generate a copyable session prompt
|
|
19
|
+
|
|
20
|
+
## Best use
|
|
21
|
+
|
|
22
|
+
- start a new agent run from a URL, project directory, or GEO artifact
|
|
23
|
+
- turn `auto-flow` output into an execution-ready session
|
|
24
|
+
- hand another agent a clear “do this first, then this” sequence
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "GEO Agent Session"
|
|
3
|
+
short_description: "Build a runnable GEO session for the next agent"
|
|
4
|
+
default_prompt: "Use $geo-ai-search-optimization-agent-session to turn this input into a runnable GEO agent session with step order, expected outputs, and a session prompt."
|
|
@@ -13,22 +13,24 @@ 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 sixteen layers:
|
|
17
17
|
|
|
18
18
|
1. `auto-flow`: auto-select the next skill and command chain
|
|
19
|
-
2. `
|
|
20
|
-
3. `
|
|
21
|
-
4. `
|
|
22
|
-
5. `
|
|
23
|
-
6. `
|
|
24
|
-
7. `
|
|
25
|
-
8. `
|
|
26
|
-
9. `
|
|
27
|
-
10. `
|
|
28
|
-
11. `
|
|
29
|
-
12. `
|
|
30
|
-
13. `
|
|
31
|
-
14. `
|
|
19
|
+
2. `agent-session`: build a runnable session for the next agent
|
|
20
|
+
3. `agent-runbook`: execution manual and checklist for the next agent
|
|
21
|
+
4. `skills`: inspect the bundled skill package
|
|
22
|
+
5. `onboard-url` / `onboard`: first look
|
|
23
|
+
6. `scan`: raw signal check
|
|
24
|
+
7. `audit` / `report`: diagnosis
|
|
25
|
+
8. `fix-plan` / `owner-board`: execution planning
|
|
26
|
+
9. `agent-handoff`: agent takeover package
|
|
27
|
+
10. `apply-plan`: execution loop
|
|
28
|
+
11. `completion-report`: closeout
|
|
29
|
+
12. `handoff-bundle`: all-in-one package
|
|
30
|
+
13. `share-pack`: audience-ready delivery
|
|
31
|
+
14. `export-pack`: folder export
|
|
32
|
+
15. `html-pack` / `publish-pack`: browsable and final delivery output
|
|
33
|
+
16. `pm-brief` / `roadmap`: stakeholder alignment
|
|
32
34
|
|
|
33
35
|
## Recommended command order
|
|
34
36
|
|
|
@@ -36,6 +38,8 @@ If the user only has a website URL:
|
|
|
36
38
|
|
|
37
39
|
```bash
|
|
38
40
|
npx geo-ai-search-optimization auto-flow https://example.com
|
|
41
|
+
npx geo-ai-search-optimization agent-session https://example.com
|
|
42
|
+
npx geo-ai-search-optimization agent-runbook https://example.com
|
|
39
43
|
npx geo-ai-search-optimization onboard-url https://example.com
|
|
40
44
|
npx geo-ai-search-optimization pm-brief https://example.com
|
|
41
45
|
npx geo-ai-search-optimization roadmap https://example.com
|
|
@@ -45,6 +49,8 @@ If the user has the website codebase:
|
|
|
45
49
|
|
|
46
50
|
```bash
|
|
47
51
|
npx geo-ai-search-optimization auto-flow ./your-site
|
|
52
|
+
npx geo-ai-search-optimization agent-session ./your-site
|
|
53
|
+
npx geo-ai-search-optimization agent-runbook ./your-site
|
|
48
54
|
npx geo-ai-search-optimization scan ./your-site
|
|
49
55
|
npx geo-ai-search-optimization audit ./your-site
|
|
50
56
|
npx geo-ai-search-optimization fix-plan ./your-site
|
|
@@ -63,6 +69,8 @@ npx geo-ai-search-optimization roadmap ./your-site
|
|
|
63
69
|
## When to recommend each command
|
|
64
70
|
|
|
65
71
|
- `auto-flow`: auto-select the next skill and command order from a task brief, URL, project path, or GEO artifact
|
|
72
|
+
- `agent-session`: build a step-by-step session packet for the next agent from the same kinds of inputs
|
|
73
|
+
- `agent-runbook`: build a checklist-driven runbook with preflight, validation, and reporting rules
|
|
66
74
|
- `onboard-url`: first-time website check from a live URL
|
|
67
75
|
- `onboard`: interactive first-time onboarding
|
|
68
76
|
- `skills`: list the bundled skills and decide which skill or command chain fits the task
|
|
@@ -88,6 +96,8 @@ When explaining the tool to a user:
|
|
|
88
96
|
|
|
89
97
|
- prefer telling them which command to run next, not listing every command
|
|
90
98
|
- if the user or the next agent is unsure where to start, move them to `auto-flow` first
|
|
99
|
+
- if the user wants something the next agent can follow step by step, move them to `agent-session`
|
|
100
|
+
- if the user wants the next agent to follow a checklist and execution manual, move them to `agent-runbook`
|
|
91
101
|
- explain the result in PM language, not implementation jargon
|
|
92
102
|
- if the user sounds new, start with `onboard-url` or `quick-start`
|
|
93
103
|
- if the user wants another agent to take over, move them to `agent-handoff`
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { createApplyPlan } from "./apply-plan.js";
|
|
3
|
+
import { createAgentSession } from "./agent-session.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-runbook 格式:${format}。可选值:${Array.from(VALID_FORMATS).join(", ")}`);
|
|
12
|
+
}
|
|
13
|
+
return resolved;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function tryCreateExecutionPlan(input, options, session) {
|
|
17
|
+
if (session.sourceType === "json" && session.artifactKind === "geo-apply-plan") {
|
|
18
|
+
const parsed = JSON.parse(await readFile(input, "utf8"));
|
|
19
|
+
if (parsed?.kind === "geo-apply-plan") {
|
|
20
|
+
return parsed;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (session.sourceType === "task-text" || session.intent === "guide") {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
return await createApplyPlan(input, {
|
|
30
|
+
format: "json",
|
|
31
|
+
taskId: options.taskId
|
|
32
|
+
});
|
|
33
|
+
} catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function inferRunbookMode(session, executionPlan) {
|
|
39
|
+
if (session.intent === "share") {
|
|
40
|
+
return "delivery-support";
|
|
41
|
+
}
|
|
42
|
+
if (session.intent === "closeout") {
|
|
43
|
+
return "closeout-support";
|
|
44
|
+
}
|
|
45
|
+
if (executionPlan?.executionType === "direct-fix") {
|
|
46
|
+
return "hands-on-fix";
|
|
47
|
+
}
|
|
48
|
+
if (executionPlan?.executionType === "recommendation-only") {
|
|
49
|
+
return "advisory-runbook";
|
|
50
|
+
}
|
|
51
|
+
if (executionPlan?.executionType === "guided-planning") {
|
|
52
|
+
return "guided-preparation";
|
|
53
|
+
}
|
|
54
|
+
if (session.intent === "execute") {
|
|
55
|
+
return "execution-preparation";
|
|
56
|
+
}
|
|
57
|
+
return "diagnostic-runbook";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function buildModeSummary(mode) {
|
|
61
|
+
switch (mode) {
|
|
62
|
+
case "hands-on-fix":
|
|
63
|
+
return "当前已经接近可直接动手修复的状态,runbook 应优先帮助 agent 在仓库里按检查表推进。";
|
|
64
|
+
case "advisory-runbook":
|
|
65
|
+
return "当前更适合输出结构化建议和修复手册,不要假装已经拥有仓库写入权限。";
|
|
66
|
+
case "guided-preparation":
|
|
67
|
+
return "当前已有部分执行工件,但还需要一个更稳定的执行手册来控制顺序和验收。";
|
|
68
|
+
case "delivery-support":
|
|
69
|
+
return "当前重点是把 GEO 结果整理成交付物,而不是重新做大范围诊断。";
|
|
70
|
+
case "closeout-support":
|
|
71
|
+
return "当前重点是整理完成情况、剩余风险和下一轮动作。";
|
|
72
|
+
case "execution-preparation":
|
|
73
|
+
return "当前需要把诊断结果继续推进成 agent 可执行的链路和检查表。";
|
|
74
|
+
default:
|
|
75
|
+
return "当前仍以诊断和建立执行方向为主,runbook 用于稳定下一步顺序。";
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function buildPreflightChecklist(session, executionPlan, mode) {
|
|
80
|
+
const items = [
|
|
81
|
+
`确认当前输入 \`${session.source}\` 是最新的,而不是过期工件。`,
|
|
82
|
+
`确认这轮目标仍然是:${session.goal}`
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
if (session.sourceType === "directory") {
|
|
86
|
+
items.push("确认当前目录就是可编辑的网站项目根目录,并且可以运行 CLI 复测命令。");
|
|
87
|
+
} else if (session.sourceType === "url") {
|
|
88
|
+
items.push("确认当前只有公开网址可见,不要把线上观察误写成已经完成代码修改。");
|
|
89
|
+
} else if (session.sourceType === "json" || session.sourceType === "file") {
|
|
90
|
+
items.push("确认当前工件和目标站点版本一致,避免基于旧结果继续执行。");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (executionPlan?.executionType === "direct-fix") {
|
|
94
|
+
items.push("开始前先找模板层、metadata helper、schema 输出点,不要一上来只 patch 单页。");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (session.contextNeeded.length > 0) {
|
|
98
|
+
for (const item of session.contextNeeded) {
|
|
99
|
+
items.push(`补齐上下文:${item}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (mode === "delivery-support") {
|
|
104
|
+
items.push("确认这轮重点是整理对外产物,不要重复打开无关的诊断分支。");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return items;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function buildOperatingRules(session, executionPlan, mode) {
|
|
111
|
+
const items = [
|
|
112
|
+
"所有输出都要保持 PM 可读,避免只给技术术语不给业务含义。",
|
|
113
|
+
"每完成一步,都说明为什么这样做、得到什么、下一步是什么。",
|
|
114
|
+
"优先修复可复用模板、metadata helper、schema 生成逻辑,而不是只修一页。",
|
|
115
|
+
"如果没有仓库或写入权限,不要声称已经完成代码修改。"
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
if (executionPlan?.executionType === "direct-fix") {
|
|
119
|
+
items.push("每做完一轮修改,就要立刻复跑至少一条 GEO CLI 验证命令。");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (mode === "delivery-support") {
|
|
123
|
+
items.push("交付阶段以整理和包装结果为主,不要在没有必要时重新定义优先级。");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (mode === "closeout-support") {
|
|
127
|
+
items.push("收尾阶段必须清楚区分:已完成、未完成、待验证、下一轮任务。");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return items;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function buildStopConditions(session, executionPlan) {
|
|
134
|
+
const items = [
|
|
135
|
+
"找不到当前输入对应的网站、项目目录或工件,无法确认执行对象。",
|
|
136
|
+
"CLI 输出与当前假设冲突,例如问题区域和已有工件不一致。",
|
|
137
|
+
"无法给出明确验收标准时,不要继续扩大范围。"
|
|
138
|
+
];
|
|
139
|
+
|
|
140
|
+
if (executionPlan?.executionType === "direct-fix") {
|
|
141
|
+
items.push("明明需要直接修复,但拿不到仓库、模板或关键文件时,应先停下并说明缺的上下文。");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (session.sourceType === "url") {
|
|
145
|
+
items.push("只有网址没有仓库时,不要进入假想修复,应切回建议模式。");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return items;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function buildCommandChecklist(steps) {
|
|
152
|
+
return steps.map((step, index) => {
|
|
153
|
+
const doneWhen = [
|
|
154
|
+
`已经运行或明确评估:\`${step.command}\``,
|
|
155
|
+
`已经拿到或确认:${step.expectedArtifact}`,
|
|
156
|
+
"已经记录本步结论,并说明下一步是否需要继续"
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
if (index === 0) {
|
|
160
|
+
doneWhen.push("已经确认第一步不是跑偏,而是符合当前会话阶段。");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
id: step.id,
|
|
165
|
+
command: step.command,
|
|
166
|
+
commandName: step.commandName,
|
|
167
|
+
suggestedSkill: step.suggestedSkill,
|
|
168
|
+
purpose: step.purpose,
|
|
169
|
+
expectedArtifact: step.expectedArtifact,
|
|
170
|
+
instructions: step.instructions,
|
|
171
|
+
doneWhen
|
|
172
|
+
};
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function buildExecutionPackets(executionPlan) {
|
|
177
|
+
if (!executionPlan) {
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return executionPlan.packets.map((packet) => ({
|
|
182
|
+
id: packet.id,
|
|
183
|
+
title: packet.title,
|
|
184
|
+
priority: packet.priority,
|
|
185
|
+
owner: packet.owner,
|
|
186
|
+
executionType: packet.executionType,
|
|
187
|
+
inspectTargets: packet.inspectTargets,
|
|
188
|
+
editPlan: packet.editPlan,
|
|
189
|
+
validationCommands: packet.validationCommands,
|
|
190
|
+
deliverables: packet.deliverables,
|
|
191
|
+
doneWhen: packet.doneWhen
|
|
192
|
+
}));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function buildValidationChecklist(session, executionPlan) {
|
|
196
|
+
const items = [];
|
|
197
|
+
|
|
198
|
+
if (executionPlan?.packets?.length) {
|
|
199
|
+
const commands = Array.from(
|
|
200
|
+
new Set(executionPlan.packets.flatMap((packet) => packet.validationCommands || []))
|
|
201
|
+
);
|
|
202
|
+
for (const command of commands) {
|
|
203
|
+
items.push(`复跑验证命令:\`${command}\``);
|
|
204
|
+
}
|
|
205
|
+
} else if (session.steps.length > 0) {
|
|
206
|
+
items.push(`至少重新确认第一条关键命令是否已达成预期:\`${session.steps[0].command}\``);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
items.push("确认最高优先级问题是否真的下降,而不是只改变了表述。");
|
|
210
|
+
items.push("确认输出仍然能解释:哪里被修复、哪里还没修、下一步是什么。");
|
|
211
|
+
|
|
212
|
+
if (session.sourceType === "url") {
|
|
213
|
+
items.push("如果只有网址,验证重点应放在公开可观察信号和建议质量,而不是虚构代码变更。");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return items;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function buildReportingChecklist(session, executionPlan) {
|
|
220
|
+
const items = [
|
|
221
|
+
"总结这轮做了什么,按问题区域或任务包分组,而不是只贴命令输出。",
|
|
222
|
+
"明确剩余风险、未完成项和下一轮最该先做的 1 到 3 件事。",
|
|
223
|
+
"告诉用户下一位 agent 或下一轮流程应该从哪个命令继续。"
|
|
224
|
+
];
|
|
225
|
+
|
|
226
|
+
if (executionPlan?.executionType === "direct-fix") {
|
|
227
|
+
items.push("回报时带上复测命令和结果,说明这次修复是否真的改变了 GEO 状态。");
|
|
228
|
+
} else {
|
|
229
|
+
items.push("回报时明确哪些建议还需要仓库、权限或更多页面上下文才能继续落地。");
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (session.intent === "share") {
|
|
233
|
+
items.push("如果这轮目标是交付,回报里要说明应该把结果发给谁,以及推荐使用哪个分享包。");
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return items;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function buildNextCommands(session, executionPlan) {
|
|
240
|
+
if (session.intent === "share") {
|
|
241
|
+
return [
|
|
242
|
+
`geo-ai-search-optimization share-pack ${session.source}`,
|
|
243
|
+
`geo-ai-search-optimization publish-pack ${session.source}`
|
|
244
|
+
];
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (session.intent === "closeout") {
|
|
248
|
+
return [
|
|
249
|
+
`geo-ai-search-optimization completion-report ${session.source}`,
|
|
250
|
+
`geo-ai-search-optimization handoff-bundle ${session.source}`
|
|
251
|
+
];
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (executionPlan) {
|
|
255
|
+
return [
|
|
256
|
+
`geo-ai-search-optimization apply-plan ${session.source}`,
|
|
257
|
+
`geo-ai-search-optimization completion-report ${session.source}`
|
|
258
|
+
];
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return session.steps.slice(0, 2).map((step) => step.command);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function buildRunbookPrompt(session, runbookMode, executionPackets) {
|
|
265
|
+
const lines = [
|
|
266
|
+
`Use $geo-ai-search-optimization-agent-runbook to continue this GEO task.`,
|
|
267
|
+
`当前输入:${session.source}`,
|
|
268
|
+
`当前阶段:${session.stage}`,
|
|
269
|
+
`当前意图:${session.intent}`,
|
|
270
|
+
`runbook 模式:${runbookMode}`,
|
|
271
|
+
`目标:${session.goal}`,
|
|
272
|
+
"请按下面顺序推进:",
|
|
273
|
+
"1. 先执行开始前检查。",
|
|
274
|
+
"2. 再按命令执行清单推进。",
|
|
275
|
+
"3. 如果有重点执行包,优先做最高优先级那一包。",
|
|
276
|
+
"4. 每完成一轮动作,都做验证清单。",
|
|
277
|
+
"5. 最后按回报清单整理给用户的结果。"
|
|
278
|
+
];
|
|
279
|
+
|
|
280
|
+
if (executionPackets.length > 0) {
|
|
281
|
+
lines.push("当前重点执行包:");
|
|
282
|
+
for (const packet of executionPackets) {
|
|
283
|
+
lines.push(`- ${packet.priority}|${packet.title}`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (session.contextNeeded.length > 0) {
|
|
288
|
+
lines.push("如果上下文不足,必须先明确缺什么,再决定是否继续。");
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return lines.join("\n");
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export async function createAgentRunbook(input, options = {}) {
|
|
295
|
+
const format = normalizeFormat(options.format);
|
|
296
|
+
const session = await createAgentSession(input, {
|
|
297
|
+
intent: options.intent
|
|
298
|
+
});
|
|
299
|
+
const executionPlan = await tryCreateExecutionPlan(input, options, session);
|
|
300
|
+
const runbookMode = inferRunbookMode(session, executionPlan);
|
|
301
|
+
const commandChecklist = buildCommandChecklist(session.steps);
|
|
302
|
+
const executionPackets = buildExecutionPackets(executionPlan);
|
|
303
|
+
|
|
304
|
+
return {
|
|
305
|
+
kind: "geo-agent-runbook",
|
|
306
|
+
input,
|
|
307
|
+
source: session.source,
|
|
308
|
+
sourceType: session.sourceType,
|
|
309
|
+
artifactKind: session.artifactKind,
|
|
310
|
+
format,
|
|
311
|
+
intent: session.intent,
|
|
312
|
+
stage: session.stage,
|
|
313
|
+
status: session.status,
|
|
314
|
+
runbookMode,
|
|
315
|
+
modeSummary: buildModeSummary(runbookMode),
|
|
316
|
+
goal: session.goal,
|
|
317
|
+
selectedSkill: session.selectedSkill,
|
|
318
|
+
secondarySkills: session.secondarySkills,
|
|
319
|
+
whyThisSkill: session.whyThisSkill,
|
|
320
|
+
nextAction: session.nextAction,
|
|
321
|
+
preflightChecklist: buildPreflightChecklist(session, executionPlan, runbookMode),
|
|
322
|
+
operatingRules: buildOperatingRules(session, executionPlan, runbookMode),
|
|
323
|
+
stopConditions: buildStopConditions(session, executionPlan),
|
|
324
|
+
commandChecklist,
|
|
325
|
+
executionPackets,
|
|
326
|
+
validationChecklist: buildValidationChecklist(session, executionPlan),
|
|
327
|
+
reportingChecklist: buildReportingChecklist(session, executionPlan),
|
|
328
|
+
nextCommands: buildNextCommands(session, executionPlan),
|
|
329
|
+
runbookPrompt: buildRunbookPrompt(session, runbookMode, executionPackets),
|
|
330
|
+
agentSession: session,
|
|
331
|
+
applyPlan: executionPlan
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export function renderAgentRunbookMarkdown(runbook) {
|
|
336
|
+
const lines = [
|
|
337
|
+
"# GEO Agent Runbook",
|
|
338
|
+
"",
|
|
339
|
+
`- 输入:\`${runbook.source}\``,
|
|
340
|
+
`- 输入类型:\`${runbook.sourceType}\``,
|
|
341
|
+
`- 工件类型:\`${runbook.artifactKind}\``,
|
|
342
|
+
`- 当前阶段:${runbook.stage}`,
|
|
343
|
+
`- 当前状态:${runbook.status}`,
|
|
344
|
+
`- runbook 模式:\`${runbook.runbookMode}\``,
|
|
345
|
+
`- 模式说明:${runbook.modeSummary}`,
|
|
346
|
+
`- 目标:${runbook.goal}`,
|
|
347
|
+
`- 当前主 skill:\`${runbook.selectedSkill.name}\``,
|
|
348
|
+
"",
|
|
349
|
+
"## 开始前检查",
|
|
350
|
+
""
|
|
351
|
+
];
|
|
352
|
+
|
|
353
|
+
for (const item of runbook.preflightChecklist) {
|
|
354
|
+
lines.push(`- [ ] ${item}`);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
lines.push("", "## 工作规则", "");
|
|
358
|
+
for (const item of runbook.operatingRules) {
|
|
359
|
+
lines.push(`- [ ] ${item}`);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
lines.push("", "## 需要停下来的情况", "");
|
|
363
|
+
for (const item of runbook.stopConditions) {
|
|
364
|
+
lines.push(`- [ ] ${item}`);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
lines.push("", "## 命令执行清单", "");
|
|
368
|
+
for (const item of runbook.commandChecklist) {
|
|
369
|
+
lines.push(`### ${item.id}|${item.commandName}`, "");
|
|
370
|
+
lines.push(`- 命令:\`${item.command}\``);
|
|
371
|
+
lines.push(`- 建议 skill:\`${item.suggestedSkill}\``);
|
|
372
|
+
lines.push(`- 目的:${item.purpose}`);
|
|
373
|
+
lines.push(`- 预期产物:${item.expectedArtifact}`);
|
|
374
|
+
lines.push("- 操作说明:");
|
|
375
|
+
for (const instruction of item.instructions) {
|
|
376
|
+
lines.push(` - ${instruction}`);
|
|
377
|
+
}
|
|
378
|
+
lines.push("- 完成标准:");
|
|
379
|
+
for (const doneWhen of item.doneWhen) {
|
|
380
|
+
lines.push(` - [ ] ${doneWhen}`);
|
|
381
|
+
}
|
|
382
|
+
lines.push("");
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (runbook.executionPackets.length > 0) {
|
|
386
|
+
lines.push("## 重点执行包", "");
|
|
387
|
+
for (const packet of runbook.executionPackets) {
|
|
388
|
+
lines.push(`### ${packet.id}|${packet.title}`, "");
|
|
389
|
+
lines.push(`- 优先级:${packet.priority}`);
|
|
390
|
+
lines.push(`- Owner:${packet.owner}`);
|
|
391
|
+
lines.push(`- 执行类型:\`${packet.executionType}\``);
|
|
392
|
+
lines.push("- 先检查:");
|
|
393
|
+
for (const target of packet.inspectTargets) {
|
|
394
|
+
lines.push(` - [ ] ${target}`);
|
|
395
|
+
}
|
|
396
|
+
lines.push("- 建议动作:");
|
|
397
|
+
for (const step of packet.editPlan) {
|
|
398
|
+
lines.push(` - [ ] ${step}`);
|
|
399
|
+
}
|
|
400
|
+
lines.push("- 验证命令:");
|
|
401
|
+
for (const command of packet.validationCommands) {
|
|
402
|
+
lines.push(` - \`${command}\``);
|
|
403
|
+
}
|
|
404
|
+
lines.push("- 交付物:");
|
|
405
|
+
for (const item of packet.deliverables) {
|
|
406
|
+
lines.push(` - ${item}`);
|
|
407
|
+
}
|
|
408
|
+
lines.push("- Done when:");
|
|
409
|
+
for (const item of packet.doneWhen) {
|
|
410
|
+
lines.push(` - [ ] ${item}`);
|
|
411
|
+
}
|
|
412
|
+
lines.push("");
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
lines.push("## 验证清单", "");
|
|
417
|
+
for (const item of runbook.validationChecklist) {
|
|
418
|
+
lines.push(`- [ ] ${item}`);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
lines.push("", "## 回报清单", "");
|
|
422
|
+
for (const item of runbook.reportingChecklist) {
|
|
423
|
+
lines.push(`- [ ] ${item}`);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
lines.push("", "## 下一步推荐命令", "");
|
|
427
|
+
for (const command of runbook.nextCommands) {
|
|
428
|
+
lines.push(`- \`${command}\``);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
lines.push("", "## 可直接复制给 Agent 的 Runbook Prompt", "", "```text", runbook.runbookPrompt, "```");
|
|
432
|
+
|
|
433
|
+
return `${lines.join("\n")}\n`;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export async function writeAgentRunbookOutput(outputPath, content) {
|
|
437
|
+
return writeScanOutput(outputPath, content);
|
|
438
|
+
}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { createAutoFlow } from "./auto-flow.js";
|
|
2
|
+
import { writeScanOutput } from "./scan.js";
|
|
3
|
+
|
|
4
|
+
function inferSessionStatus(flow) {
|
|
5
|
+
if (flow.contextNeeded.length > 0) {
|
|
6
|
+
return "needs-context";
|
|
7
|
+
}
|
|
8
|
+
if (flow.intent === "share") {
|
|
9
|
+
return "delivery-ready";
|
|
10
|
+
}
|
|
11
|
+
if (flow.intent === "closeout") {
|
|
12
|
+
return "closeout-ready";
|
|
13
|
+
}
|
|
14
|
+
if (flow.intent === "execute") {
|
|
15
|
+
return "execution-ready";
|
|
16
|
+
}
|
|
17
|
+
return "analysis-ready";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function inferSessionGoal(flow) {
|
|
21
|
+
if (flow.intent === "share") {
|
|
22
|
+
return "把当前 GEO 结果整理成适合分享、外发或交接的产物。";
|
|
23
|
+
}
|
|
24
|
+
if (flow.intent === "closeout") {
|
|
25
|
+
return "整理本轮 GEO 执行结果、剩余风险和下一轮任务。";
|
|
26
|
+
}
|
|
27
|
+
if (flow.intent === "execute") {
|
|
28
|
+
return "把当前输入推进到 agent 可接手、可执行、可验证的 GEO 修复链。";
|
|
29
|
+
}
|
|
30
|
+
if (flow.intent === "guide") {
|
|
31
|
+
return "明确现在该用哪个 skill、该跑哪些命令,以及先后顺序。";
|
|
32
|
+
}
|
|
33
|
+
return "建立当前 GEO 状态、优先级和下一步执行方向。";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function parseCommand(command) {
|
|
37
|
+
const parts = String(command).trim().split(/\s+/);
|
|
38
|
+
const commandName = parts[1] || parts[0] || "";
|
|
39
|
+
return {
|
|
40
|
+
raw: command,
|
|
41
|
+
commandName
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function inferSkillForCommand(commandName, flow) {
|
|
46
|
+
if (commandName === "auto-flow") {
|
|
47
|
+
return "geo-ai-search-optimization-auto-flow";
|
|
48
|
+
}
|
|
49
|
+
if (commandName === "agent-runbook") {
|
|
50
|
+
return "geo-ai-search-optimization-agent-runbook";
|
|
51
|
+
}
|
|
52
|
+
if (commandName === "skills" || commandName === "quick-start") {
|
|
53
|
+
return "geo-ai-search-optimization-usage";
|
|
54
|
+
}
|
|
55
|
+
if (["share-pack"].includes(commandName)) {
|
|
56
|
+
return "geo-ai-search-optimization-share-pack";
|
|
57
|
+
}
|
|
58
|
+
if (["export-pack"].includes(commandName)) {
|
|
59
|
+
return "geo-ai-search-optimization-export-pack";
|
|
60
|
+
}
|
|
61
|
+
if (["html-pack"].includes(commandName)) {
|
|
62
|
+
return "geo-ai-search-optimization-html-pack";
|
|
63
|
+
}
|
|
64
|
+
if (["publish-pack"].includes(commandName)) {
|
|
65
|
+
return "geo-ai-search-optimization-publish-pack";
|
|
66
|
+
}
|
|
67
|
+
if (["agent-handoff"].includes(commandName)) {
|
|
68
|
+
return "geo-ai-search-optimization-agent-handoff";
|
|
69
|
+
}
|
|
70
|
+
if (["apply-plan"].includes(commandName)) {
|
|
71
|
+
return "geo-ai-search-optimization-repair-loop";
|
|
72
|
+
}
|
|
73
|
+
if (["completion-report"].includes(commandName)) {
|
|
74
|
+
return "geo-ai-search-optimization-completion-report";
|
|
75
|
+
}
|
|
76
|
+
if (["handoff-bundle"].includes(commandName)) {
|
|
77
|
+
return "geo-ai-search-optimization-handoff-bundle";
|
|
78
|
+
}
|
|
79
|
+
if (["onboard", "onboard-url", "scan", "audit", "report", "fix-plan", "owner-board", "pm-brief", "roadmap", "meeting-pack", "exec-summary"].includes(commandName)) {
|
|
80
|
+
return flow.selectedSkill.name === "geo-ai-search-optimization-usage"
|
|
81
|
+
? "geo-ai-search-optimization"
|
|
82
|
+
: flow.selectedSkill.name;
|
|
83
|
+
}
|
|
84
|
+
return flow.selectedSkill.name;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function inferStepPurpose(commandName, flow) {
|
|
88
|
+
switch (commandName) {
|
|
89
|
+
case "skills":
|
|
90
|
+
return "先理解当前技能包结构,避免 agent 选错链路。";
|
|
91
|
+
case "quick-start":
|
|
92
|
+
return "快速建立从 0 到 1 的执行顺序。";
|
|
93
|
+
case "onboard":
|
|
94
|
+
case "onboard-url":
|
|
95
|
+
return "先从网址或引导流程拿到首轮 GEO 判断。";
|
|
96
|
+
case "scan":
|
|
97
|
+
return "先做原始信号扫描,确认基础缺口。";
|
|
98
|
+
case "audit":
|
|
99
|
+
return "拿到分数、问题区域和优先级。";
|
|
100
|
+
case "report":
|
|
101
|
+
return "把当前结果整理成可读报告。";
|
|
102
|
+
case "fix-plan":
|
|
103
|
+
return "把诊断结果转成待办和优先级。";
|
|
104
|
+
case "owner-board":
|
|
105
|
+
return "把任务按角色拆开,方便 PM 与执行团队分工。";
|
|
106
|
+
case "pm-brief":
|
|
107
|
+
return "先给 PM 一个可快速理解的摘要。";
|
|
108
|
+
case "roadmap":
|
|
109
|
+
return "把修复顺序转成阶段计划。";
|
|
110
|
+
case "agent-handoff":
|
|
111
|
+
return "把当前结果交接成 agent 可继续执行的工件。";
|
|
112
|
+
case "agent-runbook":
|
|
113
|
+
return "把当前链路整理成 agent 可照着执行的手册和检查表。";
|
|
114
|
+
case "apply-plan":
|
|
115
|
+
return "把交接结果推进到具体执行包。";
|
|
116
|
+
case "completion-report":
|
|
117
|
+
return "整理本轮完成项、剩余风险和下一轮动作。";
|
|
118
|
+
case "handoff-bundle":
|
|
119
|
+
return "把交接、执行与复盘整成一个总包。";
|
|
120
|
+
case "share-pack":
|
|
121
|
+
return "给不同角色生成可直接分享的视图。";
|
|
122
|
+
case "export-pack":
|
|
123
|
+
return "把分享结果导出成目录文件。";
|
|
124
|
+
case "html-pack":
|
|
125
|
+
return "把产物转成可浏览页面。";
|
|
126
|
+
case "publish-pack":
|
|
127
|
+
return "形成最终可交付包。";
|
|
128
|
+
default:
|
|
129
|
+
return "推进当前 GEO 会话到下一阶段。";
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function inferExpectedArtifact(commandName) {
|
|
134
|
+
switch (commandName) {
|
|
135
|
+
case "onboard":
|
|
136
|
+
case "onboard-url":
|
|
137
|
+
return "网址级 onboarding 结果";
|
|
138
|
+
case "scan":
|
|
139
|
+
return "基础信号扫描结果";
|
|
140
|
+
case "audit":
|
|
141
|
+
return "GEO 审计结果";
|
|
142
|
+
case "report":
|
|
143
|
+
return "可读报告";
|
|
144
|
+
case "fix-plan":
|
|
145
|
+
return "待办清单与优先级";
|
|
146
|
+
case "owner-board":
|
|
147
|
+
return "角色分栏任务板";
|
|
148
|
+
case "pm-brief":
|
|
149
|
+
return "PM 摘要";
|
|
150
|
+
case "roadmap":
|
|
151
|
+
return "阶段路线图";
|
|
152
|
+
case "agent-handoff":
|
|
153
|
+
return "agent 交接工件";
|
|
154
|
+
case "agent-runbook":
|
|
155
|
+
return "agent 执行手册";
|
|
156
|
+
case "apply-plan":
|
|
157
|
+
return "执行包";
|
|
158
|
+
case "completion-report":
|
|
159
|
+
return "复盘工件";
|
|
160
|
+
case "handoff-bundle":
|
|
161
|
+
return "执行总包";
|
|
162
|
+
case "share-pack":
|
|
163
|
+
return "角色化分享包";
|
|
164
|
+
case "export-pack":
|
|
165
|
+
return "导出目录";
|
|
166
|
+
case "html-pack":
|
|
167
|
+
return "HTML 页面包";
|
|
168
|
+
case "publish-pack":
|
|
169
|
+
return "最终可交付包";
|
|
170
|
+
default:
|
|
171
|
+
return "阶段性 GEO 输出";
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function buildStepInstructions(parsedCommand, flow) {
|
|
176
|
+
const lines = [
|
|
177
|
+
`运行 \`${parsedCommand.raw}\`。`,
|
|
178
|
+
inferStepPurpose(parsedCommand.commandName, flow),
|
|
179
|
+
`预期得到:${inferExpectedArtifact(parsedCommand.commandName)}。`
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
if (parsedCommand.commandName === "publish-pack") {
|
|
183
|
+
lines.push("完成后把 `START-HERE.md` 和 `AGENT-START.md` 当作最终入口。");
|
|
184
|
+
}
|
|
185
|
+
if (parsedCommand.commandName === "apply-plan") {
|
|
186
|
+
lines.push("执行包出来后,优先从第一包开始,不要同时展开太多任务。");
|
|
187
|
+
}
|
|
188
|
+
if (parsedCommand.commandName === "agent-runbook") {
|
|
189
|
+
lines.push("先用 runbook 稳定顺序、检查项和回报方式,再开始真正执行。");
|
|
190
|
+
}
|
|
191
|
+
if (parsedCommand.commandName === "agent-handoff" && flow.intent === "execute") {
|
|
192
|
+
lines.push("如果还是 advice-only,说明还缺仓库或本地项目上下文。");
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return lines;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function buildSessionPrompt(flow, steps) {
|
|
199
|
+
const lines = [
|
|
200
|
+
`Use $${flow.selectedSkill.name} to continue this GEO session.`,
|
|
201
|
+
`当前输入:${flow.source}`,
|
|
202
|
+
`当前阶段:${flow.stage}`,
|
|
203
|
+
`当前意图:${flow.intent}`,
|
|
204
|
+
`会话目标:${inferSessionGoal(flow)}`,
|
|
205
|
+
"请按下面顺序推进,不要跳步骤:"
|
|
206
|
+
];
|
|
207
|
+
|
|
208
|
+
for (const step of steps) {
|
|
209
|
+
lines.push(`${step.id}. ${step.command}`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (flow.contextNeeded.length > 0) {
|
|
213
|
+
lines.push("如果当前缺上下文,请先明确缺什么,不要假装已经完成执行。");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
lines.push("每一步都要说明:你为什么做、得到什么、下一步是什么。");
|
|
217
|
+
return lines.join("\n");
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export async function createAgentSession(input, options = {}) {
|
|
221
|
+
const flow = await createAutoFlow(input, { intent: options.intent });
|
|
222
|
+
const steps = flow.commandChain.map((command, index) => {
|
|
223
|
+
const parsedCommand = parseCommand(command);
|
|
224
|
+
return {
|
|
225
|
+
id: `step-${String(index + 1).padStart(2, "0")}`,
|
|
226
|
+
command,
|
|
227
|
+
commandName: parsedCommand.commandName,
|
|
228
|
+
suggestedSkill: inferSkillForCommand(parsedCommand.commandName, flow),
|
|
229
|
+
purpose: inferStepPurpose(parsedCommand.commandName, flow),
|
|
230
|
+
expectedArtifact: inferExpectedArtifact(parsedCommand.commandName),
|
|
231
|
+
instructions: buildStepInstructions(parsedCommand, flow)
|
|
232
|
+
};
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
kind: "geo-agent-session",
|
|
237
|
+
input,
|
|
238
|
+
source: flow.source,
|
|
239
|
+
sourceType: flow.sourceType,
|
|
240
|
+
artifactKind: flow.artifactKind,
|
|
241
|
+
intent: flow.intent,
|
|
242
|
+
stage: flow.stage,
|
|
243
|
+
status: inferSessionStatus(flow),
|
|
244
|
+
goal: inferSessionGoal(flow),
|
|
245
|
+
selectedSkill: flow.selectedSkill,
|
|
246
|
+
secondarySkills: flow.secondarySkills,
|
|
247
|
+
whyThisSkill: flow.whyThisSkill,
|
|
248
|
+
contextNeeded: flow.contextNeeded,
|
|
249
|
+
nextAction: flow.nextAction,
|
|
250
|
+
steps,
|
|
251
|
+
sessionPrompt: buildSessionPrompt(flow, steps),
|
|
252
|
+
autoFlow: flow
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export function renderAgentSessionMarkdown(session) {
|
|
257
|
+
const lines = [
|
|
258
|
+
"# GEO Agent Session",
|
|
259
|
+
"",
|
|
260
|
+
`- 输入:\`${session.source}\``,
|
|
261
|
+
`- 输入类型:\`${session.sourceType}\``,
|
|
262
|
+
`- 工件类型:\`${session.artifactKind}\``,
|
|
263
|
+
`- 当前阶段:${session.stage}`,
|
|
264
|
+
`- 会话状态:${session.status}`,
|
|
265
|
+
`- 当前意图:${session.intent}`,
|
|
266
|
+
`- 目标:${session.goal}`,
|
|
267
|
+
`- 自动选择的 skill:\`${session.selectedSkill.name}\``,
|
|
268
|
+
"",
|
|
269
|
+
"## 为什么这样安排",
|
|
270
|
+
"",
|
|
271
|
+
`- ${session.whyThisSkill}`,
|
|
272
|
+
"",
|
|
273
|
+
"## 下一步",
|
|
274
|
+
"",
|
|
275
|
+
`- ${session.nextAction}`
|
|
276
|
+
];
|
|
277
|
+
|
|
278
|
+
if (session.contextNeeded.length > 0) {
|
|
279
|
+
lines.push("", "## 还缺什么", "");
|
|
280
|
+
for (const item of session.contextNeeded) {
|
|
281
|
+
lines.push(`- ${item}`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
lines.push("", "## 会话步骤", "");
|
|
286
|
+
for (const step of session.steps) {
|
|
287
|
+
lines.push(`### ${step.id}|${step.commandName}`);
|
|
288
|
+
lines.push("");
|
|
289
|
+
lines.push(`- 命令:\`${step.command}\``);
|
|
290
|
+
lines.push(`- 建议 skill:\`${step.suggestedSkill}\``);
|
|
291
|
+
lines.push(`- 目的:${step.purpose}`);
|
|
292
|
+
lines.push(`- 预期产物:${step.expectedArtifact}`);
|
|
293
|
+
lines.push("- 操作说明:");
|
|
294
|
+
for (const instruction of step.instructions) {
|
|
295
|
+
lines.push(` - ${instruction}`);
|
|
296
|
+
}
|
|
297
|
+
lines.push("");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
lines.push("", "## 可直接复制给 Agent 的 Session Prompt", "", "```text", session.sessionPrompt, "```");
|
|
301
|
+
|
|
302
|
+
return `${lines.join("\n")}\n`;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export async function writeAgentSessionOutput(outputPath, content) {
|
|
306
|
+
return writeScanOutput(outputPath, content);
|
|
307
|
+
}
|
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 (/(runbook|checklist|playbook|执行手册|检查清单|操作手册)/i.test(normalized)) {
|
|
48
|
+
return "execute";
|
|
49
|
+
}
|
|
47
50
|
if (/(apply-plan|handoff|接手|交给.*agent|继续修|继续做|修复|执行|修改|落地|repair|implement|fix)/i.test(normalized)) {
|
|
48
51
|
return "execute";
|
|
49
52
|
}
|
|
@@ -147,7 +150,9 @@ function resolveEffectiveIntent(intent, detected) {
|
|
|
147
150
|
return "share";
|
|
148
151
|
}
|
|
149
152
|
if (
|
|
150
|
-
["geo-agent-handoff", "geo-apply-plan", "geo-handoff-bundle", "geo-fix-plan"].includes(
|
|
153
|
+
["geo-agent-handoff", "geo-agent-runbook", "geo-apply-plan", "geo-handoff-bundle", "geo-fix-plan"].includes(
|
|
154
|
+
detected.artifactKind
|
|
155
|
+
)
|
|
151
156
|
) {
|
|
152
157
|
return "execute";
|
|
153
158
|
}
|
|
@@ -197,7 +202,8 @@ function buildCommandChain(detected, intent) {
|
|
|
197
202
|
return [
|
|
198
203
|
`geo-ai-search-optimization onboard-url ${source}`,
|
|
199
204
|
`geo-ai-search-optimization fix-plan ${source}`,
|
|
200
|
-
`geo-ai-search-optimization agent-handoff ${source}
|
|
205
|
+
`geo-ai-search-optimization agent-handoff ${source}`,
|
|
206
|
+
`geo-ai-search-optimization agent-runbook ${source}`
|
|
201
207
|
];
|
|
202
208
|
}
|
|
203
209
|
return [
|
|
@@ -213,6 +219,7 @@ function buildCommandChain(detected, intent) {
|
|
|
213
219
|
`geo-ai-search-optimization audit ${source}`,
|
|
214
220
|
`geo-ai-search-optimization fix-plan ${source}`,
|
|
215
221
|
`geo-ai-search-optimization agent-handoff ${source}`,
|
|
222
|
+
`geo-ai-search-optimization agent-runbook ${source}`,
|
|
216
223
|
`geo-ai-search-optimization apply-plan ${source}`
|
|
217
224
|
];
|
|
218
225
|
}
|
|
@@ -230,6 +237,7 @@ function buildCommandChain(detected, intent) {
|
|
|
230
237
|
? [
|
|
231
238
|
`geo-ai-search-optimization fix-plan ${source}`,
|
|
232
239
|
`geo-ai-search-optimization agent-handoff ${source}`,
|
|
240
|
+
`geo-ai-search-optimization agent-runbook ${source}`,
|
|
233
241
|
`geo-ai-search-optimization apply-plan ${source}`
|
|
234
242
|
]
|
|
235
243
|
: [`geo-ai-search-optimization fix-plan ${source}`, `geo-ai-search-optimization owner-board ${source}`];
|
|
@@ -243,15 +251,24 @@ function buildCommandChain(detected, intent) {
|
|
|
243
251
|
case "geo-fix-plan":
|
|
244
252
|
return [
|
|
245
253
|
`geo-ai-search-optimization agent-handoff ${source}`,
|
|
254
|
+
`geo-ai-search-optimization agent-runbook ${source}`,
|
|
246
255
|
`geo-ai-search-optimization apply-plan ${source}`
|
|
247
256
|
];
|
|
248
257
|
case "geo-agent-handoff":
|
|
249
258
|
return [
|
|
259
|
+
`geo-ai-search-optimization agent-runbook ${source}`,
|
|
250
260
|
`geo-ai-search-optimization apply-plan ${source}`,
|
|
251
261
|
`geo-ai-search-optimization completion-report ${source}`
|
|
252
262
|
];
|
|
263
|
+
case "geo-agent-runbook":
|
|
264
|
+
return [
|
|
265
|
+
`geo-ai-search-optimization apply-plan ${source}`,
|
|
266
|
+
`geo-ai-search-optimization completion-report ${source}`,
|
|
267
|
+
`geo-ai-search-optimization handoff-bundle ${source}`
|
|
268
|
+
];
|
|
253
269
|
case "geo-apply-plan":
|
|
254
270
|
return [
|
|
271
|
+
`geo-ai-search-optimization agent-runbook ${source}`,
|
|
255
272
|
`geo-ai-search-optimization apply-plan ${source}`,
|
|
256
273
|
`geo-ai-search-optimization completion-report ${source}`,
|
|
257
274
|
`geo-ai-search-optimization handoff-bundle ${source}`
|
|
@@ -313,10 +330,11 @@ function pickSkillName(detected, intent) {
|
|
|
313
330
|
case "geo-report:onboarding":
|
|
314
331
|
return intent === "execute" ? "geo-ai-search-optimization-agent-handoff" : "geo-ai-search-optimization";
|
|
315
332
|
case "geo-fix-plan":
|
|
316
|
-
case "geo-agent-handoff":
|
|
317
333
|
return "geo-ai-search-optimization-agent-handoff";
|
|
334
|
+
case "geo-agent-handoff":
|
|
335
|
+
case "geo-agent-runbook":
|
|
318
336
|
case "geo-apply-plan":
|
|
319
|
-
return "geo-ai-search-optimization-
|
|
337
|
+
return "geo-ai-search-optimization-agent-runbook";
|
|
320
338
|
case "geo-completion-report":
|
|
321
339
|
return "geo-ai-search-optimization-completion-report";
|
|
322
340
|
case "geo-handoff-bundle":
|
|
@@ -346,7 +364,11 @@ function buildSecondarySkillNames(primarySkill, intent, detected) {
|
|
|
346
364
|
names.add("geo-ai-search-optimization-share-pack");
|
|
347
365
|
names.add("geo-ai-search-optimization-publish-pack");
|
|
348
366
|
}
|
|
349
|
-
if (
|
|
367
|
+
if (
|
|
368
|
+
intent === "execute" ||
|
|
369
|
+
["geo-fix-plan", "geo-agent-handoff", "geo-agent-runbook", "geo-apply-plan"].includes(detected.artifactKind)
|
|
370
|
+
) {
|
|
371
|
+
names.add("geo-ai-search-optimization-agent-runbook");
|
|
350
372
|
names.add("geo-ai-search-optimization-agent-handoff");
|
|
351
373
|
names.add("geo-ai-search-optimization-repair-loop");
|
|
352
374
|
}
|
|
@@ -369,11 +391,17 @@ function buildStage(intent, detected) {
|
|
|
369
391
|
return "执行复盘";
|
|
370
392
|
}
|
|
371
393
|
if (intent === "execute") {
|
|
372
|
-
return ["geo-fix-plan", "geo-agent-handoff", "geo-apply-plan", "geo-handoff-bundle"].includes(
|
|
394
|
+
return ["geo-fix-plan", "geo-agent-handoff", "geo-agent-runbook", "geo-apply-plan", "geo-handoff-bundle"].includes(
|
|
395
|
+
detected.artifactKind
|
|
396
|
+
)
|
|
373
397
|
? "Agent 执行"
|
|
374
398
|
: "执行准备";
|
|
375
399
|
}
|
|
376
|
-
if (
|
|
400
|
+
if (
|
|
401
|
+
["geo-fix-plan", "geo-agent-handoff", "geo-agent-runbook", "geo-apply-plan", "geo-handoff-bundle"].includes(
|
|
402
|
+
detected.artifactKind
|
|
403
|
+
)
|
|
404
|
+
) {
|
|
377
405
|
return "Agent 执行";
|
|
378
406
|
}
|
|
379
407
|
return "诊断规划";
|
package/src/cli.js
CHANGED
|
@@ -3,6 +3,8 @@ import { readFile } from "node:fs/promises";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { createApplyPlan, renderApplyPlanMarkdown, writeApplyPlanOutput } from "./apply-plan.js";
|
|
5
5
|
import { createAgentHandoff, renderAgentHandoffMarkdown, writeAgentHandoffOutput } from "./agent-handoff.js";
|
|
6
|
+
import { createAgentRunbook, renderAgentRunbookMarkdown, writeAgentRunbookOutput } from "./agent-runbook.js";
|
|
7
|
+
import { createAgentSession, renderAgentSessionMarkdown, writeAgentSessionOutput } from "./agent-session.js";
|
|
6
8
|
import { createAutoFlow, renderAutoFlowMarkdown, writeAutoFlowOutput } from "./auto-flow.js";
|
|
7
9
|
import {
|
|
8
10
|
createCompletionReport,
|
|
@@ -59,6 +61,8 @@ function printHelp() {
|
|
|
59
61
|
" geo-ai-search-optimization",
|
|
60
62
|
" geo-ai-search-optimization install [--target <dir>] [--json]",
|
|
61
63
|
" geo-ai-search-optimization auto-flow <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--json] [--out <file>]",
|
|
64
|
+
" geo-ai-search-optimization agent-session <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--json] [--out <file>]",
|
|
65
|
+
" geo-ai-search-optimization agent-runbook <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--task <id>] [--format <markdown|json>] [--out <file>]",
|
|
62
66
|
" geo-ai-search-optimization skills [--json]",
|
|
63
67
|
" geo-ai-search-optimization where",
|
|
64
68
|
" geo-ai-search-optimization doctor [--json]",
|
|
@@ -151,6 +155,57 @@ async function handleAutoFlow(args) {
|
|
|
151
155
|
process.stdout.write(renderedOutput);
|
|
152
156
|
}
|
|
153
157
|
|
|
158
|
+
async function handleAgentSession(args) {
|
|
159
|
+
const input = args.find((value) => !value.startsWith("-"));
|
|
160
|
+
if (!input) {
|
|
161
|
+
throw new Error("agent-session 需要一个输入值,可以是任务描述、项目路径、网站网址或已导出的工件");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const session = await createAgentSession(input, {
|
|
165
|
+
intent: getFlagValue(args, "--intent")
|
|
166
|
+
});
|
|
167
|
+
const outputJson = hasFlag(args, "--json");
|
|
168
|
+
const renderedOutput = outputJson
|
|
169
|
+
? `${JSON.stringify(session, null, 2)}\n`
|
|
170
|
+
: renderAgentSessionMarkdown(session);
|
|
171
|
+
|
|
172
|
+
const outputPath = getFlagValue(args, "--out");
|
|
173
|
+
if (outputPath) {
|
|
174
|
+
const resolvedOutputPath = await writeAgentSessionOutput(outputPath, renderedOutput);
|
|
175
|
+
process.stdout.write(`已保存 agent-session 结果:${resolvedOutputPath}\n`);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
process.stdout.write(renderedOutput);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async function handleAgentRunbook(args) {
|
|
183
|
+
const input = args.find((value) => !value.startsWith("-"));
|
|
184
|
+
if (!input) {
|
|
185
|
+
throw new Error("agent-runbook 需要一个输入值,可以是任务描述、项目路径、网站网址或已导出的工件");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const format = getFlagValue(args, "--format");
|
|
189
|
+
const runbook = await createAgentRunbook(input, {
|
|
190
|
+
intent: getFlagValue(args, "--intent"),
|
|
191
|
+
format,
|
|
192
|
+
taskId: getFlagValue(args, "--task")
|
|
193
|
+
});
|
|
194
|
+
const outputJson = format === "json";
|
|
195
|
+
const renderedOutput = outputJson
|
|
196
|
+
? `${JSON.stringify(runbook, null, 2)}\n`
|
|
197
|
+
: renderAgentRunbookMarkdown(runbook);
|
|
198
|
+
|
|
199
|
+
const outputPath = getFlagValue(args, "--out");
|
|
200
|
+
if (outputPath) {
|
|
201
|
+
const resolvedOutputPath = await writeAgentRunbookOutput(outputPath, renderedOutput);
|
|
202
|
+
process.stdout.write(`已保存 agent runbook:${resolvedOutputPath}\n`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
process.stdout.write(renderedOutput);
|
|
207
|
+
}
|
|
208
|
+
|
|
154
209
|
function handleWhere() {
|
|
155
210
|
process.stdout.write(
|
|
156
211
|
[
|
|
@@ -696,6 +751,16 @@ export async function runCli(args = []) {
|
|
|
696
751
|
return;
|
|
697
752
|
}
|
|
698
753
|
|
|
754
|
+
if (command === "agent-session") {
|
|
755
|
+
await handleAgentSession(rest);
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
if (command === "agent-runbook") {
|
|
760
|
+
await handleAgentRunbook(rest);
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
|
|
699
764
|
if (command === "skills") {
|
|
700
765
|
await handleSkills(rest);
|
|
701
766
|
return;
|
package/src/index.js
CHANGED
|
@@ -8,6 +8,8 @@ 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 { createAgentRunbook, renderAgentRunbookMarkdown, writeAgentRunbookOutput } from "./agent-runbook.js";
|
|
12
|
+
export { createAgentSession, renderAgentSessionMarkdown, writeAgentSessionOutput } from "./agent-session.js";
|
|
11
13
|
export { createCompletionReport, renderCompletionReportMarkdown, writeCompletionReportOutput } from "./completion-report.js";
|
|
12
14
|
export { createFixPlan, renderFixPlanMarkdown, writeFixPlanOutput } from "./fix-plan.js";
|
|
13
15
|
export { createHandoffBundle, renderHandoffBundleMarkdown, writeHandoffBundleOutput } from "./handoff-bundle.js";
|
package/src/skills.js
CHANGED
|
@@ -5,6 +5,8 @@ import { getPackageRoot } from "./paths.js";
|
|
|
5
5
|
const SKILL_ORDER = [
|
|
6
6
|
"geo-ai-search-optimization",
|
|
7
7
|
"geo-ai-search-optimization-auto-flow",
|
|
8
|
+
"geo-ai-search-optimization-agent-session",
|
|
9
|
+
"geo-ai-search-optimization-agent-runbook",
|
|
8
10
|
"geo-ai-search-optimization-usage",
|
|
9
11
|
"geo-ai-search-optimization-agent-handoff",
|
|
10
12
|
"geo-ai-search-optimization-repair-loop",
|
|
@@ -19,6 +21,8 @@ const SKILL_ORDER = [
|
|
|
19
21
|
const SKILL_CATEGORY = {
|
|
20
22
|
"geo-ai-search-optimization": "core",
|
|
21
23
|
"geo-ai-search-optimization-auto-flow": "routing",
|
|
24
|
+
"geo-ai-search-optimization-agent-session": "routing",
|
|
25
|
+
"geo-ai-search-optimization-agent-runbook": "execution",
|
|
22
26
|
"geo-ai-search-optimization-usage": "guidance",
|
|
23
27
|
"geo-ai-search-optimization-agent-handoff": "execution",
|
|
24
28
|
"geo-ai-search-optimization-repair-loop": "execution",
|
|
@@ -152,6 +156,8 @@ export function renderBundledSkillsMarkdown(bundle) {
|
|
|
152
156
|
"",
|
|
153
157
|
"- 先看核心 GEO skill。",
|
|
154
158
|
"- 如果 agent 需要自动选 skill,先跑 auto-flow。",
|
|
159
|
+
"- 如果要给 agent 明确步骤,继续进入 agent-session。",
|
|
160
|
+
"- 如果要给 agent 一份执行手册和检查表,再进入 agent-runbook。",
|
|
155
161
|
"- 再看 usage skill,知道什么时候该跑哪个命令。",
|
|
156
162
|
"- 如果要交给 agent 执行,再进入 handoff / apply / completion 这一条执行链。",
|
|
157
163
|
"- 如果要产出给团队分发,再进入 share / export / html / publish 这一条交付链。",
|