@aigne/doc-smith 0.8.5 → 0.8.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 (126) hide show
  1. package/.aigne/doc-smith/output/structure-plan.json +1 -5
  2. package/CHANGELOG.md +25 -0
  3. package/README.md +3 -3
  4. package/agents/{chat.yaml → chat/index.yaml} +7 -7
  5. package/agents/generate/check-document-structure.yaml +30 -0
  6. package/agents/{check-structure-plan.mjs → generate/check-need-generate-structure.mjs} +21 -21
  7. package/agents/generate/generate-structure.yaml +58 -0
  8. package/agents/{docs-generator.yaml → generate/index.yaml} +15 -16
  9. package/agents/generate/refine-document-structure.yaml +12 -0
  10. package/agents/{input-generator.mjs → init/index.mjs} +34 -27
  11. package/agents/{manage-prefs.mjs → prefs/index.mjs} +16 -16
  12. package/agents/publish/index.yaml +17 -0
  13. package/agents/{publish-docs.mjs → publish/publish-docs.mjs} +15 -16
  14. package/agents/schema/{structure-plan-result.yaml → document-execution-structure.yaml} +3 -3
  15. package/agents/schema/document-structure.yaml +26 -0
  16. package/agents/{language-selector.mjs → translate/choose-language.mjs} +5 -5
  17. package/agents/{retranslate.yaml → translate/index.yaml} +17 -18
  18. package/agents/translate/translate-document.yaml +32 -0
  19. package/agents/{batch-translate.yaml → translate/translate-multilingual.yaml} +5 -5
  20. package/agents/update/batch-generate-document.yaml +19 -0
  21. package/agents/{check-detail.mjs → update/check-document.mjs} +16 -16
  22. package/agents/{detail-generator-and-translate.yaml → update/generate-and-translate-document.yaml} +23 -23
  23. package/agents/update/generate-document.yaml +50 -0
  24. package/agents/{detail-regenerator.yaml → update/index.yaml} +16 -17
  25. package/agents/{action-success.mjs → utils/action-success.mjs} +2 -2
  26. package/agents/{check-detail-result.mjs → utils/check-detail-result.mjs} +3 -3
  27. package/agents/{check-feedback-refiner.mjs → utils/check-feedback-refiner.mjs} +6 -6
  28. package/agents/{find-items-by-paths.mjs → utils/choose-docs.mjs} +25 -10
  29. package/agents/{docs-fs.yaml → utils/docs-fs-actor.yaml} +3 -1
  30. package/agents/utils/feedback-refiner.yaml +50 -0
  31. package/agents/{find-item-by-path.mjs → utils/find-item-by-path.mjs} +17 -7
  32. package/agents/{find-user-preferences-by-path.mjs → utils/find-user-preferences-by-path.mjs} +1 -1
  33. package/agents/utils/format-document-structure.mjs +25 -0
  34. package/agents/{load-sources.mjs → utils/load-sources.mjs} +41 -28
  35. package/agents/{save-docs.mjs → utils/save-docs.mjs} +16 -16
  36. package/agents/{save-single-doc.mjs → utils/save-single-doc.mjs} +2 -2
  37. package/agents/{transform-detail-datasources.mjs → utils/transform-detail-datasources.mjs} +1 -1
  38. package/aigne.yaml +35 -35
  39. package/docs/cli-reference.md +1 -1
  40. package/docs/features-generate-documentation.md +1 -1
  41. package/docs/features-update-and-refine.md +2 -2
  42. package/docs-mcp/analyze-docs-relevance.yaml +10 -10
  43. package/docs-mcp/docs-search.yaml +5 -3
  44. package/package.json +10 -8
  45. package/prompts/{document → detail/custom}/custom-code-block.md +6 -6
  46. package/prompts/detail/custom/custom-components.md +172 -0
  47. package/prompts/{document → detail}/d2-chart/rules.md +95 -1
  48. package/prompts/{document → detail}/detail-example.md +80 -61
  49. package/prompts/{document/detail-generator.md → detail/document-rules.md} +4 -8
  50. package/prompts/{content-detail-generator.md → detail/generate-document.md} +48 -25
  51. package/prompts/{check-structure-planning-result.md → structure/check-document-structure.md} +23 -17
  52. package/prompts/{document/structure-planning.md → structure/document-rules.md} +0 -2
  53. package/prompts/{structure-planning.md → structure/generate-structure.md} +51 -30
  54. package/prompts/{document → structure}/structure-example.md +2 -2
  55. package/prompts/{document → structure}/structure-getting-started.md +2 -2
  56. package/prompts/translate/glossary.md +6 -0
  57. package/prompts/{translator.md → translate/translate-document.md} +29 -10
  58. package/prompts/{feedback-refiner.md → utils/feedback-refiner.md} +8 -8
  59. package/tests/agents/chat/chat.test.mjs +46 -0
  60. package/tests/agents/generate/check-document-structure.test.mjs +51 -0
  61. package/tests/agents/generate/check-need-generate-structure.test.mjs +292 -0
  62. package/tests/agents/generate/generate-structure.test.mjs +51 -0
  63. package/tests/{input-generator.test.mjs → agents/init/init.test.mjs} +19 -17
  64. package/tests/agents/prefs/prefs.test.mjs +431 -0
  65. package/tests/agents/publish/publish-docs.test.mjs +642 -0
  66. package/tests/agents/translate/choose-language.test.mjs +311 -0
  67. package/tests/agents/translate/translate-document.test.mjs +51 -0
  68. package/tests/agents/update/check-document.test.mjs +523 -0
  69. package/tests/agents/update/generate-document.test.mjs +51 -0
  70. package/tests/agents/utils/action-success.test.mjs +54 -0
  71. package/tests/{check-detail-result.test.mjs → agents/utils/check-detail-result.test.mjs} +98 -98
  72. package/tests/agents/utils/check-feedback-refiner.test.mjs +478 -0
  73. package/tests/agents/utils/choose-docs.test.mjs +417 -0
  74. package/tests/agents/utils/exit.test.mjs +70 -0
  75. package/tests/agents/utils/feedback-refiner.test.mjs +51 -0
  76. package/tests/agents/utils/find-item-by-path.test.mjs +526 -0
  77. package/tests/agents/utils/find-user-preferences-by-path.test.mjs +382 -0
  78. package/tests/agents/utils/format-document-structure.test.mjs +264 -0
  79. package/tests/agents/utils/fs.test.mjs +267 -0
  80. package/tests/{load-sources.test.mjs → agents/utils/load-sources.test.mjs} +153 -25
  81. package/tests/{save-docs.test.mjs → agents/utils/save-docs.test.mjs} +11 -5
  82. package/tests/agents/utils/save-output.test.mjs +315 -0
  83. package/tests/agents/utils/save-single-doc.test.mjs +364 -0
  84. package/tests/agents/utils/transform-detail-datasources.test.mjs +363 -0
  85. package/tests/utils/auth-utils.test.mjs +358 -0
  86. package/tests/utils/blocklet.test.mjs +334 -0
  87. package/tests/{conflict-resolution.test.mjs → utils/conflict-detector.test.mjs} +3 -3
  88. package/tests/utils/constants.test.mjs +295 -0
  89. package/tests/utils/d2-utils.test.mjs +423 -0
  90. package/tests/utils/deploy.test.mjs +365 -0
  91. package/tests/utils/docs-finder-utils.test.mjs +625 -0
  92. package/tests/utils/file-utils.test.mjs +213 -0
  93. package/tests/{kroki-utils.test.mjs → utils/kroki-utils.test.mjs} +2 -2
  94. package/tests/utils/load-config.test.mjs +141 -0
  95. package/tests/{mermaid-validation.test.mjs → utils/mermaid-validator.test.mjs} +2 -2
  96. package/tests/utils/mock-chat-model.mjs +12 -0
  97. package/tests/{preferences-utils.test.mjs → utils/preferences-utils.test.mjs} +1 -1
  98. package/tests/{save-value-to-config.test.mjs → utils/save-value-to-config.test.mjs} +61 -4
  99. package/tests/utils/utils.test.mjs +939 -0
  100. package/utils/auth-utils.mjs +1 -1
  101. package/utils/conflict-detector.mjs +1 -1
  102. package/utils/constants.mjs +5 -3
  103. package/utils/d2-utils.mjs +194 -0
  104. package/utils/deploy.mjs +3 -3
  105. package/utils/docs-finder-utils.mjs +26 -26
  106. package/utils/icon-map.mjs +26 -0
  107. package/{agents → utils}/load-config.mjs +2 -18
  108. package/utils/markdown-checker.mjs +5 -5
  109. package/agents/batch-docs-detail-generator.yaml +0 -19
  110. package/agents/check-structure-planning-result.yaml +0 -30
  111. package/agents/content-detail-generator.yaml +0 -50
  112. package/agents/feedback-refiner.yaml +0 -52
  113. package/agents/format-structure-plan.mjs +0 -25
  114. package/agents/reflective-structure-planner.yaml +0 -12
  115. package/agents/schema/structure-plan.yaml +0 -26
  116. package/agents/structure-planning.yaml +0 -58
  117. package/agents/team-publish-docs.yaml +0 -18
  118. package/agents/translate.yaml +0 -31
  119. package/prompts/document/custom-components.md +0 -104
  120. package/tests/README.md +0 -93
  121. package/tests/utils.test.mjs +0 -2067
  122. /package/agents/{exit.mjs → utils/exit.mjs} +0 -0
  123. /package/agents/{fs.mjs → utils/fs.mjs} +0 -0
  124. /package/agents/{save-output.mjs → utils/save-output.mjs} +0 -0
  125. /package/prompts/{document → detail}/d2-chart/official-examples.md +0 -0
  126. /package/prompts/{document → detail}/jsx/rules.md +0 -0
@@ -0,0 +1,292 @@
1
+ import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from "bun:test";
2
+ import * as fsPromises from "node:fs/promises";
3
+ import checkNeedGenerateStructure from "../../../agents/generate/check-need-generate-structure.mjs";
4
+
5
+ import * as preferencesUtils from "../../../utils/preferences-utils.mjs";
6
+ import * as utils from "../../../utils/utils.mjs";
7
+
8
+ describe("check-need-generate-structure", () => {
9
+ let mockOptions;
10
+ let originalDocumentStructure;
11
+
12
+ // Spies for external dependencies
13
+ let accessSpy;
14
+
15
+ // Spies for internal utils
16
+ let getActiveRulesForScopeSpy;
17
+ let getCurrentGitHeadSpy;
18
+ let hasFileChangesBetweenCommitsSpy;
19
+ let getProjectInfoSpy;
20
+ let loadConfigFromFileSpy;
21
+ let saveValueToConfigSpy;
22
+
23
+ beforeEach(() => {
24
+ // Reset all mocks
25
+ mock.restore();
26
+
27
+ originalDocumentStructure = [
28
+ { path: "/getting-started", title: "Getting Started" },
29
+ { path: "/api", title: "API Reference" },
30
+ ];
31
+
32
+ mockOptions = {
33
+ prompts: {
34
+ input: mock(async () => ""),
35
+ },
36
+ context: {
37
+ agents: { refineDocumentStructure: {} },
38
+ invoke: mock(async () => ({
39
+ documentStructure: originalDocumentStructure,
40
+ projectName: "Test Project",
41
+ projectDesc: "Test Description",
42
+ })),
43
+ },
44
+ };
45
+
46
+ // Set up spies for internal utils
47
+ getActiveRulesForScopeSpy = spyOn(preferencesUtils, "getActiveRulesForScope").mockReturnValue(
48
+ [],
49
+ );
50
+ getCurrentGitHeadSpy = spyOn(utils, "getCurrentGitHead").mockReturnValue(null);
51
+ hasFileChangesBetweenCommitsSpy = spyOn(utils, "hasFileChangesBetweenCommits").mockReturnValue(
52
+ false,
53
+ );
54
+ getProjectInfoSpy = spyOn(utils, "getProjectInfo").mockResolvedValue({
55
+ name: "Test Project",
56
+ description: "Test Description",
57
+ fromGitHub: false,
58
+ });
59
+ loadConfigFromFileSpy = spyOn(utils, "loadConfigFromFile").mockResolvedValue({});
60
+ saveValueToConfigSpy = spyOn(utils, "saveValueToConfig").mockResolvedValue();
61
+
62
+ // Set up spy for external dependencies
63
+ accessSpy = spyOn(fsPromises, "access").mockImplementation(() =>
64
+ Promise.reject(new Error("File not found")),
65
+ );
66
+
67
+ // Clear prompts mock call history
68
+ mockOptions.prompts.input.mockClear();
69
+ mockOptions.context.invoke.mockClear();
70
+ });
71
+
72
+ afterEach(() => {
73
+ // Restore all spies
74
+ accessSpy?.mockRestore();
75
+ getActiveRulesForScopeSpy?.mockRestore();
76
+ getCurrentGitHeadSpy?.mockRestore();
77
+ hasFileChangesBetweenCommitsSpy?.mockRestore();
78
+ getProjectInfoSpy?.mockRestore();
79
+ loadConfigFromFileSpy?.mockRestore();
80
+ saveValueToConfigSpy?.mockRestore();
81
+ });
82
+
83
+ test("should return original document structure when no regeneration needed", async () => {
84
+ // Test when no feedback and no sidebar file exists (default mock behavior)
85
+ const result = await checkNeedGenerateStructure(
86
+ { originalDocumentStructure, docsDir: "./docs" },
87
+ mockOptions,
88
+ );
89
+
90
+ expect(result).toBeDefined();
91
+ expect(result.documentStructure).toEqual(originalDocumentStructure);
92
+ expect(mockOptions.context.invoke).not.toHaveBeenCalled();
93
+ });
94
+
95
+ test("should prompt for user feedback when originalDocumentStructure exists", async () => {
96
+ const userFeedback = "Need more API documentation";
97
+ mockOptions.prompts.input.mockImplementation(async () => userFeedback);
98
+
99
+ await checkNeedGenerateStructure({ originalDocumentStructure, docsDir: "./docs" }, mockOptions);
100
+
101
+ expect(mockOptions.prompts.input).toHaveBeenCalledWith({
102
+ message: "How can we improve the documentation structure? (press Enter to skip):",
103
+ });
104
+ expect(mockOptions.context.invoke).toHaveBeenCalled();
105
+ });
106
+
107
+ test("should skip prompting if feedback is already provided", async () => {
108
+ const providedFeedback = "Already provided feedback";
109
+
110
+ await checkNeedGenerateStructure(
111
+ { originalDocumentStructure, feedback: providedFeedback, docsDir: "./docs" },
112
+ mockOptions,
113
+ );
114
+
115
+ expect(mockOptions.prompts.input).not.toHaveBeenCalled();
116
+ expect(mockOptions.context.invoke).toHaveBeenCalled();
117
+ });
118
+
119
+ test("should handle empty user feedback input", async () => {
120
+ mockOptions.prompts.input.mockImplementation(async () => " ");
121
+ // Default mock behavior: no sidebar file exists
122
+
123
+ const result = await checkNeedGenerateStructure(
124
+ { originalDocumentStructure, docsDir: "./docs" },
125
+ mockOptions,
126
+ );
127
+
128
+ expect(result.documentStructure).toEqual(originalDocumentStructure);
129
+ expect(mockOptions.context.invoke).not.toHaveBeenCalled();
130
+ });
131
+
132
+ test("should regenerate when _sidebar.md exists", async () => {
133
+ accessSpy.mockImplementation(() => Promise.resolve());
134
+
135
+ await checkNeedGenerateStructure({ originalDocumentStructure, docsDir: "./docs" }, mockOptions);
136
+
137
+ expect(mockOptions.context.invoke).toHaveBeenCalled();
138
+ });
139
+
140
+ test("should not regenerate when _sidebar.md does not exist", async () => {
141
+ // Default mock behavior: file access fails
142
+
143
+ const result = await checkNeedGenerateStructure(
144
+ { originalDocumentStructure, docsDir: "./docs" },
145
+ mockOptions,
146
+ );
147
+
148
+ expect(result.documentStructure).toEqual(originalDocumentStructure);
149
+ expect(mockOptions.context.invoke).not.toHaveBeenCalled();
150
+ });
151
+
152
+ test("should check git changes when lastGitHead is provided", async () => {
153
+ getCurrentGitHeadSpy.mockImplementation(() => "def456");
154
+ hasFileChangesBetweenCommitsSpy.mockImplementation(() => true);
155
+
156
+ await checkNeedGenerateStructure(
157
+ { originalDocumentStructure, lastGitHead: "abc123", docsDir: "./docs" },
158
+ mockOptions,
159
+ );
160
+
161
+ expect(hasFileChangesBetweenCommitsSpy).toHaveBeenCalledWith("abc123", "def456");
162
+ expect(mockOptions.context.invoke).toHaveBeenCalled();
163
+ });
164
+
165
+ test("should not regenerate when git head is same", async () => {
166
+ getCurrentGitHeadSpy.mockImplementation(() => "abc123");
167
+
168
+ const result = await checkNeedGenerateStructure(
169
+ { originalDocumentStructure, lastGitHead: "abc123", docsDir: "./docs" },
170
+ mockOptions,
171
+ );
172
+
173
+ expect(result.documentStructure).toEqual(originalDocumentStructure);
174
+ expect(mockOptions.context.invoke).not.toHaveBeenCalled();
175
+ });
176
+
177
+ test("should force regenerate when forceRegenerate is true", async () => {
178
+ await checkNeedGenerateStructure(
179
+ { originalDocumentStructure, forceRegenerate: true, docsDir: "./docs" },
180
+ mockOptions,
181
+ );
182
+
183
+ expect(mockOptions.context.invoke).toHaveBeenCalled();
184
+ });
185
+
186
+ test("should include user preferences", async () => {
187
+ const mockRules = [{ rule: "Structure rule 1" }];
188
+ getActiveRulesForScopeSpy.mockImplementation(() => mockRules);
189
+
190
+ await checkNeedGenerateStructure(
191
+ { originalDocumentStructure, feedback: "test", docsDir: "./docs" },
192
+ mockOptions,
193
+ );
194
+
195
+ expect(getActiveRulesForScopeSpy).toHaveBeenCalledWith("structure", []);
196
+ expect(mockOptions.context.invoke).toHaveBeenCalled();
197
+ });
198
+
199
+ test("should save project info when appropriate", async () => {
200
+ mockOptions.context.invoke.mockImplementation(async () => ({
201
+ documentStructure: originalDocumentStructure,
202
+ projectName: "New Project Name",
203
+ projectDesc: "New Description",
204
+ }));
205
+
206
+ const result = await checkNeedGenerateStructure(
207
+ { originalDocumentStructure, feedback: "test", docsDir: "./docs" },
208
+ mockOptions,
209
+ );
210
+
211
+ expect(saveValueToConfigSpy).toHaveBeenCalledWith("projectName", "New Project Name");
212
+ expect(result.projectInfoMessage).toContain("New Project Name");
213
+ });
214
+
215
+ test("should handle project info save errors", async () => {
216
+ loadConfigFromFileSpy.mockImplementation(async () => {
217
+ throw new Error("Config load failed");
218
+ });
219
+ const consoleSpy = spyOn(console, "warn").mockImplementation(() => {});
220
+
221
+ mockOptions.context.invoke.mockImplementation(async () => ({
222
+ documentStructure: originalDocumentStructure,
223
+ projectName: "New Project",
224
+ projectDesc: "New Description",
225
+ }));
226
+
227
+ const result = await checkNeedGenerateStructure(
228
+ { originalDocumentStructure, feedback: "test", docsDir: "./docs" },
229
+ mockOptions,
230
+ );
231
+
232
+ await new Promise((resolve) => setTimeout(resolve, 10));
233
+
234
+ expect(result).toBeDefined();
235
+ expect(consoleSpy).toHaveBeenCalled();
236
+ });
237
+
238
+ test("should return correct structure when no originalDocumentStructure provided", async () => {
239
+ const newDocumentStructure = [{ path: "/new", title: "New Section" }];
240
+
241
+ mockOptions.context.invoke.mockImplementation(async () => ({
242
+ documentStructure: newDocumentStructure,
243
+ }));
244
+
245
+ const result = await checkNeedGenerateStructure({ docsDir: "./docs" }, mockOptions);
246
+
247
+ expect(result.documentStructure).toEqual(newDocumentStructure);
248
+ expect(result.originalDocumentStructure).toEqual(newDocumentStructure);
249
+ });
250
+
251
+ test("should clear feedback in result", async () => {
252
+ const result = await checkNeedGenerateStructure(
253
+ { originalDocumentStructure, feedback: "some feedback", docsDir: "./docs" },
254
+ mockOptions,
255
+ );
256
+
257
+ expect(result.feedback).toBe("");
258
+ });
259
+
260
+ test("should preserve documentStructureFeedback", async () => {
261
+ const feedback = "user submitted feedback";
262
+
263
+ const result = await checkNeedGenerateStructure(
264
+ { originalDocumentStructure, feedback, docsDir: "./docs" },
265
+ mockOptions,
266
+ );
267
+
268
+ expect(result.documentStructureFeedback).toBe(feedback);
269
+ });
270
+
271
+ test("should pass through additional parameters", async () => {
272
+ const additionalParams = {
273
+ customParam1: "value1",
274
+ customParam2: "value2",
275
+ };
276
+
277
+ await checkNeedGenerateStructure(
278
+ {
279
+ originalDocumentStructure,
280
+ feedback: "test",
281
+ docsDir: "./docs",
282
+ ...additionalParams,
283
+ },
284
+ mockOptions,
285
+ );
286
+
287
+ expect(mockOptions.context.invoke).toHaveBeenCalledWith(
288
+ mockOptions.context.agents.refineDocumentStructure,
289
+ expect.objectContaining(additionalParams),
290
+ );
291
+ });
292
+ });
@@ -0,0 +1,51 @@
1
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
2
+ import { join } from "node:path";
3
+ import { AIAgent } from "@aigne/core";
4
+ import { loadAgent } from "@aigne/core/loader/index.js";
5
+ import { loadModel } from "../../utils/mock-chat-model.mjs";
6
+
7
+ describe("generateStructure Agent", () => {
8
+ beforeAll(() => {
9
+ process.env.AIGNE_OBSERVABILITY_DISABLED = "true";
10
+ });
11
+
12
+ afterAll(() => {
13
+ delete process.env.AIGNE_OBSERVABILITY_DISABLED;
14
+ });
15
+ test("should load agent correctly with proper configuration", async () => {
16
+ const agent = await loadAgent(
17
+ join(import.meta.dirname, "../../../agents/generate/generate-structure.yaml"),
18
+ {
19
+ model: loadModel,
20
+ },
21
+ );
22
+
23
+ expect(agent).toBeDefined();
24
+
25
+ // Verify agent exists and is correct type
26
+ expect(agent).toBeDefined();
27
+ expect(agent).toBeInstanceOf(AIAgent);
28
+ expect(agent.name).toBe("generateStructure");
29
+ });
30
+
31
+ test("should have instructions loaded from file", async () => {
32
+ const agent = await loadAgent(
33
+ join(import.meta.dirname, "../../../agents/generate/generate-structure.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
+ });
@@ -3,7 +3,7 @@ import { promises as fs } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import { parse as parseYAML } from "yaml";
6
- import init, { generateYAML } from "../agents/input-generator.mjs";
6
+ import init, { generateYAML } from "../../../agents/init/index.mjs";
7
7
 
8
8
  describe("generateYAML", () => {
9
9
  // Helper function to parse YAML and verify it's valid
@@ -1013,7 +1013,7 @@ describe("init", () => {
1013
1013
  );
1014
1014
 
1015
1015
  // Check that function completed successfully
1016
- expect(result).toEqual({});
1016
+ expect(result).toBeDefined();
1017
1017
 
1018
1018
  // Check that config file was created
1019
1019
  const configPath = join(tempDir, "config.yaml");
@@ -1068,7 +1068,7 @@ describe("init", () => {
1068
1068
  options,
1069
1069
  );
1070
1070
 
1071
- expect(result).toEqual({});
1071
+ expect(result).toBeDefined();
1072
1072
 
1073
1073
  // Verify the generated config
1074
1074
  const configPath = join(tempDir, "test-config.yaml");
@@ -1113,7 +1113,7 @@ describe("init", () => {
1113
1113
  options,
1114
1114
  );
1115
1115
 
1116
- expect(result).toEqual({});
1116
+ expect(result).toBeDefined();
1117
1117
 
1118
1118
  const configPath = join(tempDir, "simple-config.yaml");
1119
1119
  const configContent = await fs.readFile(configPath, "utf8");
@@ -1169,7 +1169,7 @@ describe("init", () => {
1169
1169
  options,
1170
1170
  );
1171
1171
 
1172
- expect(result).toEqual({});
1172
+ expect(result).toBeDefined();
1173
1173
 
1174
1174
  const configPath = join(tempDir, "config.yaml");
1175
1175
  const configContent = await fs.readFile(configPath, "utf8");
@@ -1214,7 +1214,7 @@ describe("init", () => {
1214
1214
  options,
1215
1215
  );
1216
1216
 
1217
- expect(result).toEqual({});
1217
+ expect(result).toBeDefined();
1218
1218
 
1219
1219
  const configPath = join(tempDir, "config.yaml");
1220
1220
  const configContent = await fs.readFile(configPath, "utf8");
@@ -1251,7 +1251,7 @@ describe("init", () => {
1251
1251
  options,
1252
1252
  );
1253
1253
 
1254
- expect(result).toEqual({});
1254
+ expect(result).toBeDefined();
1255
1255
 
1256
1256
  // Config should remain unchanged
1257
1257
  const configContent = await fs.readFile(configPath, "utf8");
@@ -1283,7 +1283,7 @@ describe("init", () => {
1283
1283
  options,
1284
1284
  );
1285
1285
 
1286
- expect(result).toEqual({});
1286
+ expect(result).toBeDefined();
1287
1287
 
1288
1288
  // Config should be generated since original was empty
1289
1289
  const configContent = await fs.readFile(configPath, "utf8");
@@ -1307,7 +1307,9 @@ describe("init", () => {
1307
1307
  if (options.message.includes("[1/8]") && options.validate) {
1308
1308
  // Test the validation function directly
1309
1309
  const validationResult = options.validate([]);
1310
- expect(validationResult).toBe("Please select at least one purpose.");
1310
+ expect(validationResult).toBe(
1311
+ "Please choose at least one goal for your documentation.",
1312
+ );
1311
1313
  validateCalled = true;
1312
1314
  // Return valid result after testing validation
1313
1315
  return Promise.resolve(["getStarted"]);
@@ -1326,7 +1328,7 @@ describe("init", () => {
1326
1328
  options,
1327
1329
  );
1328
1330
 
1329
- expect(result).toEqual({});
1331
+ expect(result).toBeDefined();
1330
1332
  expect(validateCalled).toBe(true);
1331
1333
  } finally {
1332
1334
  await cleanupTempDir(tempDir);
@@ -1346,7 +1348,7 @@ describe("init", () => {
1346
1348
  if (options.message.includes("[2/8]") && options.validate) {
1347
1349
  // Test the validation function for target audience
1348
1350
  const validationResult = options.validate([]);
1349
- expect(validationResult).toBe("Please select at least one audience.");
1351
+ expect(validationResult).toBe("Please choose at least one audience.");
1350
1352
  audienceValidateCalled = true;
1351
1353
  return Promise.resolve(["developers"]); // Valid result after testing
1352
1354
  }
@@ -1364,7 +1366,7 @@ describe("init", () => {
1364
1366
  options,
1365
1367
  );
1366
1368
 
1367
- expect(result).toEqual({});
1369
+ expect(result).toBeDefined();
1368
1370
  expect(audienceValidateCalled).toBe(true);
1369
1371
  } finally {
1370
1372
  await cleanupTempDir(tempDir);
@@ -1385,11 +1387,11 @@ describe("init", () => {
1385
1387
  if (options.message.includes("Which is most important?") && options.validate) {
1386
1388
  // Test validation for empty selection
1387
1389
  let validationResult = options.validate([]);
1388
- expect(validationResult).toBe("Please select at least one priority.");
1390
+ expect(validationResult).toBe("Please choose at least one priority.");
1389
1391
 
1390
1392
  // Test validation for too many selections
1391
1393
  validationResult = options.validate(["getStarted", "completeTasks", "findAnswers"]);
1392
- expect(validationResult).toBe("Please select maximum 2 priorities.");
1394
+ expect(validationResult).toBe("Please choose maximum 2 priorities.");
1393
1395
 
1394
1396
  // Test validation for valid selection
1395
1397
  validationResult = options.validate(["getStarted", "completeTasks"]);
@@ -1412,7 +1414,7 @@ describe("init", () => {
1412
1414
  options,
1413
1415
  );
1414
1416
 
1415
- expect(result).toEqual({});
1417
+ expect(result).toBeDefined();
1416
1418
  expect(priorityValidateCalled).toBe(true);
1417
1419
  } finally {
1418
1420
  await cleanupTempDir(tempDir);
@@ -1479,7 +1481,7 @@ describe("init", () => {
1479
1481
  options,
1480
1482
  );
1481
1483
 
1482
- expect(result).toEqual({});
1484
+ expect(result).toBeDefined();
1483
1485
 
1484
1486
  const configPath = join(tempDir, "config.yaml");
1485
1487
  const configContent = await fs.readFile(configPath, "utf8");
@@ -1524,7 +1526,7 @@ describe("init", () => {
1524
1526
  options,
1525
1527
  );
1526
1528
 
1527
- expect(result).toEqual({});
1529
+ expect(result).toBeDefined();
1528
1530
  } finally {
1529
1531
  await cleanupTempDir(tempDir);
1530
1532
  }