@aigne/doc-smith 0.8.16-beta → 0.8.16-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 (46) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/agents/evaluate/generate-report.mjs +7 -0
  3. package/agents/evaluate/index.yaml +6 -0
  4. package/agents/generate/check-need-generate-structure.mjs +8 -4
  5. package/agents/generate/document-structure-tools/add-document.mjs +4 -0
  6. package/agents/generate/document-structure-tools/update-document.mjs +11 -0
  7. package/agents/generate/draw-diagram.yaml +2 -2
  8. package/agents/generate/generate-structure.yaml +3 -2
  9. package/agents/init/index.mjs +6 -4
  10. package/agents/media/load-media-description.mjs +2 -1
  11. package/agents/schema/document-structure-item.yaml +3 -0
  12. package/agents/schema/document-structure-refine-item.yaml +3 -0
  13. package/agents/schema/document-structure.yaml +3 -0
  14. package/agents/update/pre-check-generate-diagram.yaml +1 -1
  15. package/agents/utils/document-icon-generate.yaml +52 -0
  16. package/agents/utils/generate-document-icon-if-needed.mjs +93 -0
  17. package/aigne.yaml +2 -0
  18. package/package.json +3 -7
  19. package/prompts/common/document/media-file-list-usage-rules.md +8 -2
  20. package/prompts/common/document/openapi-usage-rules.md +174 -21
  21. package/prompts/common/document-structure/document-icon-generate.md +116 -0
  22. package/prompts/common/document-structure/document-structure-rules.md +8 -3
  23. package/prompts/common/document-structure/openapi-usage-rules.md +28 -0
  24. package/prompts/common/document-structure/output-constraints.md +9 -0
  25. package/prompts/detail/custom/{custom-code-block.md → code-block-usage-rules.md} +43 -16
  26. package/prompts/detail/custom/custom-components/x-card-usage-rules.md +62 -0
  27. package/prompts/detail/custom/custom-components/x-cards-usage-rules.md +75 -0
  28. package/prompts/detail/custom/custom-components/x-field-desc-usage-rules.md +86 -0
  29. package/prompts/detail/custom/custom-components/x-field-group-usage-rules.md +95 -0
  30. package/prompts/detail/custom/custom-components/x-field-usage-rules.md +189 -0
  31. package/prompts/detail/custom/custom-components-usage-rules.md +10 -534
  32. package/prompts/detail/{d2-diagram → diagram}/rules.md +5 -3
  33. package/prompts/detail/generate/document-rules.md +6 -0
  34. package/prompts/detail/generate/system-prompt.md +3 -2
  35. package/prompts/detail/generate/user-prompt.md +7 -1
  36. package/prompts/detail/update/system-prompt.md +3 -3
  37. package/prompts/structure/generate/system-prompt.md +2 -5
  38. package/prompts/structure/generate/user-prompt.md +14 -39
  39. package/types/document-structure-schema.mjs +1 -0
  40. package/utils/evaluate/report-utils.mjs +7 -3
  41. /package/prompts/detail/{d2-diagram → diagram}/guide.md +0 -0
  42. /package/prompts/detail/{d2-diagram → diagram}/official-examples.md +0 -0
  43. /package/prompts/detail/{d2-diagram → diagram}/pre-check.md +0 -0
  44. /package/prompts/detail/{d2-diagram → diagram}/role-and-personality.md +0 -0
  45. /package/prompts/detail/{d2-diagram → diagram}/system-prompt.md +0 -0
  46. /package/prompts/detail/{d2-diagram → diagram}/user-prompt.md +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.16-beta.1](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.16-beta...v0.8.16-beta.1) (2025-11-11)
4
+
5
+
6
+ ### Features
7
+
8
+ * add document icon generation functionality and update schemas ([#286](https://github.com/AIGNE-io/aigne-doc-smith/issues/286)) ([3e20fda](https://github.com/AIGNE-io/aigne-doc-smith/commit/3e20fdaf8a6e4713ed0756f52c620180c8b47f35))
9
+ * support auto open evaluation report ([#287](https://github.com/AIGNE-io/aigne-doc-smith/issues/287)) ([93a64d5](https://github.com/AIGNE-io/aigne-doc-smith/commit/93a64d5bfb4602532efe5cc33cc90494e2b0cb48))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * tune prompts increase document expressiveness ([#284](https://github.com/AIGNE-io/aigne-doc-smith/issues/284)) ([eb79742](https://github.com/AIGNE-io/aigne-doc-smith/commit/eb79742d0782405d6143ac0271359cd8ae97286b))
15
+
3
16
  ## [0.8.16-beta](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.15...v0.8.16-beta) (2025-11-10)
4
17
 
5
18
 
@@ -1,6 +1,9 @@
1
1
  import { writeFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { pick } from "@aigne/core/utils/type-utils.js";
4
+ import isInCi from "is-in-ci";
5
+ import openTerminal from "open";
6
+
4
7
  import { DOC_SMITH_DIR } from "../../utils/constants/index.mjs";
5
8
  import {
6
9
  copyHtmlReportTemplate,
@@ -35,6 +38,7 @@ export default async function generateEvaluationReport({
35
38
  readerKnowledgeLevel,
36
39
  documentationDepth,
37
40
  targetAudience,
41
+ open = true,
38
42
  }) {
39
43
  const timestamp = new Date().toISOString();
40
44
  const timestampForFolder = generateTimestampForFolder();
@@ -69,6 +73,9 @@ export default async function generateEvaluationReport({
69
73
 
70
74
  // Generate success message
71
75
  const message = generateReportSuccessMessage(toRelativePath(jsonReportPath), htmlReportPath);
76
+ if (open && !isInCi) {
77
+ openTerminal(htmlReportPath);
78
+ }
72
79
 
73
80
  return {
74
81
  message,
@@ -37,3 +37,9 @@ skills:
37
37
  mode: sequential
38
38
  - ./generate-report.mjs
39
39
  mode: sequential
40
+ input_schema:
41
+ type: object
42
+ properties:
43
+ open:
44
+ type: boolean
45
+ description: Auto open generated report
@@ -96,8 +96,10 @@ export default async function checkNeedGenerateStructure(
96
96
  result.projectName !== projectInfo.name &&
97
97
  !projectInfo.fromGitHub
98
98
  ) {
99
- await saveValueToConfig("projectName", result.projectName);
100
- message += `Project name: \`${result.projectName}\``;
99
+ // Remove leading and trailing spaces (middle spaces are preserved and count toward limit)
100
+ const trimmedProjectName = result.projectName.trim();
101
+ await saveValueToConfig("projectName", trimmedProjectName);
102
+ message += `Project name: \`${trimmedProjectName}\``;
101
103
  hasUpdated = true;
102
104
  }
103
105
 
@@ -106,8 +108,10 @@ export default async function checkNeedGenerateStructure(
106
108
  result.projectDesc !== projectInfo.description &&
107
109
  !projectInfo.fromGitHub
108
110
  ) {
109
- await saveValueToConfig("projectDesc", result.projectDesc);
110
- message += `\nProject description: \`${result.projectDesc}\``;
111
+ // Remove leading and trailing spaces (middle spaces are preserved and count toward limit)
112
+ const trimmedProjectDesc = result.projectDesc.trim();
113
+ await saveValueToConfig("projectDesc", trimmedProjectDesc);
114
+ message += `\nProject description: \`${trimmedProjectDesc}\``;
111
115
  hasUpdated = true;
112
116
  }
113
117
 
@@ -4,6 +4,7 @@ import {
4
4
  validateAddDocumentInput,
5
5
  } from "../../../types/document-structure-schema.mjs";
6
6
  import streamlineDocumentTitlesIfNeeded from "../../utils/streamline-document-titles-if-needed.mjs";
7
+ import generateDocumentIconIfNeeded from "../../utils/generate-document-icon-if-needed.mjs";
7
8
 
8
9
  export default async function addDocument(input, options) {
9
10
  // Validate input using Zod schema
@@ -63,6 +64,9 @@ export default async function addDocument(input, options) {
63
64
  // Add the document to the structure first
64
65
  const updatedStructure = [...documentStructure, newDocument];
65
66
 
67
+ // Generate icon for root-level documents if needed
68
+ await generateDocumentIconIfNeeded({ documentStructure: updatedStructure }, options);
69
+
66
70
  const successMessage = `addDocument executed successfully.
67
71
  Successfully added document '${title}' with path '${path}'.
68
72
  Check if the latest version of documentStructure meets user feedback, if so, just return 'success'.`;
@@ -4,6 +4,7 @@ import {
4
4
  validateUpdateDocumentInput,
5
5
  } from "../../../types/document-structure-schema.mjs";
6
6
  import streamlineDocumentTitlesIfNeeded from "../../utils/streamline-document-titles-if-needed.mjs";
7
+ import generateDocumentIconIfNeeded from "../../utils/generate-document-icon-if-needed.mjs";
7
8
 
8
9
  export default async function updateDocument(input, options) {
9
10
  // Validate input using Zod schema
@@ -55,6 +56,16 @@ export default async function updateDocument(input, options) {
55
56
  const updatedStructure = [...documentStructure];
56
57
  updatedStructure[documentIndex] = updatedDocument;
57
58
 
59
+ // Generate/update icon for root-level documents if needed
60
+ // Pass original document for comparison to detect title/description changes
61
+ await generateDocumentIconIfNeeded(
62
+ {
63
+ documentStructure: updatedStructure,
64
+ originalItems: [originalDocument],
65
+ },
66
+ options,
67
+ );
68
+
58
69
  const updates = [];
59
70
  if (title !== undefined) updates.push(`title to '${title}'`);
60
71
  if (description !== undefined) updates.push("description");
@@ -2,9 +2,9 @@ name: drawDiagram
2
2
  description: Generate a D2 diagram from document content.
3
3
  instructions:
4
4
  - role: system
5
- url: ../../prompts/detail/d2-diagram/system-prompt.md
5
+ url: ../../prompts/detail/diagram/system-prompt.md
6
6
  - role: user
7
- url: ../../prompts/detail/d2-diagram/user-prompt.md
7
+ url: ../../prompts/detail/diagram/user-prompt.md
8
8
  input_schema:
9
9
  type: object
10
10
  properties:
@@ -54,10 +54,10 @@ skills:
54
54
  properties:
55
55
  projectName:
56
56
  type: string
57
- description: Project name identified from your content sources
57
+ description: Project name identified from your content sources. Max 40 characters (any language, each character = 1). Leading/trailing spaces removed. Generate complete name within limit.
58
58
  projectDesc:
59
59
  type: string
60
- description: Brief project description generated from content analysis (under 50 words)
60
+ description: Brief project description from content analysis. Max 160 characters (any language, each character = 1). Leading/trailing spaces removed. Generate complete description within limit.
61
61
  structures:
62
62
  type: array
63
63
  description: List of document structure items to add or update
@@ -109,6 +109,7 @@ skills:
109
109
  path: refinedItem.path,
110
110
  parentId: refinedItem.parentPath || null, // Convert parentPath to parentId
111
111
  sourceIds: originalItem?.sourceIds || [],
112
+ ...(refinedItem.icon && { icon: refinedItem.icon }), // Preserve icon if updated during refinement
112
113
  }
113
114
 
114
115
  return newItem
@@ -403,8 +403,9 @@ async function _init(
403
403
 
404
404
  // Save project info to config
405
405
  const projectInfo = await getProjectInfo();
406
- input.projectName = projectInfo.name;
407
- input.projectDesc = projectInfo.description;
406
+ // Remove leading and trailing spaces (middle spaces are preserved and count toward limit)
407
+ input.projectName = projectInfo.name.trim();
408
+ input.projectDesc = projectInfo.description.trim();
408
409
  input.projectLogo = projectInfo.icon;
409
410
 
410
411
  // Generate YAML content
@@ -453,8 +454,9 @@ export function generateYAML(input) {
453
454
  // Create the main configuration object that will be safely serialized
454
455
  const config = {
455
456
  // Project information (safely handled by yaml library)
456
- projectName: input.projectName || "",
457
- projectDesc: input.projectDesc || "",
457
+ // Remove leading and trailing spaces (middle spaces are preserved and count toward limit)
458
+ projectName: (input.projectName || "").trim(),
459
+ projectDesc: (input.projectDesc || "").trim(),
458
460
  projectLogo: input.projectLogo || "",
459
461
 
460
462
  thinking: {
@@ -160,9 +160,10 @@ export default async function loadMediaDescription(input, options) {
160
160
  }
161
161
 
162
162
  // Build enhanced assetsContent with descriptions
163
- let enhancedAssetsContent = "# Available Media Assets for Documentation\n\n";
163
+ let enhancedAssetsContent;
164
164
 
165
165
  if (mediaFiles.length > 0) {
166
+ enhancedAssetsContent = "# Available Media Assets for Documentation\n\n";
166
167
  const assets = mediaFiles.map((x) => {
167
168
  const mediaHash = mediaHashMap.get(x.path);
168
169
  const description = cache[mediaHash]?.description;
@@ -16,6 +16,9 @@ properties:
16
16
  description: Associated sourceId from `<data_sources>` for subsequent translation and content generation, must come from sourceId in `<data_sources>`, cannot have fake ids, **cannot be empty**
17
17
  items:
18
18
  type: string
19
+ icon:
20
+ type: string
21
+ description: Lucide icon name for root-level documents (just support lucide:icon-name, not support other icon collections)
19
22
  required:
20
23
  - title
21
24
  - description
@@ -14,6 +14,9 @@ properties:
14
14
  parentPath:
15
15
  type: string
16
16
  description: Parent node path, if null indicates it is a top-level node
17
+ icon:
18
+ type: string
19
+ description: Iconify icon name, e.g., lucide:book, lucide:rocket, lucide:* etc.
17
20
  required:
18
21
  - title
19
22
  - description
@@ -19,6 +19,9 @@ items:
19
19
  description: Associated sourceId from `<data_sources>` for subsequent translation and content generation, must come from sourceId in `<data_sources>`, cannot have fake ids, **cannot be empty**
20
20
  items:
21
21
  type: string
22
+ icon:
23
+ type: string
24
+ description: Lucide icon name for root-level documents (just support lucide:icon-name, not support other icon collections)
22
25
  required:
23
26
  - title
24
27
  - description
@@ -3,7 +3,7 @@ description: Pre-check for generating diagram
3
3
  model:
4
4
  reasoning_effort: 1
5
5
  instructions:
6
- url: ../../prompts/detail/d2-diagram/pre-check.md
6
+ url: ../../prompts/detail/diagram/pre-check.md
7
7
  input_schema:
8
8
  type: object
9
9
  properties:
@@ -0,0 +1,52 @@
1
+ name: documentIconGenerate
2
+ description: Generate appropriate Iconify icon names for document structure root nodes based on their title and description
3
+ model:
4
+ reasoning_effort: low
5
+ task_render_mode: hide
6
+ instructions:
7
+ url: ../../prompts/common/document-structure/document-icon-generate.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 analyze for icon selection
22
+ description:
23
+ type: string
24
+ description: Document description to analyze for icon selection
25
+ required:
26
+ - path
27
+ - title
28
+ - description
29
+ description: List of root-level document items (parentId is null) that need icons generated
30
+ required:
31
+ - documentList
32
+ output_schema:
33
+ type: object
34
+ properties:
35
+ documentList:
36
+ type: array
37
+ items:
38
+ type: object
39
+ properties:
40
+ path:
41
+ type: string
42
+ description: Document path (same as input for mapping)
43
+ icon:
44
+ type: string
45
+ description: Iconify icon name in the format collection:icon-name (e.g., lucide:book)
46
+ required:
47
+ - path
48
+ - icon
49
+ description: List of document items with generated Iconify icon names
50
+ required:
51
+ - documentList
52
+
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Generate icons for root-level document structure items if they don't have one or if title/description changed
3
+ * Reusable function for generating document icons in various contexts
4
+ * Can be called as a standalone function with { documentStructure, originalItems? } or as a function skill with (input, options)
5
+ * @param {Object|Array} inputOrParams - Either input from previous step (with documentStructure) or params object with documentStructure and optional originalItems
6
+ * @param {Object} options - Agent options with context
7
+ * @param {Array<{path: string, title?: string, description?: string}>} [inputOrParams.originalItems] - Original items for comparison (optional, used to detect title/description changes)
8
+ * @returns {Promise<Object>} - Returns input unchanged (modifies documentStructure in place)
9
+ */
10
+ export default async function generateDocumentIconIfNeeded(inputOrParams, options) {
11
+ // Handle both calling patterns:
12
+ // 1. As function skill: (input, options) where input.documentStructure exists
13
+ // 2. As standalone function: ({ documentStructure, originalItems? }, options)
14
+ const documentStructure =
15
+ inputOrParams?.documentStructure || (Array.isArray(inputOrParams) ? inputOrParams : null);
16
+ const originalItems = inputOrParams?.originalItems || [];
17
+
18
+ if (!documentStructure || !Array.isArray(documentStructure)) {
19
+ // Return input unchanged if no documentStructure to process
20
+ return inputOrParams || {};
21
+ }
22
+
23
+ // Create a map of original items by path for quick lookup
24
+ const originalItemsMap = new Map(
25
+ originalItems.map((item) => [item.path, { title: item.title, description: item.description }]),
26
+ );
27
+
28
+ // Filter root-level items that need icon generation or update
29
+ const itemsNeedingIcon = documentStructure.filter((item) => {
30
+ // Only process root-level items (parentId is null, undefined, or empty string)
31
+ const isRootLevel = !item.parentId || item.parentId === "null" || item.parentId === "";
32
+ if (!isRootLevel) return false;
33
+
34
+ // Must have title and description for icon generation
35
+ if (!item.title || !item.description) return false;
36
+
37
+ // Check if icon is missing
38
+ const hasNoIcon = !item.icon;
39
+
40
+ // Check if title or description changed (if original item exists)
41
+ const originalItem = originalItemsMap.get(item.path);
42
+ const titleChanged = originalItem && originalItem.title !== item.title;
43
+ const descriptionChanged = originalItem && originalItem.description !== item.description;
44
+ const contentChanged = titleChanged || descriptionChanged;
45
+
46
+ // Generate/update icon if: missing icon OR content changed
47
+ return hasNoIcon || contentChanged;
48
+ });
49
+
50
+ if (itemsNeedingIcon.length === 0) {
51
+ return;
52
+ }
53
+
54
+ const documentList = itemsNeedingIcon.map((item) => ({
55
+ path: item.path,
56
+ title: item.title,
57
+ description: item.description,
58
+ }));
59
+
60
+ const iconAgent = options?.context?.agents?.["documentIconGenerate"];
61
+ if (!iconAgent) {
62
+ console.warn("⚠️ documentIconGenerate agent not found. Skipping icon generation.");
63
+ return;
64
+ }
65
+
66
+ try {
67
+ const iconResult = await options.context.invoke(iconAgent, {
68
+ documentList,
69
+ });
70
+
71
+ // Update the document items with generated icons using path as the key
72
+ if (iconResult.documentList && Array.isArray(iconResult.documentList)) {
73
+ const iconMap = new Map(iconResult.documentList.map((item) => [item.path, item]));
74
+
75
+ for (const item of documentStructure) {
76
+ const iconData = iconMap.get(item.path);
77
+ if (iconData?.icon) {
78
+ item.icon = iconData.icon;
79
+ }
80
+ }
81
+ }
82
+ } catch (error) {
83
+ console.warn("⚠️ Failed to generate document icons:", error.message);
84
+ console.warn("Continuing without icons.");
85
+ }
86
+
87
+ // Return input unchanged (documentStructure is modified in place)
88
+ return inputOrParams || {};
89
+ }
90
+
91
+ generateDocumentIconIfNeeded.taskTitle = "Generate document icons if needed";
92
+ generateDocumentIconIfNeeded.description =
93
+ "Generate appropriate Lucide icons for root-level document structure items based on their title and description, or update icon if title/description changed";
package/aigne.yaml CHANGED
@@ -83,6 +83,8 @@ agents:
83
83
 
84
84
  - ./agents/utils/document-title-streamline.yaml
85
85
  - ./agents/utils/streamline-document-titles-if-needed.mjs
86
+ - ./agents/utils/document-icon-generate.yaml
87
+ - ./agents/utils/generate-document-icon-if-needed.mjs
86
88
 
87
89
  # User Preferences & Chat
88
90
  - ./agents/prefs/index.mjs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/doc-smith",
3
- "version": "0.8.16-beta",
3
+ "version": "0.8.16-beta.1",
4
4
  "description": "AI-driven documentation generation tool built on the AIGNE Framework",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -24,17 +24,12 @@
24
24
  "author": "Arcblock <blocklet@arcblock.io> https://github.com/blocklet",
25
25
  "license": "Elastic-2.0",
26
26
  "dependencies": {
27
- "@aigne/aigne-hub": "^0.10.5-beta.3",
28
- "@aigne/anthropic": "^0.14.5-beta.3",
29
27
  "@aigne/cli": "^1.53.1-beta.4",
30
28
  "@aigne/core": "^1.65.1-beta.3",
31
- "@aigne/gemini": "^0.14.5-beta.3",
32
- "@aigne/openai": "^0.16.5-beta.3",
33
29
  "@aigne/publish-docs": "^0.12.1",
34
30
  "@blocklet/payment-broker-client": "^1.22.8",
35
31
  "@terrastruct/d2": "^0.1.33",
36
32
  "chalk": "^5.5.0",
37
- "cli-highlight": "^2.1.11",
38
33
  "debug": "^4.4.1",
39
34
  "diff": "^8.0.2",
40
35
  "dompurify": "^3.2.6",
@@ -44,6 +39,7 @@
44
39
  "glob": "^11.0.3",
45
40
  "gpt-tokenizer": "^3.2.0",
46
41
  "image-size": "^2.0.2",
42
+ "is-in-ci": "^2.0.0",
47
43
  "isbinaryfile": "^5.0.6",
48
44
  "jsdom": "^26.1.0",
49
45
  "marked": "^15.0.12",
@@ -57,7 +53,7 @@
57
53
  "remark-gfm": "^4.0.1",
58
54
  "remark-lint": "^10.0.1",
59
55
  "remark-parse": "^11.0.0",
60
- "terminal-link": "^4.0.0",
56
+ "terminal-link": "^5.0.0",
61
57
  "typescript": "^5.9.3",
62
58
  "ufo": "^1.6.1",
63
59
  "unified": "^11.0.5",
@@ -1,12 +1,18 @@
1
1
  <media_file_list_usage_rules>
2
2
 
3
- **Usage Workflow**
3
+ ## Media File List Usage Rules
4
+
5
+ You must use the provided `<media_file_list>` data to determine which media files to use and where to insert them.
6
+
7
+ ### Usage Workflow
8
+
4
9
  1. Read the `<media_file_list>` data and take note of each file's `path` and `description` as references.
5
10
  2. Combine those descriptions with the current document's content to decide which images should be used and where they should be inserted.
6
11
  3. Confirm that every inserted image path comes from `<media_file_list>`. If a path is missing from that list, replace it with one that is included.
7
12
 
8
- **Usage Requirements**
13
+ ### Usage Requirements
9
14
  - Insert images with Markdown syntax: `![Descriptive alt text](<path-from-media_file_list>)`.
10
15
  - Never invent, reinterpret, fabricate, normalize, or rewrite any media file path under any circumstances.
16
+ - After inserting a media file, update the surrounding document text to introduce, reference, or describe the media, so the media is properly integrated and its purpose is clear to readers.
11
17
 
12
18
  </media_file_list_usage_rules>