@aigne/doc-smith 0.2.5 → 0.2.8
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 +26 -0
- package/README.md +1 -0
- package/agents/check-detail-result.mjs +13 -139
- package/agents/check-detail.mjs +4 -6
- package/agents/check-structure-plan.mjs +56 -12
- package/agents/detail-generator-and-translate.yaml +7 -1
- package/agents/detail-regenerator.yaml +3 -1
- package/agents/docs-generator.yaml +2 -1
- package/agents/find-item-by-path.mjs +64 -15
- package/agents/input-generator.mjs +31 -11
- package/agents/language-selector.mjs +89 -0
- package/agents/load-config.mjs +2 -2
- package/agents/load-sources.mjs +13 -40
- package/agents/publish-docs.mjs +47 -161
- package/agents/retranslate.yaml +74 -0
- package/agents/save-docs.mjs +19 -21
- package/agents/save-output.mjs +2 -9
- package/agents/save-single-doc.mjs +20 -1
- package/agents/schema/structure-plan.yaml +1 -1
- package/agents/structure-planning.yaml +6 -0
- package/agents/transform-detail-datasources.mjs +2 -5
- package/agents/translate.yaml +3 -0
- package/aigne.yaml +5 -1
- package/biome.json +13 -3
- package/docs-mcp/get-docs-structure.mjs +1 -1
- package/docs-mcp/read-doc-content.mjs +1 -4
- package/package.json +20 -7
- package/prompts/check-structure-planning-result.md +4 -7
- package/prompts/content-detail-generator.md +1 -2
- package/prompts/structure-planning.md +7 -2
- package/prompts/translator.md +4 -0
- package/tests/check-detail-result.test.mjs +8 -19
- package/tests/load-sources.test.mjs +65 -161
- package/tests/test-all-validation-cases.mjs +741 -0
- package/tests/test-save-docs.mjs +6 -17
- package/utils/constants.mjs +1 -2
- package/utils/markdown-checker.mjs +453 -0
- package/utils/mermaid-validator.mjs +153 -0
- package/utils/mermaid-worker-pool.mjs +250 -0
- package/utils/mermaid-worker.mjs +233 -0
- package/utils/utils.mjs +162 -114
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { shutdownMermaidWorkerPool } from "../utils/mermaid-worker-pool.mjs";
|
|
1
2
|
import { saveDocWithTranslations } from "../utils/utils.mjs";
|
|
2
3
|
|
|
3
4
|
export default async function saveSingleDoc({
|
|
@@ -7,14 +8,32 @@ export default async function saveSingleDoc({
|
|
|
7
8
|
translates,
|
|
8
9
|
labels,
|
|
9
10
|
locale,
|
|
11
|
+
isTranslate = false,
|
|
12
|
+
isShowMessage = false,
|
|
10
13
|
}) {
|
|
11
|
-
const
|
|
14
|
+
const _results = await saveDocWithTranslations({
|
|
12
15
|
path,
|
|
13
16
|
content,
|
|
14
17
|
docsDir,
|
|
15
18
|
translates,
|
|
16
19
|
labels,
|
|
17
20
|
locale,
|
|
21
|
+
isTranslate,
|
|
18
22
|
});
|
|
23
|
+
|
|
24
|
+
if (isShowMessage) {
|
|
25
|
+
// Shutdown mermaid worker pool to ensure clean exit
|
|
26
|
+
try {
|
|
27
|
+
await shutdownMermaidWorkerPool();
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.warn("Failed to shutdown mermaid worker pool:", error.message);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const message = isTranslate
|
|
33
|
+
? `✅ Translation completed successfully`
|
|
34
|
+
: `✅ Document updated successfully`;
|
|
35
|
+
return { message };
|
|
36
|
+
}
|
|
37
|
+
|
|
19
38
|
return {};
|
|
20
39
|
}
|
|
@@ -36,6 +36,12 @@ input_schema:
|
|
|
36
36
|
output_schema:
|
|
37
37
|
type: object
|
|
38
38
|
properties:
|
|
39
|
+
projectName:
|
|
40
|
+
type: string
|
|
41
|
+
description: 根据 DataSources 分析项目名称,注意是原始项目名称
|
|
42
|
+
projectDesc:
|
|
43
|
+
type: string
|
|
44
|
+
description: 根据 DataSources 分析生成当前项目描述,为原始项目生成描述,描述简洁,不超过 50 个单词
|
|
39
45
|
structurePlan: ./schema/structure-plan.yaml
|
|
40
46
|
structurePlanTree:
|
|
41
47
|
type: string
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { normalizePath, toRelativePath } from "../utils/utils.mjs";
|
|
2
2
|
|
|
3
|
-
export default function transformDetailDatasources({
|
|
4
|
-
sourceIds,
|
|
5
|
-
datasourcesList,
|
|
6
|
-
}) {
|
|
3
|
+
export default function transformDetailDatasources({ sourceIds, datasourcesList }) {
|
|
7
4
|
// Build a map for fast lookup, with path normalization for compatibility
|
|
8
5
|
const dsMap = Object.fromEntries(
|
|
9
6
|
(datasourcesList || []).map((ds) => {
|
|
10
7
|
const normalizedSourceId = normalizePath(ds.sourceId);
|
|
11
8
|
return [normalizedSourceId, ds.content];
|
|
12
|
-
})
|
|
9
|
+
}),
|
|
13
10
|
);
|
|
14
11
|
|
|
15
12
|
// Collect formatted contents in order, with path normalization
|
package/agents/translate.yaml
CHANGED
package/aigne.yaml
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
chat_model:
|
|
4
4
|
provider: google
|
|
5
|
-
name: gemini-2.5-pro
|
|
5
|
+
# name: gemini-2.5-pro
|
|
6
|
+
name: gemini-2.5-flash
|
|
6
7
|
temperature: 0.8
|
|
7
8
|
agents:
|
|
8
9
|
- ./agents/structure-planning.yaml
|
|
@@ -28,6 +29,8 @@ agents:
|
|
|
28
29
|
- ./agents/load-config.mjs
|
|
29
30
|
- ./agents/team-publish-docs.yaml
|
|
30
31
|
- ./agents/find-item-by-path.mjs
|
|
32
|
+
- ./agents/retranslate.yaml
|
|
33
|
+
- ./agents/language-selector.mjs
|
|
31
34
|
- ./docs-mcp/get-docs-structure.mjs
|
|
32
35
|
- ./docs-mcp/get-docs-detail.mjs
|
|
33
36
|
- ./docs-mcp/docs-search.yaml
|
|
@@ -40,6 +43,7 @@ cli:
|
|
|
40
43
|
- ./agents/docs-generator.yaml
|
|
41
44
|
- ./agents/detail-regenerator.yaml
|
|
42
45
|
- ./agents/team-publish-docs.yaml
|
|
46
|
+
- ./agents/retranslate.yaml
|
|
43
47
|
mcp_server:
|
|
44
48
|
agents:
|
|
45
49
|
- ./docs-mcp/get-docs-structure.mjs
|
package/biome.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://biomejs.dev/schemas/2.1.
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.1.4/schema.json",
|
|
3
3
|
"vcs": {
|
|
4
4
|
"enabled": true,
|
|
5
5
|
"clientKind": "git",
|
|
@@ -23,11 +23,21 @@
|
|
|
23
23
|
"noUnusedVariables": "error",
|
|
24
24
|
"noUnusedImports": "error",
|
|
25
25
|
"noUnusedFunctionParameters": "error",
|
|
26
|
-
"noUnusedPrivateClassMembers": "error"
|
|
26
|
+
"noUnusedPrivateClassMembers": "error",
|
|
27
|
+
"noUndeclaredVariables": "error",
|
|
28
|
+
"noUnreachable": "error",
|
|
29
|
+
"noSelfAssign": "error"
|
|
27
30
|
},
|
|
28
31
|
"suspicious": {
|
|
29
32
|
"noConfusingVoidType": "off",
|
|
30
|
-
"noExplicitAny": "off"
|
|
33
|
+
"noExplicitAny": "off",
|
|
34
|
+
"noDoubleEquals": "error",
|
|
35
|
+
"noGlobalAssign": "error",
|
|
36
|
+
"noAssignInExpressions": "warn"
|
|
37
|
+
},
|
|
38
|
+
"style": {
|
|
39
|
+
"useNodejsImportProtocol": "error",
|
|
40
|
+
"useTemplate": "error"
|
|
31
41
|
},
|
|
32
42
|
"complexity": {
|
|
33
43
|
"noForEach": "off",
|
|
@@ -3,10 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
|
|
4
4
|
const docsDir = path.join(process.cwd(), "./.aigne/doc-smith", "docs");
|
|
5
5
|
|
|
6
|
-
export default async function readDocContent({
|
|
7
|
-
relevantDocPaths,
|
|
8
|
-
docsDir: customDocsDir,
|
|
9
|
-
}) {
|
|
6
|
+
export default async function readDocContent({ relevantDocPaths, docsDir: customDocsDir }) {
|
|
10
7
|
const targetDocsDir = customDocsDir || docsDir;
|
|
11
8
|
const docContents = [];
|
|
12
9
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/doc-smith",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -12,19 +12,32 @@
|
|
|
12
12
|
"author": "Arcblock <blocklet@arcblock.io> https://github.com/blocklet",
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@aigne/
|
|
16
|
-
"@aigne/
|
|
17
|
-
"@aigne/
|
|
18
|
-
"@aigne/
|
|
19
|
-
"@aigne/
|
|
20
|
-
"@aigne/
|
|
15
|
+
"@aigne/aigne-hub": "^0.4.9",
|
|
16
|
+
"@aigne/anthropic": "^0.11.0",
|
|
17
|
+
"@aigne/cli": "^1.34.0",
|
|
18
|
+
"@aigne/core": "^1.49.0",
|
|
19
|
+
"@aigne/gemini": "^0.9.0",
|
|
20
|
+
"@aigne/openai": "^0.11.0",
|
|
21
|
+
"@aigne/publish-docs": "^0.5.4",
|
|
21
22
|
"chalk": "^5.5.0",
|
|
23
|
+
"dompurify": "^3.2.6",
|
|
22
24
|
"glob": "^11.0.3",
|
|
25
|
+
"jsdom": "^26.1.0",
|
|
26
|
+
"mermaid": "^11.9.0",
|
|
23
27
|
"open": "^10.2.0",
|
|
28
|
+
"remark-gfm": "^4.0.1",
|
|
29
|
+
"remark-lint": "^10.0.1",
|
|
30
|
+
"remark-parse": "^11.0.0",
|
|
24
31
|
"terminal-link": "^4.0.0",
|
|
25
32
|
"ufo": "^1.6.1",
|
|
33
|
+
"unified": "^11.0.5",
|
|
34
|
+
"unist-util-visit": "^5.0.0",
|
|
35
|
+
"vfile": "^6.0.3",
|
|
26
36
|
"yaml": "^2.8.0"
|
|
27
37
|
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@biomejs/biome": "^2.1.4"
|
|
40
|
+
},
|
|
28
41
|
"scripts": {
|
|
29
42
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
30
43
|
"lint": "biome check && pnpm -r run lint",
|
|
@@ -16,15 +16,13 @@
|
|
|
16
16
|
- **用户反馈**:
|
|
17
17
|
```
|
|
18
18
|
{{ feedback }}
|
|
19
|
-
|
|
20
|
-
根据最新的 Data Sources 按需要更新节点的 sourceIds。
|
|
21
19
|
```
|
|
22
20
|
</context>
|
|
23
21
|
|
|
24
22
|
<goal>
|
|
25
|
-
|
|
23
|
+
你的主要目标是验证三条关键规则:
|
|
26
24
|
1. **反馈的实现**:新的结构规划**必须**正确地实现用户反馈中要求的所有变更。
|
|
27
|
-
2. **无关节点的稳定性**:没有在用户反馈中被提及的节点 ** path 属性不能被修改 **。`path` 是关联现有内容的关键标识符,其稳定性至关重要。
|
|
25
|
+
2. **无关节点的稳定性**:没有在用户反馈中被提及的节点 ** path、sourcesIds 属性不能被修改 **。`path`、`sourcesIds` 是关联现有内容的关键标识符,其稳定性至关重要。
|
|
28
26
|
3. **数据有效性**: 所有 {{ nodeName }} 都有关联数据源,sourceIds 中都有值。
|
|
29
27
|
</goal>
|
|
30
28
|
|
|
@@ -40,9 +38,8 @@
|
|
|
40
38
|
1. **分析反馈**:仔细阅读并理解 `<context>` 中 用户反馈 提出的每一项变更要求。明确哪些节点是需要被修改、添加或删除的目标。
|
|
41
39
|
2. **验证反馈的实现**:对比 `<context>` 中的 `structurePlan` 和 `originalStructurePlan`,确认所要求的变更是否已执行。例如,如果反馈是“移除‘示例’部分”,你必须检查该部分在 `structurePlan` 中是否已不存在。
|
|
42
40
|
3. **验证无关节点的稳定性**:这是最关键的检查。遍历 `structurePlan` 中的所有节点。对于每一个在 `originalStructurePlan` 中也存在、但并未在反馈中被提及的节点:
|
|
43
|
-
* **至关重要**:其 `path` 属性**必须**与 `originalStructurePlan` 中的完全相同。
|
|
44
|
-
* 理想情况下,其他属性(如 `title
|
|
45
|
-
4. **`sourcesIds` 是允许变更的**,每次结构规划可以根据最新的 DataSources 变更依赖的数据源,sourceIds 不能为空。
|
|
41
|
+
* **至关重要**:其 `path`、`sourcesIds` 属性**必须**与 `originalStructurePlan` 中的完全相同。
|
|
42
|
+
* 理想情况下,其他属性(如 `title`、`description`)也应保持稳定,除非这些变更是由某个被要求的变更直接导致的,或者是 DataSource 变更导致。
|
|
46
43
|
</rules>
|
|
47
44
|
|
|
48
45
|
<output>
|
|
@@ -27,10 +27,15 @@
|
|
|
27
27
|
{{originalStructurePlan}}
|
|
28
28
|
</last_structure_plan>
|
|
29
29
|
|
|
30
|
+
<last_structure_plan_rule>
|
|
31
|
+
如果提供了上一轮生成的结构规划(last_structure_plan),需要遵循以下规则:
|
|
32
|
+
1. **反馈的实现**:新的结构规划**必须**正确地实现用户反馈中要求的所有变更。
|
|
33
|
+
2. **无关节点的稳定性**:没有在用户反馈中被提及的节点 ** path、sourcesIds 属性不能被修改 **。`path`、`sourcesIds` 是关联现有内容的关键标识符,其稳定性至关重要。
|
|
34
|
+
理想情况下,其他属性(如 `title`、`description`)也应保持稳定,除非这些变更是由某个被要求的变更直接导致的,或者是 DataSource 变更导致。
|
|
35
|
+
</last_structure_plan_rule>
|
|
36
|
+
|
|
30
37
|
<structure_plan_feedback>
|
|
31
38
|
{{ feedback }}
|
|
32
|
-
|
|
33
|
-
根据最新的 Data Sources 按需要更新节点的 sourceIds,如没有大的变化,可以不更新。
|
|
34
39
|
</structure_plan_feedback>
|
|
35
40
|
|
|
36
41
|
<review_structure_plan>
|
package/prompts/translator.md
CHANGED
|
@@ -23,28 +23,21 @@ async function runTests() {
|
|
|
23
23
|
const content = "This contains a [dead link](/dead-link).";
|
|
24
24
|
const result = await checkDetailResult({ structurePlan, content });
|
|
25
25
|
assert(result.isApproved === false, "Should not be approved");
|
|
26
|
-
assert(
|
|
27
|
-
result.detailFeedback.includes("Found a dead link"),
|
|
28
|
-
"Should report dead link"
|
|
29
|
-
);
|
|
26
|
+
assert(result.detailFeedback.includes("Found a dead link"), "Should report dead link");
|
|
30
27
|
console.log("✅ Test passed: should reject content with a dead link");
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
async function testRejectIncorrectTableSeparator() {
|
|
34
|
-
console.log(
|
|
35
|
-
"Testing: should reject content with incorrect table separator"
|
|
36
|
-
);
|
|
31
|
+
console.log("Testing: should reject content with incorrect table separator");
|
|
37
32
|
const structurePlan = [];
|
|
38
33
|
const content = "| Header | Header |\n| - | - |\n| Cell | Cell |";
|
|
39
34
|
const result = await checkDetailResult({ structurePlan, content });
|
|
40
35
|
assert(result.isApproved === false, "Should not be approved");
|
|
41
36
|
assert(
|
|
42
37
|
result.detailFeedback.includes("incorrect table separator"),
|
|
43
|
-
"Should report incorrect table separator"
|
|
44
|
-
);
|
|
45
|
-
console.log(
|
|
46
|
-
"✅ Test passed: should reject content with incorrect table separator"
|
|
38
|
+
"Should report incorrect table separator",
|
|
47
39
|
);
|
|
40
|
+
console.log("✅ Test passed: should reject content with incorrect table separator");
|
|
48
41
|
}
|
|
49
42
|
|
|
50
43
|
async function testApproveExternalLink() {
|
|
@@ -60,17 +53,13 @@ async function runTests() {
|
|
|
60
53
|
async function testRejectMultipleIssues() {
|
|
61
54
|
console.log("Testing: should reject content with multiple issues");
|
|
62
55
|
const structurePlan = [{ path: "/getting-started" }];
|
|
63
|
-
const content =
|
|
64
|
-
"This has a [dead link](/dead-link) and an incorrect table: | - |.";
|
|
56
|
+
const content = "This has a [dead link](/dead-link) and an incorrect table: | - |.";
|
|
65
57
|
const result = await checkDetailResult({ structurePlan, content });
|
|
66
58
|
assert(result.isApproved === false, "Should not be approved");
|
|
67
|
-
assert(
|
|
68
|
-
result.detailFeedback.includes("Found a dead link"),
|
|
69
|
-
"Should report dead link"
|
|
70
|
-
);
|
|
59
|
+
assert(result.detailFeedback.includes("Found a dead link"), "Should report dead link");
|
|
71
60
|
assert(
|
|
72
61
|
result.detailFeedback.includes("incorrect table separator"),
|
|
73
|
-
"Should report incorrect table separator"
|
|
62
|
+
"Should report incorrect table separator",
|
|
74
63
|
);
|
|
75
64
|
console.log("✅ Test passed: should reject content with multiple issues");
|
|
76
65
|
}
|
|
@@ -100,4 +89,4 @@ async function runTests() {
|
|
|
100
89
|
}
|
|
101
90
|
}
|
|
102
91
|
|
|
103
|
-
runTests();
|
|
92
|
+
runTests();
|