@reqlan/analytical 0.6.3 → 0.8.1

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 (90) hide show
  1. package/README.md +30 -0
  2. package/out/analysis/fuzzy-search-analyser.d.ts +17 -0
  3. package/out/analysis/fuzzy-search-analyser.js +25 -0
  4. package/out/analysis/fuzzy-search-analyser.js.map +1 -0
  5. package/out/analysis/fuzzy-search-worker-client.d.ts +39 -0
  6. package/out/analysis/fuzzy-search-worker-client.js +178 -0
  7. package/out/analysis/fuzzy-search-worker-client.js.map +1 -0
  8. package/out/analysis/fuzzy-search-worker.d.ts +32 -0
  9. package/out/analysis/fuzzy-search-worker.js +81 -0
  10. package/out/analysis/fuzzy-search-worker.js.map +1 -0
  11. package/out/analysis/fuzzy-search.d.ts +38 -0
  12. package/out/analysis/fuzzy-search.js +217 -0
  13. package/out/analysis/fuzzy-search.js.map +1 -0
  14. package/out/analysis/git-dates-analyser.js +12 -3
  15. package/out/analysis/git-dates-analyser.js.map +1 -1
  16. package/out/analysis-api.d.ts +16 -2
  17. package/out/analysis-api.js +36 -3
  18. package/out/analysis-api.js.map +1 -1
  19. package/out/core/barrel-page.d.ts +46 -0
  20. package/out/core/barrel-page.js +162 -0
  21. package/out/core/barrel-page.js.map +1 -0
  22. package/out/core/filter-specials.d.ts +37 -0
  23. package/out/core/filter-specials.js +113 -0
  24. package/out/core/filter-specials.js.map +1 -0
  25. package/out/core/types.d.ts +27 -1
  26. package/out/core/types.js +1 -0
  27. package/out/core/types.js.map +1 -1
  28. package/out/create-runtime.js +2 -0
  29. package/out/create-runtime.js.map +1 -1
  30. package/out/export/build-export-snapshot.d.ts +2 -2
  31. package/out/export/build-export-snapshot.js +43 -16
  32. package/out/export/build-export-snapshot.js.map +1 -1
  33. package/out/export/export-csv.d.ts +4 -0
  34. package/out/export/export-csv.js +13 -0
  35. package/out/export/export-csv.js.map +1 -0
  36. package/out/export/export-html.d.ts +2 -2
  37. package/out/export/export-html.js +7 -3
  38. package/out/export/export-html.js.map +1 -1
  39. package/out/export/export-json.d.ts +6 -0
  40. package/out/export/export-json.js +28 -0
  41. package/out/export/export-json.js.map +1 -0
  42. package/out/export/export-markdown.d.ts +4 -0
  43. package/out/export/export-markdown.js +23 -0
  44. package/out/export/export-markdown.js.map +1 -0
  45. package/out/export/html-export-assets.d.ts +1 -1
  46. package/out/export/html-export-assets.js +663 -20
  47. package/out/export/html-export-assets.js.map +1 -1
  48. package/out/export/html-export-template.js +160 -61
  49. package/out/export/html-export-template.js.map +1 -1
  50. package/out/export/html-export-utils.d.ts +33 -3
  51. package/out/export/html-export-utils.js +121 -13
  52. package/out/export/html-export-utils.js.map +1 -1
  53. package/out/export/types.d.ts +20 -1
  54. package/out/export/write-csv-export.d.ts +5 -0
  55. package/out/export/write-csv-export.js +132 -0
  56. package/out/export/write-csv-export.js.map +1 -0
  57. package/out/export/write-html-export.d.ts +2 -2
  58. package/out/export/write-html-export.js +61 -29
  59. package/out/export/write-html-export.js.map +1 -1
  60. package/out/export/write-json-export.d.ts +3 -0
  61. package/out/export/write-json-export.js +92 -0
  62. package/out/export/write-json-export.js.map +1 -0
  63. package/out/export/write-markdown-export.d.ts +5 -0
  64. package/out/export/write-markdown-export.js +177 -0
  65. package/out/export/write-markdown-export.js.map +1 -0
  66. package/out/graph/physics-core-source.d.ts +5 -0
  67. package/out/graph/physics-core-source.js +8 -0
  68. package/out/graph/physics-core-source.js.map +1 -0
  69. package/out/index-store/idea-extractor.d.ts +6 -1
  70. package/out/index-store/idea-extractor.js +56 -11
  71. package/out/index-store/idea-extractor.js.map +1 -1
  72. package/out/index-store/index-diagnostics-store.js +1 -2
  73. package/out/index-store/index-diagnostics-store.js.map +1 -1
  74. package/out/index-store/sqlite-store.d.ts +16 -3
  75. package/out/index-store/sqlite-store.js +107 -9
  76. package/out/index-store/sqlite-store.js.map +1 -1
  77. package/out/index-store/webview-graph-queries.d.ts +13 -2
  78. package/out/index-store/webview-graph-queries.js +98 -18
  79. package/out/index-store/webview-graph-queries.js.map +1 -1
  80. package/out/index-store/webview-table-queries.js +1 -0
  81. package/out/index-store/webview-table-queries.js.map +1 -1
  82. package/out/index-store/workspace-index-file.js +22 -1
  83. package/out/index-store/workspace-index-file.js.map +1 -1
  84. package/out/index-store/workspace-index.d.ts +2 -1
  85. package/out/index-store/workspace-index.js +4 -1
  86. package/out/index-store/workspace-index.js.map +1 -1
  87. package/out/index.d.ts +17 -2
  88. package/out/index.js +10 -1
  89. package/out/index.js.map +1 -1
  90. package/package.json +7 -3
package/README.md CHANGED
@@ -30,6 +30,36 @@ npm install @reqlan/analytical
30
30
 
31
31
  ## Changelog
32
32
 
33
+ ### 0.8.1
34
+
35
+ #### Patch Changes
36
+
37
+ - d46b740: Fix missed build and test errors.
38
+ - Updated dependencies [d46b740]
39
+ - @reqlan/language@1.8.1
40
+
41
+ ### 0.8.0
42
+
43
+ #### Minor Changes
44
+
45
+ - 93368c6: Update exports; add support for wildcard import; update search functionality; add barrel import
46
+
47
+ #### Patch Changes
48
+
49
+ - Updated dependencies [93368c6]
50
+ - @reqlan/language@1.8.0
51
+
52
+ ### 0.7.0
53
+
54
+ #### Minor Changes
55
+
56
+ - f7023c1: various changes and improvements.
57
+
58
+ #### Patch Changes
59
+
60
+ - Updated dependencies [f7023c1]
61
+ - @reqlan/language@1.7.0
62
+
33
63
  ### 0.6.3
34
64
 
35
65
  #### Patch Changes
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Analyser entry for fuzzy idea search.
3
+ * rq:["../../../../reqlan rq/core_analysis/search.rq".fuzzy_search]
4
+ * rq:["../../../../reqlan rq/core_analysis/search.rq".fuzzy_search_whitespace]
5
+ */
6
+ import type { Analyser } from './analyser-registry.js';
7
+ import { type FuzzySearchHit } from './fuzzy-search.js';
8
+ export interface FuzzySearchParams {
9
+ query: string;
10
+ /** Cap results after ranking; omit for uncapped (caller paginates). */
11
+ limit?: number;
12
+ /** When true, empty query returns no hits instead of every non-ideaset idea. */
13
+ requireQuery?: boolean;
14
+ /** When true mid-run, scoring aborts and returns no hits (superseded request). */
15
+ isCancelled?: () => boolean;
16
+ }
17
+ export declare const fuzzySearchAnalyser: Analyser<FuzzySearchParams, FuzzySearchHit[]>;
@@ -0,0 +1,25 @@
1
+ import { filterAndScoreIdeasAsync } from './fuzzy-search.js';
2
+ export const fuzzySearchAnalyser = {
3
+ id: 'fuzzy_search',
4
+ async run({ store }, { query, limit, requireQuery = false, isCancelled }) {
5
+ const trimmed = query.trim();
6
+ if (requireQuery && !trimmed) {
7
+ return [];
8
+ }
9
+ if (isCancelled?.()) {
10
+ return [];
11
+ }
12
+ const ideas = await store.listAllIdeas();
13
+ // listAllIdeas is sync under sql.js — yield so openIdea / newer searches can run.
14
+ await new Promise(resolve => setTimeout(resolve, 0));
15
+ if (isCancelled?.()) {
16
+ return [];
17
+ }
18
+ const hits = await filterAndScoreIdeasAsync(ideas, trimmed, { isCancelled });
19
+ if (hits === undefined || isCancelled?.()) {
20
+ return [];
21
+ }
22
+ return limit === undefined ? hits : hits.slice(0, Math.max(0, limit));
23
+ }
24
+ };
25
+ //# sourceMappingURL=fuzzy-search-analyser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fuzzy-search-analyser.js","sourceRoot":"","sources":["../../src/analysis/fuzzy-search-analyser.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,wBAAwB,EAAuB,MAAM,mBAAmB,CAAC;AAYlF,MAAM,CAAC,MAAM,mBAAmB,GAAkD;IAC9E,EAAE,EAAE,cAAc;IAClB,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,GAAG,KAAK,EAAE,WAAW,EAAE;QACpE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,YAAY,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3B,OAAO,EAAE,CAAC;QACd,CAAC;QACD,IAAI,WAAW,EAAE,EAAE,EAAE,CAAC;YAClB,OAAO,EAAE,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,YAAY,EAAE,CAAC;QACzC,kFAAkF;QAClF,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3D,IAAI,WAAW,EAAE,EAAE,EAAE,CAAC;YAClB,OAAO,EAAE,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;QAC7E,IAAI,IAAI,KAAK,SAAS,IAAI,WAAW,EAAE,EAAE,EAAE,CAAC;YACxC,OAAO,EAAE,CAAC;QACd,CAAC;QACD,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1E,CAAC;CACJ,CAAC"}
@@ -0,0 +1,39 @@
1
+ import type { IdeaSummary } from '../core/types.js';
2
+ import type { FuzzySearchHit } from './fuzzy-search.js';
3
+ /** Resolve the bundled worker script next to the extension host output. */
4
+ export declare function resolveFuzzySearchWorkerPath(explicit?: string): string;
5
+ export interface FuzzySearchWorkerSearchResult {
6
+ hits: FuzzySearchHit[];
7
+ total: number;
8
+ truncated: boolean;
9
+ }
10
+ /**
11
+ * Owns a single worker that holds the idea catalog and scores queries off-thread.
12
+ */
13
+ export declare class FuzzySearchWorkerClient {
14
+ private worker;
15
+ private readonly pending;
16
+ private catalogEpoch;
17
+ private disposed;
18
+ private readonly workerPath;
19
+ constructor(options?: {
20
+ workerPath?: string;
21
+ });
22
+ get hasCatalog(): boolean;
23
+ setCatalog(ideas: readonly IdeaSummary[]): Promise<number>;
24
+ clearCatalog(): void;
25
+ search(query: string, requestId: number, options?: {
26
+ limit?: number;
27
+ requireQuery?: boolean;
28
+ }): Promise<FuzzySearchWorkerSearchResult>;
29
+ /** Drop in-flight search promises so callers can move on (worker may still finish). */
30
+ cancelSearches(requestId?: number): void;
31
+ dispose(): void;
32
+ private ensureWorker;
33
+ private post;
34
+ private onMessage;
35
+ }
36
+ export declare class SearchCancelledError extends Error {
37
+ readonly requestId: number;
38
+ constructor(requestId: number);
39
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Host-side client for the fuzzy-search worker thread.
3
+ * rq:["../../../../reqlan rq/core_analysis/search.rq".fuzzy_search]
4
+ */
5
+ import { existsSync } from 'node:fs';
6
+ import { dirname, join } from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { Worker } from 'node:worker_threads';
9
+ function moduleDirectory() {
10
+ if (typeof __dirname === 'string') {
11
+ return __dirname;
12
+ }
13
+ const metaUrl = (0, eval)('import.meta.url');
14
+ return dirname(fileURLToPath(metaUrl));
15
+ }
16
+ /** Resolve the bundled worker script next to the extension host output. */
17
+ export function resolveFuzzySearchWorkerPath(explicit) {
18
+ if (explicit) {
19
+ return explicit;
20
+ }
21
+ const dir = moduleDirectory();
22
+ const candidates = [
23
+ join(dir, 'fuzzy-search-worker.cjs'),
24
+ join(dir, 'fuzzy-search-worker.js'),
25
+ join(dir, '..', 'fuzzy-search-worker.cjs'),
26
+ join(dir, 'extension', 'fuzzy-search-worker.cjs')
27
+ ];
28
+ for (const candidate of candidates) {
29
+ if (existsSync(candidate)) {
30
+ return candidate;
31
+ }
32
+ }
33
+ return candidates[0];
34
+ }
35
+ /**
36
+ * Owns a single worker that holds the idea catalog and scores queries off-thread.
37
+ */
38
+ export class FuzzySearchWorkerClient {
39
+ constructor(options) {
40
+ this.pending = new Map();
41
+ this.catalogEpoch = 0;
42
+ this.disposed = false;
43
+ this.workerPath = resolveFuzzySearchWorkerPath(options?.workerPath);
44
+ }
45
+ get hasCatalog() {
46
+ return this.catalogEpoch > 0;
47
+ }
48
+ async setCatalog(ideas) {
49
+ this.ensureWorker();
50
+ const epoch = ++this.catalogEpoch;
51
+ const compact = ideas.map(idea => ({
52
+ id: idea.id,
53
+ name: idea.name,
54
+ kind: idea.kind,
55
+ fileUri: idea.fileUri,
56
+ summary: idea.summary,
57
+ lineStart: idea.lineStart,
58
+ tags: idea.tags
59
+ }));
60
+ this.post({ type: 'setCatalog', ideas: compact });
61
+ return epoch;
62
+ }
63
+ clearCatalog() {
64
+ this.catalogEpoch = 0;
65
+ if (this.worker) {
66
+ this.post({ type: 'clearCatalog' });
67
+ }
68
+ }
69
+ search(query, requestId, options) {
70
+ this.ensureWorker();
71
+ return new Promise((resolve, reject) => {
72
+ this.pending.set(requestId, { resolve, reject });
73
+ this.post({
74
+ type: 'search',
75
+ requestId,
76
+ query,
77
+ limit: options?.limit,
78
+ requireQuery: options?.requireQuery
79
+ });
80
+ });
81
+ }
82
+ /** Drop in-flight search promises so callers can move on (worker may still finish). */
83
+ cancelSearches(requestId) {
84
+ if (this.worker) {
85
+ this.post({ type: 'cancel', requestId });
86
+ }
87
+ if (requestId === undefined) {
88
+ for (const [id, pending] of this.pending) {
89
+ pending.reject(new SearchCancelledError(id));
90
+ }
91
+ this.pending.clear();
92
+ return;
93
+ }
94
+ const pending = this.pending.get(requestId);
95
+ if (pending) {
96
+ this.pending.delete(requestId);
97
+ pending.reject(new SearchCancelledError(requestId));
98
+ }
99
+ }
100
+ dispose() {
101
+ this.disposed = true;
102
+ for (const [id, pending] of this.pending) {
103
+ pending.reject(new SearchCancelledError(id));
104
+ }
105
+ this.pending.clear();
106
+ const worker = this.worker;
107
+ this.worker = undefined;
108
+ void worker?.terminate();
109
+ }
110
+ ensureWorker() {
111
+ if (this.disposed) {
112
+ throw new Error('FuzzySearchWorkerClient is disposed');
113
+ }
114
+ if (this.worker) {
115
+ return this.worker;
116
+ }
117
+ const worker = new Worker(this.workerPath);
118
+ worker.on('message', (message) => {
119
+ this.onMessage(message);
120
+ });
121
+ worker.on('error', error => {
122
+ for (const [, pending] of this.pending) {
123
+ pending.reject(error instanceof Error ? error : new Error(String(error)));
124
+ }
125
+ this.pending.clear();
126
+ this.worker = undefined;
127
+ });
128
+ worker.on('exit', code => {
129
+ if (this.disposed) {
130
+ return;
131
+ }
132
+ this.worker = undefined;
133
+ if (code !== 0 && this.pending.size > 0) {
134
+ const error = new Error(`fuzzy-search worker exited with code ${code}`);
135
+ for (const [, pending] of this.pending) {
136
+ pending.reject(error);
137
+ }
138
+ this.pending.clear();
139
+ }
140
+ });
141
+ this.worker = worker;
142
+ return worker;
143
+ }
144
+ post(message) {
145
+ this.ensureWorker().postMessage(message);
146
+ }
147
+ onMessage(message) {
148
+ if (!message || typeof message !== 'object' || !('type' in message)) {
149
+ return;
150
+ }
151
+ const pending = this.pending.get(message.requestId);
152
+ if (!pending) {
153
+ return;
154
+ }
155
+ this.pending.delete(message.requestId);
156
+ if (message.type === 'result') {
157
+ pending.resolve({
158
+ hits: message.hits,
159
+ total: message.total,
160
+ truncated: message.truncated
161
+ });
162
+ return;
163
+ }
164
+ if (message.type === 'cancelled') {
165
+ pending.reject(new SearchCancelledError(message.requestId));
166
+ return;
167
+ }
168
+ pending.reject(new Error(message.message));
169
+ }
170
+ }
171
+ export class SearchCancelledError extends Error {
172
+ constructor(requestId) {
173
+ super(`Search ${requestId} cancelled`);
174
+ this.name = 'SearchCancelledError';
175
+ this.requestId = requestId;
176
+ }
177
+ }
178
+ //# sourceMappingURL=fuzzy-search-worker-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fuzzy-search-worker-client.js","sourceRoot":"","sources":["../../src/analysis/fuzzy-search-worker-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { type FuzzySearchHit } from './fuzzy-search.js';
2
+ import type { IdeaSummary } from '../core/types.js';
3
+ export type FuzzySearchWorkerIdea = Pick<IdeaSummary, 'id' | 'name' | 'kind' | 'fileUri' | 'summary' | 'lineStart' | 'tags'>;
4
+ export type FuzzySearchWorkerInbound = {
5
+ type: 'setCatalog';
6
+ ideas: FuzzySearchWorkerIdea[];
7
+ } | {
8
+ type: 'clearCatalog';
9
+ } | {
10
+ type: 'search';
11
+ requestId: number;
12
+ query: string;
13
+ limit?: number;
14
+ requireQuery?: boolean;
15
+ } | {
16
+ type: 'cancel';
17
+ requestId?: number;
18
+ };
19
+ export type FuzzySearchWorkerOutbound = {
20
+ type: 'result';
21
+ requestId: number;
22
+ hits: FuzzySearchHit[];
23
+ total: number;
24
+ truncated: boolean;
25
+ } | {
26
+ type: 'error';
27
+ requestId: number;
28
+ message: string;
29
+ } | {
30
+ type: 'cancelled';
31
+ requestId: number;
32
+ };
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Worker-thread fuzzy idea search — keeps scoring off the extension-host event loop.
3
+ * rq:["../../../../reqlan rq/core_analysis/search.rq".fuzzy_search]
4
+ * rq:["../../../../reqlan rq/core_analysis/search.rq".fuzzy_search_whitespace]
5
+ */
6
+ import { parentPort } from 'node:worker_threads';
7
+ import { filterAndScoreIdeas } from './fuzzy-search.js';
8
+ let catalog = [];
9
+ let activeRequestId;
10
+ if (!parentPort) {
11
+ throw new Error('fuzzy-search-worker must run as a worker thread');
12
+ }
13
+ parentPort.on('message', (message) => {
14
+ if (!message || typeof message !== 'object' || !('type' in message)) {
15
+ return;
16
+ }
17
+ switch (message.type) {
18
+ case 'setCatalog':
19
+ catalog = message.ideas;
20
+ break;
21
+ case 'clearCatalog':
22
+ catalog = [];
23
+ break;
24
+ case 'cancel':
25
+ if (message.requestId === undefined || message.requestId === activeRequestId) {
26
+ activeRequestId = undefined;
27
+ }
28
+ break;
29
+ case 'search': {
30
+ const { requestId, query, limit, requireQuery = false } = message;
31
+ activeRequestId = requestId;
32
+ try {
33
+ const trimmed = query.trim();
34
+ if (requireQuery && !trimmed) {
35
+ parentPort.postMessage({
36
+ type: 'result',
37
+ requestId,
38
+ hits: [],
39
+ total: 0,
40
+ truncated: false
41
+ });
42
+ break;
43
+ }
44
+ const ranked = filterAndScoreIdeas(catalog, trimmed);
45
+ if (activeRequestId !== requestId) {
46
+ parentPort.postMessage({
47
+ type: 'cancelled',
48
+ requestId
49
+ });
50
+ break;
51
+ }
52
+ const total = ranked.length;
53
+ const truncated = limit !== undefined && total > limit;
54
+ const hits = limit === undefined ? ranked : ranked.slice(0, Math.max(0, limit));
55
+ parentPort.postMessage({
56
+ type: 'result',
57
+ requestId,
58
+ hits,
59
+ total,
60
+ truncated
61
+ });
62
+ }
63
+ catch (error) {
64
+ parentPort.postMessage({
65
+ type: 'error',
66
+ requestId,
67
+ message: error instanceof Error ? error.message : String(error)
68
+ });
69
+ }
70
+ finally {
71
+ if (activeRequestId === requestId) {
72
+ activeRequestId = undefined;
73
+ }
74
+ }
75
+ break;
76
+ }
77
+ default:
78
+ break;
79
+ }
80
+ });
81
+ //# sourceMappingURL=fuzzy-search-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fuzzy-search-worker.js","sourceRoot":"","sources":["../../src/analysis/fuzzy-search-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Fuzzy / partial idea search with interchangeable separators.
3
+ * rq:["../../../../reqlan rq/core_analysis/search.rq".fuzzy_search]
4
+ * rq:["../../../../reqlan rq/core_analysis/search.rq".fuzzy_search_whitespace]
5
+ */
6
+ import type { IdeaSummary } from '../core/types.js';
7
+ export interface FuzzySearchHit {
8
+ id: string;
9
+ name: string;
10
+ kind: IdeaSummary['kind'];
11
+ fileUri: string;
12
+ summary: string;
13
+ lineStart: number;
14
+ score: number;
15
+ }
16
+ /** Lowercase and strip interchangeable separators for comparison. */
17
+ export declare function normalizeSearchSeparators(value: string): string;
18
+ /** Split on interchangeable separators into lowercase word tokens. */
19
+ export declare function splitSearchTokens(value: string): string[];
20
+ export declare function filterAndScoreIdeas(ideas: IdeaSummary[], query: string): FuzzySearchHit[];
21
+ /**
22
+ * Score ideas in chunks, yielding to the event loop so UI actions (e.g. openIdea)
23
+ * are not blocked by a long synchronous scan of a large index.
24
+ * Returns `undefined` when `isCancelled` becomes true mid-run.
25
+ */
26
+ export declare function filterAndScoreIdeasAsync(ideas: IdeaSummary[], query: string, options?: {
27
+ isCancelled?: () => boolean;
28
+ /** Ideas processed between yields; default 250. */
29
+ chunkSize?: number;
30
+ }): Promise<FuzzySearchHit[] | undefined>;
31
+ /**
32
+ * Match every query token against hay tokens.
33
+ * Prefers order-preserving matches; still accepts reordered tokens (missing
34
+ * intermediate hay words are fine either way).
35
+ */
36
+ export declare function matchQueryTokens(hayTokens: string[], queryTokens: string[]): 'ordered' | 'reordered' | null;
37
+ /** True when needle characters appear in order inside hay (simple fuzzy). */
38
+ export declare function fuzzySubsequence(hay: string, needle: string): boolean;