@aigne/doc-smith 0.9.10 → 0.9.11-beta

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 (308) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +189 -219
  3. package/README.zh.md +270 -0
  4. package/agents/bash-executor/index.mjs +347 -0
  5. package/agents/clear/ai/intent.md +142 -0
  6. package/agents/clear/choose-contents.mjs +13 -65
  7. package/agents/clear/clear-auth-tokens.mjs +17 -21
  8. package/agents/clear/clear-deployment-config.mjs +33 -24
  9. package/agents/clear/index.yaml +1 -9
  10. package/agents/content-checker/ai/intent.md +209 -0
  11. package/agents/content-checker/clean-invalid-docs.mjs +254 -0
  12. package/agents/content-checker/index.mjs +191 -0
  13. package/agents/content-checker/validate-content.mjs +983 -0
  14. package/agents/generate-images/generate-image.yaml +75 -0
  15. package/agents/generate-images/generate-summary.mjs +213 -0
  16. package/agents/generate-images/index.yaml +39 -0
  17. package/agents/generate-images/prepare-generation.mjs +286 -0
  18. package/agents/generate-images/prepare-image-generation.mjs +130 -0
  19. package/{prompts/detail/diagram/generate-image-system.md → agents/generate-images/prompts/system.md} +22 -56
  20. package/agents/generate-images/prompts/user.md +85 -0
  21. package/agents/generate-images/save-image-result.mjs +247 -0
  22. package/agents/generate-images/scan-image-slots.mjs +247 -0
  23. package/agents/localize/index.yaml +19 -42
  24. package/{prompts/translate → agents/localize/prompts}/translate-document.md +0 -139
  25. package/agents/localize/translate-documents/generate-summary.mjs +163 -0
  26. package/agents/localize/translate-documents/load-glossary.mjs +52 -0
  27. package/agents/localize/translate-documents/prepare-translation.mjs +249 -0
  28. package/agents/localize/translate-documents/save-translation.mjs +171 -0
  29. package/agents/localize/translate-documents/translate-document-to-language.mjs +209 -0
  30. package/agents/localize/translate-documents/translate-document.yaml +23 -0
  31. package/agents/localize/translate-documents/translate-to-languages.yaml +10 -0
  32. package/agents/localize/translate-images/check-image-translation.mjs +225 -0
  33. package/agents/localize/translate-images/detect-text/detect-and-update-shared.mjs +148 -0
  34. package/agents/localize/translate-images/detect-text/detect-image-text.yaml +44 -0
  35. package/agents/localize/translate-images/detect-text/detect-images-text.yaml +21 -0
  36. package/agents/localize/translate-images/detect-text/prompts/detect-image-text-system.md +43 -0
  37. package/agents/localize/translate-images/detect-text/prompts/detect-image-text-user.md +14 -0
  38. package/agents/localize/translate-images/detect-text/save-text-detection.mjs +105 -0
  39. package/agents/localize/translate-images/prepare-image-input.mjs +124 -0
  40. package/agents/localize/translate-images/save-image-translation.mjs +172 -0
  41. package/agents/localize/translate-images/scan-doc-images.mjs +165 -0
  42. package/agents/localize/translate-images/translate-doc-images.yaml +24 -0
  43. package/agents/localize/{translate-diagram.yaml → translate-images/translate-image.yaml} +25 -14
  44. package/agents/publish/ai/intent.md +182 -0
  45. package/agents/publish/check.mjs +107 -0
  46. package/agents/publish/index.yaml +9 -14
  47. package/agents/publish/publish-docs.mjs +81 -61
  48. package/agents/publish/translate-meta.mjs +79 -58
  49. package/agents/save-document/index.mjs +260 -0
  50. package/agents/structure-checker/index.mjs +307 -0
  51. package/agents/structure-checker/validate-structure.mjs +477 -0
  52. package/agents/update-image/analyze-feedback.yaml +37 -0
  53. package/agents/update-image/index.yaml +78 -0
  54. package/agents/update-image/load-existing-image.mjs +211 -0
  55. package/agents/update-image/prompts/analyze-feedback-system.md +43 -0
  56. package/agents/update-image/prompts/analyze-feedback-user.md +15 -0
  57. package/aigne.yaml +26 -139
  58. package/package.json +16 -48
  59. package/scripts/README.md +90 -0
  60. package/scripts/install.sh +86 -0
  61. package/scripts/uninstall.sh +52 -0
  62. package/skills/doc-smith/SKILL.md +285 -0
  63. package/skills/doc-smith/ai/intent/sources-improve.md +290 -0
  64. package/skills/doc-smith/references/changeset-guide.md +171 -0
  65. package/skills/doc-smith/references/document-content-guide.md +214 -0
  66. package/skills/doc-smith/references/document-structure-schema.md +138 -0
  67. package/skills/doc-smith/references/patch-guide.md +96 -0
  68. package/skills/doc-smith/references/structure-confirmation-guide.md +133 -0
  69. package/skills/doc-smith/references/structure-planning-guide.md +149 -0
  70. package/skills/doc-smith/references/update-workflow.md +108 -0
  71. package/skills/doc-smith/references/user-intent-guide.md +175 -0
  72. package/skills/doc-smith/references/workspace-initialization.md +376 -0
  73. package/skills/doc-smith-docs-detail/SKILL.md +356 -0
  74. package/skills/doc-smith-docs-detail/ai/intent.md +271 -0
  75. package/skills-entry/doc-smith/ai/intent.md +260 -0
  76. package/skills-entry/doc-smith/index.mjs +66 -0
  77. package/skills-entry/doc-smith/prompt.md +57 -0
  78. package/skills-entry/doc-smith/utils.mjs +27 -0
  79. package/skills-entry/doc-smith-docs-detail/batch.yaml +56 -0
  80. package/skills-entry/doc-smith-docs-detail/index.mjs +95 -0
  81. package/skills-entry/doc-smith-docs-detail/prompt.md +64 -0
  82. package/utils/afs-factory.mjs +183 -0
  83. package/utils/agent-constants.mjs +97 -0
  84. package/utils/{auth-utils.mjs → auth.mjs} +6 -9
  85. package/{agents/utils/update-branding.mjs → utils/branding.mjs} +3 -4
  86. package/utils/config.mjs +261 -0
  87. package/utils/constants.mjs +32 -0
  88. package/utils/deploy.mjs +3 -3
  89. package/utils/docs-converter.mjs +454 -0
  90. package/utils/docs.mjs +212 -0
  91. package/utils/document-paths.mjs +172 -0
  92. package/utils/files.mjs +74 -0
  93. package/utils/git.mjs +65 -0
  94. package/utils/{blocklet.mjs → http.mjs} +18 -0
  95. package/utils/image-slots.mjs +57 -0
  96. package/utils/image-utils.mjs +114 -0
  97. package/utils/project.mjs +95 -0
  98. package/utils/sources-path-resolver.mjs +76 -0
  99. package/utils/{upload-files.mjs → upload.mjs} +3 -3
  100. package/utils/workspace.mjs +371 -0
  101. package/agents/chat/chat-system.md +0 -38
  102. package/agents/chat/index.mjs +0 -59
  103. package/agents/chat/skills/generate-document.yaml +0 -15
  104. package/agents/chat/skills/list-documents.mjs +0 -15
  105. package/agents/chat/skills/update-document.yaml +0 -24
  106. package/agents/clear/clear-document-config.mjs +0 -36
  107. package/agents/clear/clear-document-structure.mjs +0 -102
  108. package/agents/clear/clear-generated-docs.mjs +0 -142
  109. package/agents/clear/clear-media-description.mjs +0 -129
  110. package/agents/create/aggregate-document-structure.mjs +0 -21
  111. package/agents/create/analyze-diagram-type-llm.yaml +0 -159
  112. package/agents/create/analyze-diagram-type.mjs +0 -455
  113. package/agents/create/check-document-structure.yaml +0 -30
  114. package/agents/create/check-need-generate-structure.mjs +0 -138
  115. package/agents/create/document-structure-tools/add-document.mjs +0 -85
  116. package/agents/create/document-structure-tools/delete-document.mjs +0 -116
  117. package/agents/create/document-structure-tools/move-document.mjs +0 -109
  118. package/agents/create/document-structure-tools/update-document.mjs +0 -84
  119. package/agents/create/generate-diagram-image.yaml +0 -91
  120. package/agents/create/generate-structure.yaml +0 -106
  121. package/agents/create/index.yaml +0 -45
  122. package/agents/create/refine-document-structure.yaml +0 -12
  123. package/agents/create/replace-d2-with-image.mjs +0 -610
  124. package/agents/create/update-document-structure.yaml +0 -54
  125. package/agents/create/user-add-document/add-documents-to-structure.mjs +0 -90
  126. package/agents/create/user-add-document/find-documents-to-add-links.yaml +0 -47
  127. package/agents/create/user-add-document/index.yaml +0 -46
  128. package/agents/create/user-add-document/prepare-documents-to-translate.mjs +0 -22
  129. package/agents/create/user-add-document/print-add-document-summary.mjs +0 -63
  130. package/agents/create/user-add-document/review-documents-with-new-links.mjs +0 -110
  131. package/agents/create/user-remove-document/find-documents-with-invalid-links.mjs +0 -78
  132. package/agents/create/user-remove-document/index.yaml +0 -40
  133. package/agents/create/user-remove-document/prepare-documents-to-translate.mjs +0 -22
  134. package/agents/create/user-remove-document/print-remove-document-summary.mjs +0 -53
  135. package/agents/create/user-remove-document/remove-documents-from-structure.mjs +0 -99
  136. package/agents/create/user-remove-document/review-documents-with-invalid-links.mjs +0 -115
  137. package/agents/create/user-review-document-structure.mjs +0 -139
  138. package/agents/create/utils/init-current-content.mjs +0 -34
  139. package/agents/create/utils/merge-document-structures.mjs +0 -36
  140. package/agents/evaluate/code-snippet.mjs +0 -97
  141. package/agents/evaluate/document-structure.yaml +0 -67
  142. package/agents/evaluate/document.yaml +0 -82
  143. package/agents/evaluate/generate-report.mjs +0 -85
  144. package/agents/evaluate/index.yaml +0 -46
  145. package/agents/history/index.yaml +0 -6
  146. package/agents/history/view.mjs +0 -78
  147. package/agents/init/check.mjs +0 -16
  148. package/agents/init/index.mjs +0 -643
  149. package/agents/init/validate.mjs +0 -16
  150. package/agents/localize/choose-language.mjs +0 -107
  151. package/agents/localize/record-translation-history.mjs +0 -23
  152. package/agents/localize/save-doc-translation-or-skip.mjs +0 -18
  153. package/agents/localize/set-review-content.mjs +0 -58
  154. package/agents/localize/translate-document-wrapper.mjs +0 -34
  155. package/agents/localize/translate-document.yaml +0 -24
  156. package/agents/localize/translate-multilingual.yaml +0 -57
  157. package/agents/localize/translate-or-skip-diagram.mjs +0 -52
  158. package/agents/media/batch-generate-media-description.yaml +0 -46
  159. package/agents/media/generate-media-description.yaml +0 -50
  160. package/agents/media/load-media-description.mjs +0 -454
  161. package/agents/prefs/index.mjs +0 -203
  162. package/agents/schema/document-structure-item.yaml +0 -26
  163. package/agents/schema/document-structure-refine-item.yaml +0 -23
  164. package/agents/schema/document-structure.yaml +0 -29
  165. package/agents/update/batch-generate-document.yaml +0 -27
  166. package/agents/update/batch-update-document.yaml +0 -7
  167. package/agents/update/check-diagram-flag.mjs +0 -116
  168. package/agents/update/check-document.mjs +0 -162
  169. package/agents/update/check-generate-diagram.mjs +0 -106
  170. package/agents/update/check-update-is-single.mjs +0 -53
  171. package/agents/update/document-tools/update-document-content.mjs +0 -303
  172. package/agents/update/generate-diagram.yaml +0 -80
  173. package/agents/update/generate-document.yaml +0 -70
  174. package/agents/update/handle-document-update.yaml +0 -103
  175. package/agents/update/index.yaml +0 -69
  176. package/agents/update/pre-check-generate-diagram.yaml +0 -44
  177. package/agents/update/save-and-translate-document.mjs +0 -80
  178. package/agents/update/update-document-detail.yaml +0 -71
  179. package/agents/update/update-single/update-single-document-detail.mjs +0 -322
  180. package/agents/update/update-single-document.yaml +0 -7
  181. package/agents/update/user-review-document.mjs +0 -272
  182. package/agents/utils/action-success.mjs +0 -16
  183. package/agents/utils/analyze-document-feedback-intent.yaml +0 -32
  184. package/agents/utils/analyze-feedback-intent.mjs +0 -253
  185. package/agents/utils/analyze-structure-feedback-intent.yaml +0 -29
  186. package/agents/utils/check-detail-result.mjs +0 -51
  187. package/agents/utils/check-feedback-refiner.mjs +0 -81
  188. package/agents/utils/choose-docs.mjs +0 -251
  189. package/agents/utils/document-icon-generate.yaml +0 -52
  190. package/agents/utils/document-title-streamline.yaml +0 -48
  191. package/agents/utils/ensure-document-icons.mjs +0 -129
  192. package/agents/utils/exit.mjs +0 -6
  193. package/agents/utils/feedback-refiner.yaml +0 -50
  194. package/agents/utils/find-item-by-path.mjs +0 -114
  195. package/agents/utils/find-user-preferences-by-path.mjs +0 -37
  196. package/agents/utils/format-document-structure.mjs +0 -35
  197. package/agents/utils/generate-document-or-skip.mjs +0 -41
  198. package/agents/utils/handle-diagram-operations.mjs +0 -263
  199. package/agents/utils/load-all-document-content.mjs +0 -30
  200. package/agents/utils/load-document-all-content.mjs +0 -96
  201. package/agents/utils/load-sources.mjs +0 -405
  202. package/agents/utils/map-reasoning-effort-level.mjs +0 -15
  203. package/agents/utils/post-generate.mjs +0 -133
  204. package/agents/utils/read-current-document-content.mjs +0 -46
  205. package/agents/utils/save-doc-translation.mjs +0 -30
  206. package/agents/utils/save-doc.mjs +0 -54
  207. package/agents/utils/save-output.mjs +0 -26
  208. package/agents/utils/save-sidebar.mjs +0 -38
  209. package/agents/utils/skip-if-content-exists.mjs +0 -27
  210. package/agents/utils/streamline-document-titles-if-needed.mjs +0 -88
  211. package/agents/utils/transform-detail-data-sources.mjs +0 -45
  212. package/assets/report-template/report.html +0 -198
  213. package/docs-mcp/analyze-content-relevance.yaml +0 -50
  214. package/docs-mcp/analyze-docs-relevance.yaml +0 -59
  215. package/docs-mcp/docs-search.yaml +0 -42
  216. package/docs-mcp/get-docs-detail.mjs +0 -41
  217. package/docs-mcp/get-docs-structure.mjs +0 -16
  218. package/docs-mcp/read-doc-content.mjs +0 -119
  219. package/prompts/common/document/content-rules-core.md +0 -20
  220. package/prompts/common/document/markdown-syntax-rules.md +0 -65
  221. package/prompts/common/document/media-file-list-usage-rules.md +0 -18
  222. package/prompts/common/document/openapi-usage-rules.md +0 -189
  223. package/prompts/common/document/role-and-personality.md +0 -16
  224. package/prompts/common/document/user-preferences.md +0 -9
  225. package/prompts/common/document-structure/conflict-resolution-guidance.md +0 -16
  226. package/prompts/common/document-structure/document-icon-generate.md +0 -116
  227. package/prompts/common/document-structure/document-structure-rules.md +0 -43
  228. package/prompts/common/document-structure/document-title-streamline.md +0 -86
  229. package/prompts/common/document-structure/glossary.md +0 -7
  230. package/prompts/common/document-structure/intj-traits.md +0 -5
  231. package/prompts/common/document-structure/openapi-usage-rules.md +0 -28
  232. package/prompts/common/document-structure/output-constraints.md +0 -18
  233. package/prompts/common/document-structure/user-locale-rules.md +0 -10
  234. package/prompts/common/document-structure/user-preferences.md +0 -9
  235. package/prompts/detail/custom/admonition-usage-rules.md +0 -94
  236. package/prompts/detail/custom/code-block-usage-rules.md +0 -163
  237. package/prompts/detail/custom/custom-components/x-card-usage-rules.md +0 -63
  238. package/prompts/detail/custom/custom-components/x-cards-usage-rules.md +0 -83
  239. package/prompts/detail/custom/custom-components/x-field-desc-usage-rules.md +0 -120
  240. package/prompts/detail/custom/custom-components/x-field-group-usage-rules.md +0 -80
  241. package/prompts/detail/custom/custom-components/x-field-usage-rules.md +0 -189
  242. package/prompts/detail/custom/custom-components-usage-rules.md +0 -18
  243. package/prompts/detail/diagram/generate-image-user.md +0 -81
  244. package/prompts/detail/diagram/guide.md +0 -29
  245. package/prompts/detail/diagram/official-examples.md +0 -712
  246. package/prompts/detail/diagram/pre-check.md +0 -23
  247. package/prompts/detail/diagram/role-and-personality.md +0 -2
  248. package/prompts/detail/diagram/rules.md +0 -46
  249. package/prompts/detail/diagram/system-prompt.md +0 -1139
  250. package/prompts/detail/diagram/user-prompt.md +0 -43
  251. package/prompts/detail/generate/detail-example.md +0 -457
  252. package/prompts/detail/generate/document-rules.md +0 -45
  253. package/prompts/detail/generate/system-prompt.md +0 -61
  254. package/prompts/detail/generate/user-prompt.md +0 -99
  255. package/prompts/detail/jsx/rules.md +0 -6
  256. package/prompts/detail/update/system-prompt.md +0 -121
  257. package/prompts/detail/update/user-prompt.md +0 -41
  258. package/prompts/evaluate/document-structure.md +0 -93
  259. package/prompts/evaluate/document.md +0 -149
  260. package/prompts/media/media-description/system-prompt.md +0 -43
  261. package/prompts/media/media-description/user-prompt.md +0 -17
  262. package/prompts/structure/check-document-structure.md +0 -93
  263. package/prompts/structure/document-rules.md +0 -21
  264. package/prompts/structure/find-documents-to-add-links.md +0 -52
  265. package/prompts/structure/generate/system-prompt.md +0 -13
  266. package/prompts/structure/generate/user-prompt.md +0 -137
  267. package/prompts/structure/review/structure-review-system.md +0 -81
  268. package/prompts/structure/structure-example.md +0 -89
  269. package/prompts/structure/structure-getting-started.md +0 -10
  270. package/prompts/structure/update/system-prompt.md +0 -93
  271. package/prompts/structure/update/user-prompt.md +0 -43
  272. package/prompts/translate/admonition.md +0 -20
  273. package/prompts/translate/code-block.md +0 -33
  274. package/prompts/utils/analyze-document-feedback-intent.md +0 -54
  275. package/prompts/utils/analyze-structure-feedback-intent.md +0 -43
  276. package/prompts/utils/feedback-refiner.md +0 -105
  277. package/types/document-schema.mjs +0 -55
  278. package/types/document-structure-schema.mjs +0 -261
  279. package/utils/check-document-has-diagram.mjs +0 -95
  280. package/utils/conflict-detector.mjs +0 -149
  281. package/utils/constants/index.mjs +0 -620
  282. package/utils/constants/linter.mjs +0 -102
  283. package/utils/d2-utils.mjs +0 -205
  284. package/utils/debug.mjs +0 -3
  285. package/utils/delete-diagram-images.mjs +0 -99
  286. package/utils/diagram-version-utils.mjs +0 -14
  287. package/utils/docs-finder-utils.mjs +0 -548
  288. package/utils/evaluate/report-utils.mjs +0 -132
  289. package/utils/extract-api.mjs +0 -32
  290. package/utils/file-utils.mjs +0 -960
  291. package/utils/history-utils.mjs +0 -203
  292. package/utils/icon-map.mjs +0 -26
  293. package/utils/image-compress.mjs +0 -154
  294. package/utils/kroki-utils.mjs +0 -173
  295. package/utils/linter/index.mjs +0 -50
  296. package/utils/load-config.mjs +0 -78
  297. package/utils/markdown/index.mjs +0 -26
  298. package/utils/markdown-checker.mjs +0 -694
  299. package/utils/mermaid-validator.mjs +0 -140
  300. package/utils/mermaid-worker-pool.mjs +0 -250
  301. package/utils/mermaid-worker.mjs +0 -233
  302. package/utils/openapi/index.mjs +0 -28
  303. package/utils/preferences-utils.mjs +0 -175
  304. package/utils/request.mjs +0 -10
  305. package/utils/sync-diagram-to-translations.mjs +0 -272
  306. package/utils/translate-diagram-images.mjs +0 -807
  307. package/utils/utils.mjs +0 -1354
  308. /package/{prompts/translate → agents/localize/prompts}/glossary.md +0 -0
@@ -5,21 +5,19 @@ import fs from "fs-extra";
5
5
  import { parse as yamlParse, stringify as yamlStringify } from "yaml";
6
6
  import z from "zod";
7
7
 
8
- import { DOC_SMITH_DIR } from "../../utils/constants/index.mjs";
9
- import { loadDocumentStructure } from "../../utils/docs-finder-utils.mjs";
10
- import { saveValueToConfig } from "../../utils/utils.mjs";
11
-
12
- export default async function translateMeta(
13
- { projectName, projectDesc, locale, translateLanguages = [] },
14
- options,
15
- ) {
8
+ import { PATHS } from "../../utils/agent-constants.mjs";
9
+ import { loadDocumentStructure } from "../../utils/docs.mjs";
10
+ import { saveValueToConfig } from "../../utils/config.mjs";
11
+
12
+ export default async function translateMeta({ config }, options) {
13
+ const { projectName, projectDesc, locale, translateLanguages = [] } = config;
16
14
  const languages = [...new Set([...(locale ? [locale] : []), ...(translateLanguages || [])])];
17
15
 
18
16
  // If projectDesc is empty, first try to load overview.md, then fallback to structure-plan.json
19
17
  let finalProjectDesc = projectDesc;
20
18
  if (!finalProjectDesc || finalProjectDesc.trim() === "") {
21
19
  // First, try to read overview.md
22
- const overviewFilePath = join(DOC_SMITH_DIR, "docs", "overview.md");
20
+ const overviewFilePath = join("docs", "overview", "en.md");
23
21
  const overviewExists = await fs.pathExists(overviewFilePath);
24
22
 
25
23
  if (overviewExists) {
@@ -32,7 +30,7 @@ export default async function translateMeta(
32
30
  }
33
31
  } else {
34
32
  try {
35
- const outputDir = join(DOC_SMITH_DIR, "output");
33
+ const outputDir = "./planning";
36
34
  const documentStructure = await loadDocumentStructure(outputDir);
37
35
  if (documentStructure && Array.isArray(documentStructure)) {
38
36
  const overviewItem =
@@ -50,7 +48,10 @@ export default async function translateMeta(
50
48
  }
51
49
  }
52
50
 
53
- const translationCacheFilePath = join(DOC_SMITH_DIR, "translation-cache.yaml");
51
+ // Ensure cache directory exists
52
+ await fs.ensureDir(PATHS.CACHE);
53
+
54
+ const translationCacheFilePath = join(PATHS.CACHE, "translation-cache.yaml");
54
55
  await fs.ensureFile(translationCacheFilePath);
55
56
  const translationCache = await fs.readFile(translationCacheFilePath, "utf-8");
56
57
  const parsedTranslationCache = yamlParse(translationCache || "{}");
@@ -58,36 +59,47 @@ export default async function translateMeta(
58
59
  const titleTranslation = parsedTranslationCache[projectName] || {};
59
60
  const descTranslation = parsedTranslationCache[projectDesc] || {};
60
61
 
61
- const titleLanguages = languages.filter((lang) => !titleTranslation[lang]);
62
- const descLanguages = languages.filter((lang) => !descTranslation[lang]);
63
- const titleTranslationSchema = z.object(
64
- titleLanguages.reduce((shape, lang) => {
65
- shape[lang] = z.string();
66
- return shape;
67
- }, {}),
68
- );
69
- const descTranslationSchema = z.object(
70
- descLanguages.reduce((shape, lang) => {
71
- shape[lang] = z.string();
72
- return shape;
73
- }, {}),
74
- );
75
-
76
- const agent = AIAgent.from({
77
- name: "translateMeta",
78
- instructions:
79
- "You are an **Elite Polyglot Localization and Translation Specialist** with extensive professional experience across multiple domains. Your core mission is to produce translations that are not only **100% accurate** to the source meaning but are also **natively fluent, highly readable, and culturally appropriate** in the target language.",
80
- inputKey: "message",
81
- outputSchema: z.object({
82
- title: titleTranslationSchema.describe("Translated titles with language codes as keys"),
83
- desc: descTranslationSchema.describe(
84
- "Translated descriptions with language codes as keys. Each description MUST be within 100 characters.",
85
- ),
86
- }),
87
- });
88
- if (titleLanguages.length > 0 || descLanguages.length > 0) {
89
- const translatedMetadata = await options.context.invoke(agent, {
90
- message: `Translate the following title and description into all target languages except the source language. Provide the translations in a JSON object with the language codes as keys. If the project title or description is empty, return an empty string for that field.
62
+ // If only one language, skip translation and cache original content directly
63
+ if (languages.length <= 1) {
64
+ const singleLang = languages[0] || locale || "en";
65
+ if (projectName && !titleTranslation[singleLang]) {
66
+ titleTranslation[singleLang] = projectName;
67
+ }
68
+ if (finalProjectDesc && !descTranslation[singleLang]) {
69
+ descTranslation[singleLang] = finalProjectDesc;
70
+ }
71
+ } else {
72
+ // Multiple languages: need translation
73
+ const titleLanguages = languages.filter((lang) => !titleTranslation[lang]);
74
+ const descLanguages = languages.filter((lang) => !descTranslation[lang]);
75
+ const titleTranslationSchema = z.object(
76
+ titleLanguages.reduce((shape, lang) => {
77
+ shape[lang] = z.string();
78
+ return shape;
79
+ }, {}),
80
+ );
81
+ const descTranslationSchema = z.object(
82
+ descLanguages.reduce((shape, lang) => {
83
+ shape[lang] = z.string();
84
+ return shape;
85
+ }, {}),
86
+ );
87
+
88
+ const agent = AIAgent.from({
89
+ name: "translateMeta",
90
+ instructions:
91
+ "You are an **Elite Polyglot Localization and Translation Specialist** with extensive professional experience across multiple domains. Your core mission is to produce translations that are not only **100% accurate** to the source meaning but are also **natively fluent, highly readable, and culturally appropriate** in the target language.",
92
+ inputKey: "message",
93
+ outputSchema: z.object({
94
+ title: titleTranslationSchema.describe("Translated titles with language codes as keys"),
95
+ desc: descTranslationSchema.describe(
96
+ "Translated descriptions with language codes as keys. Each description MUST be within 100 characters.",
97
+ ),
98
+ }),
99
+ });
100
+ if (titleLanguages.length > 0 || descLanguages.length > 0) {
101
+ const translatedMetadata = await options.context.invoke(agent, {
102
+ message: `Translate the following title and description into all target languages except the source language. Provide the translations in a JSON object with the language codes as keys. If the project title or description is empty, return an empty string for that field.
91
103
 
92
104
  **IMPORTANT**: The description translations MUST be concise and within 100 characters. If the source description is long, extract and translate only the key points or create a brief summary that captures the essence.
93
105
 
@@ -116,23 +128,19 @@ Respond with a JSON object in the following format:
116
128
  - Be concise and capture the core essence of the project
117
129
  - Use natural, fluent language appropriate for the target culture
118
130
  - If the source is very long, create a brief summary instead of a full translation
119
-
120
- If no translation is needed, respond with:
121
- {
122
- "title": {},
123
- "desc": {}
124
- }`,
125
- });
126
- Object.keys(translatedMetadata.title || {}).forEach((lang) => {
127
- if (translatedMetadata.title[lang]) {
128
- titleTranslation[lang] = translatedMetadata.title[lang];
129
- }
130
- });
131
- Object.keys(translatedMetadata.desc || {}).forEach((lang) => {
132
- if (translatedMetadata.desc[lang]) {
133
- descTranslation[lang] = translatedMetadata.desc[lang];
134
- }
135
- });
131
+ `,
132
+ });
133
+ Object.keys(translatedMetadata.title || {}).forEach((lang) => {
134
+ if (translatedMetadata.title[lang]) {
135
+ titleTranslation[lang] = translatedMetadata.title[lang];
136
+ }
137
+ });
138
+ Object.keys(translatedMetadata.desc || {}).forEach((lang) => {
139
+ if (translatedMetadata.desc[lang]) {
140
+ descTranslation[lang] = translatedMetadata.desc[lang];
141
+ }
142
+ });
143
+ }
136
144
  }
137
145
 
138
146
  if (!projectDesc && finalProjectDesc) {
@@ -153,3 +161,16 @@ If no translation is needed, respond with:
153
161
  },
154
162
  };
155
163
  }
164
+
165
+ translateMeta.description =
166
+ "Translate project metadata (title and description) to multiple languages";
167
+
168
+ translateMeta.input_schema = {
169
+ type: "object",
170
+ properties: {
171
+ config: {
172
+ type: "object",
173
+ description: "Configuration object from check step.",
174
+ },
175
+ },
176
+ };
@@ -0,0 +1,260 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
3
+ import { stringify as yamlStringify } from "yaml";
4
+ import path from "node:path";
5
+ import {
6
+ normalizePath,
7
+ loadDocumentPaths,
8
+ isValidDocumentPath,
9
+ } from "../../utils/document-paths.mjs";
10
+ import { PATHS, ERROR_CODES, FILE_TYPES, DOC_META_DEFAULTS } from "../../utils/agent-constants.mjs";
11
+ import { loadLocale } from "../../utils/config.mjs";
12
+
13
+ /**
14
+ * Create document folder and files
15
+ * @param {string} filePath - File path (without slash)
16
+ * @param {string} language - Language code
17
+ * @param {string} content - Document content
18
+ * @returns {Promise<Object>} - Created file paths
19
+ */
20
+ async function createDocumentFiles(filePath, language, content) {
21
+ const docFolder = path.join(PATHS.DOCS_DIR, filePath);
22
+
23
+ // 1. Create folder (recursive creation, ignore if already exists)
24
+ await mkdir(docFolder, { recursive: true });
25
+
26
+ // 2. Generate .meta.yaml
27
+ const metaContent = yamlStringify({
28
+ kind: DOC_META_DEFAULTS.KIND,
29
+ source: language,
30
+ default: language,
31
+ });
32
+ const metaPath = path.join(docFolder, FILE_TYPES.META);
33
+ await writeFile(metaPath, metaContent, "utf8");
34
+
35
+ // 3. Save language file
36
+ const langFile = `${language}${FILE_TYPES.MARKDOWN}`;
37
+ const langPath = path.join(docFolder, langFile);
38
+ await writeFile(langPath, content, "utf8");
39
+
40
+ return {
41
+ folder: docFolder,
42
+ metaFile: metaPath,
43
+ contentFile: langPath,
44
+ };
45
+ }
46
+
47
+ /**
48
+ * Save document to docs directory
49
+ * @param {Object} params - Parameters
50
+ * @param {string} params.path - Document path (with or without slash)
51
+ * @param {string} params.content - Document content (Markdown format)
52
+ * @param {Object} params.options - Options
53
+ * @param {string} params.options.language - Language code (e.g., zh, en, ja)
54
+ * @returns {Promise<Object>} - Operation result
55
+ */
56
+ export default async function saveDocument({ path: rawPath, content, options = {} }) {
57
+ try {
58
+ // 1. Parameter validation: content
59
+ if (!content || typeof content !== "string" || content.trim().length === 0) {
60
+ return {
61
+ success: false,
62
+ error: ERROR_CODES.EMPTY_CONTENT,
63
+ message: "Document content cannot be empty",
64
+ suggestion: "Please provide valid document content",
65
+ };
66
+ }
67
+
68
+ // 2. Parameter validation: language
69
+ const language = options.language;
70
+ if (!language || typeof language !== "string") {
71
+ return {
72
+ success: false,
73
+ error: ERROR_CODES.INVALID_LANGUAGE,
74
+ message: `Invalid language code: ${language}`,
75
+ suggestion: "Please provide a valid language code (e.g., zh, en, ja)",
76
+ };
77
+ }
78
+
79
+ // Validate language code format (e.g., zh, en, zh-CN, en-US)
80
+ const languagePattern = /^[a-z]{2}(-[A-Z]{2})?$/;
81
+ if (!languagePattern.test(language)) {
82
+ return {
83
+ success: false,
84
+ error: ERROR_CODES.INVALID_LANGUAGE,
85
+ message: `Invalid language code format: ${language}`,
86
+ suggestion: "Language code should follow format: zh, en, ja or zh-CN, en-US, etc.",
87
+ };
88
+ }
89
+
90
+ // 3. Parameter validation: path
91
+ if (!rawPath || typeof rawPath !== "string") {
92
+ return {
93
+ success: false,
94
+ error: ERROR_CODES.INVALID_PATH,
95
+ message: "Invalid document path",
96
+ suggestion: "Please provide a valid document path",
97
+ };
98
+ }
99
+
100
+ // 4. Normalize path
101
+ const { filePath, displayPath } = normalizePath(rawPath);
102
+
103
+ // 5. Load and validate document structure
104
+ let validPaths;
105
+ try {
106
+ validPaths = await loadDocumentPaths({ includeBothFormats: true });
107
+ } catch (error) {
108
+ if (error.message === ERROR_CODES.MISSING_STRUCTURE_FILE) {
109
+ return {
110
+ success: false,
111
+ error: ERROR_CODES.MISSING_STRUCTURE_FILE,
112
+ message: `Document structure file not found: ${PATHS.DOCUMENT_STRUCTURE}`,
113
+ suggestion: "Please generate the document structure file first",
114
+ };
115
+ }
116
+ throw error;
117
+ }
118
+
119
+ // 6. Validate path exists in document structure
120
+ if (!isValidDocumentPath(rawPath, validPaths)) {
121
+ return {
122
+ success: false,
123
+ error: ERROR_CODES.PATH_NOT_IN_STRUCTURE,
124
+ message: `Document path ${displayPath} does not exist in document structure`,
125
+ suggestion: `Please add this path to ${PATHS.DOCUMENT_STRUCTURE} first, or check if the path is correct`,
126
+ };
127
+ }
128
+
129
+ // 7. Check that language must equal project locale when creating new document
130
+ const docFolder = path.join(PATHS.DOCS_DIR, filePath);
131
+ const metaPath = path.join(docFolder, FILE_TYPES.META);
132
+ const isNewDocument = !existsSync(metaPath);
133
+
134
+ if (isNewDocument) {
135
+ let projectLocale;
136
+ try {
137
+ projectLocale = await loadLocale();
138
+ } catch (_error) {
139
+ return {
140
+ success: false,
141
+ error: ERROR_CODES.MISSING_CONFIG_FILE,
142
+ message: "Cannot read project configuration file",
143
+ suggestion: "Please ensure config.yaml exists and contains the locale field",
144
+ };
145
+ }
146
+
147
+ if (language !== projectLocale) {
148
+ return {
149
+ success: false,
150
+ error: ERROR_CODES.INVALID_LANGUAGE,
151
+ message: `New documents must use project main language: ${projectLocale}, provided: ${language}`,
152
+ suggestion: `Please change language parameter to "${projectLocale}" (project locale), generate main language version first`,
153
+ };
154
+ }
155
+ }
156
+
157
+ // 8. Create folder and files
158
+ const files = await createDocumentFiles(filePath, language, content);
159
+
160
+ // 9. Return success response
161
+ return {
162
+ success: true,
163
+ path: displayPath,
164
+ folder: files.folder,
165
+ files: {
166
+ meta: files.metaFile,
167
+ content: files.contentFile,
168
+ },
169
+ message: `Document saved successfully: ${displayPath} (${language})`,
170
+ };
171
+ } catch (error) {
172
+ // Catch unexpected errors
173
+ return {
174
+ success: false,
175
+ error: ERROR_CODES.FILE_OPERATION_ERROR,
176
+ message: `File operation failed: ${error.message}`,
177
+ suggestion: "Check file system permissions or if path is correct",
178
+ };
179
+ }
180
+ }
181
+
182
+ // Add description
183
+ saveDocument.description =
184
+ `Save document to ${PATHS.DOCS_DIR} directory, automatically create folder structure, meta info file and language version file. ` +
185
+ "[Important restriction] This tool is only for creating new documents. When editing existing documents, use the Edit tool to modify the corresponding language file directly. " +
186
+ `Must ensure ${PATHS.DOCUMENT_STRUCTURE} exists and contains the target document path before use. ` +
187
+ "[Mandatory requirement] When creating new documents, language must equal project locale (locale field in config.yaml), the system will auto-validate.";
188
+
189
+ // Define input schema
190
+ saveDocument.input_schema = {
191
+ type: "object",
192
+ required: ["path", "content", "options"],
193
+ properties: {
194
+ path: {
195
+ type: "string",
196
+ description: "Document path, must exist in planning/document-structure.yaml",
197
+ },
198
+ content: {
199
+ type: "string",
200
+ description: "Document content (Markdown format), cannot be empty",
201
+ },
202
+ options: {
203
+ type: "object",
204
+ required: ["language"],
205
+ properties: {
206
+ language: {
207
+ type: "string",
208
+ description:
209
+ "Language code (e.g., zh, en, ja), must be read from locale field in config.yaml",
210
+ },
211
+ },
212
+ },
213
+ },
214
+ };
215
+
216
+ // Define output schema
217
+ saveDocument.output_schema = {
218
+ type: "object",
219
+ required: ["success"],
220
+ properties: {
221
+ success: {
222
+ type: "boolean",
223
+ description: "Whether operation succeeded",
224
+ },
225
+ path: {
226
+ type: "string",
227
+ description: "Normalized document path (present on success)",
228
+ },
229
+ folder: {
230
+ type: "string",
231
+ description: "Created folder path (present on success)",
232
+ },
233
+ files: {
234
+ type: "object",
235
+ description: "Created file paths (present on success)",
236
+ properties: {
237
+ meta: {
238
+ type: "string",
239
+ description: "Meta info file path",
240
+ },
241
+ content: {
242
+ type: "string",
243
+ description: "Language file path",
244
+ },
245
+ },
246
+ },
247
+ message: {
248
+ type: "string",
249
+ description: "Operation result description",
250
+ },
251
+ error: {
252
+ type: "string",
253
+ description: "Error code (present on failure)",
254
+ },
255
+ suggestion: {
256
+ type: "string",
257
+ description: "Suggested action (present on failure)",
258
+ },
259
+ },
260
+ };