@aigne/doc-smith 0.2.4 → 0.2.6

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 (37) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +1 -0
  3. package/agents/check-detail-result.mjs +15 -120
  4. package/agents/check-structure-plan.mjs +56 -7
  5. package/agents/detail-generator-and-translate.yaml +7 -1
  6. package/agents/detail-regenerator.yaml +6 -57
  7. package/agents/docs-generator.yaml +5 -61
  8. package/agents/find-item-by-path.mjs +63 -14
  9. package/agents/input-generator.mjs +31 -21
  10. package/agents/language-selector.mjs +101 -0
  11. package/agents/load-config.mjs +3 -3
  12. package/agents/load-sources.mjs +55 -40
  13. package/agents/publish-docs.mjs +44 -153
  14. package/agents/retranslate.yaml +74 -0
  15. package/agents/save-docs.mjs +12 -2
  16. package/agents/save-output.mjs +9 -3
  17. package/agents/save-single-doc.mjs +19 -0
  18. package/agents/structure-planning.yaml +6 -0
  19. package/agents/team-publish-docs.yaml +7 -7
  20. package/agents/translate.yaml +3 -0
  21. package/aigne.yaml +5 -1
  22. package/docs-mcp/docs-search.yaml +1 -1
  23. package/docs-mcp/get-docs-detail.mjs +1 -1
  24. package/docs-mcp/get-docs-structure.mjs +1 -1
  25. package/docs-mcp/read-doc-content.mjs +1 -1
  26. package/package.json +16 -7
  27. package/prompts/check-structure-planning-result.md +4 -7
  28. package/prompts/content-detail-generator.md +1 -2
  29. package/prompts/structure-planning.md +7 -2
  30. package/prompts/translator.md +4 -0
  31. package/tests/test-all-validation-cases.mjs +707 -0
  32. package/utils/constants.mjs +3 -2
  33. package/utils/markdown-checker.mjs +386 -0
  34. package/utils/mermaid-validator.mjs +158 -0
  35. package/utils/mermaid-worker-pool.mjs +254 -0
  36. package/utils/mermaid-worker.mjs +242 -0
  37. package/utils/utils.mjs +155 -44
@@ -1,13 +1,16 @@
1
1
  import { writeFile, mkdir, readFile } from "node:fs/promises";
2
2
  import { join, dirname } from "node:path";
3
3
  import chalk from "chalk";
4
- import { validatePath, getAvailablePaths } from "../utils/utils.mjs";
4
+ import {
5
+ validatePath,
6
+ getAvailablePaths,
7
+ getProjectInfo,
8
+ } from "../utils/utils.mjs";
5
9
  import {
6
10
  SUPPORTED_LANGUAGES,
7
11
  DOCUMENT_STYLES,
8
12
  TARGET_AUDIENCES,
9
13
  } from "../utils/constants.mjs";
10
-
11
14
  // UI constants
12
15
  const PRESS_ENTER_TO_FINISH = "Press Enter to finish";
13
16
 
@@ -20,7 +23,7 @@ const PRESS_ENTER_TO_FINISH = "Press Enter to finish";
20
23
  */
21
24
  export default async function init(
22
25
  {
23
- outputPath = "./doc-smith",
26
+ outputPath = ".aigne/doc-smith",
24
27
  fileName = "config.yaml",
25
28
  skipIfExists = false,
26
29
  },
@@ -40,11 +43,9 @@ export default async function init(
40
43
  const input = {};
41
44
 
42
45
  // 1. Document generation rules with style selection
43
- console.log("šŸ“ Step 1/6: Document Generation Rules");
44
-
45
46
  // Let user select a document style
46
47
  const styleChoice = await options.prompts.select({
47
- message: "Choose your documentation style:",
48
+ message: "šŸ“ Step 1/6: Choose your documentation style:",
48
49
  choices: Object.entries(DOCUMENT_STYLES).map(([key, style]) => ({
49
50
  name: `${style.name} - ${style.rules}`,
50
51
  value: key,
@@ -65,11 +66,9 @@ export default async function init(
65
66
  input.rules = rules.trim();
66
67
 
67
68
  // 2. Target audience selection
68
- console.log("\nšŸ‘„ Step 2/6: Target Audience");
69
-
70
69
  // Let user select target audience
71
70
  const audienceChoice = await options.prompts.select({
72
- message: "Who is your target audience?",
71
+ message: "šŸ‘„ Step 2/6: Who is your target audience?",
73
72
  choices: Object.entries(TARGET_AUDIENCES).map(([key, audience]) => ({
74
73
  name: audience,
75
74
  value: key,
@@ -90,11 +89,9 @@ export default async function init(
90
89
  input.targetAudience = targetAudience.trim();
91
90
 
92
91
  // 3. Language settings
93
- console.log("\n🌐 Step 3/6: Primary Language");
94
-
95
92
  // Let user select primary language from supported list
96
93
  const primaryLanguageChoice = await options.prompts.select({
97
- message: "Choose primary documentation language:",
94
+ message: "🌐 Step 3/6: Choose primary documentation language:",
98
95
  choices: SUPPORTED_LANGUAGES.map((lang) => ({
99
96
  name: `${lang.label} - ${lang.sample}`,
100
97
  value: lang.code,
@@ -104,15 +101,13 @@ export default async function init(
104
101
  input.locale = primaryLanguageChoice;
105
102
 
106
103
  // 4. Translation languages
107
- console.log("\nšŸ”„ Step 4/6: Translation Languages");
108
-
109
104
  // Filter out the primary language from available choices
110
105
  const availableTranslationLanguages = SUPPORTED_LANGUAGES.filter(
111
106
  (lang) => lang.code !== primaryLanguageChoice
112
107
  );
113
108
 
114
109
  const translateLanguageChoices = await options.prompts.checkbox({
115
- message: "Select translation languages:",
110
+ message: "šŸ”„ Step 4/6: Select translation languages:",
116
111
  choices: availableTranslationLanguages.map((lang) => ({
117
112
  name: `${lang.label} - ${lang.sample}`,
118
113
  value: lang.code,
@@ -122,9 +117,8 @@ export default async function init(
122
117
  input.translateLanguages = translateLanguageChoices;
123
118
 
124
119
  // 5. Documentation directory
125
- console.log("\nšŸ“ Step 5/6: Output Directory");
126
120
  const docsDirInput = await options.prompts.input({
127
- message: `Where to save generated docs:`,
121
+ message: `šŸ“ Step 5/6: Where to save generated docs:`,
128
122
  default: `${outputPath}/docs`,
129
123
  });
130
124
  input.docsDir = docsDirInput.trim() || `${outputPath}/docs`;
@@ -189,6 +183,12 @@ export default async function init(
189
183
  // If no paths entered, use default
190
184
  input.sourcesPath = sourcePaths.length > 0 ? sourcePaths : ["./"];
191
185
 
186
+ // Save project info to config
187
+ const projectInfo = await getProjectInfo();
188
+ input.projectName = projectInfo.name;
189
+ input.projectDesc = projectInfo.description;
190
+ input.projectLogo = projectInfo.icon;
191
+
192
192
  // Generate YAML content
193
193
  const yamlContent = generateYAML(input, outputPath);
194
194
 
@@ -202,13 +202,17 @@ export default async function init(
202
202
 
203
203
  await writeFile(filePath, yamlContent, "utf8");
204
204
  console.log(`\nšŸŽ‰ Configuration saved to: ${chalk.cyan(filePath)}`);
205
+ // Print YAML content for user review
206
+ console.log(chalk.cyan("---"));
207
+ console.log(chalk.cyan(yamlContent));
208
+ console.log(chalk.cyan("---"));
205
209
  console.log(
206
- "šŸ’” You can edit the configuration file anytime to modify settings."
210
+ "šŸ’” You can edit the configuration file anytime to modify settings.\n"
207
211
  );
208
212
  console.log(
209
213
  `šŸš€ Run ${chalk.cyan(
210
214
  "'aigne doc generate'"
211
- )} to start documentation generation!`
215
+ )} to start documentation generation!\n`
212
216
  );
213
217
 
214
218
  return {};
@@ -224,12 +228,18 @@ export default async function init(
224
228
  /**
225
229
  * Generate YAML configuration content
226
230
  * @param {Object} input - Input object
227
- * @param {string} outputPath - Output path for directory configuration
228
231
  * @returns {string} YAML string
229
232
  */
230
- function generateYAML(input, outputPath) {
233
+ function generateYAML(input) {
231
234
  let yaml = "";
232
235
 
236
+ // Add project information at the beginning
237
+ yaml += `# Project information for documentation publishing\n`;
238
+ yaml += `projectName: ${input.projectName || ""}\n`;
239
+ yaml += `projectDesc: ${input.projectDesc || ""}\n`;
240
+ yaml += `projectLogo: ${input.projectLogo || ""}\n`;
241
+ yaml += `\n`;
242
+
233
243
  // Add rules (required field)
234
244
  yaml += `rules: |\n`;
235
245
  if (input.rules && input.rules.trim()) {
@@ -0,0 +1,101 @@
1
+ import { SUPPORTED_LANGUAGES } from "../utils/constants.mjs";
2
+
3
+ /**
4
+ * Interactive language selector for translation from configured languages
5
+ * @param {Object} params
6
+ * @param {Array<string>} [params.languages] - Pre-selected languages
7
+ * @param {Array<string>} params.translateLanguages - Available languages from config
8
+ * @param {Object} options - Options object with prompts
9
+ * @returns {Promise<Object>} Selected languages
10
+ */
11
+ export default async function languageSelector(
12
+ { languages, translateLanguages },
13
+ options
14
+ ) {
15
+ let selectedLanguages = [];
16
+
17
+ // Check if translateLanguages is available from config
18
+ if (
19
+ !translateLanguages ||
20
+ !Array.isArray(translateLanguages) ||
21
+ translateLanguages.length === 0
22
+ ) {
23
+ throw new Error(
24
+ "No translation languages configured in config.yaml. Please add translateLanguages to your configuration."
25
+ );
26
+ }
27
+
28
+ // If languages are provided as parameter, validate against configured languages
29
+ if (languages && Array.isArray(languages) && languages.length > 0) {
30
+ const validLanguages = languages.filter((lang) =>
31
+ translateLanguages.includes(lang)
32
+ );
33
+
34
+ if (validLanguages.length > 0) {
35
+ selectedLanguages = validLanguages;
36
+ } else {
37
+ console.log(`āš ļø Invalid languages provided: ${languages.join(", ")}`);
38
+ console.log(
39
+ "Available configured languages:",
40
+ translateLanguages.join(", ")
41
+ );
42
+ }
43
+ }
44
+
45
+ // If no valid languages were provided, let user select from configured languages
46
+ if (selectedLanguages.length === 0) {
47
+ // Create choices from configured languages with labels
48
+ const choices = translateLanguages.map((langCode) => {
49
+ const supportedLang = SUPPORTED_LANGUAGES.find(
50
+ (l) => l.code === langCode
51
+ );
52
+ return {
53
+ name: supportedLang
54
+ ? `${supportedLang.label} (${supportedLang.sample})`
55
+ : langCode,
56
+ value: langCode,
57
+ short: langCode,
58
+ };
59
+ });
60
+
61
+ selectedLanguages = await options.prompts.checkbox({
62
+ message: "Select languages to translate:",
63
+ choices: choices,
64
+ validate: (answer) => {
65
+ if (answer.length === 0) {
66
+ return "Please select at least one language";
67
+ }
68
+ return true;
69
+ },
70
+ });
71
+ }
72
+
73
+ if (selectedLanguages.length === 0) {
74
+ throw new Error("No languages selected for re-translation");
75
+ }
76
+
77
+ return {
78
+ selectedLanguages,
79
+ };
80
+ }
81
+
82
+ languageSelector.input_schema = {
83
+ type: "object",
84
+ properties: {
85
+ languages: {
86
+ type: "array",
87
+ items: {
88
+ type: "string",
89
+ },
90
+ description: "Pre-selected languages for translation",
91
+ },
92
+ translateLanguages: {
93
+ type: "array",
94
+ items: {
95
+ type: "string",
96
+ },
97
+ description: "Available translation languages from config",
98
+ },
99
+ },
100
+ required: ["translateLanguages"],
101
+ };
@@ -22,8 +22,8 @@ export default async function loadConfig({ config }) {
22
22
  nodeName: "Section",
23
23
  locale: "en",
24
24
  sourcesPath: ["./"],
25
- docDir: "./doc-smith/docs",
26
- outputDir: "./doc-smith/output",
25
+ docsDir: "./.aigne/doc-smith/docs",
26
+ outputDir: "./.aigne/doc-smith/output",
27
27
  lastGitHead: parsedConfig.lastGitHead || "",
28
28
  ...parsedConfig,
29
29
  };
@@ -38,7 +38,7 @@ loadConfig.input_schema = {
38
38
  properties: {
39
39
  config: {
40
40
  type: "string",
41
- default: "./doc-smith/config.yaml",
41
+ default: "./.aigne/doc-smith/config.yaml",
42
42
  },
43
43
  },
44
44
  };
@@ -1,4 +1,4 @@
1
- import { access, readFile } from "node:fs/promises";
1
+ import { access, readFile, stat } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { glob } from "glob";
4
4
  import {
@@ -115,50 +115,65 @@ export default async function loadSources({
115
115
 
116
116
  for (const dir of paths) {
117
117
  try {
118
- // Load .gitignore for this directory
119
- const gitignorePatterns = await loadGitignore(dir);
118
+ // Check if the path is a file or directory
119
+ const stats = await stat(dir);
120
120
 
121
- // Prepare patterns
122
- let finalIncludePatterns = null;
123
- let finalExcludePatterns = null;
121
+ if (stats.isFile()) {
122
+ // If it's a file, add it directly without filtering
123
+ allFiles.push(dir);
124
+ } else if (stats.isDirectory()) {
125
+ // If it's a directory, use the existing glob logic
126
+ // Load .gitignore for this directory
127
+ const gitignorePatterns = await loadGitignore(dir);
124
128
 
125
- if (useDefaultPatterns) {
126
- // Merge with default patterns
127
- const userInclude = includePatterns
128
- ? Array.isArray(includePatterns)
129
- ? includePatterns
130
- : [includePatterns]
131
- : [];
132
- const userExclude = excludePatterns
133
- ? Array.isArray(excludePatterns)
134
- ? excludePatterns
135
- : [excludePatterns]
136
- : [];
129
+ // Prepare patterns
130
+ let finalIncludePatterns = null;
131
+ let finalExcludePatterns = null;
137
132
 
138
- finalIncludePatterns = [...DEFAULT_INCLUDE_PATTERNS, ...userInclude];
139
- finalExcludePatterns = [...DEFAULT_EXCLUDE_PATTERNS, ...userExclude];
140
- } else {
141
- // Use only user patterns
142
- if (includePatterns) {
143
- finalIncludePatterns = Array.isArray(includePatterns)
144
- ? includePatterns
145
- : [includePatterns];
146
- }
147
- if (excludePatterns) {
148
- finalExcludePatterns = Array.isArray(excludePatterns)
149
- ? excludePatterns
150
- : [excludePatterns];
133
+ if (useDefaultPatterns) {
134
+ // Merge with default patterns
135
+ const userInclude = includePatterns
136
+ ? Array.isArray(includePatterns)
137
+ ? includePatterns
138
+ : [includePatterns]
139
+ : [];
140
+ const userExclude = excludePatterns
141
+ ? Array.isArray(excludePatterns)
142
+ ? excludePatterns
143
+ : [excludePatterns]
144
+ : [];
145
+
146
+ finalIncludePatterns = [
147
+ ...DEFAULT_INCLUDE_PATTERNS,
148
+ ...userInclude,
149
+ ];
150
+ finalExcludePatterns = [
151
+ ...DEFAULT_EXCLUDE_PATTERNS,
152
+ ...userExclude,
153
+ ];
154
+ } else {
155
+ // Use only user patterns
156
+ if (includePatterns) {
157
+ finalIncludePatterns = Array.isArray(includePatterns)
158
+ ? includePatterns
159
+ : [includePatterns];
160
+ }
161
+ if (excludePatterns) {
162
+ finalExcludePatterns = Array.isArray(excludePatterns)
163
+ ? excludePatterns
164
+ : [excludePatterns];
165
+ }
151
166
  }
152
- }
153
167
 
154
- // Get files using glob
155
- const filesInDir = await getFilesWithGlob(
156
- dir,
157
- finalIncludePatterns,
158
- finalExcludePatterns,
159
- gitignorePatterns
160
- );
161
- allFiles = allFiles.concat(filesInDir);
168
+ // Get files using glob
169
+ const filesInDir = await getFilesWithGlob(
170
+ dir,
171
+ finalIncludePatterns,
172
+ finalExcludePatterns,
173
+ gitignorePatterns
174
+ );
175
+ allFiles = allFiles.concat(filesInDir);
176
+ }
162
177
  } catch (err) {
163
178
  if (err.code !== "ENOENT") throw err;
164
179
  }
@@ -7,119 +7,12 @@ import { existsSync, mkdirSync } from "node:fs";
7
7
  import { readFile, writeFile } from "node:fs/promises";
8
8
  import { homedir } from "node:os";
9
9
  import { parse, stringify } from "yaml";
10
- import { execSync } from "node:child_process";
11
10
  import { basename } from "node:path";
12
11
  import { loadConfigFromFile, saveValueToConfig } from "../utils/utils.mjs";
13
12
 
14
13
  const WELLKNOWN_SERVICE_PATH_PREFIX = "/.well-known/service";
15
14
  const DEFAULT_APP_URL = "https://docsmith.aigne.io";
16
15
 
17
- /**
18
- * Get GitHub repository information
19
- * @param {string} repoUrl - The repository URL
20
- * @returns {Promise<Object>} - Repository information
21
- */
22
- async function getGitHubRepoInfo(repoUrl) {
23
- try {
24
- // Extract owner and repo from GitHub URL
25
- const match = repoUrl.match(
26
- /github\.com[\/:]([^\/]+)\/([^\/]+?)(?:\.git)?$/
27
- );
28
- if (!match) return null;
29
-
30
- const [, owner, repo] = match;
31
- const apiUrl = `https://api.github.com/repos/${owner}/${repo}`;
32
-
33
- const response = await fetch(apiUrl);
34
- if (!response.ok) return null;
35
-
36
- const data = await response.json();
37
- return {
38
- name: data.name,
39
- description: data.description || "",
40
- icon: data.owner?.avatar_url || "",
41
- };
42
- } catch (error) {
43
- console.warn("Failed to fetch GitHub repository info:", error.message);
44
- return null;
45
- }
46
- }
47
-
48
- /**
49
- * Get project information with user confirmation
50
- * @param {Object} options - Options object containing prompts
51
- * @returns {Promise<Object>} - Project information including name, description, and icon
52
- */
53
- async function getProjectInfo(options) {
54
- let repoInfo = null;
55
- let defaultName = basename(process.cwd());
56
- let defaultDescription = "";
57
- let defaultIcon = "";
58
-
59
- // Check if we're in a git repository
60
- try {
61
- const gitRemote = execSync("git remote get-url origin", {
62
- encoding: "utf8",
63
- stdio: ["pipe", "pipe", "ignore"],
64
- }).trim();
65
-
66
- // Extract repository name from git remote URL
67
- const repoName = gitRemote.split("/").pop().replace(".git", "");
68
- defaultName = repoName;
69
-
70
- // If it's a GitHub repository, try to get additional info
71
- if (gitRemote.includes("github.com")) {
72
- repoInfo = await getGitHubRepoInfo(gitRemote);
73
- if (repoInfo) {
74
- defaultDescription = repoInfo.description;
75
- defaultIcon = repoInfo.icon;
76
- }
77
- }
78
- } catch (error) {
79
- // Not in git repository or no origin remote, use current directory name
80
- console.warn("No git repository found, using current directory name");
81
- }
82
-
83
- // Prompt user for project information
84
- console.log("\nšŸ“‹ Project Information for Documentation Platform");
85
-
86
- const projectName = await options.prompts.input({
87
- message: "Project name:",
88
- default: defaultName,
89
- validate: (input) => {
90
- if (!input || input.trim() === "") {
91
- return "Project name cannot be empty";
92
- }
93
- return true;
94
- },
95
- });
96
-
97
- const projectDescription = await options.prompts.input({
98
- message: "Project description (optional):",
99
- default: defaultDescription,
100
- });
101
-
102
- const projectIcon = await options.prompts.input({
103
- message: "Project icon URL (optional):",
104
- default: defaultIcon,
105
- validate: (input) => {
106
- if (!input || input.trim() === "") return true;
107
- try {
108
- new URL(input);
109
- return true;
110
- } catch {
111
- return "Please enter a valid URL";
112
- }
113
- },
114
- });
115
-
116
- return {
117
- name: projectName.trim(),
118
- description: projectDescription.trim(),
119
- icon: projectIcon.trim(),
120
- };
121
- }
122
-
123
16
  /**
124
17
  * Get access token from environment, config file, or prompt user for authorization
125
18
  * @param {string} appUrl - The application URL
@@ -207,7 +100,7 @@ async function getAccessToken(appUrl) {
207
100
  }
208
101
 
209
102
  export default async function publishDocs(
210
- { docsDir, appUrl, boardId, boardName, boardDesc, boardCover },
103
+ { docsDir, appUrl, boardId, projectName, projectDesc, projectLogo },
211
104
  options
212
105
  ) {
213
106
  // Check if DOC_DISCUSS_KIT_URL is set in environment variables
@@ -260,58 +153,56 @@ export default async function publishDocs(
260
153
 
261
154
  const sidebarPath = join(docsDir, "_sidebar.md");
262
155
 
263
- let projectInfo = {
264
- name: boardName,
265
- description: boardDesc,
266
- icon: boardCover,
156
+ // Get project info from config
157
+ const projectInfo = {
158
+ name: projectName || config?.projectName || basename(process.cwd()),
159
+ description: projectDesc || config?.projectDesc || "",
160
+ icon: projectLogo || config?.projectLogo || "",
267
161
  };
268
162
 
269
- // Only get project info if we need to create a new board
270
- if (!boardName) {
271
- projectInfo = await getProjectInfo(options);
272
-
273
- // save project info to config
274
- await saveValueToConfig("boardName", projectInfo.name);
275
- await saveValueToConfig("boardDesc", projectInfo.description);
276
- await saveValueToConfig("boardCover", projectInfo.icon);
277
- }
163
+ try {
164
+ const {
165
+ success,
166
+ boardId: newBoardId,
167
+ docsUrl,
168
+ } = await publishDocsFn({
169
+ sidebarPath,
170
+ accessToken,
171
+ appUrl,
172
+ boardId,
173
+ autoCreateBoard: true,
174
+ // Pass additional project information if available
175
+ boardName: projectInfo.name,
176
+ boardDesc: projectInfo.description,
177
+ boardCover: projectInfo.icon,
178
+ });
278
179
 
279
- const {
280
- success,
281
- boardId: newBoardId,
282
- docsUrl,
283
- } = await publishDocsFn({
284
- sidebarPath,
285
- accessToken,
286
- appUrl,
287
- boardId,
288
- autoCreateBoard: true,
289
- // Pass additional project information if available
290
- boardName: projectInfo.name,
291
- boardDesc: projectInfo.description,
292
- boardCover: projectInfo.icon,
293
- });
180
+ // Save values to config.yaml if publish was successful
181
+ if (success) {
182
+ // Save appUrl to config only when not using environment variable
183
+ if (!useEnvAppUrl) {
184
+ await saveValueToConfig("appUrl", appUrl);
185
+ }
294
186
 
295
- // Save values to config.yaml if publish was successful
296
- if (success) {
297
- // Save appUrl to config only when not using environment variable
298
- if (!useEnvAppUrl) {
299
- await saveValueToConfig("appUrl", appUrl);
187
+ // Save boardId to config if it was auto-created
188
+ if (boardId !== newBoardId) {
189
+ await saveValueToConfig(
190
+ "boardId",
191
+ newBoardId,
192
+ "āš ļø Warning: boardId is auto-generated by system, please do not edit manually"
193
+ );
194
+ }
300
195
  }
301
196
 
302
- // Save boardId to config if it was auto-created
303
- if (boardId !== newBoardId) {
304
- await saveValueToConfig("boardId", newBoardId);
305
- }
197
+ const message = `āœ… Documentation Published Successfully!`;
198
+ return {
199
+ message,
200
+ };
201
+ } catch (error) {
202
+ return {
203
+ message: `āŒ Failed to publish docs: ${error.message}`,
204
+ };
306
205
  }
307
-
308
- // const message = `## āœ… Documentation Published Successfully!
309
-
310
- // Documentation is now available at: \`${docsUrl}\`
311
- // `;
312
- return {
313
- // message,
314
- };
315
206
  }
316
207
 
317
208
  publishDocs.input_schema = {
@@ -0,0 +1,74 @@
1
+ type: team
2
+ name: retranslate
3
+ alias:
4
+ - rt
5
+ - translate-again
6
+ description: Re-translate individual document content to selected languages
7
+ skills:
8
+ - url: ./input-generator.mjs
9
+ default_input:
10
+ skipIfExists: true
11
+ - ./load-config.mjs
12
+ - ./load-sources.mjs
13
+ - type: transform
14
+ jsonata: |
15
+ $merge([
16
+ $,
17
+ {
18
+ 'structurePlan': originalStructurePlan,
19
+ 'structurePlanResult': $map(originalStructurePlan, function($item) {
20
+ $merge([
21
+ $item,
22
+ {
23
+ 'translates': [$map(translateLanguages, function($lang) { {"language": $lang} })]
24
+ }
25
+ ])
26
+ })
27
+ }
28
+ ])
29
+ - url: ./find-item-by-path.mjs
30
+ default_input:
31
+ isTranslate: true
32
+ - ./language-selector.mjs
33
+ - type: transform
34
+ jsonata: |
35
+ $merge([
36
+ $,
37
+ {
38
+ 'translates': [$map(selectedLanguages, function($lang) { {"language": $lang} })]
39
+ }
40
+ ])
41
+ - ./batch-translate.yaml
42
+ - url: ./save-single-doc.mjs
43
+ default_input:
44
+ isTranslate: true
45
+ isShowMessage: true
46
+ input_schema:
47
+ type: object
48
+ properties:
49
+ glossary:
50
+ type: string
51
+ description: Glossary of terms for consistent terminology
52
+ doc-path:
53
+ type: string
54
+ description: Document path to retranslate
55
+ # languages:
56
+ # type: array
57
+ # items:
58
+ # type: string
59
+ # description: Languages to translate to
60
+ feedback:
61
+ type: string
62
+ description: Feedback for translation improvement
63
+ output_schema:
64
+ type: object
65
+ properties:
66
+ title:
67
+ type: string
68
+ description:
69
+ type: string
70
+ path:
71
+ type: string
72
+ content:
73
+ type: string
74
+ mode: sequential