@aigne/doc-smith 0.2.6 → 0.2.9

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.
@@ -1,13 +1,12 @@
1
- import { join } from "node:path";
2
- import { joinURL } from "ufo";
3
- import open from "open";
4
- import { publishDocs as publishDocsFn } from "@aigne/publish-docs";
5
- import { createConnect } from "@aigne/cli/utils/load-aigne.js";
6
1
  import { existsSync, mkdirSync } from "node:fs";
7
2
  import { readFile, writeFile } from "node:fs/promises";
8
3
  import { homedir } from "node:os";
4
+ import { basename, join } from "node:path";
5
+ import { createConnect } from "@aigne/aigne-hub";
6
+ import { publishDocs as publishDocsFn } from "@aigne/publish-docs";
7
+ import open from "open";
8
+ import { joinURL } from "ufo";
9
9
  import { parse, stringify } from "yaml";
10
- import { basename } from "node:path";
11
10
  import { loadConfigFromFile, saveValueToConfig } from "../utils/utils.mjs";
12
11
 
13
12
  const WELLKNOWN_SERVICE_PATH_PREFIX = "/.well-known/service";
@@ -19,11 +18,7 @@ const DEFAULT_APP_URL = "https://docsmith.aigne.io";
19
18
  * @returns {Promise<string>} - The access token
20
19
  */
21
20
  async function getAccessToken(appUrl) {
22
- const DOC_SMITH_ENV_FILE = join(
23
- homedir(),
24
- ".aigne",
25
- "doc-smith-connected.yaml"
26
- );
21
+ const DOC_SMITH_ENV_FILE = join(homedir(), ".aigne", "doc-smith-connected.yaml");
27
22
  const { hostname } = new URL(appUrl);
28
23
 
29
24
  let accessToken = process.env.DOC_DISCUSS_KIT_ACCESS_TOKEN;
@@ -35,7 +30,7 @@ async function getAccessToken(appUrl) {
35
30
  const data = await readFile(DOC_SMITH_ENV_FILE, "utf8");
36
31
  if (data.includes("DOC_DISCUSS_KIT_ACCESS_TOKEN")) {
37
32
  const envs = parse(data);
38
- if (envs[hostname] && envs[hostname].DOC_DISCUSS_KIT_ACCESS_TOKEN) {
33
+ if (envs[hostname]?.DOC_DISCUSS_KIT_ACCESS_TOKEN) {
39
34
  accessToken = envs[hostname].DOC_DISCUSS_KIT_ACCESS_TOKEN;
40
35
  }
41
36
  }
@@ -48,10 +43,7 @@ async function getAccessToken(appUrl) {
48
43
  // If still no access token, prompt user to authorize
49
44
  if (!accessToken) {
50
45
  const DISCUSS_KIT_URL = appUrl;
51
- const connectUrl = joinURL(
52
- new URL(DISCUSS_KIT_URL).origin,
53
- WELLKNOWN_SERVICE_PATH_PREFIX
54
- );
46
+ const connectUrl = joinURL(new URL(DISCUSS_KIT_URL).origin, WELLKNOWN_SERVICE_PATH_PREFIX);
55
47
 
56
48
  try {
57
49
  const result = await createConnect({
@@ -60,8 +52,7 @@ async function getAccessToken(appUrl) {
60
52
  source: `AIGNE DocSmith connect to Discuss Kit`,
61
53
  closeOnSuccess: true,
62
54
  appName: "AIGNE DocSmith",
63
- appLogo:
64
- "https://www.aigne.io/image-bin/uploads/a7910a71364ee15a27e86f869ad59009.svg",
55
+ appLogo: "https://www.aigne.io/image-bin/uploads/a7910a71364ee15a27e86f869ad59009.svg",
65
56
  openPage: (pageUrl) => open(pageUrl),
66
57
  });
67
58
 
@@ -86,12 +77,12 @@ async function getAccessToken(appUrl) {
86
77
  DOC_DISCUSS_KIT_ACCESS_TOKEN: accessToken,
87
78
  DOC_DISCUSS_KIT_URL: DISCUSS_KIT_URL,
88
79
  },
89
- })
80
+ }),
90
81
  );
91
82
  } catch (error) {
92
83
  console.error("Failed to get access token:", error);
93
84
  throw new Error(
94
- "Failed to obtain access token. Please check your network connection and try again later."
85
+ "Failed to obtain access token. Please check your network connection and try again later.",
95
86
  );
96
87
  }
97
88
  }
@@ -101,7 +92,7 @@ async function getAccessToken(appUrl) {
101
92
 
102
93
  export default async function publishDocs(
103
94
  { docsDir, appUrl, boardId, projectName, projectDesc, projectLogo },
104
- options
95
+ options,
105
96
  ) {
106
97
  // Check if DOC_DISCUSS_KIT_URL is set in environment variables
107
98
  const envAppUrl = process.env.DOC_DISCUSS_KIT_URL;
@@ -115,7 +106,7 @@ export default async function publishDocs(
115
106
  // Check if appUrl is default and not saved in config (only when not using env variable)
116
107
  const config = await loadConfigFromFile();
117
108
  const isDefaultAppUrl = appUrl === DEFAULT_APP_URL;
118
- const hasAppUrlInConfig = config && config.appUrl;
109
+ const hasAppUrlInConfig = config?.appUrl;
119
110
 
120
111
  if (!useEnvAppUrl && isDefaultAppUrl && !hasAppUrlInConfig) {
121
112
  const choice = await options.prompts.select({
@@ -161,11 +152,7 @@ export default async function publishDocs(
161
152
  };
162
153
 
163
154
  try {
164
- const {
165
- success,
166
- boardId: newBoardId,
167
- docsUrl,
168
- } = await publishDocsFn({
155
+ const { success, boardId: newBoardId } = await publishDocsFn({
169
156
  sidebarPath,
170
157
  accessToken,
171
158
  appUrl,
@@ -189,7 +176,7 @@ export default async function publishDocs(
189
176
  await saveValueToConfig(
190
177
  "boardId",
191
178
  newBoardId,
192
- "⚠️ Warning: boardId is auto-generated by system, please do not edit manually"
179
+ "⚠️ Warning: boardId is auto-generated by system, please do not edit manually",
193
180
  );
194
181
  }
195
182
  }
@@ -1,7 +1,7 @@
1
- import { writeFile, readdir, unlink } from "node:fs/promises";
1
+ import { readdir, unlink, writeFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
- import { getCurrentGitHead, saveGitHeadToConfig } from "../utils/utils.mjs";
4
3
  import { shutdownMermaidWorkerPool } from "../utils/mermaid-worker-pool.mjs";
4
+ import { getCurrentGitHead, saveGitHeadToConfig } from "../utils/utils.mjs";
5
5
 
6
6
  /**
7
7
  * @param {Object} params
@@ -17,7 +17,7 @@ export default async function saveDocs({
17
17
  locale,
18
18
  projectInfoMessage,
19
19
  }) {
20
- const results = [];
20
+ const _results = [];
21
21
  // Save current git HEAD to config.yaml for change detection
22
22
  try {
23
23
  const gitHead = getCurrentGitHead();
@@ -37,12 +37,7 @@ export default async function saveDocs({
37
37
 
38
38
  // Clean up invalid .md files that are no longer in the structure plan
39
39
  try {
40
- await cleanupInvalidFiles(
41
- structurePlan,
42
- docsDir,
43
- translateLanguages,
44
- locale
45
- );
40
+ await cleanupInvalidFiles(structurePlan, docsDir, translateLanguages, locale);
46
41
  } catch (err) {
47
42
  console.error("Failed to cleanup invalid .md files:", err.message);
48
43
  }
@@ -112,12 +107,7 @@ function generateFileName(flatName, language) {
112
107
  * @param {string} locale - Main language locale (e.g., 'en', 'zh', 'fr')
113
108
  * @returns {Promise<Array<{ path: string, success: boolean, error?: string }>>}
114
109
  */
115
- async function cleanupInvalidFiles(
116
- structurePlan,
117
- docsDir,
118
- translateLanguages,
119
- locale
120
- ) {
110
+ async function cleanupInvalidFiles(structurePlan, docsDir, translateLanguages, locale) {
121
111
  const results = [];
122
112
 
123
113
  try {
@@ -145,7 +135,7 @@ async function cleanupInvalidFiles(
145
135
 
146
136
  // Find files to delete (files that are not in expectedFiles and not _sidebar.md)
147
137
  const filesToDelete = mdFiles.filter(
148
- (file) => !expectedFiles.has(file) && file !== "_sidebar.md"
138
+ (file) => !expectedFiles.has(file) && file !== "_sidebar.md",
149
139
  );
150
140
 
151
141
  // Delete invalid files
@@ -168,9 +158,7 @@ async function cleanupInvalidFiles(
168
158
  }
169
159
 
170
160
  if (filesToDelete.length > 0) {
171
- console.log(
172
- `Cleaned up ${filesToDelete.length} invalid .md files from ${docsDir}`
173
- );
161
+ console.log(`Cleaned up ${filesToDelete.length} invalid .md files from ${docsDir}`);
174
162
  }
175
163
  } catch (err) {
176
164
  // If docsDir doesn't exist or can't be read, that's okay
@@ -209,7 +197,7 @@ function generateSidebar(structurePlan) {
209
197
  for (const key of Object.keys(node)) {
210
198
  const item = node[key];
211
199
  const fullSegments = [...parentSegments, key];
212
- const flatFile = fullSegments.join("-") + ".md";
200
+ const flatFile = `${fullSegments.join("-")}.md`;
213
201
  if (item.__title) {
214
202
  const realIndent = item.__parentId === null ? "" : indent;
215
203
  out += `${realIndent}* [${item.__title}](/${flatFile})\n`;
@@ -1,12 +1,7 @@
1
1
  import { promises as fs } from "node:fs";
2
2
  import { join } from "node:path";
3
3
 
4
- export default async function saveOutput({
5
- savePath,
6
- fileName,
7
- saveKey,
8
- ...rest
9
- }) {
4
+ export default async function saveOutput({ savePath, fileName, saveKey, ...rest }) {
10
5
  if (!(saveKey in rest)) {
11
6
  console.warn(`saveKey "${saveKey}" not found in input, skip saving.`);
12
7
  return {
@@ -17,9 +12,7 @@ export default async function saveOutput({
17
12
 
18
13
  const value = rest[saveKey];
19
14
  const content =
20
- typeof value === "object" && value !== null
21
- ? JSON.stringify(value, null, 2)
22
- : String(value);
15
+ typeof value === "object" && value !== null ? JSON.stringify(value, null, 2) : String(value);
23
16
  await fs.mkdir(savePath, { recursive: true });
24
17
  const filePath = join(savePath, fileName);
25
18
  await fs.writeFile(filePath, content, "utf8");
@@ -1,5 +1,5 @@
1
- import { saveDocWithTranslations } from "../utils/utils.mjs";
2
1
  import { shutdownMermaidWorkerPool } from "../utils/mermaid-worker-pool.mjs";
2
+ import { saveDocWithTranslations } from "../utils/utils.mjs";
3
3
 
4
4
  export default async function saveSingleDoc({
5
5
  path,
@@ -11,7 +11,7 @@ export default async function saveSingleDoc({
11
11
  isTranslate = false,
12
12
  isShowMessage = false,
13
13
  }) {
14
- const results = await saveDocWithTranslations({
14
+ const _results = await saveDocWithTranslations({
15
15
  path,
16
16
  content,
17
17
  docsDir,
@@ -8,7 +8,7 @@ items:
8
8
  type: string
9
9
  path:
10
10
  type: string
11
- description: 路径,以 RUL 的格式返回,不能为空, 必须以 / 开头,不需要包含语言层级,比如 /zh/about 直接返回 /about
11
+ description: 路径,以 RUL 的格式返回,不能为空, 不能包含空格等特殊字符, 必须以 / 开头,不需要包含语言层级,比如 /zh/about 直接返回 /about
12
12
  parentId:
13
13
  type:
14
14
  - string
@@ -1,15 +1,12 @@
1
1
  import { normalizePath, toRelativePath } from "../utils/utils.mjs";
2
2
 
3
- export default function transformDetailDatasources({
4
- sourceIds,
5
- datasourcesList,
6
- }) {
3
+ export default function transformDetailDatasources({ sourceIds, datasourcesList }) {
7
4
  // Build a map for fast lookup, with path normalization for compatibility
8
5
  const dsMap = Object.fromEntries(
9
6
  (datasourcesList || []).map((ds) => {
10
7
  const normalizedSourceId = normalizePath(ds.sourceId);
11
8
  return [normalizedSourceId, ds.content];
12
- })
9
+ }),
13
10
  );
14
11
 
15
12
  // Collect formatted contents in order, with path normalization
package/biome.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://biomejs.dev/schemas/2.1.2/schema.json",
2
+ "$schema": "https://biomejs.dev/schemas/2.1.4/schema.json",
3
3
  "vcs": {
4
4
  "enabled": true,
5
5
  "clientKind": "git",
@@ -23,11 +23,21 @@
23
23
  "noUnusedVariables": "error",
24
24
  "noUnusedImports": "error",
25
25
  "noUnusedFunctionParameters": "error",
26
- "noUnusedPrivateClassMembers": "error"
26
+ "noUnusedPrivateClassMembers": "error",
27
+ "noUndeclaredVariables": "error",
28
+ "noUnreachable": "error",
29
+ "noSelfAssign": "error"
27
30
  },
28
31
  "suspicious": {
29
32
  "noConfusingVoidType": "off",
30
- "noExplicitAny": "off"
33
+ "noExplicitAny": "off",
34
+ "noDoubleEquals": "error",
35
+ "noGlobalAssign": "error",
36
+ "noAssignInExpressions": "warn"
37
+ },
38
+ "style": {
39
+ "useNodejsImportProtocol": "error",
40
+ "useTemplate": "error"
31
41
  },
32
42
  "complexity": {
33
43
  "noForEach": "off",
@@ -5,7 +5,7 @@ const structureDir = path.join(
5
5
  process.cwd(),
6
6
  "./.aigne/doc-smith",
7
7
  "output",
8
- "structure-plan.json"
8
+ "structure-plan.json",
9
9
  );
10
10
 
11
11
  export default async function getDocsStructure() {
@@ -3,10 +3,7 @@ import path from "node:path";
3
3
 
4
4
  const docsDir = path.join(process.cwd(), "./.aigne/doc-smith", "docs");
5
5
 
6
- export default async function readDocContent({
7
- relevantDocPaths,
8
- docsDir: customDocsDir,
9
- }) {
6
+ export default async function readDocContent({ relevantDocPaths, docsDir: customDocsDir }) {
10
7
  const targetDocsDir = customDocsDir || docsDir;
11
8
  const docContents = [];
12
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/doc-smith",
3
- "version": "0.2.6",
3
+ "version": "0.2.9",
4
4
  "description": "",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -12,11 +12,12 @@
12
12
  "author": "Arcblock <blocklet@arcblock.io> https://github.com/blocklet",
13
13
  "license": "MIT",
14
14
  "dependencies": {
15
- "@aigne/anthropic": "^0.10.13",
16
- "@aigne/cli": "^1.33.1",
17
- "@aigne/core": "^1.48.0",
18
- "@aigne/gemini": "^0.8.17",
19
- "@aigne/openai": "^0.10.17",
15
+ "@aigne/aigne-hub": "^0.4.9",
16
+ "@aigne/anthropic": "^0.11.0",
17
+ "@aigne/cli": "^1.34.0",
18
+ "@aigne/core": "^1.49.0",
19
+ "@aigne/gemini": "^0.9.0",
20
+ "@aigne/openai": "^0.11.0",
20
21
  "@aigne/publish-docs": "^0.5.4",
21
22
  "chalk": "^5.5.0",
22
23
  "dompurify": "^3.2.6",
@@ -34,6 +35,9 @@
34
35
  "vfile": "^6.0.3",
35
36
  "yaml": "^2.8.0"
36
37
  },
38
+ "devDependencies": {
39
+ "@biomejs/biome": "^2.1.4"
40
+ },
37
41
  "scripts": {
38
42
  "test": "echo \"Error: no test specified\" && exit 1",
39
43
  "lint": "biome check && pnpm -r run lint",
@@ -23,28 +23,21 @@ async function runTests() {
23
23
  const content = "This contains a [dead link](/dead-link).";
24
24
  const result = await checkDetailResult({ structurePlan, content });
25
25
  assert(result.isApproved === false, "Should not be approved");
26
- assert(
27
- result.detailFeedback.includes("Found a dead link"),
28
- "Should report dead link"
29
- );
26
+ assert(result.detailFeedback.includes("Found a dead link"), "Should report dead link");
30
27
  console.log("✅ Test passed: should reject content with a dead link");
31
28
  }
32
29
 
33
30
  async function testRejectIncorrectTableSeparator() {
34
- console.log(
35
- "Testing: should reject content with incorrect table separator"
36
- );
31
+ console.log("Testing: should reject content with incorrect table separator");
37
32
  const structurePlan = [];
38
33
  const content = "| Header | Header |\n| - | - |\n| Cell | Cell |";
39
34
  const result = await checkDetailResult({ structurePlan, content });
40
35
  assert(result.isApproved === false, "Should not be approved");
41
36
  assert(
42
37
  result.detailFeedback.includes("incorrect table separator"),
43
- "Should report incorrect table separator"
44
- );
45
- console.log(
46
- "✅ Test passed: should reject content with incorrect table separator"
38
+ "Should report incorrect table separator",
47
39
  );
40
+ console.log("✅ Test passed: should reject content with incorrect table separator");
48
41
  }
49
42
 
50
43
  async function testApproveExternalLink() {
@@ -60,17 +53,13 @@ async function runTests() {
60
53
  async function testRejectMultipleIssues() {
61
54
  console.log("Testing: should reject content with multiple issues");
62
55
  const structurePlan = [{ path: "/getting-started" }];
63
- const content =
64
- "This has a [dead link](/dead-link) and an incorrect table: | - |.";
56
+ const content = "This has a [dead link](/dead-link) and an incorrect table: | - |.";
65
57
  const result = await checkDetailResult({ structurePlan, content });
66
58
  assert(result.isApproved === false, "Should not be approved");
67
- assert(
68
- result.detailFeedback.includes("Found a dead link"),
69
- "Should report dead link"
70
- );
59
+ assert(result.detailFeedback.includes("Found a dead link"), "Should report dead link");
71
60
  assert(
72
61
  result.detailFeedback.includes("incorrect table separator"),
73
- "Should report incorrect table separator"
62
+ "Should report incorrect table separator",
74
63
  );
75
64
  console.log("✅ Test passed: should reject content with multiple issues");
76
65
  }
@@ -100,4 +89,4 @@ async function runTests() {
100
89
  }
101
90
  }
102
91
 
103
- runTests();
92
+ runTests();