@aigne/doc-smith 0.8.11-beta.5 → 0.8.11-beta.7

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 (159) hide show
  1. package/.aigne/doc-smith/config.yaml +3 -1
  2. package/.aigne/doc-smith/output/structure-plan.json +2 -2
  3. package/.aigne/doc-smith/preferences.yml +28 -20
  4. package/.aigne/doc-smith/upload-cache.yaml +702 -0
  5. package/.release-please-manifest.json +1 -1
  6. package/CHANGELOG.md +22 -2
  7. package/README.md +2 -2
  8. package/agents/clear/choose-contents.mjs +2 -2
  9. package/agents/clear/clear-document-structure.mjs +8 -8
  10. package/agents/clear/index.yaml +1 -1
  11. package/agents/evaluate/document-structure.yaml +1 -1
  12. package/agents/generate/check-document-structure.yaml +3 -3
  13. package/agents/generate/check-need-generate-structure.mjs +8 -8
  14. package/agents/generate/document-structure-tools/add-document.mjs +38 -13
  15. package/agents/generate/document-structure-tools/delete-document.mjs +37 -14
  16. package/agents/generate/document-structure-tools/move-document.mjs +46 -19
  17. package/agents/generate/document-structure-tools/update-document.mjs +39 -12
  18. package/agents/generate/generate-structure.yaml +1 -1
  19. package/agents/generate/update-document-structure.yaml +3 -9
  20. package/agents/generate/user-review-document-structure.mjs +15 -14
  21. package/agents/translate/translate-document.yaml +1 -9
  22. package/agents/update/batch-generate-document.yaml +1 -1
  23. package/agents/update/check-document.mjs +2 -2
  24. package/agents/update/check-update-is-single.mjs +2 -1
  25. package/agents/update/document-tools/update-document-content.mjs +24 -14
  26. package/agents/update/fs-tools/glob.mjs +184 -0
  27. package/agents/update/fs-tools/grep.mjs +317 -0
  28. package/agents/update/fs-tools/read-file.mjs +307 -0
  29. package/agents/update/generate-document.yaml +4 -7
  30. package/agents/update/update-document-detail.yaml +6 -10
  31. package/agents/update/user-review-document.mjs +13 -13
  32. package/agents/utils/check-feedback-refiner.mjs +1 -1
  33. package/agents/utils/choose-docs.mjs +1 -1
  34. package/agents/utils/load-document-all-content.mjs +3 -3
  35. package/agents/utils/load-sources.mjs +1 -1
  36. package/agents/utils/save-docs.mjs +7 -28
  37. package/aigne.yaml +2 -2
  38. package/assets/screenshots/doc-complete-setup.png +0 -0
  39. package/assets/screenshots/doc-generate-docs.png +0 -0
  40. package/assets/screenshots/doc-generate.png +0 -0
  41. package/assets/screenshots/doc-generated-successfully.png +0 -0
  42. package/assets/screenshots/doc-publish.png +0 -0
  43. package/assets/screenshots/doc-regenerate.png +0 -0
  44. package/assets/screenshots/doc-translate-langs.png +0 -0
  45. package/assets/screenshots/doc-translate.png +0 -0
  46. package/assets/screenshots/doc-update.png +0 -0
  47. package/docs/_sidebar.md +1 -1
  48. package/docs/advanced-how-it-works.ja.md +31 -31
  49. package/docs/advanced-how-it-works.md +10 -10
  50. package/docs/advanced-how-it-works.zh-TW.md +24 -24
  51. package/docs/advanced-how-it-works.zh.md +20 -20
  52. package/docs/advanced-quality-assurance.ja.md +57 -61
  53. package/docs/advanced-quality-assurance.md +57 -61
  54. package/docs/advanced-quality-assurance.zh-TW.md +57 -61
  55. package/docs/advanced-quality-assurance.zh.md +57 -61
  56. package/docs/advanced.ja.md +8 -4
  57. package/docs/advanced.md +7 -3
  58. package/docs/advanced.zh-TW.md +9 -5
  59. package/docs/advanced.zh.md +9 -5
  60. package/docs/changelog.ja.md +206 -29
  61. package/docs/changelog.md +177 -0
  62. package/docs/changelog.zh-TW.md +229 -52
  63. package/docs/changelog.zh.md +204 -27
  64. package/docs/cli-reference.ja.md +181 -80
  65. package/docs/cli-reference.md +168 -67
  66. package/docs/cli-reference.zh-TW.md +177 -76
  67. package/docs/cli-reference.zh.md +172 -71
  68. package/docs/configuration-interactive-setup.ja.md +45 -42
  69. package/docs/configuration-interactive-setup.md +9 -6
  70. package/docs/configuration-interactive-setup.zh-TW.md +26 -23
  71. package/docs/configuration-interactive-setup.zh.md +25 -22
  72. package/docs/configuration-language-support.ja.md +33 -63
  73. package/docs/configuration-language-support.md +32 -62
  74. package/docs/configuration-language-support.zh-TW.md +35 -65
  75. package/docs/configuration-language-support.zh.md +32 -62
  76. package/docs/configuration-llm-setup.ja.md +25 -23
  77. package/docs/configuration-llm-setup.md +20 -18
  78. package/docs/configuration-llm-setup.zh-TW.md +21 -19
  79. package/docs/configuration-llm-setup.zh.md +20 -18
  80. package/docs/configuration-preferences.ja.md +67 -52
  81. package/docs/configuration-preferences.md +55 -40
  82. package/docs/configuration-preferences.zh-TW.md +69 -54
  83. package/docs/configuration-preferences.zh.md +68 -53
  84. package/docs/configuration.ja.md +98 -58
  85. package/docs/configuration.md +42 -2
  86. package/docs/configuration.zh-TW.md +86 -46
  87. package/docs/configuration.zh.md +76 -36
  88. package/docs/features-generate-documentation.ja.md +49 -55
  89. package/docs/features-generate-documentation.md +49 -55
  90. package/docs/features-generate-documentation.zh-TW.md +54 -60
  91. package/docs/features-generate-documentation.zh.md +48 -54
  92. package/docs/features-publish-your-docs.ja.md +68 -45
  93. package/docs/features-publish-your-docs.md +65 -42
  94. package/docs/features-publish-your-docs.zh-TW.md +74 -51
  95. package/docs/features-publish-your-docs.zh.md +67 -44
  96. package/docs/features-translate-documentation.ja.md +46 -35
  97. package/docs/features-translate-documentation.md +39 -28
  98. package/docs/features-translate-documentation.zh-TW.md +45 -34
  99. package/docs/features-translate-documentation.zh.md +39 -28
  100. package/docs/features-update-and-refine.ja.md +75 -71
  101. package/docs/features-update-and-refine.md +67 -63
  102. package/docs/features-update-and-refine.zh-TW.md +72 -67
  103. package/docs/features-update-and-refine.zh.md +71 -67
  104. package/docs/features.ja.md +29 -19
  105. package/docs/features.md +25 -15
  106. package/docs/features.zh-TW.md +28 -18
  107. package/docs/features.zh.md +31 -21
  108. package/docs/getting-started.ja.md +43 -46
  109. package/docs/getting-started.md +36 -39
  110. package/docs/getting-started.zh-TW.md +41 -44
  111. package/docs/getting-started.zh.md +39 -42
  112. package/docs/overview.ja.md +63 -11
  113. package/docs/overview.md +62 -10
  114. package/docs/overview.zh-TW.md +67 -15
  115. package/docs/overview.zh.md +62 -10
  116. package/docs-mcp/analyze-docs-relevance.yaml +6 -6
  117. package/docs-mcp/docs-search.yaml +1 -1
  118. package/media.md +9 -9
  119. package/package.json +2 -2
  120. package/prompts/common/document-structure/conflict-resolution-guidance.md +3 -3
  121. package/prompts/common/document-structure/document-structure-rules.md +2 -2
  122. package/prompts/detail/custom/custom-components.md +304 -188
  123. package/prompts/detail/document-rules.md +5 -5
  124. package/prompts/detail/generate-document.md +21 -8
  125. package/prompts/detail/update-document.md +8 -12
  126. package/prompts/evaluate/document-structure.md +6 -6
  127. package/prompts/structure/check-document-structure.md +10 -10
  128. package/prompts/structure/document-rules.md +2 -2
  129. package/prompts/structure/generate-structure-system.md +3 -3
  130. package/prompts/structure/structure-example.md +1 -1
  131. package/prompts/structure/structure-getting-started.md +1 -1
  132. package/prompts/structure/update-document-structure.md +18 -14
  133. package/prompts/utils/feedback-refiner.md +3 -3
  134. package/tests/agents/clear/choose-contents.test.mjs +1 -1
  135. package/tests/agents/clear/clear-document-structure.test.mjs +36 -30
  136. package/tests/agents/evaluate/generate-report.test.mjs +1 -1
  137. package/tests/agents/generate/check-need-generate-structure.test.mjs +1 -1
  138. package/tests/agents/generate/document-structure-tools/add-document.test.mjs +2 -2
  139. package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +4 -4
  140. package/tests/agents/generate/document-structure-tools/move-document.test.mjs +12 -12
  141. package/tests/agents/generate/document-structure-tools/update-document.test.mjs +3 -3
  142. package/tests/agents/generate/user-review-document-structure.test.mjs +36 -13
  143. package/tests/agents/update/check-document.test.mjs +1 -1
  144. package/tests/agents/update/document-tools/update-document-content.test.mjs +115 -112
  145. package/tests/agents/update/fs-tools/glob.test.mjs +438 -0
  146. package/tests/agents/update/fs-tools/grep.test.mjs +279 -0
  147. package/tests/agents/update/fs-tools/read-file.test.mjs +553 -0
  148. package/tests/agents/update/user-review-document.test.mjs +48 -27
  149. package/tests/agents/utils/format-document-structure.test.mjs +5 -5
  150. package/tests/agents/utils/load-sources.test.mjs +4 -4
  151. package/tests/agents/utils/save-docs.test.mjs +1 -1
  152. package/tests/utils/conflict-detector.test.mjs +1 -1
  153. package/tests/utils/docs-finder-utils.test.mjs +8 -8
  154. package/types/document-schema.mjs +5 -6
  155. package/types/document-structure-schema.mjs +25 -13
  156. package/utils/conflict-detector.mjs +1 -1
  157. package/utils/constants/index.mjs +4 -4
  158. package/utils/docs-finder-utils.mjs +11 -11
  159. package/utils/markdown-checker.mjs +1 -1
@@ -1,326 +1,329 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { beforeEach, describe, expect, test } from "bun:test";
2
2
  import updateDocumentContent from "../../../../agents/update/document-tools/update-document-content.mjs";
3
3
 
4
4
  describe("update-document-content", () => {
5
- // INPUT VALIDATION TESTS
6
- test("should return error when originalContent is not provided", async () => {
7
- const result = await updateDocumentContent({ diffPatch: "valid patch" });
8
- expect(result.success).toBe(false);
9
- expect(result.error).toContain("originalContent");
10
- expect(result.message).toBe("Invalid input parameters");
5
+ let mockOptions;
6
+
7
+ beforeEach(() => {
8
+ mockOptions = {
9
+ context: {
10
+ userContext: {
11
+ currentContent: "",
12
+ },
13
+ },
14
+ };
11
15
  });
12
16
 
13
- test("should return error when originalContent is not a string", async () => {
14
- const result = await updateDocumentContent({ originalContent: 123, diffPatch: "valid patch" });
15
- expect(result.success).toBe(false);
16
- expect(result.error).toContain("originalContent");
17
- expect(result.message).toBe("Invalid input parameters");
18
- });
19
-
20
- test("should return error when originalContent is empty string", async () => {
21
- const result = await updateDocumentContent({ originalContent: "", diffPatch: "valid patch" });
22
- expect(result.success).toBe(false);
23
- expect(result.error).toContain("Original content is required");
24
- expect(result.message).toBe("Invalid input parameters");
25
- });
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
+ }
26
22
 
23
+ // INPUT VALIDATION TESTS
27
24
  test("should return error when diffPatch is not provided", async () => {
28
- const result = await updateDocumentContent({ originalContent: "original content" });
25
+ mockOptions.context.userContext.currentContent = "original content";
26
+ const result = await updateDocumentContent({}, mockOptions);
29
27
  expect(result.success).toBe(false);
30
- expect(result.error).toContain("diffPatch");
31
- expect(result.message).toBe("Invalid input parameters");
28
+ expect(result.error.message).toContain("diffPatch");
32
29
  });
33
30
 
34
31
  test("should return error when diffPatch is not a string", async () => {
35
- const result = await updateDocumentContent({
36
- originalContent: "original content",
37
- diffPatch: null,
38
- });
32
+ mockOptions.context.userContext.currentContent = "original content";
33
+ const result = await updateDocumentContent({ diffPatch: null }, mockOptions);
39
34
  expect(result.success).toBe(false);
40
- expect(result.error).toContain("diffPatch");
41
- expect(result.message).toBe("Invalid input parameters");
35
+ expect(result.error.message).toContain("diffPatch");
42
36
  });
43
37
 
44
38
  test("should return error when diffPatch is empty string", async () => {
45
- const result = await updateDocumentContent({
46
- originalContent: "original content",
47
- diffPatch: "",
48
- });
39
+ mockOptions.context.userContext.currentContent = "original content";
40
+ const result = await updateDocumentContent({ diffPatch: "" }, mockOptions);
49
41
  expect(result.success).toBe(false);
50
- expect(result.error).toContain("Diff patch is required");
51
- expect(result.message).toBe("Invalid input parameters");
42
+ expect(result.error.message).toContain("Diff patch is required");
52
43
  });
53
44
 
54
45
  // SUCCESSFUL PATCH APPLICATION TESTS
55
46
  test("should successfully apply simple diff patch", async () => {
56
- const originalContent = "line 1\nline 2\nline 3";
47
+ mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
57
48
  const diffPatch = "@@ -1,3 +1,3 @@\n line 1\n-line 2\n+updated line 2\n line 3";
58
49
 
59
- const result = await updateDocumentContent({ originalContent, diffPatch });
50
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
60
51
 
61
52
  expect(result.success).toBe(true);
62
- expect(result.updatedContent).toBe("line 1\nupdated line 2\nline 3");
63
- expect(result.message).toBe("Document content updated successfully");
53
+ expect(extractContent(result.updatedContent)).toBe("line 1\nupdated line 2\nline 3");
54
+ expect(result.message).toContain("Document content updated successfully");
64
55
  });
65
56
 
66
57
  test("should handle diff with multiple hunks", async () => {
67
- const originalContent = "line 1\nline 2\nline 3\nline 4\nline 5";
58
+ mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4\nline 5";
68
59
  const diffPatch =
69
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";
70
61
 
71
- const result = await updateDocumentContent({ originalContent, diffPatch });
62
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
72
63
 
73
64
  expect(result.success).toBe(true);
74
- expect(result.updatedContent).toBe("updated line 1\nline 2\nline 3\nline 4\nupdated line 5");
65
+ expect(extractContent(result.updatedContent)).toBe(
66
+ "updated line 1\nline 2\nline 3\nline 4\nupdated line 5",
67
+ );
75
68
  });
76
69
 
77
70
  test("should handle diff with additions only", async () => {
78
- const originalContent = "line 1\nline 2";
71
+ mockOptions.context.userContext.currentContent = "line 1\nline 2";
79
72
  const diffPatch = "@@ -2,0 +3,2 @@\n line 2\n+new line 3\n+new line 4";
80
73
 
81
- const result = await updateDocumentContent({ originalContent, diffPatch });
74
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
82
75
 
83
76
  expect(result.success).toBe(true);
84
- expect(result.updatedContent).toBe("line 1\nline 2\nnew line 3\nnew line 4");
77
+ expect(extractContent(result.updatedContent)).toBe("line 1\nline 2\nnew line 3\nnew line 4");
85
78
  });
86
79
 
87
80
  test("should handle diff with deletions only", async () => {
88
- const originalContent = "line 1\nline 2\nline 3\nline 4";
81
+ mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4";
89
82
  const diffPatch = "@@ -2,2 +2,0 @@\n line 1\n-line 2\n-line 3\n line 4";
90
83
 
91
- const result = await updateDocumentContent({ originalContent, diffPatch });
84
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
92
85
 
93
86
  expect(result.success).toBe(true);
94
- expect(result.updatedContent).toBe("line 1\nline 4");
87
+ expect(extractContent(result.updatedContent)).toBe("line 1\nline 4");
95
88
  });
96
89
 
97
90
  test("should handle diff with context lines", async () => {
98
- const originalContent = "line 1\nline 2\nline 3\nline 4\nline 5";
91
+ mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4\nline 5";
99
92
  const diffPatch =
100
93
  "@@ -2,3 +2,3 @@\n line 1\n line 2\n-line 3\n+updated line 3\n line 4\n line 5";
101
94
 
102
- const result = await updateDocumentContent({ originalContent, diffPatch });
95
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
103
96
 
104
97
  expect(result.success).toBe(true);
105
- expect(result.updatedContent).toBe("line 1\nline 2\nupdated line 3\nline 4\nline 5");
98
+ expect(extractContent(result.updatedContent)).toBe(
99
+ "line 1\nline 2\nupdated line 3\nline 4\nline 5",
100
+ );
106
101
  });
107
102
 
108
103
  // DIFF PATCH PARSING TESTS
109
104
  test("should return error for invalid diff format", async () => {
110
- const originalContent = "line 1\nline 2";
105
+ mockOptions.context.userContext.currentContent = "line 1\nline 2";
111
106
  const diffPatch = "invalid diff format";
112
107
 
113
- const result = await updateDocumentContent({ originalContent, diffPatch });
108
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
114
109
 
115
110
  expect(result).toEqual({
116
111
  success: false,
117
- error: "No valid hunks found in diff",
118
- message: "Invalid diff format: No valid hunks found or parsing failed",
112
+ error: { message: "No valid hunks found in diff" },
119
113
  });
120
114
  });
121
115
 
122
116
  test("should return error for empty diff", async () => {
123
- const originalContent = "line 1\nline 2";
117
+ mockOptions.context.userContext.currentContent = "line 1\nline 2";
124
118
  const diffPatch = "\n\n";
125
119
 
126
- const result = await updateDocumentContent({ originalContent, diffPatch });
120
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
127
121
 
128
122
  expect(result).toEqual({
129
123
  success: false,
130
- error: "No valid hunks found in diff",
131
- message: "Invalid diff format: No valid hunks found or parsing failed",
124
+ error: { message: "No valid hunks found in diff" },
132
125
  });
133
126
  });
134
127
 
135
128
  test("should handle malformed hunk headers gracefully", async () => {
136
- const originalContent = "line 1\nline 2";
129
+ mockOptions.context.userContext.currentContent = "line 1\nline 2";
137
130
  const diffPatch = "@@malformed header@@\n-line 1\n+updated line 1";
138
131
 
139
- const result = await updateDocumentContent({ originalContent, diffPatch });
132
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
140
133
 
141
134
  expect(result.success).toBe(false);
142
- expect(result.message).toBe("Invalid diff format: No valid hunks found or parsing failed");
135
+ expect(result.error.message).toContain("No valid hunks found");
143
136
  });
144
137
 
145
138
  // LINE NUMBER FIXING TESTS
146
139
  test("should fix line numbers when patch position is off", async () => {
147
- const originalContent = "prefix line\nline 1\nline 2\nline 3";
140
+ mockOptions.context.userContext.currentContent = "prefix line\nline 1\nline 2\nline 3";
148
141
  // This diff patch expects to find "line 1" at line 1, but it's actually at line 2
149
142
  const diffPatch = "@@ -1,2 +1,2 @@\n-line 1\n+updated line 1\n line 2";
150
143
 
151
- const result = await updateDocumentContent({ originalContent, diffPatch });
144
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
152
145
 
153
146
  expect(result.success).toBe(true);
154
- expect(result.updatedContent).toBe("prefix line\nupdated line 1\nline 2\nline 3");
147
+ expect(extractContent(result.updatedContent)).toBe(
148
+ "prefix line\nupdated line 1\nline 2\nline 3",
149
+ );
155
150
  });
156
151
 
157
152
  test("should use fuzzy matching when exact match fails", async () => {
158
- const originalContent = "similar line 1\nsimilar line 2\ndifferent content\nsimilar line 3";
153
+ mockOptions.context.userContext.currentContent =
154
+ "similar line 1\nsimilar line 2\ndifferent content\nsimilar line 3";
159
155
  // This patch refers to lines that are similar but not exactly matching
160
156
  const diffPatch = "@@ -10,2 +10,2 @@\n-similar line 1\n+updated line 1\n similar line 2";
161
157
 
162
- const result = await updateDocumentContent({ originalContent, diffPatch });
158
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
163
159
 
164
160
  expect(result.success).toBe(true);
165
- expect(result.updatedContent).toBe(
161
+ expect(extractContent(result.updatedContent)).toBe(
166
162
  "updated line 1\nsimilar line 2\ndifferent content\nsimilar line 3",
167
163
  );
168
164
  });
169
165
 
170
166
  test("should return error when no matching context found", async () => {
171
- const originalContent = "completely different content\nnothing matches";
167
+ mockOptions.context.userContext.currentContent =
168
+ "completely different content\nnothing matches";
172
169
  const diffPatch =
173
170
  "@@ -1,2 +1,2 @@\n-line that doesn't exist\n+updated line\n another nonexistent line";
174
171
 
175
- const result = await updateDocumentContent({ originalContent, diffPatch });
172
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
176
173
 
177
174
  expect(result.success).toBe(false);
178
- expect(result.error).toContain("Cannot find matching context");
179
- expect(result.message).toBe("Cannot fix diff line number issues");
175
+ expect(result.error.message).toContain("Cannot find matching context");
180
176
  });
181
177
 
182
178
  // COMPLEX DIFF SCENARIOS
183
179
  test("should handle diff with no context lines", async () => {
184
- const originalContent = "line 1\nline 2\nline 3";
180
+ mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
185
181
  const diffPatch = "@@ -2,1 +2,1 @@\n-line 2\n+updated line 2";
186
182
 
187
- const result = await updateDocumentContent({ originalContent, diffPatch });
183
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
188
184
 
189
185
  expect(result.success).toBe(true);
190
- expect(result.updatedContent).toBe("line 1\nupdated line 2\nline 3");
186
+ expect(extractContent(result.updatedContent)).toBe("line 1\nupdated line 2\nline 3");
191
187
  });
192
188
 
193
189
  test("should handle diff with single line count (implicit 1)", async () => {
194
- const originalContent = "line 1\nline 2\nline 3";
190
+ mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
195
191
  const diffPatch = "@@ -2 +2 @@\n-line 2\n+updated line 2";
196
192
 
197
- const result = await updateDocumentContent({ originalContent, diffPatch });
193
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
198
194
 
199
195
  expect(result.success).toBe(true);
200
- expect(result.updatedContent).toBe("line 1\nupdated line 2\nline 3");
196
+ expect(extractContent(result.updatedContent)).toBe("line 1\nupdated line 2\nline 3");
201
197
  });
202
198
 
203
199
  test("should handle multiple changes in single hunk", async () => {
204
- const originalContent = "line 1\nline 2\nline 3\nline 4\nline 5";
200
+ mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4\nline 5";
205
201
  const diffPatch =
206
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";
207
203
 
208
- const result = await updateDocumentContent({ originalContent, diffPatch });
204
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
209
205
 
210
206
  expect(result.success).toBe(true);
211
- expect(result.updatedContent).toBe(
207
+ expect(extractContent(result.updatedContent)).toBe(
212
208
  "line 1\nupdated line 2\nnew line\nupdated line 3\nline 4\nline 5",
213
209
  );
214
210
  });
215
211
 
216
212
  // EDGE CASES
217
213
  test("should handle empty lines in diff", async () => {
218
- const originalContent = "line 1\n\nline 3";
214
+ mockOptions.context.userContext.currentContent = "line 1\n\nline 3";
219
215
  const diffPatch = "@@ -1,3 +1,3 @@\n line 1\n \n-line 3\n+updated line 3";
220
216
 
221
- const result = await updateDocumentContent({ originalContent, diffPatch });
217
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
222
218
 
223
219
  expect(result.success).toBe(true);
224
- expect(result.updatedContent).toBe("line 1\n\nupdated line 3");
220
+ expect(extractContent(result.updatedContent)).toBe("line 1\n\nupdated line 3");
225
221
  });
226
222
 
227
223
  test("should handle diff with trailing newlines", async () => {
228
- const originalContent = "line 1\nline 2\n";
224
+ mockOptions.context.userContext.currentContent = "line 1\nline 2\n";
229
225
  const diffPatch = "@@ -1,2 +1,2 @@\n-line 1\n+updated line 1\n line 2";
230
226
 
231
- const result = await updateDocumentContent({ originalContent, diffPatch });
227
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
232
228
 
233
229
  expect(result.success).toBe(true);
234
- expect(result.updatedContent).toBe("updated line 1\nline 2\n");
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");
235
234
  });
236
235
 
237
236
  // REALISTIC DOCUMENTATION UPDATE SCENARIOS
238
237
  test("should handle updating code blocks", async () => {
239
- const originalContent =
238
+ mockOptions.context.userContext.currentContent =
240
239
  "# API Reference\n\n```javascript\nfunction oldFunction() {\n return 'old';\n}\n```\n\nDescription here.";
241
240
  const diffPatch =
242
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 ```";
243
242
 
244
- const result = await updateDocumentContent({ originalContent, diffPatch });
243
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
245
244
 
246
245
  expect(result.success).toBe(true);
247
- expect(result.updatedContent).toContain("function newFunction()");
248
- expect(result.updatedContent).toContain("return 'new';");
246
+ const content = extractContent(result.updatedContent);
247
+ expect(content).toContain("function newFunction()");
248
+ expect(content).toContain("return 'new';");
249
249
  });
250
250
 
251
251
  test("should handle adding new sections", async () => {
252
- const originalContent =
252
+ mockOptions.context.userContext.currentContent =
253
253
  "# Documentation\n\n## Section 1\n\nContent 1\n\n## Section 3\n\nContent 3";
254
254
  const diffPatch =
255
255
  "@@ -4,0 +5,3 @@\n Content 1\n \n+## Section 2\n+\n+Content 2\n+\n ## Section 3";
256
256
 
257
- const result = await updateDocumentContent({ originalContent, diffPatch });
257
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
258
258
 
259
259
  expect(result.success).toBe(true);
260
- expect(result.updatedContent).toContain("## Section 2");
261
- expect(result.updatedContent).toContain("Content 2");
260
+ const content = extractContent(result.updatedContent);
261
+ expect(content).toContain("## Section 2");
262
+ expect(content).toContain("Content 2");
262
263
  });
263
264
 
264
265
  test("should handle removing outdated content", async () => {
265
- const originalContent =
266
+ mockOptions.context.userContext.currentContent =
266
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.";
267
268
  const diffPatch =
268
269
  "@@ -5,4 +5,0 @@\n This is current.\n \n-## Deprecated Feature\n-\n-This is deprecated.\n-\n ## Another Feature";
269
270
 
270
- const result = await updateDocumentContent({ originalContent, diffPatch });
271
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
271
272
 
272
273
  expect(result.success).toBe(true);
273
- expect(result.updatedContent).not.toContain("Deprecated Feature");
274
- expect(result.updatedContent).toContain("Current Feature");
275
- expect(result.updatedContent).toContain("Another Feature");
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");
276
278
  });
277
279
 
278
280
  // ERROR SCENARIOS WITH REALISTIC CONTENT
279
281
  test("should handle conflicting patches gracefully", async () => {
280
- const originalContent = "line 1\nline 2\nline 3";
282
+ mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
281
283
  // This patch tries to modify content that doesn't match exactly
282
284
  const diffPatch =
283
285
  "@@ -1,3 +1,3 @@\n-different line 1\n-different line 2\n+updated line 1\n+updated line 2\n line 3";
284
286
 
285
- const result = await updateDocumentContent({ originalContent, diffPatch });
287
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
286
288
 
287
289
  expect(result.success).toBe(false);
288
- expect(result.error).toContain("Cannot find matching context");
290
+ expect(result.error.message).toContain("Cannot find matching context");
289
291
  });
290
292
 
291
293
  test("should handle patches with incorrect line counts", async () => {
292
- const originalContent = "line 1\nline 2\nline 3\nline 4";
294
+ mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4";
293
295
  // Incorrect line count in hunk header (says 5 lines but content has 4)
294
296
  const diffPatch = "@@ -1,5 +1,3 @@\n-line 1\n-line 2\n line 3\n line 4";
295
297
 
296
- const result = await updateDocumentContent({ originalContent, diffPatch });
298
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
297
299
 
298
300
  expect(result.success).toBe(true);
299
- expect(result.updatedContent).toBe("line 3\nline 4");
301
+ expect(extractContent(result.updatedContent)).toBe("line 3\nline 4");
300
302
  });
301
303
 
302
304
  // FUZZY MATCHING EDGE CASES
303
305
  test("should succeed fuzzy matching with high similarity", async () => {
304
- const originalContent =
306
+ mockOptions.context.userContext.currentContent =
305
307
  "function calculateTotal(items) {\n let total = 0;\n for (item of items) {\n total += item.price;\n }\n return total;\n}";
306
308
  // Patch has slight differences but should match with fuzzy matching
307
309
  const diffPatch =
308
310
  "@@ -2,2 +2,2 @@\n function calculateTotal(items) {\n- let total = 0;\n+ let sum = 0;\n for (item of items) {";
309
311
 
310
- const result = await updateDocumentContent({ originalContent, diffPatch });
312
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
311
313
 
312
314
  expect(result.success).toBe(true);
313
- expect(result.updatedContent).toContain("let sum = 0;");
315
+ expect(extractContent(result.updatedContent)).toContain("let sum = 0;");
314
316
  });
315
317
 
316
318
  test("should fail fuzzy matching with low similarity", async () => {
317
- const originalContent = "completely different content\nwith nothing similar\nat all";
319
+ mockOptions.context.userContext.currentContent =
320
+ "completely different content\nwith nothing similar\nat all";
318
321
  const diffPatch =
319
322
  "@@ -1,2 +1,2 @@\n-some totally different text\n+updated text\n that has no relation";
320
323
 
321
- const result = await updateDocumentContent({ originalContent, diffPatch });
324
+ const result = await updateDocumentContent({ diffPatch }, mockOptions);
322
325
 
323
326
  expect(result.success).toBe(false);
324
- expect(result.error).toContain("Cannot find matching context");
327
+ expect(result.error.message).toContain("Cannot find matching context");
325
328
  });
326
329
  });