@aigne/doc-smith 0.8.12-beta.8 → 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 (264) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/agents/publish/index.yaml +4 -0
  3. package/agents/publish/publish-docs.mjs +77 -5
  4. package/agents/publish/translate-meta.mjs +103 -0
  5. package/agents/update/generate-document.yaml +30 -28
  6. package/agents/update/update-document-detail.yaml +3 -1
  7. package/agents/utils/update-branding.mjs +69 -0
  8. package/package.json +16 -2
  9. package/prompts/common/document/role-and-personality.md +3 -1
  10. package/prompts/detail/d2-diagram/guide.md +7 -1
  11. package/prompts/detail/d2-diagram/user-prompt.md +3 -0
  12. package/prompts/detail/generate/system-prompt.md +6 -7
  13. package/prompts/detail/generate/user-prompt.md +12 -3
  14. package/prompts/detail/update/user-prompt.md +0 -2
  15. package/prompts/structure/update/user-prompt.md +0 -4
  16. package/utils/file-utils.mjs +69 -24
  17. package/utils/markdown-checker.mjs +0 -20
  18. package/utils/request.mjs +7 -0
  19. package/utils/upload-files.mjs +231 -0
  20. package/utils/utils.mjs +11 -1
  21. package/.aigne/doc-smith/config.yaml +0 -77
  22. package/.aigne/doc-smith/history.yaml +0 -37
  23. package/.aigne/doc-smith/media-description.yaml +0 -91
  24. package/.aigne/doc-smith/output/structure-plan.json +0 -162
  25. package/.aigne/doc-smith/preferences.yml +0 -97
  26. package/.aigne/doc-smith/upload-cache.yaml +0 -1830
  27. package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
  28. package/.github/workflows/ci.yml +0 -54
  29. package/.github/workflows/create-release-pr.yaml +0 -21
  30. package/.github/workflows/publish-docs.yml +0 -65
  31. package/.github/workflows/release.yml +0 -49
  32. package/.github/workflows/reviewer.yml +0 -54
  33. package/.release-please-manifest.json +0 -3
  34. package/RELEASE.md +0 -9
  35. package/assets/screenshots/doc-complete-setup.png +0 -0
  36. package/assets/screenshots/doc-generate-docs.png +0 -0
  37. package/assets/screenshots/doc-generate.png +0 -0
  38. package/assets/screenshots/doc-generated-successfully.png +0 -0
  39. package/assets/screenshots/doc-publish.png +0 -0
  40. package/assets/screenshots/doc-regenerate.png +0 -0
  41. package/assets/screenshots/doc-translate-langs.png +0 -0
  42. package/assets/screenshots/doc-translate.png +0 -0
  43. package/assets/screenshots/doc-update.png +0 -0
  44. package/biome.json +0 -73
  45. package/codecov.yml +0 -15
  46. package/docs/_sidebar.md +0 -15
  47. package/docs/configuration-initial-setup.ja.md +0 -179
  48. package/docs/configuration-initial-setup.md +0 -198
  49. package/docs/configuration-initial-setup.zh-TW.md +0 -179
  50. package/docs/configuration-initial-setup.zh.md +0 -179
  51. package/docs/configuration-managing-preferences.ja.md +0 -100
  52. package/docs/configuration-managing-preferences.md +0 -100
  53. package/docs/configuration-managing-preferences.zh-TW.md +0 -100
  54. package/docs/configuration-managing-preferences.zh.md +0 -100
  55. package/docs/configuration.ja.md +0 -69
  56. package/docs/configuration.md +0 -69
  57. package/docs/configuration.zh-TW.md +0 -69
  58. package/docs/configuration.zh.md +0 -69
  59. package/docs/getting-started.ja.md +0 -107
  60. package/docs/getting-started.md +0 -107
  61. package/docs/getting-started.zh-TW.md +0 -107
  62. package/docs/getting-started.zh.md +0 -107
  63. package/docs/guides-cleaning-up.ja.md +0 -51
  64. package/docs/guides-cleaning-up.md +0 -52
  65. package/docs/guides-cleaning-up.zh-TW.md +0 -51
  66. package/docs/guides-cleaning-up.zh.md +0 -51
  67. package/docs/guides-evaluating-documents.ja.md +0 -66
  68. package/docs/guides-evaluating-documents.md +0 -107
  69. package/docs/guides-evaluating-documents.zh-TW.md +0 -66
  70. package/docs/guides-evaluating-documents.zh.md +0 -66
  71. package/docs/guides-generating-documentation.ja.md +0 -151
  72. package/docs/guides-generating-documentation.md +0 -89
  73. package/docs/guides-generating-documentation.zh-TW.md +0 -151
  74. package/docs/guides-generating-documentation.zh.md +0 -151
  75. package/docs/guides-interactive-chat.ja.md +0 -85
  76. package/docs/guides-interactive-chat.md +0 -93
  77. package/docs/guides-interactive-chat.zh-TW.md +0 -85
  78. package/docs/guides-interactive-chat.zh.md +0 -85
  79. package/docs/guides-managing-history.ja.md +0 -48
  80. package/docs/guides-managing-history.md +0 -53
  81. package/docs/guides-managing-history.zh-TW.md +0 -48
  82. package/docs/guides-managing-history.zh.md +0 -48
  83. package/docs/guides-publishing-your-docs.ja.md +0 -78
  84. package/docs/guides-publishing-your-docs.md +0 -83
  85. package/docs/guides-publishing-your-docs.zh-TW.md +0 -78
  86. package/docs/guides-publishing-your-docs.zh.md +0 -78
  87. package/docs/guides-translating-documentation.ja.md +0 -95
  88. package/docs/guides-translating-documentation.md +0 -100
  89. package/docs/guides-translating-documentation.zh-TW.md +0 -95
  90. package/docs/guides-translating-documentation.zh.md +0 -95
  91. package/docs/guides-updating-documentation.ja.md +0 -77
  92. package/docs/guides-updating-documentation.md +0 -79
  93. package/docs/guides-updating-documentation.zh-TW.md +0 -77
  94. package/docs/guides-updating-documentation.zh.md +0 -77
  95. package/docs/guides.ja.md +0 -32
  96. package/docs/guides.md +0 -32
  97. package/docs/guides.zh-TW.md +0 -32
  98. package/docs/guides.zh.md +0 -32
  99. package/docs/overview.ja.md +0 -61
  100. package/docs/overview.md +0 -61
  101. package/docs/overview.zh-TW.md +0 -61
  102. package/docs/overview.zh.md +0 -61
  103. package/docs/release-notes.ja.md +0 -255
  104. package/docs/release-notes.md +0 -288
  105. package/docs/release-notes.zh-TW.md +0 -255
  106. package/docs/release-notes.zh.md +0 -255
  107. package/prompts/common/afs/afs-tools-usage.md +0 -5
  108. package/prompts/common/afs/use-afs-instruction.md +0 -1
  109. package/release-please-config.json +0 -14
  110. package/tests/agents/chat/chat.test.mjs +0 -46
  111. package/tests/agents/clear/choose-contents.test.mjs +0 -284
  112. package/tests/agents/clear/clear-auth-tokens.test.mjs +0 -268
  113. package/tests/agents/clear/clear-document-config.test.mjs +0 -167
  114. package/tests/agents/clear/clear-document-structure.test.mjs +0 -380
  115. package/tests/agents/clear/clear-generated-docs.test.mjs +0 -222
  116. package/tests/agents/evaluate/code-snippet.test.mjs +0 -163
  117. package/tests/agents/evaluate/fixtures/api-services.md +0 -87
  118. package/tests/agents/evaluate/fixtures/js-sdk.md +0 -94
  119. package/tests/agents/evaluate/generate-report.test.mjs +0 -312
  120. package/tests/agents/generate/check-document-structure.test.mjs +0 -45
  121. package/tests/agents/generate/check-need-generate-structure.test.mjs +0 -279
  122. package/tests/agents/generate/document-structure-tools/add-document.test.mjs +0 -449
  123. package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +0 -410
  124. package/tests/agents/generate/document-structure-tools/generate-sub-structure.test.mjs +0 -277
  125. package/tests/agents/generate/document-structure-tools/move-document.test.mjs +0 -476
  126. package/tests/agents/generate/document-structure-tools/update-document.test.mjs +0 -548
  127. package/tests/agents/generate/generate-structure.test.mjs +0 -45
  128. package/tests/agents/generate/user-review-document-structure.test.mjs +0 -319
  129. package/tests/agents/history/view.test.mjs +0 -97
  130. package/tests/agents/init/init.test.mjs +0 -1657
  131. package/tests/agents/prefs/prefs.test.mjs +0 -431
  132. package/tests/agents/publish/publish-docs.test.mjs +0 -787
  133. package/tests/agents/translate/choose-language.test.mjs +0 -311
  134. package/tests/agents/translate/translate-document.test.mjs +0 -51
  135. package/tests/agents/update/check-document.test.mjs +0 -463
  136. package/tests/agents/update/check-update-is-single.test.mjs +0 -300
  137. package/tests/agents/update/document-tools/update-document-content.test.mjs +0 -329
  138. package/tests/agents/update/generate-document.test.mjs +0 -51
  139. package/tests/agents/update/save-and-translate-document.test.mjs +0 -369
  140. package/tests/agents/update/user-review-document.test.mjs +0 -582
  141. package/tests/agents/utils/action-success.test.mjs +0 -54
  142. package/tests/agents/utils/check-detail-result.test.mjs +0 -743
  143. package/tests/agents/utils/check-feedback-refiner.test.mjs +0 -478
  144. package/tests/agents/utils/choose-docs.test.mjs +0 -406
  145. package/tests/agents/utils/exit.test.mjs +0 -70
  146. package/tests/agents/utils/feedback-refiner.test.mjs +0 -51
  147. package/tests/agents/utils/find-item-by-path.test.mjs +0 -517
  148. package/tests/agents/utils/find-user-preferences-by-path.test.mjs +0 -382
  149. package/tests/agents/utils/format-document-structure.test.mjs +0 -364
  150. package/tests/agents/utils/fs.test.mjs +0 -267
  151. package/tests/agents/utils/load-sources.test.mjs +0 -1470
  152. package/tests/agents/utils/save-docs.test.mjs +0 -109
  153. package/tests/agents/utils/save-output.test.mjs +0 -315
  154. package/tests/agents/utils/save-single-doc.test.mjs +0 -364
  155. package/tests/agents/utils/transform-detail-datasources.test.mjs +0 -320
  156. package/tests/utils/auth-utils.test.mjs +0 -596
  157. package/tests/utils/blocklet.test.mjs +0 -336
  158. package/tests/utils/conflict-detector.test.mjs +0 -355
  159. package/tests/utils/constants.test.mjs +0 -295
  160. package/tests/utils/d2-utils.test.mjs +0 -437
  161. package/tests/utils/deploy.test.mjs +0 -399
  162. package/tests/utils/docs-finder-utils.test.mjs +0 -650
  163. package/tests/utils/file-utils.test.mjs +0 -521
  164. package/tests/utils/history-utils.test.mjs +0 -206
  165. package/tests/utils/kroki-utils.test.mjs +0 -646
  166. package/tests/utils/linter/fixtures/css/keyword-error.css +0 -1
  167. package/tests/utils/linter/fixtures/css/missing-semicolon.css +0 -1
  168. package/tests/utils/linter/fixtures/css/syntax-error.css +0 -1
  169. package/tests/utils/linter/fixtures/css/undeclare-variable.css +0 -1
  170. package/tests/utils/linter/fixtures/css/unused-variable.css +0 -2
  171. package/tests/utils/linter/fixtures/css/valid-code.css +0 -1
  172. package/tests/utils/linter/fixtures/dockerfile/keyword-error.dockerfile +0 -1
  173. package/tests/utils/linter/fixtures/dockerfile/missing-semicolon.dockerfile +0 -2
  174. package/tests/utils/linter/fixtures/dockerfile/syntax-error.dockerfile +0 -2
  175. package/tests/utils/linter/fixtures/dockerfile/undeclare-variable.dockerfile +0 -1
  176. package/tests/utils/linter/fixtures/dockerfile/unused-variable.dockerfile +0 -1
  177. package/tests/utils/linter/fixtures/dockerfile/valid-code.dockerfile +0 -2
  178. package/tests/utils/linter/fixtures/go/keyword-error.go +0 -5
  179. package/tests/utils/linter/fixtures/go/missing-semicolon.go +0 -5
  180. package/tests/utils/linter/fixtures/go/syntax-error.go +0 -6
  181. package/tests/utils/linter/fixtures/go/undeclare-variable.go +0 -5
  182. package/tests/utils/linter/fixtures/go/unused-variable.go +0 -5
  183. package/tests/utils/linter/fixtures/go/valid-code.go +0 -7
  184. package/tests/utils/linter/fixtures/js/keyword-error.js +0 -3
  185. package/tests/utils/linter/fixtures/js/missing-semicolon.js +0 -6
  186. package/tests/utils/linter/fixtures/js/syntax-error.js +0 -4
  187. package/tests/utils/linter/fixtures/js/undeclare-variable.js +0 -3
  188. package/tests/utils/linter/fixtures/js/unused-variable.js +0 -7
  189. package/tests/utils/linter/fixtures/js/valid-code.js +0 -15
  190. package/tests/utils/linter/fixtures/json/keyword-error.json +0 -1
  191. package/tests/utils/linter/fixtures/json/missing-semicolon.json +0 -1
  192. package/tests/utils/linter/fixtures/json/syntax-error.json +0 -1
  193. package/tests/utils/linter/fixtures/json/undeclare-variable.json +0 -1
  194. package/tests/utils/linter/fixtures/json/unused-variable.json +0 -1
  195. package/tests/utils/linter/fixtures/json/valid-code.json +0 -1
  196. package/tests/utils/linter/fixtures/jsx/keyword-error.jsx +0 -5
  197. package/tests/utils/linter/fixtures/jsx/missing-semicolon.jsx +0 -5
  198. package/tests/utils/linter/fixtures/jsx/syntax-error.jsx +0 -5
  199. package/tests/utils/linter/fixtures/jsx/undeclare-variable.jsx +0 -5
  200. package/tests/utils/linter/fixtures/jsx/unused-variable.jsx +0 -4
  201. package/tests/utils/linter/fixtures/jsx/valid-code.jsx +0 -5
  202. package/tests/utils/linter/fixtures/python/keyword-error.py +0 -3
  203. package/tests/utils/linter/fixtures/python/missing-semicolon.py +0 -2
  204. package/tests/utils/linter/fixtures/python/syntax-error.py +0 -3
  205. package/tests/utils/linter/fixtures/python/undeclare-variable.py +0 -3
  206. package/tests/utils/linter/fixtures/python/unused-variable.py +0 -6
  207. package/tests/utils/linter/fixtures/python/valid-code.py +0 -12
  208. package/tests/utils/linter/fixtures/ruby/keyword-error.rb +0 -2
  209. package/tests/utils/linter/fixtures/ruby/missing-semicolon.rb +0 -1
  210. package/tests/utils/linter/fixtures/ruby/syntax-error.rb +0 -2
  211. package/tests/utils/linter/fixtures/ruby/undeclare-variable.rb +0 -1
  212. package/tests/utils/linter/fixtures/ruby/unused-variable.rb +0 -2
  213. package/tests/utils/linter/fixtures/ruby/valid-code.rb +0 -1
  214. package/tests/utils/linter/fixtures/sass/keyword-error.sass +0 -2
  215. package/tests/utils/linter/fixtures/sass/missing-semicolon.sass +0 -3
  216. package/tests/utils/linter/fixtures/sass/syntax-error.sass +0 -3
  217. package/tests/utils/linter/fixtures/sass/undeclare-variable.sass +0 -2
  218. package/tests/utils/linter/fixtures/sass/unused-variable.sass +0 -4
  219. package/tests/utils/linter/fixtures/sass/valid-code.sass +0 -2
  220. package/tests/utils/linter/fixtures/scss/keyword-error.scss +0 -1
  221. package/tests/utils/linter/fixtures/scss/missing-semicolon.scss +0 -1
  222. package/tests/utils/linter/fixtures/scss/syntax-error.scss +0 -1
  223. package/tests/utils/linter/fixtures/scss/undeclare-variable.scss +0 -1
  224. package/tests/utils/linter/fixtures/scss/unused-variable.scss +0 -2
  225. package/tests/utils/linter/fixtures/scss/valid-code.scss +0 -1
  226. package/tests/utils/linter/fixtures/shell/keyword-error.sh +0 -5
  227. package/tests/utils/linter/fixtures/shell/missing-semicolon.sh +0 -3
  228. package/tests/utils/linter/fixtures/shell/syntax-error.sh +0 -4
  229. package/tests/utils/linter/fixtures/shell/undeclare-variable.sh +0 -3
  230. package/tests/utils/linter/fixtures/shell/unused-variable.sh +0 -4
  231. package/tests/utils/linter/fixtures/shell/valid-code.sh +0 -3
  232. package/tests/utils/linter/fixtures/ts/keyword-error.ts +0 -1
  233. package/tests/utils/linter/fixtures/ts/missing-semicolon.ts +0 -1
  234. package/tests/utils/linter/fixtures/ts/syntax-error.ts +0 -1
  235. package/tests/utils/linter/fixtures/ts/undeclare-variable.ts +0 -1
  236. package/tests/utils/linter/fixtures/ts/unused-variable.ts +0 -3
  237. package/tests/utils/linter/fixtures/ts/valid-code.ts +0 -3
  238. package/tests/utils/linter/fixtures/tsx/keyword-error.tsx +0 -5
  239. package/tests/utils/linter/fixtures/tsx/missing-semicolon.tsx +0 -5
  240. package/tests/utils/linter/fixtures/tsx/syntax-error.tsx +0 -5
  241. package/tests/utils/linter/fixtures/tsx/undeclare-variable.tsx +0 -6
  242. package/tests/utils/linter/fixtures/tsx/unused-variable.tsx +0 -6
  243. package/tests/utils/linter/fixtures/tsx/valid-code.tsx +0 -5
  244. package/tests/utils/linter/fixtures/vue/keyword-error.vue +0 -6
  245. package/tests/utils/linter/fixtures/vue/missing-semicolon.vue +0 -6
  246. package/tests/utils/linter/fixtures/vue/syntax-error.vue +0 -6
  247. package/tests/utils/linter/fixtures/vue/undeclare-variable.vue +0 -6
  248. package/tests/utils/linter/fixtures/vue/unused-variable.vue +0 -7
  249. package/tests/utils/linter/fixtures/vue/valid-code.vue +0 -6
  250. package/tests/utils/linter/fixtures/yaml/keyword-error.yml +0 -1
  251. package/tests/utils/linter/fixtures/yaml/missing-semicolon.yml +0 -2
  252. package/tests/utils/linter/fixtures/yaml/syntax-error.yml +0 -1
  253. package/tests/utils/linter/fixtures/yaml/undeclare-variable.yml +0 -1
  254. package/tests/utils/linter/fixtures/yaml/unused-variable.yml +0 -2
  255. package/tests/utils/linter/fixtures/yaml/valid-code.yml +0 -3
  256. package/tests/utils/linter/index.test.mjs +0 -440
  257. package/tests/utils/linter/scan-results.mjs +0 -42
  258. package/tests/utils/load-config.test.mjs +0 -141
  259. package/tests/utils/markdown/index.test.mjs +0 -478
  260. package/tests/utils/mermaid-validator.test.mjs +0 -541
  261. package/tests/utils/mock-chat-model.mjs +0 -12
  262. package/tests/utils/preferences-utils.test.mjs +0 -465
  263. package/tests/utils/save-value-to-config.test.mjs +0 -483
  264. 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
- });