@aigne/doc-smith 0.9.6-beta → 0.9.6-beta.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/agents/create/document-structure-tools/delete-document.mjs +32 -9
  3. package/agents/create/update-document-structure.yaml +1 -1
  4. package/agents/create/user-add-document/add-documents-to-structure.mjs +96 -0
  5. package/agents/create/user-add-document/find-documents-to-add-links.yaml +47 -0
  6. package/agents/create/user-add-document/index.yaml +46 -0
  7. package/agents/create/user-add-document/prepare-documents-to-translate.mjs +22 -0
  8. package/agents/create/user-add-document/print-add-document-summary.mjs +56 -0
  9. package/agents/create/user-add-document/review-documents-with-new-links.mjs +73 -0
  10. package/agents/create/user-remove-document/find-documents-with-invalid-links.mjs +67 -0
  11. package/agents/create/user-remove-document/index.yaml +41 -0
  12. package/agents/create/user-remove-document/prepare-documents-to-translate.mjs +22 -0
  13. package/agents/create/user-remove-document/print-remove-document-summary.mjs +56 -0
  14. package/agents/create/user-remove-document/remove-documents-from-structure.mjs +96 -0
  15. package/agents/create/user-remove-document/review-documents-with-invalid-links.mjs +116 -0
  16. package/agents/create/user-review-document-structure.mjs +1 -40
  17. package/agents/create/utils/init-current-content.mjs +38 -0
  18. package/agents/update/document-tools/update-document-content.mjs +12 -12
  19. package/agents/update/update-document-detail.yaml +5 -1
  20. package/agents/update/update-single/update-single-document-detail.mjs +21 -6
  21. package/agents/update/user-review-document.mjs +10 -13
  22. package/agents/utils/add-translates-to-structure.mjs +29 -0
  23. package/agents/utils/{analyze-feedback-intent.yaml → analyze-document-feedback-intent.yaml} +5 -2
  24. package/agents/utils/analyze-structure-feedback-intent.yaml +29 -0
  25. package/agents/utils/check-detail-result.mjs +2 -14
  26. package/aigne.yaml +10 -1
  27. package/package.json +1 -1
  28. package/prompts/structure/find-documents-to-add-links.md +52 -0
  29. package/prompts/utils/analyze-document-feedback-intent.md +54 -0
  30. package/prompts/utils/analyze-structure-feedback-intent.md +43 -0
  31. package/types/document-schema.mjs +2 -0
  32. package/types/document-structure-schema.mjs +6 -2
  33. package/utils/docs-finder-utils.mjs +82 -0
  34. package/utils/markdown-checker.mjs +50 -5
  35. package/utils/utils.mjs +103 -0
  36. package/prompts/utils/analyze-feedback-intent.md +0 -55
@@ -0,0 +1,96 @@
1
+ import chooseDocs from "../../utils/choose-docs.mjs";
2
+ import deleteDocument from "../document-structure-tools/delete-document.mjs";
3
+ import { DOC_ACTION } from "../../../utils/constants/index.mjs";
4
+ import addTranslatesToStructure from "../../utils/add-translates-to-structure.mjs";
5
+
6
+ export default async function removeDocumentsFromStructure(input = {}, options = {}) {
7
+ const { docsDir, locale = "en", translateLanguages = [], originalDocumentStructure } = input;
8
+
9
+ if (!Array.isArray(originalDocumentStructure) || originalDocumentStructure.length === 0) {
10
+ console.warn(
11
+ "🗑️ Remove Documents\n • No document structure found. Please generate documents first.",
12
+ );
13
+ process.exit(0);
14
+ }
15
+
16
+ const { documentExecutionStructure } = addTranslatesToStructure({
17
+ originalDocumentStructure,
18
+ translateLanguages,
19
+ });
20
+
21
+ // Initialize currentStructure in userContext
22
+ options.context.userContext.currentStructure = [...originalDocumentStructure];
23
+
24
+ // Use chooseDocs to select documents to delete
25
+ const chooseResult = await chooseDocs(
26
+ {
27
+ docs: [],
28
+ documentExecutionStructure,
29
+ docsDir,
30
+ locale,
31
+ isTranslate: false,
32
+ feedback: "no feedback",
33
+ requiredFeedback: false,
34
+ action: DOC_ACTION.clear,
35
+ },
36
+ options,
37
+ );
38
+
39
+ if (!chooseResult?.selectedDocs || chooseResult.selectedDocs.length === 0) {
40
+ console.log("No documents selected for removal.");
41
+ process.exit(0);
42
+ }
43
+
44
+ // Delete each selected document
45
+ const deletedDocuments = [];
46
+ const errors = [];
47
+
48
+ for (const selectedDoc of chooseResult.selectedDocs) {
49
+ try {
50
+ const deleteResult = await deleteDocument(
51
+ {
52
+ path: selectedDoc.path,
53
+ recursive: true,
54
+ },
55
+ options,
56
+ );
57
+
58
+ if (deleteResult.error) {
59
+ errors.push({
60
+ path: selectedDoc.path,
61
+ error: deleteResult.error.message,
62
+ });
63
+ } else {
64
+ // deletedDocuments is now always an array
65
+ deletedDocuments.push(...deleteResult.deletedDocuments);
66
+ }
67
+ } catch (error) {
68
+ errors.push({
69
+ path: selectedDoc.path,
70
+ error: error.message,
71
+ });
72
+ }
73
+ }
74
+
75
+ if (errors.length > 0) {
76
+ console.warn(
77
+ `🗑️ Remove Documents\n • Failed to remove documents:\n${errors
78
+ .map((e) => ` - ${e.path}: ${e.error}`)
79
+ .join("\n")}`,
80
+ );
81
+ process.exit(0);
82
+ }
83
+
84
+ // Get updated document structure
85
+ const updatedStructure = options.context.userContext.currentStructure;
86
+
87
+ return {
88
+ documentStructure: updatedStructure,
89
+ originalDocumentStructure: JSON.parse(JSON.stringify(updatedStructure)),
90
+ deletedDocuments,
91
+ };
92
+ }
93
+
94
+ removeDocumentsFromStructure.taskTitle = "Remove documents from structure";
95
+ removeDocumentsFromStructure.description =
96
+ "Select and remove documents from the documentation structure";
@@ -0,0 +1,116 @@
1
+ import { buildAllowedLinksFromStructure } from "../../../utils/docs-finder-utils.mjs";
2
+
3
+ /**
4
+ * Generate feedback message for fixing invalid links in a document
5
+ */
6
+ function generateInvalidLinksFeedback(invalidLinks, documentPath, documentExecutionStructure) {
7
+ const invalidLinksList = invalidLinks.map((link) => `- ${link}`).join("\n");
8
+
9
+ // Build allowed links from document structure for replacement suggestions
10
+ const allowedLinks = buildAllowedLinksFromStructure(documentExecutionStructure);
11
+ const allowedLinksArray = Array.from(allowedLinks)
12
+ .filter((link) => link !== documentPath) // Exclude current document path
13
+ .sort();
14
+
15
+ const allowedLinksList =
16
+ allowedLinksArray.length > 0
17
+ ? allowedLinksArray.map((link) => `- ${link}`).join("\n")
18
+ : "(No available links)";
19
+
20
+ return `This document contains invalid links that need to be fixed. Please handle them according to the following instructions:
21
+
22
+ **Invalid Links Found:**
23
+ ${invalidLinksList}
24
+
25
+ **Available Valid Links:**
26
+ ${allowedLinksList}
27
+
28
+ **Instructions for fixing invalid links:**
29
+
30
+ 1. For each invalid link found in the document:
31
+ - Using the document context and the list of available valid links, try to find a suitable replacement link from the available valid links.
32
+ - When choosing a replacement, exclude the current document path (${documentPath}); linking to the current document is not logical.
33
+ - **Do not consider the original invalid link or its related text**; they are outdated and should be replaced.
34
+
35
+ 2. If a suitable replacement link is found:
36
+ - Update **all related fields** associated with the invalid link (e.g., link URL, link text, surrounding context) according to the matched link from the available valid links.
37
+ - Ensure that after updating the link, the surrounding content remains consistent and natural. If there is a mismatch, update the corresponding content to keep everything aligned.
38
+
39
+ 3. If no suitable replacement link can be found:
40
+ - Remove the invalid link completely, including the link text and any associated content that only makes sense with that link.
41
+ - **Do not affect other unrelated content** in the document; only remove content that is directly tied to the invalid link.
42
+
43
+ 4. Ensure the document remains coherent and readable after the changes.`;
44
+ }
45
+
46
+ export default async function reviewDocumentsWithInvalidLinks(input = {}, options = {}) {
47
+ const { documentsWithInvalidLinks = [], documentExecutionStructure = [] } = input;
48
+
49
+ // If no documents with invalid links, return empty array
50
+ if (!Array.isArray(documentsWithInvalidLinks) || documentsWithInvalidLinks.length === 0) {
51
+ return {
52
+ documentsWithInvalidLinks: [],
53
+ };
54
+ }
55
+
56
+ // Create choices for user selection, default all checked
57
+ const choices = documentsWithInvalidLinks.map((doc) => {
58
+ const invalidLinksText =
59
+ doc.invalidLinks && doc.invalidLinks.length > 0
60
+ ? ` (${doc.invalidLinks.length} invalid link${doc.invalidLinks.length > 1 ? "s" : ""})`
61
+ : "";
62
+
63
+ return {
64
+ name: `${doc.title || doc.path}${invalidLinksText}`,
65
+ value: doc.path,
66
+ checked: true, // Default all selected
67
+ description: `Invalid Links: ${doc.invalidLinks.join(", ")}`,
68
+ };
69
+ });
70
+
71
+ // Let user select documents (default all selected)
72
+ const selectedPaths = await options.prompts.checkbox({
73
+ message:
74
+ "Select documents with invalid links to fix (all selected by default, press Enter to confirm, or unselect all to skip):",
75
+ choices,
76
+ });
77
+
78
+ // Filter documents based on user selection
79
+ const selectedPathsSet = new Set(selectedPaths);
80
+ const filteredDocs = documentsWithInvalidLinks.filter((doc) => selectedPathsSet.has(doc.path));
81
+
82
+ if (filteredDocs.length === 0) {
83
+ return {
84
+ documentsWithInvalidLinks: [],
85
+ documentsToUpdate: [],
86
+ };
87
+ }
88
+
89
+ // Prepare documents: add necessary fields for update (without content)
90
+ const preparedDocs = [];
91
+
92
+ for (const doc of filteredDocs) {
93
+ if (!doc.path) continue;
94
+
95
+ // Find corresponding document in documentStructure to get additional fields
96
+ const structureDoc = documentExecutionStructure.find((item) => item.path === doc.path);
97
+
98
+ // Generate feedback message for fixing invalid links
99
+ const feedback = generateInvalidLinksFeedback(
100
+ doc.invalidLinks,
101
+ doc.path,
102
+ documentExecutionStructure,
103
+ );
104
+
105
+ preparedDocs.push({
106
+ ...structureDoc,
107
+ feedback,
108
+ invalidLinks: doc.invalidLinks,
109
+ });
110
+ }
111
+
112
+ return {
113
+ documentsWithInvalidLinks: preparedDocs, // for print summary
114
+ documentsToUpdate: JSON.parse(JSON.stringify(preparedDocs)), // for batch update
115
+ };
116
+ }
@@ -1,47 +1,8 @@
1
1
  import { getActiveRulesForScope } from "../../utils/preferences-utils.mjs";
2
2
  import { recordUpdate } from "../../utils/history-utils.mjs";
3
- import { buildDocumentTree } from "../../utils/docs-finder-utils.mjs";
3
+ import { printDocumentStructure } from "../../utils/docs-finder-utils.mjs";
4
4
  import equal from "fast-deep-equal";
5
5
 
6
- function formatDocumentStructure(structure) {
7
- const { rootNodes } = buildDocumentTree(structure);
8
-
9
- function printNode(node, depth = 0) {
10
- const INDENT_SPACES = " ";
11
- const FOLDER_ICON = " 📁";
12
- const FILE_ICON = " 📄";
13
- const indent = INDENT_SPACES.repeat(depth);
14
- const prefix = depth === 0 ? FOLDER_ICON : FILE_ICON;
15
-
16
- console.log(`${indent}${prefix} ${node.title}`);
17
-
18
- if (node.children && node.children.length > 0) {
19
- node.children.forEach((child) => {
20
- printNode(child, depth + 1);
21
- });
22
- }
23
- }
24
-
25
- return { rootNodes, printNode };
26
- }
27
-
28
- function printDocumentStructure(structure) {
29
- console.log(`\n ${"-".repeat(50)}`);
30
- console.log(" Current Documentation Structure");
31
- console.log(` ${"-".repeat(50)}`);
32
-
33
- const { rootNodes, printNode } = formatDocumentStructure(structure);
34
-
35
- if (rootNodes.length === 0) {
36
- console.log(" No documentation structure found.");
37
- } else {
38
- rootNodes.forEach((node) => {
39
- printNode(node);
40
- });
41
- }
42
- console.log();
43
- }
44
-
45
6
  export default async function userReviewDocumentStructure({ documentStructure, ...rest }, options) {
46
7
  // Check if documentation structure exists
47
8
  if (!documentStructure || !Array.isArray(documentStructure) || documentStructure.length === 0) {
@@ -0,0 +1,38 @@
1
+ import {
2
+ generateFileName,
3
+ pathToFlatName,
4
+ readFileContent,
5
+ } from "../../../utils/docs-finder-utils.mjs";
6
+ import { userContextAt } from "../../../utils/utils.mjs";
7
+
8
+ /**
9
+ * Initialize currentContents in userContext for document update
10
+ * Reads document content from file system and sets it in userContext
11
+ */
12
+ export default async function initCurrentContent(input, options) {
13
+ const { path, docsDir, locale = "en" } = input;
14
+
15
+ if (!path) {
16
+ return {};
17
+ }
18
+
19
+ // Generate filename from document path
20
+ const flatName = pathToFlatName(path);
21
+ const fileName = generateFileName(flatName, locale);
22
+
23
+ // Read document content
24
+ const content = docsDir ? await readFileContent(docsDir, fileName) : null;
25
+
26
+ if (!content) {
27
+ console.warn(`⚠️ Could not read content from ${fileName}`);
28
+ return {};
29
+ }
30
+
31
+ // Initialize currentContents[path] in userContext
32
+ const contentContext = userContextAt(options, `currentContents.${path}`);
33
+ contentContext.set(content);
34
+
35
+ return {};
36
+ }
37
+
38
+ initCurrentContent.task_render_mode = "hide";
@@ -4,15 +4,9 @@ import {
4
4
  getUpdateDocumentContentOutputJsonSchema,
5
5
  validateUpdateDocumentContentInput,
6
6
  } from "../../../types/document-schema.mjs";
7
+ import { userContextAt } from "../../../utils/utils.mjs";
7
8
 
8
9
  export default async function updateDocumentContent(input, options) {
9
- // Get originalContent from shared context, fallback to input
10
- let originalContent = options?.context?.userContext?.currentContent;
11
-
12
- if (!originalContent) {
13
- originalContent = input.originalContent;
14
- }
15
-
16
10
  // Validate input using Zod schema
17
11
  const validation = validateUpdateDocumentContentInput(input);
18
12
  if (!validation.success) {
@@ -22,7 +16,15 @@ export default async function updateDocumentContent(input, options) {
22
16
  };
23
17
  }
24
18
 
25
- const { diffPatch } = validation.data;
19
+ const { diffPatch, path } = validation.data;
20
+
21
+ // Get originalContent from shared context using path, fallback to input
22
+ const contentContext = userContextAt(options, `currentContents.${path}`);
23
+ let originalContent = contentContext.get();
24
+
25
+ if (!originalContent) {
26
+ originalContent = input.originalContent;
27
+ }
26
28
 
27
29
  try {
28
30
  // Parse and validate diff patch
@@ -56,10 +58,8 @@ export default async function updateDocumentContent(input, options) {
56
58
  };
57
59
  }
58
60
 
59
- // Update shared context with new content if options is provided
60
- if (options?.context?.userContext) {
61
- options.context.userContext.currentContent = result;
62
- }
61
+ // Update shared context with new content using path
62
+ contentContext.set(result);
63
63
 
64
64
  return {
65
65
  success: true,
@@ -3,7 +3,7 @@ name: updateDocumentDetail
3
3
  description: Update and optimize document content based on user feedback using diff patches
4
4
  task_render_mode: collapse
5
5
  skills:
6
- - url: ../utils/analyze-feedback-intent.yaml
6
+ - url: ../utils/analyze-document-feedback-intent.yaml
7
7
  - type: ai
8
8
  instructions:
9
9
  - role: system
@@ -48,9 +48,13 @@ skills:
48
48
  needDataSources:
49
49
  type: boolean
50
50
  description: Whether data sources are needed for content modifications
51
+ path:
52
+ type: string
53
+ description: Document path
51
54
  required:
52
55
  - originalContent
53
56
  - feedback
57
+ - path
54
58
  output_key: message
55
59
  afs:
56
60
  modules:
@@ -2,6 +2,7 @@ import { AIAgent } from "@aigne/core";
2
2
  import { pick } from "@aigne/core/utils/type-utils.js";
3
3
  import z from "zod";
4
4
  import { DIAGRAM_PLACEHOLDER, replacePlaceholder } from "../../../utils/d2-utils.mjs";
5
+ import { userContextAt } from "../../../utils/utils.mjs";
5
6
 
6
7
  async function getIntentType(input, options) {
7
8
  const instructions = `<role>
@@ -47,19 +48,24 @@ async function saveDoc(input, options, { content }) {
47
48
  }
48
49
 
49
50
  async function addDiagram(input, options) {
51
+ const contentContext = userContextAt(options, `currentContents.${input.path}`);
52
+ const currentContent = contentContext.get();
50
53
  const generateDiagramAgent = options.context.agents["checkGenerateDiagram"];
51
54
  const generateDiagramResult = await options.context.invoke(generateDiagramAgent, {
52
55
  ...pick(input, ["locale", "path", "diagramming", "feedback"]),
53
- documentContent: options.context.userContext.currentContent,
56
+ documentContent: currentContent,
54
57
  });
55
58
  const content = generateDiagramResult.content;
59
+ contentContext.set(content);
56
60
  await saveDoc(input, options, { content });
57
61
  return { content };
58
62
  }
59
63
 
60
64
  async function updateDiagram(input, options) {
65
+ const contentContext = userContextAt(options, `currentContents.${input.path}`);
66
+ const currentContent = contentContext.get();
61
67
  let [content, previousDiagramContent] = replacePlaceholder({
62
- content: options.context.userContext.currentContent,
68
+ content: currentContent,
63
69
  });
64
70
  const generateAgent = options.context?.agents?.["generateDiagram"];
65
71
  const { diagramSourceCode } = await options.context.invoke(generateAgent, {
@@ -69,13 +75,16 @@ async function updateDiagram(input, options) {
69
75
  feedback: input.feedback,
70
76
  });
71
77
  content = content.replace(DIAGRAM_PLACEHOLDER, diagramSourceCode);
78
+ contentContext.set(content);
72
79
  await saveDoc(input, options, { content });
73
80
  return { content };
74
81
  }
75
82
 
76
83
  async function deleteDiagram(input, options) {
84
+ const contentContext = userContextAt(options, `currentContents.${input.path}`);
85
+ const currentContent = contentContext.get();
77
86
  const [documentContent] = replacePlaceholder({
78
- content: options.context.userContext.currentContent,
87
+ content: currentContent,
79
88
  });
80
89
  const instructions = `<role>
81
90
  Your task is to remove ${DIAGRAM_PLACEHOLDER} and adjust the document context (based on the user's feedback) to make it easier to understand.
@@ -103,22 +112,28 @@ Your task is to remove ${DIAGRAM_PLACEHOLDER} and adjust the document context (b
103
112
  documentContent,
104
113
  feedback: input.feedback,
105
114
  });
115
+ contentContext.set(content);
106
116
  await saveDoc(input, options, { content });
107
117
 
108
118
  return { content };
109
119
  }
110
120
 
111
121
  async function updateDocument(input, options) {
122
+ const contentContext = userContextAt(options, `currentContents.${input.path}`);
123
+ const currentContent = contentContext.get();
112
124
  const updateAgent = options.context.agents["updateDocumentDetail"];
113
125
  const updateResult = await options.context.invoke(updateAgent, {
114
126
  ...input,
115
- originalContent: options.context.userContext.currentContent,
127
+ originalContent: currentContent,
116
128
  });
117
129
  if (updateResult.message === "success") {
118
- await saveDoc(input, options, { content: options.context.userContext.currentContent });
130
+ const updatedContent = contentContext.get();
131
+
132
+ contentContext.set(updatedContent);
133
+ await saveDoc(input, options, { content: updatedContent });
119
134
  }
120
135
  return {
121
- content: options.context.userContext.currentContent,
136
+ content: contentContext.get(),
122
137
  };
123
138
  }
124
139
 
@@ -1,6 +1,7 @@
1
1
  import { marked } from "marked";
2
2
  import markedTerminal from "marked-terminal";
3
3
  import { getActiveRulesForScope } from "../../utils/preferences-utils.mjs";
4
+ import { userContextAt } from "../../utils/utils.mjs";
4
5
 
5
6
  function extractMarkdownHeadings(content) {
6
7
  if (!content || typeof content !== "string") {
@@ -136,8 +137,9 @@ export default async function userReviewDocument({ content, description, ...rest
136
137
  printDocumentHeadings(content, title || "Untitled Document");
137
138
  }
138
139
 
139
- // Initialize shared context with current content
140
- options.context.userContext.currentContent = content;
140
+ // Initialize shared context with current content using path
141
+ const contentContext = userContextAt(options, `currentContents.${rest.path}`);
142
+ contentContext.set(content);
141
143
 
142
144
  const MAX_ITERATIONS = 100;
143
145
  const feedbacks = [];
@@ -174,10 +176,7 @@ export default async function userReviewDocument({ content, description, ...rest
174
176
  if (action === "finish") {
175
177
  break;
176
178
  } else if (action === "view") {
177
- await showDocumentDetail(
178
- options.context.userContext.currentContent,
179
- title || "Untitled Document",
180
- );
179
+ await showDocumentDetail(contentContext.get(), title || "Untitled Document");
181
180
  }
182
181
 
183
182
  // Ask for feedback
@@ -218,14 +217,15 @@ export default async function userReviewDocument({ content, description, ...rest
218
217
 
219
218
  try {
220
219
  // Call updateDocument agent with feedback
220
+ const currentContent = contentContext.get();
221
221
  const result = await options.context.invoke(updateAgent, {
222
222
  ...rest,
223
- originalContent: options.context.userContext.currentContent,
223
+ originalContent: currentContent,
224
224
  feedback: feedback.trim(),
225
225
  userPreferences,
226
226
  title,
227
227
  });
228
- options.context.userContext.currentContent = result.content;
228
+ contentContext.set(result.content);
229
229
 
230
230
  // Check if feedback should be saved as user preference
231
231
  const feedbackRefinerAgent = options.context.agents["checkFeedbackRefiner"];
@@ -242,10 +242,7 @@ export default async function userReviewDocument({ content, description, ...rest
242
242
  }
243
243
 
244
244
  // Print updated document headings structure
245
- printDocumentHeadings(
246
- options.context.userContext.currentContent,
247
- title || "Untitled Document",
248
- );
245
+ printDocumentHeadings(contentContext.get(), title || "Untitled Document");
249
246
 
250
247
  if (rest.isChat) {
251
248
  break;
@@ -267,7 +264,7 @@ export default async function userReviewDocument({ content, description, ...rest
267
264
  title,
268
265
  description,
269
266
  ...rest,
270
- content: options.context.userContext.currentContent,
267
+ content: contentContext.get(),
271
268
  feedback: feedbacks.join(". "),
272
269
  };
273
270
  }
@@ -0,0 +1,29 @@
1
+ export default function addTranslatesToStructure({
2
+ originalDocumentStructure = [],
3
+ translateLanguages = [],
4
+ }) {
5
+ const documentExecutionStructure = (originalDocumentStructure || []).map((item) => ({
6
+ ...item,
7
+ translates: (translateLanguages || []).map((lang) => ({ language: lang })),
8
+ }));
9
+
10
+ return {
11
+ documentExecutionStructure,
12
+ };
13
+ }
14
+
15
+ addTranslatesToStructure.inputSchema = {
16
+ type: "object",
17
+ properties: {
18
+ originalDocumentStructure: { type: "array", items: { type: "object" } },
19
+ translateLanguages: { type: "array", items: { type: "string" } },
20
+ },
21
+ required: ["originalDocumentStructure", "translateLanguages"],
22
+ };
23
+ addTranslatesToStructure.outputSchema = {
24
+ type: "object",
25
+ properties: {
26
+ documentExecutionStructure: { type: "array" },
27
+ },
28
+ };
29
+ addTranslatesToStructure.task_render_mode = "hide";
@@ -1,8 +1,8 @@
1
- name: analyzeFeedbackIntent
1
+ name: analyzeDocumentFeedbackIntent
2
2
  description: Analyze user feedback to determine if data sources are needed for content modifications
3
3
  task_render_mode: hide
4
4
  instructions:
5
- url: ../../prompts/utils/analyze-feedback-intent.md
5
+ url: ../../prompts/utils/analyze-document-feedback-intent.md
6
6
  input_schema:
7
7
  type: object
8
8
  properties:
@@ -23,6 +23,9 @@ output_schema:
23
23
  reason:
24
24
  type: string
25
25
  description: Explanation of why data sources are or aren't needed
26
+ error:
27
+ type: boolean
28
+ description: If an error occurs during the analysis process
26
29
  required:
27
30
  - needDataSources
28
31
  - intentType
@@ -0,0 +1,29 @@
1
+ name: analyzeStructureFeedbackIntent
2
+ description: Analyze user feedback to determine if data sources are needed for structure modifications
3
+ task_render_mode: hide
4
+ instructions:
5
+ url: ../../prompts/utils/analyze-structure-feedback-intent.md
6
+ input_schema:
7
+ type: object
8
+ properties:
9
+ feedback:
10
+ type: string
11
+ description: User feedback for structure modifications
12
+ required:
13
+ - feedback
14
+ output_schema:
15
+ type: object
16
+ properties:
17
+ needDataSources:
18
+ type: boolean
19
+ description: Whether data sources are needed - true for add/edit operations that need context, false for delete/move/reorder operations
20
+ intentType:
21
+ type: string
22
+ description: The primary type of user intention
23
+ reason:
24
+ type: string
25
+ description: Explanation of why data sources are or aren't needed
26
+ required:
27
+ - needDataSources
28
+ - intentType
29
+ - reason
@@ -1,4 +1,5 @@
1
1
  import { checkMarkdown } from "../../utils/markdown-checker.mjs";
2
+ import { buildAllowedLinksFromStructure } from "../../utils/docs-finder-utils.mjs";
2
3
 
3
4
  export default async function checkDetailResult({ documentStructure, reviewContent, docsDir }) {
4
5
  if (!reviewContent || reviewContent.trim() === "") {
@@ -12,20 +13,7 @@ export default async function checkDetailResult({ documentStructure, reviewConte
12
13
  const detailFeedback = [];
13
14
 
14
15
  // Create a set of allowed links, including both original paths and processed .md paths
15
- const allowedLinks = new Set();
16
- documentStructure.forEach((item) => {
17
- // Add original path
18
- allowedLinks.add(item.path);
19
-
20
- // Add processed .md path (same logic as processContent in utils.mjs)
21
- let processedPath = item.path;
22
- if (processedPath.startsWith(".")) {
23
- processedPath = processedPath.replace(/^\./, "");
24
- }
25
- let flatPath = processedPath.replace(/^\//, "").replace(/\//g, "-");
26
- flatPath = `./${flatPath}.md`;
27
- allowedLinks.add(flatPath);
28
- });
16
+ const allowedLinks = buildAllowedLinksFromStructure(documentStructure);
29
17
 
30
18
  // Run comprehensive markdown validation with all checks
31
19
  try {
package/aigne.yaml CHANGED
@@ -68,6 +68,7 @@ agents:
68
68
  - ./agents/clear/clear-media-description.mjs
69
69
 
70
70
  # Utilities
71
+ - ./agents/utils/add-translates-to-structure.mjs
71
72
  - ./agents/utils/load-sources.mjs
72
73
  - ./agents/utils/post-generate.mjs
73
74
  - ./agents/utils/save-sidebar.mjs
@@ -79,7 +80,8 @@ agents:
79
80
  - ./agents/utils/find-item-by-path.mjs
80
81
  - ./agents/utils/check-feedback-refiner.mjs
81
82
  - ./agents/utils/feedback-refiner.yaml
82
- - ./agents/utils/analyze-feedback-intent.yaml
83
+ - ./agents/utils/analyze-structure-feedback-intent.yaml
84
+ - ./agents/utils/analyze-document-feedback-intent.yaml
83
85
 
84
86
  - ./agents/utils/document-title-streamline.yaml
85
87
  - ./agents/utils/streamline-document-titles-if-needed.mjs
@@ -126,6 +128,13 @@ cli:
126
128
  - url: ./agents/history/view.mjs
127
129
  name: view
128
130
  alias: ["log", "list"]
131
+ - name: add-document
132
+ alias: ["add"]
133
+ url: ./agents/create/user-add-document/index.yaml
134
+ - name: remove-document
135
+ alias: ["rm"]
136
+ url: ./agents/create/user-remove-document/index.yaml
137
+ - ./agents/clear/index.yaml
129
138
  mcp_server:
130
139
  agents:
131
140
  - ./docs-mcp/get-docs-structure.mjs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/doc-smith",
3
- "version": "0.9.6-beta",
3
+ "version": "0.9.6-beta.1",
4
4
  "description": "AI-driven documentation generation tool built on the AIGNE Framework",
5
5
  "publishConfig": {
6
6
  "access": "public"