@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,548 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
2
- import updateDocument from "../../../../agents/generate/document-structure-tools/update-document.mjs";
3
-
4
- describe("update-document", () => {
5
- let consoleSpy;
6
- let baseDocumentStructure;
7
-
8
- beforeEach(() => {
9
- consoleSpy = spyOn(console, "log").mockImplementation(() => {});
10
- baseDocumentStructure = [
11
- {
12
- title: "Getting Started",
13
- description: "Introduction to the project",
14
- path: "/getting-started",
15
- parentId: null,
16
- sourceIds: ["intro.md"],
17
- },
18
- {
19
- title: "API Reference",
20
- description: "Complete API documentation",
21
- path: "/api",
22
- parentId: null,
23
- sourceIds: ["api.js"],
24
- },
25
- {
26
- title: "Authentication",
27
- description: "How to authenticate with the API",
28
- path: "/api/auth",
29
- parentId: "/api",
30
- sourceIds: ["auth.js", "security.md"],
31
- },
32
- {
33
- title: "Rate Limiting",
34
- description: "API rate limiting documentation",
35
- path: "/api/rate-limiting",
36
- parentId: "/api",
37
- sourceIds: ["rate-limit.js"],
38
- },
39
- ];
40
- });
41
-
42
- afterEach(() => {
43
- consoleSpy?.mockRestore();
44
- });
45
-
46
- // SUCCESSFUL UPDATE TESTS - TITLE
47
- test("should update document title successfully", async () => {
48
- const result = await updateDocument({
49
- documentStructure: baseDocumentStructure,
50
- path: "/getting-started",
51
- title: "Quick Start Guide",
52
- });
53
-
54
- expect(result.documentStructure).toHaveLength(4);
55
- expect(result.updatedDocument).toEqual({
56
- title: "Quick Start Guide",
57
- description: "Introduction to the project",
58
- path: "/getting-started",
59
- parentId: null,
60
- sourceIds: ["intro.md"],
61
- });
62
-
63
- expect(result.originalDocument).toEqual({
64
- title: "Getting Started",
65
- description: "Introduction to the project",
66
- path: "/getting-started",
67
- parentId: null,
68
- sourceIds: ["intro.md"],
69
- });
70
-
71
- // Verify the document was actually updated in the structure
72
- const updatedDoc = result.documentStructure.find((doc) => doc.path === "/getting-started");
73
- expect(updatedDoc.title).toBe("Quick Start Guide");
74
- expect(consoleSpy).not.toHaveBeenCalled();
75
- });
76
-
77
- // SUCCESSFUL UPDATE TESTS - DESCRIPTION
78
- test("should update document description successfully", async () => {
79
- const result = await updateDocument({
80
- documentStructure: baseDocumentStructure,
81
- path: "/api",
82
- description: "Comprehensive API documentation with examples",
83
- });
84
-
85
- expect(result.updatedDocument.description).toBe(
86
- "Comprehensive API documentation with examples",
87
- );
88
- expect(result.originalDocument.description).toBe("Complete API documentation");
89
-
90
- const updatedDoc = result.documentStructure.find((doc) => doc.path === "/api");
91
- expect(updatedDoc.description).toBe("Comprehensive API documentation with examples");
92
- expect(consoleSpy).not.toHaveBeenCalled();
93
- });
94
-
95
- // SUCCESSFUL UPDATE TESTS - SOURCE IDS
96
- test("should update document sourceIds successfully", async () => {
97
- const newSourceIds = ["new-auth.js", "updated-security.md", "examples.js"];
98
- const result = await updateDocument({
99
- documentStructure: baseDocumentStructure,
100
- path: "/api/auth",
101
- sourceIds: newSourceIds,
102
- });
103
-
104
- expect(result.updatedDocument.sourceIds).toEqual(newSourceIds);
105
- expect(result.originalDocument.sourceIds).toEqual(["auth.js", "security.md"]);
106
-
107
- const updatedDoc = result.documentStructure.find((doc) => doc.path === "/api/auth");
108
- expect(updatedDoc.sourceIds).toEqual(newSourceIds);
109
- expect(consoleSpy).not.toHaveBeenCalled();
110
- });
111
-
112
- test("should create a copy of sourceIds array", async () => {
113
- const originalSourceIds = ["source1.js", "source2.md"];
114
- const result = await updateDocument({
115
- documentStructure: baseDocumentStructure,
116
- path: "/getting-started",
117
- sourceIds: originalSourceIds,
118
- });
119
-
120
- // Verify it's a copy, not a reference
121
- expect(result.updatedDocument.sourceIds).toEqual(originalSourceIds);
122
- expect(result.updatedDocument.sourceIds).not.toBe(originalSourceIds);
123
-
124
- // Modifying original should not affect the updated document
125
- originalSourceIds.push("source3.js");
126
- expect(result.updatedDocument.sourceIds).not.toContain("source3.js");
127
- });
128
-
129
- // SUCCESSFUL UPDATE TESTS - MULTIPLE FIELDS
130
- test("should update multiple fields simultaneously", async () => {
131
- const result = await updateDocument({
132
- documentStructure: baseDocumentStructure,
133
- path: "/api/rate-limiting",
134
- title: "Advanced Rate Limiting",
135
- description: "Comprehensive guide to API rate limiting with examples",
136
- sourceIds: ["rate-limit-v2.js", "examples.md", "best-practices.md"],
137
- });
138
-
139
- expect(result.updatedDocument).toEqual({
140
- title: "Advanced Rate Limiting",
141
- description: "Comprehensive guide to API rate limiting with examples",
142
- path: "/api/rate-limiting",
143
- parentId: "/api",
144
- sourceIds: ["rate-limit-v2.js", "examples.md", "best-practices.md"],
145
- });
146
-
147
- expect(result.originalDocument).toEqual({
148
- title: "Rate Limiting",
149
- description: "API rate limiting documentation",
150
- path: "/api/rate-limiting",
151
- parentId: "/api",
152
- sourceIds: ["rate-limit.js"],
153
- });
154
-
155
- expect(consoleSpy).not.toHaveBeenCalled();
156
- });
157
-
158
- test("should update only specified fields, leaving others unchanged", async () => {
159
- const result = await updateDocument({
160
- documentStructure: baseDocumentStructure,
161
- path: "/api/auth",
162
- title: "Advanced Authentication",
163
- });
164
-
165
- expect(result.updatedDocument).toEqual({
166
- title: "Advanced Authentication",
167
- description: "How to authenticate with the API", // Unchanged
168
- path: "/api/auth", // Unchanged
169
- parentId: "/api", // Unchanged
170
- sourceIds: ["auth.js", "security.md"], // Unchanged
171
- });
172
- });
173
-
174
- // VALIDATION ERROR TESTS
175
- test("should return error when path is missing", async () => {
176
- const result = await updateDocument({
177
- documentStructure: baseDocumentStructure,
178
- title: "New Title",
179
- });
180
-
181
- expect(result.documentStructure).toEqual(baseDocumentStructure);
182
- expect(result.originalDocument).toBeUndefined();
183
- expect(result.updatedDocument).toBeUndefined();
184
- expect(consoleSpy).toHaveBeenCalledWith("⚠️ Cannot update document: path: Required");
185
- });
186
-
187
- test("should return error when path is empty string", async () => {
188
- const result = await updateDocument({
189
- documentStructure: baseDocumentStructure,
190
- path: "",
191
- title: "New Title",
192
- });
193
-
194
- expect(result.documentStructure).toEqual(baseDocumentStructure);
195
- expect(consoleSpy).toHaveBeenCalledWith("⚠️ Cannot update document: path: Path is required");
196
- });
197
-
198
- test("should return error when no update fields are provided", async () => {
199
- const result = await updateDocument({
200
- documentStructure: baseDocumentStructure,
201
- path: "/getting-started",
202
- });
203
-
204
- expect(result.documentStructure).toEqual(baseDocumentStructure);
205
- expect(consoleSpy).toHaveBeenCalledWith(
206
- "⚠️ Cannot update document: : At least one field (title, description, or sourceIds) must be provided for update",
207
- );
208
- });
209
-
210
- test("should return error when all update fields are undefined", async () => {
211
- const result = await updateDocument({
212
- documentStructure: baseDocumentStructure,
213
- path: "/getting-started",
214
- title: undefined,
215
- description: undefined,
216
- sourceIds: undefined,
217
- });
218
-
219
- expect(result.documentStructure).toEqual(baseDocumentStructure);
220
- expect(consoleSpy).toHaveBeenCalledWith(
221
- "⚠️ Cannot update document: : At least one field (title, description, or sourceIds) must be provided for update",
222
- );
223
- });
224
-
225
- test("should return error when document does not exist", async () => {
226
- const result = await updateDocument({
227
- documentStructure: baseDocumentStructure,
228
- path: "/nonexistent-document",
229
- title: "New Title",
230
- });
231
-
232
- expect(result.documentStructure).toEqual(baseDocumentStructure);
233
- expect(consoleSpy).toHaveBeenCalledWith(
234
- "⚠️ Cannot update document: Document '/nonexistent-document' does not exist. Choose an existing document to update.",
235
- );
236
- });
237
-
238
- // SOURCE IDS VALIDATION TESTS
239
- test("should return error when sourceIds is not an array", async () => {
240
- const result = await updateDocument({
241
- documentStructure: baseDocumentStructure,
242
- path: "/getting-started",
243
- sourceIds: "not-an-array",
244
- });
245
-
246
- expect(result.documentStructure).toEqual(baseDocumentStructure);
247
- expect(consoleSpy).toHaveBeenCalledWith(
248
- "⚠️ Cannot update document: sourceIds: Expected array, received string",
249
- );
250
- });
251
-
252
- test("should return error when sourceIds is empty array", async () => {
253
- const result = await updateDocument({
254
- documentStructure: baseDocumentStructure,
255
- path: "/getting-started",
256
- sourceIds: [],
257
- });
258
-
259
- expect(result.documentStructure).toEqual(baseDocumentStructure);
260
- expect(consoleSpy).toHaveBeenCalledWith(
261
- "⚠️ Cannot update document: sourceIds: Array must contain at least 1 element(s)",
262
- );
263
- });
264
-
265
- test("should return error when sourceIds is null", async () => {
266
- const result = await updateDocument({
267
- documentStructure: baseDocumentStructure,
268
- path: "/getting-started",
269
- sourceIds: null,
270
- });
271
-
272
- expect(result.documentStructure).toEqual(baseDocumentStructure);
273
- expect(result.originalDocument).toBeUndefined();
274
- expect(result.updatedDocument).toBeUndefined();
275
- // null is not an array, so it triggers sourceIds validation error
276
- expect(consoleSpy).toHaveBeenCalledWith(
277
- "⚠️ Cannot update document: sourceIds: Expected array, received null",
278
- );
279
- });
280
-
281
- // EDGE CASES
282
- test("should return error when updating with empty strings (falsy values)", async () => {
283
- const result = await updateDocument({
284
- documentStructure: baseDocumentStructure,
285
- path: "/getting-started",
286
- title: "",
287
- description: "",
288
- });
289
-
290
- // Empty strings trigger specific field validation errors
291
- expect(result.documentStructure).toEqual(baseDocumentStructure);
292
- expect(result.originalDocument).toBeUndefined();
293
- expect(result.updatedDocument).toBeUndefined();
294
- expect(consoleSpy).toHaveBeenCalledWith(
295
- "⚠️ Cannot update document: title: String must contain at least 1 character(s), description: String must contain at least 1 character(s)",
296
- );
297
- });
298
-
299
- test("should handle updating deeply nested document", async () => {
300
- const nestedStructure = [
301
- ...baseDocumentStructure,
302
- {
303
- title: "OAuth",
304
- description: "OAuth authentication flow",
305
- path: "/api/auth/oauth",
306
- parentId: "/api/auth",
307
- sourceIds: ["oauth.js"],
308
- },
309
- ];
310
-
311
- const result = await updateDocument({
312
- documentStructure: nestedStructure,
313
- path: "/api/auth/oauth",
314
- title: "OAuth 2.0 Implementation",
315
- });
316
-
317
- expect(result.updatedDocument.title).toBe("OAuth 2.0 Implementation");
318
- expect(result.updatedDocument.path).toBe("/api/auth/oauth");
319
- expect(consoleSpy).not.toHaveBeenCalled();
320
- });
321
-
322
- test("should handle empty documentation structure", async () => {
323
- const result = await updateDocument({
324
- documentStructure: [],
325
- path: "/any-path",
326
- title: "New Title",
327
- });
328
-
329
- expect(result.documentStructure).toEqual([]);
330
- expect(consoleSpy).toHaveBeenCalledWith(
331
- "⚠️ Cannot update document: Document '/any-path' does not exist. Choose an existing document to update.",
332
- );
333
- });
334
-
335
- test("should handle single documentation structure", async () => {
336
- const singleDocStructure = [
337
- {
338
- title: "Only Document",
339
- description: "The only document",
340
- path: "/only",
341
- parentId: null,
342
- sourceIds: ["only.md"],
343
- },
344
- ];
345
-
346
- const result = await updateDocument({
347
- documentStructure: singleDocStructure,
348
- path: "/only",
349
- title: "Updated Only Document",
350
- });
351
-
352
- expect(result.documentStructure).toHaveLength(1);
353
- expect(result.updatedDocument.title).toBe("Updated Only Document");
354
- expect(consoleSpy).not.toHaveBeenCalled();
355
- });
356
-
357
- test("should handle special characters in paths", async () => {
358
- const specialStructure = [
359
- ...baseDocumentStructure,
360
- {
361
- title: "Special Document",
362
- description: "Document with special characters",
363
- path: "/api/special-chars_and.numbers123",
364
- parentId: "/api",
365
- sourceIds: ["special.md"],
366
- },
367
- ];
368
-
369
- const result = await updateDocument({
370
- documentStructure: specialStructure,
371
- path: "/api/special-chars_and.numbers123",
372
- title: "Updated Special Document",
373
- });
374
-
375
- expect(result.updatedDocument.title).toBe("Updated Special Document");
376
- expect(consoleSpy).not.toHaveBeenCalled();
377
- });
378
-
379
- // DATA INTEGRITY TESTS
380
- test("should not modify original documentation structure", async () => {
381
- const originalStructure = [...baseDocumentStructure];
382
-
383
- await updateDocument({
384
- documentStructure: baseDocumentStructure,
385
- path: "/getting-started",
386
- title: "Updated Title",
387
- });
388
-
389
- expect(baseDocumentStructure).toEqual(originalStructure);
390
- });
391
-
392
- test("should update only the specified document", async () => {
393
- const result = await updateDocument({
394
- documentStructure: baseDocumentStructure,
395
- path: "/api/auth",
396
- title: "Updated Authentication",
397
- });
398
-
399
- // Count how many documents have changed
400
- let changedCount = 0;
401
- for (let i = 0; i < baseDocumentStructure.length; i++) {
402
- if (
403
- JSON.stringify(baseDocumentStructure[i]) !== JSON.stringify(result.documentStructure[i])
404
- ) {
405
- changedCount++;
406
- }
407
- }
408
-
409
- expect(changedCount).toBe(1);
410
- });
411
-
412
- test("should preserve document order in array", async () => {
413
- const result = await updateDocument({
414
- documentStructure: baseDocumentStructure,
415
- path: "/api",
416
- description: "Updated API documentation",
417
- });
418
-
419
- // Verify all documents are in the same positions
420
- for (let i = 0; i < baseDocumentStructure.length; i++) {
421
- expect(result.documentStructure[i].path).toBe(baseDocumentStructure[i].path);
422
- if (baseDocumentStructure[i].path === "/api") {
423
- // This is the updated document
424
- expect(result.documentStructure[i].description).toBe("Updated API documentation");
425
- } else {
426
- // Other documents should be unchanged
427
- expect(result.documentStructure[i]).toEqual(baseDocumentStructure[i]);
428
- }
429
- }
430
- });
431
-
432
- test("should preserve parentId and path when updating other fields", async () => {
433
- const result = await updateDocument({
434
- documentStructure: baseDocumentStructure,
435
- path: "/api/auth",
436
- title: "New Authentication Title",
437
- description: "New authentication description",
438
- sourceIds: ["new-auth.js"],
439
- });
440
-
441
- expect(result.updatedDocument.path).toBe("/api/auth");
442
- expect(result.updatedDocument.parentId).toBe("/api");
443
- expect(result.originalDocument.path).toBe("/api/auth");
444
- expect(result.originalDocument.parentId).toBe("/api");
445
- });
446
-
447
- // RETURN VALUE TESTS
448
- test("should return complete original and updated document information", async () => {
449
- const result = await updateDocument({
450
- documentStructure: baseDocumentStructure,
451
- path: "/api/rate-limiting",
452
- title: "Enhanced Rate Limiting",
453
- description: "Advanced rate limiting techniques",
454
- });
455
-
456
- expect(result.originalDocument).toEqual({
457
- title: "Rate Limiting",
458
- description: "API rate limiting documentation",
459
- path: "/api/rate-limiting",
460
- parentId: "/api",
461
- sourceIds: ["rate-limit.js"],
462
- });
463
-
464
- expect(result.updatedDocument).toEqual({
465
- title: "Enhanced Rate Limiting",
466
- description: "Advanced rate limiting techniques",
467
- path: "/api/rate-limiting",
468
- parentId: "/api",
469
- sourceIds: ["rate-limit.js"],
470
- });
471
-
472
- // Verify both have all required properties
473
- ["title", "description", "path", "parentId", "sourceIds"].forEach((prop) => {
474
- expect(result.originalDocument).toHaveProperty(prop);
475
- expect(result.updatedDocument).toHaveProperty(prop);
476
- });
477
- });
478
-
479
- test("should handle updating with multiple source IDs", async () => {
480
- const multipleSourceIds = [
481
- "main.js",
482
- "helper.js",
483
- "documentation.md",
484
- "examples/example1.js",
485
- "examples/example2.js",
486
- ];
487
-
488
- const result = await updateDocument({
489
- documentStructure: baseDocumentStructure,
490
- path: "/getting-started",
491
- sourceIds: multipleSourceIds,
492
- });
493
-
494
- expect(result.updatedDocument.sourceIds).toEqual(multipleSourceIds);
495
- expect(result.updatedDocument.sourceIds).toHaveLength(5);
496
- expect(consoleSpy).not.toHaveBeenCalled();
497
- });
498
-
499
- // PARTIAL UPDATE TESTS
500
- test("should handle partial updates with mixed defined/undefined values", async () => {
501
- const result = await updateDocument({
502
- documentStructure: baseDocumentStructure,
503
- path: "/getting-started",
504
- title: "New Title",
505
- description: undefined, // Should not be updated
506
- sourceIds: ["new-source.md"], // Should be updated
507
- });
508
-
509
- expect(result.updatedDocument).toEqual({
510
- title: "New Title", // Updated
511
- description: "Introduction to the project", // Unchanged
512
- path: "/getting-started",
513
- parentId: null,
514
- sourceIds: ["new-source.md"], // Updated
515
- });
516
- });
517
-
518
- test("should correctly identify when any update field is provided", async () => {
519
- // Test with only title
520
- let result = await updateDocument({
521
- documentStructure: baseDocumentStructure,
522
- path: "/getting-started",
523
- title: "Only Title Updated",
524
- });
525
- expect(result.updatedDocument.title).toBe("Only Title Updated");
526
- expect(consoleSpy).not.toHaveBeenCalled();
527
-
528
- // Test with only description
529
- consoleSpy.mockClear();
530
- result = await updateDocument({
531
- documentStructure: baseDocumentStructure,
532
- path: "/api",
533
- description: "Only Description Updated",
534
- });
535
- expect(result.updatedDocument.description).toBe("Only Description Updated");
536
- expect(consoleSpy).not.toHaveBeenCalled();
537
-
538
- // Test with only sourceIds
539
- consoleSpy.mockClear();
540
- result = await updateDocument({
541
- documentStructure: baseDocumentStructure,
542
- path: "/api/auth",
543
- sourceIds: ["only-sources-updated.js"],
544
- });
545
- expect(result.updatedDocument.sourceIds).toEqual(["only-sources-updated.js"]);
546
- expect(consoleSpy).not.toHaveBeenCalled();
547
- });
548
- });
@@ -1,45 +0,0 @@
1
- import { afterAll, beforeAll, describe, expect, test } from "bun:test";
2
- import { join } from "node:path";
3
- import { AIAgent } from "@aigne/core";
4
- import { loadAgent } from "@aigne/core/loader/index.js";
5
- import { loadModel } from "../../utils/mock-chat-model.mjs";
6
-
7
- describe("generateStructure Agent", () => {
8
- beforeAll(() => {
9
- process.env.AIGNE_OBSERVABILITY_DISABLED = "true";
10
- });
11
-
12
- afterAll(() => {
13
- delete process.env.AIGNE_OBSERVABILITY_DISABLED;
14
- });
15
- test("should load agent correctly with proper configuration", async () => {
16
- const agent = await loadAgent(
17
- join(import.meta.dirname, "../../../agents/generate/generate-structure.yaml"),
18
- {
19
- model: loadModel,
20
- },
21
- );
22
-
23
- expect(agent).toBeDefined();
24
-
25
- // Verify agent exists and is correct type
26
- expect(agent).toBeDefined();
27
- expect(agent).toBeInstanceOf(AIAgent);
28
- });
29
-
30
- test("should have instructions loaded from file", async () => {
31
- const agent = await loadAgent(
32
- join(import.meta.dirname, "../../../agents/generate/generate-structure.yaml"),
33
- {
34
- model: loadModel,
35
- },
36
- );
37
-
38
- expect(agent).toBeDefined();
39
-
40
- // Verify instructions are loaded
41
- expect(agent.instructions).toBeDefined();
42
- const instructions = await agent.instructions.build({});
43
- expect(instructions.messages).toBeDefined();
44
- });
45
- });