@speakeasy-api/docs-mcp-core 0.1.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.
Files changed (51) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +27 -0
  3. package/dist/chunking.d.ts +3 -0
  4. package/dist/chunking.d.ts.map +1 -0
  5. package/dist/chunking.js +332 -0
  6. package/dist/chunking.js.map +1 -0
  7. package/dist/cursor.d.ts +12 -0
  8. package/dist/cursor.d.ts.map +1 -0
  9. package/dist/cursor.js +83 -0
  10. package/dist/cursor.js.map +1 -0
  11. package/dist/embedding-cache.d.ts +46 -0
  12. package/dist/embedding-cache.d.ts.map +1 -0
  13. package/dist/embedding-cache.js +230 -0
  14. package/dist/embedding-cache.js.map +1 -0
  15. package/dist/embedding.d.ts +66 -0
  16. package/dist/embedding.d.ts.map +1 -0
  17. package/dist/embedding.js +264 -0
  18. package/dist/embedding.js.map +1 -0
  19. package/dist/index.d.ts +11 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +11 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/lancedb.d.ts +42 -0
  24. package/dist/lancedb.d.ts.map +1 -0
  25. package/dist/lancedb.js +442 -0
  26. package/dist/lancedb.js.map +1 -0
  27. package/dist/manifest.d.ts +19 -0
  28. package/dist/manifest.d.ts.map +1 -0
  29. package/dist/manifest.js +245 -0
  30. package/dist/manifest.js.map +1 -0
  31. package/dist/metadata.d.ts +6 -0
  32. package/dist/metadata.d.ts.map +1 -0
  33. package/dist/metadata.js +152 -0
  34. package/dist/metadata.js.map +1 -0
  35. package/dist/parser.d.ts +6 -0
  36. package/dist/parser.d.ts.map +1 -0
  37. package/dist/parser.js +21 -0
  38. package/dist/parser.js.map +1 -0
  39. package/dist/search-common.d.ts +7 -0
  40. package/dist/search-common.d.ts.map +1 -0
  41. package/dist/search-common.js +81 -0
  42. package/dist/search-common.js.map +1 -0
  43. package/dist/search.d.ts +13 -0
  44. package/dist/search.d.ts.map +1 -0
  45. package/dist/search.js +166 -0
  46. package/dist/search.js.map +1 -0
  47. package/dist/types.d.ts +125 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +2 -0
  50. package/dist/types.js.map +1 -0
  51. package/package.json +49 -0
@@ -0,0 +1,245 @@
1
+ import matter from "gray-matter";
2
+ import picomatch from "picomatch";
3
+ const DEFAULT_STRATEGY = { chunk_by: "h2" };
4
+ const HTML_HINT_REGEX = /<!--\s*mcp_chunking_hint:\s*(\{[^}]+\})\s*-->/;
5
+ export function parseManifest(input) {
6
+ if (!input || typeof input !== "object") {
7
+ throw new Error("manifest must be an object");
8
+ }
9
+ const manifest = input;
10
+ const version = manifest.version;
11
+ if (version !== "1") {
12
+ throw new Error("manifest.version must be '1'");
13
+ }
14
+ const parsed = { version };
15
+ if (manifest.strategy) {
16
+ parsed.strategy = parseStrategy(manifest.strategy);
17
+ }
18
+ if (manifest.metadata) {
19
+ parsed.metadata = parseMetadata(manifest.metadata, "metadata");
20
+ }
21
+ if (manifest.overrides) {
22
+ parsed.overrides = parseOverrides(manifest.overrides);
23
+ }
24
+ return parsed;
25
+ }
26
+ export function parseManifestJson(contents) {
27
+ let parsed;
28
+ try {
29
+ parsed = JSON.parse(contents);
30
+ }
31
+ catch {
32
+ throw new Error("Manifest is not valid JSON");
33
+ }
34
+ return parseManifest(parsed);
35
+ }
36
+ export function resolveFileConfig(params) {
37
+ const defaults = {
38
+ strategy: params.defaults?.strategy ?? DEFAULT_STRATEGY,
39
+ metadata: params.defaults?.metadata ?? {}
40
+ };
41
+ const manifest = params.manifest;
42
+ let metadata = {
43
+ ...defaults.metadata,
44
+ ...(manifest?.metadata ?? {})
45
+ };
46
+ let strategy = manifest?.strategy ?? defaults.strategy;
47
+ const overrideMatchPath = toManifestRelativePath(params.relativeFilePath, params.manifestBaseDir);
48
+ if (manifest?.overrides) {
49
+ for (const override of manifest.overrides) {
50
+ const matcher = picomatch(override.pattern, { dot: true });
51
+ if (!matcher(overrideMatchPath)) {
52
+ continue;
53
+ }
54
+ if (override.metadata) {
55
+ metadata = {
56
+ ...metadata,
57
+ ...override.metadata
58
+ };
59
+ }
60
+ if (override.strategy) {
61
+ strategy = override.strategy;
62
+ }
63
+ }
64
+ }
65
+ if (params.markdown) {
66
+ // HTML comment hints: applied after manifest but before frontmatter
67
+ const htmlHint = parseHtmlChunkingHint(params.markdown);
68
+ if (htmlHint) {
69
+ strategy = { ...strategy, chunk_by: htmlHint.chunk_by };
70
+ }
71
+ // Frontmatter overrides: highest precedence
72
+ const frontmatterOverrides = parseFrontmatterOverrides(params.markdown);
73
+ if (frontmatterOverrides.metadata) {
74
+ metadata = {
75
+ ...metadata,
76
+ ...frontmatterOverrides.metadata
77
+ };
78
+ }
79
+ if (frontmatterOverrides.strategy) {
80
+ strategy = frontmatterOverrides.strategy;
81
+ }
82
+ }
83
+ return {
84
+ strategy,
85
+ metadata
86
+ };
87
+ }
88
+ function toManifestRelativePath(relativeFilePath, manifestBaseDir) {
89
+ const normalizedFile = toPosixPath(relativeFilePath);
90
+ if (!manifestBaseDir) {
91
+ return normalizedFile;
92
+ }
93
+ const normalizedBase = toPosixPath(manifestBaseDir).replace(/^\/+|\/+$/g, "");
94
+ if (!normalizedBase || normalizedBase === ".") {
95
+ return normalizedFile;
96
+ }
97
+ const basePrefix = `${normalizedBase}/`;
98
+ if (normalizedFile.startsWith(basePrefix)) {
99
+ return normalizedFile.slice(basePrefix.length);
100
+ }
101
+ return normalizedFile;
102
+ }
103
+ function toPosixPath(value) {
104
+ return value.replace(/\\/g, "/").replace(/^\.\//, "");
105
+ }
106
+ function parseFrontmatterOverrides(markdown) {
107
+ const parsed = matter(markdown);
108
+ if (!parsed.data || typeof parsed.data !== "object") {
109
+ return {};
110
+ }
111
+ const data = parsed.data;
112
+ let strategy;
113
+ if (data.mcp_strategy) {
114
+ strategy = parseStrategy(data.mcp_strategy);
115
+ }
116
+ else if (data.mcp_chunking_hint) {
117
+ strategy = {
118
+ chunk_by: parseChunkBy(data.mcp_chunking_hint)
119
+ };
120
+ }
121
+ let metadata;
122
+ if (data.metadata) {
123
+ metadata = parseMetadata(data.metadata, "metadata");
124
+ }
125
+ if (data.mcp_metadata) {
126
+ metadata = {
127
+ ...(metadata ?? {}),
128
+ ...parseMetadata(data.mcp_metadata, "mcp_metadata")
129
+ };
130
+ }
131
+ const result = {};
132
+ if (strategy) {
133
+ result.strategy = strategy;
134
+ }
135
+ if (metadata) {
136
+ result.metadata = metadata;
137
+ }
138
+ return result;
139
+ }
140
+ /**
141
+ * Scans markdown for an HTML comment chunking hint of the form:
142
+ * <!-- mcp_chunking_hint: {"chunk_by": "h3"} -->
143
+ *
144
+ * Returns a partial strategy override (just `chunk_by`) if found and valid,
145
+ * or undefined if no hint is present or parsing fails.
146
+ */
147
+ export function parseHtmlChunkingHint(markdown) {
148
+ const match = HTML_HINT_REGEX.exec(markdown);
149
+ if (!match) {
150
+ return undefined;
151
+ }
152
+ const jsonStr = match[1];
153
+ if (!jsonStr) {
154
+ return undefined;
155
+ }
156
+ try {
157
+ const parsed = JSON.parse(jsonStr);
158
+ if (parsed.chunk_by !== undefined) {
159
+ const chunkBy = parseChunkBy(parsed.chunk_by);
160
+ return { chunk_by: chunkBy };
161
+ }
162
+ return undefined;
163
+ }
164
+ catch {
165
+ return undefined;
166
+ }
167
+ }
168
+ function parseOverrides(value) {
169
+ if (!Array.isArray(value)) {
170
+ throw new Error("manifest.overrides must be an array");
171
+ }
172
+ return value.map((entry, index) => {
173
+ if (!entry || typeof entry !== "object") {
174
+ throw new Error(`manifest.overrides[${index}] must be an object`);
175
+ }
176
+ const override = entry;
177
+ if (typeof override.pattern !== "string" || !override.pattern.trim()) {
178
+ throw new Error(`manifest.overrides[${index}].pattern must be a non-empty string`);
179
+ }
180
+ const parsed = {
181
+ pattern: override.pattern.trim()
182
+ };
183
+ if (override.strategy) {
184
+ parsed.strategy = parseStrategy(override.strategy);
185
+ }
186
+ if (override.metadata) {
187
+ parsed.metadata = parseMetadata(override.metadata, `manifest.overrides[${index}].metadata`);
188
+ }
189
+ return parsed;
190
+ });
191
+ }
192
+ function parseStrategy(value) {
193
+ if (!value || typeof value !== "object") {
194
+ throw new Error("strategy must be an object");
195
+ }
196
+ const strategy = value;
197
+ const chunkBy = parseChunkBy(strategy.chunk_by);
198
+ const maxChunkSize = strategy.max_chunk_size;
199
+ const minChunkSize = strategy.min_chunk_size;
200
+ const parsed = {
201
+ chunk_by: chunkBy
202
+ };
203
+ if (maxChunkSize !== undefined) {
204
+ parsed.max_chunk_size = asPositiveInteger(maxChunkSize, "max_chunk_size");
205
+ }
206
+ if (minChunkSize !== undefined) {
207
+ parsed.min_chunk_size = asPositiveInteger(minChunkSize, "min_chunk_size");
208
+ }
209
+ return parsed;
210
+ }
211
+ function parseChunkBy(value) {
212
+ if (value !== "h1" && value !== "h2" && value !== "h3" && value !== "file") {
213
+ throw new Error("chunk_by must be one of: h1, h2, h3, file");
214
+ }
215
+ return value;
216
+ }
217
+ function parseMetadata(value, fieldName) {
218
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
219
+ throw new Error(`${fieldName} must be an object`);
220
+ }
221
+ const metadata = value;
222
+ const normalized = {};
223
+ for (const [rawKey, rawValue] of Object.entries(metadata)) {
224
+ const key = rawKey.trim();
225
+ if (!key) {
226
+ throw new Error(`${fieldName} contains an empty key`);
227
+ }
228
+ if (typeof rawValue !== "string") {
229
+ throw new Error(`${fieldName}.${key} must be a string`);
230
+ }
231
+ const val = rawValue.trim();
232
+ if (!val) {
233
+ throw new Error(`${fieldName}.${key} cannot be empty`);
234
+ }
235
+ normalized[key] = val;
236
+ }
237
+ return normalized;
238
+ }
239
+ function asPositiveInteger(value, fieldName) {
240
+ if (!Number.isInteger(value) || value <= 0) {
241
+ throw new Error(`${fieldName} must be a positive integer`);
242
+ }
243
+ return value;
244
+ }
245
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { CorpusMetadata } from "./types.js";
2
+ export interface NormalizeMetadataOptions {
3
+ supportedMajor?: number;
4
+ }
5
+ export declare function normalizeMetadata(input: unknown, options?: NormalizeMetadataOptions): CorpusMetadata;
6
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAoC,MAAM,YAAY,CAAC;AASnF,MAAM,WAAW,wBAAwB;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,wBAA6B,GACrC,cAAc,CAiChB"}
@@ -0,0 +1,152 @@
1
+ import semver from "semver";
2
+ const LIMITS = {
3
+ maxKeys: 64,
4
+ maxKeyLength: 64,
5
+ maxValuesPerKey: 512,
6
+ maxValueLength: 128
7
+ };
8
+ export function normalizeMetadata(input, options = {}) {
9
+ if (!input || typeof input !== "object") {
10
+ throw new Error("metadata must be an object");
11
+ }
12
+ const metadata = input;
13
+ const supportedMajor = options.supportedMajor ?? 1;
14
+ const metadataVersion = asNonEmptyString(metadata.metadata_version, "metadata_version");
15
+ if (!semver.valid(metadataVersion)) {
16
+ throw new Error("metadata_version must be valid semver");
17
+ }
18
+ const parsed = semver.parse(metadataVersion);
19
+ if (!parsed || parsed.major !== supportedMajor) {
20
+ throw new Error(`Unsupported metadata_version major: expected ${supportedMajor}.x.x, got ${metadataVersion}`);
21
+ }
22
+ const corpusDescription = asNonEmptyString(metadata.corpus_description, "corpus_description");
23
+ const taxonomy = normalizeTaxonomy(metadata.taxonomy);
24
+ const stats = normalizeStats(metadata.stats);
25
+ const embedding = normalizeEmbedding(metadata.embedding);
26
+ return {
27
+ metadata_version: metadataVersion,
28
+ corpus_description: corpusDescription,
29
+ taxonomy,
30
+ stats,
31
+ embedding
32
+ };
33
+ }
34
+ function normalizeTaxonomy(value) {
35
+ if (!value || typeof value !== "object") {
36
+ throw new Error("taxonomy must be an object");
37
+ }
38
+ const raw = value;
39
+ const entries = Object.entries(raw);
40
+ if (entries.length > LIMITS.maxKeys) {
41
+ throw new Error(`taxonomy has too many keys (max ${LIMITS.maxKeys})`);
42
+ }
43
+ const normalized = {};
44
+ for (const [rawKey, rawField] of entries) {
45
+ const key = rawKey.trim();
46
+ if (!key) {
47
+ throw new Error("taxonomy keys cannot be empty");
48
+ }
49
+ if (key.length > LIMITS.maxKeyLength) {
50
+ throw new Error(`taxonomy key '${key}' exceeds max length ${LIMITS.maxKeyLength}`);
51
+ }
52
+ if (!rawField || typeof rawField !== "object") {
53
+ throw new Error(`taxonomy field '${key}' must be an object`);
54
+ }
55
+ const field = rawField;
56
+ const values = normalizeValues(field.values, key);
57
+ const description = field.description === undefined ? undefined : asTrimmedString(field.description);
58
+ normalized[key] = description
59
+ ? { description, values }
60
+ : { values };
61
+ }
62
+ return normalized;
63
+ }
64
+ function normalizeValues(value, key) {
65
+ if (!Array.isArray(value)) {
66
+ throw new Error(`taxonomy['${key}'].values must be an array`);
67
+ }
68
+ if (value.length > LIMITS.maxValuesPerKey) {
69
+ throw new Error(`taxonomy['${key}'].values exceeds max length ${LIMITS.maxValuesPerKey}`);
70
+ }
71
+ const deduped = new Set();
72
+ for (const raw of value) {
73
+ const normalized = asTrimmedString(raw);
74
+ if (!normalized) {
75
+ throw new Error(`taxonomy['${key}'].values cannot include empty strings`);
76
+ }
77
+ if (normalized.length > LIMITS.maxValueLength) {
78
+ throw new Error(`taxonomy['${key}'].value '${normalized}' exceeds max length ${LIMITS.maxValueLength}`);
79
+ }
80
+ deduped.add(normalized);
81
+ }
82
+ return [...deduped].sort((a, b) => a.localeCompare(b));
83
+ }
84
+ function normalizeStats(value) {
85
+ if (!value || typeof value !== "object") {
86
+ throw new Error("stats must be an object");
87
+ }
88
+ const stats = value;
89
+ const totalChunks = asPositiveInteger(stats.total_chunks, "stats.total_chunks", true);
90
+ const totalFiles = asPositiveInteger(stats.total_files, "stats.total_files", true);
91
+ const indexedAt = asNonEmptyString(stats.indexed_at, "stats.indexed_at");
92
+ const sourceCommitRaw = stats.source_commit;
93
+ let sourceCommit;
94
+ if (sourceCommitRaw === undefined) {
95
+ sourceCommit = undefined;
96
+ }
97
+ else if (sourceCommitRaw === null) {
98
+ sourceCommit = null;
99
+ }
100
+ else {
101
+ sourceCommit = asTrimmedString(sourceCommitRaw);
102
+ if (!/^[a-f0-9]{40}$/.test(sourceCommit)) {
103
+ throw new Error("stats.source_commit must be a 40-char lowercase SHA-1");
104
+ }
105
+ }
106
+ const result = {
107
+ total_chunks: totalChunks,
108
+ total_files: totalFiles,
109
+ indexed_at: indexedAt
110
+ };
111
+ if (sourceCommit !== undefined) {
112
+ result.source_commit = sourceCommit;
113
+ }
114
+ return result;
115
+ }
116
+ function normalizeEmbedding(value) {
117
+ if (value === null || value === undefined) {
118
+ return null;
119
+ }
120
+ if (typeof value !== "object") {
121
+ throw new Error("embedding must be null or an object");
122
+ }
123
+ const embedding = value;
124
+ const provider = asNonEmptyString(embedding.provider, "embedding.provider");
125
+ const model = asNonEmptyString(embedding.model, "embedding.model");
126
+ const dimensions = asPositiveInteger(embedding.dimensions, "embedding.dimensions", false);
127
+ return { provider, model, dimensions };
128
+ }
129
+ function asTrimmedString(value) {
130
+ if (typeof value !== "string") {
131
+ throw new Error("expected string");
132
+ }
133
+ return value.trim();
134
+ }
135
+ function asNonEmptyString(value, fieldName) {
136
+ const normalized = asTrimmedString(value);
137
+ if (!normalized) {
138
+ throw new Error(`${fieldName} must be a non-empty string`);
139
+ }
140
+ return normalized;
141
+ }
142
+ function asPositiveInteger(value, fieldName, allowZero) {
143
+ if (!Number.isInteger(value)) {
144
+ throw new Error(`${fieldName} must be an integer`);
145
+ }
146
+ const min = allowZero ? 0 : 1;
147
+ if (value < min) {
148
+ throw new Error(`${fieldName} must be >= ${min}`);
149
+ }
150
+ return value;
151
+ }
152
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { Root } from "mdast";
2
+ /**
3
+ * Parse a markdown string into an mdast AST tree.
4
+ */
5
+ export declare function parseMarkdown(content: string): Root;
6
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAOlC;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEnD"}
package/dist/parser.js ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Markdown AST parser using unified + remark-parse + remark-frontmatter + remark-gfm.
3
+ *
4
+ * Supports YAML frontmatter and GitHub Flavored Markdown extensions
5
+ * (tables, task lists, strikethrough, autolinks).
6
+ */
7
+ import { unified } from "unified";
8
+ import remarkParse from "remark-parse";
9
+ import remarkFrontmatter from "remark-frontmatter";
10
+ import remarkGfm from "remark-gfm";
11
+ const processor = unified()
12
+ .use(remarkParse)
13
+ .use(remarkFrontmatter, ["yaml"])
14
+ .use(remarkGfm);
15
+ /**
16
+ * Parse a markdown string into an mdast AST tree.
17
+ */
18
+ export function parseMarkdown(content) {
19
+ return processor.parse(content);
20
+ }
21
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,iBAAiB,MAAM,oBAAoB,CAAC;AACnD,OAAO,SAAS,MAAM,YAAY,CAAC;AAGnC,MAAM,SAAS,GAAG,OAAO,EAAE;KACxB,GAAG,CAAC,WAAW,CAAC;KAChB,GAAG,CAAC,iBAAiB,EAAE,CAAC,MAAM,CAAC,CAAC;KAChC,GAAG,CAAC,SAAS,CAAC,CAAC;AAElB;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare function clampLimit(limit: number | undefined): number;
2
+ export declare function isChunkIdFormat(value: string): boolean;
3
+ export declare function normalizeSearchText(value: string): string;
4
+ export declare function tokenizeSearchText(value: string): string[];
5
+ export declare function makeSnippet(content: string, query: string): string;
6
+ export declare function matchesMetadataFilters(metadata: Record<string, string>, filters: Record<string, string>, taxonomyKeys?: string[]): boolean;
7
+ //# sourceMappingURL=search-common.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-common.d.ts","sourceRoot":"","sources":["../src/search-common.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAM5D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAK1D;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAsBlE;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,OAAO,CA0CT"}
@@ -0,0 +1,81 @@
1
+ const DEFAULT_LIMIT = 10;
2
+ const MAX_LIMIT = 50;
3
+ export function clampLimit(limit) {
4
+ if (limit === undefined || !Number.isInteger(limit)) {
5
+ return DEFAULT_LIMIT;
6
+ }
7
+ return Math.max(1, Math.min(MAX_LIMIT, limit));
8
+ }
9
+ export function isChunkIdFormat(value) {
10
+ return /^(?!\s)([^#\s]+)(#[^#\s]+)?$/.test(value);
11
+ }
12
+ export function normalizeSearchText(value) {
13
+ return value.toLowerCase().replace(/\s+/g, " ").trim();
14
+ }
15
+ export function tokenizeSearchText(value) {
16
+ return value
17
+ .split(/[^a-z0-9]+/g)
18
+ .map((entry) => entry.trim())
19
+ .filter(Boolean);
20
+ }
21
+ export function makeSnippet(content, query) {
22
+ const normalized = normalizeSearchText(content);
23
+ const terms = tokenizeSearchText(normalizeSearchText(query));
24
+ if (normalized.length <= 220) {
25
+ return normalized;
26
+ }
27
+ let anchor = 0;
28
+ for (const term of terms) {
29
+ const index = normalized.indexOf(term);
30
+ if (index >= 0) {
31
+ anchor = index;
32
+ break;
33
+ }
34
+ }
35
+ const start = Math.max(0, anchor - 60);
36
+ const end = Math.min(normalized.length, start + 220);
37
+ const prefix = start > 0 ? "..." : "";
38
+ const suffix = end < normalized.length ? "..." : "";
39
+ return `${prefix}${normalized.slice(start, end).trim()}${suffix}`;
40
+ }
41
+ export function matchesMetadataFilters(metadata, filters, taxonomyKeys) {
42
+ const language = filters.language;
43
+ const scope = filters.scope;
44
+ // Only apply the scope/language auto-include expansion when both keys exist
45
+ // in the taxonomy (or when taxonomyKeys is not provided, for backwards compatibility).
46
+ const hasScope = !taxonomyKeys || taxonomyKeys.includes("scope");
47
+ const hasLanguage = !taxonomyKeys || taxonomyKeys.includes("language");
48
+ if (hasScope && hasLanguage && language && !scope) {
49
+ const chunkScope = metadata.scope;
50
+ const chunkLanguage = metadata.language;
51
+ if (chunkScope === "sdk-specific") {
52
+ if (chunkLanguage !== language) {
53
+ return false;
54
+ }
55
+ }
56
+ else if (chunkScope === "global-guide") {
57
+ // Auto-include global guides.
58
+ }
59
+ else if (chunkLanguage && chunkLanguage !== language) {
60
+ return false;
61
+ }
62
+ }
63
+ else {
64
+ if (language && metadata.language !== language) {
65
+ return false;
66
+ }
67
+ if (scope && metadata.scope !== scope) {
68
+ return false;
69
+ }
70
+ }
71
+ for (const [key, value] of Object.entries(filters)) {
72
+ if (key === "language" || key === "scope") {
73
+ continue;
74
+ }
75
+ if (metadata[key] !== value) {
76
+ return false;
77
+ }
78
+ }
79
+ return true;
80
+ }
81
+ //# sourceMappingURL=search-common.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-common.js","sourceRoot":"","sources":["../src/search-common.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Chunk, DocsIndexOptions, GetDocRequest, GetDocResult, SearchEngine, SearchRequest, SearchResult } from "./types.js";
2
+ export declare class InMemorySearchEngine implements SearchEngine {
3
+ private readonly chunks;
4
+ private readonly byId;
5
+ private readonly byFile;
6
+ private readonly proximityWeight;
7
+ constructor(chunks: Chunk[], options?: DocsIndexOptions);
8
+ search(request: SearchRequest): Promise<SearchResult>;
9
+ getDoc(request: GetDocRequest): Promise<GetDocResult>;
10
+ }
11
+ export declare class DocsIndex extends InMemorySearchEngine {
12
+ }
13
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,KAAK,EACL,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,YAAY,EAGZ,aAAa,EACb,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,qBAAa,oBAAqB,YAAW,YAAY;IACvD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqB;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAE7B,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,GAAE,gBAAqB;IAiBrD,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IA4CrD,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;CA8C5D;AAGD,qBAAa,SAAU,SAAQ,oBAAoB;CAAG"}