@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
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import fsPromises from "node:fs/promises";
|
|
3
|
-
import path, { isAbsolute } from "node:path";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Detects if a file is likely binary by checking for null bytes
|
|
7
|
-
*/
|
|
8
|
-
function isBinaryFile(buffer) {
|
|
9
|
-
// Check first 8KB for null bytes
|
|
10
|
-
const checkLength = Math.min(buffer.length, 8192);
|
|
11
|
-
for (let i = 0; i < checkLength; i++) {
|
|
12
|
-
if (buffer[i] === 0) {
|
|
13
|
-
return true;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Gets MIME type based on file extension
|
|
21
|
-
*/
|
|
22
|
-
function getMimeType(filePath) {
|
|
23
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
24
|
-
const mimeTypes = {
|
|
25
|
-
// Text files
|
|
26
|
-
".txt": "text/plain",
|
|
27
|
-
".md": "text/markdown",
|
|
28
|
-
".json": "application/json",
|
|
29
|
-
".js": "text/javascript",
|
|
30
|
-
".mjs": "text/javascript",
|
|
31
|
-
".ts": "text/typescript",
|
|
32
|
-
".tsx": "text/typescript",
|
|
33
|
-
".jsx": "text/javascript",
|
|
34
|
-
".py": "text/x-python",
|
|
35
|
-
".java": "text/x-java",
|
|
36
|
-
".cpp": "text/x-c",
|
|
37
|
-
".c": "text/x-c",
|
|
38
|
-
".h": "text/x-c",
|
|
39
|
-
".css": "text/css",
|
|
40
|
-
".html": "text/html",
|
|
41
|
-
".xml": "text/xml",
|
|
42
|
-
".yaml": "text/yaml",
|
|
43
|
-
".yml": "text/yaml",
|
|
44
|
-
".toml": "text/plain",
|
|
45
|
-
".ini": "text/plain",
|
|
46
|
-
".cfg": "text/plain",
|
|
47
|
-
".conf": "text/plain",
|
|
48
|
-
".sh": "text/x-shellscript",
|
|
49
|
-
".bash": "text/x-shellscript",
|
|
50
|
-
".zsh": "text/x-shellscript",
|
|
51
|
-
".fish": "text/x-shellscript",
|
|
52
|
-
|
|
53
|
-
// Image files
|
|
54
|
-
".jpg": "image/jpeg",
|
|
55
|
-
".jpeg": "image/jpeg",
|
|
56
|
-
".png": "image/png",
|
|
57
|
-
".gif": "image/gif",
|
|
58
|
-
".webp": "image/webp",
|
|
59
|
-
".svg": "image/svg+xml",
|
|
60
|
-
".bmp": "image/bmp",
|
|
61
|
-
".ico": "image/x-icon",
|
|
62
|
-
|
|
63
|
-
// Document files
|
|
64
|
-
".pdf": "application/pdf",
|
|
65
|
-
".doc": "application/msword",
|
|
66
|
-
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
67
|
-
|
|
68
|
-
// Other
|
|
69
|
-
".zip": "application/zip",
|
|
70
|
-
".tar": "application/x-tar",
|
|
71
|
-
".gz": "application/gzip",
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
return mimeTypes[ext] || "application/octet-stream";
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Validates file path and checks accessibility
|
|
79
|
-
*/
|
|
80
|
-
function validateFilePath(filePath) {
|
|
81
|
-
if (!filePath || typeof filePath !== "string" || filePath.trim() === "") {
|
|
82
|
-
return "File path parameter is required and cannot be empty";
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (!path.isAbsolute(filePath)) {
|
|
86
|
-
return `File path must be absolute, but was relative: ${filePath}`;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
const stats = fs.statSync(filePath);
|
|
91
|
-
if (stats.isDirectory()) {
|
|
92
|
-
return `Path is a directory, not a file: ${filePath}`;
|
|
93
|
-
}
|
|
94
|
-
return null;
|
|
95
|
-
} catch (error) {
|
|
96
|
-
if (error.code === "ENOENT") {
|
|
97
|
-
return `File does not exist: ${filePath}`;
|
|
98
|
-
} else if (error.code === "EACCES") {
|
|
99
|
-
return `Permission denied: ${filePath}`;
|
|
100
|
-
}
|
|
101
|
-
return `Cannot access file: ${filePath} (${error.message})`;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Reads file content with proper handling for different file types
|
|
107
|
-
*/
|
|
108
|
-
async function readFileContent(filePath, offset = 0, limit = null, encoding = "utf8") {
|
|
109
|
-
const stats = await fsPromises.stat(filePath);
|
|
110
|
-
const fileSize = stats.size;
|
|
111
|
-
const mimeType = getMimeType(filePath);
|
|
112
|
-
|
|
113
|
-
// Handle binary files differently
|
|
114
|
-
if (
|
|
115
|
-
mimeType.startsWith("image/") ||
|
|
116
|
-
mimeType === "application/pdf" ||
|
|
117
|
-
fileSize > 10 * 1024 * 1024
|
|
118
|
-
) {
|
|
119
|
-
return {
|
|
120
|
-
content: `[Binary file: ${path.basename(filePath)}]`,
|
|
121
|
-
mimeType,
|
|
122
|
-
fileSize,
|
|
123
|
-
isBinary: true,
|
|
124
|
-
encoding: null,
|
|
125
|
-
lineCount: null,
|
|
126
|
-
isTruncated: false,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Read file as buffer first to check if it's binary
|
|
131
|
-
const buffer = await fsPromises.readFile(filePath);
|
|
132
|
-
|
|
133
|
-
if (isBinaryFile(buffer)) {
|
|
134
|
-
return {
|
|
135
|
-
content: `[Binary file: ${path.basename(filePath)}]`,
|
|
136
|
-
mimeType,
|
|
137
|
-
fileSize,
|
|
138
|
-
isBinary: true,
|
|
139
|
-
encoding: null,
|
|
140
|
-
lineCount: null,
|
|
141
|
-
isTruncated: false,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Convert buffer to text
|
|
146
|
-
let content = buffer.toString(encoding);
|
|
147
|
-
const lines = content.split(/\r?\n/);
|
|
148
|
-
const totalLines = lines.length;
|
|
149
|
-
let isTruncated = false;
|
|
150
|
-
let linesShown = [1, totalLines];
|
|
151
|
-
|
|
152
|
-
// Handle offset and limit for text files
|
|
153
|
-
if (offset > 0 || limit !== null) {
|
|
154
|
-
const startLine = Math.max(0, offset);
|
|
155
|
-
const endLine = limit !== null ? Math.min(startLine + limit, totalLines) : totalLines;
|
|
156
|
-
|
|
157
|
-
if (startLine >= totalLines) {
|
|
158
|
-
return {
|
|
159
|
-
content: "",
|
|
160
|
-
mimeType,
|
|
161
|
-
fileSize,
|
|
162
|
-
isBinary: false,
|
|
163
|
-
encoding,
|
|
164
|
-
lineCount: totalLines,
|
|
165
|
-
isTruncated: false,
|
|
166
|
-
linesShown: [startLine + 1, startLine + 1],
|
|
167
|
-
message: `Offset ${offset} is beyond file end (file has ${totalLines} lines)`,
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const selectedLines = lines.slice(startLine, endLine);
|
|
172
|
-
content = selectedLines.join("\n");
|
|
173
|
-
isTruncated = startLine > 0 || endLine < totalLines;
|
|
174
|
-
linesShown = [startLine + 1, endLine];
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Auto-truncate very large files (more than 10000 lines)
|
|
178
|
-
const maxLines = 10000;
|
|
179
|
-
if (limit === null && totalLines > maxLines) {
|
|
180
|
-
const selectedLines = lines.slice(0, maxLines);
|
|
181
|
-
content = selectedLines.join("\n");
|
|
182
|
-
isTruncated = true;
|
|
183
|
-
linesShown = [1, maxLines];
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return {
|
|
187
|
-
content,
|
|
188
|
-
mimeType,
|
|
189
|
-
fileSize,
|
|
190
|
-
isBinary: false,
|
|
191
|
-
encoding,
|
|
192
|
-
lineCount: totalLines,
|
|
193
|
-
isTruncated,
|
|
194
|
-
linesShown,
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
export default async function readFile({ path: filePath, offset, limit, encoding = "utf8" }) {
|
|
199
|
-
let result = {};
|
|
200
|
-
let error = null;
|
|
201
|
-
|
|
202
|
-
if (filePath && !isAbsolute(filePath)) filePath = path.join(process.cwd(), filePath);
|
|
203
|
-
|
|
204
|
-
try {
|
|
205
|
-
// Validate file path first (this checks if it's absolute)
|
|
206
|
-
const pathError = validateFilePath(filePath);
|
|
207
|
-
if (pathError) {
|
|
208
|
-
throw new Error(pathError);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Now we know filePath is valid and absolute
|
|
212
|
-
|
|
213
|
-
// Validate numeric parameters
|
|
214
|
-
if (offset !== undefined && (typeof offset !== "number" || offset < 0)) {
|
|
215
|
-
throw new Error("Offset must be a non-negative number");
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
if (limit !== undefined && (typeof limit !== "number" || limit <= 0)) {
|
|
219
|
-
throw new Error("Limit must be a positive number");
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Read file content
|
|
223
|
-
const fileResult = await readFileContent(filePath, offset, limit, encoding);
|
|
224
|
-
|
|
225
|
-
// Build success result
|
|
226
|
-
result = {
|
|
227
|
-
content: fileResult.content,
|
|
228
|
-
metadata: {
|
|
229
|
-
path: filePath,
|
|
230
|
-
mimeType: fileResult.mimeType,
|
|
231
|
-
fileSize: fileResult.fileSize,
|
|
232
|
-
isBinary: fileResult.isBinary,
|
|
233
|
-
encoding: fileResult.encoding,
|
|
234
|
-
lineCount: fileResult.lineCount,
|
|
235
|
-
},
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
// Add truncation info if applicable
|
|
239
|
-
if (fileResult.isTruncated) {
|
|
240
|
-
result.truncated = {
|
|
241
|
-
isTruncated: true,
|
|
242
|
-
linesShown: fileResult.linesShown,
|
|
243
|
-
totalLines: fileResult.lineCount,
|
|
244
|
-
nextOffset: fileResult.linesShown[1],
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
// Add helpful message for truncated content
|
|
248
|
-
const [start, end] = fileResult.linesShown;
|
|
249
|
-
const nextOffset = end;
|
|
250
|
-
result.message =
|
|
251
|
-
`Content truncated. Showing lines ${start}-${end} of ${fileResult.lineCount} total lines. ` +
|
|
252
|
-
`To read more, use offset: ${nextOffset}.`;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Add message if provided
|
|
256
|
-
if (fileResult.message) {
|
|
257
|
-
result.message = fileResult.message;
|
|
258
|
-
}
|
|
259
|
-
} catch (err) {
|
|
260
|
-
error = err;
|
|
261
|
-
result = {
|
|
262
|
-
content: null,
|
|
263
|
-
metadata: {
|
|
264
|
-
path: filePath,
|
|
265
|
-
mimeType: null,
|
|
266
|
-
fileSize: null,
|
|
267
|
-
isBinary: null,
|
|
268
|
-
encoding: null,
|
|
269
|
-
lineCount: null,
|
|
270
|
-
},
|
|
271
|
-
message: `Error reading file: ${err.message}`,
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
return {
|
|
276
|
-
command: "read_file",
|
|
277
|
-
arguments: {
|
|
278
|
-
path: filePath,
|
|
279
|
-
offset,
|
|
280
|
-
limit,
|
|
281
|
-
encoding,
|
|
282
|
-
},
|
|
283
|
-
result,
|
|
284
|
-
error: error && { message: error.message },
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
readFile.input_schema = {
|
|
289
|
-
type: "object",
|
|
290
|
-
properties: {
|
|
291
|
-
path: {
|
|
292
|
-
type: "string",
|
|
293
|
-
description: "The path to the file to read (for backwards compatibility)",
|
|
294
|
-
},
|
|
295
|
-
offset: {
|
|
296
|
-
type: "number",
|
|
297
|
-
description: "Optional: The 0-based line number to start reading from",
|
|
298
|
-
},
|
|
299
|
-
limit: {
|
|
300
|
-
type: "number",
|
|
301
|
-
description: "Optional: Maximum number of lines to read",
|
|
302
|
-
},
|
|
303
|
-
encoding: {
|
|
304
|
-
type: "string",
|
|
305
|
-
description: "Optional: File encoding (defaults to utf8)",
|
|
306
|
-
},
|
|
307
|
-
},
|
|
308
|
-
required: ["path"],
|
|
309
|
-
};
|
package/media.md
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# 提供在文档中可使用的媒体素材
|
|
2
|
-
|
|
3
|
-

|
|
4
|
-
|
|
5
|
-

|
|
6
|
-
|
|
7
|
-

|
|
8
|
-
|
|
9
|
-

|
|
10
|
-
|
|
11
|
-

|
|
12
|
-
|
|
13
|
-

|
|
14
|
-
|
|
15
|
-

|
|
16
|
-
|
|
17
|
-

|
|
18
|
-
|
|
19
|
-

|