@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,300 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from "bun:test";
2
- import checkUpdateIsSingle from "../../../agents/update/check-update-is-single.mjs";
3
-
4
- describe("check-update-is-single", () => {
5
- let mockOptions;
6
- let consoleSpy;
7
-
8
- beforeEach(() => {
9
- mockOptions = {
10
- context: {
11
- agents: {
12
- updateSingleDocument: { mockSingleAgent: true },
13
- batchUpdateDocument: { mockBatchAgent: true },
14
- },
15
- invoke: mock(async () => ({ mockResult: true })),
16
- },
17
- };
18
-
19
- consoleSpy = spyOn(console, "error").mockImplementation(() => {});
20
-
21
- // Clear context mock call history
22
- mockOptions.context.invoke.mockClear();
23
- });
24
-
25
- afterEach(() => {
26
- consoleSpy?.mockRestore();
27
- });
28
-
29
- // INPUT VALIDATION TESTS
30
- test("should throw error when selectedDocs is not provided", async () => {
31
- await expect(checkUpdateIsSingle({}, mockOptions)).rejects.toThrow(
32
- "selectedDocs must be provided as an array",
33
- );
34
- });
35
-
36
- test("should throw error when selectedDocs is not an array", async () => {
37
- await expect(checkUpdateIsSingle({ selectedDocs: "not-array" }, mockOptions)).rejects.toThrow(
38
- "selectedDocs must be provided as an array",
39
- );
40
- });
41
-
42
- test("should throw error when selectedDocs is empty", async () => {
43
- await expect(checkUpdateIsSingle({ selectedDocs: [] }, mockOptions)).rejects.toThrow(
44
- "selectedDocs cannot be empty",
45
- );
46
- });
47
-
48
- test("should throw error when selectedDocs is null", async () => {
49
- await expect(checkUpdateIsSingle({ selectedDocs: null }, mockOptions)).rejects.toThrow(
50
- "selectedDocs must be provided as an array",
51
- );
52
- });
53
-
54
- test("should throw error when selectedDocs is undefined", async () => {
55
- await expect(checkUpdateIsSingle({ selectedDocs: undefined }, mockOptions)).rejects.toThrow(
56
- "selectedDocs must be provided as an array",
57
- );
58
- });
59
-
60
- // AGENT AVAILABILITY TESTS
61
- test("should throw error when updateSingleDocument agent is not available", async () => {
62
- const optionsWithoutSingleAgent = {
63
- context: {
64
- agents: {
65
- batchUpdateDocument: { mockBatchAgent: true },
66
- },
67
- invoke: mock(),
68
- },
69
- };
70
-
71
- await expect(
72
- checkUpdateIsSingle({ selectedDocs: ["doc1"] }, optionsWithoutSingleAgent),
73
- ).rejects.toThrow('Agent "updateSingleDocument" is not available');
74
- });
75
-
76
- test("should throw error when batchUpdateDocument agent is not available", async () => {
77
- const optionsWithoutBatchAgent = {
78
- context: {
79
- agents: {
80
- updateSingleDocument: { mockSingleAgent: true },
81
- },
82
- invoke: mock(),
83
- },
84
- };
85
-
86
- await expect(
87
- checkUpdateIsSingle({ selectedDocs: ["doc1", "doc2"] }, optionsWithoutBatchAgent),
88
- ).rejects.toThrow('Agent "batchUpdateDocument" is not available');
89
- });
90
-
91
- test("should throw error when no agents are available", async () => {
92
- const optionsWithoutAgents = {
93
- context: {
94
- agents: {},
95
- invoke: mock(),
96
- },
97
- };
98
-
99
- await expect(
100
- checkUpdateIsSingle({ selectedDocs: ["doc1"] }, optionsWithoutAgents),
101
- ).rejects.toThrow('Agent "updateSingleDocument" is not available');
102
- });
103
-
104
- // SINGLE DOCUMENT ROUTING TESTS
105
- test("should route to updateSingleDocument when selectedDocs has one item", async () => {
106
- const result = await checkUpdateIsSingle(
107
- {
108
- selectedDocs: ["doc1"],
109
- customParam: "test",
110
- },
111
- mockOptions,
112
- );
113
-
114
- expect(mockOptions.context.invoke).toHaveBeenCalledWith(
115
- { mockSingleAgent: true },
116
- {
117
- selectedDocs: ["doc1"],
118
- customParam: "test",
119
- },
120
- );
121
- expect(result).toEqual({ mockResult: true });
122
- });
123
-
124
- test("should pass through all parameters to single document agent", async () => {
125
- await checkUpdateIsSingle(
126
- {
127
- selectedDocs: [{ path: "/doc1", content: "content" }],
128
- docsDir: "./docs",
129
- forceRegenerate: true,
130
- customData: { key: "value" },
131
- },
132
- mockOptions,
133
- );
134
-
135
- expect(mockOptions.context.invoke).toHaveBeenCalledWith(
136
- { mockSingleAgent: true },
137
- {
138
- selectedDocs: [{ path: "/doc1", content: "content" }],
139
- docsDir: "./docs",
140
- forceRegenerate: true,
141
- customData: { key: "value" },
142
- },
143
- );
144
- });
145
-
146
- // BATCH DOCUMENT ROUTING TESTS
147
- test("should route to batchUpdateDocument when selectedDocs has multiple items", async () => {
148
- const result = await checkUpdateIsSingle(
149
- {
150
- selectedDocs: ["doc1", "doc2"],
151
- customParam: "test",
152
- },
153
- mockOptions,
154
- );
155
-
156
- expect(mockOptions.context.invoke).toHaveBeenCalledWith(
157
- { mockBatchAgent: true },
158
- {
159
- selectedDocs: ["doc1", "doc2"],
160
- customParam: "test",
161
- },
162
- );
163
- expect(result).toEqual({ mockResult: true });
164
- });
165
-
166
- test("should route to batchUpdateDocument when selectedDocs has three items", async () => {
167
- await checkUpdateIsSingle(
168
- {
169
- selectedDocs: ["doc1", "doc2", "doc3"],
170
- },
171
- mockOptions,
172
- );
173
-
174
- expect(mockOptions.context.invoke).toHaveBeenCalledWith(
175
- { mockBatchAgent: true },
176
- {
177
- selectedDocs: ["doc1", "doc2", "doc3"],
178
- },
179
- );
180
- });
181
-
182
- test("should pass through all parameters to batch document agent", async () => {
183
- await checkUpdateIsSingle(
184
- {
185
- selectedDocs: [
186
- { path: "/doc1", content: "content1" },
187
- { path: "/doc2", content: "content2" },
188
- ],
189
- docsDir: "./docs",
190
- forceRegenerate: false,
191
- batchSize: 10,
192
- customSettings: { parallel: true },
193
- },
194
- mockOptions,
195
- );
196
-
197
- expect(mockOptions.context.invoke).toHaveBeenCalledWith(
198
- { mockBatchAgent: true },
199
- {
200
- selectedDocs: [
201
- { path: "/doc1", content: "content1" },
202
- { path: "/doc2", content: "content2" },
203
- ],
204
- docsDir: "./docs",
205
- forceRegenerate: false,
206
- batchSize: 10,
207
- customSettings: { parallel: true },
208
- },
209
- );
210
- });
211
-
212
- // ERROR HANDLING TESTS
213
- test("should handle and re-throw agent invocation errors for single document", async () => {
214
- const mockError = new Error("Agent execution failed");
215
- mockOptions.context.invoke.mockRejectedValue(mockError);
216
-
217
- await expect(checkUpdateIsSingle({ selectedDocs: ["doc1"] }, mockOptions)).rejects.toThrow(
218
- "Agent execution failed",
219
- );
220
-
221
- expect(consoleSpy).toHaveBeenCalledWith(
222
- "Error invoking updateSingleDocument:",
223
- "Agent execution failed",
224
- );
225
- });
226
-
227
- test("should handle and re-throw agent invocation errors for batch documents", async () => {
228
- const mockError = new Error("Batch processing failed");
229
- mockOptions.context.invoke.mockRejectedValue(mockError);
230
-
231
- await expect(
232
- checkUpdateIsSingle({ selectedDocs: ["doc1", "doc2"] }, mockOptions),
233
- ).rejects.toThrow("Batch processing failed");
234
-
235
- expect(consoleSpy).toHaveBeenCalledWith(
236
- "Error invoking batchUpdateDocument:",
237
- "Batch processing failed",
238
- );
239
- });
240
-
241
- test("should log specific error message for single document failures", async () => {
242
- const mockError = new Error("Network timeout");
243
- mockOptions.context.invoke.mockRejectedValue(mockError);
244
-
245
- try {
246
- await checkUpdateIsSingle({ selectedDocs: ["doc1"] }, mockOptions);
247
- } catch {
248
- // Expected to throw
249
- }
250
-
251
- expect(consoleSpy).toHaveBeenCalledWith(
252
- "Error invoking updateSingleDocument:",
253
- "Network timeout",
254
- );
255
- });
256
-
257
- test("should log specific error message for batch document failures", async () => {
258
- const mockError = new Error("Memory limit exceeded");
259
- mockOptions.context.invoke.mockRejectedValue(mockError);
260
-
261
- try {
262
- await checkUpdateIsSingle({ selectedDocs: ["doc1", "doc2", "doc3"] }, mockOptions);
263
- } catch {
264
- // Expected to throw
265
- }
266
-
267
- expect(consoleSpy).toHaveBeenCalledWith(
268
- "Error invoking batchUpdateDocument:",
269
- "Memory limit exceeded",
270
- );
271
- });
272
-
273
- // RESULT PASSING TESTS
274
- test("should return result from single document agent unchanged", async () => {
275
- const mockResult = {
276
- success: true,
277
- processedDocs: ["doc1"],
278
- metadata: { timestamp: "2023-01-01" },
279
- };
280
- mockOptions.context.invoke.mockResolvedValue(mockResult);
281
-
282
- const result = await checkUpdateIsSingle({ selectedDocs: ["doc1"] }, mockOptions);
283
-
284
- expect(result).toEqual(mockResult);
285
- });
286
-
287
- test("should return result from batch document agent unchanged", async () => {
288
- const mockResult = {
289
- success: true,
290
- processedDocs: ["doc1", "doc2"],
291
- errors: [],
292
- summary: "All documents processed successfully",
293
- };
294
- mockOptions.context.invoke.mockResolvedValue(mockResult);
295
-
296
- const result = await checkUpdateIsSingle({ selectedDocs: ["doc1", "doc2"] }, mockOptions);
297
-
298
- expect(result).toEqual(mockResult);
299
- });
300
- });
@@ -1,329 +0,0 @@
1
- import { beforeEach, describe, expect, test } from "bun:test";
2
- import updateDocumentContent from "../../../../agents/update/document-tools/update-document-content.mjs";
3
-
4
- describe("update-document-content", () => {
5
- let mockOptions;
6
-
7
- beforeEach(() => {
8
- mockOptions = {
9
- context: {
10
- userContext: {
11
- currentContent: "",
12
- },
13
- },
14
- };
15
- });
16
-
17
- // Helper function to extract content from page_content wrapper
18
- function extractContent(wrappedContent) {
19
- const match = wrappedContent.match(/<page_content>\s*([\s\S]*?)\s*<\/page_content>/);
20
- return match ? match[1] : wrappedContent;
21
- }
22
-
23
- // INPUT VALIDATION TESTS
24
- test("should return error when diffPatch is not provided", async () => {
25
- mockOptions.context.userContext.currentContent = "original content";
26
- const result = await updateDocumentContent({}, mockOptions);
27
- expect(result.success).toBe(false);
28
- expect(result.error.message).toContain("diffPatch");
29
- });
30
-
31
- test("should return error when diffPatch is not a string", async () => {
32
- mockOptions.context.userContext.currentContent = "original content";
33
- const result = await updateDocumentContent({ diffPatch: null }, mockOptions);
34
- expect(result.success).toBe(false);
35
- expect(result.error.message).toContain("diffPatch");
36
- });
37
-
38
- test("should return error when diffPatch is empty string", async () => {
39
- mockOptions.context.userContext.currentContent = "original content";
40
- const result = await updateDocumentContent({ diffPatch: "" }, mockOptions);
41
- expect(result.success).toBe(false);
42
- expect(result.error.message).toContain("Diff patch is required");
43
- });
44
-
45
- // SUCCESSFUL PATCH APPLICATION TESTS
46
- test("should successfully apply simple diff patch", async () => {
47
- mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
48
- const diffPatch = "@@ -1,3 +1,3 @@\n line 1\n-line 2\n+updated line 2\n line 3";
49
-
50
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
51
-
52
- expect(result.success).toBe(true);
53
- expect(extractContent(result.updatedContent)).toBe("line 1\nupdated line 2\nline 3");
54
- expect(result.message).toContain("Document content updated successfully");
55
- });
56
-
57
- test("should handle diff with multiple hunks", async () => {
58
- mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4\nline 5";
59
- const diffPatch =
60
- "@@ -1,2 +1,2 @@\n-line 1\n+updated line 1\n line 2\n@@ -4,2 +4,2 @@\n line 4\n-line 5\n+updated line 5";
61
-
62
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
63
-
64
- expect(result.success).toBe(true);
65
- expect(extractContent(result.updatedContent)).toBe(
66
- "updated line 1\nline 2\nline 3\nline 4\nupdated line 5",
67
- );
68
- });
69
-
70
- test("should handle diff with additions only", async () => {
71
- mockOptions.context.userContext.currentContent = "line 1\nline 2";
72
- const diffPatch = "@@ -2,0 +3,2 @@\n line 2\n+new line 3\n+new line 4";
73
-
74
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
75
-
76
- expect(result.success).toBe(true);
77
- expect(extractContent(result.updatedContent)).toBe("line 1\nline 2\nnew line 3\nnew line 4");
78
- });
79
-
80
- test("should handle diff with deletions only", async () => {
81
- mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4";
82
- const diffPatch = "@@ -2,2 +2,0 @@\n line 1\n-line 2\n-line 3\n line 4";
83
-
84
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
85
-
86
- expect(result.success).toBe(true);
87
- expect(extractContent(result.updatedContent)).toBe("line 1\nline 4");
88
- });
89
-
90
- test("should handle diff with context lines", async () => {
91
- mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4\nline 5";
92
- const diffPatch =
93
- "@@ -2,3 +2,3 @@\n line 1\n line 2\n-line 3\n+updated line 3\n line 4\n line 5";
94
-
95
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
96
-
97
- expect(result.success).toBe(true);
98
- expect(extractContent(result.updatedContent)).toBe(
99
- "line 1\nline 2\nupdated line 3\nline 4\nline 5",
100
- );
101
- });
102
-
103
- // DIFF PATCH PARSING TESTS
104
- test("should return error for invalid diff format", async () => {
105
- mockOptions.context.userContext.currentContent = "line 1\nline 2";
106
- const diffPatch = "invalid diff format";
107
-
108
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
109
-
110
- expect(result).toEqual({
111
- success: false,
112
- error: { message: "No valid hunks found in diff" },
113
- });
114
- });
115
-
116
- test("should return error for empty diff", async () => {
117
- mockOptions.context.userContext.currentContent = "line 1\nline 2";
118
- const diffPatch = "\n\n";
119
-
120
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
121
-
122
- expect(result).toEqual({
123
- success: false,
124
- error: { message: "No valid hunks found in diff" },
125
- });
126
- });
127
-
128
- test("should handle malformed hunk headers gracefully", async () => {
129
- mockOptions.context.userContext.currentContent = "line 1\nline 2";
130
- const diffPatch = "@@malformed header@@\n-line 1\n+updated line 1";
131
-
132
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
133
-
134
- expect(result.success).toBe(false);
135
- expect(result.error.message).toContain("No valid hunks found");
136
- });
137
-
138
- // LINE NUMBER FIXING TESTS
139
- test("should fix line numbers when patch position is off", async () => {
140
- mockOptions.context.userContext.currentContent = "prefix line\nline 1\nline 2\nline 3";
141
- // This diff patch expects to find "line 1" at line 1, but it's actually at line 2
142
- const diffPatch = "@@ -1,2 +1,2 @@\n-line 1\n+updated line 1\n line 2";
143
-
144
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
145
-
146
- expect(result.success).toBe(true);
147
- expect(extractContent(result.updatedContent)).toBe(
148
- "prefix line\nupdated line 1\nline 2\nline 3",
149
- );
150
- });
151
-
152
- test("should use fuzzy matching when exact match fails", async () => {
153
- mockOptions.context.userContext.currentContent =
154
- "similar line 1\nsimilar line 2\ndifferent content\nsimilar line 3";
155
- // This patch refers to lines that are similar but not exactly matching
156
- const diffPatch = "@@ -10,2 +10,2 @@\n-similar line 1\n+updated line 1\n similar line 2";
157
-
158
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
159
-
160
- expect(result.success).toBe(true);
161
- expect(extractContent(result.updatedContent)).toBe(
162
- "updated line 1\nsimilar line 2\ndifferent content\nsimilar line 3",
163
- );
164
- });
165
-
166
- test("should return error when no matching context found", async () => {
167
- mockOptions.context.userContext.currentContent =
168
- "completely different content\nnothing matches";
169
- const diffPatch =
170
- "@@ -1,2 +1,2 @@\n-line that doesn't exist\n+updated line\n another nonexistent line";
171
-
172
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
173
-
174
- expect(result.success).toBe(false);
175
- expect(result.error.message).toContain("Cannot find matching context");
176
- });
177
-
178
- // COMPLEX DIFF SCENARIOS
179
- test("should handle diff with no context lines", async () => {
180
- mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
181
- const diffPatch = "@@ -2,1 +2,1 @@\n-line 2\n+updated line 2";
182
-
183
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
184
-
185
- expect(result.success).toBe(true);
186
- expect(extractContent(result.updatedContent)).toBe("line 1\nupdated line 2\nline 3");
187
- });
188
-
189
- test("should handle diff with single line count (implicit 1)", async () => {
190
- mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
191
- const diffPatch = "@@ -2 +2 @@\n-line 2\n+updated line 2";
192
-
193
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
194
-
195
- expect(result.success).toBe(true);
196
- expect(extractContent(result.updatedContent)).toBe("line 1\nupdated line 2\nline 3");
197
- });
198
-
199
- test("should handle multiple changes in single hunk", async () => {
200
- mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4\nline 5";
201
- const diffPatch =
202
- "@@ -2,3 +2,4 @@\n line 1\n-line 2\n-line 3\n+updated line 2\n+new line\n+updated line 3\n line 4";
203
-
204
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
205
-
206
- expect(result.success).toBe(true);
207
- expect(extractContent(result.updatedContent)).toBe(
208
- "line 1\nupdated line 2\nnew line\nupdated line 3\nline 4\nline 5",
209
- );
210
- });
211
-
212
- // EDGE CASES
213
- test("should handle empty lines in diff", async () => {
214
- mockOptions.context.userContext.currentContent = "line 1\n\nline 3";
215
- const diffPatch = "@@ -1,3 +1,3 @@\n line 1\n \n-line 3\n+updated line 3";
216
-
217
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
218
-
219
- expect(result.success).toBe(true);
220
- expect(extractContent(result.updatedContent)).toBe("line 1\n\nupdated line 3");
221
- });
222
-
223
- test("should handle diff with trailing newlines", async () => {
224
- mockOptions.context.userContext.currentContent = "line 1\nline 2\n";
225
- const diffPatch = "@@ -1,2 +1,2 @@\n-line 1\n+updated line 1\n line 2";
226
-
227
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
228
-
229
- expect(result.success).toBe(true);
230
- // Note: applyPatch may normalize trailing newlines
231
- const content = extractContent(result.updatedContent);
232
- expect(content).toContain("updated line 1");
233
- expect(content).toContain("line 2");
234
- });
235
-
236
- // REALISTIC DOCUMENTATION UPDATE SCENARIOS
237
- test("should handle updating code blocks", async () => {
238
- mockOptions.context.userContext.currentContent =
239
- "# API Reference\n\n```javascript\nfunction oldFunction() {\n return 'old';\n}\n```\n\nDescription here.";
240
- const diffPatch =
241
- "@@ -3,3 +3,3 @@\n # API Reference\n \n ```javascript\n-function oldFunction() {\n- return 'old';\n+function newFunction() {\n+ return 'new';\n }\n ```";
242
-
243
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
244
-
245
- expect(result.success).toBe(true);
246
- const content = extractContent(result.updatedContent);
247
- expect(content).toContain("function newFunction()");
248
- expect(content).toContain("return 'new';");
249
- });
250
-
251
- test("should handle adding new sections", async () => {
252
- mockOptions.context.userContext.currentContent =
253
- "# Documentation\n\n## Section 1\n\nContent 1\n\n## Section 3\n\nContent 3";
254
- const diffPatch =
255
- "@@ -4,0 +5,3 @@\n Content 1\n \n+## Section 2\n+\n+Content 2\n+\n ## Section 3";
256
-
257
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
258
-
259
- expect(result.success).toBe(true);
260
- const content = extractContent(result.updatedContent);
261
- expect(content).toContain("## Section 2");
262
- expect(content).toContain("Content 2");
263
- });
264
-
265
- test("should handle removing outdated content", async () => {
266
- mockOptions.context.userContext.currentContent =
267
- "# Guide\n\n## Current Feature\n\nThis is current.\n\n## Deprecated Feature\n\nThis is deprecated.\n\n## Another Feature\n\nThis is also current.";
268
- const diffPatch =
269
- "@@ -5,4 +5,0 @@\n This is current.\n \n-## Deprecated Feature\n-\n-This is deprecated.\n-\n ## Another Feature";
270
-
271
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
272
-
273
- expect(result.success).toBe(true);
274
- const content = extractContent(result.updatedContent);
275
- expect(content).not.toContain("Deprecated Feature");
276
- expect(content).toContain("Current Feature");
277
- expect(content).toContain("Another Feature");
278
- });
279
-
280
- // ERROR SCENARIOS WITH REALISTIC CONTENT
281
- test("should handle conflicting patches gracefully", async () => {
282
- mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
283
- // This patch tries to modify content that doesn't match exactly
284
- const diffPatch =
285
- "@@ -1,3 +1,3 @@\n-different line 1\n-different line 2\n+updated line 1\n+updated line 2\n line 3";
286
-
287
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
288
-
289
- expect(result.success).toBe(false);
290
- expect(result.error.message).toContain("Cannot find matching context");
291
- });
292
-
293
- test("should handle patches with incorrect line counts", async () => {
294
- mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4";
295
- // Incorrect line count in hunk header (says 5 lines but content has 4)
296
- const diffPatch = "@@ -1,5 +1,3 @@\n-line 1\n-line 2\n line 3\n line 4";
297
-
298
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
299
-
300
- expect(result.success).toBe(true);
301
- expect(extractContent(result.updatedContent)).toBe("line 3\nline 4");
302
- });
303
-
304
- // FUZZY MATCHING EDGE CASES
305
- test("should succeed fuzzy matching with high similarity", async () => {
306
- mockOptions.context.userContext.currentContent =
307
- "function calculateTotal(items) {\n let total = 0;\n for (item of items) {\n total += item.price;\n }\n return total;\n}";
308
- // Patch has slight differences but should match with fuzzy matching
309
- const diffPatch =
310
- "@@ -2,2 +2,2 @@\n function calculateTotal(items) {\n- let total = 0;\n+ let sum = 0;\n for (item of items) {";
311
-
312
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
313
-
314
- expect(result.success).toBe(true);
315
- expect(extractContent(result.updatedContent)).toContain("let sum = 0;");
316
- });
317
-
318
- test("should fail fuzzy matching with low similarity", async () => {
319
- mockOptions.context.userContext.currentContent =
320
- "completely different content\nwith nothing similar\nat all";
321
- const diffPatch =
322
- "@@ -1,2 +1,2 @@\n-some totally different text\n+updated text\n that has no relation";
323
-
324
- const result = await updateDocumentContent({ diffPatch }, mockOptions);
325
-
326
- expect(result.success).toBe(false);
327
- expect(result.error.message).toContain("Cannot find matching context");
328
- });
329
- });
@@ -1,51 +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("generateDocument 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/update/generate-document.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
- expect(agent.name).toBe("generateDocument");
29
- });
30
-
31
- test("should have instructions loaded from file", async () => {
32
- const agent = await loadAgent(
33
- join(import.meta.dirname, "../../../agents/update/generate-document.yaml"),
34
- {
35
- model: loadModel,
36
- },
37
- );
38
-
39
- expect(agent).toBeDefined();
40
-
41
- // Verify instructions are loaded
42
- expect(agent.instructions).toBeDefined();
43
- const instructions = await agent.instructions.build({});
44
- expect(instructions.messages).toBeDefined();
45
- expect(instructions.messages.length).toBeGreaterThan(0);
46
-
47
- // The instructions should contain content from the prompt file
48
- const systemMessage = instructions.messages.find((m) => m.role === "system");
49
- expect(systemMessage).toBeDefined();
50
- });
51
- });