@neottia/searchable-core 0.2.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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +5 -0
  3. package/README.md +71 -0
  4. package/config.schema.json +246 -0
  5. package/dist/config.d.ts +423 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +343 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/errors.d.ts +32 -0
  10. package/dist/errors.d.ts.map +1 -0
  11. package/dist/errors.js +41 -0
  12. package/dist/errors.js.map +1 -0
  13. package/dist/extraction-worker.d.ts +2 -0
  14. package/dist/extraction-worker.d.ts.map +1 -0
  15. package/dist/extraction-worker.js +38 -0
  16. package/dist/extraction-worker.js.map +1 -0
  17. package/dist/fetcher.d.ts +5 -0
  18. package/dist/fetcher.d.ts.map +1 -0
  19. package/dist/fetcher.js +173 -0
  20. package/dist/fetcher.js.map +1 -0
  21. package/dist/http.d.ts +54 -0
  22. package/dist/http.d.ts.map +1 -0
  23. package/dist/http.js +372 -0
  24. package/dist/http.js.map +1 -0
  25. package/dist/index.d.ts +14 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +14 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/migration-worker.d.ts +2 -0
  30. package/dist/migration-worker.d.ts.map +1 -0
  31. package/dist/migration-worker.js +60 -0
  32. package/dist/migration-worker.js.map +1 -0
  33. package/dist/migration.d.ts +19 -0
  34. package/dist/migration.d.ts.map +1 -0
  35. package/dist/migration.js +221 -0
  36. package/dist/migration.js.map +1 -0
  37. package/dist/providers.d.ts +9 -0
  38. package/dist/providers.d.ts.map +1 -0
  39. package/dist/providers.js +210 -0
  40. package/dist/providers.js.map +1 -0
  41. package/dist/redaction.d.ts +9 -0
  42. package/dist/redaction.d.ts.map +1 -0
  43. package/dist/redaction.js +161 -0
  44. package/dist/redaction.js.map +1 -0
  45. package/dist/runtime.d.ts +20 -0
  46. package/dist/runtime.d.ts.map +1 -0
  47. package/dist/runtime.js +205 -0
  48. package/dist/runtime.js.map +1 -0
  49. package/dist/schemas.d.ts +49 -0
  50. package/dist/schemas.d.ts.map +1 -0
  51. package/dist/schemas.js +64 -0
  52. package/dist/schemas.js.map +1 -0
  53. package/dist/services.d.ts +20 -0
  54. package/dist/services.d.ts.map +1 -0
  55. package/dist/services.js +2 -0
  56. package/dist/services.js.map +1 -0
  57. package/dist/stash.d.ts +65 -0
  58. package/dist/stash.d.ts.map +1 -0
  59. package/dist/stash.js +490 -0
  60. package/dist/stash.js.map +1 -0
  61. package/dist/tool-contracts.d.ts +104 -0
  62. package/dist/tool-contracts.d.ts.map +1 -0
  63. package/dist/tool-contracts.js +71 -0
  64. package/dist/tool-contracts.js.map +1 -0
  65. package/dist/tools.d.ts +23 -0
  66. package/dist/tools.d.ts.map +1 -0
  67. package/dist/tools.js +134 -0
  68. package/dist/tools.js.map +1 -0
  69. package/dist/utf8.d.ts +2 -0
  70. package/dist/utf8.d.ts.map +1 -0
  71. package/dist/utf8.js +14 -0
  72. package/dist/utf8.js.map +1 -0
  73. package/dist/worker.d.ts +12 -0
  74. package/dist/worker.d.ts.map +1 -0
  75. package/dist/worker.js +45 -0
  76. package/dist/worker.js.map +1 -0
  77. package/package.json +63 -0
@@ -0,0 +1,14 @@
1
+ export * from './config.js';
2
+ export * from './errors.js';
3
+ export * from './fetcher.js';
4
+ export * from './http.js';
5
+ export * from './migration.js';
6
+ export * from './providers.js';
7
+ export * from './redaction.js';
8
+ export * from './runtime.js';
9
+ export * from './schemas.js';
10
+ export * from './services.js';
11
+ export * from './stash.js';
12
+ export * from './tool-contracts.js';
13
+ export * from './tools.js';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ export * from './config.js';
2
+ export * from './errors.js';
3
+ export * from './fetcher.js';
4
+ export * from './http.js';
5
+ export * from './migration.js';
6
+ export * from './providers.js';
7
+ export * from './redaction.js';
8
+ export * from './runtime.js';
9
+ export * from './schemas.js';
10
+ export * from './services.js';
11
+ export * from './stash.js';
12
+ export * from './tool-contracts.js';
13
+ export * from './tools.js';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=migration-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-worker.d.ts","sourceRoot":"","sources":["../src/migration-worker.ts"],"names":[],"mappings":""}
@@ -0,0 +1,60 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ import { parentPort, workerData } from 'node:worker_threads';
3
+ import { SearchableError } from './errors.js';
4
+ import { normalizeStashUrl } from './stash.js';
5
+ function readRows(input) {
6
+ const database = new DatabaseSync(input.path, { readOnly: true });
7
+ try {
8
+ const integrity = database.prepare('PRAGMA integrity_check').get();
9
+ if (!integrity || Object.values(integrity)[0] !== 'ok')
10
+ throw new SearchableError('service', 'LEGACY_DATABASE_INVALID', 'The legacy database failed integrity_check.');
11
+ const columns = database.prepare("PRAGMA table_info('pages')").all();
12
+ const names = new Set(columns.map((column) => column['name']));
13
+ if (!['url', 'title', 'content'].every((name) => names.has(name)))
14
+ throw new SearchableError('service', 'LEGACY_DATABASE_INVALID', 'The legacy pages table has an unsupported schema.');
15
+ const statement = database.prepare('SELECT url,title,content FROM pages ORDER BY url');
16
+ const rows = [];
17
+ let aggregate = 0;
18
+ for (const raw of statement.iterate()) {
19
+ if (rows.length >= 10_000)
20
+ throw new SearchableError('resource_limit', 'LEGACY_DATABASE_TOO_LARGE', 'The legacy database has too many pages.');
21
+ if (typeof raw['url'] !== 'string' || typeof raw['title'] !== 'string' || typeof raw['content'] !== 'string')
22
+ throw new SearchableError('service', 'LEGACY_DATABASE_INVALID', 'A legacy page has invalid fields.');
23
+ const row = {
24
+ url: normalizeStashUrl(raw['url']),
25
+ title: raw['title'].trim(),
26
+ content: raw['content'],
27
+ };
28
+ if (!row.title || !row.content.trim())
29
+ throw new SearchableError('service', 'LEGACY_DATABASE_INVALID', 'A legacy page has blank title or content.');
30
+ if (Buffer.byteLength(row.url, 'utf8') > input.limits.maxUrlBytes)
31
+ throw tooLarge('A legacy URL exceeds max_url_bytes.');
32
+ if (Buffer.byteLength(row.title, 'utf8') > input.limits.maxTitleBytes)
33
+ throw tooLarge('A legacy title exceeds max_title_bytes.');
34
+ if (Buffer.byteLength(row.content, 'utf8') > input.limits.maxContentBytes)
35
+ throw tooLarge('Legacy content exceeds max_content_bytes.');
36
+ aggregate += Buffer.byteLength(JSON.stringify(row), 'utf8');
37
+ if (aggregate > input.limits.maxStorageBytes)
38
+ throw tooLarge('Legacy page content exceeds max_storage_bytes.');
39
+ rows.push(row);
40
+ }
41
+ return rows;
42
+ }
43
+ finally {
44
+ database.close();
45
+ }
46
+ }
47
+ function tooLarge(message) {
48
+ return new SearchableError('resource_limit', 'LEGACY_DATABASE_TOO_LARGE', message);
49
+ }
50
+ try {
51
+ const rows = readRows(workerData);
52
+ parentPort?.postMessage({ ok: true, rows });
53
+ }
54
+ catch (error) {
55
+ const failure = error instanceof SearchableError
56
+ ? { ok: false, code: error.code, message: error.message }
57
+ : { ok: false, code: 'LEGACY_DATABASE_INVALID', message: 'The legacy database could not be read.' };
58
+ parentPort?.postMessage(failure);
59
+ }
60
+ //# sourceMappingURL=migration-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-worker.js","sourceRoot":"","sources":["../src/migration-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { SearchableOperationContext } from './services.js';
2
+ import { type SearchableStore } from './stash.js';
3
+ export interface LegacyImportOptions {
4
+ readonly path: string;
5
+ readonly preview?: boolean;
6
+ readonly signal?: AbortSignal;
7
+ readonly deadline?: number;
8
+ }
9
+ export interface LegacyImportReport {
10
+ readonly preview: boolean;
11
+ readonly valid: boolean;
12
+ readonly planned: number;
13
+ readonly imported: number;
14
+ readonly conflicts: readonly string[];
15
+ readonly warnings: readonly string[];
16
+ readonly errors: readonly string[];
17
+ }
18
+ export declare function importLegacySearchableDatabase(store: SearchableStore, options: LegacyImportOptions, context?: SearchableOperationContext): Promise<LegacyImportReport>;
19
+ //# sourceMappingURL=migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../src/migration.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAA0C,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAO1F,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAE9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAGD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAkBD,wBAAsB,8BAA8B,CAClD,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE,mBAAmB,EAC5B,OAAO,CAAC,EAAE,0BAA0B,GACnC,OAAO,CAAC,kBAAkB,CAAC,CAwE7B"}
@@ -0,0 +1,221 @@
1
+ import { constants, existsSync, lstatSync, mkdtempSync, rmSync } from 'node:fs';
2
+ import { open } from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import { dirname, isAbsolute, relative, resolve } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { Worker } from 'node:worker_threads';
7
+ import { SearchableError } from './errors.js';
8
+ import { checkSearchableDeadline, createSearchableDeadline, remainingSearchableDeadline, } from './http.js';
9
+ import { pageId } from './stash.js';
10
+ import { runBoundedWorker } from './worker.js';
11
+ const MIGRATION_TIMEOUT_MS = 60_000;
12
+ const COPY_CHUNK_BYTES = 64 * 1024;
13
+ export async function importLegacySearchableDatabase(store, options, context) {
14
+ const preview = options.preview ?? true;
15
+ const signal = options.signal ?? context?.signal;
16
+ const epochDeadline = options.deadline ?? context?.deadline;
17
+ const requestedDeadline = createSearchableDeadline(MIGRATION_TIMEOUT_MS, epochDeadline);
18
+ const deadline = context?.transportDeadline
19
+ ? { expiresAt: Math.min(context.transportDeadline.expiresAt, requestedDeadline.expiresAt) }
20
+ : requestedDeadline;
21
+ let source;
22
+ try {
23
+ checkControl(signal, deadline);
24
+ const path = projectPath(store.cwd, options.path);
25
+ source = await openLegacySource(path);
26
+ const identity = await safeLegacyIdentity(source, store.config.security.limits.max_storage_bytes);
27
+ await assertSourceIdentity(source, path, identity);
28
+ rejectSidecars(path);
29
+ const directory = mkdtempSync(resolve(tmpdir(), 'neottia-searchable-import-'));
30
+ const snapshot = resolve(directory, 'legacy.sqlite');
31
+ try {
32
+ await copyLegacySnapshot(source, snapshot, store.config.security.limits.max_storage_bytes, signal, deadline);
33
+ await assertSourceIdentity(source, path, identity);
34
+ const rows = await readLegacyRows(snapshot, store.config, signal, deadline);
35
+ const duplicates = duplicateUrls(rows);
36
+ if (duplicates.length)
37
+ return report(preview, false, rows.length, 0, duplicates, [], ['The legacy database contains duplicate normalized URLs.']);
38
+ await assertSourceIdentity(source, path, identity);
39
+ const imported = await store.importPages(rows, preview, {
40
+ cwd: context?.cwd ?? store.cwd,
41
+ config: context?.config ?? store.config,
42
+ ...(signal === undefined ? {} : { signal }),
43
+ ...(epochDeadline === undefined ? {} : { deadline: epochDeadline }),
44
+ transportDeadline: deadline,
45
+ ...(context?.onStaleCache === undefined ? {} : { onStaleCache: context.onStaleCache }),
46
+ });
47
+ return report(preview, imported.conflicts.length === 0, imported.planned, imported.imported, imported.conflicts, [
48
+ ...imported.warnings,
49
+ ...(imported.existing.length
50
+ ? [`${imported.existing.length} legacy page(s) already match canonical records.`]
51
+ : []),
52
+ ], imported.conflicts.length ? ['Canonical conflicts must be resolved before import.'] : []);
53
+ }
54
+ finally {
55
+ rmSync(directory, { recursive: true, force: true });
56
+ }
57
+ }
58
+ catch (error) {
59
+ return report(preview, false, 0, 0, [], [], [error instanceof SearchableError ? error.message : 'Legacy import failed.']);
60
+ }
61
+ finally {
62
+ await source?.close();
63
+ }
64
+ }
65
+ async function openLegacySource(path) {
66
+ try {
67
+ return await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
68
+ }
69
+ catch {
70
+ throw new SearchableError('service', 'LEGACY_PATH_UNSAFE', 'The legacy database must be a regular singly-linked file.');
71
+ }
72
+ }
73
+ async function safeLegacyIdentity(source, maximumBytes) {
74
+ const stat = await source.stat();
75
+ if (!stat.isFile() || stat.nlink !== 1)
76
+ throw new SearchableError('service', 'LEGACY_PATH_UNSAFE', 'The legacy database must be a regular singly-linked file.');
77
+ if (stat.size > maximumBytes)
78
+ throw new SearchableError('resource_limit', 'LEGACY_DATABASE_TOO_LARGE', 'The legacy database exceeds max_storage_bytes.');
79
+ return {
80
+ dev: stat.dev,
81
+ ino: stat.ino,
82
+ size: stat.size,
83
+ mtimeMs: stat.mtimeMs,
84
+ ctimeMs: stat.ctimeMs,
85
+ };
86
+ }
87
+ async function copyLegacySnapshot(source, destinationPath, maximumBytes, signal, deadline) {
88
+ const destination = await open(destinationPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL, 0o600);
89
+ const buffer = Buffer.allocUnsafe(COPY_CHUNK_BYTES);
90
+ let offset = 0;
91
+ try {
92
+ while (true) {
93
+ checkControl(signal, deadline);
94
+ const { bytesRead } = await source.read(buffer, 0, buffer.byteLength, offset);
95
+ if (bytesRead === 0)
96
+ break;
97
+ offset += bytesRead;
98
+ if (offset > maximumBytes)
99
+ throw new SearchableError('resource_limit', 'LEGACY_DATABASE_TOO_LARGE', 'The legacy database exceeds max_storage_bytes.');
100
+ let written = 0;
101
+ while (written < bytesRead) {
102
+ checkControl(signal, deadline);
103
+ const result = await destination.write(buffer, written, bytesRead - written, offset - bytesRead + written);
104
+ written += result.bytesWritten;
105
+ }
106
+ }
107
+ await destination.sync();
108
+ }
109
+ finally {
110
+ await destination.close();
111
+ }
112
+ }
113
+ async function assertSourceIdentity(source, path, expected) {
114
+ const descriptor = await source.stat();
115
+ let pathname;
116
+ try {
117
+ pathname = lstatSync(path);
118
+ }
119
+ catch {
120
+ throw replacedSource();
121
+ }
122
+ if (!pathname.isFile() ||
123
+ pathname.isSymbolicLink() ||
124
+ pathname.nlink !== 1 ||
125
+ descriptor.nlink !== 1 ||
126
+ descriptor.dev !== expected.dev ||
127
+ descriptor.ino !== expected.ino ||
128
+ descriptor.size !== expected.size ||
129
+ descriptor.mtimeMs !== expected.mtimeMs ||
130
+ descriptor.ctimeMs !== expected.ctimeMs ||
131
+ pathname.dev !== expected.dev ||
132
+ pathname.ino !== expected.ino ||
133
+ pathname.size !== expected.size ||
134
+ pathname.mtimeMs !== expected.mtimeMs ||
135
+ pathname.ctimeMs !== expected.ctimeMs)
136
+ throw replacedSource();
137
+ }
138
+ function replacedSource() {
139
+ return new SearchableError('service', 'LEGACY_SOURCE_REPLACED', 'The legacy database changed while it was read.');
140
+ }
141
+ async function readLegacyRows(path, config, signal, deadline) {
142
+ checkControl(signal, deadline);
143
+ const localWorker = new URL('./migration-worker.js', import.meta.url);
144
+ const workerUrl = existsSync(fileURLToPath(localWorker))
145
+ ? localWorker
146
+ : new URL('../dist/migration-worker.js', import.meta.url);
147
+ const worker = new Worker(workerUrl, {
148
+ workerData: {
149
+ path,
150
+ limits: {
151
+ maxUrlBytes: config.security.limits.max_url_bytes,
152
+ maxTitleBytes: config.security.limits.max_title_bytes,
153
+ maxContentBytes: config.security.limits.max_content_bytes,
154
+ maxStorageBytes: config.security.limits.max_storage_bytes,
155
+ },
156
+ },
157
+ });
158
+ return runBoundedWorker(worker, {
159
+ ...(signal === undefined ? {} : { signal }),
160
+ timeoutMs: remainingSearchableDeadline(deadline),
161
+ cancellationError: () => new SearchableError('cancelled', 'OPERATION_CANCELLED', 'Searchable migration was cancelled.'),
162
+ timeoutError: deadlineError,
163
+ workerError: () => new SearchableError('service', 'LEGACY_DATABASE_INVALID', 'The legacy database worker failed.'),
164
+ decode(value) {
165
+ const message = value;
166
+ if (message.ok && Array.isArray(message.rows))
167
+ return message.rows;
168
+ throw new SearchableError(message.code === 'LEGACY_DATABASE_TOO_LARGE' ? 'resource_limit' : 'service', message.code ?? 'LEGACY_DATABASE_INVALID', message.message ?? 'The legacy database could not be read.');
169
+ },
170
+ });
171
+ }
172
+ function projectPath(cwd, value) {
173
+ if (!value || isAbsolute(value))
174
+ throw new SearchableError('validation', 'LEGACY_PATH_INVALID', 'The legacy path must be project-relative.');
175
+ const root = resolve(cwd);
176
+ const path = resolve(root, value);
177
+ const nested = relative(root, path);
178
+ if (!nested || nested === '..' || nested.startsWith('../') || dirname(nested) !== '.')
179
+ throw new SearchableError('validation', 'LEGACY_PATH_INVALID', 'The legacy database must be a direct child of the project root.');
180
+ return path;
181
+ }
182
+ function rejectSidecars(path) {
183
+ for (const suffix of ['-wal', '-shm'])
184
+ try {
185
+ lstatSync(`${path}${suffix}`);
186
+ throw new SearchableError('service', 'LEGACY_DATABASE_BUSY', 'Stop the legacy server and remove live WAL/SHM state before import.');
187
+ }
188
+ catch (error) {
189
+ if (error instanceof SearchableError)
190
+ throw error;
191
+ if (!(error instanceof Error) || !('code' in error) || error.code !== 'ENOENT')
192
+ throw error;
193
+ }
194
+ }
195
+ function duplicateUrls(rows) {
196
+ const seen = new Set();
197
+ const duplicates = new Set();
198
+ for (const row of rows) {
199
+ if (seen.has(row.url))
200
+ duplicates.add(pageId(row.url));
201
+ seen.add(row.url);
202
+ }
203
+ return [...duplicates].slice(0, 100);
204
+ }
205
+ function report(preview, valid, planned, imported, conflicts, warnings, errors) {
206
+ return { preview, valid, planned, imported, conflicts, warnings, errors };
207
+ }
208
+ function checkControl(signal, deadline) {
209
+ try {
210
+ checkSearchableDeadline(deadline, signal);
211
+ }
212
+ catch (error) {
213
+ if (signal?.aborted)
214
+ throw new SearchableError('cancelled', 'OPERATION_CANCELLED', 'Searchable migration was cancelled.');
215
+ throw error;
216
+ }
217
+ }
218
+ function deadlineError() {
219
+ return new SearchableError('service', 'DEADLINE_EXCEEDED', 'Searchable migration exceeded its deadline.');
220
+ }
221
+ //# sourceMappingURL=migration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration.js","sourceRoot":"","sources":["../src/migration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { type SearchableHttpTransport } from './http.js';
2
+ import type { SearchableOperationContext } from './services.js';
3
+ import type { ResolvedSearchableToolInput, SearchableToolOutput } from './tool-contracts.js';
4
+ export interface SearchProvider {
5
+ search(input: ResolvedSearchableToolInput<'web_search'>, context: SearchableOperationContext): Promise<SearchableToolOutput<'web_search'>>;
6
+ }
7
+ export declare function createSearchProvider(transport: SearchableHttpTransport, input: ResolvedSearchableToolInput<'web_search'>): SearchProvider;
8
+ export declare function searchProvider(transport: SearchableHttpTransport, input: ResolvedSearchableToolInput<'web_search'>, context: SearchableOperationContext): Promise<SearchableToolOutput<'web_search'>>;
9
+ //# sourceMappingURL=providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAEA,OAAO,EAA4B,KAAK,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAEnF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,KAAK,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAG7F,MAAM,WAAW,cAAc;IAC7B,MAAM,CACJ,KAAK,EAAE,2BAA2B,CAAC,YAAY,CAAC,EAChD,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC,CAAC;CAChD;AAGD,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,uBAAuB,EAClC,KAAK,EAAE,2BAA2B,CAAC,YAAY,CAAC,GAC/C,cAAc,CAIhB;AAGD,wBAAsB,cAAc,CAClC,SAAS,EAAE,uBAAuB,EAClC,KAAK,EAAE,2BAA2B,CAAC,YAAY,CAAC,EAChD,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC,CA2E7C"}
@@ -0,0 +1,210 @@
1
+ import { JSDOM } from 'jsdom';
2
+ import { SearchableError } from './errors.js';
3
+ import { createSearchableDeadline } from './http.js';
4
+ import { containsCredential } from './redaction.js';
5
+ export function createSearchProvider(transport, input) {
6
+ return {
7
+ search: async (_resolved, context) => searchProvider(transport, input, context),
8
+ };
9
+ }
10
+ export async function searchProvider(transport, input, context) {
11
+ const deadline = context.transportDeadline ?? createSearchableDeadline(context.config.search.timeout_ms, context.deadline);
12
+ const maximumBytes = Math.min(context.config.fetch.max_response_bytes, context.config.security.limits.max_result_bytes);
13
+ let results;
14
+ if (input.provider === 'duckduckgo') {
15
+ const body = new URLSearchParams({ q: input.query }).toString();
16
+ const response = await transport.request({
17
+ url: new URL('https://html.duckduckgo.com/html/'),
18
+ method: 'POST',
19
+ headers: { 'content-type': 'application/x-www-form-urlencoded', 'user-agent': 'Neottia Searchable/1' },
20
+ body: Buffer.from(body),
21
+ signal: context.signal,
22
+ deadline,
23
+ maximumBytes,
24
+ redirectPolicy: 'none',
25
+ });
26
+ assertProviderStatus(response.status, input.provider);
27
+ results = parseDuckDuckGo(Buffer.from(response.bytes).toString('utf8'));
28
+ }
29
+ else if (input.provider === 'google') {
30
+ const key = requireCredential(context.config.search.credentials.google_api_key, 'google_api_key', 'google');
31
+ const cx = requireCredential(context.config.search.credentials.google_cse_id, 'google_cse_id', 'google');
32
+ const url = new URL('https://www.googleapis.com/customsearch/v1');
33
+ url.search = new URLSearchParams({ key, cx, q: input.query, num: String(Math.min(input.limit, 10)) }).toString();
34
+ const response = await transport.request({
35
+ url,
36
+ signal: context.signal,
37
+ deadline,
38
+ maximumBytes,
39
+ redirectPolicy: 'none',
40
+ });
41
+ assertProviderStatus(response.status, input.provider);
42
+ results = parseJsonResults(response.bytes, input.provider, 'items');
43
+ }
44
+ else if (input.provider === 'bing') {
45
+ const key = requireCredential(context.config.search.credentials.bing_api_key, 'bing_api_key', 'bing');
46
+ const url = new URL(context.config.search.bing_api_endpoint);
47
+ if (url.protocol !== 'https:' || url.username || url.password)
48
+ throw new SearchableError('configuration', 'PROVIDER_ENDPOINT_INVALID', 'The Bing endpoint must be an HTTPS URL without user information.');
49
+ url.searchParams.set('q', input.query);
50
+ url.searchParams.set('count', String(Math.min(input.limit, 50)));
51
+ const response = await transport.request({
52
+ url,
53
+ headers: { 'Ocp-Apim-Subscription-Key': key },
54
+ signal: context.signal,
55
+ deadline,
56
+ maximumBytes,
57
+ redirectPolicy: 'none',
58
+ });
59
+ assertProviderStatus(response.status, input.provider);
60
+ results = parseBing(response.bytes);
61
+ }
62
+ else {
63
+ const key = requireCredential(context.config.search.credentials.brave_api_key, 'brave_api_key', 'brave');
64
+ const url = new URL('https://api.search.brave.com/res/v1/web/search');
65
+ url.search = new URLSearchParams({ q: input.query, count: String(Math.min(input.limit, 20)) }).toString();
66
+ const response = await transport.request({
67
+ url,
68
+ headers: { accept: 'application/json', 'x-subscription-token': key },
69
+ signal: context.signal,
70
+ deadline,
71
+ maximumBytes,
72
+ redirectPolicy: 'none',
73
+ });
74
+ assertProviderStatus(response.status, input.provider);
75
+ results = parseBrave(response.bytes);
76
+ }
77
+ const bounded = results.slice(0, input.limit);
78
+ rejectCredentialLeak(bounded, Object.values(context.config.search.credentials));
79
+ return { results: bounded };
80
+ }
81
+ function parseDuckDuckGo(html) {
82
+ const dom = new JSDOM(html);
83
+ try {
84
+ const results = [];
85
+ for (const node of dom.window.document.querySelectorAll('.result')) {
86
+ const link = node.querySelector('.result__a');
87
+ if (!link?.textContent || !link.href)
88
+ continue;
89
+ const redirect = new URL(link.href, 'https://html.duckduckgo.com');
90
+ const target = redirect.searchParams.get('uddg') ?? link.href;
91
+ const url = normalizeResultUrl(target);
92
+ if (!url)
93
+ continue;
94
+ results.push({
95
+ title: link.textContent.trim(),
96
+ url,
97
+ snippet: node.querySelector('.result__snippet')?.textContent?.trim() ?? '',
98
+ });
99
+ }
100
+ return results;
101
+ }
102
+ finally {
103
+ dom.window.close();
104
+ }
105
+ }
106
+ function parseJsonResults(bytes, provider, field) {
107
+ const root = parseJsonRecord(bytes, provider);
108
+ const values = Array.isArray(root[field]) ? root[field] : [];
109
+ return values.flatMap((entry) => {
110
+ if (!isRecord(entry))
111
+ return [];
112
+ const url = normalizeResultUrl(entry['link']);
113
+ return typeof entry['title'] === 'string' && url
114
+ ? [{ title: entry['title'], url, snippet: typeof entry['snippet'] === 'string' ? entry['snippet'] : '' }]
115
+ : [];
116
+ });
117
+ }
118
+ function parseBing(bytes) {
119
+ const root = parseJsonRecord(bytes, 'bing');
120
+ const webPages = isRecord(root['webPages']) ? root['webPages'] : {};
121
+ const values = Array.isArray(webPages['value']) ? webPages['value'] : [];
122
+ return values.flatMap((entry) => {
123
+ if (!isRecord(entry))
124
+ return [];
125
+ const url = normalizeResultUrl(entry['url']);
126
+ return typeof entry['name'] === 'string' && url
127
+ ? [{ title: entry['name'], url, snippet: typeof entry['snippet'] === 'string' ? entry['snippet'] : '' }]
128
+ : [];
129
+ });
130
+ }
131
+ function parseBrave(bytes) {
132
+ const root = parseJsonRecord(bytes, 'brave');
133
+ const web = isRecord(root['web']) ? root['web'] : {};
134
+ const values = Array.isArray(web['results']) ? web['results'] : [];
135
+ return values.flatMap((entry) => {
136
+ if (!isRecord(entry))
137
+ return [];
138
+ const url = normalizeResultUrl(entry['url']);
139
+ return typeof entry['title'] === 'string' && url
140
+ ? [
141
+ {
142
+ title: entry['title'],
143
+ url,
144
+ snippet: typeof entry['description'] === 'string'
145
+ ? entry['description']
146
+ : typeof entry['snippet'] === 'string'
147
+ ? entry['snippet']
148
+ : '',
149
+ },
150
+ ]
151
+ : [];
152
+ });
153
+ }
154
+ function parseJsonRecord(bytes, provider) {
155
+ try {
156
+ const value = JSON.parse(Buffer.from(bytes).toString('utf8'));
157
+ if (isRecord(value))
158
+ return value;
159
+ }
160
+ catch {
161
+ }
162
+ throw new SearchableError('service', 'PROVIDER_RESPONSE_INVALID', `The ${provider} response is not valid JSON.`);
163
+ }
164
+ function assertProviderStatus(status, provider) {
165
+ if (status >= 200 && status < 300)
166
+ return;
167
+ const code = status === 401 || status === 403
168
+ ? 'PROVIDER_AUTH_FAILED'
169
+ : status === 429
170
+ ? 'PROVIDER_RATE_LIMITED'
171
+ : 'PROVIDER_UNAVAILABLE';
172
+ throw new SearchableError('service', code, `The ${provider} provider returned HTTP ${status}.`, [], {
173
+ provider,
174
+ status,
175
+ });
176
+ }
177
+ function requireCredential(value, name, provider) {
178
+ if (!value)
179
+ throw new SearchableError('configuration', 'PROVIDER_CREDENTIAL_MISSING', `The ${provider} provider requires ${name}.`, [`search.credentials.${name}`]);
180
+ return value;
181
+ }
182
+ function normalizeResultUrl(value) {
183
+ if (typeof value !== 'string')
184
+ return undefined;
185
+ try {
186
+ const url = new URL(value);
187
+ return ['http:', 'https:'].includes(url.protocol) && !url.username && !url.password ? url.href : undefined;
188
+ }
189
+ catch {
190
+ return undefined;
191
+ }
192
+ }
193
+ function rejectCredentialLeak(value, credentials) {
194
+ const secrets = credentials.filter((credential) => Boolean(credential));
195
+ if (containsCredentialInValue(value, secrets))
196
+ throw new SearchableError('service', 'PROVIDER_RESPONSE_INVALID', 'The provider response contained a configured credential.');
197
+ }
198
+ function containsCredentialInValue(value, credentials) {
199
+ if (typeof value === 'string')
200
+ return containsCredential(value, credentials);
201
+ if (Array.isArray(value))
202
+ return value.some((entry) => containsCredentialInValue(entry, credentials));
203
+ if (!isRecord(value))
204
+ return false;
205
+ return Object.values(value).some((entry) => containsCredentialInValue(entry, credentials));
206
+ }
207
+ function isRecord(value) {
208
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
209
+ }
210
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { DeepReadonly } from '@neottia/config';
2
+ import type { SearchableConfig } from './config.js';
3
+ import { SearchableError } from './errors.js';
4
+ export declare function redactDiagnosticUrl(value: string): string;
5
+ export declare function redactDiagnosticText(value: string, credentials?: readonly string[]): string;
6
+ export declare function containsCredential(value: string, credentials: readonly string[]): boolean;
7
+ export declare function searchableCredentialValues(config: DeepReadonly<SearchableConfig>): readonly string[];
8
+ export declare function asRedactedSearchableError(error: unknown, config: DeepReadonly<SearchableConfig>): SearchableError;
9
+ //# sourceMappingURL=redaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redaction.d.ts","sourceRoot":"","sources":["../src/redaction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAa9C,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWzD;AAGD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,GAAE,SAAS,MAAM,EAAO,GAAG,MAAM,CAQ/F;AAGD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAMzF;AA4BD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,YAAY,CAAC,gBAAgB,CAAC,GAAG,SAAS,MAAM,EAAE,CAEpG;AAGD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,gBAAgB,CAAC,GAAG,eAAe,CA4BjH"}