geo-ai-search-optimization 1.2.2 → 1.2.4
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 +52 -0
- package/package.json +1 -1
- package/resources/geo-ai-search-optimization/references/quick-start.md +5 -1
- package/resources/geo-ai-search-optimization-export-pack/SKILL.md +26 -0
- package/resources/geo-ai-search-optimization-html-pack/SKILL.md +24 -0
- package/resources/geo-ai-search-optimization-usage/SKILL.md +10 -2
- package/resources/geo-ai-search-optimization-usage/references/usage-patterns.md +16 -0
- package/src/cli.js +43 -0
- package/src/export-pack.js +111 -0
- package/src/html-pack.js +177 -0
- package/src/index.js +2 -0
- package/src/quick-start.js +3 -1
package/README.md
CHANGED
|
@@ -225,6 +225,42 @@ geo-ai-search-optimization share-pack https://example.com
|
|
|
225
225
|
- 给下一位 agent 的交接入口
|
|
226
226
|
- 建议分享顺序
|
|
227
227
|
|
|
228
|
+
## Export Pack 命令
|
|
229
|
+
|
|
230
|
+
如果你希望直接导出一整包可外发文件,而不是自己一个个生成,现在可以用 `export-pack`:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
geo-ai-search-optimization export-pack ./your-site --out-dir ./exports/your-site-pack
|
|
234
|
+
geo-ai-search-optimization export-pack ./your-site --task fix-01 --format json --out-dir ./exports/your-site-json
|
|
235
|
+
geo-ai-search-optimization export-pack https://example.com --out-dir ./exports/example-pack
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`export-pack` 会生成:
|
|
239
|
+
|
|
240
|
+
- `pm-brief`
|
|
241
|
+
- `owner-board`
|
|
242
|
+
- `exec-summary`
|
|
243
|
+
- `agent-handoff-bundle`
|
|
244
|
+
- `share-pack`
|
|
245
|
+
|
|
246
|
+
## HTML Pack 命令
|
|
247
|
+
|
|
248
|
+
如果你希望直接生成可浏览的静态 HTML 页面,而不是 Markdown 文件,现在可以用 `html-pack`:
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
geo-ai-search-optimization html-pack ./your-site --out-dir ./exports/your-site-html
|
|
252
|
+
geo-ai-search-optimization html-pack https://example.com --out-dir ./exports/example-html
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
`html-pack` 会生成:
|
|
256
|
+
|
|
257
|
+
- `index.html`
|
|
258
|
+
- `pm.html`
|
|
259
|
+
- `engineering.html`
|
|
260
|
+
- `exec.html`
|
|
261
|
+
- `agent.html`
|
|
262
|
+
- `share.html`
|
|
263
|
+
|
|
228
264
|
## Fix Plan 命令
|
|
229
265
|
|
|
230
266
|
如果你已经跑过 `audit`、`report` 或 `onboard-url`,下一步就可以直接把结果转成 PM 待办清单:
|
|
@@ -380,6 +416,8 @@ geo-ai-search-optimization apply-plan ./my-site
|
|
|
380
416
|
geo-ai-search-optimization completion-report ./my-site
|
|
381
417
|
geo-ai-search-optimization handoff-bundle ./my-site
|
|
382
418
|
geo-ai-search-optimization share-pack ./my-site
|
|
419
|
+
geo-ai-search-optimization export-pack ./my-site --out-dir ./exports/my-site-pack
|
|
420
|
+
geo-ai-search-optimization html-pack ./my-site --out-dir ./exports/my-site-html
|
|
383
421
|
geo-ai-search-optimization exec-summary ./my-site
|
|
384
422
|
geo-ai-search-optimization fix-plan ./my-site
|
|
385
423
|
geo-ai-search-optimization owner-board ./my-site
|
|
@@ -395,6 +433,20 @@ geo-ai-search-optimization version
|
|
|
395
433
|
geo-ai-search-optimization help
|
|
396
434
|
```
|
|
397
435
|
|
|
436
|
+
## New in 1.2.4
|
|
437
|
+
|
|
438
|
+
- 新增 `html-pack`
|
|
439
|
+
- 直接生成可浏览的静态 HTML 页面目录
|
|
440
|
+
- 更适合直接分享链接或打包给不同角色查看
|
|
441
|
+
- 新增 `geo-ai-search-optimization-html-pack` skill,帮助消费 HTML 包
|
|
442
|
+
|
|
443
|
+
## New in 1.2.3
|
|
444
|
+
|
|
445
|
+
- 新增 `export-pack`
|
|
446
|
+
- 直接生成一组可外发文件,而不是只在终端显示
|
|
447
|
+
- 一次导出 PM、工程、管理层、Agent 四类视图
|
|
448
|
+
- 新增 `geo-ai-search-optimization-export-pack` skill,帮助消费导出结果
|
|
449
|
+
|
|
398
450
|
## New in 1.2.2
|
|
399
451
|
|
|
400
452
|
- 新增 `share-pack`
|
package/package.json
CHANGED
|
@@ -47,6 +47,8 @@ geo-ai-search-optimization apply-plan ./your-site --out ./reports/apply-plan.md
|
|
|
47
47
|
geo-ai-search-optimization completion-report ./your-site --out ./reports/completion-report.md
|
|
48
48
|
geo-ai-search-optimization handoff-bundle ./your-site --out ./reports/handoff-bundle.md
|
|
49
49
|
geo-ai-search-optimization share-pack ./your-site --out ./reports/share-pack.md
|
|
50
|
+
geo-ai-search-optimization export-pack ./your-site --out-dir ./exports/your-site-pack
|
|
51
|
+
geo-ai-search-optimization html-pack ./your-site --out-dir ./exports/your-site-html
|
|
50
52
|
geo-ai-search-optimization owner-board ./your-site --out ./reports/owner-board.md
|
|
51
53
|
geo-ai-search-optimization meeting-pack ./your-site --out ./reports/meeting-pack.md
|
|
52
54
|
geo-ai-search-optimization pm-brief ./your-site --out ./reports/pm-brief.md
|
|
@@ -65,7 +67,9 @@ geo-ai-search-optimization roadmap ./your-site --out ./reports/roadmap.md
|
|
|
65
67
|
6. 完成一轮后生成 completion-report
|
|
66
68
|
7. 需要完整交接包时生成 handoff-bundle
|
|
67
69
|
8. 需要发给不同角色时生成 share-pack
|
|
68
|
-
9.
|
|
70
|
+
9. 需要一整包文件时生成 export-pack
|
|
71
|
+
10. 需要直接分享页面时生成 html-pack
|
|
72
|
+
11. 重跑 scan / audit / report 验证是否改善
|
|
69
73
|
|
|
70
74
|
## 推荐节奏
|
|
71
75
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: geo-ai-search-optimization-export-pack
|
|
3
|
+
description: Export GEO results into a shareable folder structure for different audiences. Use when a PM or agent wants ready-to-send files such as pm-brief, owner-board, exec-summary, and agent handoff bundle generated together.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GEO Export Pack
|
|
7
|
+
|
|
8
|
+
Use this skill when the user wants one command to generate a folder of GEO deliverables.
|
|
9
|
+
|
|
10
|
+
`GEO = Generative Engine Optimization`
|
|
11
|
+
|
|
12
|
+
## What it exports
|
|
13
|
+
|
|
14
|
+
- `pm-brief`
|
|
15
|
+
- `owner-board`
|
|
16
|
+
- `exec-summary`
|
|
17
|
+
- `agent-handoff-bundle`
|
|
18
|
+
- `share-pack`
|
|
19
|
+
|
|
20
|
+
## How to use it
|
|
21
|
+
|
|
22
|
+
- export once
|
|
23
|
+
- send `pm-brief` to PM
|
|
24
|
+
- send `owner-board` to execution teams
|
|
25
|
+
- send `exec-summary` to management
|
|
26
|
+
- send `agent-handoff-bundle` to the next agent
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: geo-ai-search-optimization-html-pack
|
|
3
|
+
description: Generate a static HTML share package for GEO results. Use when the user wants browsable files like index.html, pm.html, engineering.html, exec.html, and agent.html instead of plain markdown or JSON exports.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GEO HTML Pack
|
|
7
|
+
|
|
8
|
+
Use this skill when the user wants a visually shareable GEO output package.
|
|
9
|
+
|
|
10
|
+
`GEO = Generative Engine Optimization`
|
|
11
|
+
|
|
12
|
+
## What it generates
|
|
13
|
+
|
|
14
|
+
- `index.html`
|
|
15
|
+
- `pm.html`
|
|
16
|
+
- `engineering.html`
|
|
17
|
+
- `exec.html`
|
|
18
|
+
- `agent.html`
|
|
19
|
+
- `share.html`
|
|
20
|
+
|
|
21
|
+
## Best use
|
|
22
|
+
|
|
23
|
+
- send `index.html` as the landing page
|
|
24
|
+
- share role-specific pages directly when needed
|
|
@@ -13,7 +13,7 @@ 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 twelve layers:
|
|
17
17
|
|
|
18
18
|
1. `onboard-url` / `onboard`: first look
|
|
19
19
|
2. `scan`: raw signal check
|
|
@@ -24,7 +24,9 @@ The package is best explained as ten layers:
|
|
|
24
24
|
7. `completion-report`: closeout
|
|
25
25
|
8. `handoff-bundle`: all-in-one package
|
|
26
26
|
9. `share-pack`: audience-ready delivery
|
|
27
|
-
10. `
|
|
27
|
+
10. `export-pack`: folder export
|
|
28
|
+
11. `html-pack`: browsable output
|
|
29
|
+
12. `pm-brief` / `roadmap`: stakeholder alignment
|
|
28
30
|
|
|
29
31
|
## Recommended command order
|
|
30
32
|
|
|
@@ -47,6 +49,8 @@ npx geo-ai-search-optimization apply-plan ./your-site
|
|
|
47
49
|
npx geo-ai-search-optimization completion-report ./your-site
|
|
48
50
|
npx geo-ai-search-optimization handoff-bundle ./your-site
|
|
49
51
|
npx geo-ai-search-optimization share-pack ./your-site
|
|
52
|
+
npx geo-ai-search-optimization export-pack ./your-site
|
|
53
|
+
npx geo-ai-search-optimization html-pack ./your-site
|
|
50
54
|
npx geo-ai-search-optimization owner-board ./your-site
|
|
51
55
|
npx geo-ai-search-optimization roadmap ./your-site
|
|
52
56
|
```
|
|
@@ -64,6 +68,8 @@ npx geo-ai-search-optimization roadmap ./your-site
|
|
|
64
68
|
- `completion-report`: summarize what the agent finished, residual risks, and next-round work
|
|
65
69
|
- `handoff-bundle`: combine handoff, execution, and closeout into one artifact
|
|
66
70
|
- `share-pack`: prepare role-specific shareable outputs for PM, engineering, management, and agents
|
|
71
|
+
- `export-pack`: generate a folder with multiple ready-to-send files
|
|
72
|
+
- `html-pack`: generate static HTML pages for sharing and browsing
|
|
67
73
|
- `owner-board`: group tasks by PM / engineering / SEO / content
|
|
68
74
|
- `pm-brief`: prepare a PM summary for meetings and prioritization
|
|
69
75
|
- `roadmap`: turn tasks into a 2-week / 4-week execution sequence
|
|
@@ -80,6 +86,8 @@ When explaining the tool to a user:
|
|
|
80
86
|
- if the user wants a closeout summary after one round, move them to `completion-report`
|
|
81
87
|
- if the user wants one consolidated artifact, move them to `handoff-bundle`
|
|
82
88
|
- if the user wants something ready to forward to multiple audiences, move them to `share-pack`
|
|
89
|
+
- if the user wants actual files on disk for each audience, move them to `export-pack`
|
|
90
|
+
- if the user wants browsable HTML pages, move them to `html-pack`
|
|
83
91
|
- if the user already has a report, move them to `fix-plan`, `owner-board`, or `roadmap`
|
|
84
92
|
|
|
85
93
|
Read [references/usage-patterns.md](references/usage-patterns.md) when you need response patterns and command selection examples.
|
|
@@ -103,6 +103,22 @@ Recommend:
|
|
|
103
103
|
npx geo-ai-search-optimization share-pack ./your-site
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
+
## If the user says "我想直接导出一整包文件"
|
|
107
|
+
|
|
108
|
+
Recommend:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
npx geo-ai-search-optimization export-pack ./your-site --out-dir ./exports/your-site-pack
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## If the user says "我想直接分享 HTML 页面"
|
|
115
|
+
|
|
116
|
+
Recommend:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npx geo-ai-search-optimization html-pack ./your-site --out-dir ./exports/your-site-html
|
|
120
|
+
```
|
|
121
|
+
|
|
106
122
|
## If the user says "我要开会同步"
|
|
107
123
|
|
|
108
124
|
Recommend:
|
package/src/cli.js
CHANGED
|
@@ -17,6 +17,8 @@ import { createLlmsTxt } from "./llms-txt.js";
|
|
|
17
17
|
import { auditProject, renderAuditMarkdown, writeAuditOutput } from "./audit.js";
|
|
18
18
|
import { createFixPlan, renderFixPlanMarkdown, writeFixPlanOutput } from "./fix-plan.js";
|
|
19
19
|
import { createExecSummary, renderExecSummaryMarkdown, writeExecSummaryOutput } from "./exec-summary.js";
|
|
20
|
+
import { renderExportPackMarkdown, writeExportPack } from "./export-pack.js";
|
|
21
|
+
import { renderHtmlPackMarkdown, writeHtmlPack } from "./html-pack.js";
|
|
20
22
|
import { createOwnerBoard, renderOwnerBoardMarkdown, writeOwnerBoardOutput } from "./owner-board.js";
|
|
21
23
|
import { createMeetingPack, renderMeetingPackMarkdown, writeMeetingPackOutput } from "./meeting-pack.js";
|
|
22
24
|
import { createPmBrief, renderPmBriefMarkdown, writePmBriefOutput } from "./pm-brief.js";
|
|
@@ -66,6 +68,8 @@ function printHelp() {
|
|
|
66
68
|
" geo-ai-search-optimization completion-report <input> [--format <markdown|json>] [--out <file>]",
|
|
67
69
|
" geo-ai-search-optimization handoff-bundle <input> [--task <id>] [--format <markdown|json>] [--out <file>]",
|
|
68
70
|
" geo-ai-search-optimization share-pack <input> [--task <id>] [--format <markdown|json>] [--out <file>]",
|
|
71
|
+
" geo-ai-search-optimization export-pack <input> [--task <id>] [--format <markdown|json>] [--out-dir <dir>]",
|
|
72
|
+
" geo-ai-search-optimization html-pack <input> [--task <id>] [--out-dir <dir>]",
|
|
69
73
|
" geo-ai-search-optimization exec-summary <input> [--format <markdown|json>] [--out <file>]",
|
|
70
74
|
" geo-ai-search-optimization fix-plan <input> [--format <markdown|json>] [--out <file>]",
|
|
71
75
|
" geo-ai-search-optimization owner-board <input> [--format <markdown|json>] [--out <file>]",
|
|
@@ -473,6 +477,35 @@ async function handleSharePack(args) {
|
|
|
473
477
|
process.stdout.write(renderedOutput);
|
|
474
478
|
}
|
|
475
479
|
|
|
480
|
+
async function handleExportPack(args) {
|
|
481
|
+
const input = args.find((value) => !value.startsWith("-"));
|
|
482
|
+
if (!input) {
|
|
483
|
+
throw new Error("export-pack 需要一个输入值,可以是项目路径、网站网址或已导出的 JSON 工件");
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const pack = await writeExportPack(input, {
|
|
487
|
+
format: getFlagValue(args, "--format"),
|
|
488
|
+
taskId: getFlagValue(args, "--task"),
|
|
489
|
+
outputDir: getFlagValue(args, "--out-dir")
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
process.stdout.write(renderExportPackMarkdown(pack));
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
async function handleHtmlPack(args) {
|
|
496
|
+
const input = args.find((value) => !value.startsWith("-"));
|
|
497
|
+
if (!input) {
|
|
498
|
+
throw new Error("html-pack 需要一个输入值,可以是项目路径、网站网址或已导出的 JSON 工件");
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const pack = await writeHtmlPack(input, {
|
|
502
|
+
taskId: getFlagValue(args, "--task"),
|
|
503
|
+
outputDir: getFlagValue(args, "--out-dir")
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
process.stdout.write(renderHtmlPackMarkdown(pack));
|
|
507
|
+
}
|
|
508
|
+
|
|
476
509
|
async function handleExecSummary(args) {
|
|
477
510
|
const input = args.find((value) => !value.startsWith("-"));
|
|
478
511
|
if (!input) {
|
|
@@ -671,6 +704,16 @@ export async function runCli(args = []) {
|
|
|
671
704
|
return;
|
|
672
705
|
}
|
|
673
706
|
|
|
707
|
+
if (command === "export-pack") {
|
|
708
|
+
await handleExportPack(rest);
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
if (command === "html-pack") {
|
|
713
|
+
await handleHtmlPack(rest);
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
|
|
674
717
|
if (command === "exec-summary") {
|
|
675
718
|
await handleExecSummary(rest);
|
|
676
719
|
return;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createExecSummary, renderExecSummaryMarkdown } from "./exec-summary.js";
|
|
4
|
+
import { createHandoffBundle, renderHandoffBundleMarkdown } from "./handoff-bundle.js";
|
|
5
|
+
import { createOwnerBoard, renderOwnerBoardMarkdown } from "./owner-board.js";
|
|
6
|
+
import { createPmBrief, renderPmBriefMarkdown } from "./pm-brief.js";
|
|
7
|
+
import { createSharePack, renderSharePackMarkdown } from "./share-pack.js";
|
|
8
|
+
|
|
9
|
+
const VALID_FORMATS = new Set(["markdown", "json"]);
|
|
10
|
+
|
|
11
|
+
function normalizeFormat(format) {
|
|
12
|
+
const resolved = (format || "markdown").toLowerCase();
|
|
13
|
+
if (!VALID_FORMATS.has(resolved)) {
|
|
14
|
+
throw new Error(`不支持的 export-pack 格式:${format}。可选值:${Array.from(VALID_FORMATS).join(", ")}`);
|
|
15
|
+
}
|
|
16
|
+
return resolved;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function sanitizeSegment(value) {
|
|
20
|
+
return String(value)
|
|
21
|
+
.replace(/[^a-z0-9-_]+/gi, "-")
|
|
22
|
+
.replace(/^-+|-+$/g, "")
|
|
23
|
+
.toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function buildBaseName(sourceType, source) {
|
|
27
|
+
if (sourceType === "url") {
|
|
28
|
+
try {
|
|
29
|
+
const hostname = new URL(source).hostname || "website";
|
|
30
|
+
return sanitizeSegment(hostname) || "website";
|
|
31
|
+
} catch {
|
|
32
|
+
return "website";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return sanitizeSegment(path.basename(source)) || "site";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getExtension(format) {
|
|
40
|
+
return format === "json" ? "json" : "md";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function renderByFormat(payload, renderMarkdown, format) {
|
|
44
|
+
return format === "json" ? `${JSON.stringify(payload, null, 2)}\n` : renderMarkdown(payload);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function createExportPack(input, options = {}) {
|
|
48
|
+
const format = normalizeFormat(options.format);
|
|
49
|
+
const taskId = options.taskId || null;
|
|
50
|
+
const [sharePack, pmBrief, ownerBoard, execSummary, handoffBundle] = await Promise.all([
|
|
51
|
+
createSharePack(input, { format: "json", taskId }),
|
|
52
|
+
createPmBrief(input, { format: "json" }),
|
|
53
|
+
createOwnerBoard(input, { format: "json" }),
|
|
54
|
+
createExecSummary(input, { format: "json" }),
|
|
55
|
+
createHandoffBundle(input, { format: "json", taskId })
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
const baseName = buildBaseName(sharePack.sourceType, sharePack.source);
|
|
59
|
+
const extension = getExtension(format);
|
|
60
|
+
const outputDir = path.resolve(options.outputDir || `./exports/${baseName}-geo-pack`);
|
|
61
|
+
|
|
62
|
+
const files = [
|
|
63
|
+
{ key: "share_pack", filename: `share-pack.${extension}`, content: renderByFormat(sharePack, renderSharePackMarkdown, format) },
|
|
64
|
+
{ key: "pm", filename: `pm-brief.${extension}`, content: renderByFormat(pmBrief, renderPmBriefMarkdown, format) },
|
|
65
|
+
{ key: "engineering", filename: `owner-board.${extension}`, content: renderByFormat(ownerBoard, renderOwnerBoardMarkdown, format) },
|
|
66
|
+
{ key: "exec", filename: `exec-summary.${extension}`, content: renderByFormat(execSummary, renderExecSummaryMarkdown, format) },
|
|
67
|
+
{ key: "agent", filename: `agent-handoff-bundle.${extension}`, content: renderByFormat(handoffBundle, renderHandoffBundleMarkdown, format) }
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
kind: "geo-export-pack",
|
|
72
|
+
source: sharePack.source,
|
|
73
|
+
sourceType: sharePack.sourceType,
|
|
74
|
+
format,
|
|
75
|
+
outputDir,
|
|
76
|
+
files
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function writeExportPack(input, options = {}) {
|
|
81
|
+
const pack = await createExportPack(input, options);
|
|
82
|
+
await fs.mkdir(pack.outputDir, { recursive: true });
|
|
83
|
+
|
|
84
|
+
const writtenFiles = [];
|
|
85
|
+
for (const file of pack.files) {
|
|
86
|
+
const targetPath = path.join(pack.outputDir, file.filename);
|
|
87
|
+
await fs.writeFile(targetPath, file.content, "utf8");
|
|
88
|
+
writtenFiles.push({ ...file, path: targetPath });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return { ...pack, files: writtenFiles };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function renderExportPackMarkdown(pack) {
|
|
95
|
+
const lines = [
|
|
96
|
+
"# GEO Export Pack",
|
|
97
|
+
"",
|
|
98
|
+
`- 输入来源:\`${pack.source}\``,
|
|
99
|
+
`- 来源类型:\`${pack.sourceType}\``,
|
|
100
|
+
`- 导出目录:\`${pack.outputDir}\``,
|
|
101
|
+
"",
|
|
102
|
+
"## 导出文件",
|
|
103
|
+
""
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
for (const file of pack.files) {
|
|
107
|
+
lines.push(`- ${file.key}:\`${file.path || path.join(pack.outputDir, file.filename)}\``);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return `${lines.join("\n")}\n`;
|
|
111
|
+
}
|
package/src/html-pack.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createExportPack } from "./export-pack.js";
|
|
4
|
+
|
|
5
|
+
function escapeHtml(value) {
|
|
6
|
+
return String(value)
|
|
7
|
+
.replaceAll("&", "&")
|
|
8
|
+
.replaceAll("<", "<")
|
|
9
|
+
.replaceAll(">", ">")
|
|
10
|
+
.replaceAll('"', """)
|
|
11
|
+
.replaceAll("'", "'");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function wrapHtml(title, body) {
|
|
15
|
+
return [
|
|
16
|
+
"<!doctype html>",
|
|
17
|
+
'<html lang="zh-Hant">',
|
|
18
|
+
"<head>",
|
|
19
|
+
'<meta charset="utf-8">',
|
|
20
|
+
'<meta name="viewport" content="width=device-width, initial-scale=1">',
|
|
21
|
+
`<title>${escapeHtml(title)}</title>`,
|
|
22
|
+
"<style>",
|
|
23
|
+
"body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;margin:0;background:#f5f7fb;color:#16324f;}",
|
|
24
|
+
".shell{max-width:1100px;margin:0 auto;padding:32px 20px 64px;}",
|
|
25
|
+
".hero,.card{background:#fff;border:1px solid #d9e2ec;border-radius:16px;box-shadow:0 8px 24px rgba(15,23,42,.06);}",
|
|
26
|
+
".hero{padding:28px;margin-bottom:24px;}",
|
|
27
|
+
".grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px;}",
|
|
28
|
+
".card{padding:20px;}",
|
|
29
|
+
"h1,h2,h3{margin-top:0;color:#102a43;}",
|
|
30
|
+
"ul{padding-left:20px;line-height:1.7;}",
|
|
31
|
+
"a{color:#0b7285;text-decoration:none;}",
|
|
32
|
+
"code,pre{background:#f4f7fb;border-radius:10px;}",
|
|
33
|
+
"pre{padding:16px;white-space:pre-wrap;overflow:auto;}",
|
|
34
|
+
".meta{display:flex;gap:12px;flex-wrap:wrap;color:#486581;}",
|
|
35
|
+
"</style>",
|
|
36
|
+
"</head>",
|
|
37
|
+
"<body>",
|
|
38
|
+
body,
|
|
39
|
+
"</body>",
|
|
40
|
+
"</html>"
|
|
41
|
+
].join("");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function buildIndexHtml(pack) {
|
|
45
|
+
const cards = pack.files
|
|
46
|
+
.map(
|
|
47
|
+
(file) => `
|
|
48
|
+
<article class="card">
|
|
49
|
+
<h3>${escapeHtml(file.label)}</h3>
|
|
50
|
+
<p>${escapeHtml(file.description)}</p>
|
|
51
|
+
<a href="./${escapeHtml(file.filename)}">打开 ${escapeHtml(file.filename)}</a>
|
|
52
|
+
</article>
|
|
53
|
+
`
|
|
54
|
+
)
|
|
55
|
+
.join("");
|
|
56
|
+
|
|
57
|
+
return wrapHtml(
|
|
58
|
+
"GEO HTML Pack",
|
|
59
|
+
`
|
|
60
|
+
<main class="shell">
|
|
61
|
+
<section class="hero">
|
|
62
|
+
<h1>GEO HTML Pack</h1>
|
|
63
|
+
<div class="meta">
|
|
64
|
+
<span>来源:${escapeHtml(pack.source)}</span>
|
|
65
|
+
<span>类型:${escapeHtml(pack.sourceType)}</span>
|
|
66
|
+
<span>目录:${escapeHtml(pack.outputDir)}</span>
|
|
67
|
+
</div>
|
|
68
|
+
<p>这是一个适合直接分享的静态 GEO 页面包,分别提供给 PM、工程、管理层和下一位 agent。</p>
|
|
69
|
+
</section>
|
|
70
|
+
<section class="grid">
|
|
71
|
+
${cards}
|
|
72
|
+
</section>
|
|
73
|
+
</main>
|
|
74
|
+
`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function buildDocumentHtml(title, content) {
|
|
79
|
+
return wrapHtml(
|
|
80
|
+
title,
|
|
81
|
+
`
|
|
82
|
+
<main class="shell">
|
|
83
|
+
<section class="hero">
|
|
84
|
+
<h1>${escapeHtml(title)}</h1>
|
|
85
|
+
</section>
|
|
86
|
+
<section class="card">
|
|
87
|
+
<pre>${escapeHtml(content)}</pre>
|
|
88
|
+
</section>
|
|
89
|
+
</main>
|
|
90
|
+
`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export async function writeHtmlPack(input, options = {}) {
|
|
95
|
+
const baseOutputDir = path.resolve(options.outputDir || "./exports/html-pack");
|
|
96
|
+
const exportPack = await createExportPack(input, {
|
|
97
|
+
format: "markdown",
|
|
98
|
+
taskId: options.taskId,
|
|
99
|
+
outputDir: baseOutputDir
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
await fs.mkdir(baseOutputDir, { recursive: true });
|
|
103
|
+
|
|
104
|
+
const files = [
|
|
105
|
+
{
|
|
106
|
+
key: "pm",
|
|
107
|
+
label: "PM Brief",
|
|
108
|
+
description: "给 PM 的优先级与推进摘要。",
|
|
109
|
+
filename: "pm.html",
|
|
110
|
+
content: exportPack.files.find((file) => file.key === "pm")?.content || ""
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
key: "engineering",
|
|
114
|
+
label: "Owner Board",
|
|
115
|
+
description: "给工程与执行团队的任务视图。",
|
|
116
|
+
filename: "engineering.html",
|
|
117
|
+
content: exportPack.files.find((file) => file.key === "engineering")?.content || ""
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
key: "exec",
|
|
121
|
+
label: "Exec Summary",
|
|
122
|
+
description: "给管理层的高层摘要。",
|
|
123
|
+
filename: "exec.html",
|
|
124
|
+
content: exportPack.files.find((file) => file.key === "exec")?.content || ""
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
key: "agent",
|
|
128
|
+
label: "Agent Bundle",
|
|
129
|
+
description: "给下一位 agent 的交接入口。",
|
|
130
|
+
filename: "agent.html",
|
|
131
|
+
content: exportPack.files.find((file) => file.key === "agent")?.content || ""
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
key: "share",
|
|
135
|
+
label: "Share Pack",
|
|
136
|
+
description: "给协调者的总览页面。",
|
|
137
|
+
filename: "share.html",
|
|
138
|
+
content: exportPack.files.find((file) => file.key === "share_pack")?.content || ""
|
|
139
|
+
}
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
await fs.writeFile(path.join(baseOutputDir, "index.html"), buildIndexHtml({ ...exportPack, files }), "utf8");
|
|
143
|
+
|
|
144
|
+
for (const file of files) {
|
|
145
|
+
await fs.writeFile(path.join(baseOutputDir, file.filename), buildDocumentHtml(file.label, file.content), "utf8");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
kind: "geo-html-pack",
|
|
150
|
+
source: exportPack.source,
|
|
151
|
+
sourceType: exportPack.sourceType,
|
|
152
|
+
outputDir: baseOutputDir,
|
|
153
|
+
files: [
|
|
154
|
+
{ key: "index", path: path.join(baseOutputDir, "index.html") },
|
|
155
|
+
...files.map((file) => ({ key: file.key, path: path.join(baseOutputDir, file.filename) }))
|
|
156
|
+
]
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function renderHtmlPackMarkdown(pack) {
|
|
161
|
+
const lines = [
|
|
162
|
+
"# GEO HTML Pack",
|
|
163
|
+
"",
|
|
164
|
+
`- 输入来源:\`${pack.source}\``,
|
|
165
|
+
`- 来源类型:\`${pack.sourceType}\``,
|
|
166
|
+
`- 输出目录:\`${pack.outputDir}\``,
|
|
167
|
+
"",
|
|
168
|
+
"## 页面文件",
|
|
169
|
+
""
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
for (const file of pack.files) {
|
|
173
|
+
lines.push(`- ${file.key}:\`${file.path}\``);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return `${lines.join("\n")}\n`;
|
|
177
|
+
}
|
package/src/index.js
CHANGED
|
@@ -10,11 +10,13 @@ export { createAgentHandoff, renderAgentHandoffMarkdown, writeAgentHandoffOutput
|
|
|
10
10
|
export { createCompletionReport, renderCompletionReportMarkdown, writeCompletionReportOutput } from "./completion-report.js";
|
|
11
11
|
export { createFixPlan, renderFixPlanMarkdown, writeFixPlanOutput } from "./fix-plan.js";
|
|
12
12
|
export { createHandoffBundle, renderHandoffBundleMarkdown, writeHandoffBundleOutput } from "./handoff-bundle.js";
|
|
13
|
+
export { renderHtmlPackMarkdown, writeHtmlPack } from "./html-pack.js";
|
|
13
14
|
export { installSkill } from "./install-skill.js";
|
|
14
15
|
export { runCli } from "./cli.js";
|
|
15
16
|
export { runDoctor, renderDoctorMarkdown } from "./doctor.js";
|
|
16
17
|
export { createLlmsTxt } from "./llms-txt.js";
|
|
17
18
|
export { createExecSummary, renderExecSummaryMarkdown, writeExecSummaryOutput } from "./exec-summary.js";
|
|
19
|
+
export { createExportPack, renderExportPackMarkdown, writeExportPack } from "./export-pack.js";
|
|
18
20
|
export { createMeetingPack, renderMeetingPackMarkdown, writeMeetingPackOutput } from "./meeting-pack.js";
|
|
19
21
|
export { createOwnerBoard, renderOwnerBoardMarkdown, writeOwnerBoardOutput } from "./owner-board.js";
|
|
20
22
|
export { createPmBrief, renderPmBriefMarkdown, writePmBriefOutput } from "./pm-brief.js";
|
package/src/quick-start.js
CHANGED
|
@@ -62,7 +62,9 @@ function buildSteps() {
|
|
|
62
62
|
"geo-ai-search-optimization apply-plan ./your-site --out ./reports/apply-plan.md",
|
|
63
63
|
"geo-ai-search-optimization completion-report ./your-site --out ./reports/completion-report.md",
|
|
64
64
|
"geo-ai-search-optimization handoff-bundle ./your-site --out ./reports/handoff-bundle.md",
|
|
65
|
-
"geo-ai-search-optimization share-pack ./your-site --out ./reports/share-pack.md"
|
|
65
|
+
"geo-ai-search-optimization share-pack ./your-site --out ./reports/share-pack.md",
|
|
66
|
+
"geo-ai-search-optimization export-pack ./your-site --out-dir ./exports/your-site-pack",
|
|
67
|
+
"geo-ai-search-optimization html-pack ./your-site --out-dir ./exports/your-site-html"
|
|
66
68
|
]
|
|
67
69
|
},
|
|
68
70
|
{
|