@aigne/doc-smith 0.0.2 → 0.1.1
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 +22 -0
- package/README.md +11 -5
- package/agents/check-structure-planning-result.yaml +1 -1
- package/agents/check-structure-planning.mjs +4 -4
- package/agents/detail-generator-and-translate.yaml +1 -1
- package/agents/detail-regenerator.yaml +4 -2
- package/agents/docs-generator.yaml +5 -2
- package/agents/find-item-by-path.mjs +5 -5
- package/agents/load-sources.mjs +30 -8
- package/agents/structure-planning.yaml +1 -1
- package/agents/team-publish-docs.yaml +3 -0
- package/aigne.yaml +17 -0
- package/docs-mcp/analyze-content-relevance.yaml +50 -0
- package/docs-mcp/analyze-docs-relevance.yaml +59 -0
- package/docs-mcp/docs-search.yaml +40 -0
- package/docs-mcp/get-docs-detail.mjs +2 -3
- package/docs-mcp/get-docs-structure.mjs +8 -3
- package/docs-mcp/read-doc-content.mjs +93 -0
- package/package.json +7 -7
- package/prompts/check-structure-planning-result.md +7 -5
- package/prompts/structure-planning.md +3 -1
- package/docs-mcp/aigne.yaml +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.1](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.1.0...v0.1.1) (2025-07-31)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* agent add alias ([7e25014](https://github.com/AIGNE-io/aigne-doc-smith/commit/7e250147309849fe0f4cc554077134d2e443d344))
|
|
9
|
+
* docs mcp add doc search ([de96e0e](https://github.com/AIGNE-io/aigne-doc-smith/commit/de96e0e08455831dc6918d5fbc59d38b6a921373))
|
|
10
|
+
* polish code ([8cb0a5c](https://github.com/AIGNE-io/aigne-doc-smith/commit/8cb0a5ce67cf009c672b2fb1aa9b89ef6d965a86))
|
|
11
|
+
|
|
12
|
+
## [0.1.0](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.0.2...v0.1.0) (2025-07-31)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* add entry agents for mcp server and cli ([fa85d65](https://github.com/AIGNE-io/aigne-doc-smith/commit/fa85d651e8dc723e2b97150fc2258b115c6c5bb0))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* polish command param ([#3](https://github.com/AIGNE-io/aigne-doc-smith/issues/3)) ([003f6b8](https://github.com/AIGNE-io/aigne-doc-smith/commit/003f6b8ae2c9e1af55ba1841458fa8567a0eb2f0))
|
|
23
|
+
* polish docs mcp agent ([8654cd4](https://github.com/AIGNE-io/aigne-doc-smith/commit/8654cd4ea38034f3af0244f56b27acf66ba704e1))
|
|
24
|
+
|
|
3
25
|
## 0.0.2 (2025-07-30)
|
|
4
26
|
|
|
5
27
|
|
package/README.md
CHANGED
|
@@ -64,14 +64,14 @@ npx --no doc-smith run --entry-agent init
|
|
|
64
64
|
npx --no doc-smith run --entry-agent generator --model gemini:gemini-2.5-flash
|
|
65
65
|
|
|
66
66
|
# 重新生成单篇
|
|
67
|
-
npx --no doc-smith run --entry-agent regenerator --input-path bitnet-
|
|
67
|
+
npx --no doc-smith run --entry-agent regenerator --input-path bitnet-getting-started
|
|
68
68
|
|
|
69
69
|
# 结构规划优化
|
|
70
|
-
npx --no doc-smith run --
|
|
70
|
+
npx --no doc-smith run --entry-agent generator --input-feedback "补充节点的 sourceIds,确保所有节点 sourceIds 都有值" --model gemini:gemini-2.5-pro
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
# 发布文档
|
|
74
|
-
npx --no doc-smith run --
|
|
74
|
+
npx --no doc-smith run --entry-agent publish
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
```
|
|
@@ -83,14 +83,20 @@ npx --no doc-smith run --input @./doc-smith/config.yaml --format yaml --entry-ag
|
|
|
83
83
|
aigne doc init
|
|
84
84
|
|
|
85
85
|
# 生成文档
|
|
86
|
-
aigne doc
|
|
86
|
+
aigne doc generate
|
|
87
|
+
|
|
88
|
+
# 优化结构规划
|
|
89
|
+
aigne doc generate --feedback "删除 About 文档"
|
|
87
90
|
|
|
88
91
|
# 优化单篇文档
|
|
89
|
-
|
|
92
|
+
# 可使用 structure-plan.json 中的 path ,或 Discuss Kit 中访问的 path
|
|
93
|
+
aigne doc update --doc-path /faq --feedback "添加更多的 FAQ"
|
|
90
94
|
|
|
91
95
|
# 发布文档
|
|
92
96
|
aigne doc publish
|
|
93
97
|
|
|
98
|
+
# 将文档作为 MCP Server
|
|
99
|
+
aigne doc serve-mcp
|
|
94
100
|
|
|
95
101
|
```
|
|
96
102
|
|
|
@@ -9,11 +9,11 @@ import { OpenAIChatModel } from "@aigne/openai";
|
|
|
9
9
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
10
|
|
|
11
11
|
export default async function checkStructurePlanning(
|
|
12
|
-
{ originalStructurePlan,
|
|
12
|
+
{ originalStructurePlan, feedback, ...rest },
|
|
13
13
|
options
|
|
14
14
|
) {
|
|
15
15
|
// If originalStructurePlan exists, return directly
|
|
16
|
-
if (originalStructurePlan && !
|
|
16
|
+
if (originalStructurePlan && !feedback) {
|
|
17
17
|
return {
|
|
18
18
|
structurePlan: originalStructurePlan,
|
|
19
19
|
};
|
|
@@ -39,14 +39,14 @@ export default async function checkStructurePlanning(
|
|
|
39
39
|
const panningAgent = aigne.agents["reflective-structure-planner"];
|
|
40
40
|
|
|
41
41
|
const result = await options.context.invoke(panningAgent, {
|
|
42
|
-
|
|
42
|
+
feedback: feedback || "",
|
|
43
43
|
originalStructurePlan,
|
|
44
44
|
...rest,
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
return {
|
|
48
48
|
...result,
|
|
49
|
-
|
|
49
|
+
feedback: "", // clear feedback
|
|
50
50
|
originalStructurePlan: originalStructurePlan
|
|
51
51
|
? originalStructurePlan
|
|
52
52
|
: JSON.parse(JSON.stringify(result.structurePlan || [])),
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
type: team
|
|
2
|
-
name:
|
|
2
|
+
name: update
|
|
3
|
+
alias:
|
|
4
|
+
- up
|
|
3
5
|
description: Optimize and regenerate individual document content and translations
|
|
4
6
|
skills:
|
|
5
7
|
- ./load-config.mjs
|
|
@@ -43,7 +45,7 @@ input_schema:
|
|
|
43
45
|
glossary:
|
|
44
46
|
type: string
|
|
45
47
|
description: Glossary of terms for consistent terminology
|
|
46
|
-
path:
|
|
48
|
+
doc-path:
|
|
47
49
|
type: string
|
|
48
50
|
description: Document path to regenerate
|
|
49
51
|
feedback:
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
type: team
|
|
2
|
-
name:
|
|
2
|
+
name: generate
|
|
3
|
+
alias:
|
|
4
|
+
- gen
|
|
5
|
+
- g
|
|
3
6
|
description: Automatically generates comprehensive project documentation
|
|
4
7
|
skills:
|
|
5
8
|
- ./load-config.mjs
|
|
@@ -94,7 +97,7 @@ input_schema:
|
|
|
94
97
|
# type: string
|
|
95
98
|
# description: Type of documentation (general, getting-started, reference, faq)
|
|
96
99
|
# default: general
|
|
97
|
-
|
|
100
|
+
feedback:
|
|
98
101
|
type: string
|
|
99
102
|
description: Feedback for structure planning adjustments
|
|
100
103
|
# labels:
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
export default async function findItemByPath({
|
|
2
|
-
path,
|
|
2
|
+
"doc-path": docPath,
|
|
3
3
|
structurePlanResult,
|
|
4
4
|
boardId,
|
|
5
5
|
}) {
|
|
6
6
|
let foundItem = null;
|
|
7
7
|
|
|
8
8
|
// First try direct path matching
|
|
9
|
-
foundItem = structurePlanResult.find((item) => item.path ===
|
|
9
|
+
foundItem = structurePlanResult.find((item) => item.path === docPath);
|
|
10
10
|
|
|
11
11
|
// If not found and boardId is provided, try boardId-flattenedPath format matching
|
|
12
12
|
if (!foundItem && boardId) {
|
|
13
13
|
// Check if path starts with boardId followed by a dash
|
|
14
|
-
if (
|
|
14
|
+
if (docPath.startsWith(`${boardId}-`)) {
|
|
15
15
|
// Extract the flattened path part after boardId-
|
|
16
|
-
const flattenedPath =
|
|
16
|
+
const flattenedPath = docPath.substring(boardId.length + 1);
|
|
17
17
|
|
|
18
18
|
// Find item by comparing flattened paths
|
|
19
19
|
foundItem = structurePlanResult.find((item) => {
|
|
@@ -28,7 +28,7 @@ export default async function findItemByPath({
|
|
|
28
28
|
|
|
29
29
|
if (!foundItem) {
|
|
30
30
|
throw new Error(
|
|
31
|
-
`Item with path "${
|
|
31
|
+
`Item with path "${docPath}" not found in structurePlanResult`
|
|
32
32
|
);
|
|
33
33
|
}
|
|
34
34
|
|
package/agents/load-sources.mjs
CHANGED
|
@@ -155,7 +155,8 @@ export default async function loadSources({
|
|
|
155
155
|
excludePatterns,
|
|
156
156
|
outputDir,
|
|
157
157
|
docsDir,
|
|
158
|
-
|
|
158
|
+
"doc-path": docPath,
|
|
159
|
+
boardId,
|
|
159
160
|
useDefaultPatterns = true,
|
|
160
161
|
} = {}) {
|
|
161
162
|
let files = Array.isArray(sources) ? [...sources] : [];
|
|
@@ -250,15 +251,32 @@ export default async function loadSources({
|
|
|
250
251
|
|
|
251
252
|
// Get the last output result of the specified path
|
|
252
253
|
let content;
|
|
253
|
-
if (
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
254
|
+
if (docPath) {
|
|
255
|
+
let fileFullName;
|
|
256
|
+
|
|
257
|
+
// First try direct path matching (original format)
|
|
258
|
+
const flatName = docPath.replace(/^\//, "").replace(/\//g, "-");
|
|
259
|
+
fileFullName = `${flatName}.md`;
|
|
260
|
+
let filePath = path.join(docsDir, fileFullName);
|
|
261
|
+
|
|
257
262
|
try {
|
|
258
263
|
await access(filePath);
|
|
259
264
|
content = await readFile(filePath, "utf8");
|
|
260
265
|
} catch {
|
|
261
|
-
//
|
|
266
|
+
// If not found and boardId is provided, try boardId-flattenedPath format
|
|
267
|
+
if (boardId && docPath.startsWith(`${boardId}-`)) {
|
|
268
|
+
// Extract the flattened path part after boardId-
|
|
269
|
+
const flattenedPath = docPath.substring(boardId.length + 1);
|
|
270
|
+
fileFullName = `${flattenedPath}.md`;
|
|
271
|
+
filePath = path.join(docsDir, fileFullName);
|
|
272
|
+
|
|
273
|
+
try {
|
|
274
|
+
await access(filePath);
|
|
275
|
+
content = await readFile(filePath, "utf8");
|
|
276
|
+
} catch {
|
|
277
|
+
// The file does not exist, content remains undefined
|
|
278
|
+
}
|
|
279
|
+
}
|
|
262
280
|
}
|
|
263
281
|
}
|
|
264
282
|
|
|
@@ -298,9 +316,13 @@ loadSources.input_schema = {
|
|
|
298
316
|
description:
|
|
299
317
|
"Whether to use default include/exclude patterns. Defaults to true.",
|
|
300
318
|
},
|
|
301
|
-
|
|
319
|
+
"doc-path": {
|
|
320
|
+
type: "string",
|
|
321
|
+
description: "The document path to load content for",
|
|
322
|
+
},
|
|
323
|
+
boardId: {
|
|
302
324
|
type: "string",
|
|
303
|
-
description: "The
|
|
325
|
+
description: "The board ID for boardId-flattenedPath format matching",
|
|
304
326
|
},
|
|
305
327
|
},
|
|
306
328
|
required: [],
|
package/aigne.yaml
CHANGED
|
@@ -29,3 +29,20 @@ agents:
|
|
|
29
29
|
- ./agents/load-config.mjs
|
|
30
30
|
- ./agents/team-publish-docs.yaml
|
|
31
31
|
- ./agents/find-item-by-path.mjs
|
|
32
|
+
- ./docs-mcp/get-docs-structure.mjs
|
|
33
|
+
- ./docs-mcp/get-docs-detail.mjs
|
|
34
|
+
- ./docs-mcp/docs-search.yaml
|
|
35
|
+
- ./docs-mcp/analyze-docs-relevance.yaml
|
|
36
|
+
- ./docs-mcp/read-doc-content.mjs
|
|
37
|
+
- ./docs-mcp/analyze-content-relevance.yaml
|
|
38
|
+
cli:
|
|
39
|
+
agents:
|
|
40
|
+
- ./agents/input-generator.mjs
|
|
41
|
+
- ./agents/docs-generator.yaml
|
|
42
|
+
- ./agents/detail-regenerator.yaml
|
|
43
|
+
- ./agents/team-publish-docs.yaml
|
|
44
|
+
mcp_server:
|
|
45
|
+
agents:
|
|
46
|
+
- ./docs-mcp/get-docs-structure.mjs
|
|
47
|
+
- ./docs-mcp/get-docs-detail.mjs
|
|
48
|
+
- ./docs-mcp/docs-search.yaml
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: analyze-content-relevance
|
|
2
|
+
description: Analyze document content relevance to user query and extract relevant information
|
|
3
|
+
instructions: |
|
|
4
|
+
You are an AI assistant that analyzes the relevance between user queries and document content.
|
|
5
|
+
|
|
6
|
+
<user-query>
|
|
7
|
+
{{ query }}
|
|
8
|
+
</user-query>
|
|
9
|
+
|
|
10
|
+
<document-content>
|
|
11
|
+
{{ allDocumentsText }}
|
|
12
|
+
</document-content>
|
|
13
|
+
|
|
14
|
+
Given a user query and multiple document contents, your task is to:
|
|
15
|
+
1. Understand the user's specific information needs from the query
|
|
16
|
+
2. Analyze document content for relevance to the query
|
|
17
|
+
3. Extract and synthesize the most relevant information from the documents
|
|
18
|
+
4. Provide a comprehensive answer that directly addresses the user's query
|
|
19
|
+
5. Answer user questions based on the given document content, do not return false or non-existent information
|
|
20
|
+
|
|
21
|
+
Guidelines:
|
|
22
|
+
- Focus on information that directly answers the user's question
|
|
23
|
+
- Extract specific facts, examples, and explanations from the documents
|
|
24
|
+
- Organize the information logically and coherently
|
|
25
|
+
- Include relevant code examples, configuration details, or step-by-step instructions when available
|
|
26
|
+
- Cite the source documents when referencing specific information
|
|
27
|
+
- If multiple documents contain related information, synthesize them into a unified response
|
|
28
|
+
- If no relevant information is found, clearly state this
|
|
29
|
+
|
|
30
|
+
Format your response as a comprehensive answer that:
|
|
31
|
+
- Directly addresses the user's query
|
|
32
|
+
- Includes relevant excerpts from the documents
|
|
33
|
+
- Provides context and explanations where needed
|
|
34
|
+
- Is well-structured and easy to understand
|
|
35
|
+
includeInputInOutput: false
|
|
36
|
+
input_schema:
|
|
37
|
+
type: object
|
|
38
|
+
properties:
|
|
39
|
+
query:
|
|
40
|
+
type: string
|
|
41
|
+
description: User search query
|
|
42
|
+
allDocumentsText:
|
|
43
|
+
type: string
|
|
44
|
+
description: Combined text content of all successfully read documents
|
|
45
|
+
output_schema:
|
|
46
|
+
type: object
|
|
47
|
+
properties:
|
|
48
|
+
relevantContent:
|
|
49
|
+
type: string
|
|
50
|
+
description: Comprehensive answer synthesizing relevant information from documents
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
name: analyze-docs-relevance
|
|
2
|
+
description: Analyze which documents in the structure plan are relevant to the user query
|
|
3
|
+
instructions: |
|
|
4
|
+
You are an AI assistant that analyzes the relevance between a user query and documents in a structure plan.
|
|
5
|
+
|
|
6
|
+
<structure-plan>
|
|
7
|
+
{{ originalStructurePlan }}
|
|
8
|
+
</structure-plan>
|
|
9
|
+
|
|
10
|
+
<user-query>
|
|
11
|
+
{{ query }}
|
|
12
|
+
</user-query>
|
|
13
|
+
|
|
14
|
+
Given a user query and a structure plan containing multiple documents, your task is to:
|
|
15
|
+
1. Understand the user's search intent from the query
|
|
16
|
+
2. Analyze each document in the structure plan to determine relevance
|
|
17
|
+
3. Return a list of relevant documents with their paths, titles, and descriptions
|
|
18
|
+
|
|
19
|
+
Consider the following factors for relevance:
|
|
20
|
+
- Semantic similarity between query and document title/description
|
|
21
|
+
- Topic alignment
|
|
22
|
+
- User intent matching
|
|
23
|
+
- Content scope overlap
|
|
24
|
+
|
|
25
|
+
Return only the most relevant documents (top 5-10) to avoid overwhelming results.
|
|
26
|
+
|
|
27
|
+
Format your response as a JSON object with:
|
|
28
|
+
- relevantDocs: array of relevant document paths
|
|
29
|
+
- reasoning: brief explanation of why these documents were selected
|
|
30
|
+
input_schema:
|
|
31
|
+
type: object
|
|
32
|
+
properties:
|
|
33
|
+
query:
|
|
34
|
+
type: string
|
|
35
|
+
description: User search query
|
|
36
|
+
originalStructurePlan:
|
|
37
|
+
type: array
|
|
38
|
+
items:
|
|
39
|
+
type: object
|
|
40
|
+
properties:
|
|
41
|
+
path:
|
|
42
|
+
type: string
|
|
43
|
+
title:
|
|
44
|
+
type: string
|
|
45
|
+
description:
|
|
46
|
+
type: string
|
|
47
|
+
description: Structure plan containing all available documents
|
|
48
|
+
output_schema:
|
|
49
|
+
type: object
|
|
50
|
+
properties:
|
|
51
|
+
relevantDocPaths:
|
|
52
|
+
type: array
|
|
53
|
+
items:
|
|
54
|
+
type: string
|
|
55
|
+
description: Must be selected from paths in the structure plan, cannot be other paths
|
|
56
|
+
description: List of relevant documents
|
|
57
|
+
reasoning:
|
|
58
|
+
type: string
|
|
59
|
+
description: Brief explanation of document selection
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
type: team
|
|
2
|
+
name: docs-search
|
|
3
|
+
description: Search relevant documents based on user query
|
|
4
|
+
skills:
|
|
5
|
+
- ../agents/load-config.mjs
|
|
6
|
+
- ../agents/load-sources.mjs
|
|
7
|
+
- analyze-docs-relevance.yaml
|
|
8
|
+
- read-doc-content.mjs
|
|
9
|
+
- analyze-content-relevance.yaml
|
|
10
|
+
includeInputInOutput: false
|
|
11
|
+
input_schema:
|
|
12
|
+
type: object
|
|
13
|
+
properties:
|
|
14
|
+
query:
|
|
15
|
+
type: string
|
|
16
|
+
description: User search query
|
|
17
|
+
required: true
|
|
18
|
+
config:
|
|
19
|
+
type: string
|
|
20
|
+
description: Path to the config file
|
|
21
|
+
default: ./doc-smith/config.yaml
|
|
22
|
+
output_schema:
|
|
23
|
+
type: object
|
|
24
|
+
properties:
|
|
25
|
+
relevantContent:
|
|
26
|
+
type: string
|
|
27
|
+
description: AI analyzed relevant content from documents
|
|
28
|
+
relevantDocs:
|
|
29
|
+
type: array
|
|
30
|
+
items:
|
|
31
|
+
type: object
|
|
32
|
+
properties:
|
|
33
|
+
path:
|
|
34
|
+
type: string
|
|
35
|
+
title:
|
|
36
|
+
type: string
|
|
37
|
+
description:
|
|
38
|
+
type: string
|
|
39
|
+
description: List of relevant documents from structure plan
|
|
40
|
+
mode: sequential
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
|
-
const docsDir =
|
|
5
|
-
"/Users/lban/arcblock/code/arcblock-sdk-docs/packages/aigne-framework/docs/";
|
|
4
|
+
const docsDir = path.join(process.cwd(), "doc-smith", "docs");
|
|
6
5
|
|
|
7
6
|
export default async function getDocDetail({ path: docPath }) {
|
|
8
7
|
try {
|
|
@@ -39,4 +38,4 @@ getDocDetail.input_schema = {
|
|
|
39
38
|
},
|
|
40
39
|
};
|
|
41
40
|
|
|
42
|
-
getDocDetail.description = "Get
|
|
41
|
+
getDocDetail.description = "Get single docs detail";
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
2
3
|
|
|
3
|
-
const structureDir =
|
|
4
|
-
|
|
4
|
+
const structureDir = path.join(
|
|
5
|
+
process.cwd(),
|
|
6
|
+
"doc-smith",
|
|
7
|
+
"output",
|
|
8
|
+
"structure-plan.json"
|
|
9
|
+
);
|
|
5
10
|
|
|
6
11
|
export default async function getDocsStructure() {
|
|
7
12
|
const structure = await fs.readFile(structureDir, "utf-8");
|
|
8
13
|
return { structure };
|
|
9
14
|
}
|
|
10
15
|
|
|
11
|
-
getDocsStructure.description = "Get
|
|
16
|
+
getDocsStructure.description = "Get docs structure";
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
const docsDir = path.join(process.cwd(), "doc-smith", "docs");
|
|
5
|
+
|
|
6
|
+
export default async function readDocContent({
|
|
7
|
+
relevantDocPaths,
|
|
8
|
+
docsDir: customDocsDir,
|
|
9
|
+
}) {
|
|
10
|
+
const targetDocsDir = customDocsDir || docsDir;
|
|
11
|
+
const docContents = [];
|
|
12
|
+
|
|
13
|
+
for (const docPath of relevantDocPaths) {
|
|
14
|
+
try {
|
|
15
|
+
// Flatten path: remove leading /, replace all / with - (same logic as utils.mjs)
|
|
16
|
+
const flatName = docPath.replace(/^\//, "").replace(/\//g, "-");
|
|
17
|
+
const fileFullName = `${flatName}.md`;
|
|
18
|
+
const filePath = path.join(targetDocsDir, fileFullName);
|
|
19
|
+
|
|
20
|
+
// Read the markdown file
|
|
21
|
+
const content = await fs.readFile(filePath, "utf8");
|
|
22
|
+
|
|
23
|
+
docContents.push({
|
|
24
|
+
success: true,
|
|
25
|
+
path: docPath,
|
|
26
|
+
content,
|
|
27
|
+
filePath,
|
|
28
|
+
});
|
|
29
|
+
} catch (error) {
|
|
30
|
+
docContents.push({
|
|
31
|
+
success: false,
|
|
32
|
+
path: docPath,
|
|
33
|
+
error: error.message,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Combine all successful document contents into a single text
|
|
39
|
+
const allDocumentsText = docContents
|
|
40
|
+
.filter((doc) => doc.success)
|
|
41
|
+
.map((doc) => doc.content)
|
|
42
|
+
.join("\n\n---\n\n");
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
docContents,
|
|
46
|
+
allDocumentsText,
|
|
47
|
+
totalDocs: relevantDocPaths.length,
|
|
48
|
+
successfulReads: docContents.filter((doc) => doc.success).length,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
readDocContent.input_schema = {
|
|
53
|
+
type: "object",
|
|
54
|
+
properties: {
|
|
55
|
+
relevantDocPaths: {
|
|
56
|
+
type: "array",
|
|
57
|
+
items: { type: "string" },
|
|
58
|
+
description: "List of document paths to read",
|
|
59
|
+
},
|
|
60
|
+
docsDir: {
|
|
61
|
+
type: "string",
|
|
62
|
+
description: "Custom docs directory path (optional)",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
required: ["relevantDocPaths"],
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
readDocContent.output_schema = {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: {
|
|
71
|
+
docContents: {
|
|
72
|
+
type: "array",
|
|
73
|
+
items: {
|
|
74
|
+
type: "object",
|
|
75
|
+
properties: {
|
|
76
|
+
success: { type: "boolean" },
|
|
77
|
+
path: { type: "string" },
|
|
78
|
+
content: { type: "string" },
|
|
79
|
+
filePath: { type: "string" },
|
|
80
|
+
error: { type: "string" },
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
allDocumentsText: {
|
|
85
|
+
type: "string",
|
|
86
|
+
description: "Combined text content of all successfully read documents",
|
|
87
|
+
},
|
|
88
|
+
totalDocs: { type: "number" },
|
|
89
|
+
successfulReads: { type: "number" },
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
readDocContent.description = "Read markdown content for multiple documents";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/doc-smith",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
"author": "Arcblock <blocklet@arcblock.io> https://github.com/blocklet",
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@aigne/anthropic": "^0.10.
|
|
16
|
-
"@aigne/cli": "^1.
|
|
17
|
-
"@aigne/core": "^1.
|
|
18
|
-
"@aigne/gemini": "^0.8.
|
|
19
|
-
"@aigne/openai": "^0.10.
|
|
20
|
-
"@aigne/publish-docs": "^0.5.
|
|
15
|
+
"@aigne/anthropic": "^0.10.4",
|
|
16
|
+
"@aigne/cli": "^1.29.0",
|
|
17
|
+
"@aigne/core": "^1.41.0",
|
|
18
|
+
"@aigne/gemini": "^0.8.8",
|
|
19
|
+
"@aigne/openai": "^0.10.8",
|
|
20
|
+
"@aigne/publish-docs": "^0.5.1",
|
|
21
21
|
"glob": "^11.0.3",
|
|
22
22
|
"open": "^10.2.0",
|
|
23
23
|
"ufo": "^1.6.1",
|
|
@@ -13,16 +13,18 @@
|
|
|
13
13
|
{{ structurePlan }}
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
-
|
|
16
|
+
- **用户反馈**:
|
|
17
17
|
```
|
|
18
|
-
{{
|
|
18
|
+
{{ feedback }}
|
|
19
|
+
|
|
20
|
+
根据最新的 Data Sources 按需要更新节点的 sourceIds ,更新至状态。
|
|
19
21
|
```
|
|
20
22
|
</context>
|
|
21
23
|
|
|
22
24
|
<goal>
|
|
23
25
|
你的主要目标是验证两条关键规则:
|
|
24
26
|
1. **反馈的实现**:新的结构规划**必须**正确地实现用户反馈中要求的所有变更。
|
|
25
|
-
2.
|
|
27
|
+
2. **无关节点的稳定性**:没有在用户反馈中被提及的节点 ** path 属性不能被修改 **。`path` 是关联现有内容的关键标识符,其稳定性至关重要。
|
|
26
28
|
3. **数据有效性**: 所有 {{ nodeName }} 都有关联数据源,sourceIds 中都有值。
|
|
27
29
|
</goal>
|
|
28
30
|
|
|
@@ -35,12 +37,12 @@
|
|
|
35
37
|
这是主要场景。你必须执行详细的比较。
|
|
36
38
|
|
|
37
39
|
**分步分析**:
|
|
38
|
-
1. **分析反馈**:仔细阅读并理解 `<context>` 中
|
|
40
|
+
1. **分析反馈**:仔细阅读并理解 `<context>` 中 用户反馈 提出的每一项变更要求。明确哪些节点是需要被修改、添加或删除的目标。
|
|
39
41
|
2. **验证反馈的实现**:对比 `<context>` 中的 `structurePlan` 和 `originalStructurePlan`,确认所要求的变更是否已执行。例如,如果反馈是“移除‘示例’部分”,你必须检查该部分在 `structurePlan` 中是否已不存在。
|
|
40
42
|
3. **验证无关节点的稳定性**:这是最关键的检查。遍历 `structurePlan` 中的所有节点。对于每一个在 `originalStructurePlan` 中也存在、但并未在反馈中被提及的节点:
|
|
41
43
|
* **至关重要**:其 `path` 属性**必须**与 `originalStructurePlan` 中的完全相同。
|
|
42
44
|
* 理想情况下,其他属性(如 `title`)也应保持稳定,除非这些变更是由某个被要求的变更直接导致的。
|
|
43
|
-
|
|
45
|
+
4. **`sourcesIds` 是允许变更的**,每次结构规划可以根据最新的 DataSources 变更依赖的数据源,sourceIds 不能为空。
|
|
44
46
|
</rules>
|
|
45
47
|
|
|
46
48
|
<output>
|