@hcu-lab.me/mcp-device 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.
- package/LICENSE +21 -0
- package/README.md +51 -0
- package/dist/bootstrap.d.ts +1 -0
- package/dist/bootstrap.js +22 -0
- package/dist/command-manager.d.ts +8 -0
- package/dist/command-manager.js +241 -0
- package/dist/config-field-definitions.d.ts +41 -0
- package/dist/config-field-definitions.js +37 -0
- package/dist/config-manager.d.ts +102 -0
- package/dist/config-manager.js +291 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.js +10 -0
- package/dist/custom-stdio.d.ts +51 -0
- package/dist/custom-stdio.js +358 -0
- package/dist/data/official-app-ca.pem +12 -0
- package/dist/data/onboarding-prompts.json +70 -0
- package/dist/device/device-state.d.ts +13 -0
- package/dist/device/device-state.js +100 -0
- package/dist/device/device-status.d.ts +81 -0
- package/dist/device/device-status.js +156 -0
- package/dist/device/device.d.ts +16 -0
- package/dist/device/device.js +190 -0
- package/dist/device/execution-engine.d.ts +144 -0
- package/dist/device/execution-engine.js +195 -0
- package/dist/device/gateway-channel.d.ts +48 -0
- package/dist/device/gateway-channel.js +384 -0
- package/dist/device/gateway-config.d.ts +40 -0
- package/dist/device/gateway-config.js +207 -0
- package/dist/device/gateway-identity.d.ts +35 -0
- package/dist/device/gateway-identity.js +178 -0
- package/dist/device/gateway-pairing.d.ts +25 -0
- package/dist/device/gateway-pairing.js +105 -0
- package/dist/device/gateway-secure-transport.d.ts +25 -0
- package/dist/device/gateway-secure-transport.js +117 -0
- package/dist/device/gateway-tool-adapter.d.ts +17 -0
- package/dist/device/gateway-tool-adapter.js +284 -0
- package/dist/device/gateway-url-policy.d.ts +3 -0
- package/dist/device/gateway-url-policy.js +43 -0
- package/dist/device/linux-service.d.ts +70 -0
- package/dist/device/linux-service.js +268 -0
- package/dist/device/official-trust.d.ts +7 -0
- package/dist/device/official-trust.js +49 -0
- package/dist/device/project-inspection.d.ts +1 -0
- package/dist/device/project-inspection.js +180 -0
- package/dist/device/runtime-owner.d.ts +41 -0
- package/dist/device/runtime-owner.js +177 -0
- package/dist/device/windows-dpapi.d.ts +11 -0
- package/dist/device/windows-dpapi.js +67 -0
- package/dist/device/windows-service.d.ts +56 -0
- package/dist/device/windows-service.js +238 -0
- package/dist/error-handlers.d.ts +7 -0
- package/dist/error-handlers.js +15 -0
- package/dist/handlers/edit-search-handlers.d.ts +6 -0
- package/dist/handlers/edit-search-handlers.js +6 -0
- package/dist/handlers/filesystem-handlers.d.ts +38 -0
- package/dist/handlers/filesystem-handlers.js +440 -0
- package/dist/handlers/history-handlers.d.ts +12 -0
- package/dist/handlers/history-handlers.js +67 -0
- package/dist/handlers/index.d.ts +6 -0
- package/dist/handlers/index.js +7 -0
- package/dist/handlers/process-handlers.d.ts +9 -0
- package/dist/handlers/process-handlers.js +15 -0
- package/dist/handlers/search-handlers.d.ts +17 -0
- package/dist/handlers/search-handlers.js +224 -0
- package/dist/handlers/terminal-handlers.d.ts +21 -0
- package/dist/handlers/terminal-handlers.js +35 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +138 -0
- package/dist/mcp-device.d.ts +2 -0
- package/dist/mcp-device.js +7 -0
- package/dist/npm-scripts/remote.d.ts +3 -0
- package/dist/npm-scripts/remote.js +314 -0
- package/dist/search-manager.d.ts +147 -0
- package/dist/search-manager.js +828 -0
- package/dist/server.d.ts +46 -0
- package/dist/server.js +1563 -0
- package/dist/terminal-manager.d.ts +104 -0
- package/dist/terminal-manager.js +635 -0
- package/dist/tools/config.d.ts +96 -0
- package/dist/tools/config.js +260 -0
- package/dist/tools/edit.d.ts +38 -0
- package/dist/tools/edit.js +435 -0
- package/dist/tools/feedback.d.ts +8 -0
- package/dist/tools/feedback.js +132 -0
- package/dist/tools/filesystem.d.ts +79 -0
- package/dist/tools/filesystem.js +947 -0
- package/dist/tools/fuzzySearch.d.ts +12 -0
- package/dist/tools/fuzzySearch.js +74 -0
- package/dist/tools/fuzzySearchCore.d.ts +52 -0
- package/dist/tools/fuzzySearchCore.js +125 -0
- package/dist/tools/improved-process-tools.d.ts +24 -0
- package/dist/tools/improved-process-tools.js +627 -0
- package/dist/tools/mime-types.d.ts +3 -0
- package/dist/tools/mime-types.js +28 -0
- package/dist/tools/pdf/extract-images.d.ts +34 -0
- package/dist/tools/pdf/extract-images.js +132 -0
- package/dist/tools/pdf/index.d.ts +6 -0
- package/dist/tools/pdf/index.js +3 -0
- package/dist/tools/pdf/lib/pdf2md.d.ts +36 -0
- package/dist/tools/pdf/lib/pdf2md.js +76 -0
- package/dist/tools/pdf/manipulations.d.ts +13 -0
- package/dist/tools/pdf/manipulations.js +99 -0
- package/dist/tools/pdf/markdown.d.ts +26 -0
- package/dist/tools/pdf/markdown.js +275 -0
- package/dist/tools/pdf/utils.d.ts +12 -0
- package/dist/tools/pdf/utils.js +34 -0
- package/dist/tools/process.d.ts +3 -0
- package/dist/tools/process.js +56 -0
- package/dist/tools/prompts.d.ts +28 -0
- package/dist/tools/prompts.js +259 -0
- package/dist/tools/schemas.d.ts +454 -0
- package/dist/tools/schemas.js +242 -0
- package/dist/tools/usage.d.ts +5 -0
- package/dist/tools/usage.js +24 -0
- package/dist/types.d.ts +83 -0
- package/dist/types.js +1 -0
- package/dist/ui/config-editor/config-editor-runtime.js +150 -0
- package/dist/ui/config-editor/index.html +13 -0
- package/dist/ui/config-editor/src/app.d.ts +43 -0
- package/dist/ui/config-editor/src/app.js +831 -0
- package/dist/ui/config-editor/src/array-modal.d.ts +19 -0
- package/dist/ui/config-editor/src/array-modal.js +185 -0
- package/dist/ui/config-editor/src/main.d.ts +1 -0
- package/dist/ui/config-editor/src/main.js +2 -0
- package/dist/ui/config-editor/styles.css +587 -0
- package/dist/ui/contracts.d.ts +14 -0
- package/dist/ui/contracts.js +21 -0
- package/dist/ui/file-preview/index.html +16 -0
- package/dist/ui/file-preview/preview-runtime.js +469 -0
- package/dist/ui/file-preview/shared/preview-file-types.d.ts +5 -0
- package/dist/ui/file-preview/shared/preview-file-types.js +59 -0
- package/dist/ui/file-preview/src/app.d.ts +4 -0
- package/dist/ui/file-preview/src/app.js +680 -0
- package/dist/ui/file-preview/src/components/code-viewer.d.ts +6 -0
- package/dist/ui/file-preview/src/components/code-viewer.js +73 -0
- package/dist/ui/file-preview/src/components/highlighting.d.ts +2 -0
- package/dist/ui/file-preview/src/components/highlighting.js +54 -0
- package/dist/ui/file-preview/src/components/html-renderer.d.ts +5 -0
- package/dist/ui/file-preview/src/components/html-renderer.js +47 -0
- package/dist/ui/file-preview/src/components/markdown-renderer.d.ts +1 -0
- package/dist/ui/file-preview/src/components/markdown-renderer.js +59 -0
- package/dist/ui/file-preview/src/directory-controller.d.ts +8 -0
- package/dist/ui/file-preview/src/directory-controller.js +240 -0
- package/dist/ui/file-preview/src/document-layout.d.ts +20 -0
- package/dist/ui/file-preview/src/document-layout.js +109 -0
- package/dist/ui/file-preview/src/document-outline.d.ts +17 -0
- package/dist/ui/file-preview/src/document-outline.js +97 -0
- package/dist/ui/file-preview/src/document-workspace.d.ts +19 -0
- package/dist/ui/file-preview/src/document-workspace.js +33 -0
- package/dist/ui/file-preview/src/file-type-handlers.d.ts +10 -0
- package/dist/ui/file-preview/src/file-type-handlers.js +109 -0
- package/dist/ui/file-preview/src/host/external-actions.d.ts +8 -0
- package/dist/ui/file-preview/src/host/external-actions.js +55 -0
- package/dist/ui/file-preview/src/host/selection-context.d.ts +9 -0
- package/dist/ui/file-preview/src/host/selection-context.js +106 -0
- package/dist/ui/file-preview/src/image-preview.d.ts +3 -0
- package/dist/ui/file-preview/src/image-preview.js +21 -0
- package/dist/ui/file-preview/src/main.d.ts +1 -0
- package/dist/ui/file-preview/src/main.js +5 -0
- package/dist/ui/file-preview/src/markdown/conflict-dialog.d.ts +40 -0
- package/dist/ui/file-preview/src/markdown/conflict-dialog.js +163 -0
- package/dist/ui/file-preview/src/markdown/controller.d.ts +44 -0
- package/dist/ui/file-preview/src/markdown/controller.js +1043 -0
- package/dist/ui/file-preview/src/markdown/editor.d.ts +131 -0
- package/dist/ui/file-preview/src/markdown/editor.js +1479 -0
- package/dist/ui/file-preview/src/markdown/linking.d.ts +16 -0
- package/dist/ui/file-preview/src/markdown/linking.js +228 -0
- package/dist/ui/file-preview/src/markdown/outline.d.ts +2 -0
- package/dist/ui/file-preview/src/markdown/outline.js +16 -0
- package/dist/ui/file-preview/src/markdown/parser.d.ts +30 -0
- package/dist/ui/file-preview/src/markdown/parser.js +38 -0
- package/dist/ui/file-preview/src/markdown/preview.d.ts +1 -0
- package/dist/ui/file-preview/src/markdown/preview.js +20 -0
- package/dist/ui/file-preview/src/markdown/slugify.d.ts +3 -0
- package/dist/ui/file-preview/src/markdown/slugify.js +31 -0
- package/dist/ui/file-preview/src/markdown/utils.d.ts +1 -0
- package/dist/ui/file-preview/src/markdown/utils.js +15 -0
- package/dist/ui/file-preview/src/model.d.ts +35 -0
- package/dist/ui/file-preview/src/model.js +1 -0
- package/dist/ui/file-preview/src/panel-actions.d.ts +17 -0
- package/dist/ui/file-preview/src/panel-actions.js +182 -0
- package/dist/ui/file-preview/src/path-utils.d.ts +6 -0
- package/dist/ui/file-preview/src/path-utils.js +64 -0
- package/dist/ui/file-preview/src/payload-utils.d.ts +11 -0
- package/dist/ui/file-preview/src/payload-utils.js +119 -0
- package/dist/ui/file-preview/src/types.d.ts +1 -0
- package/dist/ui/file-preview/src/types.js +1 -0
- package/dist/ui/file-preview/styles.css +1631 -0
- package/dist/ui/resources.d.ts +28 -0
- package/dist/ui/resources.js +86 -0
- package/dist/ui/shared/compact-row.d.ts +11 -0
- package/dist/ui/shared/compact-row.js +18 -0
- package/dist/ui/shared/escape-html.d.ts +4 -0
- package/dist/ui/shared/escape-html.js +11 -0
- package/dist/ui/shared/host-context.d.ts +15 -0
- package/dist/ui/shared/host-context.js +51 -0
- package/dist/ui/shared/tool-bridge.d.ts +30 -0
- package/dist/ui/shared/tool-bridge.js +137 -0
- package/dist/ui/shared/tool-shell.d.ts +25 -0
- package/dist/ui/shared/tool-shell.js +107 -0
- package/dist/ui/shared/ui-event-tracker.d.ts +9 -0
- package/dist/ui/shared/ui-event-tracker.js +27 -0
- package/dist/ui/shared/widget-state.d.ts +33 -0
- package/dist/ui/shared/widget-state.js +158 -0
- package/dist/utils/ab-test.d.ts +12 -0
- package/dist/utils/ab-test.js +104 -0
- package/dist/utils/capture.d.ts +35 -0
- package/dist/utils/capture.js +481 -0
- package/dist/utils/dockerPrompt.d.ts +17 -0
- package/dist/utils/dockerPrompt.js +53 -0
- package/dist/utils/feature-flags.d.ts +59 -0
- package/dist/utils/feature-flags.js +215 -0
- package/dist/utils/files/base.d.ts +173 -0
- package/dist/utils/files/base.js +5 -0
- package/dist/utils/files/binary.d.ts +21 -0
- package/dist/utils/files/binary.js +65 -0
- package/dist/utils/files/docx.d.ts +47 -0
- package/dist/utils/files/docx.js +679 -0
- package/dist/utils/files/excel.d.ts +24 -0
- package/dist/utils/files/excel.js +437 -0
- package/dist/utils/files/factory.d.ts +41 -0
- package/dist/utils/files/factory.js +113 -0
- package/dist/utils/files/image.d.ts +21 -0
- package/dist/utils/files/image.js +78 -0
- package/dist/utils/files/index.d.ts +10 -0
- package/dist/utils/files/index.js +13 -0
- package/dist/utils/files/pdf.d.ts +32 -0
- package/dist/utils/files/pdf.js +142 -0
- package/dist/utils/files/text.d.ts +63 -0
- package/dist/utils/files/text.js +370 -0
- package/dist/utils/fuzzySearchLogger.d.ts +30 -0
- package/dist/utils/fuzzySearchLogger.js +126 -0
- package/dist/utils/lineEndingHandler.d.ts +21 -0
- package/dist/utils/lineEndingHandler.js +77 -0
- package/dist/utils/logger.d.ts +32 -0
- package/dist/utils/logger.js +72 -0
- package/dist/utils/mcp-ui-ab-test.d.ts +13 -0
- package/dist/utils/mcp-ui-ab-test.js +62 -0
- package/dist/utils/open-browser.d.ts +9 -0
- package/dist/utils/open-browser.js +42 -0
- package/dist/utils/process-detection.d.ts +23 -0
- package/dist/utils/process-detection.js +150 -0
- package/dist/utils/ripgrep-resolver.d.ts +9 -0
- package/dist/utils/ripgrep-resolver.js +74 -0
- package/dist/utils/system-info.d.ts +71 -0
- package/dist/utils/system-info.js +712 -0
- package/dist/utils/toolHistory.d.ts +86 -0
- package/dist/utils/toolHistory.js +257 -0
- package/dist/utils/trackTools.d.ts +6 -0
- package/dist/utils/trackTools.js +54 -0
- package/dist/utils/unsupportedParams.d.ts +24 -0
- package/dist/utils/unsupportedParams.js +66 -0
- package/dist/utils/usageTracker.d.ts +133 -0
- package/dist/utils/usageTracker.js +477 -0
- package/dist/utils/welcome-onboarding.d.ts +11 -0
- package/dist/utils/welcome-onboarding.js +99 -0
- package/dist/utils/withTimeout.d.ts +28 -0
- package/dist/utils/withTimeout.js +85 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +1 -0
- package/package.json +131 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FuzzyMatch } from './fuzzySearchCore.js';
|
|
2
|
+
export { recursiveFuzzyIndexOf, getSimilarityRatio } from './fuzzySearchCore.js';
|
|
3
|
+
/** Abort fuzzy search in the worker after this many ms to avoid unbounded CPU burn. */
|
|
4
|
+
export declare const FUZZY_SEARCH_TIMEOUT_MS = 30000;
|
|
5
|
+
/**
|
|
6
|
+
* Runs the fuzzy search in a Worker thread so the main MCP event loop stays
|
|
7
|
+
* responsive to pings and other tool calls during heavy scans. Rejects if the
|
|
8
|
+
* scan exceeds timeoutMs, terminating the worker so it doesn't linger in the
|
|
9
|
+
* background. Search metrics come back with the result and are captured here,
|
|
10
|
+
* on the main thread, where the client identity is initialized.
|
|
11
|
+
*/
|
|
12
|
+
export declare function runFuzzySearchInWorker(text: string, query: string, timeoutMs?: number): Promise<FuzzyMatch>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { capture } from '../utils/capture.js';
|
|
2
|
+
import { Worker } from 'worker_threads';
|
|
3
|
+
// Re-export so existing callers keep importing from this module.
|
|
4
|
+
export { recursiveFuzzyIndexOf, getSimilarityRatio } from './fuzzySearchCore.js';
|
|
5
|
+
/** Abort fuzzy search in the worker after this many ms to avoid unbounded CPU burn. */
|
|
6
|
+
export const FUZZY_SEARCH_TIMEOUT_MS = 30000;
|
|
7
|
+
/**
|
|
8
|
+
* Inline worker entry: imports the dependency-free core module (passed as
|
|
9
|
+
* moduleUrl) and runs the search off the main thread. The core module is
|
|
10
|
+
* deliberately a leaf — importing this module (or anything app-level) from the
|
|
11
|
+
* worker would boot the whole server per search. Kept as an eval'd snippet so
|
|
12
|
+
* the worker needs no separate file to ship alongside the compiled output.
|
|
13
|
+
*/
|
|
14
|
+
const WORKER_CODE = `
|
|
15
|
+
const { workerData, parentPort } = require('worker_threads');
|
|
16
|
+
import(workerData.moduleUrl)
|
|
17
|
+
.then((m) => {
|
|
18
|
+
parentPort.postMessage({ ok: true, ...m.runFuzzySearch(workerData.text, workerData.query) });
|
|
19
|
+
})
|
|
20
|
+
.catch((err) => {
|
|
21
|
+
parentPort.postMessage({ ok: false, error: String(err && err.stack || err) });
|
|
22
|
+
});
|
|
23
|
+
`;
|
|
24
|
+
const CORE_MODULE_URL = new URL('./fuzzySearchCore.js', import.meta.url).href;
|
|
25
|
+
/**
|
|
26
|
+
* Runs the fuzzy search in a Worker thread so the main MCP event loop stays
|
|
27
|
+
* responsive to pings and other tool calls during heavy scans. Rejects if the
|
|
28
|
+
* scan exceeds timeoutMs, terminating the worker so it doesn't linger in the
|
|
29
|
+
* background. Search metrics come back with the result and are captured here,
|
|
30
|
+
* on the main thread, where the client identity is initialized.
|
|
31
|
+
*/
|
|
32
|
+
export function runFuzzySearchInWorker(text, query, timeoutMs = FUZZY_SEARCH_TIMEOUT_MS) {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const worker = new Worker(WORKER_CODE, { eval: true, workerData: { moduleUrl: CORE_MODULE_URL, text, query } });
|
|
35
|
+
// Never let a scan keep the server process alive during shutdown.
|
|
36
|
+
worker.unref();
|
|
37
|
+
const timer = setTimeout(() => {
|
|
38
|
+
worker.terminate();
|
|
39
|
+
reject(new Error(`Fuzzy search timed out after ${timeoutMs}ms`));
|
|
40
|
+
}, timeoutMs);
|
|
41
|
+
timer.unref();
|
|
42
|
+
worker.on('message', (msg) => {
|
|
43
|
+
clearTimeout(timer);
|
|
44
|
+
if (msg.ok) {
|
|
45
|
+
captureFuzzySearchMetrics(msg.metrics);
|
|
46
|
+
resolve(msg.result);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
reject(new Error(`Fuzzy search worker failed: ${msg.error}`));
|
|
50
|
+
}
|
|
51
|
+
// Don't let the worker wind down on its own; the answer is already
|
|
52
|
+
// here, and a lingering worker holds its copy of the file text.
|
|
53
|
+
// The promise is settled, so the exit-code rejection below is a no-op.
|
|
54
|
+
worker.terminate();
|
|
55
|
+
});
|
|
56
|
+
worker.on('error', (err) => {
|
|
57
|
+
clearTimeout(timer);
|
|
58
|
+
reject(err);
|
|
59
|
+
});
|
|
60
|
+
worker.on('exit', (code) => {
|
|
61
|
+
clearTimeout(timer);
|
|
62
|
+
if (code !== 0) {
|
|
63
|
+
reject(new Error(`Fuzzy search worker exited with code ${code}`));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/** Same telemetry events the search used to emit inline, now sent from the main thread. */
|
|
69
|
+
function captureFuzzySearchMetrics(metrics) {
|
|
70
|
+
capture('fuzzy_search_recursive_metrics', metrics.recursive);
|
|
71
|
+
if (metrics.iterative) {
|
|
72
|
+
capture('fuzzy_search_iterative_metrics', metrics.iterative);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure fuzzy-search core, kept free of app imports on purpose: it runs inside
|
|
3
|
+
* the worker thread spawned by runFuzzySearchInWorker (fuzzySearch.ts), and
|
|
4
|
+
* anything imported here is loaded per worker. Telemetry is returned as data
|
|
5
|
+
* and captured on the main thread, which has the real client identity.
|
|
6
|
+
*/
|
|
7
|
+
export interface FuzzyMatch {
|
|
8
|
+
start: number;
|
|
9
|
+
end: number;
|
|
10
|
+
value: string;
|
|
11
|
+
distance: number;
|
|
12
|
+
}
|
|
13
|
+
export interface FuzzySearchMetrics {
|
|
14
|
+
recursive: {
|
|
15
|
+
execution_time_ms: number;
|
|
16
|
+
text_length: number;
|
|
17
|
+
query_length: number;
|
|
18
|
+
result_distance: number;
|
|
19
|
+
};
|
|
20
|
+
iterative: {
|
|
21
|
+
execution_time_ms: number;
|
|
22
|
+
iterations: number;
|
|
23
|
+
segment_length: number;
|
|
24
|
+
query_length: number;
|
|
25
|
+
final_distance: number;
|
|
26
|
+
} | null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Runs a full fuzzy search and returns the match together with the timing
|
|
30
|
+
* metrics that used to be captured inline.
|
|
31
|
+
*/
|
|
32
|
+
export declare function runFuzzySearch(text: string, query: string): {
|
|
33
|
+
result: FuzzyMatch;
|
|
34
|
+
metrics: FuzzySearchMetrics;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Recursively finds the closest match to a query string within text using fuzzy matching
|
|
38
|
+
* @param text The text to search within
|
|
39
|
+
* @param query The query string to find
|
|
40
|
+
* @param start Start index in the text (default: 0)
|
|
41
|
+
* @param end End index in the text (default: text.length)
|
|
42
|
+
* @param parentDistance Best distance found so far (default: Infinity)
|
|
43
|
+
* @returns Object with start and end indices, matched value, and Levenshtein distance
|
|
44
|
+
*/
|
|
45
|
+
export declare function recursiveFuzzyIndexOf(text: string, query: string, start?: number, end?: number | null, parentDistance?: number): FuzzyMatch;
|
|
46
|
+
/**
|
|
47
|
+
* Calculates the similarity ratio between two strings
|
|
48
|
+
* @param a First string
|
|
49
|
+
* @param b Second string
|
|
50
|
+
* @returns Similarity ratio (0-1)
|
|
51
|
+
*/
|
|
52
|
+
export declare function getSimilarityRatio(a: string, b: string): number;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { distance } from 'fastest-levenshtein';
|
|
2
|
+
// Set by iterativeReduction during a search (exactly one terminal call per
|
|
3
|
+
// search) and collected by runFuzzySearch. Single-threaded per context, so a
|
|
4
|
+
// module-level slot is safe.
|
|
5
|
+
let lastIterativeMetrics = null;
|
|
6
|
+
/**
|
|
7
|
+
* Runs a full fuzzy search and returns the match together with the timing
|
|
8
|
+
* metrics that used to be captured inline.
|
|
9
|
+
*/
|
|
10
|
+
export function runFuzzySearch(text, query) {
|
|
11
|
+
const startTime = performance.now();
|
|
12
|
+
lastIterativeMetrics = null;
|
|
13
|
+
const result = recursiveFuzzyIndexOf(text, query);
|
|
14
|
+
return {
|
|
15
|
+
result,
|
|
16
|
+
metrics: {
|
|
17
|
+
recursive: {
|
|
18
|
+
execution_time_ms: performance.now() - startTime,
|
|
19
|
+
text_length: text.length,
|
|
20
|
+
query_length: query.length,
|
|
21
|
+
result_distance: result.distance
|
|
22
|
+
},
|
|
23
|
+
iterative: lastIterativeMetrics
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Recursively finds the closest match to a query string within text using fuzzy matching
|
|
29
|
+
* @param text The text to search within
|
|
30
|
+
* @param query The query string to find
|
|
31
|
+
* @param start Start index in the text (default: 0)
|
|
32
|
+
* @param end End index in the text (default: text.length)
|
|
33
|
+
* @param parentDistance Best distance found so far (default: Infinity)
|
|
34
|
+
* @returns Object with start and end indices, matched value, and Levenshtein distance
|
|
35
|
+
*/
|
|
36
|
+
export function recursiveFuzzyIndexOf(text, query, start = 0, end = null, parentDistance = Infinity) {
|
|
37
|
+
if (end === null)
|
|
38
|
+
end = text.length;
|
|
39
|
+
// For small text segments, use iterative approach
|
|
40
|
+
if (end - start <= 2 * query.length) {
|
|
41
|
+
return iterativeReduction(text, query, start, end, parentDistance);
|
|
42
|
+
}
|
|
43
|
+
let midPoint = start + Math.floor((end - start) / 2);
|
|
44
|
+
let leftEnd = Math.min(end, midPoint + query.length); // Include query length to cover overlaps
|
|
45
|
+
let rightStart = Math.max(start, midPoint - query.length); // Include query length to cover overlaps
|
|
46
|
+
// Calculate distance for current segments
|
|
47
|
+
let leftDistance = distance(text.substring(start, leftEnd), query);
|
|
48
|
+
let rightDistance = distance(text.substring(rightStart, end), query);
|
|
49
|
+
let bestDistance = Math.min(leftDistance, parentDistance, rightDistance);
|
|
50
|
+
// If parent distance is already the best, use iterative approach
|
|
51
|
+
if (parentDistance === bestDistance) {
|
|
52
|
+
return iterativeReduction(text, query, start, end, parentDistance);
|
|
53
|
+
}
|
|
54
|
+
// Recursively search the better half
|
|
55
|
+
if (leftDistance < rightDistance) {
|
|
56
|
+
return recursiveFuzzyIndexOf(text, query, start, leftEnd, bestDistance);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return recursiveFuzzyIndexOf(text, query, rightStart, end, bestDistance);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Iteratively refines the best match by reducing the search area
|
|
64
|
+
* @param text The text to search within
|
|
65
|
+
* @param query The query string to find
|
|
66
|
+
* @param start Start index in the text
|
|
67
|
+
* @param end End index in the text
|
|
68
|
+
* @param parentDistance Best distance found so far
|
|
69
|
+
* @returns Object with start and end indices, matched value, and Levenshtein distance
|
|
70
|
+
*/
|
|
71
|
+
function iterativeReduction(text, query, start, end, parentDistance) {
|
|
72
|
+
const startTime = performance.now();
|
|
73
|
+
let iterations = 0;
|
|
74
|
+
// Seed with the measured distance of this slice. For recursive callers
|
|
75
|
+
// this equals parentDistance (the parent measured exactly this slice), but
|
|
76
|
+
// a top-level call on text <= 2x query length arrives with Infinity, which
|
|
77
|
+
// made the first shrink unconditional and a position-0 match unreachable.
|
|
78
|
+
let bestDistance = distance(text.substring(start, end), query);
|
|
79
|
+
let bestStart = start;
|
|
80
|
+
let bestEnd = end;
|
|
81
|
+
// Improve start position
|
|
82
|
+
let nextDistance = distance(text.substring(bestStart + 1, bestEnd), query);
|
|
83
|
+
while (nextDistance < bestDistance) {
|
|
84
|
+
bestDistance = nextDistance;
|
|
85
|
+
bestStart++;
|
|
86
|
+
const smallerString = text.substring(bestStart + 1, bestEnd);
|
|
87
|
+
nextDistance = distance(smallerString, query);
|
|
88
|
+
iterations++;
|
|
89
|
+
}
|
|
90
|
+
// Improve end position
|
|
91
|
+
nextDistance = distance(text.substring(bestStart, bestEnd - 1), query);
|
|
92
|
+
while (nextDistance < bestDistance) {
|
|
93
|
+
bestDistance = nextDistance;
|
|
94
|
+
bestEnd--;
|
|
95
|
+
const smallerString = text.substring(bestStart, bestEnd - 1);
|
|
96
|
+
nextDistance = distance(smallerString, query);
|
|
97
|
+
iterations++;
|
|
98
|
+
}
|
|
99
|
+
lastIterativeMetrics = {
|
|
100
|
+
execution_time_ms: performance.now() - startTime,
|
|
101
|
+
iterations: iterations,
|
|
102
|
+
segment_length: end - start,
|
|
103
|
+
query_length: query.length,
|
|
104
|
+
final_distance: bestDistance
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
start: bestStart,
|
|
108
|
+
end: bestEnd,
|
|
109
|
+
value: text.substring(bestStart, bestEnd),
|
|
110
|
+
distance: bestDistance
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Calculates the similarity ratio between two strings
|
|
115
|
+
* @param a First string
|
|
116
|
+
* @param b Second string
|
|
117
|
+
* @returns Similarity ratio (0-1)
|
|
118
|
+
*/
|
|
119
|
+
export function getSimilarityRatio(a, b) {
|
|
120
|
+
const maxLength = Math.max(a.length, b.length);
|
|
121
|
+
if (maxLength === 0)
|
|
122
|
+
return 1; // Both strings are empty
|
|
123
|
+
const levenshteinDistance = distance(a, b);
|
|
124
|
+
return 1 - (levenshteinDistance / maxLength);
|
|
125
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ServerResult } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Start a new process (renamed from execute_command)
|
|
4
|
+
* Includes early detection of process waiting for input
|
|
5
|
+
*/
|
|
6
|
+
export declare function startProcess(args: unknown): Promise<ServerResult>;
|
|
7
|
+
/**
|
|
8
|
+
* Read output from a running process with file-like pagination
|
|
9
|
+
* Supports offset/length parameters for controlled reading
|
|
10
|
+
*/
|
|
11
|
+
export declare function readProcessOutput(args: unknown): Promise<ServerResult>;
|
|
12
|
+
/**
|
|
13
|
+
* Interact with a running process (renamed from send_input)
|
|
14
|
+
* Automatically detects when process is ready and returns output
|
|
15
|
+
*/
|
|
16
|
+
export declare function interactWithProcess(args: unknown): Promise<ServerResult>;
|
|
17
|
+
/**
|
|
18
|
+
* Force terminate a process
|
|
19
|
+
*/
|
|
20
|
+
export declare function forceTerminate(args: unknown): Promise<ServerResult>;
|
|
21
|
+
/**
|
|
22
|
+
* List active sessions
|
|
23
|
+
*/
|
|
24
|
+
export declare function listSessions(): Promise<ServerResult>;
|