@aigne/doc-smith 0.8.12-beta.6 → 0.8.12-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.
- package/.aigne/doc-smith/config.yaml +1 -1
- package/.aigne/doc-smith/history.yaml +37 -0
- package/.aigne/doc-smith/media-description.yaml +91 -0
- package/.aigne/doc-smith/preferences.yml +12 -0
- package/.aigne/doc-smith/upload-cache.yaml +36 -69
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +24 -0
- package/agents/clear/choose-contents.mjs +14 -1
- package/agents/clear/clear-media-description.mjs +129 -0
- package/agents/clear/index.yaml +3 -1
- package/agents/evaluate/code-snippet.mjs +28 -24
- package/agents/evaluate/document-structure.yaml +0 -4
- package/agents/evaluate/document.yaml +1 -5
- package/agents/generate/index.yaml +1 -0
- package/agents/generate/update-document-structure.yaml +9 -3
- package/agents/history/view.mjs +5 -2
- package/agents/init/index.mjs +10 -0
- package/agents/media/batch-generate-media-description.yaml +44 -0
- package/agents/media/generate-media-description.yaml +47 -0
- package/agents/media/load-media-description.mjs +238 -0
- package/agents/update/generate-document.yaml +10 -4
- package/agents/update/index.yaml +1 -0
- package/agents/update/update-document-detail.yaml +9 -3
- package/agents/update/user-review-document.mjs +2 -1
- package/agents/utils/load-sources.mjs +103 -53
- package/aigne.yaml +6 -0
- package/assets/report-template/report.html +34 -34
- package/docs/configuration-initial-setup.md +74 -55
- package/docs/configuration.ja.md +59 -86
- package/docs/configuration.md +59 -86
- package/docs/configuration.zh-TW.md +59 -86
- package/docs/configuration.zh.md +59 -86
- package/docs/getting-started.ja.md +43 -24
- package/docs/getting-started.md +29 -10
- package/docs/getting-started.zh-TW.md +42 -23
- package/docs/getting-started.zh.md +39 -20
- package/docs/guides-cleaning-up.ja.md +16 -15
- package/docs/guides-cleaning-up.md +19 -17
- package/docs/guides-cleaning-up.zh-TW.md +16 -15
- package/docs/guides-cleaning-up.zh.md +12 -11
- package/docs/guides-evaluating-documents.md +70 -29
- package/docs/guides-generating-documentation.ja.md +34 -32
- package/docs/guides-generating-documentation.md +59 -119
- package/docs/guides-generating-documentation.zh-TW.md +34 -32
- package/docs/guides-generating-documentation.zh.md +30 -28
- package/docs/guides-interactive-chat.md +34 -26
- package/docs/guides-managing-history.ja.md +17 -20
- package/docs/guides-managing-history.md +19 -17
- package/docs/guides-managing-history.zh-TW.md +18 -21
- package/docs/guides-managing-history.zh.md +13 -16
- package/docs/guides-publishing-your-docs.md +40 -35
- package/docs/guides-translating-documentation.ja.md +17 -17
- package/docs/guides-translating-documentation.md +39 -34
- package/docs/guides-translating-documentation.zh-TW.md +21 -21
- package/docs/guides-translating-documentation.zh.md +18 -18
- package/docs/guides-updating-documentation.ja.md +35 -35
- package/docs/guides-updating-documentation.md +11 -9
- package/docs/guides-updating-documentation.zh-TW.md +27 -27
- package/docs/guides-updating-documentation.zh.md +26 -26
- package/docs/overview.ja.md +13 -13
- package/docs/overview.md +2 -2
- package/docs/overview.zh-TW.md +19 -19
- package/docs/overview.zh.md +16 -16
- package/docs/release-notes.md +60 -27
- package/package.json +2 -1
- package/prompts/common/afs/afs-tools-usage.md +5 -0
- package/prompts/common/afs/use-afs-instruction.md +1 -0
- package/prompts/detail/generate/system-prompt.md +0 -13
- package/prompts/detail/generate/user-prompt.md +7 -0
- package/prompts/detail/update/system-prompt.md +1 -2
- package/prompts/detail/update/user-prompt.md +7 -0
- package/prompts/evaluate/document-structure.md +6 -7
- package/prompts/evaluate/document.md +16 -25
- package/prompts/media/media-description/system-prompt.md +35 -0
- package/prompts/media/media-description/user-prompt.md +8 -0
- package/prompts/structure/generate/system-prompt.md +0 -19
- package/prompts/structure/generate/user-prompt.md +22 -1
- package/prompts/structure/update/system-prompt.md +0 -17
- package/prompts/structure/update/user-prompt.md +24 -0
- package/tests/agents/history/view.test.mjs +97 -0
- package/tests/utils/history-utils.test.mjs +125 -97
- package/utils/constants/index.mjs +0 -107
- package/utils/file-utils.mjs +42 -1
- package/utils/history-utils.mjs +3 -3
- package/agents/update/fs-tools/glob.mjs +0 -184
- package/agents/update/fs-tools/grep.mjs +0 -317
- package/agents/update/fs-tools/read-file.mjs +0 -309
- package/media.md +0 -19
- package/tests/agents/update/fs-tools/glob.test.mjs +0 -438
- package/tests/agents/update/fs-tools/grep.test.mjs +0 -279
- package/tests/agents/update/fs-tools/read-file.test.mjs +0 -549
|
@@ -38,32 +38,37 @@ export default async function evaluateDocumentCode({ content }) {
|
|
|
38
38
|
const checkList = await pMap(
|
|
39
39
|
checkPromiseList,
|
|
40
40
|
async (item) => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
41
|
+
try {
|
|
42
|
+
const result = await pRetry(() => lintCode(item), {
|
|
43
|
+
onFailedAttempt: ({ error, attemptNumber, retriesLeft }) => {
|
|
44
|
+
debug(
|
|
45
|
+
`Attempt ${attemptNumber} failed: ${error.message}. There are ${retriesLeft} retries left.`,
|
|
46
|
+
);
|
|
47
|
+
},
|
|
48
|
+
retries: 3,
|
|
49
|
+
});
|
|
50
|
+
// lint occurs error, ignore
|
|
51
|
+
if (!result.success) {
|
|
52
|
+
debug("Lint failed", item, result);
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
if (!result.issues || result.issues.length === 0) {
|
|
57
|
+
debug("Lint result empty issues", item, result);
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
errorCount += 1;
|
|
62
|
+
return result.issues.map((x) => {
|
|
63
|
+
return {
|
|
64
|
+
...x,
|
|
65
|
+
level: severityMapLevel[x.severity],
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
} catch (error) {
|
|
69
|
+
debug("Lint occurred error", error);
|
|
57
70
|
return [];
|
|
58
71
|
}
|
|
59
|
-
|
|
60
|
-
errorCount += 1;
|
|
61
|
-
return result.issues.map((x) => {
|
|
62
|
-
return {
|
|
63
|
-
...x,
|
|
64
|
-
level: severityMapLevel[x.severity],
|
|
65
|
-
};
|
|
66
|
-
});
|
|
67
72
|
},
|
|
68
73
|
{ concurrency: 5 },
|
|
69
74
|
);
|
|
@@ -71,7 +76,6 @@ export default async function evaluateDocumentCode({ content }) {
|
|
|
71
76
|
|
|
72
77
|
return {
|
|
73
78
|
codeEvaluation: {
|
|
74
|
-
baseline: 100,
|
|
75
79
|
details: checkListResult,
|
|
76
80
|
totalCount,
|
|
77
81
|
ignoreCount,
|
|
@@ -32,9 +32,6 @@ output_schema:
|
|
|
32
32
|
structureEvaluation:
|
|
33
33
|
type: object
|
|
34
34
|
properties:
|
|
35
|
-
baseline:
|
|
36
|
-
type: integer
|
|
37
|
-
description: Baseline score of selected purposes
|
|
38
35
|
details:
|
|
39
36
|
type: array
|
|
40
37
|
items:
|
|
@@ -64,7 +61,6 @@ output_schema:
|
|
|
64
61
|
- description
|
|
65
62
|
description: List of detailed evaluations for each purpose dimension
|
|
66
63
|
required:
|
|
67
|
-
- baseline
|
|
68
64
|
- details
|
|
69
65
|
required:
|
|
70
66
|
- structureEvaluation
|
|
@@ -39,9 +39,6 @@ output_schema:
|
|
|
39
39
|
documentEvaluation:
|
|
40
40
|
type: object
|
|
41
41
|
properties:
|
|
42
|
-
baseline:
|
|
43
|
-
type: integer
|
|
44
|
-
description: Fixed baseline score (80)
|
|
45
42
|
details:
|
|
46
43
|
type: array
|
|
47
44
|
description: Detailed observations contributing to the final score
|
|
@@ -50,7 +47,7 @@ output_schema:
|
|
|
50
47
|
properties:
|
|
51
48
|
dimension:
|
|
52
49
|
type: string
|
|
53
|
-
enum: [readability, coherence, contentQuality, consistency, purposeAlignment, audienceAlignment, knowledgeLevelAlignment
|
|
50
|
+
enum: [readability, coherence, contentQuality, consistency, purposeAlignment, audienceAlignment, knowledgeLevelAlignment]
|
|
54
51
|
description: Dimension associated with this observation
|
|
55
52
|
level:
|
|
56
53
|
type: string
|
|
@@ -72,7 +69,6 @@ output_schema:
|
|
|
72
69
|
- line
|
|
73
70
|
- description
|
|
74
71
|
required:
|
|
75
|
-
- baseline
|
|
76
72
|
- details
|
|
77
73
|
required:
|
|
78
74
|
- documentEvaluation
|
|
@@ -32,11 +32,17 @@ input_schema:
|
|
|
32
32
|
- documentStructure
|
|
33
33
|
- feedback
|
|
34
34
|
output_key: message
|
|
35
|
+
afs:
|
|
36
|
+
modules:
|
|
37
|
+
- module: system-fs
|
|
38
|
+
options:
|
|
39
|
+
mount: /sources
|
|
40
|
+
path: .
|
|
41
|
+
description: |
|
|
42
|
+
Codebase of the project to be documented used as context for document generation,
|
|
43
|
+
should search and read as needed while generating document content
|
|
35
44
|
skills:
|
|
36
45
|
- ./document-structure-tools/add-document.mjs
|
|
37
46
|
- ./document-structure-tools/delete-document.mjs
|
|
38
47
|
- ./document-structure-tools/update-document.mjs
|
|
39
48
|
- ./document-structure-tools/move-document.mjs
|
|
40
|
-
- ../update/fs-tools/glob.mjs
|
|
41
|
-
- ../update/fs-tools/grep.mjs
|
|
42
|
-
- ../update/fs-tools/read-file.mjs
|
package/agents/history/view.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
2
3
|
import { getHistory } from "../../utils/history-utils.mjs";
|
|
3
4
|
|
|
4
5
|
export default function viewHistory() {
|
|
@@ -35,8 +36,10 @@ export default function viewHistory() {
|
|
|
35
36
|
* Generate a short hash from timestamp (git-style)
|
|
36
37
|
*/
|
|
37
38
|
function generateShortHash(timestamp) {
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
// Create a deterministic hash from timestamp only
|
|
40
|
+
// This ensures the same timestamp always produces the same hash
|
|
41
|
+
const hash = createHash("sha1").update(timestamp).digest("hex");
|
|
42
|
+
return hash.substring(0, 8); // First 8 chars of SHA1 hash
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
/**
|
package/agents/init/index.mjs
CHANGED
|
@@ -418,6 +418,10 @@ export function generateYAML(input) {
|
|
|
418
418
|
// Paths
|
|
419
419
|
docsDir: input.docsDir || "./aigne/doc-smith/docs",
|
|
420
420
|
sourcesPath: input.sourcesPath || [],
|
|
421
|
+
media: {
|
|
422
|
+
// Image filtering settings
|
|
423
|
+
minImageWidth: input.minImageWidth || 800,
|
|
424
|
+
},
|
|
421
425
|
};
|
|
422
426
|
|
|
423
427
|
// Generate comments and structure
|
|
@@ -530,6 +534,12 @@ export function generateYAML(input) {
|
|
|
530
534
|
const sourcesPathSection = yamlStringify({ sourcesPath: config.sourcesPath }).trim();
|
|
531
535
|
yaml += `${sourcesPathSection.replace(/^sourcesPath:/, "sourcesPath: # Source code paths to analyze")}\n`;
|
|
532
536
|
|
|
537
|
+
// Image filtering settings
|
|
538
|
+
const mediaInfoSection = yamlStringify({
|
|
539
|
+
media: config.media,
|
|
540
|
+
}).trim();
|
|
541
|
+
yaml += `# minImageWidth: Only images wider than this value (in pixels) will be used in page generation\n${mediaInfoSection}\n`;
|
|
542
|
+
|
|
533
543
|
return yaml;
|
|
534
544
|
}
|
|
535
545
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
type: team
|
|
2
|
+
name: batchGenerateMediaDescription
|
|
3
|
+
description: Batch generate media (image/video) descriptions with concurrency
|
|
4
|
+
skills:
|
|
5
|
+
- url: ./generate-media-description.yaml
|
|
6
|
+
task_render_mode: collapse
|
|
7
|
+
task_title: Generate Media Description
|
|
8
|
+
input_schema:
|
|
9
|
+
type: object
|
|
10
|
+
properties:
|
|
11
|
+
mediaToDescribe:
|
|
12
|
+
type: array
|
|
13
|
+
items:
|
|
14
|
+
type: object
|
|
15
|
+
properties:
|
|
16
|
+
name:
|
|
17
|
+
type: string
|
|
18
|
+
width:
|
|
19
|
+
type: number
|
|
20
|
+
height:
|
|
21
|
+
type: number
|
|
22
|
+
hash:
|
|
23
|
+
type: string
|
|
24
|
+
path:
|
|
25
|
+
type: string
|
|
26
|
+
type:
|
|
27
|
+
type: string
|
|
28
|
+
mediaFile:
|
|
29
|
+
type: array
|
|
30
|
+
items:
|
|
31
|
+
type: object
|
|
32
|
+
properties:
|
|
33
|
+
type:
|
|
34
|
+
type: string
|
|
35
|
+
path:
|
|
36
|
+
type: string
|
|
37
|
+
filename:
|
|
38
|
+
type: string
|
|
39
|
+
mimeType:
|
|
40
|
+
type: string
|
|
41
|
+
description: Array of media files (images/videos) that need descriptions
|
|
42
|
+
iterate_on: mediaToDescribe
|
|
43
|
+
concurrency: 5
|
|
44
|
+
mode: sequential
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: generateMediaDescription
|
|
2
|
+
description: Generate description for a single media file (image/video)
|
|
3
|
+
model: "google/gemini-2.5-flash"
|
|
4
|
+
modalities: ["text", "image"]
|
|
5
|
+
instructions:
|
|
6
|
+
- role: system
|
|
7
|
+
url: ../../prompts/media/media-description/system-prompt.md
|
|
8
|
+
- role: user
|
|
9
|
+
url: ../../prompts/media/media-description/user-prompt.md
|
|
10
|
+
input_file_key: mediaFile
|
|
11
|
+
include_input_in_output: true
|
|
12
|
+
input_schema:
|
|
13
|
+
type: object
|
|
14
|
+
properties:
|
|
15
|
+
name:
|
|
16
|
+
type: string
|
|
17
|
+
description: Media file name
|
|
18
|
+
width:
|
|
19
|
+
type: number
|
|
20
|
+
description: Media width in pixels
|
|
21
|
+
height:
|
|
22
|
+
type: number
|
|
23
|
+
description: Media height in pixels
|
|
24
|
+
hash:
|
|
25
|
+
type: string
|
|
26
|
+
path:
|
|
27
|
+
type: string
|
|
28
|
+
description: Media path
|
|
29
|
+
type:
|
|
30
|
+
type: string
|
|
31
|
+
description: Media type (image/video)
|
|
32
|
+
mediaFile:
|
|
33
|
+
type: array
|
|
34
|
+
items:
|
|
35
|
+
type: object
|
|
36
|
+
properties:
|
|
37
|
+
type:
|
|
38
|
+
type: string
|
|
39
|
+
path:
|
|
40
|
+
type: string
|
|
41
|
+
filename:
|
|
42
|
+
type: string
|
|
43
|
+
mimeType:
|
|
44
|
+
type: string
|
|
45
|
+
required:
|
|
46
|
+
- name
|
|
47
|
+
output_key: description
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { parse, stringify } from "yaml";
|
|
6
|
+
import { getMediaDescriptionCachePath } from "../../utils/file-utils.mjs";
|
|
7
|
+
|
|
8
|
+
const SIZE_THRESHOLD = 10 * 1024 * 1024; // 10MB
|
|
9
|
+
|
|
10
|
+
// Supported MIME types for Gemini AI
|
|
11
|
+
const SUPPORTED_IMAGE_TYPES = new Set([
|
|
12
|
+
"image/png",
|
|
13
|
+
"image/jpeg",
|
|
14
|
+
"image/webp",
|
|
15
|
+
"image/heic",
|
|
16
|
+
"image/heif",
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
const SUPPORTED_VIDEO_TYPES = new Set([
|
|
20
|
+
"video/mp4",
|
|
21
|
+
"video/mpeg",
|
|
22
|
+
"video/mov",
|
|
23
|
+
"video/avi",
|
|
24
|
+
"video/x-flv",
|
|
25
|
+
"video/mpg",
|
|
26
|
+
"video/webm",
|
|
27
|
+
"video/wmv",
|
|
28
|
+
"video/3gpp",
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Calculate hash for a media file
|
|
33
|
+
* For files < 10MB: use file content
|
|
34
|
+
* For files >= 10MB: use path + size + mtime to avoid memory issues
|
|
35
|
+
* @param {string} absolutePath - The absolute path to the media file
|
|
36
|
+
* @returns {Promise<string>} - The hash of the file
|
|
37
|
+
*/
|
|
38
|
+
async function calculateMediaHash(absolutePath) {
|
|
39
|
+
const stats = await stat(absolutePath);
|
|
40
|
+
|
|
41
|
+
if (stats.size < SIZE_THRESHOLD) {
|
|
42
|
+
// Small file: use full content
|
|
43
|
+
const content = await readFile(absolutePath);
|
|
44
|
+
return createHash("sha256").update(content).digest("hex");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Large file: use path + size + mtime
|
|
48
|
+
const hashInput = `${absolutePath}:${stats.size}:${stats.mtimeMs}`;
|
|
49
|
+
return createHash("sha256").update(hashInput).digest("hex");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Load media descriptions from cache and generate new ones if needed
|
|
54
|
+
* @param {Object} input - Input parameters
|
|
55
|
+
* @param {Array} input.mediaFiles - Array of media file objects from load-sources
|
|
56
|
+
* @param {string} input.docsDir - Base directory for documentation
|
|
57
|
+
* @param {Object} options - Agent options
|
|
58
|
+
* @returns {Promise<Object>} - Updated assetsContent with media descriptions
|
|
59
|
+
*/
|
|
60
|
+
export default async function loadMediaDescription(input, options) {
|
|
61
|
+
const { mediaFiles = [], docsDir } = input;
|
|
62
|
+
|
|
63
|
+
// Filter to get image and video files with supported MIME types
|
|
64
|
+
const mediaFilesToProcess = mediaFiles.filter((file) => {
|
|
65
|
+
if (file.type === "image") {
|
|
66
|
+
return SUPPORTED_IMAGE_TYPES.has(file.mimeType);
|
|
67
|
+
}
|
|
68
|
+
if (file.type === "video") {
|
|
69
|
+
return SUPPORTED_VIDEO_TYPES.has(file.mimeType);
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Path to media description cache file
|
|
75
|
+
const cacheFilePath = getMediaDescriptionCachePath();
|
|
76
|
+
|
|
77
|
+
// Load existing cache
|
|
78
|
+
let cache = {};
|
|
79
|
+
if (existsSync(cacheFilePath)) {
|
|
80
|
+
try {
|
|
81
|
+
const cacheContent = await readFile(cacheFilePath, "utf8");
|
|
82
|
+
const parsedCache = parse(cacheContent);
|
|
83
|
+
cache = parsedCache?.descriptions || {};
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.warn("Failed to read media description cache:", error.message);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Find media files without descriptions
|
|
90
|
+
const mediaToDescribe = [];
|
|
91
|
+
const mediaHashMap = new Map();
|
|
92
|
+
|
|
93
|
+
const absoluteDocsDir = path.resolve(process.cwd(), docsDir);
|
|
94
|
+
|
|
95
|
+
// Only process media files that need AI description
|
|
96
|
+
for (const mediaFile of mediaFilesToProcess) {
|
|
97
|
+
// Convert relative path to absolute path for consistent hashing
|
|
98
|
+
// mediaFiles.path is relative to docsDir
|
|
99
|
+
const absolutePath = path.join(absoluteDocsDir, mediaFile.path);
|
|
100
|
+
const mediaHash = await calculateMediaHash(absolutePath);
|
|
101
|
+
mediaHashMap.set(mediaFile.path, mediaHash);
|
|
102
|
+
|
|
103
|
+
if (!cache[mediaHash]) {
|
|
104
|
+
mediaToDescribe.push({
|
|
105
|
+
...mediaFile,
|
|
106
|
+
hash: mediaHash,
|
|
107
|
+
path: mediaFile.path,
|
|
108
|
+
mediaFile: [
|
|
109
|
+
{
|
|
110
|
+
type: "local",
|
|
111
|
+
path: absolutePath,
|
|
112
|
+
filename: mediaFile.name,
|
|
113
|
+
mimeType: mediaFile.mimeType,
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Generate descriptions for media files without cache - use team agent for concurrent processing
|
|
121
|
+
const newDescriptions = {};
|
|
122
|
+
if (mediaToDescribe.length > 0) {
|
|
123
|
+
try {
|
|
124
|
+
// Use batch team agent for concurrent processing
|
|
125
|
+
const results = await options.context.invoke(
|
|
126
|
+
options.context.agents["batchGenerateMediaDescription"],
|
|
127
|
+
{
|
|
128
|
+
mediaToDescribe,
|
|
129
|
+
},
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// Process results - results is an array of individual results
|
|
133
|
+
if (Array.isArray(results?.mediaToDescribe)) {
|
|
134
|
+
for (const result of results.mediaToDescribe) {
|
|
135
|
+
if (result?.hash && result?.description) {
|
|
136
|
+
newDescriptions[result.hash] = {
|
|
137
|
+
path: result.path,
|
|
138
|
+
description: result.description,
|
|
139
|
+
generatedAt: new Date().toISOString(),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Merge new descriptions into cache
|
|
146
|
+
Object.assign(cache, newDescriptions);
|
|
147
|
+
|
|
148
|
+
// Save updated cache
|
|
149
|
+
await mkdir(path.dirname(cacheFilePath), { recursive: true });
|
|
150
|
+
const cacheYaml = stringify({
|
|
151
|
+
descriptions: cache,
|
|
152
|
+
lastUpdated: new Date().toISOString(),
|
|
153
|
+
});
|
|
154
|
+
await writeFile(cacheFilePath, cacheYaml, "utf8");
|
|
155
|
+
|
|
156
|
+
console.log(`Generated descriptions for ${Object.keys(newDescriptions).length} media files`);
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error("Failed to generate media descriptions:", error.message);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Build enhanced assetsContent with descriptions
|
|
163
|
+
let enhancedAssetsContent = "# Available Media Assets for Documentation\n\n";
|
|
164
|
+
|
|
165
|
+
if (mediaFiles.length > 0) {
|
|
166
|
+
enhancedAssetsContent += "```yaml\n";
|
|
167
|
+
enhancedAssetsContent += "assets:\n";
|
|
168
|
+
|
|
169
|
+
for (const asset of mediaFiles) {
|
|
170
|
+
enhancedAssetsContent += ` - name: "${asset.name}"\n`;
|
|
171
|
+
enhancedAssetsContent += ` path: "${asset.path}"\n`;
|
|
172
|
+
enhancedAssetsContent += ` type: "${asset.type}"\n`;
|
|
173
|
+
|
|
174
|
+
// Add description for images and videos
|
|
175
|
+
if (asset.type === "image" || asset.type === "video") {
|
|
176
|
+
const mediaHash = mediaHashMap.get(asset.path);
|
|
177
|
+
const cachedDesc = cache[mediaHash];
|
|
178
|
+
if (cachedDesc?.description) {
|
|
179
|
+
enhancedAssetsContent += ` description: "${cachedDesc.description}"\n`;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Add dimensions for images and videos
|
|
184
|
+
if (asset.width && asset.height) {
|
|
185
|
+
enhancedAssetsContent += ` width: ${asset.width}\n`;
|
|
186
|
+
enhancedAssetsContent += ` height: ${asset.height}\n`;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
enhancedAssetsContent += "```\n";
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
...input,
|
|
195
|
+
assetsContent: enhancedAssetsContent,
|
|
196
|
+
mediaFiles,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
loadMediaDescription.input_schema = {
|
|
201
|
+
type: "object",
|
|
202
|
+
properties: {
|
|
203
|
+
mediaFiles: {
|
|
204
|
+
type: "array",
|
|
205
|
+
items: {
|
|
206
|
+
type: "object",
|
|
207
|
+
properties: {
|
|
208
|
+
name: { type: "string" },
|
|
209
|
+
path: { type: "string" },
|
|
210
|
+
type: { type: "string" },
|
|
211
|
+
width: { type: "number" },
|
|
212
|
+
height: { type: "number" },
|
|
213
|
+
mimeType: { type: "string" },
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
description: "Array of media file objects (images/videos)",
|
|
217
|
+
},
|
|
218
|
+
docsDir: {
|
|
219
|
+
type: "string",
|
|
220
|
+
description: "Base directory for documentation",
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
required: ["mediaFiles", "docsDir"],
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
loadMediaDescription.output_schema = {
|
|
227
|
+
type: "object",
|
|
228
|
+
properties: {
|
|
229
|
+
assetsContent: {
|
|
230
|
+
type: "string",
|
|
231
|
+
description: "Enhanced assets content with media descriptions",
|
|
232
|
+
},
|
|
233
|
+
mediaFiles: {
|
|
234
|
+
type: "array",
|
|
235
|
+
description: "Array of media file objects",
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
};
|
|
@@ -45,10 +45,16 @@ input_schema:
|
|
|
45
45
|
- datasources
|
|
46
46
|
- originalDocumentStructure
|
|
47
47
|
output_key: content
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
afs:
|
|
49
|
+
modules:
|
|
50
|
+
- module: system-fs
|
|
51
|
+
options:
|
|
52
|
+
mount: /sources
|
|
53
|
+
path: .
|
|
54
|
+
description: |
|
|
55
|
+
Codebase of the project to be documented used as context for document generation,
|
|
56
|
+
should search and read as needed while generating document content
|
|
57
|
+
# skills:
|
|
52
58
|
# FIXME: @zhanghan temporary disable diagram tool
|
|
53
59
|
# - type: team
|
|
54
60
|
# task_render_mode: collapse
|
package/agents/update/index.yaml
CHANGED
|
@@ -30,6 +30,7 @@ skills:
|
|
|
30
30
|
default_input:
|
|
31
31
|
requiredFeedback: false
|
|
32
32
|
- ../utils/format-document-structure.mjs
|
|
33
|
+
- ../media/load-media-description.mjs
|
|
33
34
|
- ../update/check-update-is-single.mjs
|
|
34
35
|
- ../update/save-and-translate-document.mjs
|
|
35
36
|
- url: ../utils/action-success.mjs
|
|
@@ -44,9 +44,15 @@ input_schema:
|
|
|
44
44
|
- originalContent
|
|
45
45
|
- feedback
|
|
46
46
|
output_key: message
|
|
47
|
+
afs:
|
|
48
|
+
modules:
|
|
49
|
+
- module: system-fs
|
|
50
|
+
options:
|
|
51
|
+
mount: /sources
|
|
52
|
+
path: .
|
|
53
|
+
description: |
|
|
54
|
+
Codebase of the project to be documented used as context for document generation,
|
|
55
|
+
should search and read as needed while generating document content
|
|
47
56
|
skills:
|
|
48
57
|
- ./document-tools/update-document-content.mjs
|
|
49
|
-
- ./fs-tools/glob.mjs
|
|
50
|
-
- ./fs-tools/grep.mjs
|
|
51
|
-
- ./fs-tools/read-file.mjs
|
|
52
58
|
task_render_mode: collapse
|