@aigne/doc-smith 0.9.8-alpha.3 → 0.9.8-alpha.5
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/CLAUDE.md +43 -0
- package/README.md +94 -250
- package/aigne.yaml +5 -146
- package/doc-smith/SKILL.md +117 -0
- package/doc-smith/references/changeset_schema.md +118 -0
- package/doc-smith/references/document_structure_schema.md +139 -0
- package/doc-smith/references/document_update_guide.md +193 -0
- package/doc-smith/references/structure_confirmation_guide.md +133 -0
- package/doc-smith/references/structure_planning_guide.md +146 -0
- package/doc-smith/references/user_intent_guide.md +172 -0
- package/doc-smith.yaml +114 -0
- package/main-system-prompt.md +56 -0
- package/package.json +3 -69
- package/scripts/README.md +90 -0
- package/scripts/install.sh +86 -0
- package/scripts/uninstall.sh +52 -0
- package/CHANGELOG.md +0 -994
- package/LICENSE +0 -93
- package/agentic-agents/common/base-info.md +0 -53
- package/agentic-agents/common/completer.md +0 -54
- package/agentic-agents/common/planner.md +0 -168
- package/agentic-agents/common/worker.md +0 -93
- package/agentic-agents/create/index.yaml +0 -129
- package/agentic-agents/create/objective.md +0 -44
- package/agentic-agents/create/set-custom-prompt.mjs +0 -27
- package/agentic-agents/detail/index.yaml +0 -95
- package/agentic-agents/detail/objective.md +0 -9
- package/agentic-agents/detail/set-custom-prompt.mjs +0 -88
- package/agentic-agents/predict-resources/index.yaml +0 -44
- package/agentic-agents/predict-resources/instructions.md +0 -61
- package/agentic-agents/structure/design-rules.md +0 -39
- package/agentic-agents/structure/index.yaml +0 -86
- package/agentic-agents/structure/objective.md +0 -14
- package/agentic-agents/structure/review-criteria.md +0 -55
- package/agentic-agents/structure/set-custom-prompt.mjs +0 -78
- package/agentic-agents/utils/init-workspace-cache.mjs +0 -171
- package/agentic-agents/utils/load-base-sources.mjs +0 -20
- package/agentic-agents/workspace-cache-sharing-design.md +0 -671
- package/agents/chat/chat-system.md +0 -38
- package/agents/chat/index.mjs +0 -59
- package/agents/chat/skills/generate-document.yaml +0 -15
- package/agents/chat/skills/list-documents.mjs +0 -15
- package/agents/chat/skills/update-document.yaml +0 -24
- package/agents/clear/choose-contents.mjs +0 -192
- package/agents/clear/clear-auth-tokens.mjs +0 -88
- package/agents/clear/clear-deployment-config.mjs +0 -49
- package/agents/clear/clear-document-config.mjs +0 -36
- package/agents/clear/clear-document-structure.mjs +0 -102
- package/agents/clear/clear-generated-docs.mjs +0 -142
- package/agents/clear/clear-media-description.mjs +0 -129
- package/agents/clear/index.yaml +0 -26
- package/agents/create/analyze-diagram-type-llm.yaml +0 -160
- package/agents/create/analyze-diagram-type.mjs +0 -297
- package/agents/create/check-document-structure.yaml +0 -30
- package/agents/create/check-need-generate-structure.mjs +0 -105
- package/agents/create/document-structure-tools/add-document.mjs +0 -85
- package/agents/create/document-structure-tools/delete-document.mjs +0 -116
- package/agents/create/document-structure-tools/move-document.mjs +0 -109
- package/agents/create/document-structure-tools/update-document.mjs +0 -84
- package/agents/create/generate-diagram-image.yaml +0 -60
- package/agents/create/generate-structure.yaml +0 -117
- package/agents/create/index.yaml +0 -49
- package/agents/create/refine-document-structure.yaml +0 -12
- package/agents/create/replace-d2-with-image.mjs +0 -625
- package/agents/create/update-document-structure.yaml +0 -54
- package/agents/create/user-add-document/add-documents-to-structure.mjs +0 -90
- package/agents/create/user-add-document/find-documents-to-add-links.yaml +0 -47
- package/agents/create/user-add-document/index.yaml +0 -46
- package/agents/create/user-add-document/prepare-documents-to-translate.mjs +0 -22
- package/agents/create/user-add-document/print-add-document-summary.mjs +0 -63
- package/agents/create/user-add-document/review-documents-with-new-links.mjs +0 -110
- package/agents/create/user-remove-document/find-documents-with-invalid-links.mjs +0 -78
- package/agents/create/user-remove-document/index.yaml +0 -40
- package/agents/create/user-remove-document/prepare-documents-to-translate.mjs +0 -22
- package/agents/create/user-remove-document/print-remove-document-summary.mjs +0 -53
- package/agents/create/user-remove-document/remove-documents-from-structure.mjs +0 -99
- package/agents/create/user-remove-document/review-documents-with-invalid-links.mjs +0 -115
- package/agents/create/user-review-document-structure.mjs +0 -140
- package/agents/create/utils/init-current-content.mjs +0 -34
- package/agents/create/utils/merge-document-structures.mjs +0 -30
- package/agents/evaluate/code-snippet.mjs +0 -97
- package/agents/evaluate/document-structure.yaml +0 -67
- package/agents/evaluate/document.yaml +0 -82
- package/agents/evaluate/generate-report.mjs +0 -85
- package/agents/evaluate/index.yaml +0 -46
- package/agents/history/index.yaml +0 -6
- package/agents/history/view.mjs +0 -78
- package/agents/init/check.mjs +0 -16
- package/agents/init/index.mjs +0 -275
- package/agents/init/validate.mjs +0 -16
- package/agents/localize/choose-language.mjs +0 -107
- package/agents/localize/index.yaml +0 -58
- package/agents/localize/record-translation-history.mjs +0 -23
- package/agents/localize/translate-document.yaml +0 -24
- package/agents/localize/translate-multilingual.yaml +0 -51
- package/agents/media/batch-generate-media-description.yaml +0 -46
- package/agents/media/generate-media-description.yaml +0 -50
- package/agents/media/load-media-description.mjs +0 -256
- package/agents/prefs/index.mjs +0 -203
- package/agents/publish/index.yaml +0 -26
- package/agents/publish/publish-docs.mjs +0 -356
- package/agents/publish/translate-meta.mjs +0 -103
- package/agents/schema/document-structure-item.yaml +0 -26
- package/agents/schema/document-structure-refine-item.yaml +0 -23
- package/agents/schema/document-structure.yaml +0 -29
- package/agents/update/batch-generate-document.yaml +0 -27
- package/agents/update/batch-update-document.yaml +0 -7
- package/agents/update/check-diagram-flag.mjs +0 -116
- package/agents/update/check-document.mjs +0 -162
- package/agents/update/check-generate-diagram.mjs +0 -106
- package/agents/update/check-sync-image-flag.mjs +0 -55
- package/agents/update/check-update-is-single.mjs +0 -53
- package/agents/update/document-tools/update-document-content.mjs +0 -303
- package/agents/update/generate-diagram.yaml +0 -63
- package/agents/update/generate-document.yaml +0 -70
- package/agents/update/handle-document-update.yaml +0 -103
- package/agents/update/index.yaml +0 -79
- package/agents/update/pre-check-generate-diagram.yaml +0 -44
- package/agents/update/save-and-translate-document.mjs +0 -76
- package/agents/update/sync-images-and-exit.mjs +0 -148
- package/agents/update/update-document-detail.yaml +0 -71
- package/agents/update/update-single/update-single-document-detail.mjs +0 -280
- package/agents/update/update-single-document.yaml +0 -7
- package/agents/update/user-review-document.mjs +0 -272
- package/agents/utils/action-success.mjs +0 -16
- package/agents/utils/analyze-document-feedback-intent.yaml +0 -32
- package/agents/utils/analyze-feedback-intent.mjs +0 -136
- package/agents/utils/analyze-structure-feedback-intent.yaml +0 -29
- package/agents/utils/check-detail-result.mjs +0 -38
- package/agents/utils/check-feedback-refiner.mjs +0 -81
- package/agents/utils/choose-docs.mjs +0 -293
- package/agents/utils/document-icon-generate.yaml +0 -52
- package/agents/utils/document-title-streamline.yaml +0 -48
- package/agents/utils/ensure-document-icons.mjs +0 -129
- package/agents/utils/exit.mjs +0 -6
- package/agents/utils/feedback-refiner.yaml +0 -50
- package/agents/utils/find-item-by-path.mjs +0 -114
- package/agents/utils/find-user-preferences-by-path.mjs +0 -37
- package/agents/utils/format-document-structure.mjs +0 -35
- package/agents/utils/generate-document-or-skip.mjs +0 -41
- package/agents/utils/handle-diagram-operations.mjs +0 -263
- package/agents/utils/load-all-document-content.mjs +0 -30
- package/agents/utils/load-document-all-content.mjs +0 -84
- package/agents/utils/load-sources.mjs +0 -405
- package/agents/utils/map-reasoning-effort-level.mjs +0 -15
- package/agents/utils/post-generate.mjs +0 -144
- package/agents/utils/read-current-document-content.mjs +0 -46
- package/agents/utils/save-doc-translation.mjs +0 -61
- package/agents/utils/save-doc.mjs +0 -88
- package/agents/utils/save-output.mjs +0 -26
- package/agents/utils/save-sidebar.mjs +0 -51
- package/agents/utils/skip-if-content-exists.mjs +0 -27
- package/agents/utils/streamline-document-titles-if-needed.mjs +0 -88
- package/agents/utils/transform-detail-data-sources.mjs +0 -45
- package/agents/utils/update-branding.mjs +0 -84
- package/assets/report-template/report.html +0 -198
- package/docs-mcp/analyze-content-relevance.yaml +0 -50
- package/docs-mcp/analyze-docs-relevance.yaml +0 -59
- package/docs-mcp/docs-search.yaml +0 -42
- package/docs-mcp/get-docs-detail.mjs +0 -41
- package/docs-mcp/get-docs-structure.mjs +0 -16
- package/docs-mcp/read-doc-content.mjs +0 -119
- package/prompts/common/document/content-rules-core.md +0 -20
- package/prompts/common/document/markdown-syntax-rules.md +0 -65
- package/prompts/common/document/media-file-list-usage-rules.md +0 -18
- package/prompts/common/document/openapi-usage-rules.md +0 -189
- package/prompts/common/document/role-and-personality.md +0 -16
- package/prompts/common/document/user-preferences.md +0 -9
- package/prompts/common/document-structure/conflict-resolution-guidance.md +0 -16
- package/prompts/common/document-structure/document-icon-generate.md +0 -116
- package/prompts/common/document-structure/document-structure-rules.md +0 -43
- package/prompts/common/document-structure/document-title-streamline.md +0 -86
- package/prompts/common/document-structure/glossary.md +0 -7
- package/prompts/common/document-structure/intj-traits.md +0 -5
- package/prompts/common/document-structure/openapi-usage-rules.md +0 -28
- package/prompts/common/document-structure/output-constraints.md +0 -18
- package/prompts/common/document-structure/user-locale-rules.md +0 -10
- package/prompts/common/document-structure/user-preferences.md +0 -9
- package/prompts/detail/custom/admonition-usage-rules.md +0 -94
- package/prompts/detail/custom/code-block-usage-rules.md +0 -163
- package/prompts/detail/custom/custom-components/x-card-usage-rules.md +0 -63
- package/prompts/detail/custom/custom-components/x-cards-usage-rules.md +0 -83
- package/prompts/detail/custom/custom-components/x-field-desc-usage-rules.md +0 -120
- package/prompts/detail/custom/custom-components/x-field-group-usage-rules.md +0 -80
- package/prompts/detail/custom/custom-components/x-field-usage-rules.md +0 -189
- package/prompts/detail/custom/custom-components-usage-rules.md +0 -18
- package/prompts/detail/diagram/generate-image-system.md +0 -135
- package/prompts/detail/diagram/generate-image-user.md +0 -32
- package/prompts/detail/diagram/guide.md +0 -29
- package/prompts/detail/diagram/official-examples.md +0 -712
- package/prompts/detail/diagram/pre-check.md +0 -23
- package/prompts/detail/diagram/role-and-personality.md +0 -2
- package/prompts/detail/diagram/rules.md +0 -46
- package/prompts/detail/diagram/system-prompt.md +0 -1139
- package/prompts/detail/diagram/user-prompt.md +0 -43
- package/prompts/detail/generate/detail-example.md +0 -457
- package/prompts/detail/generate/document-rules.md +0 -45
- package/prompts/detail/generate/system-prompt.md +0 -61
- package/prompts/detail/generate/user-prompt.md +0 -99
- package/prompts/detail/jsx/rules.md +0 -6
- package/prompts/detail/update/system-prompt.md +0 -121
- package/prompts/detail/update/user-prompt.md +0 -41
- package/prompts/evaluate/document-structure.md +0 -93
- package/prompts/evaluate/document.md +0 -149
- package/prompts/media/media-description/system-prompt.md +0 -43
- package/prompts/media/media-description/user-prompt.md +0 -17
- package/prompts/structure/check-document-structure.md +0 -93
- package/prompts/structure/document-rules.md +0 -21
- package/prompts/structure/find-documents-to-add-links.md +0 -52
- package/prompts/structure/generate/system-prompt.md +0 -13
- package/prompts/structure/generate/user-prompt.md +0 -137
- package/prompts/structure/review/structure-review-system.md +0 -81
- package/prompts/structure/structure-example.md +0 -89
- package/prompts/structure/structure-getting-started.md +0 -10
- package/prompts/structure/update/system-prompt.md +0 -93
- package/prompts/structure/update/user-prompt.md +0 -43
- package/prompts/translate/admonition.md +0 -20
- package/prompts/translate/code-block.md +0 -33
- package/prompts/translate/glossary.md +0 -6
- package/prompts/translate/translate-document.md +0 -305
- package/prompts/utils/analyze-document-feedback-intent.md +0 -54
- package/prompts/utils/analyze-structure-feedback-intent.md +0 -43
- package/prompts/utils/feedback-refiner.md +0 -105
- package/types/document-schema.mjs +0 -55
- package/types/document-structure-schema.mjs +0 -261
- package/utils/auth-utils.mjs +0 -275
- package/utils/blocklet.mjs +0 -104
- package/utils/check-document-has-diagram.mjs +0 -95
- package/utils/conflict-detector.mjs +0 -149
- package/utils/constants/index.mjs +0 -620
- package/utils/constants/linter.mjs +0 -102
- package/utils/d2-utils.mjs +0 -198
- package/utils/debug.mjs +0 -3
- package/utils/delete-diagram-images.mjs +0 -99
- package/utils/deploy.mjs +0 -86
- package/utils/docs-finder-utils.mjs +0 -623
- package/utils/evaluate/report-utils.mjs +0 -132
- package/utils/extract-api.mjs +0 -32
- package/utils/file-utils.mjs +0 -960
- package/utils/history-utils.mjs +0 -203
- package/utils/icon-map.mjs +0 -26
- package/utils/image-compress.mjs +0 -75
- package/utils/kroki-utils.mjs +0 -173
- package/utils/linter/index.mjs +0 -50
- package/utils/load-config.mjs +0 -107
- package/utils/markdown/index.mjs +0 -26
- package/utils/markdown-checker.mjs +0 -694
- package/utils/mermaid-validator.mjs +0 -140
- package/utils/mermaid-worker-pool.mjs +0 -250
- package/utils/mermaid-worker.mjs +0 -233
- package/utils/openapi/index.mjs +0 -28
- package/utils/preferences-utils.mjs +0 -175
- package/utils/request.mjs +0 -10
- package/utils/store/index.mjs +0 -45
- package/utils/sync-diagram-to-translations.mjs +0 -262
- package/utils/upload-files.mjs +0 -231
- package/utils/utils.mjs +0 -1354
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Simplified Mermaid validation using Worker Thread pool
|
|
3
|
-
* Provides concurrent-safe validation with isolated worker environments
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { getMermaidWorkerPool, shutdownMermaidWorkerPool } from "./mermaid-worker-pool.mjs";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Basic mermaid syntax validation fallback
|
|
10
|
-
* Used when worker validation fails due to environment issues
|
|
11
|
-
* @param {string} content - Mermaid diagram content
|
|
12
|
-
* @returns {boolean} - True if basic validation passes
|
|
13
|
-
* @throws {Error} - If validation fails
|
|
14
|
-
*/
|
|
15
|
-
export function validateBasicMermaidSyntax(content) {
|
|
16
|
-
const trimmedContent = content.trim();
|
|
17
|
-
|
|
18
|
-
if (!trimmedContent) {
|
|
19
|
-
throw new Error("Empty mermaid diagram");
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Check for valid diagram type
|
|
23
|
-
const validDiagramTypes = [
|
|
24
|
-
"flowchart",
|
|
25
|
-
"graph",
|
|
26
|
-
"sequenceDiagram",
|
|
27
|
-
"classDiagram",
|
|
28
|
-
"stateDiagram",
|
|
29
|
-
"entityRelationshipDiagram",
|
|
30
|
-
"erDiagram",
|
|
31
|
-
"journey",
|
|
32
|
-
"gantt",
|
|
33
|
-
"pie",
|
|
34
|
-
"requirement",
|
|
35
|
-
"gitgraph",
|
|
36
|
-
"mindmap",
|
|
37
|
-
"timeline",
|
|
38
|
-
"quadrantChart",
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
const firstLine = trimmedContent.split("\n")[0].trim();
|
|
42
|
-
const hasValidType = validDiagramTypes.some((type) => firstLine.includes(type));
|
|
43
|
-
|
|
44
|
-
if (!hasValidType) {
|
|
45
|
-
throw new Error("Invalid or missing diagram type");
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Basic bracket matching
|
|
49
|
-
const openBrackets = (content.match(/[[{(]/g) || []).length;
|
|
50
|
-
const closeBrackets = (content.match(/[\]})]/g) || []).length;
|
|
51
|
-
|
|
52
|
-
if (openBrackets !== closeBrackets) {
|
|
53
|
-
throw new Error("Unmatched brackets in diagram");
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Basic quote matching
|
|
57
|
-
const singleQuotes = (content.match(/'/g) || []).length;
|
|
58
|
-
const doubleQuotes = (content.match(/"/g) || []).length;
|
|
59
|
-
|
|
60
|
-
if (singleQuotes % 2 !== 0) {
|
|
61
|
-
throw new Error("Unmatched single quotes in diagram");
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (doubleQuotes % 2 !== 0) {
|
|
65
|
-
throw new Error("Unmatched double quotes in diagram");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Main validation function using simplified worker pool for concurrency safety
|
|
73
|
-
* @param {string} content - Mermaid diagram content
|
|
74
|
-
* @returns {Promise<boolean>} - True if validation passes
|
|
75
|
-
* @throws {Error} - If validation fails
|
|
76
|
-
*/
|
|
77
|
-
export async function validateMermaidSyntax(content) {
|
|
78
|
-
if (!content || !content.trim()) {
|
|
79
|
-
throw new Error("Empty mermaid diagram");
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
try {
|
|
83
|
-
// Use simplified worker pool for validation
|
|
84
|
-
const workerPool = getMermaidWorkerPool({
|
|
85
|
-
poolSize: 2, // Reduced pool size
|
|
86
|
-
timeout: 10000, // Reduced timeout
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
const result = await workerPool.validate(content);
|
|
90
|
-
return result;
|
|
91
|
-
} catch (error) {
|
|
92
|
-
// If worker validation fails, check if it's an environment issue
|
|
93
|
-
const errorMsg = error.message || String(error);
|
|
94
|
-
|
|
95
|
-
if (
|
|
96
|
-
errorMsg.includes("Worker error") ||
|
|
97
|
-
errorMsg.includes("Worker exited") ||
|
|
98
|
-
errorMsg.includes("Worker pool") ||
|
|
99
|
-
errorMsg.includes("timeout") ||
|
|
100
|
-
errorMsg.includes("Cannot resolve module") ||
|
|
101
|
-
errorMsg.includes("window is not defined") ||
|
|
102
|
-
errorMsg.includes("canvas") ||
|
|
103
|
-
errorMsg.includes("Web APIs") ||
|
|
104
|
-
errorMsg.includes("getComputedTextLength") ||
|
|
105
|
-
errorMsg.includes("document is not defined")
|
|
106
|
-
) {
|
|
107
|
-
// Fall back to basic validation for environment issues
|
|
108
|
-
console.warn(
|
|
109
|
-
"Worker-based mermaid validation failed, falling back to basic validation:",
|
|
110
|
-
errorMsg,
|
|
111
|
-
);
|
|
112
|
-
return validateBasicMermaidSyntax(content);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// If it's a genuine syntax error, re-throw it
|
|
116
|
-
throw error;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Get worker pool statistics for monitoring
|
|
122
|
-
* @returns {Object} - Pool statistics
|
|
123
|
-
*/
|
|
124
|
-
export function getValidationStats() {
|
|
125
|
-
try {
|
|
126
|
-
const workerPool = getMermaidWorkerPool();
|
|
127
|
-
return workerPool.getStats();
|
|
128
|
-
} catch (error) {
|
|
129
|
-
return { error: error.message };
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Shutdown the validation worker pool
|
|
135
|
-
* Call this when shutting down the application
|
|
136
|
-
* @returns {Promise<void>}
|
|
137
|
-
*/
|
|
138
|
-
export async function shutdownValidation() {
|
|
139
|
-
await shutdownMermaidWorkerPool();
|
|
140
|
-
}
|
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Simplified Mermaid Worker Pool
|
|
5
|
-
* Manages worker threads for concurrent mermaid validation
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { dirname, join } from "node:path";
|
|
9
|
-
import { fileURLToPath } from "node:url";
|
|
10
|
-
import { Worker } from "node:worker_threads";
|
|
11
|
-
|
|
12
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
-
const __dirname = dirname(__filename);
|
|
14
|
-
|
|
15
|
-
class SimpleMermaidWorkerPool {
|
|
16
|
-
constructor(options = {}) {
|
|
17
|
-
this.poolSize = options.poolSize || 3;
|
|
18
|
-
this.timeout = options.timeout || 15000; // Reduced timeout
|
|
19
|
-
|
|
20
|
-
this.workers = [];
|
|
21
|
-
this.availableWorkers = [];
|
|
22
|
-
this.requestQueue = [];
|
|
23
|
-
this.nextRequestId = 1;
|
|
24
|
-
this.isShuttingDown = false;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Initialize worker pool
|
|
29
|
-
*/
|
|
30
|
-
async initialize() {
|
|
31
|
-
if (this.workers.length > 0) return; // Already initialized
|
|
32
|
-
|
|
33
|
-
const workerPath = join(__dirname, "mermaid-worker.mjs");
|
|
34
|
-
|
|
35
|
-
for (let i = 0; i < this.poolSize; i++) {
|
|
36
|
-
await this.createWorker(workerPath, i);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Create a single worker
|
|
42
|
-
*/
|
|
43
|
-
async createWorker(workerPath, workerId) {
|
|
44
|
-
return new Promise((resolve, reject) => {
|
|
45
|
-
try {
|
|
46
|
-
const worker = new Worker(workerPath);
|
|
47
|
-
worker.workerId = workerId;
|
|
48
|
-
worker.isAvailable = true;
|
|
49
|
-
worker.currentRequest = null;
|
|
50
|
-
|
|
51
|
-
// Handle worker errors more gracefully
|
|
52
|
-
worker.on("error", (error) => {
|
|
53
|
-
if (worker.currentRequest) {
|
|
54
|
-
worker.currentRequest.reject(new Error(`Worker error: ${error.message}`));
|
|
55
|
-
worker.currentRequest = null;
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
worker.on("exit", (_code) => {
|
|
60
|
-
if (worker.currentRequest) {
|
|
61
|
-
worker.currentRequest.reject(new Error("Worker exited unexpectedly"));
|
|
62
|
-
worker.currentRequest = null;
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
worker.on("message", (data) => {
|
|
67
|
-
this.handleWorkerMessage(worker, data);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
this.workers.push(worker);
|
|
71
|
-
this.availableWorkers.push(worker);
|
|
72
|
-
|
|
73
|
-
resolve(worker);
|
|
74
|
-
} catch (error) {
|
|
75
|
-
reject(error);
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Handle worker message
|
|
82
|
-
*/
|
|
83
|
-
handleWorkerMessage(worker, data) {
|
|
84
|
-
if (!worker.currentRequest) return;
|
|
85
|
-
|
|
86
|
-
const { resolve, reject, timeoutId } = worker.currentRequest;
|
|
87
|
-
|
|
88
|
-
// Clear timeout
|
|
89
|
-
if (timeoutId) {
|
|
90
|
-
clearTimeout(timeoutId);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Reset worker state
|
|
94
|
-
worker.currentRequest = null;
|
|
95
|
-
worker.isAvailable = true;
|
|
96
|
-
|
|
97
|
-
// Move worker back to available pool
|
|
98
|
-
const workerIndex = this.workers.indexOf(worker);
|
|
99
|
-
if (workerIndex > -1 && !this.availableWorkers.includes(worker)) {
|
|
100
|
-
this.availableWorkers.push(worker);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Process queued requests
|
|
104
|
-
this.processQueue();
|
|
105
|
-
|
|
106
|
-
// Handle response
|
|
107
|
-
if (data.error) {
|
|
108
|
-
reject(new Error(data.error));
|
|
109
|
-
} else {
|
|
110
|
-
resolve(data.result);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Process queued requests
|
|
116
|
-
*/
|
|
117
|
-
processQueue() {
|
|
118
|
-
while (this.requestQueue.length > 0 && this.availableWorkers.length > 0) {
|
|
119
|
-
const queuedRequest = this.requestQueue.shift();
|
|
120
|
-
const worker = this.availableWorkers.shift();
|
|
121
|
-
|
|
122
|
-
this.executeRequest(worker, queuedRequest);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Execute a request on a worker
|
|
128
|
-
*/
|
|
129
|
-
executeRequest(worker, request) {
|
|
130
|
-
const { content, resolve, reject } = request;
|
|
131
|
-
const requestId = this.nextRequestId++;
|
|
132
|
-
|
|
133
|
-
// Set timeout
|
|
134
|
-
const timeoutId = setTimeout(() => {
|
|
135
|
-
worker.currentRequest = null;
|
|
136
|
-
worker.isAvailable = true;
|
|
137
|
-
if (!this.availableWorkers.includes(worker)) {
|
|
138
|
-
this.availableWorkers.push(worker);
|
|
139
|
-
}
|
|
140
|
-
reject(new Error(`Validation timeout after ${this.timeout}ms`));
|
|
141
|
-
}, this.timeout);
|
|
142
|
-
|
|
143
|
-
// Store request info
|
|
144
|
-
worker.currentRequest = { resolve, reject, timeoutId };
|
|
145
|
-
worker.isAvailable = false;
|
|
146
|
-
|
|
147
|
-
// Send request
|
|
148
|
-
worker.postMessage({
|
|
149
|
-
id: requestId,
|
|
150
|
-
content: content,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Validate content using worker pool
|
|
156
|
-
*/
|
|
157
|
-
async validate(content) {
|
|
158
|
-
if (this.isShuttingDown) {
|
|
159
|
-
throw new Error("Worker pool is shutting down");
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Initialize if needed
|
|
163
|
-
await this.initialize();
|
|
164
|
-
|
|
165
|
-
return new Promise((resolve, reject) => {
|
|
166
|
-
const request = { content, resolve, reject };
|
|
167
|
-
|
|
168
|
-
// If worker available, use it immediately
|
|
169
|
-
if (this.availableWorkers.length > 0) {
|
|
170
|
-
const worker = this.availableWorkers.shift();
|
|
171
|
-
this.executeRequest(worker, request);
|
|
172
|
-
} else {
|
|
173
|
-
// Queue the request
|
|
174
|
-
this.requestQueue.push(request);
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Get pool statistics
|
|
181
|
-
*/
|
|
182
|
-
getStats() {
|
|
183
|
-
return {
|
|
184
|
-
poolSize: this.poolSize,
|
|
185
|
-
totalWorkers: this.workers.length,
|
|
186
|
-
availableWorkers: this.availableWorkers.length,
|
|
187
|
-
busyWorkers: this.workers.length - this.availableWorkers.length,
|
|
188
|
-
queuedRequests: this.requestQueue.length,
|
|
189
|
-
isShuttingDown: this.isShuttingDown,
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Shutdown the pool
|
|
195
|
-
*/
|
|
196
|
-
async shutdown() {
|
|
197
|
-
if (this.isShuttingDown) return;
|
|
198
|
-
|
|
199
|
-
this.isShuttingDown = true;
|
|
200
|
-
|
|
201
|
-
// Reject all queued requests
|
|
202
|
-
while (this.requestQueue.length > 0) {
|
|
203
|
-
const request = this.requestQueue.shift();
|
|
204
|
-
request.reject(new Error("Worker pool is shutting down"));
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Terminate all workers
|
|
208
|
-
const terminationPromises = this.workers.map(async (worker) => {
|
|
209
|
-
try {
|
|
210
|
-
await worker.terminate();
|
|
211
|
-
} catch (_error) {
|
|
212
|
-
// Ignore termination errors
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
await Promise.allSettled(terminationPromises);
|
|
217
|
-
|
|
218
|
-
// Clear arrays
|
|
219
|
-
this.workers.length = 0;
|
|
220
|
-
this.availableWorkers.length = 0;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// Global pool instance
|
|
225
|
-
let globalPool = null;
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Get global worker pool
|
|
229
|
-
*/
|
|
230
|
-
export function getMermaidWorkerPool(options = {}) {
|
|
231
|
-
if (!globalPool) {
|
|
232
|
-
globalPool = new SimpleMermaidWorkerPool(options);
|
|
233
|
-
}
|
|
234
|
-
return globalPool;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Shutdown global pool
|
|
239
|
-
*/
|
|
240
|
-
export async function shutdownMermaidWorkerPool() {
|
|
241
|
-
if (globalPool) {
|
|
242
|
-
await globalPool.shutdown();
|
|
243
|
-
globalPool = null;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Note: We don't add global process event listeners here to avoid preventing clean exit
|
|
248
|
-
// The application should call shutdownMermaidWorkerPool() explicitly when needed
|
|
249
|
-
|
|
250
|
-
export { SimpleMermaidWorkerPool };
|
package/utils/mermaid-worker.mjs
DELETED
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Simplified Mermaid Validation Worker
|
|
5
|
-
* Runs in isolated Worker thread to avoid global state conflicts
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { parentPort } from "node:worker_threads";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Validate mermaid syntax using official parser in isolated environment
|
|
12
|
-
*/
|
|
13
|
-
async function validateMermaidWithOfficialParser(content) {
|
|
14
|
-
const trimmedContent = content.trim();
|
|
15
|
-
if (!content || !trimmedContent) {
|
|
16
|
-
throw new Error("Empty mermaid diagram");
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
// Import dependencies
|
|
21
|
-
const { JSDOM } = await import("jsdom");
|
|
22
|
-
const DOMPurifyModule = await import("dompurify");
|
|
23
|
-
|
|
24
|
-
// Create isolated DOM environment
|
|
25
|
-
const { window } = new JSDOM(`<!DOCTYPE html><html><body></body></html>`, {
|
|
26
|
-
pretendToBeVisual: true,
|
|
27
|
-
resources: "usable",
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
// Setup globals (safe in worker - no conflicts)
|
|
31
|
-
global.window = window;
|
|
32
|
-
global.document = window.document;
|
|
33
|
-
|
|
34
|
-
// Only set navigator if it doesn't exist
|
|
35
|
-
if (!global.navigator) {
|
|
36
|
-
global.navigator = {
|
|
37
|
-
userAgent: "node.js",
|
|
38
|
-
platform: "node",
|
|
39
|
-
cookieEnabled: false,
|
|
40
|
-
onLine: true,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
global.DOMParser = window.DOMParser;
|
|
45
|
-
global.XMLSerializer = window.XMLSerializer;
|
|
46
|
-
global.HTMLElement = window.HTMLElement;
|
|
47
|
-
global.HTMLDivElement = window.HTMLDivElement;
|
|
48
|
-
global.SVGElement = window.SVGElement;
|
|
49
|
-
global.Element = window.Element;
|
|
50
|
-
global.Node = window.Node;
|
|
51
|
-
|
|
52
|
-
// Initialize DOMPurify with the JSDOM window
|
|
53
|
-
const dompurify = DOMPurifyModule.default(window);
|
|
54
|
-
|
|
55
|
-
// Verify DOMPurify is working before proceeding
|
|
56
|
-
if (typeof dompurify.sanitize !== "function") {
|
|
57
|
-
throw new Error("DOMPurify initialization failed - sanitize method not available");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Test DOMPurify functionality
|
|
61
|
-
dompurify.sanitize("<p>test</p>");
|
|
62
|
-
|
|
63
|
-
// Step 5: Comprehensively set up DOMPurify in all possible global locations
|
|
64
|
-
global.DOMPurify = dompurify;
|
|
65
|
-
window.DOMPurify = dompurify;
|
|
66
|
-
|
|
67
|
-
// For ES module interception, we need to ensure DOMPurify is available
|
|
68
|
-
// in all the ways mermaid might try to access it
|
|
69
|
-
if (typeof globalThis !== "undefined") {
|
|
70
|
-
globalThis.DOMPurify = dompurify;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Set up on the global scope itself
|
|
74
|
-
if (typeof self !== "undefined") {
|
|
75
|
-
self.DOMPurify = dompurify;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// CRITICAL: Override the DOMPurify constructor/factory to always use our window
|
|
79
|
-
// This is the key to solving the issue: mermaid imports DOMPurify directly
|
|
80
|
-
const originalDOMPurifyFactory = DOMPurifyModule.default;
|
|
81
|
-
try {
|
|
82
|
-
// This might work: intercept the factory function itself
|
|
83
|
-
if (typeof originalDOMPurifyFactory === "function" && !originalDOMPurifyFactory.sanitize) {
|
|
84
|
-
// This means DOMPurify.default is a factory function, not an instance
|
|
85
|
-
// We need to make sure when mermaid calls DOMPurify.sanitize, it works
|
|
86
|
-
const factoryResult = originalDOMPurifyFactory(window);
|
|
87
|
-
|
|
88
|
-
// Copy methods from our working instance to the factory result
|
|
89
|
-
Object.assign(originalDOMPurifyFactory, factoryResult);
|
|
90
|
-
}
|
|
91
|
-
} catch (_factoryError) {
|
|
92
|
-
// If factory modification fails, that's OK - we have other fallbacks
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Import and setup mermaid
|
|
96
|
-
const mermaid = await import("mermaid");
|
|
97
|
-
|
|
98
|
-
mermaid.default.initialize({
|
|
99
|
-
startOnLoad: false,
|
|
100
|
-
theme: "default",
|
|
101
|
-
securityLevel: "loose",
|
|
102
|
-
htmlLabels: false,
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
// Parse content
|
|
106
|
-
await mermaid.default.parse(trimmedContent);
|
|
107
|
-
|
|
108
|
-
return true;
|
|
109
|
-
} catch (error) {
|
|
110
|
-
const errorMessage = error.message || String(error);
|
|
111
|
-
|
|
112
|
-
// Keep parse errors as-is for useful info
|
|
113
|
-
if (errorMessage.includes("Parse error")) {
|
|
114
|
-
throw new Error(errorMessage);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (errorMessage.includes("Expecting ")) {
|
|
118
|
-
throw new Error(`Syntax error: ${errorMessage.replace(/^.*Expecting /, "Expected ")}`);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (errorMessage.includes("Lexical error")) {
|
|
122
|
-
throw new Error("Syntax error: invalid characters or tokens");
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (errorMessage.includes("No diagram type detected")) {
|
|
126
|
-
throw new Error("Syntax error: invalid or unrecognized diagram type");
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
throw new Error(errorMessage);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Basic validation fallback
|
|
135
|
-
*/
|
|
136
|
-
function validateBasicMermaidSyntax(content) {
|
|
137
|
-
const trimmedContent = content.trim();
|
|
138
|
-
|
|
139
|
-
if (!trimmedContent) {
|
|
140
|
-
throw new Error("Empty mermaid diagram");
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const validDiagramTypes = [
|
|
144
|
-
"flowchart",
|
|
145
|
-
"graph",
|
|
146
|
-
"sequenceDiagram",
|
|
147
|
-
"classDiagram",
|
|
148
|
-
"stateDiagram",
|
|
149
|
-
"entityRelationshipDiagram",
|
|
150
|
-
"erDiagram",
|
|
151
|
-
"journey",
|
|
152
|
-
"gantt",
|
|
153
|
-
"pie",
|
|
154
|
-
"requirement",
|
|
155
|
-
"gitgraph",
|
|
156
|
-
"mindmap",
|
|
157
|
-
"timeline",
|
|
158
|
-
"quadrantChart",
|
|
159
|
-
];
|
|
160
|
-
|
|
161
|
-
const firstLine = trimmedContent.split("\n")[0].trim();
|
|
162
|
-
const hasValidType = validDiagramTypes.some((type) => firstLine.includes(type));
|
|
163
|
-
|
|
164
|
-
if (!hasValidType) {
|
|
165
|
-
throw new Error("Invalid or missing diagram type");
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Basic bracket matching
|
|
169
|
-
const openBrackets = (content.match(/[[{(]/g) || []).length;
|
|
170
|
-
const closeBrackets = (content.match(/[\]})]/g) || []).length;
|
|
171
|
-
|
|
172
|
-
if (openBrackets !== closeBrackets) {
|
|
173
|
-
throw new Error("Unmatched brackets in diagram");
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return true;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Main validation with fallback
|
|
181
|
-
*/
|
|
182
|
-
async function validateMermaidSyntax(content) {
|
|
183
|
-
try {
|
|
184
|
-
return await validateMermaidWithOfficialParser(content);
|
|
185
|
-
} catch (officialError) {
|
|
186
|
-
const errorMsg = officialError.message || String(officialError);
|
|
187
|
-
|
|
188
|
-
// Check if it's an environment issue
|
|
189
|
-
if (
|
|
190
|
-
errorMsg.includes("Cannot resolve module") ||
|
|
191
|
-
errorMsg.includes("window is not defined") ||
|
|
192
|
-
errorMsg.includes("canvas") ||
|
|
193
|
-
errorMsg.includes("Web APIs") ||
|
|
194
|
-
errorMsg.includes("getComputedTextLength") ||
|
|
195
|
-
errorMsg.includes("document is not defined") ||
|
|
196
|
-
errorMsg.includes("DOMPurify")
|
|
197
|
-
) {
|
|
198
|
-
// Fall back to basic validation
|
|
199
|
-
return validateBasicMermaidSyntax(content);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Re-throw syntax errors
|
|
203
|
-
throw officialError;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Worker message handler
|
|
208
|
-
if (parentPort) {
|
|
209
|
-
parentPort.on("message", async (data) => {
|
|
210
|
-
const { id, content } = data;
|
|
211
|
-
|
|
212
|
-
try {
|
|
213
|
-
if (!id || !content) {
|
|
214
|
-
throw new Error("Missing id or content");
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const result = await validateMermaidSyntax(content);
|
|
218
|
-
|
|
219
|
-
parentPort.postMessage({
|
|
220
|
-
id,
|
|
221
|
-
success: true,
|
|
222
|
-
result,
|
|
223
|
-
});
|
|
224
|
-
} catch (error) {
|
|
225
|
-
parentPort.postMessage({
|
|
226
|
-
id,
|
|
227
|
-
error: error.message || String(error),
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export { validateMermaidSyntax };
|
package/utils/openapi/index.mjs
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { parse } from "yaml";
|
|
2
|
-
|
|
3
|
-
function isMatchOpenAPISpec(content) {
|
|
4
|
-
if (!content) return false;
|
|
5
|
-
if (!(content.openapi || content.swagger)) return false;
|
|
6
|
-
if (!content.paths) return false;
|
|
7
|
-
if (!(content.info?.title && content.info?.version)) return false;
|
|
8
|
-
return true;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function isOpenAPISpecFile(content) {
|
|
12
|
-
const trimmedContent = content.trim();
|
|
13
|
-
try {
|
|
14
|
-
const parsed = parse(trimmedContent, {
|
|
15
|
-
logLevel: "silent",
|
|
16
|
-
});
|
|
17
|
-
return isMatchOpenAPISpec(parsed);
|
|
18
|
-
} catch {
|
|
19
|
-
//
|
|
20
|
-
}
|
|
21
|
-
try {
|
|
22
|
-
const parsed = JSON.parse(trimmedContent);
|
|
23
|
-
return isMatchOpenAPISpec(parsed);
|
|
24
|
-
} catch {
|
|
25
|
-
//
|
|
26
|
-
}
|
|
27
|
-
return false;
|
|
28
|
-
}
|