@octoseq/mir 0.1.0-main.0d2814e

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 (48) hide show
  1. package/dist/chunk-DUWYCAVG.js +1525 -0
  2. package/dist/chunk-DUWYCAVG.js.map +1 -0
  3. package/dist/index.d.ts +450 -0
  4. package/dist/index.js +1234 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/runMir-CSIBwNZ3.d.ts +84 -0
  7. package/dist/runner/runMir.d.ts +2 -0
  8. package/dist/runner/runMir.js +3 -0
  9. package/dist/runner/runMir.js.map +1 -0
  10. package/dist/runner/workerProtocol.d.ts +169 -0
  11. package/dist/runner/workerProtocol.js +11 -0
  12. package/dist/runner/workerProtocol.js.map +1 -0
  13. package/dist/types-BE3py4fZ.d.ts +83 -0
  14. package/package.json +55 -0
  15. package/src/dsp/fft.ts +22 -0
  16. package/src/dsp/fftBackend.ts +53 -0
  17. package/src/dsp/fftBackendFftjs.ts +60 -0
  18. package/src/dsp/hpss.ts +152 -0
  19. package/src/dsp/hpssGpu.ts +101 -0
  20. package/src/dsp/mel.ts +219 -0
  21. package/src/dsp/mfcc.ts +119 -0
  22. package/src/dsp/onset.ts +205 -0
  23. package/src/dsp/peakPick.ts +112 -0
  24. package/src/dsp/spectral.ts +95 -0
  25. package/src/dsp/spectrogram.ts +176 -0
  26. package/src/gpu/README.md +34 -0
  27. package/src/gpu/context.ts +44 -0
  28. package/src/gpu/helpers.ts +87 -0
  29. package/src/gpu/hpssMasks.ts +116 -0
  30. package/src/gpu/kernels/hpssMasks.wgsl.ts +137 -0
  31. package/src/gpu/kernels/melProject.wgsl.ts +48 -0
  32. package/src/gpu/kernels/onsetEnvelope.wgsl.ts +56 -0
  33. package/src/gpu/melProject.ts +98 -0
  34. package/src/gpu/onsetEnvelope.ts +81 -0
  35. package/src/gpu/webgpu.d.ts +176 -0
  36. package/src/index.ts +121 -0
  37. package/src/runner/runMir.ts +431 -0
  38. package/src/runner/workerProtocol.ts +189 -0
  39. package/src/search/featureVectorV1.ts +123 -0
  40. package/src/search/fingerprintV1.ts +230 -0
  41. package/src/search/refinedModelV1.ts +321 -0
  42. package/src/search/searchTrackV1.ts +206 -0
  43. package/src/search/searchTrackV1Guided.ts +863 -0
  44. package/src/search/similarity.ts +98 -0
  45. package/src/types.ts +105 -0
  46. package/src/util/display.ts +80 -0
  47. package/src/util/normalise.ts +58 -0
  48. package/src/util/stats.ts +25 -0
@@ -0,0 +1,48 @@
1
+ /**
2
+ * WGSL kernel: mel filterbank projection.
3
+ *
4
+ * Computes per-frame mel band energies:
5
+ * out[frame, mel] = log10(eps + sum_k mags[frame, k] * filters[mel, k])
6
+ *
7
+ * Notes:
8
+ * - FFT/STFT stays on CPU (spectrogram()). This kernel only accelerates the dense projection.
9
+ * - Numerical differences vs CPU are expected to be small (floating point order-of-ops).
10
+ */
11
+ export const melProjectWGSL = /* wgsl */ `
12
+ struct Params {
13
+ nBins: u32,
14
+ nMels: u32,
15
+ nFrames: u32,
16
+ _pad: u32,
17
+ };
18
+
19
+ @group(0) @binding(0) var<storage, read> mags : array<f32>;
20
+ @group(0) @binding(1) var<storage, read> filters : array<f32>;
21
+ @group(0) @binding(2) var<storage, read_write> out : array<f32>;
22
+ @group(0) @binding(3) var<uniform> params : Params;
23
+
24
+ fn log10(x: f32) -> f32 {
25
+ return log(x) / log(10.0);
26
+ }
27
+
28
+ @compute @workgroup_size(16, 16)
29
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
30
+ let frame = gid.x;
31
+ let mel = gid.y;
32
+ if (frame >= params.nFrames || mel >= params.nMels) {
33
+ return;
34
+ }
35
+
36
+ var sum: f32 = 0.0;
37
+ let bins = params.nBins;
38
+ let magBase = frame * bins;
39
+ let filBase = mel * bins;
40
+
41
+ for (var k: u32 = 0u; k < bins; k = k + 1u) {
42
+ sum = sum + mags[magBase + k] * filters[filBase + k];
43
+ }
44
+
45
+ let eps: f32 = 1e-12;
46
+ out[frame * params.nMels + mel] = log10(eps + sum);
47
+ }
48
+ `;
@@ -0,0 +1,56 @@
1
+ export const onsetEnvelopeWGSL = /* wgsl */ `
2
+ // Compute onset strength envelope from a (log) mel spectrogram.
3
+ //
4
+ // Input layout: melFlat[t*nMels + m]
5
+ // Output layout: out[t]
6
+ //
7
+ // We compute novelty per frame:
8
+ // novelty[t] = sum_m max(0, mel[t,m] - mel[t-1,m]) (rectified)
9
+ // or sum_m abs(...)
10
+ //
11
+ // One invocation computes one frame index (t). This is memory-bound but reduces a full
12
+ // (frames*mels) loop to the GPU and provides an end-to-end submit->readback timing.
13
+
14
+ struct Params {
15
+ nMels: u32,
16
+ nFrames: u32,
17
+ diffMethod: u32, // 0=rectified, 1=abs
18
+ _pad: u32,
19
+ };
20
+
21
+ @group(0) @binding(0) var<storage, read> melFlat: array<f32>;
22
+ @group(0) @binding(1) var<storage, read_write> out: array<f32>;
23
+ @group(0) @binding(2) var<uniform> params: Params;
24
+
25
+ @compute @workgroup_size(256)
26
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
27
+ let t = gid.x;
28
+ if (t >= params.nFrames) { return; }
29
+
30
+ if (t == 0u) {
31
+ out[t] = 0.0;
32
+ return;
33
+ }
34
+
35
+ let nMels = params.nMels;
36
+ var sum: f32 = 0.0;
37
+
38
+ // Linear loop: nMels is small (e.g. 64). Keeping it serial per-frame is fine.
39
+ // (Future optimisation: parallelise reduction within workgroup.)
40
+ for (var m: u32 = 0u; m < nMels; m = m + 1u) {
41
+ let a = melFlat[t * nMels + m];
42
+ let b = melFlat[(t - 1u) * nMels + m];
43
+ let d = a - b;
44
+
45
+ if (params.diffMethod == 1u) {
46
+ // abs
47
+ sum = sum + abs(d);
48
+ } else {
49
+ // rectified
50
+ sum = sum + max(0.0, d);
51
+ }
52
+ }
53
+
54
+ out[t] = sum / max(1.0, f32(nMels));
55
+ }
56
+ `;
@@ -0,0 +1,98 @@
1
+ import type { MirGPU } from "./context";
2
+
3
+ import {
4
+ byteSizeF32,
5
+ createAndWriteStorageBuffer,
6
+ createReadbackBuffer,
7
+ createStorageOutBuffer,
8
+ createUniformBufferU32x4,
9
+ submitAndReadback,
10
+ type GpuDispatchResult,
11
+ } from "./helpers";
12
+
13
+ import { melProjectWGSL } from "./kernels/melProject.wgsl";
14
+
15
+ export type GpuMelProjectInput = {
16
+ nFrames: number;
17
+ nBins: number;
18
+ nMels: number;
19
+ magsFlat: Float32Array; // length = nFrames*nBins
20
+ filterFlat: Float32Array; // length = nMels*nBins
21
+ };
22
+
23
+ export type GpuMelProjectOutput = {
24
+ outFlat: Float32Array; // length = nFrames*nMels
25
+ };
26
+
27
+ /**
28
+ * Real WebGPU compute stage: dense mel projection.
29
+ *
30
+ * Returns outFlat plus GPU timing that measures submit->readback.
31
+ */
32
+ export async function gpuMelProjectFlat(
33
+ gpu: MirGPU,
34
+ input: GpuMelProjectInput
35
+ ): Promise<GpuDispatchResult<GpuMelProjectOutput>> {
36
+ const { device } = gpu;
37
+
38
+ const { nFrames, nBins, nMels, magsFlat, filterFlat } = input;
39
+ if (magsFlat.length !== nFrames * nBins) {
40
+ throw new Error("@octoseq/mir: magsFlat length mismatch");
41
+ }
42
+ if (filterFlat.length !== nMels * nBins) {
43
+ throw new Error("@octoseq/mir: filterFlat length mismatch");
44
+ }
45
+
46
+ const magsBuffer = createAndWriteStorageBuffer(gpu, magsFlat);
47
+ const filterBuffer = createAndWriteStorageBuffer(gpu, filterFlat);
48
+
49
+ const outByteLen = byteSizeF32(nFrames * nMels);
50
+ const outBuffer = createStorageOutBuffer(gpu, outByteLen);
51
+ const readback = createReadbackBuffer(gpu, outByteLen);
52
+
53
+ const shader = device.createShaderModule({ code: melProjectWGSL });
54
+ const pipeline = device.createComputePipeline({
55
+ layout: "auto",
56
+ compute: {
57
+ module: shader,
58
+ entryPoint: "main",
59
+ },
60
+ });
61
+
62
+ const params = createUniformBufferU32x4(gpu, new Uint32Array([nBins, nMels, nFrames, 0]));
63
+
64
+ const bindGroup = device.createBindGroup({
65
+ layout: pipeline.getBindGroupLayout(0),
66
+ entries: [
67
+ { binding: 0, resource: { buffer: magsBuffer } },
68
+ { binding: 1, resource: { buffer: filterBuffer } },
69
+ { binding: 2, resource: { buffer: outBuffer } },
70
+ { binding: 3, resource: { buffer: params } },
71
+ ],
72
+ });
73
+
74
+ const encoder = device.createCommandEncoder();
75
+ const pass = encoder.beginComputePass();
76
+ pass.setPipeline(pipeline);
77
+ pass.setBindGroup(0, bindGroup);
78
+
79
+ const wgX = Math.ceil(nFrames / 16);
80
+ const wgY = Math.ceil(nMels / 16);
81
+ pass.dispatchWorkgroups(wgX, wgY);
82
+ pass.end();
83
+
84
+ const { value: bytes, timing } = await submitAndReadback(gpu, encoder, outBuffer, readback, outByteLen);
85
+
86
+ // Cleanup (simple; no pooling in v0.1)
87
+ magsBuffer.destroy();
88
+ filterBuffer.destroy();
89
+ outBuffer.destroy();
90
+ params.destroy();
91
+ readback.destroy();
92
+
93
+ const outFlat = new Float32Array(bytes);
94
+ return {
95
+ value: { outFlat },
96
+ timing,
97
+ };
98
+ }
@@ -0,0 +1,81 @@
1
+ import type { MirGPU } from "./context";
2
+
3
+ import {
4
+ byteSizeF32,
5
+ createAndWriteStorageBuffer,
6
+ createReadbackBuffer,
7
+ createStorageOutBuffer,
8
+ createUniformBufferU32x4,
9
+ submitAndReadback,
10
+ type GpuDispatchResult,
11
+ } from "./helpers";
12
+
13
+ import { onsetEnvelopeWGSL } from "./kernels/onsetEnvelope.wgsl";
14
+
15
+ export type GpuOnsetEnvelopeInput = {
16
+ nFrames: number;
17
+ nMels: number;
18
+ melFlat: Float32Array; // length=nFrames*nMels
19
+ diffMethod: "rectified" | "abs";
20
+ };
21
+
22
+ export type GpuOnsetEnvelopeOutput = {
23
+ out: Float32Array; // length=nFrames
24
+ };
25
+
26
+ export async function gpuOnsetEnvelopeFromMelFlat(
27
+ gpu: MirGPU,
28
+ input: GpuOnsetEnvelopeInput
29
+ ): Promise<GpuDispatchResult<GpuOnsetEnvelopeOutput>> {
30
+ const { device } = gpu;
31
+
32
+ const { nFrames, nMels, melFlat, diffMethod } = input;
33
+ if (melFlat.length !== nFrames * nMels) {
34
+ throw new Error("@octoseq/mir: melFlat length mismatch");
35
+ }
36
+
37
+ const melBuffer = createAndWriteStorageBuffer(gpu, melFlat);
38
+
39
+ const outByteLen = byteSizeF32(nFrames);
40
+ const outBuffer = createStorageOutBuffer(gpu, outByteLen);
41
+ const readback = createReadbackBuffer(gpu, outByteLen);
42
+
43
+ const shader = device.createShaderModule({ code: onsetEnvelopeWGSL });
44
+ const pipeline = device.createComputePipeline({
45
+ layout: "auto",
46
+ compute: { module: shader, entryPoint: "main" },
47
+ });
48
+
49
+ const diffU32 = diffMethod === "abs" ? 1 : 0;
50
+ const params = createUniformBufferU32x4(gpu, new Uint32Array([nMels, nFrames, diffU32, 0]));
51
+
52
+ const bindGroup = device.createBindGroup({
53
+ layout: pipeline.getBindGroupLayout(0),
54
+ entries: [
55
+ { binding: 0, resource: { buffer: melBuffer } },
56
+ { binding: 1, resource: { buffer: outBuffer } },
57
+ { binding: 2, resource: { buffer: params } },
58
+ ],
59
+ });
60
+
61
+ const encoder = device.createCommandEncoder();
62
+ const pass = encoder.beginComputePass();
63
+ pass.setPipeline(pipeline);
64
+ pass.setBindGroup(0, bindGroup);
65
+
66
+ const wg = Math.ceil(nFrames / 256);
67
+ pass.dispatchWorkgroups(wg);
68
+ pass.end();
69
+
70
+ const { value: bytes, timing } = await submitAndReadback(gpu, encoder, outBuffer, readback, outByteLen);
71
+
72
+ melBuffer.destroy();
73
+ outBuffer.destroy();
74
+ params.destroy();
75
+ readback.destroy();
76
+
77
+ return {
78
+ value: { out: new Float32Array(bytes) },
79
+ timing,
80
+ };
81
+ }
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Minimal WebGPU type declarations.
3
+ *
4
+ * Why this exists:
5
+ * - TypeScript's built-in lib set does not always include WebGPU types in all environments.
6
+ * - We avoid adding extra dependencies in this scaffold package.
7
+ *
8
+ * These declarations are intentionally minimal and are designed to *merge* with real WebGPU
9
+ * types when they are available (interface merging), rather than conflicting.
10
+ */
11
+
12
+ export { };
13
+
14
+ declare global {
15
+ interface Navigator {
16
+ gpu?: GPU;
17
+ }
18
+
19
+ interface GPU {
20
+ requestAdapter(options?: GPURequestAdapterOptions): Promise<GPUAdapter | null>;
21
+ }
22
+
23
+ interface GPURequestAdapterOptions {
24
+ powerPreference?: "low-power" | "high-performance";
25
+ forceFallbackAdapter?: boolean;
26
+ }
27
+
28
+ interface GPUAdapter {
29
+ requestDevice(descriptor?: GPUDeviceDescriptor): Promise<GPUDevice>;
30
+ }
31
+
32
+ interface GPUDeviceDescriptor {
33
+ requiredFeatures?: Iterable<string>;
34
+ requiredLimits?: Record<string, number>;
35
+ label?: string;
36
+ }
37
+
38
+ interface GPUDevice {
39
+ readonly queue: GPUQueue;
40
+ createBuffer(descriptor: GPUBufferDescriptor): GPUBuffer;
41
+ createShaderModule(descriptor: GPUShaderModuleDescriptor): GPUShaderModule;
42
+ createComputePipeline(descriptor: GPUComputePipelineDescriptor): GPUComputePipeline;
43
+ createBindGroupLayout(descriptor: GPUBindGroupLayoutDescriptor): GPUBindGroupLayout;
44
+ createPipelineLayout(descriptor: GPUPipelineLayoutDescriptor): GPUPipelineLayout;
45
+ createBindGroup(descriptor: GPUBindGroupDescriptor): GPUBindGroup;
46
+ createCommandEncoder(descriptor?: GPUCommandEncoderDescriptor): GPUCommandEncoder;
47
+ }
48
+
49
+ interface GPUQueue {
50
+ writeBuffer(
51
+ buffer: GPUBuffer,
52
+ bufferOffset: number,
53
+ data: BufferSource,
54
+ dataOffset?: number,
55
+ size?: number
56
+ ): void;
57
+ submit(commandBuffers: Iterable<GPUCommandBuffer>): void;
58
+ }
59
+
60
+ interface GPUBuffer {
61
+ mapAsync(mode: number, offset?: number, size?: number): Promise<void>;
62
+ getMappedRange(offset?: number, size?: number): ArrayBuffer;
63
+ unmap(): void;
64
+ destroy(): void;
65
+ }
66
+
67
+ interface GPUBufferDescriptor {
68
+ size: number;
69
+ usage: number;
70
+ mappedAtCreation?: boolean;
71
+ label?: string;
72
+ }
73
+
74
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
75
+ interface GPUShaderModule { }
76
+
77
+ interface GPUShaderModuleDescriptor {
78
+ code: string;
79
+ label?: string;
80
+ }
81
+
82
+ interface GPUComputePipeline {
83
+ getBindGroupLayout(index: number): GPUBindGroupLayout;
84
+ }
85
+
86
+ interface GPUComputePipelineDescriptor {
87
+ layout?: GPUPipelineLayout | "auto";
88
+ compute: {
89
+ module: GPUShaderModule;
90
+ entryPoint: string;
91
+ };
92
+ label?: string;
93
+ }
94
+
95
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
96
+ interface GPUBindGroupLayout { }
97
+
98
+ interface GPUBindGroupLayoutDescriptor {
99
+ entries: Array<{
100
+ binding: number;
101
+ visibility: number;
102
+ buffer?: { type?: "uniform" | "storage" | "read-only-storage" };
103
+ }>;
104
+ label?: string;
105
+ }
106
+
107
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
108
+ interface GPUPipelineLayout { }
109
+
110
+ interface GPUPipelineLayoutDescriptor {
111
+ bindGroupLayouts: GPUBindGroupLayout[];
112
+ label?: string;
113
+ }
114
+
115
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
116
+ interface GPUBindGroup { }
117
+
118
+ interface GPUBindGroupDescriptor {
119
+ layout: GPUBindGroupLayout;
120
+ entries: Array<{ binding: number; resource: { buffer: GPUBuffer } }>;
121
+ label?: string;
122
+ }
123
+
124
+ interface GPUCommandEncoder {
125
+ beginComputePass(descriptor?: GPUComputePassDescriptor): GPUComputePassEncoder;
126
+ copyBufferToBuffer(
127
+ source: GPUBuffer,
128
+ sourceOffset: number,
129
+ destination: GPUBuffer,
130
+ destinationOffset: number,
131
+ size: number
132
+ ): void;
133
+ finish(): GPUCommandBuffer;
134
+ }
135
+
136
+ interface GPUCommandEncoderDescriptor {
137
+ label?: string;
138
+ }
139
+
140
+ interface GPUComputePassEncoder {
141
+ setPipeline(pipeline: GPUComputePipeline): void;
142
+ setBindGroup(index: number, bindGroup: GPUBindGroup): void;
143
+ dispatchWorkgroups(
144
+ workgroupCountX: number,
145
+ workgroupCountY?: number,
146
+ workgroupCountZ?: number
147
+ ): void;
148
+ end(): void;
149
+ }
150
+
151
+ interface GPUComputePassDescriptor {
152
+ label?: string;
153
+ }
154
+
155
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
156
+ interface GPUCommandBuffer { }
157
+
158
+ // Common WebGPU constants. These are numbers in the real API.
159
+ // We declare them as `var` so they exist at runtime only if provided by the environment.
160
+ // (We only use these constants when running in a WebGPU-capable browser.)
161
+ var GPUBufferUsage: {
162
+ MAP_READ: number;
163
+ COPY_DST: number;
164
+ COPY_SRC: number;
165
+ STORAGE: number;
166
+ UNIFORM: number;
167
+ };
168
+
169
+ var GPUMapMode: {
170
+ READ: number;
171
+ };
172
+
173
+ var GPUShaderStage: {
174
+ COMPUTE: number;
175
+ };
176
+ }
package/src/index.ts ADDED
@@ -0,0 +1,121 @@
1
+ export type MirVersion = "0.1.0";
2
+
3
+ export type {
4
+ MirBackend,
5
+ MirRunTimings,
6
+ MirRunMeta,
7
+ Mir1DResult,
8
+ Mir2DResult,
9
+ MirResult,
10
+ MirFunctionId,
11
+ MirRunRequest,
12
+ MirAudioPayload
13
+ } from "./types";
14
+
15
+ export const MIR_VERSION: MirVersion = "0.1.0";
16
+
17
+ // ----------------------------
18
+ // Core Types
19
+ // ----------------------------
20
+
21
+ export type AudioBufferLike = {
22
+ sampleRate: number;
23
+ getChannelData(channel: number): Float32Array;
24
+ numberOfChannels: number;
25
+ };
26
+
27
+ // ----------------------------
28
+ // GPU
29
+ // ----------------------------
30
+
31
+ export { MirGPU } from "./gpu/context";
32
+
33
+ // ----------------------------
34
+ // Shared runner (main thread / worker)
35
+ // ----------------------------
36
+
37
+ export { runMir } from "./runner/runMir";
38
+
39
+ // ----------------------------
40
+ // Spectrogram (shared primitive)
41
+ // ----------------------------
42
+
43
+ export type { SpectrogramConfig, Spectrogram } from "./dsp/spectrogram";
44
+ export { spectrogram } from "./dsp/spectrogram";
45
+
46
+ // ----------------------------
47
+ // Derived spectral features (CPU, reuse spectrogram)
48
+ // ----------------------------
49
+
50
+ export { spectralCentroid, spectralFlux } from "./dsp/spectral";
51
+
52
+ // ----------------------------
53
+ // Onsets / Peaks
54
+ // ----------------------------
55
+
56
+ export type { OnsetEnvelope, OnsetEnvelopeOptions, OnsetEnvelopeGpuResult } from "./dsp/onset";
57
+ export { onsetEnvelopeFromSpectrogram, onsetEnvelopeFromMel, onsetEnvelopeFromMelGpu } from "./dsp/onset";
58
+
59
+ export type { PeakPickEvent, PeakPickOptions } from "./dsp/peakPick";
60
+ export { peakPick } from "./dsp/peakPick";
61
+
62
+ // ----------------------------
63
+ // HPSS
64
+ // ----------------------------
65
+
66
+ export type { SpectrogramLike2D, HpssOptions } from "./dsp/hpss";
67
+ export { hpss } from "./dsp/hpss";
68
+
69
+ // ----------------------------
70
+ // MFCC + Deltas
71
+ // ----------------------------
72
+
73
+ export type { MfccOptions, MfccResult, DeltaOptions, Features2D } from "./dsp/mfcc";
74
+ export { mfcc, delta, deltaDelta } from "./dsp/mfcc";
75
+
76
+ // ----------------------------
77
+ // Mel spectrogram
78
+ // ----------------------------
79
+
80
+ export type { MelConfig, MelSpectrogram } from "./dsp/mel";
81
+ export { melSpectrogram } from "./dsp/mel";
82
+
83
+ // ----------------------------
84
+ // Visualisation utilities
85
+ // ----------------------------
86
+
87
+ export { normaliseForWaveform } from "./util/normalise";
88
+ export type { Spectrogram2D, SpectrogramToDbOptions } from "./util/display";
89
+ export { spectrogramToDb, clampDb } from "./util/display";
90
+
91
+ // ----------------------------
92
+ // Utility helpers
93
+ // ----------------------------
94
+
95
+ export type { MinMax } from "./util/stats";
96
+ export { minMax } from "./util/stats";
97
+
98
+ // ----------------------------
99
+ // Search (deterministic within-track similarity)
100
+ // ----------------------------
101
+
102
+ export type { MirFingerprintV1 } from "./search/fingerprintV1";
103
+ export { fingerprintV1 } from "./search/fingerprintV1";
104
+
105
+ export type { MirFingerprintVectorWeights } from "./search/similarity";
106
+ export { fingerprintToVectorV1, similarityFingerprintV1 } from "./search/similarity";
107
+
108
+ export type { MirSearchCandidate, MirSearchOptionsV1, MirSearchResultV1 } from "./search/searchTrackV1";
109
+ export { searchTrackV1 } from "./search/searchTrackV1";
110
+
111
+ export type { MirRefinementCandidateLabelV1, MirSearchCurveKindV1, MirSearchGuidedOptionsV1, MirSearchResultV1Guided } from "./search/searchTrackV1Guided";
112
+ export { searchTrackV1Guided } from "./search/searchTrackV1Guided";
113
+
114
+ /**
115
+ * Backwards-compat placeholder from the initial skeleton.
116
+ *
117
+ * Note: kept so existing internal references/tests don't break.
118
+ */
119
+ export function helloMir(name = "world") {
120
+ return `Hello, ${name} from @octoseq/mir v${MIR_VERSION}`;
121
+ }