@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
@@ -1,364 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
- import { stringify } from "yaml";
3
- import formatDocumentStructure from "../../../agents/utils/format-document-structure.mjs";
4
-
5
- describe("format-document-structure", () => {
6
- // EDGE CASE TESTS
7
- test("should handle when both documentStructure and originalDocumentStructure are null", async () => {
8
- const result = await formatDocumentStructure({
9
- documentStructure: null,
10
- originalDocumentStructure: null,
11
- });
12
-
13
- expect(result).toEqual({
14
- documentStructureYaml: "",
15
- documentStructure: [],
16
- });
17
- });
18
-
19
- test("should handle when both documentStructure and originalDocumentStructure are undefined", async () => {
20
- const result = await formatDocumentStructure({
21
- documentStructure: undefined,
22
- originalDocumentStructure: undefined,
23
- });
24
-
25
- expect(result).toEqual({
26
- documentStructureYaml: "",
27
- documentStructure: [],
28
- });
29
- });
30
-
31
- test("should handle when both parameters are missing", async () => {
32
- const result = await formatDocumentStructure({});
33
-
34
- expect(result).toEqual({
35
- documentStructureYaml: "",
36
- documentStructure: [],
37
- });
38
- });
39
-
40
- test("should use originalDocumentStructure when documentStructure is null", async () => {
41
- const originalDocumentStructure = [
42
- {
43
- title: "Original Document",
44
- path: "/original",
45
- parentId: null,
46
- description: "From original structure",
47
- extraField: "should be filtered out",
48
- },
49
- ];
50
-
51
- const result = await formatDocumentStructure({
52
- documentStructure: null,
53
- originalDocumentStructure,
54
- });
55
-
56
- const expectedData = [
57
- {
58
- title: "Original Document",
59
- path: "/original",
60
- parentId: null,
61
- description: "From original structure",
62
- },
63
- ];
64
- const expectedYaml = stringify(expectedData, {
65
- indent: 2,
66
- lineWidth: 120,
67
- minContentWidth: 20,
68
- });
69
-
70
- expect(result.documentStructureYaml).toBe(expectedYaml);
71
- expect(result.documentStructure).toBe(null);
72
- });
73
-
74
- test("should use originalDocumentStructure when documentStructure is undefined", async () => {
75
- const originalDocumentStructure = [
76
- {
77
- title: "Fallback Document",
78
- path: "/fallback",
79
- parentId: "parent-id",
80
- description: "Fallback to original",
81
- },
82
- ];
83
-
84
- const result = await formatDocumentStructure({
85
- originalDocumentStructure,
86
- });
87
-
88
- const expectedData = [
89
- {
90
- title: "Fallback Document",
91
- path: "/fallback",
92
- parentId: "parent-id",
93
- description: "Fallback to original",
94
- },
95
- ];
96
- const expectedYaml = stringify(expectedData, {
97
- indent: 2,
98
- lineWidth: 120,
99
- minContentWidth: 20,
100
- });
101
-
102
- expect(result.documentStructureYaml).toBe(expectedYaml);
103
- expect(result.documentStructure).toBe(undefined);
104
- });
105
-
106
- // BASIC FUNCTIONALITY TESTS
107
- test("should format empty documentation structure", async () => {
108
- const result = await formatDocumentStructure({
109
- documentStructure: [],
110
- });
111
-
112
- const expectedYaml = stringify([], {
113
- indent: 2,
114
- lineWidth: 120,
115
- minContentWidth: 20,
116
- });
117
-
118
- expect(result).toEqual({
119
- documentStructureYaml: expectedYaml,
120
- documentStructure: [],
121
- });
122
- });
123
-
124
- test("should format single item documentation structure", async () => {
125
- const documentStructure = [
126
- {
127
- title: "Getting Started",
128
- path: "/getting-started",
129
- parentId: null,
130
- description: "Introduction to the platform",
131
- extraField: "should be ignored",
132
- },
133
- ];
134
-
135
- const result = await formatDocumentStructure({ documentStructure });
136
-
137
- const expectedData = [
138
- {
139
- title: "Getting Started",
140
- path: "/getting-started",
141
- parentId: null,
142
- description: "Introduction to the platform",
143
- },
144
- ];
145
- const expectedYaml = stringify(expectedData, {
146
- indent: 2,
147
- lineWidth: 120,
148
- minContentWidth: 20,
149
- });
150
-
151
- expect(result.documentStructure).toEqual(documentStructure);
152
- expect(result.documentStructureYaml).toBe(expectedYaml);
153
- });
154
-
155
- test("should format multiple items documentation structure", async () => {
156
- const documentStructure = [
157
- {
158
- title: "API Reference",
159
- path: "/api",
160
- parentId: null,
161
- description: "Complete API documentation",
162
- },
163
- {
164
- title: "Authentication",
165
- path: "/api/auth",
166
- parentId: "/api",
167
- description: "Authentication endpoints",
168
- },
169
- {
170
- title: "Users",
171
- path: "/api/users",
172
- parentId: "/api",
173
- description: "User management endpoints",
174
- },
175
- ];
176
-
177
- const result = await formatDocumentStructure({ documentStructure });
178
-
179
- const expectedData = [
180
- {
181
- title: "API Reference",
182
- path: "/api",
183
- parentId: null,
184
- description: "Complete API documentation",
185
- },
186
- {
187
- title: "Authentication",
188
- path: "/api/auth",
189
- parentId: "/api",
190
- description: "Authentication endpoints",
191
- },
192
- {
193
- title: "Users",
194
- path: "/api/users",
195
- parentId: "/api",
196
- description: "User management endpoints",
197
- },
198
- ];
199
- const expectedYaml = stringify(expectedData, {
200
- indent: 2,
201
- lineWidth: 120,
202
- minContentWidth: 20,
203
- });
204
-
205
- expect(result.documentStructure).toEqual(documentStructure);
206
- expect(result.documentStructureYaml).toBe(expectedYaml);
207
- });
208
-
209
- // FIELD EXTRACTION TESTS
210
- test("should extract only required fields", async () => {
211
- const documentStructure = [
212
- {
213
- title: "Test Document",
214
- path: "/test",
215
- parentId: "parent-123",
216
- description: "Test description",
217
- // Extra fields that should be filtered out
218
- id: "doc-123",
219
- content: "Document content",
220
- metadata: { tags: ["test"] },
221
- lastModified: "2024-01-01",
222
- author: "John Doe",
223
- },
224
- ];
225
-
226
- const result = await formatDocumentStructure({ documentStructure });
227
-
228
- const expectedData = [
229
- {
230
- title: "Test Document",
231
- path: "/test",
232
- parentId: "parent-123",
233
- description: "Test description",
234
- },
235
- ];
236
- const expectedYaml = stringify(expectedData, {
237
- indent: 2,
238
- lineWidth: 120,
239
- minContentWidth: 20,
240
- });
241
-
242
- expect(result.documentStructureYaml).toBe(expectedYaml);
243
- // Verify extra fields are not in the YAML output
244
- expect(result.documentStructureYaml).not.toContain("doc-123");
245
- expect(result.documentStructureYaml).not.toContain("Document content");
246
- expect(result.documentStructureYaml).not.toContain("John Doe");
247
- });
248
-
249
- test("should handle items with missing optional fields", async () => {
250
- const documentStructure = [
251
- {
252
- title: "Required Title",
253
- path: "/required-path",
254
- // parentId and description are missing
255
- },
256
- ];
257
-
258
- const result = await formatDocumentStructure({ documentStructure });
259
-
260
- const expectedData = [
261
- {
262
- title: "Required Title",
263
- path: "/required-path",
264
- parentId: undefined,
265
- description: undefined,
266
- },
267
- ];
268
- const expectedYaml = stringify(expectedData, {
269
- indent: 2,
270
- lineWidth: 120,
271
- minContentWidth: 20,
272
- });
273
-
274
- expect(result.documentStructureYaml).toBe(expectedYaml);
275
- });
276
-
277
- test("should preserve null and undefined values", async () => {
278
- const documentStructure = [
279
- {
280
- title: "Test Item",
281
- path: "/test",
282
- parentId: null,
283
- description: undefined,
284
- },
285
- ];
286
-
287
- const result = await formatDocumentStructure({ documentStructure });
288
-
289
- const expectedData = [
290
- {
291
- title: "Test Item",
292
- path: "/test",
293
- parentId: null,
294
- description: undefined,
295
- },
296
- ];
297
- const expectedYaml = stringify(expectedData, {
298
- indent: 2,
299
- lineWidth: 120,
300
- minContentWidth: 20,
301
- });
302
-
303
- expect(result.documentStructureYaml).toBe(expectedYaml);
304
- });
305
-
306
- test("should handle items with special characters", async () => {
307
- const documentStructure = [
308
- {
309
- title: "Special Characters: @#$%^&*()",
310
- path: "/special-chars-test",
311
- parentId: null,
312
- description: 'Testing with 中文, émojis 🚀, and "quotes"',
313
- },
314
- ];
315
-
316
- const result = await formatDocumentStructure({ documentStructure });
317
-
318
- // Since YAML is mocked, just verify the function runs without error
319
- // and returns a structure with the expected properties
320
- expect(result.documentStructureYaml).toBeDefined();
321
- expect(result.documentStructure).toEqual(documentStructure);
322
- });
323
-
324
- test("should return both yaml string and original documentation structure", async () => {
325
- const documentStructure = [
326
- {
327
- title: "Return Test",
328
- path: "/return-test",
329
- parentId: null,
330
- description: "Testing return values",
331
- },
332
- ];
333
-
334
- const result = await formatDocumentStructure({ documentStructure });
335
-
336
- expect(result).toHaveProperty("documentStructureYaml");
337
- expect(result).toHaveProperty("documentStructure");
338
- expect(typeof result.documentStructureYaml).toBe("string");
339
- expect(result.documentStructure).toBe(documentStructure); // Should be the same reference
340
- });
341
-
342
- test("should preserve original documentation structure unchanged", async () => {
343
- const originalDocumentStructure = [
344
- {
345
- title: "Original",
346
- path: "/original",
347
- parentId: null,
348
- description: "Original description",
349
- extraField: "should remain",
350
- },
351
- ];
352
-
353
- const result = await formatDocumentStructure({
354
- documentStructure: originalDocumentStructure,
355
- });
356
-
357
- // Original should be unchanged
358
- expect(originalDocumentStructure[0]).toHaveProperty("extraField");
359
- expect(originalDocumentStructure[0].extraField).toBe("should remain");
360
-
361
- // Return value should reference the same object
362
- expect(result.documentStructure).toBe(originalDocumentStructure);
363
- });
364
- });
@@ -1,267 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
2
- import * as fsPromises from "node:fs/promises";
3
- import * as path from "node:path";
4
- import fs from "../../../agents/utils/fs.mjs";
5
-
6
- describe("fs utility", () => {
7
- let readFileSpy;
8
- let writeFileSpy;
9
- let mkdirSpy;
10
- let rmSpy;
11
- let readdirSpy;
12
- let joinSpy;
13
- let dirnameSpy;
14
-
15
- beforeEach(() => {
16
- // Spy on fs/promises methods
17
- readFileSpy = spyOn(fsPromises, "readFile").mockResolvedValue("mocked file content");
18
- writeFileSpy = spyOn(fsPromises, "writeFile").mockResolvedValue();
19
- mkdirSpy = spyOn(fsPromises, "mkdir").mockResolvedValue();
20
- rmSpy = spyOn(fsPromises, "rm").mockResolvedValue();
21
- readdirSpy = spyOn(fsPromises, "readdir").mockResolvedValue([
22
- { name: "file1.txt", parentPath: "/test/root", isDirectory: () => false },
23
- { name: "subdir", parentPath: "/test/root", isDirectory: () => true },
24
- ]);
25
-
26
- // Spy on path methods
27
- joinSpy = spyOn(path, "join").mockImplementation((...paths) => paths.join("/"));
28
- dirnameSpy = spyOn(path, "dirname").mockImplementation(
29
- (path) => path.split("/").slice(0, -1).join("/") || "/",
30
- );
31
- });
32
-
33
- afterEach(() => {
34
- // Restore all spies
35
- readFileSpy?.mockRestore();
36
- writeFileSpy?.mockRestore();
37
- mkdirSpy?.mockRestore();
38
- rmSpy?.mockRestore();
39
- readdirSpy?.mockRestore();
40
- joinSpy?.mockRestore();
41
- dirnameSpy?.mockRestore();
42
- });
43
-
44
- // ERROR HANDLING TESTS
45
- test("should throw error when rootDir is not specified", async () => {
46
- await expect(
47
- fs({
48
- action: "read_file",
49
- path: "test.txt",
50
- }),
51
- ).rejects.toThrow("Root directory is not specified");
52
- });
53
-
54
- test("should throw error when rootDir is empty string", async () => {
55
- await expect(
56
- fs({
57
- rootDir: "",
58
- action: "read_file",
59
- path: "test.txt",
60
- }),
61
- ).rejects.toThrow("Root directory is not specified");
62
- });
63
-
64
- // READ_FILE ACTION TESTS
65
- test("should read file successfully", async () => {
66
- readFileSpy.mockResolvedValue("test file content");
67
-
68
- const result = await fs({
69
- rootDir: "/test/root",
70
- action: "read_file",
71
- path: "test.txt",
72
- });
73
-
74
- expect(joinSpy).toHaveBeenCalledWith("/test/root", "test.txt");
75
- expect(readFileSpy).toHaveBeenCalledWith("/test/root/test.txt", "utf-8");
76
- expect(result).toEqual({
77
- status: "ok",
78
- path: "/test/root/test.txt",
79
- content: "test file content",
80
- });
81
- });
82
-
83
- test("should handle read file with nested path", async () => {
84
- await fs({
85
- rootDir: "/project",
86
- action: "read_file",
87
- path: "src/components/Button.tsx",
88
- });
89
-
90
- expect(joinSpy).toHaveBeenCalledWith("/project", "src/components/Button.tsx");
91
- expect(readFileSpy).toHaveBeenCalledWith("/project/src/components/Button.tsx", "utf-8");
92
- });
93
-
94
- // WRITE_FILE ACTION TESTS
95
- test("should write file successfully", async () => {
96
- const result = await fs({
97
- rootDir: "/test/root",
98
- action: "write_file",
99
- path: "output.txt",
100
- content: "Hello, world!",
101
- });
102
-
103
- expect(dirnameSpy).toHaveBeenCalledWith("/test/root/output.txt");
104
- expect(mkdirSpy).toHaveBeenCalledWith("/test/root", { recursive: true });
105
- expect(writeFileSpy).toHaveBeenCalledWith("/test/root/output.txt", "Hello, world!");
106
- expect(result).toEqual({
107
- status: "ok",
108
- path: "/test/root/output.txt",
109
- content: "Hello, world!",
110
- });
111
- });
112
-
113
- test("should write file with empty content when content is not provided", async () => {
114
- const result = await fs({
115
- rootDir: "/test/root",
116
- action: "write_file",
117
- path: "empty.txt",
118
- });
119
-
120
- expect(writeFileSpy).toHaveBeenCalledWith("/test/root/empty.txt", "");
121
- expect(result.content).toBeUndefined(); // The function returns the original content parameter
122
- });
123
-
124
- test("should create directories recursively when writing file", async () => {
125
- dirnameSpy.mockReturnValue("/test/root/deep/nested");
126
-
127
- await fs({
128
- rootDir: "/test/root",
129
- action: "write_file",
130
- path: "deep/nested/file.txt",
131
- content: "nested content",
132
- });
133
-
134
- expect(mkdirSpy).toHaveBeenCalledWith("/test/root/deep/nested", {
135
- recursive: true,
136
- });
137
- });
138
-
139
- // DELETE_FILE ACTION TESTS
140
- test("should delete file successfully", async () => {
141
- const result = await fs({
142
- rootDir: "/test/root",
143
- action: "delete_file",
144
- path: "to-delete.txt",
145
- });
146
-
147
- expect(joinSpy).toHaveBeenCalledWith("/test/root", "to-delete.txt");
148
- expect(rmSpy).toHaveBeenCalledWith("/test/root/to-delete.txt", {
149
- recursive: true,
150
- force: true,
151
- });
152
- expect(result).toEqual({
153
- status: "ok",
154
- path: "/test/root/to-delete.txt",
155
- });
156
- });
157
-
158
- test("should delete directory recursively", async () => {
159
- await fs({
160
- rootDir: "/project",
161
- action: "delete_file",
162
- path: "build",
163
- });
164
-
165
- expect(rmSpy).toHaveBeenCalledWith("/project/build", {
166
- recursive: true,
167
- force: true,
168
- });
169
- });
170
-
171
- // LIST_DIRECTORY ACTION TESTS
172
- test("should list directory entries successfully", async () => {
173
- const result = await fs({
174
- rootDir: "/test/root",
175
- action: "list_directory",
176
- path: "src",
177
- });
178
-
179
- expect(joinSpy).toHaveBeenCalledWith("/test/root", "src");
180
- expect(readdirSpy).toHaveBeenCalledWith("/test/root/src", { withFileTypes: true });
181
- expect(result).toEqual({
182
- status: "ok",
183
- entries: [
184
- { path: "/test/root/file1.txt", isDirectory: false },
185
- { path: "/test/root/subdir", isDirectory: true },
186
- ],
187
- });
188
- });
189
-
190
- test("should handle empty directory listing", async () => {
191
- readdirSpy.mockResolvedValue([]);
192
-
193
- const result = await fs({
194
- rootDir: "/test/root",
195
- action: "list_directory",
196
- path: "empty-dir",
197
- });
198
-
199
- expect(result.entries).toEqual([]);
200
- });
201
-
202
- // PATH HANDLING TESTS
203
- test("should handle root directory with trailing slash", async () => {
204
- await fs({
205
- rootDir: "/test/root/",
206
- action: "read_file",
207
- path: "file.txt",
208
- });
209
-
210
- expect(joinSpy).toHaveBeenCalledWith("/test/root/", "file.txt");
211
- });
212
-
213
- test("should handle path with leading slash", async () => {
214
- await fs({
215
- rootDir: "/test/root",
216
- action: "read_file",
217
- path: "/absolute/path.txt",
218
- });
219
-
220
- expect(joinSpy).toHaveBeenCalledWith("/test/root", "/absolute/path.txt");
221
- });
222
-
223
- test("should handle complex nested paths", async () => {
224
- await fs({
225
- rootDir: "/project",
226
- action: "write_file",
227
- path: "src/components/ui/Button/index.tsx",
228
- content: "export default Button;",
229
- });
230
-
231
- expect(joinSpy).toHaveBeenCalledWith("/project", "src/components/ui/Button/index.tsx");
232
- });
233
-
234
- // UNDEFINED ACTION TEST
235
- test("should return undefined for unknown action", async () => {
236
- const result = await fs({
237
- rootDir: "/test/root",
238
- action: "unknown_action",
239
- path: "test.txt",
240
- });
241
-
242
- expect(result).toBeUndefined();
243
- });
244
-
245
- // EDGE CASES
246
- test("should handle special characters in paths", async () => {
247
- await fs({
248
- rootDir: "/test/root",
249
- action: "read_file",
250
- path: "文件名 with spaces & symbols!.txt",
251
- });
252
-
253
- expect(joinSpy).toHaveBeenCalledWith("/test/root", "文件名 with spaces & symbols!.txt");
254
- });
255
-
256
- test("should handle null content for write_file", async () => {
257
- const result = await fs({
258
- rootDir: "/test/root",
259
- action: "write_file",
260
- path: "null-content.txt",
261
- content: null,
262
- });
263
-
264
- expect(writeFileSpy).toHaveBeenCalledWith("/test/root/null-content.txt", "");
265
- expect(result.content).toBe(null);
266
- });
267
- });