@aigne/doc-smith 0.8.12-beta.7 → 0.8.12-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/agents/clear/choose-contents.mjs +14 -1
- package/agents/clear/clear-media-description.mjs +129 -0
- package/agents/clear/index.yaml +3 -1
- package/agents/evaluate/code-snippet.mjs +28 -24
- package/agents/evaluate/document-structure.yaml +0 -4
- package/agents/evaluate/document.yaml +1 -5
- package/agents/generate/index.yaml +1 -0
- package/agents/init/index.mjs +10 -0
- package/agents/media/batch-generate-media-description.yaml +44 -0
- package/agents/media/generate-media-description.yaml +47 -0
- package/agents/media/load-media-description.mjs +238 -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/index.yaml +1 -0
- package/agents/update/update-document-detail.yaml +3 -1
- package/agents/utils/load-sources.mjs +103 -53
- package/agents/utils/update-branding.mjs +69 -0
- package/aigne.yaml +6 -0
- package/assets/report-template/report.html +34 -34
- package/package.json +17 -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/evaluate/document-structure.md +6 -7
- package/prompts/evaluate/document.md +16 -25
- package/prompts/media/media-description/system-prompt.md +35 -0
- package/prompts/media/media-description/user-prompt.md +8 -0
- package/prompts/structure/update/user-prompt.md +0 -4
- package/utils/constants/index.mjs +0 -107
- package/utils/file-utils.mjs +86 -0
- 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/output/structure-plan.json +0 -162
- package/.aigne/doc-smith/preferences.yml +0 -97
- package/.aigne/doc-smith/upload-cache.yaml +0 -1893
- 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 -179
- 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 -96
- package/docs/configuration.md +0 -96
- package/docs/configuration.zh-TW.md +0 -96
- package/docs/configuration.zh.md +0 -96
- package/docs/getting-started.ja.md +0 -88
- package/docs/getting-started.md +0 -88
- package/docs/getting-started.zh-TW.md +0 -88
- package/docs/getting-started.zh.md +0 -88
- package/docs/guides-cleaning-up.ja.md +0 -51
- package/docs/guides-cleaning-up.md +0 -51
- 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 -66
- 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 -151
- 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 -85
- 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 -48
- 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 -78
- 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 -95
- 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 -77
- 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 -255
- package/docs/release-notes.zh-TW.md +0 -255
- package/docs/release-notes.zh.md +0 -255
- package/media.md +0 -19
- 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,300 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from "bun:test";
|
|
2
|
-
import checkUpdateIsSingle from "../../../agents/update/check-update-is-single.mjs";
|
|
3
|
-
|
|
4
|
-
describe("check-update-is-single", () => {
|
|
5
|
-
let mockOptions;
|
|
6
|
-
let consoleSpy;
|
|
7
|
-
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
mockOptions = {
|
|
10
|
-
context: {
|
|
11
|
-
agents: {
|
|
12
|
-
updateSingleDocument: { mockSingleAgent: true },
|
|
13
|
-
batchUpdateDocument: { mockBatchAgent: true },
|
|
14
|
-
},
|
|
15
|
-
invoke: mock(async () => ({ mockResult: true })),
|
|
16
|
-
},
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
consoleSpy = spyOn(console, "error").mockImplementation(() => {});
|
|
20
|
-
|
|
21
|
-
// Clear context mock call history
|
|
22
|
-
mockOptions.context.invoke.mockClear();
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
afterEach(() => {
|
|
26
|
-
consoleSpy?.mockRestore();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
// INPUT VALIDATION TESTS
|
|
30
|
-
test("should throw error when selectedDocs is not provided", async () => {
|
|
31
|
-
await expect(checkUpdateIsSingle({}, mockOptions)).rejects.toThrow(
|
|
32
|
-
"selectedDocs must be provided as an array",
|
|
33
|
-
);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test("should throw error when selectedDocs is not an array", async () => {
|
|
37
|
-
await expect(checkUpdateIsSingle({ selectedDocs: "not-array" }, mockOptions)).rejects.toThrow(
|
|
38
|
-
"selectedDocs must be provided as an array",
|
|
39
|
-
);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test("should throw error when selectedDocs is empty", async () => {
|
|
43
|
-
await expect(checkUpdateIsSingle({ selectedDocs: [] }, mockOptions)).rejects.toThrow(
|
|
44
|
-
"selectedDocs cannot be empty",
|
|
45
|
-
);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test("should throw error when selectedDocs is null", async () => {
|
|
49
|
-
await expect(checkUpdateIsSingle({ selectedDocs: null }, mockOptions)).rejects.toThrow(
|
|
50
|
-
"selectedDocs must be provided as an array",
|
|
51
|
-
);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test("should throw error when selectedDocs is undefined", async () => {
|
|
55
|
-
await expect(checkUpdateIsSingle({ selectedDocs: undefined }, mockOptions)).rejects.toThrow(
|
|
56
|
-
"selectedDocs must be provided as an array",
|
|
57
|
-
);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// AGENT AVAILABILITY TESTS
|
|
61
|
-
test("should throw error when updateSingleDocument agent is not available", async () => {
|
|
62
|
-
const optionsWithoutSingleAgent = {
|
|
63
|
-
context: {
|
|
64
|
-
agents: {
|
|
65
|
-
batchUpdateDocument: { mockBatchAgent: true },
|
|
66
|
-
},
|
|
67
|
-
invoke: mock(),
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
await expect(
|
|
72
|
-
checkUpdateIsSingle({ selectedDocs: ["doc1"] }, optionsWithoutSingleAgent),
|
|
73
|
-
).rejects.toThrow('Agent "updateSingleDocument" is not available');
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test("should throw error when batchUpdateDocument agent is not available", async () => {
|
|
77
|
-
const optionsWithoutBatchAgent = {
|
|
78
|
-
context: {
|
|
79
|
-
agents: {
|
|
80
|
-
updateSingleDocument: { mockSingleAgent: true },
|
|
81
|
-
},
|
|
82
|
-
invoke: mock(),
|
|
83
|
-
},
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
await expect(
|
|
87
|
-
checkUpdateIsSingle({ selectedDocs: ["doc1", "doc2"] }, optionsWithoutBatchAgent),
|
|
88
|
-
).rejects.toThrow('Agent "batchUpdateDocument" is not available');
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test("should throw error when no agents are available", async () => {
|
|
92
|
-
const optionsWithoutAgents = {
|
|
93
|
-
context: {
|
|
94
|
-
agents: {},
|
|
95
|
-
invoke: mock(),
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
await expect(
|
|
100
|
-
checkUpdateIsSingle({ selectedDocs: ["doc1"] }, optionsWithoutAgents),
|
|
101
|
-
).rejects.toThrow('Agent "updateSingleDocument" is not available');
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// SINGLE DOCUMENT ROUTING TESTS
|
|
105
|
-
test("should route to updateSingleDocument when selectedDocs has one item", async () => {
|
|
106
|
-
const result = await checkUpdateIsSingle(
|
|
107
|
-
{
|
|
108
|
-
selectedDocs: ["doc1"],
|
|
109
|
-
customParam: "test",
|
|
110
|
-
},
|
|
111
|
-
mockOptions,
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
expect(mockOptions.context.invoke).toHaveBeenCalledWith(
|
|
115
|
-
{ mockSingleAgent: true },
|
|
116
|
-
{
|
|
117
|
-
selectedDocs: ["doc1"],
|
|
118
|
-
customParam: "test",
|
|
119
|
-
},
|
|
120
|
-
);
|
|
121
|
-
expect(result).toEqual({ mockResult: true });
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
test("should pass through all parameters to single document agent", async () => {
|
|
125
|
-
await checkUpdateIsSingle(
|
|
126
|
-
{
|
|
127
|
-
selectedDocs: [{ path: "/doc1", content: "content" }],
|
|
128
|
-
docsDir: "./docs",
|
|
129
|
-
forceRegenerate: true,
|
|
130
|
-
customData: { key: "value" },
|
|
131
|
-
},
|
|
132
|
-
mockOptions,
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
expect(mockOptions.context.invoke).toHaveBeenCalledWith(
|
|
136
|
-
{ mockSingleAgent: true },
|
|
137
|
-
{
|
|
138
|
-
selectedDocs: [{ path: "/doc1", content: "content" }],
|
|
139
|
-
docsDir: "./docs",
|
|
140
|
-
forceRegenerate: true,
|
|
141
|
-
customData: { key: "value" },
|
|
142
|
-
},
|
|
143
|
-
);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
// BATCH DOCUMENT ROUTING TESTS
|
|
147
|
-
test("should route to batchUpdateDocument when selectedDocs has multiple items", async () => {
|
|
148
|
-
const result = await checkUpdateIsSingle(
|
|
149
|
-
{
|
|
150
|
-
selectedDocs: ["doc1", "doc2"],
|
|
151
|
-
customParam: "test",
|
|
152
|
-
},
|
|
153
|
-
mockOptions,
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
expect(mockOptions.context.invoke).toHaveBeenCalledWith(
|
|
157
|
-
{ mockBatchAgent: true },
|
|
158
|
-
{
|
|
159
|
-
selectedDocs: ["doc1", "doc2"],
|
|
160
|
-
customParam: "test",
|
|
161
|
-
},
|
|
162
|
-
);
|
|
163
|
-
expect(result).toEqual({ mockResult: true });
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
test("should route to batchUpdateDocument when selectedDocs has three items", async () => {
|
|
167
|
-
await checkUpdateIsSingle(
|
|
168
|
-
{
|
|
169
|
-
selectedDocs: ["doc1", "doc2", "doc3"],
|
|
170
|
-
},
|
|
171
|
-
mockOptions,
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
expect(mockOptions.context.invoke).toHaveBeenCalledWith(
|
|
175
|
-
{ mockBatchAgent: true },
|
|
176
|
-
{
|
|
177
|
-
selectedDocs: ["doc1", "doc2", "doc3"],
|
|
178
|
-
},
|
|
179
|
-
);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
test("should pass through all parameters to batch document agent", async () => {
|
|
183
|
-
await checkUpdateIsSingle(
|
|
184
|
-
{
|
|
185
|
-
selectedDocs: [
|
|
186
|
-
{ path: "/doc1", content: "content1" },
|
|
187
|
-
{ path: "/doc2", content: "content2" },
|
|
188
|
-
],
|
|
189
|
-
docsDir: "./docs",
|
|
190
|
-
forceRegenerate: false,
|
|
191
|
-
batchSize: 10,
|
|
192
|
-
customSettings: { parallel: true },
|
|
193
|
-
},
|
|
194
|
-
mockOptions,
|
|
195
|
-
);
|
|
196
|
-
|
|
197
|
-
expect(mockOptions.context.invoke).toHaveBeenCalledWith(
|
|
198
|
-
{ mockBatchAgent: true },
|
|
199
|
-
{
|
|
200
|
-
selectedDocs: [
|
|
201
|
-
{ path: "/doc1", content: "content1" },
|
|
202
|
-
{ path: "/doc2", content: "content2" },
|
|
203
|
-
],
|
|
204
|
-
docsDir: "./docs",
|
|
205
|
-
forceRegenerate: false,
|
|
206
|
-
batchSize: 10,
|
|
207
|
-
customSettings: { parallel: true },
|
|
208
|
-
},
|
|
209
|
-
);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// ERROR HANDLING TESTS
|
|
213
|
-
test("should handle and re-throw agent invocation errors for single document", async () => {
|
|
214
|
-
const mockError = new Error("Agent execution failed");
|
|
215
|
-
mockOptions.context.invoke.mockRejectedValue(mockError);
|
|
216
|
-
|
|
217
|
-
await expect(checkUpdateIsSingle({ selectedDocs: ["doc1"] }, mockOptions)).rejects.toThrow(
|
|
218
|
-
"Agent execution failed",
|
|
219
|
-
);
|
|
220
|
-
|
|
221
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
222
|
-
"Error invoking updateSingleDocument:",
|
|
223
|
-
"Agent execution failed",
|
|
224
|
-
);
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
test("should handle and re-throw agent invocation errors for batch documents", async () => {
|
|
228
|
-
const mockError = new Error("Batch processing failed");
|
|
229
|
-
mockOptions.context.invoke.mockRejectedValue(mockError);
|
|
230
|
-
|
|
231
|
-
await expect(
|
|
232
|
-
checkUpdateIsSingle({ selectedDocs: ["doc1", "doc2"] }, mockOptions),
|
|
233
|
-
).rejects.toThrow("Batch processing failed");
|
|
234
|
-
|
|
235
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
236
|
-
"Error invoking batchUpdateDocument:",
|
|
237
|
-
"Batch processing failed",
|
|
238
|
-
);
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
test("should log specific error message for single document failures", async () => {
|
|
242
|
-
const mockError = new Error("Network timeout");
|
|
243
|
-
mockOptions.context.invoke.mockRejectedValue(mockError);
|
|
244
|
-
|
|
245
|
-
try {
|
|
246
|
-
await checkUpdateIsSingle({ selectedDocs: ["doc1"] }, mockOptions);
|
|
247
|
-
} catch {
|
|
248
|
-
// Expected to throw
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
252
|
-
"Error invoking updateSingleDocument:",
|
|
253
|
-
"Network timeout",
|
|
254
|
-
);
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
test("should log specific error message for batch document failures", async () => {
|
|
258
|
-
const mockError = new Error("Memory limit exceeded");
|
|
259
|
-
mockOptions.context.invoke.mockRejectedValue(mockError);
|
|
260
|
-
|
|
261
|
-
try {
|
|
262
|
-
await checkUpdateIsSingle({ selectedDocs: ["doc1", "doc2", "doc3"] }, mockOptions);
|
|
263
|
-
} catch {
|
|
264
|
-
// Expected to throw
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
268
|
-
"Error invoking batchUpdateDocument:",
|
|
269
|
-
"Memory limit exceeded",
|
|
270
|
-
);
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
// RESULT PASSING TESTS
|
|
274
|
-
test("should return result from single document agent unchanged", async () => {
|
|
275
|
-
const mockResult = {
|
|
276
|
-
success: true,
|
|
277
|
-
processedDocs: ["doc1"],
|
|
278
|
-
metadata: { timestamp: "2023-01-01" },
|
|
279
|
-
};
|
|
280
|
-
mockOptions.context.invoke.mockResolvedValue(mockResult);
|
|
281
|
-
|
|
282
|
-
const result = await checkUpdateIsSingle({ selectedDocs: ["doc1"] }, mockOptions);
|
|
283
|
-
|
|
284
|
-
expect(result).toEqual(mockResult);
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
test("should return result from batch document agent unchanged", async () => {
|
|
288
|
-
const mockResult = {
|
|
289
|
-
success: true,
|
|
290
|
-
processedDocs: ["doc1", "doc2"],
|
|
291
|
-
errors: [],
|
|
292
|
-
summary: "All documents processed successfully",
|
|
293
|
-
};
|
|
294
|
-
mockOptions.context.invoke.mockResolvedValue(mockResult);
|
|
295
|
-
|
|
296
|
-
const result = await checkUpdateIsSingle({ selectedDocs: ["doc1", "doc2"] }, mockOptions);
|
|
297
|
-
|
|
298
|
-
expect(result).toEqual(mockResult);
|
|
299
|
-
});
|
|
300
|
-
});
|
|
@@ -1,329 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, test } from "bun:test";
|
|
2
|
-
import updateDocumentContent from "../../../../agents/update/document-tools/update-document-content.mjs";
|
|
3
|
-
|
|
4
|
-
describe("update-document-content", () => {
|
|
5
|
-
let mockOptions;
|
|
6
|
-
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
mockOptions = {
|
|
9
|
-
context: {
|
|
10
|
-
userContext: {
|
|
11
|
-
currentContent: "",
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
};
|
|
15
|
-
});
|
|
16
|
-
|
|
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
|
-
}
|
|
22
|
-
|
|
23
|
-
// INPUT VALIDATION TESTS
|
|
24
|
-
test("should return error when diffPatch is not provided", async () => {
|
|
25
|
-
mockOptions.context.userContext.currentContent = "original content";
|
|
26
|
-
const result = await updateDocumentContent({}, mockOptions);
|
|
27
|
-
expect(result.success).toBe(false);
|
|
28
|
-
expect(result.error.message).toContain("diffPatch");
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test("should return error when diffPatch is not a string", async () => {
|
|
32
|
-
mockOptions.context.userContext.currentContent = "original content";
|
|
33
|
-
const result = await updateDocumentContent({ diffPatch: null }, mockOptions);
|
|
34
|
-
expect(result.success).toBe(false);
|
|
35
|
-
expect(result.error.message).toContain("diffPatch");
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test("should return error when diffPatch is empty string", async () => {
|
|
39
|
-
mockOptions.context.userContext.currentContent = "original content";
|
|
40
|
-
const result = await updateDocumentContent({ diffPatch: "" }, mockOptions);
|
|
41
|
-
expect(result.success).toBe(false);
|
|
42
|
-
expect(result.error.message).toContain("Diff patch is required");
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// SUCCESSFUL PATCH APPLICATION TESTS
|
|
46
|
-
test("should successfully apply simple diff patch", async () => {
|
|
47
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
|
|
48
|
-
const diffPatch = "@@ -1,3 +1,3 @@\n line 1\n-line 2\n+updated line 2\n line 3";
|
|
49
|
-
|
|
50
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
51
|
-
|
|
52
|
-
expect(result.success).toBe(true);
|
|
53
|
-
expect(extractContent(result.updatedContent)).toBe("line 1\nupdated line 2\nline 3");
|
|
54
|
-
expect(result.message).toContain("Document content updated successfully");
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test("should handle diff with multiple hunks", async () => {
|
|
58
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4\nline 5";
|
|
59
|
-
const diffPatch =
|
|
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";
|
|
61
|
-
|
|
62
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
63
|
-
|
|
64
|
-
expect(result.success).toBe(true);
|
|
65
|
-
expect(extractContent(result.updatedContent)).toBe(
|
|
66
|
-
"updated line 1\nline 2\nline 3\nline 4\nupdated line 5",
|
|
67
|
-
);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test("should handle diff with additions only", async () => {
|
|
71
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2";
|
|
72
|
-
const diffPatch = "@@ -2,0 +3,2 @@\n line 2\n+new line 3\n+new line 4";
|
|
73
|
-
|
|
74
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
75
|
-
|
|
76
|
-
expect(result.success).toBe(true);
|
|
77
|
-
expect(extractContent(result.updatedContent)).toBe("line 1\nline 2\nnew line 3\nnew line 4");
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("should handle diff with deletions only", async () => {
|
|
81
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4";
|
|
82
|
-
const diffPatch = "@@ -2,2 +2,0 @@\n line 1\n-line 2\n-line 3\n line 4";
|
|
83
|
-
|
|
84
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
85
|
-
|
|
86
|
-
expect(result.success).toBe(true);
|
|
87
|
-
expect(extractContent(result.updatedContent)).toBe("line 1\nline 4");
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test("should handle diff with context lines", async () => {
|
|
91
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4\nline 5";
|
|
92
|
-
const diffPatch =
|
|
93
|
-
"@@ -2,3 +2,3 @@\n line 1\n line 2\n-line 3\n+updated line 3\n line 4\n line 5";
|
|
94
|
-
|
|
95
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
96
|
-
|
|
97
|
-
expect(result.success).toBe(true);
|
|
98
|
-
expect(extractContent(result.updatedContent)).toBe(
|
|
99
|
-
"line 1\nline 2\nupdated line 3\nline 4\nline 5",
|
|
100
|
-
);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// DIFF PATCH PARSING TESTS
|
|
104
|
-
test("should return error for invalid diff format", async () => {
|
|
105
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2";
|
|
106
|
-
const diffPatch = "invalid diff format";
|
|
107
|
-
|
|
108
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
109
|
-
|
|
110
|
-
expect(result).toEqual({
|
|
111
|
-
success: false,
|
|
112
|
-
error: { message: "No valid hunks found in diff" },
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
test("should return error for empty diff", async () => {
|
|
117
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2";
|
|
118
|
-
const diffPatch = "\n\n";
|
|
119
|
-
|
|
120
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
121
|
-
|
|
122
|
-
expect(result).toEqual({
|
|
123
|
-
success: false,
|
|
124
|
-
error: { message: "No valid hunks found in diff" },
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test("should handle malformed hunk headers gracefully", async () => {
|
|
129
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2";
|
|
130
|
-
const diffPatch = "@@malformed header@@\n-line 1\n+updated line 1";
|
|
131
|
-
|
|
132
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
133
|
-
|
|
134
|
-
expect(result.success).toBe(false);
|
|
135
|
-
expect(result.error.message).toContain("No valid hunks found");
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// LINE NUMBER FIXING TESTS
|
|
139
|
-
test("should fix line numbers when patch position is off", async () => {
|
|
140
|
-
mockOptions.context.userContext.currentContent = "prefix line\nline 1\nline 2\nline 3";
|
|
141
|
-
// This diff patch expects to find "line 1" at line 1, but it's actually at line 2
|
|
142
|
-
const diffPatch = "@@ -1,2 +1,2 @@\n-line 1\n+updated line 1\n line 2";
|
|
143
|
-
|
|
144
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
145
|
-
|
|
146
|
-
expect(result.success).toBe(true);
|
|
147
|
-
expect(extractContent(result.updatedContent)).toBe(
|
|
148
|
-
"prefix line\nupdated line 1\nline 2\nline 3",
|
|
149
|
-
);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
test("should use fuzzy matching when exact match fails", async () => {
|
|
153
|
-
mockOptions.context.userContext.currentContent =
|
|
154
|
-
"similar line 1\nsimilar line 2\ndifferent content\nsimilar line 3";
|
|
155
|
-
// This patch refers to lines that are similar but not exactly matching
|
|
156
|
-
const diffPatch = "@@ -10,2 +10,2 @@\n-similar line 1\n+updated line 1\n similar line 2";
|
|
157
|
-
|
|
158
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
159
|
-
|
|
160
|
-
expect(result.success).toBe(true);
|
|
161
|
-
expect(extractContent(result.updatedContent)).toBe(
|
|
162
|
-
"updated line 1\nsimilar line 2\ndifferent content\nsimilar line 3",
|
|
163
|
-
);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
test("should return error when no matching context found", async () => {
|
|
167
|
-
mockOptions.context.userContext.currentContent =
|
|
168
|
-
"completely different content\nnothing matches";
|
|
169
|
-
const diffPatch =
|
|
170
|
-
"@@ -1,2 +1,2 @@\n-line that doesn't exist\n+updated line\n another nonexistent line";
|
|
171
|
-
|
|
172
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
173
|
-
|
|
174
|
-
expect(result.success).toBe(false);
|
|
175
|
-
expect(result.error.message).toContain("Cannot find matching context");
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
// COMPLEX DIFF SCENARIOS
|
|
179
|
-
test("should handle diff with no context lines", async () => {
|
|
180
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
|
|
181
|
-
const diffPatch = "@@ -2,1 +2,1 @@\n-line 2\n+updated line 2";
|
|
182
|
-
|
|
183
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
184
|
-
|
|
185
|
-
expect(result.success).toBe(true);
|
|
186
|
-
expect(extractContent(result.updatedContent)).toBe("line 1\nupdated line 2\nline 3");
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test("should handle diff with single line count (implicit 1)", async () => {
|
|
190
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
|
|
191
|
-
const diffPatch = "@@ -2 +2 @@\n-line 2\n+updated line 2";
|
|
192
|
-
|
|
193
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
194
|
-
|
|
195
|
-
expect(result.success).toBe(true);
|
|
196
|
-
expect(extractContent(result.updatedContent)).toBe("line 1\nupdated line 2\nline 3");
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
test("should handle multiple changes in single hunk", async () => {
|
|
200
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4\nline 5";
|
|
201
|
-
const diffPatch =
|
|
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";
|
|
203
|
-
|
|
204
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
205
|
-
|
|
206
|
-
expect(result.success).toBe(true);
|
|
207
|
-
expect(extractContent(result.updatedContent)).toBe(
|
|
208
|
-
"line 1\nupdated line 2\nnew line\nupdated line 3\nline 4\nline 5",
|
|
209
|
-
);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// EDGE CASES
|
|
213
|
-
test("should handle empty lines in diff", async () => {
|
|
214
|
-
mockOptions.context.userContext.currentContent = "line 1\n\nline 3";
|
|
215
|
-
const diffPatch = "@@ -1,3 +1,3 @@\n line 1\n \n-line 3\n+updated line 3";
|
|
216
|
-
|
|
217
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
218
|
-
|
|
219
|
-
expect(result.success).toBe(true);
|
|
220
|
-
expect(extractContent(result.updatedContent)).toBe("line 1\n\nupdated line 3");
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
test("should handle diff with trailing newlines", async () => {
|
|
224
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2\n";
|
|
225
|
-
const diffPatch = "@@ -1,2 +1,2 @@\n-line 1\n+updated line 1\n line 2";
|
|
226
|
-
|
|
227
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
228
|
-
|
|
229
|
-
expect(result.success).toBe(true);
|
|
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");
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
// REALISTIC DOCUMENTATION UPDATE SCENARIOS
|
|
237
|
-
test("should handle updating code blocks", async () => {
|
|
238
|
-
mockOptions.context.userContext.currentContent =
|
|
239
|
-
"# API Reference\n\n```javascript\nfunction oldFunction() {\n return 'old';\n}\n```\n\nDescription here.";
|
|
240
|
-
const diffPatch =
|
|
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 ```";
|
|
242
|
-
|
|
243
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
244
|
-
|
|
245
|
-
expect(result.success).toBe(true);
|
|
246
|
-
const content = extractContent(result.updatedContent);
|
|
247
|
-
expect(content).toContain("function newFunction()");
|
|
248
|
-
expect(content).toContain("return 'new';");
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
test("should handle adding new sections", async () => {
|
|
252
|
-
mockOptions.context.userContext.currentContent =
|
|
253
|
-
"# Documentation\n\n## Section 1\n\nContent 1\n\n## Section 3\n\nContent 3";
|
|
254
|
-
const diffPatch =
|
|
255
|
-
"@@ -4,0 +5,3 @@\n Content 1\n \n+## Section 2\n+\n+Content 2\n+\n ## Section 3";
|
|
256
|
-
|
|
257
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
258
|
-
|
|
259
|
-
expect(result.success).toBe(true);
|
|
260
|
-
const content = extractContent(result.updatedContent);
|
|
261
|
-
expect(content).toContain("## Section 2");
|
|
262
|
-
expect(content).toContain("Content 2");
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
test("should handle removing outdated content", async () => {
|
|
266
|
-
mockOptions.context.userContext.currentContent =
|
|
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.";
|
|
268
|
-
const diffPatch =
|
|
269
|
-
"@@ -5,4 +5,0 @@\n This is current.\n \n-## Deprecated Feature\n-\n-This is deprecated.\n-\n ## Another Feature";
|
|
270
|
-
|
|
271
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
272
|
-
|
|
273
|
-
expect(result.success).toBe(true);
|
|
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");
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
// ERROR SCENARIOS WITH REALISTIC CONTENT
|
|
281
|
-
test("should handle conflicting patches gracefully", async () => {
|
|
282
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
|
|
283
|
-
// This patch tries to modify content that doesn't match exactly
|
|
284
|
-
const diffPatch =
|
|
285
|
-
"@@ -1,3 +1,3 @@\n-different line 1\n-different line 2\n+updated line 1\n+updated line 2\n line 3";
|
|
286
|
-
|
|
287
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
288
|
-
|
|
289
|
-
expect(result.success).toBe(false);
|
|
290
|
-
expect(result.error.message).toContain("Cannot find matching context");
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
test("should handle patches with incorrect line counts", async () => {
|
|
294
|
-
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4";
|
|
295
|
-
// Incorrect line count in hunk header (says 5 lines but content has 4)
|
|
296
|
-
const diffPatch = "@@ -1,5 +1,3 @@\n-line 1\n-line 2\n line 3\n line 4";
|
|
297
|
-
|
|
298
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
299
|
-
|
|
300
|
-
expect(result.success).toBe(true);
|
|
301
|
-
expect(extractContent(result.updatedContent)).toBe("line 3\nline 4");
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
// FUZZY MATCHING EDGE CASES
|
|
305
|
-
test("should succeed fuzzy matching with high similarity", async () => {
|
|
306
|
-
mockOptions.context.userContext.currentContent =
|
|
307
|
-
"function calculateTotal(items) {\n let total = 0;\n for (item of items) {\n total += item.price;\n }\n return total;\n}";
|
|
308
|
-
// Patch has slight differences but should match with fuzzy matching
|
|
309
|
-
const diffPatch =
|
|
310
|
-
"@@ -2,2 +2,2 @@\n function calculateTotal(items) {\n- let total = 0;\n+ let sum = 0;\n for (item of items) {";
|
|
311
|
-
|
|
312
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
313
|
-
|
|
314
|
-
expect(result.success).toBe(true);
|
|
315
|
-
expect(extractContent(result.updatedContent)).toContain("let sum = 0;");
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
test("should fail fuzzy matching with low similarity", async () => {
|
|
319
|
-
mockOptions.context.userContext.currentContent =
|
|
320
|
-
"completely different content\nwith nothing similar\nat all";
|
|
321
|
-
const diffPatch =
|
|
322
|
-
"@@ -1,2 +1,2 @@\n-some totally different text\n+updated text\n that has no relation";
|
|
323
|
-
|
|
324
|
-
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
325
|
-
|
|
326
|
-
expect(result.success).toBe(false);
|
|
327
|
-
expect(result.error.message).toContain("Cannot find matching context");
|
|
328
|
-
});
|
|
329
|
-
});
|
|
@@ -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("generateDocument 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/update/generate-document.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("generateDocument");
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test("should have instructions loaded from file", async () => {
|
|
32
|
-
const agent = await loadAgent(
|
|
33
|
-
join(import.meta.dirname, "../../../agents/update/generate-document.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
|
-
});
|