@aigne/doc-smith 0.8.15 → 0.8.16-beta
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 +13 -0
- package/agents/chat/chat-system.md +32 -0
- package/agents/chat/index.yaml +14 -22
- package/agents/chat/skills/generate-document.yaml +15 -0
- package/agents/chat/skills/update-document.yaml +24 -0
- package/agents/generate/check-need-generate-structure.mjs +4 -0
- package/agents/generate/document-structure-tools/add-document.mjs +5 -1
- package/agents/generate/document-structure-tools/update-document.mjs +7 -0
- package/agents/generate/user-review-document-structure.mjs +44 -29
- package/agents/update/user-review-document.mjs +56 -42
- package/agents/utils/document-title-streamline.yaml +48 -0
- package/agents/utils/list-docs.mjs +15 -0
- package/agents/utils/streamline-document-titles-if-needed.mjs +88 -0
- package/aigne.yaml +5 -1
- package/package.json +2 -1
- package/prompts/common/document-structure/document-title-streamline.md +86 -0
- package/agents/utils/docs-fs-actor.yaml +0 -27
- package/agents/utils/fs.mjs +0 -60
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.8.16-beta](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.15...v0.8.16-beta) (2025-11-10)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* enable AFS for chat agent & improve chat skills ([#281](https://github.com/AIGNE-io/aigne-doc-smith/issues/281)) ([b1c770e](https://github.com/AIGNE-io/aigne-doc-smith/commit/b1c770e60c8866dd08d41ebdd52817c14dd3dd41))
|
|
9
|
+
* implement document title streamlining functionality ([#276](https://github.com/AIGNE-io/aigne-doc-smith/issues/276)) ([918edb8](https://github.com/AIGNE-io/aigne-doc-smith/commit/918edb8f1b2dc03572c4125971092ef0023cd7b3))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* update chat model from aignehub/gemini-2.5-pro to google/gemini-2.5-pro ([#283](https://github.com/AIGNE-io/aigne-doc-smith/issues/283)) ([3559a56](https://github.com/AIGNE-io/aigne-doc-smith/commit/3559a56e49ca3105fd800110b67b3cb3346e3096))
|
|
15
|
+
|
|
3
16
|
## [0.8.15](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.15-beta.16...v0.8.15) (2025-11-07)
|
|
4
17
|
|
|
5
18
|
## [0.8.15-beta.16](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.15-beta.15...v0.8.15-beta.16) (2025-11-07)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
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.
|
|
2
|
+
|
|
3
|
+
Core Capabilities:
|
|
4
|
+
- Generate comprehensive documentation from user inputs and specifications
|
|
5
|
+
- Regenerate and refine document details based on feedback
|
|
6
|
+
- Translate and localize documentation content
|
|
7
|
+
- Publish and manage team documentation workflows
|
|
8
|
+
- Provide interactive guidance throughout the document creation process
|
|
9
|
+
|
|
10
|
+
Interaction Guidelines:
|
|
11
|
+
- Engage users in a professional yet friendly manner
|
|
12
|
+
- Ask clarifying questions to understand specific documentation needs
|
|
13
|
+
- Suggest appropriate skills and workflows based on user requests
|
|
14
|
+
- Provide clear explanations of available capabilities and processes
|
|
15
|
+
- Maintain context throughout multi-step documentation tasks
|
|
16
|
+
- Offer proactive suggestions for improving document quality and structure
|
|
17
|
+
|
|
18
|
+
<skill_usage>
|
|
19
|
+
- afs_xxx skills: AFS(AIGNE File System) skills provide capabilities to explore, read, write and manage files and virtual modules within the AIGNE environment.
|
|
20
|
+
You can use these skills to access source files and other resources needed for documentation tasks.
|
|
21
|
+
- listDocs: This skill lists all available documentation files in the system.
|
|
22
|
+
You can use this skill to get an overview of existing documents before creating or modifying documentation. for documentation tasks,
|
|
23
|
+
you should use this skill rather than afs_read to list documentation files.
|
|
24
|
+
- generateDocument: This skill generates new documentation or updates existing documents structure based on user inputs and specifications,
|
|
25
|
+
You can use this skill to create comprehensive documents from scratch or based on existing templates or update document structure as per user requirements.
|
|
26
|
+
- updateDocument: This skill updates existing documentation content with new information or revisions provided by the user.
|
|
27
|
+
You can use this skill to refine and enhance documents content based on feedback or additional details.
|
|
28
|
+
- publish: This skill publishes completed documentation to an online website to make it accessible to the intended audience.
|
|
29
|
+
You can use this skill to manage the publication process and ensure documents are properly formatted and available.
|
|
30
|
+
- translate: This skill translates documentation content into different languages for localization purposes.
|
|
31
|
+
You can use this skill to adapt documents for diverse audiences by providing translations in the required languages.
|
|
32
|
+
</skill_usage>
|
package/agents/chat/index.yaml
CHANGED
|
@@ -1,30 +1,22 @@
|
|
|
1
1
|
type: ai
|
|
2
2
|
name: chat
|
|
3
3
|
description: Start interactive document generation assistant
|
|
4
|
-
instructions:
|
|
5
|
-
|
|
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
|
|
4
|
+
instructions:
|
|
5
|
+
url: ./chat-system.md
|
|
21
6
|
input_key: message
|
|
22
|
-
|
|
7
|
+
afs:
|
|
8
|
+
modules:
|
|
9
|
+
- module: system-fs
|
|
10
|
+
options:
|
|
11
|
+
path: .
|
|
12
|
+
mount: /source
|
|
13
|
+
description: Project root directory for document generation
|
|
14
|
+
afs_config:
|
|
15
|
+
inject_History: true
|
|
23
16
|
skills:
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
- ../update/index.yaml
|
|
17
|
+
- ./skills/generate-document.yaml
|
|
18
|
+
- ./skills/update-document.yaml
|
|
27
19
|
- ../publish/index.yaml
|
|
28
20
|
- ../translate/index.yaml
|
|
29
|
-
- ../utils/docs-fs-actor.yaml
|
|
30
21
|
- ../utils/exit.mjs
|
|
22
|
+
- ../utils/list-docs.mjs
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type: team
|
|
2
|
+
name: generateDocument
|
|
3
|
+
description: Generate complete documentation for your project, or update/delete existing documents or structure based on user feedback
|
|
4
|
+
input_schema:
|
|
5
|
+
type: object
|
|
6
|
+
properties:
|
|
7
|
+
feedback:
|
|
8
|
+
type: string
|
|
9
|
+
description: How to generate or update the document content
|
|
10
|
+
required:
|
|
11
|
+
- feedback
|
|
12
|
+
skills:
|
|
13
|
+
- url: ../../generate/index.yaml
|
|
14
|
+
default_input:
|
|
15
|
+
isChat: true
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
type: team
|
|
2
|
+
name: updateDocument
|
|
3
|
+
description: Update a existing document based on user feedback
|
|
4
|
+
input_schema:
|
|
5
|
+
type: object
|
|
6
|
+
properties:
|
|
7
|
+
docs:
|
|
8
|
+
type: array
|
|
9
|
+
items:
|
|
10
|
+
type: string
|
|
11
|
+
description: Documents to update, must from listDocs output
|
|
12
|
+
feedback:
|
|
13
|
+
type: string
|
|
14
|
+
description: Tell us what to change in this content
|
|
15
|
+
reset:
|
|
16
|
+
type: boolean
|
|
17
|
+
description: Regenerate the document from scratch, ignoring previous versions
|
|
18
|
+
required:
|
|
19
|
+
- docs
|
|
20
|
+
- feedback
|
|
21
|
+
skills:
|
|
22
|
+
- url: ../../update/index.yaml
|
|
23
|
+
default_input:
|
|
24
|
+
isChat: true
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { getActiveRulesForScope } from "../../utils/preferences-utils.mjs";
|
|
3
3
|
import { getProjectInfo, loadConfigFromFile, saveValueToConfig } from "../../utils/utils.mjs";
|
|
4
|
+
import streamlineDocumentTitlesIfNeeded from "../utils/streamline-document-titles-if-needed.mjs";
|
|
4
5
|
|
|
5
6
|
export default async function checkNeedGenerateStructure(
|
|
6
7
|
{ originalDocumentStructure, forceRegenerate, ...rest },
|
|
@@ -70,6 +71,9 @@ export default async function checkNeedGenerateStructure(
|
|
|
70
71
|
feedback: finalFeedback || "",
|
|
71
72
|
});
|
|
72
73
|
|
|
74
|
+
await streamlineDocumentTitlesIfNeeded({ documentStructure: result.documentStructure }, options);
|
|
75
|
+
options.context.userContext.streamlinedDocumentTitles = true;
|
|
76
|
+
|
|
73
77
|
let message = "";
|
|
74
78
|
|
|
75
79
|
// Check and save project information
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
getAddDocumentOutputJsonSchema,
|
|
4
4
|
validateAddDocumentInput,
|
|
5
5
|
} from "../../../types/document-structure-schema.mjs";
|
|
6
|
+
import streamlineDocumentTitlesIfNeeded from "../../utils/streamline-document-titles-if-needed.mjs";
|
|
6
7
|
|
|
7
8
|
export default async function addDocument(input, options) {
|
|
8
9
|
// Validate input using Zod schema
|
|
@@ -56,7 +57,10 @@ export default async function addDocument(input, options) {
|
|
|
56
57
|
sourceIds: [...sourceIds], // Create a copy of the array
|
|
57
58
|
};
|
|
58
59
|
|
|
59
|
-
//
|
|
60
|
+
// Streamline document titles if needed (will streamline the new document if title > 18 characters)
|
|
61
|
+
await streamlineDocumentTitlesIfNeeded({ documentStructure: [newDocument] }, options);
|
|
62
|
+
|
|
63
|
+
// Add the document to the structure first
|
|
60
64
|
const updatedStructure = [...documentStructure, newDocument];
|
|
61
65
|
|
|
62
66
|
const successMessage = `addDocument executed successfully.
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
getUpdateDocumentOutputJsonSchema,
|
|
4
4
|
validateUpdateDocumentInput,
|
|
5
5
|
} from "../../../types/document-structure-schema.mjs";
|
|
6
|
+
import streamlineDocumentTitlesIfNeeded from "../../utils/streamline-document-titles-if-needed.mjs";
|
|
6
7
|
|
|
7
8
|
export default async function updateDocument(input, options) {
|
|
8
9
|
// Validate input using Zod schema
|
|
@@ -44,6 +45,12 @@ export default async function updateDocument(input, options) {
|
|
|
44
45
|
...(sourceIds !== undefined && { sourceIds: [...sourceIds] }), // Create a copy of the array
|
|
45
46
|
};
|
|
46
47
|
|
|
48
|
+
if (!options.context.userContext.streamlinedDocumentTitles) {
|
|
49
|
+
// Streamline document titles if needed (will streamline the updated document if title > 18 characters)
|
|
50
|
+
await streamlineDocumentTitlesIfNeeded({ documentStructure: [updatedDocument] }, options);
|
|
51
|
+
options.context.userContext.streamlinedDocumentTitles = true;
|
|
52
|
+
}
|
|
53
|
+
|
|
47
54
|
// Update the document in the structure
|
|
48
55
|
const updatedStructure = [...documentStructure];
|
|
49
56
|
updatedStructure[documentIndex] = updatedDocument;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getActiveRulesForScope } from "../../utils/preferences-utils.mjs";
|
|
2
2
|
import { recordUpdate } from "../../utils/history-utils.mjs";
|
|
3
3
|
import { buildDocumentTree } from "../../utils/docs-finder-utils.mjs";
|
|
4
|
+
import equal from "fast-deep-equal";
|
|
4
5
|
|
|
5
6
|
function formatDocumentStructure(structure) {
|
|
6
7
|
const { rootNodes } = buildDocumentTree(structure);
|
|
@@ -49,25 +50,27 @@ export default async function userReviewDocumentStructure({ documentStructure, .
|
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
// Print current documentation structure in a user-friendly format
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
53
|
+
if (!rest.isChat) {
|
|
54
|
+
printDocumentStructure(documentStructure);
|
|
55
|
+
|
|
56
|
+
// Ask user if they want to review the documentation structure
|
|
57
|
+
const needReview = await options.prompts.select({
|
|
58
|
+
message: "Would you like to refine the documentation structure?",
|
|
59
|
+
choices: [
|
|
60
|
+
{
|
|
61
|
+
name: "No, looks good",
|
|
62
|
+
value: "no",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "Yes, optimize the structure (e.g. rename 'Getting Started' to 'Quick Start', move 'API Reference' before 'Configuration')",
|
|
66
|
+
value: "yes",
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
if (needReview === "no") {
|
|
72
|
+
return { documentStructure };
|
|
73
|
+
}
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
let currentStructure = documentStructure;
|
|
@@ -81,15 +84,17 @@ export default async function userReviewDocumentStructure({ documentStructure, .
|
|
|
81
84
|
iterationCount++;
|
|
82
85
|
|
|
83
86
|
// Ask for feedback
|
|
84
|
-
const feedback =
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
87
|
+
const feedback = rest.isChat
|
|
88
|
+
? rest.feedback
|
|
89
|
+
: await options.prompts.input({
|
|
90
|
+
message:
|
|
91
|
+
"How would you like to improve the structure?\n" +
|
|
92
|
+
"Examples:\n" +
|
|
93
|
+
" • Add a new document 'Troubleshooting'\n" +
|
|
94
|
+
" • Remove the 'Legacy Features' document\n" +
|
|
95
|
+
" • Move 'Installation' to the top of the structure\n\n" +
|
|
96
|
+
" Press Enter to finish reviewing:",
|
|
97
|
+
});
|
|
93
98
|
|
|
94
99
|
// If no feedback, break the loop
|
|
95
100
|
if (!feedback?.trim()) {
|
|
@@ -115,7 +120,7 @@ export default async function userReviewDocumentStructure({ documentStructure, .
|
|
|
115
120
|
|
|
116
121
|
try {
|
|
117
122
|
// Call refineDocumentStructure agent with feedback
|
|
118
|
-
await options.context.invoke(refineAgent, {
|
|
123
|
+
const { message } = await options.context.invoke(refineAgent, {
|
|
119
124
|
...rest,
|
|
120
125
|
dataSourceChunk: rest.dataSources[0].dataSourceChunk,
|
|
121
126
|
feedback: feedback.trim(),
|
|
@@ -125,6 +130,12 @@ export default async function userReviewDocumentStructure({ documentStructure, .
|
|
|
125
130
|
|
|
126
131
|
currentStructure = options.context.userContext.currentStructure;
|
|
127
132
|
|
|
133
|
+
if (rest.isChat && equal(currentStructure, documentStructure)) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
`The suggested structure changes did not modify the existing documentation structure. ${message}`,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
128
139
|
// Check if feedback should be saved as user preference
|
|
129
140
|
const feedbackRefinerAgent = options.context.agents["checkFeedbackRefiner"];
|
|
130
141
|
if (feedbackRefinerAgent) {
|
|
@@ -147,6 +158,10 @@ export default async function userReviewDocumentStructure({ documentStructure, .
|
|
|
147
158
|
|
|
148
159
|
// Print current documentation structure in a user-friendly format
|
|
149
160
|
printDocumentStructure(currentStructure);
|
|
161
|
+
|
|
162
|
+
if (rest.isChat) {
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
150
165
|
} catch (error) {
|
|
151
166
|
console.error("Error processing your feedback:");
|
|
152
167
|
console.error(`Type: ${error.name}`);
|
|
@@ -132,7 +132,9 @@ export default async function userReviewDocument({ content, description, ...rest
|
|
|
132
132
|
const title = rest.documentStructure?.find((x) => x.path === rest.path)?.title;
|
|
133
133
|
|
|
134
134
|
// Print current document headings structure
|
|
135
|
-
|
|
135
|
+
if (!rest.isChat) {
|
|
136
|
+
printDocumentHeadings(content, title || "Untitled Document");
|
|
137
|
+
}
|
|
136
138
|
|
|
137
139
|
// Initialize shared context with current content
|
|
138
140
|
options.context.userContext.currentContent = content;
|
|
@@ -140,54 +142,62 @@ export default async function userReviewDocument({ content, description, ...rest
|
|
|
140
142
|
const MAX_ITERATIONS = 100;
|
|
141
143
|
const feedbacks = [];
|
|
142
144
|
let iterationCount = 0;
|
|
145
|
+
|
|
146
|
+
let feedback = "";
|
|
147
|
+
|
|
143
148
|
while (iterationCount < MAX_ITERATIONS) {
|
|
149
|
+
feedback = "";
|
|
144
150
|
iterationCount++;
|
|
145
151
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
152
|
+
if (rest.isChat && rest.feedback) {
|
|
153
|
+
feedback = rest.feedback;
|
|
154
|
+
} else {
|
|
155
|
+
// Ask user what they want to do
|
|
156
|
+
const action = await options.prompts.select({
|
|
157
|
+
message: "What would you like to do next?",
|
|
158
|
+
choices: [
|
|
159
|
+
{
|
|
160
|
+
name: "View document",
|
|
161
|
+
value: "view",
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: "Give feedback",
|
|
165
|
+
value: "feedback",
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: "Done",
|
|
169
|
+
value: "finish",
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
});
|
|
164
173
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
174
|
+
if (action === "finish") {
|
|
175
|
+
break;
|
|
176
|
+
} else if (action === "view") {
|
|
177
|
+
await showDocumentDetail(
|
|
178
|
+
options.context.userContext.currentContent,
|
|
179
|
+
title || "Untitled Document",
|
|
180
|
+
);
|
|
181
|
+
}
|
|
173
182
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
183
|
+
// Ask for feedback
|
|
184
|
+
feedback = await options.prompts.input({
|
|
185
|
+
message:
|
|
186
|
+
"How would you like to improve this document?\n" +
|
|
187
|
+
"Examples:\n" +
|
|
188
|
+
" • Add troubleshooting section for common errors\n" +
|
|
189
|
+
" • Simplify the explanation for beginners\n" +
|
|
190
|
+
" • Remove the outdated information about version 1.0\n\n" +
|
|
191
|
+
" Your feedback:",
|
|
192
|
+
});
|
|
184
193
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
194
|
+
// If no feedback, finish the loop
|
|
195
|
+
if (!feedback?.trim()) {
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
189
198
|
|
|
190
|
-
|
|
199
|
+
feedbacks.push(feedback.trim());
|
|
200
|
+
}
|
|
191
201
|
|
|
192
202
|
// Get the updateDocument agent
|
|
193
203
|
const updateAgent = options.context.agents["handleDocumentUpdate"];
|
|
@@ -236,6 +246,10 @@ export default async function userReviewDocument({ content, description, ...rest
|
|
|
236
246
|
options.context.userContext.currentContent,
|
|
237
247
|
title || "Untitled Document",
|
|
238
248
|
);
|
|
249
|
+
|
|
250
|
+
if (rest.isChat) {
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
239
253
|
} catch (error) {
|
|
240
254
|
console.error("Error processing your feedback:");
|
|
241
255
|
console.error(`Type: ${error.name}`);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: documentTitleStreamline
|
|
2
|
+
description: Streamline document titles by shortening them while preserving meaning for better sidebar navigation
|
|
3
|
+
model:
|
|
4
|
+
reasoning_effort: low
|
|
5
|
+
task_render_mode: hide
|
|
6
|
+
instructions:
|
|
7
|
+
url: ../../prompts/common/document-structure/document-title-streamline.md
|
|
8
|
+
input_schema:
|
|
9
|
+
type: object
|
|
10
|
+
properties:
|
|
11
|
+
documentList:
|
|
12
|
+
type: array
|
|
13
|
+
items:
|
|
14
|
+
type: object
|
|
15
|
+
properties:
|
|
16
|
+
path:
|
|
17
|
+
type: string
|
|
18
|
+
description: Document path for mapping purposes
|
|
19
|
+
title:
|
|
20
|
+
type: string
|
|
21
|
+
description: Document title to streamline
|
|
22
|
+
required:
|
|
23
|
+
- path
|
|
24
|
+
- title
|
|
25
|
+
description: List of document items with titles to streamline
|
|
26
|
+
required:
|
|
27
|
+
- documentList
|
|
28
|
+
output_schema:
|
|
29
|
+
type: object
|
|
30
|
+
properties:
|
|
31
|
+
documentList:
|
|
32
|
+
type: array
|
|
33
|
+
items:
|
|
34
|
+
type: object
|
|
35
|
+
properties:
|
|
36
|
+
path:
|
|
37
|
+
type: string
|
|
38
|
+
description: Document path (same as input for mapping)
|
|
39
|
+
title:
|
|
40
|
+
type: string
|
|
41
|
+
description: Streamlined document title (max 24 characters for English, 12 characters for character-based languages)
|
|
42
|
+
required:
|
|
43
|
+
- path
|
|
44
|
+
- title
|
|
45
|
+
description: List of streamlined document items with shortened titles
|
|
46
|
+
required:
|
|
47
|
+
- documentList
|
|
48
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getMainLanguageFiles } from "../../utils/docs-finder-utils.mjs";
|
|
2
|
+
import init from "../init/index.mjs";
|
|
3
|
+
|
|
4
|
+
export default async function listDocs(_, options) {
|
|
5
|
+
const config = await init({ checkOnly: true }, options);
|
|
6
|
+
|
|
7
|
+
// Get all main language .md files in docsDir
|
|
8
|
+
const mainLanguageFiles = await getMainLanguageFiles(config.docsDir, config.locale);
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
documents: mainLanguageFiles,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
listDocs.description = "List all available documentation files";
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if a string contains character-based language characters (Chinese, Japanese, Korean, etc.)
|
|
3
|
+
* @param {string} str - String to check
|
|
4
|
+
* @returns {boolean} - True if string contains character-based language characters
|
|
5
|
+
*/
|
|
6
|
+
function isCharacterBasedLanguage(str) {
|
|
7
|
+
if (!str) return false;
|
|
8
|
+
// Check for Chinese, Japanese, Korean, and other character-based languages
|
|
9
|
+
// Chinese: \u4e00-\u9fff (CJK Unified Ideographs)
|
|
10
|
+
// Japanese: \u3040-\u309f (Hiragana), \u30a0-\u30ff (Katakana)
|
|
11
|
+
// Korean: \uac00-\ud7a3 (Hangul Syllables)
|
|
12
|
+
// Thai: \u0e00-\u0e7f
|
|
13
|
+
// Arabic: \u0600-\u06ff
|
|
14
|
+
const characterBasedPattern =
|
|
15
|
+
/[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7a3\u0e00-\u0e7f\u0600-\u06ff]/;
|
|
16
|
+
return characterBasedPattern.test(str);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get character limit based on language type
|
|
21
|
+
* @param {string} title - Title to check
|
|
22
|
+
* @returns {number} - Character limit (24 for English, 12 for character-based languages)
|
|
23
|
+
*/
|
|
24
|
+
function getCharacterLimit(title) {
|
|
25
|
+
return isCharacterBasedLanguage(title) ? 12 : 24;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Streamline document titles if they exceed length limits
|
|
30
|
+
* Reusable function for streamlining document titles in various contexts
|
|
31
|
+
* @param {Object} params
|
|
32
|
+
* @param {Array<{title: string, path: string}>} params.documentStructure - Document structure array
|
|
33
|
+
* @param {Object} options - Agent options with context
|
|
34
|
+
* @returns {Promise<void>} - Modifies documentStructure in place
|
|
35
|
+
*/
|
|
36
|
+
export default async function streamlineDocumentTitlesIfNeeded({ documentStructure }, options) {
|
|
37
|
+
if (!documentStructure || !Array.isArray(documentStructure)) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Filter items that need streamlining based on character count and language type
|
|
42
|
+
// English: > 24 characters, Character-based languages (Chinese, Japanese, etc.): > 12 characters
|
|
43
|
+
const itemsNeedingStreamline = documentStructure.filter((item) => {
|
|
44
|
+
if (!item.title) return false;
|
|
45
|
+
const limit = getCharacterLimit(item.title);
|
|
46
|
+
return item.title.length > limit;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (itemsNeedingStreamline.length === 0) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const documentList = itemsNeedingStreamline.map((item) => ({
|
|
54
|
+
path: item.path,
|
|
55
|
+
title: item.title,
|
|
56
|
+
}));
|
|
57
|
+
|
|
58
|
+
const streamlineAgent = options?.context?.agents?.["documentTitleStreamline"];
|
|
59
|
+
if (!streamlineAgent) {
|
|
60
|
+
console.warn("⚠️ documentTitleStreamline agent not found. Skipping title streamlining.");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
const streamlineResult = await options.context.invoke(streamlineAgent, {
|
|
66
|
+
documentList,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Update the document items with streamlined titles using path as the key
|
|
70
|
+
if (streamlineResult.documentList && Array.isArray(streamlineResult.documentList)) {
|
|
71
|
+
const streamlineMap = new Map(streamlineResult.documentList.map((item) => [item.path, item]));
|
|
72
|
+
|
|
73
|
+
for (const item of documentStructure) {
|
|
74
|
+
const streamlined = streamlineMap.get(item.path);
|
|
75
|
+
if (streamlined) {
|
|
76
|
+
item.title = streamlined.title;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.warn("⚠️ Failed to streamline document titles:", error.message);
|
|
82
|
+
console.warn("Continuing with original titles.");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
streamlineDocumentTitlesIfNeeded.taskTitle = "Streamline document titles if needed";
|
|
87
|
+
streamlineDocumentTitlesIfNeeded.description =
|
|
88
|
+
"Shorten document titles that exceed length limits to make sidebar navigation less crowded";
|
package/aigne.yaml
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
model:
|
|
4
4
|
# model: aignehub/gpt-5
|
|
5
5
|
# model: aignehub/claude-sonnet-4-0
|
|
6
|
-
model:
|
|
6
|
+
model: google/gemini-2.5-pro # reasoning_effort 128-32768
|
|
7
7
|
# https://github.com/AIGNE-io/aigne-framework/blob/main/models/gemini/src/gemini-chat-model.ts#L115
|
|
8
8
|
reasoning_effort:
|
|
9
9
|
$get: reasoningEffort
|
|
@@ -79,6 +79,10 @@ agents:
|
|
|
79
79
|
- ./agents/utils/check-feedback-refiner.mjs
|
|
80
80
|
- ./agents/utils/feedback-refiner.yaml
|
|
81
81
|
- ./agents/utils/analyze-feedback-intent.yaml
|
|
82
|
+
- ./agents/utils/list-docs.mjs
|
|
83
|
+
|
|
84
|
+
- ./agents/utils/document-title-streamline.yaml
|
|
85
|
+
- ./agents/utils/streamline-document-titles-if-needed.mjs
|
|
82
86
|
|
|
83
87
|
# User Preferences & Chat
|
|
84
88
|
- ./agents/prefs/index.mjs
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/doc-smith",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.16-beta",
|
|
4
4
|
"description": "AI-driven documentation generation tool built on the AIGNE Framework",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"debug": "^4.4.1",
|
|
39
39
|
"diff": "^8.0.2",
|
|
40
40
|
"dompurify": "^3.2.6",
|
|
41
|
+
"fast-deep-equal": "^3.1.3",
|
|
41
42
|
"file-type": "^21.0.0",
|
|
42
43
|
"fs-extra": "^11.3.1",
|
|
43
44
|
"glob": "^11.0.3",
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Document Title Streamline
|
|
2
|
+
|
|
3
|
+
<role>
|
|
4
|
+
You are a document title optimizer. Your task is to streamline document titles by shortening them while preserving their original meaning and clarity. The primary goal is to make sidebar navigation less crowded and easier to scan at a glance.
|
|
5
|
+
</role>
|
|
6
|
+
|
|
7
|
+
<input>
|
|
8
|
+
|
|
9
|
+
- documentList: {{documentList}}
|
|
10
|
+
|
|
11
|
+
</input>
|
|
12
|
+
|
|
13
|
+
<streamlining_rules>
|
|
14
|
+
|
|
15
|
+
**Core Requirements:**
|
|
16
|
+
|
|
17
|
+
1. **Title Constraints (Optimized for Sidebar Display):**
|
|
18
|
+
|
|
19
|
+
- **Character-based limits** (not word-based, as character count determines visual width):
|
|
20
|
+
- **For English titles: Maximum 24 characters**
|
|
21
|
+
- **For character-based languages (Chinese, Japanese, etc.): Maximum 12 characters** (half of English limit)
|
|
22
|
+
- **Purpose**: These limits are specifically designed for sidebar navigation display to prevent crowding and improve readability
|
|
23
|
+
- **Why character count, not word count**:
|
|
24
|
+
- Character width is what determines visual space in sidebar navigation
|
|
25
|
+
- English words vary greatly in length (e.g., "API" = 3 chars, "Configuration" = 13 chars)
|
|
26
|
+
- Character count provides more accurate control over sidebar display width
|
|
27
|
+
- Ensures consistent visual width across different languages
|
|
28
|
+
- Must capture the core concept
|
|
29
|
+
- Use concise, clear terminology
|
|
30
|
+
- Preserve key technical terms or proper nouns when essential
|
|
31
|
+
- Remove unnecessary articles (a, an, the) and filler words
|
|
32
|
+
- Keep titles scannable and user-friendly
|
|
33
|
+
- Optimize specifically for sidebar navigation display
|
|
34
|
+
|
|
35
|
+
2. **General Guidelines:**
|
|
36
|
+
|
|
37
|
+
- Maintain consistency in terminology across all items
|
|
38
|
+
- Prioritize clarity over brevity when there's a conflict
|
|
39
|
+
- Keep technical accuracy intact
|
|
40
|
+
- Preserve brand names, product names, and critical keywords
|
|
41
|
+
- Use title case for document titles
|
|
42
|
+
- Consider the document's context and hierarchy when streamlining
|
|
43
|
+
- Focus on making titles easy to scan in a sidebar navigation menu
|
|
44
|
+
|
|
45
|
+
**Optimization Strategies:**
|
|
46
|
+
|
|
47
|
+
- Replace long phrases with shorter equivalents
|
|
48
|
+
- Use common abbreviations when widely understood
|
|
49
|
+
- Remove redundant modifiers
|
|
50
|
+
- Combine related concepts when possible
|
|
51
|
+
- Focus on the most important information
|
|
52
|
+
- Remove unnecessary words that don't add meaning
|
|
53
|
+
|
|
54
|
+
**Important Notes:**
|
|
55
|
+
|
|
56
|
+
- Only streamline the title, descriptions are not modified
|
|
57
|
+
- **Sidebar Display Consideration**: Character-based limits (24 for English, 12 for other languages) are specifically chosen to optimize sidebar navigation display
|
|
58
|
+
- Sidebar navigation typically has limited horizontal space
|
|
59
|
+
- Character count determines visual width, not word count
|
|
60
|
+
- English: 24 characters ≈ 4-5 average words, fits standard sidebar width (250-300px)
|
|
61
|
+
- Character-based languages: 12 characters ≈ same visual width as 24 English characters
|
|
62
|
+
- Shorter titles prevent text wrapping and improve visual scanning
|
|
63
|
+
- These limits ensure titles remain readable and don't crowd the navigation menu
|
|
64
|
+
- The goal is to make sidebar navigation less crowded and more readable
|
|
65
|
+
- Titles should be immediately understandable without reading the full description
|
|
66
|
+
- **Language detection**: Determine the primary language of the title and apply the appropriate character limit
|
|
67
|
+
|
|
68
|
+
</streamlining_rules>
|
|
69
|
+
|
|
70
|
+
<output_rules>
|
|
71
|
+
|
|
72
|
+
Return a JSON object with:
|
|
73
|
+
|
|
74
|
+
- `documentList`: array of streamlined document items, each containing:
|
|
75
|
+
- `path`: the same path from input (for mapping purposes)
|
|
76
|
+
- `title`: shortened title (maximum 24 characters for English, 12 characters for character-based languages, optimized for sidebar display)
|
|
77
|
+
|
|
78
|
+
Ensure each streamlined item:
|
|
79
|
+
- Preserves the exact `path` value from the corresponding input item
|
|
80
|
+
- Maintains the original intent and meaning
|
|
81
|
+
- Uses clear, scannable language
|
|
82
|
+
- Fits within the word/character count constraints
|
|
83
|
+
- Provides enough context for users to understand the document's purpose at a glance
|
|
84
|
+
- Is optimized for sidebar navigation display
|
|
85
|
+
|
|
86
|
+
</output_rules>
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
type: team
|
|
2
|
-
name: docs_fs_actor
|
|
3
|
-
description: File system operations for documentation management
|
|
4
|
-
skills:
|
|
5
|
-
- url: ../init/index.mjs
|
|
6
|
-
default_input:
|
|
7
|
-
skipIfExists: true
|
|
8
|
-
- url: ./fs.mjs
|
|
9
|
-
default_input:
|
|
10
|
-
rootDir:
|
|
11
|
-
$get: docsDir
|
|
12
|
-
input_schema:
|
|
13
|
-
type: object
|
|
14
|
-
properties:
|
|
15
|
-
action:
|
|
16
|
-
type: "string"
|
|
17
|
-
enum: ["read_file", "write_file", "delete_file", "list_directory"]
|
|
18
|
-
description:
|
|
19
|
-
"The file system action to perform, available actions are: read_file, write_file, delete_file, list_directory"
|
|
20
|
-
path:
|
|
21
|
-
type: "string"
|
|
22
|
-
description: "The path to the file or directory to operate on"
|
|
23
|
-
content:
|
|
24
|
-
type: "string"
|
|
25
|
-
description: "The content to write to the file, required for write_file action"
|
|
26
|
-
required: ["action", "path"]
|
|
27
|
-
task_render_mode: hide
|
package/agents/utils/fs.mjs
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
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
|
-
};
|