@aigne/doc-smith 0.8.12-beta.7 → 0.8.12-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/agents/clear/choose-contents.mjs +14 -1
  3. package/agents/clear/clear-media-description.mjs +129 -0
  4. package/agents/clear/index.yaml +3 -1
  5. package/agents/evaluate/code-snippet.mjs +28 -24
  6. package/agents/evaluate/document-structure.yaml +0 -4
  7. package/agents/evaluate/document.yaml +1 -5
  8. package/agents/generate/index.yaml +1 -0
  9. package/agents/init/index.mjs +10 -0
  10. package/agents/media/batch-generate-media-description.yaml +44 -0
  11. package/agents/media/generate-media-description.yaml +47 -0
  12. package/agents/media/load-media-description.mjs +238 -0
  13. package/agents/publish/index.yaml +4 -0
  14. package/agents/publish/publish-docs.mjs +77 -5
  15. package/agents/publish/translate-meta.mjs +103 -0
  16. package/agents/update/generate-document.yaml +30 -28
  17. package/agents/update/index.yaml +1 -0
  18. package/agents/update/update-document-detail.yaml +3 -1
  19. package/agents/utils/load-sources.mjs +103 -53
  20. package/agents/utils/update-branding.mjs +69 -0
  21. package/aigne.yaml +6 -0
  22. package/assets/report-template/report.html +34 -34
  23. package/package.json +17 -2
  24. package/prompts/common/document/role-and-personality.md +3 -1
  25. package/prompts/detail/d2-diagram/guide.md +7 -1
  26. package/prompts/detail/d2-diagram/user-prompt.md +3 -0
  27. package/prompts/detail/generate/system-prompt.md +6 -7
  28. package/prompts/detail/generate/user-prompt.md +12 -3
  29. package/prompts/detail/update/user-prompt.md +0 -2
  30. package/prompts/evaluate/document-structure.md +6 -7
  31. package/prompts/evaluate/document.md +16 -25
  32. package/prompts/media/media-description/system-prompt.md +35 -0
  33. package/prompts/media/media-description/user-prompt.md +8 -0
  34. package/prompts/structure/update/user-prompt.md +0 -4
  35. package/utils/constants/index.mjs +0 -107
  36. package/utils/file-utils.mjs +86 -0
  37. package/utils/markdown-checker.mjs +0 -20
  38. package/utils/request.mjs +7 -0
  39. package/utils/upload-files.mjs +231 -0
  40. package/utils/utils.mjs +11 -1
  41. package/.aigne/doc-smith/config.yaml +0 -77
  42. package/.aigne/doc-smith/history.yaml +0 -37
  43. package/.aigne/doc-smith/output/structure-plan.json +0 -162
  44. package/.aigne/doc-smith/preferences.yml +0 -97
  45. package/.aigne/doc-smith/upload-cache.yaml +0 -1893
  46. package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
  47. package/.github/workflows/ci.yml +0 -54
  48. package/.github/workflows/create-release-pr.yaml +0 -21
  49. package/.github/workflows/publish-docs.yml +0 -65
  50. package/.github/workflows/release.yml +0 -49
  51. package/.github/workflows/reviewer.yml +0 -54
  52. package/.release-please-manifest.json +0 -3
  53. package/RELEASE.md +0 -9
  54. package/assets/screenshots/doc-complete-setup.png +0 -0
  55. package/assets/screenshots/doc-generate-docs.png +0 -0
  56. package/assets/screenshots/doc-generate.png +0 -0
  57. package/assets/screenshots/doc-generated-successfully.png +0 -0
  58. package/assets/screenshots/doc-publish.png +0 -0
  59. package/assets/screenshots/doc-regenerate.png +0 -0
  60. package/assets/screenshots/doc-translate-langs.png +0 -0
  61. package/assets/screenshots/doc-translate.png +0 -0
  62. package/assets/screenshots/doc-update.png +0 -0
  63. package/biome.json +0 -73
  64. package/codecov.yml +0 -15
  65. package/docs/_sidebar.md +0 -15
  66. package/docs/configuration-initial-setup.ja.md +0 -179
  67. package/docs/configuration-initial-setup.md +0 -179
  68. package/docs/configuration-initial-setup.zh-TW.md +0 -179
  69. package/docs/configuration-initial-setup.zh.md +0 -179
  70. package/docs/configuration-managing-preferences.ja.md +0 -100
  71. package/docs/configuration-managing-preferences.md +0 -100
  72. package/docs/configuration-managing-preferences.zh-TW.md +0 -100
  73. package/docs/configuration-managing-preferences.zh.md +0 -100
  74. package/docs/configuration.ja.md +0 -96
  75. package/docs/configuration.md +0 -96
  76. package/docs/configuration.zh-TW.md +0 -96
  77. package/docs/configuration.zh.md +0 -96
  78. package/docs/getting-started.ja.md +0 -88
  79. package/docs/getting-started.md +0 -88
  80. package/docs/getting-started.zh-TW.md +0 -88
  81. package/docs/getting-started.zh.md +0 -88
  82. package/docs/guides-cleaning-up.ja.md +0 -51
  83. package/docs/guides-cleaning-up.md +0 -51
  84. package/docs/guides-cleaning-up.zh-TW.md +0 -51
  85. package/docs/guides-cleaning-up.zh.md +0 -51
  86. package/docs/guides-evaluating-documents.ja.md +0 -66
  87. package/docs/guides-evaluating-documents.md +0 -66
  88. package/docs/guides-evaluating-documents.zh-TW.md +0 -66
  89. package/docs/guides-evaluating-documents.zh.md +0 -66
  90. package/docs/guides-generating-documentation.ja.md +0 -151
  91. package/docs/guides-generating-documentation.md +0 -151
  92. package/docs/guides-generating-documentation.zh-TW.md +0 -151
  93. package/docs/guides-generating-documentation.zh.md +0 -151
  94. package/docs/guides-interactive-chat.ja.md +0 -85
  95. package/docs/guides-interactive-chat.md +0 -85
  96. package/docs/guides-interactive-chat.zh-TW.md +0 -85
  97. package/docs/guides-interactive-chat.zh.md +0 -85
  98. package/docs/guides-managing-history.ja.md +0 -48
  99. package/docs/guides-managing-history.md +0 -48
  100. package/docs/guides-managing-history.zh-TW.md +0 -48
  101. package/docs/guides-managing-history.zh.md +0 -48
  102. package/docs/guides-publishing-your-docs.ja.md +0 -78
  103. package/docs/guides-publishing-your-docs.md +0 -78
  104. package/docs/guides-publishing-your-docs.zh-TW.md +0 -78
  105. package/docs/guides-publishing-your-docs.zh.md +0 -78
  106. package/docs/guides-translating-documentation.ja.md +0 -95
  107. package/docs/guides-translating-documentation.md +0 -95
  108. package/docs/guides-translating-documentation.zh-TW.md +0 -95
  109. package/docs/guides-translating-documentation.zh.md +0 -95
  110. package/docs/guides-updating-documentation.ja.md +0 -77
  111. package/docs/guides-updating-documentation.md +0 -77
  112. package/docs/guides-updating-documentation.zh-TW.md +0 -77
  113. package/docs/guides-updating-documentation.zh.md +0 -77
  114. package/docs/guides.ja.md +0 -32
  115. package/docs/guides.md +0 -32
  116. package/docs/guides.zh-TW.md +0 -32
  117. package/docs/guides.zh.md +0 -32
  118. package/docs/overview.ja.md +0 -61
  119. package/docs/overview.md +0 -61
  120. package/docs/overview.zh-TW.md +0 -61
  121. package/docs/overview.zh.md +0 -61
  122. package/docs/release-notes.ja.md +0 -255
  123. package/docs/release-notes.md +0 -255
  124. package/docs/release-notes.zh-TW.md +0 -255
  125. package/docs/release-notes.zh.md +0 -255
  126. package/media.md +0 -19
  127. package/prompts/common/afs/afs-tools-usage.md +0 -5
  128. package/prompts/common/afs/use-afs-instruction.md +0 -1
  129. package/release-please-config.json +0 -14
  130. package/tests/agents/chat/chat.test.mjs +0 -46
  131. package/tests/agents/clear/choose-contents.test.mjs +0 -284
  132. package/tests/agents/clear/clear-auth-tokens.test.mjs +0 -268
  133. package/tests/agents/clear/clear-document-config.test.mjs +0 -167
  134. package/tests/agents/clear/clear-document-structure.test.mjs +0 -380
  135. package/tests/agents/clear/clear-generated-docs.test.mjs +0 -222
  136. package/tests/agents/evaluate/code-snippet.test.mjs +0 -163
  137. package/tests/agents/evaluate/fixtures/api-services.md +0 -87
  138. package/tests/agents/evaluate/fixtures/js-sdk.md +0 -94
  139. package/tests/agents/evaluate/generate-report.test.mjs +0 -312
  140. package/tests/agents/generate/check-document-structure.test.mjs +0 -45
  141. package/tests/agents/generate/check-need-generate-structure.test.mjs +0 -279
  142. package/tests/agents/generate/document-structure-tools/add-document.test.mjs +0 -449
  143. package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +0 -410
  144. package/tests/agents/generate/document-structure-tools/generate-sub-structure.test.mjs +0 -277
  145. package/tests/agents/generate/document-structure-tools/move-document.test.mjs +0 -476
  146. package/tests/agents/generate/document-structure-tools/update-document.test.mjs +0 -548
  147. package/tests/agents/generate/generate-structure.test.mjs +0 -45
  148. package/tests/agents/generate/user-review-document-structure.test.mjs +0 -319
  149. package/tests/agents/history/view.test.mjs +0 -97
  150. package/tests/agents/init/init.test.mjs +0 -1657
  151. package/tests/agents/prefs/prefs.test.mjs +0 -431
  152. package/tests/agents/publish/publish-docs.test.mjs +0 -787
  153. package/tests/agents/translate/choose-language.test.mjs +0 -311
  154. package/tests/agents/translate/translate-document.test.mjs +0 -51
  155. package/tests/agents/update/check-document.test.mjs +0 -463
  156. package/tests/agents/update/check-update-is-single.test.mjs +0 -300
  157. package/tests/agents/update/document-tools/update-document-content.test.mjs +0 -329
  158. package/tests/agents/update/generate-document.test.mjs +0 -51
  159. package/tests/agents/update/save-and-translate-document.test.mjs +0 -369
  160. package/tests/agents/update/user-review-document.test.mjs +0 -582
  161. package/tests/agents/utils/action-success.test.mjs +0 -54
  162. package/tests/agents/utils/check-detail-result.test.mjs +0 -743
  163. package/tests/agents/utils/check-feedback-refiner.test.mjs +0 -478
  164. package/tests/agents/utils/choose-docs.test.mjs +0 -406
  165. package/tests/agents/utils/exit.test.mjs +0 -70
  166. package/tests/agents/utils/feedback-refiner.test.mjs +0 -51
  167. package/tests/agents/utils/find-item-by-path.test.mjs +0 -517
  168. package/tests/agents/utils/find-user-preferences-by-path.test.mjs +0 -382
  169. package/tests/agents/utils/format-document-structure.test.mjs +0 -364
  170. package/tests/agents/utils/fs.test.mjs +0 -267
  171. package/tests/agents/utils/load-sources.test.mjs +0 -1470
  172. package/tests/agents/utils/save-docs.test.mjs +0 -109
  173. package/tests/agents/utils/save-output.test.mjs +0 -315
  174. package/tests/agents/utils/save-single-doc.test.mjs +0 -364
  175. package/tests/agents/utils/transform-detail-datasources.test.mjs +0 -320
  176. package/tests/utils/auth-utils.test.mjs +0 -596
  177. package/tests/utils/blocklet.test.mjs +0 -336
  178. package/tests/utils/conflict-detector.test.mjs +0 -355
  179. package/tests/utils/constants.test.mjs +0 -295
  180. package/tests/utils/d2-utils.test.mjs +0 -437
  181. package/tests/utils/deploy.test.mjs +0 -399
  182. package/tests/utils/docs-finder-utils.test.mjs +0 -650
  183. package/tests/utils/file-utils.test.mjs +0 -521
  184. package/tests/utils/history-utils.test.mjs +0 -206
  185. package/tests/utils/kroki-utils.test.mjs +0 -646
  186. package/tests/utils/linter/fixtures/css/keyword-error.css +0 -1
  187. package/tests/utils/linter/fixtures/css/missing-semicolon.css +0 -1
  188. package/tests/utils/linter/fixtures/css/syntax-error.css +0 -1
  189. package/tests/utils/linter/fixtures/css/undeclare-variable.css +0 -1
  190. package/tests/utils/linter/fixtures/css/unused-variable.css +0 -2
  191. package/tests/utils/linter/fixtures/css/valid-code.css +0 -1
  192. package/tests/utils/linter/fixtures/dockerfile/keyword-error.dockerfile +0 -1
  193. package/tests/utils/linter/fixtures/dockerfile/missing-semicolon.dockerfile +0 -2
  194. package/tests/utils/linter/fixtures/dockerfile/syntax-error.dockerfile +0 -2
  195. package/tests/utils/linter/fixtures/dockerfile/undeclare-variable.dockerfile +0 -1
  196. package/tests/utils/linter/fixtures/dockerfile/unused-variable.dockerfile +0 -1
  197. package/tests/utils/linter/fixtures/dockerfile/valid-code.dockerfile +0 -2
  198. package/tests/utils/linter/fixtures/go/keyword-error.go +0 -5
  199. package/tests/utils/linter/fixtures/go/missing-semicolon.go +0 -5
  200. package/tests/utils/linter/fixtures/go/syntax-error.go +0 -6
  201. package/tests/utils/linter/fixtures/go/undeclare-variable.go +0 -5
  202. package/tests/utils/linter/fixtures/go/unused-variable.go +0 -5
  203. package/tests/utils/linter/fixtures/go/valid-code.go +0 -7
  204. package/tests/utils/linter/fixtures/js/keyword-error.js +0 -3
  205. package/tests/utils/linter/fixtures/js/missing-semicolon.js +0 -6
  206. package/tests/utils/linter/fixtures/js/syntax-error.js +0 -4
  207. package/tests/utils/linter/fixtures/js/undeclare-variable.js +0 -3
  208. package/tests/utils/linter/fixtures/js/unused-variable.js +0 -7
  209. package/tests/utils/linter/fixtures/js/valid-code.js +0 -15
  210. package/tests/utils/linter/fixtures/json/keyword-error.json +0 -1
  211. package/tests/utils/linter/fixtures/json/missing-semicolon.json +0 -1
  212. package/tests/utils/linter/fixtures/json/syntax-error.json +0 -1
  213. package/tests/utils/linter/fixtures/json/undeclare-variable.json +0 -1
  214. package/tests/utils/linter/fixtures/json/unused-variable.json +0 -1
  215. package/tests/utils/linter/fixtures/json/valid-code.json +0 -1
  216. package/tests/utils/linter/fixtures/jsx/keyword-error.jsx +0 -5
  217. package/tests/utils/linter/fixtures/jsx/missing-semicolon.jsx +0 -5
  218. package/tests/utils/linter/fixtures/jsx/syntax-error.jsx +0 -5
  219. package/tests/utils/linter/fixtures/jsx/undeclare-variable.jsx +0 -5
  220. package/tests/utils/linter/fixtures/jsx/unused-variable.jsx +0 -4
  221. package/tests/utils/linter/fixtures/jsx/valid-code.jsx +0 -5
  222. package/tests/utils/linter/fixtures/python/keyword-error.py +0 -3
  223. package/tests/utils/linter/fixtures/python/missing-semicolon.py +0 -2
  224. package/tests/utils/linter/fixtures/python/syntax-error.py +0 -3
  225. package/tests/utils/linter/fixtures/python/undeclare-variable.py +0 -3
  226. package/tests/utils/linter/fixtures/python/unused-variable.py +0 -6
  227. package/tests/utils/linter/fixtures/python/valid-code.py +0 -12
  228. package/tests/utils/linter/fixtures/ruby/keyword-error.rb +0 -2
  229. package/tests/utils/linter/fixtures/ruby/missing-semicolon.rb +0 -1
  230. package/tests/utils/linter/fixtures/ruby/syntax-error.rb +0 -2
  231. package/tests/utils/linter/fixtures/ruby/undeclare-variable.rb +0 -1
  232. package/tests/utils/linter/fixtures/ruby/unused-variable.rb +0 -2
  233. package/tests/utils/linter/fixtures/ruby/valid-code.rb +0 -1
  234. package/tests/utils/linter/fixtures/sass/keyword-error.sass +0 -2
  235. package/tests/utils/linter/fixtures/sass/missing-semicolon.sass +0 -3
  236. package/tests/utils/linter/fixtures/sass/syntax-error.sass +0 -3
  237. package/tests/utils/linter/fixtures/sass/undeclare-variable.sass +0 -2
  238. package/tests/utils/linter/fixtures/sass/unused-variable.sass +0 -4
  239. package/tests/utils/linter/fixtures/sass/valid-code.sass +0 -2
  240. package/tests/utils/linter/fixtures/scss/keyword-error.scss +0 -1
  241. package/tests/utils/linter/fixtures/scss/missing-semicolon.scss +0 -1
  242. package/tests/utils/linter/fixtures/scss/syntax-error.scss +0 -1
  243. package/tests/utils/linter/fixtures/scss/undeclare-variable.scss +0 -1
  244. package/tests/utils/linter/fixtures/scss/unused-variable.scss +0 -2
  245. package/tests/utils/linter/fixtures/scss/valid-code.scss +0 -1
  246. package/tests/utils/linter/fixtures/shell/keyword-error.sh +0 -5
  247. package/tests/utils/linter/fixtures/shell/missing-semicolon.sh +0 -3
  248. package/tests/utils/linter/fixtures/shell/syntax-error.sh +0 -4
  249. package/tests/utils/linter/fixtures/shell/undeclare-variable.sh +0 -3
  250. package/tests/utils/linter/fixtures/shell/unused-variable.sh +0 -4
  251. package/tests/utils/linter/fixtures/shell/valid-code.sh +0 -3
  252. package/tests/utils/linter/fixtures/ts/keyword-error.ts +0 -1
  253. package/tests/utils/linter/fixtures/ts/missing-semicolon.ts +0 -1
  254. package/tests/utils/linter/fixtures/ts/syntax-error.ts +0 -1
  255. package/tests/utils/linter/fixtures/ts/undeclare-variable.ts +0 -1
  256. package/tests/utils/linter/fixtures/ts/unused-variable.ts +0 -3
  257. package/tests/utils/linter/fixtures/ts/valid-code.ts +0 -3
  258. package/tests/utils/linter/fixtures/tsx/keyword-error.tsx +0 -5
  259. package/tests/utils/linter/fixtures/tsx/missing-semicolon.tsx +0 -5
  260. package/tests/utils/linter/fixtures/tsx/syntax-error.tsx +0 -5
  261. package/tests/utils/linter/fixtures/tsx/undeclare-variable.tsx +0 -6
  262. package/tests/utils/linter/fixtures/tsx/unused-variable.tsx +0 -6
  263. package/tests/utils/linter/fixtures/tsx/valid-code.tsx +0 -5
  264. package/tests/utils/linter/fixtures/vue/keyword-error.vue +0 -6
  265. package/tests/utils/linter/fixtures/vue/missing-semicolon.vue +0 -6
  266. package/tests/utils/linter/fixtures/vue/syntax-error.vue +0 -6
  267. package/tests/utils/linter/fixtures/vue/undeclare-variable.vue +0 -6
  268. package/tests/utils/linter/fixtures/vue/unused-variable.vue +0 -7
  269. package/tests/utils/linter/fixtures/vue/valid-code.vue +0 -6
  270. package/tests/utils/linter/fixtures/yaml/keyword-error.yml +0 -1
  271. package/tests/utils/linter/fixtures/yaml/missing-semicolon.yml +0 -2
  272. package/tests/utils/linter/fixtures/yaml/syntax-error.yml +0 -1
  273. package/tests/utils/linter/fixtures/yaml/undeclare-variable.yml +0 -1
  274. package/tests/utils/linter/fixtures/yaml/unused-variable.yml +0 -2
  275. package/tests/utils/linter/fixtures/yaml/valid-code.yml +0 -3
  276. package/tests/utils/linter/index.test.mjs +0 -440
  277. package/tests/utils/linter/scan-results.mjs +0 -42
  278. package/tests/utils/load-config.test.mjs +0 -141
  279. package/tests/utils/markdown/index.test.mjs +0 -478
  280. package/tests/utils/mermaid-validator.test.mjs +0 -541
  281. package/tests/utils/mock-chat-model.mjs +0 -12
  282. package/tests/utils/preferences-utils.test.mjs +0 -465
  283. package/tests/utils/save-value-to-config.test.mjs +0 -483
  284. package/tests/utils/utils.test.mjs +0 -941
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.12-beta.9](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.12-beta.8...v0.8.12-beta.9) (2025-10-15)
4
+
5
+
6
+ ### Features
7
+
8
+ * **branding:** support updating branding information during publish doc ([#190](https://github.com/AIGNE-io/aigne-doc-smith/issues/190)) ([1918cae](https://github.com/AIGNE-io/aigne-doc-smith/commit/1918cae6ceefd24d76b6086730b6e0d038057cb6))
9
+ * support translate meta in publish ([#189](https://github.com/AIGNE-io/aigne-doc-smith/issues/189)) ([3a34e38](https://github.com/AIGNE-io/aigne-doc-smith/commit/3a34e38f4283d4b2a19a88e426a8b49f0dd52bb6))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * generate d2 diagram by tool use ([#184](https://github.com/AIGNE-io/aigne-doc-smith/issues/184)) ([0d04349](https://github.com/AIGNE-io/aigne-doc-smith/commit/0d04349d14cde62388467f755dedc10b74d14980))
15
+
16
+ ## [0.8.12-beta.8](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.12-beta.7...v0.8.12-beta.8) (2025-10-14)
17
+
18
+
19
+ ### Features
20
+
21
+ * **media:** support filter and describe and use media files with AI ([#185](https://github.com/AIGNE-io/aigne-doc-smith/issues/185)) ([230271d](https://github.com/AIGNE-io/aigne-doc-smith/commit/230271d70ce2e701be8d6c6e3bdc27f5fadc6cf7))
22
+
23
+
24
+ ### Bug Fixes
25
+
26
+ * update evaluate page template ([#182](https://github.com/AIGNE-io/aigne-doc-smith/issues/182)) ([aef2104](https://github.com/AIGNE-io/aigne-doc-smith/commit/aef21049ded2f1ddfe9309dac67d6db1a026d3f6))
27
+
3
28
  ## [0.8.12-beta.7](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.12-beta.6...v0.8.12-beta.7) (2025-10-12)
4
29
 
5
30
 
@@ -1,5 +1,10 @@
1
1
  import { getDocSmithEnvFilePath } from "../../utils/auth-utils.mjs";
2
- import { getConfigFilePath, getStructurePlanPath, toDisplayPath } from "../../utils/file-utils.mjs";
2
+ import {
3
+ getConfigFilePath,
4
+ getMediaDescriptionCachePath,
5
+ getStructurePlanPath,
6
+ toDisplayPath,
7
+ } from "../../utils/file-utils.mjs";
3
8
 
4
9
  const TARGET_METADATA = {
5
10
  generatedDocs: {
@@ -36,6 +41,14 @@ const TARGET_METADATA = {
36
41
  `Delete appUrl from './${toDisplayPath(getConfigFilePath(workDir))}'.`,
37
42
  agent: "clearDeploymentConfig",
38
43
  },
44
+ mediaDescription: {
45
+ label: "media file descriptions",
46
+ description: () =>
47
+ `Delete AI-generated descriptions in './${toDisplayPath(
48
+ getMediaDescriptionCachePath(),
49
+ )}' (will regenerate on next generation).`,
50
+ agent: "clearMediaDescription",
51
+ },
39
52
  };
40
53
 
41
54
  const TARGET_KEYS = Object.keys(TARGET_METADATA);
@@ -0,0 +1,129 @@
1
+ import { existsSync } from "node:fs";
2
+ import { readFile, writeFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import chalk from "chalk";
5
+ import { parse, stringify } from "yaml";
6
+ import { getMediaDescriptionCachePath } from "../../utils/file-utils.mjs";
7
+
8
+ export default async function clearMediaDescription(_input = {}, options = {}) {
9
+ const cacheFilePath = getMediaDescriptionCachePath();
10
+
11
+ // Check if the cache file exists
12
+ if (!existsSync(cacheFilePath)) {
13
+ return {
14
+ message: "No media descriptions found to clear",
15
+ };
16
+ }
17
+
18
+ try {
19
+ // Read existing cache
20
+ const cacheContent = await readFile(cacheFilePath, "utf8");
21
+ const parsedCache = parse(cacheContent);
22
+ const cache = parsedCache?.descriptions || {};
23
+
24
+ // Get all media files from cache
25
+ const mediaHashes = Object.keys(cache);
26
+
27
+ if (mediaHashes.length === 0) {
28
+ return {
29
+ message: "No media descriptions found to clear",
30
+ };
31
+ }
32
+
33
+ // Build choices from cache - extract filename from path
34
+ const choices = mediaHashes.map((hash) => {
35
+ const mediaPath = cache[hash]?.path || "unknown";
36
+ const filename = path.basename(mediaPath);
37
+ const description = cache[hash]?.description || "";
38
+ const truncatedDesc =
39
+ description.length > 80 ? `${description.slice(0, 80)}...` : description;
40
+
41
+ return {
42
+ name: filename,
43
+ description: truncatedDesc,
44
+ value: hash,
45
+ checked: false,
46
+ };
47
+ });
48
+
49
+ // Add an option to clear all media descriptions
50
+ choices.push({
51
+ name: chalk.red("🗑️ Clear ALL media descriptions"),
52
+ value: "__ALL__",
53
+ checked: false,
54
+ });
55
+
56
+ let selectedHashes = [];
57
+
58
+ if (options?.prompts?.checkbox) {
59
+ selectedHashes = await options.prompts.checkbox({
60
+ message: "Select media files to clear descriptions:",
61
+ choices,
62
+ validate: (answer) => (answer.length > 0 ? true : "Please select at least one item."),
63
+ });
64
+ } else {
65
+ // If no prompts available, clear all
66
+ selectedHashes = ["__ALL__"];
67
+ }
68
+
69
+ if (selectedHashes.length === 0) {
70
+ return {
71
+ message: "No media files selected for clearing descriptions",
72
+ };
73
+ }
74
+
75
+ const results = [];
76
+ let clearedCount = 0;
77
+
78
+ if (selectedHashes.includes("__ALL__")) {
79
+ // Clear all media descriptions
80
+ await writeFile(
81
+ cacheFilePath,
82
+ stringify({
83
+ descriptions: {},
84
+ lastUpdated: new Date().toISOString(),
85
+ }),
86
+ );
87
+ results.push(`Cleared descriptions for all media files (${mediaHashes.length} files)`);
88
+ clearedCount = mediaHashes.length;
89
+ } else {
90
+ // Clear descriptions for selected files
91
+ const updatedCache = { ...cache };
92
+
93
+ for (const hash of selectedHashes) {
94
+ if (updatedCache[hash]) {
95
+ const filename = path.basename(updatedCache[hash].path);
96
+ delete updatedCache[hash];
97
+ results.push(`Cleared description for ${chalk.cyan(filename)}`);
98
+ clearedCount++;
99
+ }
100
+ }
101
+
102
+ await writeFile(
103
+ cacheFilePath,
104
+ stringify({
105
+ descriptions: updatedCache,
106
+ lastUpdated: new Date().toISOString(),
107
+ }),
108
+ );
109
+ }
110
+
111
+ const header = `✨ Successfully cleared media descriptions`;
112
+ const detailLines = results.join("\n");
113
+
114
+ const message = [header, "", detailLines, ""].filter(Boolean).join("\n");
115
+
116
+ return {
117
+ message,
118
+ clearedCount,
119
+ };
120
+ } catch (error) {
121
+ return {
122
+ message: `Error clearing media descriptions: ${error.message}`,
123
+ error: true,
124
+ };
125
+ }
126
+ }
127
+
128
+ clearMediaDescription.taskTitle = "Clear media file descriptions";
129
+ clearMediaDescription.description = "Clear AI-generated descriptions for media files";
@@ -21,4 +21,6 @@ input_schema:
21
21
  - documentStructure
22
22
  - generatedDocs
23
23
  - documentConfig
24
- - authTokens
24
+ - authTokens
25
+ - deploymentConfig
26
+ - mediaDescription
@@ -38,32 +38,37 @@ export default async function evaluateDocumentCode({ content }) {
38
38
  const checkList = await pMap(
39
39
  checkPromiseList,
40
40
  async (item) => {
41
- const result = await pRetry(() => lintCode(item), {
42
- onFailedAttempt: ({ error, attemptNumber, retriesLeft }) => {
43
- debug(
44
- `Attempt ${attemptNumber} failed: ${error.message}. There are ${retriesLeft} retries left.`,
45
- );
46
- },
47
- retries: 3,
48
- });
49
- // lint occurs error, ignore
50
- if (!result.success) {
51
- debug("Lint failed", item, result);
52
- return [];
53
- }
41
+ try {
42
+ const result = await pRetry(() => lintCode(item), {
43
+ onFailedAttempt: ({ error, attemptNumber, retriesLeft }) => {
44
+ debug(
45
+ `Attempt ${attemptNumber} failed: ${error.message}. There are ${retriesLeft} retries left.`,
46
+ );
47
+ },
48
+ retries: 3,
49
+ });
50
+ // lint occurs error, ignore
51
+ if (!result.success) {
52
+ debug("Lint failed", item, result);
53
+ return [];
54
+ }
54
55
 
55
- if (!result.issues || result.issues.length === 0) {
56
- debug("Lint result empty issues", item, result);
56
+ if (!result.issues || result.issues.length === 0) {
57
+ debug("Lint result empty issues", item, result);
58
+ return [];
59
+ }
60
+
61
+ errorCount += 1;
62
+ return result.issues.map((x) => {
63
+ return {
64
+ ...x,
65
+ level: severityMapLevel[x.severity],
66
+ };
67
+ });
68
+ } catch (error) {
69
+ debug("Lint occurred error", error);
57
70
  return [];
58
71
  }
59
-
60
- errorCount += 1;
61
- return result.issues.map((x) => {
62
- return {
63
- ...x,
64
- level: severityMapLevel[x.severity],
65
- };
66
- });
67
72
  },
68
73
  { concurrency: 5 },
69
74
  );
@@ -71,7 +76,6 @@ export default async function evaluateDocumentCode({ content }) {
71
76
 
72
77
  return {
73
78
  codeEvaluation: {
74
- baseline: 100,
75
79
  details: checkListResult,
76
80
  totalCount,
77
81
  ignoreCount,
@@ -32,9 +32,6 @@ output_schema:
32
32
  structureEvaluation:
33
33
  type: object
34
34
  properties:
35
- baseline:
36
- type: integer
37
- description: Baseline score of selected purposes
38
35
  details:
39
36
  type: array
40
37
  items:
@@ -64,7 +61,6 @@ output_schema:
64
61
  - description
65
62
  description: List of detailed evaluations for each purpose dimension
66
63
  required:
67
- - baseline
68
64
  - details
69
65
  required:
70
66
  - structureEvaluation
@@ -39,9 +39,6 @@ output_schema:
39
39
  documentEvaluation:
40
40
  type: object
41
41
  properties:
42
- baseline:
43
- type: integer
44
- description: Fixed baseline score (80)
45
42
  details:
46
43
  type: array
47
44
  description: Detailed observations contributing to the final score
@@ -50,7 +47,7 @@ output_schema:
50
47
  properties:
51
48
  dimension:
52
49
  type: string
53
- enum: [readability, coherence, contentQuality, consistency, purposeAlignment, audienceAlignment, knowledgeLevelAlignment, navigability]
50
+ enum: [readability, coherence, contentQuality, consistency, purposeAlignment, audienceAlignment, knowledgeLevelAlignment]
54
51
  description: Dimension associated with this observation
55
52
  level:
56
53
  type: string
@@ -72,7 +69,6 @@ output_schema:
72
69
  - line
73
70
  - description
74
71
  required:
75
- - baseline
76
72
  - details
77
73
  required:
78
74
  - documentEvaluation
@@ -42,6 +42,7 @@ skills:
42
42
  }
43
43
  ])
44
44
  - ../utils/format-document-structure.mjs
45
+ - ../media/load-media-description.mjs
45
46
  - ../update/batch-generate-document.yaml
46
47
  - url: ../utils/check-feedback-refiner.mjs
47
48
  default_input:
@@ -418,6 +418,10 @@ export function generateYAML(input) {
418
418
  // Paths
419
419
  docsDir: input.docsDir || "./aigne/doc-smith/docs",
420
420
  sourcesPath: input.sourcesPath || [],
421
+ media: {
422
+ // Image filtering settings
423
+ minImageWidth: input.minImageWidth || 800,
424
+ },
421
425
  };
422
426
 
423
427
  // Generate comments and structure
@@ -530,6 +534,12 @@ export function generateYAML(input) {
530
534
  const sourcesPathSection = yamlStringify({ sourcesPath: config.sourcesPath }).trim();
531
535
  yaml += `${sourcesPathSection.replace(/^sourcesPath:/, "sourcesPath: # Source code paths to analyze")}\n`;
532
536
 
537
+ // Image filtering settings
538
+ const mediaInfoSection = yamlStringify({
539
+ media: config.media,
540
+ }).trim();
541
+ yaml += `# minImageWidth: Only images wider than this value (in pixels) will be used in page generation\n${mediaInfoSection}\n`;
542
+
533
543
  return yaml;
534
544
  }
535
545
 
@@ -0,0 +1,44 @@
1
+ type: team
2
+ name: batchGenerateMediaDescription
3
+ description: Batch generate media (image/video) descriptions with concurrency
4
+ skills:
5
+ - url: ./generate-media-description.yaml
6
+ task_render_mode: collapse
7
+ task_title: Generate Media Description
8
+ input_schema:
9
+ type: object
10
+ properties:
11
+ mediaToDescribe:
12
+ type: array
13
+ items:
14
+ type: object
15
+ properties:
16
+ name:
17
+ type: string
18
+ width:
19
+ type: number
20
+ height:
21
+ type: number
22
+ hash:
23
+ type: string
24
+ path:
25
+ type: string
26
+ type:
27
+ type: string
28
+ mediaFile:
29
+ type: array
30
+ items:
31
+ type: object
32
+ properties:
33
+ type:
34
+ type: string
35
+ path:
36
+ type: string
37
+ filename:
38
+ type: string
39
+ mimeType:
40
+ type: string
41
+ description: Array of media files (images/videos) that need descriptions
42
+ iterate_on: mediaToDescribe
43
+ concurrency: 5
44
+ mode: sequential
@@ -0,0 +1,47 @@
1
+ name: generateMediaDescription
2
+ description: Generate description for a single media file (image/video)
3
+ model: "google/gemini-2.5-flash"
4
+ modalities: ["text", "image"]
5
+ instructions:
6
+ - role: system
7
+ url: ../../prompts/media/media-description/system-prompt.md
8
+ - role: user
9
+ url: ../../prompts/media/media-description/user-prompt.md
10
+ input_file_key: mediaFile
11
+ include_input_in_output: true
12
+ input_schema:
13
+ type: object
14
+ properties:
15
+ name:
16
+ type: string
17
+ description: Media file name
18
+ width:
19
+ type: number
20
+ description: Media width in pixels
21
+ height:
22
+ type: number
23
+ description: Media height in pixels
24
+ hash:
25
+ type: string
26
+ path:
27
+ type: string
28
+ description: Media path
29
+ type:
30
+ type: string
31
+ description: Media type (image/video)
32
+ mediaFile:
33
+ type: array
34
+ items:
35
+ type: object
36
+ properties:
37
+ type:
38
+ type: string
39
+ path:
40
+ type: string
41
+ filename:
42
+ type: string
43
+ mimeType:
44
+ type: string
45
+ required:
46
+ - name
47
+ output_key: description
@@ -0,0 +1,238 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync } from "node:fs";
3
+ import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { parse, stringify } from "yaml";
6
+ import { getMediaDescriptionCachePath } from "../../utils/file-utils.mjs";
7
+
8
+ const SIZE_THRESHOLD = 10 * 1024 * 1024; // 10MB
9
+
10
+ // Supported MIME types for Gemini AI
11
+ const SUPPORTED_IMAGE_TYPES = new Set([
12
+ "image/png",
13
+ "image/jpeg",
14
+ "image/webp",
15
+ "image/heic",
16
+ "image/heif",
17
+ ]);
18
+
19
+ const SUPPORTED_VIDEO_TYPES = new Set([
20
+ "video/mp4",
21
+ "video/mpeg",
22
+ "video/mov",
23
+ "video/avi",
24
+ "video/x-flv",
25
+ "video/mpg",
26
+ "video/webm",
27
+ "video/wmv",
28
+ "video/3gpp",
29
+ ]);
30
+
31
+ /**
32
+ * Calculate hash for a media file
33
+ * For files < 10MB: use file content
34
+ * For files >= 10MB: use path + size + mtime to avoid memory issues
35
+ * @param {string} absolutePath - The absolute path to the media file
36
+ * @returns {Promise<string>} - The hash of the file
37
+ */
38
+ async function calculateMediaHash(absolutePath) {
39
+ const stats = await stat(absolutePath);
40
+
41
+ if (stats.size < SIZE_THRESHOLD) {
42
+ // Small file: use full content
43
+ const content = await readFile(absolutePath);
44
+ return createHash("sha256").update(content).digest("hex");
45
+ }
46
+
47
+ // Large file: use path + size + mtime
48
+ const hashInput = `${absolutePath}:${stats.size}:${stats.mtimeMs}`;
49
+ return createHash("sha256").update(hashInput).digest("hex");
50
+ }
51
+
52
+ /**
53
+ * Load media descriptions from cache and generate new ones if needed
54
+ * @param {Object} input - Input parameters
55
+ * @param {Array} input.mediaFiles - Array of media file objects from load-sources
56
+ * @param {string} input.docsDir - Base directory for documentation
57
+ * @param {Object} options - Agent options
58
+ * @returns {Promise<Object>} - Updated assetsContent with media descriptions
59
+ */
60
+ export default async function loadMediaDescription(input, options) {
61
+ const { mediaFiles = [], docsDir } = input;
62
+
63
+ // Filter to get image and video files with supported MIME types
64
+ const mediaFilesToProcess = mediaFiles.filter((file) => {
65
+ if (file.type === "image") {
66
+ return SUPPORTED_IMAGE_TYPES.has(file.mimeType);
67
+ }
68
+ if (file.type === "video") {
69
+ return SUPPORTED_VIDEO_TYPES.has(file.mimeType);
70
+ }
71
+ return false;
72
+ });
73
+
74
+ // Path to media description cache file
75
+ const cacheFilePath = getMediaDescriptionCachePath();
76
+
77
+ // Load existing cache
78
+ let cache = {};
79
+ if (existsSync(cacheFilePath)) {
80
+ try {
81
+ const cacheContent = await readFile(cacheFilePath, "utf8");
82
+ const parsedCache = parse(cacheContent);
83
+ cache = parsedCache?.descriptions || {};
84
+ } catch (error) {
85
+ console.warn("Failed to read media description cache:", error.message);
86
+ }
87
+ }
88
+
89
+ // Find media files without descriptions
90
+ const mediaToDescribe = [];
91
+ const mediaHashMap = new Map();
92
+
93
+ const absoluteDocsDir = path.resolve(process.cwd(), docsDir);
94
+
95
+ // Only process media files that need AI description
96
+ for (const mediaFile of mediaFilesToProcess) {
97
+ // Convert relative path to absolute path for consistent hashing
98
+ // mediaFiles.path is relative to docsDir
99
+ const absolutePath = path.join(absoluteDocsDir, mediaFile.path);
100
+ const mediaHash = await calculateMediaHash(absolutePath);
101
+ mediaHashMap.set(mediaFile.path, mediaHash);
102
+
103
+ if (!cache[mediaHash]) {
104
+ mediaToDescribe.push({
105
+ ...mediaFile,
106
+ hash: mediaHash,
107
+ path: mediaFile.path,
108
+ mediaFile: [
109
+ {
110
+ type: "local",
111
+ path: absolutePath,
112
+ filename: mediaFile.name,
113
+ mimeType: mediaFile.mimeType,
114
+ },
115
+ ],
116
+ });
117
+ }
118
+ }
119
+
120
+ // Generate descriptions for media files without cache - use team agent for concurrent processing
121
+ const newDescriptions = {};
122
+ if (mediaToDescribe.length > 0) {
123
+ try {
124
+ // Use batch team agent for concurrent processing
125
+ const results = await options.context.invoke(
126
+ options.context.agents["batchGenerateMediaDescription"],
127
+ {
128
+ mediaToDescribe,
129
+ },
130
+ );
131
+
132
+ // Process results - results is an array of individual results
133
+ if (Array.isArray(results?.mediaToDescribe)) {
134
+ for (const result of results.mediaToDescribe) {
135
+ if (result?.hash && result?.description) {
136
+ newDescriptions[result.hash] = {
137
+ path: result.path,
138
+ description: result.description,
139
+ generatedAt: new Date().toISOString(),
140
+ };
141
+ }
142
+ }
143
+ }
144
+
145
+ // Merge new descriptions into cache
146
+ Object.assign(cache, newDescriptions);
147
+
148
+ // Save updated cache
149
+ await mkdir(path.dirname(cacheFilePath), { recursive: true });
150
+ const cacheYaml = stringify({
151
+ descriptions: cache,
152
+ lastUpdated: new Date().toISOString(),
153
+ });
154
+ await writeFile(cacheFilePath, cacheYaml, "utf8");
155
+
156
+ console.log(`Generated descriptions for ${Object.keys(newDescriptions).length} media files`);
157
+ } catch (error) {
158
+ console.error("Failed to generate media descriptions:", error.message);
159
+ }
160
+ }
161
+
162
+ // Build enhanced assetsContent with descriptions
163
+ let enhancedAssetsContent = "# Available Media Assets for Documentation\n\n";
164
+
165
+ if (mediaFiles.length > 0) {
166
+ enhancedAssetsContent += "```yaml\n";
167
+ enhancedAssetsContent += "assets:\n";
168
+
169
+ for (const asset of mediaFiles) {
170
+ enhancedAssetsContent += ` - name: "${asset.name}"\n`;
171
+ enhancedAssetsContent += ` path: "${asset.path}"\n`;
172
+ enhancedAssetsContent += ` type: "${asset.type}"\n`;
173
+
174
+ // Add description for images and videos
175
+ if (asset.type === "image" || asset.type === "video") {
176
+ const mediaHash = mediaHashMap.get(asset.path);
177
+ const cachedDesc = cache[mediaHash];
178
+ if (cachedDesc?.description) {
179
+ enhancedAssetsContent += ` description: "${cachedDesc.description}"\n`;
180
+ }
181
+ }
182
+
183
+ // Add dimensions for images and videos
184
+ if (asset.width && asset.height) {
185
+ enhancedAssetsContent += ` width: ${asset.width}\n`;
186
+ enhancedAssetsContent += ` height: ${asset.height}\n`;
187
+ }
188
+ }
189
+
190
+ enhancedAssetsContent += "```\n";
191
+ }
192
+
193
+ return {
194
+ ...input,
195
+ assetsContent: enhancedAssetsContent,
196
+ mediaFiles,
197
+ };
198
+ }
199
+
200
+ loadMediaDescription.input_schema = {
201
+ type: "object",
202
+ properties: {
203
+ mediaFiles: {
204
+ type: "array",
205
+ items: {
206
+ type: "object",
207
+ properties: {
208
+ name: { type: "string" },
209
+ path: { type: "string" },
210
+ type: { type: "string" },
211
+ width: { type: "number" },
212
+ height: { type: "number" },
213
+ mimeType: { type: "string" },
214
+ },
215
+ },
216
+ description: "Array of media file objects (images/videos)",
217
+ },
218
+ docsDir: {
219
+ type: "string",
220
+ description: "Base directory for documentation",
221
+ },
222
+ },
223
+ required: ["mediaFiles", "docsDir"],
224
+ };
225
+
226
+ loadMediaDescription.output_schema = {
227
+ type: "object",
228
+ properties: {
229
+ assetsContent: {
230
+ type: "string",
231
+ description: "Enhanced assets content with media descriptions",
232
+ },
233
+ mediaFiles: {
234
+ type: "array",
235
+ description: "Array of media file objects",
236
+ },
237
+ },
238
+ };
@@ -9,6 +9,7 @@ skills:
9
9
  default_input:
10
10
  skipIfExists: true
11
11
  checkOnly: true
12
+ - translate-meta.mjs
12
13
  - publish-docs.mjs
13
14
  input_schema:
14
15
  type: object
@@ -16,3 +17,6 @@ input_schema:
16
17
  appUrl:
17
18
  type: string
18
19
  description: Website URL where docs will be published (optional - leave empty for interactive setup)
20
+ with-branding:
21
+ type: boolean
22
+ description: Update your website branding (title, description, logo)