@aigne/doc-smith 0.8.14 → 0.8.15-beta.1
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.
- package/CHANGELOG.md +19 -0
- package/agents/update/check-document.mjs +15 -0
- package/agents/update/index.yaml +1 -1
- package/agents/utils/choose-docs.mjs +6 -1
- package/agents/utils/load-sources.mjs +80 -22
- package/agents/utils/transform-detail-datasources.mjs +24 -2
- package/package.json +1 -1
- package/prompts/detail/custom/custom-components.md +247 -153
- package/prompts/detail/d2-diagram/system-prompt.md +33 -7
- package/prompts/detail/generate/detail-example.md +24 -8
- package/prompts/detail/generate/document-rules.md +4 -5
- package/prompts/detail/generate/user-prompt.md +37 -0
- package/prompts/structure/generate/user-prompt.md +34 -0
- package/prompts/translate/code-block.md +14 -7
- package/prompts/translate/translate-document.md +111 -7
- package/utils/file-utils.mjs +83 -7
- package/utils/openapi/index.mjs +24 -0
|
@@ -913,6 +913,28 @@ Ensure that the shape names used in connections are accurate and match the actua
|
|
|
913
913
|
- **Good Practice:**
|
|
914
914
|
```d2
|
|
915
915
|
shape: sequence_diagram
|
|
916
|
+
User: {
|
|
917
|
+
shape: c4-person
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
App: {
|
|
921
|
+
label: "Your Application"
|
|
922
|
+
shape: rectangle
|
|
923
|
+
|
|
924
|
+
ResumeSubscription: {
|
|
925
|
+
label: "ResumeSubscription Component"
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
Payment-API: {
|
|
930
|
+
label: "Payment Backend API"
|
|
931
|
+
shape: rectangle
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
DID-Wallet: {
|
|
935
|
+
label: "DID Wallet"
|
|
936
|
+
icon: "https://www.arcblock.io/image-bin/uploads/37198ddc4a0b9e91e5c1c821ab895a34.svg"
|
|
937
|
+
}
|
|
916
938
|
|
|
917
939
|
User -> App.ResumeSubscription: "1. Triggers resume action"
|
|
918
940
|
|
|
@@ -922,12 +944,16 @@ Ensure that the shape names used in connections are accurate and match the actua
|
|
|
922
944
|
App.ResumeSubscription.t1 -> User: "4. Display confirmation dialog"
|
|
923
945
|
User -> App.ResumeSubscription.t1: "5. Clicks 'Confirm'"
|
|
924
946
|
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
947
|
+
"If Re-Staking is Required": {
|
|
948
|
+
App.ResumeSubscription.t1 -> DID-Wallet: "6a. Open 're-stake' session"
|
|
949
|
+
User -> DID-Wallet: "7a. Approve in wallet"
|
|
950
|
+
DID-Wallet -> App.ResumeSubscription.t1: "8a. Send success callback"
|
|
951
|
+
}
|
|
928
952
|
|
|
929
|
-
|
|
930
|
-
|
|
953
|
+
"If No Staking is Required": {
|
|
954
|
+
App.ResumeSubscription.t1 -> Payment-API: "6b. Call recover endpoint\n(PUT /recover)"
|
|
955
|
+
Payment-API -> App.ResumeSubscription.t1: "7b. Return success"
|
|
956
|
+
}
|
|
931
957
|
|
|
932
958
|
App.ResumeSubscription.t1 -> Payment-API: "9. Fetch updated subscription details"
|
|
933
959
|
Payment-API -> App.ResumeSubscription.t1: "10. Return latest subscription"
|
|
@@ -1086,12 +1112,12 @@ Ensure that the shape names used in connections are accurate and match the actua
|
|
|
1086
1112
|
Blocklet-Service -> Application.Auth-Middleware: "4. Return permissions"
|
|
1087
1113
|
Application.Auth-Middleware -> Application.Auth-Middleware: "5. Evaluate all rules"
|
|
1088
1114
|
|
|
1089
|
-
"If Authorized" {
|
|
1115
|
+
"If Authorized": {
|
|
1090
1116
|
Application.Auth-Middleware -> Application.Protected-Route: "6a. next()"
|
|
1091
1117
|
Application.Protected-Route -> Client: "7a. 200 OK Response"
|
|
1092
1118
|
}
|
|
1093
1119
|
|
|
1094
|
-
"If Forbidden" {
|
|
1120
|
+
"If Forbidden": {
|
|
1095
1121
|
Application.Auth-Middleware -> Client: "6b. 403 Forbidden Response"
|
|
1096
1122
|
}
|
|
1097
1123
|
```
|
|
@@ -80,7 +80,9 @@ Here are some high-quality documentation details for your reference:
|
|
|
80
80
|
|
|
81
81
|
**Returns**
|
|
82
82
|
|
|
83
|
-
<x-field
|
|
83
|
+
<x-field-group>
|
|
84
|
+
<x-field data-name="product" data-type="TProductExpanded" data-desc="The newly created product object, including expanded details"></x-field>
|
|
85
|
+
</x-field-group>
|
|
84
86
|
|
|
85
87
|
**Example**
|
|
86
88
|
|
|
@@ -130,11 +132,15 @@ Here are some high-quality documentation details for your reference:
|
|
|
130
132
|
|
|
131
133
|
**Parameters**
|
|
132
134
|
|
|
133
|
-
<x-field
|
|
135
|
+
<x-field-group>
|
|
136
|
+
<x-field data-name="id" data-type="string" data-required="true" data-desc="The unique identifier of the product to retrieve."></x-field>
|
|
137
|
+
</x-field-group>
|
|
134
138
|
|
|
135
139
|
**Returns**
|
|
136
140
|
|
|
137
|
-
<x-field
|
|
141
|
+
<x-field-group>
|
|
142
|
+
<x-field data-name="product" data-type="TProductExpanded" data-desc="The retrieved product object, including expanded details."></x-field>
|
|
143
|
+
</x-field-group>
|
|
138
144
|
|
|
139
145
|
**Example**
|
|
140
146
|
|
|
@@ -176,7 +182,9 @@ Here are some high-quality documentation details for your reference:
|
|
|
176
182
|
|
|
177
183
|
**Returns**
|
|
178
184
|
|
|
179
|
-
<x-field
|
|
185
|
+
<x-field-group>
|
|
186
|
+
<x-field data-name="product" data-type="TProductExpanded" data-desc="The updated product object."></x-field>
|
|
187
|
+
</x-field-group>
|
|
180
188
|
|
|
181
189
|
**Example**
|
|
182
190
|
|
|
@@ -341,11 +349,15 @@ Here are some high-quality documentation details for your reference:
|
|
|
341
349
|
|
|
342
350
|
**Parameters**
|
|
343
351
|
|
|
344
|
-
<x-field
|
|
352
|
+
<x-field-group>
|
|
353
|
+
<x-field data-name="id" data-type="string" data-required="true" data-desc="The unique identifier of the product to archive."></x-field>
|
|
354
|
+
</x-field-group>
|
|
345
355
|
|
|
346
356
|
**Returns**
|
|
347
357
|
|
|
348
|
-
<x-field
|
|
358
|
+
<x-field-group>
|
|
359
|
+
<x-field data-name="product" data-type="TProduct" data-desc="The archived product object."></x-field>
|
|
360
|
+
</x-field-group>
|
|
349
361
|
|
|
350
362
|
**Example**
|
|
351
363
|
|
|
@@ -380,11 +392,15 @@ Here are some high-quality documentation details for your reference:
|
|
|
380
392
|
|
|
381
393
|
**Parameters**
|
|
382
394
|
|
|
383
|
-
<x-field
|
|
395
|
+
<x-field-group>
|
|
396
|
+
<x-field data-name="id" data-type="string" data-required="true" data-desc="The unique identifier of the product to delete."></x-field>
|
|
397
|
+
</x-field-group>
|
|
384
398
|
|
|
385
399
|
**Returns**
|
|
386
400
|
|
|
387
|
-
<x-field
|
|
401
|
+
<x-field-group>
|
|
402
|
+
<x-field data-name="product" data-type="TProduct" data-desc="The deleted product object."></x-field>
|
|
403
|
+
</x-field-group>
|
|
388
404
|
|
|
389
405
|
**Example**
|
|
390
406
|
|
|
@@ -7,18 +7,17 @@ Documentation Generation Rules:
|
|
|
7
7
|
- Since API names are already specified in document titles, avoid repeating them in subheadings—use sub-API names directly
|
|
8
8
|
- Include links to related documents in the introduction using Markdown format to help users navigate to relevant content
|
|
9
9
|
- Add links to further reading materials in the summary section using Markdown format
|
|
10
|
+
- **Markdown Syntax Constraint**: Use only GitHub Flavored Markdown (GFM) syntax by default. Prohibited extensions include: custom blocks `:::`, footnotes `[^1]: notes`, math formulas `$$ LaTeX`, highlighted text `==code==`, and other non-GFM syntax unless explicitly defined in custom component rules
|
|
10
11
|
- Use proper Markdown link syntax, for example: [Next Chapter Title](next_chapter_path)
|
|
11
12
|
- **Ensure next_chapter_path references either external URLs or valid paths from the documentation structure**—use absolute paths from the documentation structure
|
|
12
13
|
- When DataSources includes third-party links, incorporate them appropriately throughout the document
|
|
13
14
|
- Structure each section with: title, introduction, code examples, response data samples, and explanatory notes. Place explanations directly after code examples without separate "Example Description" subheadings
|
|
14
15
|
- Maintain content completeness and logical flow so users can follow the documentation seamlessly
|
|
15
16
|
- Provide comprehensive explanations for configuration options and parameters. When parameters accept multiple values, explain each option's purpose and include code examples where applicable
|
|
16
|
-
- Use the `<x-field>` custom component only for displaying structured object data such as API parameters, return values, network request body/query/headers, and complex object properties (e.g., ContextType). This component does not exist independently but represents complete object structures
|
|
17
|
-
- Do not use `<x-field>` for individual field descriptions (e.g., name or version in package.json, logo or appUrl in config.yaml) - use regular Markdown text instead
|
|
18
|
-
- Wrap the outermost `<x-field>` elements with `<x-field-group>` when describing multiple properties of the same object, even if there's only one `<x-field>` element
|
|
19
|
-
- Use recursive `<x-field>` structures to fully express complex object type hierarchies, decomposing all nested properties into more fundamental types. Limit nesting to 5 levels maximum
|
|
20
17
|
- All interface and method documentation must include **response data examples**
|
|
21
|
-
-
|
|
18
|
+
- **Use `<x-field-group>` for all structured data**: Represent objects with nested `<x-field>` elements, and expand each structure to the **deepest relevant level**.
|
|
19
|
+
- **Enhance field descriptions with example values**: For structured data defined using `<x-field-group>`, extract example values from type definitions, comments, or test cases to make documentation more practical and user-friendly.
|
|
20
|
+
- **Use Markdown tables** for predefined values (e.g., status types, options) or term definitions to improve clarity and allow side-by-side comparison.
|
|
22
21
|
- Validate output Markdown for completeness, ensuring tables are properly formatted
|
|
23
22
|
- **Content Integrity**: Generate complete, syntactically correct code blocks (JSON, etc.). Perform self-validation to ensure all code blocks, lists, and tables are properly closed without truncation
|
|
24
23
|
- **Markdown Syntax Validation**: Ensure correct Markdown formatting, particularly table separators (e.g., `|---|---|---|`) that match column counts
|
|
@@ -27,6 +27,43 @@
|
|
|
27
27
|
|
|
28
28
|
</datasources>
|
|
29
29
|
|
|
30
|
+
{% if openAPISpec %}
|
|
31
|
+
<openapi>
|
|
32
|
+
|
|
33
|
+
**Goal:** Use the provided OpenAPI (Swagger) specification, align it with the current page objective, and leverage it to refine this document.
|
|
34
|
+
|
|
35
|
+
**OpenAPI File Content:**
|
|
36
|
+
<openapi_doc>
|
|
37
|
+
|
|
38
|
+
{{ openAPISpec }}
|
|
39
|
+
|
|
40
|
+
</openapi_doc>
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
### **Documentation Requirements and Constraints**
|
|
45
|
+
|
|
46
|
+
1. **Extract the core content:**
|
|
47
|
+
* Organize the document by functional modules.
|
|
48
|
+
* For each path item, include the following elements:
|
|
49
|
+
* HTTP method and path.
|
|
50
|
+
* Concise summary.
|
|
51
|
+
* Detailed description.
|
|
52
|
+
* Request parameters: name, location (`in`), type, required flag, description.
|
|
53
|
+
* Request body: describe its structure when present.
|
|
54
|
+
* Responses: at least the key status codes (e.g., 200, 201, 400, 500) and their schemas.
|
|
55
|
+
|
|
56
|
+
2. **Mandatory API description constraints (deduplication rule):**
|
|
57
|
+
* **Ensure that throughout the document (including preface, overview, etc.), any introduction to the project APIs appears only within this OpenAPI-generated "API reference" section.**
|
|
58
|
+
* **Never** repeat or expand the interface list elsewhere in the document (for example, "Quick Start" or "Architecture Overview" sections).
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
**Expected output format:** A concise, clear, and easy-to-scan Markdown document.
|
|
63
|
+
|
|
64
|
+
</openapi>
|
|
65
|
+
{% endif %}
|
|
66
|
+
|
|
30
67
|
|
|
31
68
|
{% include "./detail-example.md" %}
|
|
32
69
|
|
|
@@ -12,6 +12,40 @@
|
|
|
12
12
|
{{ datasources }}
|
|
13
13
|
</datasources>
|
|
14
14
|
|
|
15
|
+
{% if userContext.openAPISpec %}
|
|
16
|
+
<openapi>
|
|
17
|
+
|
|
18
|
+
**Goal:** Use the provided OpenAPI (Swagger) specification to design how the OpenAPI content and the overall document should be structured together.
|
|
19
|
+
|
|
20
|
+
**OpenAPI File Content:**
|
|
21
|
+
<openapi_doc>
|
|
22
|
+
|
|
23
|
+
{{ userContext.openAPISpec }}
|
|
24
|
+
|
|
25
|
+
</openapi_doc>
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
### **Documentation Requirements and Constraints**
|
|
30
|
+
|
|
31
|
+
1. **Section structure and titles:**
|
|
32
|
+
* Create a dedicated top-level section for the OpenAPI content.
|
|
33
|
+
* The section title must be professional and user friendly; **never** include terms such as OpenAPI, Swagger, or file formats. Recommended titles include **"API Interface Reference"** or **"Interface Reference"**.
|
|
34
|
+
|
|
35
|
+
2. **Content hierarchy and presentation:**
|
|
36
|
+
* **Ideal state (single-level page):** Prefer to present all API endpoints within **one Markdown file (one page)**.
|
|
37
|
+
* **Split criteria (two-level pages):** Only when the number of endpoints is too large for a single file should you split by OpenAPI tags or logical modules, creating individual Markdown files per module.
|
|
38
|
+
* **Forced file hierarchy constraint:** Whether using one or two levels, the generated API reference files (Markdown) may contain **no more than two levels.**
|
|
39
|
+
* **Example (two-level structure):** `/api-reference.md` (index) -> `/api/user.md`, `/api/order.md` (module pages)
|
|
40
|
+
* **Disallow any third level or deeper structure:** for example, `/api/v1/user/get.md`.
|
|
41
|
+
|
|
42
|
+
3. **Mandatory API description constraints (deduplication rule):**
|
|
43
|
+
* **Ensure that for the entire document (including preface, overview, etc.), any introduction to the project APIs appears only within this OpenAPI-generated "API reference" section.**
|
|
44
|
+
* **Never** repeat or extend the API list elsewhere in the document (for example, "Quick Start" or "Architecture Overview" sections).
|
|
45
|
+
|
|
46
|
+
</openapi>
|
|
47
|
+
{% endif %}
|
|
48
|
+
|
|
15
49
|
|
|
16
50
|
{% if originalDocumentStructure %}
|
|
17
51
|
<last_document_structure>
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
<code_block_rules>
|
|
2
2
|
The following formats are considered Code Blocks:
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
|
|
4
|
+
- Wrapped with ```
|
|
5
|
+
- Supports configurations: language, title, icon, where title and icon are optional
|
|
6
|
+
- content can be code, command line examples, text or any other content
|
|
6
7
|
|
|
7
8
|
<code_block_sample>
|
|
9
|
+
|
|
8
10
|
```{language} [{title}] [icon={icon}]
|
|
9
11
|
{content}
|
|
10
12
|
```
|
|
13
|
+
|
|
11
14
|
</code_block_sample>
|
|
12
15
|
|
|
13
|
-
Code Block Translation:
|
|
14
|
-
|
|
15
|
-
- For
|
|
16
|
-
|
|
16
|
+
Code Block Translation Rules:
|
|
17
|
+
|
|
18
|
+
- For D2 code blocks, translate **labels only**; leave all variable names, component names, and syntax unchanged.
|
|
19
|
+
- Translate **comments only** using the language-specific comment syntax; **preserve** all code, variables, functions, and syntax.
|
|
20
|
+
- **Do not translate** command examples, terminal/log outputs, or runtime output.
|
|
21
|
+
- **Preserve** all formatting, indentation, and code block structure.
|
|
22
|
+
|
|
23
|
+
</code_block_rules>
|
|
@@ -9,6 +9,7 @@ Core Mandates:
|
|
|
9
9
|
3. Readability and Flow: The final output must be **smooth, logical, and highly readable**. Sentences must flow naturally, ensuring a pleasant and coherent reading experience for the target audience.
|
|
10
10
|
4. Localization and Clarity: Where a **literal (word-for-word) translation** of a term, phrase, or idiom would be **uncommon, confusing, or ambiguous** in the target language, you must apply **localization best practices**. This means translating the **concept** into the most **idiomatic, common, and easily understandable expression** in the target language.
|
|
11
11
|
5. Versatility and Scope: You are proficient in handling **any pair of requested languages** (e.g., Chinese $\leftrightarrow$ English, English $\leftrightarrow$ Japanese) and are adept at translating diverse **document types**, including but not limited to: **Technical Manuals, Business Reports, Marketing Copy/Ads, Legal Documents, Academic Papers, and General Correspondence.**
|
|
12
|
+
|
|
12
13
|
</role_and_goal>
|
|
13
14
|
|
|
14
15
|
<translation_rules>
|
|
@@ -19,11 +20,12 @@ Translation Requirements:
|
|
|
19
20
|
- Strictly Protect Markdown Syntax: All Markdown syntax characters, including but not limited to `|` and `-` in tables, `*` and `-` in lists, `#` in headings, `` ` `` in code blocks, etc., must be **copied exactly**, with no modification, addition, deletion, or merging. Table separators (e.g., `|---|---|---|`) must match the original column count and format exactly, with separator columns matching table data columns.
|
|
20
21
|
- Use Terminology Reference: Ensure accuracy and consistency of professional terminology.
|
|
21
22
|
- Preserve Terms: Retain specific terms in their original form, avoiding translation.
|
|
23
|
+
- Maintain tone consistency: use a neutral tone for developer/DevOps docs, a polite tone for end-user/client docs, and do not mix address styles (e.g., **"you"** vs **"您"**).
|
|
24
|
+
- Translate Descriptions Only in <x-field>: All `<x-field>` component attributes must maintain the original format. Only translate the description content within `data-desc` attribute or `<x-field-desc>` elements.
|
|
22
25
|
|
|
23
26
|
{% include "./code-block.md" %}
|
|
24
27
|
</translation_rules>
|
|
25
28
|
|
|
26
|
-
|
|
27
29
|
{% if feedback %}
|
|
28
30
|
<translation_user_feedback>
|
|
29
31
|
{{ feedback }}
|
|
@@ -41,10 +43,11 @@ Translation Requirements:
|
|
|
41
43
|
{{userPreferences}}
|
|
42
44
|
|
|
43
45
|
User preference guidelines:
|
|
46
|
+
|
|
44
47
|
- User preferences are derived from feedback provided in previous user interactions. When generating translations, consider user preferences to avoid repeating issues mentioned in user feedback
|
|
45
48
|
- User preferences carry less weight than current user feedback
|
|
46
|
-
</user_preferences>
|
|
47
|
-
{% endif %}
|
|
49
|
+
</user_preferences>
|
|
50
|
+
{% endif %}
|
|
48
51
|
|
|
49
52
|
{% include "./glossary.md" %}
|
|
50
53
|
|
|
@@ -58,7 +61,7 @@ Terms to preserve (do not translate):
|
|
|
58
61
|
|
|
59
62
|
<example>
|
|
60
63
|
<example_item>
|
|
61
|
-
|
|
64
|
+
Table Translation - Demonstrates how to translate table content while preserving markdown structure and separators.
|
|
62
65
|
|
|
63
66
|
<before_translate>
|
|
64
67
|
| Name | Type | Description |
|
|
@@ -77,7 +80,8 @@ Terms to preserve (do not translate):
|
|
|
77
80
|
</example_item>
|
|
78
81
|
|
|
79
82
|
<example_item>
|
|
80
|
-
|
|
83
|
+
XField Component Translation - Shows how to translate only description content within x-field components while preserving all attributes.
|
|
84
|
+
|
|
81
85
|
<before_translate>
|
|
82
86
|
|
|
83
87
|
<x-field data-name="teamDid" data-type="string" data-required="true" data-desc="The DID of the team or Blocklet managing the webhook."></x-field>
|
|
@@ -96,9 +100,10 @@ Terms to preserve (do not translate):
|
|
|
96
100
|
</example_item>
|
|
97
101
|
|
|
98
102
|
<example_item>
|
|
99
|
-
|
|
103
|
+
Code Block Translation - Illustrates translating only comments in code blocks while keeping all code content unchanged.
|
|
100
104
|
|
|
101
105
|
<before_translate>
|
|
106
|
+
|
|
102
107
|
```xxx
|
|
103
108
|
// Initialize the API client
|
|
104
109
|
const client = new APIClient({
|
|
@@ -125,9 +130,11 @@ async function getUserData(userId) {
|
|
|
125
130
|
}
|
|
126
131
|
}
|
|
127
132
|
```
|
|
133
|
+
|
|
128
134
|
</before_translate>
|
|
129
135
|
|
|
130
136
|
<after_translate>
|
|
137
|
+
|
|
131
138
|
```xxx
|
|
132
139
|
// 初始化 API 客户端
|
|
133
140
|
const client = new APIClient({
|
|
@@ -154,13 +161,15 @@ async function getUserData(userId) {
|
|
|
154
161
|
}
|
|
155
162
|
}
|
|
156
163
|
```
|
|
164
|
+
|
|
157
165
|
</after_translate>
|
|
158
166
|
</example_item>
|
|
159
167
|
|
|
160
168
|
<example_item>
|
|
161
|
-
|
|
169
|
+
Command and Log Preservation - Demonstrates preserving command execution and log output without translation.
|
|
162
170
|
|
|
163
171
|
<before_translate>
|
|
172
|
+
|
|
164
173
|
```text Timeout Error Message
|
|
165
174
|
Blocklet Server failed to stop within 5 minutes
|
|
166
175
|
You can stop blocklet server with blocklet stop --force
|
|
@@ -171,9 +180,11 @@ $ cli log
|
|
|
171
180
|
|
|
172
181
|
Cache for server cleared: [list of cleared cache keys]
|
|
173
182
|
```
|
|
183
|
+
|
|
174
184
|
</before_translate>
|
|
175
185
|
|
|
176
186
|
<after_translate>
|
|
187
|
+
|
|
177
188
|
```text 超时错误消息
|
|
178
189
|
Blocklet Server failed to stop within 5 minutes
|
|
179
190
|
You can stop blocklet server with blocklet stop --force
|
|
@@ -184,6 +195,99 @@ $ cli log
|
|
|
184
195
|
|
|
185
196
|
Cache for server cleared: [list of cleared cache keys]
|
|
186
197
|
```
|
|
198
|
+
|
|
199
|
+
</after_translate>
|
|
200
|
+
</example_item>
|
|
201
|
+
|
|
202
|
+
<example_item>
|
|
203
|
+
D2 Diagram Translation - Shows how to translate only labels in D2 diagrams while preserving all syntax and structure.
|
|
204
|
+
|
|
205
|
+
<before_translate>
|
|
206
|
+
|
|
207
|
+
```d2 High-Level Architecture
|
|
208
|
+
direction: down
|
|
209
|
+
|
|
210
|
+
User: {
|
|
211
|
+
shape: c4-person
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
Your-Application: {
|
|
215
|
+
label: "Your Application"
|
|
216
|
+
shape: rectangle
|
|
217
|
+
|
|
218
|
+
PaymentProvider: {
|
|
219
|
+
label: "PaymentProvider"
|
|
220
|
+
shape: rectangle
|
|
221
|
+
|
|
222
|
+
Payment-Components: {
|
|
223
|
+
label: "Payment Components"
|
|
224
|
+
shape: rectangle
|
|
225
|
+
grid-columns: 2
|
|
226
|
+
|
|
227
|
+
CheckoutForm: { label: "CheckoutForm" }
|
|
228
|
+
CheckoutTable: { label: "CheckoutTable" }
|
|
229
|
+
CheckoutDonate: { label: "CheckoutDonate" }
|
|
230
|
+
CustomerInvoiceList: { label: "CustomerInvoiceList" }
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
Payment-Kit-Backend: {
|
|
236
|
+
label: "Payment Kit Backend"
|
|
237
|
+
shape: cylinder
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
User -> Your-Application.PaymentProvider.Payment-Components: "Interacts with UI"
|
|
241
|
+
Your-Application.PaymentProvider -> Payment-Kit-Backend: "Handles API Communication"
|
|
242
|
+
Payment-Kit-Backend -> Your-Application.PaymentProvider: "Returns Data"
|
|
243
|
+
Your-Application.PaymentProvider.Payment-Components -> User: "Renders UI Updates"
|
|
244
|
+
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
</before_translate>
|
|
248
|
+
|
|
249
|
+
<after_translate>
|
|
250
|
+
|
|
251
|
+
```d2 高层架构
|
|
252
|
+
direction: down
|
|
253
|
+
|
|
254
|
+
User: {
|
|
255
|
+
shape: c4-person
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
Your-Application: {
|
|
259
|
+
label: "您的应用程序"
|
|
260
|
+
shape: rectangle
|
|
261
|
+
|
|
262
|
+
PaymentProvider: {
|
|
263
|
+
label: "PaymentProvider"
|
|
264
|
+
shape: rectangle
|
|
265
|
+
|
|
266
|
+
Payment-Components: {
|
|
267
|
+
label: "支付组件"
|
|
268
|
+
shape: rectangle
|
|
269
|
+
grid-columns: 2
|
|
270
|
+
|
|
271
|
+
CheckoutForm: { label: "CheckoutForm" }
|
|
272
|
+
CheckoutTable: { label: "CheckoutTable" }
|
|
273
|
+
CheckoutDonate: { label: "CheckoutDonate" }
|
|
274
|
+
CustomerInvoiceList: { label: "CustomerInvoiceList" }
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
Payment-Kit-Backend: {
|
|
280
|
+
label: "Payment Kit 后端"
|
|
281
|
+
shape: cylinder
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
User -> Your-Application.PaymentProvider.Payment-Components: "与 UI 交互"
|
|
285
|
+
Your-Application.PaymentProvider -> Payment-Kit-Backend: "处理 API 通信"
|
|
286
|
+
Payment-Kit-Backend -> Your-Application.PaymentProvider: "返回数据"
|
|
287
|
+
Your-Application.PaymentProvider.Payment-Components -> User: "渲染 UI 更新"
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
|
|
187
291
|
</after_translate>
|
|
188
292
|
</example_item>
|
|
189
293
|
|
package/utils/file-utils.mjs
CHANGED
|
@@ -8,6 +8,8 @@ import { isBinaryFile } from "isbinaryfile";
|
|
|
8
8
|
import { encode } from "gpt-tokenizer";
|
|
9
9
|
import { fileTypeFromBuffer } from "file-type";
|
|
10
10
|
import { gunzipSync } from "node:zlib";
|
|
11
|
+
|
|
12
|
+
import { debug } from "./debug.mjs";
|
|
11
13
|
import { isGlobPattern } from "./utils.mjs";
|
|
12
14
|
import { INTELLIGENT_SUGGESTION_TOKEN_THRESHOLD } from "./constants/index.mjs";
|
|
13
15
|
import { uploadFiles } from "./upload-files.mjs";
|
|
@@ -284,6 +286,11 @@ export async function loadFilesFromPaths(sourcesPath, options = {}) {
|
|
|
284
286
|
continue;
|
|
285
287
|
}
|
|
286
288
|
|
|
289
|
+
if (checkIsRemoteFile(dir)) {
|
|
290
|
+
allFiles.push(dir);
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
|
|
287
294
|
// First try to access as a file or directory
|
|
288
295
|
const stats = await stat(dir);
|
|
289
296
|
|
|
@@ -313,7 +320,13 @@ export async function loadFilesFromPaths(sourcesPath, options = {}) {
|
|
|
313
320
|
: [];
|
|
314
321
|
|
|
315
322
|
finalIncludePatterns = [...defaultIncludePatterns, ...userInclude];
|
|
316
|
-
finalExcludePatterns = [
|
|
323
|
+
finalExcludePatterns = [
|
|
324
|
+
...defaultExcludePatterns,
|
|
325
|
+
...userExclude.map((x) => {
|
|
326
|
+
const prefix = `${dir}/`;
|
|
327
|
+
return x.startsWith(prefix) ? x.slice(prefix.length) : x;
|
|
328
|
+
}),
|
|
329
|
+
];
|
|
317
330
|
} else {
|
|
318
331
|
// Use only user patterns
|
|
319
332
|
if (includePatterns) {
|
|
@@ -374,6 +387,10 @@ export async function loadFilesFromPaths(sourcesPath, options = {}) {
|
|
|
374
387
|
* @returns {Promise<boolean>} True if file appears to be a text file
|
|
375
388
|
*/
|
|
376
389
|
async function isTextFile(filePath) {
|
|
390
|
+
if (checkIsRemoteFile(filePath)) {
|
|
391
|
+
return checkIsHttpTextFile(filePath);
|
|
392
|
+
}
|
|
393
|
+
|
|
377
394
|
try {
|
|
378
395
|
const isBinary = await isBinaryFile(filePath);
|
|
379
396
|
return !isBinary;
|
|
@@ -383,6 +400,53 @@ async function isTextFile(filePath) {
|
|
|
383
400
|
}
|
|
384
401
|
}
|
|
385
402
|
|
|
403
|
+
export function checkIsRemoteFile(filepath) {
|
|
404
|
+
if (filepath.startsWith("http://") || filepath.startsWith("https://")) {
|
|
405
|
+
return true;
|
|
406
|
+
}
|
|
407
|
+
return false;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export async function checkIsHttpTextFile(fileUrl) {
|
|
411
|
+
try {
|
|
412
|
+
const res = await fetch(fileUrl, {
|
|
413
|
+
method: "HEAD",
|
|
414
|
+
});
|
|
415
|
+
const contentType = res.headers.get("content-type") || "";
|
|
416
|
+
const textMimeTypes = [
|
|
417
|
+
"application/json",
|
|
418
|
+
"application/ld+json",
|
|
419
|
+
"application/graphql+json",
|
|
420
|
+
"application/xml",
|
|
421
|
+
"application/xhtml+xml",
|
|
422
|
+
"application/javascript",
|
|
423
|
+
"application/ecmascript",
|
|
424
|
+
"application/x-www-form-urlencoded",
|
|
425
|
+
"application/rss+xml",
|
|
426
|
+
"application/atom+xml",
|
|
427
|
+
];
|
|
428
|
+
if (contentType.startsWith("text/") || textMimeTypes.includes(contentType)) {
|
|
429
|
+
return true;
|
|
430
|
+
}
|
|
431
|
+
return false;
|
|
432
|
+
} catch (error) {
|
|
433
|
+
debug(`Failed to check HTTP file content type: ${fileUrl} - ${error.message}`);
|
|
434
|
+
return null;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export async function getHttpFileContent(file) {
|
|
439
|
+
if (!file) return null;
|
|
440
|
+
try {
|
|
441
|
+
const res = await fetch(file);
|
|
442
|
+
const text = await res.text();
|
|
443
|
+
return text;
|
|
444
|
+
} catch (error) {
|
|
445
|
+
debug(`Failed to fetch HTTP file content: ${file} - ${error.message}`);
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
386
450
|
/**
|
|
387
451
|
* Read and parse file contents from an array of file paths
|
|
388
452
|
* @param {string[]} files - Array of file paths to read
|
|
@@ -405,12 +469,24 @@ export async function readFileContents(files, baseDir = process.cwd(), options =
|
|
|
405
469
|
}
|
|
406
470
|
|
|
407
471
|
try {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
472
|
+
if (checkIsRemoteFile(file)) {
|
|
473
|
+
const content = await getHttpFileContent(file);
|
|
474
|
+
if (content) {
|
|
475
|
+
return {
|
|
476
|
+
sourceId: file,
|
|
477
|
+
content,
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
return null;
|
|
482
|
+
} else {
|
|
483
|
+
const content = await readFile(file, "utf8");
|
|
484
|
+
const relativePath = path.relative(baseDir, file);
|
|
485
|
+
return {
|
|
486
|
+
sourceId: relativePath,
|
|
487
|
+
content,
|
|
488
|
+
};
|
|
489
|
+
}
|
|
414
490
|
} catch (error) {
|
|
415
491
|
// If reading as text fails (e.g., binary file), skip it
|
|
416
492
|
console.warn(`Failed to read file as text: ${file} - ${error.message}`);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { parse } from "yaml";
|
|
2
|
+
|
|
3
|
+
export function isOpenAPISpecFile(content) {
|
|
4
|
+
const trimmedContent = content.trim();
|
|
5
|
+
try {
|
|
6
|
+
const parsed = parse(trimmedContent, {
|
|
7
|
+
logLevel: "silent",
|
|
8
|
+
});
|
|
9
|
+
if (parsed.openapi || parsed.swagger) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
} catch {
|
|
13
|
+
//
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const parsed = JSON.parse(trimmedContent);
|
|
17
|
+
if (parsed.openapi || parsed.swagger) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
} catch {
|
|
21
|
+
//
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|