@aigne/doc-smith 0.8.11 → 0.8.12-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 (56) hide show
  1. package/.github/workflows/publish-docs.yml +1 -0
  2. package/.release-please-manifest.json +1 -1
  3. package/CHANGELOG.md +19 -0
  4. package/agents/generate/check-diagram.mjs +40 -0
  5. package/agents/generate/draw-diagram.yaml +23 -0
  6. package/agents/generate/generate-structure.yaml +5 -1
  7. package/agents/generate/merge-d2-diagram.yaml +3 -3
  8. package/agents/generate/update-document-structure.yaml +5 -2
  9. package/agents/generate/user-review-document-structure.mjs +7 -0
  10. package/agents/generate/wrap-diagram-code.mjs +35 -0
  11. package/agents/history/index.yaml +6 -0
  12. package/agents/history/view.mjs +75 -0
  13. package/agents/translate/index.yaml +3 -2
  14. package/agents/translate/record-translation-history.mjs +19 -0
  15. package/agents/translate/translate-multilingual.yaml +2 -1
  16. package/agents/update/batch-update-document.yaml +1 -1
  17. package/agents/update/check-document.mjs +1 -1
  18. package/agents/update/fs-tools/read-file.mjs +3 -1
  19. package/agents/update/generate-document.yaml +31 -25
  20. package/agents/update/{generate-and-translate-document.yaml → handle-document-update.yaml} +2 -11
  21. package/agents/update/index.yaml +1 -0
  22. package/agents/update/save-and-translate-document.mjs +101 -0
  23. package/agents/update/update-document-detail.yaml +5 -1
  24. package/agents/update/update-single-document.yaml +1 -10
  25. package/agents/update/user-review-document.mjs +4 -1
  26. package/aigne.yaml +8 -1
  27. package/package.json +1 -1
  28. package/prompts/detail/d2-diagram/guide.md +19 -0
  29. package/prompts/detail/d2-diagram/role-and-personality.md +2 -0
  30. package/prompts/detail/d2-diagram/rules.md +24 -0
  31. package/prompts/detail/d2-diagram/{rules-system.md → system-prompt.md} +3 -9
  32. package/prompts/detail/{document-rules.md → generate/document-rules.md} +1 -1
  33. package/prompts/detail/generate/system-prompt.md +72 -0
  34. package/prompts/detail/generate/user-prompt.md +54 -0
  35. package/prompts/detail/{update-document.md → update/system-prompt.md} +43 -67
  36. package/prompts/detail/update/user-prompt.md +33 -0
  37. package/prompts/structure/{generate-structure-system.md → generate/system-prompt.md} +7 -40
  38. package/prompts/structure/{generate-structure-user.md → generate/user-prompt.md} +17 -13
  39. package/prompts/structure/{update-document-structure.md → update/system-prompt.md} +16 -27
  40. package/prompts/structure/update/user-prompt.md +19 -0
  41. package/tests/agents/generate/user-review-document-structure.test.mjs +2 -0
  42. package/tests/agents/update/check-document.test.mjs +1 -1
  43. package/tests/agents/update/fs-tools/read-file.test.mjs +8 -12
  44. package/tests/agents/utils/check-detail-result.test.mjs +13 -0
  45. package/tests/utils/d2-utils.test.mjs +14 -0
  46. package/tests/utils/docs-finder-utils.test.mjs +13 -0
  47. package/tests/utils/history-utils.test.mjs +178 -0
  48. package/utils/d2-utils.mjs +9 -0
  49. package/utils/docs-finder-utils.mjs +10 -1
  50. package/utils/history-utils.mjs +191 -0
  51. package/utils/markdown-checker.mjs +20 -0
  52. package/agents/generate/check-d2-diagram-valid.mjs +0 -26
  53. package/agents/generate/generate-d2-diagram.yaml +0 -23
  54. package/prompts/detail/generate-document.md +0 -125
  55. /package/prompts/detail/d2-diagram/{rules-user.md → user-prompt.md} +0 -0
  56. /package/prompts/detail/{detail-example.md → generate/detail-example.md} +0 -0
@@ -2,6 +2,7 @@ name: publish docs
2
2
 
3
3
  env:
4
4
  GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
5
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
5
6
 
6
7
  permissions:
7
8
  contents: write
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "0.8.11"
2
+ ".": "0.8.12-beta.1"
3
3
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.12-beta.1](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.12-beta...v0.8.12-beta.1) (2025-10-08)
4
+
5
+
6
+ ### Features
7
+
8
+ * add history tracking and make translation optional during update ([#165](https://github.com/AIGNE-io/aigne-doc-smith/issues/165)) ([e1d3d97](https://github.com/AIGNE-io/aigne-doc-smith/commit/e1d3d97c7e57c1c663c0478870aab7421de9d4bc))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * split generate/update document & structure to system & user ([#159](https://github.com/AIGNE-io/aigne-doc-smith/issues/159)) ([ad1802d](https://github.com/AIGNE-io/aigne-doc-smith/commit/ad1802d1aecefc414ab3d1217a9ba31655479e86))
14
+
15
+ ## [0.8.12-beta](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.11...v0.8.12-beta) (2025-10-07)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * read file tool should support relative path ([#162](https://github.com/AIGNE-io/aigne-doc-smith/issues/162)) ([cf1291b](https://github.com/AIGNE-io/aigne-doc-smith/commit/cf1291b0be5b51db15d052310c30b0552a4092e1))
21
+
3
22
  ## [0.8.11](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.11-beta.7...v0.8.11) (2025-10-05)
4
23
 
5
24
 
@@ -0,0 +1,40 @@
1
+ import { checkContent } from "../../utils/d2-utils.mjs";
2
+
3
+ export default async function checkD2DiagramIsValid({ diagramSourceCode }) {
4
+ try {
5
+ await checkContent({ content: diagramSourceCode });
6
+ return {
7
+ isValid: true,
8
+ };
9
+ } catch (err) {
10
+ return {
11
+ isValid: false,
12
+ error: err.message,
13
+ };
14
+ }
15
+ }
16
+
17
+ checkD2DiagramIsValid.input_schema = {
18
+ type: "object",
19
+ properties: {
20
+ diagramSourceCode: {
21
+ type: "string",
22
+ description: "Source code of d2 diagram",
23
+ },
24
+ },
25
+ required: ["diagramSourceCode"],
26
+ };
27
+ checkD2DiagramIsValid.output_schema = {
28
+ type: "object",
29
+ properties: {
30
+ isValid: {
31
+ type: "boolean",
32
+ description: "Indicates whether the provided d2 diagram source passes validation",
33
+ },
34
+ error: {
35
+ type: "string",
36
+ description: "Validation error details when the diagram does not pass",
37
+ },
38
+ },
39
+ required: ["isValid"],
40
+ };
@@ -0,0 +1,23 @@
1
+ name: drawDiagram
2
+ description: Generate a D2 diagram from document content.
3
+ instructions:
4
+ - role: system
5
+ url: ../../prompts/detail/d2-diagram/system-prompt.md
6
+ - role: user
7
+ url: ../../prompts/detail/d2-diagram/user-prompt.md
8
+ input_schema:
9
+ type: object
10
+ properties:
11
+ documentContent:
12
+ type: string
13
+ description: The **raw text content** of the current document. (**Note:** This is the original document and **does not include** any existing diagram source code.)
14
+ required:
15
+ - documentContent
16
+ output_schema:
17
+ type: object
18
+ properties:
19
+ diagramSourceCode:
20
+ type: string
21
+ description: The **diagram source code** generated from the input text.
22
+ required:
23
+ - diagramSourceCode
@@ -1,7 +1,11 @@
1
1
  name: generateStructure
2
2
  description: Generate the structure and organization of your documentation
3
3
  instructions:
4
- url: ../../prompts/structure/generate-structure-system.md
4
+ - role: system
5
+ url: ../../prompts/structure/generate/system-prompt.md
6
+ - role: user
7
+ url: ../../prompts/structure/generate/user-prompt.md
8
+
5
9
  input_schema:
6
10
  type: object
7
11
  properties:
@@ -7,7 +7,7 @@ instructions: |
7
7
  {{ content }}
8
8
  </datasources>
9
9
  <datasources>
10
- {{ d2DiagramSourceCode }}
10
+ {{ diagramSourceCode }}
11
11
  </datasources>
12
12
 
13
13
  Given the source content of a document and the D2 diagram source code, your task is to:
@@ -22,12 +22,12 @@ input_schema:
22
22
  content:
23
23
  type: string
24
24
  description: Source content of the document
25
- d2DiagramSourceCode:
25
+ diagramSourceCode:
26
26
  type: string
27
27
  description: Source content of D2 Diagram
28
28
  required:
29
29
  - content
30
- - d2DiagramSourceCode
30
+ - diagramSourceCode
31
31
  output_schema:
32
32
  type: object
33
33
  properties:
@@ -2,7 +2,10 @@ type: ai
2
2
  name: updateDocumentStructure
3
3
  description: Update documentation structure based on user feedback and intentions using structure modification tools
4
4
  instructions:
5
- url: ../../prompts/structure/update-document-structure.md
5
+ - role: system
6
+ url: ../../prompts/structure/update/system-prompt.md
7
+ - role: user
8
+ url: ../../prompts/structure/update/user-prompt.md
6
9
  input_schema:
7
10
  type: object
8
11
  properties:
@@ -33,4 +36,4 @@ skills:
33
36
  - ./document-structure-tools/add-document.mjs
34
37
  - ./document-structure-tools/delete-document.mjs
35
38
  - ./document-structure-tools/update-document.mjs
36
- - ./document-structure-tools/move-document.mjs
39
+ - ./document-structure-tools/move-document.mjs
@@ -1,4 +1,5 @@
1
1
  import { getActiveRulesForScope } from "../../utils/preferences-utils.mjs";
2
+ import { recordUpdate } from "../../utils/history-utils.mjs";
2
3
 
3
4
  function formatDocumentStructure(structure) {
4
5
  // Build a tree structure for better display
@@ -158,6 +159,12 @@ export default async function userReviewDocumentStructure({ documentStructure, .
158
159
  }
159
160
  }
160
161
 
162
+ // Record update in history
163
+ recordUpdate({
164
+ operation: "structure_update",
165
+ feedback: feedback.trim(),
166
+ });
167
+
161
168
  // Print current documentation structure in a user-friendly format
162
169
  printDocumentStructure(currentStructure);
163
170
  } catch (error) {
@@ -0,0 +1,35 @@
1
+ import { wrapCode } from "../../utils/d2-utils.mjs";
2
+
3
+ export default async function wrapDiagramCode({ diagramSourceCode }) {
4
+ try {
5
+ const result = await wrapCode({ content: diagramSourceCode });
6
+ return {
7
+ diagramSourceCode: result,
8
+ };
9
+ } catch {
10
+ return {
11
+ diagramSourceCode,
12
+ };
13
+ }
14
+ }
15
+
16
+ wrapDiagramCode.input_schema = {
17
+ type: "object",
18
+ properties: {
19
+ diagramSourceCode: {
20
+ type: "string",
21
+ description: "Source code of d2 diagram",
22
+ },
23
+ },
24
+ required: ["diagramSourceCode"],
25
+ };
26
+ wrapDiagramCode.output_schema = {
27
+ type: "object",
28
+ properties: {
29
+ diagramSourceCode: {
30
+ type: "string",
31
+ description: "Source code of d2 diagram",
32
+ },
33
+ },
34
+ required: ["diagramSourceCode"],
35
+ };
@@ -0,0 +1,6 @@
1
+ name: "history"
2
+ description: "View and manage document update history"
3
+ tasks:
4
+ - name: "view"
5
+ description: "View update history in compact format"
6
+ agent: "viewHistory"
@@ -0,0 +1,75 @@
1
+ import chalk from "chalk";
2
+ import { getHistory } from "../../utils/history-utils.mjs";
3
+
4
+ export default function viewHistory() {
5
+ const history = getHistory();
6
+
7
+ if (!history.entries || history.entries.length === 0) {
8
+ console.log(chalk.yellow("\nNo update history found\n"));
9
+ return {};
10
+ }
11
+
12
+ console.log(chalk.cyan("\n📜 Update History\n"));
13
+
14
+ history.entries.forEach((entry) => {
15
+ // Format: <short-hash> <date> <operation> <feedback>
16
+ const hash = generateShortHash(entry.timestamp);
17
+ const date = formatRelativeDate(entry.timestamp);
18
+ const operation = entry.operation;
19
+
20
+ // Handle document path (now a string)
21
+ const documentInfo = entry.documentPath ? chalk.dim(` (${entry.documentPath})`) : "";
22
+
23
+ // Git-style oneline format
24
+ console.log(
25
+ `${chalk.yellow(hash)} ${chalk.dim(date)} ${chalk.cyan(operation)}${documentInfo}: ${entry.feedback}`,
26
+ );
27
+ });
28
+
29
+ console.log(); // Empty line at end
30
+
31
+ return {};
32
+ }
33
+
34
+ /**
35
+ * Generate a short hash from timestamp (git-style)
36
+ */
37
+ function generateShortHash(timestamp) {
38
+ const hash = timestamp.replace(/[-:.TZ]/g, "");
39
+ return hash.substring(hash.length - 7); // Last 7 chars
40
+ }
41
+
42
+ /**
43
+ * Format date in relative time (git-style)
44
+ */
45
+ function formatRelativeDate(timestamp) {
46
+ const date = new Date(timestamp);
47
+ const now = new Date();
48
+ const diffMs = now - date;
49
+ const diffSecs = Math.floor(diffMs / 1000);
50
+ const diffMins = Math.floor(diffSecs / 60);
51
+ const diffHours = Math.floor(diffMins / 60);
52
+ const diffDays = Math.floor(diffHours / 24);
53
+
54
+ if (diffSecs < 60) {
55
+ return `${diffSecs} seconds ago`;
56
+ }
57
+ if (diffMins < 60) {
58
+ return `${diffMins} minute${diffMins === 1 ? "" : "s"} ago`;
59
+ }
60
+ if (diffHours < 24) {
61
+ return `${diffHours} hour${diffHours === 1 ? "" : "s"} ago`;
62
+ }
63
+ if (diffDays < 7) {
64
+ return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
65
+ }
66
+ // Show actual date for older entries
67
+ return date.toLocaleDateString("en-US", {
68
+ month: "short",
69
+ day: "numeric",
70
+ year: date.getFullYear() !== now.getFullYear() ? "numeric" : undefined,
71
+ });
72
+ }
73
+
74
+ viewHistory.description = "View update history in compact format";
75
+ viewHistory.taskTitle = "View update history";
@@ -32,6 +32,7 @@ skills:
32
32
  name: batchTranslateDocument
33
33
  skills:
34
34
  - ../translate/translate-multilingual.yaml
35
+ - url: ./record-translation-history.mjs
35
36
  - url: ../utils/save-single-doc.mjs
36
37
  default_input:
37
38
  isTranslate: true
@@ -42,7 +43,7 @@ skills:
42
43
  stage: translation_refine
43
44
  - url: ../utils/action-success.mjs
44
45
  default_input:
45
- action: "✅ Translation completed"
46
+ action: '✅ Translation completed'
46
47
  input_schema:
47
48
  type: object
48
49
  properties:
@@ -58,7 +59,7 @@ input_schema:
58
59
  type: array
59
60
  items:
60
61
  type: string
61
- description: "Target languages (available: en, zh, zh-TW, ja, fr, de, es, it, ru, ko, pt, ar)"
62
+ description: 'Target languages (available: en, zh, zh-TW, ja, fr, de, es, it, ru, ko, pt, ar)'
62
63
  feedback:
63
64
  type: string
64
65
  description: Tell us how to improve the translation style
@@ -0,0 +1,19 @@
1
+ import { recordUpdate } from "../../utils/history-utils.mjs";
2
+
3
+ export default function recordTranslationHistory({ feedback, path }) {
4
+ // Skip if no feedback provided
5
+ if (!feedback?.trim()) {
6
+ return {};
7
+ }
8
+
9
+ // Record translation history for this document
10
+ recordUpdate({
11
+ operation: "translation_update",
12
+ feedback: feedback.trim(),
13
+ documentPath: path,
14
+ });
15
+
16
+ return {};
17
+ }
18
+
19
+ recordTranslationHistory.task_render_mode = "hide";
@@ -47,4 +47,5 @@ output_schema:
47
47
  translation:
48
48
  type: string
49
49
  iterate_on: translates
50
- mode: sequential
50
+ concurrency: 3
51
+
@@ -2,6 +2,6 @@
2
2
  type: team
3
3
  name: batchUpdateDocument
4
4
  skills:
5
- - ../update/generate-and-translate-document.yaml
5
+ - ../update/handle-document-update.yaml
6
6
  iterate_on: selectedDocs
7
7
  concurrency: 5
@@ -112,7 +112,7 @@ export default async function checkDocument(
112
112
 
113
113
  const teamAgent = TeamAgent.from({
114
114
  name: "generateDocument",
115
- skills: [options.context.agents["generateAndTranslateDocument"]],
115
+ skills: [options.context.agents["handleDocumentUpdate"]],
116
116
  });
117
117
 
118
118
  const result = await options.context.invoke(teamAgent, {
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import fsPromises from "node:fs/promises";
3
- import path from "node:path";
3
+ import path, { isAbsolute } from "node:path";
4
4
 
5
5
  /**
6
6
  * Detects if a file is likely binary by checking for null bytes
@@ -199,6 +199,8 @@ export default async function readFile({ path: filePath, offset, limit, encoding
199
199
  let result = {};
200
200
  let error = null;
201
201
 
202
+ if (filePath && !isAbsolute(filePath)) filePath = path.join(process.cwd(), filePath);
203
+
202
204
  try {
203
205
  // Validate file path first (this checks if it's absolute)
204
206
  const pathError = validateFilePath(filePath);
@@ -1,7 +1,10 @@
1
1
  name: generateDocument
2
2
  description: Comprehensive content generator for documentation that creates detailed, high-quality document content from various data sources with intelligent analysis.
3
3
  instructions:
4
- url: ../../prompts/detail/generate-document.md
4
+ - role: system
5
+ url: ../../prompts/detail/generate/system-prompt.md
6
+ - role: user
7
+ url: ../../prompts/detail/generate/user-prompt.md
5
8
  input_schema:
6
9
  type: object
7
10
  properties:
@@ -46,27 +49,30 @@ skills:
46
49
  - fs-tools/glob.mjs
47
50
  - fs-tools/grep.mjs
48
51
  - fs-tools/read-file.mjs
49
- - type: team
50
- task_render_mode: collapse
51
- name: generateD2DiagramContent
52
- skills:
53
- - ../generate/generate-d2-diagram.yaml
54
- reflection:
55
- reviewer: ../generate/check-d2-diagram-valid.mjs
56
- is_approved: isValid
57
- max_iterations: 5
58
- return_last_on_max_iterations: true
59
- input_schema:
60
- type: object
61
- properties:
62
- documentContent:
63
- type: string
64
- description: Source code of current document (without the D2 diagram)
65
- required:
66
- - documentContent
67
- output_schema:
68
- type: object
69
- properties:
70
- d2DiagramSourceCode:
71
- type: string
72
- description: Source code for the D2 diagram
52
+ # FIXME: @zhanghan temporary disable diagram tool
53
+ # - type: team
54
+ # task_render_mode: collapse
55
+ # name: generateDiagram
56
+ # skills:
57
+ # - ../generate/draw-diagram.yaml
58
+ # - ../generate/wrap-diagram-code.mjs
59
+ # reflection:
60
+ # reviewer: ../generate/check-diagram.mjs
61
+ # is_approved: isValid
62
+ # max_iterations: 5
63
+ # return_last_on_max_iterations: false
64
+ # custom_error_message: "MUST NOT generate any diagram: validation failed after max iterations."
65
+ # input_schema:
66
+ # type: object
67
+ # properties:
68
+ # documentContent:
69
+ # type: string
70
+ # description: The **raw text content** of the current document. (**Note:** This is the original document and **does not include** any existing diagram source code.)
71
+ # required:
72
+ # - documentContent
73
+ # output_schema:
74
+ # type: object
75
+ # properties:
76
+ # diagramSourceCode:
77
+ # type: string
78
+ # description: The **diagram source code** generated from the input text.
@@ -1,6 +1,6 @@
1
1
  type: team
2
- name: generateAndTranslateDocument
3
- description: Generate and translate documents
2
+ name: handleDocumentUpdate
3
+ description: Update a document in a batch
4
4
  skills:
5
5
  - ../utils/transform-detail-datasources.mjs
6
6
  - type: team
@@ -23,15 +23,6 @@ skills:
23
23
  max_iterations: 5
24
24
  return_last_on_max_iterations: true
25
25
  task_title: Generate document for '{{ title }}'
26
- - type: transform
27
- task_render_mode: hide
28
- jsonata: |
29
- $merge([
30
- $,
31
- { "feedback": "" }
32
- ])
33
- - ../translate/translate-multilingual.yaml
34
- - ../utils/save-single-doc.mjs
35
26
  input_schema:
36
27
  type: object
37
28
  properties:
@@ -31,6 +31,7 @@ skills:
31
31
  requiredFeedback: false
32
32
  - ../utils/format-document-structure.mjs
33
33
  - ../update/check-update-is-single.mjs
34
+ - ../update/save-and-translate-document.mjs
34
35
  - url: ../utils/action-success.mjs
35
36
  default_input:
36
37
  action: "✅ Documents updated successfully"
@@ -0,0 +1,101 @@
1
+ import { recordUpdate } from "../../utils/history-utils.mjs";
2
+
3
+ export default async function saveAndTranslateDocument(input, options) {
4
+ const { selectedDocs, docsDir, translateLanguages, locale } = input;
5
+
6
+ // Saves a document with optional translation data
7
+ const saveDocument = async (doc, translates = null, isTranslate = false) => {
8
+ const saveAgent = options.context.agents["saveSingleDoc"];
9
+
10
+ return await options.context.invoke(saveAgent, {
11
+ path: doc.path,
12
+ content: doc.content,
13
+ docsDir: docsDir,
14
+ locale: locale,
15
+ translates: translates || doc.translates,
16
+ labels: doc.labels,
17
+ isTranslate: isTranslate,
18
+ });
19
+ };
20
+
21
+ // Only prompt user if translation is actually needed
22
+ let shouldTranslate = false;
23
+ if (
24
+ Array.isArray(translateLanguages) &&
25
+ translateLanguages.filter((lang) => lang !== locale).length > 0
26
+ ) {
27
+ const choice = await options.prompts.select({
28
+ message: "Document update completed. Would you like to translate these documents now?",
29
+ choices: [
30
+ {
31
+ name: "Review documents first, translate later",
32
+ value: "no",
33
+ },
34
+ {
35
+ name: "Translate now",
36
+ value: "yes",
37
+ },
38
+ ],
39
+ });
40
+ shouldTranslate = choice === "yes";
41
+ }
42
+
43
+ // Process documents in batches for better performance
44
+ const batchSize = 3;
45
+ for (let i = 0; i < selectedDocs.length; i += batchSize) {
46
+ const batch = selectedDocs.slice(i, i + batchSize);
47
+
48
+ const savePromises = batch.map(async (doc) => {
49
+ try {
50
+ await saveDocument(doc);
51
+
52
+ // Record history for each document if feedback is provided
53
+ if (doc.feedback?.trim()) {
54
+ recordUpdate({
55
+ operation: "document_update",
56
+ feedback: doc.feedback.trim(),
57
+ documentPath: doc.path,
58
+ });
59
+ // clear feedback
60
+ doc.feedback = "";
61
+ }
62
+ } catch (error) {
63
+ console.error(`❌ Failed to save document ${doc.path}:`, error.message);
64
+ }
65
+ });
66
+
67
+ await Promise.all(savePromises);
68
+ }
69
+
70
+ // Return results if user chose to skip translation
71
+ if (!shouldTranslate) {
72
+ return {};
73
+ }
74
+
75
+ // Translate documents in batches
76
+ const translateAgent = options.context.agents["translateMultilingual"];
77
+
78
+ for (let i = 0; i < selectedDocs.length; i += batchSize) {
79
+ const batch = selectedDocs.slice(i, i + batchSize);
80
+
81
+ const translatePromises = batch.map(async (doc) => {
82
+ try {
83
+ const result = await options.context.invoke(translateAgent, {
84
+ ...input, // Pass context for translation
85
+ content: doc.content,
86
+ translates: doc.translates,
87
+ title: doc.title,
88
+ });
89
+
90
+ // Save the translated content
91
+ await saveDocument(doc, result.translates, true);
92
+ } catch (error) {
93
+ console.error(`❌ Failed to translate document ${doc.path}:`, error.message);
94
+ }
95
+ });
96
+
97
+ await Promise.all(translatePromises);
98
+ }
99
+
100
+ return {};
101
+ }
@@ -2,7 +2,11 @@ type: ai
2
2
  name: updateDocumentDetail
3
3
  description: Update and optimize document content based on user feedback using diff patches
4
4
  instructions:
5
- url: ../../prompts/detail/update-document.md
5
+ - role: system
6
+ url: ../../prompts/detail/update/system-prompt.md
7
+ - role: user
8
+ url: ../../prompts/detail/update/user-prompt.md
9
+
6
10
  input_schema:
7
11
  type: object
8
12
  properties:
@@ -3,14 +3,5 @@ name: updateSingleDocument
3
3
  skills:
4
4
  - ../utils/transform-detail-datasources.mjs
5
5
  - ../update/user-review-document.mjs
6
- - type: transform
7
- task_render_mode: hide
8
- jsonata: |
9
- $merge([
10
- $,
11
- { "feedback": "" }
12
- ])
13
- - ../translate/translate-multilingual.yaml
14
- - ../utils/save-single-doc.mjs
15
6
  iterate_on: selectedDocs
16
- concurrency: 1
7
+ concurrency: 1
@@ -138,6 +138,7 @@ export default async function userReviewDocument(
138
138
  options.context.userContext.currentContent = content;
139
139
 
140
140
  const MAX_ITERATIONS = 100;
141
+ const feedbacks = [];
141
142
  let iterationCount = 0;
142
143
  while (iterationCount < MAX_ITERATIONS) {
143
144
  iterationCount++;
@@ -185,6 +186,8 @@ export default async function userReviewDocument(
185
186
  break;
186
187
  }
187
188
 
189
+ feedbacks.push(feedback.trim());
190
+
188
191
  // Get the updateDocument agent
189
192
  const updateAgent = options.context.agents["updateDocumentDetail"];
190
193
  if (!updateAgent) {
@@ -242,7 +245,7 @@ export default async function userReviewDocument(
242
245
  }
243
246
  }
244
247
 
245
- return { content: options.context.userContext.currentContent };
248
+ return { content: options.context.userContext.currentContent, feedback: feedbacks.join(". ") };
246
249
  }
247
250
 
248
251
  userReviewDocument.taskTitle = "User review and modify document content";