@aigne/doc-smith 0.8.12-beta.9 → 0.8.13-beta

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.
@@ -21,14 +21,13 @@ import {
21
21
  validatePath,
22
22
  } from "../../utils/utils.mjs";
23
23
 
24
- // UI constants
25
24
  const _PRESS_ENTER_TO_FINISH = "Press Enter to finish";
26
25
 
27
26
  /**
28
- * Guide users through multi-turn dialogue to collect information and generate YAML configuration
27
+ * Guides the user through a multi-turn dialog to generate a YAML configuration file.
29
28
  * @param {Object} params
30
- * @param {string} params.outputPath - Output file path
31
- * @param {string} params.fileName - File name
29
+ * @param {string} params.outputPath - The path to the output file.
30
+ * @param {string} params.fileName - The name of the file.
32
31
  * @returns {Promise<Object>}
33
32
  */
34
33
  export default async function init(
@@ -47,7 +46,7 @@ export default async function init(
47
46
  const configContent = await readFile(filePath, "utf8").catch(() => null);
48
47
 
49
48
  if (!configContent || configContent.trim() === "") {
50
- console.log(`⚠️ No configuration found.`);
49
+ console.log("⚠️ No configuration file found.");
51
50
  console.log(
52
51
  `🚀 Run ${chalk.cyan("aigne doc init")} to set up your documentation configuration.`,
53
52
  );
@@ -71,14 +70,12 @@ export default async function init(
71
70
  console.log("🚀 Welcome to AIGNE DocSmith!");
72
71
  console.log("Let's set up your documentation preferences.\n");
73
72
 
74
- // Collect user information
75
73
  const input = {};
76
74
 
77
- // 1. Primary purpose - what's the main outcome you want readers to achieve?
78
75
  const purposeChoices = await options.prompts.checkbox({
79
76
  message: "📝 [1/9]: What should your documentation help readers achieve?",
80
77
  choices: Object.entries(DOCUMENT_STYLES)
81
- .filter(([key]) => key !== "custom") // Remove custom option for multiselect
78
+ .filter(([key]) => key !== "custom")
82
79
  .map(([key, style]) => ({
83
80
  name: `${style.name}`,
84
81
  description: style.description,
@@ -86,19 +83,18 @@ export default async function init(
86
83
  })),
87
84
  validate: (input) => {
88
85
  if (input.length === 0) {
89
- return "Please choose at least one goal for your documentation.";
86
+ return "You must choose at least one goal for your documentation.";
90
87
  }
91
88
  return true;
92
89
  },
93
90
  });
94
91
 
95
- // Follow-up logic: If ONLY mixedPurpose selected, ask for priority ranking
96
92
  let prioritizedPurposes = purposeChoices;
97
93
  if (purposeChoices.length === 1 && purposeChoices.includes("mixedPurpose")) {
98
94
  const topPriorities = await options.prompts.checkbox({
99
- message: "🎯 Which is most important? (Select top 2 priorities)",
95
+ message: "🎯 Which is most important? (Select up to 2 priorities)",
100
96
  choices: Object.entries(DOCUMENT_STYLES)
101
- .filter(([key]) => key !== "custom" && key !== "mixedPurpose") // Filter out custom and mixedPurpose
97
+ .filter(([key]) => key !== "custom" && key !== "mixedPurpose")
102
98
  .map(([key, style]) => ({
103
99
  name: `${style.name}`,
104
100
  description: style.description,
@@ -106,27 +102,24 @@ export default async function init(
106
102
  })),
107
103
  validate: (input) => {
108
104
  if (input.length === 0) {
109
- return "Please choose at least one priority.";
105
+ return "You must choose at least one priority.";
110
106
  }
111
107
  if (input.length > 2) {
112
- return "Please choose maximum 2 priorities.";
108
+ return "You may only choose up to 2 priorities.";
113
109
  }
114
110
  return true;
115
111
  },
116
112
  });
117
113
 
118
- // Replace mixedPurpose with selected priorities
119
114
  prioritizedPurposes = topPriorities;
120
115
  }
121
116
 
122
- // Save document purpose choices as keys
123
117
  input.documentPurpose = prioritizedPurposes;
124
118
 
125
- // 2. Target audience - who will be reading this most often?
126
119
  const audienceChoices = await options.prompts.checkbox({
127
120
  message: "👥 [2/9]: Who will be reading your documentation?",
128
121
  choices: Object.entries(TARGET_AUDIENCES)
129
- .filter(([key]) => key !== "custom") // Remove custom option for multiselect
122
+ .filter(([key]) => key !== "custom")
130
123
  .map(([key, audience]) => ({
131
124
  name: `${audience.name}`,
132
125
  description: audience.description,
@@ -134,23 +127,19 @@ export default async function init(
134
127
  })),
135
128
  validate: (input) => {
136
129
  if (input.length === 0) {
137
- return "Please choose at least one audience.";
130
+ return "You must choose at least one audience.";
138
131
  }
139
132
  return true;
140
133
  },
141
134
  });
142
135
 
143
- // Save target audience choices as keys
144
136
  input.targetAudienceTypes = audienceChoices;
145
137
 
146
- // 3. Reader knowledge level - what do readers typically know when they arrive?
147
- // Determine default based on selected purposes using mapping
148
138
  const mappedPurpose = prioritizedPurposes.find(
149
139
  (purpose) => PURPOSE_TO_KNOWLEDGE_MAPPING[purpose],
150
140
  );
151
141
  const defaultKnowledge = mappedPurpose ? PURPOSE_TO_KNOWLEDGE_MAPPING[mappedPurpose] : null;
152
142
 
153
- // Filter knowledge level options based on previous selections
154
143
  const { filteredOptions: filteredKnowledgeOptions } = getFilteredOptions(
155
144
  "readerKnowledgeLevel",
156
145
  { documentPurpose: prioritizedPurposes, targetAudienceTypes: audienceChoices },
@@ -158,7 +147,7 @@ export default async function init(
158
147
  );
159
148
 
160
149
  const knowledgeChoice = await options.prompts.select({
161
- message: "🧠 [3/9]: How much do readers already know about your project?",
150
+ message: "🧠 [3/9]: How much do your readers already know about your project?",
162
151
  choices: Object.entries(filteredKnowledgeOptions).map(([key, level]) => ({
163
152
  name: `${level.name}`,
164
153
  description: level.description,
@@ -221,7 +210,7 @@ export default async function init(
221
210
 
222
211
  // Let user select primary language from supported list
223
212
  const primaryLanguageChoice = await options.prompts.select({
224
- message: "🌐 [5/9]: What's your main documentation language?",
213
+ message: "🌐 [5/9]: What is the main language of your documentation?",
225
214
  choices: SUPPORTED_LANGUAGES.map((lang) => ({
226
215
  name: `${lang.label} - ${lang.sample}`,
227
216
  value: lang.code,
@@ -238,7 +227,7 @@ export default async function init(
238
227
  );
239
228
 
240
229
  const translateLanguageChoices = await options.prompts.checkbox({
241
- message: "🔄 [6/9]: Which languages should we translate to?",
230
+ message: "🔄 [6/9]: What languages should we translate to?",
242
231
  choices: availableTranslationLanguages.map((lang) => ({
243
232
  name: `${lang.label} - ${lang.sample}`,
244
233
  value: lang.code,
@@ -257,15 +246,17 @@ export default async function init(
257
246
  // 8. Content sources
258
247
  console.log("\n🔍 [8/9]: Content Sources");
259
248
  console.log(
260
- "What folders/files should we analyze for documentation? (e.g., ./src, ./docs, ./README.md)",
249
+ "Please specify the folders and files we should analyze to generate your documentation (e.g., ./src, ./docs, ./README.md).",
261
250
  );
262
- console.log("💡 Advanced: Use patterns like src/**/*.js or docs/**/*.md for specific files");
263
- console.log("💡 Leave empty to scan everything");
251
+ console.log(
252
+ "💡 You can also use glob patterns like src/**/*.js or docs/**/*.md for more specific file matching.",
253
+ );
254
+ console.log("💡 If you leave this empty, we will scan the entire directory.");
264
255
 
265
256
  const sourcePaths = [];
266
257
  while (true) {
267
258
  const selectedPath = await options.prompts.search({
268
- message: "File/folder path or pattern:",
259
+ message: "Please enter a file or folder path, or a glob pattern:",
269
260
  source: async (input) => {
270
261
  if (!input || input.trim() === "") {
271
262
  return [
@@ -292,7 +283,7 @@ export default async function init(
292
283
  options.push({
293
284
  name: searchTerm,
294
285
  value: searchTerm,
295
- description: "This input will be used as a glob pattern for file matching",
286
+ description: "Use this glob pattern for file matching.",
296
287
  });
297
288
  }
298
289
 
@@ -342,7 +333,7 @@ export default async function init(
342
333
  // 9. Custom rules - any specific requirements for the documentation?
343
334
  const rulesInput = await options.prompts.input({
344
335
  message:
345
- "📋 [9/9]: Any custom rules or requirements for your documentation? (Optional, press Enter to skip)",
336
+ "📋 [9/9]: Do you have any custom rules or requirements for your documentation? (Optional, press Enter to skip)",
346
337
  default: "",
347
338
  });
348
339
  input.rules = rulesInput.trim();
@@ -365,22 +356,24 @@ export default async function init(
365
356
  await mkdir(dirPath, { recursive: true });
366
357
 
367
358
  await writeFile(filePath, yamlContent, "utf8");
368
- console.log(`\n✅ Setup complete! Configuration saved to: ${chalk.cyan(filePath)}`);
369
- // Print YAML content for user review
359
+ console.log(
360
+ `\n✅ Setup complete! Your configuration has been saved to: ${chalk.cyan(filePath)}`,
361
+ );
370
362
  console.log(chalk.cyan("---"));
371
363
  console.log(chalk.cyan(yamlContent));
372
364
  console.log(chalk.cyan("---"));
373
- console.log("💡 You can edit the configuration file anytime to modify settings.\n");
374
- console.log(`🚀 Ready to generate docs? Run: ${chalk.cyan("aigne doc generate")}\n`);
365
+ console.log("💡 You can edit this file at any time to change your settings.\n");
366
+ console.log(`🚀 To generate your documentation, run: ${chalk.cyan("aigne doc generate")}\n`);
375
367
 
376
- // load config from file
377
368
  if (skipIfExists) {
378
369
  return loadConfig({ config: filePath, appUrl });
379
370
  }
380
371
 
381
372
  return {};
382
373
  } catch (error) {
383
- console.error(`❌ Failed to save configuration file: ${error.message}`);
374
+ console.error(
375
+ `❌ Sorry, I encountered an error while saving your configuration file: ${error.message}`,
376
+ );
384
377
  return {
385
378
  inputGeneratorStatus: false,
386
379
  inputGeneratorError: error.message,
@@ -502,14 +495,15 @@ export function generateYAML(input) {
502
495
  yaml += `${rulesSection.replace(/rules: ''/, "rules: |\n ")}\n\n`;
503
496
 
504
497
  // Target Audience Description
505
- yaml += "# Target Audience: Describe your specific target audience and their characteristics\n";
498
+ yaml += "# Target Audience: Describe your specific target audience and their characteristics.\n";
506
499
  const targetAudienceSection = yamlStringify({ targetAudience: config.targetAudience }).trim();
507
500
  // Use literal style for multiline strings
508
501
  yaml += `${targetAudienceSection.replace(/targetAudience: ''/, "targetAudience: |\n ")}\n\n`;
509
502
 
510
503
  // Glossary Configuration
511
- yaml += "# Glossary: Define project-specific terms and definitions\n";
512
- yaml += '# glossary: "@glossary.md" # Path to markdown file containing glossary definitions\n\n';
504
+ yaml += "# Glossary: Define project-specific terms and definitions.\n";
505
+ yaml +=
506
+ '# glossary: "@glossary.md" # Path to a markdown file containing glossary definitions.\n\n';
513
507
 
514
508
  // Language settings - safely serialize
515
509
  const localeSection = yamlStringify({ locale: config.locale }).trim();
@@ -522,25 +516,25 @@ export function generateYAML(input) {
522
516
  }).trim();
523
517
  yaml += `${translateLanguagesSection.replace(/^translateLanguages:/, "translateLanguages:")}\n`;
524
518
  } else {
525
- yaml += "# translateLanguages: # List of languages to translate the documentation to\n";
519
+ yaml += "# translateLanguages: # A list of languages to translate the documentation to.\n";
526
520
  yaml += "# - zh # Example: Chinese translation\n";
527
521
  yaml += "# - en # Example: English translation\n";
528
522
  }
529
523
 
530
524
  // Directory and source path configurations - safely serialize
531
525
  const docsDirSection = yamlStringify({ docsDir: config.docsDir }).trim();
532
- yaml += `${docsDirSection.replace(/^docsDir:/, "docsDir:")} # Directory to save generated documentation\n`;
526
+ yaml += `${docsDirSection.replace(/^docsDir:/, "docsDir:")} # The directory where the generated documentation will be saved.\n`;
533
527
 
534
528
  const sourcesPathSection = yamlStringify({ sourcesPath: config.sourcesPath }).trim();
535
- yaml += `${sourcesPathSection.replace(/^sourcesPath:/, "sourcesPath: # Source code paths to analyze")}\n`;
529
+ yaml += `${sourcesPathSection.replace(/^sourcesPath:/, "sourcesPath: # The source code paths to analyze.")}\n`;
536
530
 
537
531
  // Image filtering settings
538
532
  const mediaInfoSection = yamlStringify({
539
533
  media: config.media,
540
534
  }).trim();
541
- yaml += `# minImageWidth: Only images wider than this value (in pixels) will be used in page generation\n${mediaInfoSection}\n`;
535
+ yaml += `# minImageWidth: Only images wider than this value (in pixels) will be used in the page generation.\n${mediaInfoSection}\n`;
542
536
 
543
537
  return yaml;
544
538
  }
545
539
 
546
- init.description = "Generate a configuration file for the documentation generation process";
540
+ init.description = "Create a configuration file for the documentation generation process.";
@@ -9,6 +9,7 @@ skills:
9
9
  default_input:
10
10
  skipIfExists: true
11
11
  checkOnly: true
12
+ - url: ../init/check.mjs
12
13
  - translate-meta.mjs
13
14
  - publish-docs.mjs
14
15
  input_schema:
@@ -1,12 +1,10 @@
1
- import { basename, extname, join, relative } from "node:path";
2
- import slugify from "slugify";
1
+ import { basename, extname, join } from "node:path";
3
2
  import { publishDocs as publishDocsFn } from "@aigne/publish-docs";
4
3
  import { BrokerClient } from "@blocklet/payment-broker-client/node";
5
4
  import chalk from "chalk";
6
5
  import fs from "fs-extra";
6
+ import slugify from "slugify";
7
7
 
8
- import { getExtnameFromContentType } from "../../utils/file-utils.mjs";
9
- import { isHttp } from "../../utils/utils.mjs";
10
8
  import { getAccessToken, getOfficialAccessToken } from "../../utils/auth-utils.mjs";
11
9
  import {
12
10
  CLOUD_SERVICE_URL_PROD,
@@ -17,7 +15,14 @@ import {
17
15
  } from "../../utils/constants/index.mjs";
18
16
  import { beforePublishHook, ensureTmpDir } from "../../utils/d2-utils.mjs";
19
17
  import { deploy } from "../../utils/deploy.mjs";
20
- import { getGithubRepoUrl, loadConfigFromFile, saveValueToConfig } from "../../utils/utils.mjs";
18
+ import { getExtnameFromContentType } from "../../utils/file-utils.mjs";
19
+ import { uploadFiles } from "../../utils/upload-files.mjs";
20
+ import {
21
+ getGithubRepoUrl,
22
+ isHttp,
23
+ loadConfigFromFile,
24
+ saveValueToConfig,
25
+ } from "../../utils/utils.mjs";
21
26
  import updateBranding from "../utils/update-branding.mjs";
22
27
 
23
28
  const BASE_URL = process.env.DOC_SMITH_BASE_URL || CLOUD_SERVICE_URL_PROD;
@@ -86,16 +91,8 @@ export default async function publishDocs(
86
91
  }
87
92
 
88
93
  const choice = await options.prompts.select({
89
- message: "Select platform to publish your documents:",
94
+ message: "Please select a platform to publish your documents:",
90
95
  choices: [
91
- {
92
- 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.`,
93
- value: "default",
94
- },
95
- {
96
- name: `${chalk.blue("Your existing website")} - Integrate and publish directly on your current site (setup required)`,
97
- value: "custom",
98
- },
99
96
  ...(sessionId
100
97
  ? [
101
98
  {
@@ -104,6 +101,14 @@ export default async function publishDocs(
104
101
  },
105
102
  ]
106
103
  : []),
104
+ {
105
+ 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.`,
106
+ value: "default",
107
+ },
108
+ {
109
+ name: `${chalk.blue("Your existing website")} - Integrate and publish directly on your current site (setup required)`,
110
+ value: "custom",
111
+ },
107
112
  {
108
113
  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.`,
109
114
  value: "new-instance",
@@ -117,7 +122,7 @@ export default async function publishDocs(
117
122
  `Start here to run your own website:\n${chalk.cyan(DISCUSS_KIT_STORE_URL)}\n`,
118
123
  );
119
124
  const userInput = await options.prompts.input({
120
- message: "Please enter your website URL:",
125
+ message: "Please enter the URL of your website:",
121
126
  validate: (input) => {
122
127
  try {
123
128
  // Check if input contains protocol, if not, prepend https://
@@ -146,7 +151,7 @@ export default async function publishDocs(
146
151
  paymentUrl = paymentLink;
147
152
  console.log(`\nResuming your previous website setup...`);
148
153
  } else {
149
- console.log(`\nCreating new website for your documentation...`);
154
+ console.log(`\nCreating a new website for your documentation...`);
150
155
  }
151
156
  const { appUrl: homeUrl, token: ltToken } = (await deploy(id, paymentUrl)) || {};
152
157
 
@@ -155,7 +160,7 @@ export default async function publishDocs(
155
160
  }
156
161
  }
157
162
 
158
- console.log(`\nPublishing docs to ${chalk.cyan(appUrl)}\n`);
163
+ console.log(`\nPublishing your documentation to ${chalk.cyan(appUrl)}\n`);
159
164
 
160
165
  const accessToken = await getAccessToken(appUrl, token);
161
166
 
@@ -192,8 +197,16 @@ export default async function publishDocs(
192
197
  const finalPath = ext ? `${tempFilePath}.${ext}` : tempFilePath;
193
198
  fs.writeFileSync(finalPath, buffer);
194
199
 
195
- // Update to relative path
196
- projectInfo.icon = relative(join(process.cwd(), DOC_SMITH_DIR), finalPath);
200
+ const filePath = join(process.cwd(), finalPath);
201
+ const { results: uploadResults } = await uploadFiles({
202
+ appUrl,
203
+ filePaths: [filePath],
204
+ accessToken,
205
+ concurrency: 1,
206
+ });
207
+
208
+ // FIXME: 暂时保持使用绝对路径,需要修改为相对路径 @pengfei
209
+ projectInfo.icon = uploadResults?.[0]?.url || projectInfo.icon;
197
210
  }
198
211
  } catch (error) {
199
212
  console.warn(`Failed to download project logo from ${projectInfo.icon}: ${error.message}`);
@@ -253,21 +266,21 @@ export default async function publishDocs(
253
266
  } else {
254
267
  // If the error is 401 or 403, it means the access token is invalid
255
268
  if (error?.includes("401") || error?.includes("403")) {
256
- message = `❌ Publishing failed: you don't have valid authorization.\n Run ${chalk.cyan("aigne doc clear")} to reset it, then publish again.`;
269
+ message = `❌ Publishing failed due to an authorization error. Please run ${chalk.cyan("aigne doc clear")} to reset your credentials and try again.`;
257
270
  }
258
271
  }
259
272
 
260
273
  // clean up tmp work dir
261
274
  await fs.rm(docsDir, { recursive: true, force: true });
262
275
  } catch (error) {
263
- message = `❌ Failed to publish docs: ${error.message}`;
276
+ message = `❌ Sorry, I encountered an error while publishing your documentation: ${error.message}`;
264
277
 
265
278
  // clean up tmp work dir in case of error
266
279
  try {
267
280
  const docsDir = join(DOC_SMITH_DIR, TMP_DIR, TMP_DOCS_DIR);
268
281
  await fs.rm(docsDir, { recursive: true, force: true });
269
282
  } catch {
270
- // ignore cleanup errors
283
+ // Ignore cleanup errors
271
284
  }
272
285
  }
273
286
 
@@ -279,34 +292,34 @@ publishDocs.input_schema = {
279
292
  properties: {
280
293
  docsDir: {
281
294
  type: "string",
282
- description: "The directory of the docs",
295
+ description: "The directory of the documentation.",
283
296
  },
284
297
  appUrl: {
285
298
  type: "string",
286
- description: "The url of the app",
299
+ description: "The URL of the app.",
287
300
  default: CLOUD_SERVICE_URL_PROD,
288
301
  },
289
302
  boardId: {
290
303
  type: "string",
291
- description: "The id of the board",
304
+ description: "The ID of the board.",
292
305
  },
293
306
  "with-branding": {
294
307
  type: "boolean",
295
- description: "Update your website branding (title, description, logo)",
308
+ description: "Update the website branding (title, description, and logo).",
296
309
  },
297
310
  projectName: {
298
311
  type: "string",
299
- description: "The name of the project",
312
+ description: "The name of the project.",
300
313
  },
301
314
  projectDesc: {
302
315
  type: "string",
303
- description: "The description of the project",
316
+ description: "A description of the project.",
304
317
  },
305
318
  projectLogo: {
306
319
  type: "string",
307
- description: "The logo/icon of the project",
320
+ description: "The logo or icon of the project.",
308
321
  },
309
322
  },
310
323
  };
311
324
 
312
- publishDocs.description = "Publish the documentation to website";
325
+ publishDocs.description = "Publish the documentation to a website";
@@ -2,12 +2,12 @@ import { SUPPORTED_LANGUAGES } from "../../utils/constants/index.mjs";
2
2
  import { loadConfigFromFile, saveValueToConfig } from "../../utils/utils.mjs";
3
3
 
4
4
  /**
5
- * Interactive language selector for translation from configured languages
5
+ * Interactively selects languages for translation.
6
6
  * @param {Object} params
7
- * @param {Array<string>} [params.langs] - Pre-selected languages
8
- * @param {string} params.locale - Primary language code
9
- * @param {Object} options - Options object with prompts
10
- * @returns {Promise<Object>} Selected languages
7
+ * @param {Array<string>} [params.langs] - Pre-selected languages.
8
+ * @param {string} params.locale - The primary language code.
9
+ * @param {Object} options - Options object with prompts.
10
+ * @returns {Promise<Object>} The selected languages.
11
11
  */
12
12
  export default async function chooseLanguage({ langs, locale, selectedDocs }, options) {
13
13
  let selectedLanguages = [];
@@ -24,7 +24,7 @@ export default async function chooseLanguage({ langs, locale, selectedDocs }, op
24
24
  (lang) => lang.code !== primaryLanguage,
25
25
  );
26
26
 
27
- // If languages are provided as parameter, validate against available languages
27
+ // If languages are provided as a parameter, validate them
28
28
  if (langs && Array.isArray(langs) && langs.length > 0) {
29
29
  const validLanguages = langs.filter((lang) =>
30
30
  availableTranslationLanguages.some((availableLang) => availableLang.code === lang),
@@ -35,8 +35,7 @@ export default async function chooseLanguage({ langs, locale, selectedDocs }, op
35
35
  } else {
36
36
  console.log(`⚠️ Invalid languages provided: ${langs.join(", ")}`);
37
37
  console.log(
38
- "Available translation languages:",
39
- availableTranslationLanguages.map((l) => l.code).join(", "),
38
+ `Available languages: ${availableTranslationLanguages.map((l) => l.code).join(", ")}`,
40
39
  );
41
40
  }
42
41
  }
@@ -51,11 +50,11 @@ export default async function chooseLanguage({ langs, locale, selectedDocs }, op
51
50
  }));
52
51
 
53
52
  selectedLanguages = await options.prompts.checkbox({
54
- message: "Select translation languages:",
53
+ message: "Please select the languages you'd like to translate to:",
55
54
  choices: choices,
56
55
  validate: (answer) => {
57
56
  if (answer.length === 0) {
58
- return "Please select at least one language";
57
+ return "You must select at least one language.";
59
58
  }
60
59
  return true;
61
60
  },
@@ -63,7 +62,7 @@ export default async function chooseLanguage({ langs, locale, selectedDocs }, op
63
62
  }
64
63
 
65
64
  if (selectedLanguages.length === 0) {
66
- throw new Error("No languages selected for translation");
65
+ throw new Error("You must select at least one language to continue.");
67
66
  }
68
67
 
69
68
  // Find new languages that need to be added
@@ -98,12 +97,13 @@ chooseLanguage.input_schema = {
98
97
  items: {
99
98
  type: "string",
100
99
  },
101
- description: "Pre-selected languages for translation",
100
+ description: "A list of pre-selected languages for translation.",
102
101
  },
103
102
 
104
103
  locale: {
105
104
  type: "string",
106
- description: "Primary language code (will be excluded from translation options)",
105
+ description:
106
+ "The primary language code, which will be excluded from the translation options.",
107
107
  },
108
108
  },
109
109
  required: [],
@@ -7,6 +7,7 @@ skills:
7
7
  skipIfExists: true
8
8
  checkOnly: true
9
9
  - ../utils/load-sources.mjs
10
+ - url: ../init/check.mjs
10
11
  - type: transform
11
12
  task_render_mode: hide
12
13
  jsonata: |
@@ -1,10 +1,10 @@
1
1
  export default async function checkUpdateIsSingle({ selectedDocs, ...rest }, options) {
2
2
  if (!selectedDocs || !Array.isArray(selectedDocs)) {
3
- throw new Error("selectedDocs must be provided as an array");
3
+ throw new Error("A list of documents to update must be provided.");
4
4
  }
5
5
 
6
6
  if (selectedDocs.length === 0) {
7
- throw new Error("selectedDocs cannot be empty");
7
+ throw new Error("You must select at least one document to update.");
8
8
  }
9
9
 
10
10
  let targetAgent;
@@ -20,7 +20,7 @@ export default async function checkUpdateIsSingle({ selectedDocs, ...rest }, opt
20
20
  }
21
21
 
22
22
  if (!targetAgent) {
23
- throw new Error(`Agent "${agentName}" is not available`);
23
+ throw new Error(`Sorry, I can't seem to find the "${agentName}" agent.`);
24
24
  }
25
25
 
26
26
  try {
@@ -31,7 +31,10 @@ export default async function checkUpdateIsSingle({ selectedDocs, ...rest }, opt
31
31
 
32
32
  return result;
33
33
  } catch (error) {
34
- console.error(`Error invoking ${agentName}:`, error.message);
34
+ console.error(
35
+ `Sorry, I encountered an error while trying to run the ${agentName} agent:`,
36
+ error.message,
37
+ );
35
38
  throw error;
36
39
  }
37
40
  }
@@ -8,6 +8,7 @@ skills:
8
8
  default_input:
9
9
  skipIfExists: true
10
10
  checkOnly: true
11
+ - url: ../init/check.mjs
11
12
  - ../utils/load-sources.mjs
12
13
  - type: transform
13
14
  task_render_mode: hide
@@ -1,3 +1,4 @@
1
+ import chalk from "chalk";
1
2
  import {
2
3
  addFeedbackToItems,
3
4
  findItemByPath,
@@ -35,7 +36,7 @@ export default async function chooseDocs(
35
36
 
36
37
  if (mainLanguageFiles.length === 0) {
37
38
  throw new Error(
38
- "No documents found in the docs directory. Please run `aigne docs generate` to generate the documents",
39
+ `No documents found in the docs directory. Please run ${chalk.yellow("`aigne doc generate`")} to generate the documents`,
39
40
  );
40
41
  }
41
42
 
@@ -80,9 +81,10 @@ export default async function chooseDocs(
80
81
  // Process selected files and convert to found items
81
82
  foundItems = await processSelectedFiles(selectedFiles, documentExecutionStructure, docsDir);
82
83
  } catch (error) {
83
- throw new Error(
84
+ console.log(
84
85
  getActionText(isTranslate, `\nFailed to select documents to {action}: ${error.message}`),
85
86
  );
87
+ process.exit(0);
86
88
  }
87
89
  } else {
88
90
  // Process the provided docs array
@@ -17,12 +17,13 @@ export default async function updateBranding({ appUrl, projectInfo, accessToken
17
17
  try {
18
18
  const origin = new URL(appUrl).origin;
19
19
  if ([CLOUD_SERVICE_URL_PROD, CLOUD_SERVICE_URL_STAGING].includes(origin)) {
20
- console.log("Skipped updating branding for official service\n");
20
+ console.log("ℹ️ Skipped updating branding for official service\n");
21
21
  return;
22
22
  }
23
23
 
24
24
  console.log(`🔄 Updating branding for ${chalk.cyan(origin)}`);
25
25
 
26
+ // Get component information and mount point
26
27
  const componentInfo = await getComponentInfoWithMountPoint(origin, DISCUSS_KIT_DID);
27
28
  const mountPoint = componentInfo.mountPoint || "/";
28
29
 
@@ -56,7 +57,7 @@ export default async function updateBranding({ appUrl, projectInfo, accessToken
56
57
  endpoint: `${origin}/.well-known/service/blocklet/logo/upload/square/${componentInfo.did}`,
57
58
  });
58
59
  }
59
- console.log("✅ Updated branding successfully!\n");
60
+ console.log("✅ Branding has been successfully updated\n");
60
61
  } catch (error) {
61
62
  console.warn(`⚠️ Just failed to update logo: ${error.message}\n`);
62
63
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/doc-smith",
3
- "version": "0.8.12-beta.9",
3
+ "version": "0.8.13-beta",
4
4
  "description": "AI-driven documentation generation tool built on the AIGNE Framework",
5
5
  "publishConfig": {
6
6
  "access": "public"