@intomind/sdk 0.0.0-stage → 1.4.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.
package/LICENSING.md ADDED
@@ -0,0 +1,45 @@
1
+ # Licensing
2
+
3
+ This project is free software under the GNU Affero General Public License,
4
+ version 3. The full text is in `LICENSE`. It covers the code in this
5
+ repository.
6
+
7
+ A commercial license is also available. The two are alternatives: use
8
+ either one.
9
+
10
+ ## What the Affero license asks of you
11
+
12
+ You may use, study, change, and share this software. If you share it, or
13
+ a work based on it, you pass on the same freedoms and the source. The
14
+ Affero clause adds one thing to the ordinary General Public License: if
15
+ you run a modified version as a network service, the people using that
16
+ service can ask you for its source.
17
+
18
+ Building your own product on top of these libraries is what they are for.
19
+ Running them, recording with them, and publishing what you make with them
20
+ are not affected at all. The license is about the software, never about
21
+ the data you record with it.
22
+
23
+ ## When you want the commercial license instead
24
+
25
+ Take the commercial license when you want to build a closed product on
26
+ this code, or run a modified service without publishing your changes.
27
+ Write to contact@intomind.com.
28
+
29
+ IntoMind can offer both because IntoMind holds the copyright in the
30
+ code, which is also why contributions are covered by the agreement in
31
+ `CONTRIBUTING.md`.
32
+
33
+ ## Contributions
34
+
35
+ The first time you contribute, you sign a contributor license agreement.
36
+ It says you wrote what you are contributing and that you give IntoMind
37
+ the rights to use it under both licenses, while you keep the copyright
38
+ in your own work. `CONTRIBUTING.md` has the detail and the process.
39
+
40
+ ## Trademarks
41
+
42
+ IntoMind is a trademark of IntoMind, Inc. The license covers the code,
43
+ not the name. You may say your product works with an IntoMind device.
44
+ You may not call your product IntoMind or use the mark in a way that
45
+ suggests IntoMind made or endorsed it.
package/README.md CHANGED
@@ -1,3 +1,148 @@
1
- # Temporary Holding Version
1
+ # @intomind/sdk
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The IntoMind instrument client for JavaScript. One package, every IntoMind
4
+ device, in a browser and in Node.
5
+
6
+ ```ts
7
+ import { requestAndConnect } from "@intomind/sdk";
8
+
9
+ const device = await requestAndConnect({
10
+ onEvent(event) {
11
+ if (event.type === "samples") plot(event.batch);
12
+ if (event.type === "gap") mark(event.gap);
13
+ },
14
+ });
15
+ await device.send(device.session.startStream());
16
+ ```
17
+
18
+ It owns the protocol spoken to a device, the session that turns
19
+ notifications into events, the clock that puts those events on the host's
20
+ timeline, and one transport for the browser. It knows nothing about any
21
+ particular device beyond what that device tells it, and nothing about any
22
+ application built on top of it.
23
+
24
+ ## What is in here
25
+
26
+ | | |
27
+ |---|---|
28
+ | `src/protocol.ts` | the wire, and nothing else |
29
+ | `src/session.ts` | one device as a state machine: bytes in, events out |
30
+ | `src/timebase.ts` | device time onto host time, and what it refuses to believe |
31
+ | `src/web-bluetooth.ts` | the browser transport, and the only file that touches a radio |
32
+ | `src/index.ts` | the public surface |
33
+
34
+ The protocol, the session, and the timebase do no input and no output.
35
+ They take bytes that arrived and hand back bytes to send, so they run over
36
+ whatever Bluetooth stack you already have, on whatever runtime you already
37
+ use, and they can be tested without either.
38
+
39
+ ```ts
40
+ import { Session, protocol } from "@intomind/sdk";
41
+
42
+ const session = new Session();
43
+ session.onDeviceInfo(await readDeviceInfoSomehow());
44
+ for (const event of session.onNotification(protocol.FILL.EEG_DATA, notification)) {
45
+ // ...
46
+ }
47
+ ```
48
+
49
+ ## Capabilities are the device's answer, never this package's assumption
50
+
51
+ A device declares what it is over the protocol, and everything follows
52
+ from that declaration. The channel count, the converter's resolution and
53
+ reference, the rates it offers, whether it can detect lead-off, whether it
54
+ carries a model: all of it is asked and none of it is assumed.
55
+
56
+ ```ts
57
+ session.requireInfo().channels // what the device said
58
+ session.can("model") // a capability bit, not a version number
59
+ session.setLeadoff(true) // throws NotCapable if the device never claimed it
60
+ ```
61
+
62
+ A table of specific hardware in this package is a defect. A capability the
63
+ device does not claim is not asked for, and asking anyway throws rather
64
+ than putting a byte on the wire the device will refuse.
65
+
66
+ ## The timeline is never silently repaired
67
+
68
+ Every sample carries the device's own index and the device time of its own
69
+ conversion. A forward step in that index is a loss with an exact count. A
70
+ step that is not forward is a break whose extent is not a number, and this
71
+ package says so rather than returning a count that would be a fiction.
72
+
73
+ ```ts
74
+ if (event.type === "gap") {
75
+ event.gap.samplesLost; // a number, or null for a break
76
+ }
77
+ ```
78
+
79
+ A gap is emitted before the samples that follow it, so a caller writing
80
+ samples down writes the gap down first. Nothing splices.
81
+
82
+ ## The contract is tested, not assumed
83
+
84
+ `contract/conformance.json` is emitted by the firmware from the codec the
85
+ device itself runs. Every message this package decodes, it decodes to the
86
+ fields that file states, and every malformed one it refuses for the reason
87
+ that file states: truncated, invalid, or reserved, which are three
88
+ different errors because the contract treats them as three different
89
+ things.
90
+
91
+ ```
92
+ npm test
93
+ ```
94
+
95
+ No device, no network, no build step. That is the command, and there is no
96
+ other. It needs Node 22.18 or newer, which runs the TypeScript as it is
97
+ written. `npm run build` produces the JavaScript that is published, which
98
+ runs on Node 20 and in any current browser.
99
+
100
+ ## Time
101
+
102
+ A device's clock is a different crystal from the host's. The fit between
103
+ them is a line, and one exchange cannot tell a clock difference from a slow
104
+ answer, so one exchange fixes an offset and claims no rate. A skew beyond a
105
+ thousand parts per million, or a slope whose standard error is worse than a
106
+ hundred parts per million, is refused rather than believed. The offset is
107
+ kept, because the offset is the part that was measured.
108
+
109
+ ```ts
110
+ await device.timeSync();
111
+ device.session.timebase?.fit; // skewUsed says whether the rate is real
112
+ device.session.hostTime(batch.deviceTime);
113
+ ```
114
+
115
+ ## The model
116
+
117
+ A device can carry an encoder that turns a window of signal into an
118
+ embedding, and a head that turns that embedding into a few outputs. A head
119
+ is weights, never code.
120
+
121
+ ```ts
122
+ import { buildHead, quantizeEmbedding, evaluateHead, decodeHead } from "@intomind/sdk";
123
+
124
+ const blob = buildHead(weights, bias, scale, { name: "focus" });
125
+ evaluateHead(decodeHead(blob), quantizeEmbedding(embedding));
126
+ ```
127
+
128
+ The embedding is quantized to a fixed scale that is part of the contract,
129
+ so what a head produces on a host is what it produces on the device,
130
+ because the device evaluates exactly those integers.
131
+
132
+ ## The browser
133
+
134
+ `web-bluetooth.ts` is the only file that reaches `navigator.bluetooth`.
135
+ Web Bluetooth needs a secure context and a user gesture, so
136
+ `requestDevice` has to be called from a click. Everything else in this
137
+ package works with no browser at all, which is how the tests run.
138
+
139
+ ## License
140
+
141
+ Free software under the GNU Affero General Public License, version 3. A
142
+ commercial license is available for building a closed product on this code
143
+ or running a modified service without publishing the changes. Write to
144
+ contact@intomind.com. See `LICENSING.md`, and `CONTRIBUTING.md` before a
145
+ first pull request.
146
+
147
+ IntoMind is a trademark of IntoMind, Inc. The license covers the code, not
148
+ the name.
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The two digests the contract names, both synchronous.
3
+ *
4
+ * The update service reports a CRC-32 over the bytes it has accepted, and a
5
+ * head blob carries a SHA-256 of everything before it. Both are computed
6
+ * here rather than through a platform interface because `crypto.subtle` is
7
+ * asynchronous in a browser and the codec is not, and because a decoder that
8
+ * has to await a digest cannot refuse a bad blob where it reads it.
9
+ */
10
+ /** Running CRC-32, for a transfer that arrives in pieces. */
11
+ export declare class Crc32 {
12
+ private state;
13
+ /** Fold more bytes into the running checksum, and return this so calls chain. */
14
+ update(data: Uint8Array): this;
15
+ /** The checksum over every slice folded in so far. */
16
+ finish(): number;
17
+ }
18
+ /** CRC-32 of one slice. */
19
+ export declare function crc32(data: Uint8Array): number;
20
+ /** SHA-256 of one slice, as thirty two bytes. */
21
+ export declare function sha256(data: Uint8Array): Uint8Array;
22
+ //# sourceMappingURL=digest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../src/digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgBH,6DAA6D;AAC7D,qBAAa,KAAK;IAChB,OAAO,CAAC,KAAK,CAAc;IAE3B,iFAAiF;IACjF,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAW9B,sDAAsD;IACtD,MAAM,IAAI,MAAM;CAGjB;AAED,2BAA2B;AAC3B,wBAAgB,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAE9C;AAaD,iDAAiD;AACjD,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CA+CnD"}
package/dist/digest.js ADDED
@@ -0,0 +1,109 @@
1
+ /**
2
+ * The two digests the contract names, both synchronous.
3
+ *
4
+ * The update service reports a CRC-32 over the bytes it has accepted, and a
5
+ * head blob carries a SHA-256 of everything before it. Both are computed
6
+ * here rather than through a platform interface because `crypto.subtle` is
7
+ * asynchronous in a browser and the codec is not, and because a decoder that
8
+ * has to await a digest cannot refuse a bad blob where it reads it.
9
+ */
10
+ // CRC-32, IEEE 802.3, the same polynomial zlib uses. Four bits at a time,
11
+ // which keeps the table at sixteen entries.
12
+ const CRC_POLY = 0xedb88320;
13
+ const CRC_TABLE = (() => {
14
+ const t = new Uint32Array(16);
15
+ for (let i = 0; i < 16; i++) {
16
+ let c = i;
17
+ for (let k = 0; k < 4; k++)
18
+ c = c & 1 ? (CRC_POLY ^ (c >>> 1)) >>> 0 : c >>> 1;
19
+ t[i] = c;
20
+ }
21
+ return t;
22
+ })();
23
+ /** Running CRC-32, for a transfer that arrives in pieces. */
24
+ export class Crc32 {
25
+ state = 0xffffffff;
26
+ /** Fold more bytes into the running checksum, and return this so calls chain. */
27
+ update(data) {
28
+ let c = this.state;
29
+ for (let i = 0; i < data.length; i++) {
30
+ c = (c ^ data[i]) >>> 0;
31
+ c = (CRC_TABLE[c & 0xf] ^ (c >>> 4)) >>> 0;
32
+ c = (CRC_TABLE[c & 0xf] ^ (c >>> 4)) >>> 0;
33
+ }
34
+ this.state = c;
35
+ return this;
36
+ }
37
+ /** The checksum over every slice folded in so far. */
38
+ finish() {
39
+ return (this.state ^ 0xffffffff) >>> 0;
40
+ }
41
+ }
42
+ /** CRC-32 of one slice. */
43
+ export function crc32(data) {
44
+ return new Crc32().update(data).finish();
45
+ }
46
+ const K = new Uint32Array([
47
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
48
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
49
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
50
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
51
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
52
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
53
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
54
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
55
+ ]);
56
+ /** SHA-256 of one slice, as thirty two bytes. */
57
+ export function sha256(data) {
58
+ const h = new Uint32Array([
59
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
60
+ ]);
61
+ // Message, a one bit, zeros, then the length in bits as a 64 bit count.
62
+ const bitLength = BigInt(data.length) * 8n;
63
+ const padded = new Uint8Array(((data.length + 9 + 63) >> 6) << 6);
64
+ padded.set(data);
65
+ padded[data.length] = 0x80;
66
+ new DataView(padded.buffer).setBigUint64(padded.length - 8, bitLength, false);
67
+ const w = new Uint32Array(64);
68
+ const block = new DataView(padded.buffer);
69
+ for (let at = 0; at < padded.length; at += 64) {
70
+ for (let i = 0; i < 16; i++)
71
+ w[i] = block.getUint32(at + i * 4, false);
72
+ for (let i = 16; i < 64; i++) {
73
+ const a = w[i - 15];
74
+ const b = w[i - 2];
75
+ const s0 = (rotr(a, 7) ^ rotr(a, 18) ^ (a >>> 3)) >>> 0;
76
+ const s1 = (rotr(b, 17) ^ rotr(b, 19) ^ (b >>> 10)) >>> 0;
77
+ w[i] = (w[i - 16] + s0 + w[i - 7] + s1) >>> 0;
78
+ }
79
+ let [a, b, c, d, e, f, g, hh] = h;
80
+ for (let i = 0; i < 64; i++) {
81
+ const s1 = (rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25)) >>> 0;
82
+ const ch = ((e & f) ^ (~e & g)) >>> 0;
83
+ const t1 = (hh + s1 + ch + K[i] + w[i]) >>> 0;
84
+ const s0 = (rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22)) >>> 0;
85
+ const maj = ((a & b) ^ (a & c) ^ (b & c)) >>> 0;
86
+ const t2 = (s0 + maj) >>> 0;
87
+ hh = g;
88
+ g = f;
89
+ f = e;
90
+ e = (d + t1) >>> 0;
91
+ d = c;
92
+ c = b;
93
+ b = a;
94
+ a = (t1 + t2) >>> 0;
95
+ }
96
+ const round = [a, b, c, d, e, f, g, hh];
97
+ for (let i = 0; i < 8; i++)
98
+ h[i] = (h[i] + round[i]) >>> 0;
99
+ }
100
+ const out = new Uint8Array(32);
101
+ const view = new DataView(out.buffer);
102
+ for (let i = 0; i < 8; i++)
103
+ view.setUint32(i * 4, h[i], false);
104
+ return out;
105
+ }
106
+ function rotr(x, n) {
107
+ return ((x >>> n) | (x << (32 - n))) >>> 0;
108
+ }
109
+ //# sourceMappingURL=digest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.js","sourceRoot":"","sources":["../src/digest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The IntoMind instrument client, for a browser and for Node.
3
+ *
4
+ * The protocol, the session, and the timebase do no input and no output.
5
+ * They are handed bytes that arrived and they hand back bytes to send,
6
+ * which means they work over whatever Bluetooth stack you already have and
7
+ * can be tested without one. `web-bluetooth.ts` is the browser transport,
8
+ * and it is the only file in this package that touches a radio.
9
+ *
10
+ * ```ts
11
+ * import { requestAndConnect } from "@intomind/sdk";
12
+ *
13
+ * const device = await requestAndConnect({
14
+ * onEvent(event) {
15
+ * if (event.type === "samples") write(event.batch);
16
+ * // Written down, never smoothed over.
17
+ * if (event.type === "gap") writeGap(event.gap);
18
+ * },
19
+ * });
20
+ * await device.send(device.session.startStream());
21
+ * ```
22
+ *
23
+ * What a device can do is what the device says it can do. Nothing here
24
+ * holds a table of hardware, and a capability is a bit the device reports
25
+ * rather than a version number this package compares against.
26
+ */
27
+ export * as protocol from "./protocol.ts";
28
+ export { CAPABILITIES, CAPABILITIES_HIGH, DeviceInfo, EMBED_SCALE, FILL, GAIN_BY_CODE, Invalid, MODES, NAME_MAX_COMPOSED, NAME_PREFIX, NO_ENCODER_ID, OPCODES, PRODUCT_NAME, ProtocolError, RATE_BY_CODE, Reserved, SERVICE, Truncated, VERSION, buildHead, composeName, continuity, decodeHead, decodeModelInterval, decodeNameParts, decodePacket, displayNames, evaluateHead, microvolts, nameFits, quantizeEmbedding, uuid, } from "./protocol.ts";
29
+ export type { CapabilityHighName, CapabilityName, Continuity, ModeName, ModelInterval, Envelope, HeadBlob, HeadEntry, OpcodeName, Packet, Prediction, Refusal, Request, Response, Status, UpdateResponse, } from "./protocol.ts";
30
+ export { Batch, NoDeviceInfo, NotCapable, Session, SessionError } from "./session.ts";
31
+ export type { Command, Event, Gap } from "./session.ts";
32
+ export { Exchange, MAX_SKEW_PPM, MAX_SKEW_STDERR_PPM, Timebase } from "./timebase.ts";
33
+ export type { Fit } from "./timebase.ts";
34
+ export { ChecksumMismatch, OffsetMismatch, Refused, Rejected, Transfer, TransferError, Unexpected, activate, } from "./transfer.ts";
35
+ export type { Step } from "./transfer.ts";
36
+ export { Connection, NoBluetooth, connect, hostClock, requestAndConnect, requestDevice } from "./web-bluetooth.ts";
37
+ export type { ConnectOptions, RequestOptions } from "./web-bluetooth.ts";
38
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,WAAW,EACX,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,KAAK,EACL,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,OAAO,EACP,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,SAAS,EACT,OAAO,EACP,SAAS,EACT,WAAW,EACX,UAAU,EACV,UAAU,EACV,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,IAAI,GACL,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,UAAU,EACV,MAAM,EACN,UAAU,EACV,OAAO,EACP,OAAO,EACP,QAAQ,EACR,MAAM,EACN,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACtF,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAExD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACtF,YAAY,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,UAAU,EACV,QAAQ,GACT,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnH,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The IntoMind instrument client, for a browser and for Node.
3
+ *
4
+ * The protocol, the session, and the timebase do no input and no output.
5
+ * They are handed bytes that arrived and they hand back bytes to send,
6
+ * which means they work over whatever Bluetooth stack you already have and
7
+ * can be tested without one. `web-bluetooth.ts` is the browser transport,
8
+ * and it is the only file in this package that touches a radio.
9
+ *
10
+ * ```ts
11
+ * import { requestAndConnect } from "@intomind/sdk";
12
+ *
13
+ * const device = await requestAndConnect({
14
+ * onEvent(event) {
15
+ * if (event.type === "samples") write(event.batch);
16
+ * // Written down, never smoothed over.
17
+ * if (event.type === "gap") writeGap(event.gap);
18
+ * },
19
+ * });
20
+ * await device.send(device.session.startStream());
21
+ * ```
22
+ *
23
+ * What a device can do is what the device says it can do. Nothing here
24
+ * holds a table of hardware, and a capability is a bit the device reports
25
+ * rather than a version number this package compares against.
26
+ */
27
+ export * as protocol from "./protocol.js";
28
+ export { CAPABILITIES, CAPABILITIES_HIGH, DeviceInfo, EMBED_SCALE, FILL, GAIN_BY_CODE, Invalid, MODES, NAME_MAX_COMPOSED, NAME_PREFIX, NO_ENCODER_ID, OPCODES, PRODUCT_NAME, ProtocolError, RATE_BY_CODE, Reserved, SERVICE, Truncated, VERSION, buildHead, composeName, continuity, decodeHead, decodeModelInterval, decodeNameParts, decodePacket, displayNames, evaluateHead, microvolts, nameFits, quantizeEmbedding, uuid, } from "./protocol.js";
29
+ export { Batch, NoDeviceInfo, NotCapable, Session, SessionError } from "./session.js";
30
+ export { Exchange, MAX_SKEW_PPM, MAX_SKEW_STDERR_PPM, Timebase } from "./timebase.js";
31
+ export { ChecksumMismatch, OffsetMismatch, Refused, Rejected, Transfer, TransferError, Unexpected, activate, } from "./transfer.js";
32
+ export { Connection, NoBluetooth, connect, hostClock, requestAndConnect, requestDevice } from "./web-bluetooth.js";
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,WAAW,EACX,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,KAAK,EACL,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,OAAO,EACP,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,SAAS,EACT,OAAO,EACP,SAAS,EACT,WAAW,EACX,UAAU,EACV,UAAU,EACV,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,IAAI,GACL,MAAM,eAAe,CAAC;AAqBvB,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGtF,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGtF,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,UAAU,EACV,QAAQ,GACT,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}