@aigne/doc-smith 0.8.11-beta.4 → 0.8.11-beta.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 (118) hide show
  1. package/.aigne/doc-smith/config.yaml +2 -4
  2. package/.release-please-manifest.json +1 -1
  3. package/CHANGELOG.md +17 -2
  4. package/README.md +1 -1
  5. package/agents/clear/choose-contents.mjs +2 -2
  6. package/agents/clear/clear-document-structure.mjs +8 -8
  7. package/agents/clear/index.yaml +1 -1
  8. package/agents/evaluate/document-structure.yaml +1 -1
  9. package/agents/generate/check-d2-diagram-valid.mjs +26 -0
  10. package/agents/generate/check-document-structure.yaml +3 -3
  11. package/agents/generate/check-need-generate-structure.mjs +8 -8
  12. package/agents/generate/document-structure-tools/add-document.mjs +3 -3
  13. package/agents/generate/document-structure-tools/delete-document.mjs +2 -2
  14. package/agents/generate/document-structure-tools/move-document.mjs +3 -2
  15. package/agents/generate/document-structure-tools/update-document.mjs +2 -2
  16. package/agents/generate/generate-d2-diagram.yaml +23 -0
  17. package/agents/generate/generate-structure.yaml +1 -1
  18. package/agents/generate/merge-d2-diagram.yaml +39 -0
  19. package/agents/generate/update-document-structure.yaml +3 -3
  20. package/agents/generate/user-review-document-structure.mjs +10 -10
  21. package/agents/init/index.mjs +18 -10
  22. package/agents/publish/publish-docs.mjs +17 -20
  23. package/agents/update/batch-generate-document.yaml +1 -1
  24. package/agents/update/check-document.mjs +2 -2
  25. package/agents/update/generate-document.yaml +25 -0
  26. package/agents/utils/check-feedback-refiner.mjs +1 -1
  27. package/agents/utils/choose-docs.mjs +1 -1
  28. package/agents/utils/load-document-all-content.mjs +3 -3
  29. package/agents/utils/load-sources.mjs +1 -1
  30. package/agents/utils/save-docs.mjs +7 -28
  31. package/aigne.yaml +2 -2
  32. package/docs/_sidebar.md +1 -1
  33. package/docs/advanced-how-it-works.md +3 -3
  34. package/docs/advanced-quality-assurance.md +1 -1
  35. package/docs/cli-reference.ja.md +151 -80
  36. package/docs/cli-reference.md +126 -55
  37. package/docs/cli-reference.zh-TW.md +133 -62
  38. package/docs/cli-reference.zh.md +143 -72
  39. package/docs/configuration-interactive-setup.md +1 -1
  40. package/docs/configuration-language-support.md +1 -1
  41. package/docs/configuration-preferences.md +1 -1
  42. package/docs/configuration.ja.md +104 -48
  43. package/docs/configuration.md +58 -2
  44. package/docs/configuration.zh-TW.md +99 -42
  45. package/docs/configuration.zh.md +78 -21
  46. package/docs/features-generate-documentation.ja.md +63 -44
  47. package/docs/features-generate-documentation.md +54 -35
  48. package/docs/features-generate-documentation.zh-TW.md +67 -48
  49. package/docs/features-generate-documentation.zh.md +61 -41
  50. package/docs/features-publish-your-docs.ja.md +69 -46
  51. package/docs/features-publish-your-docs.md +65 -42
  52. package/docs/features-publish-your-docs.zh-TW.md +73 -50
  53. package/docs/features-publish-your-docs.zh.md +67 -44
  54. package/docs/features-translate-documentation.ja.md +35 -33
  55. package/docs/features-translate-documentation.md +24 -22
  56. package/docs/features-translate-documentation.zh-TW.md +32 -30
  57. package/docs/features-translate-documentation.zh.md +29 -27
  58. package/docs/features-update-and-refine.ja.md +120 -66
  59. package/docs/features-update-and-refine.md +110 -56
  60. package/docs/features-update-and-refine.zh-TW.md +116 -62
  61. package/docs/features-update-and-refine.zh.md +118 -64
  62. package/docs/getting-started.ja.md +22 -22
  63. package/docs/getting-started.md +1 -1
  64. package/docs/getting-started.zh-TW.md +16 -16
  65. package/docs/getting-started.zh.md +28 -28
  66. package/docs/overview.md +3 -3
  67. package/docs-mcp/analyze-docs-relevance.yaml +6 -6
  68. package/docs-mcp/docs-search.yaml +1 -1
  69. package/package.json +3 -3
  70. package/prompts/common/document-structure/conflict-resolution-guidance.md +3 -3
  71. package/prompts/common/document-structure/document-structure-rules.md +2 -2
  72. package/prompts/detail/{d2-chart/rules.md → d2-diagram/rules-system.md} +41 -5
  73. package/prompts/detail/d2-diagram/rules-user.md +4 -0
  74. package/prompts/detail/document-rules.md +3 -4
  75. package/prompts/detail/generate-document.md +8 -2
  76. package/prompts/detail/update-document.md +0 -2
  77. package/prompts/evaluate/document-structure.md +6 -6
  78. package/prompts/structure/check-document-structure.md +10 -10
  79. package/prompts/structure/document-rules.md +2 -2
  80. package/prompts/structure/generate-structure-system.md +3 -3
  81. package/prompts/structure/structure-example.md +1 -1
  82. package/prompts/structure/structure-getting-started.md +1 -1
  83. package/prompts/structure/update-document-structure.md +9 -9
  84. package/prompts/utils/feedback-refiner.md +1 -1
  85. package/tests/agents/clear/choose-contents.test.mjs +1 -1
  86. package/tests/agents/clear/clear-document-structure.test.mjs +36 -30
  87. package/tests/agents/evaluate/generate-report.test.mjs +1 -1
  88. package/tests/agents/generate/check-need-generate-structure.test.mjs +1 -1
  89. package/tests/agents/generate/document-structure-tools/add-document.test.mjs +2 -2
  90. package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +4 -4
  91. package/tests/agents/generate/document-structure-tools/move-document.test.mjs +3 -3
  92. package/tests/agents/generate/document-structure-tools/update-document.test.mjs +3 -3
  93. package/tests/agents/generate/user-review-document-structure.test.mjs +7 -5
  94. package/tests/agents/init/init.test.mjs +25 -19
  95. package/tests/agents/publish/publish-docs.test.mjs +99 -0
  96. package/tests/agents/update/check-document.test.mjs +1 -1
  97. package/tests/agents/utils/check-detail-result.test.mjs +2 -15
  98. package/tests/agents/utils/format-document-structure.test.mjs +5 -5
  99. package/tests/agents/utils/load-sources.test.mjs +4 -4
  100. package/tests/agents/utils/save-docs.test.mjs +1 -1
  101. package/tests/utils/auth-utils.test.mjs +1 -1
  102. package/tests/utils/conflict-detector.test.mjs +1 -1
  103. package/tests/utils/d2-utils.test.mjs +4 -4
  104. package/tests/utils/deploy.test.mjs +3 -10
  105. package/tests/utils/docs-finder-utils.test.mjs +8 -8
  106. package/tests/utils/kroki-utils.test.mjs +5 -5
  107. package/tests/utils/preferences-utils.test.mjs +5 -3
  108. package/tests/utils/save-value-to-config.test.mjs +3 -1
  109. package/types/document-structure-schema.mjs +9 -9
  110. package/utils/auth-utils.mjs +4 -0
  111. package/utils/conflict-detector.mjs +1 -1
  112. package/utils/constants/index.mjs +7 -4
  113. package/utils/d2-utils.mjs +11 -6
  114. package/utils/deploy.mjs +4 -20
  115. package/utils/docs-finder-utils.mjs +11 -11
  116. package/utils/kroki-utils.mjs +5 -4
  117. package/utils/markdown-checker.mjs +1 -21
  118. /package/prompts/detail/{d2-chart → d2-diagram}/official-examples.md +0 -0
@@ -15,6 +15,7 @@ import publishDocs from "../../../agents/publish/publish-docs.mjs";
15
15
  import * as authUtils from "../../../utils/auth-utils.mjs";
16
16
  import * as d2Utils from "../../../utils/d2-utils.mjs";
17
17
  import * as utils from "../../../utils/utils.mjs";
18
+ import * as deployUtils from "../../../utils/deploy.mjs";
18
19
 
19
20
  // Mock all external dependencies
20
21
  const mockPublishDocs = {
@@ -51,6 +52,7 @@ describe("publish-docs", () => {
51
52
  let getGithubRepoUrlSpy;
52
53
  let loadConfigFromFileSpy;
53
54
  let saveValueToConfigSpy;
55
+ let deploySpy;
54
56
 
55
57
  beforeAll(() => {
56
58
  // Apply mocks for external dependencies only
@@ -98,6 +100,10 @@ describe("publish-docs", () => {
98
100
  );
99
101
  loadConfigFromFileSpy = spyOn(utils, "loadConfigFromFile").mockResolvedValue({});
100
102
  saveValueToConfigSpy = spyOn(utils, "saveValueToConfig").mockResolvedValue();
103
+ deploySpy = spyOn(deployUtils, "deploy").mockResolvedValue({
104
+ appUrl: "https://deployed.example.com",
105
+ token: "deploy-token",
106
+ });
101
107
 
102
108
  mockOptions = {
103
109
  prompts: {
@@ -125,6 +131,7 @@ describe("publish-docs", () => {
125
131
  getGithubRepoUrlSpy?.mockRestore();
126
132
  loadConfigFromFileSpy?.mockRestore();
127
133
  saveValueToConfigSpy?.mockRestore();
134
+ deploySpy?.mockRestore();
128
135
  });
129
136
 
130
137
  // BASIC FUNCTIONALITY TESTS
@@ -593,6 +600,98 @@ describe("publish-docs", () => {
593
600
  expect(mockOptions.prompts.select).not.toHaveBeenCalled();
594
601
  });
595
602
 
603
+ // RESUME PREVIOUS WEBSITE SETUP TESTS
604
+ test("should show resume option when checkoutId exists in config", async () => {
605
+ loadConfigFromFileSpy.mockResolvedValue({
606
+ checkoutId: "cached-checkout-123",
607
+ });
608
+ mockOptions.prompts.select.mockResolvedValue("default");
609
+
610
+ await publishDocs(
611
+ {
612
+ docsDir: "./docs",
613
+ appUrl: "https://docsmith.aigne.io",
614
+ },
615
+ mockOptions,
616
+ );
617
+
618
+ expect(mockOptions.prompts.select).toHaveBeenCalledWith(
619
+ expect.objectContaining({
620
+ message: "Select platform to publish your documents:",
621
+ choices: expect.arrayContaining([
622
+ expect.objectContaining({
623
+ name: expect.stringContaining("Resume previous website setup"),
624
+ value: "new-instance-continue",
625
+ }),
626
+ ]),
627
+ }),
628
+ );
629
+
630
+ // Verify the exact text content
631
+ const selectCall = mockOptions.prompts.select.mock.calls[0][0];
632
+ const resumeChoice = selectCall.choices.find(
633
+ (choice) => choice.value === "new-instance-continue",
634
+ );
635
+ expect(resumeChoice.name).toContain("Resume previous website setup");
636
+ expect(resumeChoice.name).toContain("Already paid.");
637
+ expect(resumeChoice.name).toContain(
638
+ "Continue where you left off. Your payment has already been processed.",
639
+ );
640
+ });
641
+
642
+ test("should not show resume option when no checkoutId in config", async () => {
643
+ loadConfigFromFileSpy.mockResolvedValue({});
644
+ mockOptions.prompts.select.mockResolvedValue("default");
645
+
646
+ await publishDocs(
647
+ {
648
+ docsDir: "./docs",
649
+ appUrl: "https://docsmith.aigne.io",
650
+ },
651
+ mockOptions,
652
+ );
653
+
654
+ expect(mockOptions.prompts.select).toHaveBeenCalledWith(
655
+ expect.objectContaining({
656
+ message: "Select platform to publish your documents:",
657
+ choices: expect.not.arrayContaining([
658
+ expect.objectContaining({
659
+ value: "new-instance-continue",
660
+ }),
661
+ ]),
662
+ }),
663
+ );
664
+ });
665
+
666
+ test("should handle resume previous website setup selection", async () => {
667
+ deploySpy.mockResolvedValue({
668
+ appUrl: "https://resumed.example.com",
669
+ token: "resume-token",
670
+ });
671
+
672
+ loadConfigFromFileSpy.mockResolvedValue({
673
+ checkoutId: "cached-checkout-123",
674
+ paymentUrl: "https://payment.example.com",
675
+ });
676
+ mockOptions.prompts.select.mockResolvedValue("new-instance-continue");
677
+
678
+ const consoleSpy = spyOn(console, "log").mockImplementation(() => {});
679
+
680
+ await publishDocs(
681
+ {
682
+ docsDir: "./docs",
683
+ appUrl: "https://docsmith.aigne.io",
684
+ },
685
+ mockOptions,
686
+ );
687
+
688
+ expect(consoleSpy).toHaveBeenCalledWith("\nResuming your previous website setup...");
689
+ expect(deploySpy).toHaveBeenCalledWith("cached-checkout-123", "https://payment.example.com");
690
+ expect(getAccessTokenSpy).toHaveBeenCalledWith("https://resumed.example.com", "resume-token");
691
+
692
+ consoleSpy.mockRestore();
693
+ });
694
+
596
695
  test("should handle URL validation edge cases", async () => {
597
696
  loadConfigFromFileSpy.mockResolvedValue({});
598
697
  mockOptions.prompts.select.mockResolvedValue("custom");
@@ -177,7 +177,7 @@ describe("check-document", () => {
177
177
  expect(mockOptions.context.invoke).not.toHaveBeenCalled();
178
178
  });
179
179
 
180
- test("should handle missing original node in document structure", async () => {
180
+ test("should handle missing original node in documentation structure", async () => {
181
181
  accessSpy.mockResolvedValue();
182
182
  checkDetailResultSpy.mockResolvedValue({ isApproved: true });
183
183
 
@@ -229,7 +229,7 @@ set -euo pipefail
229
229
  function deploy_app() {
230
230
  local app_name="$1"
231
231
  local version="$2"
232
-
232
+
233
233
  echo "Deploying $app_name version $version"
234
234
  docker run --rm "$app_name:$version"
235
235
  }
@@ -337,19 +337,6 @@ This document demonstrates various programming language code blocks.`;
337
337
  });
338
338
  });
339
339
 
340
- describe("D2 syntax validation", () => {
341
- test("should handle D2 syntax errors", async () => {
342
- const documentStructure = [];
343
- const reviewContent =
344
- "```d2\n" +
345
- "invalid d2 syntax {{\n" + // Malformed D2
346
- "```\n\n" +
347
- "This has proper structure.";
348
- const result = await checkDetailResult({ documentStructure, reviewContent });
349
- expect(result.isApproved).toBe(false);
350
- });
351
- });
352
-
353
340
  describe("Advanced table edge cases", () => {
354
341
  test("should handle empty table cells correctly", async () => {
355
342
  const documentStructure = [];
@@ -660,7 +647,7 @@ flowchart TD
660
647
  A["1. Create Backend Implementation<br>api/src/providers/"]
661
648
  B["2. Add Backend Configuration<br>api/src/providers/models.ts"]
662
649
  C["3. Update Frontend Selector<br>src/pages/config/ai-providers/"]
663
-
650
+
664
651
  A --> B --> C
665
652
  \`\`\`
666
653
 
@@ -104,7 +104,7 @@ describe("format-document-structure", () => {
104
104
  });
105
105
 
106
106
  // BASIC FUNCTIONALITY TESTS
107
- test("should format empty document structure", async () => {
107
+ test("should format empty documentation structure", async () => {
108
108
  const result = await formatDocumentStructure({
109
109
  documentStructure: [],
110
110
  });
@@ -121,7 +121,7 @@ describe("format-document-structure", () => {
121
121
  });
122
122
  });
123
123
 
124
- test("should format single item document structure", async () => {
124
+ test("should format single item documentation structure", async () => {
125
125
  const documentStructure = [
126
126
  {
127
127
  title: "Getting Started",
@@ -152,7 +152,7 @@ describe("format-document-structure", () => {
152
152
  expect(result.documentStructureYaml).toBe(expectedYaml);
153
153
  });
154
154
 
155
- test("should format multiple items document structure", async () => {
155
+ test("should format multiple items documentation structure", async () => {
156
156
  const documentStructure = [
157
157
  {
158
158
  title: "API Reference",
@@ -321,7 +321,7 @@ describe("format-document-structure", () => {
321
321
  expect(result.documentStructure).toEqual(documentStructure);
322
322
  });
323
323
 
324
- test("should return both yaml string and original document structure", async () => {
324
+ test("should return both yaml string and original documentation structure", async () => {
325
325
  const documentStructure = [
326
326
  {
327
327
  title: "Return Test",
@@ -339,7 +339,7 @@ describe("format-document-structure", () => {
339
339
  expect(result.documentStructure).toBe(documentStructure); // Should be the same reference
340
340
  });
341
341
 
342
- test("should preserve original document structure unchanged", async () => {
342
+ test("should preserve original documentation structure unchanged", async () => {
343
343
  const originalDocumentStructure = [
344
344
  {
345
345
  title: "Original",
@@ -1030,8 +1030,8 @@ describe("load-sources", () => {
1030
1030
  });
1031
1031
  });
1032
1032
 
1033
- describe("Document path and document structure handling", () => {
1034
- test("should load existing document structure", async () => {
1033
+ describe("Document path and documentation structure handling", () => {
1034
+ test("should load existing documentation structure", async () => {
1035
1035
  const documentStructure = {
1036
1036
  sections: ["Introduction", "API", "Examples"],
1037
1037
  lastUpdated: new Date().toISOString(),
@@ -1050,7 +1050,7 @@ describe("load-sources", () => {
1050
1050
  expect(result.originalDocumentStructure).toEqual(documentStructure);
1051
1051
  });
1052
1052
 
1053
- test("should handle malformed document structure JSON", async () => {
1053
+ test("should handle malformed documentation structure JSON", async () => {
1054
1054
  await writeFile(path.join(tempDir, "structure-plan.json"), "{ invalid json content");
1055
1055
 
1056
1056
  const result = await loadSources({
@@ -1064,7 +1064,7 @@ describe("load-sources", () => {
1064
1064
  expect(result.originalDocumentStructure).toBeUndefined();
1065
1065
  });
1066
1066
 
1067
- test("should handle non-ENOENT errors when reading document structure JSON", async () => {
1067
+ test("should handle non-ENOENT errors when reading documentation structure JSON", async () => {
1068
1068
  // Import fs promises module to spy on
1069
1069
  const fsPromises = await import("node:fs/promises");
1070
1070
 
@@ -52,7 +52,7 @@ describe("save-docs", () => {
52
52
  expect(initialFiles).toContain("getting-started.md");
53
53
  expect(initialFiles).toContain("old-file.md");
54
54
 
55
- // Test document structure
55
+ // Test documentation structure
56
56
  const documentStructure = [
57
57
  {
58
58
  path: "/overview",
@@ -336,7 +336,7 @@ describe("auth-utils", () => {
336
336
 
337
337
  // Test that openPage calls the mock open function
338
338
  await capturedOpenPage("https://auth.example.com");
339
- expect(mockOpen).toHaveBeenCalledWith("https://auth.example.com/");
339
+ expect(mockOpen).toHaveBeenCalledWith("https://auth.example.com/?required_roles=owner%2Cadmin");
340
340
  });
341
341
 
342
342
  test("should handle authorization failure", async () => {
@@ -309,7 +309,7 @@ describe("conflict-detector", () => {
309
309
 
310
310
  // Should include conflict resolution rules in final rules
311
311
  expect(result.rules).toContain("=== Conflict Resolution Guidelines ===");
312
- expect(result.rules).toContain("Create layered document structure");
312
+ expect(result.rules).toContain("Create layered documentation structure");
313
313
  expect(result.rules).toContain("Create separate user paths");
314
314
 
315
315
  // Should also include regular configuration content with enhanced format
@@ -6,7 +6,7 @@ import path from "node:path";
6
6
 
7
7
  import Debug from "debug";
8
8
 
9
- import { TMP_ASSETS_DIR } from "../../utils/constants/index.mjs";
9
+ import { DOC_SMITH_DIR, TMP_ASSETS_DIR, TMP_DIR } from "../../utils/constants/index.mjs";
10
10
  import {
11
11
  beforePublishHook,
12
12
  checkContent,
@@ -346,7 +346,7 @@ E -> F
346
346
  try {
347
347
  await checkContent({ content });
348
348
 
349
- const assetDir = path.join(process.cwd(), ".aigne", "doc-smith", ".tmp", "assets", "d2");
349
+ const assetDir = path.join(process.cwd(), DOC_SMITH_DIR, TMP_DIR, TMP_ASSETS_DIR, "d2");
350
350
  const files = await readdir(assetDir);
351
351
  const d2File = files.find((file) => file.endsWith(".d2"));
352
352
  expect(d2File).toBeDefined();
@@ -365,7 +365,7 @@ E -> F
365
365
  try {
366
366
  await ensureTmpDir();
367
367
 
368
- const tmpDir = path.join(tempDir, ".aigne", "doc-smith", ".tmp");
368
+ const tmpDir = path.join(tempDir, DOC_SMITH_DIR, TMP_DIR);
369
369
  const gitignorePath = path.join(tmpDir, ".gitignore");
370
370
 
371
371
  expect(existsSync(tmpDir)).toBe(true);
@@ -386,7 +386,7 @@ E -> F
386
386
  // First call
387
387
  await ensureTmpDir();
388
388
 
389
- const tmpDir = path.join(tempDir, ".aigne", "doc-smith", ".tmp");
389
+ const tmpDir = path.join(tempDir, DOC_SMITH_DIR, TMP_DIR);
390
390
  const gitignorePath = path.join(tmpDir, ".gitignore");
391
391
 
392
392
  // Modify .gitignore to test if it gets overwritten
@@ -91,15 +91,8 @@ describe("deploy", () => {
91
91
 
92
92
  // Verify BrokerClient was constructed with correct config
93
93
  expect(mockBrokerClientConstructor).toHaveBeenCalledWith({
94
- baseUrl: "",
95
94
  authToken: "mock-auth-token",
96
- paymentLinkKey: "PAYMENT_LINK_ID",
97
- timeout: 300000,
98
- polling: {
99
- interval: 3000,
100
- maxAttempts: 100,
101
- backoffStrategy: "linear",
102
- },
95
+ baseUrl: "https://docsmith.aigne.io",
103
96
  });
104
97
 
105
98
  // Verify deploy was called with correct parameters
@@ -120,7 +113,6 @@ describe("deploy", () => {
120
113
  ACCESS_PREPARING: expect.any(Function),
121
114
  ACCESS_READY: expect.any(Function),
122
115
  }),
123
- onError: expect.any(Function),
124
116
  }),
125
117
  );
126
118
 
@@ -348,7 +340,8 @@ describe("deploy", () => {
348
340
  // Verify BrokerClient was constructed with empty baseUrl
349
341
  expect(mockBrokerClientConstructor).toHaveBeenCalledWith(
350
342
  expect.objectContaining({
351
- baseUrl: "",
343
+ authToken: "mock-auth-token",
344
+ baseUrl: "https://docsmith.aigne.io",
352
345
  }),
353
346
  );
354
347
  });
@@ -125,7 +125,7 @@ describe("docs-finder-utils", () => {
125
125
  expect(result).toBeUndefined();
126
126
  });
127
127
 
128
- test("should handle empty document structure", () => {
128
+ test("should handle empty documentation structure", () => {
129
129
  const result = findItemByFlatName([], "any-name");
130
130
  expect(result).toBeUndefined();
131
131
  });
@@ -243,7 +243,7 @@ describe("docs-finder-utils", () => {
243
243
  expect(result).toEqual(["guide.zh.md", "overview.zh.md"]);
244
244
  });
245
245
 
246
- test("should sort files by document structure order", async () => {
246
+ test("should sort files by documentation structure order", async () => {
247
247
  readdirSpy.mockResolvedValue(["guide.md", "overview.md", "advanced.md"]);
248
248
 
249
249
  const documentStructure = [{ path: "/overview" }, { path: "/guide" }, { path: "/advanced" }];
@@ -253,7 +253,7 @@ describe("docs-finder-utils", () => {
253
253
  expect(result).toEqual(["overview.md", "guide.md", "advanced.md"]);
254
254
  });
255
255
 
256
- test("should handle files not in document structure", async () => {
256
+ test("should handle files not in documentation structure", async () => {
257
257
  readdirSpy.mockResolvedValue(["guide.md", "extra.md", "overview.md"]);
258
258
 
259
259
  const documentStructure = [{ path: "/overview" }, { path: "/guide" }];
@@ -480,7 +480,7 @@ describe("docs-finder-utils", () => {
480
480
  ]);
481
481
  });
482
482
 
483
- test("should warn for files not in document structure", async () => {
483
+ test("should warn for files not in documentation structure", async () => {
484
484
  readFileSpy.mockResolvedValue("content");
485
485
 
486
486
  const selectedFiles = ["unknown.md"];
@@ -488,7 +488,7 @@ describe("docs-finder-utils", () => {
488
488
 
489
489
  expect(result).toEqual([]);
490
490
  expect(consoleWarnSpy).toHaveBeenCalledWith(
491
- "⚠️ No document structure item found for file: unknown.md",
491
+ "⚠️ No documentation structure item found for file: unknown.md",
492
492
  );
493
493
  });
494
494
 
@@ -508,7 +508,7 @@ describe("docs-finder-utils", () => {
508
508
  },
509
509
  ]);
510
510
  expect(consoleWarnSpy).toHaveBeenCalledWith(
511
- "⚠️ No document structure item found for file: unknown.md",
511
+ "⚠️ No documentation structure item found for file: unknown.md",
512
512
  );
513
513
  });
514
514
 
@@ -623,14 +623,14 @@ describe("docs-finder-utils", () => {
623
623
  await expect(getMainLanguageFiles("/denied", "en")).rejects.toThrow("Permission denied");
624
624
  });
625
625
 
626
- test("processSelectedFiles should handle empty document structure", async () => {
626
+ test("processSelectedFiles should handle empty documentation structure", async () => {
627
627
  readFileSpy.mockResolvedValue("content");
628
628
 
629
629
  const result = await processSelectedFiles(["test.md"], [], "/docs");
630
630
 
631
631
  expect(result).toEqual([]);
632
632
  expect(consoleWarnSpy).toHaveBeenCalledWith(
633
- "⚠️ No document structure item found for file: test.md",
633
+ "⚠️ No documentation structure item found for file: test.md",
634
634
  );
635
635
  });
636
636
  });
@@ -6,7 +6,7 @@ import path from "node:path";
6
6
 
7
7
  import Debug from "debug";
8
8
 
9
- import { TMP_ASSETS_DIR } from "../../utils/constants/index.mjs";
9
+ import { DOC_SMITH_DIR, TMP_ASSETS_DIR, TMP_DIR } from "../../utils/constants/index.mjs";
10
10
  import {
11
11
  beforePublishHook,
12
12
  checkD2Content,
@@ -451,7 +451,7 @@ E -> F
451
451
  try {
452
452
  await checkD2Content({ content });
453
453
 
454
- const assetDir = path.join(process.cwd(), ".aigne", "doc-smith", ".tmp", "assets", "d2");
454
+ const assetDir = path.join(process.cwd(), DOC_SMITH_DIR, TMP_DIR, TMP_ASSETS_DIR, "d2");
455
455
  const files = await readdir(assetDir);
456
456
  const d2File = files.find((file) => file.endsWith(".d2"));
457
457
  expect(d2File).toBeDefined();
@@ -470,7 +470,7 @@ E -> F
470
470
  try {
471
471
  await ensureTmpDir();
472
472
 
473
- const tmpDir = path.join(tempDir, ".aigne", "doc-smith", ".tmp");
473
+ const tmpDir = path.join(tempDir, DOC_SMITH_DIR, TMP_DIR);
474
474
  const gitignorePath = path.join(tmpDir, ".gitignore");
475
475
 
476
476
  expect(existsSync(tmpDir)).toBe(true);
@@ -491,7 +491,7 @@ E -> F
491
491
  // First call
492
492
  await ensureTmpDir();
493
493
 
494
- const tmpDir = path.join(tempDir, ".aigne", "doc-smith", ".tmp");
494
+ const tmpDir = path.join(tempDir, DOC_SMITH_DIR, TMP_DIR);
495
495
  const gitignorePath = path.join(tmpDir, ".gitignore");
496
496
 
497
497
  // Modify .gitignore to test if it gets overwritten
@@ -632,7 +632,7 @@ E -> F
632
632
  await Promise.all(promises);
633
633
 
634
634
  // Should only create directory once
635
- const tmpDir = path.join(tempDir, ".aigne", "doc-smith", ".tmp");
635
+ const tmpDir = path.join(tempDir, DOC_SMITH_DIR, TMP_DIR);
636
636
  expect(existsSync(tmpDir)).toBe(true);
637
637
 
638
638
  // .gitignore should be created properly
@@ -3,6 +3,8 @@ import { existsSync } from "node:fs";
3
3
  import { mkdir, rm, writeFile } from "node:fs/promises";
4
4
  import { dirname, join } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
+
7
+ import { DOC_SMITH_DIR } from "../../utils/constants/index.mjs";
6
8
  import {
7
9
  addPreferenceRule,
8
10
  deactivateRule,
@@ -44,7 +46,7 @@ describe("preferences-utils", () => {
44
46
 
45
47
  test("should read existing preferences file", async () => {
46
48
  // Create preferences directory and file
47
- const prefsDir = join(testDir, ".aigne", "doc-smith");
49
+ const prefsDir = join(testDir, DOC_SMITH_DIR);
48
50
  await mkdir(prefsDir, { recursive: true });
49
51
 
50
52
  await writeFile(
@@ -69,7 +71,7 @@ describe("preferences-utils", () => {
69
71
 
70
72
  test("should handle malformed YAML gracefully", async () => {
71
73
  // Create preferences directory and invalid file
72
- const prefsDir = join(testDir, ".aigne", "doc-smith");
74
+ const prefsDir = join(testDir, DOC_SMITH_DIR);
73
75
  await mkdir(prefsDir, { recursive: true });
74
76
 
75
77
  await writeFile(join(prefsDir, "preferences.yml"), "invalid: yaml: content: [", "utf8");
@@ -85,7 +87,7 @@ describe("preferences-utils", () => {
85
87
 
86
88
  writePreferences(testPreferences);
87
89
 
88
- const prefsDir = join(testDir, ".aigne", "doc-smith");
90
+ const prefsDir = join(testDir, DOC_SMITH_DIR);
89
91
  expect(existsSync(prefsDir)).toBe(true);
90
92
  expect(existsSync(join(prefsDir, "preferences.yml"))).toBe(true);
91
93
  });
@@ -5,6 +5,8 @@ import fsPromisesDefault, * as fsPromises from "node:fs/promises";
5
5
  import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
6
6
  import { dirname, join } from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
+
9
+ import { DOC_SMITH_DIR } from "../../utils/constants/index.mjs";
8
10
  import { saveValueToConfig } from "../../utils/utils.mjs";
9
11
 
10
12
  const __filename = fileURLToPath(import.meta.url);
@@ -12,7 +14,7 @@ const __dirname = dirname(__filename);
12
14
 
13
15
  // Test directory for isolated testing
14
16
  const TEST_DIR = join(__dirname, "temp-config-test");
15
- const TEST_CONFIG_DIR = join(TEST_DIR, ".aigne", "doc-smith");
17
+ const TEST_CONFIG_DIR = join(TEST_DIR, DOC_SMITH_DIR);
16
18
  const TEST_CONFIG_PATH = join(TEST_CONFIG_DIR, "config.yaml");
17
19
 
18
20
  // Store original working directory
@@ -10,7 +10,7 @@ export const documentItemSchema = z.object({
10
10
  sourceIds: z.array(z.string()).min(1, "At least one source ID is required"),
11
11
  });
12
12
 
13
- // Document structure schema - represents the entire document structure array
13
+ // Documentation structure schema - represents the entire documentation structure array
14
14
  export const documentStructureSchema = z.array(documentItemSchema);
15
15
 
16
16
  // Add document schemas
@@ -80,7 +80,7 @@ export const getAddDocumentInputJsonSchema = () => {
80
80
  const schema = zodToJsonSchema(addDocumentInputSchema);
81
81
  // Add custom descriptions
82
82
  if (schema.properties) {
83
- schema.properties.documentStructure.description = "Current document structure array";
83
+ schema.properties.documentStructure.description = "Current documentation structure array";
84
84
  schema.properties.title.description = "Title of the new document";
85
85
  schema.properties.description.description = "Description of the new document";
86
86
  schema.properties.path.description = "URL path for the new document (must start with '/')";
@@ -96,7 +96,7 @@ export const getAddDocumentOutputJsonSchema = () => {
96
96
  const schema = zodToJsonSchema(addDocumentOutputSchema);
97
97
  if (schema.properties) {
98
98
  schema.properties.documentStructure.description =
99
- "Updated document structure array with the new document added";
99
+ "Updated documentation structure array with the new document added";
100
100
  schema.properties.addedDocument.description = "The newly added document object";
101
101
  }
102
102
  return schema;
@@ -105,7 +105,7 @@ export const getAddDocumentOutputJsonSchema = () => {
105
105
  export const getDeleteDocumentInputJsonSchema = () => {
106
106
  const schema = zodToJsonSchema(deleteDocumentInputSchema);
107
107
  if (schema.properties) {
108
- schema.properties.documentStructure.description = "Current document structure array";
108
+ schema.properties.documentStructure.description = "Current documentation structure array";
109
109
  schema.properties.path.description = "URL path of the document to delete";
110
110
  }
111
111
  return schema;
@@ -115,7 +115,7 @@ export const getDeleteDocumentOutputJsonSchema = () => {
115
115
  const schema = zodToJsonSchema(deleteDocumentOutputSchema);
116
116
  if (schema.properties) {
117
117
  schema.properties.documentStructure.description =
118
- "Updated document structure array with the document removed";
118
+ "Updated documentation structure array with the document removed";
119
119
  schema.properties.deletedDocument.description = "The deleted document object";
120
120
  }
121
121
  return schema;
@@ -124,7 +124,7 @@ export const getDeleteDocumentOutputJsonSchema = () => {
124
124
  export const getMoveDocumentInputJsonSchema = () => {
125
125
  const schema = zodToJsonSchema(moveDocumentInputSchema);
126
126
  if (schema.properties) {
127
- schema.properties.documentStructure.description = "Current document structure array";
127
+ schema.properties.documentStructure.description = "Current documentation structure array";
128
128
  schema.properties.path.description = "URL path of the document to move";
129
129
  schema.properties.newParentId.description =
130
130
  "Path of the new parent document (leave empty for top-level)";
@@ -136,7 +136,7 @@ export const getMoveDocumentOutputJsonSchema = () => {
136
136
  const schema = zodToJsonSchema(moveDocumentOutputSchema);
137
137
  if (schema.properties) {
138
138
  schema.properties.documentStructure.description =
139
- "Updated document structure array with the document moved";
139
+ "Updated documentation structure array with the document moved";
140
140
  schema.properties.originalDocument.description = "The original document object before moving";
141
141
  schema.properties.updatedDocument.description = "The updated document object after moving";
142
142
  }
@@ -146,7 +146,7 @@ export const getMoveDocumentOutputJsonSchema = () => {
146
146
  export const getUpdateDocumentInputJsonSchema = () => {
147
147
  const schema = zodToJsonSchema(updateDocumentInputSchema);
148
148
  if (schema.properties) {
149
- schema.properties.documentStructure.description = "Current document structure array";
149
+ schema.properties.documentStructure.description = "Current documentation structure array";
150
150
  schema.properties.path.description = "URL path of the document to update";
151
151
  schema.properties.title.description = "New title for the document (optional)";
152
152
  schema.properties.description.description = "New description for the document (optional)";
@@ -166,7 +166,7 @@ export const getUpdateDocumentOutputJsonSchema = () => {
166
166
  const schema = zodToJsonSchema(updateDocumentOutputSchema);
167
167
  if (schema.properties) {
168
168
  schema.properties.documentStructure.description =
169
- "Updated document structure array with the document modified";
169
+ "Updated documentation structure array with the document modified";
170
170
  schema.properties.originalDocument.description = "The original document object before update";
171
171
  schema.properties.updatedDocument.description =
172
172
  "The updated document object after modification";
@@ -15,6 +15,7 @@ import {
15
15
  } from "./blocklet.mjs";
16
16
  import {
17
17
  BLOCKLET_ADD_COMPONENT_DOCS,
18
+ DEFAULT_APP_URL,
18
19
  DISCUSS_KIT_DID,
19
20
  DISCUSS_KIT_STORE_URL,
20
21
  DOC_OFFICIAL_ACCESS_TOKEN,
@@ -97,6 +98,9 @@ export async function getAccessToken(appUrl, ltToken = "") {
97
98
  appLogo: "https://docsmith.aigne.io/image-bin/uploads/9645caf64b4232699982c4d940b03b90.svg",
98
99
  openPage: (pageUrl) => {
99
100
  const url = new URL(pageUrl);
101
+ if (url.hostname !== DEFAULT_APP_URL) {
102
+ url.searchParams.set("required_roles", "owner,admin");
103
+ }
100
104
  if (ltToken) {
101
105
  url.searchParams.set("__lt", ltToken);
102
106
  }
@@ -76,7 +76,7 @@ export function getFilteredOptions(targetQuestion, currentSelections, allOptions
76
76
  }
77
77
 
78
78
  /**
79
- * Detect conflicts in user configuration selections that can be resolved through document structure
79
+ * Detect conflicts in user configuration selections that can be resolved through documentation structure
80
80
  * @param {Object} config - User configuration
81
81
  * @returns {Array} Array of detected conflicts with resolution strategies
82
82
  */