@aigne/doc-smith 0.2.3 → 0.2.5
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 +14 -0
- package/agents/check-detail-result.mjs +16 -0
- package/agents/detail-regenerator.yaml +3 -56
- package/agents/docs-generator.yaml +3 -60
- package/agents/input-generator.mjs +6 -15
- package/agents/load-config.mjs +3 -3
- package/agents/load-sources.mjs +55 -40
- package/agents/save-docs.mjs +22 -22
- package/agents/save-output.mjs +9 -3
- package/agents/team-publish-docs.yaml +7 -7
- package/docs-mcp/docs-search.yaml +1 -1
- package/docs-mcp/get-docs-detail.mjs +1 -1
- package/docs-mcp/get-docs-structure.mjs +1 -1
- package/docs-mcp/read-doc-content.mjs +1 -1
- package/package.json +1 -1
- package/prompts/document/structure-planning.md +1 -0
- package/utils/constants.mjs +3 -2
- package/utils/utils.mjs +42 -26
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.5](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.2.4...v0.2.5) (2025-08-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* polish cli process ([#17](https://github.com/AIGNE-io/aigne-doc-smith/issues/17)) ([4c94263](https://github.com/AIGNE-io/aigne-doc-smith/commit/4c9426378dff9ca3270bd0e455aa6fb1045f6abb))
|
|
9
|
+
|
|
10
|
+
## [0.2.4](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.2.3...v0.2.4) (2025-08-07)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* polish agent output log ([40a2451](https://github.com/AIGNE-io/aigne-doc-smith/commit/40a245122ce4d8747e5b5dbe88be6986047c38ae))
|
|
16
|
+
|
|
3
17
|
## [0.2.3](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.2.2...v0.2.3) (2025-08-07)
|
|
4
18
|
|
|
5
19
|
|
|
@@ -128,6 +128,22 @@ export default async function checkDetailResult({
|
|
|
128
128
|
`Found backticks in Mermaid node label in ${source} at line ${lineNumber}: "${label}" - backticks in node labels cause rendering issues in Mermaid diagrams`
|
|
129
129
|
);
|
|
130
130
|
}
|
|
131
|
+
|
|
132
|
+
// Check for edge descriptions with numbered list format
|
|
133
|
+
// Pattern: -- "1. description" --> or similar variants
|
|
134
|
+
const edgeDescriptionRegex = /--\s*"([^"]*)"\s*-->/g;
|
|
135
|
+
let edgeMatch;
|
|
136
|
+
|
|
137
|
+
while ((edgeMatch = edgeDescriptionRegex.exec(line)) !== null) {
|
|
138
|
+
const description = edgeMatch[1];
|
|
139
|
+
// Check if description starts with number followed by period
|
|
140
|
+
if (/^\d+\.\s/.test(description)) {
|
|
141
|
+
isApproved = false;
|
|
142
|
+
detailFeedback.push(
|
|
143
|
+
`Unsupported markdown: list - Found numbered list format in Mermaid edge description in ${source} at line ${lineNumber}: "${description}" - numbered lists in edge descriptions are not supported`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
131
147
|
}
|
|
132
148
|
}
|
|
133
149
|
|
|
@@ -31,20 +31,10 @@ skills:
|
|
|
31
31
|
input_schema:
|
|
32
32
|
type: object
|
|
33
33
|
properties:
|
|
34
|
-
config:
|
|
35
|
-
type: string
|
|
36
|
-
description: Path to the config file
|
|
37
|
-
default: ./doc-smith/config.yaml
|
|
38
|
-
# nodeName:
|
|
39
|
-
# type: string
|
|
40
|
-
# description: Name of the section to generate documentation for
|
|
41
|
-
# default: Section
|
|
42
|
-
# locale:
|
|
43
|
-
# type: string
|
|
44
|
-
# description: Primary language for documentation (e.g., zh, en)
|
|
45
|
-
# targetAudience:
|
|
34
|
+
# config:
|
|
46
35
|
# type: string
|
|
47
|
-
# description:
|
|
36
|
+
# description: Path to the config file
|
|
37
|
+
# default: ./.aigne/doc-smith/config.yaml
|
|
48
38
|
glossary:
|
|
49
39
|
type: string
|
|
50
40
|
description: Glossary of terms for consistent terminology
|
|
@@ -54,49 +44,6 @@ input_schema:
|
|
|
54
44
|
feedback:
|
|
55
45
|
type: string
|
|
56
46
|
description: Feedback for content improvement
|
|
57
|
-
# sources:
|
|
58
|
-
# type: array
|
|
59
|
-
# items:
|
|
60
|
-
# type: string
|
|
61
|
-
# description: Source code files for documentation generation
|
|
62
|
-
# sourcesPath:
|
|
63
|
-
# type: array
|
|
64
|
-
# description: Source code paths
|
|
65
|
-
# items:
|
|
66
|
-
# type: string
|
|
67
|
-
# default:
|
|
68
|
-
# - ./
|
|
69
|
-
# includePatterns:
|
|
70
|
-
# type: array
|
|
71
|
-
# description: File patterns to include
|
|
72
|
-
# items:
|
|
73
|
-
# type: string
|
|
74
|
-
# excludePatterns:
|
|
75
|
-
# type: array
|
|
76
|
-
# description: File patterns to exclude
|
|
77
|
-
# items:
|
|
78
|
-
# type: string
|
|
79
|
-
# outputDir:
|
|
80
|
-
# type: string
|
|
81
|
-
# description: Output directory for intermediate files
|
|
82
|
-
# default: ./doc-smith/output
|
|
83
|
-
# docsDir:
|
|
84
|
-
# type: string
|
|
85
|
-
# description: Directory to save generated documentation
|
|
86
|
-
# default: ./doc-smith/docs
|
|
87
|
-
# additionalInformation:
|
|
88
|
-
# type: string
|
|
89
|
-
# description: Additional context or information for documentation
|
|
90
|
-
# translateLanguages:
|
|
91
|
-
# type: array
|
|
92
|
-
# items:
|
|
93
|
-
# type: string
|
|
94
|
-
# description: Target languages for translation (e.g., zh, en)
|
|
95
|
-
# labels:
|
|
96
|
-
# type: array
|
|
97
|
-
# items:
|
|
98
|
-
# type: string
|
|
99
|
-
# description: Tags or labels for categorization
|
|
100
47
|
output_schema:
|
|
101
48
|
type: object
|
|
102
49
|
properties:
|
|
@@ -40,76 +40,19 @@ skills:
|
|
|
40
40
|
input_schema:
|
|
41
41
|
type: object
|
|
42
42
|
properties:
|
|
43
|
-
config:
|
|
44
|
-
type: string
|
|
45
|
-
description: Path to the config file
|
|
46
|
-
default: ./doc-smith/config.yaml
|
|
47
|
-
# nodeName:
|
|
48
|
-
# type: string
|
|
49
|
-
# description: Name of the section to generate documentation for
|
|
50
|
-
# default: Section
|
|
51
|
-
# rules:
|
|
52
|
-
# type: string
|
|
53
|
-
# description: Documentation generation requirements and rules
|
|
54
|
-
# locale:
|
|
55
|
-
# type: string
|
|
56
|
-
# description: Primary language for documentation (e.g., zh, en)
|
|
57
|
-
# sources:
|
|
58
|
-
# type: array
|
|
59
|
-
# items:
|
|
60
|
-
# type: string
|
|
61
|
-
# description: Source code files for documentation generation
|
|
62
|
-
# sourcesPath:
|
|
63
|
-
# type: array
|
|
64
|
-
# description: Source code paths
|
|
65
|
-
# items:
|
|
66
|
-
# type: string
|
|
67
|
-
# default:
|
|
68
|
-
# - ./
|
|
69
|
-
# includePatterns:
|
|
70
|
-
# type: array
|
|
71
|
-
# description: File patterns to include
|
|
72
|
-
# items:
|
|
73
|
-
# type: string
|
|
74
|
-
# excludePatterns:
|
|
75
|
-
# type: array
|
|
76
|
-
# description: File patterns to exclude
|
|
77
|
-
# items:
|
|
78
|
-
# type: string
|
|
79
|
-
# docsDir:
|
|
43
|
+
# config:
|
|
80
44
|
# type: string
|
|
81
|
-
# description:
|
|
82
|
-
# default:
|
|
83
|
-
# outputDir:
|
|
84
|
-
# type: string
|
|
85
|
-
# description: Output directory for intermediate files
|
|
86
|
-
# default: ./doc-smith/output
|
|
87
|
-
# translateLanguages:
|
|
88
|
-
# type: array
|
|
89
|
-
# items:
|
|
90
|
-
# type: string
|
|
91
|
-
# description: Target languages for translation (e.g., zh, en)
|
|
45
|
+
# description: Path to the config file
|
|
46
|
+
# default: ./.aigne/doc-smith/config.yaml
|
|
92
47
|
glossary:
|
|
93
48
|
type: string
|
|
94
49
|
description: Glossary of terms for consistent terminology
|
|
95
|
-
# additionalInformation:
|
|
96
|
-
# type: string
|
|
97
|
-
# description: Additional context or information for documentation
|
|
98
|
-
# docsType:
|
|
99
|
-
# type: string
|
|
100
|
-
# description: Type of documentation (general, getting-started, reference, faq)
|
|
101
|
-
# default: general
|
|
102
50
|
feedback:
|
|
103
51
|
type: string
|
|
104
52
|
description: Feedback for structure planning adjustments
|
|
105
53
|
forceRegenerate:
|
|
106
54
|
type: boolean
|
|
107
55
|
description: Force regenerate all documentation
|
|
108
|
-
# labels:
|
|
109
|
-
# type: array
|
|
110
|
-
# items:
|
|
111
|
-
# type: string
|
|
112
|
-
# description: Tags or labels for categorization
|
|
113
56
|
required:
|
|
114
57
|
- config
|
|
115
58
|
mode: sequential
|
|
@@ -20,7 +20,7 @@ const PRESS_ENTER_TO_FINISH = "Press Enter to finish";
|
|
|
20
20
|
*/
|
|
21
21
|
export default async function init(
|
|
22
22
|
{
|
|
23
|
-
outputPath = "
|
|
23
|
+
outputPath = ".aigne/doc-smith",
|
|
24
24
|
fileName = "config.yaml",
|
|
25
25
|
skipIfExists = false,
|
|
26
26
|
},
|
|
@@ -40,11 +40,9 @@ export default async function init(
|
|
|
40
40
|
const input = {};
|
|
41
41
|
|
|
42
42
|
// 1. Document generation rules with style selection
|
|
43
|
-
console.log("📝 Step 1/6: Document Generation Rules");
|
|
44
|
-
|
|
45
43
|
// Let user select a document style
|
|
46
44
|
const styleChoice = await options.prompts.select({
|
|
47
|
-
message: "Choose your documentation style:",
|
|
45
|
+
message: "📝 Step 1/6: Choose your documentation style:",
|
|
48
46
|
choices: Object.entries(DOCUMENT_STYLES).map(([key, style]) => ({
|
|
49
47
|
name: `${style.name} - ${style.rules}`,
|
|
50
48
|
value: key,
|
|
@@ -65,11 +63,9 @@ export default async function init(
|
|
|
65
63
|
input.rules = rules.trim();
|
|
66
64
|
|
|
67
65
|
// 2. Target audience selection
|
|
68
|
-
console.log("\n👥 Step 2/6: Target Audience");
|
|
69
|
-
|
|
70
66
|
// Let user select target audience
|
|
71
67
|
const audienceChoice = await options.prompts.select({
|
|
72
|
-
message: "Who is your target audience?",
|
|
68
|
+
message: "👥 Step 2/6: Who is your target audience?",
|
|
73
69
|
choices: Object.entries(TARGET_AUDIENCES).map(([key, audience]) => ({
|
|
74
70
|
name: audience,
|
|
75
71
|
value: key,
|
|
@@ -90,11 +86,9 @@ export default async function init(
|
|
|
90
86
|
input.targetAudience = targetAudience.trim();
|
|
91
87
|
|
|
92
88
|
// 3. Language settings
|
|
93
|
-
console.log("\n🌐 Step 3/6: Primary Language");
|
|
94
|
-
|
|
95
89
|
// Let user select primary language from supported list
|
|
96
90
|
const primaryLanguageChoice = await options.prompts.select({
|
|
97
|
-
message: "Choose primary documentation language:",
|
|
91
|
+
message: "🌐 Step 3/6: Choose primary documentation language:",
|
|
98
92
|
choices: SUPPORTED_LANGUAGES.map((lang) => ({
|
|
99
93
|
name: `${lang.label} - ${lang.sample}`,
|
|
100
94
|
value: lang.code,
|
|
@@ -104,15 +98,13 @@ export default async function init(
|
|
|
104
98
|
input.locale = primaryLanguageChoice;
|
|
105
99
|
|
|
106
100
|
// 4. Translation languages
|
|
107
|
-
console.log("\n🔄 Step 4/6: Translation Languages");
|
|
108
|
-
|
|
109
101
|
// Filter out the primary language from available choices
|
|
110
102
|
const availableTranslationLanguages = SUPPORTED_LANGUAGES.filter(
|
|
111
103
|
(lang) => lang.code !== primaryLanguageChoice
|
|
112
104
|
);
|
|
113
105
|
|
|
114
106
|
const translateLanguageChoices = await options.prompts.checkbox({
|
|
115
|
-
message: "Select translation languages:",
|
|
107
|
+
message: "🔄 Step 4/6: Select translation languages:",
|
|
116
108
|
choices: availableTranslationLanguages.map((lang) => ({
|
|
117
109
|
name: `${lang.label} - ${lang.sample}`,
|
|
118
110
|
value: lang.code,
|
|
@@ -122,9 +114,8 @@ export default async function init(
|
|
|
122
114
|
input.translateLanguages = translateLanguageChoices;
|
|
123
115
|
|
|
124
116
|
// 5. Documentation directory
|
|
125
|
-
console.log("\n📁 Step 5/6: Output Directory");
|
|
126
117
|
const docsDirInput = await options.prompts.input({
|
|
127
|
-
message:
|
|
118
|
+
message: `📁 Step 5/6: Where to save generated docs:`,
|
|
128
119
|
default: `${outputPath}/docs`,
|
|
129
120
|
});
|
|
130
121
|
input.docsDir = docsDirInput.trim() || `${outputPath}/docs`;
|
package/agents/load-config.mjs
CHANGED
|
@@ -22,8 +22,8 @@ export default async function loadConfig({ config }) {
|
|
|
22
22
|
nodeName: "Section",
|
|
23
23
|
locale: "en",
|
|
24
24
|
sourcesPath: ["./"],
|
|
25
|
-
|
|
26
|
-
outputDir: "
|
|
25
|
+
docsDir: "./.aigne/doc-smith/docs",
|
|
26
|
+
outputDir: "./.aigne/doc-smith/output",
|
|
27
27
|
lastGitHead: parsedConfig.lastGitHead || "",
|
|
28
28
|
...parsedConfig,
|
|
29
29
|
};
|
|
@@ -38,7 +38,7 @@ loadConfig.input_schema = {
|
|
|
38
38
|
properties: {
|
|
39
39
|
config: {
|
|
40
40
|
type: "string",
|
|
41
|
-
default: "
|
|
41
|
+
default: "./.aigne/doc-smith/config.yaml",
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
44
|
};
|
package/agents/load-sources.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { access, readFile } from "node:fs/promises";
|
|
1
|
+
import { access, readFile, stat } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { glob } from "glob";
|
|
4
4
|
import {
|
|
@@ -115,50 +115,65 @@ export default async function loadSources({
|
|
|
115
115
|
|
|
116
116
|
for (const dir of paths) {
|
|
117
117
|
try {
|
|
118
|
-
//
|
|
119
|
-
const
|
|
118
|
+
// Check if the path is a file or directory
|
|
119
|
+
const stats = await stat(dir);
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
if (stats.isFile()) {
|
|
122
|
+
// If it's a file, add it directly without filtering
|
|
123
|
+
allFiles.push(dir);
|
|
124
|
+
} else if (stats.isDirectory()) {
|
|
125
|
+
// If it's a directory, use the existing glob logic
|
|
126
|
+
// Load .gitignore for this directory
|
|
127
|
+
const gitignorePatterns = await loadGitignore(dir);
|
|
124
128
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
? Array.isArray(includePatterns)
|
|
129
|
-
? includePatterns
|
|
130
|
-
: [includePatterns]
|
|
131
|
-
: [];
|
|
132
|
-
const userExclude = excludePatterns
|
|
133
|
-
? Array.isArray(excludePatterns)
|
|
134
|
-
? excludePatterns
|
|
135
|
-
: [excludePatterns]
|
|
136
|
-
: [];
|
|
129
|
+
// Prepare patterns
|
|
130
|
+
let finalIncludePatterns = null;
|
|
131
|
+
let finalExcludePatterns = null;
|
|
137
132
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
133
|
+
if (useDefaultPatterns) {
|
|
134
|
+
// Merge with default patterns
|
|
135
|
+
const userInclude = includePatterns
|
|
136
|
+
? Array.isArray(includePatterns)
|
|
137
|
+
? includePatterns
|
|
138
|
+
: [includePatterns]
|
|
139
|
+
: [];
|
|
140
|
+
const userExclude = excludePatterns
|
|
141
|
+
? Array.isArray(excludePatterns)
|
|
142
|
+
? excludePatterns
|
|
143
|
+
: [excludePatterns]
|
|
144
|
+
: [];
|
|
145
|
+
|
|
146
|
+
finalIncludePatterns = [
|
|
147
|
+
...DEFAULT_INCLUDE_PATTERNS,
|
|
148
|
+
...userInclude,
|
|
149
|
+
];
|
|
150
|
+
finalExcludePatterns = [
|
|
151
|
+
...DEFAULT_EXCLUDE_PATTERNS,
|
|
152
|
+
...userExclude,
|
|
153
|
+
];
|
|
154
|
+
} else {
|
|
155
|
+
// Use only user patterns
|
|
156
|
+
if (includePatterns) {
|
|
157
|
+
finalIncludePatterns = Array.isArray(includePatterns)
|
|
158
|
+
? includePatterns
|
|
159
|
+
: [includePatterns];
|
|
160
|
+
}
|
|
161
|
+
if (excludePatterns) {
|
|
162
|
+
finalExcludePatterns = Array.isArray(excludePatterns)
|
|
163
|
+
? excludePatterns
|
|
164
|
+
: [excludePatterns];
|
|
165
|
+
}
|
|
151
166
|
}
|
|
152
|
-
}
|
|
153
167
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
168
|
+
// Get files using glob
|
|
169
|
+
const filesInDir = await getFilesWithGlob(
|
|
170
|
+
dir,
|
|
171
|
+
finalIncludePatterns,
|
|
172
|
+
finalExcludePatterns,
|
|
173
|
+
gitignorePatterns
|
|
174
|
+
);
|
|
175
|
+
allFiles = allFiles.concat(filesInDir);
|
|
176
|
+
}
|
|
162
177
|
} catch (err) {
|
|
163
178
|
if (err.code !== "ENOENT") throw err;
|
|
164
179
|
}
|
package/agents/save-docs.mjs
CHANGED
|
@@ -45,41 +45,41 @@ export default async function saveDocs({
|
|
|
45
45
|
console.error("Failed to cleanup invalid .md files:", err.message);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
const message = `## ✅ Documentation Generated Successfully!
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
Successfully generated **${structurePlan.length}** documents and saved to: \`${docsDir}\`
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
### 🚀 Next Steps
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
1. Publish Documentation
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
\`\`\`bash
|
|
57
|
+
aigne doc publish
|
|
58
|
+
\`\`\`
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
Get an online preview link to share with your team
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
### 🔧 Optional Improvements
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
1. Update Specific Documents
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
\`\`\`bash
|
|
67
|
+
aigne doc update
|
|
68
|
+
\`\`\`
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
Regenerate content for specific documents
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
2. Provide Structure Feedback
|
|
73
|
+
\`\`\`bash
|
|
74
|
+
aigne doc generate --feedback "Your feedback on document structure"
|
|
75
|
+
\`\`\`
|
|
76
|
+
Improve the overall documentation structure
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
---
|
|
79
|
+
`;
|
|
80
80
|
|
|
81
81
|
return {
|
|
82
|
-
|
|
82
|
+
message,
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
85
|
|
package/agents/save-output.mjs
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { promises as fs } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
-
export default async function saveOutput({
|
|
5
|
-
|
|
4
|
+
export default async function saveOutput({
|
|
5
|
+
savePath,
|
|
6
|
+
fileName,
|
|
7
|
+
saveKey,
|
|
8
|
+
...rest
|
|
9
|
+
}) {
|
|
6
10
|
if (!(saveKey in rest)) {
|
|
7
11
|
console.warn(`saveKey "${saveKey}" not found in input, skip saving.`);
|
|
8
12
|
return {
|
|
@@ -13,7 +17,9 @@ export default async function saveOutput({ savePath, fileName, saveKey, ...rest
|
|
|
13
17
|
|
|
14
18
|
const value = rest[saveKey];
|
|
15
19
|
const content =
|
|
16
|
-
typeof value === "object" && value !== null
|
|
20
|
+
typeof value === "object" && value !== null
|
|
21
|
+
? JSON.stringify(value, null, 2)
|
|
22
|
+
: String(value);
|
|
17
23
|
await fs.mkdir(savePath, { recursive: true });
|
|
18
24
|
const filePath = join(savePath, fileName);
|
|
19
25
|
await fs.writeFile(filePath, content, "utf8");
|
|
@@ -10,10 +10,10 @@ skills:
|
|
|
10
10
|
skipIfExists: true
|
|
11
11
|
- load-config.mjs
|
|
12
12
|
- publish-docs.mjs
|
|
13
|
-
input_schema:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
# input_schema:
|
|
14
|
+
# type: object
|
|
15
|
+
# properties:
|
|
16
|
+
# config:
|
|
17
|
+
# type: string
|
|
18
|
+
# description: Path to the config file
|
|
19
|
+
# default: ./.aigne/doc-smith/config.yaml
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
|
-
const docsDir = path.join(process.cwd(), "doc-smith", "docs");
|
|
4
|
+
const docsDir = path.join(process.cwd(), "./.aigne/doc-smith", "docs");
|
|
5
5
|
|
|
6
6
|
export default async function getDocDetail({ path: docPath }) {
|
|
7
7
|
try {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
|
-
const docsDir = path.join(process.cwd(), "doc-smith", "docs");
|
|
4
|
+
const docsDir = path.join(process.cwd(), "./.aigne/doc-smith", "docs");
|
|
5
5
|
|
|
6
6
|
export default async function readDocContent({
|
|
7
7
|
relevantDocPaths,
|
package/package.json
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
- 结构规划要精炼,避免同一个功能被拆为了多个部分,当内容足够复杂,放在一起展示过长影响用户阅读时,考虑拆出子层级
|
|
8
8
|
- **第一层 <= 7 项**,层级 <= 3 级;同一层使用统一语义(动词时态、名词单复数)
|
|
9
9
|
- 如果当前部分是存在子文档,当前文档只展示简要的内容,引导用户到子文档中查看详细的内容
|
|
10
|
+
- 如果存在测试相关的代码,可以作为生成文档的参考,**不要为测试代码生成文档**
|
|
10
11
|
- 总是在一开始包含下列内容:
|
|
11
12
|
- Overview:简要说明产品能解决什么,产品能提供什么,产品的结构信息,让用户能快速有一个全面的认识,给出下一步的入口,引导用户阅读
|
|
12
13
|
- Getting Started:内容包含安装、最小运行示例,让用户用通过一部分文档,在很短的时间就能跑通一个最简单的示例
|
package/utils/constants.mjs
CHANGED
|
@@ -25,6 +25,7 @@ export const DEFAULT_INCLUDE_PATTERNS = [
|
|
|
25
25
|
export const DEFAULT_EXCLUDE_PATTERNS = [
|
|
26
26
|
"aigne-docs/**",
|
|
27
27
|
"doc-smith/**",
|
|
28
|
+
".aigne/**",
|
|
28
29
|
"assets/**",
|
|
29
30
|
"data/**",
|
|
30
31
|
"images/**",
|
|
@@ -62,14 +63,14 @@ export const DEFAULT_EXCLUDE_PATTERNS = [
|
|
|
62
63
|
// Supported languages for documentation
|
|
63
64
|
export const SUPPORTED_LANGUAGES = [
|
|
64
65
|
{ code: "en", label: "English (en)", sample: "Hello" },
|
|
65
|
-
{ code: "zh
|
|
66
|
+
{ code: "zh", label: "简体中文 (zh)", sample: "你好" },
|
|
66
67
|
{ code: "zh-TW", label: "繁體中文 (zh-TW)", sample: "你好" },
|
|
67
68
|
{ code: "ja", label: "日本語 (ja)", sample: "こんにちは" },
|
|
68
69
|
{ code: "ko", label: "한국어 (ko)", sample: "안녕하세요" },
|
|
69
70
|
{ code: "es", label: "Español (es)", sample: "Hola" },
|
|
70
71
|
{ code: "fr", label: "Français (fr)", sample: "Bonjour" },
|
|
71
72
|
{ code: "de", label: "Deutsch (de)", sample: "Hallo" },
|
|
72
|
-
{ code: "pt
|
|
73
|
+
{ code: "pt", label: "Português (pt)", sample: "Olá" },
|
|
73
74
|
{ code: "ru", label: "Русский (ru)", sample: "Привет" },
|
|
74
75
|
{ code: "it", label: "Italiano (it)", sample: "Ciao" },
|
|
75
76
|
{ code: "ar", label: "العربية (ar)", sample: "مرحبا" },
|
package/utils/utils.mjs
CHANGED
|
@@ -162,7 +162,7 @@ export async function saveGitHeadToConfig(gitHead) {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
try {
|
|
165
|
-
const docSmithDir = path.join(process.cwd(), "doc-smith");
|
|
165
|
+
const docSmithDir = path.join(process.cwd(), "./.aigne/doc-smith");
|
|
166
166
|
if (!existsSync(docSmithDir)) {
|
|
167
167
|
mkdirSync(docSmithDir, { recursive: true });
|
|
168
168
|
}
|
|
@@ -345,7 +345,11 @@ export function hasFileChangesBetweenCommits(
|
|
|
345
345
|
* @returns {Promise<Object|null>} - The config object or null if file doesn't exist
|
|
346
346
|
*/
|
|
347
347
|
export async function loadConfigFromFile() {
|
|
348
|
-
const configPath = path.join(
|
|
348
|
+
const configPath = path.join(
|
|
349
|
+
process.cwd(),
|
|
350
|
+
"./.aigne/doc-smith",
|
|
351
|
+
"config.yaml"
|
|
352
|
+
);
|
|
349
353
|
|
|
350
354
|
try {
|
|
351
355
|
if (!existsSync(configPath)) {
|
|
@@ -371,7 +375,7 @@ export async function saveValueToConfig(key, value) {
|
|
|
371
375
|
}
|
|
372
376
|
|
|
373
377
|
try {
|
|
374
|
-
const docSmithDir = path.join(process.cwd(), "doc-smith");
|
|
378
|
+
const docSmithDir = path.join(process.cwd(), "./.aigne/doc-smith");
|
|
375
379
|
if (!existsSync(docSmithDir)) {
|
|
376
380
|
mkdirSync(docSmithDir, { recursive: true });
|
|
377
381
|
}
|
|
@@ -472,20 +476,20 @@ export function validatePaths(paths) {
|
|
|
472
476
|
}
|
|
473
477
|
|
|
474
478
|
/**
|
|
475
|
-
* Check if input is a valid directory and add it to results if so
|
|
479
|
+
* Check if input is a valid directory or file and add it to results if so
|
|
476
480
|
* @param {string} searchTerm - The search term to check
|
|
477
481
|
* @param {Array} results - The results array to modify
|
|
478
482
|
*/
|
|
479
|
-
function
|
|
483
|
+
function addExactPathMatch(searchTerm, results) {
|
|
480
484
|
const inputValidation = validatePath(searchTerm);
|
|
481
485
|
if (inputValidation.isValid) {
|
|
482
486
|
const stats = statSync(normalizePath(searchTerm));
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
}
|
|
487
|
+
const isDirectory = stats.isDirectory();
|
|
488
|
+
results.unshift({
|
|
489
|
+
name: searchTerm,
|
|
490
|
+
value: searchTerm,
|
|
491
|
+
description: isDirectory ? "📁 Directory" : "📄 File",
|
|
492
|
+
});
|
|
489
493
|
}
|
|
490
494
|
}
|
|
491
495
|
|
|
@@ -510,7 +514,7 @@ export function getAvailablePaths(userInput = "") {
|
|
|
510
514
|
const dirPath = path.dirname(searchTerm);
|
|
511
515
|
const fileName = path.basename(searchTerm);
|
|
512
516
|
results = getDirectoryContents(dirPath, fileName);
|
|
513
|
-
|
|
517
|
+
addExactPathMatch(searchTerm, results);
|
|
514
518
|
}
|
|
515
519
|
// Handle relative paths
|
|
516
520
|
else if (searchTerm.startsWith("./") || searchTerm.startsWith("../")) {
|
|
@@ -519,7 +523,7 @@ export function getAvailablePaths(userInput = "") {
|
|
|
519
523
|
if (lastSlashIndex === -1) {
|
|
520
524
|
// No slash found, treat as current directory search
|
|
521
525
|
results = getDirectoryContents("./", searchTerm);
|
|
522
|
-
|
|
526
|
+
addExactPathMatch(searchTerm, results);
|
|
523
527
|
} else {
|
|
524
528
|
const dirPath = searchTerm.substring(0, lastSlashIndex + 1);
|
|
525
529
|
const fileName = searchTerm.substring(lastSlashIndex + 1);
|
|
@@ -537,13 +541,13 @@ export function getAvailablePaths(userInput = "") {
|
|
|
537
541
|
}
|
|
538
542
|
|
|
539
543
|
results = getDirectoryContents(dirPath, fileName);
|
|
540
|
-
|
|
544
|
+
addExactPathMatch(searchTerm, results);
|
|
541
545
|
}
|
|
542
546
|
}
|
|
543
547
|
// Handle simple file/directory names (search in current directory)
|
|
544
548
|
else {
|
|
545
549
|
results = getDirectoryContents("./", searchTerm);
|
|
546
|
-
|
|
550
|
+
addExactPathMatch(searchTerm, results);
|
|
547
551
|
}
|
|
548
552
|
|
|
549
553
|
// Remove duplicates based on value (path)
|
|
@@ -571,7 +575,7 @@ export function getAvailablePaths(userInput = "") {
|
|
|
571
575
|
* Get directory contents for a specific path
|
|
572
576
|
* @param {string} dirPath - Directory path to search in
|
|
573
577
|
* @param {string} searchTerm - Optional search term to filter results
|
|
574
|
-
* @returns {Array<Object>} - Array of path objects
|
|
578
|
+
* @returns {Array<Object>} - Array of path objects (both files and directories)
|
|
575
579
|
*/
|
|
576
580
|
function getDirectoryContents(dirPath, searchTerm = "") {
|
|
577
581
|
try {
|
|
@@ -595,7 +599,12 @@ function getDirectoryContents(dirPath, searchTerm = "") {
|
|
|
595
599
|
|
|
596
600
|
for (const entry of entries) {
|
|
597
601
|
const entryName = entry.name;
|
|
598
|
-
|
|
602
|
+
|
|
603
|
+
// Preserve ./ prefix when dirPath is "./"
|
|
604
|
+
let relativePath = path.join(dirPath, entryName);
|
|
605
|
+
if (dirPath?.startsWith("./")) {
|
|
606
|
+
relativePath = `./${relativePath}`;
|
|
607
|
+
}
|
|
599
608
|
|
|
600
609
|
// Filter by search term if provided
|
|
601
610
|
if (
|
|
@@ -618,17 +627,24 @@ function getDirectoryContents(dirPath, searchTerm = "") {
|
|
|
618
627
|
|
|
619
628
|
const isDirectory = entry.isDirectory();
|
|
620
629
|
|
|
621
|
-
//
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
}
|
|
630
|
+
// Include both directories and files
|
|
631
|
+
items.push({
|
|
632
|
+
name: relativePath,
|
|
633
|
+
value: relativePath,
|
|
634
|
+
description: isDirectory ? "📁 Directory" : "📄 File",
|
|
635
|
+
});
|
|
628
636
|
}
|
|
629
637
|
|
|
630
|
-
// Sort alphabetically (
|
|
631
|
-
items.sort((a, b) =>
|
|
638
|
+
// Sort alphabetically (directories first, then files)
|
|
639
|
+
items.sort((a, b) => {
|
|
640
|
+
const aIsDir = a.description === "📁 Directory";
|
|
641
|
+
const bIsDir = b.description === "📁 Directory";
|
|
642
|
+
|
|
643
|
+
if (aIsDir && !bIsDir) return -1;
|
|
644
|
+
if (!aIsDir && bIsDir) return 1;
|
|
645
|
+
|
|
646
|
+
return a.name.localeCompare(b.name);
|
|
647
|
+
});
|
|
632
648
|
|
|
633
649
|
return items;
|
|
634
650
|
} catch (error) {
|