@oxog/npm-llms 1.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.
@@ -0,0 +1,4133 @@
1
+ import { gunzipSync } from 'zlib';
2
+
3
+ // src/errors.ts
4
+ var NpmLlmsError = class extends Error {
5
+ /**
6
+ * Create a new NpmLlmsError
7
+ * @param message - Error message
8
+ * @param code - Error code
9
+ * @param details - Additional error details
10
+ */
11
+ constructor(message, code, details) {
12
+ super(message);
13
+ this.code = code;
14
+ this.details = details;
15
+ this.name = "NpmLlmsError";
16
+ if (Error.captureStackTrace) {
17
+ Error.captureStackTrace(this, this.constructor);
18
+ }
19
+ }
20
+ /**
21
+ * Convert error to JSON
22
+ */
23
+ toJSON() {
24
+ return {
25
+ name: this.name,
26
+ message: this.message,
27
+ code: this.code,
28
+ details: this.details
29
+ };
30
+ }
31
+ };
32
+ var PackageNotFoundError = class extends NpmLlmsError {
33
+ constructor(packageName) {
34
+ super(`Package "${packageName}" not found on npm`, "PACKAGE_NOT_FOUND", { packageName });
35
+ this.name = "PackageNotFoundError";
36
+ }
37
+ };
38
+ var VersionNotFoundError = class extends NpmLlmsError {
39
+ constructor(packageName, version) {
40
+ super(`Version "${version}" not found for package "${packageName}"`, "VERSION_NOT_FOUND", {
41
+ packageName,
42
+ version
43
+ });
44
+ this.name = "VersionNotFoundError";
45
+ }
46
+ };
47
+ var DownloadError = class extends NpmLlmsError {
48
+ constructor(message, url) {
49
+ super(message, "DOWNLOAD_FAILED", { url });
50
+ this.name = "DownloadError";
51
+ }
52
+ };
53
+ var AIError = class extends NpmLlmsError {
54
+ constructor(message, provider) {
55
+ super(message, "AI_ERROR", { provider });
56
+ this.name = "AIError";
57
+ }
58
+ };
59
+ var PluginError = class extends NpmLlmsError {
60
+ constructor(message, pluginName) {
61
+ super(message, "PLUGIN_ERROR", { pluginName });
62
+ this.name = "PluginError";
63
+ }
64
+ };
65
+ var TarError = class extends NpmLlmsError {
66
+ constructor(message, offset) {
67
+ super(message, "TAR_ERROR", { offset });
68
+ this.name = "TarError";
69
+ }
70
+ };
71
+ var TimeoutError = class extends NpmLlmsError {
72
+ constructor(message, timeout) {
73
+ super(message, "TIMEOUT_ERROR", { timeout });
74
+ this.name = "TimeoutError";
75
+ }
76
+ };
77
+ var ValidationError = class extends NpmLlmsError {
78
+ constructor(message, field) {
79
+ super(message, "VALIDATION_ERROR", { field });
80
+ this.name = "ValidationError";
81
+ }
82
+ };
83
+ var DEFAULT_REGISTRY = "https://registry.npmjs.org";
84
+ var DEFAULT_TIMEOUT = 3e4;
85
+ function createTimeoutController(timeout) {
86
+ const controller = new AbortController();
87
+ const timeoutId = setTimeout(() => {
88
+ controller.abort();
89
+ }, timeout);
90
+ return {
91
+ controller,
92
+ cleanup: () => clearTimeout(timeoutId)
93
+ };
94
+ }
95
+ async function fetchJson(url, options = {}) {
96
+ const timeout = options.timeout ?? DEFAULT_TIMEOUT;
97
+ const { controller, cleanup } = createTimeoutController(timeout);
98
+ try {
99
+ const response = await fetch(url, {
100
+ method: "GET",
101
+ headers: {
102
+ Accept: "application/json",
103
+ ...options.headers
104
+ },
105
+ signal: controller.signal
106
+ });
107
+ if (!response.ok) {
108
+ throw new DownloadError(`HTTP ${response.status}: ${response.statusText}`, url);
109
+ }
110
+ const data = await response.json();
111
+ return {
112
+ data,
113
+ status: response.status,
114
+ headers: response.headers
115
+ };
116
+ } catch (error) {
117
+ if (error instanceof DownloadError) {
118
+ throw error;
119
+ }
120
+ if (error instanceof Error) {
121
+ if (error.name === "AbortError") {
122
+ throw new TimeoutError(`Request timed out after ${timeout}ms`, timeout);
123
+ }
124
+ throw new DownloadError(error.message, url);
125
+ }
126
+ throw new DownloadError("Unknown fetch error", url);
127
+ } finally {
128
+ cleanup();
129
+ }
130
+ }
131
+ async function fetchBinary(url, options = {}) {
132
+ const timeout = options.timeout ?? DEFAULT_TIMEOUT;
133
+ const { controller, cleanup } = createTimeoutController(timeout);
134
+ try {
135
+ const response = await fetch(url, {
136
+ method: "GET",
137
+ headers: {
138
+ Accept: "application/octet-stream",
139
+ ...options.headers
140
+ },
141
+ signal: controller.signal
142
+ });
143
+ if (!response.ok) {
144
+ throw new DownloadError(`HTTP ${response.status}: ${response.statusText}`, url);
145
+ }
146
+ const data = await response.arrayBuffer();
147
+ return {
148
+ data,
149
+ status: response.status,
150
+ headers: response.headers
151
+ };
152
+ } catch (error) {
153
+ if (error instanceof DownloadError) {
154
+ throw error;
155
+ }
156
+ if (error instanceof Error) {
157
+ if (error.name === "AbortError") {
158
+ throw new TimeoutError(`Request timed out after ${timeout}ms`, timeout);
159
+ }
160
+ throw new DownloadError(error.message, url);
161
+ }
162
+ throw new DownloadError("Unknown fetch error", url);
163
+ } finally {
164
+ cleanup();
165
+ }
166
+ }
167
+ async function fetchGzipped(url, options = {}) {
168
+ const { data: gzipped } = await fetchBinary(url, options);
169
+ try {
170
+ return gunzipSync(Buffer.from(gzipped));
171
+ } catch (error) {
172
+ const message = error instanceof Error ? error.message : "Unknown decompression error";
173
+ throw new DownloadError(`Failed to decompress gzip: ${message}`, url);
174
+ }
175
+ }
176
+ function encodePackageName(name) {
177
+ if (name.startsWith("@")) {
178
+ const slashIndex = name.indexOf("/");
179
+ if (slashIndex === -1) {
180
+ return encodeURIComponent(name);
181
+ }
182
+ const scope = name.slice(0, slashIndex);
183
+ const pkg = name.slice(slashIndex + 1);
184
+ return `${scope}%2F${encodeURIComponent(pkg)}`;
185
+ }
186
+ return encodeURIComponent(name);
187
+ }
188
+ function buildPackageUrl(name, version, registry = DEFAULT_REGISTRY) {
189
+ const encodedName = encodePackageName(name);
190
+ const base = `${registry}/${encodedName}`;
191
+ return version ? `${base}/${version}` : base;
192
+ }
193
+
194
+ // src/utils/tar.ts
195
+ var BLOCK_SIZE = 512;
196
+ var TAR_TYPES = {
197
+ FILE: "0",
198
+ FILE_ALT: "",
199
+ GNU_LONGNAME: "L"};
200
+ var decoder = new TextDecoder("utf-8");
201
+ function isZeroBlock(buffer, offset) {
202
+ const end = Math.min(offset + BLOCK_SIZE, buffer.length);
203
+ for (let i = offset; i < end; i++) {
204
+ if (buffer[i] !== 0) return false;
205
+ }
206
+ return true;
207
+ }
208
+ function parseOctal(buffer, offset, length) {
209
+ const bytes = buffer.slice(offset, offset + length);
210
+ const str = decoder.decode(bytes).replace(/\0/g, "").trim();
211
+ if (!str) return 0;
212
+ return parseInt(str, 8) || 0;
213
+ }
214
+ function parseString(buffer, offset, length) {
215
+ const bytes = buffer.slice(offset, offset + length);
216
+ const str = decoder.decode(bytes);
217
+ const nullIndex = str.indexOf("\0");
218
+ return nullIndex >= 0 ? str.slice(0, nullIndex) : str;
219
+ }
220
+ function calculateChecksum(buffer, offset) {
221
+ let sum = 0;
222
+ for (let i = 0; i < BLOCK_SIZE; i++) {
223
+ if (i >= 148 && i < 156) {
224
+ sum += 32;
225
+ } else {
226
+ sum += buffer[offset + i] ?? 0;
227
+ }
228
+ }
229
+ return sum;
230
+ }
231
+ function parseTarHeader(buffer, offset) {
232
+ if (isZeroBlock(buffer, offset)) {
233
+ return null;
234
+ }
235
+ if (offset + BLOCK_SIZE > buffer.length) {
236
+ throw new TarError("Unexpected end of tar archive", offset);
237
+ }
238
+ const name = parseString(buffer, offset, 100);
239
+ const mode = parseOctal(buffer, offset + 100, 8);
240
+ const uid = parseOctal(buffer, offset + 108, 8);
241
+ const gid = parseOctal(buffer, offset + 116, 8);
242
+ const size = parseOctal(buffer, offset + 124, 12);
243
+ const mtime = parseOctal(buffer, offset + 136, 12);
244
+ const checksum = parseOctal(buffer, offset + 148, 8);
245
+ const type = parseString(buffer, offset + 156, 1);
246
+ const linkname = parseString(buffer, offset + 157, 100);
247
+ const calculatedChecksum = calculateChecksum(buffer, offset);
248
+ if (checksum !== 0 && checksum !== calculatedChecksum) {
249
+ throw new TarError(`Invalid tar header checksum: expected ${checksum}, got ${calculatedChecksum}`, offset);
250
+ }
251
+ const magic = parseString(buffer, offset + 257, 6);
252
+ let fullName = name;
253
+ if (magic === "ustar" || magic === "ustar ") {
254
+ const prefix = parseString(buffer, offset + 345, 155);
255
+ if (prefix) {
256
+ fullName = `${prefix}/${name}`;
257
+ }
258
+ }
259
+ return {
260
+ name: fullName,
261
+ mode,
262
+ uid,
263
+ gid,
264
+ size,
265
+ mtime,
266
+ checksum,
267
+ type,
268
+ linkname
269
+ };
270
+ }
271
+ function sanitizePath(path) {
272
+ let normalized = path.replace(/\\/g, "/");
273
+ if (normalized.startsWith("/")) {
274
+ normalized = normalized.slice(1);
275
+ }
276
+ const parts = normalized.split("/");
277
+ const safeParts = [];
278
+ for (const part of parts) {
279
+ if (part === "..") {
280
+ throw new TarError(`Path traversal detected: ${path}`);
281
+ }
282
+ if (part && part !== ".") {
283
+ safeParts.push(part);
284
+ }
285
+ }
286
+ return safeParts.join("/");
287
+ }
288
+ function removePackagePrefix(path) {
289
+ const prefixes = ["package/", "package\\"];
290
+ for (const prefix of prefixes) {
291
+ if (path.startsWith(prefix)) {
292
+ return path.slice(prefix.length);
293
+ }
294
+ }
295
+ return path;
296
+ }
297
+ function getEntryType(_type) {
298
+ return "file";
299
+ }
300
+ function shouldExtract(path) {
301
+ const lower = path.toLowerCase();
302
+ if (lower.endsWith(".d.ts") || lower.endsWith(".d.mts") || lower.endsWith(".d.cts")) {
303
+ return true;
304
+ }
305
+ if (lower.endsWith(".ts") || lower.endsWith(".tsx") || lower.endsWith(".js") || lower.endsWith(".mjs") || lower.endsWith(".cjs") || lower.endsWith(".jsx")) {
306
+ return true;
307
+ }
308
+ if (lower.endsWith(".md") || lower.endsWith(".txt") || lower.endsWith(".json") || lower.endsWith(".yaml") || lower.endsWith(".yml")) {
309
+ return true;
310
+ }
311
+ const filename = path.split("/").pop() ?? "";
312
+ if (filename === "package.json" || filename === "README.md" || filename === "CHANGELOG.md" || filename === "LICENSE" || filename === "LICENSE.md") {
313
+ return true;
314
+ }
315
+ return false;
316
+ }
317
+ function* extractTarSync(buffer) {
318
+ const data = buffer instanceof Buffer ? new Uint8Array(buffer) : new Uint8Array(buffer);
319
+ let offset = 0;
320
+ let gnuLongName = null;
321
+ while (offset < data.length) {
322
+ const header = parseTarHeader(data, offset);
323
+ if (!header) {
324
+ break;
325
+ }
326
+ offset += BLOCK_SIZE;
327
+ if (header.type === TAR_TYPES.GNU_LONGNAME) {
328
+ const contentBytes = data.slice(offset, offset + header.size);
329
+ gnuLongName = decoder.decode(contentBytes).replace(/\0/g, "");
330
+ offset += Math.ceil(header.size / BLOCK_SIZE) * BLOCK_SIZE;
331
+ continue;
332
+ }
333
+ const entryName = gnuLongName ?? header.name;
334
+ gnuLongName = null;
335
+ if (header.type !== TAR_TYPES.FILE && header.type !== TAR_TYPES.FILE_ALT) {
336
+ offset += Math.ceil(header.size / BLOCK_SIZE) * BLOCK_SIZE;
337
+ continue;
338
+ }
339
+ let path;
340
+ try {
341
+ path = sanitizePath(entryName);
342
+ path = removePackagePrefix(path);
343
+ } catch {
344
+ offset += Math.ceil(header.size / BLOCK_SIZE) * BLOCK_SIZE;
345
+ continue;
346
+ }
347
+ if (!shouldExtract(path)) {
348
+ offset += Math.ceil(header.size / BLOCK_SIZE) * BLOCK_SIZE;
349
+ continue;
350
+ }
351
+ const content = data.slice(offset, offset + header.size);
352
+ const textContent = decoder.decode(content);
353
+ yield {
354
+ path,
355
+ content: textContent,
356
+ size: header.size,
357
+ type: getEntryType(header.type)
358
+ };
359
+ offset += Math.ceil(header.size / BLOCK_SIZE) * BLOCK_SIZE;
360
+ }
361
+ }
362
+ function extractTarToMap(buffer) {
363
+ const files = /* @__PURE__ */ new Map();
364
+ for (const entry of extractTarSync(buffer)) {
365
+ if (entry.type === "file") {
366
+ files.set(entry.path, entry.content);
367
+ }
368
+ }
369
+ return files;
370
+ }
371
+
372
+ // src/core/fetcher.ts
373
+ function validatePackageName(name) {
374
+ if (!name || typeof name !== "string") {
375
+ throw new ValidationError("Package name is required", "name");
376
+ }
377
+ const validPattern = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
378
+ if (!validPattern.test(name)) {
379
+ throw new ValidationError(
380
+ `Invalid package name: "${name}". Package names must be lowercase and may contain letters, numbers, hyphens, dots, and underscores.`,
381
+ "name"
382
+ );
383
+ }
384
+ if (name.length > 214) {
385
+ throw new ValidationError("Package name cannot exceed 214 characters", "name");
386
+ }
387
+ }
388
+ function parsePackageSpec(spec) {
389
+ if (!spec || typeof spec !== "string") {
390
+ throw new ValidationError("Package specifier is required", "spec");
391
+ }
392
+ const trimmed = spec.trim();
393
+ if (trimmed.startsWith("@")) {
394
+ const firstSlash = trimmed.indexOf("/");
395
+ if (firstSlash === -1) {
396
+ throw new ValidationError(`Invalid scoped package: "${spec}"`, "spec");
397
+ }
398
+ const afterScope = trimmed.slice(firstSlash + 1);
399
+ const versionSep = afterScope.lastIndexOf("@");
400
+ if (versionSep > 0) {
401
+ const name = trimmed.slice(0, firstSlash + 1 + versionSep);
402
+ const version = afterScope.slice(versionSep + 1);
403
+ return { name, version: version || void 0 };
404
+ }
405
+ return { name: trimmed };
406
+ }
407
+ const atIndex = trimmed.lastIndexOf("@");
408
+ if (atIndex > 0) {
409
+ const name = trimmed.slice(0, atIndex);
410
+ const version = trimmed.slice(atIndex + 1);
411
+ return { name, version: version || void 0 };
412
+ }
413
+ return { name: trimmed };
414
+ }
415
+ function resolveVersion(packageName, versions, distTags, requested) {
416
+ if (!requested) {
417
+ const latest = distTags["latest"];
418
+ if (latest && versions.includes(latest)) {
419
+ return latest;
420
+ }
421
+ return versions.sort(compareVersions).pop();
422
+ }
423
+ if (distTags[requested]) {
424
+ return distTags[requested];
425
+ }
426
+ if (versions.includes(requested)) {
427
+ return requested;
428
+ }
429
+ const matching = versions.filter((v) => v.startsWith(requested));
430
+ if (matching.length > 0) {
431
+ return matching.sort(compareVersions).pop();
432
+ }
433
+ throw new VersionNotFoundError(packageName, requested);
434
+ }
435
+ function compareVersions(a, b) {
436
+ const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
437
+ const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
438
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
439
+ const na = pa[i] || 0;
440
+ const nb = pb[i] || 0;
441
+ if (na !== nb) return na - nb;
442
+ }
443
+ return 0;
444
+ }
445
+ async function fetchPackageMetadata(name, version, options = {}) {
446
+ validatePackageName(name);
447
+ const registry = options.registry ?? DEFAULT_REGISTRY;
448
+ const httpOptions = { timeout: options.timeout };
449
+ if (version && !["latest", "next", "beta", "alpha"].includes(version)) {
450
+ try {
451
+ const url2 = buildPackageUrl(name, version, registry);
452
+ const { data } = await fetchJson(url2, httpOptions);
453
+ return extractMetadata(data);
454
+ } catch (error) {
455
+ if (!(error instanceof DownloadError) || !error.message.includes("404")) {
456
+ throw error;
457
+ }
458
+ }
459
+ }
460
+ const url = buildPackageUrl(name, void 0, registry);
461
+ try {
462
+ const { data } = await fetchJson(url, httpOptions);
463
+ const versions = Object.keys(data.versions ?? {});
464
+ if (versions.length === 0) {
465
+ throw new PackageNotFoundError(name);
466
+ }
467
+ const resolvedVersion = resolveVersion(
468
+ name,
469
+ versions,
470
+ data["dist-tags"] ?? {},
471
+ version
472
+ );
473
+ const versionData = data.versions[resolvedVersion];
474
+ if (!versionData) {
475
+ throw new VersionNotFoundError(name, resolvedVersion);
476
+ }
477
+ return extractMetadata(versionData);
478
+ } catch (error) {
479
+ if (error instanceof DownloadError && error.message.includes("404")) {
480
+ throw new PackageNotFoundError(name);
481
+ }
482
+ throw error;
483
+ }
484
+ }
485
+ function extractMetadata(data) {
486
+ if (!data.dist?.tarball) {
487
+ throw new DownloadError("Package metadata missing tarball URL");
488
+ }
489
+ let repository;
490
+ if (data.repository) {
491
+ if (typeof data.repository === "string") {
492
+ repository = { type: "git", url: data.repository };
493
+ } else {
494
+ repository = data.repository;
495
+ }
496
+ }
497
+ return {
498
+ name: data.name,
499
+ version: data.version,
500
+ description: data.description,
501
+ tarball: data.dist.tarball,
502
+ types: data.types ?? data.typings,
503
+ main: data.main,
504
+ exports: data.exports,
505
+ repository,
506
+ keywords: data.keywords,
507
+ author: data.author,
508
+ license: data.license,
509
+ homepage: data.homepage
510
+ };
511
+ }
512
+ async function downloadPackageFiles(tarballUrl, options = {}) {
513
+ const buffer = await fetchGzipped(tarballUrl, options);
514
+ return extractTarToMap(buffer);
515
+ }
516
+ async function fetchPackage(spec, options = {}) {
517
+ const { name, version } = parsePackageSpec(spec);
518
+ const metadata = await fetchPackageMetadata(name, version, options);
519
+ const files = await downloadPackageFiles(metadata.tarball, {
520
+ timeout: options.timeout
521
+ });
522
+ return {
523
+ ...metadata,
524
+ files
525
+ };
526
+ }
527
+
528
+ // src/plugins/core/types-resolver.ts
529
+ function hasDtsFiles(files) {
530
+ for (const path of files.keys()) {
531
+ if (path.endsWith(".d.ts")) {
532
+ return true;
533
+ }
534
+ }
535
+ return false;
536
+ }
537
+ function getTypesPackageName(packageName) {
538
+ if (packageName.startsWith("@")) {
539
+ const withoutAt = packageName.slice(1);
540
+ return `@types/${withoutAt.replace("/", "__")}`;
541
+ }
542
+ return `@types/${packageName}`;
543
+ }
544
+ function isTypesPackage(packageName) {
545
+ return packageName.startsWith("@types/");
546
+ }
547
+ var typesResolverPlugin = {
548
+ name: "types-resolver",
549
+ version: "1.0.0",
550
+ category: "parser",
551
+ install(kernel) {
552
+ kernel.on("package:fetched", async (context) => {
553
+ const { files, name } = context.package;
554
+ if (isTypesPackage(name)) {
555
+ return;
556
+ }
557
+ if (hasDtsFiles(files)) {
558
+ return;
559
+ }
560
+ const typesPackageName = getTypesPackageName(name);
561
+ try {
562
+ const typesPackage = await fetchPackage(typesPackageName);
563
+ let mergedCount = 0;
564
+ for (const [path, content] of typesPackage.files) {
565
+ if (path.endsWith(".d.ts")) {
566
+ const newPath = `__types__/${path}`;
567
+ files.set(newPath, content);
568
+ mergedCount++;
569
+ }
570
+ }
571
+ if (typesPackage.types && !context.package.types) {
572
+ context.package.types = `__types__/${typesPackage.types}`;
573
+ }
574
+ if (mergedCount > 0) {
575
+ console.error(
576
+ `[types-resolver] Merged ${mergedCount} .d.ts files from ${typesPackageName}`
577
+ );
578
+ }
579
+ } catch (error) {
580
+ }
581
+ });
582
+ }
583
+ };
584
+
585
+ // src/parsers/jsdoc.ts
586
+ var TAG_PATTERNS = {
587
+ /** @param {type} name - description */
588
+ param: /@param\s+(?:\{([^}]*)\})?\s*(\[?\w+(?:\.\w+)*\]?)\s*(?:-\s*)?(.*)$/gm,
589
+ /** @returns {type} description */
590
+ returns: /@returns?\s+(?:\{([^}]*)\})?\s*(.*)/g,
591
+ /** @example ... */
592
+ example: /@example\s*([\s\S]*?)(?=@\w|$)/g,
593
+ /** @deprecated reason */
594
+ deprecated: /@deprecated\s*(.*)/g,
595
+ /** @since version */
596
+ since: /@since\s*(.*)/g,
597
+ /** @see reference */
598
+ see: /@see\s*(.*)/g,
599
+ /** @throws {type} description */
600
+ throws: /@throws?\s+(?:\{([^}]*)\})?\s*(.*)/g,
601
+ /** @template T - description */
602
+ typeParam: /@template\s+(\w+)\s*(?:-\s*)?(.*)/g};
603
+ function cleanJSDocComment(comment) {
604
+ return comment.replace(/^\/\*\*\s*/, "").replace(/\s*\*\/$/, "").replace(/^\s*\*\s?/gm, "").trim();
605
+ }
606
+ function extractDescription(content) {
607
+ const tagMatch = content.match(/@\w+/);
608
+ if (!tagMatch) {
609
+ return content.trim() || void 0;
610
+ }
611
+ const description = content.slice(0, tagMatch.index).trim();
612
+ return description || void 0;
613
+ }
614
+ function parseParams(content) {
615
+ const params = [];
616
+ const pattern = new RegExp(TAG_PATTERNS.param.source, "gm");
617
+ let match;
618
+ while ((match = pattern.exec(content)) !== null) {
619
+ const [, type, rawName, description] = match;
620
+ if (!rawName) continue;
621
+ const name = rawName;
622
+ const isOptional = name.startsWith("[") && name.endsWith("]");
623
+ const cleanName = isOptional ? name.slice(1, -1) : name;
624
+ params.push({
625
+ name: cleanName,
626
+ type: type?.trim(),
627
+ description: description?.trim() || void 0,
628
+ optional: isOptional
629
+ });
630
+ }
631
+ return params;
632
+ }
633
+ function parseReturns(content) {
634
+ const pattern = new RegExp(TAG_PATTERNS.returns.source, "g");
635
+ const match = pattern.exec(content);
636
+ if (!match) return void 0;
637
+ const [, type, description] = match;
638
+ return {
639
+ type: type?.trim(),
640
+ description: description?.trim() || void 0
641
+ };
642
+ }
643
+ function parseExamples(content) {
644
+ const examples = [];
645
+ const pattern = new RegExp(TAG_PATTERNS.example.source, "g");
646
+ let match;
647
+ while ((match = pattern.exec(content)) !== null) {
648
+ const example = match[1]?.trim();
649
+ if (example) {
650
+ examples.push(example);
651
+ }
652
+ }
653
+ return examples;
654
+ }
655
+ function parseDeprecated(content) {
656
+ const pattern = new RegExp(TAG_PATTERNS.deprecated.source, "g");
657
+ const match = pattern.exec(content);
658
+ return match ? match[1]?.trim() || "true" : void 0;
659
+ }
660
+ function parseSince(content) {
661
+ const pattern = new RegExp(TAG_PATTERNS.since.source, "g");
662
+ const match = pattern.exec(content);
663
+ return match ? match[1]?.trim() : void 0;
664
+ }
665
+ function parseSee(content) {
666
+ const refs = [];
667
+ const pattern = new RegExp(TAG_PATTERNS.see.source, "g");
668
+ let match;
669
+ while ((match = pattern.exec(content)) !== null) {
670
+ const ref = match[1]?.trim();
671
+ if (ref) {
672
+ refs.push(ref);
673
+ }
674
+ }
675
+ return refs;
676
+ }
677
+ function parseThrows(content) {
678
+ const throws = [];
679
+ const pattern = new RegExp(TAG_PATTERNS.throws.source, "g");
680
+ let match;
681
+ while ((match = pattern.exec(content)) !== null) {
682
+ const [, type, description] = match;
683
+ throws.push({
684
+ type: type?.trim(),
685
+ description: description?.trim() || void 0
686
+ });
687
+ }
688
+ return throws;
689
+ }
690
+ function parseTypeParams(content) {
691
+ const params = [];
692
+ const pattern = new RegExp(TAG_PATTERNS.typeParam.source, "g");
693
+ let match;
694
+ while ((match = pattern.exec(content)) !== null) {
695
+ const [, name, description] = match;
696
+ if (!name) continue;
697
+ params.push({
698
+ name: name.trim(),
699
+ description: description?.trim() || void 0
700
+ });
701
+ }
702
+ return params;
703
+ }
704
+ function parseJSDoc(comment) {
705
+ const content = cleanJSDocComment(comment);
706
+ return {
707
+ description: extractDescription(content),
708
+ params: parseParams(content).map((p) => ({
709
+ name: p.name,
710
+ type: p.type,
711
+ description: p.description,
712
+ optional: p.optional,
713
+ defaultValue: p.defaultValue
714
+ })),
715
+ returns: parseReturns(content),
716
+ examples: parseExamples(content),
717
+ deprecated: parseDeprecated(content),
718
+ since: parseSince(content),
719
+ see: parseSee(content),
720
+ throws: parseThrows(content),
721
+ typeParams: parseTypeParams(content)
722
+ };
723
+ }
724
+ function extractJSDocComments(source) {
725
+ const comments = [];
726
+ const pattern = /\/\*\*[\s\S]*?\*\//g;
727
+ let match;
728
+ while ((match = pattern.exec(source)) !== null) {
729
+ comments.push({
730
+ comment: match[0],
731
+ start: match.index,
732
+ end: match.index + match[0].length
733
+ });
734
+ }
735
+ return comments;
736
+ }
737
+ function findPrecedingJSDoc(source, position, comments) {
738
+ const allComments = comments ?? extractJSDocComments(source);
739
+ for (let i = allComments.length - 1; i >= 0; i--) {
740
+ const comment = allComments[i];
741
+ if (!comment || comment.end > position) continue;
742
+ const between = source.slice(comment.end, position);
743
+ if (/^\s*$/.test(between)) {
744
+ return parseJSDoc(comment.comment);
745
+ }
746
+ if (comment.end < position - 500) break;
747
+ }
748
+ return void 0;
749
+ }
750
+
751
+ // src/parsers/dts.ts
752
+ var PATTERNS = {
753
+ /** Export function declaration */
754
+ exportFunction: /export\s+(?:declare\s+)?function\s+(\w+)\s*(<[^>]*>)?\s*\(([^)]*)\)\s*:\s*([^;{]+)/g,
755
+ /** Export const declaration */
756
+ exportConst: /export\s+(?:declare\s+)?const\s+(\w+)\s*:\s*([^;=]+)/g,
757
+ /** Export class declaration */
758
+ exportClass: /export\s+(?:declare\s+)?(?:abstract\s+)?class\s+(\w+)(?:\s*<([^>]*)>)?(?:\s+extends\s+([^\s{]+))?(?:\s+implements\s+([^{]+))?\s*\{/g,
759
+ /** Export interface declaration */
760
+ exportInterface: /export\s+(?:declare\s+)?interface\s+(\w+)(?:\s*<([^>]*)>)?(?:\s+extends\s+([^{]+))?\s*\{/g,
761
+ /** Export type declaration */
762
+ exportType: /export\s+(?:declare\s+)?type\s+(\w+)(?:\s*<([^>]*)>)?\s*=\s*([^;]+)/g,
763
+ /** Export enum declaration */
764
+ exportEnum: /export\s+(?:declare\s+)?(?:const\s+)?enum\s+(\w+)\s*\{/g,
765
+ /** Import statement */
766
+ importStatement: /import\s*(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)\s*from\s*['"]([^'"]+)['"]/g,
767
+ /** Declare module (module augmentation) */
768
+ declareModule: /declare\s+module\s+['"]([^'"]+)['"]\s*\{/g};
769
+ function parseParameters(paramStr) {
770
+ if (!paramStr.trim()) return [];
771
+ const params = [];
772
+ const parts = splitParameters(paramStr);
773
+ for (const part of parts) {
774
+ const trimmed = part.trim();
775
+ if (!trimmed) continue;
776
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
777
+ const colonIndex = findTypeColonIndex(trimmed);
778
+ if (colonIndex > 0) {
779
+ params.push({
780
+ name: "options",
781
+ type: trimmed.slice(colonIndex + 1).trim(),
782
+ optional: trimmed.includes("?")
783
+ });
784
+ }
785
+ continue;
786
+ }
787
+ const match = trimmed.match(/^(\w+)(\?)?\s*:\s*(.+?)(?:\s*=\s*(.+))?$/);
788
+ if (match) {
789
+ const [, name, optional, type, defaultValue] = match;
790
+ if (name && type) {
791
+ params.push({
792
+ name,
793
+ type: type.trim(),
794
+ optional: !!optional,
795
+ defaultValue: defaultValue?.trim()
796
+ });
797
+ }
798
+ } else {
799
+ const nameMatch = trimmed.match(/^(\w+)(\?)?$/);
800
+ if (nameMatch && nameMatch[1]) {
801
+ params.push({
802
+ name: nameMatch[1],
803
+ type: "unknown",
804
+ optional: !!nameMatch[2]
805
+ });
806
+ }
807
+ }
808
+ }
809
+ return params;
810
+ }
811
+ function splitParameters(paramStr) {
812
+ const parts = [];
813
+ let current = "";
814
+ let depth = 0;
815
+ for (let i = 0; i < paramStr.length; i++) {
816
+ const char = paramStr[i];
817
+ if (char === "<" || char === "{" || char === "[" || char === "(") {
818
+ depth++;
819
+ current += char;
820
+ } else if (char === ">" || char === "}" || char === "]" || char === ")") {
821
+ depth--;
822
+ current += char;
823
+ } else if (char === "," && depth === 0) {
824
+ parts.push(current);
825
+ current = "";
826
+ } else {
827
+ current += char;
828
+ }
829
+ }
830
+ if (current.trim()) {
831
+ parts.push(current);
832
+ }
833
+ return parts;
834
+ }
835
+ function findTypeColonIndex(str) {
836
+ let depth = 0;
837
+ for (let i = 0; i < str.length; i++) {
838
+ const char = str[i];
839
+ if (char === "{" || char === "[" || char === "<" || char === "(") {
840
+ depth++;
841
+ } else if (char === "}" || char === "]" || char === ">" || char === ")") {
842
+ depth--;
843
+ } else if (char === ":" && depth === 0) {
844
+ return i;
845
+ }
846
+ }
847
+ return -1;
848
+ }
849
+ function extractBody(source, startIndex) {
850
+ let depth = 0;
851
+ let i = startIndex;
852
+ while (i < source.length) {
853
+ if (source[i] === "{") depth++;
854
+ else if (source[i] === "}") {
855
+ depth--;
856
+ if (depth === 0) break;
857
+ }
858
+ i++;
859
+ }
860
+ return source.slice(startIndex + 1, i);
861
+ }
862
+ function parseClassMembers(body, comments, bodyOffset) {
863
+ const methods = [];
864
+ const properties = [];
865
+ const methodPattern = /(?:(?:public|private|protected|static|readonly)\s+)*(\w+)\s*(<[^>]*>)?\s*\(([^)]*)\)\s*:\s*([^;{]+)/g;
866
+ let match;
867
+ while ((match = methodPattern.exec(body)) !== null) {
868
+ const [fullMatch, name, generics, params, returnType] = match;
869
+ if (!name || !returnType) continue;
870
+ const jsdoc = findPrecedingJSDoc(body, match.index, comments.map((c) => ({
871
+ ...c,
872
+ start: c.start - bodyOffset,
873
+ end: c.end - bodyOffset
874
+ })));
875
+ methods.push({
876
+ kind: "function",
877
+ name,
878
+ signature: `${name}${generics || ""}(${params || ""}): ${returnType.trim()}`,
879
+ description: jsdoc?.description,
880
+ params: mergeParamDocs(parseParameters(params || ""), jsdoc?.params),
881
+ returns: {
882
+ type: returnType.trim(),
883
+ description: jsdoc?.returns?.description
884
+ },
885
+ examples: jsdoc?.examples
886
+ });
887
+ }
888
+ const propPattern = /(?:(?:public|private|protected|static|readonly)\s+)*(\w+)(\?)?\s*:\s*([^;]+)/g;
889
+ while ((match = propPattern.exec(body)) !== null) {
890
+ const [, name, optional, type] = match;
891
+ if (!name || !type) continue;
892
+ if (type.includes("=>") || type.includes("(")) continue;
893
+ properties.push({
894
+ kind: "constant",
895
+ name,
896
+ signature: `${name}${optional || ""}: ${type.trim()}`,
897
+ description: findPrecedingJSDoc(body, match.index)?.description
898
+ });
899
+ }
900
+ return { methods, properties };
901
+ }
902
+ function mergeParamDocs(sigParams, jsdocParams) {
903
+ if (!jsdocParams || jsdocParams.length === 0) return sigParams;
904
+ return sigParams.map((param) => {
905
+ const jsdocParam = jsdocParams.find((p) => p.name === param.name);
906
+ if (jsdocParam) {
907
+ return {
908
+ ...param,
909
+ description: jsdocParam.description || param.description,
910
+ type: param.type || jsdocParam.type,
911
+ optional: param.optional || jsdocParam.optional,
912
+ defaultValue: param.defaultValue || jsdocParam.defaultValue
913
+ };
914
+ }
915
+ return param;
916
+ });
917
+ }
918
+ function parseEnumMembers(body) {
919
+ const members = [];
920
+ const pattern = /(\w+)\s*(?:=\s*([^,}]+))?/g;
921
+ let match;
922
+ while ((match = pattern.exec(body)) !== null) {
923
+ const [, name, value] = match;
924
+ if (!name) continue;
925
+ let parsedValue;
926
+ if (value !== void 0) {
927
+ const trimmed = value.trim();
928
+ const num = Number(trimmed);
929
+ if (!isNaN(num)) {
930
+ parsedValue = num;
931
+ } else {
932
+ parsedValue = trimmed.replace(/^['"]|['"]$/g, "");
933
+ }
934
+ }
935
+ members.push({ name, value: parsedValue });
936
+ }
937
+ return members;
938
+ }
939
+ function parseDts(content, filePath) {
940
+ const exports$1 = [];
941
+ const imports = [];
942
+ let moduleName;
943
+ const comments = extractJSDocComments(content);
944
+ const moduleMatch = PATTERNS.declareModule.exec(content);
945
+ if (moduleMatch) {
946
+ moduleName = moduleMatch[1];
947
+ }
948
+ let match;
949
+ PATTERNS.exportFunction.lastIndex = 0;
950
+ while ((match = PATTERNS.exportFunction.exec(content)) !== null) {
951
+ const [fullMatch, name, generics, params, returnType] = match;
952
+ if (!name || !returnType) continue;
953
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
954
+ exports$1.push({
955
+ kind: "function",
956
+ name,
957
+ signature: `function ${name}${generics || ""}(${params || ""}): ${returnType.trim()}`,
958
+ description: jsdoc?.description,
959
+ params: mergeParamDocs(parseParameters(params || ""), jsdoc?.params),
960
+ returns: {
961
+ type: returnType.trim(),
962
+ description: jsdoc?.returns?.description
963
+ },
964
+ examples: jsdoc?.examples,
965
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
966
+ since: jsdoc?.since,
967
+ see: jsdoc?.see,
968
+ sourceFile: filePath
969
+ });
970
+ }
971
+ PATTERNS.exportConst.lastIndex = 0;
972
+ while ((match = PATTERNS.exportConst.exec(content)) !== null) {
973
+ const [, name, type] = match;
974
+ if (!name || !type) continue;
975
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
976
+ exports$1.push({
977
+ kind: "constant",
978
+ name,
979
+ signature: `const ${name}: ${type.trim()}`,
980
+ description: jsdoc?.description,
981
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
982
+ sourceFile: filePath
983
+ });
984
+ }
985
+ PATTERNS.exportClass.lastIndex = 0;
986
+ while ((match = PATTERNS.exportClass.exec(content)) !== null) {
987
+ const [, name, generics, extendsClause, implementsClause] = match;
988
+ if (!name) continue;
989
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
990
+ const bodyStart = match.index + match[0].length - 1;
991
+ const body = extractBody(content, bodyStart);
992
+ const { methods, properties } = parseClassMembers(body, comments, bodyStart);
993
+ exports$1.push({
994
+ kind: "class",
995
+ name,
996
+ signature: `class ${name}${generics ? `<${generics}>` : ""}`,
997
+ description: jsdoc?.description,
998
+ extends: extendsClause ? [extendsClause.trim()] : void 0,
999
+ implements: implementsClause ? implementsClause.split(",").map((s) => s.trim()) : void 0,
1000
+ methods,
1001
+ properties,
1002
+ typeParams: generics ? generics.split(",").map((s) => s.trim()) : void 0,
1003
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1004
+ sourceFile: filePath
1005
+ });
1006
+ }
1007
+ PATTERNS.exportInterface.lastIndex = 0;
1008
+ while ((match = PATTERNS.exportInterface.exec(content)) !== null) {
1009
+ const [, name, generics, extendsClause] = match;
1010
+ if (!name) continue;
1011
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1012
+ const bodyStart = match.index + match[0].length - 1;
1013
+ const body = extractBody(content, bodyStart);
1014
+ const { methods, properties } = parseClassMembers(body, comments, bodyStart);
1015
+ exports$1.push({
1016
+ kind: "interface",
1017
+ name,
1018
+ signature: `interface ${name}${generics ? `<${generics}>` : ""}`,
1019
+ description: jsdoc?.description,
1020
+ extends: extendsClause ? extendsClause.split(",").map((s) => s.trim()) : void 0,
1021
+ methods,
1022
+ properties,
1023
+ typeParams: generics ? generics.split(",").map((s) => s.trim()) : void 0,
1024
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1025
+ sourceFile: filePath
1026
+ });
1027
+ }
1028
+ PATTERNS.exportType.lastIndex = 0;
1029
+ while ((match = PATTERNS.exportType.exec(content)) !== null) {
1030
+ const [, name, generics, definition] = match;
1031
+ if (!name || !definition) continue;
1032
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1033
+ exports$1.push({
1034
+ kind: "type",
1035
+ name,
1036
+ signature: `type ${name}${generics ? `<${generics}>` : ""} = ${definition.trim()}`,
1037
+ description: jsdoc?.description,
1038
+ typeParams: generics ? generics.split(",").map((s) => s.trim()) : void 0,
1039
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1040
+ sourceFile: filePath
1041
+ });
1042
+ }
1043
+ PATTERNS.exportEnum.lastIndex = 0;
1044
+ while ((match = PATTERNS.exportEnum.exec(content)) !== null) {
1045
+ const [, name] = match;
1046
+ if (!name) continue;
1047
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1048
+ const bodyStart = match.index + match[0].length - 1;
1049
+ const body = extractBody(content, bodyStart);
1050
+ const members = parseEnumMembers(body);
1051
+ exports$1.push({
1052
+ kind: "enum",
1053
+ name,
1054
+ signature: `enum ${name}`,
1055
+ description: jsdoc?.description,
1056
+ members,
1057
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1058
+ sourceFile: filePath
1059
+ });
1060
+ }
1061
+ PATTERNS.importStatement.lastIndex = 0;
1062
+ while ((match = PATTERNS.importStatement.exec(content)) !== null) {
1063
+ if (match[1]) {
1064
+ imports.push(match[1]);
1065
+ }
1066
+ }
1067
+ PATTERNS.declareModule.lastIndex = 0;
1068
+ while ((match = PATTERNS.declareModule.exec(content)) !== null) {
1069
+ const moduleBodyStart = match.index + match[0].length - 1;
1070
+ const moduleBody = extractBody(content, moduleBodyStart);
1071
+ const moduleExports = parseModuleAugmentation(moduleBody, comments, moduleBodyStart, filePath);
1072
+ for (const entry of moduleExports) {
1073
+ exports$1.push(entry);
1074
+ }
1075
+ }
1076
+ return { exports: exports$1, imports, moduleName };
1077
+ }
1078
+ function parseModuleAugmentation(body, _comments, _bodyOffset, filePath) {
1079
+ const entries = [];
1080
+ const moduleComments = extractJSDocComments(body);
1081
+ const interfacePattern = /interface\s+(\w+)(?:\s*<([^>]*)>)?(?:\s+extends\s+([^{]+))?\s*\{/g;
1082
+ let match;
1083
+ while ((match = interfacePattern.exec(body)) !== null) {
1084
+ const [, interfaceName, generics, extendsClause] = match;
1085
+ if (!interfaceName) continue;
1086
+ const ifaceBodyStart = match.index + match[0].length - 1;
1087
+ const ifaceBody = extractBody(body, ifaceBodyStart);
1088
+ if (interfaceName === "LoDashStatic" || interfaceName.endsWith("Static")) {
1089
+ const methods = parseInterfaceMethodsAsExports(
1090
+ ifaceBody,
1091
+ moduleComments,
1092
+ ifaceBodyStart,
1093
+ filePath
1094
+ );
1095
+ for (const method of methods) {
1096
+ entries.push(method);
1097
+ }
1098
+ }
1099
+ }
1100
+ return entries;
1101
+ }
1102
+ function parseInterfaceMethodsAsExports(body, _comments, _bodyOffset, filePath) {
1103
+ const methods = [];
1104
+ const bodyComments = extractJSDocComments(body);
1105
+ const methodPattern = /(\w+)\s*(<[^>]*>)?\s*\(([^)]*)\)\s*:\s*([^;]+);/g;
1106
+ let match;
1107
+ while ((match = methodPattern.exec(body)) !== null) {
1108
+ const [fullMatch, name, generics, params, returnType] = match;
1109
+ if (!name || !returnType) continue;
1110
+ if (["constructor", "toString", "valueOf", "toJSON"].includes(name)) continue;
1111
+ const jsdoc = findPrecedingJSDoc(body, match.index, bodyComments);
1112
+ methods.push({
1113
+ kind: "function",
1114
+ name,
1115
+ signature: `function ${name}${generics || ""}(${params || ""}): ${returnType.trim()}`,
1116
+ description: jsdoc?.description,
1117
+ params: mergeParamDocs(parseParameters(params || ""), jsdoc?.params),
1118
+ returns: {
1119
+ type: returnType.trim(),
1120
+ description: jsdoc?.returns?.description
1121
+ },
1122
+ examples: jsdoc?.examples,
1123
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1124
+ since: jsdoc?.since,
1125
+ see: jsdoc?.see,
1126
+ sourceFile: filePath
1127
+ });
1128
+ }
1129
+ return methods;
1130
+ }
1131
+ function sortExports(exports$1) {
1132
+ const kindOrder = {
1133
+ function: 1,
1134
+ class: 2,
1135
+ interface: 3,
1136
+ type: 4,
1137
+ enum: 5,
1138
+ constant: 6
1139
+ };
1140
+ return [...exports$1].sort((a, b) => {
1141
+ const kindDiff = kindOrder[a.kind] - kindOrder[b.kind];
1142
+ if (kindDiff !== 0) return kindDiff;
1143
+ return a.name.localeCompare(b.name);
1144
+ });
1145
+ }
1146
+ function findMainDtsFile(files, typesField) {
1147
+ if (typesField) {
1148
+ const normalized = typesField.replace(/^\.\//, "");
1149
+ if (files.has(normalized)) return normalized;
1150
+ }
1151
+ const priorities = [
1152
+ "index.d.ts",
1153
+ "dist/index.d.ts",
1154
+ "lib/index.d.ts",
1155
+ "types/index.d.ts",
1156
+ "src/index.d.ts",
1157
+ // @types packages merged via types-resolver plugin
1158
+ "__types__/index.d.ts",
1159
+ "__types__/dist/index.d.ts",
1160
+ "__types__/lib/index.d.ts",
1161
+ "__types__/types/index.d.ts"
1162
+ ];
1163
+ for (const path of priorities) {
1164
+ if (files.has(path)) return path;
1165
+ }
1166
+ for (const path of files.keys()) {
1167
+ if (path.endsWith(".d.ts") && !path.startsWith("__types__/")) {
1168
+ return path;
1169
+ }
1170
+ }
1171
+ for (const path of files.keys()) {
1172
+ if (path.endsWith(".d.ts") && path.startsWith("__types__/")) {
1173
+ return path;
1174
+ }
1175
+ }
1176
+ return void 0;
1177
+ }
1178
+
1179
+ // src/plugins/core/dts-parser.ts
1180
+ var dtsParserPlugin = {
1181
+ name: "dts-parser",
1182
+ version: "1.0.0",
1183
+ category: "parser",
1184
+ install(kernel) {
1185
+ kernel.on("parse:start", async (context) => {
1186
+ const { files } = context.package;
1187
+ const mainDts = findMainDtsFile(files, context.package.types);
1188
+ if (!mainDts) {
1189
+ return;
1190
+ }
1191
+ const dtsFiles = Array.from(files.entries()).filter(([path]) => path.endsWith(".d.ts")).sort(([a], [b]) => {
1192
+ if (a === mainDts) return -1;
1193
+ if (b === mainDts) return 1;
1194
+ if (a.includes("index.d.ts")) return -1;
1195
+ if (b.includes("index.d.ts")) return 1;
1196
+ return a.localeCompare(b);
1197
+ });
1198
+ const seenNames = /* @__PURE__ */ new Set();
1199
+ for (const [path, content] of dtsFiles) {
1200
+ try {
1201
+ const result = parseDts(content, path);
1202
+ for (const entry of result.exports) {
1203
+ if (!seenNames.has(entry.name)) {
1204
+ seenNames.add(entry.name);
1205
+ context.api.push(entry);
1206
+ }
1207
+ }
1208
+ } catch (error) {
1209
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
1210
+ }
1211
+ }
1212
+ context.api = sortExports(context.api);
1213
+ });
1214
+ }
1215
+ };
1216
+
1217
+ // src/parsers/typescript.ts
1218
+ var PATTERNS2 = {
1219
+ /** Export function */
1220
+ exportFunction: /export\s+(?:async\s+)?function\s+(\w+)\s*(<[^>]*>)?\s*\(([^)]*)\)(?:\s*:\s*([^{]+))?\s*\{/g,
1221
+ /** Export arrow function */
1222
+ exportArrow: /export\s+const\s+(\w+)\s*(?::\s*([^=]+))?\s*=\s*(?:async\s*)?\([^)]*\)\s*(?::\s*([^=]+))?\s*=>/g,
1223
+ /** Export class */
1224
+ exportClass: /export\s+(?:abstract\s+)?class\s+(\w+)(?:\s*<([^>]*)>)?(?:\s+extends\s+([^\s{]+))?(?:\s+implements\s+([^{]+))?\s*\{/g,
1225
+ /** Export interface */
1226
+ exportInterface: /export\s+interface\s+(\w+)(?:\s*<([^>]*)>)?(?:\s+extends\s+([^{]+))?\s*\{/g,
1227
+ /** Export type */
1228
+ exportType: /export\s+type\s+(\w+)(?:\s*<([^>]*)>)?\s*=\s*([^;]+)/g,
1229
+ /** Export const/let */
1230
+ exportConst: /export\s+(?:const|let)\s+(\w+)(?:\s*:\s*([^=]+))?\s*=/g,
1231
+ /** Export enum */
1232
+ exportEnum: /export\s+(?:const\s+)?enum\s+(\w+)\s*\{/g};
1233
+ function parseSourceParams(paramStr) {
1234
+ if (!paramStr.trim()) return [];
1235
+ const params = [];
1236
+ const parts = splitParams(paramStr);
1237
+ for (const part of parts) {
1238
+ const trimmed = part.trim();
1239
+ if (!trimmed) continue;
1240
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
1241
+ const colonIndex = findBalancedColon(trimmed);
1242
+ if (colonIndex > 0) {
1243
+ params.push({
1244
+ name: "options",
1245
+ type: trimmed.slice(colonIndex + 1).trim(),
1246
+ optional: trimmed.includes("?")
1247
+ });
1248
+ } else {
1249
+ params.push({
1250
+ name: "options",
1251
+ type: "object"
1252
+ });
1253
+ }
1254
+ continue;
1255
+ }
1256
+ const match = trimmed.match(/^(\w+)(\?)?\s*(?::\s*(.+?))?(?:\s*=\s*(.+))?$/);
1257
+ if (match && match[1]) {
1258
+ const [, name, optional, type, defaultValue] = match;
1259
+ params.push({
1260
+ name,
1261
+ type: type?.trim() || inferTypeFromDefault(defaultValue),
1262
+ optional: !!optional || !!defaultValue,
1263
+ defaultValue: defaultValue?.trim()
1264
+ });
1265
+ }
1266
+ }
1267
+ return params;
1268
+ }
1269
+ function splitParams(str) {
1270
+ const parts = [];
1271
+ let current = "";
1272
+ let depth = 0;
1273
+ for (const char of str) {
1274
+ if (char === "<" || char === "{" || char === "[" || char === "(") {
1275
+ depth++;
1276
+ current += char;
1277
+ } else if (char === ">" || char === "}" || char === "]" || char === ")") {
1278
+ depth--;
1279
+ current += char;
1280
+ } else if (char === "," && depth === 0) {
1281
+ parts.push(current);
1282
+ current = "";
1283
+ } else {
1284
+ current += char;
1285
+ }
1286
+ }
1287
+ if (current.trim()) parts.push(current);
1288
+ return parts;
1289
+ }
1290
+ function findBalancedColon(str) {
1291
+ let depth = 0;
1292
+ for (let i = 0; i < str.length; i++) {
1293
+ const char = str[i];
1294
+ if (char === "{" || char === "[" || char === "<" || char === "(") {
1295
+ depth++;
1296
+ } else if (char === "}" || char === "]" || char === ">" || char === ")") {
1297
+ depth--;
1298
+ } else if (char === ":" && depth === 0) {
1299
+ return i;
1300
+ }
1301
+ }
1302
+ return -1;
1303
+ }
1304
+ function inferTypeFromDefault(defaultValue) {
1305
+ if (!defaultValue) return "unknown";
1306
+ const trimmed = defaultValue.trim();
1307
+ if (trimmed === "true" || trimmed === "false") return "boolean";
1308
+ if (trimmed.startsWith("'") || trimmed.startsWith('"') || trimmed.startsWith("`")) {
1309
+ return "string";
1310
+ }
1311
+ if (/^-?\d+(\.\d+)?$/.test(trimmed)) return "number";
1312
+ if (trimmed === "null") return "null";
1313
+ if (trimmed === "undefined") return "undefined";
1314
+ if (trimmed.startsWith("[")) return "unknown[]";
1315
+ if (trimmed.startsWith("{")) return "object";
1316
+ if (trimmed.startsWith("()") || trimmed.includes("=>")) return "Function";
1317
+ return "unknown";
1318
+ }
1319
+ function parseTypeScript(content, filePath) {
1320
+ const exports$1 = [];
1321
+ let hasTypes = false;
1322
+ hasTypes = /:\s*\w+/.test(content) || content.includes("interface ") || content.includes("type ");
1323
+ const comments = extractJSDocComments(content);
1324
+ let match;
1325
+ PATTERNS2.exportFunction.lastIndex = 0;
1326
+ while ((match = PATTERNS2.exportFunction.exec(content)) !== null) {
1327
+ const [, name, generics, params, returnType] = match;
1328
+ if (!name) continue;
1329
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1330
+ const paramStr = params || "";
1331
+ exports$1.push({
1332
+ kind: "function",
1333
+ name,
1334
+ signature: `function ${name}${generics || ""}(${paramStr})${returnType ? `: ${returnType.trim()}` : ""}`,
1335
+ description: jsdoc?.description,
1336
+ params: mergeParams(parseSourceParams(paramStr), jsdoc?.params),
1337
+ returns: returnType ? { type: returnType.trim(), description: jsdoc?.returns?.description } : void 0,
1338
+ examples: jsdoc?.examples,
1339
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1340
+ sourceFile: filePath
1341
+ });
1342
+ }
1343
+ PATTERNS2.exportArrow.lastIndex = 0;
1344
+ while ((match = PATTERNS2.exportArrow.exec(content)) !== null) {
1345
+ const [fullMatch, name, typeAnnotation, returnType] = match;
1346
+ if (!name || !fullMatch) continue;
1347
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1348
+ const paramsStart = fullMatch.indexOf("(");
1349
+ const paramsEnd = fullMatch.indexOf(")", paramsStart);
1350
+ const params = fullMatch.slice(paramsStart + 1, paramsEnd);
1351
+ exports$1.push({
1352
+ kind: "function",
1353
+ name,
1354
+ signature: typeAnnotation ? `const ${name}: ${typeAnnotation.trim()}` : `const ${name} = (${params})${returnType ? ` => ${returnType.trim()}` : ""}`,
1355
+ description: jsdoc?.description,
1356
+ params: mergeParams(parseSourceParams(params), jsdoc?.params),
1357
+ returns: returnType ? { type: returnType.trim(), description: jsdoc?.returns?.description } : void 0,
1358
+ examples: jsdoc?.examples,
1359
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1360
+ sourceFile: filePath
1361
+ });
1362
+ }
1363
+ PATTERNS2.exportClass.lastIndex = 0;
1364
+ while ((match = PATTERNS2.exportClass.exec(content)) !== null) {
1365
+ const [, name, generics, extendsClause, implementsClause] = match;
1366
+ if (!name) continue;
1367
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1368
+ exports$1.push({
1369
+ kind: "class",
1370
+ name,
1371
+ signature: `class ${name}${generics ? `<${generics}>` : ""}`,
1372
+ description: jsdoc?.description,
1373
+ extends: extendsClause ? [extendsClause.trim()] : void 0,
1374
+ implements: implementsClause ? implementsClause.split(",").map((s) => s.trim()) : void 0,
1375
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1376
+ sourceFile: filePath
1377
+ });
1378
+ }
1379
+ PATTERNS2.exportInterface.lastIndex = 0;
1380
+ while ((match = PATTERNS2.exportInterface.exec(content)) !== null) {
1381
+ const [, name, generics, extendsClause] = match;
1382
+ if (!name) continue;
1383
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1384
+ exports$1.push({
1385
+ kind: "interface",
1386
+ name,
1387
+ signature: `interface ${name}${generics ? `<${generics}>` : ""}`,
1388
+ description: jsdoc?.description,
1389
+ extends: extendsClause ? extendsClause.split(",").map((s) => s.trim()) : void 0,
1390
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1391
+ sourceFile: filePath
1392
+ });
1393
+ }
1394
+ PATTERNS2.exportType.lastIndex = 0;
1395
+ while ((match = PATTERNS2.exportType.exec(content)) !== null) {
1396
+ const [, name, generics, definition] = match;
1397
+ if (!name || !definition) continue;
1398
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1399
+ exports$1.push({
1400
+ kind: "type",
1401
+ name,
1402
+ signature: `type ${name}${generics ? `<${generics}>` : ""} = ${definition.trim()}`,
1403
+ description: jsdoc?.description,
1404
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1405
+ sourceFile: filePath
1406
+ });
1407
+ }
1408
+ PATTERNS2.exportConst.lastIndex = 0;
1409
+ while ((match = PATTERNS2.exportConst.exec(content)) !== null) {
1410
+ const [, name, type] = match;
1411
+ if (!name) continue;
1412
+ if (content.slice(match.index, match.index + 200).includes("=>")) continue;
1413
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1414
+ exports$1.push({
1415
+ kind: "constant",
1416
+ name,
1417
+ signature: `const ${name}${type ? `: ${type.trim()}` : ""}`,
1418
+ description: jsdoc?.description,
1419
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1420
+ sourceFile: filePath
1421
+ });
1422
+ }
1423
+ PATTERNS2.exportEnum.lastIndex = 0;
1424
+ while ((match = PATTERNS2.exportEnum.exec(content)) !== null) {
1425
+ const [, name] = match;
1426
+ if (!name) continue;
1427
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1428
+ exports$1.push({
1429
+ kind: "enum",
1430
+ name,
1431
+ signature: `enum ${name}`,
1432
+ description: jsdoc?.description,
1433
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1434
+ sourceFile: filePath
1435
+ });
1436
+ }
1437
+ return { exports: exports$1, hasTypes };
1438
+ }
1439
+ function mergeParams(sourceParams, jsdocParams) {
1440
+ if (!jsdocParams || jsdocParams.length === 0) return sourceParams;
1441
+ return sourceParams.map((param) => {
1442
+ const jsdocParam = jsdocParams.find((p) => p.name === param.name);
1443
+ if (jsdocParam) {
1444
+ return {
1445
+ ...param,
1446
+ description: jsdocParam.description || param.description,
1447
+ type: param.type !== "unknown" ? param.type : jsdocParam.type
1448
+ };
1449
+ }
1450
+ return param;
1451
+ });
1452
+ }
1453
+ function findTypeScriptFiles(files, mainField) {
1454
+ const tsFiles = [];
1455
+ const priorities = [];
1456
+ if (mainField) {
1457
+ const base = mainField.replace(/^\.\//, "").replace(/\.[jt]sx?$/, "");
1458
+ priorities.push(
1459
+ `${base}.ts`,
1460
+ `${base}.tsx`,
1461
+ `src/${base}.ts`,
1462
+ `src/${base}.tsx`
1463
+ );
1464
+ }
1465
+ priorities.push(
1466
+ "src/index.ts",
1467
+ "src/index.tsx",
1468
+ "index.ts",
1469
+ "index.tsx",
1470
+ "lib/index.ts",
1471
+ "src/main.ts"
1472
+ );
1473
+ for (const path of priorities) {
1474
+ if (files.has(path) && !tsFiles.includes(path)) {
1475
+ tsFiles.push(path);
1476
+ }
1477
+ }
1478
+ for (const path of files.keys()) {
1479
+ if ((path.endsWith(".ts") || path.endsWith(".tsx")) && !path.endsWith(".d.ts")) {
1480
+ if (!tsFiles.includes(path)) {
1481
+ tsFiles.push(path);
1482
+ }
1483
+ }
1484
+ }
1485
+ return tsFiles;
1486
+ }
1487
+
1488
+ // src/plugins/core/ts-source-parser.ts
1489
+ var tsSourceParserPlugin = {
1490
+ name: "ts-source-parser",
1491
+ version: "1.0.0",
1492
+ category: "parser",
1493
+ install(kernel) {
1494
+ kernel.on("parse:start", async (context) => {
1495
+ if (context.api.length > 0) {
1496
+ return;
1497
+ }
1498
+ const { files } = context.package;
1499
+ const tsFiles = findTypeScriptFiles(files, context.package.main);
1500
+ if (tsFiles.length === 0) {
1501
+ return;
1502
+ }
1503
+ const seenNames = /* @__PURE__ */ new Set();
1504
+ for (const path of tsFiles) {
1505
+ const content = files.get(path);
1506
+ if (!content) continue;
1507
+ try {
1508
+ const result = parseTypeScript(content, path);
1509
+ for (const entry of result.exports) {
1510
+ if (!seenNames.has(entry.name)) {
1511
+ seenNames.add(entry.name);
1512
+ context.api.push(entry);
1513
+ }
1514
+ }
1515
+ } catch (error) {
1516
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
1517
+ }
1518
+ }
1519
+ context.api = sortExports(context.api);
1520
+ });
1521
+ }
1522
+ };
1523
+
1524
+ // src/parsers/readme.ts
1525
+ var SECTION_PATTERNS = {
1526
+ installation: /^#+\s*(installation|install|setup|getting started)/i,
1527
+ quickStart: /^#+\s*(quick\s*start|usage|getting\s*started|basic\s*usage)/i,
1528
+ api: /^#+\s*(api|api\s*reference|reference|methods|functions)/i,
1529
+ examples: /^#+\s*(examples?|code\s*examples?)/i};
1530
+ var BADGE_PATTERN = /\[!\[([^\]]*)\]\(([^)]+)\)\]\([^)]+\)|\!\[([^\]]*)\]\(([^)]+)\)/g;
1531
+ var CODE_BLOCK_PATTERN = /```(\w+)?\s*\n([\s\S]*?)```/g;
1532
+ function parseReadme(content) {
1533
+ const sections = extractSections(content);
1534
+ const badges = extractBadges(content);
1535
+ const { title, description } = extractTitleAndDescription(content, sections);
1536
+ const installation = findSection(sections, SECTION_PATTERNS.installation);
1537
+ const quickStart = findSection(sections, SECTION_PATTERNS.quickStart);
1538
+ const api = findSection(sections, SECTION_PATTERNS.api);
1539
+ const examples = findExampleSections(sections);
1540
+ return {
1541
+ title,
1542
+ description,
1543
+ badges,
1544
+ installation: installation?.content,
1545
+ quickStart: quickStart?.content || findQuickStartFromCode(content),
1546
+ examples,
1547
+ api: api?.content,
1548
+ sections
1549
+ };
1550
+ }
1551
+ function extractSections(content) {
1552
+ const sections = [];
1553
+ const lines = content.split("\n");
1554
+ let currentSection = null;
1555
+ let currentContent = [];
1556
+ let charIndex = 0;
1557
+ function finishSection() {
1558
+ if (currentSection) {
1559
+ currentSection.content = currentContent.join("\n").trim();
1560
+ currentSection.endIndex = charIndex;
1561
+ sections.push(currentSection);
1562
+ currentContent = [];
1563
+ }
1564
+ }
1565
+ for (const line of lines) {
1566
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
1567
+ if (headingMatch && headingMatch[1] && headingMatch[2]) {
1568
+ finishSection();
1569
+ const level = headingMatch[1].length;
1570
+ const title = headingMatch[2].trim();
1571
+ currentSection = {
1572
+ title,
1573
+ content: "",
1574
+ level,
1575
+ startIndex: charIndex,
1576
+ endIndex: 0
1577
+ };
1578
+ currentContent = [];
1579
+ } else if (currentSection) {
1580
+ currentContent.push(line);
1581
+ }
1582
+ charIndex += line.length + 1;
1583
+ }
1584
+ finishSection();
1585
+ return sections;
1586
+ }
1587
+ function findSection(sections, pattern) {
1588
+ return sections.find((s) => pattern.test(`# ${s.title}`));
1589
+ }
1590
+ function findExampleSections(sections) {
1591
+ const examples = [];
1592
+ for (const section of sections) {
1593
+ if (SECTION_PATTERNS.examples.test(`# ${section.title}`)) {
1594
+ const codeBlocks = extractCodeBlocks(section.content);
1595
+ examples.push(...codeBlocks);
1596
+ }
1597
+ }
1598
+ return examples;
1599
+ }
1600
+ function extractCodeBlocks(content) {
1601
+ const blocks = [];
1602
+ const pattern = new RegExp(CODE_BLOCK_PATTERN.source, "g");
1603
+ let match;
1604
+ while ((match = pattern.exec(content)) !== null) {
1605
+ const [, language, code] = match;
1606
+ if (code && code.trim()) {
1607
+ blocks.push(language ? `\`\`\`${language}
1608
+ ${code.trim()}
1609
+ \`\`\`` : code.trim());
1610
+ }
1611
+ }
1612
+ return blocks;
1613
+ }
1614
+ function extractBadges(content) {
1615
+ const badges = [];
1616
+ const pattern = new RegExp(BADGE_PATTERN.source, "g");
1617
+ let match;
1618
+ while ((match = pattern.exec(content)) !== null) {
1619
+ const altText = match[1] || match[3] || "";
1620
+ if (altText) {
1621
+ badges.push(altText);
1622
+ }
1623
+ }
1624
+ return badges;
1625
+ }
1626
+ function extractTitleAndDescription(content, sections) {
1627
+ let title;
1628
+ let description;
1629
+ const firstHeading = sections[0];
1630
+ if (firstHeading?.level === 1) {
1631
+ title = firstHeading.title;
1632
+ } else {
1633
+ const lines = content.split("\n");
1634
+ for (const line of lines) {
1635
+ const trimmed = line.trim();
1636
+ if (!trimmed) continue;
1637
+ if (trimmed.startsWith("!") || trimmed.startsWith("[!")) continue;
1638
+ if (trimmed.startsWith("#")) {
1639
+ title = trimmed.replace(/^#+\s*/, "");
1640
+ break;
1641
+ }
1642
+ }
1643
+ }
1644
+ const afterTitle = content.split("\n").slice(1);
1645
+ let foundContent = false;
1646
+ for (const line of afterTitle) {
1647
+ const trimmed = line.trim();
1648
+ if (trimmed.startsWith("!") || trimmed.startsWith("[!")) continue;
1649
+ if (trimmed.startsWith("#")) break;
1650
+ if (!trimmed && !foundContent) continue;
1651
+ if (!trimmed && foundContent) break;
1652
+ if (trimmed) {
1653
+ foundContent = true;
1654
+ if (!description) {
1655
+ description = trimmed;
1656
+ } else {
1657
+ description += " " + trimmed;
1658
+ }
1659
+ }
1660
+ }
1661
+ if (description) {
1662
+ description = description.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/\*([^*]+)\*/g, "$1").trim();
1663
+ }
1664
+ return { title, description };
1665
+ }
1666
+ function findQuickStartFromCode(content) {
1667
+ const installMatch = content.match(/installation|install|setup/i);
1668
+ const startIndex = installMatch?.index ?? 0;
1669
+ const searchArea = content.slice(startIndex, startIndex + 2e3);
1670
+ const codeBlocks = extractCodeBlocks(searchArea);
1671
+ for (const block of codeBlocks) {
1672
+ if (block.startsWith("```javascript") || block.startsWith("```typescript") || block.startsWith("```js") || block.startsWith("```ts") || block.startsWith("```jsx") || block.startsWith("```tsx")) {
1673
+ return block;
1674
+ }
1675
+ }
1676
+ return codeBlocks[0];
1677
+ }
1678
+
1679
+ // src/plugins/core/readme-parser.ts
1680
+ var readmeParserPlugin = {
1681
+ name: "readme-parser",
1682
+ version: "1.0.0",
1683
+ category: "parser",
1684
+ install(kernel) {
1685
+ kernel.on("parse:start", async (context) => {
1686
+ const { files } = context.package;
1687
+ let readmeContent;
1688
+ const readmePatterns = [
1689
+ "README.md",
1690
+ "readme.md",
1691
+ "Readme.md",
1692
+ "README.MD",
1693
+ "README",
1694
+ "readme"
1695
+ ];
1696
+ for (const pattern of readmePatterns) {
1697
+ if (files.has(pattern)) {
1698
+ readmeContent = files.get(pattern);
1699
+ break;
1700
+ }
1701
+ }
1702
+ if (!readmeContent) {
1703
+ for (const [path, content] of files) {
1704
+ if (path.toLowerCase().includes("readme")) {
1705
+ readmeContent = content;
1706
+ break;
1707
+ }
1708
+ }
1709
+ }
1710
+ if (!readmeContent) {
1711
+ return;
1712
+ }
1713
+ try {
1714
+ context.readme = parseReadme(readmeContent);
1715
+ if (!context.package.description && context.readme.description) {
1716
+ context.package.description = context.readme.description;
1717
+ }
1718
+ } catch (error) {
1719
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
1720
+ }
1721
+ });
1722
+ }
1723
+ };
1724
+
1725
+ // src/core/tokens.ts
1726
+ var CHARS_PER_TOKEN = {
1727
+ /** English prose: ~4 chars per token */
1728
+ prose: 4,
1729
+ /** Code blocks: ~3 chars per token (more special tokens) */
1730
+ code: 3};
1731
+ var PRIORITY_ORDER = {
1732
+ functions: 100,
1733
+ examples: 90,
1734
+ classes: 80,
1735
+ interfaces: 70,
1736
+ types: 60,
1737
+ readme: 50
1738
+ };
1739
+ function countTokens(text) {
1740
+ if (!text) return 0;
1741
+ let tokens = 0;
1742
+ const codeBlockRegex = /```[\s\S]*?```/g;
1743
+ const parts = [];
1744
+ let lastIndex = 0;
1745
+ let match;
1746
+ while ((match = codeBlockRegex.exec(text)) !== null) {
1747
+ if (match.index > lastIndex) {
1748
+ parts.push({
1749
+ text: text.slice(lastIndex, match.index),
1750
+ isCode: false
1751
+ });
1752
+ }
1753
+ parts.push({
1754
+ text: match[0],
1755
+ isCode: true
1756
+ });
1757
+ lastIndex = match.index + match[0].length;
1758
+ }
1759
+ if (lastIndex < text.length) {
1760
+ parts.push({
1761
+ text: text.slice(lastIndex),
1762
+ isCode: false
1763
+ });
1764
+ }
1765
+ for (const part of parts) {
1766
+ const charsPerToken = part.isCode ? CHARS_PER_TOKEN.code : CHARS_PER_TOKEN.prose;
1767
+ tokens += Math.ceil(part.text.length / charsPerToken);
1768
+ }
1769
+ return tokens;
1770
+ }
1771
+ function parseSections(text) {
1772
+ const sections = [];
1773
+ const lines = text.split("\n");
1774
+ let currentSection = null;
1775
+ let currentContent = [];
1776
+ function finishSection() {
1777
+ if (currentSection) {
1778
+ currentSection.content = currentContent.join("\n").trim();
1779
+ currentSection.tokens = countTokens(currentSection.content);
1780
+ sections.push(currentSection);
1781
+ currentContent = [];
1782
+ }
1783
+ }
1784
+ for (const line of lines) {
1785
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
1786
+ if (headingMatch && headingMatch[2]) {
1787
+ finishSection();
1788
+ const title = headingMatch[2].trim();
1789
+ const priority = inferPriority(title);
1790
+ currentSection = {
1791
+ id: title.toLowerCase().replace(/[^a-z0-9]+/g, "-"),
1792
+ title,
1793
+ content: "",
1794
+ priority,
1795
+ tokens: 0
1796
+ };
1797
+ currentContent = [line];
1798
+ } else if (currentSection) {
1799
+ currentContent.push(line);
1800
+ } else {
1801
+ if (line.trim()) {
1802
+ if (!currentSection) {
1803
+ currentSection = {
1804
+ id: "intro",
1805
+ title: "Introduction",
1806
+ content: "",
1807
+ priority: "readme",
1808
+ tokens: 0
1809
+ };
1810
+ }
1811
+ currentContent.push(line);
1812
+ }
1813
+ }
1814
+ }
1815
+ finishSection();
1816
+ return sections;
1817
+ }
1818
+ function inferPriority(title) {
1819
+ const lower = title.toLowerCase();
1820
+ if (lower.includes("function") || lower.includes("method") || lower.includes("api")) {
1821
+ return "functions";
1822
+ }
1823
+ if (lower.includes("example") || lower.includes("usage") || lower.includes("quick start")) {
1824
+ return "examples";
1825
+ }
1826
+ if (lower.includes("class")) {
1827
+ return "classes";
1828
+ }
1829
+ if (lower.includes("interface")) {
1830
+ return "interfaces";
1831
+ }
1832
+ if (lower.includes("type")) {
1833
+ return "types";
1834
+ }
1835
+ return "readme";
1836
+ }
1837
+ function prioritizeSections(sections, priorities = ["functions", "examples"]) {
1838
+ const customOrder = { ...PRIORITY_ORDER };
1839
+ priorities.forEach((p, i) => {
1840
+ customOrder[p] = 1e3 - i;
1841
+ });
1842
+ return [...sections].sort((a, b) => {
1843
+ return (customOrder[b.priority] ?? 0) - (customOrder[a.priority] ?? 0);
1844
+ });
1845
+ }
1846
+ function truncateToTokenLimit(text, limit, priorities = ["functions", "examples"]) {
1847
+ const currentTokens = countTokens(text);
1848
+ if (currentTokens <= limit) {
1849
+ return {
1850
+ text,
1851
+ truncated: false,
1852
+ tokenCount: currentTokens,
1853
+ includedSections: [],
1854
+ removedSections: []
1855
+ };
1856
+ }
1857
+ const sections = parseSections(text);
1858
+ const prioritized = prioritizeSections(sections, priorities);
1859
+ const included = [];
1860
+ const removed = [];
1861
+ let usedTokens = 0;
1862
+ for (const section of prioritized) {
1863
+ if (usedTokens + section.tokens <= limit) {
1864
+ included.push(section);
1865
+ usedTokens += section.tokens;
1866
+ } else {
1867
+ const remaining = limit - usedTokens;
1868
+ if (remaining > 50 && section.tokens > 0) {
1869
+ const truncated = truncateSectionContent(section, remaining);
1870
+ if (truncated) {
1871
+ included.push(truncated);
1872
+ usedTokens += truncated.tokens;
1873
+ }
1874
+ }
1875
+ removed.push(section);
1876
+ }
1877
+ }
1878
+ const sectionOrder = sections.map((s) => s.id);
1879
+ included.sort((a, b) => sectionOrder.indexOf(a.id) - sectionOrder.indexOf(b.id));
1880
+ const output = included.map((s) => s.content).join("\n\n");
1881
+ return {
1882
+ text: output.trim(),
1883
+ truncated: true,
1884
+ tokenCount: countTokens(output),
1885
+ includedSections: included.map((s) => s.title),
1886
+ removedSections: removed.map((s) => s.title)
1887
+ };
1888
+ }
1889
+ function truncateSectionContent(section, maxTokens) {
1890
+ const lines = section.content.split("\n");
1891
+ const truncatedLines = [];
1892
+ let tokens = 0;
1893
+ for (const line of lines) {
1894
+ const lineTokens = countTokens(line);
1895
+ if (tokens + lineTokens <= maxTokens) {
1896
+ truncatedLines.push(line);
1897
+ tokens += lineTokens;
1898
+ } else {
1899
+ break;
1900
+ }
1901
+ }
1902
+ if (truncatedLines.length === 0) {
1903
+ return null;
1904
+ }
1905
+ truncatedLines.push("\n...(truncated)");
1906
+ return {
1907
+ ...section,
1908
+ content: truncatedLines.join("\n"),
1909
+ tokens: countTokens(truncatedLines.join("\n"))
1910
+ };
1911
+ }
1912
+
1913
+ // src/outputs/llms.ts
1914
+ var DEFAULT_LLMS_TOKEN_LIMIT = Infinity;
1915
+ function generateLlmsTxt(context, options = {}) {
1916
+ const {
1917
+ tokenLimit = DEFAULT_LLMS_TOKEN_LIMIT,
1918
+ includeInstall = true,
1919
+ includeQuickStart = true,
1920
+ maxFunctions = Infinity,
1921
+ maxClasses = Infinity
1922
+ } = options;
1923
+ const { package: pkg, api, readme } = context;
1924
+ const sections = [];
1925
+ sections.push(`# ${pkg.name}`);
1926
+ if (pkg.description) {
1927
+ sections.push(`
1928
+ > ${pkg.description}`);
1929
+ }
1930
+ sections.push("");
1931
+ if (includeInstall) {
1932
+ sections.push("## Install\n");
1933
+ sections.push("```bash");
1934
+ sections.push(`npm install ${pkg.name}`);
1935
+ sections.push("```\n");
1936
+ }
1937
+ if (includeQuickStart && readme?.quickStart) {
1938
+ sections.push("## Quick Start\n");
1939
+ sections.push(readme.quickStart);
1940
+ sections.push("");
1941
+ }
1942
+ sections.push("## API\n");
1943
+ const functions = api.filter((e) => e.kind === "function");
1944
+ const classes = api.filter((e) => e.kind === "class");
1945
+ const interfaces = api.filter((e) => e.kind === "interface");
1946
+ const types = api.filter((e) => e.kind === "type");
1947
+ const constants = api.filter((e) => e.kind === "constant");
1948
+ if (functions.length > 0) {
1949
+ sections.push("### Functions\n");
1950
+ const limit = Math.min(functions.length, maxFunctions);
1951
+ for (let i = 0; i < limit; i++) {
1952
+ sections.push(formatFunctionBrief(functions[i]));
1953
+ }
1954
+ if (functions.length > maxFunctions && maxFunctions < Infinity) {
1955
+ sections.push(`
1956
+ ...and ${functions.length - maxFunctions} more functions.`);
1957
+ }
1958
+ sections.push("");
1959
+ }
1960
+ if (classes.length > 0) {
1961
+ sections.push("### Classes\n");
1962
+ const limit = Math.min(classes.length, maxClasses);
1963
+ for (let i = 0; i < limit; i++) {
1964
+ sections.push(formatClassBrief(classes[i]));
1965
+ }
1966
+ if (classes.length > maxClasses && maxClasses < Infinity) {
1967
+ sections.push(`
1968
+ ...and ${classes.length - maxClasses} more classes.`);
1969
+ }
1970
+ sections.push("");
1971
+ }
1972
+ if (interfaces.length > 0 || types.length > 0) {
1973
+ sections.push("### Types\n");
1974
+ const allTypes = [...interfaces, ...types];
1975
+ for (const t of allTypes) {
1976
+ const desc = t.description ? ` - ${truncate(t.description, 80)}` : "";
1977
+ sections.push(`- \`${t.name}\`${desc}`);
1978
+ }
1979
+ sections.push("");
1980
+ }
1981
+ if (constants.length > 0) {
1982
+ sections.push("### Constants\n");
1983
+ for (const c of constants) {
1984
+ const desc = c.description ? ` - ${truncate(c.description, 80)}` : "";
1985
+ sections.push(`- \`${c.name}\`${desc}`);
1986
+ }
1987
+ sections.push("");
1988
+ }
1989
+ let output = sections.join("\n");
1990
+ const currentTokens = countTokens(output);
1991
+ if (currentTokens > tokenLimit) {
1992
+ const result = truncateToTokenLimit(output, tokenLimit, ["functions", "examples"]);
1993
+ output = result.text;
1994
+ context.truncated = result.truncated;
1995
+ }
1996
+ context.tokenCount = countTokens(output);
1997
+ return output;
1998
+ }
1999
+ function formatFunctionBrief(fn) {
2000
+ const params = fn.params?.map((p) => `${p.name}${p.optional ? "?" : ""}`).join(", ") || "";
2001
+ const returnType = fn.returns?.type ? `: ${simplifyType(fn.returns.type)}` : "";
2002
+ const desc = fn.description ? ` - ${truncate(fn.description, 60)}` : "";
2003
+ return `- \`${fn.name}(${params})${returnType}\`${desc}`;
2004
+ }
2005
+ function formatClassBrief(cls) {
2006
+ const lines = [];
2007
+ const desc = cls.description ? ` - ${truncate(cls.description, 60)}` : "";
2008
+ lines.push(`- \`${cls.name}\`${desc}`);
2009
+ if (cls.methods && cls.methods.length > 0) {
2010
+ const keyMethods = cls.methods.slice(0, 3);
2011
+ for (const method of keyMethods) {
2012
+ lines.push(` - \`${method.name}()\``);
2013
+ }
2014
+ if (cls.methods.length > 3) {
2015
+ lines.push(` - ...${cls.methods.length - 3} more methods`);
2016
+ }
2017
+ }
2018
+ return lines.join("\n");
2019
+ }
2020
+ function simplifyType(type) {
2021
+ if (type.length > 30) {
2022
+ const genericStart = type.indexOf("<");
2023
+ if (genericStart > 0) {
2024
+ return type.slice(0, genericStart) + "<...>";
2025
+ }
2026
+ }
2027
+ return type;
2028
+ }
2029
+ function truncate(text, maxLength) {
2030
+ if (text.length <= maxLength) return text;
2031
+ return text.slice(0, maxLength - 3) + "...";
2032
+ }
2033
+
2034
+ // src/plugins/core/llms-output.ts
2035
+ var llmsOutputPlugin = {
2036
+ name: "llms-output",
2037
+ version: "1.0.0",
2038
+ category: "output",
2039
+ install(kernel) {
2040
+ kernel.on("output:start", async (context) => {
2041
+ if (!context.options.formats?.includes("llms")) {
2042
+ return;
2043
+ }
2044
+ try {
2045
+ const tokenLimit = context.options.llmsTokenLimit ?? DEFAULT_LLMS_TOKEN_LIMIT;
2046
+ const output = generateLlmsTxt(context, {
2047
+ tokenLimit,
2048
+ includeInstall: true,
2049
+ includeQuickStart: true
2050
+ });
2051
+ context.outputs.set("llms", output);
2052
+ } catch (error) {
2053
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
2054
+ }
2055
+ });
2056
+ }
2057
+ };
2058
+
2059
+ // src/outputs/llms-full.ts
2060
+ function generateLlmsFullTxt(context, options = {}) {
2061
+ const {
2062
+ includeExamples = true,
2063
+ includeParamDescriptions = true,
2064
+ includeSourceLocations = false,
2065
+ includeDeprecations = true
2066
+ } = options;
2067
+ const { package: pkg, api, readme } = context;
2068
+ const sections = [];
2069
+ sections.push(`# ${pkg.name} v${pkg.version}`);
2070
+ if (pkg.description) {
2071
+ sections.push(`
2072
+ > ${pkg.description}`);
2073
+ }
2074
+ sections.push("");
2075
+ sections.push("## Package Info\n");
2076
+ sections.push(`- **Version:** ${pkg.version}`);
2077
+ if (pkg.license) {
2078
+ sections.push(`- **License:** ${pkg.license}`);
2079
+ }
2080
+ if (pkg.homepage) {
2081
+ sections.push(`- **Homepage:** ${pkg.homepage}`);
2082
+ }
2083
+ if (pkg.repository) {
2084
+ sections.push(`- **Repository:** ${pkg.repository.url}`);
2085
+ }
2086
+ sections.push("");
2087
+ sections.push("## Installation\n");
2088
+ sections.push("```bash");
2089
+ sections.push(`# npm`);
2090
+ sections.push(`npm install ${pkg.name}`);
2091
+ sections.push("");
2092
+ sections.push(`# yarn`);
2093
+ sections.push(`yarn add ${pkg.name}`);
2094
+ sections.push("");
2095
+ sections.push(`# pnpm`);
2096
+ sections.push(`pnpm add ${pkg.name}`);
2097
+ sections.push("```\n");
2098
+ if (readme?.quickStart) {
2099
+ sections.push("## Quick Start\n");
2100
+ sections.push(readme.quickStart);
2101
+ sections.push("");
2102
+ }
2103
+ sections.push("## API Reference\n");
2104
+ const functions = api.filter((e) => e.kind === "function");
2105
+ const classes = api.filter((e) => e.kind === "class");
2106
+ const interfaces = api.filter((e) => e.kind === "interface");
2107
+ const types = api.filter((e) => e.kind === "type");
2108
+ const constants = api.filter((e) => e.kind === "constant");
2109
+ const enums = api.filter((e) => e.kind === "enum");
2110
+ if (functions.length > 0) {
2111
+ sections.push("### Functions\n");
2112
+ for (const fn of functions) {
2113
+ sections.push(formatFunction(fn, { includeExamples, includeParamDescriptions, includeDeprecations, includeSourceLocations }));
2114
+ sections.push("");
2115
+ }
2116
+ }
2117
+ if (classes.length > 0) {
2118
+ sections.push("### Classes\n");
2119
+ for (const cls of classes) {
2120
+ sections.push(formatClass(cls, { includeExamples, includeDeprecations}));
2121
+ sections.push("");
2122
+ }
2123
+ }
2124
+ if (interfaces.length > 0) {
2125
+ sections.push("### Interfaces\n");
2126
+ for (const iface of interfaces) {
2127
+ sections.push(formatInterface(iface, { includeDeprecations}));
2128
+ sections.push("");
2129
+ }
2130
+ }
2131
+ if (types.length > 0) {
2132
+ sections.push("### Types\n");
2133
+ for (const type of types) {
2134
+ sections.push(formatType(type, { includeDeprecations }));
2135
+ sections.push("");
2136
+ }
2137
+ }
2138
+ if (enums.length > 0) {
2139
+ sections.push("### Enums\n");
2140
+ for (const enumEntry of enums) {
2141
+ sections.push(formatEnum(enumEntry));
2142
+ sections.push("");
2143
+ }
2144
+ }
2145
+ if (constants.length > 0) {
2146
+ sections.push("### Constants\n");
2147
+ for (const constant of constants) {
2148
+ sections.push(formatConstant(constant));
2149
+ sections.push("");
2150
+ }
2151
+ }
2152
+ const output = sections.join("\n");
2153
+ context.tokenCount = countTokens(output);
2154
+ return output;
2155
+ }
2156
+ function formatFunction(fn, options) {
2157
+ const lines = [];
2158
+ lines.push(`#### \`${fn.name}\``);
2159
+ if (options.includeDeprecations && fn.deprecated) {
2160
+ lines.push(`
2161
+ > \u26A0\uFE0F **Deprecated:** ${typeof fn.deprecated === "string" ? fn.deprecated : "This function is deprecated."}`);
2162
+ }
2163
+ if (fn.description) {
2164
+ lines.push(`
2165
+ ${fn.description}`);
2166
+ }
2167
+ lines.push("\n**Signature:**");
2168
+ lines.push("```typescript");
2169
+ lines.push(fn.signature);
2170
+ lines.push("```");
2171
+ if (fn.params && fn.params.length > 0 && options.includeParamDescriptions) {
2172
+ lines.push("\n**Parameters:**\n");
2173
+ for (const param of fn.params) {
2174
+ const optional = param.optional ? " (optional)" : "";
2175
+ const defaultVal = param.defaultValue ? ` = \`${param.defaultValue}\`` : "";
2176
+ lines.push(`- \`${param.name}: ${param.type || "unknown"}\`${optional}${defaultVal}`);
2177
+ if (param.description) {
2178
+ lines.push(` - ${param.description}`);
2179
+ }
2180
+ }
2181
+ }
2182
+ if (fn.returns) {
2183
+ lines.push("\n**Returns:**");
2184
+ lines.push(`- \`${fn.returns.type}\`${fn.returns.description ? ` - ${fn.returns.description}` : ""}`);
2185
+ }
2186
+ if (options.includeExamples && fn.examples && fn.examples.length > 0) {
2187
+ lines.push("\n**Examples:**");
2188
+ for (const example of fn.examples) {
2189
+ if (example.includes("```")) {
2190
+ lines.push(example);
2191
+ } else {
2192
+ lines.push("```typescript");
2193
+ lines.push(example);
2194
+ lines.push("```");
2195
+ }
2196
+ }
2197
+ }
2198
+ if (options.includeSourceLocations && fn.sourceFile) {
2199
+ lines.push(`
2200
+ *Source: ${fn.sourceFile}${fn.line ? `:${fn.line}` : ""}*`);
2201
+ }
2202
+ return lines.join("\n");
2203
+ }
2204
+ function formatClass(cls, options) {
2205
+ const lines = [];
2206
+ lines.push(`#### \`${cls.name}\``);
2207
+ if (options.includeDeprecations && cls.deprecated) {
2208
+ lines.push(`
2209
+ > \u26A0\uFE0F **Deprecated:** ${typeof cls.deprecated === "string" ? cls.deprecated : "This class is deprecated."}`);
2210
+ }
2211
+ if (cls.description) {
2212
+ lines.push(`
2213
+ ${cls.description}`);
2214
+ }
2215
+ lines.push("\n**Signature:**");
2216
+ lines.push("```typescript");
2217
+ let sig = cls.signature;
2218
+ if (cls.extends && cls.extends.length > 0) {
2219
+ sig += ` extends ${cls.extends.join(", ")}`;
2220
+ }
2221
+ if (cls.implements && cls.implements.length > 0) {
2222
+ sig += ` implements ${cls.implements.join(", ")}`;
2223
+ }
2224
+ lines.push(sig);
2225
+ lines.push("```");
2226
+ if (cls.properties && cls.properties.length > 0) {
2227
+ lines.push("\n**Properties:**\n");
2228
+ for (const prop of cls.properties) {
2229
+ lines.push(`- \`${prop.name}\`: \`${prop.signature.split(":").slice(1).join(":").trim() || "unknown"}\``);
2230
+ if (prop.description) {
2231
+ lines.push(` - ${prop.description}`);
2232
+ }
2233
+ }
2234
+ }
2235
+ if (cls.methods && cls.methods.length > 0) {
2236
+ lines.push("\n**Methods:**\n");
2237
+ for (const method of cls.methods) {
2238
+ const params = method.params?.map((p) => `${p.name}: ${p.type || "unknown"}`).join(", ") || "";
2239
+ const returnType = method.returns?.type || "void";
2240
+ lines.push(`- \`${method.name}(${params}): ${returnType}\``);
2241
+ if (method.description) {
2242
+ lines.push(` - ${method.description}`);
2243
+ }
2244
+ }
2245
+ }
2246
+ if (options.includeExamples && cls.examples && cls.examples.length > 0) {
2247
+ lines.push("\n**Examples:**");
2248
+ for (const example of cls.examples) {
2249
+ if (example.includes("```")) {
2250
+ lines.push(example);
2251
+ } else {
2252
+ lines.push("```typescript");
2253
+ lines.push(example);
2254
+ lines.push("```");
2255
+ }
2256
+ }
2257
+ }
2258
+ return lines.join("\n");
2259
+ }
2260
+ function formatInterface(iface, options) {
2261
+ const lines = [];
2262
+ lines.push(`#### \`${iface.name}\``);
2263
+ if (options.includeDeprecations && iface.deprecated) {
2264
+ lines.push(`
2265
+ > \u26A0\uFE0F **Deprecated**`);
2266
+ }
2267
+ if (iface.description) {
2268
+ lines.push(`
2269
+ ${iface.description}`);
2270
+ }
2271
+ lines.push("\n```typescript");
2272
+ let sig = iface.signature;
2273
+ if (iface.extends && iface.extends.length > 0) {
2274
+ sig += ` extends ${iface.extends.join(", ")}`;
2275
+ }
2276
+ lines.push(sig + " {");
2277
+ if (iface.properties && iface.properties.length > 0) {
2278
+ for (const prop of iface.properties) {
2279
+ lines.push(` ${prop.signature};`);
2280
+ }
2281
+ }
2282
+ if (iface.methods && iface.methods.length > 0) {
2283
+ for (const method of iface.methods) {
2284
+ lines.push(` ${method.signature};`);
2285
+ }
2286
+ }
2287
+ lines.push("}");
2288
+ lines.push("```");
2289
+ return lines.join("\n");
2290
+ }
2291
+ function formatType(type, options) {
2292
+ const lines = [];
2293
+ lines.push(`#### \`${type.name}\``);
2294
+ if (options.includeDeprecations && type.deprecated) {
2295
+ lines.push(`
2296
+ > \u26A0\uFE0F **Deprecated**`);
2297
+ }
2298
+ if (type.description) {
2299
+ lines.push(`
2300
+ ${type.description}`);
2301
+ }
2302
+ lines.push("\n```typescript");
2303
+ lines.push(type.signature);
2304
+ lines.push("```");
2305
+ return lines.join("\n");
2306
+ }
2307
+ function formatEnum(enumEntry) {
2308
+ const lines = [];
2309
+ lines.push(`#### \`${enumEntry.name}\``);
2310
+ if (enumEntry.description) {
2311
+ lines.push(`
2312
+ ${enumEntry.description}`);
2313
+ }
2314
+ lines.push("\n```typescript");
2315
+ lines.push(`enum ${enumEntry.name} {`);
2316
+ if (enumEntry.members) {
2317
+ for (const member of enumEntry.members) {
2318
+ if (member.value !== void 0) {
2319
+ lines.push(` ${member.name} = ${JSON.stringify(member.value)},`);
2320
+ } else {
2321
+ lines.push(` ${member.name},`);
2322
+ }
2323
+ }
2324
+ }
2325
+ lines.push("}");
2326
+ lines.push("```");
2327
+ return lines.join("\n");
2328
+ }
2329
+ function formatConstant(constant) {
2330
+ const lines = [];
2331
+ lines.push(`#### \`${constant.name}\``);
2332
+ if (constant.description) {
2333
+ lines.push(`
2334
+ ${constant.description}`);
2335
+ }
2336
+ lines.push("\n```typescript");
2337
+ lines.push(constant.signature);
2338
+ lines.push("```");
2339
+ return lines.join("\n");
2340
+ }
2341
+
2342
+ // src/plugins/core/llms-full-output.ts
2343
+ var llmsFullOutputPlugin = {
2344
+ name: "llms-full-output",
2345
+ version: "1.0.0",
2346
+ category: "output",
2347
+ install(kernel) {
2348
+ kernel.on("output:start", async (context) => {
2349
+ if (!context.options.formats?.includes("llms-full")) {
2350
+ return;
2351
+ }
2352
+ try {
2353
+ const output = generateLlmsFullTxt(context, {
2354
+ includeExamples: true,
2355
+ includeParamDescriptions: true,
2356
+ includeDeprecations: true
2357
+ });
2358
+ context.outputs.set("llms-full", output);
2359
+ } catch (error) {
2360
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
2361
+ }
2362
+ });
2363
+ }
2364
+ };
2365
+
2366
+ // src/outputs/markdown.ts
2367
+ function generateMarkdown(context, options = {}) {
2368
+ const {
2369
+ includeToc = true,
2370
+ includeParamTables = true,
2371
+ includeBadges = true,
2372
+ repositoryUrl
2373
+ } = options;
2374
+ const { package: pkg, api, readme } = context;
2375
+ const sections = [];
2376
+ sections.push(`# ${pkg.name}`);
2377
+ sections.push("");
2378
+ if (includeBadges) {
2379
+ const badges = [];
2380
+ badges.push(`![npm version](https://img.shields.io/npm/v/${encodeURIComponent(pkg.name)})`);
2381
+ if (pkg.license) {
2382
+ badges.push(`![license](https://img.shields.io/npm/l/${encodeURIComponent(pkg.name)})`);
2383
+ }
2384
+ if (badges.length > 0) {
2385
+ sections.push(badges.join(" "));
2386
+ sections.push("");
2387
+ }
2388
+ }
2389
+ if (pkg.description) {
2390
+ sections.push(`> ${pkg.description}`);
2391
+ sections.push("");
2392
+ }
2393
+ if (includeToc) {
2394
+ sections.push("## Table of Contents\n");
2395
+ sections.push("- [Installation](#installation)");
2396
+ if (readme?.quickStart) {
2397
+ sections.push("- [Quick Start](#quick-start)");
2398
+ }
2399
+ sections.push("- [API Reference](#api-reference)");
2400
+ const functions2 = api.filter((e) => e.kind === "function");
2401
+ const classes2 = api.filter((e) => e.kind === "class");
2402
+ const interfaces2 = api.filter((e) => e.kind === "interface");
2403
+ const types2 = api.filter((e) => e.kind === "type");
2404
+ if (functions2.length > 0) {
2405
+ sections.push(" - [Functions](#functions)");
2406
+ }
2407
+ if (classes2.length > 0) {
2408
+ sections.push(" - [Classes](#classes)");
2409
+ }
2410
+ if (interfaces2.length > 0) {
2411
+ sections.push(" - [Interfaces](#interfaces)");
2412
+ }
2413
+ if (types2.length > 0) {
2414
+ sections.push(" - [Types](#types)");
2415
+ }
2416
+ sections.push("");
2417
+ }
2418
+ sections.push("## Installation\n");
2419
+ sections.push("```bash");
2420
+ sections.push(`npm install ${pkg.name}`);
2421
+ sections.push("```\n");
2422
+ sections.push("Or with yarn:\n");
2423
+ sections.push("```bash");
2424
+ sections.push(`yarn add ${pkg.name}`);
2425
+ sections.push("```\n");
2426
+ if (readme?.quickStart) {
2427
+ sections.push("## Quick Start\n");
2428
+ sections.push(readme.quickStart);
2429
+ sections.push("");
2430
+ }
2431
+ sections.push("## API Reference\n");
2432
+ const functions = api.filter((e) => e.kind === "function");
2433
+ const classes = api.filter((e) => e.kind === "class");
2434
+ const interfaces = api.filter((e) => e.kind === "interface");
2435
+ const types = api.filter((e) => e.kind === "type");
2436
+ const enums = api.filter((e) => e.kind === "enum");
2437
+ const constants = api.filter((e) => e.kind === "constant");
2438
+ if (functions.length > 0) {
2439
+ sections.push("### Functions\n");
2440
+ for (const fn of functions) {
2441
+ sections.push(formatFunctionMd(fn, { includeParamTables, repositoryUrl }));
2442
+ sections.push("");
2443
+ sections.push("---\n");
2444
+ }
2445
+ }
2446
+ if (classes.length > 0) {
2447
+ sections.push("### Classes\n");
2448
+ for (const cls of classes) {
2449
+ sections.push(formatClassMd(cls));
2450
+ sections.push("");
2451
+ sections.push("---\n");
2452
+ }
2453
+ }
2454
+ if (interfaces.length > 0) {
2455
+ sections.push("### Interfaces\n");
2456
+ for (const iface of interfaces) {
2457
+ sections.push(formatInterfaceMd(iface));
2458
+ sections.push("");
2459
+ sections.push("---\n");
2460
+ }
2461
+ }
2462
+ if (types.length > 0) {
2463
+ sections.push("### Types\n");
2464
+ for (const type of types) {
2465
+ sections.push(formatTypeMd(type));
2466
+ sections.push("");
2467
+ }
2468
+ }
2469
+ if (enums.length > 0) {
2470
+ sections.push("### Enums\n");
2471
+ for (const enumEntry of enums) {
2472
+ sections.push(formatEnumMd(enumEntry));
2473
+ sections.push("");
2474
+ }
2475
+ }
2476
+ if (constants.length > 0) {
2477
+ sections.push("### Constants\n");
2478
+ for (const constant of constants) {
2479
+ sections.push(formatConstantMd(constant));
2480
+ }
2481
+ sections.push("");
2482
+ }
2483
+ const output = sections.join("\n");
2484
+ context.tokenCount = countTokens(output);
2485
+ return output;
2486
+ }
2487
+ function formatFunctionMd(fn, options) {
2488
+ const lines = [];
2489
+ const anchor = fn.name.toLowerCase();
2490
+ lines.push(`<a name="${anchor}"></a>`);
2491
+ lines.push(`#### \`${fn.name}()\``);
2492
+ if (fn.deprecated) {
2493
+ lines.push(`
2494
+ > \u26A0\uFE0F **Deprecated:** ${typeof fn.deprecated === "string" ? fn.deprecated : "This function is deprecated."}
2495
+ `);
2496
+ }
2497
+ if (fn.description) {
2498
+ lines.push(`
2499
+ ${fn.description}
2500
+ `);
2501
+ }
2502
+ lines.push("**Signature:**\n");
2503
+ lines.push("```typescript");
2504
+ lines.push(fn.signature);
2505
+ lines.push("```\n");
2506
+ if (fn.params && fn.params.length > 0 && options.includeParamTables) {
2507
+ lines.push("**Parameters:**\n");
2508
+ lines.push("| Name | Type | Required | Description |");
2509
+ lines.push("|------|------|----------|-------------|");
2510
+ for (const param of fn.params) {
2511
+ const required = param.optional ? "No" : "Yes";
2512
+ const desc = param.description || "-";
2513
+ const defaultVal = param.defaultValue ? ` (default: \`${param.defaultValue}\`)` : "";
2514
+ lines.push(`| \`${param.name}\` | \`${param.type || "unknown"}\` | ${required} | ${desc}${defaultVal} |`);
2515
+ }
2516
+ lines.push("");
2517
+ }
2518
+ if (fn.returns) {
2519
+ lines.push("**Returns:**\n");
2520
+ lines.push(`\`${fn.returns.type}\`${fn.returns.description ? ` - ${fn.returns.description}` : ""}
2521
+ `);
2522
+ }
2523
+ if (fn.examples && fn.examples.length > 0) {
2524
+ lines.push("**Example:**\n");
2525
+ for (const example of fn.examples) {
2526
+ if (example.includes("```")) {
2527
+ lines.push(example);
2528
+ } else {
2529
+ lines.push("```typescript");
2530
+ lines.push(example);
2531
+ lines.push("```");
2532
+ }
2533
+ }
2534
+ lines.push("");
2535
+ }
2536
+ if (options.repositoryUrl && fn.sourceFile) {
2537
+ const sourceUrl = `${options.repositoryUrl}/blob/main/${fn.sourceFile}${fn.line ? `#L${fn.line}` : ""}`;
2538
+ lines.push(`[View source](${sourceUrl})
2539
+ `);
2540
+ }
2541
+ return lines.join("\n");
2542
+ }
2543
+ function formatClassMd(cls, options) {
2544
+ const lines = [];
2545
+ const anchor = cls.name.toLowerCase();
2546
+ lines.push(`<a name="${anchor}"></a>`);
2547
+ lines.push(`#### \`${cls.name}\``);
2548
+ if (cls.deprecated) {
2549
+ lines.push(`
2550
+ > \u26A0\uFE0F **Deprecated**
2551
+ `);
2552
+ }
2553
+ if (cls.description) {
2554
+ lines.push(`
2555
+ ${cls.description}
2556
+ `);
2557
+ }
2558
+ if (cls.extends && cls.extends.length > 0) {
2559
+ lines.push(`**Extends:** ${cls.extends.map((e) => `\`${e}\``).join(", ")}
2560
+ `);
2561
+ }
2562
+ if (cls.implements && cls.implements.length > 0) {
2563
+ lines.push(`**Implements:** ${cls.implements.map((e) => `\`${e}\``).join(", ")}
2564
+ `);
2565
+ }
2566
+ const constructor = cls.methods?.find((m) => m.name === "constructor");
2567
+ if (constructor) {
2568
+ lines.push("**Constructor:**\n");
2569
+ lines.push("```typescript");
2570
+ lines.push(`new ${cls.name}(${constructor.params?.map((p) => `${p.name}: ${p.type}`).join(", ") || ""})`);
2571
+ lines.push("```\n");
2572
+ }
2573
+ if (cls.properties && cls.properties.length > 0) {
2574
+ lines.push("**Properties:**\n");
2575
+ lines.push("| Name | Type | Description |");
2576
+ lines.push("|------|------|-------------|");
2577
+ for (const prop of cls.properties) {
2578
+ const type = prop.signature.split(":").slice(1).join(":").trim() || "unknown";
2579
+ lines.push(`| \`${prop.name}\` | \`${type}\` | ${prop.description || "-"} |`);
2580
+ }
2581
+ lines.push("");
2582
+ }
2583
+ const methods = cls.methods?.filter((m) => m.name !== "constructor") || [];
2584
+ if (methods.length > 0) {
2585
+ lines.push("**Methods:**\n");
2586
+ lines.push("| Method | Returns | Description |");
2587
+ lines.push("|--------|---------|-------------|");
2588
+ for (const method of methods) {
2589
+ const params = method.params?.map((p) => `${p.name}`).join(", ") || "";
2590
+ const returnType = method.returns?.type || "void";
2591
+ lines.push(`| \`${method.name}(${params})\` | \`${returnType}\` | ${method.description || "-"} |`);
2592
+ }
2593
+ lines.push("");
2594
+ }
2595
+ return lines.join("\n");
2596
+ }
2597
+ function formatInterfaceMd(iface) {
2598
+ const lines = [];
2599
+ lines.push(`#### \`${iface.name}\``);
2600
+ if (iface.description) {
2601
+ lines.push(`
2602
+ ${iface.description}
2603
+ `);
2604
+ }
2605
+ if (iface.extends && iface.extends.length > 0) {
2606
+ lines.push(`**Extends:** ${iface.extends.map((e) => `\`${e}\``).join(", ")}
2607
+ `);
2608
+ }
2609
+ if (iface.properties && iface.properties.length > 0) {
2610
+ lines.push("| Property | Type | Description |");
2611
+ lines.push("|----------|------|-------------|");
2612
+ for (const prop of iface.properties) {
2613
+ const type = prop.signature.split(":").slice(1).join(":").trim() || "unknown";
2614
+ lines.push(`| \`${prop.name}\` | \`${type}\` | ${prop.description || "-"} |`);
2615
+ }
2616
+ lines.push("");
2617
+ }
2618
+ lines.push("<details>");
2619
+ lines.push("<summary>Full Definition</summary>\n");
2620
+ lines.push("```typescript");
2621
+ lines.push(`interface ${iface.name} {`);
2622
+ if (iface.properties) {
2623
+ for (const prop of iface.properties) {
2624
+ lines.push(` ${prop.signature};`);
2625
+ }
2626
+ }
2627
+ if (iface.methods) {
2628
+ for (const method of iface.methods) {
2629
+ lines.push(` ${method.signature};`);
2630
+ }
2631
+ }
2632
+ lines.push("}");
2633
+ lines.push("```");
2634
+ lines.push("</details>");
2635
+ return lines.join("\n");
2636
+ }
2637
+ function formatTypeMd(type) {
2638
+ const lines = [];
2639
+ lines.push(`#### \`${type.name}\``);
2640
+ if (type.description) {
2641
+ lines.push(`
2642
+ ${type.description}
2643
+ `);
2644
+ }
2645
+ lines.push("```typescript");
2646
+ lines.push(type.signature);
2647
+ lines.push("```");
2648
+ return lines.join("\n");
2649
+ }
2650
+ function formatEnumMd(enumEntry) {
2651
+ const lines = [];
2652
+ lines.push(`#### \`${enumEntry.name}\``);
2653
+ if (enumEntry.description) {
2654
+ lines.push(`
2655
+ ${enumEntry.description}
2656
+ `);
2657
+ }
2658
+ if (enumEntry.members && enumEntry.members.length > 0) {
2659
+ lines.push("| Member | Value |");
2660
+ lines.push("|--------|-------|");
2661
+ for (const member of enumEntry.members) {
2662
+ const value = member.value !== void 0 ? `\`${JSON.stringify(member.value)}\`` : "-";
2663
+ lines.push(`| \`${member.name}\` | ${value} |`);
2664
+ }
2665
+ lines.push("");
2666
+ }
2667
+ return lines.join("\n");
2668
+ }
2669
+ function formatConstantMd(constant) {
2670
+ const lines = [];
2671
+ lines.push(`- **\`${constant.name}\`**: \`${constant.signature.split(":").slice(1).join(":").trim() || "unknown"}\``);
2672
+ if (constant.description) {
2673
+ lines.push(` - ${constant.description}`);
2674
+ }
2675
+ return lines.join("\n");
2676
+ }
2677
+
2678
+ // src/plugins/core/markdown-output.ts
2679
+ var markdownOutputPlugin = {
2680
+ name: "markdown-output",
2681
+ version: "1.0.0",
2682
+ category: "output",
2683
+ install(kernel) {
2684
+ kernel.on("output:start", async (context) => {
2685
+ if (!context.options.formats?.includes("markdown")) {
2686
+ return;
2687
+ }
2688
+ try {
2689
+ const repositoryUrl = context.package.repository?.url?.replace(/^git\+/, "").replace(/\.git$/, "");
2690
+ const output = generateMarkdown(context, {
2691
+ includeToc: true,
2692
+ includeParamTables: true,
2693
+ includeBadges: true,
2694
+ repositoryUrl
2695
+ });
2696
+ context.outputs.set("markdown", output);
2697
+ } catch (error) {
2698
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
2699
+ }
2700
+ });
2701
+ }
2702
+ };
2703
+
2704
+ // src/outputs/json.ts
2705
+ function generateJson(context, options = {}) {
2706
+ const { pretty = true, includeEmpty = false, includeSourceLocations = true } = options;
2707
+ const output = generateJsonObject(context, { includeEmpty, includeSourceLocations });
2708
+ return pretty ? JSON.stringify(output, null, 2) : JSON.stringify(output);
2709
+ }
2710
+ function generateJsonObject(context, options = {}) {
2711
+ const { includeEmpty = false, includeSourceLocations = true } = options;
2712
+ const { package: pkg, api } = context;
2713
+ const functions = api.filter((e) => e.kind === "function");
2714
+ const classes = api.filter((e) => e.kind === "class");
2715
+ const interfaces = api.filter((e) => e.kind === "interface");
2716
+ const types = api.filter((e) => e.kind === "type");
2717
+ const enums = api.filter((e) => e.kind === "enum");
2718
+ const constants = api.filter((e) => e.kind === "constant");
2719
+ const documented = api.filter((e) => e.description).length;
2720
+ const withExamples = api.filter((e) => e.examples && e.examples.length > 0).length;
2721
+ const output = {
2722
+ $schema: "https://npm-llms.oxog.dev/schema/v1.json",
2723
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
2724
+ package: {
2725
+ name: pkg.name,
2726
+ version: pkg.version,
2727
+ description: pkg.description,
2728
+ license: pkg.license,
2729
+ homepage: pkg.homepage,
2730
+ repository: pkg.repository?.url,
2731
+ keywords: pkg.keywords
2732
+ },
2733
+ api: {
2734
+ functions: functions.map((fn) => transformFunction(fn, includeSourceLocations)),
2735
+ classes: classes.map((cls) => transformClass(cls, includeSourceLocations)),
2736
+ interfaces: interfaces.map(transformInterface),
2737
+ types: types.map(transformType),
2738
+ enums: enums.map(transformEnum),
2739
+ constants: constants.map(transformConstant)
2740
+ },
2741
+ stats: {
2742
+ totalExports: api.length,
2743
+ functions: functions.length,
2744
+ classes: classes.length,
2745
+ interfaces: interfaces.length,
2746
+ types: types.length,
2747
+ enums: enums.length,
2748
+ constants: constants.length,
2749
+ documented,
2750
+ withExamples
2751
+ }
2752
+ };
2753
+ if (!includeEmpty) {
2754
+ const apiObj = output.api;
2755
+ for (const [key, value] of Object.entries(apiObj)) {
2756
+ if (Array.isArray(value) && value.length === 0) {
2757
+ delete apiObj[key];
2758
+ }
2759
+ }
2760
+ }
2761
+ return output;
2762
+ }
2763
+ function transformFunction(entry, includeSource) {
2764
+ const result = {
2765
+ name: entry.name,
2766
+ signature: entry.signature,
2767
+ description: entry.description,
2768
+ params: (entry.params || []).map((p) => ({
2769
+ name: p.name,
2770
+ type: p.type || "unknown",
2771
+ optional: p.optional ?? false,
2772
+ defaultValue: p.defaultValue,
2773
+ description: p.description
2774
+ })),
2775
+ returns: entry.returns ? {
2776
+ type: entry.returns.type,
2777
+ description: entry.returns.description
2778
+ } : void 0,
2779
+ examples: entry.examples || [],
2780
+ deprecated: entry.deprecated,
2781
+ since: entry.since,
2782
+ see: entry.see
2783
+ };
2784
+ if (includeSource) {
2785
+ result.sourceFile = entry.sourceFile;
2786
+ result.line = entry.line;
2787
+ }
2788
+ return result;
2789
+ }
2790
+ function transformClass(entry, includeSource) {
2791
+ const result = {
2792
+ name: entry.name,
2793
+ signature: entry.signature,
2794
+ description: entry.description,
2795
+ extends: entry.extends,
2796
+ implements: entry.implements,
2797
+ typeParams: entry.typeParams,
2798
+ properties: (entry.properties || []).map((p) => ({
2799
+ name: p.name,
2800
+ type: p.signature.split(":").slice(1).join(":").trim() || "unknown",
2801
+ description: p.description
2802
+ })),
2803
+ methods: (entry.methods || []).map((m) => transformFunction(m, includeSource)),
2804
+ deprecated: entry.deprecated
2805
+ };
2806
+ if (includeSource) {
2807
+ result.sourceFile = entry.sourceFile;
2808
+ }
2809
+ return result;
2810
+ }
2811
+ function transformInterface(entry) {
2812
+ return {
2813
+ name: entry.name,
2814
+ signature: entry.signature,
2815
+ description: entry.description,
2816
+ extends: entry.extends,
2817
+ typeParams: entry.typeParams,
2818
+ properties: (entry.properties || []).map((p) => ({
2819
+ name: p.name,
2820
+ type: p.signature.split(":").slice(1).join(":").trim() || "unknown",
2821
+ optional: p.signature.includes("?:"),
2822
+ description: p.description
2823
+ })),
2824
+ methods: (entry.methods || []).map((m) => ({
2825
+ name: m.name,
2826
+ signature: m.signature,
2827
+ description: m.description
2828
+ })),
2829
+ deprecated: entry.deprecated
2830
+ };
2831
+ }
2832
+ function transformType(entry) {
2833
+ return {
2834
+ name: entry.name,
2835
+ signature: entry.signature,
2836
+ description: entry.description,
2837
+ typeParams: entry.typeParams,
2838
+ deprecated: entry.deprecated
2839
+ };
2840
+ }
2841
+ function transformEnum(entry) {
2842
+ return {
2843
+ name: entry.name,
2844
+ description: entry.description,
2845
+ members: entry.members || []
2846
+ };
2847
+ }
2848
+ function transformConstant(entry) {
2849
+ return {
2850
+ name: entry.name,
2851
+ type: entry.signature.split(":").slice(1).join(":").trim() || "unknown",
2852
+ description: entry.description
2853
+ };
2854
+ }
2855
+
2856
+ // src/plugins/core/json-output.ts
2857
+ var jsonOutputPlugin = {
2858
+ name: "json-output",
2859
+ version: "1.0.0",
2860
+ category: "output",
2861
+ install(kernel) {
2862
+ kernel.on("output:start", async (context) => {
2863
+ if (!context.options.formats?.includes("json")) {
2864
+ return;
2865
+ }
2866
+ try {
2867
+ const output = generateJson(context, {
2868
+ pretty: true,
2869
+ includeEmpty: false,
2870
+ includeSourceLocations: true
2871
+ });
2872
+ context.outputs.set("json", output);
2873
+ } catch (error) {
2874
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
2875
+ }
2876
+ });
2877
+ }
2878
+ };
2879
+
2880
+ // src/plugins/core/index.ts
2881
+ var coreParserPlugins = [
2882
+ typesResolverPlugin,
2883
+ dtsParserPlugin,
2884
+ tsSourceParserPlugin,
2885
+ readmeParserPlugin
2886
+ ];
2887
+ var coreOutputPlugins = [
2888
+ llmsOutputPlugin,
2889
+ llmsFullOutputPlugin,
2890
+ markdownOutputPlugin,
2891
+ jsonOutputPlugin
2892
+ ];
2893
+ var corePlugins = [
2894
+ ...coreParserPlugins,
2895
+ ...coreOutputPlugins
2896
+ ];
2897
+
2898
+ // src/plugins/optional/ai-base.ts
2899
+ var DEFAULT_OPTIONS = {
2900
+ tasks: ["descriptions", "examples"],
2901
+ maxTokensPerRequest: 1e3,
2902
+ temperature: 0.3,
2903
+ batchSize: 5,
2904
+ skipExisting: true
2905
+ };
2906
+ var SYSTEM_PROMPTS = {
2907
+ descriptions: `You are a technical documentation expert. Generate concise, clear descriptions for API entries.
2908
+ Rules:
2909
+ - Be specific about what the function/class does
2910
+ - Mention important parameters and return values
2911
+ - Keep descriptions under 100 words
2912
+ - Use present tense ("Returns..." not "Will return...")
2913
+ - Don't include example code in descriptions`,
2914
+ examples: `You are a technical documentation expert. Generate practical usage examples for API entries.
2915
+ Rules:
2916
+ - Create 1-2 realistic examples
2917
+ - Show common use cases
2918
+ - Include proper TypeScript/JavaScript syntax
2919
+ - Keep examples concise but complete
2920
+ - Use meaningful variable names`,
2921
+ summary: `You are a technical documentation expert. Generate a summary of an npm package.
2922
+ Rules:
2923
+ - Describe the main purpose and use cases
2924
+ - Mention key features
2925
+ - Keep it under 150 words
2926
+ - Be objective and informative`,
2927
+ params: `You are a technical documentation expert. Generate parameter descriptions.
2928
+ Rules:
2929
+ - Be specific about expected values
2930
+ - Mention valid ranges or formats
2931
+ - Note if parameter is optional
2932
+ - Keep each description under 20 words`,
2933
+ returns: `You are a technical documentation expert. Generate return value descriptions.
2934
+ Rules:
2935
+ - Describe what is returned
2936
+ - Mention possible values or states
2937
+ - Keep descriptions under 30 words`
2938
+ };
2939
+ function generateEntryPrompt(entry, task) {
2940
+ const parts = [`${entry.kind}: ${entry.name}`, `Signature: ${entry.signature}`];
2941
+ if (entry.description) {
2942
+ parts.push(`Current description: ${entry.description}`);
2943
+ }
2944
+ if (entry.params && entry.params.length > 0) {
2945
+ const paramList = entry.params.map((p) => `- ${p.name}: ${p.type || "unknown"}`).join("\n");
2946
+ parts.push(`Parameters:
2947
+ ${paramList}`);
2948
+ }
2949
+ if (entry.returns) {
2950
+ parts.push(`Returns: ${entry.returns.type}`);
2951
+ }
2952
+ switch (task) {
2953
+ case "descriptions":
2954
+ parts.push("\nGenerate a clear description for this API entry:");
2955
+ break;
2956
+ case "examples":
2957
+ parts.push("\nGenerate a practical usage example:");
2958
+ break;
2959
+ }
2960
+ return parts.join("\n");
2961
+ }
2962
+ function generateSummaryPrompt(context) {
2963
+ const { package: pkg, api } = context;
2964
+ const functionCount = api.filter((e) => e.kind === "function").length;
2965
+ const classCount = api.filter((e) => e.kind === "class").length;
2966
+ const typeCount = api.filter((e) => e.kind === "type" || e.kind === "interface").length;
2967
+ return `
2968
+ Package: ${pkg.name}@${pkg.version}
2969
+ Description: ${pkg.description || "No description available"}
2970
+ Functions: ${functionCount}
2971
+ Classes: ${classCount}
2972
+ Types: ${typeCount}
2973
+
2974
+ Top exports:
2975
+ ${api.slice(0, 10).map((e) => `- ${e.kind} ${e.name}`).join("\n")}
2976
+
2977
+ Generate a summary of this package that explains its purpose and main features:
2978
+ `.trim();
2979
+ }
2980
+ function parseDescriptionResponse(response) {
2981
+ return response.trim().replace(/^Description:\s*/i, "").replace(/^["']|["']$/g, "");
2982
+ }
2983
+ function parseExampleResponse(response) {
2984
+ const examples = [];
2985
+ const codeBlockRegex = /```(?:\w+)?\n?([\s\S]*?)```/g;
2986
+ let match;
2987
+ while ((match = codeBlockRegex.exec(response)) !== null) {
2988
+ if (match[1]?.trim()) {
2989
+ examples.push(match[1].trim());
2990
+ }
2991
+ }
2992
+ if (examples.length === 0 && response.trim()) {
2993
+ examples.push(response.trim());
2994
+ }
2995
+ return examples;
2996
+ }
2997
+ function createAIEnrichmentPlugin(provider, options = {}) {
2998
+ const opts = { ...DEFAULT_OPTIONS, ...options };
2999
+ return {
3000
+ name: `ai-enrichment-${provider.name}`,
3001
+ version: "1.0.0",
3002
+ category: "ai",
3003
+ install(kernel) {
3004
+ kernel.on("ai:enrich", async (context) => {
3005
+ if (!provider.isAvailable()) {
3006
+ throw new AIError(`AI provider ${provider.name} is not available`, provider.name);
3007
+ }
3008
+ if (opts.tasks.includes("descriptions") || opts.tasks.includes("examples")) {
3009
+ await enrichEntries(context, provider, opts);
3010
+ }
3011
+ if (opts.tasks.includes("summary")) {
3012
+ await enrichSummary(context, provider, opts);
3013
+ }
3014
+ });
3015
+ }
3016
+ };
3017
+ }
3018
+ async function enrichEntries(context, provider, options) {
3019
+ const { api } = context;
3020
+ const { tasks, batchSize, skipExisting, maxTokensPerRequest, temperature } = options;
3021
+ const entriesToEnrich = api.filter((entry) => {
3022
+ if (skipExisting) {
3023
+ if (tasks.includes("descriptions") && entry.description) return false;
3024
+ if (tasks.includes("examples") && entry.examples && entry.examples.length > 0) return false;
3025
+ }
3026
+ return entry.kind === "function" || entry.kind === "class";
3027
+ });
3028
+ for (let i = 0; i < entriesToEnrich.length; i += batchSize) {
3029
+ const batch = entriesToEnrich.slice(i, i + batchSize);
3030
+ await Promise.all(
3031
+ batch.map(async (entry) => {
3032
+ try {
3033
+ if (tasks.includes("descriptions") && (!skipExisting || !entry.description)) {
3034
+ const prompt = generateEntryPrompt(entry, "descriptions");
3035
+ const response = await provider.complete(prompt, {
3036
+ maxTokens: maxTokensPerRequest,
3037
+ temperature,
3038
+ systemPrompt: SYSTEM_PROMPTS.descriptions
3039
+ });
3040
+ entry.description = parseDescriptionResponse(response);
3041
+ }
3042
+ if (tasks.includes("examples") && (!skipExisting || !entry.examples?.length)) {
3043
+ const prompt = generateEntryPrompt(entry, "examples");
3044
+ const response = await provider.complete(prompt, {
3045
+ maxTokens: maxTokensPerRequest,
3046
+ temperature,
3047
+ systemPrompt: SYSTEM_PROMPTS.examples
3048
+ });
3049
+ entry.examples = parseExampleResponse(response);
3050
+ }
3051
+ } catch (error) {
3052
+ context.errors.push(
3053
+ error instanceof Error ? error : new Error(`AI enrichment failed for ${entry.name}`)
3054
+ );
3055
+ }
3056
+ })
3057
+ );
3058
+ }
3059
+ }
3060
+ async function enrichSummary(context, provider, options) {
3061
+ try {
3062
+ const prompt = generateSummaryPrompt(context);
3063
+ const response = await provider.complete(prompt, {
3064
+ maxTokens: options.maxTokensPerRequest,
3065
+ temperature: options.temperature,
3066
+ systemPrompt: SYSTEM_PROMPTS.summary
3067
+ });
3068
+ if (context.readme) {
3069
+ if (!context.readme.description) {
3070
+ context.readme.description = response.trim();
3071
+ }
3072
+ }
3073
+ } catch (error) {
3074
+ context.errors.push(
3075
+ error instanceof Error ? error : new Error("AI summary generation failed")
3076
+ );
3077
+ }
3078
+ }
3079
+ function createSimpleProvider(name, completeFn, isAvailableFn = () => true) {
3080
+ return {
3081
+ name,
3082
+ isAvailable: isAvailableFn,
3083
+ complete: completeFn
3084
+ };
3085
+ }
3086
+
3087
+ // src/plugins/optional/claude-ai.ts
3088
+ var DEFAULT_CONFIG = {
3089
+ apiKey: "",
3090
+ model: "claude-haiku-4-5-20251001",
3091
+ baseUrl: "https://api.anthropic.com",
3092
+ timeout: 3e4
3093
+ };
3094
+ function createClaudeProvider(config = {}) {
3095
+ const cfg = {
3096
+ ...DEFAULT_CONFIG,
3097
+ ...config,
3098
+ apiKey: config.apiKey || process.env["ANTHROPIC_API_KEY"] || ""
3099
+ };
3100
+ return {
3101
+ name: "claude",
3102
+ isAvailable() {
3103
+ return !!cfg.apiKey;
3104
+ },
3105
+ async complete(prompt, options) {
3106
+ if (!cfg.apiKey) {
3107
+ throw new AIError("ANTHROPIC_API_KEY not set", "claude");
3108
+ }
3109
+ const requestBody = {
3110
+ model: cfg.model,
3111
+ max_tokens: options?.maxTokens ?? 1e3,
3112
+ messages: [{ role: "user", content: prompt }],
3113
+ temperature: options?.temperature ?? 0.3
3114
+ };
3115
+ if (options?.systemPrompt) {
3116
+ requestBody.system = options.systemPrompt;
3117
+ }
3118
+ const controller = new AbortController();
3119
+ const timeoutId = setTimeout(() => controller.abort(), cfg.timeout);
3120
+ try {
3121
+ const response = await fetch(`${cfg.baseUrl}/v1/messages`, {
3122
+ method: "POST",
3123
+ headers: {
3124
+ "Content-Type": "application/json",
3125
+ "x-api-key": cfg.apiKey,
3126
+ "anthropic-version": "2023-06-01"
3127
+ },
3128
+ body: JSON.stringify(requestBody),
3129
+ signal: controller.signal
3130
+ });
3131
+ clearTimeout(timeoutId);
3132
+ if (!response.ok) {
3133
+ const errorText = await response.text();
3134
+ throw new AIError(
3135
+ `Claude API error: ${response.status} ${response.statusText} - ${errorText}`,
3136
+ "claude"
3137
+ );
3138
+ }
3139
+ const data = await response.json();
3140
+ const textContent = data.content.find((c) => c.type === "text");
3141
+ if (!textContent) {
3142
+ throw new AIError("No text content in Claude response", "claude");
3143
+ }
3144
+ return textContent.text;
3145
+ } catch (error) {
3146
+ clearTimeout(timeoutId);
3147
+ if (error instanceof AIError) {
3148
+ throw error;
3149
+ }
3150
+ if (error instanceof Error && error.name === "AbortError") {
3151
+ throw new AIError("Claude API request timed out", "claude");
3152
+ }
3153
+ throw new AIError(
3154
+ `Claude API request failed: ${error instanceof Error ? error.message : "Unknown error"}`,
3155
+ "claude"
3156
+ );
3157
+ }
3158
+ }
3159
+ };
3160
+ }
3161
+ function createClaudePlugin(config = {}, enrichmentOptions) {
3162
+ const provider = createClaudeProvider(config);
3163
+ return createAIEnrichmentPlugin(provider, enrichmentOptions);
3164
+ }
3165
+
3166
+ // src/plugins/optional/openai-ai.ts
3167
+ var OPENAI_COMPATIBLE_PRESETS = {
3168
+ openai: {
3169
+ name: "openai",
3170
+ baseUrl: "https://api.openai.com/v1",
3171
+ envKey: "OPENAI_API_KEY",
3172
+ defaultModel: "gpt-4.1-nano"
3173
+ },
3174
+ xai: {
3175
+ name: "xai",
3176
+ baseUrl: "https://api.x.ai/v1",
3177
+ envKey: "XAI_API_KEY",
3178
+ defaultModel: "grok-3-mini-fast"
3179
+ },
3180
+ zai: {
3181
+ name: "zai",
3182
+ baseUrl: "https://api.z.ai/api/paas/v4",
3183
+ envKey: "ZAI_API_KEY",
3184
+ defaultModel: "glm-4.7"
3185
+ },
3186
+ together: {
3187
+ name: "together",
3188
+ baseUrl: "https://api.together.xyz/v1",
3189
+ envKey: "TOGETHER_API_KEY",
3190
+ defaultModel: "meta-llama/Llama-3.3-70B-Instruct-Turbo"
3191
+ },
3192
+ perplexity: {
3193
+ name: "perplexity",
3194
+ baseUrl: "https://api.perplexity.ai",
3195
+ envKey: "PERPLEXITY_API_KEY",
3196
+ defaultModel: "sonar-pro"
3197
+ },
3198
+ openrouter: {
3199
+ name: "openrouter",
3200
+ baseUrl: "https://openrouter.ai/api/v1",
3201
+ envKey: "OPENROUTER_API_KEY",
3202
+ defaultModel: "anthropic/claude-3.5-sonnet"
3203
+ },
3204
+ deepseek: {
3205
+ name: "deepseek",
3206
+ baseUrl: "https://api.deepseek.com/v1",
3207
+ envKey: "DEEPSEEK_API_KEY",
3208
+ defaultModel: "deepseek-chat"
3209
+ },
3210
+ mistral: {
3211
+ name: "mistral",
3212
+ baseUrl: "https://api.mistral.ai/v1",
3213
+ envKey: "MISTRAL_API_KEY",
3214
+ defaultModel: "mistral-small-latest"
3215
+ }
3216
+ };
3217
+ var DEFAULT_CONFIG2 = {
3218
+ apiKey: "",
3219
+ model: "gpt-4.1-nano",
3220
+ baseUrl: "https://api.openai.com/v1",
3221
+ timeout: 3e4,
3222
+ organization: void 0,
3223
+ preset: void 0
3224
+ };
3225
+ function createOpenAIProvider(config = {}) {
3226
+ const preset = config.preset ? OPENAI_COMPATIBLE_PRESETS[config.preset] : null;
3227
+ const cfg = {
3228
+ ...DEFAULT_CONFIG2,
3229
+ ...preset && {
3230
+ baseUrl: preset.baseUrl,
3231
+ model: preset.defaultModel
3232
+ },
3233
+ ...config,
3234
+ apiKey: config.apiKey || process.env[preset?.envKey ?? "OPENAI_API_KEY"] || ""
3235
+ };
3236
+ const providerName = preset?.name ?? "openai";
3237
+ return {
3238
+ name: providerName,
3239
+ isAvailable() {
3240
+ return !!cfg.apiKey;
3241
+ },
3242
+ async complete(prompt, options) {
3243
+ if (!cfg.apiKey) {
3244
+ throw new AIError(`${preset?.envKey ?? "OPENAI_API_KEY"} not set`, providerName);
3245
+ }
3246
+ const messages = [];
3247
+ if (options?.systemPrompt) {
3248
+ messages.push({ role: "system", content: options.systemPrompt });
3249
+ }
3250
+ messages.push({ role: "user", content: prompt });
3251
+ const requestBody = {
3252
+ model: cfg.model,
3253
+ messages,
3254
+ max_tokens: options?.maxTokens ?? 1e3,
3255
+ temperature: options?.temperature ?? 0.3
3256
+ };
3257
+ const headers = {
3258
+ "Content-Type": "application/json",
3259
+ Authorization: `Bearer ${cfg.apiKey}`
3260
+ };
3261
+ if (cfg.organization) {
3262
+ headers["OpenAI-Organization"] = cfg.organization;
3263
+ }
3264
+ const controller = new AbortController();
3265
+ const timeoutId = setTimeout(() => controller.abort(), cfg.timeout);
3266
+ try {
3267
+ const response = await fetch(`${cfg.baseUrl}/chat/completions`, {
3268
+ method: "POST",
3269
+ headers,
3270
+ body: JSON.stringify(requestBody),
3271
+ signal: controller.signal
3272
+ });
3273
+ clearTimeout(timeoutId);
3274
+ if (!response.ok) {
3275
+ const errorText = await response.text();
3276
+ throw new AIError(
3277
+ `${providerName} API error: ${response.status} ${response.statusText} - ${errorText}`,
3278
+ providerName
3279
+ );
3280
+ }
3281
+ const data = await response.json();
3282
+ const choice = data.choices[0];
3283
+ if (!choice || !choice.message.content) {
3284
+ throw new AIError(`No content in ${providerName} response`, providerName);
3285
+ }
3286
+ return choice.message.content;
3287
+ } catch (error) {
3288
+ clearTimeout(timeoutId);
3289
+ if (error instanceof AIError) {
3290
+ throw error;
3291
+ }
3292
+ if (error instanceof Error && error.name === "AbortError") {
3293
+ throw new AIError(`${providerName} API request timed out`, providerName);
3294
+ }
3295
+ throw new AIError(
3296
+ `${providerName} API request failed: ${error instanceof Error ? error.message : "Unknown error"}`,
3297
+ providerName
3298
+ );
3299
+ }
3300
+ }
3301
+ };
3302
+ }
3303
+ function createOpenAIPlugin(config = {}, enrichmentOptions) {
3304
+ const provider = createOpenAIProvider(config);
3305
+ return createAIEnrichmentPlugin(provider, enrichmentOptions);
3306
+ }
3307
+
3308
+ // src/plugins/optional/gemini-ai.ts
3309
+ var DEFAULT_CONFIG3 = {
3310
+ model: "gemini-3-flash-preview",
3311
+ baseUrl: "https://generativelanguage.googleapis.com/v1beta",
3312
+ timeout: 6e4,
3313
+ maxTokens: 1024,
3314
+ temperature: 0.3
3315
+ };
3316
+ function createGeminiProvider(config = {}) {
3317
+ const cfg = {
3318
+ ...DEFAULT_CONFIG3,
3319
+ ...config,
3320
+ apiKey: config.apiKey || process.env["GOOGLE_API_KEY"] || process.env["GEMINI_API_KEY"] || ""
3321
+ };
3322
+ return {
3323
+ name: "gemini",
3324
+ isAvailable() {
3325
+ return !!cfg.apiKey;
3326
+ },
3327
+ async complete(prompt, options) {
3328
+ if (!cfg.apiKey) {
3329
+ throw new Error("Gemini API key not configured. Set GOOGLE_API_KEY or GEMINI_API_KEY environment variable.");
3330
+ }
3331
+ const url = `${cfg.baseUrl}/models/${cfg.model}:generateContent?key=${cfg.apiKey}`;
3332
+ const contents = [];
3333
+ if (options?.systemPrompt) {
3334
+ contents.push({
3335
+ role: "user",
3336
+ parts: [{ text: `System instruction: ${options.systemPrompt}
3337
+
3338
+ Now respond to the following:` }]
3339
+ });
3340
+ contents.push({
3341
+ role: "model",
3342
+ parts: [{ text: "Understood. I will follow those instructions." }]
3343
+ });
3344
+ }
3345
+ contents.push({
3346
+ role: "user",
3347
+ parts: [{ text: prompt }]
3348
+ });
3349
+ const body = {
3350
+ contents,
3351
+ generationConfig: {
3352
+ maxOutputTokens: options?.maxTokens ?? cfg.maxTokens,
3353
+ temperature: options?.temperature ?? cfg.temperature
3354
+ }
3355
+ };
3356
+ const controller = new AbortController();
3357
+ const timeoutId = setTimeout(() => controller.abort(), cfg.timeout);
3358
+ try {
3359
+ const response = await fetch(url, {
3360
+ method: "POST",
3361
+ headers: {
3362
+ "Content-Type": "application/json"
3363
+ },
3364
+ body: JSON.stringify(body),
3365
+ signal: controller.signal
3366
+ });
3367
+ clearTimeout(timeoutId);
3368
+ if (!response.ok) {
3369
+ const errorText = await response.text();
3370
+ throw new Error(`Gemini API error (${response.status}): ${errorText}`);
3371
+ }
3372
+ const data = await response.json();
3373
+ if (data.error) {
3374
+ throw new Error(`Gemini API error: ${data.error.message}`);
3375
+ }
3376
+ const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
3377
+ if (!text) {
3378
+ throw new Error("No response generated from Gemini");
3379
+ }
3380
+ return text;
3381
+ } catch (error) {
3382
+ clearTimeout(timeoutId);
3383
+ if (error instanceof Error && error.name === "AbortError") {
3384
+ throw new Error(`Gemini request timed out after ${cfg.timeout}ms`);
3385
+ }
3386
+ throw error;
3387
+ }
3388
+ }
3389
+ };
3390
+ }
3391
+ function createGeminiPlugin(config = {}, enrichmentOptions) {
3392
+ const provider = createGeminiProvider(config);
3393
+ return createAIEnrichmentPlugin(provider, enrichmentOptions);
3394
+ }
3395
+ function checkGeminiAvailable() {
3396
+ return !!(process.env["GOOGLE_API_KEY"] || process.env["GEMINI_API_KEY"]);
3397
+ }
3398
+
3399
+ // src/plugins/optional/ollama-ai.ts
3400
+ var DEFAULT_CONFIG4 = {
3401
+ model: "llama3.2",
3402
+ baseUrl: "http://localhost:11434",
3403
+ timeout: 12e4
3404
+ // Longer timeout for local models
3405
+ };
3406
+ function createOllamaProvider(config = {}) {
3407
+ const cfg = { ...DEFAULT_CONFIG4, ...config };
3408
+ let available = null;
3409
+ return {
3410
+ name: "ollama",
3411
+ isAvailable() {
3412
+ if (available !== null) {
3413
+ return available;
3414
+ }
3415
+ return true;
3416
+ },
3417
+ async complete(prompt, options) {
3418
+ const requestBody = {
3419
+ model: cfg.model,
3420
+ prompt,
3421
+ stream: false,
3422
+ options: {
3423
+ temperature: options?.temperature ?? 0.3,
3424
+ num_predict: options?.maxTokens ?? 1e3
3425
+ }
3426
+ };
3427
+ if (options?.systemPrompt) {
3428
+ requestBody.system = options.systemPrompt;
3429
+ }
3430
+ const controller = new AbortController();
3431
+ const timeoutId = setTimeout(() => controller.abort(), cfg.timeout);
3432
+ try {
3433
+ const response = await fetch(`${cfg.baseUrl}/api/generate`, {
3434
+ method: "POST",
3435
+ headers: {
3436
+ "Content-Type": "application/json"
3437
+ },
3438
+ body: JSON.stringify(requestBody),
3439
+ signal: controller.signal
3440
+ });
3441
+ clearTimeout(timeoutId);
3442
+ if (!response.ok) {
3443
+ available = false;
3444
+ const errorText = await response.text();
3445
+ throw new AIError(
3446
+ `Ollama API error: ${response.status} ${response.statusText} - ${errorText}`,
3447
+ "ollama"
3448
+ );
3449
+ }
3450
+ available = true;
3451
+ const data = await response.json();
3452
+ if (!data.response) {
3453
+ throw new AIError("No response from Ollama", "ollama");
3454
+ }
3455
+ return data.response;
3456
+ } catch (error) {
3457
+ clearTimeout(timeoutId);
3458
+ if (error instanceof AIError) {
3459
+ throw error;
3460
+ }
3461
+ if (error instanceof Error && error.name === "AbortError") {
3462
+ throw new AIError("Ollama request timed out", "ollama");
3463
+ }
3464
+ if (error instanceof Error && error.message.includes("ECONNREFUSED")) {
3465
+ available = false;
3466
+ throw new AIError("Ollama is not running. Start it with: ollama serve", "ollama");
3467
+ }
3468
+ throw new AIError(
3469
+ `Ollama request failed: ${error instanceof Error ? error.message : "Unknown error"}`,
3470
+ "ollama"
3471
+ );
3472
+ }
3473
+ }
3474
+ };
3475
+ }
3476
+ function createOllamaPlugin(config = {}, enrichmentOptions) {
3477
+ const provider = createOllamaProvider(config);
3478
+ return createAIEnrichmentPlugin(provider, enrichmentOptions);
3479
+ }
3480
+ async function checkOllamaAvailable(baseUrl = "http://localhost:11434") {
3481
+ try {
3482
+ const response = await fetch(`${baseUrl}/api/tags`, {
3483
+ method: "GET",
3484
+ signal: AbortSignal.timeout(5e3)
3485
+ });
3486
+ return response.ok;
3487
+ } catch {
3488
+ return false;
3489
+ }
3490
+ }
3491
+ async function listOllamaModels(baseUrl = "http://localhost:11434") {
3492
+ try {
3493
+ const response = await fetch(`${baseUrl}/api/tags`, {
3494
+ method: "GET",
3495
+ signal: AbortSignal.timeout(5e3)
3496
+ });
3497
+ if (!response.ok) {
3498
+ return [];
3499
+ }
3500
+ const data = await response.json();
3501
+ return data.models.map((m) => m.name);
3502
+ } catch {
3503
+ return [];
3504
+ }
3505
+ }
3506
+
3507
+ // src/plugins/optional/groq-ai.ts
3508
+ var DEFAULT_CONFIG5 = {
3509
+ apiKey: "",
3510
+ model: "llama-3.1-8b-instant",
3511
+ baseUrl: "https://api.groq.com/openai",
3512
+ timeout: 3e4
3513
+ };
3514
+ function createGroqProvider(config = {}) {
3515
+ const cfg = {
3516
+ ...DEFAULT_CONFIG5,
3517
+ ...config,
3518
+ apiKey: config.apiKey || process.env["GROQ_API_KEY"] || ""
3519
+ };
3520
+ return {
3521
+ name: "groq",
3522
+ isAvailable() {
3523
+ return !!cfg.apiKey;
3524
+ },
3525
+ async complete(prompt, options) {
3526
+ if (!cfg.apiKey) {
3527
+ throw new AIError("GROQ_API_KEY not set", "groq");
3528
+ }
3529
+ const messages = [];
3530
+ if (options?.systemPrompt) {
3531
+ messages.push({ role: "system", content: options.systemPrompt });
3532
+ }
3533
+ messages.push({ role: "user", content: prompt });
3534
+ const requestBody = {
3535
+ model: cfg.model,
3536
+ messages,
3537
+ max_tokens: options?.maxTokens ?? 1e3,
3538
+ temperature: options?.temperature ?? 0.3
3539
+ };
3540
+ const controller = new AbortController();
3541
+ const timeoutId = setTimeout(() => controller.abort(), cfg.timeout);
3542
+ try {
3543
+ const response = await fetch(`${cfg.baseUrl}/v1/chat/completions`, {
3544
+ method: "POST",
3545
+ headers: {
3546
+ "Content-Type": "application/json",
3547
+ Authorization: `Bearer ${cfg.apiKey}`
3548
+ },
3549
+ body: JSON.stringify(requestBody),
3550
+ signal: controller.signal
3551
+ });
3552
+ clearTimeout(timeoutId);
3553
+ if (!response.ok) {
3554
+ const errorText = await response.text();
3555
+ throw new AIError(
3556
+ `Groq API error: ${response.status} ${response.statusText} - ${errorText}`,
3557
+ "groq"
3558
+ );
3559
+ }
3560
+ const data = await response.json();
3561
+ const choice = data.choices[0];
3562
+ if (!choice || !choice.message.content) {
3563
+ throw new AIError("No content in Groq response", "groq");
3564
+ }
3565
+ return choice.message.content;
3566
+ } catch (error) {
3567
+ clearTimeout(timeoutId);
3568
+ if (error instanceof AIError) {
3569
+ throw error;
3570
+ }
3571
+ if (error instanceof Error && error.name === "AbortError") {
3572
+ throw new AIError("Groq API request timed out", "groq");
3573
+ }
3574
+ throw new AIError(
3575
+ `Groq API request failed: ${error instanceof Error ? error.message : "Unknown error"}`,
3576
+ "groq"
3577
+ );
3578
+ }
3579
+ }
3580
+ };
3581
+ }
3582
+ function createGroqPlugin(config = {}, enrichmentOptions) {
3583
+ const provider = createGroqProvider(config);
3584
+ return createAIEnrichmentPlugin(provider, enrichmentOptions);
3585
+ }
3586
+
3587
+ // src/kernel.ts
3588
+ function createKernel() {
3589
+ const plugins = /* @__PURE__ */ new Map();
3590
+ const eventHandlers = /* @__PURE__ */ new Map();
3591
+ const handlerToPlugin = /* @__PURE__ */ new Map();
3592
+ function handlePluginError(error, pluginName) {
3593
+ const plugin = pluginName ? plugins.get(pluginName) : void 0;
3594
+ if (plugin?.onError) {
3595
+ try {
3596
+ plugin.onError(error);
3597
+ } catch {
3598
+ }
3599
+ }
3600
+ }
3601
+ function use(plugin) {
3602
+ if (!plugin.name) {
3603
+ throw new PluginError("Plugin must have a name");
3604
+ }
3605
+ if (plugins.has(plugin.name)) {
3606
+ throw new PluginError(`Plugin "${plugin.name}" is already registered`, plugin.name);
3607
+ }
3608
+ if (plugin.dependencies) {
3609
+ for (const dep of plugin.dependencies) {
3610
+ if (!plugins.has(dep)) {
3611
+ throw new PluginError(
3612
+ `Plugin "${plugin.name}" depends on "${dep}" which is not registered`,
3613
+ plugin.name
3614
+ );
3615
+ }
3616
+ }
3617
+ }
3618
+ try {
3619
+ plugin.install(kernel);
3620
+ plugins.set(plugin.name, plugin);
3621
+ } catch (error) {
3622
+ const err = error instanceof Error ? error : new Error(String(error));
3623
+ throw new PluginError(
3624
+ `Failed to install plugin "${plugin.name}": ${err.message}`,
3625
+ plugin.name
3626
+ );
3627
+ }
3628
+ return kernel;
3629
+ }
3630
+ function unregister(name) {
3631
+ const plugin = plugins.get(name);
3632
+ if (!plugin) {
3633
+ return false;
3634
+ }
3635
+ for (const [, p] of plugins) {
3636
+ if (p.dependencies?.includes(name)) {
3637
+ throw new PluginError(
3638
+ `Cannot unregister "${name}": plugin "${p.name}" depends on it`,
3639
+ name
3640
+ );
3641
+ }
3642
+ }
3643
+ for (const [event, handlers] of eventHandlers) {
3644
+ const toRemove = [];
3645
+ for (const entry of handlers) {
3646
+ if (entry.pluginName === name) {
3647
+ toRemove.push(entry);
3648
+ handlerToPlugin.delete(entry.handler);
3649
+ }
3650
+ }
3651
+ for (const entry of toRemove) {
3652
+ handlers.delete(entry);
3653
+ }
3654
+ if (handlers.size === 0) {
3655
+ eventHandlers.delete(event);
3656
+ }
3657
+ }
3658
+ try {
3659
+ plugin.onDestroy?.();
3660
+ } catch {
3661
+ }
3662
+ plugins.delete(name);
3663
+ return true;
3664
+ }
3665
+ function on(event, handler) {
3666
+ if (!eventHandlers.has(event)) {
3667
+ eventHandlers.set(event, /* @__PURE__ */ new Set());
3668
+ }
3669
+ const pluginName = getCurrentPluginContext() ?? "unknown";
3670
+ const entry = { handler, pluginName };
3671
+ eventHandlers.get(event).add(entry);
3672
+ handlerToPlugin.set(handler, pluginName);
3673
+ }
3674
+ function off(event, handler) {
3675
+ const handlers = eventHandlers.get(event);
3676
+ if (!handlers) return;
3677
+ for (const entry of handlers) {
3678
+ if (entry.handler === handler) {
3679
+ handlers.delete(entry);
3680
+ handlerToPlugin.delete(handler);
3681
+ break;
3682
+ }
3683
+ }
3684
+ if (handlers.size === 0) {
3685
+ eventHandlers.delete(event);
3686
+ }
3687
+ }
3688
+ async function emit(event, context, ...args) {
3689
+ const handlers = eventHandlers.get(event);
3690
+ if (!handlers || handlers.size === 0) return;
3691
+ for (const entry of handlers) {
3692
+ try {
3693
+ await entry.handler(context, ...args);
3694
+ } catch (error) {
3695
+ const err = error instanceof Error ? error : new Error(String(error));
3696
+ handlePluginError(err, entry.pluginName);
3697
+ }
3698
+ }
3699
+ }
3700
+ function listPlugins() {
3701
+ return Array.from(plugins.values()).map((p) => ({
3702
+ name: p.name,
3703
+ version: p.version,
3704
+ category: p.category,
3705
+ dependencies: p.dependencies ?? []
3706
+ }));
3707
+ }
3708
+ function getPlugin(name) {
3709
+ return plugins.get(name);
3710
+ }
3711
+ function hasPlugin(name) {
3712
+ return plugins.has(name);
3713
+ }
3714
+ async function destroy() {
3715
+ const pluginNames = Array.from(plugins.keys()).reverse();
3716
+ for (const name of pluginNames) {
3717
+ const plugin = plugins.get(name);
3718
+ if (plugin?.onDestroy) {
3719
+ try {
3720
+ await plugin.onDestroy();
3721
+ } catch {
3722
+ }
3723
+ }
3724
+ }
3725
+ plugins.clear();
3726
+ eventHandlers.clear();
3727
+ handlerToPlugin.clear();
3728
+ }
3729
+ let currentPluginContext = null;
3730
+ function getCurrentPluginContext() {
3731
+ return currentPluginContext;
3732
+ }
3733
+ const originalUse = use;
3734
+ function wrappedUse(plugin) {
3735
+ currentPluginContext = plugin.name;
3736
+ try {
3737
+ originalUse(plugin);
3738
+ return kernel;
3739
+ } finally {
3740
+ currentPluginContext = null;
3741
+ }
3742
+ }
3743
+ const kernel = {
3744
+ use: wrappedUse,
3745
+ unregister,
3746
+ on,
3747
+ off,
3748
+ emit,
3749
+ listPlugins,
3750
+ getPlugin,
3751
+ hasPlugin,
3752
+ destroy
3753
+ };
3754
+ return kernel;
3755
+ }
3756
+ function definePlugin(definition) {
3757
+ return definition;
3758
+ }
3759
+ function composePlugins(name, plugins) {
3760
+ return {
3761
+ name,
3762
+ version: "1.0.0",
3763
+ category: "utility",
3764
+ dependencies: plugins.flatMap((p) => p.dependencies ?? []),
3765
+ install(kernel) {
3766
+ for (const plugin of plugins) {
3767
+ kernel.use(plugin);
3768
+ }
3769
+ },
3770
+ async onDestroy() {
3771
+ }
3772
+ };
3773
+ }
3774
+
3775
+ // src/plugins/optional/changelog-parser.ts
3776
+ function parseChangelog(content) {
3777
+ const versions = [];
3778
+ const lines = content.split("\n");
3779
+ let currentVersion = null;
3780
+ let currentType = "other";
3781
+ const versionRegex = /^##\s+\[?(\d+\.\d+\.\d+(?:-[\w.]+)?)\]?(?:\s*[-–(]\s*(\d{4}-\d{2}-\d{2}))?/;
3782
+ const typeMap = {
3783
+ added: "added",
3784
+ changed: "changed",
3785
+ deprecated: "deprecated",
3786
+ removed: "removed",
3787
+ fixed: "fixed",
3788
+ security: "security"
3789
+ };
3790
+ for (const line of lines) {
3791
+ const versionMatch = versionRegex.exec(line);
3792
+ if (versionMatch) {
3793
+ if (currentVersion) {
3794
+ versions.push(currentVersion);
3795
+ }
3796
+ currentVersion = {
3797
+ version: versionMatch[1],
3798
+ date: versionMatch[2],
3799
+ changes: []
3800
+ };
3801
+ currentType = "other";
3802
+ continue;
3803
+ }
3804
+ if (line.startsWith("### ")) {
3805
+ const typeText = line.slice(4).toLowerCase().trim();
3806
+ currentType = typeMap[typeText] || "other";
3807
+ continue;
3808
+ }
3809
+ const itemMatch = /^[-*]\s+(.+)/.exec(line);
3810
+ if (itemMatch && currentVersion) {
3811
+ currentVersion.changes.push({
3812
+ type: currentType,
3813
+ description: itemMatch[1].trim()
3814
+ });
3815
+ }
3816
+ }
3817
+ if (currentVersion) {
3818
+ versions.push(currentVersion);
3819
+ }
3820
+ return { versions };
3821
+ }
3822
+ function findChangelog(files) {
3823
+ const names = [
3824
+ "CHANGELOG.md",
3825
+ "changelog.md",
3826
+ "CHANGELOG",
3827
+ "changelog",
3828
+ "HISTORY.md",
3829
+ "history.md",
3830
+ "CHANGES.md",
3831
+ "changes.md"
3832
+ ];
3833
+ for (const name of names) {
3834
+ const content = files.get(name) || files.get(`package/${name}`);
3835
+ if (content) {
3836
+ return content;
3837
+ }
3838
+ }
3839
+ return void 0;
3840
+ }
3841
+ function getLatestVersion(changelog) {
3842
+ return changelog.versions[0];
3843
+ }
3844
+ function getVersion(changelog, version) {
3845
+ return changelog.versions.find((v) => v.version === version);
3846
+ }
3847
+ function formatChangelogEntry(entry) {
3848
+ const lines = [];
3849
+ lines.push(`## ${entry.version}${entry.date ? ` (${entry.date})` : ""}`);
3850
+ lines.push("");
3851
+ const grouped = /* @__PURE__ */ new Map();
3852
+ for (const change of entry.changes) {
3853
+ const existing = grouped.get(change.type) || [];
3854
+ existing.push(change.description);
3855
+ grouped.set(change.type, existing);
3856
+ }
3857
+ const typeLabels = {
3858
+ added: "Added",
3859
+ changed: "Changed",
3860
+ deprecated: "Deprecated",
3861
+ removed: "Removed",
3862
+ fixed: "Fixed",
3863
+ security: "Security",
3864
+ other: "Other"
3865
+ };
3866
+ for (const [type, changes] of grouped) {
3867
+ lines.push(`### ${typeLabels[type] || type}`);
3868
+ for (const change of changes) {
3869
+ lines.push(`- ${change}`);
3870
+ }
3871
+ lines.push("");
3872
+ }
3873
+ return lines.join("\n");
3874
+ }
3875
+ function createChangelogParserPlugin() {
3876
+ return definePlugin({
3877
+ name: "changelog-parser",
3878
+ version: "1.0.0",
3879
+ category: "parser",
3880
+ install(kernel) {
3881
+ kernel.on("parse:changelog", async (ctx) => {
3882
+ const changelogContent = findChangelog(ctx.package.files);
3883
+ if (changelogContent) {
3884
+ ctx.changelog = parseChangelog(changelogContent);
3885
+ }
3886
+ });
3887
+ }
3888
+ });
3889
+ }
3890
+
3891
+ // src/plugins/optional/html-output.ts
3892
+ var DEFAULT_OPTIONS2 = {
3893
+ includeStyles: true,
3894
+ syntaxHighlighting: true,
3895
+ darkMode: true
3896
+ };
3897
+ function escapeHTML(str) {
3898
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
3899
+ }
3900
+ function generateStyles(options) {
3901
+ if (!options.includeStyles) return "";
3902
+ let css = `
3903
+ :root {
3904
+ --bg: #ffffff;
3905
+ --text: #1a1a1a;
3906
+ --code-bg: #f5f5f5;
3907
+ --border: #e5e5e5;
3908
+ --link: #0066cc;
3909
+ --heading: #000000;
3910
+ --param-type: #0550ae;
3911
+ --deprecated: #d93025;
3912
+ }
3913
+ ${options.darkMode ? `
3914
+ @media (prefers-color-scheme: dark) {
3915
+ :root {
3916
+ --bg: #1a1a1a;
3917
+ --text: #e5e5e5;
3918
+ --code-bg: #2d2d2d;
3919
+ --border: #404040;
3920
+ --link: #58a6ff;
3921
+ --heading: #ffffff;
3922
+ --param-type: #79c0ff;
3923
+ --deprecated: #f85149;
3924
+ }
3925
+ }` : ""}
3926
+ * { box-sizing: border-box; }
3927
+ body {
3928
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
3929
+ line-height: 1.6;
3930
+ color: var(--text);
3931
+ background: var(--bg);
3932
+ max-width: 900px;
3933
+ margin: 0 auto;
3934
+ padding: 2rem;
3935
+ }
3936
+ h1, h2, h3, h4 { color: var(--heading); margin-top: 2rem; }
3937
+ h1 { border-bottom: 2px solid var(--border); padding-bottom: 0.5rem; }
3938
+ code {
3939
+ font-family: 'SFMono-Regular', Consolas, monospace;
3940
+ font-size: 0.9em;
3941
+ background: var(--code-bg);
3942
+ padding: 0.2em 0.4em;
3943
+ border-radius: 3px;
3944
+ }
3945
+ pre {
3946
+ background: var(--code-bg);
3947
+ padding: 1rem;
3948
+ overflow-x: auto;
3949
+ border-radius: 6px;
3950
+ border: 1px solid var(--border);
3951
+ }
3952
+ pre code { background: none; padding: 0; }
3953
+ a { color: var(--link); text-decoration: none; }
3954
+ a:hover { text-decoration: underline; }
3955
+ .api-entry {
3956
+ margin: 2rem 0;
3957
+ padding: 1.5rem;
3958
+ border: 1px solid var(--border);
3959
+ border-radius: 8px;
3960
+ }
3961
+ .api-entry h3 { margin-top: 0; }
3962
+ .signature { font-size: 0.95rem; }
3963
+ .param-type { color: var(--param-type); }
3964
+ .deprecated { color: var(--deprecated); font-style: italic; }
3965
+ .params-table {
3966
+ width: 100%;
3967
+ border-collapse: collapse;
3968
+ margin: 1rem 0;
3969
+ }
3970
+ .params-table th, .params-table td {
3971
+ text-align: left;
3972
+ padding: 0.5rem;
3973
+ border-bottom: 1px solid var(--border);
3974
+ }
3975
+ .params-table th { font-weight: 600; }
3976
+ .toc { background: var(--code-bg); padding: 1rem; border-radius: 6px; }
3977
+ .toc ul { margin: 0; padding-left: 1.5rem; }
3978
+ .badge {
3979
+ display: inline-block;
3980
+ padding: 0.2em 0.5em;
3981
+ font-size: 0.75rem;
3982
+ font-weight: 600;
3983
+ border-radius: 4px;
3984
+ margin-left: 0.5rem;
3985
+ }
3986
+ .badge-function { background: #ddf4ff; color: #0550ae; }
3987
+ .badge-class { background: #fff8c5; color: #735c0f; }
3988
+ .badge-interface { background: #dafbe1; color: #116329; }
3989
+ .badge-type { background: #f6e8ff; color: #8250df; }
3990
+ .badge-constant { background: #ffebe9; color: #cf222e; }
3991
+ .badge-enum { background: #fdf4ff; color: #bf3989; }
3992
+ `;
3993
+ if (options.customCSS) {
3994
+ css += options.customCSS;
3995
+ }
3996
+ return `<style>${css}</style>`;
3997
+ }
3998
+ function kindBadge(kind) {
3999
+ return `<span class="badge badge-${kind}">${kind}</span>`;
4000
+ }
4001
+ function generateTOC(entries) {
4002
+ if (entries.length === 0) return "";
4003
+ const grouped = /* @__PURE__ */ new Map();
4004
+ for (const entry of entries) {
4005
+ const list = grouped.get(entry.kind) || [];
4006
+ list.push(entry);
4007
+ grouped.set(entry.kind, list);
4008
+ }
4009
+ let html = '<nav class="toc"><h2>Table of Contents</h2>';
4010
+ for (const [kind, items] of grouped) {
4011
+ html += `<h4>${kind.charAt(0).toUpperCase() + kind.slice(1)}s</h4><ul>`;
4012
+ for (const item of items) {
4013
+ const id = `${kind}-${item.name}`.toLowerCase().replace(/[^a-z0-9-]/g, "-");
4014
+ html += `<li><a href="#${id}">${escapeHTML(item.name)}</a></li>`;
4015
+ }
4016
+ html += "</ul>";
4017
+ }
4018
+ html += "</nav>";
4019
+ return html;
4020
+ }
4021
+ function generateParams(entry) {
4022
+ if (!entry.params || entry.params.length === 0) return "";
4023
+ let html = '<h4>Parameters</h4><table class="params-table"><thead><tr>';
4024
+ html += "<th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody>";
4025
+ for (const param of entry.params) {
4026
+ const name = param.optional ? `${param.name}?` : param.name;
4027
+ const type = param.type ? `<code class="param-type">${escapeHTML(param.type)}</code>` : "-";
4028
+ const desc = param.description ? escapeHTML(param.description) : "-";
4029
+ html += `<tr><td><code>${escapeHTML(name)}</code></td><td>${type}</td><td>${desc}</td></tr>`;
4030
+ }
4031
+ html += "</tbody></table>";
4032
+ return html;
4033
+ }
4034
+ function generateExamples(examples) {
4035
+ if (examples.length === 0) return "";
4036
+ let html = "<h4>Examples</h4>";
4037
+ for (const example of examples) {
4038
+ html += `<pre><code>${escapeHTML(example)}</code></pre>`;
4039
+ }
4040
+ return html;
4041
+ }
4042
+ function generateEntry(entry) {
4043
+ const id = `${entry.kind}-${entry.name}`.toLowerCase().replace(/[^a-z0-9-]/g, "-");
4044
+ let html = `<div class="api-entry" id="${id}">`;
4045
+ html += `<h3>${escapeHTML(entry.name)} ${kindBadge(entry.kind)}</h3>`;
4046
+ if (entry.deprecated) {
4047
+ const reason = typeof entry.deprecated === "string" ? entry.deprecated : "";
4048
+ html += `<p class="deprecated">Deprecated${reason ? `: ${escapeHTML(reason)}` : ""}</p>`;
4049
+ }
4050
+ if (entry.description) {
4051
+ html += `<p>${escapeHTML(entry.description)}</p>`;
4052
+ }
4053
+ html += `<pre class="signature"><code>${escapeHTML(entry.signature)}</code></pre>`;
4054
+ html += generateParams(entry);
4055
+ if (entry.returns) {
4056
+ html += "<h4>Returns</h4>";
4057
+ html += `<p><code class="param-type">${escapeHTML(entry.returns.type)}</code>`;
4058
+ if (entry.returns.description) {
4059
+ html += ` - ${escapeHTML(entry.returns.description)}`;
4060
+ }
4061
+ html += "</p>";
4062
+ }
4063
+ if (entry.examples && entry.examples.length > 0) {
4064
+ html += generateExamples(entry.examples);
4065
+ }
4066
+ html += "</div>";
4067
+ return html;
4068
+ }
4069
+ function generateHeader(name, version, description, readme) {
4070
+ let html = `<header>`;
4071
+ html += `<h1>${escapeHTML(name)} <small>v${escapeHTML(version)}</small></h1>`;
4072
+ if (description) {
4073
+ html += `<p>${escapeHTML(description)}</p>`;
4074
+ }
4075
+ if (readme?.installation) {
4076
+ html += "<h2>Installation</h2>";
4077
+ html += `<pre><code>${escapeHTML(readme.installation)}</code></pre>`;
4078
+ }
4079
+ html += "</header>";
4080
+ return html;
4081
+ }
4082
+ function generateHTML(ctx, options = {}) {
4083
+ const opts = { ...DEFAULT_OPTIONS2, ...options };
4084
+ const title = opts.title || `${ctx.package.name} API Documentation`;
4085
+ let html = '<!DOCTYPE html>\n<html lang="en">\n<head>\n';
4086
+ html += '<meta charset="UTF-8">\n';
4087
+ html += '<meta name="viewport" content="width=device-width, initial-scale=1.0">\n';
4088
+ html += `<title>${escapeHTML(title)}</title>
4089
+ `;
4090
+ html += generateStyles(opts);
4091
+ html += "</head>\n<body>\n";
4092
+ html += generateHeader(ctx.package.name, ctx.package.version, ctx.package.description, ctx.readme);
4093
+ html += generateTOC(ctx.api);
4094
+ html += "<main>";
4095
+ const grouped = /* @__PURE__ */ new Map();
4096
+ for (const entry of ctx.api) {
4097
+ const list = grouped.get(entry.kind) || [];
4098
+ list.push(entry);
4099
+ grouped.set(entry.kind, list);
4100
+ }
4101
+ const kindOrder = ["function", "class", "interface", "type", "constant", "enum"];
4102
+ for (const kind of kindOrder) {
4103
+ const entries = grouped.get(kind);
4104
+ if (!entries || entries.length === 0) continue;
4105
+ html += `<section><h2>${kind.charAt(0).toUpperCase() + kind.slice(1)}s</h2>`;
4106
+ for (const entry of entries) {
4107
+ html += generateEntry(entry);
4108
+ }
4109
+ html += "</section>";
4110
+ }
4111
+ html += "</main>\n";
4112
+ html += '<footer><p>Generated by <a href="https://github.com/oxog/npm-llms">@oxog/npm-llms</a></p></footer>\n';
4113
+ html += "</body>\n</html>";
4114
+ return html;
4115
+ }
4116
+ function createHTMLOutputPlugin(options = {}) {
4117
+ return definePlugin({
4118
+ name: "html-output",
4119
+ version: "1.0.0",
4120
+ category: "output",
4121
+ install(kernel) {
4122
+ kernel.on("output:generate", async (ctx) => {
4123
+ if (!ctx.options.formats?.includes("html")) return;
4124
+ const html = generateHTML(ctx, options);
4125
+ ctx.outputs.set("html", html);
4126
+ });
4127
+ }
4128
+ });
4129
+ }
4130
+
4131
+ export { checkGeminiAvailable, checkOllamaAvailable, composePlugins, coreOutputPlugins, coreParserPlugins, corePlugins, createAIEnrichmentPlugin, createChangelogParserPlugin, createClaudePlugin, createClaudeProvider, createGeminiPlugin, createGeminiProvider, createGroqPlugin, createGroqProvider, createHTMLOutputPlugin, createKernel, createOllamaPlugin, createOllamaProvider, createOpenAIPlugin, createOpenAIProvider, createSimpleProvider, definePlugin, dtsParserPlugin, findChangelog, formatChangelogEntry, generateHTML, getLatestVersion, getVersion, jsonOutputPlugin, listOllamaModels, llmsFullOutputPlugin, llmsOutputPlugin, markdownOutputPlugin, parseChangelog, readmeParserPlugin, tsSourceParserPlugin, typesResolverPlugin };
4132
+ //# sourceMappingURL=index.js.map
4133
+ //# sourceMappingURL=index.js.map