@bitbaum/chatkit 0.2.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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +132 -0
  3. package/dist/attachments.d.ts +72 -0
  4. package/dist/attachments.d.ts.map +1 -0
  5. package/dist/attachments.js +64 -0
  6. package/dist/attachments.js.map +1 -0
  7. package/dist/composer.d.ts +34 -0
  8. package/dist/composer.d.ts.map +1 -0
  9. package/dist/composer.js +41 -0
  10. package/dist/composer.js.map +1 -0
  11. package/dist/dictation.d.ts +60 -0
  12. package/dist/dictation.d.ts.map +1 -0
  13. package/dist/dictation.js +93 -0
  14. package/dist/dictation.js.map +1 -0
  15. package/dist/index.d.ts +11 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +11 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/markdown.d.ts +64 -0
  20. package/dist/markdown.d.ts.map +1 -0
  21. package/dist/markdown.js +129 -0
  22. package/dist/markdown.js.map +1 -0
  23. package/dist/react/Composer.d.ts +85 -0
  24. package/dist/react/Composer.d.ts.map +1 -0
  25. package/dist/react/Composer.js +132 -0
  26. package/dist/react/Composer.js.map +1 -0
  27. package/dist/react/Markdown.d.ts +27 -0
  28. package/dist/react/Markdown.d.ts.map +1 -0
  29. package/dist/react/Markdown.js +62 -0
  30. package/dist/react/Markdown.js.map +1 -0
  31. package/dist/react/Thread.d.ts +90 -0
  32. package/dist/react/Thread.d.ts.map +1 -0
  33. package/dist/react/Thread.js +64 -0
  34. package/dist/react/Thread.js.map +1 -0
  35. package/dist/react/hooks.d.ts +40 -0
  36. package/dist/react/hooks.d.ts.map +1 -0
  37. package/dist/react/hooks.js +99 -0
  38. package/dist/react/hooks.js.map +1 -0
  39. package/dist/react/icons.d.ts +12 -0
  40. package/dist/react/icons.d.ts.map +1 -0
  41. package/dist/react/icons.js +21 -0
  42. package/dist/react/icons.js.map +1 -0
  43. package/dist/react/index.d.ts +21 -0
  44. package/dist/react/index.d.ts.map +1 -0
  45. package/dist/react/index.js +16 -0
  46. package/dist/react/index.js.map +1 -0
  47. package/dist/react/use-attachments.d.ts +26 -0
  48. package/dist/react/use-attachments.d.ts.map +1 -0
  49. package/dist/react/use-attachments.js +202 -0
  50. package/dist/react/use-attachments.js.map +1 -0
  51. package/dist/react/use-dictation.d.ts +49 -0
  52. package/dist/react/use-dictation.d.ts.map +1 -0
  53. package/dist/react/use-dictation.js +365 -0
  54. package/dist/react/use-dictation.js.map +1 -0
  55. package/dist/scroll.d.ts +13 -0
  56. package/dist/scroll.d.ts.map +1 -0
  57. package/dist/scroll.js +11 -0
  58. package/dist/scroll.js.map +1 -0
  59. package/package.json +83 -0
  60. package/styles.css +689 -0
@@ -0,0 +1,365 @@
1
+ "use client";
2
+ import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from "react";
3
+ import { MAX_RECORDING_MS, PERMISSION_WAIT_MS, RECORDING_MIME_CANDIDATES, START_TIMEOUT_MS, deadRecogniserStillTrusted, fallbackCanRescue, problemFor, problemForRecording, } from "../dictation.js";
4
+ function recogniser() {
5
+ if (typeof window === "undefined")
6
+ return undefined;
7
+ const w = window;
8
+ return w.SpeechRecognition ?? w.webkitSpeechRecognition;
9
+ }
10
+ function canRecord() {
11
+ return (typeof window !== "undefined" &&
12
+ typeof MediaRecorder !== "undefined" &&
13
+ !!navigator.mediaDevices?.getUserMedia);
14
+ }
15
+ const noSubscribe = () => () => { };
16
+ const DEFAULT_REMEMBER_KEY = "chatkit.dictation.recogniser-dead.v1";
17
+ function readDead(key) {
18
+ if (!key)
19
+ return false;
20
+ try {
21
+ const raw = window.localStorage.getItem(key);
22
+ return deadRecogniserStillTrusted(raw === null ? null : Number(raw));
23
+ }
24
+ catch {
25
+ return false;
26
+ }
27
+ }
28
+ function rememberDead(key) {
29
+ if (!key)
30
+ return;
31
+ try {
32
+ window.localStorage.setItem(key, String(Date.now()));
33
+ }
34
+ catch {
35
+ /* private mode — the person simply waits again next time */
36
+ }
37
+ }
38
+ async function awaitingPermission() {
39
+ try {
40
+ const s = await navigator.permissions.query({ name: "microphone" });
41
+ return s.state === "prompt";
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ async function postAudio(url, audio, locale) {
48
+ const body = new FormData();
49
+ const ext = audio.type.includes("mp4") ? "m4a" : audio.type.includes("ogg") ? "ogg" : "webm";
50
+ body.append("audio", new File([audio], `voice.${ext}`, { type: audio.type || "audio/webm" }));
51
+ body.append("locale", locale);
52
+ const res = await fetch(url, { method: "POST", body });
53
+ if (!res.ok)
54
+ throw new Error(`transcription ${res.status}`);
55
+ const data = (await res.json().catch(() => ({})));
56
+ return typeof data.text === "string" ? data.text.trim() : "";
57
+ }
58
+ /**
59
+ * Speaking instead of typing — with a microphone that is never a dead button.
60
+ *
61
+ * Browser recogniser first (unless `prefer: "server"`); when it is missing, or
62
+ * accepts `start()` and then says nothing (heidi measured nine silent seconds
63
+ * on a real Chromium), the same press RECORDS and the server transcribes. A
64
+ * failure always ends as a `problem` the composer shows in words.
65
+ *
66
+ * Every microphone track is stopped on every exit path. A mic left open on
67
+ * someone's device because a request failed is the worst bug a chat can have.
68
+ */
69
+ export function useDictation(opts) {
70
+ const { prefer = "browser", maxRecordingMs = MAX_RECORDING_MS } = opts;
71
+ const rememberKey = opts.rememberKey === undefined ? DEFAULT_REMEMBER_KEY : opts.rememberKey;
72
+ const hasServer = Boolean(opts.transcribe || opts.transcribeUrl);
73
+ const supported = useSyncExternalStore(noSubscribe, () => Boolean(recogniser()) || (hasServer && canRecord()), () => false);
74
+ const [status, setStatus] = useState("idle");
75
+ const [startedAt, setStartedAt] = useState(null);
76
+ const [problem, setProblem] = useState(null);
77
+ // Latest options in refs, assigned in an effect (never during render), so a
78
+ // take that outlives a re-render calls the current callbacks.
79
+ const optsRef = useRef(opts);
80
+ useEffect(() => {
81
+ optsRef.current = opts;
82
+ });
83
+ const recRef = useRef(null);
84
+ const recorderRef = useRef(null);
85
+ const streamRef = useRef(null);
86
+ const cancelledRef = useRef(false);
87
+ const capTimer = useRef(null);
88
+ const locale = useCallback(() => {
89
+ const l = optsRef.current.lang ??
90
+ (typeof document !== "undefined" ? document.documentElement.lang : "") ??
91
+ "";
92
+ return l || (typeof navigator !== "undefined" ? navigator.language : "en") || "en";
93
+ }, []);
94
+ const releaseMic = useCallback(() => {
95
+ streamRef.current?.getTracks().forEach((t) => t.stop());
96
+ streamRef.current = null;
97
+ if (capTimer.current) {
98
+ clearTimeout(capTimer.current);
99
+ capTimer.current = null;
100
+ }
101
+ }, []);
102
+ const deliver = useCallback((said) => {
103
+ const t = said.trim();
104
+ if (t)
105
+ optsRef.current.onText(t);
106
+ else
107
+ setProblem("silence");
108
+ }, []);
109
+ const transcribe = useCallback(async (audio) => {
110
+ const o = optsRef.current;
111
+ const lang = locale().split("-")[0] ?? "en";
112
+ if (o.transcribe)
113
+ return o.transcribe(audio, lang);
114
+ if (o.transcribeUrl)
115
+ return postAudio(o.transcribeUrl, audio, lang);
116
+ throw new Error("no server leg");
117
+ }, [locale]);
118
+ /** The server leg: record, then transcribe. */
119
+ const record = useCallback(async () => {
120
+ if (!canRecord() || !(optsRef.current.transcribe || optsRef.current.transcribeUrl)) {
121
+ setProblem("unavailable");
122
+ setStatus("idle");
123
+ return;
124
+ }
125
+ setProblem(null);
126
+ cancelledRef.current = false;
127
+ let stream;
128
+ try {
129
+ stream = await navigator.mediaDevices.getUserMedia({ audio: true });
130
+ }
131
+ catch (e) {
132
+ setProblem(problemForRecording(e));
133
+ setStatus("idle");
134
+ return;
135
+ }
136
+ streamRef.current = stream;
137
+ let rec;
138
+ try {
139
+ const mime = RECORDING_MIME_CANDIDATES.find((m) => MediaRecorder.isTypeSupported?.(m));
140
+ rec = mime ? new MediaRecorder(stream, { mimeType: mime }) : new MediaRecorder(stream);
141
+ }
142
+ catch (e) {
143
+ releaseMic();
144
+ setProblem(problemForRecording(e));
145
+ setStatus("idle");
146
+ return;
147
+ }
148
+ const chunks = [];
149
+ rec.ondataavailable = (e) => {
150
+ if (e.data && e.data.size > 0)
151
+ chunks.push(e.data);
152
+ };
153
+ rec.onstop = async () => {
154
+ releaseMic();
155
+ recorderRef.current = null;
156
+ setStartedAt(null);
157
+ if (cancelledRef.current) {
158
+ setStatus("idle");
159
+ return;
160
+ }
161
+ const audio = new Blob(chunks, { type: rec.mimeType || "audio/webm" });
162
+ if (audio.size === 0) {
163
+ setProblem("silence");
164
+ setStatus("idle");
165
+ return;
166
+ }
167
+ setStatus("transcribing");
168
+ try {
169
+ deliver(await transcribe(audio));
170
+ }
171
+ catch {
172
+ setProblem("unavailable");
173
+ }
174
+ finally {
175
+ setStatus("idle");
176
+ }
177
+ };
178
+ recorderRef.current = rec;
179
+ rec.start();
180
+ setStatus("listening");
181
+ setStartedAt(Date.now());
182
+ capTimer.current = setTimeout(() => {
183
+ if (recorderRef.current?.state === "recording")
184
+ recorderRef.current.stop();
185
+ }, maxRecordingMs);
186
+ }, [deliver, maxRecordingMs, releaseMic, transcribe]);
187
+ /** The browser leg, with the silent-recogniser watchdog. */
188
+ const listen = useCallback((Ctor) => {
189
+ setProblem(null);
190
+ cancelledRef.current = false;
191
+ const rec = new Ctor();
192
+ rec.lang = locale();
193
+ // Whole thoughts, not one breath: a take ends when the person presses
194
+ // confirm (or the cap), not at the first pause.
195
+ rec.continuous = true;
196
+ rec.interimResults = false;
197
+ const current = () => recRef.current === rec;
198
+ const heard = [];
199
+ let started = false;
200
+ let handedOff = false;
201
+ const finish = (next) => {
202
+ if (!current())
203
+ return;
204
+ recRef.current = null;
205
+ if (capTimer.current) {
206
+ clearTimeout(capTimer.current);
207
+ capTimer.current = null;
208
+ }
209
+ setStatus("idle");
210
+ setStartedAt(null);
211
+ if (next)
212
+ setProblem(next);
213
+ };
214
+ const handOff = () => {
215
+ // The recogniser cannot do this here — record instead, and do not make
216
+ // the person rediscover that on the next press.
217
+ handedOff = true;
218
+ rememberDead(rememberKey);
219
+ finish(null);
220
+ try {
221
+ rec.abort();
222
+ }
223
+ catch {
224
+ /* already gone */
225
+ }
226
+ void record();
227
+ };
228
+ rec.onstart = () => {
229
+ started = true;
230
+ };
231
+ rec.onresult = (event) => {
232
+ for (let i = event.resultIndex; i < event.results.length; i++) {
233
+ const r = event.results[i];
234
+ if (r && r.isFinal !== false)
235
+ heard.push(r[0]?.transcript ?? "");
236
+ }
237
+ };
238
+ rec.onerror = (event) => {
239
+ const why = problemFor(event?.error);
240
+ if (fallbackCanRescue(why) && canRecord() && hasServer && !cancelledRef.current) {
241
+ handOff();
242
+ return;
243
+ }
244
+ finish(why);
245
+ };
246
+ rec.onend = () => {
247
+ if (!current() || handedOff)
248
+ return;
249
+ const said = heard.join(" ");
250
+ finish(null);
251
+ if (!cancelledRef.current)
252
+ deliver(said);
253
+ };
254
+ recRef.current = rec;
255
+ try {
256
+ rec.start();
257
+ }
258
+ catch {
259
+ if (canRecord() && hasServer)
260
+ handOff();
261
+ else
262
+ finish("unavailable");
263
+ return;
264
+ }
265
+ setStatus("listening");
266
+ setStartedAt(Date.now());
267
+ capTimer.current = setTimeout(() => {
268
+ if (current())
269
+ rec.stop();
270
+ }, maxRecordingMs);
271
+ const giveUpAt = Date.now() + PERMISSION_WAIT_MS;
272
+ const watch = () => {
273
+ setTimeout(async () => {
274
+ if (started || !current())
275
+ return;
276
+ if (Date.now() < giveUpAt && (await awaitingPermission())) {
277
+ watch();
278
+ return;
279
+ }
280
+ if (started || !current())
281
+ return;
282
+ if (canRecord() && hasServer)
283
+ handOff();
284
+ else
285
+ finish("unavailable");
286
+ }, START_TIMEOUT_MS);
287
+ };
288
+ watch();
289
+ }, [deliver, hasServer, locale, maxRecordingMs, record, rememberKey]);
290
+ const start = useCallback(() => {
291
+ if (status !== "idle")
292
+ return;
293
+ const Ctor = recogniser();
294
+ const serverFirst = prefer === "server" && canRecord() && hasServer;
295
+ if (Ctor && !serverFirst && !readDead(rememberKey))
296
+ listen(Ctor);
297
+ else if (canRecord() && hasServer)
298
+ void record();
299
+ else if (Ctor)
300
+ listen(Ctor);
301
+ else
302
+ setProblem("unavailable");
303
+ }, [hasServer, listen, prefer, record, rememberKey, status]);
304
+ const stop = useCallback(() => {
305
+ const rec = recRef.current;
306
+ if (rec)
307
+ rec.stop();
308
+ const rc = recorderRef.current;
309
+ if (rc && rc.state !== "inactive")
310
+ rc.stop();
311
+ }, []);
312
+ const cancel = useCallback(() => {
313
+ cancelledRef.current = true;
314
+ const rec = recRef.current;
315
+ recRef.current = null;
316
+ try {
317
+ rec?.abort();
318
+ }
319
+ catch {
320
+ /* already gone */
321
+ }
322
+ const rc = recorderRef.current;
323
+ if (rc && rc.state !== "inactive")
324
+ rc.stop();
325
+ releaseMic();
326
+ setStatus("idle");
327
+ setStartedAt(null);
328
+ }, [releaseMic]);
329
+ const toggle = useCallback(() => {
330
+ // A press while the server is answering is ignored: a second take would
331
+ // race the first one's words into the box.
332
+ if (status === "transcribing")
333
+ return;
334
+ if (status === "listening")
335
+ stop();
336
+ else
337
+ start();
338
+ }, [start, status, stop]);
339
+ // A live microphone must not outlive the component that opened it.
340
+ useEffect(() => () => {
341
+ cancelledRef.current = true;
342
+ try {
343
+ recRef.current?.abort();
344
+ }
345
+ catch {
346
+ /* gone */
347
+ }
348
+ const rc = recorderRef.current;
349
+ if (rc && rc.state !== "inactive")
350
+ rc.stop();
351
+ streamRef.current?.getTracks().forEach((t) => t.stop());
352
+ }, []);
353
+ return {
354
+ supported,
355
+ status,
356
+ startedAt,
357
+ problem,
358
+ clearProblem: () => setProblem(null),
359
+ start,
360
+ stop,
361
+ cancel,
362
+ toggle,
363
+ };
364
+ }
365
+ //# sourceMappingURL=use-dictation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-dictation.js","sourceRoot":"","sources":["../../src/react/use-dictation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * How close to the bottom still counts as "following the conversation". Above
3
+ * this, the reader is reading something older and must not be yanked back
4
+ * every time a token arrives — the bug in every chat here except loki's and
5
+ * orangecat's.
6
+ */
7
+ export declare const FOLLOW_THRESHOLD_PX = 120;
8
+ export declare function isFollowing(el: {
9
+ scrollHeight: number;
10
+ scrollTop: number;
11
+ clientHeight: number;
12
+ }, threshold?: number): boolean;
13
+ //# sourceMappingURL=scroll.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll.d.ts","sourceRoot":"","sources":["../src/scroll.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,wBAAgB,WAAW,CACzB,EAAE,EAAE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,EACrE,SAAS,SAAsB,GAC9B,OAAO,CAET"}
package/dist/scroll.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * How close to the bottom still counts as "following the conversation". Above
3
+ * this, the reader is reading something older and must not be yanked back
4
+ * every time a token arrives — the bug in every chat here except loki's and
5
+ * orangecat's.
6
+ */
7
+ export const FOLLOW_THRESHOLD_PX = 120;
8
+ export function isFollowing(el, threshold = FOLLOW_THRESHOLD_PX) {
9
+ return el.scrollHeight - el.scrollTop - el.clientHeight < threshold;
10
+ }
11
+ //# sourceMappingURL=scroll.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll.js","sourceRoot":"","sources":["../src/scroll.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC,MAAM,UAAU,WAAW,CACzB,EAAqE,EACrE,SAAS,GAAG,mBAAmB;IAE/B,OAAO,EAAE,CAAC,YAAY,GAAG,EAAE,CAAC,SAAS,GAAG,EAAE,CAAC,YAAY,GAAG,SAAS,CAAC;AACtE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,83 @@
1
+ {
2
+ "name": "@bitbaum/chatkit",
3
+ "version": "0.2.1",
4
+ "description": "One chat for every product: a composer with a microphone that always works, a thread that does not fight the reader, messages with copy and retry, and LLM markdown \u2014 the fleet's chat standard as a package.",
5
+ "license": "MIT",
6
+ "author": "Cato",
7
+ "homepage": "https://github.com/bitbaum/chatkit#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/bitbaum/chatkit.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/bitbaum/chatkit/issues"
14
+ },
15
+ "keywords": [
16
+ "chat",
17
+ "composer",
18
+ "voice",
19
+ "dictation",
20
+ "speech-to-text",
21
+ "markdown",
22
+ "react",
23
+ "ai"
24
+ ],
25
+ "type": "module",
26
+ "sideEffects": [
27
+ "*.css"
28
+ ],
29
+ "packageManager": "pnpm@11.25.0",
30
+ "engines": {
31
+ "node": ">=20"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public",
35
+ "provenance": true
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "styles.css"
40
+ ],
41
+ "exports": {
42
+ ".": {
43
+ "types": "./dist/index.d.ts",
44
+ "default": "./dist/index.js"
45
+ },
46
+ "./react": {
47
+ "types": "./dist/react/index.d.ts",
48
+ "default": "./dist/react/index.js"
49
+ },
50
+ "./styles.css": "./styles.css"
51
+ },
52
+ "scripts": {
53
+ "build": "rm -rf dist && tsc -p tsconfig.json",
54
+ "lint": "eslint .",
55
+ "typecheck": "tsc -p tsconfig.json --noEmit",
56
+ "test": "node --test test/*.test.js",
57
+ "check:dist": "git diff --exit-code --stat -- dist",
58
+ "verify": "pnpm run format:check && pnpm run lint && pnpm run typecheck && pnpm run build && pnpm test && pnpm run test:browser",
59
+ "format": "prettier --write .",
60
+ "format:check": "prettier --check .",
61
+ "demo": "esbuild demo/demo.tsx --bundle --jsx=automatic --format=iife --define:process.env.NODE_ENV='\"production\"' --outfile=demo/dist/demo.js --log-level=warning",
62
+ "test:browser": "pnpm run demo && node test/browser.mjs"
63
+ },
64
+ "devDependencies": {
65
+ "@bitbaum/design-tokens": "^1.1.0",
66
+ "@eslint/js": "^10.0.1",
67
+ "@types/node": "^26.4.0",
68
+ "@types/react": "^19.2.18",
69
+ "@types/react-dom": "^19.2.3",
70
+ "esbuild": "^0.28.2",
71
+ "eslint": "^10.9.1",
72
+ "globals": "^17.11.0",
73
+ "playwright": "1.63.0",
74
+ "prettier": "^3.9.6",
75
+ "react": "^19.2.8",
76
+ "react-dom": "^19.2.8",
77
+ "typescript": "^6.0.3",
78
+ "typescript-eslint": "^8.68.0"
79
+ },
80
+ "peerDependencies": {
81
+ "react": ">=18"
82
+ }
83
+ }