cursor-buddy 0.0.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/LICENSE +21 -0
- package/README.md +314 -0
- package/dist/client/index.d.mts +151 -0
- package/dist/client/index.d.mts.map +1 -0
- package/dist/client/index.mjs +1123 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +1 -0
- package/dist/server/adapters/next.d.mts +22 -0
- package/dist/server/adapters/next.d.mts.map +1 -0
- package/dist/server/adapters/next.mjs +24 -0
- package/dist/server/adapters/next.mjs.map +1 -0
- package/dist/server/index.d.mts +34 -0
- package/dist/server/index.d.mts.map +1 -0
- package/dist/server/index.mjs +163 -0
- package/dist/server/index.mjs.map +1 -0
- package/dist/types-B2GUdTzP.d.mts +37 -0
- package/dist/types-B2GUdTzP.d.mts.map +1 -0
- package/dist/types-b2KrNyuu.d.mts +59 -0
- package/dist/types-b2KrNyuu.d.mts.map +1 -0
- package/package.json +104 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 leojuriolli7
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
# cursor-buddy
|
|
2
|
+
|
|
3
|
+
AI-powered cursor companion for web apps. Push-to-talk voice assistant that can see your screen and point at things.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Push-to-talk voice input** — Hold a hotkey to speak, release to send
|
|
8
|
+
- **Screenshot context** — AI sees your current viewport
|
|
9
|
+
- **Voice responses** — Text-to-speech playback
|
|
10
|
+
- **Cursor pointing** — AI can point at UI elements it references
|
|
11
|
+
- **Framework agnostic** — Adapter-based server, works with Next.js, Express, Hono
|
|
12
|
+
- **Customizable** — CSS variables, custom components, headless mode
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install cursor-buddy
|
|
18
|
+
# or
|
|
19
|
+
pnpm add cursor-buddy
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
### 1. Server Setup
|
|
25
|
+
|
|
26
|
+
Create an API route that handles chat, transcription, and TTS.
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
// lib/cursor-buddy.ts
|
|
30
|
+
import { createCursorBuddyHandler } from "cursor-buddy/server"
|
|
31
|
+
import { openai } from "@ai-sdk/openai"
|
|
32
|
+
|
|
33
|
+
export const cursorBuddy = createCursorBuddyHandler({
|
|
34
|
+
model: openai("gpt-4o"),
|
|
35
|
+
speechModel: openai.speech("tts-1"),
|
|
36
|
+
transcriptionModel: openai.transcription("whisper-1"),
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
#### Next.js App Router
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
// app/api/cursor-buddy/[...path]/route.ts
|
|
44
|
+
import { toNextJsHandler } from "cursor-buddy/server/next"
|
|
45
|
+
import { cursorBuddy } from "@/lib/cursor-buddy"
|
|
46
|
+
|
|
47
|
+
export const { GET, POST } = toNextJsHandler(cursorBuddy)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. Client Setup
|
|
51
|
+
|
|
52
|
+
Add the `<CursorBuddy />` component to your app.
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
// app/layout.tsx
|
|
56
|
+
import { CursorBuddy } from "cursor-buddy/client"
|
|
57
|
+
|
|
58
|
+
export default function RootLayout({ children }) {
|
|
59
|
+
return (
|
|
60
|
+
<html>
|
|
61
|
+
<body>
|
|
62
|
+
{children}
|
|
63
|
+
<CursorBuddy endpoint="/api/cursor-buddy" />
|
|
64
|
+
</body>
|
|
65
|
+
</html>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
That's it! Hold **Ctrl+Alt** to speak, release to send.
|
|
71
|
+
|
|
72
|
+
## Server Configuration
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
createCursorBuddyHandler({
|
|
76
|
+
// Required
|
|
77
|
+
model: LanguageModel, // AI SDK chat model
|
|
78
|
+
speechModel: SpeechModel, // AI SDK speech model
|
|
79
|
+
transcriptionModel: TranscriptionModel, // AI SDK transcription model
|
|
80
|
+
|
|
81
|
+
// Optional
|
|
82
|
+
system: string | ((ctx) => string), // Custom system prompt
|
|
83
|
+
tools: Record<string, Tool>, // AI SDK tools
|
|
84
|
+
maxHistory: number, // Max conversation history (default: 10)
|
|
85
|
+
})
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Custom System Prompt
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
createCursorBuddyHandler({
|
|
92
|
+
model: openai("gpt-4o"),
|
|
93
|
+
speechModel: openai.speech("tts-1"),
|
|
94
|
+
transcriptionModel: openai.transcription("whisper-1"),
|
|
95
|
+
|
|
96
|
+
// Extend the default prompt
|
|
97
|
+
system: ({ defaultPrompt }) => `
|
|
98
|
+
${defaultPrompt}
|
|
99
|
+
|
|
100
|
+
You are helping users navigate a project management dashboard.
|
|
101
|
+
The sidebar contains: Projects, Tasks, Calendar, Settings.
|
|
102
|
+
`,
|
|
103
|
+
})
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Client Configuration
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
<CursorBuddy
|
|
110
|
+
// Required
|
|
111
|
+
endpoint="/api/cursor-buddy"
|
|
112
|
+
|
|
113
|
+
// Optional
|
|
114
|
+
hotkey="ctrl+alt" // Push-to-talk hotkey (default: "ctrl+alt")
|
|
115
|
+
muted={false} // Disable TTS playback
|
|
116
|
+
container={element} // Portal container (default: document.body)
|
|
117
|
+
|
|
118
|
+
// Custom components
|
|
119
|
+
cursor={(props) => <CustomCursor {...props} />}
|
|
120
|
+
speechBubble={(props) => <CustomBubble {...props} />}
|
|
121
|
+
waveform={(props) => <CustomWaveform {...props} />}
|
|
122
|
+
|
|
123
|
+
// Callbacks
|
|
124
|
+
onTranscript={(text) => {}} // Called when speech is transcribed
|
|
125
|
+
onResponse={(text) => {}} // Called when AI responds
|
|
126
|
+
onPoint={(target) => {}} // Called when AI points at element
|
|
127
|
+
onStateChange={(state) => {}} // Called on state change
|
|
128
|
+
onError={(error) => {}} // Called on error
|
|
129
|
+
/>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Customization
|
|
133
|
+
|
|
134
|
+
### CSS Variables
|
|
135
|
+
|
|
136
|
+
Cursor buddy styles are customizable via CSS variables. Override them in your stylesheet:
|
|
137
|
+
|
|
138
|
+
```css
|
|
139
|
+
:root {
|
|
140
|
+
/* Cursor colors by state */
|
|
141
|
+
--cursor-buddy-color-idle: #3b82f6;
|
|
142
|
+
--cursor-buddy-color-listening: #ef4444;
|
|
143
|
+
--cursor-buddy-color-processing: #eab308;
|
|
144
|
+
--cursor-buddy-color-responding: #22c55e;
|
|
145
|
+
|
|
146
|
+
/* Speech bubble */
|
|
147
|
+
--cursor-buddy-bubble-bg: #ffffff;
|
|
148
|
+
--cursor-buddy-bubble-text: #1f2937;
|
|
149
|
+
--cursor-buddy-bubble-radius: 8px;
|
|
150
|
+
--cursor-buddy-bubble-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
151
|
+
|
|
152
|
+
/* Waveform */
|
|
153
|
+
--cursor-buddy-waveform-color: #ef4444;
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Custom Components
|
|
158
|
+
|
|
159
|
+
Replace default components with your own:
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
import { CursorBuddy, type CursorRenderProps } from "cursor-buddy/client"
|
|
163
|
+
|
|
164
|
+
function MyCursor({ state, rotation, scale }: CursorRenderProps) {
|
|
165
|
+
return (
|
|
166
|
+
<div style={{ transform: `rotate(${rotation}rad) scale(${scale})` }}>
|
|
167
|
+
{state === "listening" ? "🎤" : "👆"}
|
|
168
|
+
</div>
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
<CursorBuddy
|
|
173
|
+
endpoint="/api/cursor-buddy"
|
|
174
|
+
cursor={(props) => <MyCursor {...props} />}
|
|
175
|
+
/>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Headless Mode
|
|
179
|
+
|
|
180
|
+
For full control, use the provider and hook directly:
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
import {
|
|
184
|
+
CursorBuddyProvider,
|
|
185
|
+
useCursorBuddy
|
|
186
|
+
} from "cursor-buddy/client"
|
|
187
|
+
|
|
188
|
+
function App() {
|
|
189
|
+
return (
|
|
190
|
+
<CursorBuddyProvider endpoint="/api/cursor-buddy">
|
|
191
|
+
<MyCustomUI />
|
|
192
|
+
</CursorBuddyProvider>
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function MyCustomUI() {
|
|
197
|
+
const {
|
|
198
|
+
state, // "idle" | "listening" | "processing" | "responding"
|
|
199
|
+
transcript, // Latest user speech
|
|
200
|
+
response, // Latest AI response
|
|
201
|
+
audioLevel, // 0-1, for waveform visualization
|
|
202
|
+
isEnabled,
|
|
203
|
+
isSpeaking,
|
|
204
|
+
isPointing,
|
|
205
|
+
error,
|
|
206
|
+
|
|
207
|
+
// Actions
|
|
208
|
+
startListening,
|
|
209
|
+
stopListening,
|
|
210
|
+
setEnabled,
|
|
211
|
+
speak, // Manually trigger TTS
|
|
212
|
+
pointAt, // Manually point at coordinates
|
|
213
|
+
reset,
|
|
214
|
+
} = useCursorBuddy()
|
|
215
|
+
|
|
216
|
+
return (
|
|
217
|
+
<div>
|
|
218
|
+
<p>State: {state}</p>
|
|
219
|
+
<button
|
|
220
|
+
onMouseDown={startListening}
|
|
221
|
+
onMouseUp={stopListening}
|
|
222
|
+
>
|
|
223
|
+
Hold to speak
|
|
224
|
+
</button>
|
|
225
|
+
</div>
|
|
226
|
+
)
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Render Props Types
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
interface CursorRenderProps {
|
|
234
|
+
state: "idle" | "listening" | "processing" | "responding"
|
|
235
|
+
isPointing: boolean
|
|
236
|
+
rotation: number // Radians, direction of travel
|
|
237
|
+
scale: number // 1.0 normal, up to 1.3 during flight
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
interface SpeechBubbleRenderProps {
|
|
241
|
+
text: string
|
|
242
|
+
isVisible: boolean
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
interface WaveformRenderProps {
|
|
246
|
+
audioLevel: number // 0-1
|
|
247
|
+
isListening: boolean
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## API Reference
|
|
252
|
+
|
|
253
|
+
### Server Exports (`cursor-buddy/server`)
|
|
254
|
+
|
|
255
|
+
| Export | Description |
|
|
256
|
+
|--------|-------------|
|
|
257
|
+
| `createCursorBuddyHandler` | Create the main request handler |
|
|
258
|
+
| `DEFAULT_SYSTEM_PROMPT` | Default system prompt for reference |
|
|
259
|
+
| `CursorBuddyHandlerConfig` | Type for handler configuration |
|
|
260
|
+
| `CursorBuddyHandler` | Return type of `createCursorBuddyHandler` |
|
|
261
|
+
|
|
262
|
+
### Server Adapters (`cursor-buddy/server/next`)
|
|
263
|
+
|
|
264
|
+
| Export | Description |
|
|
265
|
+
|--------|-------------|
|
|
266
|
+
| `toNextJsHandler` | Convert handler to Next.js App Router format |
|
|
267
|
+
|
|
268
|
+
### Client Exports (`cursor-buddy/client`)
|
|
269
|
+
|
|
270
|
+
| Export | Description |
|
|
271
|
+
|--------|-------------|
|
|
272
|
+
| `CursorBuddy` | Drop-in component with built-in UI |
|
|
273
|
+
| `CursorBuddyProvider` | Headless provider for custom UI |
|
|
274
|
+
| `useCursorBuddy` | Hook to access state and actions |
|
|
275
|
+
|
|
276
|
+
### Types (`cursor-buddy/client`)
|
|
277
|
+
|
|
278
|
+
| Export | Description |
|
|
279
|
+
|--------|-------------|
|
|
280
|
+
| `CursorBuddyProps` | Props for `<CursorBuddy />` |
|
|
281
|
+
| `CursorBuddyProviderProps` | Props for `<CursorBuddyProvider />` |
|
|
282
|
+
| `CursorBuddyContextValue` | Return type of `useCursorBuddy()` |
|
|
283
|
+
| `CursorRenderProps` | Props passed to custom cursor |
|
|
284
|
+
| `SpeechBubbleRenderProps` | Props passed to custom speech bubble |
|
|
285
|
+
| `WaveformRenderProps` | Props passed to custom waveform |
|
|
286
|
+
|
|
287
|
+
### Core Types (`cursor-buddy`)
|
|
288
|
+
|
|
289
|
+
| Export | Description |
|
|
290
|
+
|--------|-------------|
|
|
291
|
+
| `VoiceState` | `"idle" \| "listening" \| "processing" \| "responding"` |
|
|
292
|
+
| `PointingTarget` | `{ x: number, y: number, label: string }` |
|
|
293
|
+
| `Point` | `{ x: number, y: number }` |
|
|
294
|
+
|
|
295
|
+
## How It Works
|
|
296
|
+
|
|
297
|
+
1. User holds the hotkey (Ctrl+Alt)
|
|
298
|
+
2. Microphone captures audio, waveform shows audio level
|
|
299
|
+
3. User releases hotkey
|
|
300
|
+
4. Screenshot of viewport is captured
|
|
301
|
+
5. Audio is transcribed via AI SDK
|
|
302
|
+
6. Screenshot + capture metadata sent to AI model
|
|
303
|
+
7. AI responds with text, optionally including `[POINT:x,y:label]` tag in screenshot-image coordinates
|
|
304
|
+
8. Response is spoken via TTS
|
|
305
|
+
9. If pointing tag present, coordinates are mapped back to the live viewport and the cursor animates to the target location
|
|
306
|
+
|
|
307
|
+
## TODOS
|
|
308
|
+
- [ ] Faster transcription -> chat -> TTS flow (eg single endpoint instead of 3 calls)
|
|
309
|
+
- [ ] Composition pattern for custom components
|
|
310
|
+
- [ ] Better hotkey management
|
|
311
|
+
|
|
312
|
+
## License
|
|
313
|
+
|
|
314
|
+
MIT
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { a as VoiceState, i as SpeechBubbleRenderProps, o as WaveformRenderProps, r as PointingTarget, t as CursorRenderProps } from "../types-b2KrNyuu.mjs";
|
|
3
|
+
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/client/components/Overlay.d.ts
|
|
6
|
+
interface OverlayProps {
|
|
7
|
+
/** Custom cursor renderer */
|
|
8
|
+
cursor?: React.ReactNode | ((props: CursorRenderProps) => React.ReactNode);
|
|
9
|
+
/** Custom speech bubble renderer */
|
|
10
|
+
speechBubble?: (props: SpeechBubbleRenderProps) => React.ReactNode;
|
|
11
|
+
/** Custom waveform renderer */
|
|
12
|
+
waveform?: (props: WaveformRenderProps) => React.ReactNode;
|
|
13
|
+
/** Container element for portal (defaults to document.body) */
|
|
14
|
+
container?: HTMLElement | null;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/client/CursorBuddy.d.ts
|
|
18
|
+
interface CursorBuddyProps extends Pick<OverlayProps, "cursor" | "speechBubble" | "waveform"> {
|
|
19
|
+
/** API endpoint for cursor buddy server */
|
|
20
|
+
endpoint: string;
|
|
21
|
+
/** Hotkey for push-to-talk (default: "ctrl+alt") */
|
|
22
|
+
hotkey?: string;
|
|
23
|
+
/** Whether TTS is muted */
|
|
24
|
+
muted?: boolean;
|
|
25
|
+
/** Container element for portal (defaults to document.body) */
|
|
26
|
+
container?: HTMLElement | null;
|
|
27
|
+
/** Callback when transcript is ready */
|
|
28
|
+
onTranscript?: (text: string) => void;
|
|
29
|
+
/** Callback when AI responds */
|
|
30
|
+
onResponse?: (text: string) => void;
|
|
31
|
+
/** Callback when pointing at element */
|
|
32
|
+
onPoint?: (target: PointingTarget) => void;
|
|
33
|
+
/** Callback when state changes */
|
|
34
|
+
onStateChange?: (state: VoiceState) => void;
|
|
35
|
+
/** Callback when error occurs */
|
|
36
|
+
onError?: (error: Error) => void;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Drop-in cursor buddy component.
|
|
40
|
+
*
|
|
41
|
+
* Adds an AI-powered cursor companion to your app. Users hold the hotkey
|
|
42
|
+
* (default: Ctrl+Alt) to speak. The SDK captures a screenshot, transcribes
|
|
43
|
+
* the speech, sends it to the AI, speaks the response, and can point at
|
|
44
|
+
* elements on screen.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* import { CursorBuddy } from "cursor-buddy/client"
|
|
49
|
+
*
|
|
50
|
+
* function App() {
|
|
51
|
+
* return (
|
|
52
|
+
* <>
|
|
53
|
+
* <YourApp />
|
|
54
|
+
* <CursorBuddy endpoint="/api/cursor-buddy" />
|
|
55
|
+
* </>
|
|
56
|
+
* )
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare function CursorBuddy({
|
|
61
|
+
endpoint,
|
|
62
|
+
hotkey,
|
|
63
|
+
muted,
|
|
64
|
+
container,
|
|
65
|
+
cursor,
|
|
66
|
+
speechBubble,
|
|
67
|
+
waveform,
|
|
68
|
+
onTranscript,
|
|
69
|
+
onResponse,
|
|
70
|
+
onPoint,
|
|
71
|
+
onStateChange,
|
|
72
|
+
onError
|
|
73
|
+
}: CursorBuddyProps): _$react_jsx_runtime0.JSX.Element;
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/client/CursorBuddyProvider.d.ts
|
|
76
|
+
interface CursorBuddyProviderProps {
|
|
77
|
+
/** API endpoint for cursor buddy server */
|
|
78
|
+
endpoint: string;
|
|
79
|
+
/** Whether TTS is muted */
|
|
80
|
+
muted?: boolean;
|
|
81
|
+
/** Callback when transcript is ready */
|
|
82
|
+
onTranscript?: (text: string) => void;
|
|
83
|
+
/** Callback when AI responds */
|
|
84
|
+
onResponse?: (text: string) => void;
|
|
85
|
+
/** Callback when pointing at element */
|
|
86
|
+
onPoint?: (target: {
|
|
87
|
+
x: number;
|
|
88
|
+
y: number;
|
|
89
|
+
label: string;
|
|
90
|
+
}) => void;
|
|
91
|
+
/** Callback when state changes */
|
|
92
|
+
onStateChange?: (state: VoiceState) => void;
|
|
93
|
+
/** Callback when error occurs */
|
|
94
|
+
onError?: (error: Error) => void;
|
|
95
|
+
/** Children */
|
|
96
|
+
children: React.ReactNode;
|
|
97
|
+
}
|
|
98
|
+
declare function CursorBuddyProvider({
|
|
99
|
+
endpoint,
|
|
100
|
+
muted,
|
|
101
|
+
onTranscript,
|
|
102
|
+
onResponse,
|
|
103
|
+
onPoint,
|
|
104
|
+
onStateChange,
|
|
105
|
+
onError,
|
|
106
|
+
children
|
|
107
|
+
}: CursorBuddyProviderProps): _$react_jsx_runtime0.JSX.Element;
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/client/context.d.ts
|
|
110
|
+
interface CursorBuddyContextValue {
|
|
111
|
+
/** Current voice state */
|
|
112
|
+
state: VoiceState;
|
|
113
|
+
/** Latest transcribed user speech */
|
|
114
|
+
transcript: string;
|
|
115
|
+
/** Latest AI response (stripped of POINT tags) */
|
|
116
|
+
response: string;
|
|
117
|
+
/** Current audio level (0-1) */
|
|
118
|
+
audioLevel: number;
|
|
119
|
+
/** Whether the buddy is enabled */
|
|
120
|
+
isEnabled: boolean;
|
|
121
|
+
/** Whether TTS is currently playing */
|
|
122
|
+
isSpeaking: boolean;
|
|
123
|
+
/** Whether currently engaged with a pointing target */
|
|
124
|
+
isPointing: boolean;
|
|
125
|
+
/** Current error (null if none) */
|
|
126
|
+
error: Error | null;
|
|
127
|
+
/** Start listening (called automatically by hotkey) */
|
|
128
|
+
startListening: () => void;
|
|
129
|
+
/** Stop listening and process (called automatically by hotkey release) */
|
|
130
|
+
stopListening: () => void;
|
|
131
|
+
/** Enable or disable the buddy */
|
|
132
|
+
setEnabled: (enabled: boolean) => void;
|
|
133
|
+
/** Manually speak text via TTS */
|
|
134
|
+
speak: (text: string) => Promise<void>;
|
|
135
|
+
/** Manually point at coordinates */
|
|
136
|
+
pointAt: (x: number, y: number, label: string) => void;
|
|
137
|
+
/** Dismiss the current pointing target and return to follow mode */
|
|
138
|
+
dismissPointing: () => void;
|
|
139
|
+
/** Reset to idle state */
|
|
140
|
+
reset: () => void;
|
|
141
|
+
}
|
|
142
|
+
//#endregion
|
|
143
|
+
//#region src/client/hooks/useCursorBuddy.d.ts
|
|
144
|
+
/**
|
|
145
|
+
* Hook to access cursor buddy state and actions.
|
|
146
|
+
* Must be used within a CursorBuddyProvider.
|
|
147
|
+
*/
|
|
148
|
+
declare function useCursorBuddy(): CursorBuddyContextValue;
|
|
149
|
+
//#endregion
|
|
150
|
+
export { CursorBuddy, type CursorBuddyContextValue, type CursorBuddyProps, CursorBuddyProvider, type CursorBuddyProviderProps, type CursorRenderProps, type SpeechBubbleRenderProps, type WaveformRenderProps, useCursorBuddy };
|
|
151
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/client/components/Overlay.tsx","../../src/client/CursorBuddy.tsx","../../src/client/CursorBuddyProvider.tsx","../../src/client/context.ts","../../src/client/hooks/useCursorBuddy.ts"],"mappings":";;;;UAoBiB,YAAA;;EAEf,MAAA,GAAS,KAAA,CAAM,SAAA,KAAc,KAAA,EAAO,iBAAA,KAAsB,KAAA,CAAM,SAAA;;EAEhE,YAAA,IAAgB,KAAA,EAAO,uBAAA,KAA4B,KAAA,CAAM,SAAA;EAJ9B;EAM3B,QAAA,IAAY,KAAA,EAAO,mBAAA,KAAwB,KAAA,CAAM,SAAA;EAJxC;EAMT,SAAA,GAAY,WAAA;AAAA;;;UChBG,gBAAA,SACP,IAAA,CAAK,YAAA;;EAEb,QAAA;EDKe;ECHf,MAAA;;EAEA,KAAA;EDGoC;ECDpC,SAAA,GAAY,WAAA;EDGW;ECDvB,YAAA,IAAgB,IAAA;EDGG;ECDnB,UAAA,IAAc,IAAA;EDGF;ECDZ,OAAA,IAAW,MAAA,EAAQ,cAAA;EDCI;ECCvB,aAAA,IAAiB,KAAA,EAAO,UAAA;EDPf;ECST,OAAA,IAAW,KAAA,EAAO,KAAA;AAAA;;;;;;;;;;;;;;;;;;;;;AAnBpB;;iBAwEgB,WAAA,CAAA;EACd,QAAA;EACA,MAAA;EACA,KAAA;EACA,SAAA;EACA,MAAA;EACA,YAAA;EACA,QAAA;EACA,YAAA;EACA,UAAA;EACA,OAAA;EACA,aAAA;EACA;AAAA,GACC,gBAAA,GAAgB,oBAAA,CAAA,GAAA,CAAA,OAAA;;;UC9DF,wBAAA;;EAEf,QAAA;;EAEA,KAAA;EFnB2B;EEqB3B,YAAA,IAAgB,IAAA;EFnBP;EEqBT,UAAA,IAAc,IAAA;EFrB4C;EEuB1D,OAAA,IAAW,MAAA;IAAU,CAAA;IAAW,CAAA;IAAW,KAAA;EAAA;EFjBpB;EEmBvB,aAAA,IAAiB,KAAA,EAAO,UAAA;EFzBxB;EE2BA,OAAA,IAAW,KAAA,EAAO,KAAA;EF3BH;EE6Bf,QAAA,EAAU,KAAA,CAAM,SAAA;AAAA;AAAA,iBAiCF,mBAAA,CAAA;EACd,QAAA;EACA,KAAA;EACA,YAAA;EACA,UAAA;EACA,OAAA;EACA,aAAA;EACA,OAAA;EACA;AAAA,GACC,wBAAA,GAAwB,oBAAA,CAAA,GAAA,CAAA,OAAA;;;UC1FV,uBAAA;;EAEf,KAAA,EAAO,UAAA;;EAEP,UAAA;EHa2B;EGX3B,QAAA;EHaS;EGXT,UAAA;EHW0D;EGT1D,SAAA;EHWmD;EGTnD,UAAA;EHW2C;EGT3C,UAAA;EHWuB;EGTvB,KAAA,EAAO,KAAA;EHGP;EGAA,cAAA;EHAe;EGEf,aAAA;EHF6B;EGI7B,UAAA,GAAa,OAAA;EHJmD;EGMhE,KAAA,GAAQ,IAAA,aAAiB,OAAA;EHJF;EGMvB,OAAA,GAAU,CAAA,UAAW,CAAA,UAAW,KAAA;EHNmB;EGQnD,eAAA;EHNA;EGQA,KAAA;AAAA;;;;;;;iBC3Bc,cAAA,CAAA,GAAkB,uBAAA"}
|