@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,521 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, test } from "bun:test";
2
- import { mkdir, rm, writeFile } from "node:fs/promises";
3
- import { dirname, join } from "node:path";
4
- import { fileURLToPath } from "node:url";
5
- import {
6
- buildSourcesContent,
7
- calculateFileStats,
8
- getFilesWithGlob,
9
- loadFilesFromPaths,
10
- loadGitignore,
11
- pathExists,
12
- readFileContents,
13
- resolveToAbsolute,
14
- toDisplayPath,
15
- } from "../../utils/file-utils.mjs";
16
-
17
- const __dirname = dirname(fileURLToPath(import.meta.url));
18
-
19
- describe("file-utils", () => {
20
- let testDir;
21
-
22
- beforeEach(async () => {
23
- // Create a temporary test directory
24
- testDir = join(__dirname, "test-file-utils");
25
- await mkdir(testDir, { recursive: true });
26
- });
27
-
28
- afterEach(async () => {
29
- // Clean up test directory
30
- try {
31
- await rm(testDir, { recursive: true, force: true });
32
- } catch {
33
- // Ignore cleanup errors since they don't affect test results
34
- }
35
- });
36
-
37
- describe("loadGitignore", () => {
38
- test("should load gitignore patterns from current directory", async () => {
39
- const gitignorePath = join(testDir, ".gitignore");
40
- const gitignoreContent = `
41
- node_modules/
42
- dist/
43
- *.log
44
- .env
45
- # Comment line
46
- `.trim();
47
-
48
- await writeFile(gitignorePath, gitignoreContent);
49
-
50
- const patterns = await loadGitignore(testDir);
51
-
52
- expect(patterns).toBeDefined();
53
- expect(Array.isArray(patterns)).toBe(true);
54
- expect(patterns.length).toBeGreaterThan(0);
55
-
56
- // Should convert gitignore patterns to glob patterns
57
- expect(patterns.some((p) => p.includes("node_modules"))).toBe(true);
58
- expect(patterns.some((p) => p.includes("dist"))).toBe(true);
59
- expect(patterns.some((p) => p.includes("*.log"))).toBe(true);
60
- expect(patterns.some((p) => p.includes(".env"))).toBe(true);
61
- });
62
-
63
- test("should load gitignore patterns from git repository", async () => {
64
- const patterns = await loadGitignore(testDir);
65
- // Since we're in a git repository, it should load patterns
66
- expect(patterns).not.toBeNull();
67
- expect(Array.isArray(patterns)).toBe(true);
68
- });
69
-
70
- test("should handle empty gitignore file", async () => {
71
- const gitignorePath = join(testDir, ".gitignore");
72
- await writeFile(gitignorePath, "");
73
-
74
- const patterns = await loadGitignore(testDir);
75
- // Even with empty gitignore, parent git repo patterns are loaded
76
- expect(patterns).not.toBeNull();
77
- expect(Array.isArray(patterns)).toBe(true);
78
- });
79
-
80
- test("should ignore comment lines and empty lines", async () => {
81
- const gitignorePath = join(testDir, ".gitignore");
82
- const gitignoreContent = `
83
- # This is a comment
84
- node_modules/
85
-
86
- # Another comment
87
- *.log
88
- `.trim();
89
-
90
- await writeFile(gitignorePath, gitignoreContent);
91
-
92
- const patterns = await loadGitignore(testDir);
93
-
94
- expect(patterns).toBeDefined();
95
- // Should not contain empty strings or comments
96
- expect(patterns.every((p) => p.trim().length > 0 && !p.startsWith("#"))).toBe(true);
97
- });
98
-
99
- test("should handle various gitignore pattern formats", async () => {
100
- const gitignorePath = join(testDir, ".gitignore");
101
- const gitignoreContent = `
102
- /absolute-path
103
- relative-path
104
- directory/
105
- *.extension
106
- **/*.js
107
- temp*
108
- `.trim();
109
-
110
- await writeFile(gitignorePath, gitignoreContent);
111
-
112
- const patterns = await loadGitignore(testDir);
113
-
114
- expect(patterns).toBeDefined();
115
- expect(patterns.length).toBeGreaterThan(0);
116
-
117
- // Should handle different pattern types
118
- expect(patterns.some((p) => p.includes("absolute-path"))).toBe(true);
119
- expect(patterns.some((p) => p.includes("relative-path"))).toBe(true);
120
- expect(patterns.some((p) => p.includes("directory"))).toBe(true);
121
- expect(patterns.some((p) => p.includes("*.extension"))).toBe(true);
122
- });
123
- });
124
-
125
- describe("getFilesWithGlob", () => {
126
- beforeEach(async () => {
127
- // Create test file structure
128
- await mkdir(join(testDir, "src"), { recursive: true });
129
- await mkdir(join(testDir, "lib"), { recursive: true });
130
- await mkdir(join(testDir, "node_modules"), { recursive: true });
131
-
132
- await writeFile(join(testDir, "src", "index.js"), "// main file");
133
- await writeFile(join(testDir, "src", "utils.ts"), "// utils file");
134
- await writeFile(join(testDir, "lib", "helper.js"), "// helper file");
135
- await writeFile(join(testDir, "README.md"), "# readme");
136
- await writeFile(join(testDir, "package.json"), "{}");
137
- await writeFile(join(testDir, "node_modules", "dep.js"), "// dependency");
138
- });
139
-
140
- test("should find files with basic include patterns", async () => {
141
- const files = await getFilesWithGlob(testDir, ["*.js"], [], []);
142
-
143
- expect(files).toBeDefined();
144
- expect(Array.isArray(files)).toBe(true);
145
- expect(files.some((f) => f.includes("index.js"))).toBe(true);
146
- expect(files.some((f) => f.includes("helper.js"))).toBe(true);
147
- });
148
-
149
- test("should exclude files based on exclude patterns", async () => {
150
- const files = await getFilesWithGlob(testDir, ["**/*.js"], ["node_modules/**"], []);
151
-
152
- expect(files).toBeDefined();
153
- expect(files.some((f) => f.includes("index.js"))).toBe(true);
154
- expect(files.some((f) => f.includes("helper.js"))).toBe(true);
155
- expect(files.some((f) => f.includes("node_modules"))).toBe(false);
156
- });
157
-
158
- test("should handle multiple include patterns", async () => {
159
- const files = await getFilesWithGlob(testDir, ["*.js", "*.ts"], [], []);
160
-
161
- expect(files).toBeDefined();
162
- expect(files.some((f) => f.includes("index.js"))).toBe(true);
163
- expect(files.some((f) => f.includes("utils.ts"))).toBe(true);
164
- expect(files.some((f) => f.includes("helper.js"))).toBe(true);
165
- });
166
-
167
- test("should handle gitignore patterns", async () => {
168
- const gitignorePatterns = ["node_modules/**"];
169
- const files = await getFilesWithGlob(testDir, ["**/*.js"], [], gitignorePatterns);
170
-
171
- expect(files).toBeDefined();
172
- expect(files.some((f) => f.includes("index.js"))).toBe(true);
173
- expect(files.some((f) => f.includes("node_modules"))).toBe(false);
174
- });
175
-
176
- test("should return empty array for empty include patterns", async () => {
177
- const files = await getFilesWithGlob(testDir, [], [], []);
178
-
179
- expect(files).toBeDefined();
180
- expect(Array.isArray(files)).toBe(true);
181
- expect(files.length).toBe(0);
182
- });
183
-
184
- test("should return absolute paths", async () => {
185
- const files = await getFilesWithGlob(testDir, ["*.js"], [], []);
186
-
187
- expect(files).toBeDefined();
188
- files.forEach((file) => {
189
- expect(file.startsWith("/")).toBe(true);
190
- });
191
- });
192
-
193
- test("should handle nested directory patterns", async () => {
194
- await mkdir(join(testDir, "src", "components"), { recursive: true });
195
- await writeFile(join(testDir, "src", "components", "button.js"), "// button");
196
-
197
- const files = await getFilesWithGlob(testDir, ["src/**/*.js"], [], []);
198
-
199
- expect(files).toBeDefined();
200
- expect(files.some((f) => f.includes("index.js"))).toBe(true);
201
- expect(files.some((f) => f.includes("button.js"))).toBe(true);
202
- });
203
-
204
- test("should handle complex glob patterns", async () => {
205
- const files = await getFilesWithGlob(testDir, ["**/*.{js,ts,md}"], ["node_modules/**"], []);
206
-
207
- expect(files).toBeDefined();
208
- expect(files.some((f) => f.includes("index.js"))).toBe(true);
209
- expect(files.some((f) => f.includes("utils.ts"))).toBe(true);
210
- expect(files.some((f) => f.includes("README.md"))).toBe(true);
211
- expect(files.some((f) => f.includes("node_modules"))).toBe(false);
212
- });
213
-
214
- test("should handle non-existent directory gracefully", async () => {
215
- const nonExistentDir = join(testDir, "non-existent");
216
- const files = await getFilesWithGlob(nonExistentDir, ["*.js"], [], []);
217
-
218
- expect(files).toBeDefined();
219
- expect(Array.isArray(files)).toBe(true);
220
- expect(files.length).toBe(0);
221
- });
222
- });
223
-
224
- describe("pathExists", () => {
225
- test("should return true for existing file", async () => {
226
- const testFile = join(testDir, "exists.txt");
227
- await writeFile(testFile, "test");
228
-
229
- const exists = await pathExists(testFile);
230
- expect(exists).toBe(true);
231
- });
232
-
233
- test("should return true for existing directory", async () => {
234
- const exists = await pathExists(testDir);
235
- expect(exists).toBe(true);
236
- });
237
-
238
- test("should return false for non-existent path", async () => {
239
- const nonExistent = join(testDir, "does-not-exist.txt");
240
- const exists = await pathExists(nonExistent);
241
- expect(exists).toBe(false);
242
- });
243
- });
244
-
245
- describe("toDisplayPath", () => {
246
- test("should return relative path for paths inside cwd", () => {
247
- const testPath = join(process.cwd(), "test", "file.txt");
248
- const display = toDisplayPath(testPath);
249
- expect(display.startsWith("..")).toBe(false);
250
- expect(display).toContain("test");
251
- });
252
-
253
- test("should return absolute path for paths outside cwd", () => {
254
- const testPath = "/some/other/path/file.txt";
255
- const display = toDisplayPath(testPath);
256
- expect(display.startsWith("/") || display.startsWith("..")).toBe(true);
257
- });
258
-
259
- test("should return . for current directory", () => {
260
- const display = toDisplayPath(process.cwd());
261
- expect(display).toBe(".");
262
- });
263
- });
264
-
265
- describe("resolveToAbsolute", () => {
266
- test("should return absolute path as-is", () => {
267
- const absolutePath = "/absolute/path/file.txt";
268
- const resolved = resolveToAbsolute(absolutePath);
269
- expect(resolved).toBe(absolutePath);
270
- });
271
-
272
- test("should resolve relative path to absolute", () => {
273
- const relativePath = "relative/file.txt";
274
- const resolved = resolveToAbsolute(relativePath);
275
- expect(resolved).toBeDefined();
276
- expect(resolved?.startsWith("/")).toBe(true);
277
- expect(resolved).toContain("relative");
278
- });
279
-
280
- test("should return undefined for empty value", () => {
281
- expect(resolveToAbsolute("")).toBeUndefined();
282
- expect(resolveToAbsolute(null)).toBeUndefined();
283
- expect(resolveToAbsolute(undefined)).toBeUndefined();
284
- });
285
- });
286
-
287
- describe("loadFilesFromPaths", () => {
288
- beforeEach(async () => {
289
- await mkdir(join(testDir, "src"), { recursive: true });
290
- await mkdir(join(testDir, "docs"), { recursive: true });
291
- await writeFile(join(testDir, "src", "index.js"), "// index");
292
- await writeFile(join(testDir, "src", "utils.ts"), "// utils");
293
- await writeFile(join(testDir, "docs", "readme.md"), "# readme");
294
- await writeFile(join(testDir, "config.json"), "{}");
295
- });
296
-
297
- test("should load single file path", async () => {
298
- const filePath = join(testDir, "config.json");
299
- const files = await loadFilesFromPaths(filePath);
300
-
301
- expect(files).toBeDefined();
302
- expect(files.length).toBe(1);
303
- expect(files[0]).toBe(filePath);
304
- });
305
-
306
- test("should load multiple file paths", async () => {
307
- const file1 = join(testDir, "config.json");
308
- const file2 = join(testDir, "docs", "readme.md");
309
- const files = await loadFilesFromPaths([file1, file2]);
310
-
311
- expect(files.length).toBe(2);
312
- expect(files).toContain(file1);
313
- expect(files).toContain(file2);
314
- });
315
-
316
- test("should load files from directory with default patterns", async () => {
317
- const files = await loadFilesFromPaths(testDir, {
318
- useDefaultPatterns: true,
319
- defaultIncludePatterns: ["**/*.js", "**/*.ts"],
320
- defaultExcludePatterns: [],
321
- });
322
-
323
- expect(files.length).toBeGreaterThan(0);
324
- expect(files.some((f) => f.includes("index.js"))).toBe(true);
325
- expect(files.some((f) => f.includes("utils.ts"))).toBe(true);
326
- });
327
-
328
- test("should handle glob patterns", async () => {
329
- const files = await loadFilesFromPaths(join(testDir, "**/*.js"));
330
-
331
- expect(files).toBeDefined();
332
- expect(files.some((f) => f.includes("index.js"))).toBe(true);
333
- });
334
-
335
- test("should handle invalid paths gracefully", async () => {
336
- const files = await loadFilesFromPaths([123, null, "valid-but-not-exist"], {
337
- useDefaultPatterns: false,
338
- });
339
-
340
- expect(Array.isArray(files)).toBe(true);
341
- });
342
-
343
- test("should apply include and exclude patterns", async () => {
344
- const files = await loadFilesFromPaths(testDir, {
345
- includePatterns: ["**/*.js", "**/*.ts"],
346
- excludePatterns: ["**/*.ts"],
347
- useDefaultPatterns: false,
348
- });
349
-
350
- expect(files.some((f) => f.includes("index.js"))).toBe(true);
351
- expect(files.some((f) => f.includes("utils.ts"))).toBe(false);
352
- });
353
-
354
- test("should handle string patterns as array", async () => {
355
- const files = await loadFilesFromPaths(testDir, {
356
- includePatterns: "**/*.js",
357
- excludePatterns: "**/*.ts",
358
- useDefaultPatterns: false,
359
- });
360
-
361
- expect(Array.isArray(files)).toBe(true);
362
- });
363
- });
364
-
365
- describe("readFileContents", () => {
366
- beforeEach(async () => {
367
- await mkdir(join(testDir, "src"), { recursive: true });
368
- await writeFile(join(testDir, "src", "file1.js"), "const x = 1;");
369
- await writeFile(join(testDir, "src", "file2.js"), "const y = 2;");
370
- });
371
-
372
- test("should read multiple files with content", async () => {
373
- const files = [join(testDir, "src", "file1.js"), join(testDir, "src", "file2.js")];
374
- const contents = await readFileContents(files, testDir);
375
-
376
- expect(contents.length).toBe(2);
377
- expect(contents[0].sourceId).toContain("file1.js");
378
- expect(contents[0].content).toContain("const x = 1");
379
- expect(contents[1].sourceId).toContain("file2.js");
380
- expect(contents[1].content).toContain("const y = 2");
381
- });
382
-
383
- test("should use custom baseDir for relative paths", async () => {
384
- const files = [join(testDir, "src", "file1.js")];
385
- const contents = await readFileContents(files, testDir);
386
-
387
- expect(contents[0].sourceId).not.toContain(testDir);
388
- expect(contents[0].sourceId).toContain("src");
389
- });
390
-
391
- test("should skip binary files by default", async () => {
392
- const binaryFile = join(testDir, "binary.bin");
393
- await writeFile(binaryFile, Buffer.from([0xff, 0xfe, 0xfd, 0xfc]));
394
- const textFile = join(testDir, "text.txt");
395
- await writeFile(textFile, "text content");
396
-
397
- const contents = await readFileContents([binaryFile, textFile], testDir);
398
-
399
- expect(contents.length).toBeGreaterThanOrEqual(1);
400
- expect(contents.some((c) => c.sourceId.includes("text.txt"))).toBe(true);
401
- });
402
-
403
- test("should include binary files when skipBinaryFiles is false", async () => {
404
- const binaryFile = join(testDir, "binary.bin");
405
- await writeFile(binaryFile, Buffer.from([0x48, 0x65, 0x6c, 0x6c, 0x6f]));
406
-
407
- const contents = await readFileContents([binaryFile], testDir, {
408
- skipBinaryFiles: false,
409
- });
410
-
411
- expect(contents.length).toBeGreaterThanOrEqual(0);
412
- });
413
-
414
- test("should handle empty file array", async () => {
415
- const contents = await readFileContents([], testDir);
416
- expect(contents.length).toBe(0);
417
- });
418
- });
419
-
420
- describe("calculateFileStats", () => {
421
- test("should calculate tokens and lines correctly", () => {
422
- const sourceFiles = [
423
- { content: "const x = 1;\nconst y = 2;" },
424
- { content: "function test() {\n return true;\n}" },
425
- ];
426
-
427
- const stats = calculateFileStats(sourceFiles);
428
-
429
- expect(stats.totalTokens).toBeGreaterThan(0);
430
- expect(stats.totalLines).toBeGreaterThan(0);
431
- expect(stats.totalLines).toBeGreaterThan(3);
432
- });
433
-
434
- test("should handle empty content", () => {
435
- const sourceFiles = [{ content: "" }, { content: "" }];
436
- const stats = calculateFileStats(sourceFiles);
437
-
438
- expect(stats.totalTokens).toBe(0);
439
- expect(stats.totalLines).toBe(0);
440
- });
441
-
442
- test("should exclude empty lines from line count", () => {
443
- const sourceFiles = [{ content: "line1\n\nline2\n\n\nline3" }];
444
- const stats = calculateFileStats(sourceFiles);
445
-
446
- expect(stats.totalLines).toBe(3);
447
- });
448
-
449
- test("should handle files without content property", () => {
450
- const sourceFiles = [{ noContent: true }, { content: "test" }];
451
- const stats = calculateFileStats(sourceFiles);
452
-
453
- expect(stats.totalTokens).toBeGreaterThan(0);
454
- expect(stats.totalLines).toBe(1);
455
- });
456
- });
457
-
458
- describe("buildSourcesContent", () => {
459
- test("should build sources for normal context", () => {
460
- const sourceFiles = [
461
- { sourceId: "file1.js", content: "const x = 1;" },
462
- { sourceId: "file2.js", content: "const y = 2;" },
463
- ];
464
-
465
- const sources = buildSourcesContent(sourceFiles, false);
466
-
467
- expect(sources).toContain("// sourceId: file1.js");
468
- expect(sources).toContain("const x = 1;");
469
- expect(sources).toContain("// sourceId: file2.js");
470
- expect(sources).toContain("const y = 2;");
471
- expect(sources).not.toContain("Note: Context is large");
472
- });
473
-
474
- test("should filter core files for large context", () => {
475
- const sourceFiles = [
476
- { sourceId: "package.json", content: '{"name": "test"}' },
477
- { sourceId: "README.md", content: "# Test" },
478
- { sourceId: "random.js", content: "const x = 1;" },
479
- ];
480
-
481
- const sources = buildSourcesContent(sourceFiles, true);
482
-
483
- expect(sources).toContain("Note: Context is large");
484
- expect(sources).toContain("package.json");
485
- expect(sources).toContain("README.md");
486
- });
487
-
488
- test("should include core files matching patterns", () => {
489
- const sourceFiles = [
490
- { sourceId: "index.js", content: "// entry" },
491
- { sourceId: "main.ts", content: "// main" },
492
- { sourceId: "types.d.ts", content: "// types" },
493
- { sourceId: "api/routes.js", content: "// routes" },
494
- ];
495
-
496
- const sources = buildSourcesContent(sourceFiles, true);
497
-
498
- expect(sources).toContain("index.js");
499
- expect(sources).toContain("main.ts");
500
- expect(sources).toContain("types.d.ts");
501
- expect(sources).toContain("routes.js");
502
- });
503
-
504
- test("should handle empty sourceFiles array", () => {
505
- const sources = buildSourcesContent([], false);
506
- expect(sources).toBe("");
507
- });
508
-
509
- test("should use all files as fallback when no core files in large context", () => {
510
- const sourceFiles = [
511
- { sourceId: "random1.xyz", content: "test1" },
512
- { sourceId: "random2.xyz", content: "test2" },
513
- ];
514
-
515
- const sources = buildSourcesContent(sourceFiles, true);
516
-
517
- expect(sources).toContain("Note: Context is large");
518
- expect(sources).toContain("showing a sample of files");
519
- });
520
- });
521
- });