@guuey/chat 0.4.0 → 0.6.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.
Files changed (69) hide show
  1. package/dist/hitl.d.ts +58 -0
  2. package/dist/hitl.d.ts.map +1 -0
  3. package/dist/hitl.js +81 -0
  4. package/dist/index.d.ts +3 -2
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +2 -1
  7. package/dist/native/components.d.ts +110 -0
  8. package/dist/native/components.d.ts.map +1 -0
  9. package/dist/native/components.js +341 -0
  10. package/dist/native/markdown.d.ts +31 -0
  11. package/dist/native/markdown.d.ts.map +1 -0
  12. package/dist/native/markdown.js +69 -0
  13. package/dist/native/theme-native.d.ts +27 -0
  14. package/dist/native/theme-native.d.ts.map +1 -0
  15. package/dist/native/theme-native.js +28 -0
  16. package/dist/native/transcript.d.ts +48 -0
  17. package/dist/native/transcript.d.ts.map +1 -0
  18. package/dist/native/transcript.js +86 -0
  19. package/dist/native.d.ts +26 -0
  20. package/dist/native.d.ts.map +1 -0
  21. package/dist/native.js +27 -0
  22. package/dist/plan.d.ts +15 -0
  23. package/dist/plan.d.ts.map +1 -1
  24. package/dist/plan.js +211 -13
  25. package/dist/policy.d.ts +4 -0
  26. package/dist/policy.d.ts.map +1 -1
  27. package/dist/policy.js +2 -0
  28. package/dist/react/components.d.ts +42 -5
  29. package/dist/react/components.d.ts.map +1 -1
  30. package/dist/react/components.js +51 -1
  31. package/dist/react/guuey-chat.d.ts +62 -4
  32. package/dist/react/guuey-chat.d.ts.map +1 -1
  33. package/dist/react/guuey-chat.js +73 -8
  34. package/dist/react/transcript.d.ts +1 -1
  35. package/dist/react/transcript.d.ts.map +1 -1
  36. package/dist/react/transcript.js +2 -2
  37. package/dist/react/use-transcript.d.ts +21 -2
  38. package/dist/react/use-transcript.d.ts.map +1 -1
  39. package/dist/react/use-transcript.js +57 -3
  40. package/dist/react.d.ts +2 -2
  41. package/dist/react.d.ts.map +1 -1
  42. package/dist/react.js +1 -1
  43. package/dist/strings.d.ts +13 -0
  44. package/dist/strings.d.ts.map +1 -1
  45. package/dist/strings.js +8 -0
  46. package/dist/types.d.ts +146 -7
  47. package/dist/types.d.ts.map +1 -1
  48. package/package.json +18 -7
  49. package/src/corpus/README.md +13 -1
  50. package/src/corpus/__snapshots__/corpus.test.ts.snap +304 -0
  51. package/src/corpus/drive.ts +3 -3
  52. package/src/corpus/fixtures.ts +220 -1
  53. package/src/hitl.ts +103 -0
  54. package/src/index.ts +15 -0
  55. package/src/native/components.tsx +812 -0
  56. package/src/native/markdown.tsx +205 -0
  57. package/src/native/theme-native.ts +48 -0
  58. package/src/native/transcript.tsx +189 -0
  59. package/src/native.tsx +63 -0
  60. package/src/plan.ts +233 -20
  61. package/src/policy.ts +4 -0
  62. package/src/react/components.tsx +171 -8
  63. package/src/react/guuey-chat.tsx +143 -9
  64. package/src/react/transcript.tsx +4 -3
  65. package/src/react/use-transcript.ts +83 -5
  66. package/src/react.tsx +3 -1
  67. package/src/strings.ts +25 -0
  68. package/src/types.ts +152 -6
  69. package/styles.css +21 -0
@@ -0,0 +1,205 @@
1
+ /**
2
+ * The R1 markdown surface, React Native projection.
3
+ *
4
+ * Same sanitizer boundary as the web kit (`react/markdown.tsx`), same
5
+ * pipeline: `@silverprotocol/richtext` parses markdown into a TYPED AST in
6
+ * which raw HTML is structurally unrepresentable — `<script>` in model
7
+ * output can only ever be literal text, there is no image node type (the
8
+ * spec's F5 ruling holds structurally), and link `href` is populated
9
+ * upstream only for http/https/mailto (`SAFE_HREF`). This module is pure
10
+ * presentation: AST node → themed RN elements. Navigable links open
11
+ * through `Linking` — the href is already allowlist-gated upstream, so no
12
+ * second gate is re-derived here.
13
+ *
14
+ * Streaming-tolerant by upstream design: an unclosed `**bol` renders as
15
+ * bold-so-far and completes in place as deltas arrive.
16
+ *
17
+ * Prior art: portal's `MarkdownText` (guuey#95) — this is its published,
18
+ * token-driven descendant (colors/fonts come from the kit's resolved
19
+ * `NativeChatTokens`, not an app theme context).
20
+ */
21
+ import type { ReactNode } from "react";
22
+ import { Linking, Text, View } from "react-native";
23
+ import {
24
+ parseRichText,
25
+ type RichTextBlock,
26
+ type RichTextInline,
27
+ } from "@silverprotocol/richtext";
28
+ import type { NativeChatTokens } from "./theme-native.js";
29
+
30
+ function InlineRuns({
31
+ nodes,
32
+ color,
33
+ tokens,
34
+ bold,
35
+ italic,
36
+ }: {
37
+ nodes: RichTextInline[];
38
+ color: string;
39
+ tokens: NativeChatTokens;
40
+ bold?: boolean;
41
+ italic?: boolean;
42
+ }): ReactNode {
43
+ return nodes.map((node, i) => {
44
+ const baseStyle = {
45
+ color,
46
+ fontSize: tokens.fontSize,
47
+ fontFamily: tokens.fontFamily,
48
+ fontWeight: bold ? ("700" as const) : ("400" as const),
49
+ fontStyle: italic ? ("italic" as const) : ("normal" as const),
50
+ };
51
+ switch (node.type) {
52
+ case "text":
53
+ return (
54
+ <Text key={i} style={baseStyle}>
55
+ {node.text}
56
+ </Text>
57
+ );
58
+ case "break":
59
+ return <Text key={i}>{"\n"}</Text>;
60
+ case "strong":
61
+ return (
62
+ <InlineRuns key={i} nodes={node.children} color={color} tokens={tokens} bold italic={italic} />
63
+ );
64
+ case "em":
65
+ return (
66
+ <InlineRuns key={i} nodes={node.children} color={color} tokens={tokens} bold={bold} italic />
67
+ );
68
+ case "code":
69
+ return (
70
+ <Text
71
+ key={i}
72
+ style={{
73
+ color,
74
+ fontSize: tokens.fontSize - 1,
75
+ fontFamily: tokens.monoFontFamily,
76
+ backgroundColor: tokens.palette.canvasMuted,
77
+ }}
78
+ >
79
+ {node.code}
80
+ </Text>
81
+ );
82
+ case "link": {
83
+ const href = node.href;
84
+ if (href === undefined) {
85
+ // Unsafe or unresolvable target: the styled text, no press target.
86
+ return (
87
+ <Text key={i} style={{ ...baseStyle, textDecorationLine: "underline" }}>
88
+ <InlineRuns nodes={node.children} color={color} tokens={tokens} bold={bold} italic={italic} />
89
+ </Text>
90
+ );
91
+ }
92
+ return (
93
+ <Text
94
+ key={i}
95
+ accessibilityRole="link"
96
+ style={{ ...baseStyle, color: tokens.palette.accent, textDecorationLine: "underline" }}
97
+ onPress={() => {
98
+ void Linking.openURL(href).catch(() => {
99
+ // An unopenable-but-safe URL is a platform condition, not an error surface.
100
+ });
101
+ }}
102
+ >
103
+ <InlineRuns nodes={node.children} color={color} tokens={tokens} bold={bold} italic={italic} />
104
+ </Text>
105
+ );
106
+ }
107
+ }
108
+ });
109
+ }
110
+
111
+ function BlockView({
112
+ block,
113
+ color,
114
+ tokens,
115
+ trailing,
116
+ }: {
117
+ block: RichTextBlock;
118
+ color: string;
119
+ tokens: NativeChatTokens;
120
+ trailing?: ReactNode;
121
+ }): ReactNode {
122
+ switch (block.type) {
123
+ case "paragraph":
124
+ return (
125
+ <Text style={{ fontSize: tokens.fontSize, lineHeight: Math.round(tokens.fontSize * 1.45) }}>
126
+ <InlineRuns nodes={block.children} color={color} tokens={tokens} />
127
+ {trailing}
128
+ </Text>
129
+ );
130
+ case "heading":
131
+ return (
132
+ <Text
133
+ style={{
134
+ color,
135
+ fontSize: tokens.fontSize + (block.level <= 3 ? 2 : 0),
136
+ fontFamily: tokens.fontFamily,
137
+ fontWeight: "700",
138
+ }}
139
+ >
140
+ <InlineRuns nodes={block.children} color={color} tokens={tokens} bold />
141
+ {trailing}
142
+ </Text>
143
+ );
144
+ case "code-fence":
145
+ return (
146
+ <View
147
+ style={{
148
+ backgroundColor: tokens.palette.canvasMuted,
149
+ borderRadius: tokens.radius,
150
+ padding: tokens.pad,
151
+ }}
152
+ >
153
+ <Text style={{ color, fontSize: tokens.fontSize - 2, fontFamily: tokens.monoFontFamily }}>
154
+ {block.code}
155
+ </Text>
156
+ {trailing}
157
+ </View>
158
+ );
159
+ case "list":
160
+ return (
161
+ <View style={{ gap: 2 }}>
162
+ {block.items.map((item, j) => (
163
+ <View key={j} style={{ flexDirection: "row" }}>
164
+ <Text style={{ color, fontSize: tokens.fontSize, fontFamily: tokens.fontFamily }}>
165
+ {block.ordered ? `${(block.start ?? 1) + j}. ` : "• "}
166
+ </Text>
167
+ <Text style={{ flexShrink: 1, fontSize: tokens.fontSize, lineHeight: Math.round(tokens.fontSize * 1.45) }}>
168
+ <InlineRuns nodes={item.children} color={color} tokens={tokens} />
169
+ {j === block.items.length - 1 ? trailing : null}
170
+ </Text>
171
+ </View>
172
+ ))}
173
+ </View>
174
+ );
175
+ }
176
+ }
177
+
178
+ /** Sanitized markdown → themed RN elements (see the module docblock). */
179
+ export function NativeMarkdown({
180
+ text,
181
+ color,
182
+ tokens,
183
+ trailing,
184
+ }: {
185
+ text: string;
186
+ color: string;
187
+ tokens: NativeChatTokens;
188
+ /** Appended inside the LAST block so a streaming caret hugs the text. */
189
+ trailing?: ReactNode;
190
+ }): ReactNode {
191
+ const blocks = parseRichText(text);
192
+ return (
193
+ <View style={{ gap: 6 }}>
194
+ {blocks.map((block, i) => (
195
+ <BlockView
196
+ key={i}
197
+ block={block}
198
+ color={color}
199
+ tokens={tokens}
200
+ trailing={i === blocks.length - 1 ? trailing : undefined}
201
+ />
202
+ ))}
203
+ </View>
204
+ );
205
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The React Native theme projection (spec §6): `GuueyChatTheme` is the
3
+ * cross-platform contract; CSS custom properties are the WEB projection
4
+ * (`react/theme-css.ts`), and this module is the native one — the same
5
+ * schema resolved into a flat token object RN components read as style
6
+ * values. No new vocabulary: every field here derives from the schema.
7
+ */
8
+ import { resolveTheme, type GuueyChatPalette, type GuueyChatTheme } from "../theme.js";
9
+
10
+ export type NativeThemeMode = "light" | "dark";
11
+
12
+ /** The resolved style tokens the native components consume. */
13
+ export interface NativeChatTokens {
14
+ /** The mode-resolved palette (per-token fallback already applied). */
15
+ palette: GuueyChatPalette;
16
+ /** shape.radius → px: none 0, soft 10, round 18. */
17
+ radius: number;
18
+ /** shape.density → the bubble padding / row gap pair. */
19
+ pad: number;
20
+ gap: number;
21
+ /** typography — undefined means the platform default font. */
22
+ fontFamily: string | undefined;
23
+ monoFontFamily: string | undefined;
24
+ /** Base body size in sp, typography.scale applied (default 15). */
25
+ fontSize: number;
26
+ }
27
+
28
+ const RADIUS: Record<GuueyChatTheme["shape"]["radius"], number> = {
29
+ none: 0,
30
+ soft: 10,
31
+ round: 18,
32
+ };
33
+
34
+ /** Resolve a (possibly partial/stale) theme + mode into native tokens. */
35
+ export function resolveNativeTheme(theme: GuueyChatTheme, mode: NativeThemeMode): NativeChatTokens {
36
+ const resolved = resolveTheme(theme);
37
+ const palette = resolved.colors[mode];
38
+ const comfortable = resolved.shape.density === "comfortable";
39
+ return {
40
+ palette,
41
+ radius: RADIUS[resolved.shape.radius],
42
+ pad: comfortable ? 12 : 8,
43
+ gap: comfortable ? 10 : 6,
44
+ fontFamily: resolved.typography.fontFamily,
45
+ monoFontFamily: resolved.typography.monoFontFamily,
46
+ fontSize: Math.round(15 * (resolved.typography.scale ?? 1)),
47
+ };
48
+ }
@@ -0,0 +1,189 @@
1
+ /**
2
+ * `<NativeTranscript>` — the plan walker + the §3.2 renderer obligations,
3
+ * restated over React Native's own mechanics:
4
+ *
5
+ * - **Scroll contract, the inverted way.** The list is an INVERTED
6
+ * FlatList over the reversed plan (the chat-app contract portal's
7
+ * agent-chat screen ratified — guuey#94/#100): content grows at the
8
+ * scroll ORIGIN, so "stick to bottom while streaming" and "never shift
9
+ * the viewport while the reader is up in history" hold by construction
10
+ * — no scrollTo calls during streaming, no re-pin race with content
11
+ * resize (an R6 card growing at the origin cannot move the reader's
12
+ * viewport). "Release on scroll-up" is likewise structural; the kit
13
+ * adds the jump-to-latest affordance when the reader has left the
14
+ * newest turn, and its scroll animation respects the platform
15
+ * reduce-motion setting.
16
+ * - **Windowing** is the list primitive's own virtualization — FlatList
17
+ * windows the DOM-equivalent natively; the plan's stable keys are the
18
+ * `keyExtractor`, so item identity survives streaming updates.
19
+ * - **Accessibility** lives on the item components (`components.tsx`).
20
+ *
21
+ * Platform chrome (keyboard insets, dismiss modes, dock scroll policies)
22
+ * stays HOST-OWNED: `listProps` passes the host's FlatList behavior
23
+ * through, with the kit composing `onScroll` so both the host's policy and
24
+ * the jump affordance see every event. The kit owns data/renderItem/keys/
25
+ * inversion — a host overriding those would be fighting the plan.
26
+ */
27
+ import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from "react";
28
+ import {
29
+ AccessibilityInfo,
30
+ FlatList,
31
+ Pressable,
32
+ Text,
33
+ View,
34
+ type FlatListProps,
35
+ type NativeScrollEvent,
36
+ type NativeSyntheticEvent,
37
+ } from "react-native";
38
+ import { DEFAULT_CHAT_THEME, type GuueyChatTheme } from "../theme.js";
39
+ import { defaultChatStrings, type ChatStrings } from "../strings.js";
40
+ import type { DisplayItem, TranscriptPlan } from "../types.js";
41
+ import {
42
+ nativeTranscriptComponents,
43
+ renderNativeItem,
44
+ type NativeTranscriptComponents,
45
+ type NativeTranscriptItemContext,
46
+ } from "./components.js";
47
+ import { resolveNativeTheme, type NativeThemeMode } from "./theme-native.js";
48
+
49
+ /** Offset (px) past which the reader counts as "up in history". */
50
+ const JUMP_THRESHOLD_PX = 160;
51
+
52
+ /** The host-behavior pass-through — everything the kit deliberately does NOT own. */
53
+ export type NativeTranscriptListProps = Pick<
54
+ FlatListProps<DisplayItem>,
55
+ | "style"
56
+ | "contentContainerStyle"
57
+ | "keyboardDismissMode"
58
+ | "keyboardShouldPersistTaps"
59
+ | "automaticallyAdjustKeyboardInsets"
60
+ | "onScroll"
61
+ | "scrollEventThrottle"
62
+ | "ListEmptyComponent"
63
+ | "scrollIndicatorInsets"
64
+ >;
65
+
66
+ export interface NativeTranscriptProps
67
+ extends Pick<
68
+ NativeTranscriptItemContext,
69
+ "onToggle" | "onRetry" | "onPromptAction" | "onErrorAction" | "resolvedMounts" | "onViewPhase" | "onViewRef"
70
+ > {
71
+ plan: TranscriptPlan;
72
+ /** Per-slot component overrides (spec §3's override column). */
73
+ components?: Partial<NativeTranscriptComponents>;
74
+ /** The i18n seam — pass the same strings the policy carries. */
75
+ strings?: ChatStrings;
76
+ theme?: GuueyChatTheme;
77
+ mode?: NativeThemeMode;
78
+ /** Host-owned FlatList behavior (keyboard/scroll chrome). */
79
+ listProps?: NativeTranscriptListProps;
80
+ }
81
+
82
+ export function NativeTranscript(props: NativeTranscriptProps): ReactNode {
83
+ const {
84
+ plan,
85
+ components,
86
+ strings = defaultChatStrings,
87
+ theme = DEFAULT_CHAT_THEME,
88
+ mode = "light",
89
+ listProps,
90
+ onToggle,
91
+ onRetry,
92
+ onPromptAction,
93
+ onErrorAction,
94
+ resolvedMounts,
95
+ onViewPhase,
96
+ onViewRef,
97
+ } = props;
98
+
99
+ const tokens = useMemo(() => resolveNativeTheme(theme, mode), [theme, mode]);
100
+ const resolvedComponents: NativeTranscriptComponents = useMemo(
101
+ () => ({ ...nativeTranscriptComponents, ...components }),
102
+ [components],
103
+ );
104
+ const ctx: NativeTranscriptItemContext = useMemo(
105
+ () => ({ strings, tokens, onToggle, onRetry, onPromptAction, onErrorAction, resolvedMounts, onViewPhase, onViewRef }),
106
+ [strings, tokens, onToggle, onRetry, onPromptAction, onErrorAction, resolvedMounts, onViewPhase, onViewRef],
107
+ );
108
+
109
+ // Inverted-list data: reversed plan, newest at index 0 (the visual
110
+ // bottom / scroll origin). Keys are the plan's stable keys.
111
+ const data = useMemo(() => [...plan.items].reverse(), [plan.items]);
112
+
113
+ // Reduce motion: the ONE animation the kit owns is the jump scroll.
114
+ const [reduceMotion, setReduceMotion] = useState(false);
115
+ useEffect(() => {
116
+ let alive = true;
117
+ void AccessibilityInfo.isReduceMotionEnabled().then((v) => {
118
+ if (alive) setReduceMotion(v);
119
+ });
120
+ const sub = AccessibilityInfo.addEventListener("reduceMotionChanged", setReduceMotion);
121
+ return () => {
122
+ alive = false;
123
+ sub.remove();
124
+ };
125
+ }, []);
126
+
127
+ const listRef = useRef<FlatList<DisplayItem>>(null);
128
+ const [showJump, setShowJump] = useState(false);
129
+ const hostOnScroll = listProps?.onScroll;
130
+ const onScroll = useCallback(
131
+ (e: NativeSyntheticEvent<NativeScrollEvent>) => {
132
+ // Inverted coordinates: offset 0 IS the newest turn.
133
+ setShowJump(e.nativeEvent.contentOffset.y > JUMP_THRESHOLD_PX);
134
+ hostOnScroll?.(e);
135
+ },
136
+ [hostOnScroll],
137
+ );
138
+
139
+ const StatusComponent = resolvedComponents.status;
140
+
141
+ return (
142
+ <View style={{ flex: 1, backgroundColor: tokens.palette.canvas }}>
143
+ <FlatList
144
+ ref={listRef}
145
+ {...listProps}
146
+ onScroll={onScroll}
147
+ scrollEventThrottle={listProps?.scrollEventThrottle ?? 16}
148
+ // Inverted only while non-empty: an inverted ListEmptyComponent
149
+ // renders upside-down (RN gotcha — portal's receipt).
150
+ inverted={data.length > 0}
151
+ data={data}
152
+ keyExtractor={(item) => item.key}
153
+ renderItem={({ item }) => (
154
+ <View style={{ paddingVertical: tokens.gap / 2 }}>
155
+ {renderNativeItem(item, resolvedComponents, ctx)}
156
+ </View>
157
+ )}
158
+ // Inverted list: the header renders at the VISUAL BOTTOM — where
159
+ // the live status line belongs.
160
+ ListHeaderComponent={
161
+ plan.status !== null ? <StatusComponent item={plan.status} ctx={ctx} /> : null
162
+ }
163
+ />
164
+ {showJump ? (
165
+ <Pressable
166
+ accessibilityRole="button"
167
+ onPress={() => {
168
+ setShowJump(false);
169
+ listRef.current?.scrollToOffset({ offset: 0, animated: !reduceMotion });
170
+ }}
171
+ style={{
172
+ position: "absolute",
173
+ bottom: 12,
174
+ alignSelf: "center",
175
+ backgroundColor: tokens.palette.surface,
176
+ borderRadius: 999,
177
+ paddingHorizontal: 14,
178
+ paddingVertical: 8,
179
+ elevation: 3,
180
+ }}
181
+ >
182
+ <Text style={{ color: tokens.palette.ink, fontSize: tokens.fontSize - 2, fontFamily: tokens.fontFamily }}>
183
+ {strings.jumpToLatest}
184
+ </Text>
185
+ </Pressable>
186
+ ) : null}
187
+ </View>
188
+ );
189
+ }
package/src/native.tsx ADDED
@@ -0,0 +1,63 @@
1
+ /**
2
+ * React Native entry point (`@guuey/chat/native`) — the RN renderer over
3
+ * the SAME headless view-model as `./react` (wave 3c, guuey#135).
4
+ *
5
+ * Zero duplication by construction: the view-model, policies, theme
6
+ * schema, and strings are the root subpath's exports, and the
7
+ * renderer-state hooks (`useTranscript`, `useTranscriptInputs`) are the
8
+ * SAME modules the web kit uses — they are React-generic (no DOM), so both
9
+ * arms share one implementation. Only the walk differs: RN primitives, the
10
+ * inverted-list scroll contract, and the schema's native theme projection
11
+ * (`resolveNativeTheme` — CSS custom properties are the web projection).
12
+ *
13
+ * The R6 default is the documented native default-gap: this tier ships
14
+ * WITHOUT a WebView dependency, so `view` is a required override (a
15
+ * labeled placeholder renders otherwise — never blank). See
16
+ * `native/components.tsx`.
17
+ *
18
+ * `react` and `react-native` are OPTIONAL peers — the root subpath stays
19
+ * importable everywhere; this arm loads only inside an RN runtime.
20
+ */
21
+ export {
22
+ NativeTranscript,
23
+ type NativeTranscriptProps,
24
+ type NativeTranscriptListProps,
25
+ } from "./native/transcript.js";
26
+ export {
27
+ nativeTranscriptComponents,
28
+ renderNativeItem,
29
+ NativeUserMessage,
30
+ NativeText,
31
+ NativeReasoning,
32
+ NativeTool,
33
+ NativeToolGroup,
34
+ NativeDataResult,
35
+ NativeView,
36
+ NativeViewRef,
37
+ NativeMedia,
38
+ NativeCode,
39
+ NativeCitations,
40
+ NativePrompt,
41
+ NativeError,
42
+ NativeHistoryBoundary,
43
+ NativeCompaction,
44
+ NativeUnknown,
45
+ NativeStatus,
46
+ type NativeTranscriptComponents,
47
+ type NativeTranscriptItemContext,
48
+ } from "./native/components.js";
49
+ export { NativeMarkdown } from "./native/markdown.js";
50
+ export {
51
+ resolveNativeTheme,
52
+ type NativeChatTokens,
53
+ type NativeThemeMode,
54
+ } from "./native/theme-native.js";
55
+ // The React-generic renderer-state owner + live assembler — shared with
56
+ // the web kit (one implementation, two walks).
57
+ export {
58
+ useTranscript,
59
+ useTranscriptInputs,
60
+ type UseTranscriptArgs,
61
+ type UseTranscriptResult,
62
+ type UseTranscriptInputsResult,
63
+ } from "./react/use-transcript.js";