@speechos/core 0.2.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.
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Reactive state management for SpeechOS SDK
3
+ * Provides a centralized state store with subscriptions (similar to Zustand pattern)
4
+ */
5
+ import type { SpeechOSState, StateChangeCallback, UnsubscribeFn } from "./types.js";
6
+ /**
7
+ * State manager class
8
+ */
9
+ declare class StateManager {
10
+ private state;
11
+ private subscribers;
12
+ constructor(initialState: SpeechOSState);
13
+ /**
14
+ * Get the current state (returns a copy to prevent mutations)
15
+ */
16
+ getState(): SpeechOSState;
17
+ /**
18
+ * Update state with partial values
19
+ * @param partial - Partial state to merge with current state
20
+ */
21
+ setState(partial: Partial<SpeechOSState>): void;
22
+ /**
23
+ * Subscribe to state changes
24
+ * @param callback - Function to call when state changes
25
+ * @returns Unsubscribe function
26
+ */
27
+ subscribe(callback: StateChangeCallback): UnsubscribeFn;
28
+ /**
29
+ * Reset state to initial values
30
+ */
31
+ reset(): void;
32
+ /**
33
+ * Show the widget
34
+ */
35
+ show(): void;
36
+ /**
37
+ * Hide the widget and reset expanded state
38
+ */
39
+ hide(): void;
40
+ /**
41
+ * Toggle the action bubbles expansion
42
+ */
43
+ toggleExpanded(): void;
44
+ /**
45
+ * Set the focused form element
46
+ * @param element - The form element that has focus
47
+ */
48
+ setFocusedElement(element: HTMLElement | null): void;
49
+ /**
50
+ * Set the active action
51
+ * @param action - The action to set as active
52
+ */
53
+ setActiveAction(action: SpeechOSState["activeAction"]): void;
54
+ /**
55
+ * Set the recording state
56
+ * @param recordingState - The recording state to set
57
+ */
58
+ setRecordingState(recordingState: SpeechOSState["recordingState"]): void;
59
+ /**
60
+ * Set the connection state
61
+ * @param isConnected - Whether connected to LiveKit
62
+ */
63
+ setConnected(isConnected: boolean): void;
64
+ /**
65
+ * Set the microphone enabled state
66
+ * @param isMicEnabled - Whether microphone is enabled
67
+ */
68
+ setMicEnabled(isMicEnabled: boolean): void;
69
+ /**
70
+ * Start recording flow (connecting → recording)
71
+ */
72
+ startRecording(): void;
73
+ /**
74
+ * Stop recording and start processing
75
+ */
76
+ stopRecording(): void;
77
+ /**
78
+ * Complete the recording flow and return to idle
79
+ */
80
+ completeRecording(): void;
81
+ /**
82
+ * Cancel recording and return to idle
83
+ */
84
+ cancelRecording(): void;
85
+ /**
86
+ * Set error state with a message
87
+ * @param message - Error message to display
88
+ */
89
+ setError(message: string): void;
90
+ /**
91
+ * Clear error state and return to idle
92
+ */
93
+ clearError(): void;
94
+ }
95
+ export declare const state: StateManager;
96
+ /**
97
+ * Create a new state manager instance (useful for testing)
98
+ */
99
+ export declare function createStateManager(initial?: Partial<SpeechOSState>): StateManager;
100
+ export {};
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Reactive state management for SpeechOS SDK
3
+ * Provides a centralized state store with subscriptions (similar to Zustand pattern)
4
+ */
5
+ import type { SpeechOSState, StateChangeCallback, UnsubscribeFn } from "./types.js";
6
+ /**
7
+ * State manager class
8
+ */
9
+ declare class StateManager {
10
+ private state;
11
+ private subscribers;
12
+ constructor(initialState: SpeechOSState);
13
+ /**
14
+ * Get the current state (returns a copy to prevent mutations)
15
+ */
16
+ getState(): SpeechOSState;
17
+ /**
18
+ * Update state with partial values
19
+ * @param partial - Partial state to merge with current state
20
+ */
21
+ setState(partial: Partial<SpeechOSState>): void;
22
+ /**
23
+ * Subscribe to state changes
24
+ * @param callback - Function to call when state changes
25
+ * @returns Unsubscribe function
26
+ */
27
+ subscribe(callback: StateChangeCallback): UnsubscribeFn;
28
+ /**
29
+ * Reset state to initial values
30
+ */
31
+ reset(): void;
32
+ /**
33
+ * Show the widget
34
+ */
35
+ show(): void;
36
+ /**
37
+ * Hide the widget and reset expanded state
38
+ */
39
+ hide(): void;
40
+ /**
41
+ * Toggle the action bubbles expansion
42
+ */
43
+ toggleExpanded(): void;
44
+ /**
45
+ * Set the focused form element
46
+ * @param element - The form element that has focus
47
+ */
48
+ setFocusedElement(element: HTMLElement | null): void;
49
+ /**
50
+ * Set the active action
51
+ * @param action - The action to set as active
52
+ */
53
+ setActiveAction(action: SpeechOSState["activeAction"]): void;
54
+ /**
55
+ * Set the recording state
56
+ * @param recordingState - The recording state to set
57
+ */
58
+ setRecordingState(recordingState: SpeechOSState["recordingState"]): void;
59
+ /**
60
+ * Set the connection state
61
+ * @param isConnected - Whether connected to LiveKit
62
+ */
63
+ setConnected(isConnected: boolean): void;
64
+ /**
65
+ * Set the microphone enabled state
66
+ * @param isMicEnabled - Whether microphone is enabled
67
+ */
68
+ setMicEnabled(isMicEnabled: boolean): void;
69
+ /**
70
+ * Start recording flow (connecting → recording)
71
+ */
72
+ startRecording(): void;
73
+ /**
74
+ * Stop recording and start processing
75
+ */
76
+ stopRecording(): void;
77
+ /**
78
+ * Complete the recording flow and return to idle
79
+ */
80
+ completeRecording(): void;
81
+ /**
82
+ * Cancel recording and return to idle
83
+ */
84
+ cancelRecording(): void;
85
+ /**
86
+ * Set error state with a message
87
+ * @param message - Error message to display
88
+ */
89
+ setError(message: string): void;
90
+ /**
91
+ * Clear error state and return to idle
92
+ */
93
+ clearError(): void;
94
+ }
95
+ export declare const state: StateManager;
96
+ /**
97
+ * Create a new state manager instance (useful for testing)
98
+ */
99
+ export declare function createStateManager(initial?: Partial<SpeechOSState>): StateManager;
100
+ export {};
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Transcript history store
3
+ * Persists transcripts to localStorage for viewing in the settings modal
4
+ */
5
+ export type TranscriptAction = "dictate" | "edit";
6
+ export interface TranscriptEntry {
7
+ id: string;
8
+ text: string;
9
+ timestamp: number;
10
+ action: TranscriptAction;
11
+ /** Original text before edit (only for edit actions) */
12
+ originalText?: string;
13
+ }
14
+ /**
15
+ * Get all transcripts from localStorage
16
+ */
17
+ export declare function getTranscripts(): TranscriptEntry[];
18
+ /**
19
+ * Save a new transcript entry
20
+ */
21
+ export declare function saveTranscript(text: string, action: TranscriptAction, originalText?: string): TranscriptEntry;
22
+ /**
23
+ * Clear all transcript history
24
+ */
25
+ export declare function clearTranscripts(): void;
26
+ /**
27
+ * Delete a single transcript by ID
28
+ */
29
+ export declare function deleteTranscript(id: string): void;
30
+ export declare const transcriptStore: {
31
+ getTranscripts: typeof getTranscripts;
32
+ saveTranscript: typeof saveTranscript;
33
+ clearTranscripts: typeof clearTranscripts;
34
+ deleteTranscript: typeof deleteTranscript;
35
+ };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Transcript history store
3
+ * Persists transcripts to localStorage for viewing in the settings modal
4
+ */
5
+ export type TranscriptAction = "dictate" | "edit";
6
+ export interface TranscriptEntry {
7
+ id: string;
8
+ text: string;
9
+ timestamp: number;
10
+ action: TranscriptAction;
11
+ /** Original text before edit (only for edit actions) */
12
+ originalText?: string;
13
+ }
14
+ /**
15
+ * Get all transcripts from localStorage
16
+ */
17
+ export declare function getTranscripts(): TranscriptEntry[];
18
+ /**
19
+ * Save a new transcript entry
20
+ */
21
+ export declare function saveTranscript(text: string, action: TranscriptAction, originalText?: string): TranscriptEntry;
22
+ /**
23
+ * Clear all transcript history
24
+ */
25
+ export declare function clearTranscripts(): void;
26
+ /**
27
+ * Delete a single transcript by ID
28
+ */
29
+ export declare function deleteTranscript(id: string): void;
30
+ export declare const transcriptStore: {
31
+ getTranscripts: typeof getTranscripts;
32
+ saveTranscript: typeof saveTranscript;
33
+ clearTranscripts: typeof clearTranscripts;
34
+ deleteTranscript: typeof deleteTranscript;
35
+ };
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Shared TypeScript types for SpeechOS Core SDK
3
+ */
4
+ /**
5
+ * Server error message structure received via LiveKit data channel
6
+ */
7
+ export interface ServerErrorMessage {
8
+ type: "error";
9
+ /** Error code identifying the type of error (e.g., "transcription_failed", "edit_failed") */
10
+ code?: string;
11
+ /** User-facing error message */
12
+ message: string;
13
+ /** Optional technical details for debugging */
14
+ details?: string;
15
+ }
16
+ /**
17
+ * Error source indicating where the error originated
18
+ */
19
+ export type ErrorSource = "init" | "connection" | "timeout" | "server";
20
+ /**
21
+ * Configuration options for initializing SpeechOS
22
+ */
23
+ export interface SpeechOSConfig {
24
+ /** API key for authentication with SpeechOS backend */
25
+ apiKey?: string;
26
+ /** Optional user identifier for tracking which end user is using the SDK */
27
+ userId?: string;
28
+ /** Backend host URL for API calls (default: https://app.speechos.ai) */
29
+ host?: string;
30
+ /** Position of the widget on screen (used by client package) */
31
+ position?: "bottom-center" | "bottom-right" | "bottom-left";
32
+ /** Custom z-index for widget overlay (used by client package) */
33
+ zIndex?: number;
34
+ /** Enable debug logging */
35
+ debug?: boolean;
36
+ }
37
+ /**
38
+ * LiveKit token response from the backend
39
+ */
40
+ export interface LiveKitTokenResponse {
41
+ token: string;
42
+ ws_url: string;
43
+ room: string;
44
+ identity: string;
45
+ }
46
+ /**
47
+ * Available actions that can be triggered from the widget
48
+ */
49
+ export type SpeechOSAction = "dictate" | "edit";
50
+ /**
51
+ * Recording/dictation states
52
+ */
53
+ export type RecordingState = "idle" | "connecting" | "recording" | "processing" | "error";
54
+ /**
55
+ * Internal state of the SpeechOS SDK
56
+ */
57
+ export interface SpeechOSState {
58
+ /** Whether the widget is visible on screen */
59
+ isVisible: boolean;
60
+ /** Whether the action bubbles are expanded */
61
+ isExpanded: boolean;
62
+ /** Whether connected to LiveKit room */
63
+ isConnected: boolean;
64
+ /** Whether microphone is enabled and publishing */
65
+ isMicEnabled: boolean;
66
+ /** Currently active action, if any */
67
+ activeAction: SpeechOSAction | null;
68
+ /** The form field element that currently has focus (set by client) */
69
+ focusedElement: HTMLElement | null;
70
+ /** Current recording state */
71
+ recordingState: RecordingState;
72
+ /** Error message to display (if any) */
73
+ errorMessage: string | null;
74
+ }
75
+ /**
76
+ * Event payload types for SpeechOS events
77
+ *
78
+ * Events are organized into categories:
79
+ * - Core events: Emitted by @speechos/core (no DOM dependencies)
80
+ * - Client events: Emitted by @speechos/client (DOM-specific)
81
+ */
82
+ export interface SpeechOSEventMap {
83
+ /** Emitted when a text input field receives focus */
84
+ "form:focus": {
85
+ element: HTMLElement;
86
+ };
87
+ /** Emitted when focus leaves a text input field */
88
+ "form:blur": {
89
+ element: HTMLElement | null;
90
+ };
91
+ /** Emitted when the widget becomes visible */
92
+ "widget:show": void;
93
+ /** Emitted when the widget is hidden */
94
+ "widget:hide": void;
95
+ /** Emitted when user selects an action (dictate/edit) */
96
+ "action:select": {
97
+ action: SpeechOSAction;
98
+ };
99
+ /** Emitted when internal state changes */
100
+ "state:change": {
101
+ state: SpeechOSState;
102
+ };
103
+ /** Emitted when transcription is received from the server */
104
+ "transcription:complete": {
105
+ text: string;
106
+ };
107
+ /** Emitted when edited text is received from the server */
108
+ "edit:complete": {
109
+ text: string;
110
+ originalText: string;
111
+ };
112
+ /** Emitted when transcribed text is inserted into a form field */
113
+ "transcription:inserted": {
114
+ text: string;
115
+ element: HTMLElement;
116
+ };
117
+ /** Emitted when edited text is applied to a form field */
118
+ "edit:applied": {
119
+ originalContent: string;
120
+ editedContent: string;
121
+ element: HTMLElement;
122
+ };
123
+ /** Emitted when an error occurs */
124
+ error: {
125
+ code: string;
126
+ message: string;
127
+ source: ErrorSource;
128
+ };
129
+ }
130
+ /**
131
+ * Callback function for state changes
132
+ */
133
+ export type StateChangeCallback = (newState: SpeechOSState, prevState: SpeechOSState) => void;
134
+ /**
135
+ * Unsubscribe function returned by event listeners
136
+ */
137
+ export type UnsubscribeFn = () => void;
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Shared TypeScript types for SpeechOS Core SDK
3
+ */
4
+ /**
5
+ * Server error message structure received via LiveKit data channel
6
+ */
7
+ export interface ServerErrorMessage {
8
+ type: "error";
9
+ /** Error code identifying the type of error (e.g., "transcription_failed", "edit_failed") */
10
+ code?: string;
11
+ /** User-facing error message */
12
+ message: string;
13
+ /** Optional technical details for debugging */
14
+ details?: string;
15
+ }
16
+ /**
17
+ * Error source indicating where the error originated
18
+ */
19
+ export type ErrorSource = "init" | "connection" | "timeout" | "server";
20
+ /**
21
+ * Configuration options for initializing SpeechOS
22
+ */
23
+ export interface SpeechOSConfig {
24
+ /** API key for authentication with SpeechOS backend */
25
+ apiKey?: string;
26
+ /** Optional user identifier for tracking which end user is using the SDK */
27
+ userId?: string;
28
+ /** Backend host URL for API calls (default: https://app.speechos.ai) */
29
+ host?: string;
30
+ /** Position of the widget on screen (used by client package) */
31
+ position?: "bottom-center" | "bottom-right" | "bottom-left";
32
+ /** Custom z-index for widget overlay (used by client package) */
33
+ zIndex?: number;
34
+ /** Enable debug logging */
35
+ debug?: boolean;
36
+ }
37
+ /**
38
+ * LiveKit token response from the backend
39
+ */
40
+ export interface LiveKitTokenResponse {
41
+ token: string;
42
+ ws_url: string;
43
+ room: string;
44
+ identity: string;
45
+ }
46
+ /**
47
+ * Available actions that can be triggered from the widget
48
+ */
49
+ export type SpeechOSAction = "dictate" | "edit";
50
+ /**
51
+ * Recording/dictation states
52
+ */
53
+ export type RecordingState = "idle" | "connecting" | "recording" | "processing" | "error";
54
+ /**
55
+ * Internal state of the SpeechOS SDK
56
+ */
57
+ export interface SpeechOSState {
58
+ /** Whether the widget is visible on screen */
59
+ isVisible: boolean;
60
+ /** Whether the action bubbles are expanded */
61
+ isExpanded: boolean;
62
+ /** Whether connected to LiveKit room */
63
+ isConnected: boolean;
64
+ /** Whether microphone is enabled and publishing */
65
+ isMicEnabled: boolean;
66
+ /** Currently active action, if any */
67
+ activeAction: SpeechOSAction | null;
68
+ /** The form field element that currently has focus (set by client) */
69
+ focusedElement: HTMLElement | null;
70
+ /** Current recording state */
71
+ recordingState: RecordingState;
72
+ /** Error message to display (if any) */
73
+ errorMessage: string | null;
74
+ }
75
+ /**
76
+ * Event payload types for SpeechOS events
77
+ *
78
+ * Events are organized into categories:
79
+ * - Core events: Emitted by @speechos/core (no DOM dependencies)
80
+ * - Client events: Emitted by @speechos/client (DOM-specific)
81
+ */
82
+ export interface SpeechOSEventMap {
83
+ /** Emitted when a text input field receives focus */
84
+ "form:focus": {
85
+ element: HTMLElement;
86
+ };
87
+ /** Emitted when focus leaves a text input field */
88
+ "form:blur": {
89
+ element: HTMLElement | null;
90
+ };
91
+ /** Emitted when the widget becomes visible */
92
+ "widget:show": void;
93
+ /** Emitted when the widget is hidden */
94
+ "widget:hide": void;
95
+ /** Emitted when user selects an action (dictate/edit) */
96
+ "action:select": {
97
+ action: SpeechOSAction;
98
+ };
99
+ /** Emitted when internal state changes */
100
+ "state:change": {
101
+ state: SpeechOSState;
102
+ };
103
+ /** Emitted when transcription is received from the server */
104
+ "transcription:complete": {
105
+ text: string;
106
+ };
107
+ /** Emitted when edited text is received from the server */
108
+ "edit:complete": {
109
+ text: string;
110
+ originalText: string;
111
+ };
112
+ /** Emitted when transcribed text is inserted into a form field */
113
+ "transcription:inserted": {
114
+ text: string;
115
+ element: HTMLElement;
116
+ };
117
+ /** Emitted when edited text is applied to a form field */
118
+ "edit:applied": {
119
+ originalContent: string;
120
+ editedContent: string;
121
+ element: HTMLElement;
122
+ };
123
+ /** Emitted when an error occurs */
124
+ error: {
125
+ code: string;
126
+ message: string;
127
+ source: ErrorSource;
128
+ };
129
+ }
130
+ /**
131
+ * Callback function for state changes
132
+ */
133
+ export type StateChangeCallback = (newState: SpeechOSState, prevState: SpeechOSState) => void;
134
+ /**
135
+ * Unsubscribe function returned by event listeners
136
+ */
137
+ export type UnsubscribeFn = () => void;
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@speechos/core",
3
+ "version": "0.2.0",
4
+ "description": "Headless core SDK for SpeechOS - state, events, LiveKit integration",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "sideEffects": false,
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/speechos-org/speechos.git",
26
+ "directory": "speechos-client/packages/core"
27
+ },
28
+ "homepage": "https://speechos.ai",
29
+ "bugs": {
30
+ "url": "https://github.com/speechos-org/speechos/issues"
31
+ },
32
+ "scripts": {
33
+ "build": "tsdown",
34
+ "dev": "tsdown --watch",
35
+ "type-check": "tsc --noEmit",
36
+ "test": "vitest run",
37
+ "test:watch": "vitest"
38
+ },
39
+ "keywords": [
40
+ "speechos",
41
+ "sdk",
42
+ "core",
43
+ "voice",
44
+ "ai",
45
+ "headless"
46
+ ],
47
+ "author": "SpeechOS",
48
+ "license": "MIT",
49
+ "devDependencies": {
50
+ "tsdown": "^0.2.0",
51
+ "tslib": "^2.8.1",
52
+ "typescript": "^5.7.3",
53
+ "vitest": "^4.0.16"
54
+ },
55
+ "dependencies": {
56
+ "livekit-client": "^2.16.1"
57
+ }
58
+ }