@aigne/doc-smith 0.8.12-beta.2 → 0.8.12-beta.4

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 (170) hide show
  1. package/.aigne/doc-smith/config.yaml +9 -6
  2. package/.aigne/doc-smith/output/structure-plan.json +123 -109
  3. package/.aigne/doc-smith/upload-cache.yaml +48 -0
  4. package/.github/workflows/publish-docs.yml +4 -7
  5. package/.release-please-manifest.json +1 -1
  6. package/CHANGELOG.md +20 -0
  7. package/agents/clear/choose-contents.mjs +22 -5
  8. package/agents/clear/clear-auth-tokens.mjs +2 -4
  9. package/agents/clear/clear-deployment-config.mjs +49 -0
  10. package/agents/clear/clear-document-config.mjs +2 -5
  11. package/agents/clear/clear-document-structure.mjs +2 -6
  12. package/agents/clear/clear-generated-docs.mjs +0 -1
  13. package/agents/generate/check-need-generate-structure.mjs +15 -60
  14. package/agents/generate/document-structure-tools/generate-sub-structure.mjs +131 -0
  15. package/agents/generate/generate-structure-without-tools.yaml +65 -0
  16. package/agents/generate/generate-structure.yaml +7 -1
  17. package/agents/generate/index.yaml +0 -3
  18. package/agents/generate/update-document-structure.yaml +3 -0
  19. package/agents/generate/user-review-document-structure.mjs +7 -5
  20. package/agents/init/index.mjs +15 -15
  21. package/agents/publish/publish-docs.mjs +132 -113
  22. package/agents/translate/index.yaml +1 -1
  23. package/agents/update/batch-generate-document.yaml +1 -1
  24. package/agents/update/batch-update-document.yaml +1 -1
  25. package/agents/update/check-document.mjs +3 -19
  26. package/agents/update/user-review-document.mjs +4 -3
  27. package/agents/utils/load-sources.mjs +54 -151
  28. package/agents/utils/transform-detail-datasources.mjs +14 -18
  29. package/aigne.yaml +2 -0
  30. package/biome.json +1 -1
  31. package/docs/_sidebar.md +13 -15
  32. package/docs/configuration-initial-setup.ja.md +179 -0
  33. package/docs/configuration-initial-setup.md +179 -0
  34. package/docs/configuration-initial-setup.zh-TW.md +179 -0
  35. package/docs/configuration-initial-setup.zh.md +179 -0
  36. package/docs/configuration-managing-preferences.ja.md +100 -0
  37. package/docs/configuration-managing-preferences.md +100 -0
  38. package/docs/configuration-managing-preferences.zh-TW.md +100 -0
  39. package/docs/configuration-managing-preferences.zh.md +100 -0
  40. package/docs/configuration.ja.md +68 -184
  41. package/docs/configuration.md +62 -178
  42. package/docs/configuration.zh-TW.md +70 -186
  43. package/docs/configuration.zh.md +67 -183
  44. package/docs/getting-started.ja.md +46 -78
  45. package/docs/getting-started.md +46 -78
  46. package/docs/getting-started.zh-TW.md +47 -79
  47. package/docs/getting-started.zh.md +47 -79
  48. package/docs/guides-cleaning-up.ja.md +50 -0
  49. package/docs/guides-cleaning-up.md +50 -0
  50. package/docs/guides-cleaning-up.zh-TW.md +50 -0
  51. package/docs/guides-cleaning-up.zh.md +50 -0
  52. package/docs/guides-evaluating-documents.ja.md +66 -0
  53. package/docs/guides-evaluating-documents.md +66 -0
  54. package/docs/guides-evaluating-documents.zh-TW.md +66 -0
  55. package/docs/guides-evaluating-documents.zh.md +66 -0
  56. package/docs/guides-generating-documentation.ja.md +149 -0
  57. package/docs/guides-generating-documentation.md +149 -0
  58. package/docs/guides-generating-documentation.zh-TW.md +149 -0
  59. package/docs/guides-generating-documentation.zh.md +149 -0
  60. package/docs/guides-interactive-chat.ja.md +85 -0
  61. package/docs/guides-interactive-chat.md +85 -0
  62. package/docs/guides-interactive-chat.zh-TW.md +85 -0
  63. package/docs/guides-interactive-chat.zh.md +85 -0
  64. package/docs/guides-managing-history.ja.md +51 -0
  65. package/docs/guides-managing-history.md +51 -0
  66. package/docs/guides-managing-history.zh-TW.md +51 -0
  67. package/docs/guides-managing-history.zh.md +51 -0
  68. package/docs/guides-publishing-your-docs.ja.md +78 -0
  69. package/docs/guides-publishing-your-docs.md +78 -0
  70. package/docs/guides-publishing-your-docs.zh-TW.md +78 -0
  71. package/docs/guides-publishing-your-docs.zh.md +78 -0
  72. package/docs/guides-translating-documentation.ja.md +95 -0
  73. package/docs/guides-translating-documentation.md +95 -0
  74. package/docs/guides-translating-documentation.zh-TW.md +95 -0
  75. package/docs/guides-translating-documentation.zh.md +95 -0
  76. package/docs/guides-updating-documentation.ja.md +77 -0
  77. package/docs/guides-updating-documentation.md +77 -0
  78. package/docs/guides-updating-documentation.zh-TW.md +77 -0
  79. package/docs/guides-updating-documentation.zh.md +77 -0
  80. package/docs/guides.ja.md +32 -0
  81. package/docs/guides.md +32 -0
  82. package/docs/guides.zh-TW.md +32 -0
  83. package/docs/guides.zh.md +32 -0
  84. package/docs/overview.ja.md +39 -60
  85. package/docs/overview.md +39 -60
  86. package/docs/overview.zh-TW.md +39 -60
  87. package/docs/overview.zh.md +39 -60
  88. package/docs/release-notes.ja.md +255 -0
  89. package/docs/release-notes.md +255 -0
  90. package/docs/release-notes.zh-TW.md +255 -0
  91. package/docs/release-notes.zh.md +255 -0
  92. package/package.json +4 -2
  93. package/prompts/common/document/content-rules-core.md +1 -0
  94. package/prompts/common/document-structure/document-structure-rules.md +8 -9
  95. package/prompts/common/document-structure/output-constraints.md +1 -1
  96. package/prompts/structure/document-rules.md +8 -2
  97. package/prompts/structure/generate/system-prompt.md +27 -2
  98. package/prompts/structure/generate/user-prompt.md +18 -0
  99. package/prompts/structure/update/system-prompt.md +12 -0
  100. package/prompts/structure/update/user-prompt.md +3 -0
  101. package/tests/agents/clear/choose-contents.test.mjs +8 -4
  102. package/tests/agents/generate/check-need-generate-structure.test.mjs +53 -63
  103. package/tests/agents/generate/document-structure-tools/generate-sub-structure.test.mjs +277 -0
  104. package/tests/agents/init/init.test.mjs +18 -18
  105. package/tests/agents/publish/publish-docs.test.mjs +79 -0
  106. package/tests/agents/update/check-document.test.mjs +7 -67
  107. package/tests/agents/utils/load-sources.test.mjs +90 -90
  108. package/tests/agents/utils/transform-detail-datasources.test.mjs +153 -196
  109. package/tests/utils/file-utils.test.mjs +309 -1
  110. package/utils/auth-utils.mjs +12 -5
  111. package/utils/constants/index.mjs +5 -2
  112. package/utils/deploy.mjs +2 -2
  113. package/utils/file-utils.mjs +315 -0
  114. package/utils/utils.mjs +89 -50
  115. package/docs/advanced-how-it-works.ja.md +0 -101
  116. package/docs/advanced-how-it-works.md +0 -101
  117. package/docs/advanced-how-it-works.zh-TW.md +0 -101
  118. package/docs/advanced-how-it-works.zh.md +0 -101
  119. package/docs/advanced-quality-assurance.ja.md +0 -92
  120. package/docs/advanced-quality-assurance.md +0 -92
  121. package/docs/advanced-quality-assurance.zh-TW.md +0 -92
  122. package/docs/advanced-quality-assurance.zh.md +0 -92
  123. package/docs/advanced.ja.md +0 -20
  124. package/docs/advanced.md +0 -20
  125. package/docs/advanced.zh-TW.md +0 -20
  126. package/docs/advanced.zh.md +0 -20
  127. package/docs/changelog.ja.md +0 -486
  128. package/docs/changelog.md +0 -486
  129. package/docs/changelog.zh-TW.md +0 -486
  130. package/docs/changelog.zh.md +0 -486
  131. package/docs/cli-reference.ja.md +0 -311
  132. package/docs/cli-reference.md +0 -311
  133. package/docs/cli-reference.zh-TW.md +0 -311
  134. package/docs/cli-reference.zh.md +0 -311
  135. package/docs/configuration-interactive-setup.ja.md +0 -138
  136. package/docs/configuration-interactive-setup.md +0 -138
  137. package/docs/configuration-interactive-setup.zh-TW.md +0 -138
  138. package/docs/configuration-interactive-setup.zh.md +0 -138
  139. package/docs/configuration-language-support.ja.md +0 -64
  140. package/docs/configuration-language-support.md +0 -64
  141. package/docs/configuration-language-support.zh-TW.md +0 -64
  142. package/docs/configuration-language-support.zh.md +0 -64
  143. package/docs/configuration-llm-setup.ja.md +0 -56
  144. package/docs/configuration-llm-setup.md +0 -56
  145. package/docs/configuration-llm-setup.zh-TW.md +0 -56
  146. package/docs/configuration-llm-setup.zh.md +0 -56
  147. package/docs/configuration-preferences.ja.md +0 -144
  148. package/docs/configuration-preferences.md +0 -144
  149. package/docs/configuration-preferences.zh-TW.md +0 -144
  150. package/docs/configuration-preferences.zh.md +0 -144
  151. package/docs/features-generate-documentation.ja.md +0 -95
  152. package/docs/features-generate-documentation.md +0 -95
  153. package/docs/features-generate-documentation.zh-TW.md +0 -95
  154. package/docs/features-generate-documentation.zh.md +0 -95
  155. package/docs/features-publish-your-docs.ja.md +0 -130
  156. package/docs/features-publish-your-docs.md +0 -130
  157. package/docs/features-publish-your-docs.zh-TW.md +0 -130
  158. package/docs/features-publish-your-docs.zh.md +0 -130
  159. package/docs/features-translate-documentation.ja.md +0 -90
  160. package/docs/features-translate-documentation.md +0 -90
  161. package/docs/features-translate-documentation.zh-TW.md +0 -90
  162. package/docs/features-translate-documentation.zh.md +0 -90
  163. package/docs/features-update-and-refine.ja.md +0 -142
  164. package/docs/features-update-and-refine.md +0 -142
  165. package/docs/features-update-and-refine.zh-TW.md +0 -143
  166. package/docs/features-update-and-refine.zh.md +0 -142
  167. package/docs/features.ja.md +0 -62
  168. package/docs/features.md +0 -62
  169. package/docs/features.zh-TW.md +0 -62
  170. package/docs/features.zh.md +0 -62
@@ -1,12 +1,13 @@
1
1
  import { basename, join } from "node:path";
2
2
 
3
3
  import { publishDocs as publishDocsFn } from "@aigne/publish-docs";
4
+ import { BrokerClient } from "@blocklet/payment-broker-client/node";
4
5
  import chalk from "chalk";
5
6
  import fs from "fs-extra";
6
7
 
7
- import { getAccessToken } from "../../utils/auth-utils.mjs";
8
+ import { getAccessToken, getOfficialAccessToken } from "../../utils/auth-utils.mjs";
8
9
  import {
9
- DEFAULT_APP_URL,
10
+ CLOUD_SERVICE_URL_PROD,
10
11
  DISCUSS_KIT_STORE_URL,
11
12
  DOC_SMITH_DIR,
12
13
  TMP_DIR,
@@ -16,96 +17,112 @@ import { beforePublishHook, ensureTmpDir } from "../../utils/d2-utils.mjs";
16
17
  import { deploy } from "../../utils/deploy.mjs";
17
18
  import { getGithubRepoUrl, loadConfigFromFile, saveValueToConfig } from "../../utils/utils.mjs";
18
19
 
20
+ const BASE_URL = process.env.DOC_SMITH_BASE_URL || CLOUD_SERVICE_URL_PROD;
21
+
19
22
  export default async function publishDocs(
20
23
  { docsDir: rawDocsDir, appUrl, boardId, projectName, projectDesc, projectLogo },
21
24
  options,
22
25
  ) {
23
- // move work dir to tmp-dir
24
- await ensureTmpDir();
25
-
26
- const docsDir = join(DOC_SMITH_DIR, TMP_DIR, TMP_DOCS_DIR);
27
- await fs.rm(docsDir, { recursive: true, force: true });
28
- await fs.mkdir(docsDir, {
29
- recursive: true,
30
- });
31
- await fs.cp(rawDocsDir, docsDir, { recursive: true });
32
-
33
- // ----------------- trigger beforePublishHook -----------------------------
34
- await beforePublishHook({ docsDir });
35
-
36
- // ----------------- main publish process flow -----------------------------
37
- // Check if DOC_DISCUSS_KIT_URL is set in environment variables
38
- const envAppUrl = process.env.DOC_DISCUSS_KIT_URL;
39
- const useEnvAppUrl = !!envAppUrl;
40
-
41
- // Use environment variable if available, otherwise use the provided appUrl
42
- if (useEnvAppUrl) {
43
- appUrl = envAppUrl;
44
- }
26
+ let message;
45
27
 
46
- // Check if appUrl is default and not saved in config (only when not using env variable)
47
- const config = await loadConfigFromFile();
48
- const isDefaultAppUrl = appUrl === DEFAULT_APP_URL;
49
- const hasAppUrlInConfig = config?.appUrl;
50
-
51
- let token = "";
52
-
53
- if (!useEnvAppUrl && isDefaultAppUrl && !hasAppUrlInConfig) {
54
- const hasCachedCheckoutId = !!config?.checkoutId;
55
- const choice = await options.prompts.select({
56
- message: "Select platform to publish your documents:",
57
- choices: [
58
- {
59
- name: `${chalk.blue("DocSmith Cloud (docsmith.aigne.io)")} – ${chalk.green("Free")} hosting. Your documents will be publicly accessible. Best for open-source projects or community sharing.`,
60
- value: "default",
61
- },
62
- {
63
- name: `${chalk.blue("Your existing website")} - Integrate and publish directly on your current site (setup required)`,
64
- value: "custom",
65
- },
66
- ...(hasCachedCheckoutId
67
- ? [
68
- {
69
- name: `${chalk.yellow("Resume previous website setup")} - ${chalk.green("Already paid.")} Continue where you left off. Your payment has already been processed.`,
70
- value: "new-instance-continue",
71
- },
72
- ]
73
- : []),
74
- {
75
- name: `${chalk.blue("New website")} - ${chalk.yellow("Paid service.")} We'll help you set up a brand-new website with custom domain and hosting. Great if you want a professional presence.`,
76
- value: "new-instance",
77
- },
78
- ],
28
+ try {
29
+ // move work dir to tmp-dir
30
+ await ensureTmpDir();
31
+
32
+ const docsDir = join(DOC_SMITH_DIR, TMP_DIR, TMP_DOCS_DIR);
33
+ await fs.rm(docsDir, { recursive: true, force: true });
34
+ await fs.mkdir(docsDir, {
35
+ recursive: true,
79
36
  });
37
+ await fs.cp(rawDocsDir, docsDir, { recursive: true });
38
+
39
+ // ----------------- trigger beforePublishHook -----------------------------
40
+ await beforePublishHook({ docsDir });
41
+
42
+ // ----------------- main publish process flow -----------------------------
43
+ // Check if DOC_DISCUSS_KIT_URL is set in environment variables
44
+ const envAppUrl = process.env.DOC_DISCUSS_KIT_URL;
45
+ const useEnvAppUrl = !!envAppUrl;
46
+
47
+ // Use environment variable if available, otherwise use the provided appUrl
48
+ if (useEnvAppUrl) {
49
+ appUrl = envAppUrl;
50
+ }
51
+
52
+ // Check if appUrl is default and not saved in config (only when not using env variable)
53
+ const config = await loadConfigFromFile();
54
+ const isDefaultAppUrl = appUrl === CLOUD_SERVICE_URL_PROD;
55
+ const hasAppUrlInConfig = config?.appUrl;
56
+
57
+ let token = "";
58
+
59
+ if (!useEnvAppUrl && isDefaultAppUrl && !hasAppUrlInConfig) {
60
+ const authToken = await getOfficialAccessToken(BASE_URL);
61
+
62
+ if (!authToken) {
63
+ throw new Error("Failed to get official access token");
64
+ }
80
65
 
81
- if (choice === "custom") {
82
- console.log(
83
- `${chalk.bold("\n💡 Tips")}\n\n` +
84
- `Start here to run your own website:\n${chalk.cyan(DISCUSS_KIT_STORE_URL)}\n`,
85
- );
86
- const userInput = await options.prompts.input({
87
- message: "Please enter your website URL:",
88
- validate: (input) => {
89
- try {
90
- // Check if input contains protocol, if not, prepend https://
91
- const urlWithProtocol = input.includes("://") ? input : `https://${input}`;
92
- new URL(urlWithProtocol);
93
- return true;
94
- } catch {
95
- return "Please enter a valid URL";
96
- }
97
- },
66
+ const client = new BrokerClient({ baseUrl: BASE_URL, authToken });
67
+
68
+ const { sessionId, paymentLink } = await client.checkCacheSession({
69
+ needShortUrl: true,
70
+ sessionId: config?.checkoutId,
71
+ });
72
+
73
+ const choice = await options.prompts.select({
74
+ message: "Select platform to publish your documents:",
75
+ choices: [
76
+ {
77
+ name: `${chalk.blue("DocSmith Cloud (docsmith.aigne.io)")} – ${chalk.green("Free")} hosting. Your documents will be publicly accessible. Best for open-source projects or community sharing.`,
78
+ value: "default",
79
+ },
80
+ {
81
+ name: `${chalk.blue("Your existing website")} - Integrate and publish directly on your current site (setup required)`,
82
+ value: "custom",
83
+ },
84
+ ...(sessionId
85
+ ? [
86
+ {
87
+ name: `${chalk.yellow("Resume previous website setup")} - ${chalk.green("Already paid.")} Continue where you left off. Your payment has already been processed.`,
88
+ value: "new-instance-continue",
89
+ },
90
+ ]
91
+ : []),
92
+ {
93
+ name: `${chalk.blue("New website")} - ${chalk.yellow("Paid service.")} We'll help you set up a brand-new website with custom domain and hosting. Great if you want a professional presence.`,
94
+ value: "new-instance",
95
+ },
96
+ ],
98
97
  });
99
- // Ensure appUrl has protocol
100
- appUrl = userInput.includes("://") ? userInput : `https://${userInput}`;
101
- } else if (["new-instance", "new-instance-continue"].includes(choice)) {
102
- // Deploy a new Discuss Kit service
103
- try {
98
+
99
+ if (choice === "custom") {
100
+ console.log(
101
+ `${chalk.bold("\n💡 Tips")}\n\n` +
102
+ `Start here to run your own website:\n${chalk.cyan(DISCUSS_KIT_STORE_URL)}\n`,
103
+ );
104
+ const userInput = await options.prompts.input({
105
+ message: "Please enter your website URL:",
106
+ validate: (input) => {
107
+ try {
108
+ // Check if input contains protocol, if not, prepend https://
109
+ const urlWithProtocol = input.includes("://") ? input : `https://${input}`;
110
+ new URL(urlWithProtocol);
111
+ return true;
112
+ } catch {
113
+ return "Please enter a valid URL";
114
+ }
115
+ },
116
+ });
117
+ // Ensure appUrl has protocol
118
+ appUrl = userInput.includes("://") ? userInput : `https://${userInput}`;
119
+ } else if (["new-instance", "new-instance-continue"].includes(choice)) {
120
+ // Deploy a new Discuss Kit service
104
121
  let id = "";
105
122
  let paymentUrl = "";
106
123
  if (choice === "new-instance-continue") {
107
- id = config?.checkoutId;
108
- paymentUrl = config?.paymentUrl;
124
+ id = sessionId;
125
+ paymentUrl = paymentLink;
109
126
  console.log(`\nResuming your previous website setup...`);
110
127
  } else {
111
128
  console.log(`\nCreating new website for your documentation...`);
@@ -114,42 +131,35 @@ export default async function publishDocs(
114
131
 
115
132
  appUrl = homeUrl;
116
133
  token = ltToken;
117
- } catch (error) {
118
- const errorMsg = error?.message || "Unknown error occurred";
119
- return { message: `${chalk.red("❌ Failed to publish to website:")} ${errorMsg}` };
120
134
  }
121
135
  }
122
- }
123
-
124
- console.log(`\nPublishing docs to ${chalk.cyan(appUrl)}\n`);
125
136
 
126
- const accessToken = await getAccessToken(appUrl, token);
137
+ console.log(`\nPublishing docs to ${chalk.cyan(appUrl)}\n`);
127
138
 
128
- process.env.DOC_ROOT_DIR = docsDir;
139
+ const accessToken = await getAccessToken(appUrl, token);
129
140
 
130
- const sidebarPath = join(docsDir, "_sidebar.md");
141
+ process.env.DOC_ROOT_DIR = docsDir;
131
142
 
132
- // Get project info from config
133
- const projectInfo = {
134
- name: projectName || config?.projectName || basename(process.cwd()),
135
- description: projectDesc || config?.projectDesc || "",
136
- icon: projectLogo || config?.projectLogo || "",
137
- };
143
+ const sidebarPath = join(docsDir, "_sidebar.md");
138
144
 
139
- // Construct boardMeta object
140
- const boardMeta = {
141
- category: config?.documentPurpose || [],
142
- githubRepoUrl: getGithubRepoUrl(),
143
- commitSha: config?.lastGitHead || "",
144
- languages: [
145
- ...(config?.locale ? [config.locale] : []),
146
- ...(config?.translateLanguages || []),
147
- ].filter((lang, index, arr) => arr.indexOf(lang) === index), // Remove duplicates
148
- };
145
+ // Get project info from config
146
+ const projectInfo = {
147
+ name: projectName || config?.projectName || basename(process.cwd()),
148
+ description: projectDesc || config?.projectDesc || "",
149
+ icon: projectLogo || config?.projectLogo || "",
150
+ };
149
151
 
150
- let message;
152
+ // Construct boardMeta object
153
+ const boardMeta = {
154
+ category: config?.documentPurpose || [],
155
+ githubRepoUrl: getGithubRepoUrl(),
156
+ commitSha: config?.lastGitHead || "",
157
+ languages: [
158
+ ...(config?.locale ? [config.locale] : []),
159
+ ...(config?.translateLanguages || []),
160
+ ].filter((lang, index, arr) => arr.indexOf(lang) === index), // Remove duplicates
161
+ };
151
162
 
152
- try {
153
163
  const {
154
164
  success,
155
165
  boardId: newBoardId,
@@ -184,16 +194,25 @@ export default async function publishDocs(
184
194
  } else {
185
195
  // If the error is 401 or 403, it means the access token is invalid
186
196
  if (error?.includes("401") || error?.includes("403")) {
187
- message = `❌ Publishing failed: you dont have valid authorization.\n Run ${chalk.cyan("aigne doc clear")} to reset it, then publish again.`;
197
+ message = `❌ Publishing failed: you don't have valid authorization.\n Run ${chalk.cyan("aigne doc clear")} to reset it, then publish again.`;
188
198
  }
189
199
  }
200
+
201
+ // clean up tmp work dir
202
+ await fs.rm(docsDir, { recursive: true, force: true });
190
203
  } catch (error) {
191
204
  message = `❌ Failed to publish docs: ${error.message}`;
205
+
206
+ // clean up tmp work dir in case of error
207
+ try {
208
+ const docsDir = join(DOC_SMITH_DIR, TMP_DIR, TMP_DOCS_DIR);
209
+ await fs.rm(docsDir, { recursive: true, force: true });
210
+ } catch {
211
+ // ignore cleanup errors
212
+ }
192
213
  }
193
- await saveValueToConfig("checkoutId", "", "Checkout ID for document deployment service");
194
214
 
195
- // clean up tmp work dir
196
- await fs.rm(docsDir, { recursive: true, force: true });
215
+ await saveValueToConfig("checkoutId", "", "Checkout ID for document deployment service");
197
216
  return message ? { message } : {};
198
217
  }
199
218
 
@@ -207,7 +226,7 @@ publishDocs.input_schema = {
207
226
  appUrl: {
208
227
  type: "string",
209
228
  description: "The url of the app",
210
- default: DEFAULT_APP_URL,
229
+ default: CLOUD_SERVICE_URL_PROD,
211
230
  },
212
231
  boardId: {
213
232
  type: "string",
@@ -37,7 +37,7 @@ skills:
37
37
  default_input:
38
38
  isTranslate: true
39
39
  iterate_on: selectedDocs
40
- concurrency: 3
40
+ concurrency: 10
41
41
  - url: ../utils/check-feedback-refiner.mjs
42
42
  default_input:
43
43
  stage: translation_refine
@@ -15,5 +15,5 @@ input_schema:
15
15
  items: { type: string }
16
16
  description: Array of modified files since last generation
17
17
  iterate_on: documentExecutionStructure
18
- concurrency: 3
18
+ concurrency: 10
19
19
  mode: sequential
@@ -4,4 +4,4 @@ name: batchUpdateDocument
4
4
  skills:
5
5
  - ../update/handle-document-update.yaml
6
6
  iterate_on: selectedDocs
7
- concurrency: 5
7
+ concurrency: 10
@@ -2,7 +2,6 @@ import { access, readFile } from "node:fs/promises";
2
2
  import { dirname, join } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { TeamAgent } from "@aigne/core";
5
- import { hasSourceFilesChanged } from "../../utils/utils.mjs";
6
5
  import checkDetailResult from "../utils/check-detail-result.mjs";
7
6
 
8
7
  // Get current script directory
@@ -17,13 +16,14 @@ export default async function checkDocument(
17
16
  documentStructure,
18
17
  modifiedFiles,
19
18
  forceRegenerate,
19
+ locale,
20
20
  ...rest
21
21
  },
22
22
  options,
23
23
  ) {
24
24
  // Check if the detail file already exists
25
25
  const flatName = path.replace(/^\//, "").replace(/\//g, "-");
26
- const fileFullName = `${flatName}.md`;
26
+ const fileFullName = locale === "en" ? `${flatName}.md` : `${flatName}.${locale}.md`;
27
27
  const filePath = join(docsDir, fileFullName);
28
28
  let detailGenerated = true;
29
29
  let fileContent = null;
@@ -69,16 +69,6 @@ export default async function checkDocument(
69
69
  }
70
70
  }
71
71
 
72
- // Check if source files have changed since last generation
73
- let sourceFilesChanged = false;
74
- if (sourceIds && sourceIds.length > 0 && modifiedFiles) {
75
- sourceFilesChanged = hasSourceFilesChanged(sourceIds, modifiedFiles);
76
-
77
- if (sourceFilesChanged) {
78
- console.log(`Source files changed for ${path}, will regenerate`);
79
- }
80
- }
81
-
82
72
  // If file exists, check content validation
83
73
  let contentValidationFailed = false;
84
74
  let validationResult = {};
@@ -95,13 +85,7 @@ export default async function checkDocument(
95
85
  }
96
86
 
97
87
  // If file exists, sourceIds haven't changed, source files haven't changed, and content validation passes, no need to regenerate
98
- if (
99
- detailGenerated &&
100
- !sourceIdsChanged &&
101
- !sourceFilesChanged &&
102
- !contentValidationFailed &&
103
- !forceRegenerate
104
- ) {
88
+ if (detailGenerated && !sourceIdsChanged && !contentValidationFailed && !forceRegenerate) {
105
89
  return {
106
90
  path,
107
91
  docsDir,
@@ -175,9 +175,10 @@ export default async function userReviewDocument(
175
175
  const feedback = await options.prompts.input({
176
176
  message:
177
177
  "How would you like to improve this document?\n" +
178
- " • Add, modify, or remove content\n" +
179
- " • Improve clarity, accuracy, or completeness\n" +
180
- " • Adjust tone, style, or technical level\n\n" +
178
+ "Examples:\n" +
179
+ " • Add troubleshooting section for common errors\n" +
180
+ " • Simplify the explanation for beginners\n" +
181
+ " • Remove the outdated information about version 1.0\n\n" +
181
182
  " Your feedback:",
182
183
  });
183
184
 
@@ -1,15 +1,21 @@
1
- import { readFile, stat } from "node:fs/promises";
1
+ import { readFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import {
4
- DEFAULT_EXCLUDE_PATTERNS,
5
- DEFAULT_INCLUDE_PATTERNS,
6
- } from "../../utils/constants/index.mjs";
7
- import { getFilesWithGlob, loadGitignore } from "../../utils/file-utils.mjs";
4
+ buildSourcesContent,
5
+ calculateFileStats,
6
+ loadFilesFromPaths,
7
+ readFileContents,
8
+ } from "../../utils/file-utils.mjs";
8
9
  import {
9
10
  getCurrentGitHead,
10
11
  getModifiedFilesBetweenCommits,
11
- isGlobPattern,
12
+ toRelativePath,
12
13
  } from "../../utils/utils.mjs";
14
+ import {
15
+ INTELLIGENT_SUGGESTION_TOKEN_THRESHOLD,
16
+ DEFAULT_EXCLUDE_PATTERNS,
17
+ DEFAULT_INCLUDE_PATTERNS,
18
+ } from "../../utils/constants/index.mjs";
13
19
 
14
20
  export default async function loadSources({
15
21
  sources = [],
@@ -27,103 +33,22 @@ export default async function loadSources({
27
33
  let files = Array.isArray(sources) ? [...sources] : [];
28
34
 
29
35
  if (sourcesPath) {
30
- const paths = Array.isArray(sourcesPath) ? sourcesPath : [sourcesPath];
31
- let allFiles = [];
32
-
33
- for (const dir of paths) {
34
- try {
35
- if (typeof dir !== "string") {
36
- console.warn(`Invalid source path: ${dir}`);
37
- continue;
38
- }
39
-
40
- // First try to access as a file or directory
41
- const stats = await stat(dir);
42
-
43
- if (stats.isFile()) {
44
- // If it's a file, add it directly without filtering
45
- allFiles.push(dir);
46
- } else if (stats.isDirectory()) {
47
- // If it's a directory, use the existing glob logic
48
- // Load .gitignore for this directory
49
- const gitignorePatterns = await loadGitignore(dir);
50
-
51
- // Prepare patterns
52
- let finalIncludePatterns = null;
53
- let finalExcludePatterns = null;
54
-
55
- if (useDefaultPatterns) {
56
- // Merge with default patterns
57
- const userInclude = includePatterns
58
- ? Array.isArray(includePatterns)
59
- ? includePatterns
60
- : [includePatterns]
61
- : [];
62
- const userExclude = excludePatterns
63
- ? Array.isArray(excludePatterns)
64
- ? excludePatterns
65
- : [excludePatterns]
66
- : [];
67
-
68
- finalIncludePatterns = [...DEFAULT_INCLUDE_PATTERNS, ...userInclude];
69
- finalExcludePatterns = [...DEFAULT_EXCLUDE_PATTERNS, ...userExclude];
70
- } else {
71
- // Use only user patterns
72
- if (includePatterns) {
73
- finalIncludePatterns = Array.isArray(includePatterns)
74
- ? includePatterns
75
- : [includePatterns];
76
- }
77
- if (excludePatterns) {
78
- finalExcludePatterns = Array.isArray(excludePatterns)
79
- ? excludePatterns
80
- : [excludePatterns];
81
- }
82
- }
83
-
84
- // Get files using glob
85
- const filesInDir = await getFilesWithGlob(
86
- dir,
87
- finalIncludePatterns,
88
- finalExcludePatterns,
89
- gitignorePatterns,
90
- );
91
- allFiles = allFiles.concat(filesInDir);
92
- }
93
- } catch (err) {
94
- if (err.code === "ENOENT") {
95
- // Path doesn't exist as file or directory, try as glob pattern
96
- try {
97
- // Check if it looks like a glob pattern
98
- const isGlobPatternResult = isGlobPattern(dir);
99
-
100
- if (isGlobPatternResult) {
101
- // Use glob to find matching files from current working directory
102
- const { glob } = await import("glob");
103
- const matchedFiles = await glob(dir, {
104
- absolute: true,
105
- nodir: true, // Only files, not directories
106
- dot: false, // Don't include hidden files
107
- });
108
-
109
- if (matchedFiles.length > 0) {
110
- allFiles = allFiles.concat(matchedFiles);
111
- }
112
- }
113
- } catch (globErr) {
114
- console.warn(`Failed to process glob pattern "${dir}": ${globErr.message}`);
115
- }
116
- } else {
117
- throw err;
118
- }
119
- }
120
- }
36
+ const allFiles = await loadFilesFromPaths(sourcesPath, {
37
+ includePatterns,
38
+ excludePatterns,
39
+ useDefaultPatterns,
40
+ defaultIncludePatterns: DEFAULT_INCLUDE_PATTERNS,
41
+ defaultExcludePatterns: DEFAULT_EXCLUDE_PATTERNS,
42
+ });
121
43
 
122
44
  files = files.concat(allFiles);
123
45
  }
124
46
 
125
47
  files = [...new Set(files)];
126
48
 
49
+ // all files path
50
+ const allFilesPaths = files.map((file) => `- ${toRelativePath(file)}`).join("\n");
51
+
127
52
  // Define media file extensions
128
53
  const mediaExtensions = [
129
54
  ".jpg",
@@ -142,38 +67,40 @@ export default async function loadSources({
142
67
  ];
143
68
 
144
69
  // Separate source files from media files
145
- const sourceFiles = [];
70
+ const sourceFilesPaths = [];
146
71
  const mediaFiles = [];
147
- let allSources = "";
148
72
 
149
- await Promise.all(
150
- files.map(async (file) => {
151
- const ext = path.extname(file).toLowerCase();
73
+ for (const file of files) {
74
+ const ext = path.extname(file).toLowerCase();
75
+
76
+ if (mediaExtensions.includes(ext)) {
77
+ // This is a media file
78
+ const relativePath = path.relative(docsDir, file);
79
+ const fileName = path.basename(file);
80
+ const description = path.parse(fileName).name;
81
+
82
+ mediaFiles.push({
83
+ name: fileName,
84
+ path: relativePath,
85
+ description,
86
+ });
87
+ } else {
88
+ // This is a source file
89
+ sourceFilesPaths.push(file);
90
+ }
91
+ }
92
+
93
+ // Read all source files using the utility function
94
+ const sourceFiles = await readFileContents(sourceFilesPaths, process.cwd());
152
95
 
153
- if (mediaExtensions.includes(ext)) {
154
- // This is a media file
155
- const relativePath = path.relative(docsDir, file);
156
- const fileName = path.basename(file);
157
- const description = path.parse(fileName).name;
96
+ // Count tokens and lines using utility function
97
+ const { totalTokens, totalLines } = calculateFileStats(sourceFiles);
158
98
 
159
- mediaFiles.push({
160
- name: fileName,
161
- path: relativePath,
162
- description,
163
- });
164
- } else {
165
- // This is a source file
166
- const content = await readFile(file, "utf8");
167
- const relativePath = path.relative(process.cwd(), file);
168
- allSources += `// sourceId: ${relativePath}\n${content}\n`;
99
+ // check if totalTokens is too large
100
+ const isLargeContext = totalTokens > INTELLIGENT_SUGGESTION_TOKEN_THRESHOLD;
169
101
 
170
- sourceFiles.push({
171
- sourceId: relativePath,
172
- content,
173
- });
174
- }
175
- }),
176
- );
102
+ // Build allSources string using utility function
103
+ const allSources = buildSourcesContent(sourceFiles, isLargeContext);
177
104
 
178
105
  // Get the last documentation structure
179
106
  let originalDocumentStructure;
@@ -283,31 +210,17 @@ export default async function loadSources({
283
210
  assetsContent += "```\n";
284
211
  }
285
212
 
286
- // Count words and lines in allSources
287
- let totalWords = 0;
288
- let totalLines = 0;
289
-
290
- for (const source of Object.values(allSources)) {
291
- if (typeof source === "string") {
292
- // Count English words (simple regex for words containing a-zA-Z)
293
- const words = source.match(/[a-zA-Z]+/g) || [];
294
- totalWords += words.length;
295
-
296
- // Count lines (excluding empty lines)
297
- totalLines += source.split("\n").filter((line) => line.trim() !== "").length;
298
- }
299
- }
300
-
301
213
  return {
302
- datasourcesList: sourceFiles,
303
214
  datasources: allSources,
304
215
  content,
305
216
  originalDocumentStructure,
306
217
  files,
307
218
  modifiedFiles,
308
- totalWords,
219
+ totalTokens,
309
220
  totalLines,
310
221
  assetsContent,
222
+ isLargeContext,
223
+ allFilesPaths,
311
224
  };
312
225
  }
313
226
 
@@ -357,16 +270,6 @@ loadSources.output_schema = {
357
270
  datasources: {
358
271
  type: "string",
359
272
  },
360
- datasourcesList: {
361
- type: "array",
362
- items: {
363
- type: "object",
364
- properties: {
365
- sourceId: { type: "string" },
366
- content: { type: "string" },
367
- },
368
- },
369
- },
370
273
  files: {
371
274
  type: "array",
372
275
  items: { type: "string" },