@aigne/doc-smith 0.8.12-beta.8 → 0.8.12
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/CHANGELOG.md +15 -0
- package/agents/publish/index.yaml +4 -0
- package/agents/publish/publish-docs.mjs +77 -5
- package/agents/publish/translate-meta.mjs +103 -0
- package/agents/update/generate-document.yaml +30 -28
- package/agents/update/update-document-detail.yaml +3 -1
- package/agents/utils/update-branding.mjs +69 -0
- package/package.json +16 -2
- package/prompts/common/document/role-and-personality.md +3 -1
- package/prompts/detail/d2-diagram/guide.md +7 -1
- package/prompts/detail/d2-diagram/user-prompt.md +3 -0
- package/prompts/detail/generate/system-prompt.md +6 -7
- package/prompts/detail/generate/user-prompt.md +12 -3
- package/prompts/detail/update/user-prompt.md +0 -2
- package/prompts/structure/update/user-prompt.md +0 -4
- package/utils/file-utils.mjs +69 -24
- package/utils/markdown-checker.mjs +0 -20
- package/utils/request.mjs +7 -0
- package/utils/upload-files.mjs +231 -0
- package/utils/utils.mjs +11 -1
- package/.aigne/doc-smith/config.yaml +0 -77
- package/.aigne/doc-smith/history.yaml +0 -37
- package/.aigne/doc-smith/media-description.yaml +0 -91
- package/.aigne/doc-smith/output/structure-plan.json +0 -162
- package/.aigne/doc-smith/preferences.yml +0 -97
- package/.aigne/doc-smith/upload-cache.yaml +0 -1830
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
- package/.github/workflows/ci.yml +0 -54
- package/.github/workflows/create-release-pr.yaml +0 -21
- package/.github/workflows/publish-docs.yml +0 -65
- package/.github/workflows/release.yml +0 -49
- package/.github/workflows/reviewer.yml +0 -54
- package/.release-please-manifest.json +0 -3
- package/RELEASE.md +0 -9
- package/assets/screenshots/doc-complete-setup.png +0 -0
- package/assets/screenshots/doc-generate-docs.png +0 -0
- package/assets/screenshots/doc-generate.png +0 -0
- package/assets/screenshots/doc-generated-successfully.png +0 -0
- package/assets/screenshots/doc-publish.png +0 -0
- package/assets/screenshots/doc-regenerate.png +0 -0
- package/assets/screenshots/doc-translate-langs.png +0 -0
- package/assets/screenshots/doc-translate.png +0 -0
- package/assets/screenshots/doc-update.png +0 -0
- package/biome.json +0 -73
- package/codecov.yml +0 -15
- package/docs/_sidebar.md +0 -15
- package/docs/configuration-initial-setup.ja.md +0 -179
- package/docs/configuration-initial-setup.md +0 -198
- package/docs/configuration-initial-setup.zh-TW.md +0 -179
- package/docs/configuration-initial-setup.zh.md +0 -179
- package/docs/configuration-managing-preferences.ja.md +0 -100
- package/docs/configuration-managing-preferences.md +0 -100
- package/docs/configuration-managing-preferences.zh-TW.md +0 -100
- package/docs/configuration-managing-preferences.zh.md +0 -100
- package/docs/configuration.ja.md +0 -69
- package/docs/configuration.md +0 -69
- package/docs/configuration.zh-TW.md +0 -69
- package/docs/configuration.zh.md +0 -69
- package/docs/getting-started.ja.md +0 -107
- package/docs/getting-started.md +0 -107
- package/docs/getting-started.zh-TW.md +0 -107
- package/docs/getting-started.zh.md +0 -107
- package/docs/guides-cleaning-up.ja.md +0 -51
- package/docs/guides-cleaning-up.md +0 -52
- package/docs/guides-cleaning-up.zh-TW.md +0 -51
- package/docs/guides-cleaning-up.zh.md +0 -51
- package/docs/guides-evaluating-documents.ja.md +0 -66
- package/docs/guides-evaluating-documents.md +0 -107
- package/docs/guides-evaluating-documents.zh-TW.md +0 -66
- package/docs/guides-evaluating-documents.zh.md +0 -66
- package/docs/guides-generating-documentation.ja.md +0 -151
- package/docs/guides-generating-documentation.md +0 -89
- package/docs/guides-generating-documentation.zh-TW.md +0 -151
- package/docs/guides-generating-documentation.zh.md +0 -151
- package/docs/guides-interactive-chat.ja.md +0 -85
- package/docs/guides-interactive-chat.md +0 -93
- package/docs/guides-interactive-chat.zh-TW.md +0 -85
- package/docs/guides-interactive-chat.zh.md +0 -85
- package/docs/guides-managing-history.ja.md +0 -48
- package/docs/guides-managing-history.md +0 -53
- package/docs/guides-managing-history.zh-TW.md +0 -48
- package/docs/guides-managing-history.zh.md +0 -48
- package/docs/guides-publishing-your-docs.ja.md +0 -78
- package/docs/guides-publishing-your-docs.md +0 -83
- package/docs/guides-publishing-your-docs.zh-TW.md +0 -78
- package/docs/guides-publishing-your-docs.zh.md +0 -78
- package/docs/guides-translating-documentation.ja.md +0 -95
- package/docs/guides-translating-documentation.md +0 -100
- package/docs/guides-translating-documentation.zh-TW.md +0 -95
- package/docs/guides-translating-documentation.zh.md +0 -95
- package/docs/guides-updating-documentation.ja.md +0 -77
- package/docs/guides-updating-documentation.md +0 -79
- package/docs/guides-updating-documentation.zh-TW.md +0 -77
- package/docs/guides-updating-documentation.zh.md +0 -77
- package/docs/guides.ja.md +0 -32
- package/docs/guides.md +0 -32
- package/docs/guides.zh-TW.md +0 -32
- package/docs/guides.zh.md +0 -32
- package/docs/overview.ja.md +0 -61
- package/docs/overview.md +0 -61
- package/docs/overview.zh-TW.md +0 -61
- package/docs/overview.zh.md +0 -61
- package/docs/release-notes.ja.md +0 -255
- package/docs/release-notes.md +0 -288
- package/docs/release-notes.zh-TW.md +0 -255
- package/docs/release-notes.zh.md +0 -255
- package/prompts/common/afs/afs-tools-usage.md +0 -5
- package/prompts/common/afs/use-afs-instruction.md +0 -1
- package/release-please-config.json +0 -14
- package/tests/agents/chat/chat.test.mjs +0 -46
- package/tests/agents/clear/choose-contents.test.mjs +0 -284
- package/tests/agents/clear/clear-auth-tokens.test.mjs +0 -268
- package/tests/agents/clear/clear-document-config.test.mjs +0 -167
- package/tests/agents/clear/clear-document-structure.test.mjs +0 -380
- package/tests/agents/clear/clear-generated-docs.test.mjs +0 -222
- package/tests/agents/evaluate/code-snippet.test.mjs +0 -163
- package/tests/agents/evaluate/fixtures/api-services.md +0 -87
- package/tests/agents/evaluate/fixtures/js-sdk.md +0 -94
- package/tests/agents/evaluate/generate-report.test.mjs +0 -312
- package/tests/agents/generate/check-document-structure.test.mjs +0 -45
- package/tests/agents/generate/check-need-generate-structure.test.mjs +0 -279
- package/tests/agents/generate/document-structure-tools/add-document.test.mjs +0 -449
- package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +0 -410
- package/tests/agents/generate/document-structure-tools/generate-sub-structure.test.mjs +0 -277
- package/tests/agents/generate/document-structure-tools/move-document.test.mjs +0 -476
- package/tests/agents/generate/document-structure-tools/update-document.test.mjs +0 -548
- package/tests/agents/generate/generate-structure.test.mjs +0 -45
- package/tests/agents/generate/user-review-document-structure.test.mjs +0 -319
- package/tests/agents/history/view.test.mjs +0 -97
- package/tests/agents/init/init.test.mjs +0 -1657
- package/tests/agents/prefs/prefs.test.mjs +0 -431
- package/tests/agents/publish/publish-docs.test.mjs +0 -787
- package/tests/agents/translate/choose-language.test.mjs +0 -311
- package/tests/agents/translate/translate-document.test.mjs +0 -51
- package/tests/agents/update/check-document.test.mjs +0 -463
- package/tests/agents/update/check-update-is-single.test.mjs +0 -300
- package/tests/agents/update/document-tools/update-document-content.test.mjs +0 -329
- package/tests/agents/update/generate-document.test.mjs +0 -51
- package/tests/agents/update/save-and-translate-document.test.mjs +0 -369
- package/tests/agents/update/user-review-document.test.mjs +0 -582
- package/tests/agents/utils/action-success.test.mjs +0 -54
- package/tests/agents/utils/check-detail-result.test.mjs +0 -743
- package/tests/agents/utils/check-feedback-refiner.test.mjs +0 -478
- package/tests/agents/utils/choose-docs.test.mjs +0 -406
- package/tests/agents/utils/exit.test.mjs +0 -70
- package/tests/agents/utils/feedback-refiner.test.mjs +0 -51
- package/tests/agents/utils/find-item-by-path.test.mjs +0 -517
- package/tests/agents/utils/find-user-preferences-by-path.test.mjs +0 -382
- package/tests/agents/utils/format-document-structure.test.mjs +0 -364
- package/tests/agents/utils/fs.test.mjs +0 -267
- package/tests/agents/utils/load-sources.test.mjs +0 -1470
- package/tests/agents/utils/save-docs.test.mjs +0 -109
- package/tests/agents/utils/save-output.test.mjs +0 -315
- package/tests/agents/utils/save-single-doc.test.mjs +0 -364
- package/tests/agents/utils/transform-detail-datasources.test.mjs +0 -320
- package/tests/utils/auth-utils.test.mjs +0 -596
- package/tests/utils/blocklet.test.mjs +0 -336
- package/tests/utils/conflict-detector.test.mjs +0 -355
- package/tests/utils/constants.test.mjs +0 -295
- package/tests/utils/d2-utils.test.mjs +0 -437
- package/tests/utils/deploy.test.mjs +0 -399
- package/tests/utils/docs-finder-utils.test.mjs +0 -650
- package/tests/utils/file-utils.test.mjs +0 -521
- package/tests/utils/history-utils.test.mjs +0 -206
- package/tests/utils/kroki-utils.test.mjs +0 -646
- package/tests/utils/linter/fixtures/css/keyword-error.css +0 -1
- package/tests/utils/linter/fixtures/css/missing-semicolon.css +0 -1
- package/tests/utils/linter/fixtures/css/syntax-error.css +0 -1
- package/tests/utils/linter/fixtures/css/undeclare-variable.css +0 -1
- package/tests/utils/linter/fixtures/css/unused-variable.css +0 -2
- package/tests/utils/linter/fixtures/css/valid-code.css +0 -1
- package/tests/utils/linter/fixtures/dockerfile/keyword-error.dockerfile +0 -1
- package/tests/utils/linter/fixtures/dockerfile/missing-semicolon.dockerfile +0 -2
- package/tests/utils/linter/fixtures/dockerfile/syntax-error.dockerfile +0 -2
- package/tests/utils/linter/fixtures/dockerfile/undeclare-variable.dockerfile +0 -1
- package/tests/utils/linter/fixtures/dockerfile/unused-variable.dockerfile +0 -1
- package/tests/utils/linter/fixtures/dockerfile/valid-code.dockerfile +0 -2
- package/tests/utils/linter/fixtures/go/keyword-error.go +0 -5
- package/tests/utils/linter/fixtures/go/missing-semicolon.go +0 -5
- package/tests/utils/linter/fixtures/go/syntax-error.go +0 -6
- package/tests/utils/linter/fixtures/go/undeclare-variable.go +0 -5
- package/tests/utils/linter/fixtures/go/unused-variable.go +0 -5
- package/tests/utils/linter/fixtures/go/valid-code.go +0 -7
- package/tests/utils/linter/fixtures/js/keyword-error.js +0 -3
- package/tests/utils/linter/fixtures/js/missing-semicolon.js +0 -6
- package/tests/utils/linter/fixtures/js/syntax-error.js +0 -4
- package/tests/utils/linter/fixtures/js/undeclare-variable.js +0 -3
- package/tests/utils/linter/fixtures/js/unused-variable.js +0 -7
- package/tests/utils/linter/fixtures/js/valid-code.js +0 -15
- package/tests/utils/linter/fixtures/json/keyword-error.json +0 -1
- package/tests/utils/linter/fixtures/json/missing-semicolon.json +0 -1
- package/tests/utils/linter/fixtures/json/syntax-error.json +0 -1
- package/tests/utils/linter/fixtures/json/undeclare-variable.json +0 -1
- package/tests/utils/linter/fixtures/json/unused-variable.json +0 -1
- package/tests/utils/linter/fixtures/json/valid-code.json +0 -1
- package/tests/utils/linter/fixtures/jsx/keyword-error.jsx +0 -5
- package/tests/utils/linter/fixtures/jsx/missing-semicolon.jsx +0 -5
- package/tests/utils/linter/fixtures/jsx/syntax-error.jsx +0 -5
- package/tests/utils/linter/fixtures/jsx/undeclare-variable.jsx +0 -5
- package/tests/utils/linter/fixtures/jsx/unused-variable.jsx +0 -4
- package/tests/utils/linter/fixtures/jsx/valid-code.jsx +0 -5
- package/tests/utils/linter/fixtures/python/keyword-error.py +0 -3
- package/tests/utils/linter/fixtures/python/missing-semicolon.py +0 -2
- package/tests/utils/linter/fixtures/python/syntax-error.py +0 -3
- package/tests/utils/linter/fixtures/python/undeclare-variable.py +0 -3
- package/tests/utils/linter/fixtures/python/unused-variable.py +0 -6
- package/tests/utils/linter/fixtures/python/valid-code.py +0 -12
- package/tests/utils/linter/fixtures/ruby/keyword-error.rb +0 -2
- package/tests/utils/linter/fixtures/ruby/missing-semicolon.rb +0 -1
- package/tests/utils/linter/fixtures/ruby/syntax-error.rb +0 -2
- package/tests/utils/linter/fixtures/ruby/undeclare-variable.rb +0 -1
- package/tests/utils/linter/fixtures/ruby/unused-variable.rb +0 -2
- package/tests/utils/linter/fixtures/ruby/valid-code.rb +0 -1
- package/tests/utils/linter/fixtures/sass/keyword-error.sass +0 -2
- package/tests/utils/linter/fixtures/sass/missing-semicolon.sass +0 -3
- package/tests/utils/linter/fixtures/sass/syntax-error.sass +0 -3
- package/tests/utils/linter/fixtures/sass/undeclare-variable.sass +0 -2
- package/tests/utils/linter/fixtures/sass/unused-variable.sass +0 -4
- package/tests/utils/linter/fixtures/sass/valid-code.sass +0 -2
- package/tests/utils/linter/fixtures/scss/keyword-error.scss +0 -1
- package/tests/utils/linter/fixtures/scss/missing-semicolon.scss +0 -1
- package/tests/utils/linter/fixtures/scss/syntax-error.scss +0 -1
- package/tests/utils/linter/fixtures/scss/undeclare-variable.scss +0 -1
- package/tests/utils/linter/fixtures/scss/unused-variable.scss +0 -2
- package/tests/utils/linter/fixtures/scss/valid-code.scss +0 -1
- package/tests/utils/linter/fixtures/shell/keyword-error.sh +0 -5
- package/tests/utils/linter/fixtures/shell/missing-semicolon.sh +0 -3
- package/tests/utils/linter/fixtures/shell/syntax-error.sh +0 -4
- package/tests/utils/linter/fixtures/shell/undeclare-variable.sh +0 -3
- package/tests/utils/linter/fixtures/shell/unused-variable.sh +0 -4
- package/tests/utils/linter/fixtures/shell/valid-code.sh +0 -3
- package/tests/utils/linter/fixtures/ts/keyword-error.ts +0 -1
- package/tests/utils/linter/fixtures/ts/missing-semicolon.ts +0 -1
- package/tests/utils/linter/fixtures/ts/syntax-error.ts +0 -1
- package/tests/utils/linter/fixtures/ts/undeclare-variable.ts +0 -1
- package/tests/utils/linter/fixtures/ts/unused-variable.ts +0 -3
- package/tests/utils/linter/fixtures/ts/valid-code.ts +0 -3
- package/tests/utils/linter/fixtures/tsx/keyword-error.tsx +0 -5
- package/tests/utils/linter/fixtures/tsx/missing-semicolon.tsx +0 -5
- package/tests/utils/linter/fixtures/tsx/syntax-error.tsx +0 -5
- package/tests/utils/linter/fixtures/tsx/undeclare-variable.tsx +0 -6
- package/tests/utils/linter/fixtures/tsx/unused-variable.tsx +0 -6
- package/tests/utils/linter/fixtures/tsx/valid-code.tsx +0 -5
- package/tests/utils/linter/fixtures/vue/keyword-error.vue +0 -6
- package/tests/utils/linter/fixtures/vue/missing-semicolon.vue +0 -6
- package/tests/utils/linter/fixtures/vue/syntax-error.vue +0 -6
- package/tests/utils/linter/fixtures/vue/undeclare-variable.vue +0 -6
- package/tests/utils/linter/fixtures/vue/unused-variable.vue +0 -7
- package/tests/utils/linter/fixtures/vue/valid-code.vue +0 -6
- package/tests/utils/linter/fixtures/yaml/keyword-error.yml +0 -1
- package/tests/utils/linter/fixtures/yaml/missing-semicolon.yml +0 -2
- package/tests/utils/linter/fixtures/yaml/syntax-error.yml +0 -1
- package/tests/utils/linter/fixtures/yaml/undeclare-variable.yml +0 -1
- package/tests/utils/linter/fixtures/yaml/unused-variable.yml +0 -2
- package/tests/utils/linter/fixtures/yaml/valid-code.yml +0 -3
- package/tests/utils/linter/index.test.mjs +0 -440
- package/tests/utils/linter/scan-results.mjs +0 -42
- package/tests/utils/load-config.test.mjs +0 -141
- package/tests/utils/markdown/index.test.mjs +0 -478
- package/tests/utils/mermaid-validator.test.mjs +0 -541
- package/tests/utils/mock-chat-model.mjs +0 -12
- package/tests/utils/preferences-utils.test.mjs +0 -465
- package/tests/utils/save-value-to-config.test.mjs +0 -483
- package/tests/utils/utils.test.mjs +0 -941
|
@@ -1,406 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from "bun:test";
|
|
2
|
-
import chooseDocs from "../../../agents/utils/choose-docs.mjs";
|
|
3
|
-
import * as docsFinderUtils from "../../../utils/docs-finder-utils.mjs";
|
|
4
|
-
|
|
5
|
-
describe("chooseDocs utility", () => {
|
|
6
|
-
let getMainLanguageFilesSpy;
|
|
7
|
-
let processSelectedFilesSpy;
|
|
8
|
-
let findItemByPathSpy;
|
|
9
|
-
let getActionTextSpy;
|
|
10
|
-
let addFeedbackToItemsSpy;
|
|
11
|
-
let consoleErrorSpy;
|
|
12
|
-
let consoleWarnSpy;
|
|
13
|
-
let mockOptions;
|
|
14
|
-
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
// Spy on utility functions
|
|
17
|
-
getMainLanguageFilesSpy = spyOn(docsFinderUtils, "getMainLanguageFiles").mockResolvedValue([
|
|
18
|
-
"/docs/guide.md",
|
|
19
|
-
"/docs/api.md",
|
|
20
|
-
"/docs/tutorial.md",
|
|
21
|
-
]);
|
|
22
|
-
processSelectedFilesSpy = spyOn(docsFinderUtils, "processSelectedFiles").mockResolvedValue([
|
|
23
|
-
{ path: "/docs/guide.md", content: "# Guide", title: "Guide" },
|
|
24
|
-
{ path: "/docs/api.md", content: "# API", title: "API" },
|
|
25
|
-
]);
|
|
26
|
-
findItemByPathSpy = spyOn(docsFinderUtils, "findItemByPath").mockResolvedValue({
|
|
27
|
-
path: "/docs/guide.md",
|
|
28
|
-
content: "# Guide",
|
|
29
|
-
title: "Guide",
|
|
30
|
-
});
|
|
31
|
-
getActionTextSpy = spyOn(docsFinderUtils, "getActionText").mockImplementation(
|
|
32
|
-
(isTranslate, template) => template.replace("{action}", isTranslate ? "translate" : "update"),
|
|
33
|
-
);
|
|
34
|
-
addFeedbackToItemsSpy = spyOn(docsFinderUtils, "addFeedbackToItems").mockImplementation(
|
|
35
|
-
(items, feedback) => items.map((item) => ({ ...item, feedback })),
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
// Spy on console methods
|
|
39
|
-
consoleErrorSpy = spyOn(console, "error").mockImplementation(() => {});
|
|
40
|
-
consoleWarnSpy = spyOn(console, "warn").mockImplementation(() => {});
|
|
41
|
-
|
|
42
|
-
// Mock options with prompts
|
|
43
|
-
mockOptions = {
|
|
44
|
-
prompts: {
|
|
45
|
-
checkbox: mock().mockResolvedValue(["/docs/guide.md", "/docs/api.md"]),
|
|
46
|
-
input: mock().mockResolvedValue("Test feedback"),
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
afterEach(() => {
|
|
52
|
-
// Restore all spies
|
|
53
|
-
getMainLanguageFilesSpy?.mockRestore();
|
|
54
|
-
processSelectedFilesSpy?.mockRestore();
|
|
55
|
-
findItemByPathSpy?.mockRestore();
|
|
56
|
-
getActionTextSpy?.mockRestore();
|
|
57
|
-
addFeedbackToItemsSpy?.mockRestore();
|
|
58
|
-
consoleErrorSpy?.mockRestore();
|
|
59
|
-
consoleWarnSpy?.mockRestore();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// DOCS PROVIDED TESTS
|
|
63
|
-
test("should process provided docs array successfully", async () => {
|
|
64
|
-
const input = {
|
|
65
|
-
docs: ["/docs/guide.md", "/docs/api.md"],
|
|
66
|
-
documentExecutionStructure: [{ path: "/docs/guide.md" }],
|
|
67
|
-
boardId: "board-123",
|
|
68
|
-
docsDir: "/project/docs",
|
|
69
|
-
isTranslate: false,
|
|
70
|
-
feedback: "Update these docs",
|
|
71
|
-
locale: "en",
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const result = await chooseDocs(input, mockOptions);
|
|
75
|
-
|
|
76
|
-
expect(findItemByPathSpy).toHaveBeenCalledTimes(2);
|
|
77
|
-
expect(findItemByPathSpy).toHaveBeenCalledWith(
|
|
78
|
-
input.documentExecutionStructure,
|
|
79
|
-
"/docs/guide.md",
|
|
80
|
-
"board-123",
|
|
81
|
-
"/project/docs",
|
|
82
|
-
"en",
|
|
83
|
-
);
|
|
84
|
-
expect(addFeedbackToItemsSpy).toHaveBeenCalledWith(expect.any(Array), "Update these docs");
|
|
85
|
-
expect(result).toEqual({
|
|
86
|
-
selectedDocs: expect.any(Array),
|
|
87
|
-
feedback: "Update these docs",
|
|
88
|
-
selectedPaths: expect.any(Array),
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test("should handle docs with some items not found", async () => {
|
|
93
|
-
findItemByPathSpy.mockImplementation((_, path) => {
|
|
94
|
-
if (path === "/docs/missing.md") {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
return { path, content: `Content for ${path}`, title: path };
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
const input = {
|
|
101
|
-
docs: ["/docs/guide.md", "/docs/missing.md", "/docs/api.md"],
|
|
102
|
-
documentExecutionStructure: [],
|
|
103
|
-
boardId: "board-123",
|
|
104
|
-
docsDir: "/project/docs",
|
|
105
|
-
isTranslate: false,
|
|
106
|
-
locale: "en",
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const result = await chooseDocs(input, mockOptions);
|
|
110
|
-
|
|
111
|
-
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
112
|
-
'⚠️ Item with path "/docs/missing.md" not found in documentExecutionStructure',
|
|
113
|
-
);
|
|
114
|
-
expect(result.selectedDocs).toHaveLength(2); // Only found items
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
test("should throw error when none of provided docs are found", async () => {
|
|
118
|
-
findItemByPathSpy.mockResolvedValue(null);
|
|
119
|
-
|
|
120
|
-
const input = {
|
|
121
|
-
docs: ["/docs/missing1.md", "/docs/missing2.md"],
|
|
122
|
-
documentExecutionStructure: [],
|
|
123
|
-
boardId: "board-123",
|
|
124
|
-
docsDir: "/project/docs",
|
|
125
|
-
isTranslate: false,
|
|
126
|
-
locale: "en",
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
await expect(chooseDocs(input, mockOptions)).rejects.toThrow(
|
|
130
|
-
"None of the specified document paths were found in documentExecutionStructure",
|
|
131
|
-
);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
// INTERACTIVE SELECTION TESTS
|
|
135
|
-
test("should handle interactive document selection when docs not provided", async () => {
|
|
136
|
-
const input = {
|
|
137
|
-
docs: [],
|
|
138
|
-
documentExecutionStructure: [{ path: "/docs/guide.md" }],
|
|
139
|
-
docsDir: "/project/docs",
|
|
140
|
-
isTranslate: false,
|
|
141
|
-
locale: "en",
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
const result = await chooseDocs(input, mockOptions);
|
|
145
|
-
|
|
146
|
-
expect(getMainLanguageFilesSpy).toHaveBeenCalledWith(
|
|
147
|
-
"/project/docs",
|
|
148
|
-
"en",
|
|
149
|
-
input.documentExecutionStructure,
|
|
150
|
-
);
|
|
151
|
-
expect(mockOptions.prompts.checkbox).toHaveBeenCalled();
|
|
152
|
-
expect(processSelectedFilesSpy).toHaveBeenCalledWith(
|
|
153
|
-
["/docs/guide.md", "/docs/api.md"],
|
|
154
|
-
input.documentExecutionStructure,
|
|
155
|
-
"/project/docs",
|
|
156
|
-
);
|
|
157
|
-
expect(result.selectedDocs).toBeDefined();
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
test("should handle interactive selection when docs is null", async () => {
|
|
161
|
-
const input = {
|
|
162
|
-
docs: null,
|
|
163
|
-
documentExecutionStructure: [],
|
|
164
|
-
docsDir: "/project/docs",
|
|
165
|
-
isTranslate: true,
|
|
166
|
-
locale: "zh",
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
await chooseDocs(input, mockOptions);
|
|
170
|
-
|
|
171
|
-
expect(getMainLanguageFilesSpy).toHaveBeenCalled();
|
|
172
|
-
expect(getActionTextSpy).toHaveBeenCalledWith(true, "Select documents to {action}:");
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
test("should throw error when no main language files found", async () => {
|
|
176
|
-
getMainLanguageFilesSpy.mockResolvedValue([]);
|
|
177
|
-
|
|
178
|
-
const input = {
|
|
179
|
-
docs: [],
|
|
180
|
-
documentExecutionStructure: [],
|
|
181
|
-
docsDir: "/empty/docs",
|
|
182
|
-
isTranslate: false,
|
|
183
|
-
locale: "en",
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
await expect(chooseDocs(input, mockOptions)).rejects.toThrow();
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test("should throw error when no documents selected interactively", async () => {
|
|
190
|
-
mockOptions.prompts.checkbox.mockResolvedValue([]);
|
|
191
|
-
|
|
192
|
-
const input = {
|
|
193
|
-
docs: [],
|
|
194
|
-
documentExecutionStructure: [],
|
|
195
|
-
docsDir: "/project/docs",
|
|
196
|
-
isTranslate: false,
|
|
197
|
-
locale: "en",
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
await expect(chooseDocs(input, mockOptions)).rejects.toThrow();
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
// CHECKBOX VALIDATION TESTS
|
|
204
|
-
test("should validate checkbox selection requires at least one document", async () => {
|
|
205
|
-
const input = {
|
|
206
|
-
docs: [],
|
|
207
|
-
documentExecutionStructure: [],
|
|
208
|
-
docsDir: "/project/docs",
|
|
209
|
-
isTranslate: false,
|
|
210
|
-
locale: "en",
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
await chooseDocs(input, mockOptions);
|
|
214
|
-
|
|
215
|
-
const checkboxCall = mockOptions.prompts.checkbox.mock.calls[0][0];
|
|
216
|
-
expect(checkboxCall.validate([])).toBe("Please select at least one document");
|
|
217
|
-
expect(checkboxCall.validate(["/docs/guide.md"])).toBe(true);
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
test("should filter choices based on search term", async () => {
|
|
221
|
-
const input = {
|
|
222
|
-
docs: [],
|
|
223
|
-
documentExecutionStructure: [],
|
|
224
|
-
docsDir: "/project/docs",
|
|
225
|
-
isTranslate: false,
|
|
226
|
-
locale: "en",
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
await chooseDocs(input, mockOptions);
|
|
230
|
-
|
|
231
|
-
const checkboxCall = mockOptions.prompts.checkbox.mock.calls[0][0];
|
|
232
|
-
const choices = checkboxCall.source();
|
|
233
|
-
expect(choices).toHaveLength(3);
|
|
234
|
-
|
|
235
|
-
const filteredChoices = checkboxCall.source("api");
|
|
236
|
-
expect(filteredChoices).toHaveLength(1);
|
|
237
|
-
expect(filteredChoices[0].value).toBe("/docs/api.md");
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
// FEEDBACK HANDLING TESTS
|
|
241
|
-
test("should prompt for feedback when not provided", async () => {
|
|
242
|
-
const input = {
|
|
243
|
-
docs: ["/docs/guide.md"],
|
|
244
|
-
documentExecutionStructure: [],
|
|
245
|
-
boardId: "board-123",
|
|
246
|
-
docsDir: "/project/docs",
|
|
247
|
-
isTranslate: true,
|
|
248
|
-
locale: "en",
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
const result = await chooseDocs(input, mockOptions);
|
|
252
|
-
|
|
253
|
-
expect(mockOptions.prompts.input).toHaveBeenCalled();
|
|
254
|
-
expect(result.feedback).toBe("Test feedback");
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
test("should use provided feedback without prompting", async () => {
|
|
258
|
-
const input = {
|
|
259
|
-
docs: ["/docs/guide.md"],
|
|
260
|
-
documentExecutionStructure: [],
|
|
261
|
-
boardId: "board-123",
|
|
262
|
-
docsDir: "/project/docs",
|
|
263
|
-
isTranslate: false,
|
|
264
|
-
feedback: "Provided feedback",
|
|
265
|
-
locale: "en",
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
const result = await chooseDocs(input, mockOptions);
|
|
269
|
-
|
|
270
|
-
expect(mockOptions.prompts.input).not.toHaveBeenCalled();
|
|
271
|
-
expect(result.feedback).toBe("Provided feedback");
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
test("should handle empty feedback gracefully", async () => {
|
|
275
|
-
mockOptions.prompts.input.mockResolvedValue("");
|
|
276
|
-
|
|
277
|
-
const input = {
|
|
278
|
-
docs: ["/docs/guide.md"],
|
|
279
|
-
documentExecutionStructure: [],
|
|
280
|
-
boardId: "board-123",
|
|
281
|
-
docsDir: "/project/docs",
|
|
282
|
-
isTranslate: false,
|
|
283
|
-
locale: "en",
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
const result = await chooseDocs(input, mockOptions);
|
|
287
|
-
|
|
288
|
-
expect(result.feedback).toBe("");
|
|
289
|
-
expect(addFeedbackToItemsSpy).toHaveBeenCalledWith(expect.any(Array), "");
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
// RESET FUNCTIONALITY TESTS
|
|
293
|
-
test("should reset content to null when reset is true", async () => {
|
|
294
|
-
const input = {
|
|
295
|
-
docs: ["/docs/guide.md"],
|
|
296
|
-
documentExecutionStructure: [],
|
|
297
|
-
boardId: "board-123",
|
|
298
|
-
docsDir: "/project/docs",
|
|
299
|
-
isTranslate: false,
|
|
300
|
-
feedback: "Reset test",
|
|
301
|
-
locale: "en",
|
|
302
|
-
reset: true,
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
const result = await chooseDocs(input, mockOptions);
|
|
306
|
-
|
|
307
|
-
expect(result.selectedDocs).toEqual(
|
|
308
|
-
expect.arrayContaining([
|
|
309
|
-
expect.objectContaining({
|
|
310
|
-
content: null,
|
|
311
|
-
}),
|
|
312
|
-
]),
|
|
313
|
-
);
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
test("should preserve content when reset is false", async () => {
|
|
317
|
-
const input = {
|
|
318
|
-
docs: ["/docs/guide.md"],
|
|
319
|
-
documentExecutionStructure: [],
|
|
320
|
-
boardId: "board-123",
|
|
321
|
-
docsDir: "/project/docs",
|
|
322
|
-
isTranslate: false,
|
|
323
|
-
feedback: "No reset test",
|
|
324
|
-
locale: "en",
|
|
325
|
-
reset: false,
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
const result = await chooseDocs(input, mockOptions);
|
|
329
|
-
|
|
330
|
-
expect(result.selectedDocs).toEqual(
|
|
331
|
-
expect.arrayContaining([
|
|
332
|
-
expect.objectContaining({
|
|
333
|
-
content: expect.any(String),
|
|
334
|
-
}),
|
|
335
|
-
]),
|
|
336
|
-
);
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
// RETURN VALUE STRUCTURE TESTS
|
|
340
|
-
test("should return correct structure with all required fields", async () => {
|
|
341
|
-
const input = {
|
|
342
|
-
docs: ["/docs/guide.md", "/docs/api.md"],
|
|
343
|
-
documentExecutionStructure: [],
|
|
344
|
-
boardId: "board-123",
|
|
345
|
-
docsDir: "/project/docs",
|
|
346
|
-
isTranslate: false,
|
|
347
|
-
feedback: "Structure test",
|
|
348
|
-
locale: "en",
|
|
349
|
-
};
|
|
350
|
-
|
|
351
|
-
const result = await chooseDocs(input, mockOptions);
|
|
352
|
-
|
|
353
|
-
expect(result).toHaveProperty("selectedDocs");
|
|
354
|
-
expect(result).toHaveProperty("feedback");
|
|
355
|
-
expect(result).toHaveProperty("selectedPaths");
|
|
356
|
-
expect(Array.isArray(result.selectedDocs)).toBe(true);
|
|
357
|
-
expect(Array.isArray(result.selectedPaths)).toBe(true);
|
|
358
|
-
expect(typeof result.feedback).toBe("string");
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
test("should map selectedPaths correctly from selectedDocs", async () => {
|
|
362
|
-
findItemByPathSpy.mockImplementation((_, path) => ({
|
|
363
|
-
path,
|
|
364
|
-
content: `Content for ${path}`,
|
|
365
|
-
title: path,
|
|
366
|
-
}));
|
|
367
|
-
|
|
368
|
-
const input = {
|
|
369
|
-
docs: ["/docs/guide.md", "/docs/api.md"],
|
|
370
|
-
documentExecutionStructure: [],
|
|
371
|
-
boardId: "board-123",
|
|
372
|
-
docsDir: "/project/docs",
|
|
373
|
-
isTranslate: false,
|
|
374
|
-
feedback: "Path mapping test",
|
|
375
|
-
locale: "en",
|
|
376
|
-
};
|
|
377
|
-
|
|
378
|
-
const result = await chooseDocs(input, mockOptions);
|
|
379
|
-
|
|
380
|
-
expect(result.selectedPaths).toEqual(["/docs/guide.md", "/docs/api.md"]);
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
// EDGE CASES
|
|
384
|
-
test("should handle special characters in file paths", async () => {
|
|
385
|
-
const specialPaths = ["/docs/中文文档.md", "/docs/file with spaces.md"];
|
|
386
|
-
findItemByPathSpy.mockImplementation((_, path) => ({
|
|
387
|
-
path,
|
|
388
|
-
content: `Content for ${path}`,
|
|
389
|
-
title: path,
|
|
390
|
-
}));
|
|
391
|
-
|
|
392
|
-
const input = {
|
|
393
|
-
docs: specialPaths,
|
|
394
|
-
documentExecutionStructure: [],
|
|
395
|
-
boardId: "board-123",
|
|
396
|
-
docsDir: "/project/docs",
|
|
397
|
-
isTranslate: false,
|
|
398
|
-
feedback: "Special chars test",
|
|
399
|
-
locale: "zh",
|
|
400
|
-
};
|
|
401
|
-
|
|
402
|
-
const result = await chooseDocs(input, mockOptions);
|
|
403
|
-
|
|
404
|
-
expect(result.selectedPaths).toEqual(specialPaths);
|
|
405
|
-
});
|
|
406
|
-
});
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
|
|
2
|
-
import exit from "../../../agents/utils/exit.mjs";
|
|
3
|
-
|
|
4
|
-
describe("exit", () => {
|
|
5
|
-
let processExitSpy;
|
|
6
|
-
let originalProcessExit;
|
|
7
|
-
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
// Save the original process.exit
|
|
10
|
-
originalProcessExit = process.exit;
|
|
11
|
-
|
|
12
|
-
// Spy on process.exit to prevent actual process termination
|
|
13
|
-
processExitSpy = spyOn(process, "exit").mockImplementation(() => {
|
|
14
|
-
// Mock implementation that doesn't actually exit
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
afterEach(() => {
|
|
19
|
-
// Restore the original process.exit
|
|
20
|
-
processExitSpy?.mockRestore();
|
|
21
|
-
process.exit = originalProcessExit;
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// BASIC FUNCTIONALITY TESTS
|
|
25
|
-
test("should call process.exit with code 0", async () => {
|
|
26
|
-
await exit();
|
|
27
|
-
|
|
28
|
-
expect(processExitSpy).toHaveBeenCalledWith(0);
|
|
29
|
-
expect(processExitSpy).toHaveBeenCalledTimes(1);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test("should be callable multiple times (in theory)", async () => {
|
|
33
|
-
await exit();
|
|
34
|
-
await exit();
|
|
35
|
-
|
|
36
|
-
expect(processExitSpy).toHaveBeenCalledWith(0);
|
|
37
|
-
expect(processExitSpy).toHaveBeenCalledTimes(2);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test("should maintain process.exit behavior characteristics", async () => {
|
|
41
|
-
// Test that our spy captures the essential behavior
|
|
42
|
-
await exit();
|
|
43
|
-
|
|
44
|
-
// Verify the call was made with the expected arguments
|
|
45
|
-
const calls = processExitSpy.mock.calls;
|
|
46
|
-
expect(calls).toHaveLength(1);
|
|
47
|
-
expect(calls[0]).toEqual([0]);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
// ERROR HANDLING TESTS
|
|
51
|
-
test("should handle spy restoration correctly", async () => {
|
|
52
|
-
await exit();
|
|
53
|
-
expect(processExitSpy).toHaveBeenCalled();
|
|
54
|
-
|
|
55
|
-
// Manually restore and verify
|
|
56
|
-
processExitSpy.mockRestore();
|
|
57
|
-
expect(process.exit).toBe(originalProcessExit);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test("should work correctly when process.exit throws (theoretical)", async () => {
|
|
61
|
-
// Reset the spy to throw an error
|
|
62
|
-
processExitSpy.mockImplementation(() => {
|
|
63
|
-
throw new Error("Mock exit error");
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// The function should still attempt to call process.exit
|
|
67
|
-
await expect(exit()).rejects.toThrow("Mock exit error");
|
|
68
|
-
expect(processExitSpy).toHaveBeenCalledWith(0);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { AIAgent } from "@aigne/core";
|
|
4
|
-
import { loadAgent } from "@aigne/core/loader/index.js";
|
|
5
|
-
import { loadModel } from "../../utils/mock-chat-model.mjs";
|
|
6
|
-
|
|
7
|
-
describe("feedbackRefiner 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/utils/feedback-refiner.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("feedbackRefiner");
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test("should have instructions loaded from file", async () => {
|
|
32
|
-
const agent = await loadAgent(
|
|
33
|
-
join(import.meta.dirname, "../../../agents/utils/feedback-refiner.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
|
-
});
|