@page.su/ai-blog-cli 0.1.0-beta.1

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.
Files changed (146) hide show
  1. package/README.md +145 -0
  2. package/dist/api-client.d.ts +39 -0
  3. package/dist/api-client.d.ts.map +1 -0
  4. package/dist/api-client.js +163 -0
  5. package/dist/api-client.js.map +1 -0
  6. package/dist/api-client.test.d.ts +2 -0
  7. package/dist/api-client.test.d.ts.map +1 -0
  8. package/dist/api-client.test.js +83 -0
  9. package/dist/api-client.test.js.map +1 -0
  10. package/dist/cli.d.ts +3 -0
  11. package/dist/cli.d.ts.map +1 -0
  12. package/dist/cli.js +74 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/commands/build.d.ts +4 -0
  15. package/dist/commands/build.d.ts.map +1 -0
  16. package/dist/commands/build.js +158 -0
  17. package/dist/commands/build.js.map +1 -0
  18. package/dist/commands/code-repo.d.ts +4 -0
  19. package/dist/commands/code-repo.d.ts.map +1 -0
  20. package/dist/commands/code-repo.js +102 -0
  21. package/dist/commands/code-repo.js.map +1 -0
  22. package/dist/commands/comments.d.ts +4 -0
  23. package/dist/commands/comments.d.ts.map +1 -0
  24. package/dist/commands/comments.js +53 -0
  25. package/dist/commands/comments.js.map +1 -0
  26. package/dist/commands/demo.d.ts +4 -0
  27. package/dist/commands/demo.d.ts.map +1 -0
  28. package/dist/commands/demo.js +72 -0
  29. package/dist/commands/demo.js.map +1 -0
  30. package/dist/commands/helpers.d.ts +21 -0
  31. package/dist/commands/helpers.d.ts.map +1 -0
  32. package/dist/commands/helpers.js +66 -0
  33. package/dist/commands/helpers.js.map +1 -0
  34. package/dist/commands/knowledge.d.ts +4 -0
  35. package/dist/commands/knowledge.d.ts.map +1 -0
  36. package/dist/commands/knowledge.js +146 -0
  37. package/dist/commands/knowledge.js.map +1 -0
  38. package/dist/commands/post.d.ts +4 -0
  39. package/dist/commands/post.d.ts.map +1 -0
  40. package/dist/commands/post.js +207 -0
  41. package/dist/commands/post.js.map +1 -0
  42. package/dist/commands/scout.d.ts +4 -0
  43. package/dist/commands/scout.d.ts.map +1 -0
  44. package/dist/commands/scout.js +48 -0
  45. package/dist/commands/scout.js.map +1 -0
  46. package/dist/commands/series.d.ts +4 -0
  47. package/dist/commands/series.d.ts.map +1 -0
  48. package/dist/commands/series.js +101 -0
  49. package/dist/commands/series.js.map +1 -0
  50. package/dist/commands/skills.d.ts +3 -0
  51. package/dist/commands/skills.d.ts.map +1 -0
  52. package/dist/commands/skills.js +79 -0
  53. package/dist/commands/skills.js.map +1 -0
  54. package/dist/commands/taxonomy.d.ts +4 -0
  55. package/dist/commands/taxonomy.d.ts.map +1 -0
  56. package/dist/commands/taxonomy.js +52 -0
  57. package/dist/commands/taxonomy.js.map +1 -0
  58. package/dist/commands/uploads.d.ts +4 -0
  59. package/dist/commands/uploads.d.ts.map +1 -0
  60. package/dist/commands/uploads.js +37 -0
  61. package/dist/commands/uploads.js.map +1 -0
  62. package/dist/config.d.ts +19 -0
  63. package/dist/config.d.ts.map +1 -0
  64. package/dist/config.js +84 -0
  65. package/dist/config.js.map +1 -0
  66. package/dist/config.test.d.ts +2 -0
  67. package/dist/config.test.d.ts.map +1 -0
  68. package/dist/config.test.js +53 -0
  69. package/dist/config.test.js.map +1 -0
  70. package/dist/index.d.ts +3 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +100 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/prompts/index.d.ts +9 -0
  75. package/dist/prompts/index.d.ts.map +1 -0
  76. package/dist/prompts/index.js +178 -0
  77. package/dist/prompts/index.js.map +1 -0
  78. package/dist/resources/syntax-spec.d.ts +23 -0
  79. package/dist/resources/syntax-spec.d.ts.map +1 -0
  80. package/dist/resources/syntax-spec.js +105 -0
  81. package/dist/resources/syntax-spec.js.map +1 -0
  82. package/dist/resources/syntax-spec.test.d.ts +2 -0
  83. package/dist/resources/syntax-spec.test.d.ts.map +1 -0
  84. package/dist/resources/syntax-spec.test.js +47 -0
  85. package/dist/resources/syntax-spec.test.js.map +1 -0
  86. package/dist/tools/build.d.ts +13 -0
  87. package/dist/tools/build.d.ts.map +1 -0
  88. package/dist/tools/build.js +181 -0
  89. package/dist/tools/build.js.map +1 -0
  90. package/dist/tools/code-repos.d.ts +5 -0
  91. package/dist/tools/code-repos.d.ts.map +1 -0
  92. package/dist/tools/code-repos.js +149 -0
  93. package/dist/tools/code-repos.js.map +1 -0
  94. package/dist/tools/comments.d.ts +12 -0
  95. package/dist/tools/comments.d.ts.map +1 -0
  96. package/dist/tools/comments.js +87 -0
  97. package/dist/tools/comments.js.map +1 -0
  98. package/dist/tools/demos.d.ts +5 -0
  99. package/dist/tools/demos.d.ts.map +1 -0
  100. package/dist/tools/demos.js +98 -0
  101. package/dist/tools/demos.js.map +1 -0
  102. package/dist/tools/glossary.d.ts +4 -0
  103. package/dist/tools/glossary.d.ts.map +1 -0
  104. package/dist/tools/glossary.js +139 -0
  105. package/dist/tools/glossary.js.map +1 -0
  106. package/dist/tools/helpers.d.ts +44 -0
  107. package/dist/tools/helpers.d.ts.map +1 -0
  108. package/dist/tools/helpers.js +65 -0
  109. package/dist/tools/helpers.js.map +1 -0
  110. package/dist/tools/knowledge.d.ts +4 -0
  111. package/dist/tools/knowledge.d.ts.map +1 -0
  112. package/dist/tools/knowledge.js +140 -0
  113. package/dist/tools/knowledge.js.map +1 -0
  114. package/dist/tools/math-concepts.d.ts +4 -0
  115. package/dist/tools/math-concepts.d.ts.map +1 -0
  116. package/dist/tools/math-concepts.js +158 -0
  117. package/dist/tools/math-concepts.js.map +1 -0
  118. package/dist/tools/posts.d.ts +35 -0
  119. package/dist/tools/posts.d.ts.map +1 -0
  120. package/dist/tools/posts.js +278 -0
  121. package/dist/tools/posts.js.map +1 -0
  122. package/dist/tools/scout.d.ts +10 -0
  123. package/dist/tools/scout.d.ts.map +1 -0
  124. package/dist/tools/scout.js +111 -0
  125. package/dist/tools/scout.js.map +1 -0
  126. package/dist/tools/series.d.ts +12 -0
  127. package/dist/tools/series.d.ts.map +1 -0
  128. package/dist/tools/series.js +120 -0
  129. package/dist/tools/series.js.map +1 -0
  130. package/dist/tools/syntax-capabilities.d.ts +15 -0
  131. package/dist/tools/syntax-capabilities.d.ts.map +1 -0
  132. package/dist/tools/syntax-capabilities.js +859 -0
  133. package/dist/tools/syntax-capabilities.js.map +1 -0
  134. package/dist/tools/taxonomy.d.ts +4 -0
  135. package/dist/tools/taxonomy.d.ts.map +1 -0
  136. package/dist/tools/taxonomy.js +73 -0
  137. package/dist/tools/taxonomy.js.map +1 -0
  138. package/dist/tools/uploads.d.ts +15 -0
  139. package/dist/tools/uploads.d.ts.map +1 -0
  140. package/dist/tools/uploads.js +56 -0
  141. package/dist/tools/uploads.js.map +1 -0
  142. package/dist/tools/workflows.d.ts +9 -0
  143. package/dist/tools/workflows.d.ts.map +1 -0
  144. package/dist/tools/workflows.js +249 -0
  145. package/dist/tools/workflows.js.map +1 -0
  146. package/package.json +41 -0
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Agent skills 速查表 (~500 tokens)。
3
+ *
4
+ * 适合注入 Agent system prompt,让 Agent 快速了解可用命令。
5
+ * Agent 不确定用法时调 `aib <command> --help` 按需获取详情。
6
+ *
7
+ * 三层渐进式发现:
8
+ * L1: 本速查表(aib skills)— 覆盖 90% 场景
9
+ * L2: aib <command> --help — 命令组详情
10
+ * L3: aib <command> <subcommand> --help — 单命令参数
11
+ */
12
+ const SKILLS_MD = `# ai-blog CLI (aib)
13
+
14
+ Env: AI_BLOG_BASE_URL + AI_BLOG_PAT
15
+
16
+ ## Write a post
17
+ 1. \`aib taxonomy list --json\` — get category/tag IDs
18
+ 2. \`aib post create --title "Title" --content-file draft.md --status draft\` — create
19
+ 3. \`aib post validate --content-file draft.md\` — validate (fix errors before publish)
20
+ 4. \`aib post publish <id>\` — publish
21
+
22
+ ## Long posts (>5000 words, save tokens)
23
+ 1. \`aib post outline <id>\` — get section outline
24
+ 2. \`aib post section <id> --index 3\` — read section 3
25
+ 3. \`aib post replace-section <id> --index 3 --content-file new.md\` — replace section
26
+ 4. \`aib post append <id> --content-file chapter.md\` — append new chapter
27
+ 5. \`aib post insert-section <id> --after-index 2 --content-file section.md\` — insert
28
+
29
+ ## Demos (interactive code sandboxes)
30
+ - \`aib demo list <postId>\` — list demos (slot, title, file sizes)
31
+ - \`aib demo get-file <postId> <slot> <fileName>\` — read single file (preferred)
32
+ - \`aib demo patch-file <postId> <slot> <fileName> --content-file new.js\` — update file
33
+ - \`aib demo upsert <postId> <slot> --files-file files.json\` — create/replace demo
34
+
35
+ ## Code repositories
36
+ - \`aib code-repo get <postId>\` — get repo linked to post
37
+ - \`aib code-repo list --search "react"\` — find reusable repos
38
+ - \`aib code-repo link <postId> <repoId>\` — link existing repo (N:1 sharing)
39
+ - \`aib code-repo patch-file <postId> --file-path src/index.ts --content-file new.ts\`
40
+
41
+ ## Knowledge base
42
+ - \`aib knowledge find "Promise"\` — find or suggest term entry
43
+ - \`aib knowledge list --domain math\` — list math concepts
44
+
45
+ ## Scout (research material)
46
+ - \`aib scout search "LangGraph" --min-score 7 --json\` — search tech items
47
+ - \`aib scout add-refs <postId> --refs-file refs.json\` — add references to post
48
+
49
+ ## Series
50
+ - \`aib series list\` — list all series
51
+ - \`aib series create --slug "guide" --title "Guide"\`
52
+ - \`aib series add-post <seriesId> <postId>\`
53
+
54
+ ## Build syntax blocks
55
+ - \`aib build frontmatter --title "..." --status draft\`
56
+ - \`aib build image --url "..." --alt "..." --width 50\`
57
+ - \`aib build reference --key "vaswani2017" --title "..." --type paper\`
58
+ - \`aib build live-demo --title "Demo" --files-file files.json\`
59
+ - \`aib build code-group tabs.json\`
60
+ - \`aib build details --title "Details" --content-file body.md\`
61
+ - \`aib build timeline --events-file events.json\`
62
+
63
+ ## Upload images
64
+ - \`aib upload image-from-url <url>\` — upload to blog OSS
65
+
66
+ ## Conventions
67
+ - Add \`--json\` for structured JSON output
68
+ - Use \`--content-file <path>\` for large content
69
+ - Pipe: \`cat draft.md | aib post validate --stdin\`
70
+ - Call \`aib <command> --help\` for detailed usage`;
71
+ export function registerSkillsCommand(program) {
72
+ program
73
+ .command("skills")
74
+ .description("Output a lightweight skills reference for Agent system prompts (~500 tokens)")
75
+ .action(() => {
76
+ console.log(SKILLS_MD);
77
+ });
78
+ }
79
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/commands/skills.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mDA0DiC,CAAC;AAEpD,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,8EAA8E,CAAC;SAC3F,MAAM,CAAC,GAAG,EAAE;QACX,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Command } from "commander";
2
+ import type { ApiClient } from "../api-client.js";
3
+ export declare function registerTaxonomyCommands(program: Command, api: ApiClient): void;
4
+ //# sourceMappingURL=taxonomy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taxonomy.d.ts","sourceRoot":"","sources":["../../src/commands/taxonomy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGlD,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAmD/E"}
@@ -0,0 +1,52 @@
1
+ import { run, isJson } from "./helpers.js";
2
+ export function registerTaxonomyCommands(program, api) {
3
+ const taxonomy = program.command("taxonomy").description("Manage categories and tags");
4
+ // ── taxonomy list ──
5
+ taxonomy
6
+ .command("list")
7
+ .description("List all categories and tags. Call this before creating/updating posts.")
8
+ .option("--json", "Output as JSON")
9
+ .action(async (opts) => {
10
+ await run(() => api.get("/api/cli/taxonomy"), isJson(opts));
11
+ });
12
+ // ── taxonomy create ──
13
+ taxonomy
14
+ .command("create")
15
+ .description("Create a category or tag")
16
+ .requiredOption("--type <type>", "Type: category or tag")
17
+ .requiredOption("--label <label>", "Display name")
18
+ .option("--slug <slug>", "URL slug (auto-generated if empty)")
19
+ .option("--json", "Output as JSON")
20
+ .action(async (opts) => {
21
+ const data = { label: opts.label };
22
+ if (opts.slug)
23
+ data.slug = opts.slug;
24
+ await run(() => api.post("/api/cli/taxonomy", { action: "create", type: opts.type, data }), isJson(opts));
25
+ });
26
+ // ── taxonomy update ──
27
+ taxonomy
28
+ .command("update")
29
+ .description("Update a category or tag")
30
+ .requiredOption("--type <type>", "Type: category or tag")
31
+ .requiredOption("--id <id>", "Entry id (uuid)")
32
+ .requiredOption("--label <label>", "New display name")
33
+ .option("--slug <slug>", "New URL slug")
34
+ .option("--json", "Output as JSON")
35
+ .action(async (opts) => {
36
+ const data = { id: opts.id, label: opts.label };
37
+ if (opts.slug)
38
+ data.slug = opts.slug;
39
+ await run(() => api.post("/api/cli/taxonomy", { action: "update", type: opts.type, data }), isJson(opts));
40
+ });
41
+ // ── taxonomy delete ──
42
+ taxonomy
43
+ .command("delete")
44
+ .description("Permanently delete a category or tag")
45
+ .requiredOption("--type <type>", "Type: category or tag")
46
+ .requiredOption("--id <id>", "Entry id (uuid)")
47
+ .option("--json", "Output as JSON")
48
+ .action(async (opts) => {
49
+ await run(() => api.post("/api/cli/taxonomy", { action: "delete", type: opts.type, id: opts.id }), isJson(opts));
50
+ });
51
+ }
52
+ //# sourceMappingURL=taxonomy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taxonomy.js","sourceRoot":"","sources":["../../src/commands/taxonomy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Command } from "commander";
2
+ import type { ApiClient } from "../api-client.js";
3
+ export declare function registerUploadCommands(program: Command, api: ApiClient): void;
4
+ //# sourceMappingURL=uploads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploads.d.ts","sourceRoot":"","sources":["../../src/commands/uploads.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGlD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAiC7E"}
@@ -0,0 +1,37 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { run, isJson } from "./helpers.js";
3
+ export function registerUploadCommands(program, api) {
4
+ const upload = program.command("upload").description("Upload images to blog OSS");
5
+ // ── upload image-from-url ──
6
+ upload
7
+ .command("image-from-url <url>")
8
+ .description("Upload a remote image to blog OSS, returns stable in-site URL")
9
+ .option("--filename <name>", "Override filename (affects OSS path extension)")
10
+ .option("--json", "Output as JSON")
11
+ .action(async (url, opts) => {
12
+ const body = { source: "url", url };
13
+ if (opts.filename)
14
+ body.filename = opts.filename;
15
+ await run(() => api.post("/api/cli/uploads/image", body), isJson(opts));
16
+ });
17
+ // ── upload image-from-base64 ──
18
+ upload
19
+ .command("image-from-base64")
20
+ .description("Upload a base64-encoded image to blog OSS")
21
+ .requiredOption("--base64-file <path>", "File containing pure base64 (no data: prefix)")
22
+ .requiredOption("--content-type <type>", "Image MIME type (e.g. image/png)")
23
+ .option("--filename <name>", "Override filename")
24
+ .option("--json", "Output as JSON")
25
+ .action(async (opts) => {
26
+ const base64 = readFileSync(opts.base64File, "utf-8").trim();
27
+ const body = {
28
+ source: "base64",
29
+ base64,
30
+ contentType: opts.contentType,
31
+ };
32
+ if (opts.filename)
33
+ body.filename = opts.filename;
34
+ await run(() => api.post("/api/cli/uploads/image", body), isJson(opts));
35
+ });
36
+ }
37
+ //# sourceMappingURL=uploads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploads.js","sourceRoot":"","sources":["../../src/commands/uploads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGvC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,UAAU,sBAAsB,CAAC,OAAgB,EAAE,GAAc;IACrE,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;IAElF,8BAA8B;IAC9B,MAAM;SACH,OAAO,CAAC,sBAAsB,CAAC;SAC/B,WAAW,CAAC,+DAA+D,CAAC;SAC5E,MAAM,CAAC,mBAAmB,EAAE,gDAAgD,CAAC;SAC7E,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC1B,MAAM,IAAI,GAA4B,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QAC7D,IAAI,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QACjD,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,wBAAwB,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEL,iCAAiC;IACjC,MAAM;SACH,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,2CAA2C,CAAC;SACxD,cAAc,CAAC,sBAAsB,EAAE,+CAA+C,CAAC;SACvF,cAAc,CAAC,uBAAuB,EAAE,kCAAkC,CAAC;SAC3E,MAAM,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;SAChD,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7D,MAAM,IAAI,GAA4B;YACpC,MAAM,EAAE,QAAQ;YAChB,MAAM;YACN,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC;QACF,IAAI,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QACjD,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,wBAAwB,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * ai-blog CLI 的运行时配置。
3
+ *
4
+ * 配置优先级(从高到低):
5
+ * 1. 环境变量(AI_BLOG_BASE_URL / AI_BLOG_PAT / AI_BLOG_REQUEST_TIMEOUT_MS)
6
+ * 2. ~/.aib.env 文件(KEY=VALUE 格式,与 .env 相同)
7
+ * 3. ./.aib.env 文件(当前目录,适合项目级覆盖)
8
+ *
9
+ * 任何缺失关键变量的情况都直接 throw,避免起来一个"半残"的 CLI
10
+ * 让用户在调用命令时才看到错误,定位成本高。
11
+ */
12
+ export interface CliConfig {
13
+ baseUrl: string;
14
+ pat: string;
15
+ requestTimeoutMs: number;
16
+ }
17
+ /** 读取并校验环境变量;返回归一化后的配置对象 */
18
+ export declare function loadCliConfig(env?: NodeJS.ProcessEnv): CliConfig;
19
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAuDD,4BAA4B;AAC5B,wBAAgB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAqChE"}
package/dist/config.js ADDED
@@ -0,0 +1,84 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ const DEFAULT_TIMEOUT_MS = 30_000;
5
+ /**
6
+ * 解析 .env 格式文件内容为 key-value 对象。
7
+ * 忽略空行和 # 注释行,支持 VALUE 中包含 = 号。
8
+ */
9
+ function parseEnvFile(content) {
10
+ const result = {};
11
+ for (const line of content.split("\n")) {
12
+ const trimmed = line.trim();
13
+ if (!trimmed || trimmed.startsWith("#")) {
14
+ continue;
15
+ }
16
+ const eqIndex = trimmed.indexOf("=");
17
+ if (eqIndex === -1) {
18
+ continue;
19
+ }
20
+ const key = trimmed.slice(0, eqIndex).trim();
21
+ let value = trimmed.slice(eqIndex + 1).trim();
22
+ // 去掉首尾引号
23
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
24
+ value = value.slice(1, -1);
25
+ }
26
+ result[key] = value;
27
+ }
28
+ return result;
29
+ }
30
+ /**
31
+ * 尝试读取 .aib.env 文件并返回解析后的 key-value。
32
+ * 文件不存在时返回空对象,不抛错。
33
+ */
34
+ function loadEnvFile(filePath) {
35
+ try {
36
+ const content = readFileSync(filePath, "utf-8");
37
+ return parseEnvFile(content);
38
+ }
39
+ catch {
40
+ return {};
41
+ }
42
+ }
43
+ /**
44
+ * 合并配置源:环境变量优先于 .env 文件。
45
+ * 本地 ./.aib.env 优先于全局 ~/.aib.env。
46
+ */
47
+ function resolveEnv() {
48
+ const globalEnv = loadEnvFile(join(homedir(), ".aib.env"));
49
+ const localEnv = loadEnvFile(join(process.cwd(), ".aib.env"));
50
+ // 优先级:process.env > local .aib.env > global ~/.aib.env
51
+ return { ...globalEnv, ...localEnv, ...process.env };
52
+ }
53
+ /** 读取并校验环境变量;返回归一化后的配置对象 */
54
+ export function loadCliConfig(env) {
55
+ const resolvedEnv = env ?? resolveEnv();
56
+ const baseUrl = (resolvedEnv.AI_BLOG_BASE_URL ?? "").trim();
57
+ if (!baseUrl) {
58
+ throw new Error("AI_BLOG_BASE_URL is required.\n" +
59
+ "Set it via environment variable or in ~/.aib.env:\n" +
60
+ ' AI_BLOG_BASE_URL=https://your-blog.example.com');
61
+ }
62
+ // 去掉末尾的 `/`,避免拼接 URL 时出现 `//` 双斜杠
63
+ const normalizedBaseUrl = baseUrl.replace(/\/+$/, "");
64
+ const pat = (resolvedEnv.AI_BLOG_PAT ?? "").trim();
65
+ if (!pat) {
66
+ throw new Error("AI_BLOG_PAT is required.\n" +
67
+ "Create a token at /admin/settings/tokens, then set it:\n" +
68
+ " export AI_BLOG_PAT=aib_pat_xxx # or put it in ~/.aib.env");
69
+ }
70
+ let requestTimeoutMs = DEFAULT_TIMEOUT_MS;
71
+ const rawTimeout = resolvedEnv.AI_BLOG_REQUEST_TIMEOUT_MS;
72
+ if (rawTimeout) {
73
+ const parsed = Number.parseInt(rawTimeout, 10);
74
+ if (Number.isFinite(parsed) && parsed > 0) {
75
+ requestTimeoutMs = parsed;
76
+ }
77
+ }
78
+ return {
79
+ baseUrl: normalizedBaseUrl,
80
+ pat,
81
+ requestTimeoutMs,
82
+ };
83
+ }
84
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { loadCliConfig } from "./config.js";
3
+ /**
4
+ * 验证 loadCliConfig 的边界行为:
5
+ * - 缺关键变量直接抛
6
+ * - URL 末尾斜杠会被归一化
7
+ * - 默认超时存在
8
+ * - AI_BLOG_REQUEST_TIMEOUT_MS 合法时被采纳
9
+ *
10
+ * 注:NodeJS.ProcessEnv 在 @types/node 里被声明为含 NODE_ENV 等必填字段的接口,
11
+ * 但 loadCliConfig 只读取自己关心的几个字段。这里通过 unknown 中转,
12
+ * 让 TypeScript 接受我们构造的"局部 env 对象"。
13
+ */
14
+ function makeEnv(env) {
15
+ return env;
16
+ }
17
+ describe("loadCliConfig", () => {
18
+ it("缺少 AI_BLOG_BASE_URL 时直接抛错", () => {
19
+ expect(() => loadCliConfig(makeEnv({ AI_BLOG_PAT: "x" }))).toThrow(/AI_BLOG_BASE_URL/);
20
+ });
21
+ it("缺少 AI_BLOG_PAT 时直接抛错", () => {
22
+ expect(() => loadCliConfig(makeEnv({ AI_BLOG_BASE_URL: "https://example.com" }))).toThrow(/AI_BLOG_PAT/);
23
+ });
24
+ it("BASE_URL 末尾的斜杠被归一化", () => {
25
+ const config = loadCliConfig(makeEnv({
26
+ AI_BLOG_BASE_URL: "https://example.com///",
27
+ AI_BLOG_PAT: "aib_pat_xxx",
28
+ }));
29
+ expect(config.baseUrl).toBe("https://example.com");
30
+ });
31
+ it("默认超时为 30s,合法配置覆盖默认值", () => {
32
+ const defaults = loadCliConfig(makeEnv({
33
+ AI_BLOG_BASE_URL: "https://example.com",
34
+ AI_BLOG_PAT: "aib_pat_xxx",
35
+ }));
36
+ expect(defaults.requestTimeoutMs).toBe(30_000);
37
+ const overridden = loadCliConfig(makeEnv({
38
+ AI_BLOG_BASE_URL: "https://example.com",
39
+ AI_BLOG_PAT: "aib_pat_xxx",
40
+ AI_BLOG_REQUEST_TIMEOUT_MS: "5000",
41
+ }));
42
+ expect(overridden.requestTimeoutMs).toBe(5_000);
43
+ });
44
+ it("非法超时值被忽略并回落默认", () => {
45
+ const config = loadCliConfig(makeEnv({
46
+ AI_BLOG_BASE_URL: "https://example.com",
47
+ AI_BLOG_PAT: "aib_pat_xxx",
48
+ AI_BLOG_REQUEST_TIMEOUT_MS: "not-a-number",
49
+ }));
50
+ expect(config.requestTimeoutMs).toBe(30_000);
51
+ });
52
+ });
53
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;;;;;;GAUG;AAEH,SAAS,OAAO,CAAC,GAA2B;IAC1C,OAAO,GAAmC,CAAC;AAC7C,CAAC;AAED,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CACvF,aAAa,CACd,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,MAAM,GAAG,aAAa,CAC1B,OAAO,CAAC;YACN,gBAAgB,EAAE,wBAAwB;YAC1C,WAAW,EAAE,aAAa;SAC3B,CAAC,CACH,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,QAAQ,GAAG,aAAa,CAC5B,OAAO,CAAC;YACN,gBAAgB,EAAE,qBAAqB;YACvC,WAAW,EAAE,aAAa;SAC3B,CAAC,CACH,CAAC;QACF,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE/C,MAAM,UAAU,GAAG,aAAa,CAC9B,OAAO,CAAC;YACN,gBAAgB,EAAE,qBAAqB;YACvC,WAAW,EAAE,aAAa;YAC1B,0BAA0B,EAAE,MAAM;SACnC,CAAC,CACH,CAAC;QACF,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,eAAe,EAAE,GAAG,EAAE;QACvB,MAAM,MAAM,GAAG,aAAa,CAC1B,OAAO,CAAC;YACN,gBAAgB,EAAE,qBAAqB;YACvC,WAAW,EAAE,aAAa;YAC1B,0BAA0B,EAAE,cAAc;SAC3C,CAAC,CACH,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ import { dirname, resolve } from "node:path";
5
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
+ import { createApiClient } from "./api-client.js";
8
+ import { loadMcpServerConfig } from "./config.js";
9
+ /**
10
+ * 从和入口同级的 package.json 读取版本号(编译后 dist/index.js 位于 dist/,
11
+ * package.json 在其上一级目录)。这样后续发新版时只需改 package.json 一处。
12
+ */
13
+ function readOwnVersion() {
14
+ const distDir = dirname(fileURLToPath(import.meta.url));
15
+ const pkgPath = resolve(distDir, "..", "package.json");
16
+ try {
17
+ const raw = readFileSync(pkgPath, "utf-8");
18
+ const pkg = JSON.parse(raw);
19
+ return pkg.version ?? "0.0.0";
20
+ }
21
+ catch {
22
+ return "0.0.0";
23
+ }
24
+ }
25
+ import { registerBuildTools } from "./tools/build.js";
26
+ import { registerCommentTools } from "./tools/comments.js";
27
+ import { registerDemoTools } from "./tools/demos.js";
28
+ import { registerPostTools } from "./tools/posts.js";
29
+ import { registerTaxonomyTools } from "./tools/taxonomy.js";
30
+ import { registerUploadTools } from "./tools/uploads.js";
31
+ import { registerKnowledgeTools } from "./tools/knowledge.js";
32
+ import { registerScoutTools } from "./tools/scout.js";
33
+ import { registerSeriesTools } from "./tools/series.js";
34
+ import { registerCodeRepoTools } from "./tools/code-repos.js";
35
+ import { registerSyntaxCapabilitiesTools } from "./tools/syntax-capabilities.js";
36
+ import { registerWorkflowTools } from "./tools/workflows.js";
37
+ import { registerSyntaxSpecResources } from "./resources/syntax-spec.js";
38
+ import { registerPrompts } from "./prompts/index.js";
39
+ /**
40
+ * ai-blog MCP server 入口(stdio)。
41
+ *
42
+ * 启动流程:
43
+ * 1. 读取环境变量配置(缺失即直接退出,避免半残运行)
44
+ * 2. 实例化 McpServer,注册 tools / resources
45
+ * 3. 通过 StdioServerTransport 接管 stdin / stdout,进入消息循环
46
+ *
47
+ * 任何运行期错误都会写到 stderr —— 务必避免污染 stdout,
48
+ * 否则会破坏 MCP JSON-RPC 协议帧。
49
+ */
50
+ async function main() {
51
+ const config = loadMcpServerConfig();
52
+ const api = createApiClient(config);
53
+ const serverVersion = readOwnVersion();
54
+ const server = new McpServer({
55
+ name: "ai-blog-mcp-server",
56
+ version: serverVersion,
57
+ }, {
58
+ capabilities: {
59
+ tools: {},
60
+ resources: {},
61
+ prompts: {},
62
+ },
63
+ });
64
+ // 注册 tools
65
+ registerPostTools(server, api);
66
+ registerDemoTools(server, api);
67
+ registerCommentTools(server, api);
68
+ registerTaxonomyTools(server, api);
69
+ registerKnowledgeTools(server, api);
70
+ registerBuildTools(server, api);
71
+ registerUploadTools(server, api);
72
+ registerScoutTools(server, api);
73
+ registerSeriesTools(server, api);
74
+ registerCodeRepoTools(server, api);
75
+ registerSyntaxCapabilitiesTools(server);
76
+ registerWorkflowTools(server);
77
+ // 注册 resources
78
+ registerSyntaxSpecResources(server, api);
79
+ // 注册 prompts(写作模板)
80
+ registerPrompts(server);
81
+ const transport = new StdioServerTransport();
82
+ await server.connect(transport);
83
+ // 友好的退出处理:收到信号时先 close 再退出
84
+ const shutdown = async (signal) => {
85
+ process.stderr.write(`[ai-blog-mcp] received ${signal}, shutting down...\n`);
86
+ try {
87
+ await server.close();
88
+ }
89
+ finally {
90
+ process.exit(0);
91
+ }
92
+ };
93
+ process.on("SIGINT", () => void shutdown("SIGINT"));
94
+ process.on("SIGTERM", () => void shutdown("SIGTERM"));
95
+ }
96
+ main().catch((error) => {
97
+ process.stderr.write(`[ai-blog-mcp] fatal: ${error instanceof Error ? error.message : String(error)}\n`);
98
+ process.exit(1);
99
+ });
100
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * 写作辅助类 MCP Prompts。
4
+ *
5
+ * 每个模板在 messages 开头都引导 AI 先调 `describe_workflows` 获取完整工作流路线图,
6
+ * 再按推荐步骤执行。大文章场景引导使用 outline/section 精准读写工作流。
7
+ */
8
+ export declare function registerPrompts(server: McpServer): void;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4LvD"}