@aigne/doc-smith 0.8.15-beta.6 โ†’ 0.8.15-beta.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.
Files changed (34) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/agents/clear/choose-contents.mjs +4 -4
  3. package/agents/clear/clear-auth-tokens.mjs +8 -8
  4. package/agents/clear/clear-deployment-config.mjs +2 -2
  5. package/agents/clear/clear-document-config.mjs +3 -3
  6. package/agents/clear/clear-document-structure.mjs +10 -10
  7. package/agents/clear/clear-generated-docs.mjs +103 -14
  8. package/agents/clear/clear-media-description.mjs +7 -7
  9. package/agents/generate/check-need-generate-structure.mjs +2 -7
  10. package/agents/generate/generate-structure.yaml +159 -65
  11. package/agents/generate/user-review-document-structure.mjs +1 -0
  12. package/agents/generate/utils/merge-document-structures.mjs +54 -0
  13. package/agents/schema/document-structure-item.yaml +23 -0
  14. package/agents/schema/document-structure.yaml +1 -3
  15. package/agents/translate/index.yaml +1 -1
  16. package/agents/translate/record-translation-history.mjs +6 -2
  17. package/agents/update/save-and-translate-document.mjs +11 -0
  18. package/agents/utils/choose-docs.mjs +2 -1
  19. package/agents/utils/load-sources.mjs +55 -38
  20. package/agents/utils/save-doc.mjs +0 -9
  21. package/aigne.yaml +2 -4
  22. package/package.json +2 -1
  23. package/prompts/detail/custom/custom-components.md +38 -3
  24. package/prompts/structure/generate/system-prompt.md +0 -30
  25. package/prompts/structure/generate/user-prompt.md +68 -27
  26. package/prompts/structure/review/structure-review-system.md +73 -0
  27. package/prompts/translate/code-block.md +13 -3
  28. package/types/document-structure-schema.mjs +3 -3
  29. package/utils/docs-finder-utils.mjs +48 -0
  30. package/utils/extract-api.mjs +32 -0
  31. package/utils/file-utils.mjs +14 -87
  32. package/utils/history-utils.mjs +20 -8
  33. package/agents/generate/document-structure-tools/generate-sub-structure.mjs +0 -131
  34. package/agents/generate/generate-structure-without-tools.yaml +0 -65
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.15-beta.8](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.15-beta.7...v0.8.15-beta.8) (2025-11-01)
4
+
5
+
6
+ ### Features
7
+
8
+ * smarter structure generation with team-based architecture ([#225](https://github.com/AIGNE-io/aigne-doc-smith/issues/225)) ([eb3404a](https://github.com/AIGNE-io/aigne-doc-smith/commit/eb3404a8889364912a077e84688cfcd48d69ef47))
9
+
10
+ ## [0.8.15-beta.7](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.15-beta.6...v0.8.15-beta.7) (2025-10-31)
11
+
12
+
13
+ ### Features
14
+
15
+ * add web-smith powered web-pages ([#229](https://github.com/AIGNE-io/aigne-doc-smith/issues/229)) ([c3c00c1](https://github.com/AIGNE-io/aigne-doc-smith/commit/c3c00c12f092b125b6adb1a13ed5ff9720fbdab7))
16
+ * support cleaning specific documents ([#231](https://github.com/AIGNE-io/aigne-doc-smith/issues/231)) ([67607c9](https://github.com/AIGNE-io/aigne-doc-smith/commit/67607c9ff3852cc81a29e5a11b2151d26879b000))
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * tune custom component prompt and batch update history ([#228](https://github.com/AIGNE-io/aigne-doc-smith/issues/228)) ([ab13b97](https://github.com/AIGNE-io/aigne-doc-smith/commit/ab13b9737e5f111d0939f9c39ee76e13c0692a68))
22
+
3
23
  ## [0.8.15-beta.6](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.15-beta.5...v0.8.15-beta.6) (2025-10-30)
4
24
 
5
25
 
@@ -10,7 +10,7 @@ const TARGET_METADATA = {
10
10
  generatedDocs: {
11
11
  label: "Generated Documents",
12
12
  description: ({ docsDir }) =>
13
- `Delete all generated documents in './${toDisplayPath(docsDir)}'. The documentation structure will be preserved.`,
13
+ `Select and delete specific generated documents in './${toDisplayPath(docsDir)}'. The documentation structure will be preserved.`,
14
14
  agent: "clearGeneratedDocs",
15
15
  },
16
16
  documentStructure: {
@@ -150,9 +150,9 @@ export default async function chooseContents(input = {}, options = {}) {
150
150
  }
151
151
 
152
152
  const header = hasError
153
- ? "Cleanup finished with some issues."
154
- : "Cleanup completed successfully!";
155
- const detailLines = results.map((item) => `- ${item.message}`).join("\n");
153
+ ? "๐Ÿงน Cleanup finished with some issues.\n"
154
+ : "๐Ÿงน Cleanup completed successfully!\n";
155
+ const detailLines = results.map((item) => `${item.message}`).join("\n\n");
156
156
 
157
157
  const suggestions = [];
158
158
  results.forEach((result) => {
@@ -9,7 +9,7 @@ export default async function clearAuthTokens(_input = {}, options = {}) {
9
9
  // Check if the file exists
10
10
  if (!existsSync(DOC_SMITH_ENV_FILE)) {
11
11
  return {
12
- message: "No site authorizations found to clear",
12
+ message: "๐Ÿ”‘ No site authorizations found to clear",
13
13
  };
14
14
  }
15
15
 
@@ -23,7 +23,7 @@ export default async function clearAuthTokens(_input = {}, options = {}) {
23
23
 
24
24
  if (siteHostnames.length === 0) {
25
25
  return {
26
- message: "No site authorizations found to clear",
26
+ message: "๐Ÿ”‘ No site authorizations found to clear",
27
27
  };
28
28
  }
29
29
 
@@ -58,7 +58,7 @@ export default async function clearAuthTokens(_input = {}, options = {}) {
58
58
 
59
59
  if (selectedSites.length === 0) {
60
60
  return {
61
- message: "No sites selected for clearing authorization",
61
+ message: "๐Ÿ”‘ No sites selected for clearing authorization",
62
62
  };
63
63
  }
64
64
 
@@ -68,7 +68,7 @@ export default async function clearAuthTokens(_input = {}, options = {}) {
68
68
  if (selectedSites.includes("__ALL__")) {
69
69
  // Clear all site authorizations
70
70
  await writeFile(DOC_SMITH_ENV_FILE, stringify({}));
71
- results.push(`Cleared site authorization for all sites (${siteHostnames.length} sites)`);
71
+ results.push(`โœ” Cleared site authorization for all sites (${siteHostnames.length} sites)`);
72
72
  clearedCount = siteHostnames.length;
73
73
  } else {
74
74
  // Clear site authorizations for selected sites
@@ -79,7 +79,7 @@ export default async function clearAuthTokens(_input = {}, options = {}) {
79
79
  // Remove the entire site object
80
80
  delete updatedEnvs[hostname];
81
81
 
82
- results.push(`Cleared site authorization for ${chalk.cyan(hostname)}`);
82
+ results.push(`โœ” Cleared site authorization for ${chalk.cyan(hostname)}`);
83
83
  clearedCount++;
84
84
  }
85
85
  }
@@ -87,8 +87,8 @@ export default async function clearAuthTokens(_input = {}, options = {}) {
87
87
  await writeFile(DOC_SMITH_ENV_FILE, stringify(updatedEnvs));
88
88
  }
89
89
 
90
- const header = `Successfully cleared site authorizations!`;
91
- const detailLines = results.join("\n");
90
+ const header = `๐Ÿ”‘ Successfully cleared site authorizations!`;
91
+ const detailLines = results.map((item) => ` ${item}`).join("\n");
92
92
 
93
93
  const message = [header, "", detailLines, ""].filter(Boolean).join("\n");
94
94
 
@@ -99,7 +99,7 @@ export default async function clearAuthTokens(_input = {}, options = {}) {
99
99
  };
100
100
  } catch (error) {
101
101
  return {
102
- message: `Failed to clear site authorizations: ${error.message}`,
102
+ message: `โš ๏ธ Failed to clear site authorizations: ${error.message}`,
103
103
  error: true,
104
104
  };
105
105
  }
@@ -36,12 +36,12 @@ export default async function clearDeploymentConfig(input = {}) {
36
36
  }
37
37
 
38
38
  return {
39
- message: `๐Ÿงน Cleared appUrl from config file (${displayPath})`,
39
+ message: `๐Ÿ“ฆ Cleared appUrl from config file (${displayPath})`,
40
40
  };
41
41
  } catch (error) {
42
42
  return {
43
43
  error: true,
44
- message: `โŒ Failed to clear deployment config: ${error.message}`,
44
+ message: `โš ๏ธ Failed to clear deployment config: ${error.message}`,
45
45
  };
46
46
  }
47
47
  }
@@ -10,8 +10,8 @@ export default async function clearDocumentConfig({ workDir }) {
10
10
  await rm(documentConfigPath, { recursive: true, force: true });
11
11
 
12
12
  const message = existed
13
- ? `Cleared document configuration (${displayPath})`
14
- : `Document configuration already empty (${displayPath})`;
13
+ ? `โš™๏ธ Cleared document configuration (${displayPath})`
14
+ : `โš™๏ธ Document configuration already empty (${displayPath})`;
15
15
 
16
16
  const suggestions = existed
17
17
  ? ["Run `aigne doc init` to generate a fresh configuration file."]
@@ -25,7 +25,7 @@ export default async function clearDocumentConfig({ workDir }) {
25
25
  };
26
26
  } catch (error) {
27
27
  return {
28
- message: `Failed to clear document configuration: ${error.message}`,
28
+ message: `โš ๏ธ Failed to clear document configuration: ${error.message}`,
29
29
  error: true,
30
30
  path: displayPath,
31
31
  };
@@ -16,8 +16,8 @@ export default async function clearDocumentStructure(input = {}, _options = {})
16
16
 
17
17
  const structureDisplayPath = toDisplayPath(structurePlanPath);
18
18
  const structureMessage = structureExists
19
- ? `Cleared documentation structure (${structureDisplayPath})`
20
- : `Documentation structure already empty (${structureDisplayPath})`;
19
+ ? `โœ” Cleared documentation structure (${structureDisplayPath})`
20
+ : `โ€ข Documentation structure already empty (${structureDisplayPath})`;
21
21
 
22
22
  results.push({
23
23
  type: "structure",
@@ -29,7 +29,7 @@ export default async function clearDocumentStructure(input = {}, _options = {})
29
29
  results.push({
30
30
  type: "structure",
31
31
  error: true,
32
- message: `Failed to clear documentation structure: ${error.message}`,
32
+ message: `โœ— Failed to clear documentation structure: ${error.message}`,
33
33
  });
34
34
  }
35
35
 
@@ -41,8 +41,8 @@ export default async function clearDocumentStructure(input = {}, _options = {})
41
41
 
42
42
  const docsDisplayPath = toDisplayPath(docsDir);
43
43
  const docsMessage = docsExists
44
- ? `Cleared documents directory (${docsDisplayPath})`
45
- : `Documents directory already empty (${docsDisplayPath})`;
44
+ ? `โœ” Cleared documents directory (${docsDisplayPath})`
45
+ : `โ€ข Documents directory already empty (${docsDisplayPath})`;
46
46
 
47
47
  results.push({
48
48
  type: "documents",
@@ -54,7 +54,7 @@ export default async function clearDocumentStructure(input = {}, _options = {})
54
54
  results.push({
55
55
  type: "documents",
56
56
  error: true,
57
- message: `Failed to clear documents directory: ${error.message}`,
57
+ message: `โœ— Failed to clear documents directory: ${error.message}`,
58
58
  });
59
59
  }
60
60
  }
@@ -65,14 +65,14 @@ export default async function clearDocumentStructure(input = {}, _options = {})
65
65
 
66
66
  let header;
67
67
  if (errorItems > 0) {
68
- header = "Documentation Structure cleanup finished with some issues.";
68
+ header = "โš ๏ธ Documentation Structure cleanup finished with some issues.";
69
69
  } else if (clearedItems > 0) {
70
- header = "Documentation Structure cleared successfully!";
70
+ header = "๐Ÿ“– Documentation Structure cleared successfully!";
71
71
  } else {
72
- header = "Documentation Structure already empty.";
72
+ header = "๐Ÿ“– Documentation Structure already empty.";
73
73
  }
74
74
 
75
- const detailLines = results.map((item) => `- ${item.message}`).join("\n");
75
+ const detailLines = results.map((item) => ` ${item.message}`).join("\n");
76
76
  const message = [header, "", detailLines].filter(Boolean).join("\n");
77
77
 
78
78
  return {
@@ -1,12 +1,19 @@
1
1
  import { rm } from "node:fs/promises";
2
+ import { join } from "node:path";
2
3
  import { pathExists, resolveToAbsolute, toDisplayPath } from "../../utils/file-utils.mjs";
4
+ import {
5
+ pathToFlatName,
6
+ generateFileName,
7
+ loadDocumentStructure,
8
+ } from "../../utils/docs-finder-utils.mjs";
9
+ import chooseDocs from "../utils/choose-docs.mjs";
3
10
 
4
- export default async function clearGeneratedDocs(input = {}, _options = {}) {
5
- const { docsDir } = input;
11
+ export default async function clearGeneratedDocs(input = {}, options = {}) {
12
+ const { docsDir, outputDir, locale, translateLanguages } = input;
6
13
 
7
14
  if (!docsDir) {
8
15
  return {
9
- message: "No generated documents directory specified",
16
+ message: "๐Ÿ“ No generated documents directory specified",
10
17
  };
11
18
  }
12
19
 
@@ -14,23 +21,104 @@ export default async function clearGeneratedDocs(input = {}, _options = {}) {
14
21
  const displayPath = toDisplayPath(generatedDocsPath);
15
22
 
16
23
  try {
17
- const existed = await pathExists(generatedDocsPath);
18
- await rm(generatedDocsPath, { recursive: true, force: true });
24
+ const dirExists = await pathExists(generatedDocsPath);
25
+ if (!dirExists) {
26
+ return {
27
+ message: `๐Ÿ“ Generated documents directory does not exist (${displayPath})`,
28
+ cleared: false,
29
+ };
30
+ }
19
31
 
20
- const message = existed
21
- ? `Cleared generated documents (${displayPath})`
22
- : `Generated documents already empty (${displayPath})`;
32
+ const documentExecutionStructure = (await loadDocumentStructure(outputDir)) || [];
33
+ // select documents interactively
34
+ const chooseResult = await chooseDocs(
35
+ {
36
+ docs: [], // Empty to trigger interactive selection
37
+ documentExecutionStructure,
38
+ docsDir: generatedDocsPath,
39
+ locale: locale || "en",
40
+ isTranslate: false,
41
+ title: "Select documents to delete:",
42
+ feedback: "Skip feedback",
43
+ requiredFeedback: false,
44
+ },
45
+ options,
46
+ );
47
+
48
+ if (!chooseResult?.selectedDocs || chooseResult.selectedDocs.length === 0) {
49
+ return {
50
+ message: "๐Ÿ“ No documents selected for deletion",
51
+ cleared: false,
52
+ path: displayPath,
53
+ };
54
+ }
55
+
56
+ // Extract file names
57
+ const filesToDelete = new Set();
58
+ const allLanguages = [locale || "en", ...(translateLanguages || [])];
59
+
60
+ for (const selectedDoc of chooseResult.selectedDocs) {
61
+ // Convert path to flat filename format using utility function
62
+ const flatName = pathToFlatName(selectedDoc.path);
63
+
64
+ // Generate file names for all languages
65
+ for (const lang of allLanguages) {
66
+ const fileName = generateFileName(flatName, lang);
67
+ filesToDelete.add(fileName);
68
+ }
69
+ }
70
+
71
+ if (filesToDelete.size === 0) {
72
+ return {
73
+ message: "๐Ÿ“ No documents were deleted.",
74
+ cleared: false,
75
+ };
76
+ }
77
+
78
+ // Delete selected files (including all language versions)
79
+ const deletedFiles = [];
80
+ const failedFiles = [];
81
+ let hasError = false;
82
+
83
+ for (const file of filesToDelete) {
84
+ try {
85
+ const filePath = join(generatedDocsPath, file);
86
+ await rm(filePath, { force: true });
87
+ deletedFiles.push(file);
88
+ } catch (error) {
89
+ hasError = true;
90
+ failedFiles.push({ file, error: error.message });
91
+ }
92
+ }
93
+
94
+ // Build result message
95
+ const deletedCount = deletedFiles.length;
96
+ const failedCount = failedFiles.length;
97
+
98
+ let message = "";
99
+ if (deletedCount > 0) {
100
+ const lastIndex = deletedFiles.length - 1;
101
+ message = `๐Ÿ“ Deleted ${deletedCount} document(s) in "${displayPath}":\n${deletedFiles
102
+ .map((f, i) => ` ${i === lastIndex ? "โ””โ”€" : "โ”œโ”€"} ${f}`)
103
+ .join("\n")}`;
104
+ }
105
+
106
+ if (failedCount > 0) {
107
+ const lastIndex = failedFiles.length - 1;
108
+ message = `โš ๏ธ Failed to delete ${failedCount} document(s) in "${displayPath}":\n${failedFiles
109
+ .map((f, i) => ` ${i === lastIndex ? "โ””โ”€" : "โ”œโ”€"} ${f.file}: ${f.error}`)
110
+ .join("\n")}`;
111
+ }
23
112
 
24
113
  return {
25
114
  message,
26
- cleared: existed,
27
- path: displayPath,
115
+ cleared: deletedCount > 0,
116
+ error: hasError,
28
117
  };
29
118
  } catch (error) {
30
119
  return {
31
- message: `Failed to clear generated documents: ${error.message}`,
120
+ message: `โš ๏ธ Failed to clear generated documents: ${error.message}`,
32
121
  error: true,
33
- path: displayPath,
34
122
  };
35
123
  }
36
124
  }
@@ -46,5 +134,6 @@ clearGeneratedDocs.input_schema = {
46
134
  required: ["docsDir"],
47
135
  };
48
136
 
49
- clearGeneratedDocs.taskTitle = "Clear all generated documents";
50
- clearGeneratedDocs.description = "Clear the generated documents directory";
137
+ clearGeneratedDocs.taskTitle = "Clear generated documents";
138
+ clearGeneratedDocs.description =
139
+ "Select and delete specific generated documents from the docs directory";
@@ -11,7 +11,7 @@ export default async function clearMediaDescription(_input = {}, options = {}) {
11
11
  // Check if the cache file exists
12
12
  if (!existsSync(cacheFilePath)) {
13
13
  return {
14
- message: "No media descriptions found to clear",
14
+ message: "๐Ÿ–ผ๏ธ No media descriptions found to clear",
15
15
  };
16
16
  }
17
17
 
@@ -26,7 +26,7 @@ export default async function clearMediaDescription(_input = {}, options = {}) {
26
26
 
27
27
  if (mediaHashes.length === 0) {
28
28
  return {
29
- message: "No media descriptions found to clear",
29
+ message: "๐Ÿ–ผ๏ธ No media descriptions found to clear",
30
30
  };
31
31
  }
32
32
 
@@ -68,7 +68,7 @@ export default async function clearMediaDescription(_input = {}, options = {}) {
68
68
 
69
69
  if (selectedHashes.length === 0) {
70
70
  return {
71
- message: "No media files selected for clearing descriptions",
71
+ message: "๐Ÿ–ผ๏ธ No media files selected for clearing descriptions",
72
72
  };
73
73
  }
74
74
 
@@ -84,7 +84,7 @@ export default async function clearMediaDescription(_input = {}, options = {}) {
84
84
  lastUpdated: new Date().toISOString(),
85
85
  }),
86
86
  );
87
- results.push(`Cleared descriptions for all media files (${mediaHashes.length} files)`);
87
+ results.push(`โœ” Cleared descriptions for all media files (${mediaHashes.length} files)`);
88
88
  clearedCount = mediaHashes.length;
89
89
  } else {
90
90
  // Clear descriptions for selected files
@@ -94,7 +94,7 @@ export default async function clearMediaDescription(_input = {}, options = {}) {
94
94
  if (updatedCache[hash]) {
95
95
  const filename = path.basename(updatedCache[hash].path);
96
96
  delete updatedCache[hash];
97
- results.push(`Cleared description for ${chalk.cyan(filename)}`);
97
+ results.push(`โœ” Cleared description for ${chalk.cyan(filename)}`);
98
98
  clearedCount++;
99
99
  }
100
100
  }
@@ -108,8 +108,8 @@ export default async function clearMediaDescription(_input = {}, options = {}) {
108
108
  );
109
109
  }
110
110
 
111
- const header = `โœจ Successfully cleared media descriptions`;
112
- const detailLines = results.join("\n");
111
+ const header = `๐Ÿ–ผ๏ธ Successfully cleared media descriptions`;
112
+ const detailLines = results.map((item) => ` ${item}`).join("\n");
113
113
 
114
114
  const message = [header, "", detailLines, ""].filter(Boolean).join("\n");
115
115
 
@@ -3,7 +3,7 @@ import { getActiveRulesForScope } from "../../utils/preferences-utils.mjs";
3
3
  import { getProjectInfo, loadConfigFromFile, saveValueToConfig } from "../../utils/utils.mjs";
4
4
 
5
5
  export default async function checkNeedGenerateStructure(
6
- { originalDocumentStructure, forceRegenerate, isLargeContext, ...rest },
6
+ { originalDocumentStructure, forceRegenerate, ...rest },
7
7
  options,
8
8
  ) {
9
9
  // Check if originalDocumentStructure is empty and prompt user
@@ -53,11 +53,7 @@ export default async function checkNeedGenerateStructure(
53
53
  };
54
54
  }
55
55
 
56
- // Performance optimization: Using both structured output and tools with the Gemini model can cause redundant calls.
57
- // Only use tools when the context is very large.
58
- const generateStructureAgent = isLargeContext
59
- ? options.context.agents["generateStructure"]
60
- : options.context.agents["generateStructureWithoutTools"];
56
+ const generateStructureAgent = options.context.agents["generateStructure"];
61
57
 
62
58
  const structureRules = getActiveRulesForScope("structure", []);
63
59
  const globalRules = getActiveRulesForScope("global", []);
@@ -72,7 +68,6 @@ export default async function checkNeedGenerateStructure(
72
68
  originalDocumentStructure,
73
69
  userPreferences,
74
70
  feedback: finalFeedback || "",
75
- isLargeContext,
76
71
  });
77
72
 
78
73
  let message = "";
@@ -1,68 +1,162 @@
1
+ type: team
1
2
  name: generateStructure
2
3
  description: Generate the structure and organization of your documentation
3
- instructions:
4
- - role: system
5
- url: ../../prompts/structure/generate/system-prompt.md
6
- - role: user
7
- url: ../../prompts/structure/generate/user-prompt.md
8
4
  skills:
9
- - ./document-structure-tools/generate-sub-structure.mjs
10
- task_render_mode: collapse
11
- task_title: Generate the structure of the documentation
12
- tool_calls_concurrency: 5
13
- input_schema:
14
- type: object
15
- properties:
16
- rules:
17
- type: string
18
- description: Your specific requirements for documentation structure
19
- locale:
20
- type: string
21
- description: Primary language for documentation (e.g., zh, en, ja)
22
- datasources:
23
- type: string
24
- description: Project content and context to help generate documentation structure
25
- targetAudience:
26
- type: string
27
- description: Target audience for the documentation
28
- nodeName:
29
- type: string
30
- description: Specific section or page name to focus on
31
- glossary:
32
- type: string
33
- description: Glossary for consistent terminology
34
- feedback:
35
- type: string
36
- description: Tell us how to improve the documentation structure
37
- userPreferences:
38
- type: string
39
- description: Your saved preferences for structure and documentation style
40
- docsType:
41
- type: string
42
- description: "Documentation type (options: general, getting-started, reference, faq)"
43
- default: general
44
- required:
45
- - rules
46
- - datasources
47
- output_schema:
48
- type: object
49
- properties:
50
- projectName:
51
- type: string
52
- description: Project name identified from your content sources
53
- projectDesc:
54
- type: string
55
- description: Brief project description generated from content analysis (under 50 words)
56
- documentStructure: ../schema/document-structure.yaml
57
- documentStructureTree:
58
- type: string
59
- description: |
60
- Visual tree structure showing documentation hierarchy with indented levels for easy review:
61
- ```
62
- - Home
63
- - Getting Started
64
- - Installation
65
- - Requirements
66
- ```
67
- required:
68
- - documentStructure
5
+ - type: team
6
+ name: generateStructureWorker
7
+ iterate_on: datasources
8
+ skills:
9
+ - type: ai
10
+ model:
11
+ reasoning_effort: 500
12
+ instructions:
13
+ - role: system
14
+ url: ../../prompts/structure/generate/system-prompt.md
15
+ - role: user
16
+ url: ../../prompts/structure/generate/user-prompt.md
17
+ task_render_mode: collapse
18
+ task_title: Generate the structure of the documentation
19
+ tool_calls_concurrency: 5
20
+ input_schema:
21
+ type: object
22
+ properties:
23
+ rules:
24
+ type: string
25
+ description: Your specific requirements for documentation structure
26
+ locale:
27
+ type: string
28
+ description: Primary language for documentation (e.g., zh, en, ja)
29
+ datasources:
30
+ type: string
31
+ description: Project content and context to help generate documentation structure
32
+ targetAudience:
33
+ type: string
34
+ description: Target audience for the documentation
35
+ nodeName:
36
+ type: string
37
+ description: Specific section or page name to focus on
38
+ glossary:
39
+ type: string
40
+ description: Glossary for consistent terminology
41
+ feedback:
42
+ type: string
43
+ description: Tell us how to improve the documentation structure
44
+ userPreferences:
45
+ type: string
46
+ description: Your saved preferences for structure and documentation style
47
+ docsType:
48
+ type: string
49
+ description: "Documentation type (options: general, getting-started, reference, faq)"
50
+ default: general
51
+ required:
52
+ - rules
53
+ - datasources
54
+ output_schema:
55
+ type: object
56
+ properties:
57
+ projectName:
58
+ type: string
59
+ description: Project name identified from your content sources
60
+ projectDesc:
61
+ type: string
62
+ description: Brief project description generated from content analysis (under 50 words)
63
+ add:
64
+ type: array
65
+ description: List of document structure items to add, null or empty array means no addition
66
+ items:
67
+ type: object
68
+ properties:
69
+ index:
70
+ type: integer
71
+ description: Position to insert the new item, null means append to the end
72
+ item: ../schema/document-structure-item.yaml
73
+ required:
74
+ - item
75
+ update:
76
+ type: array
77
+ description: List of document structure items to update, replace the item with the same path, null or empty array means no update
78
+ items:
79
+ type: object
80
+ properties:
81
+ path:
82
+ type: string
83
+ description: Path of the document structure item to update or replace
84
+ item: ../schema/document-structure-item.yaml
85
+ required:
86
+ - path
87
+ - item
88
+
89
+ - ./utils/merge-document-structures.mjs
90
+
91
+ - type: function
92
+ name: aggregateDocumentStructure
93
+ process: |
94
+ return {
95
+ documentStructure: options.context.userContext.originalDocumentStructure.map(i => ({
96
+ ...i,
97
+ id: i.title.toLowerCase().replace(/\s+/g, '-'),
98
+ })),
99
+ projectName: options.context.userContext.projectName,
100
+ projectDesc: options.context.userContext.projectDesc,
101
+ }
102
+
103
+ - type: ai
104
+ name: refineStructure
105
+ model:
106
+ reasoning_effort: 500
107
+ instructions:
108
+ - role: system
109
+ url: ../../prompts/structure/review/structure-review-system.md
110
+ output_schema:
111
+ type: object
112
+ properties:
113
+ refinedStructure:
114
+ type: array
115
+ description: Optimized document structure array
116
+ items:
117
+ type: object
118
+ description: Document structure item representing a node in the document hierarchy
119
+ properties:
120
+ id:
121
+ type: string
122
+ description: Unique identifier for the document structure item
123
+ newIndex:
124
+ type: integer
125
+ description: Used for ordering purposes, indicates the new position index of the document structure item
126
+ newPath:
127
+ type: string
128
+ description: The new path of the document structure item if it has been changed, otherwise can be omitted
129
+ newParentPath:
130
+ type: string
131
+ description: The new parentPath of the document structure item if it has been changed, otherwise can be omitted
132
+ required:
133
+ - id
134
+ required:
135
+ - refinedStructure
136
+
137
+ - type: function
138
+ name: finalizeDocumentStructure
139
+ process: |
140
+ return {
141
+ projectName: input.projectName,
142
+ projectDesc: input.projectDesc,
143
+ documentStructure: input.documentStructure
144
+ .map((item) => {
145
+ const refined = input.refinedStructure?.find(i => i.id === item.id)
146
+
147
+ return {
148
+ ...item,
149
+ index: refined?.newIndex || item.index,
150
+ path: refined?.newPath || item.path,
151
+ parentId: refined?.newParentPath || item.parentPath,
152
+ }
153
+ })
154
+ .sort((a, b) => a.index - b.index)
155
+ .map(i => {
156
+ const newItem = { ...i }
157
+ delete newItem.index
158
+ delete newItem.id
159
+ delete newItem.parentPath
160
+ return newItem
161
+ }),
162
+ }