geo-ai-search-optimization 1.2.18 → 1.2.19
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 +31 -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-resume/SKILL.md +24 -0
- package/resources/geo-ai-search-optimization-agent-resume/agents/openai.yaml +4 -0
- package/resources/geo-ai-search-optimization-usage/SKILL.md +30 -25
- package/src/agent-resume.js +329 -0
- package/src/agent-session.js +10 -0
- package/src/auto-flow.js +47 -29
- package/src/cli.js +31 -0
- package/src/index.js +1 -0
- package/src/skills.js +3 -0
package/README.md
CHANGED
|
@@ -63,6 +63,27 @@ geo-ai-search-optimization agent-orchestrator ./reports/agent-playbook-pack.json
|
|
|
63
63
|
- 做完之后下一条是什么
|
|
64
64
|
- 可直接复制给 agent 的 orchestrator prompt
|
|
65
65
|
|
|
66
|
+
## Agent Resume 命令
|
|
67
|
+
|
|
68
|
+
如果 GEO 工作已经做过一轮或多轮,你不想让下一个 agent 从头重新判断,而是想让它从最近一个可靠恢复点继续,可以直接用 `agent-resume`:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
geo-ai-search-optimization agent-resume "继续这个 GEO 任务"
|
|
72
|
+
geo-ai-search-optimization agent-resume https://example.com
|
|
73
|
+
geo-ai-search-optimization agent-resume ./your-site
|
|
74
|
+
geo-ai-search-optimization agent-resume ./reports/agent-playbook-pack.json --format json --out ./reports/agent-resume.json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
它会输出:
|
|
78
|
+
|
|
79
|
+
- 恢复模式
|
|
80
|
+
- 从哪里恢复
|
|
81
|
+
- 现在只恢复哪一条命令
|
|
82
|
+
- 恢复前要先确认什么
|
|
83
|
+
- 恢复时不要重置什么
|
|
84
|
+
- 恢复后下一条是什么
|
|
85
|
+
- 可直接复制给 agent 的 resume prompt
|
|
86
|
+
|
|
66
87
|
## Auto Flow 命令
|
|
67
88
|
|
|
68
89
|
如果你希望 agent 不用自己判断现在该用哪个 skill、该跑哪个命令,可以直接用 `auto-flow`:
|
|
@@ -682,6 +703,7 @@ geo-ai-search-optimization
|
|
|
682
703
|
geo-ai-search-optimization install
|
|
683
704
|
geo-ai-search-optimization install --target ./tmp/custom-skills --json
|
|
684
705
|
geo-ai-search-optimization agent-orchestrator ./your-site
|
|
706
|
+
geo-ai-search-optimization agent-resume ./your-site
|
|
685
707
|
geo-ai-search-optimization auto-flow "audit this site and tell me the next skill"
|
|
686
708
|
geo-ai-search-optimization agent-session ./your-site
|
|
687
709
|
geo-ai-search-optimization agent-runbook ./your-site
|
|
@@ -763,6 +785,14 @@ geo-ai-search-optimization help
|
|
|
763
785
|
- 输出 do-now checklist、stop checklist、success checklist、验证命令和回报模板
|
|
764
786
|
- 新增 `geo-ai-search-optimization-agent-executor` skill
|
|
765
787
|
|
|
788
|
+
## New in 1.2.19
|
|
789
|
+
|
|
790
|
+
- 新增 `agent-resume`
|
|
791
|
+
- 把 `agent-orchestrator + agent-playbook-pack` 收敛成“从最近一个可靠恢复点继续”的恢复入口
|
|
792
|
+
- 输出 `resume_mode`、`resume_from`、`resume_command`、`verify_before_resume`、`do_not_reset`、`after_resume`
|
|
793
|
+
- `auto-flow`、`agent-session`、`skills` 已经把 `agent-resume` 视为正式恢复链路
|
|
794
|
+
- 新增 `geo-ai-search-optimization-agent-resume` skill
|
|
795
|
+
|
|
766
796
|
## New in 1.2.18
|
|
767
797
|
|
|
768
798
|
- 新增 `agent-orchestrator`
|
|
@@ -1009,6 +1039,7 @@ The installed package now includes a bundled GEO skill pack, including:
|
|
|
1009
1039
|
- `geo-ai-search-optimization`
|
|
1010
1040
|
- `geo-ai-search-optimization-auto-flow`
|
|
1011
1041
|
- `geo-ai-search-optimization-agent-orchestrator`
|
|
1042
|
+
- `geo-ai-search-optimization-agent-resume`
|
|
1012
1043
|
- `geo-ai-search-optimization-agent-session`
|
|
1013
1044
|
- `geo-ai-search-optimization-agent-runbook`
|
|
1014
1045
|
- `geo-ai-search-optimization-agent-executor`
|
package/package.json
CHANGED
|
@@ -42,6 +42,16 @@ Best for:
|
|
|
42
42
|
- returning a short contract with expected artifact, stop conditions, and follow-up command
|
|
43
43
|
- reducing ambiguity for PM-to-agent or agent-to-agent handoffs
|
|
44
44
|
|
|
45
|
+
### `geo-ai-search-optimization-agent-resume`
|
|
46
|
+
|
|
47
|
+
Use this when the next agent should continue from the latest reliable GEO checkpoint instead of restarting the whole chain.
|
|
48
|
+
|
|
49
|
+
Best for:
|
|
50
|
+
|
|
51
|
+
- resuming from a playbook pack, decision log, status board, checkpoint, or similar GEO artifact
|
|
52
|
+
- telling the next agent exactly where to continue and what not to reset
|
|
53
|
+
- turning a previously interrupted GEO chain into one resume command plus one follow-up command
|
|
54
|
+
|
|
45
55
|
### `geo-ai-search-optimization-agent-session`
|
|
46
56
|
|
|
47
57
|
Use this when the next agent needs a runnable session plan, not just a routing answer.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: geo-ai-search-optimization-agent-resume
|
|
3
|
+
description: Resume a GEO workflow from the latest reliable point instead of restarting the whole chain. Use when an agent, PM, or another workflow has a GEO URL, codebase, playbook pack, decision log, status board, checkpoint, or related artifact and needs the exact resume command, pre-resume checks, and a clear list of what should not be reset.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GEO Agent Resume
|
|
7
|
+
|
|
8
|
+
Use this skill when the next agent should continue, not restart.
|
|
9
|
+
|
|
10
|
+
`GEO = Generative Engine Optimization`
|
|
11
|
+
|
|
12
|
+
## What it does
|
|
13
|
+
|
|
14
|
+
- finds the latest reliable GEO recovery point
|
|
15
|
+
- tells the next agent which one command to resume now
|
|
16
|
+
- explains what to verify before resuming
|
|
17
|
+
- lists what should not be reset while continuing the chain
|
|
18
|
+
- keeps the agent aligned with the current packet, next packet, and follow-up command
|
|
19
|
+
|
|
20
|
+
## Best use
|
|
21
|
+
|
|
22
|
+
- when GEO work was interrupted and another agent needs to continue safely
|
|
23
|
+
- when PM wants to say "pick up from where the last agent left off"
|
|
24
|
+
- when there are already GEO artifacts and the risk is restarting the chain from the wrong place
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "GEO Agent Resume"
|
|
3
|
+
short_description: "Resume GEO work from the latest reliable point"
|
|
4
|
+
default_prompt: "Use $geo-ai-search-optimization-agent-resume to continue this GEO workflow from the latest reliable checkpoint, identify the one resume command to run now, list what to verify first, and explain what must not be reset."
|
|
@@ -13,33 +13,34 @@ 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 twenty-
|
|
16
|
+
The package is best explained as twenty-six layers:
|
|
17
17
|
|
|
18
18
|
1. `agent-orchestrator`: choose the one next GEO command to run right now
|
|
19
|
-
2. `
|
|
20
|
-
3. `
|
|
21
|
-
4. `agent-
|
|
22
|
-
5. `agent-
|
|
23
|
-
6. `agent-
|
|
24
|
-
7. `agent-
|
|
25
|
-
8. `agent-
|
|
26
|
-
9. `agent-
|
|
27
|
-
10. `agent-
|
|
28
|
-
11. `agent-
|
|
29
|
-
12. `agent-
|
|
30
|
-
13. `
|
|
31
|
-
14. `
|
|
32
|
-
15. `
|
|
33
|
-
16. `
|
|
34
|
-
17. `
|
|
35
|
-
18. `
|
|
36
|
-
19. `
|
|
37
|
-
20. `
|
|
38
|
-
21. `
|
|
39
|
-
22. `
|
|
40
|
-
23. `
|
|
41
|
-
24. `
|
|
42
|
-
25. `
|
|
19
|
+
2. `agent-resume`: resume from the latest reliable GEO checkpoint instead of restarting the whole chain
|
|
20
|
+
3. `auto-flow`: auto-select the next skill and command chain
|
|
21
|
+
4. `agent-session`: build a runnable session for the next agent
|
|
22
|
+
5. `agent-runbook`: execution manual and checklist for the next agent
|
|
23
|
+
6. `agent-executor`: choose one packet to execute right now
|
|
24
|
+
7. `agent-batch-executor`: queue the first few packets, but still advance one packet at a time
|
|
25
|
+
8. `agent-progress-tracker`: track which packet is done, which one is active, and what comes next
|
|
26
|
+
9. `agent-status-board`: turn the execution state into a board view for PM and agents
|
|
27
|
+
10. `agent-checkpoint`: freeze the current round into a continue / unblock / closeout decision
|
|
28
|
+
11. `agent-decision-log`: preserve why each round continued, paused, or closed out
|
|
29
|
+
12. `agent-retrospective`: explain multi-round patterns, lessons, and next-round advice
|
|
30
|
+
13. `agent-playbook-pack`: compress retrospective, decision history, and handoff into one resume entrypoint
|
|
31
|
+
14. `skills`: inspect the bundled skill package
|
|
32
|
+
15. `onboard-url` / `onboard`: first look
|
|
33
|
+
16. `scan`: raw signal check
|
|
34
|
+
17. `audit` / `report`: diagnosis
|
|
35
|
+
18. `fix-plan` / `owner-board`: execution planning
|
|
36
|
+
19. `agent-handoff`: agent takeover package
|
|
37
|
+
20. `apply-plan`: execution loop
|
|
38
|
+
21. `completion-report`: closeout
|
|
39
|
+
22. `handoff-bundle`: all-in-one package
|
|
40
|
+
23. `share-pack`: audience-ready delivery
|
|
41
|
+
24. `export-pack`: folder export
|
|
42
|
+
25. `html-pack` / `publish-pack`: browsable and final delivery output
|
|
43
|
+
26. `pm-brief` / `roadmap`: stakeholder alignment
|
|
43
44
|
|
|
44
45
|
## Recommended command order
|
|
45
46
|
|
|
@@ -47,6 +48,7 @@ If the user only has a website URL:
|
|
|
47
48
|
|
|
48
49
|
```bash
|
|
49
50
|
npx geo-ai-search-optimization agent-orchestrator https://example.com
|
|
51
|
+
npx geo-ai-search-optimization agent-resume https://example.com
|
|
50
52
|
npx geo-ai-search-optimization auto-flow https://example.com
|
|
51
53
|
npx geo-ai-search-optimization agent-session https://example.com
|
|
52
54
|
npx geo-ai-search-optimization agent-runbook https://example.com
|
|
@@ -67,6 +69,7 @@ If the user has the website codebase:
|
|
|
67
69
|
|
|
68
70
|
```bash
|
|
69
71
|
npx geo-ai-search-optimization agent-orchestrator ./your-site
|
|
72
|
+
npx geo-ai-search-optimization agent-resume ./your-site
|
|
70
73
|
npx geo-ai-search-optimization auto-flow ./your-site
|
|
71
74
|
npx geo-ai-search-optimization agent-session ./your-site
|
|
72
75
|
npx geo-ai-search-optimization agent-runbook ./your-site
|
|
@@ -96,6 +99,7 @@ npx geo-ai-search-optimization roadmap ./your-site
|
|
|
96
99
|
## When to recommend each command
|
|
97
100
|
|
|
98
101
|
- `agent-orchestrator`: choose the one next GEO command to run now, plus expected artifact, stop conditions, and follow-up command
|
|
102
|
+
- `agent-resume`: resume from the latest reliable checkpoint, confirm what not to reset, and tell the next agent the one resume command to run
|
|
99
103
|
- `auto-flow`: auto-select the next skill and command order from a task brief, URL, project path, or GEO artifact
|
|
100
104
|
- `agent-session`: build a step-by-step session packet for the next agent from the same kinds of inputs
|
|
101
105
|
- `agent-runbook`: build a checklist-driven runbook with preflight, validation, and reporting rules
|
|
@@ -132,6 +136,7 @@ When explaining the tool to a user:
|
|
|
132
136
|
|
|
133
137
|
- prefer telling them which command to run next, not listing every command
|
|
134
138
|
- if the user or next agent wants just one next command, move them to `agent-orchestrator`
|
|
139
|
+
- if the user or next agent needs to continue from the latest reliable checkpoint without restarting, move them to `agent-resume`
|
|
135
140
|
- if the user or the next agent is unsure where to start, move them to `auto-flow` first
|
|
136
141
|
- if the user wants something the next agent can follow step by step, move them to `agent-session`
|
|
137
142
|
- if the user wants the next agent to follow a checklist and execution manual, move them to `agent-runbook`
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createAgentOrchestrator } from "./agent-orchestrator.js";
|
|
4
|
+
import { createAgentPlaybookPack } from "./agent-playbook-pack.js";
|
|
5
|
+
import { writeScanOutput } from "./scan.js";
|
|
6
|
+
|
|
7
|
+
const VALID_FORMATS = new Set(["markdown", "json"]);
|
|
8
|
+
|
|
9
|
+
function normalizeFormat(format) {
|
|
10
|
+
const resolved = (format || "markdown").toLowerCase();
|
|
11
|
+
if (!VALID_FORMATS.has(resolved)) {
|
|
12
|
+
throw new Error(`不支持的 agent-resume 格式:${format}。可选值:${Array.from(VALID_FORMATS).join(", ")}`);
|
|
13
|
+
}
|
|
14
|
+
return resolved;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function pathExists(targetPath) {
|
|
18
|
+
try {
|
|
19
|
+
await fs.access(targetPath);
|
|
20
|
+
return true;
|
|
21
|
+
} catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function tryReadExistingPlaybookPack(input) {
|
|
27
|
+
const resolvedPath = path.resolve(String(input));
|
|
28
|
+
if (!(await pathExists(resolvedPath)) || path.extname(resolvedPath).toLowerCase() !== ".json") {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const parsed = JSON.parse(await fs.readFile(resolvedPath, "utf8"));
|
|
34
|
+
if (parsed.kind === "geo-agent-playbook-pack") {
|
|
35
|
+
return parsed;
|
|
36
|
+
}
|
|
37
|
+
if (parsed.kind === "geo-agent-resume" && parsed.playbookPack) {
|
|
38
|
+
return parsed.playbookPack;
|
|
39
|
+
}
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function tryCreatePlaybookPack(input) {
|
|
48
|
+
const existing = await tryReadExistingPlaybookPack(input);
|
|
49
|
+
if (existing) {
|
|
50
|
+
return existing;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
return await createAgentPlaybookPack(input, { format: "json" });
|
|
54
|
+
} catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function inferResumeMode(orchestrator, playbookPack) {
|
|
60
|
+
if (orchestrator.orchestration_mode === "needs-context") {
|
|
61
|
+
return "needs-context";
|
|
62
|
+
}
|
|
63
|
+
if (playbookPack?.playbookStatus === "closeout-ready") {
|
|
64
|
+
return "resume-closeout";
|
|
65
|
+
}
|
|
66
|
+
if (playbookPack?.playbookStatus === "unblock-first") {
|
|
67
|
+
return "resume-after-unblock";
|
|
68
|
+
}
|
|
69
|
+
if (playbookPack?.playbookStatus === "advice-ready") {
|
|
70
|
+
return "resume-advice";
|
|
71
|
+
}
|
|
72
|
+
if (playbookPack?.currentPacket) {
|
|
73
|
+
return "resume-current-packet";
|
|
74
|
+
}
|
|
75
|
+
return "resume-workflow";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function buildResumeFrom(orchestrator, playbookPack) {
|
|
79
|
+
if (playbookPack?.playbookStatus === "closeout-ready") {
|
|
80
|
+
return "从 closeout 阶段继续";
|
|
81
|
+
}
|
|
82
|
+
if (playbookPack?.playbookStatus === "unblock-first") {
|
|
83
|
+
return `先从解除阻塞继续,再回到 ${playbookPack.currentPacket?.id || "当前包"}`;
|
|
84
|
+
}
|
|
85
|
+
if (playbookPack?.currentPacket) {
|
|
86
|
+
return `从 ${playbookPack.currentPacket.id}|${playbookPack.currentPacket.title} 继续`;
|
|
87
|
+
}
|
|
88
|
+
if (orchestrator.next_command) {
|
|
89
|
+
return `从下一条命令继续:${orchestrator.next_command}`;
|
|
90
|
+
}
|
|
91
|
+
return "先补输入后再恢复";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function buildResumeSummary(orchestrator, playbookPack) {
|
|
95
|
+
if (orchestrator.orchestration_mode === "needs-context") {
|
|
96
|
+
return "当前还没有足够上下文恢复上一轮工作,先补网址、目录或 GEO 工件。";
|
|
97
|
+
}
|
|
98
|
+
if (playbookPack?.playbookStatus === "closeout-ready") {
|
|
99
|
+
return "当前已经进入或接近收尾,恢复时不要重新回到执行第一包。";
|
|
100
|
+
}
|
|
101
|
+
if (playbookPack?.playbookStatus === "unblock-first") {
|
|
102
|
+
return "当前恢复重点不是继续改动,而是先清掉重复阻塞项,再回到当前包。";
|
|
103
|
+
}
|
|
104
|
+
if (playbookPack?.currentPacket) {
|
|
105
|
+
return `当前最稳的恢复点是 ${playbookPack.currentPacket.id},不要把前面已经排好的链重新拆掉。`;
|
|
106
|
+
}
|
|
107
|
+
return orchestrator.why_now;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function shouldUnwrapResumeCommand(orchestrator) {
|
|
111
|
+
return /\bagent-resume\b/.test(orchestrator.next_command || "");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function buildResumeCommand(orchestrator, playbookPack) {
|
|
115
|
+
if (shouldUnwrapResumeCommand(orchestrator) && playbookPack?.startCommand) {
|
|
116
|
+
return playbookPack.startCommand;
|
|
117
|
+
}
|
|
118
|
+
return orchestrator.next_command;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function buildAfterResume(orchestrator, playbookPack, resumeCommand) {
|
|
122
|
+
if (shouldUnwrapResumeCommand(orchestrator) && Array.isArray(playbookPack?.followupCommands)) {
|
|
123
|
+
return playbookPack.followupCommands.find((command) => command && command !== resumeCommand) || orchestrator.after_that;
|
|
124
|
+
}
|
|
125
|
+
return orchestrator.after_that;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function inferExpectedArtifactFromCommand(command) {
|
|
129
|
+
const normalized = String(command || "").toLowerCase();
|
|
130
|
+
|
|
131
|
+
if (normalized.includes("completion-report")) {
|
|
132
|
+
return "复盘工件";
|
|
133
|
+
}
|
|
134
|
+
if (normalized.includes("agent-executor")) {
|
|
135
|
+
return "agent 单任务执行包";
|
|
136
|
+
}
|
|
137
|
+
if (normalized.includes("agent-batch-executor")) {
|
|
138
|
+
return "agent 多任务批次执行包";
|
|
139
|
+
}
|
|
140
|
+
if (normalized.includes("agent-runbook")) {
|
|
141
|
+
return "agent 执行手册";
|
|
142
|
+
}
|
|
143
|
+
if (normalized.includes("agent-status-board")) {
|
|
144
|
+
return "agent 执行状态看板";
|
|
145
|
+
}
|
|
146
|
+
if (normalized.includes("agent-progress-tracker")) {
|
|
147
|
+
return "agent 执行进度追踪工件";
|
|
148
|
+
}
|
|
149
|
+
if (normalized.includes("agent-decision-log")) {
|
|
150
|
+
return "agent 决策历史工件";
|
|
151
|
+
}
|
|
152
|
+
if (normalized.includes("fix-plan")) {
|
|
153
|
+
return "待办清单与优先级";
|
|
154
|
+
}
|
|
155
|
+
if (normalized.includes("audit")) {
|
|
156
|
+
return "GEO 审计结果";
|
|
157
|
+
}
|
|
158
|
+
if (normalized.includes("scan")) {
|
|
159
|
+
return "基础信号扫描结果";
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function buildExpectedArtifact(orchestrator, playbookPack, resumeCommand) {
|
|
165
|
+
if (shouldUnwrapResumeCommand(orchestrator)) {
|
|
166
|
+
return inferExpectedArtifactFromCommand(resumeCommand) || playbookPack?.resumeSummary || "阶段性 GEO 输出";
|
|
167
|
+
}
|
|
168
|
+
return orchestrator.expected_artifact;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function buildVerifyBeforeResume(orchestrator, playbookPack) {
|
|
172
|
+
const items = [];
|
|
173
|
+
|
|
174
|
+
if (playbookPack) {
|
|
175
|
+
items.push(...playbookPack.readOrder.slice(0, 2));
|
|
176
|
+
if (playbookPack.currentPacket) {
|
|
177
|
+
items.push(`确认当前包仍然是 ${playbookPack.currentPacket.id},不要在恢复时改成别的包。`);
|
|
178
|
+
}
|
|
179
|
+
} else if (orchestrator.sourceType === "task-text") {
|
|
180
|
+
items.push("先确认是否已经有网址、目录或 JSON 工件,否则无法恢复上一轮。");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
items.push(...orchestrator.stop_if);
|
|
184
|
+
return Array.from(new Set(items));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function buildDoNotReset(playbookPack) {
|
|
188
|
+
if (!playbookPack) {
|
|
189
|
+
return ["没有恢复工件时,不要假装已经知道上一轮做到哪里。"];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const items = ["不要从第一步重新跑整条链,除非当前工件已经明显过时。", ...playbookPack.avoidNowChecklist];
|
|
193
|
+
return Array.from(new Set(items));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function buildResumePrompt(resume) {
|
|
197
|
+
const lines = [
|
|
198
|
+
`Use $${resume.selectedSkill.name} to resume this GEO task without restarting the chain.`,
|
|
199
|
+
`当前输入:${resume.source}`,
|
|
200
|
+
`恢复模式:${resume.resume_mode}`,
|
|
201
|
+
`恢复点:${resume.resume_from}`,
|
|
202
|
+
`恢复摘要:${resume.resume_summary}`
|
|
203
|
+
];
|
|
204
|
+
|
|
205
|
+
if (resume.resume_command) {
|
|
206
|
+
lines.push(`现在只恢复这一条命令:${resume.resume_command}`);
|
|
207
|
+
}
|
|
208
|
+
if (resume.expected_artifact) {
|
|
209
|
+
lines.push(`预期恢复产物:${resume.expected_artifact}`);
|
|
210
|
+
}
|
|
211
|
+
if (resume.after_resume) {
|
|
212
|
+
lines.push(`恢复后下一条:${resume.after_resume}`);
|
|
213
|
+
}
|
|
214
|
+
if (resume.verify_before_resume.length > 0) {
|
|
215
|
+
lines.push("恢复前先确认:");
|
|
216
|
+
for (const item of resume.verify_before_resume) {
|
|
217
|
+
lines.push(`- ${item}`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (resume.do_not_reset.length > 0) {
|
|
221
|
+
lines.push("恢复时不要做这些事:");
|
|
222
|
+
for (const item of resume.do_not_reset) {
|
|
223
|
+
lines.push(`- ${item}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
lines.push("输出时先说明你是从哪里恢复的,再说明为什么不需要重新规划整条链。");
|
|
228
|
+
return lines.join("\n");
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export async function createAgentResume(input, options = {}) {
|
|
232
|
+
const format = normalizeFormat(options.format);
|
|
233
|
+
const [orchestrator, playbookPack] = await Promise.all([
|
|
234
|
+
createAgentOrchestrator(input, { format: "json", intent: options.intent }),
|
|
235
|
+
tryCreatePlaybookPack(input)
|
|
236
|
+
]);
|
|
237
|
+
const resumeCommand = buildResumeCommand(orchestrator, playbookPack);
|
|
238
|
+
const afterResume = buildAfterResume(orchestrator, playbookPack, resumeCommand);
|
|
239
|
+
const expectedArtifact = buildExpectedArtifact(orchestrator, playbookPack, resumeCommand);
|
|
240
|
+
|
|
241
|
+
const resume = {
|
|
242
|
+
kind: "geo-agent-resume",
|
|
243
|
+
input,
|
|
244
|
+
source: orchestrator.source,
|
|
245
|
+
sourceType: orchestrator.sourceType,
|
|
246
|
+
artifactKind: orchestrator.artifactKind,
|
|
247
|
+
format,
|
|
248
|
+
resume_mode: inferResumeMode(orchestrator, playbookPack),
|
|
249
|
+
resume_from: buildResumeFrom(orchestrator, playbookPack),
|
|
250
|
+
resume_summary: buildResumeSummary(orchestrator, playbookPack),
|
|
251
|
+
resume_command: resumeCommand,
|
|
252
|
+
expected_artifact: expectedArtifact,
|
|
253
|
+
verify_before_resume: buildVerifyBeforeResume(orchestrator, playbookPack),
|
|
254
|
+
do_not_reset: buildDoNotReset(playbookPack),
|
|
255
|
+
after_resume: afterResume,
|
|
256
|
+
selectedSkill: {
|
|
257
|
+
name: "geo-ai-search-optimization-agent-resume",
|
|
258
|
+
displayName: "GEO Agent Resume"
|
|
259
|
+
},
|
|
260
|
+
next_skill: orchestrator.next_skill || orchestrator.selectedSkill?.name || "geo-ai-search-optimization",
|
|
261
|
+
contextNeeded: orchestrator.session?.contextNeeded || [],
|
|
262
|
+
currentPacket: playbookPack?.currentPacket || null,
|
|
263
|
+
nextPacket: playbookPack?.nextPacket || null,
|
|
264
|
+
playbookStatus: playbookPack?.playbookStatus || null,
|
|
265
|
+
orchestrator,
|
|
266
|
+
playbookPack,
|
|
267
|
+
resume_prompt: ""
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
resume.resume_prompt = buildResumePrompt(resume);
|
|
271
|
+
return resume;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export function renderAgentResumeMarkdown(resume) {
|
|
275
|
+
const lines = [
|
|
276
|
+
"# GEO Agent Resume",
|
|
277
|
+
"",
|
|
278
|
+
`- 输入:\`${resume.source}\``,
|
|
279
|
+
`- 输入类型:\`${resume.sourceType}\``,
|
|
280
|
+
`- 工件类型:\`${resume.artifactKind}\``,
|
|
281
|
+
`- 恢复模式:\`${resume.resume_mode}\``,
|
|
282
|
+
`- 当前建议 skill:\`${resume.next_skill}\``,
|
|
283
|
+
"",
|
|
284
|
+
"## 从哪里恢复",
|
|
285
|
+
"",
|
|
286
|
+
`- ${resume.resume_from}`,
|
|
287
|
+
`- ${resume.resume_summary}`,
|
|
288
|
+
"",
|
|
289
|
+
"## 现在恢复这一条",
|
|
290
|
+
"",
|
|
291
|
+
`- 命令:\`${resume.resume_command || "先补输入"}\``,
|
|
292
|
+
`- 预期产物:${resume.expected_artifact || "先补输入再恢复"}`,
|
|
293
|
+
""
|
|
294
|
+
];
|
|
295
|
+
|
|
296
|
+
if (resume.currentPacket) {
|
|
297
|
+
lines.push("## 当前包", "", `- ${resume.currentPacket.id}|${resume.currentPacket.title}`, "");
|
|
298
|
+
}
|
|
299
|
+
if (resume.nextPacket) {
|
|
300
|
+
lines.push("## 下一包", "", `- ${resume.nextPacket.id}|${resume.nextPacket.title}`, "");
|
|
301
|
+
}
|
|
302
|
+
if (resume.after_resume) {
|
|
303
|
+
lines.push("## 恢复后下一条", "", `- \`${resume.after_resume}\``, "");
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
lines.push("## 恢复前先确认", "");
|
|
307
|
+
for (const item of resume.verify_before_resume) {
|
|
308
|
+
lines.push(`- ${item}`);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
lines.push("", "## 恢复时不要重置", "");
|
|
312
|
+
for (const item of resume.do_not_reset) {
|
|
313
|
+
lines.push(`- ${item}`);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (resume.contextNeeded.length > 0) {
|
|
317
|
+
lines.push("", "## 还缺什么", "");
|
|
318
|
+
for (const item of resume.contextNeeded) {
|
|
319
|
+
lines.push(`- ${item}`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
lines.push("", "## 可直接复制给 Agent 的 Resume Prompt", "", "```text", resume.resume_prompt, "```");
|
|
324
|
+
return `${lines.join("\n")}\n`;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export async function writeAgentResumeOutput(outputPath, content) {
|
|
328
|
+
return writeScanOutput(outputPath, content);
|
|
329
|
+
}
|
package/src/agent-session.js
CHANGED
|
@@ -46,6 +46,9 @@ function inferSkillForCommand(commandName, flow) {
|
|
|
46
46
|
if (commandName === "auto-flow") {
|
|
47
47
|
return "geo-ai-search-optimization-auto-flow";
|
|
48
48
|
}
|
|
49
|
+
if (commandName === "agent-resume") {
|
|
50
|
+
return "geo-ai-search-optimization-agent-resume";
|
|
51
|
+
}
|
|
49
52
|
if (commandName === "agent-runbook") {
|
|
50
53
|
return "geo-ai-search-optimization-agent-runbook";
|
|
51
54
|
}
|
|
@@ -114,6 +117,8 @@ function inferStepPurpose(commandName, flow) {
|
|
|
114
117
|
return "先理解当前技能包结构,避免 agent 选错链路。";
|
|
115
118
|
case "quick-start":
|
|
116
119
|
return "快速建立从 0 到 1 的执行顺序。";
|
|
120
|
+
case "agent-resume":
|
|
121
|
+
return "从最近一个可靠恢复点继续,而不是把整条 GEO 链重新跑一遍。";
|
|
117
122
|
case "onboard":
|
|
118
123
|
case "onboard-url":
|
|
119
124
|
return "先从网址或引导流程拿到首轮 GEO 判断。";
|
|
@@ -191,6 +196,8 @@ function inferExpectedArtifact(commandName) {
|
|
|
191
196
|
return "阶段路线图";
|
|
192
197
|
case "agent-handoff":
|
|
193
198
|
return "agent 交接工件";
|
|
199
|
+
case "agent-resume":
|
|
200
|
+
return "agent 恢复入口工件";
|
|
194
201
|
case "agent-runbook":
|
|
195
202
|
return "agent 执行手册";
|
|
196
203
|
case "agent-executor":
|
|
@@ -238,6 +245,9 @@ function buildStepInstructions(parsedCommand, flow) {
|
|
|
238
245
|
if (parsedCommand.commandName === "publish-pack") {
|
|
239
246
|
lines.push("完成后把 `START-HERE.md` 和 `AGENT-START.md` 当作最终入口。");
|
|
240
247
|
}
|
|
248
|
+
if (parsedCommand.commandName === "agent-resume") {
|
|
249
|
+
lines.push("先确认恢复点、当前包和不要重置的内容,再继续执行。");
|
|
250
|
+
}
|
|
241
251
|
if (parsedCommand.commandName === "apply-plan") {
|
|
242
252
|
lines.push("执行包出来后,优先从第一包开始,不要同时展开太多任务。");
|
|
243
253
|
}
|
package/src/auto-flow.js
CHANGED
|
@@ -41,6 +41,9 @@ function detectArtifactKindFromParsedJson(parsed) {
|
|
|
41
41
|
function inferTaskTextMode(text) {
|
|
42
42
|
const normalized = String(text).toLowerCase();
|
|
43
43
|
|
|
44
|
+
if (/(agent-resume|resume|恢复继续|从中断处继续|接着上次继续|从最近恢复点继续)/i.test(normalized)) {
|
|
45
|
+
return "execute";
|
|
46
|
+
}
|
|
44
47
|
if (/(share-pack|export-pack|html-pack|publish-pack|分享|导出|交付|外发|报告包)/i.test(normalized)) {
|
|
45
48
|
return "share";
|
|
46
49
|
}
|
|
@@ -171,6 +174,9 @@ function resolveEffectiveIntent(intent, detected) {
|
|
|
171
174
|
if (detected.artifactKind === "geo-agent-playbook-pack") {
|
|
172
175
|
return detected.parsed?.playbookStatus === "closeout-ready" ? "closeout" : "execute";
|
|
173
176
|
}
|
|
177
|
+
if (detected.artifactKind === "geo-agent-resume") {
|
|
178
|
+
return detected.parsed?.resume_mode === "resume-closeout" ? "closeout" : "execute";
|
|
179
|
+
}
|
|
174
180
|
if (
|
|
175
181
|
[
|
|
176
182
|
"geo-share-pack",
|
|
@@ -338,79 +344,79 @@ function buildCommandChain(detected, intent) {
|
|
|
338
344
|
case "geo-agent-progress-tracker":
|
|
339
345
|
return detected.parsed?.status === "completed"
|
|
340
346
|
? [
|
|
347
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
341
348
|
`geo-ai-search-optimization completion-report ${source}`,
|
|
342
349
|
`geo-ai-search-optimization handoff-bundle ${source}`,
|
|
343
350
|
`geo-ai-search-optimization publish-pack ${source}`
|
|
344
351
|
]
|
|
345
352
|
: detected.parsed?.currentTaskId
|
|
346
353
|
? [
|
|
347
|
-
`geo-ai-search-optimization agent-
|
|
348
|
-
`geo-ai-search-optimization
|
|
349
|
-
`geo-ai-search-optimization
|
|
354
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
355
|
+
`geo-ai-search-optimization agent-progress-tracker ${source}`,
|
|
356
|
+
`geo-ai-search-optimization agent-decision-log ${source}`
|
|
350
357
|
]
|
|
351
358
|
: [
|
|
359
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
352
360
|
`geo-ai-search-optimization agent-batch-executor ${source}`,
|
|
353
|
-
`geo-ai-search-optimization
|
|
354
|
-
`geo-ai-search-optimization handoff-bundle ${source}`
|
|
361
|
+
`geo-ai-search-optimization agent-progress-tracker ${source}`
|
|
355
362
|
];
|
|
356
363
|
case "geo-agent-status-board":
|
|
357
364
|
return detected.parsed?.boardStatus === "completed"
|
|
358
365
|
? [
|
|
366
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
359
367
|
`geo-ai-search-optimization completion-report ${source}`,
|
|
360
368
|
`geo-ai-search-optimization handoff-bundle ${source}`,
|
|
361
369
|
`geo-ai-search-optimization publish-pack ${source}`
|
|
362
370
|
]
|
|
363
371
|
: detected.parsed?.tracker?.currentTaskId
|
|
364
372
|
? [
|
|
365
|
-
`geo-ai-search-optimization agent-
|
|
373
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
366
374
|
`geo-ai-search-optimization agent-progress-tracker ${source}`,
|
|
367
|
-
`geo-ai-search-optimization
|
|
375
|
+
`geo-ai-search-optimization agent-decision-log ${source}`
|
|
368
376
|
]
|
|
369
377
|
: [
|
|
378
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
370
379
|
`geo-ai-search-optimization agent-progress-tracker ${source}`,
|
|
371
|
-
`geo-ai-search-optimization
|
|
372
|
-
`geo-ai-search-optimization handoff-bundle ${source}`
|
|
380
|
+
`geo-ai-search-optimization agent-decision-log ${source}`
|
|
373
381
|
];
|
|
374
382
|
case "geo-agent-checkpoint":
|
|
375
383
|
return detected.parsed?.decision === "move-to-closeout"
|
|
376
384
|
? [
|
|
385
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
377
386
|
`geo-ai-search-optimization completion-report ${source}`,
|
|
378
387
|
`geo-ai-search-optimization handoff-bundle ${source}`,
|
|
379
388
|
`geo-ai-search-optimization publish-pack ${source}`
|
|
380
389
|
]
|
|
381
390
|
: detected.parsed?.decision === "resolve-blockers"
|
|
382
391
|
? [
|
|
383
|
-
|
|
392
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
384
393
|
`geo-ai-search-optimization agent-status-board ${source}`,
|
|
385
394
|
`geo-ai-search-optimization agent-progress-tracker ${source}`
|
|
386
395
|
]
|
|
387
396
|
: [
|
|
388
|
-
|
|
397
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
389
398
|
`geo-ai-search-optimization agent-progress-tracker ${source}`,
|
|
390
|
-
`geo-ai-search-optimization
|
|
399
|
+
`geo-ai-search-optimization agent-decision-log ${source}`
|
|
391
400
|
];
|
|
392
401
|
case "geo-agent-decision-log": {
|
|
393
402
|
const baseSource = detected.parsed?.latestCheckpoint?.source || detected.parsed?.source || source;
|
|
394
403
|
const latestDecision = detected.parsed?.latestDecision;
|
|
395
|
-
const suggestedNext =
|
|
396
|
-
detected.parsed?.suggestedNextCommand ||
|
|
397
|
-
detected.parsed?.latestCheckpoint?.suggestedNextCommand ||
|
|
398
|
-
`geo-ai-search-optimization agent-executor ${baseSource}`;
|
|
399
404
|
|
|
400
405
|
return latestDecision === "move-to-closeout"
|
|
401
406
|
? [
|
|
407
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
402
408
|
`geo-ai-search-optimization completion-report ${baseSource}`,
|
|
403
409
|
`geo-ai-search-optimization handoff-bundle ${baseSource}`,
|
|
404
410
|
`geo-ai-search-optimization publish-pack ${baseSource}`
|
|
405
411
|
]
|
|
406
412
|
: latestDecision === "resolve-blockers"
|
|
407
413
|
? [
|
|
408
|
-
|
|
414
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
409
415
|
`geo-ai-search-optimization agent-status-board ${source}`,
|
|
410
416
|
`geo-ai-search-optimization agent-decision-log ${baseSource} --append-from ${source}`
|
|
411
417
|
]
|
|
412
418
|
: [
|
|
413
|
-
|
|
419
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
414
420
|
`geo-ai-search-optimization agent-progress-tracker ${source}`,
|
|
415
421
|
`geo-ai-search-optimization agent-decision-log ${baseSource} --append-from ${source}`
|
|
416
422
|
];
|
|
@@ -425,16 +431,21 @@ function buildCommandChain(detected, intent) {
|
|
|
425
431
|
const baseSource = detected.parsed?.source || source;
|
|
426
432
|
return detected.parsed?.playbookStatus === "closeout-ready"
|
|
427
433
|
? [
|
|
428
|
-
|
|
434
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
429
435
|
`geo-ai-search-optimization meeting-pack ${baseSource}`,
|
|
430
436
|
`geo-ai-search-optimization publish-pack ${baseSource}`
|
|
431
437
|
]
|
|
432
438
|
: [
|
|
433
|
-
|
|
439
|
+
`geo-ai-search-optimization agent-resume ${source}`,
|
|
434
440
|
`geo-ai-search-optimization agent-status-board ${baseSource}`,
|
|
435
441
|
`geo-ai-search-optimization agent-decision-log ${baseSource}`
|
|
436
442
|
];
|
|
437
443
|
}
|
|
444
|
+
case "geo-agent-resume": {
|
|
445
|
+
const resumeCommand = detected.parsed?.resume_command;
|
|
446
|
+
const afterResume = detected.parsed?.after_resume;
|
|
447
|
+
return [resumeCommand, afterResume].filter(Boolean);
|
|
448
|
+
}
|
|
438
449
|
case "geo-apply-plan":
|
|
439
450
|
return [
|
|
440
451
|
`geo-ai-search-optimization agent-executor ${source}`,
|
|
@@ -511,17 +522,14 @@ function pickSkillName(detected, intent) {
|
|
|
511
522
|
case "geo-agent-batch-executor":
|
|
512
523
|
return "geo-ai-search-optimization-agent-batch-executor";
|
|
513
524
|
case "geo-agent-progress-tracker":
|
|
514
|
-
return "geo-ai-search-optimization-agent-progress-tracker";
|
|
515
525
|
case "geo-agent-status-board":
|
|
516
|
-
return "geo-ai-search-optimization-agent-status-board";
|
|
517
526
|
case "geo-agent-checkpoint":
|
|
518
|
-
return "geo-ai-search-optimization-agent-checkpoint";
|
|
519
527
|
case "geo-agent-decision-log":
|
|
520
|
-
|
|
528
|
+
case "geo-agent-playbook-pack":
|
|
529
|
+
case "geo-agent-resume":
|
|
530
|
+
return "geo-ai-search-optimization-agent-resume";
|
|
521
531
|
case "geo-agent-retrospective":
|
|
522
532
|
return "geo-ai-search-optimization-agent-retrospective";
|
|
523
|
-
case "geo-agent-playbook-pack":
|
|
524
|
-
return "geo-ai-search-optimization-agent-playbook-pack";
|
|
525
533
|
case "geo-completion-report":
|
|
526
534
|
return "geo-ai-search-optimization-completion-report";
|
|
527
535
|
case "geo-handoff-bundle":
|
|
@@ -563,12 +571,14 @@ function buildSecondarySkillNames(primarySkill, intent, detected) {
|
|
|
563
571
|
"geo-agent-status-board",
|
|
564
572
|
"geo-agent-checkpoint",
|
|
565
573
|
"geo-agent-decision-log",
|
|
574
|
+
"geo-agent-resume",
|
|
566
575
|
"geo-agent-playbook-pack",
|
|
567
576
|
"geo-apply-plan"
|
|
568
577
|
].includes(
|
|
569
578
|
detected.artifactKind
|
|
570
579
|
)
|
|
571
580
|
) {
|
|
581
|
+
names.add("geo-ai-search-optimization-agent-resume");
|
|
572
582
|
names.add("geo-ai-search-optimization-agent-batch-executor");
|
|
573
583
|
names.add("geo-ai-search-optimization-agent-progress-tracker");
|
|
574
584
|
names.add("geo-ai-search-optimization-agent-status-board");
|
|
@@ -590,6 +600,9 @@ function buildSecondarySkillNames(primarySkill, intent, detected) {
|
|
|
590
600
|
}
|
|
591
601
|
|
|
592
602
|
function buildStage(intent, detected) {
|
|
603
|
+
if (detected.artifactKind === "geo-agent-resume") {
|
|
604
|
+
return "恢复继续";
|
|
605
|
+
}
|
|
593
606
|
if (intent === "guide") {
|
|
594
607
|
return "使用引导";
|
|
595
608
|
}
|
|
@@ -610,6 +623,7 @@ function buildStage(intent, detected) {
|
|
|
610
623
|
"geo-agent-status-board",
|
|
611
624
|
"geo-agent-checkpoint",
|
|
612
625
|
"geo-agent-decision-log",
|
|
626
|
+
"geo-agent-resume",
|
|
613
627
|
"geo-agent-playbook-pack",
|
|
614
628
|
"geo-agent-retrospective",
|
|
615
629
|
"geo-apply-plan",
|
|
@@ -629,6 +643,7 @@ function buildStage(intent, detected) {
|
|
|
629
643
|
"geo-agent-status-board",
|
|
630
644
|
"geo-agent-checkpoint",
|
|
631
645
|
"geo-agent-decision-log",
|
|
646
|
+
"geo-agent-resume",
|
|
632
647
|
"geo-agent-playbook-pack",
|
|
633
648
|
"geo-agent-retrospective",
|
|
634
649
|
"geo-apply-plan",
|
|
@@ -717,14 +732,17 @@ function buildNextAction(detected, intent, commands) {
|
|
|
717
732
|
return `先运行 \`${commands[0]}\` 生成适合外发或交接的结果。`;
|
|
718
733
|
}
|
|
719
734
|
if (intent === "execute") {
|
|
735
|
+
if (detected.artifactKind === "geo-agent-resume") {
|
|
736
|
+
return `先运行 \`${commands[0]}\`,从最近一个可靠恢复点继续,不要把整条 GEO 链重新跑一遍。`;
|
|
737
|
+
}
|
|
720
738
|
if (detected.artifactKind === "geo-agent-progress-tracker") {
|
|
721
|
-
return `先运行 \`${commands[0]}
|
|
739
|
+
return `先运行 \`${commands[0]}\`,先确认最近一个可靠恢复点,再继续当前执行包。`;
|
|
722
740
|
}
|
|
723
741
|
if (detected.artifactKind === "geo-agent-decision-log") {
|
|
724
|
-
return `先运行 \`${commands[0]}
|
|
742
|
+
return `先运行 \`${commands[0]}\`,沿着最近一次阶段决策恢复,而不是重新判断整条链。`;
|
|
725
743
|
}
|
|
726
744
|
if (detected.artifactKind === "geo-agent-playbook-pack") {
|
|
727
|
-
return `先运行 \`${commands[0]}
|
|
745
|
+
return `先运行 \`${commands[0]}\`,直接从 playbook 对应的恢复点继续,不要重新拆链。`;
|
|
728
746
|
}
|
|
729
747
|
return `先运行 \`${commands[0]}\`,把当前输入推进到 agent 可执行状态。`;
|
|
730
748
|
}
|
package/src/cli.js
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
renderAgentOrchestratorMarkdown,
|
|
22
22
|
writeAgentOrchestratorOutput
|
|
23
23
|
} from "./agent-orchestrator.js";
|
|
24
|
+
import { createAgentResume, renderAgentResumeMarkdown, writeAgentResumeOutput } from "./agent-resume.js";
|
|
24
25
|
import {
|
|
25
26
|
createAgentPlaybookPack,
|
|
26
27
|
renderAgentPlaybookPackMarkdown,
|
|
@@ -86,6 +87,7 @@ function printHelp() {
|
|
|
86
87
|
" geo-ai-search-optimization",
|
|
87
88
|
" geo-ai-search-optimization install [--target <dir>] [--json]",
|
|
88
89
|
" geo-ai-search-optimization agent-orchestrator <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--format <markdown|json>] [--out <file>]",
|
|
90
|
+
" geo-ai-search-optimization agent-resume <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--format <markdown|json>] [--out <file>]",
|
|
89
91
|
" geo-ai-search-optimization auto-flow <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--json] [--out <file>]",
|
|
90
92
|
" geo-ai-search-optimization agent-session <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--json] [--out <file>]",
|
|
91
93
|
" geo-ai-search-optimization agent-runbook <input> [--intent <auto|diagnose|guide|execute|share|closeout>] [--task <id>] [--format <markdown|json>] [--out <file>]",
|
|
@@ -215,6 +217,30 @@ async function handleAgentOrchestrator(args) {
|
|
|
215
217
|
process.stdout.write(renderedOutput);
|
|
216
218
|
}
|
|
217
219
|
|
|
220
|
+
async function handleAgentResume(args) {
|
|
221
|
+
const input = args.find((value) => !value.startsWith("-"));
|
|
222
|
+
if (!input) {
|
|
223
|
+
throw new Error("agent-resume 需要一个输入值,可以是任务描述、项目路径、网站网址或已导出的工件");
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const format = getFlagValue(args, "--format") || (hasFlag(args, "--json") ? "json" : undefined);
|
|
227
|
+
const resume = await createAgentResume(input, {
|
|
228
|
+
intent: getFlagValue(args, "--intent"),
|
|
229
|
+
format
|
|
230
|
+
});
|
|
231
|
+
const outputJson = resume.format === "json";
|
|
232
|
+
const renderedOutput = outputJson ? `${JSON.stringify(resume, null, 2)}\n` : renderAgentResumeMarkdown(resume);
|
|
233
|
+
|
|
234
|
+
const outputPath = getFlagValue(args, "--out");
|
|
235
|
+
if (outputPath) {
|
|
236
|
+
const resolvedOutputPath = await writeAgentResumeOutput(outputPath, renderedOutput);
|
|
237
|
+
process.stdout.write(`已保存 agent-resume 结果:${resolvedOutputPath}\n`);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
process.stdout.write(renderedOutput);
|
|
242
|
+
}
|
|
243
|
+
|
|
218
244
|
async function handleAgentSession(args) {
|
|
219
245
|
const input = args.find((value) => !value.startsWith("-"));
|
|
220
246
|
if (!input) {
|
|
@@ -1036,6 +1062,11 @@ export async function runCli(args = []) {
|
|
|
1036
1062
|
return;
|
|
1037
1063
|
}
|
|
1038
1064
|
|
|
1065
|
+
if (command === "agent-resume") {
|
|
1066
|
+
await handleAgentResume(rest);
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1039
1070
|
if (command === "agent-session") {
|
|
1040
1071
|
await handleAgentSession(rest);
|
|
1041
1072
|
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 { createAgentOrchestrator, renderAgentOrchestratorMarkdown, writeAgentOrchestratorOutput } from "./agent-orchestrator.js";
|
|
11
|
+
export { createAgentResume, renderAgentResumeMarkdown, writeAgentResumeOutput } from "./agent-resume.js";
|
|
11
12
|
export { createAgentBatchExecutor, renderAgentBatchExecutorMarkdown, writeAgentBatchExecutorOutput } from "./agent-batch-executor.js";
|
|
12
13
|
export { createAgentCheckpoint, renderAgentCheckpointMarkdown, writeAgentCheckpointOutput } from "./agent-checkpoint.js";
|
|
13
14
|
export { createAgentDecisionLog, renderAgentDecisionLogMarkdown, writeAgentDecisionLogOutput } from "./agent-decision-log.js";
|
package/src/skills.js
CHANGED
|
@@ -6,6 +6,7 @@ const SKILL_ORDER = [
|
|
|
6
6
|
"geo-ai-search-optimization",
|
|
7
7
|
"geo-ai-search-optimization-auto-flow",
|
|
8
8
|
"geo-ai-search-optimization-agent-orchestrator",
|
|
9
|
+
"geo-ai-search-optimization-agent-resume",
|
|
9
10
|
"geo-ai-search-optimization-agent-session",
|
|
10
11
|
"geo-ai-search-optimization-agent-runbook",
|
|
11
12
|
"geo-ai-search-optimization-agent-executor",
|
|
@@ -31,6 +32,7 @@ const SKILL_CATEGORY = {
|
|
|
31
32
|
"geo-ai-search-optimization": "core",
|
|
32
33
|
"geo-ai-search-optimization-auto-flow": "routing",
|
|
33
34
|
"geo-ai-search-optimization-agent-orchestrator": "routing",
|
|
35
|
+
"geo-ai-search-optimization-agent-resume": "routing",
|
|
34
36
|
"geo-ai-search-optimization-agent-session": "routing",
|
|
35
37
|
"geo-ai-search-optimization-agent-runbook": "execution",
|
|
36
38
|
"geo-ai-search-optimization-agent-executor": "execution",
|
|
@@ -174,6 +176,7 @@ export function renderBundledSkillsMarkdown(bundle) {
|
|
|
174
176
|
"",
|
|
175
177
|
"- 先看核心 GEO skill。",
|
|
176
178
|
"- 如果你只想让 agent 立刻知道现在唯一该跑哪条命令,先跑 agent-orchestrator。",
|
|
179
|
+
"- 如果工作中断后要从最近一个可靠恢复点继续,先跑 agent-resume。",
|
|
177
180
|
"- 如果 agent 需要自动选 skill,先跑 auto-flow。",
|
|
178
181
|
"- 如果要给 agent 明确步骤,继续进入 agent-session。",
|
|
179
182
|
"- 如果要给 agent 一份执行手册和检查表,再进入 agent-runbook。",
|