simple-dynamsoft-mcp 6.3.0 → 7.0.0
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/.env.example +35 -9
- package/README.md +156 -497
- package/package.json +13 -7
- package/scripts/prebuild-rag-index.mjs +1 -1
- package/scripts/run-gemini-tests.mjs +1 -1
- package/scripts/sync-submodules.mjs +1 -1
- package/scripts/verify-doc-resources.mjs +79 -0
- package/src/data/bootstrap.js +475 -0
- package/src/data/download-utils.js +99 -0
- package/src/data/hydration-mode.js +15 -0
- package/src/data/hydration-policy.js +39 -0
- package/src/data/repo-map.js +149 -0
- package/src/{data-root.js → data/root.js} +1 -1
- package/src/{submodule-sync.js → data/submodule-sync.js} +1 -1
- package/src/index.js +49 -1499
- package/src/observability/logging.js +51 -0
- package/src/rag/config.js +96 -0
- package/src/rag/index.js +266 -0
- package/src/rag/lexical-provider.js +170 -0
- package/src/rag/logger.js +46 -0
- package/src/rag/profile-config.js +48 -0
- package/src/rag/providers.js +585 -0
- package/src/rag/search-utils.js +166 -0
- package/src/rag/vector-cache.js +323 -0
- package/src/server/create-server.js +168 -0
- package/src/server/helpers/server-helpers.js +33 -0
- package/src/{resource-index → server/resource-index}/paths.js +2 -2
- package/src/{resource-index → server/resource-index}/samples.js +9 -1
- package/src/{resource-index.js → server/resource-index.js} +158 -93
- package/src/server/resources/register-resources.js +56 -0
- package/src/server/runtime-config.js +66 -0
- package/src/server/tools/register-index-tools.js +130 -0
- package/src/server/tools/register-project-tools.js +305 -0
- package/src/server/tools/register-quickstart-tools.js +572 -0
- package/src/server/tools/register-sample-tools.js +333 -0
- package/src/server/tools/register-version-tools.js +136 -0
- package/src/server/transports/http.js +84 -0
- package/src/server/transports/stdio.js +12 -0
- package/src/data-bootstrap.js +0 -255
- package/src/rag.js +0 -1203
- /package/src/{gemini-retry.js → rag/gemini-retry.js} +0 -0
- /package/src/{normalizers.js → server/normalizers.js} +0 -0
- /package/src/{resource-index → server/resource-index}/builders.js +0 -0
- /package/src/{resource-index → server/resource-index}/config.js +0 -0
- /package/src/{resource-index → server/resource-index}/docs-loader.js +0 -0
- /package/src/{resource-index → server/resource-index}/uri.js +0 -0
- /package/src/{resource-index → server/resource-index}/version-policy.js +0 -0
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
2
|
+
import { extname, join } from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
export function registerQuickstartTools({
|
|
6
|
+
server,
|
|
7
|
+
registry,
|
|
8
|
+
ensureScopeHydrated,
|
|
9
|
+
ensureLatestMajor,
|
|
10
|
+
normalizeProduct,
|
|
11
|
+
normalizePlatform,
|
|
12
|
+
normalizeEdition,
|
|
13
|
+
normalizeApiLevel,
|
|
14
|
+
discoverDcvMobileSamples,
|
|
15
|
+
discoverDcvWebSamples,
|
|
16
|
+
findCodeFilesInSample,
|
|
17
|
+
getMobileSamplePath,
|
|
18
|
+
getDbrServerSamplePath,
|
|
19
|
+
getDcvMobileSamplePath,
|
|
20
|
+
getDcvServerSamplePath,
|
|
21
|
+
getDcvWebSamplePath,
|
|
22
|
+
getDwtSamplePath,
|
|
23
|
+
getDdvSamplePath,
|
|
24
|
+
readCodeFile,
|
|
25
|
+
getMainCodeFile,
|
|
26
|
+
getWebSamplePath
|
|
27
|
+
}) {
|
|
28
|
+
server.registerTool(
|
|
29
|
+
"get_quickstart",
|
|
30
|
+
{
|
|
31
|
+
title: "Get Quickstart",
|
|
32
|
+
description: "Opinionated quickstart for a target product/edition/platform. DCV supports MRZ/VIN/document-normalization/driver-license workflows.",
|
|
33
|
+
inputSchema: {
|
|
34
|
+
product: z.string().describe("Product: dcv, dbr, dwt, or ddv"),
|
|
35
|
+
edition: z.string().optional().describe("Edition: core, mobile, web, server/desktop"),
|
|
36
|
+
platform: z.string().optional().describe("Platform: android, ios, maui, react-native, flutter, js, python, cpp, java, dotnet, nodejs, angular, blazor, capacitor, electron, es6, native-ts, next, nuxt, pwa, react, requirejs, svelte, vue, webview, spm, core"),
|
|
37
|
+
language: z.string().optional().describe("Language hint: kotlin, java, swift, js, ts, python, cpp, csharp, react, vue, angular"),
|
|
38
|
+
version: z.string().optional().describe("Version constraint"),
|
|
39
|
+
api_level: z.string().optional().describe("API level: high-level or low-level (mobile only)"),
|
|
40
|
+
scenario: z.string().optional().describe("Scenario: camera, image, single, multiple, MRZ, VIN, document scan/normalization, driver license, react, etc.")
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
async ({ product, edition, platform, language, version, api_level, scenario }) => {
|
|
44
|
+
const normalizedProduct = normalizeProduct(product);
|
|
45
|
+
const normalizedPlatform = normalizePlatform(platform);
|
|
46
|
+
const normalizedEdition = normalizeEdition(edition, normalizedPlatform, normalizedProduct);
|
|
47
|
+
|
|
48
|
+
await ensureScopeHydrated({
|
|
49
|
+
product: normalizedProduct,
|
|
50
|
+
edition: normalizedEdition,
|
|
51
|
+
platform: normalizedPlatform,
|
|
52
|
+
type: "any"
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const policy = ensureLatestMajor({
|
|
56
|
+
product: normalizedProduct,
|
|
57
|
+
version,
|
|
58
|
+
query: scenario,
|
|
59
|
+
edition: normalizedEdition,
|
|
60
|
+
platform: normalizedPlatform
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
if (!policy.ok) {
|
|
64
|
+
return { isError: true, content: [{ type: "text", text: policy.message }] };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (normalizedProduct === "dcv") {
|
|
68
|
+
const scenarioLower = `${scenario || ""} ${language || ""}`.toLowerCase();
|
|
69
|
+
const effectiveEdition = normalizedEdition || (normalizedPlatform ? normalizeEdition("", normalizedPlatform, "dcv") : "server");
|
|
70
|
+
|
|
71
|
+
function selectDcvServerSample(platformHint, hint) {
|
|
72
|
+
const platformName = normalizePlatform(platformHint) || "python";
|
|
73
|
+
if (platformName === "python") {
|
|
74
|
+
if (hint.includes("mrz")) return "mrz_scanner";
|
|
75
|
+
if (hint.includes("vin")) return "vin_scanner";
|
|
76
|
+
if (hint.includes("driver") || hint.includes("license")) return "driver_license_scanner";
|
|
77
|
+
if (hint.includes("gs1")) return "gs1_ai_scanner";
|
|
78
|
+
return "document_scanner";
|
|
79
|
+
}
|
|
80
|
+
if (platformName === "nodejs") {
|
|
81
|
+
if (hint.includes("lambda")) return "lambda";
|
|
82
|
+
if (hint.includes("pdf")) return "pdf-advanced";
|
|
83
|
+
if (hint.includes("koa")) return "koa";
|
|
84
|
+
return "express";
|
|
85
|
+
}
|
|
86
|
+
if (hint.includes("mrz")) return "MRZScanner";
|
|
87
|
+
if (hint.includes("vin")) return "VINScanner";
|
|
88
|
+
if (hint.includes("driver") || hint.includes("license")) return "DriverLicenseScanner";
|
|
89
|
+
if (hint.includes("gs1")) return "GS1AIScanner";
|
|
90
|
+
return "DocumentScanner";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function selectMobileSample(sampleNames, hint) {
|
|
94
|
+
const lowerToName = new Map(sampleNames.map((name) => [String(name).toLowerCase(), name]));
|
|
95
|
+
const candidates = hint.includes("mrz")
|
|
96
|
+
? ["scanmrz", "mrzscanner"]
|
|
97
|
+
: hint.includes("vin")
|
|
98
|
+
? ["scanvin", "vinscanner"]
|
|
99
|
+
: (hint.includes("driver") || hint.includes("license"))
|
|
100
|
+
? ["driverlicensescanner"]
|
|
101
|
+
: ["scandocument", "documentscanner"];
|
|
102
|
+
for (const candidate of candidates) {
|
|
103
|
+
if (lowerToName.has(candidate)) return lowerToName.get(candidate);
|
|
104
|
+
}
|
|
105
|
+
return sampleNames[0] || "";
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function readBestSampleContent(samplePath) {
|
|
109
|
+
if (!samplePath || !existsSync(samplePath)) return { text: "", fence: "text" };
|
|
110
|
+
const sampleStat = statSync(samplePath);
|
|
111
|
+
if (sampleStat.isFile()) {
|
|
112
|
+
return {
|
|
113
|
+
text: readCodeFile(samplePath),
|
|
114
|
+
fence: extname(samplePath).replace(".", "") || "text"
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const readmePath = join(samplePath, "README.md");
|
|
118
|
+
if (existsSync(readmePath)) return { text: readCodeFile(readmePath), fence: "markdown" };
|
|
119
|
+
|
|
120
|
+
const codeFiles = findCodeFilesInSample(samplePath);
|
|
121
|
+
if (codeFiles.length > 0) {
|
|
122
|
+
const preferredNames = ["index.html", "index.js", "index.ts", "main.dart", "App.tsx", "MainActivity.kt", "MainActivity.java"];
|
|
123
|
+
const preferred = codeFiles.find((file) => preferredNames.includes(file.filename)) || codeFiles[0];
|
|
124
|
+
return {
|
|
125
|
+
text: readCodeFile(preferred.path),
|
|
126
|
+
fence: preferred.extension ? preferred.extension.replace(".", "") : "text"
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return { text: "Sample found, but no code files detected.", fence: "text" };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function formatInstallLines(installation) {
|
|
134
|
+
if (!installation || typeof installation !== "object") return [];
|
|
135
|
+
const lines = [];
|
|
136
|
+
for (const value of Object.values(installation)) {
|
|
137
|
+
if (typeof value === "string" && value.trim()) lines.push(value);
|
|
138
|
+
}
|
|
139
|
+
return lines;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (effectiveEdition === "server") {
|
|
143
|
+
const sdkEntry = registry.sdks["dcv-server"];
|
|
144
|
+
const targetPlatform = normalizePlatform(normalizedPlatform || sdkEntry.default_platform || "python");
|
|
145
|
+
const sampleName = selectDcvServerSample(targetPlatform, scenarioLower);
|
|
146
|
+
const samplePath = getDcvServerSamplePath(targetPlatform, sampleName);
|
|
147
|
+
|
|
148
|
+
if (!samplePath || !existsSync(samplePath)) {
|
|
149
|
+
return { isError: true, content: [{ type: "text", text: `Sample not found: ${sampleName}.` }] };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const { text: sampleContent, fence } = readBestSampleContent(samplePath);
|
|
153
|
+
const installLines = formatInstallLines(sdkEntry.platforms?.[targetPlatform]?.installation);
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
content: [{
|
|
157
|
+
type: "text",
|
|
158
|
+
text: [
|
|
159
|
+
`# Quick Start: DCV Server (${targetPlatform})`,
|
|
160
|
+
"",
|
|
161
|
+
`**SDK Version:** ${sdkEntry.version}`,
|
|
162
|
+
`**Trial License:** \`${registry.trial_license}\``,
|
|
163
|
+
"",
|
|
164
|
+
installLines.length ? "## Install" : "",
|
|
165
|
+
installLines.length ? "```bash" : "",
|
|
166
|
+
...installLines,
|
|
167
|
+
installLines.length ? "```" : "",
|
|
168
|
+
installLines.length ? "" : "",
|
|
169
|
+
`## ${sampleName}`,
|
|
170
|
+
"```" + fence,
|
|
171
|
+
sampleContent,
|
|
172
|
+
"```",
|
|
173
|
+
"",
|
|
174
|
+
`Docs: ${sdkEntry.platforms?.[targetPlatform]?.docs?.["user-guide"] || "N/A"}`
|
|
175
|
+
].filter(Boolean).join("\n")
|
|
176
|
+
}]
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (effectiveEdition === "web") {
|
|
181
|
+
const sdkEntry = registry.sdks["dcv-web"];
|
|
182
|
+
const available = discoverDcvWebSamples();
|
|
183
|
+
const sampleName = scenarioLower.includes("vin") ? "VINScanner" : (available[0] || "VINScanner");
|
|
184
|
+
const samplePath = getDcvWebSamplePath(sampleName);
|
|
185
|
+
if (!samplePath || !existsSync(samplePath)) {
|
|
186
|
+
return { isError: true, content: [{ type: "text", text: `Sample not found: ${sampleName}.` }] };
|
|
187
|
+
}
|
|
188
|
+
const { text: sampleContent, fence } = readBestSampleContent(samplePath);
|
|
189
|
+
const installLines = formatInstallLines(sdkEntry.platforms?.web?.installation);
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
content: [{
|
|
193
|
+
type: "text",
|
|
194
|
+
text: [
|
|
195
|
+
"# Quick Start: DCV Web",
|
|
196
|
+
"",
|
|
197
|
+
`**SDK Version:** ${sdkEntry.version}`,
|
|
198
|
+
`**Trial License:** \`${registry.trial_license}\``,
|
|
199
|
+
"",
|
|
200
|
+
installLines.length ? "## Install" : "",
|
|
201
|
+
installLines.length ? "```bash" : "",
|
|
202
|
+
...installLines,
|
|
203
|
+
installLines.length ? "```" : "",
|
|
204
|
+
installLines.length ? "" : "",
|
|
205
|
+
`## ${sampleName}`,
|
|
206
|
+
"```" + fence,
|
|
207
|
+
sampleContent,
|
|
208
|
+
"```",
|
|
209
|
+
"",
|
|
210
|
+
`Docs: ${sdkEntry.platforms?.web?.docs?.["user-guide"] || "N/A"}`
|
|
211
|
+
].filter(Boolean).join("\n")
|
|
212
|
+
}]
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (effectiveEdition === "mobile") {
|
|
217
|
+
const sdkEntry = registry.sdks["dcv-mobile"];
|
|
218
|
+
const targetPlatform = normalizePlatform(normalizedPlatform || sdkEntry.default_platform || "android");
|
|
219
|
+
const sampleNames = discoverDcvMobileSamples(targetPlatform);
|
|
220
|
+
const sampleName = selectMobileSample(sampleNames, scenarioLower);
|
|
221
|
+
const samplePath = getDcvMobileSamplePath(targetPlatform, sampleName);
|
|
222
|
+
|
|
223
|
+
if (!samplePath || !existsSync(samplePath)) {
|
|
224
|
+
return { isError: true, content: [{ type: "text", text: `Sample not found: ${sampleName || "N/A"}.` }] };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const { text: sampleContent, fence } = readBestSampleContent(samplePath);
|
|
228
|
+
const installLines = formatInstallLines(sdkEntry.platforms?.[targetPlatform]?.installation);
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
content: [{
|
|
232
|
+
type: "text",
|
|
233
|
+
text: [
|
|
234
|
+
`# Quick Start: DCV Mobile (${targetPlatform})`,
|
|
235
|
+
"",
|
|
236
|
+
`**SDK Version:** ${sdkEntry.version}`,
|
|
237
|
+
`**Trial License:** \`${registry.trial_license}\``,
|
|
238
|
+
"",
|
|
239
|
+
installLines.length ? "## Install" : "",
|
|
240
|
+
installLines.length ? "```bash" : "",
|
|
241
|
+
...installLines,
|
|
242
|
+
installLines.length ? "```" : "",
|
|
243
|
+
installLines.length ? "" : "",
|
|
244
|
+
`## ${sampleName}`,
|
|
245
|
+
"```" + fence,
|
|
246
|
+
sampleContent,
|
|
247
|
+
"```",
|
|
248
|
+
"",
|
|
249
|
+
`Docs: ${sdkEntry.platforms?.[targetPlatform]?.docs?.["user-guide"] || "N/A"}`
|
|
250
|
+
].filter(Boolean).join("\n")
|
|
251
|
+
}]
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (effectiveEdition === "core") {
|
|
256
|
+
const sdkEntry = registry.sdks["dcv-core"];
|
|
257
|
+
return {
|
|
258
|
+
content: [{
|
|
259
|
+
type: "text",
|
|
260
|
+
text: [
|
|
261
|
+
"# Quick Start: DCV Core",
|
|
262
|
+
"",
|
|
263
|
+
`**SDK Version:** ${sdkEntry.version}`,
|
|
264
|
+
"",
|
|
265
|
+
"DCV core docs aggregate architecture, parameters, and cross-product workflows.",
|
|
266
|
+
`Docs: ${sdkEntry.platforms?.core?.docs?.introduction || "https://www.dynamsoft.com/capture-vision/docs/core/"}`
|
|
267
|
+
].join("\n")
|
|
268
|
+
}]
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (normalizedProduct === "dbr" && normalizedEdition === "server") {
|
|
274
|
+
const sdkEntry = registry.sdks["dbr-server"];
|
|
275
|
+
const scenarioLower = (scenario || "").toLowerCase();
|
|
276
|
+
const sampleName = scenarioLower.includes("video") ? "video_decoding" : "read_an_image";
|
|
277
|
+
const samplePath = getDbrServerSamplePath("python", sampleName);
|
|
278
|
+
|
|
279
|
+
if (!existsSync(samplePath)) {
|
|
280
|
+
return { isError: true, content: [{ type: "text", text: `Sample not found: ${sampleName}.` }] };
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const content = readCodeFile(samplePath);
|
|
284
|
+
|
|
285
|
+
return {
|
|
286
|
+
content: [{
|
|
287
|
+
type: "text",
|
|
288
|
+
text: [
|
|
289
|
+
"# Quick Start: DBR Server (Python)",
|
|
290
|
+
"",
|
|
291
|
+
`**SDK Version:** ${sdkEntry.version}`,
|
|
292
|
+
`**Trial License:** \`${registry.trial_license}\``,
|
|
293
|
+
"",
|
|
294
|
+
"## Install",
|
|
295
|
+
"```bash",
|
|
296
|
+
sdkEntry.platforms.python.installation.pip,
|
|
297
|
+
"```",
|
|
298
|
+
"",
|
|
299
|
+
`## ${sampleName}.py`,
|
|
300
|
+
"```python",
|
|
301
|
+
content,
|
|
302
|
+
"```",
|
|
303
|
+
"",
|
|
304
|
+
`Docs: ${sdkEntry.platforms.python.docs["user-guide"]}`
|
|
305
|
+
].join("\n")
|
|
306
|
+
}]
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (normalizedProduct === "dbr" && normalizedEdition === "web") {
|
|
311
|
+
const sdkEntry = registry.sdks["dbr-web"];
|
|
312
|
+
const scenarioLower = (scenario || "").toLowerCase();
|
|
313
|
+
const sampleName = scenarioLower.includes("image") ? "read-an-image" : "hello-world";
|
|
314
|
+
const samplePath = getWebSamplePath("root", sampleName);
|
|
315
|
+
|
|
316
|
+
if (!samplePath || !existsSync(samplePath)) {
|
|
317
|
+
return { isError: true, content: [{ type: "text", text: `Sample not found: ${sampleName}.` }] };
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const content = readCodeFile(samplePath);
|
|
321
|
+
|
|
322
|
+
return {
|
|
323
|
+
content: [{
|
|
324
|
+
type: "text",
|
|
325
|
+
text: [
|
|
326
|
+
"# Quick Start: DBR Web",
|
|
327
|
+
"",
|
|
328
|
+
`**SDK Version:** ${sdkEntry.version}`,
|
|
329
|
+
`**Trial License:** \`${registry.trial_license}\``,
|
|
330
|
+
"",
|
|
331
|
+
"## Option 1: CDN",
|
|
332
|
+
"```html",
|
|
333
|
+
`<script src="${sdkEntry.platforms.web.installation.cdn}"></script>`,
|
|
334
|
+
"```",
|
|
335
|
+
"",
|
|
336
|
+
"## Option 2: NPM",
|
|
337
|
+
"```bash",
|
|
338
|
+
sdkEntry.platforms.web.installation.npm,
|
|
339
|
+
"```",
|
|
340
|
+
"",
|
|
341
|
+
`## ${sampleName}.html`,
|
|
342
|
+
"```html",
|
|
343
|
+
content,
|
|
344
|
+
"```",
|
|
345
|
+
"",
|
|
346
|
+
`Docs: ${sdkEntry.platforms.web.docs["user-guide"]}`
|
|
347
|
+
].join("\n")
|
|
348
|
+
}]
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (normalizedProduct === "dbr" && normalizedEdition === "mobile") {
|
|
353
|
+
const sdkEntry = registry.sdks["dbr-mobile"];
|
|
354
|
+
const targetPlatform = normalizedPlatform || "android";
|
|
355
|
+
const level = normalizeApiLevel(api_level || scenario);
|
|
356
|
+
const scenarioLower = (scenario || "").toLowerCase();
|
|
357
|
+
|
|
358
|
+
let sampleName = "ScanSingleBarcode";
|
|
359
|
+
if (scenarioLower.includes("multiple") || scenarioLower.includes("batch")) sampleName = "ScanMultipleBarcodes";
|
|
360
|
+
else if (scenarioLower.includes("image") || scenarioLower.includes("file")) sampleName = "DecodeFromAnImage";
|
|
361
|
+
|
|
362
|
+
if (level === "low-level") {
|
|
363
|
+
if (sampleName === "ScanSingleBarcode" || sampleName === "ScanMultipleBarcodes") {
|
|
364
|
+
sampleName = "DecodeWithCameraEnhancer";
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const samplePath = getMobileSamplePath(targetPlatform, level, sampleName);
|
|
369
|
+
if (!existsSync(samplePath)) {
|
|
370
|
+
return { isError: true, content: [{ type: "text", text: `Sample not found: ${sampleName}.` }] };
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const mainFile = getMainCodeFile(targetPlatform, samplePath);
|
|
374
|
+
if (!mainFile) {
|
|
375
|
+
return { isError: true, content: [{ type: "text", text: "Could not find main code file." }] };
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const content = readCodeFile(mainFile.path);
|
|
379
|
+
const langExt = mainFile.filename.split(".").pop();
|
|
380
|
+
|
|
381
|
+
let deps = "";
|
|
382
|
+
if (targetPlatform === "android") {
|
|
383
|
+
deps = `
|
|
384
|
+
## Dependencies
|
|
385
|
+
|
|
386
|
+
**Project build.gradle**
|
|
387
|
+
\`\`\`groovy
|
|
388
|
+
allprojects {
|
|
389
|
+
repositories {
|
|
390
|
+
google()
|
|
391
|
+
mavenCentral()
|
|
392
|
+
maven { url "${registry.maven_url}" }
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
\`\`\`
|
|
396
|
+
|
|
397
|
+
**App build.gradle**
|
|
398
|
+
\`\`\`groovy
|
|
399
|
+
dependencies {
|
|
400
|
+
implementation 'com.dynamsoft:barcodereaderbundle:${sdkEntry.version}'
|
|
401
|
+
}
|
|
402
|
+
\`\`\`
|
|
403
|
+
|
|
404
|
+
**AndroidManifest.xml**
|
|
405
|
+
\`\`\`xml
|
|
406
|
+
<uses-permission android:name="android.permission.CAMERA" />
|
|
407
|
+
\`\`\``;
|
|
408
|
+
} else {
|
|
409
|
+
deps = `
|
|
410
|
+
## Dependencies
|
|
411
|
+
|
|
412
|
+
**Podfile**
|
|
413
|
+
\`\`\`ruby
|
|
414
|
+
platform :ios, '11.0'
|
|
415
|
+
use_frameworks!
|
|
416
|
+
|
|
417
|
+
target 'YourApp' do
|
|
418
|
+
pod 'DynamsoftBarcodeReaderBundle'
|
|
419
|
+
end
|
|
420
|
+
\`\`\`
|
|
421
|
+
|
|
422
|
+
**Info.plist**
|
|
423
|
+
\`\`\`xml
|
|
424
|
+
<key>NSCameraUsageDescription</key>
|
|
425
|
+
<string>Camera access for barcode scanning</string>
|
|
426
|
+
\`\`\``;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const output = [
|
|
430
|
+
"# Quick Start: DBR Mobile",
|
|
431
|
+
"",
|
|
432
|
+
`**SDK Version:** ${sdkEntry.version}`,
|
|
433
|
+
`**API Level:** ${level}`,
|
|
434
|
+
`**Trial License:** \`${registry.trial_license}\``,
|
|
435
|
+
"",
|
|
436
|
+
deps,
|
|
437
|
+
"",
|
|
438
|
+
`## ${mainFile.filename}`,
|
|
439
|
+
"```" + langExt,
|
|
440
|
+
content,
|
|
441
|
+
"```",
|
|
442
|
+
"",
|
|
443
|
+
`Docs: ${sdkEntry.platforms[targetPlatform]?.docs[level]?.["user-guide"] || "N/A"}`
|
|
444
|
+
];
|
|
445
|
+
|
|
446
|
+
return { content: [{ type: "text", text: output.join("\n") }] };
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (normalizedProduct === "dwt") {
|
|
450
|
+
const sdkEntry = registry.sdks["dwt"];
|
|
451
|
+
const samplePath = getDwtSamplePath("scan", "basic-scan");
|
|
452
|
+
|
|
453
|
+
if (!samplePath || !existsSync(samplePath)) {
|
|
454
|
+
return { isError: true, content: [{ type: "text", text: "Sample not found: basic-scan." }] };
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const content = readCodeFile(samplePath);
|
|
458
|
+
|
|
459
|
+
return {
|
|
460
|
+
content: [{
|
|
461
|
+
type: "text",
|
|
462
|
+
text: [
|
|
463
|
+
"# Quick Start: Dynamic Web TWAIN",
|
|
464
|
+
"",
|
|
465
|
+
`**SDK Version:** ${sdkEntry.version}`,
|
|
466
|
+
`**Trial License:** \`${registry.trial_license}\``,
|
|
467
|
+
"",
|
|
468
|
+
"## Option 1: CDN",
|
|
469
|
+
"```html",
|
|
470
|
+
`<script src="${sdkEntry.platforms.web.installation.cdn}"></script>`,
|
|
471
|
+
"```",
|
|
472
|
+
"",
|
|
473
|
+
"## Option 2: NPM",
|
|
474
|
+
"```bash",
|
|
475
|
+
sdkEntry.platforms.web.installation.npm,
|
|
476
|
+
"```",
|
|
477
|
+
"",
|
|
478
|
+
"## basic-scan.html",
|
|
479
|
+
"```html",
|
|
480
|
+
content,
|
|
481
|
+
"```",
|
|
482
|
+
"",
|
|
483
|
+
`Docs: ${sdkEntry.platforms.web.docs["user-guide"]}`
|
|
484
|
+
].join("\n")
|
|
485
|
+
}]
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if (normalizedProduct === "ddv") {
|
|
490
|
+
const sdkEntry = registry.sdks["ddv"];
|
|
491
|
+
const hint = `${scenario || ""} ${language || ""}`.toLowerCase();
|
|
492
|
+
let sampleName = "hello-world";
|
|
493
|
+
|
|
494
|
+
if (hint.includes("react")) sampleName = "react-vite";
|
|
495
|
+
else if (hint.includes("vue")) sampleName = "vue";
|
|
496
|
+
else if (hint.includes("angular")) sampleName = "angular";
|
|
497
|
+
else if (hint.includes("next")) sampleName = "next";
|
|
498
|
+
|
|
499
|
+
const samplePath = getDdvSamplePath(sampleName);
|
|
500
|
+
if (!samplePath || !existsSync(samplePath)) {
|
|
501
|
+
return { isError: true, content: [{ type: "text", text: `Sample not found: ${sampleName}.` }] };
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
let sampleContent = "";
|
|
505
|
+
let fence = "text";
|
|
506
|
+
const stat = statSync(samplePath);
|
|
507
|
+
if (stat.isDirectory()) {
|
|
508
|
+
const readmePath = join(samplePath, "README.md");
|
|
509
|
+
if (existsSync(readmePath)) {
|
|
510
|
+
sampleContent = readCodeFile(readmePath);
|
|
511
|
+
fence = "markdown";
|
|
512
|
+
} else {
|
|
513
|
+
const codeFiles = findCodeFilesInSample(samplePath);
|
|
514
|
+
if (codeFiles.length > 0) {
|
|
515
|
+
const preferredNames = [
|
|
516
|
+
"main.tsx",
|
|
517
|
+
"main.jsx",
|
|
518
|
+
"main.ts",
|
|
519
|
+
"main.js",
|
|
520
|
+
"App.tsx",
|
|
521
|
+
"App.jsx",
|
|
522
|
+
"App.vue"
|
|
523
|
+
];
|
|
524
|
+
const preferred = codeFiles.find((file) => preferredNames.includes(file.filename)) || codeFiles[0];
|
|
525
|
+
sampleContent = readCodeFile(preferred.path);
|
|
526
|
+
fence = preferred.extension ? preferred.extension.replace(".", "") : "text";
|
|
527
|
+
} else {
|
|
528
|
+
sampleContent = "Sample found, but no code files detected.";
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
} else {
|
|
532
|
+
sampleContent = readCodeFile(samplePath);
|
|
533
|
+
fence = extname(samplePath).replace(".", "") || "text";
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
return {
|
|
537
|
+
content: [{
|
|
538
|
+
type: "text",
|
|
539
|
+
text: [
|
|
540
|
+
"# Quick Start: Dynamsoft Document Viewer",
|
|
541
|
+
"",
|
|
542
|
+
`**SDK Version:** ${sdkEntry.version}`,
|
|
543
|
+
`**Trial License:** \`${registry.trial_license}\``,
|
|
544
|
+
"",
|
|
545
|
+
"## Option 1: CDN",
|
|
546
|
+
"```html",
|
|
547
|
+
`<script src="${sdkEntry.platforms.web.installation.cdn}"></script>`,
|
|
548
|
+
"```",
|
|
549
|
+
"",
|
|
550
|
+
"## Option 2: NPM",
|
|
551
|
+
"```bash",
|
|
552
|
+
sdkEntry.platforms.web.installation.npm,
|
|
553
|
+
"```",
|
|
554
|
+
"",
|
|
555
|
+
`## ${sampleName}`,
|
|
556
|
+
"```" + fence,
|
|
557
|
+
sampleContent,
|
|
558
|
+
"```",
|
|
559
|
+
"",
|
|
560
|
+
`Docs: ${sdkEntry.platforms.web.docs["user-guide"]}`
|
|
561
|
+
].join("\n")
|
|
562
|
+
}]
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
return {
|
|
567
|
+
isError: true,
|
|
568
|
+
content: [{ type: "text", text: "Unsupported product/edition for quickstart." }]
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
);
|
|
572
|
+
}
|