@aigne/doc-smith 0.8.6 → 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.
- package/.aigne/doc-smith/output/structure-plan.json +1 -5
- package/CHANGELOG.md +7 -0
- package/README.md +3 -3
- package/agents/{chat.yaml → chat/index.yaml} +7 -7
- package/agents/generate/check-document-structure.yaml +30 -0
- package/agents/{check-structure-plan.mjs → generate/check-need-generate-structure.mjs} +20 -20
- package/agents/{structure-planning.yaml → generate/generate-structure.yaml} +6 -6
- package/agents/{docs-generator.yaml → generate/index.yaml} +11 -12
- package/agents/generate/refine-document-structure.yaml +12 -0
- package/agents/{input-generator.mjs → init/index.mjs} +12 -5
- package/agents/{manage-prefs.mjs → prefs/index.mjs} +1 -1
- package/agents/{team-publish-docs.yaml → publish/index.yaml} +1 -2
- package/agents/{publish-docs.mjs → publish/publish-docs.mjs} +6 -5
- package/agents/schema/{structure-plan-result.yaml → document-execution-structure.yaml} +3 -3
- package/agents/schema/document-structure.yaml +26 -0
- package/agents/{language-selector.mjs → translate/choose-language.mjs} +5 -5
- package/agents/{retranslate.yaml → translate/index.yaml} +11 -12
- package/agents/{translate.yaml → translate/translate-document.yaml} +3 -2
- package/agents/{batch-translate.yaml → translate/translate-multilingual.yaml} +5 -5
- package/agents/update/batch-generate-document.yaml +19 -0
- package/agents/{check-detail.mjs → update/check-document.mjs} +16 -16
- package/agents/{detail-generator-and-translate.yaml → update/generate-and-translate-document.yaml} +23 -23
- package/agents/update/generate-document.yaml +50 -0
- package/agents/{detail-regenerator.yaml → update/index.yaml} +10 -11
- package/agents/{action-success.mjs → utils/action-success.mjs} +1 -1
- package/agents/{check-detail-result.mjs → utils/check-detail-result.mjs} +3 -3
- package/agents/{check-feedback-refiner.mjs → utils/check-feedback-refiner.mjs} +6 -6
- package/agents/{find-items-by-paths.mjs → utils/choose-docs.mjs} +24 -9
- package/agents/{docs-fs.yaml → utils/docs-fs-actor.yaml} +3 -1
- package/agents/{feedback-refiner.yaml → utils/feedback-refiner.yaml} +2 -4
- package/agents/{find-item-by-path.mjs → utils/find-item-by-path.mjs} +16 -6
- package/agents/{find-user-preferences-by-path.mjs → utils/find-user-preferences-by-path.mjs} +1 -1
- package/agents/utils/format-document-structure.mjs +25 -0
- package/agents/{load-sources.mjs → utils/load-sources.mjs} +41 -28
- package/agents/{save-docs.mjs → utils/save-docs.mjs} +16 -16
- package/agents/{save-single-doc.mjs → utils/save-single-doc.mjs} +2 -2
- package/agents/{transform-detail-datasources.mjs → utils/transform-detail-datasources.mjs} +1 -1
- package/aigne.yaml +35 -35
- package/docs-mcp/analyze-docs-relevance.yaml +10 -10
- package/docs-mcp/docs-search.yaml +5 -3
- package/package.json +10 -8
- package/prompts/{document → detail/custom}/custom-code-block.md +6 -6
- package/prompts/detail/custom/custom-components.md +172 -0
- package/prompts/{document → detail}/d2-chart/rules.md +95 -1
- package/prompts/{document → detail}/detail-example.md +80 -61
- package/prompts/{document/detail-generator.md → detail/document-rules.md} +4 -8
- package/prompts/{content-detail-generator.md → detail/generate-document.md} +48 -25
- package/prompts/{check-structure-planning-result.md → structure/check-document-structure.md} +23 -17
- package/prompts/{document/structure-planning.md → structure/document-rules.md} +0 -2
- package/prompts/{structure-planning.md → structure/generate-structure.md} +51 -30
- package/prompts/{document → structure}/structure-example.md +2 -2
- package/prompts/{document → structure}/structure-getting-started.md +2 -2
- package/prompts/translate/glossary.md +6 -0
- package/prompts/{translator.md → translate/translate-document.md} +29 -10
- package/prompts/{feedback-refiner.md → utils/feedback-refiner.md} +8 -8
- package/tests/agents/chat/chat.test.mjs +46 -0
- package/tests/agents/generate/check-document-structure.test.mjs +51 -0
- package/tests/agents/generate/check-need-generate-structure.test.mjs +292 -0
- package/tests/agents/generate/generate-structure.test.mjs +51 -0
- package/tests/{input-generator.test.mjs → agents/init/init.test.mjs} +13 -13
- package/tests/agents/prefs/prefs.test.mjs +431 -0
- package/tests/agents/publish/publish-docs.test.mjs +642 -0
- package/tests/agents/translate/choose-language.test.mjs +311 -0
- package/tests/agents/translate/translate-document.test.mjs +51 -0
- package/tests/agents/update/check-document.test.mjs +523 -0
- package/tests/agents/update/generate-document.test.mjs +51 -0
- package/tests/agents/utils/action-success.test.mjs +54 -0
- package/tests/{check-detail-result.test.mjs → agents/utils/check-detail-result.test.mjs} +98 -98
- package/tests/agents/utils/check-feedback-refiner.test.mjs +478 -0
- package/tests/agents/utils/choose-docs.test.mjs +417 -0
- package/tests/agents/utils/exit.test.mjs +70 -0
- package/tests/agents/utils/feedback-refiner.test.mjs +51 -0
- package/tests/agents/utils/find-item-by-path.test.mjs +526 -0
- package/tests/agents/utils/find-user-preferences-by-path.test.mjs +382 -0
- package/tests/agents/utils/format-document-structure.test.mjs +264 -0
- package/tests/agents/utils/fs.test.mjs +267 -0
- package/tests/{load-sources.test.mjs → agents/utils/load-sources.test.mjs} +153 -25
- package/tests/{save-docs.test.mjs → agents/utils/save-docs.test.mjs} +11 -5
- package/tests/agents/utils/save-output.test.mjs +315 -0
- package/tests/agents/utils/save-single-doc.test.mjs +364 -0
- package/tests/agents/utils/transform-detail-datasources.test.mjs +363 -0
- package/tests/utils/auth-utils.test.mjs +358 -0
- package/tests/utils/blocklet.test.mjs +334 -0
- package/tests/{conflict-resolution.test.mjs → utils/conflict-detector.test.mjs} +3 -3
- package/tests/utils/constants.test.mjs +295 -0
- package/tests/utils/d2-utils.test.mjs +423 -0
- package/tests/{deploy.test.mjs → utils/deploy.test.mjs} +25 -36
- package/tests/utils/docs-finder-utils.test.mjs +625 -0
- package/tests/utils/file-utils.test.mjs +213 -0
- package/tests/{kroki-utils.test.mjs → utils/kroki-utils.test.mjs} +2 -2
- package/tests/utils/load-config.test.mjs +141 -0
- package/tests/{mermaid-validation.test.mjs → utils/mermaid-validator.test.mjs} +2 -2
- package/tests/utils/mock-chat-model.mjs +12 -0
- package/tests/{preferences-utils.test.mjs → utils/preferences-utils.test.mjs} +1 -1
- package/tests/{save-value-to-config.test.mjs → utils/save-value-to-config.test.mjs} +61 -4
- package/tests/utils/utils.test.mjs +939 -0
- package/utils/conflict-detector.mjs +1 -1
- package/utils/constants.mjs +5 -3
- package/utils/d2-utils.mjs +194 -0
- package/utils/docs-finder-utils.mjs +26 -26
- package/utils/icon-map.mjs +26 -0
- package/{agents → utils}/load-config.mjs +2 -18
- package/utils/markdown-checker.mjs +5 -5
- package/agents/batch-docs-detail-generator.yaml +0 -19
- package/agents/check-structure-planning-result.yaml +0 -30
- package/agents/content-detail-generator.yaml +0 -50
- package/agents/format-structure-plan.mjs +0 -25
- package/agents/reflective-structure-planner.yaml +0 -12
- package/agents/schema/structure-plan.yaml +0 -26
- package/prompts/document/custom-components.md +0 -104
- package/tests/README.md +0 -93
- package/tests/utils.test.mjs +0 -2067
- /package/agents/{exit.mjs → utils/exit.mjs} +0 -0
- /package/agents/{fs.mjs → utils/fs.mjs} +0 -0
- /package/agents/{save-output.mjs → utils/save-output.mjs} +0 -0
- /package/prompts/{document → detail}/d2-chart/official-examples.md +0 -0
- /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 "
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
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");
|
|
@@ -1328,7 +1328,7 @@ describe("init", () => {
|
|
|
1328
1328
|
options,
|
|
1329
1329
|
);
|
|
1330
1330
|
|
|
1331
|
-
expect(result).
|
|
1331
|
+
expect(result).toBeDefined();
|
|
1332
1332
|
expect(validateCalled).toBe(true);
|
|
1333
1333
|
} finally {
|
|
1334
1334
|
await cleanupTempDir(tempDir);
|
|
@@ -1366,7 +1366,7 @@ describe("init", () => {
|
|
|
1366
1366
|
options,
|
|
1367
1367
|
);
|
|
1368
1368
|
|
|
1369
|
-
expect(result).
|
|
1369
|
+
expect(result).toBeDefined();
|
|
1370
1370
|
expect(audienceValidateCalled).toBe(true);
|
|
1371
1371
|
} finally {
|
|
1372
1372
|
await cleanupTempDir(tempDir);
|
|
@@ -1414,7 +1414,7 @@ describe("init", () => {
|
|
|
1414
1414
|
options,
|
|
1415
1415
|
);
|
|
1416
1416
|
|
|
1417
|
-
expect(result).
|
|
1417
|
+
expect(result).toBeDefined();
|
|
1418
1418
|
expect(priorityValidateCalled).toBe(true);
|
|
1419
1419
|
} finally {
|
|
1420
1420
|
await cleanupTempDir(tempDir);
|
|
@@ -1481,7 +1481,7 @@ describe("init", () => {
|
|
|
1481
1481
|
options,
|
|
1482
1482
|
);
|
|
1483
1483
|
|
|
1484
|
-
expect(result).
|
|
1484
|
+
expect(result).toBeDefined();
|
|
1485
1485
|
|
|
1486
1486
|
const configPath = join(tempDir, "config.yaml");
|
|
1487
1487
|
const configContent = await fs.readFile(configPath, "utf8");
|
|
@@ -1526,7 +1526,7 @@ describe("init", () => {
|
|
|
1526
1526
|
options,
|
|
1527
1527
|
);
|
|
1528
1528
|
|
|
1529
|
-
expect(result).
|
|
1529
|
+
expect(result).toBeDefined();
|
|
1530
1530
|
} finally {
|
|
1531
1531
|
await cleanupTempDir(tempDir);
|
|
1532
1532
|
}
|