@aigne/doc-smith 0.5.1 → 0.7.0
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/.github/workflows/ci.yml +46 -0
- package/.github/workflows/reviewer.yml +2 -1
- package/CHANGELOG.md +17 -0
- package/agents/chat.yaml +30 -0
- package/agents/check-detail-result.mjs +2 -1
- package/agents/check-detail.mjs +1 -0
- package/agents/check-structure-plan.mjs +1 -1
- package/agents/docs-fs.yaml +25 -0
- package/agents/exit.mjs +6 -0
- package/agents/feedback-refiner.yaml +5 -1
- package/agents/find-items-by-paths.mjs +10 -4
- package/agents/fs.mjs +60 -0
- package/agents/input-generator.mjs +159 -90
- package/agents/load-config.mjs +0 -5
- package/agents/load-sources.mjs +119 -12
- package/agents/publish-docs.mjs +28 -11
- package/agents/retranslate.yaml +1 -1
- package/agents/team-publish-docs.yaml +2 -2
- package/aigne.yaml +1 -0
- package/package.json +13 -10
- package/prompts/content-detail-generator.md +12 -4
- package/prompts/document/custom-components.md +80 -0
- package/prompts/document/d2-chart/diy-examples.md +44 -0
- package/prompts/document/d2-chart/official-examples.md +708 -0
- package/prompts/document/d2-chart/rules.md +48 -0
- package/prompts/document/detail-generator.md +13 -15
- package/prompts/document/structure-planning.md +1 -3
- package/prompts/feedback-refiner.md +81 -60
- package/prompts/structure-planning.md +20 -3
- package/tests/check-detail-result.test.mjs +50 -2
- package/tests/conflict-resolution.test.mjs +237 -0
- package/tests/input-generator.test.mjs +940 -0
- package/tests/load-sources.test.mjs +627 -3
- package/tests/preferences-utils.test.mjs +94 -0
- package/tests/save-value-to-config.test.mjs +182 -5
- package/tests/utils.test.mjs +49 -0
- package/utils/auth-utils.mjs +1 -1
- package/utils/conflict-detector.mjs +72 -1
- package/utils/constants.mjs +139 -126
- package/utils/kroki-utils.mjs +162 -0
- package/utils/markdown-checker.mjs +175 -67
- package/utils/utils.mjs +97 -29
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
env:
|
|
4
|
+
NODE_OPTIONS: "--max_old_space_size=6144"
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
lint_and_test:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
|
|
19
|
+
if: "!contains(github.event.head_commit.message, '[skip ci]')"
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout repo
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- uses: pnpm/action-setup@v3
|
|
26
|
+
with:
|
|
27
|
+
version: 10
|
|
28
|
+
|
|
29
|
+
- name: Setup node
|
|
30
|
+
uses: actions/setup-node@v4
|
|
31
|
+
with:
|
|
32
|
+
node-version: 23
|
|
33
|
+
cache: pnpm
|
|
34
|
+
|
|
35
|
+
- name: Setup bun
|
|
36
|
+
uses: oven-sh/setup-bun@v2
|
|
37
|
+
|
|
38
|
+
- name: Install dependencies
|
|
39
|
+
run: |
|
|
40
|
+
pnpm install
|
|
41
|
+
|
|
42
|
+
- name: Lint
|
|
43
|
+
run: pnpm lint
|
|
44
|
+
|
|
45
|
+
- name: Test
|
|
46
|
+
run: pnpm test:coverage
|
|
@@ -21,7 +21,7 @@ jobs:
|
|
|
21
21
|
review:
|
|
22
22
|
runs-on: ubuntu-latest
|
|
23
23
|
steps:
|
|
24
|
-
- uses: aigne-io/aigne-
|
|
24
|
+
- uses: aigne-io/aigne-code-smith@latest
|
|
25
25
|
env:
|
|
26
26
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
27
27
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
@@ -32,6 +32,7 @@ jobs:
|
|
|
32
32
|
disable_review: false
|
|
33
33
|
review_simple_changes: false
|
|
34
34
|
review_comment_lgtm: false
|
|
35
|
+
suggest_pr_title: true
|
|
35
36
|
path_filters: |
|
|
36
37
|
!docs/*
|
|
37
38
|
!**/*.md
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.7.0](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.6.0...v0.7.0) (2025-08-30)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add chat mode support ([#60](https://github.com/AIGNE-io/aigne-doc-smith/issues/60)) ([9b2ce50](https://github.com/AIGNE-io/aigne-doc-smith/commit/9b2ce50014d1894a4e41bf043e699fdc4f1d74b7))
|
|
9
|
+
* support custom components and more robust config handling ([#70](https://github.com/AIGNE-io/aigne-doc-smith/issues/70)) ([727ab42](https://github.com/AIGNE-io/aigne-doc-smith/commit/727ab429b00f924ef605530b35d2a12b4be77e3a))
|
|
10
|
+
* support d2 chart in doc generate and publish workflow ([#69](https://github.com/AIGNE-io/aigne-doc-smith/issues/69)) ([bf95889](https://github.com/AIGNE-io/aigne-doc-smith/commit/bf958891516973636c4847b084c6fe75d1ea124b))
|
|
11
|
+
* support multi purpose doc planning and generating ([#68](https://github.com/AIGNE-io/aigne-doc-smith/issues/68)) ([44152c5](https://github.com/AIGNE-io/aigne-doc-smith/commit/44152c53b7e8f82e3af1245a1affd77b9817486d))
|
|
12
|
+
|
|
13
|
+
## [0.6.0](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.5.1...v0.6.0) (2025-08-27)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* complete support for media processing before publish ([#63](https://github.com/AIGNE-io/aigne-doc-smith/issues/63)) ([5257ca1](https://github.com/AIGNE-io/aigne-doc-smith/commit/5257ca1756f47487b65a1813949e547b6fc51aca))
|
|
19
|
+
|
|
3
20
|
## [0.5.1](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.5.0...v0.5.1) (2025-08-26)
|
|
4
21
|
|
|
5
22
|
|
package/agents/chat.yaml
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type: ai
|
|
2
|
+
name: chat
|
|
3
|
+
description: Start interactive document generation assistant
|
|
4
|
+
instructions: |
|
|
5
|
+
You are a professional document generation assistant that helps users create, modify, and manage documentation through interactive chat. Your primary role is to understand user requirements and intelligently call upon various specialized skills to complete documentation tasks efficiently.
|
|
6
|
+
|
|
7
|
+
Core Capabilities:
|
|
8
|
+
- Generate comprehensive documentation from user inputs and specifications
|
|
9
|
+
- Regenerate and refine document details based on feedback
|
|
10
|
+
- Translate and localize documentation content
|
|
11
|
+
- Publish and manage team documentation workflows
|
|
12
|
+
- Provide interactive guidance throughout the document creation process
|
|
13
|
+
|
|
14
|
+
Interaction Guidelines:
|
|
15
|
+
- Engage users in a professional yet friendly manner
|
|
16
|
+
- Ask clarifying questions to understand specific documentation needs
|
|
17
|
+
- Suggest appropriate skills and workflows based on user requests
|
|
18
|
+
- Provide clear explanations of available capabilities and processes
|
|
19
|
+
- Maintain context throughout multi-step documentation tasks
|
|
20
|
+
- Offer proactive suggestions for improving document quality and structure
|
|
21
|
+
input_key: message
|
|
22
|
+
memory: true
|
|
23
|
+
skills:
|
|
24
|
+
- ./input-generator.mjs
|
|
25
|
+
- ./docs-generator.yaml
|
|
26
|
+
- ./detail-regenerator.yaml
|
|
27
|
+
- ./team-publish-docs.yaml
|
|
28
|
+
- ./retranslate.yaml
|
|
29
|
+
- ./docs-fs.yaml
|
|
30
|
+
- ./exit.mjs
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { checkMarkdown } from "../utils/markdown-checker.mjs";
|
|
2
2
|
|
|
3
|
-
export default async function checkDetailResult({ structurePlan, reviewContent }) {
|
|
3
|
+
export default async function checkDetailResult({ structurePlan, reviewContent, docsDir }) {
|
|
4
4
|
let isApproved = true;
|
|
5
5
|
const detailFeedback = [];
|
|
6
6
|
|
|
@@ -24,6 +24,7 @@ export default async function checkDetailResult({ structurePlan, reviewContent }
|
|
|
24
24
|
try {
|
|
25
25
|
const markdownErrors = await checkMarkdown(reviewContent, "result", {
|
|
26
26
|
allowedLinks,
|
|
27
|
+
baseDir: docsDir,
|
|
27
28
|
});
|
|
28
29
|
|
|
29
30
|
if (markdownErrors.length > 0) {
|
package/agents/check-detail.mjs
CHANGED
|
@@ -63,7 +63,7 @@ export default async function checkStructurePlan(
|
|
|
63
63
|
1. 对于新增的内容,可以根据需要新增节点,或补充到原有节点展示
|
|
64
64
|
2. 谨慎删除节点,除非节点关联 sourceIds 都被删除了
|
|
65
65
|
3. 不能修改原有节点的 path
|
|
66
|
-
4. 根据最新的 Data Sources
|
|
66
|
+
4. 根据最新的 Data Sources 可以按需要更新节点的 sourceIds。
|
|
67
67
|
`;
|
|
68
68
|
}
|
|
69
69
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
type: team
|
|
2
|
+
name: docs_fs_actor
|
|
3
|
+
description: File system operations for documentation management
|
|
4
|
+
skills:
|
|
5
|
+
- ./load-config.mjs
|
|
6
|
+
- url: ./fs.mjs
|
|
7
|
+
default_input:
|
|
8
|
+
rootDir:
|
|
9
|
+
$get: docsDir
|
|
10
|
+
input_schema:
|
|
11
|
+
type: object
|
|
12
|
+
properties:
|
|
13
|
+
action:
|
|
14
|
+
type: "string"
|
|
15
|
+
enum: ["read_file", "write_file", "delete_file", "list_directory"]
|
|
16
|
+
description:
|
|
17
|
+
"The file system action to perform, available actions are: read_file, write_file, delete_file, list_directory"
|
|
18
|
+
path:
|
|
19
|
+
type: "string"
|
|
20
|
+
description: "The path to the file or directory to operate on"
|
|
21
|
+
content:
|
|
22
|
+
type: "string"
|
|
23
|
+
description: "The content to write to the file, required for write_file action"
|
|
24
|
+
required: ["action", "path"]
|
|
25
|
+
task_render_mode: hide
|
package/agents/exit.mjs
ADDED
|
@@ -41,8 +41,12 @@ output_schema:
|
|
|
41
41
|
limitToInputPaths:
|
|
42
42
|
type: boolean
|
|
43
43
|
description: Whether to limit to the "paths specified in current input" when used subsequently
|
|
44
|
+
reason:
|
|
45
|
+
type: string
|
|
46
|
+
description: Explanation of why the save decision was made and how the rule and scope were derived
|
|
44
47
|
required:
|
|
45
48
|
- rule
|
|
46
49
|
- scope
|
|
47
50
|
- save
|
|
48
|
-
- limitToInputPaths
|
|
51
|
+
- limitToInputPaths
|
|
52
|
+
- reason
|
|
@@ -26,10 +26,16 @@ export default async function selectedDocs(
|
|
|
26
26
|
// Let user select multiple files
|
|
27
27
|
selectedFiles = await options.prompts.checkbox({
|
|
28
28
|
message: getActionText(isTranslate, "Select documents to {action}:"),
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
source: (term) => {
|
|
30
|
+
const choices = mainLanguageFiles.map((file) => ({
|
|
31
|
+
name: file,
|
|
32
|
+
value: file,
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
if (!term) return choices;
|
|
36
|
+
|
|
37
|
+
return choices.filter((choice) => choice.name.toLowerCase().includes(term.toLowerCase()));
|
|
38
|
+
},
|
|
33
39
|
validate: (answer) => {
|
|
34
40
|
if (answer.length === 0) {
|
|
35
41
|
return "Please select at least one document";
|
package/agents/fs.mjs
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
|
|
4
|
+
export default async function fs({ rootDir, action, path, content }) {
|
|
5
|
+
if (!rootDir) throw new Error("Root directory is not specified");
|
|
6
|
+
|
|
7
|
+
path = join(rootDir, path);
|
|
8
|
+
|
|
9
|
+
switch (action) {
|
|
10
|
+
case "read_file":
|
|
11
|
+
return {
|
|
12
|
+
status: "ok",
|
|
13
|
+
path,
|
|
14
|
+
content: await readFile(path, "utf-8"),
|
|
15
|
+
};
|
|
16
|
+
case "write_file": {
|
|
17
|
+
await mkdir(dirname(path), { recursive: true });
|
|
18
|
+
await writeFile(path, content || "");
|
|
19
|
+
return {
|
|
20
|
+
status: "ok",
|
|
21
|
+
path,
|
|
22
|
+
content,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
case "delete_file":
|
|
26
|
+
await rm(path, { recursive: true, force: true });
|
|
27
|
+
return {
|
|
28
|
+
status: "ok",
|
|
29
|
+
path,
|
|
30
|
+
};
|
|
31
|
+
case "list_directory":
|
|
32
|
+
return {
|
|
33
|
+
status: "ok",
|
|
34
|
+
entries: await readdir(path, { withFileTypes: true }).then((list) =>
|
|
35
|
+
list.map((entry) => ({
|
|
36
|
+
path: join(entry.parentPath, entry.name),
|
|
37
|
+
isDirectory: entry.isDirectory(),
|
|
38
|
+
})),
|
|
39
|
+
),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
fs.input_schema = {
|
|
45
|
+
type: "object",
|
|
46
|
+
properties: {
|
|
47
|
+
action: {
|
|
48
|
+
type: "string",
|
|
49
|
+
enum: ["read_file", "write_file", "delete_file", "list_directory"],
|
|
50
|
+
description:
|
|
51
|
+
"The file system action to perform, available actions are: read_file, write_file, delete_file, list_directory",
|
|
52
|
+
},
|
|
53
|
+
path: { type: "string", description: "The path to the file or directory to operate on" },
|
|
54
|
+
content: {
|
|
55
|
+
type: "string",
|
|
56
|
+
description: "The content to write to the file, required for write_file action",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
required: ["action", "path"],
|
|
60
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
+
import { stringify as yamlStringify } from "yaml";
|
|
4
5
|
import { getFilteredOptions, validateSelection } from "../utils/conflict-detector.mjs";
|
|
5
6
|
import {
|
|
6
7
|
DEPTH_RECOMMENDATION_LOGIC,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
detectSystemLanguage,
|
|
16
17
|
getAvailablePaths,
|
|
17
18
|
getProjectInfo,
|
|
19
|
+
isGlobPattern,
|
|
18
20
|
validatePath,
|
|
19
21
|
} from "../utils/utils.mjs";
|
|
20
22
|
|
|
@@ -34,7 +36,9 @@ export default async function init(
|
|
|
34
36
|
) {
|
|
35
37
|
if (skipIfExists) {
|
|
36
38
|
const filePath = join(outputPath, fileName);
|
|
37
|
-
|
|
39
|
+
const configContent = await readFile(filePath, "utf8").catch(() => null);
|
|
40
|
+
// Only skip if file exists AND has non-empty content
|
|
41
|
+
if (configContent && configContent.trim() !== "") {
|
|
38
42
|
return {};
|
|
39
43
|
}
|
|
40
44
|
}
|
|
@@ -228,17 +232,18 @@ export default async function init(
|
|
|
228
232
|
// 8. Source code paths
|
|
229
233
|
console.log("\n🔍 [8/8]: Source Code Paths");
|
|
230
234
|
console.log("Enter paths to analyze for documentation (e.g., ./src, ./lib)");
|
|
235
|
+
console.log("💡 You can also enter glob patterns (e.g., src/**/*.js, **/*.md)");
|
|
231
236
|
console.log("💡 If no paths are configured, './' will be used as default");
|
|
232
237
|
|
|
233
238
|
const sourcePaths = [];
|
|
234
239
|
while (true) {
|
|
235
240
|
const selectedPath = await options.prompts.search({
|
|
236
|
-
message: "Path:",
|
|
241
|
+
message: "Path or glob pattern:",
|
|
237
242
|
source: async (input) => {
|
|
238
243
|
if (!input || input.trim() === "") {
|
|
239
244
|
return [
|
|
240
245
|
{
|
|
241
|
-
name:
|
|
246
|
+
name: _PRESS_ENTER_TO_FINISH,
|
|
242
247
|
value: "",
|
|
243
248
|
description: "",
|
|
244
249
|
},
|
|
@@ -247,35 +252,71 @@ export default async function init(
|
|
|
247
252
|
|
|
248
253
|
const searchTerm = input.trim();
|
|
249
254
|
|
|
255
|
+
// Check if input looks like a glob pattern
|
|
256
|
+
const isGlobPatternResult = isGlobPattern(searchTerm);
|
|
257
|
+
|
|
258
|
+
if (isGlobPatternResult) {
|
|
259
|
+
// If it looks like a glob pattern, allow direct input
|
|
260
|
+
return [
|
|
261
|
+
{
|
|
262
|
+
name: `Use glob pattern: ${searchTerm}`,
|
|
263
|
+
value: searchTerm,
|
|
264
|
+
description: "Glob pattern for file matching",
|
|
265
|
+
},
|
|
266
|
+
];
|
|
267
|
+
}
|
|
268
|
+
|
|
250
269
|
// Search for matching files and folders in current directory
|
|
251
270
|
const availablePaths = getAvailablePaths(searchTerm);
|
|
252
271
|
|
|
253
|
-
|
|
272
|
+
// Also add option to use as glob pattern
|
|
273
|
+
const options = [...availablePaths];
|
|
274
|
+
if (searchTerm.length > 0) {
|
|
275
|
+
options.unshift({
|
|
276
|
+
name: `Use as glob pattern: ${searchTerm}`,
|
|
277
|
+
value: searchTerm,
|
|
278
|
+
description: "Treat input as glob pattern",
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return options;
|
|
254
283
|
},
|
|
255
284
|
});
|
|
256
285
|
|
|
257
286
|
// Check if user chose to exit
|
|
258
|
-
if (!selectedPath || selectedPath.trim() === "" || selectedPath ===
|
|
287
|
+
if (!selectedPath || selectedPath.trim() === "" || selectedPath === _PRESS_ENTER_TO_FINISH) {
|
|
259
288
|
break;
|
|
260
289
|
}
|
|
261
290
|
|
|
262
291
|
const trimmedPath = selectedPath.trim();
|
|
263
292
|
|
|
264
|
-
//
|
|
265
|
-
const
|
|
293
|
+
// Check if it's a glob pattern
|
|
294
|
+
const isGlobPatternResult = isGlobPattern(trimmedPath);
|
|
266
295
|
|
|
267
|
-
if (
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
296
|
+
if (isGlobPatternResult) {
|
|
297
|
+
// For glob patterns, just add them without validation
|
|
298
|
+
if (sourcePaths.includes(trimmedPath)) {
|
|
299
|
+
console.log(`⚠️ Pattern already exists: ${trimmedPath}`);
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
sourcePaths.push(trimmedPath);
|
|
303
|
+
} else {
|
|
304
|
+
// Use validatePath to check if path is valid for regular paths
|
|
305
|
+
const validation = validatePath(trimmedPath);
|
|
306
|
+
|
|
307
|
+
if (!validation.isValid) {
|
|
308
|
+
console.log(`⚠️ ${validation.error}`);
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
271
311
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
312
|
+
// Avoid duplicate paths
|
|
313
|
+
if (sourcePaths.includes(trimmedPath)) {
|
|
314
|
+
console.log(`⚠️ Path already exists: ${trimmedPath}`);
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
277
317
|
|
|
278
|
-
|
|
318
|
+
sourcePaths.push(trimmedPath);
|
|
319
|
+
}
|
|
279
320
|
}
|
|
280
321
|
|
|
281
322
|
// If no paths entered, use default
|
|
@@ -324,114 +365,142 @@ export default async function init(
|
|
|
324
365
|
* @param {Object} input - Input object
|
|
325
366
|
* @returns {string} YAML string
|
|
326
367
|
*/
|
|
327
|
-
function generateYAML(input) {
|
|
328
|
-
|
|
368
|
+
export function generateYAML(input) {
|
|
369
|
+
// Create the main configuration object that will be safely serialized
|
|
370
|
+
const config = {
|
|
371
|
+
// Project information (safely handled by yaml library)
|
|
372
|
+
projectName: input.projectName || "",
|
|
373
|
+
projectDesc: input.projectDesc || "",
|
|
374
|
+
projectLogo: input.projectLogo || "",
|
|
375
|
+
|
|
376
|
+
// Documentation configuration
|
|
377
|
+
documentPurpose: input.documentPurpose || [],
|
|
378
|
+
targetAudienceTypes: input.targetAudienceTypes || [],
|
|
379
|
+
readerKnowledgeLevel: input.readerKnowledgeLevel || "",
|
|
380
|
+
documentationDepth: input.documentationDepth || "",
|
|
381
|
+
|
|
382
|
+
// Custom rules and target audience (empty for user to fill)
|
|
383
|
+
rules: "",
|
|
384
|
+
targetAudience: "",
|
|
385
|
+
|
|
386
|
+
// Language settings
|
|
387
|
+
locale: input.locale || "en",
|
|
388
|
+
translateLanguages: input.translateLanguages?.filter((lang) => lang.trim()) || [],
|
|
389
|
+
|
|
390
|
+
// Paths
|
|
391
|
+
docsDir: input.docsDir || "./aigne/doc-smith/docs",
|
|
392
|
+
sourcesPath: input.sourcesPath || [],
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
// Generate comments and structure
|
|
396
|
+
let yaml = "# Project information for documentation publishing\n";
|
|
329
397
|
|
|
330
|
-
//
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
398
|
+
// Serialize the project info section safely
|
|
399
|
+
const projectSection = yamlStringify({
|
|
400
|
+
projectName: config.projectName,
|
|
401
|
+
projectDesc: config.projectDesc,
|
|
402
|
+
projectLogo: config.projectLogo,
|
|
403
|
+
}).trim();
|
|
336
404
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
yaml +=
|
|
405
|
+
yaml += `${projectSection}\n\n`;
|
|
406
|
+
|
|
407
|
+
// Add documentation configuration with comments
|
|
408
|
+
yaml += "# =============================================================================\n";
|
|
409
|
+
yaml += "# Documentation Configuration\n";
|
|
410
|
+
yaml += "# =============================================================================\n\n";
|
|
341
411
|
|
|
342
412
|
// Document Purpose with all available options
|
|
343
|
-
yaml +=
|
|
344
|
-
yaml +=
|
|
413
|
+
yaml += "# Purpose: What's the main outcome you want readers to achieve?\n";
|
|
414
|
+
yaml += "# Available options (uncomment and modify as needed):\n";
|
|
345
415
|
Object.entries(DOCUMENT_STYLES).forEach(([key, style]) => {
|
|
346
416
|
if (key !== "custom") {
|
|
347
417
|
yaml += `# ${key.padEnd(16)} - ${style.name}: ${style.description}\n`;
|
|
348
418
|
}
|
|
349
419
|
});
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
yaml += `\n`;
|
|
420
|
+
|
|
421
|
+
// Safely serialize documentPurpose
|
|
422
|
+
const documentPurposeSection = yamlStringify({ documentPurpose: config.documentPurpose }).trim();
|
|
423
|
+
yaml += `${documentPurposeSection.replace(/^documentPurpose:/, "documentPurpose:")}\n\n`;
|
|
357
424
|
|
|
358
425
|
// Target Audience Types with all available options
|
|
359
|
-
yaml +=
|
|
360
|
-
yaml +=
|
|
426
|
+
yaml += "# Target Audience: Who will be reading this most often?\n";
|
|
427
|
+
yaml += "# Available options (uncomment and modify as needed):\n";
|
|
361
428
|
Object.entries(TARGET_AUDIENCES).forEach(([key, audience]) => {
|
|
362
429
|
if (key !== "custom") {
|
|
363
430
|
yaml += `# ${key.padEnd(16)} - ${audience.name}: ${audience.description}\n`;
|
|
364
431
|
}
|
|
365
432
|
});
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
}
|
|
372
|
-
yaml += `\n`;
|
|
433
|
+
|
|
434
|
+
// Safely serialize targetAudienceTypes
|
|
435
|
+
const targetAudienceTypesSection = yamlStringify({
|
|
436
|
+
targetAudienceTypes: config.targetAudienceTypes,
|
|
437
|
+
}).trim();
|
|
438
|
+
yaml += `${targetAudienceTypesSection.replace(/^targetAudienceTypes:/, "targetAudienceTypes:")}\n\n`;
|
|
373
439
|
|
|
374
440
|
// Reader Knowledge Level with all available options
|
|
375
|
-
yaml +=
|
|
376
|
-
yaml +=
|
|
441
|
+
yaml += "# Reader Knowledge Level: What do readers typically know when they arrive?\n";
|
|
442
|
+
yaml += "# Available options (uncomment and modify as needed):\n";
|
|
377
443
|
Object.entries(READER_KNOWLEDGE_LEVELS).forEach(([key, level]) => {
|
|
378
444
|
yaml += `# ${key.padEnd(20)} - ${level.name}: ${level.description}\n`;
|
|
379
445
|
});
|
|
380
|
-
|
|
381
|
-
|
|
446
|
+
|
|
447
|
+
// Safely serialize readerKnowledgeLevel
|
|
448
|
+
const readerKnowledgeLevelSection = yamlStringify({
|
|
449
|
+
readerKnowledgeLevel: config.readerKnowledgeLevel,
|
|
450
|
+
}).trim();
|
|
451
|
+
yaml += `${readerKnowledgeLevelSection.replace(/^readerKnowledgeLevel:/, "readerKnowledgeLevel:")}\n\n`;
|
|
382
452
|
|
|
383
453
|
// Documentation Depth with all available options
|
|
384
|
-
yaml +=
|
|
385
|
-
yaml +=
|
|
454
|
+
yaml += "# Documentation Depth: How comprehensive should the documentation be?\n";
|
|
455
|
+
yaml += "# Available options (uncomment and modify as needed):\n";
|
|
386
456
|
Object.entries(DOCUMENTATION_DEPTH).forEach(([key, depth]) => {
|
|
387
457
|
yaml += `# ${key.padEnd(18)} - ${depth.name}: ${depth.description}\n`;
|
|
388
458
|
});
|
|
389
|
-
|
|
390
|
-
|
|
459
|
+
|
|
460
|
+
// Safely serialize documentationDepth
|
|
461
|
+
const documentationDepthSection = yamlStringify({
|
|
462
|
+
documentationDepth: config.documentationDepth,
|
|
463
|
+
}).trim();
|
|
464
|
+
yaml += `${documentationDepthSection.replace(/^documentationDepth:/, "documentationDepth:")}\n\n`;
|
|
391
465
|
|
|
392
466
|
// Custom Documentation Rules and Requirements
|
|
393
|
-
yaml +=
|
|
394
|
-
|
|
395
|
-
|
|
467
|
+
yaml += "# Custom Rules: Define specific documentation generation rules and requirements\n";
|
|
468
|
+
const rulesSection = yamlStringify({ rules: config.rules }).trim();
|
|
469
|
+
// Use literal style for multiline strings
|
|
470
|
+
yaml += `${rulesSection.replace(/rules: ''/, "rules: |\n ")}\n\n`;
|
|
396
471
|
|
|
397
472
|
// Target Audience Description
|
|
398
|
-
yaml +=
|
|
399
|
-
|
|
400
|
-
|
|
473
|
+
yaml += "# Target Audience: Describe your specific target audience and their characteristics\n";
|
|
474
|
+
const targetAudienceSection = yamlStringify({ targetAudience: config.targetAudience }).trim();
|
|
475
|
+
// Use literal style for multiline strings
|
|
476
|
+
yaml += `${targetAudienceSection.replace(/targetAudience: ''/, "targetAudience: |\n ")}\n\n`;
|
|
401
477
|
|
|
402
478
|
// Glossary Configuration
|
|
403
|
-
yaml +=
|
|
404
|
-
yaml +=
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
yaml +=
|
|
409
|
-
|
|
410
|
-
//
|
|
411
|
-
if (
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
yaml += `translateLanguages:\n`;
|
|
417
|
-
input.translateLanguages.forEach((lang) => {
|
|
418
|
-
if (lang.trim()) {
|
|
419
|
-
yaml += ` - ${lang}\n`;
|
|
420
|
-
}
|
|
421
|
-
});
|
|
479
|
+
yaml += "# Glossary: Define project-specific terms and definitions\n";
|
|
480
|
+
yaml += '# glossary: "@glossary.md" # Path to markdown file containing glossary definitions\n\n';
|
|
481
|
+
|
|
482
|
+
// Language settings - safely serialize
|
|
483
|
+
const localeSection = yamlStringify({ locale: config.locale }).trim();
|
|
484
|
+
yaml += `${localeSection.replace(/^locale:/, "locale:")}\n`;
|
|
485
|
+
|
|
486
|
+
// Translation languages
|
|
487
|
+
if (config.translateLanguages.length > 0) {
|
|
488
|
+
const translateLanguagesSection = yamlStringify({
|
|
489
|
+
translateLanguages: config.translateLanguages,
|
|
490
|
+
}).trim();
|
|
491
|
+
yaml += `${translateLanguagesSection.replace(/^translateLanguages:/, "translateLanguages:")}\n`;
|
|
422
492
|
} else {
|
|
423
|
-
yaml +=
|
|
424
|
-
yaml +=
|
|
425
|
-
yaml +=
|
|
493
|
+
yaml += "# translateLanguages: # List of languages to translate the documentation to\n";
|
|
494
|
+
yaml += "# - zh # Example: Chinese translation\n";
|
|
495
|
+
yaml += "# - en # Example: English translation\n";
|
|
426
496
|
}
|
|
427
497
|
|
|
428
|
-
//
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
});
|
|
498
|
+
// Directory and source path configurations - safely serialize
|
|
499
|
+
const docsDirSection = yamlStringify({ docsDir: config.docsDir }).trim();
|
|
500
|
+
yaml += `${docsDirSection.replace(/^docsDir:/, "docsDir:")} # Directory to save generated documentation\n`;
|
|
501
|
+
|
|
502
|
+
const sourcesPathSection = yamlStringify({ sourcesPath: config.sourcesPath }).trim();
|
|
503
|
+
yaml += `${sourcesPathSection.replace(/^sourcesPath:/, "sourcesPath: # Source code paths to analyze")}\n`;
|
|
435
504
|
|
|
436
505
|
return yaml;
|
|
437
506
|
}
|
package/agents/load-config.mjs
CHANGED
|
@@ -31,11 +31,6 @@ export default async function loadConfig({ config, appUrl }) {
|
|
|
31
31
|
const processedConfig = processConfigFields(parsedConfig);
|
|
32
32
|
|
|
33
33
|
return {
|
|
34
|
-
nodeName: "Section",
|
|
35
|
-
locale: "en",
|
|
36
|
-
sourcesPath: ["./"],
|
|
37
|
-
docsDir: "./.aigne/doc-smith/docs",
|
|
38
|
-
outputDir: "./.aigne/doc-smith/output",
|
|
39
34
|
lastGitHead: parsedConfig.lastGitHead || "",
|
|
40
35
|
...parsedConfig,
|
|
41
36
|
...processedConfig,
|